fix(journal): unify $var lookup and error

EvalContext.lookup now receives the full $var name, matching getCombined,
setBase, and getMods, and parseFactor throws "Unknown variable" when the
lookup returns undefined. /set and /roll use the new resolveVariable() so a
typo errors instead of silently evaluating to 0.

Declarations and tag modifiers stay lenient (unknown -> 0): the documented
$hp = $con*5+$mod_hp pattern depends on external/undeclared variables
defaulting to 0.
This commit is contained in:
hyper
2026-09-12 22:34:12 +08:00
parent 02442a1100
commit 16f2038fd8
6 changed files with 83 additions and 41 deletions
+12 -6
View File
@@ -75,23 +75,29 @@ The items below are still open.
`journalStreamState.variableBases` so bases are restored exactly instead of
falling back to combined values.
### 4. `lookup` contract disagrees with its docs — low
### 4. `lookup` contract disagrees with its docs — ✅ fixed
- **Where:** `EvalContext.lookup` documents "Resolve `$var`", but
`parseFactor` calls `ctx.lookup(varName.slice(1))` (bare name), and every
caller re-adds `$`.
- **Symptom:** a caller following the doc would key variables with `$` and
silently get `0`s.
- **Fix:** update the doc comment to state the argument is the bare name (no
`$`), or stop stripping in `parseFactor` and update callers.
- **Fixed:** `EvalContext.lookup` now receives the full `$var` name (including
`$`), consistent with every other variable API (`getCombined`, `setBase`,
`getMods`, `resolveVariable`). Callers no longer add or strip `$`.
### 5. Undefined variables evaluate to `0` — low
### 5. Undefined variables evaluate to `0` — ✅ fixed (strict for commands)
- **Where:** `parseFactor` (`variable-expression.ts`) returns a numeric `0` for
an unresolved `$var`.
- **Symptom:** `/set $hp $cn*5` (typo) silently sets `0` instead of failing.
- **Fix:** consider erroring on unknown variables in `/set` context while
keeping lenient behavior for display/roll contexts, or warn.
- **Fixed:** `parseFactor` now throws `Unknown variable: $x` whenever `lookup`
returns `undefined`, and `resolveVariable()` distinguishes unknown from a real
`0`. `/set` and `/roll` use the strict resolver, so typos fail loudly via
`dispatchError`. Declarations and tag modifiers stay lenient on purpose: they
resolve unknown references to `0` through `getCombined`, because the
documented pattern (`$hp = $con*5+$mod_hp`) relies on external/undeclared
variables defaulting to 0.
### 6. Tokenizer accepts malformed numbers — ✅ fixed