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
+25 -12
View File
@@ -331,6 +331,24 @@ export function getCombined(key: string, fallback?: VariableStore): string {
return "0";
}
/**
* Resolve a `$var` to its combined value, distinguishing an unknown variable
* (undefined) from a real value of "0". Strict contexts such as `/set` and
* `/roll` use this so a typo'd or undeclared reference errors instead of
* silently evaluating to 0.
*/
export function resolveVariable(
key: string,
fallback?: VariableStore,
): string | undefined {
const known =
baseValues.has(key) ||
numericMods.has(key) ||
tagMapMods.has(key) ||
(fallback !== undefined && fallback[key] !== undefined);
return known ? getCombined(key, fallback) : undefined;
}
/**
* Get the effective tagmap for a variable (base + tagmap mods).
* Returns null if the variable is not a tagmap variable.
@@ -472,10 +490,9 @@ export function computeInitialValues(
try {
const result = evaluateExpression(expr, {
lookup: (name: string) => {
const k = "$" + name;
return getCombined(k, currentVars);
},
// Declarations may reference runtime/external variables; getCombined
// defaults unknown keys to "0" rather than erroring.
lookup: (name) => getCombined(name, currentVars),
});
const rawValue = exprValueToString(result.value);
@@ -550,10 +567,8 @@ function applyTagMapActivations(
}
const evalResult = evaluateExpression(mod.expression, {
lookup: (name: string) => {
const k = "$" + name;
return getCombined(k, fallback);
},
// Modifier expressions tolerate undefined references (→ "0").
lookup: (name) => getCombined(name, fallback),
});
// Modifier expressions must evaluate to a number
@@ -716,10 +731,8 @@ function reevaluateDependents(
if (!expr) continue;
const result = evaluateExpression(expr, {
lookup: (name: string) => {
const k = "$" + name;
return getCombined(k, fallback);
},
// Declaration re-evaluation stays lenient for undeclared references.
lookup: (name) => getCombined(name, fallback),
});
const rawValue = exprValueToString(result.value);