solve-engine 2.2.0 → 2.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{Configuration-B6W0-T67.d.cts → Configuration-Culg8H_o.d.cts} +17 -0
- package/dist/{Configuration-B6W0-T67.d.ts → Configuration-Culg8H_o.d.ts} +17 -0
- package/dist/{PackageCompatibility-Cv7zjqSV.d.cts → PackageCompatibility-CN-2CVhu.d.cts} +1 -1
- package/dist/{PackageCompatibility-DBsZ0l2a.d.ts → PackageCompatibility-DbpyKYOe.d.ts} +1 -1
- package/dist/{PackageRegistry-BSGQ6saH.d.cts → PackageRegistry-DXsvmpQN.d.cts} +24 -1
- package/dist/{PackageRegistry-DRbqNJfI.d.ts → PackageRegistry-jqdAsm6U.d.ts} +24 -1
- package/dist/{chunk-7GK3XEZF.js → chunk-7E7NXKQ5.js} +2 -2
- package/dist/chunk-7E7NXKQ5.js.map +1 -0
- package/dist/chunk-AIIPKVKO.js +3 -0
- package/dist/chunk-AIIPKVKO.js.map +1 -0
- package/dist/chunk-BAVZMGTZ.cjs +2 -0
- package/dist/chunk-BAVZMGTZ.cjs.map +1 -0
- package/dist/chunk-ESXQDRP7.js +2 -0
- package/dist/chunk-ESXQDRP7.js.map +1 -0
- package/dist/chunk-JFREB45J.cjs +3 -0
- package/dist/chunk-JFREB45J.cjs.map +1 -0
- package/dist/chunk-L7ZQQ773.cjs +5 -0
- package/dist/chunk-L7ZQQ773.cjs.map +1 -0
- package/dist/{chunk-ZCNBT44X.cjs → chunk-LNZNJSRW.cjs} +2 -2
- package/dist/chunk-LNZNJSRW.cjs.map +1 -0
- package/dist/chunk-NNYMXK6H.js +5 -0
- package/dist/chunk-NNYMXK6H.js.map +1 -0
- package/dist/{chunk-6C6IPUBH.cjs → chunk-PBGPQM3X.cjs} +3 -3
- package/dist/{chunk-6C6IPUBH.cjs.map → chunk-PBGPQM3X.cjs.map} +1 -1
- package/dist/{chunk-7NXAZJDB.js → chunk-PXWOATTF.js} +3 -3
- package/dist/{chunk-7NXAZJDB.js.map → chunk-PXWOATTF.js.map} +1 -1
- package/dist/constants.cjs +1 -1
- package/dist/constants.d.cts +1 -1
- package/dist/constants.d.ts +1 -1
- package/dist/constants.js +1 -1
- package/dist/engine.cjs +1 -1
- package/dist/engine.d.cts +5 -5
- package/dist/engine.d.ts +5 -5
- package/dist/engine.js +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +4 -4
- package/dist/index.d.ts +4 -4
- package/dist/index.js +1 -1
- package/dist/language.d.cts +3 -3
- package/dist/language.d.ts +3 -3
- package/dist/packages.cjs +1 -1
- package/dist/packages.d.cts +11 -2
- package/dist/packages.d.ts +11 -2
- package/dist/packages.js +1 -1
- package/dist/resolvers.cjs +1 -1
- package/dist/resolvers.d.cts +14 -0
- package/dist/resolvers.d.ts +14 -0
- package/dist/resolvers.js +1 -1
- package/dist/testing.cjs +2 -2
- package/dist/testing.d.cts +3 -3
- package/dist/testing.d.ts +3 -3
- package/dist/testing.js +1 -1
- package/dist/worker.cjs +2 -2
- package/dist/worker.d.cts +2 -2
- package/dist/worker.d.ts +2 -2
- package/dist/worker.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-7GK3XEZF.js.map +0 -1
- package/dist/chunk-E2Q3PQ2G.js +0 -3
- package/dist/chunk-E2Q3PQ2G.js.map +0 -1
- package/dist/chunk-KVTOV3TZ.js +0 -2
- package/dist/chunk-KVTOV3TZ.js.map +0 -1
- package/dist/chunk-OVKDDTXO.cjs +0 -3
- package/dist/chunk-OVKDDTXO.cjs.map +0 -1
- package/dist/chunk-U2UZJX5W.cjs +0 -5
- package/dist/chunk-U2UZJX5W.cjs.map +0 -1
- package/dist/chunk-X3R7B7XM.cjs +0 -2
- package/dist/chunk-X3R7B7XM.cjs.map +0 -1
- package/dist/chunk-YU3PACLE.js +0 -5
- package/dist/chunk-YU3PACLE.js.map +0 -1
- package/dist/chunk-ZCNBT44X.cjs.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/api/PackageCompatibility.ts","../src/api/SemverRange.ts","../src/api/EngineVersionCompatibility.ts","../src/engine/EngineSnapshot.ts","../src/cache/LineCache.ts","../src/vm/HolidayCalendar.ts","../src/engine/BackgroundRefreshManager.ts","../src/telemetry/AllocationTracker.ts","../src/engine/ExpressionEngineSafety.ts","../src/packages/uom/UserUnitTable.ts","../src/packages/uom/normalizer/UserUnitNormalizerRule.ts","../src/explain/LineExplainer.ts","../src/engine/ExpressionEngine.ts","../src/workers/engine.worker.ts","../src/engine/ExecutionPool.ts","../src/engine/AsyncResolutionBatcher.ts"],"names":["collectParseletConflicts","kind","fieldName","existingPkg","candidate","out","existingEntries","candidateEntries","existingTypes","tokenType","checkOnePackagePair","conflicts","phrase","existingTokenType","name","key","n","existingNames","r","rule","existingVocab","candidateVocab","word","op","existingNamespaces","resolver","category","existingCategory","checkPackageCompatibility","existing","c","VERSION_CORE","NUMERIC_PART","coerceVersion","input","match","compare","a","b","parseParts","text","parts","nums","i","caret","upper","tilde","parseComparator","token","v","opMatch","parseRange","range","clauses","orClause","tokens","comparators","parsed","isValidRange","satisfiesComparator","version","comparator","ordering","satisfies","clause","checkEngineVersionCompatibility","pkg","engineVersion","ENGINE_VERSION","comparableVersion","assertEngineVersionCompatible","result","ErrorFactory","SNAPSHOT_FORMAT","SNAPSHOT_VERSION","encodeNumber","decodeNumber","SnapshotErrorCodes","serializeDecimal","d","deserializeDecimal","serializeRational","deserializeRational","valueTypeName","type","ValueType","unsupportedValue","where","serializeValue","value","raw","m","data","cell","serializeMatrixCell","deserializeValue","sv","Value","serializeBytecode","program","serializeUserFunction","deserializeBytecode","sb","deserializeUserFunction","fn","assertRestorable","snapshot","LineCacheEntry","bytecode","readVariables","writeVariable","LineCache","_LineCache","expression","line","exprKey","entries","entry","callback","localDateKey","epochMs","month","day","entryToKey","resolveHolidayPredicate","calendar","keys","valuesDiffer","previous","next","prevUnit","nextUnit","BackgroundRefreshManager","_BackgroundRefreshManager","dag","enqueue","packageId","queryKey","registration","id","timer","still","e","AllocationTracker","stage","opts","startMem","startTime","endTime","endMem","wallTimeNs","allocBytes","alloc","telemetry","title","lines","aggregate","agg","totalAllocBytes","sum","t","totalWallNs","fastPathCount","stageMap","allocations","wallTimes","count","s","percentile","stages","fastPath","totalWallTimeNs","sorted","p","index","lower","fraction","checkExpressionLength","config","err","numberValue","checkExpressionComplexity","functionCallCount","nestingDepth","maxParens","complexityScore","isVarName","isUnitLiteralContext","prev","findMatchingRParenIdx","openIdx","depth","collectFunctionParamNames","excluded","closeIdx","j","extractReadsAndWrites","reads","writes","functionParamNames","globalDagKey","varName","isEmptyLine","lineText","sharedLexer","findInlineSolvesInLine","lineNumber","pluralInsensitiveKey","words","last","singular","UserUnitTable","nameWords","ratioText","baseUnit","length","definition","userUnitExpansionRule","table","priority","pos","maxWords","matched","star","LexerToken","tokenTypeId","ratio","unit","SUM","PRODUCT","EXPONENT","ON_OFF","infixBindingPower","TokenTypes","connective","tokenEnd","OPERAND_TOKEN_TYPES","isBoundary","Parser","node","minBindingPower","left","bindingPower","rightBindingPower","right","first","signStart","sawSign","group","end","open","inner","close","Builder","source","evaluate","locale","getLocale","root","cached","formatted","formatValue","DEFAULT_FORMATTING_SETTINGS","buildExplanation","params","terminal","steps","_ExpressionEngine","options","DependencyGraph","ScopeManager","ResolverRegistry","BytecodeBuilder","diagnostics","packages","mergeEngineConfig","DEFAULT_CONFIG","Lexer","buildTokenLookup","ParseletRegistry","createEngineContext","DiagnosticPipeline","TimelineDiagnosticCollector","TokenNormalizer","BUILTIN_PHRASES","implicitMultiplyRule","pkgList","engineError","normalizeUnknownError","PrecedenceParser","createVM","createQueryClient","AsyncResolutionBatcher","doc","scan","state","sr","variable","bound","symbolicTolerant","targetLine","errorValue","frame","stackBefore","executeBytecode","maxEntries","oldest","compatibility","conflict","contribution","parselet","handler","pluginFunctionIndexFor","registerTokenCategory","registerAsConverter","packageName","namespace","unregisterTokenCategory","unregisterAsConverter","ruleName","tracePipeline","traceExpression","controller","abortLocal","abortLogger","setActiveQueryClient","pending","pendingValue","signal","effectivePackageId","error","asyncCheck","maxLines","countLines","scanResults","processedLines","solve","reports","documentText","previousBatchScanResults","previousBatchParsedLines","scanResult","startPosition","endPosition","isEmpty","inlineSolves","hasInlineSolves","parsedLine","isVariableAssignment","errorMessage","contentOffset","values","preTokenized","hasParens","builder","allowLabelFallback","leftover","labelIsAllNumeric","literal","names","equation","factorValues","combined","product","matrixMultiply","inv","inverse","rhsValue","ratioToken","baseToken","stringValue","nameTok","opTok","isName","isCompound","rhs","accTokens","createFusedToken","normalizedTokens","beforeTokens","scalar","solved","containsSymbolicCall","eqIdx","rhsTokens","freeVar","factorNames","lhsTokens","unknowns","lhs","solveEquationValues","onToken","onFusion","lengthCheck","exprTokens","complexityCheck","symbolicResult","compoundReadsWrites","compound","cachedProgram","parserAlloc","parseResult","preflightController","abortPreflight","preflightSignal","prep","preflight","freezeIfDev","inputType","inlineSolveMatch","label","icon","colorClass","stepNumber","elapsedNs","skipped","output","pipeline","hasCollectors","parseletsBefore","trackEnabled","stageAllocs","zeroElapsed","DiagnosticEventType","lexResult","tokenTypes","inlineSolveSpans","endIdx","et","fusionCount","normalizerFusions","normalizerRuleCounts","fusion","cachedBefore","emptyProgram","hasAsyncGuard","emitVmTrace","vmResult","isPending","resultValue","resultType","rawDebug","debug","lineParselets","lineParseCategories","evalResult","items","pkgItems","lineCacheEntries","colonIdx","expressionPart","asyncCache","q","status","checkpointer","cp","normalized","EngineError","trimmed","getActiveQueryClient","dagSnapshot","asyncLines","lineEntries","latestWriter","isAsync","writeVar","variables","userFunctions","lineCache","bytecodeCache","engine","def","newValue","affectedLines","updated","ExpressionEngine","engine_worker_default","compileEngine","getCompileEngine","executeVm","getExecuteVm","sharedOpRegistry","compileOne","item","base","eng","isVariableDef","opcodes","numbers","opcodesBuffer","numbersBuffer","handleCompileBatch","msg","results","transferList","executeOne","vmm","val","handleExecuteBatch","inWorkerScope","handleMessage","event","WORKER_BATCH_TIMEOUT_MS","WORKER_OFFLOAD_THRESHOLD","ExecutionPool","poolSize","orderedLineNumbers","opcodesClone","numbersClone","batchId","worker","resolve","timeoutId","batch","w","reconstructValue","hexValue","bigIntValue","datetimeValue","percentageValue","uomValue","boolValue","_AsyncResolutionBatcher","vm","highWaterMark","dedup","deduped","compositeKey","errorEntries","okEntries","allAffected","allQueryKeys","allEntries","affected","ordered","entryMap","inDegree","adjacency","producerOf","readVar","producer","queue","degree","current","downstream","newDegree","remaining","workerResults","updatedLineNumbers","wr"],"mappings":"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","file":"chunk-L7ZQQ773.cjs","sourcesContent":["import type { IEnginePackage } from \"@solve-js/api/PackageRegistry\";\n\n/**\n * Package load-time compatibility checking, the \"detect overlapping\n * logic between packages\" SDK surface.\n *\n * This engine's package system (`IEnginePackage`) has always had SOME\n * collision visibility, but it's inconsistent and scattered: `ParseletRegistry`\n * warns on a token-type overwrite, `asConverterRegistry` warns on a converter\n * name overwrite, and `PhraseTrie` warns on... nothing at all, a second\n * package fusing the exact same multi-word phrase to a different token type\n * silently wins with zero signal, the same class of gap\n * `ParseletRegistry.registerPrefix()`'s collision-visibility fix closed for\n * parselets specifically (see `ARCHITECTURE.md`'s punch list). And none of\n * these existing checks can be run BEFORE registration, they only fire at\n * the moment a collision actually happens, deep inside a live engine.\n *\n * `checkPackageCompatibility()` is a single, pure, side-effect-free function\n * that statically compares one candidate package's declared descriptor\n * against a list of already-registered packages' descriptors, across every\n * collision-capable field `IEnginePackage` has, callable standalone (a host\n * building a plugin marketplace could run it before ever constructing an\n * engine) or wired into registration itself (see\n * `ExpressionEngine.registerPackage()`, which calls this automatically and\n * logs every conflict found, the \"load-up resiliency\" half of this\n * mechanism).\n *\n * A real, concrete motivating bug (found the same session this module was\n * built): the currency package's real `IEnginePackage` descriptor\n * (`CurrencyPackage.ts`) and its parallel test-harness registration helper\n * (`parselets/index.ts`'s `registerCurrencyParselets()`) drifted out of sync\n *, new currency-symbol token types were wired into one but not the other\n * caught only by a test happening to exercise the stale path. This module\n * doesn't catch THAT specific class of bug (two hand-written registration\n * functions for the same logical package diverging is a source-consistency\n * problem, not a runtime collision), but it DOES catch the more common and\n * more dangerous sibling: two DIFFERENT, independently-authored packages\n * unknowingly claiming the same token type, phrase, converter name, plugin\n * function index, or lexer keyword.\n */\n\n/** How serious a detected conflict is. */\nexport type CompatibilitySeverity = \"error\" | \"warning\" | \"info\";\n\n/** The category of overlap detected between two packages. */\nexport type CompatibilityConflictKind =\n | \"prefixParseletTokenType\"\n | \"infixParseletTokenType\"\n | \"phrase\"\n | \"converterName\"\n | \"pluginFunctionName\"\n | \"lexerKeyword\"\n | \"lexerOperator\"\n | \"asyncResolverNamespace\"\n | \"tokenCategory\"\n | \"normalizerRuleName\";\n\n/** One way two packages collide, for example claiming the same keyword. */\nexport interface CompatibilityConflict {\n kind: CompatibilityConflictKind;\n severity: CompatibilitySeverity;\n /** Human-readable description, safe to log directly. */\n detail: string;\n /** The two package names involved, [existing, candidate]. */\n packages: [string, string];\n}\n\n/** Every conflict found between a candidate package and those already registered. */\nexport interface CompatibilityReport {\n /** `false` iff at least one \"error\"-severity conflict was found. */\n compatible: boolean;\n conflicts: CompatibilityConflict[];\n}\n\nfunction collectParseletConflicts(\n kind: \"prefixParseletTokenType\" | \"infixParseletTokenType\",\n fieldName: \"prefixParselets\" | \"infixParselets\",\n existingPkg: IEnginePackage,\n candidate: IEnginePackage,\n out: CompatibilityConflict[],\n): void {\n const existingEntries = existingPkg[fieldName];\n const candidateEntries = candidate[fieldName];\n if (!existingEntries || !candidateEntries) return;\n const existingTypes = new Set(Object.keys(existingEntries));\n for (const tokenType of Object.keys(candidateEntries)) {\n if (existingTypes.has(tokenType)) {\n out.push({\n kind,\n // A different parselet INSTANCE silently wins at registration time\n // (matches ParseletRegistry.registerPrefix/registerInfix's own\n // \"warn on a genuinely different instance, stay quiet on idempotent\n // re-registration\" behavior), flagged as a warning, not an error\n // since deliberate override is sometimes the intended use (a\n // package explicitly built to replace a built-in's grammar).\n severity: \"warning\",\n detail: `Both \"${existingPkg.name}\" and \"${candidate.name}\" register a ${fieldName === \"prefixParselets\" ? \"prefix\" : \"infix\"} parselet for token type \"${tokenType}\" — the later-registered one silently wins.`,\n packages: [existingPkg.name, candidate.name],\n });\n }\n }\n}\n\nfunction checkOnePackagePair(existingPkg: IEnginePackage, candidate: IEnginePackage): CompatibilityConflict[] {\n const conflicts: CompatibilityConflict[] = [];\n\n collectParseletConflicts(\"prefixParseletTokenType\", \"prefixParselets\", existingPkg, candidate, conflicts);\n collectParseletConflicts(\"infixParseletTokenType\", \"infixParselets\", existingPkg, candidate, conflicts);\n\n // Phrases, the ONE category with zero pre-existing runtime warning\n // anywhere (PhraseTrie silently overwrites on an exact-key collision).\n if (existingPkg.phrases && candidate.phrases) {\n for (const [phrase, tokenType] of Object.entries(candidate.phrases)) {\n const existingTokenType = existingPkg.phrases[phrase];\n if (existingTokenType !== undefined && existingTokenType !== tokenType) {\n conflicts.push({\n kind: \"phrase\",\n severity: \"warning\",\n detail: `Both \"${existingPkg.name}\" (-> \"${existingTokenType}\") and \"${candidate.name}\" (-> \"${tokenType}\") fuse the phrase \"${phrase}\" to DIFFERENT token types — PhraseTrie has no collision detection of its own, so the later-registered mapping silently wins with no other signal.`,\n packages: [existingPkg.name, candidate.name],\n });\n }\n }\n }\n\n // asConverters, mirrors registerAsConverter()'s own runtime warning, but\n // callable before either package is ever registered.\n if (existingPkg.asConverters && candidate.asConverters) {\n for (const name of Object.keys(candidate.asConverters)) {\n const key = name.toLowerCase();\n if (Object.keys(existingPkg.asConverters).some((n) => n.toLowerCase() === key)) {\n conflicts.push({\n kind: \"converterName\",\n severity: \"warning\",\n detail: `Both \"${existingPkg.name}\" and \"${candidate.name}\" register an \"as ${name}\" converter — the later-registered handler silently wins.`,\n packages: [existingPkg.name, candidate.name],\n });\n }\n }\n }\n\n // pluginFunctions are keyed by a package-local name; the engine assigns the\n // registry index at registration (pluginFunctionIndexFor), so two packages\n // can no longer collide on a hardcoded index, so the old error class is gone.\n // They CAN name a function the same, and the engine's name->index map is\n // last-registration-wins, so warn (as with the parselet/converter overrides).\n if (existingPkg.pluginFunctions && candidate.pluginFunctions) {\n const existingNames = new Set(Object.keys(existingPkg.pluginFunctions));\n for (const name of Object.keys(candidate.pluginFunctions)) {\n if (existingNames.has(name)) {\n conflicts.push({\n kind: \"pluginFunctionName\",\n severity: \"warning\",\n detail: `Both \"${existingPkg.name}\" and \"${candidate.name}\" register a plugin function named \"${name}\" — the later registration wins in the engine's name-to-index map. Give each package's functions package-unique names.`,\n packages: [existingPkg.name, candidate.name],\n });\n }\n }\n }\n\n // normalizerRules, keyed by `name`. TokenNormalizer.unregister() removes\n // EVERY rule whose name matches, so two packages sharing a rule name means\n // unregistering one silently drops the other's rule too. (Rule ORDER is not\n // checked: rules compose by their explicit `priority` and the normalizer's\n // multi-pass loop, not by registration order, so distinct names + distinct\n // priorities is the contract, not list position.)\n if (existingPkg.normalizerRules && candidate.normalizerRules) {\n const existingNames = new Set(existingPkg.normalizerRules.map((r) => r.name));\n for (const rule of candidate.normalizerRules) {\n if (existingNames.has(rule.name)) {\n conflicts.push({\n kind: \"normalizerRuleName\",\n severity: \"warning\",\n detail: `Both \"${existingPkg.name}\" and \"${candidate.name}\" register a normalizer rule named \"${rule.name}\" — the normalizer unregisters rules by name, so removing either package would drop both rules. Give each package's rules a package-unique name.`,\n packages: [existingPkg.name, candidate.name],\n });\n }\n }\n }\n\n // Lexer keywords/operators, a word/symbol can only mean ONE token type.\n // `units` is deliberately NOT checked here: units live in a Set, and two\n // packages both recognizing the same unit WORD is harmless/idempotent\n // (there's no \"which token type wins\" ambiguity the way there is for a\n // keyword->tokenType or operator->tokenType mapping).\n const existingVocab = existingPkg.lexerVocabulary;\n const candidateVocab = candidate.lexerVocabulary;\n if (existingVocab?.keywords && candidateVocab?.keywords) {\n for (const [word, tokenType] of Object.entries(candidateVocab.keywords)) {\n const existingTokenType = existingVocab.keywords[word];\n if (existingTokenType !== undefined && existingTokenType !== tokenType) {\n conflicts.push({\n kind: \"lexerKeyword\",\n severity: \"error\",\n detail: `Both \"${existingPkg.name}\" (-> \"${existingTokenType}\") and \"${candidate.name}\" (-> \"${tokenType}\") register the lexer keyword \"${word}\" for DIFFERENT token types — whichever package registers second wins, and the loser's grammar becomes silently unreachable for that word.`,\n packages: [existingPkg.name, candidate.name],\n });\n }\n }\n }\n if (existingVocab?.operators && candidateVocab?.operators) {\n for (const [op, tokenType] of Object.entries(candidateVocab.operators)) {\n const existingTokenType = existingVocab.operators[op];\n if (existingTokenType !== undefined && existingTokenType !== tokenType) {\n conflicts.push({\n kind: \"lexerOperator\",\n severity: \"error\",\n detail: `Both \"${existingPkg.name}\" (-> \"${existingTokenType}\") and \"${candidate.name}\" (-> \"${tokenType}\") register the lexer operator \"${op}\" for DIFFERENT token types.`,\n packages: [existingPkg.name, candidate.name],\n });\n }\n }\n }\n\n // Async resolver namespaces, ResolverRegistry is keyed by namespace;\n // the JSDoc on IEnginePackage.asyncResolvers already states \"each\n // resolver must have a unique namespace\" as a hard requirement.\n if (existingPkg.asyncResolvers && candidate.asyncResolvers) {\n const existingNamespaces = new Set(existingPkg.asyncResolvers.map((r) => r.namespace));\n for (const resolver of candidate.asyncResolvers) {\n if (existingNamespaces.has(resolver.namespace)) {\n conflicts.push({\n kind: \"asyncResolverNamespace\",\n severity: \"error\",\n detail: `Both \"${existingPkg.name}\" and \"${candidate.name}\" register an async resolver under the namespace \"${resolver.namespace}\" — ResolverRegistry is keyed by namespace, so one resolver's cache/preflight state will silently clobber the other's.`,\n packages: [existingPkg.name, candidate.name],\n });\n }\n }\n }\n\n // Token categories. Same token type, different highlight category.\n // Cosmetic only (doesn't break parsing/evaluation), so \"info\" not\n // \"warning\"/\"error\", but still worth surfacing, since a silently-wrong\n // highlight color is exactly the kind of thing that's invisible until a\n // user notices their editor coloring looks off.\n if (existingPkg.tokenCategories && candidate.tokenCategories) {\n for (const [tokenType, category] of Object.entries(candidate.tokenCategories)) {\n const existingCategory = existingPkg.tokenCategories[tokenType];\n if (existingCategory !== undefined && existingCategory !== category) {\n conflicts.push({\n kind: \"tokenCategory\",\n severity: \"info\",\n detail: `Both \"${existingPkg.name}\" (-> \"${existingCategory}\") and \"${candidate.name}\" (-> \"${category}\") declare a highlight category for token type \"${tokenType}\" — cosmetic only, but the later registration wins.`,\n packages: [existingPkg.name, candidate.name],\n });\n }\n }\n }\n\n return conflicts;\n}\n\n/**\n * Statically check `candidate` against every package in `existing` for\n * overlapping/conflicting declarations, across every collision-capable\n * field `IEnginePackage` has. Pure and side-effect-free, does not touch\n * any shared registry, does not require a live `ExpressionEngine`.\n *\n * @example\n * ```ts\n * const report = checkPackageCompatibility(myNewPackage, BUILTIN_PACKAGES);\n * if (!report.compatible) {\n * for (const c of report.conflicts) console.error(c.detail);\n * }\n * ```\n */\nexport function checkPackageCompatibility(\n candidate: IEnginePackage,\n existing: IEnginePackage[],\n): CompatibilityReport {\n const conflicts: CompatibilityConflict[] = [];\n for (const existingPkg of existing) {\n if (existingPkg === candidate || existingPkg.name === candidate.name) continue;\n conflicts.push(...checkOnePackagePair(existingPkg, candidate));\n }\n return {\n compatible: !conflicts.some((c) => c.severity === \"error\"),\n conflicts,\n };\n}\n","/**\n * A small semver-range checker, enough for engine-version package gating.\n *\n * Replaces a dependency on `semver` that backed a single caret/range check in\n * {@link EngineVersionCompatibility}. The whole of `semver`'s named-import slice\n * pulled into the bundle for that one use; this covers the range grammar a\n * package's declared `engineVersion` actually uses, and nothing more:\n *\n * - exact `1.2.0`,\n * - caret `^1.2.0` (with node-semver's documented `0.x` narrowing: `^0.1.0` is\n * `>=0.1.0 <0.2.0`, `^0.0.3` is `>=0.0.3 <0.0.4`),\n * - tilde `~1.2.0` (`>=1.2.0 <1.3.0`),\n * - comparators `>=`, `<=`, `>`, `<`, `=`,\n * - AND by whitespace (`>=0.2.0 <1.0.0`) and OR by `||`,\n * - the `*` / `x` wildcard.\n *\n * Anything it cannot parse is reported invalid rather than guessed at, so a\n * typo in a package's own descriptor surfaces as a distinct error (see\n * {@link EngineVersionCompatibility}). Prerelease and build tails are not part\n * of the grammar: {@link coerceVersion} drops them, so a `1.0.0-beta.0` engine\n * is compared as the `1.0.0` release it presents the API of.\n */\n\n/** A `[major, minor, patch]` version, with any prerelease/build tail dropped. */\nexport type SemverVersion = readonly [number, number, number];\n\ntype Op = \"<\" | \"<=\" | \">\" | \">=\" | \"=\";\ninterface Comparator {\n\treadonly op: Op;\n\treadonly v: SemverVersion;\n}\n\nconst VERSION_CORE = /(\\d+)\\.(\\d+)\\.(\\d+)/;\nconst NUMERIC_PART = /^\\d+$/;\n\n/**\n * Parse a version to `[major, minor, patch]`, ignoring any prerelease or build\n * tail so `1.0.0-beta.0` reads as `1.0.0`. Returns `null` when no\n * `major.minor.patch` core is present.\n */\nexport function coerceVersion(input: string): SemverVersion | null {\n\tconst match = VERSION_CORE.exec(input.trim());\n\treturn match ? [Number(match[1]), Number(match[2]), Number(match[3])] : null;\n}\n\n/** Order two versions the semver way: major, then minor, then patch. */\nfunction compare(a: SemverVersion, b: SemverVersion): number {\n\treturn a[0] - b[0] || a[1] - b[1] || a[2] - b[2];\n}\n\n/**\n * Parse `major[.minor[.patch]]` with numeric parts only, missing parts filled\n * with 0. Returns `null` if any present part is not a number, so a non-version\n * token (`garbage`, `not`) is rejected rather than coerced.\n */\nfunction parseParts(text: string): SemverVersion | null {\n\tconst parts = text.split(\".\");\n\tif (parts.length === 0 || parts.length > 3) return null;\n\tconst nums = [0, 0, 0];\n\tfor (let i = 0; i < parts.length; i++) {\n\t\tif (!NUMERIC_PART.test(parts[i])) return null;\n\t\tnums[i] = Number(parts[i]);\n\t}\n\treturn [nums[0], nums[1], nums[2]];\n}\n\n/** `^a.b.c` -> `>=a.b.c` and the narrowed upper bound node-semver uses for 0.x. */\nfunction caret([a, b, c]: SemverVersion): Comparator[] {\n\tconst upper: SemverVersion = a > 0 ? [a + 1, 0, 0] : b > 0 ? [0, b + 1, 0] : [0, 0, c + 1];\n\treturn [\n\t\t{ op: \">=\", v: [a, b, c] },\n\t\t{ op: \"<\", v: upper },\n\t];\n}\n\n/** `~a.b.c` -> `>=a.b.c <a.(b+1).0`. */\nfunction tilde([a, b, c]: SemverVersion): Comparator[] {\n\treturn [\n\t\t{ op: \">=\", v: [a, b, c] },\n\t\t{ op: \"<\", v: [a, b + 1, 0] },\n\t];\n}\n\n/**\n * One whitespace-delimited token to the comparators it imposes (ALL must hold),\n * or `null` when it is not a recognised comparator. `*` / `x` / empty impose no\n * constraint (an empty comparator list, which every version satisfies).\n */\nfunction parseComparator(token: string): Comparator[] | null {\n\tif (token === \"\" || token === \"*\" || token === \"x\" || token === \"X\") return [];\n\tif (token[0] === \"^\") {\n\t\tconst v = parseParts(token.slice(1));\n\t\treturn v && caret(v);\n\t}\n\tif (token[0] === \"~\") {\n\t\tconst v = parseParts(token.slice(1));\n\t\treturn v && tilde(v);\n\t}\n\tconst opMatch = /^(>=|<=|>|<|=)/.exec(token);\n\tconst op = (opMatch ? opMatch[1] : \"=\") as Op;\n\tconst v = parseParts(opMatch ? token.slice(opMatch[1].length) : token);\n\treturn v && [{ op, v }];\n}\n\n/**\n * Parse a range into OR-clauses of AND-comparators, or `null` if any token is\n * unrecognised. A clause with no tokens (a bare `*` or empty string) is the\n * always-true clause.\n */\nfunction parseRange(range: string): Comparator[][] | null {\n\tconst clauses: Comparator[][] = [];\n\tfor (const orClause of range.split(\"||\")) {\n\t\tconst tokens = orClause.trim().split(/\\s+/).filter((token) => token !== \"\");\n\t\tconst comparators: Comparator[] = [];\n\t\tfor (const token of tokens) {\n\t\t\tconst parsed = parseComparator(token);\n\t\t\tif (parsed === null) return null;\n\t\t\tcomparators.push(...parsed);\n\t\t}\n\t\tclauses.push(comparators);\n\t}\n\treturn clauses;\n}\n\n/**\n * Whether `range` is a range this checker can parse. A range it cannot parse is\n * reported invalid rather than treated as an unsatisfied constraint, so a typo\n * is distinguishable from a genuine version mismatch.\n */\nexport function isValidRange(range: string): boolean {\n\treturn parseRange(range.trim()) !== null;\n}\n\n/** Whether a version satisfies one primitive comparator. */\nfunction satisfiesComparator(version: SemverVersion, comparator: Comparator): boolean {\n\tconst ordering = compare(version, comparator.v);\n\tswitch (comparator.op) {\n\t\tcase \"<\":\n\t\t\treturn ordering < 0;\n\t\tcase \"<=\":\n\t\t\treturn ordering <= 0;\n\t\tcase \">\":\n\t\t\treturn ordering > 0;\n\t\tcase \">=\":\n\t\t\treturn ordering >= 0;\n\t\tcase \"=\":\n\t\t\treturn ordering === 0;\n\t}\n}\n\n/**\n * Whether `version` satisfies `range`. An unparseable range is not satisfied by\n * anything; callers that need to tell \"invalid range\" apart from \"valid range,\n * not satisfied\" check {@link isValidRange} first.\n */\nexport function satisfies(version: SemverVersion, range: string): boolean {\n\tconst clauses = parseRange(range.trim());\n\tif (clauses === null) return false;\n\treturn clauses.some((clause) => clause.every((comparator) => satisfiesComparator(version, comparator)));\n}\n","import { satisfies, isValidRange, coerceVersion } from \"@solve-js/api/SemverRange\";\nimport type { IEnginePackage } from \"@solve-js/api/PackageRegistry\";\nimport { ENGINE_VERSION } from \"@solve-js/constants/version\";\nimport { ErrorFactory } from \"@solve-js/errors/UnifiedErrorFramework\";\n\n/**\n * Engine-version package compatibility gating, the \"reject a package built\n * for a different engine version\" SDK surface.\n *\n * This is a DIFFERENT kind of check from `api/PackageCompatibility.ts`'s\n * `checkPackageCompatibility()`, and deliberately kept in its own module\n * rather than folded into that one. `checkPackageCompatibility()` answers\n * \"do these two SIMULTANEOUSLY-registered packages' declared fields\n * collide\" and its contract, pure, package-vs-package, every conflict\n * including \"error\" severity is advisory, the caller always just logs and\n * proceeds, is locked in by its own regression suite and stated explicitly\n * in `ExpressionEngine.registerPackage()`'s comments. This module answers a\n * different question, \"can THIS package's declared engine-version range\n * run against the engine that's actually running RIGHT NOW\", and, unlike\n * every other compatibility signal in this codebase, a mismatch here is a\n * hard REJECTION, not a warning. Mixing that blocking behavior into\n * `checkPackageCompatibility()`'s report type would be a footgun for any\n * future reader who's learned (correctly, until now) that every conflict\n * that module can produce stays advisory.\n *\n * `checkEngineVersionCompatibility()` is the pure predicate (mirrors\n * `checkPackageCompatibility()`'s \"return a result, caller decides\" shape,\n * and this codebase's own testing convention of asserting against plain\n * result objects rather than `toThrow()` for a pure function).\n * `assertEngineVersionCompatible()` is the thin throwing wrapper\n * `ExpressionEngine.registerPackage()` calls as the very first thing it\n * does. See `ARCHITECTURE.md` §5.3.\n */\n\nexport type EngineVersionCheckResult =\n | { compatible: true }\n | { compatible: false; reason: \"range-not-satisfied\"; declaredRange: string; engineVersion: string }\n | { compatible: false; reason: \"invalid-range\"; declaredRange: string; engineVersion: string };\n\n/**\n * Pure, side-effect-free. Returns `{ compatible: true }` when `pkg` declares\n * no `engineVersion` at all (no constraint = always allowed, preserves\n * every package that predates this field), when the declared range is\n * satisfied by `engineVersion`, or a `{ compatible: false, reason, ... }`\n * result otherwise. A malformed/unparseable range string (a typo in the\n * package's own descriptor) is its own distinct `\"invalid-range\"` reason\n * never conflated with a genuine `\"range-not-satisfied\"` mismatch, so a\n * package author gets feedback about the actual problem they have.\n */\nexport function checkEngineVersionCompatibility(\n pkg: IEnginePackage,\n engineVersion: string = ENGINE_VERSION,\n): EngineVersionCheckResult {\n if (!pkg.engineVersion) return { compatible: true };\n\n if (!isValidRange(pkg.engineVersion)) {\n return { compatible: false, reason: \"invalid-range\", declaredRange: pkg.engineVersion, engineVersion };\n }\n\n // Compare against the release the prerelease is a prerelease OF, not the\n // prerelease string itself.\n //\n // Semver sorts 1.0.0-beta.0 BELOW 1.0.0, so it falls outside `^1.0.0` and a\n // package declaring that range would be rejected by the very beta meant to\n // ship its API. Coercing is the semantically right answer: 1.0.0-beta.N\n // presents the 1.0.0 API surface, which is the thing a package declares a\n // range against. `coerceVersion` drops the prerelease tail, so `^0.1.0` still\n // correctly rejects a 1.0.0 engine and 1.2.3 and 2.0.0 behave unchanged\n // against `^1.0.0`.\n const comparableVersion = coerceVersion(engineVersion);\n\n if (comparableVersion === null || !satisfies(comparableVersion, pkg.engineVersion)) {\n return { compatible: false, reason: \"range-not-satisfied\", declaredRange: pkg.engineVersion, engineVersion };\n }\n\n return { compatible: true };\n}\n\n/**\n * Throws an `EngineError` (`ErrorCategory.CONFIG`, matching the existing\n * precedent for `PLUGIN_KEYWORD_COLLISION`/`PLUGIN_OPERATOR_COLLISION`/\n * `PLUGIN_UNIT_COLLISION` in `lexer/ExpressionLexer.ts`, the only other\n * place in this codebase that hard-rejects a package at registration time)\n * when `pkg` is not engine-version compatible. Does nothing when compatible.\n */\nexport function assertEngineVersionCompatible(\n pkg: IEnginePackage,\n engineVersion: string = ENGINE_VERSION,\n): void {\n const result = checkEngineVersionCompatibility(pkg, engineVersion);\n if (result.compatible) return;\n\n if (result.reason === \"invalid-range\") {\n throw ErrorFactory.config({\n code: \"PACKAGE_ENGINE_VERSION_INVALID_RANGE\",\n message: `Package \"${pkg.name}\" declares an invalid engineVersion range: \"${result.declaredRange}\" is not a valid semver range.`,\n expected: `a valid semver range string (e.g. \"^0.1.0\", \">=0.2.0 <1.0.0\")`,\n found: `\"${result.declaredRange}\"`,\n suggestion: `This is a range-syntax typo in \"${pkg.name}\"'s own descriptor, not a version mismatch with the running engine — check for a stray character.`,\n context: { packageName: pkg.name, declaredRange: result.declaredRange },\n });\n }\n\n throw ErrorFactory.config({\n code: \"PACKAGE_ENGINE_VERSION_MISMATCH\",\n message: `Package \"${pkg.name}\" declares engineVersion \"${result.declaredRange}\", which is not satisfied by the running engine version \"${result.engineVersion}\".`,\n expected: `an engine version satisfying \"${result.declaredRange}\"`,\n found: `engine version \"${result.engineVersion}\"`,\n suggestion: `Update \"${pkg.name}\" to a version built against solve-engine ${result.engineVersion}, or pin solve-engine to a version satisfying \"${result.declaredRange}\".`,\n context: { packageName: pkg.name, declaredRange: result.declaredRange, engineVersion: result.engineVersion },\n });\n}\n","/**\n * Serialise and restore the state a session accumulates in memory.\n *\n * An engine builds up three things while it evaluates a document: named\n * variables, user-defined functions, and a per-line result/bytecode cache.\n * All three live only in memory, so a host that wants to persist a session,\n * warm-start a process, or move a document between contexts has to re-evaluate\n * the whole thing from scratch. This module turns that state into a plain,\n * JSON-safe object (see {@link EngineSnapshot}) and back again, so the host can\n * store it and rehydrate an engine that behaves as though it had evaluated the\n * document itself.\n *\n * What is deliberately NOT carried:\n * - Resolved async values (weather, stocks, currency, any package that fetches).\n * Those are point-in-time and must be re-fetched, not restored stale, so the\n * snapshot omits every line and variable backed by an async resolver. See\n * {@link ExpressionEngine.toJSON}, which filters them out before this module\n * ever sees them.\n * - Package-contributed state (a package's own caches or globals). Core state\n * only for now; a package opt-in is a follow-up. See the guide.\n *\n * JSON safety is the load-bearing contract here. `JSON.stringify` cannot encode\n * a `bigint` (it throws) and turns `NaN`/`Infinity` into `null` (a silent\n * corruption), and typed arrays round-trip as sparse objects rather than\n * arrays. Every value that crosses this boundary therefore goes through\n * {@link encodeNumber} (non-finite numbers become sentinel strings) or is\n * written as a decimal string (every `bigint`), and typed arrays are copied to\n * plain arrays. A snapshot produced here survives `JSON.stringify` followed by\n * `JSON.parse` unchanged.\n */\n\nimport { Value, ValueType, type MatrixData, type MatrixEntry } from \"@solve-js/vm/Value\";\nimport type { BytecodeProgram, UserFunctionDef, AnonymousBodyDef } from \"@solve-js/parser/BytecodeBuilder\";\nimport type { DecimalData } from \"@solve-js/decimal\";\nimport type { Rational } from \"@solve-js/symbolic\";\nimport { ErrorFactory } from \"@solve-js/errors/UnifiedErrorFramework\";\n\n/**\n * The magic string every snapshot carries, so a host handing `fromJSON` an\n * arbitrary object (a config file, a different tool's export) is refused with a\n * clear error rather than half-restored. See {@link assertRestorable}.\n */\nexport const SNAPSHOT_FORMAT = \"solve-engine/snapshot\" as const;\n\n/**\n * The snapshot layout version, bumped whenever the serialised shape changes in\n * a way an older reader cannot understand. `fromJSON` accepts only the exact\n * version it was built for and refuses anything else with a coded error, which\n * is the whole point of the field: a snapshot taken by a future (or older)\n * engine is rejected loudly instead of being restored wrongly. This is separate\n * from the engine's own semver (recorded alongside it as {@link\n * EngineSnapshot.engineVersion} for diagnostics), because the serialised shape\n * and the published API version do not have to move together.\n */\nexport const SNAPSHOT_VERSION = 1 as const;\n\n// ── JSON-safe number encoding ──────────────────────────────────────────────\n\n/**\n * A number as it appears in a snapshot: an ordinary JSON number when finite, or\n * a sentinel string when not. `JSON.stringify` writes `NaN`/`Infinity`/\n * `-Infinity` as `null`, which would silently turn a real `1/0` into an absent\n * value on the way back, so the three non-finite doubles are named instead.\n */\nexport type SerializedNumber = number | \"NaN\" | \"Infinity\" | \"-Infinity\";\n\n/** Encode a double for the snapshot, naming the non-finite ones (see {@link SerializedNumber}). */\nexport function encodeNumber(n: number): SerializedNumber {\n\tif (Number.isFinite(n)) return n;\n\tif (Number.isNaN(n)) return \"NaN\";\n\treturn n > 0 ? \"Infinity\" : \"-Infinity\";\n}\n\n/** Reverse {@link encodeNumber}. Throws {@link SnapshotErrorCodes.SNAPSHOT_MALFORMED} on an unrecognised sentinel. */\nexport function decodeNumber(n: SerializedNumber): number {\n\tif (typeof n === \"number\") return n;\n\tif (n === \"NaN\") return NaN;\n\tif (n === \"Infinity\") return Infinity;\n\tif (n === \"-Infinity\") return -Infinity;\n\tthrow ErrorFactory.validation({\n\t\tcode: SnapshotErrorCodes.SNAPSHOT_MALFORMED,\n\t\tmessage: `Snapshot holds an unrecognised number sentinel: ${JSON.stringify(n)}`,\n\t\texpected: `a JSON number, or one of \"NaN\", \"Infinity\", \"-Infinity\"`,\n\t\tfound: JSON.stringify(n),\n\t});\n}\n\n// ── Serialised shapes ──────────────────────────────────────────────────────\n\n/** {@link DecimalData} with its `bigint` coefficient written as a decimal string. */\nexport interface SerializedDecimal {\n\tcoef: string;\n\tscale: number;\n}\n\n/** {@link Rational} with both `bigint` components written as decimal strings. */\nexport interface SerializedRational {\n\tn: string;\n\td: string;\n}\n\n/**\n * A {@link Value} in JSON-safe form, discriminated by its {@link ValueType}\n * on the `t` field. Only the types a session can leave in a variable, a\n * function result, or a cached line are represented; {@link ValueType.Pending}\n * is filtered out upstream (an in-flight async result), and\n * {@link ValueType.Symbolic} plus symbolic matrix cells are refused with a\n * clear error (deferred, see the module doc).\n */\nexport type SerializedValue =\n\t| { t: ValueType.Number; v: SerializedNumber; exact?: SerializedDecimal; rational?: SerializedRational }\n\t| { t: ValueType.Hex; v: SerializedNumber | string; big?: boolean; base?: string }\n\t| { t: ValueType.BigInt; v: string }\n\t| { t: ValueType.String; v: string }\n\t| { t: ValueType.Datetime; v: SerializedNumber }\n\t| { t: ValueType.Percentage; v: SerializedNumber }\n\t| { t: ValueType.Uom; v: SerializedNumber; unit: string; exact?: SerializedDecimal }\n\t| { t: ValueType.Matrix; rows: number; cols: number; data: (SerializedNumber | boolean)[] }\n\t| { t: ValueType.Range; min: SerializedNumber; max: SerializedNumber }\n\t| { t: ValueType.Boolean; v: boolean }\n\t| { t: ValueType.Error; code: string; message: string };\n\n/** A {@link BytecodeProgram} with its typed arrays copied to plain arrays and non-finite constants named. */\nexport interface SerializedBytecode {\n\topcodes: number[];\n\tnumbers: SerializedNumber[];\n\tstrings: string[];\n\thasAsync: boolean;\n\tconstants?: [number, number][];\n\tuserFunctionBodies?: SerializedUserFunction[];\n\tanonymousBodies?: SerializedAnonymousBody[];\n}\n\n/** A {@link UserFunctionDef}: name, parameter names, and the body compiled to its own program. */\nexport interface SerializedUserFunction {\n\tname: string;\n\tparams: string[];\n\tprogram: SerializedBytecode;\n}\n\n/** An {@link AnonymousBodyDef}: a `map`/`reduce` inline transform body, a user function minus the name. */\nexport interface SerializedAnonymousBody {\n\tparams: string[];\n\tprogram: SerializedBytecode;\n}\n\n/** One cached line: the result, the compiled program, and the reads/writes the dependency graph needs. */\nexport interface SerializedLineCacheEntry {\n\tline: number;\n\t/** The expression text this entry is keyed under, or \"\" for an expressionless entry. Mirrors `LineCache`'s own two-level key. */\n\texpression: string;\n\tresult: SerializedValue;\n\tbytecode: SerializedBytecode;\n\treads: string[];\n\twriteVar: string | null;\n}\n\n/**\n * A complete, JSON-safe snapshot of an engine's session state.\n *\n * Produced by {@link ExpressionEngine.toJSON} and consumed by\n * {@link ExpressionEngine.fromJSON}. Safe to `JSON.stringify`, store, and\n * `JSON.parse` back into `fromJSON`.\n */\nexport interface EngineSnapshot {\n\t/** Always {@link SNAPSHOT_FORMAT}. Identifies the object as a snapshot before anything reads deeper. */\n\tformat: typeof SNAPSHOT_FORMAT;\n\t/** The serialised-shape version, {@link SNAPSHOT_VERSION} at write time. `fromJSON` refuses any other value. */\n\tversion: number;\n\t/** The engine's semver at write time, for diagnostics and forward compatibility decisions. Not itself a gate. */\n\tengineVersion: string;\n\t/** The locale the snapshot was taken under, so `fromJSON` can rebuild a matching lexer when the caller does not override it. */\n\tlocale: string;\n\t/** Named variables, by name. Async-backed and in-flight variables are omitted (see the module doc). */\n\tvariables: Record<string, SerializedValue>;\n\t/** User-defined functions (`f(x) = ...`). */\n\tuserFunctions: SerializedUserFunction[];\n\t/** Cached lines, minus any backed by an async resolver. */\n\tlineCache: SerializedLineCacheEntry[];\n\t/** The expression-keyed bytecode cache, a pure recompilation cache, carried so a warm start skips re-parsing unchanged expressions. */\n\tbytecodeCache: { expression: string; program: SerializedBytecode }[];\n}\n\n/**\n * The coded errors this module and `fromJSON` raise. Registered in\n * `errors/ErrorCode.ts` so the catalog test can see them.\n */\nexport const SnapshotErrorCodes = {\n\t/** The object handed to `fromJSON` is not a snapshot at all, or its version does not match this engine's reader. */\n\tSNAPSHOT_VERSION_MISMATCH: \"SNAPSHOT_VERSION_MISMATCH\",\n\t/** A snapshot with the right envelope but internally inconsistent contents (a bad number sentinel, a missing field). */\n\tSNAPSHOT_MALFORMED: \"SNAPSHOT_MALFORMED\",\n\t/** A value the snapshot format cannot yet represent (a symbolic expression, a symbolic matrix cell). Deferred, see the module doc. */\n\tSNAPSHOT_UNSUPPORTED_VALUE: \"SNAPSHOT_UNSUPPORTED_VALUE\",\n} as const;\n\n// ── Value serialisation ─────────────────────────────────────────────────────\n\nfunction serializeDecimal(d: DecimalData): SerializedDecimal {\n\treturn { coef: d.coef.toString(), scale: d.scale };\n}\n\nfunction deserializeDecimal(d: SerializedDecimal): DecimalData {\n\treturn { coef: BigInt(d.coef), scale: d.scale };\n}\n\nfunction serializeRational(r: Rational): SerializedRational {\n\treturn { n: r.n.toString(), d: r.d.toString() };\n}\n\nfunction deserializeRational(r: SerializedRational): Rational {\n\treturn { n: BigInt(r.n), d: BigInt(r.d) };\n}\n\n/** The label a caller sees when a value cannot be serialised, so the error names what it choked on rather than a bare enum number. */\nfunction valueTypeName(type: ValueType): string {\n\treturn ValueType[type] ?? String(type);\n}\n\nfunction unsupportedValue(type: ValueType, where: string): never {\n\tthrow ErrorFactory.validation({\n\t\tcode: SnapshotErrorCodes.SNAPSHOT_UNSUPPORTED_VALUE,\n\t\tmessage: `A ${valueTypeName(type)} value (${where}) cannot be included in a snapshot yet.`,\n\t\texpected: \"a concrete number, string, boolean, unit, range, matrix, bigint, or money value\",\n\t\tfound: `${valueTypeName(type)} value`,\n\t\tsuggestion: \"Symbolic (algebra) values are deferred to a follow-up. Evaluate the document without the symbolic line, or re-derive it after restoring.\",\n\t\tcontext: { valueType: type, location: where },\n\t});\n}\n\n/**\n * Turn a runtime {@link Value} into its JSON-safe form.\n *\n * @param value - The value to serialise.\n * @param where - A short human label for the value's origin (`variable \"x\"`, a\n * line number), folded into the error message when the type is unsupported so\n * the host learns which value refused rather than only that one did.\n * @throws {@link SnapshotErrorCodes.SNAPSHOT_UNSUPPORTED_VALUE} for a symbolic\n * value (or a symbolic matrix cell), the one class this v1 format defers.\n */\nexport function serializeValue(value: Value, where: string): SerializedValue {\n\tswitch (value.type) {\n\t\tcase ValueType.Number: {\n\t\t\tconst out: Extract<SerializedValue, { t: ValueType.Number }> = { t: ValueType.Number, v: encodeNumber(value.value as number) };\n\t\t\tif (value.exact !== undefined) out.exact = serializeDecimal(value.exact);\n\t\t\tif (value.rational !== undefined) out.rational = serializeRational(value.rational);\n\t\t\treturn out;\n\t\t}\n\t\tcase ValueType.Hex: {\n\t\t\tconst raw = value.value;\n\t\t\tif (typeof raw === \"bigint\") {\n\t\t\t\treturn { t: ValueType.Hex, v: raw.toString(), big: true, base: value.unit };\n\t\t\t}\n\t\t\treturn { t: ValueType.Hex, v: encodeNumber(raw as number), base: value.unit };\n\t\t}\n\t\tcase ValueType.BigInt:\n\t\t\treturn { t: ValueType.BigInt, v: (value.value as bigint).toString() };\n\t\tcase ValueType.String:\n\t\t\treturn { t: ValueType.String, v: value.value as string };\n\t\tcase ValueType.Datetime:\n\t\t\treturn { t: ValueType.Datetime, v: encodeNumber(value.value as number) };\n\t\tcase ValueType.Percentage:\n\t\t\treturn { t: ValueType.Percentage, v: encodeNumber(value.value as number) };\n\t\tcase ValueType.Uom: {\n\t\t\tconst out: Extract<SerializedValue, { t: ValueType.Uom }> = { t: ValueType.Uom, v: encodeNumber(value.value as number), unit: value.unit ?? \"\" };\n\t\t\tif (value.exact !== undefined) out.exact = serializeDecimal(value.exact);\n\t\t\treturn out;\n\t\t}\n\t\tcase ValueType.Matrix: {\n\t\t\tconst m = value.value as MatrixData;\n\t\t\tif (m.hasSymbolic) unsupportedValue(ValueType.Symbolic, `${where} (symbolic matrix cell)`);\n\t\t\tconst data = m.data.map((cell) => serializeMatrixCell(cell, where));\n\t\t\treturn { t: ValueType.Matrix, rows: m.rows, cols: m.cols, data };\n\t\t}\n\t\tcase ValueType.Range: {\n\t\t\tconst r = value.value as { min: number; max: number };\n\t\t\treturn { t: ValueType.Range, min: encodeNumber(r.min), max: encodeNumber(r.max) };\n\t\t}\n\t\tcase ValueType.Boolean:\n\t\t\treturn { t: ValueType.Boolean, v: value.value as boolean };\n\t\tcase ValueType.Error:\n\t\t\treturn { t: ValueType.Error, code: value.value as string, message: value.unit ?? \"\" };\n\t\tdefault:\n\t\t\t// Pending is filtered out before this function is called; Symbolic and\n\t\t\t// the lexer-only Unit type land here and are refused by name.\n\t\t\treturn unsupportedValue(value.type, where);\n\t}\n}\n\nfunction serializeMatrixCell(cell: MatrixEntry, where: string): SerializedNumber | boolean {\n\tif (typeof cell === \"boolean\") return cell;\n\tif (typeof cell === \"number\") return encodeNumber(cell);\n\t// The only remaining MatrixEntry variant is a SymbolicNode object, which the\n\t// hasSymbolic guard above should already have caught; this is the backstop.\n\treturn unsupportedValue(ValueType.Symbolic, `${where} (symbolic matrix cell)`);\n}\n\n/** Reverse {@link serializeValue}. Builds a fresh {@link Value}; never touches the arena, so it is safe to call outside evaluation. */\nexport function deserializeValue(sv: SerializedValue): Value {\n\tswitch (sv.t) {\n\t\tcase ValueType.Number: {\n\t\t\tconst v = new Value(ValueType.Number, decodeNumber(sv.v));\n\t\t\tif (sv.exact !== undefined) v.exact = deserializeDecimal(sv.exact);\n\t\t\tif (sv.rational !== undefined) v.rational = deserializeRational(sv.rational);\n\t\t\treturn v;\n\t\t}\n\t\tcase ValueType.Hex: {\n\t\t\tconst value = sv.big ? BigInt(sv.v as string) : decodeNumber(sv.v as SerializedNumber);\n\t\t\treturn new Value(ValueType.Hex, value, sv.base);\n\t\t}\n\t\tcase ValueType.BigInt:\n\t\t\treturn new Value(ValueType.BigInt, BigInt(sv.v));\n\t\tcase ValueType.String:\n\t\t\treturn new Value(ValueType.String, sv.v);\n\t\tcase ValueType.Datetime:\n\t\t\treturn new Value(ValueType.Datetime, decodeNumber(sv.v));\n\t\tcase ValueType.Percentage:\n\t\t\treturn new Value(ValueType.Percentage, decodeNumber(sv.v));\n\t\tcase ValueType.Uom: {\n\t\t\tconst v = new Value(ValueType.Uom, decodeNumber(sv.v), sv.unit);\n\t\t\tif (sv.exact !== undefined) v.exact = deserializeDecimal(sv.exact);\n\t\t\treturn v;\n\t\t}\n\t\tcase ValueType.Matrix: {\n\t\t\tconst data: MatrixEntry[] = sv.data.map((cell) => (typeof cell === \"boolean\" ? cell : decodeNumber(cell)));\n\t\t\t// hasSymbolic is always false: a symbolic matrix is refused at serialise\n\t\t\t// time, so anything restored here is purely numeric/boolean.\n\t\t\tconst m: MatrixData = { rows: sv.rows, cols: sv.cols, data, hasSymbolic: false };\n\t\t\treturn new Value(ValueType.Matrix, m);\n\t\t}\n\t\tcase ValueType.Range:\n\t\t\treturn new Value(ValueType.Range, { min: decodeNumber(sv.min), max: decodeNumber(sv.max) });\n\t\tcase ValueType.Boolean:\n\t\t\treturn new Value(ValueType.Boolean, sv.v);\n\t\tcase ValueType.Error:\n\t\t\treturn new Value(ValueType.Error, sv.code, sv.message);\n\t\tdefault:\n\t\t\tthrow ErrorFactory.validation({\n\t\t\t\tcode: SnapshotErrorCodes.SNAPSHOT_MALFORMED,\n\t\t\t\tmessage: `Snapshot holds a value with an unknown type tag: ${JSON.stringify((sv as { t: unknown }).t)}`,\n\t\t\t\texpected: \"a known SerializedValue type tag\",\n\t\t\t\tfound: JSON.stringify((sv as { t: unknown }).t),\n\t\t\t});\n\t}\n}\n\n// ── Bytecode serialisation ──────────────────────────────────────────────────\n\n/** Turn a compiled {@link BytecodeProgram} into its JSON-safe form, recursively for nested function and anonymous bodies. */\nexport function serializeBytecode(program: BytecodeProgram): SerializedBytecode {\n\tconst out: SerializedBytecode = {\n\t\topcodes: Array.from(program.opcodes),\n\t\tnumbers: Array.from(program.numbers, encodeNumber),\n\t\tstrings: program.strings.slice(),\n\t\thasAsync: program.hasAsync,\n\t};\n\tif (program.constants) out.constants = Array.from(program.constants.entries());\n\tif (program.userFunctionBodies) out.userFunctionBodies = program.userFunctionBodies.map(serializeUserFunction);\n\tif (program.anonymousBodies) {\n\t\tout.anonymousBodies = program.anonymousBodies.map((b) => ({ params: b.params.slice(), program: serializeBytecode(b.program) }));\n\t}\n\treturn out;\n}\n\n/** Reverse {@link serializeBytecode}, rebuilding the typed arrays and nested bodies. */\nexport function deserializeBytecode(sb: SerializedBytecode): BytecodeProgram {\n\tconst program: BytecodeProgram = {\n\t\topcodes: Uint8Array.from(sb.opcodes),\n\t\tnumbers: Float64Array.from(sb.numbers, decodeNumber),\n\t\tstrings: sb.strings.slice(),\n\t\thasAsync: sb.hasAsync,\n\t};\n\tif (sb.constants) program.constants = new Map(sb.constants);\n\tif (sb.userFunctionBodies) program.userFunctionBodies = sb.userFunctionBodies.map(deserializeUserFunction);\n\tif (sb.anonymousBodies) {\n\t\tprogram.anonymousBodies = sb.anonymousBodies.map((b): AnonymousBodyDef => ({ params: b.params.slice(), program: deserializeBytecode(b.program) }));\n\t}\n\treturn program;\n}\n\n/** Serialise one user-defined function, body and all. */\nexport function serializeUserFunction(fn: UserFunctionDef): SerializedUserFunction {\n\treturn { name: fn.name, params: fn.params.slice(), program: serializeBytecode(fn.program) };\n}\n\n/** Reverse {@link serializeUserFunction}. */\nexport function deserializeUserFunction(fn: SerializedUserFunction): UserFunctionDef {\n\treturn { name: fn.name, params: fn.params.slice(), program: deserializeBytecode(fn.program) };\n}\n\n// ── Envelope gating ─────────────────────────────────────────────────────────\n\n/**\n * Confirm an arbitrary object really is a snapshot this engine can restore, and\n * throw a clear, coded error otherwise.\n *\n * This is the \"refuse a snapshot from an incompatible engine rather than\n * restore it wrongly\" contract the feature was asked for. A missing/mismatched\n * {@link SNAPSHOT_FORMAT} or {@link SNAPSHOT_VERSION} is a hard rejection: a\n * snapshot written by a newer or older serialised shape could deserialise into\n * a subtly wrong engine, which is worse than not restoring at all.\n *\n * @param snapshot - The candidate, typed `unknown` because it typically arrives\n * straight from `JSON.parse` of untrusted storage.\n * @returns The same object, narrowed to {@link EngineSnapshot}, when it passes.\n * @throws {@link SnapshotErrorCodes.SNAPSHOT_VERSION_MISMATCH} when the envelope\n * is absent or its version differs from {@link SNAPSHOT_VERSION}.\n */\nexport function assertRestorable(snapshot: unknown): asserts snapshot is EngineSnapshot {\n\tif (typeof snapshot !== \"object\" || snapshot === null) {\n\t\tthrow ErrorFactory.validation({\n\t\t\tcode: SnapshotErrorCodes.SNAPSHOT_VERSION_MISMATCH,\n\t\t\tmessage: \"fromJSON was given something that is not a snapshot object.\",\n\t\t\texpected: `an object produced by ExpressionEngine.toJSON() with format \"${SNAPSHOT_FORMAT}\"`,\n\t\t\tfound: snapshot === null ? \"null\" : typeof snapshot,\n\t\t});\n\t}\n\n\tconst candidate = snapshot as Partial<EngineSnapshot>;\n\tif (candidate.format !== SNAPSHOT_FORMAT) {\n\t\tthrow ErrorFactory.validation({\n\t\t\tcode: SnapshotErrorCodes.SNAPSHOT_VERSION_MISMATCH,\n\t\t\tmessage: `This object is not a solve-engine snapshot (its \"format\" is ${JSON.stringify(candidate.format)}).`,\n\t\t\texpected: `format \"${SNAPSHOT_FORMAT}\"`,\n\t\t\tfound: JSON.stringify(candidate.format),\n\t\t});\n\t}\n\n\tif (candidate.version !== SNAPSHOT_VERSION) {\n\t\tthrow ErrorFactory.validation({\n\t\t\tcode: SnapshotErrorCodes.SNAPSHOT_VERSION_MISMATCH,\n\t\t\tmessage: `This snapshot was written for format version ${candidate.version}, but this engine restores version ${SNAPSHOT_VERSION}.`,\n\t\t\texpected: `snapshot version ${SNAPSHOT_VERSION}`,\n\t\t\tfound: `version ${candidate.version}`,\n\t\t\tsuggestion: \"Regenerate the snapshot with a matching engine version, or re-evaluate the document from source.\",\n\t\t\tcontext: { snapshotVersion: candidate.version, readerVersion: SNAPSHOT_VERSION, engineVersion: candidate.engineVersion },\n\t\t});\n\t}\n}\n","import { Value } from \"@solve-js/vm/Value\";\nimport { BytecodeProgram } from \"@solve-js/parser/BytecodeBuilder\";\n\n/**\n * One line's compiled bytecode, plus the variables it reads and writes.\n *\n * The reads and writes are what let the dependency graph re-evaluate only the\n * lines an edit actually affected.\n */\nexport class LineCacheEntry {\n constructor(\n public result: Value,\n public bytecode: BytecodeProgram,\n public readVariables: string[],\n public writeVariable: string | null\n ) {}\n}\n\n/**\n * Per-line result + bytecode cache.\n *\n * Entries are stored in a two-level map (line number → expression → entry)\n * so per-line operations, getEntryForLine, removeAllForLine, are O(1)\n * lookups instead of scans over every cached key. Entries with no\n * expression are stored under the empty-string key.\n *\n * The string keys exposed by keys()/forEach() keep the historical\n * \"line\" / \"line:expression\" format for diagnostics consumers.\n *\n * INVARIANT: at most one entry per line number at a time. `set()` stores\n * the expression alongside the entry ONLY as a same-key staleness check for\n * `get(line, expression)`, a line's previous text is never meaningfully\n * cacheable once the line has moved on, since `get()`/`getEntryForLine()`\n * are only ever called with the line's CURRENT text (see\n * `ExpressionEngine.reEvaluateLine()`). Before this invariant was enforced,\n * every distinct keystroke state of a line accumulated its own entry here\n * forever (nothing ever called `remove()`/`removeAllForLine()` per-edit,\n * only a full `clear()` on document switch), an unbounded, session-long\n * memory leak reachable via ordinary typing, and a latent correctness bug\n * in `getEntryForLine()`, which picks \"first in insertion order\" and could\n * silently return a STALE entry from an old edit of the line instead of\n * its current one once more than one entry had piled up.\n */\nexport class LineCache {\n /** line number → (expression, or \"\" for expressionless entries) → entry */\n private byLine: Map<number, Map<string, LineCacheEntry>> = new Map();\n private count = 0;\n\n private static exprKey(expression?: string): string {\n return expression ?? \"\";\n }\n\n private static displayKey(line: number, exprKey: string): string {\n return exprKey === \"\" ? `${line}` : `${line}:${exprKey}`;\n }\n\n get(line: number, expression?: string): LineCacheEntry | undefined {\n return this.byLine.get(line)?.get(LineCache.exprKey(expression));\n }\n\n /** Find any cache entry for the given line number, regardless of expression suffix */\n getEntryForLine(line: number): LineCacheEntry | undefined {\n const entries = this.byLine.get(line);\n if (!entries) return undefined;\n // First entry in insertion order, matches the historical scan behavior.\n for (const entry of entries.values()) {\n return entry;\n }\n return undefined;\n }\n\n set(line: number, entry: LineCacheEntry, expression?: string): void {\n let entries = this.byLine.get(line);\n if (!entries) {\n entries = new Map();\n this.byLine.set(line, entries);\n }\n const key = LineCache.exprKey(expression);\n // Enforce the one-entry-per-line invariant (see class doc comment):\n // any entry under a DIFFERENT expression key for this same line is for\n // text this line no longer has, drop it rather than let it pile up.\n if (entries.size > 0 && !entries.has(key)) {\n this.count -= entries.size;\n entries.clear();\n }\n if (!entries.has(key)) this.count++;\n entries.set(key, entry);\n }\n\n has(line: number, expression?: string): boolean {\n return this.byLine.get(line)?.has(LineCache.exprKey(expression)) ?? false;\n }\n\n remove(line: number, expression?: string): void {\n const entries = this.byLine.get(line);\n if (!entries) return;\n if (entries.delete(LineCache.exprKey(expression))) {\n this.count--;\n if (entries.size === 0) this.byLine.delete(line);\n }\n }\n\n removeAllForLine(line: number): void {\n const entries = this.byLine.get(line);\n if (!entries) return;\n this.count -= entries.size;\n this.byLine.delete(line);\n }\n\n clearLine(line: number): void {\n this.removeAllForLine(line);\n }\n\n /**\n * Number of entries in the cache. Useful for diagnostics.\n */\n get size(): number {\n return this.count;\n }\n\n clear(): void {\n this.byLine.clear();\n this.count = 0;\n }\n\n /**\n * Iterate all cache entries for diagnostics/debugging.\n */\n forEach(callback: (key: string, entry: LineCacheEntry) => void): void {\n for (const [line, entries] of this.byLine) {\n for (const [exprKey, entry] of entries) {\n callback(LineCache.displayKey(line, exprKey), entry);\n }\n }\n }\n\n /**\n * Structured iteration for serialization: one record per stored entry,\n * carrying the raw line number and expression key rather than the lossy\n * \"line:expression\" display key `keys()`/`forEach()` produce (an expression\n * containing a colon cannot be split back apart from that string). Used by\n * the engine snapshot to walk every entry without re-parsing display keys.\n */\n snapshotEntries(): { line: number; expression: string; entry: LineCacheEntry }[] {\n const out: { line: number; expression: string; entry: LineCacheEntry }[] = [];\n for (const [line, entries] of this.byLine) {\n for (const [exprKey, entry] of entries) {\n out.push({ line, expression: exprKey, entry });\n }\n }\n return out;\n }\n\n /**\n * Get all entry keys.\n */\n keys(): string[] {\n const result: string[] = [];\n for (const [line, entries] of this.byLine) {\n for (const exprKey of entries.keys()) {\n result.push(LineCache.displayKey(line, exprKey));\n }\n }\n return result;\n }\n}\n","/**\n * Turn a host's {@link HolidayCalendar} into the single `(epochMs) => boolean`\n * predicate the VM's business-day walk consults (see `vm/BusinessDays.ts`).\n *\n * A host can hand over either a function it already has, or a plain list of\n * dates. Both collapse to the same predicate here so the VM never has to know\n * which was given. No calendar resolves to `undefined`, which the VM reads as\n * weekends-only, the honest default described on `constants/Configuration.ts`'s\n * `date.holidays`.\n *\n * Dates are compared on their LOCAL calendar day, matching the rest of the\n * engine's date arithmetic (a date literal is local midnight). A `YYYY-MM-DD`\n * string is read as that calendar day directly, never through `new Date(str)`,\n * which would read a bare date as UTC and land on the previous day west of\n * Greenwich.\n */\n\nimport type { HolidayCalendar } from \"@solve-js/constants/Configuration\";\n\n/** `2024-12-25`, the key both a stored date and a queried instant reduce to. */\nfunction localDateKey(epochMs: number): string {\n\tconst d = new Date(epochMs);\n\tconst month = String(d.getMonth() + 1).padStart(2, \"0\");\n\tconst day = String(d.getDate()).padStart(2, \"0\");\n\treturn `${d.getFullYear()}-${month}-${day}`;\n}\n\n/** The local-day key for one calendar entry, or `null` if it is unreadable. A\n * string is matched on its leading `YYYY-MM-DD` so a full ISO timestamp works\n * too; a number is epoch milliseconds; a `Date` is taken as-is. */\nfunction entryToKey(entry: string | number | Date): string | null {\n\tif (entry instanceof Date) return localDateKey(entry.getTime());\n\tif (typeof entry === \"number\") {\n\t\treturn Number.isFinite(entry) ? localDateKey(entry) : null;\n\t}\n\tconst match = /^(\\d{4})-(\\d{2})-(\\d{2})/.exec(entry.trim());\n\tif (!match) return null;\n\treturn `${match[1]}-${match[2]}-${match[3]}`;\n}\n\n/**\n * Resolve a host calendar to the VM's holiday predicate.\n *\n * A function is wrapped so the VM can call it with an epoch rather than a\n * `Date`. A list is frozen into a `Set` of local-day keys once, here, so the\n * per-day membership test the walk runs thousands of times is a hash lookup,\n * not a re-scan of the list.\n *\n * @returns the predicate, or `undefined` for no calendar (weekends-only).\n */\nexport function resolveHolidayPredicate(\n\tcalendar: HolidayCalendar | undefined,\n): ((epochMs: number) => boolean) | undefined {\n\tif (calendar === undefined) return undefined;\n\n\tif (typeof calendar === \"function\") {\n\t\treturn (epochMs: number) => calendar(new Date(epochMs));\n\t}\n\n\tconst keys = new Set<string>();\n\tfor (const entry of calendar) {\n\t\tconst key = entryToKey(entry);\n\t\tif (key !== null) keys.add(key);\n\t}\n\t// An empty or all-unreadable list is still a configured calendar with no\n\t// holidays in it, which is a legitimate thing to say. It reads weekends-only\n\t// like the unconfigured case, but through a real (always-false) predicate.\n\treturn (epochMs: number) => keys.has(localDateKey(epochMs));\n}\n","/**\n * Proactive background refresh of live async values.\n *\n * The engine's async resolution is pull-based: a value refetches when a line is\n * re-evaluated (a keystroke) and it has gone stale. A note left open, showing a\n * live quote or an FX rate, holds whatever it last resolved. This manager closes\n * that gap for the values currently on screen: it drives a refetch on each\n * value's own cadence and, when the fresh result differs, asks the engine to\n * re-evaluate the affected lines, so the answer updates without the reader\n * touching the document.\n *\n * It is deliberately small, because query-core owns the fetching, dedup and\n * cache. This manager owns only the timers and the liveness bookkeeping:\n *\n * - **Only what is live.** A key stops refreshing the moment no line references\n * it any more (the reader edited that line away). Each tick checks the DAG\n * before fetching, so a stale key never reaches the network, and its timer\n * stops itself.\n * - **Back-pressure.** A tick that finds its own previous fetch still running\n * skips this round rather than stacking a second request on a slow source.\n * - **Off unless asked.** The engine constructs this only when the host has\n * enabled background refresh; otherwise no timers exist at all.\n *\n * The fresh value reaches the host through the engine's existing event stream\n * (the {@link enqueue} callback feeds the same batcher the pull path does), so a\n * host that already consumes `getEventStream()` needs no new wiring.\n */\nimport type { Value } from \"@solve-js/vm/Value\";\nimport type { DependencyGraph } from \"@solve-js/vm/DependencyGraph\";\n\n/** What a resolver hands the manager when a live value wants background refresh. */\nexport interface BackgroundRefreshRegistration {\n\t/** The package that owns the value, for the DAG lookup and the re-eval enqueue (`_engine` in practice). */\n\tpackageId: string;\n\t/** The value's cache key, as the batcher and DAG know it (e.g. `weather:current:london`). */\n\tqueryKey: string;\n\t/** How often to refetch, in ms. Must be positive; a non-positive value is ignored. */\n\tintervalMs: number;\n\t/** Force a fresh fetch and return the new value. Provided by the resolver. */\n\trefetch: () => Promise<Value>;\n}\n\ninterface LiveEntry extends BackgroundRefreshRegistration {\n\ttimer: ReturnType<typeof setInterval>;\n\t/** The last value pushed to the host, so an unchanged refetch does not trigger a needless re-render. */\n\tlastValue: Value | null;\n\t/** True while a refetch for this key is in flight, so a slow source does not stack requests. */\n\tinFlight: boolean;\n}\n\n/** Whether a refetched value differs from the last one pushed, enough to be worth a re-render. */\nfunction valuesDiffer(previous: Value | null, next: Value): boolean {\n\tif (!previous) return true;\n\tif (previous.type !== next.type) return true;\n\t// Scalars (a number, a temperature, a price, a description) carry their\n\t// answer in `value` and, for a unit, `unit`. A structured value (matrix,\n\t// colour) holds an object in `value`, where a fresh fetch is a new reference\n\t// and this reports a change, which is the safe direction: re-render rather\n\t// than risk showing a stale figure.\n\tif (previous.value !== next.value) return true;\n\tconst prevUnit = (previous as { unit?: unknown }).unit;\n\tconst nextUnit = (next as { unit?: unknown }).unit;\n\treturn prevUnit !== nextUnit;\n}\n\n/**\n * Owns the timers and liveness bookkeeping for proactive background refresh; see\n * the module comment above for the full picture. The engine constructs one only\n * when the host has enabled the feature, hands it the dependency graph and a\n * callback that re-evaluates a query's lines, and drives it through\n * {@link register} (start refreshing a value) and {@link clearAll} (stop\n * everything on teardown).\n */\nexport class BackgroundRefreshManager {\n\t/** Live entries, keyed by JSON.stringify([packageId, queryKey]), which is unambiguous whatever the query text. */\n\tprivate readonly entries = new Map<string, LiveEntry>();\n\n\t/**\n\t * @param dag - The engine's dependency graph, read to tell whether a key is still on screen.\n\t * @param enqueue - Called with `(packageId, queryKey)` when a background refetch produced a\n\t * changed value, to re-evaluate the lines that depend on it. Wired to the engine's batcher.\n\t */\n\tconstructor(\n\t\tprivate readonly dag: DependencyGraph,\n\t\tprivate readonly enqueue: (packageId: string, queryKey: string) => void,\n\t) {}\n\n\t/** Number of keys currently being polled. */\n\tget size(): number {\n\t\treturn this.entries.size;\n\t}\n\n\tprivate static idOf(packageId: string, queryKey: string): string {\n\t\treturn JSON.stringify([packageId, queryKey]);\n\t}\n\n\t/**\n\t * Start refreshing a live value on its cadence. Idempotent: a key already\n\t * being polled is left as it is (the first registration's cadence stands).\n\t */\n\tregister(registration: BackgroundRefreshRegistration): void {\n\t\tif (!(registration.intervalMs > 0)) return;\n\t\tconst id = BackgroundRefreshManager.idOf(registration.packageId, registration.queryKey);\n\t\tif (this.entries.has(id)) return;\n\n\t\tconst timer = setInterval(() => void this.tick(id), registration.intervalMs);\n\t\t// Node keeps its event loop alive for any pending timer; a background\n\t\t// refresher must not be the reason a process cannot exit. `unref` is\n\t\t// Node-only and browsers need no equivalent.\n\t\t(timer as unknown as { unref?: () => void }).unref?.();\n\n\t\tthis.entries.set(id, { ...registration, timer, lastValue: null, inFlight: false });\n\t}\n\n\tprivate async tick(id: string): Promise<void> {\n\t\tconst entry = this.entries.get(id);\n\t\tif (!entry) return;\n\t\t// Back-pressure: a previous refetch for this key is still running.\n\t\tif (entry.inFlight) return;\n\t\t// Liveness: no line references this value any more, so stop, before the\n\t\t// network is touched. This is what keeps an open note from leaking timers\n\t\t// and requests once the reader has edited a live line away.\n\t\tif (this.isDead(entry)) {\n\t\t\tthis.stop(id);\n\t\t\treturn;\n\t\t}\n\n\t\tentry.inFlight = true;\n\t\ttry {\n\t\t\tconst next = await entry.refetch();\n\t\t\t// The engine may have been cleared, or the key edited away, during the\n\t\t\t// fetch; re-read rather than trust the captured entry.\n\t\t\tconst still = this.entries.get(id);\n\t\t\tif (!still) return;\n\t\t\tif (next && valuesDiffer(still.lastValue, next)) {\n\t\t\t\tstill.lastValue = next;\n\t\t\t\tthis.enqueue(still.packageId, still.queryKey);\n\t\t\t}\n\t\t} catch {\n\t\t\t// A background refetch that throws is swallowed: the resolver's own\n\t\t\t// onError has already cached an honest error value, which the pull path\n\t\t\t// surfaces on the next re-evaluation. A timer callback must never throw.\n\t\t} finally {\n\t\t\tconst e = this.entries.get(id);\n\t\t\tif (e) e.inFlight = false;\n\t\t}\n\t}\n\n\tprivate isDead(entry: LiveEntry): boolean {\n\t\treturn this.dag.getAffectedLinesByDataSource(entry.packageId, [entry.queryKey]).size === 0;\n\t}\n\n\t/**\n\t * Stop polling every key no longer referenced by any line. Optional: each\n\t * tick already drops a dead key, so a key stops within one interval on its\n\t * own; calling this after an evaluation pass stops it at once instead.\n\t */\n\treconcile(): void {\n\t\tfor (const [id, entry] of this.entries) {\n\t\t\tif (this.isDead(entry)) this.stop(id);\n\t\t}\n\t}\n\n\tprivate stop(id: string): void {\n\t\tconst entry = this.entries.get(id);\n\t\tif (!entry) return;\n\t\tclearInterval(entry.timer);\n\t\tthis.entries.delete(id);\n\t}\n\n\t/** Stop every timer and forget every key. The manager is reusable afterwards (the engine survives clear()). */\n\tclearAll(): void {\n\t\tfor (const entry of this.entries.values()) clearInterval(entry.timer);\n\t\tthis.entries.clear();\n\t}\n}\n","// ── Allocation Tracker Telemetry Framework ─────────────────────────────────\n// Phase 1: Per-stage allocation + wall-time tracking for the 5-layer pipeline.\n//\n// Usage:\n// AllocationTracker.enable();\n// const { result, alloc } = AllocationTracker.track('lexer', () => lexer.tokenizeAll());\n// AllocationTracker.disable();\n//\n// Each track() call captures:\n// - Wall-clock time (via process.hrtime in Node.js, performance.now in browser)\n// - Heap delta (via process.memoryUsage in Node.js, unavailable in browser)\n// - Object counts (reserved for Phase 2+ with --expose-gc heap snapshots)\n//\n// Design principle: Zero overhead when disabled. The enabled flag is a static\n// boolean, a single branch that V8's JIT eliminates when allocation tracking\n// is disabled in production.\n\n\n// ── Types ─────────────────────────────────────────────────────────────────\n\n/** The pipeline stages allocation is attributed to. */\nexport type PipelineStage =\n | 'lexer'\n | 'normalizer'\n | 'parser'\n | 'resolver'\n | 'vm'\n | 'orchestrator';\n\n/** What one stage allocated during one measured span. */\nexport interface StageAllocation {\n /** Pipeline stage name. */\n stage: PipelineStage;\n /** Number of objects allocated (reserved, requires --expose-gc snapshots). */\n allocCount: number;\n /** Heap bytes allocated (delta of process.memoryUsage().heapUsed). */\n allocBytes: number;\n /** Breakdown of object types allocated (reserved, requires heap snapshots). */\n objectCounts: Record<string, number>;\n /** Wall-clock duration in nanoseconds. */\n wallTimeNs: number;\n /** Optional: sub-stage name for finer-grained tracking within a stage. */\n subStage?: string;\n /** Optional: whether this stage hit a cache (zero-parse, zero-lex). */\n cacheHit?: boolean;\n}\n\n/** Per-stage allocation for a single expression, in pipeline order. */\nexport interface PipelineTelemetry {\n /** The expression text that was evaluated. */\n expression: string;\n /** Per-stage allocation and timing data, in execution order. */\n stages: StageAllocation[];\n /** Total heap bytes allocated across all stages. */\n totalAllocBytes: number;\n /** Total wall-clock duration in nanoseconds. */\n totalWallTimeNs: number;\n /** Whether the expression took the orchestrator fast path. */\n fastPath: boolean;\n}\n\n/** Aggregate statistics across multiple pipeline runs. */\nexport interface StageAggregate {\n stage: PipelineStage;\n count: number;\n meanAllocBytes: number;\n meanWallTimeNs: number;\n minWallTimeNs: number;\n maxWallTimeNs: number;\n p50WallTimeNs: number;\n p95WallTimeNs: number;\n p99WallTimeNs: number;\n}\n\n// ── AllocationTracker ─────────────────────────────────────────────────────\n\n/**\n * Measures heap allocation per pipeline stage.\n *\n * A development tool: it reads `process.memoryUsage().heapUsed` around each\n * stage, which is only meaningful over the exact span it wraps. Widening a\n * measured span to cover more work does not measure more, it measures garbage\n * collection, and produces negative readings when a collection lands inside.\n */\nexport class AllocationTracker {\n /** Master kill-switch. Disabled in production, zero allocation overhead. */\n private static enabled: boolean = false;\n\n // ══ Lifecycle ═══════════════════════════════════════════════════════════\n\n /** Enable allocation tracking. Idempotent. */\n static enable(): void {\n this.enabled = true;\n }\n\n /** Disable allocation tracking. Idempotent. */\n static disable(): void {\n this.enabled = false;\n }\n\n /** Query whether tracking is currently enabled. */\n static isEnabled(): boolean {\n return this.enabled;\n }\n\n // ══ Core: Track a pipeline stage ═══════════════════════════════════════\n\n /**\n * Execute a function and capture allocation + wall-time data.\n *\n * When disabled, executes `fn()` with zero overhead (no measurements taken).\n * When enabled, captures heap delta via process.memoryUsage() (Node.js) and\n * wall-clock via process.hrtime() (Node.js) or performance.now() (browser).\n *\n * @param stage - Pipeline stage name (e.g., 'lexer', 'parser', 'vm').\n * @param fn - The pipeline stage function to execute and measure.\n * @param opts - Optional: sub-stage name and cache-hit flag.\n * @returns The function's result and the allocation/timing data.\n */\n static track<T>(\n stage: PipelineStage,\n fn: () => T,\n opts?: { subStage?: string; cacheHit?: boolean }\n ): { result: T; alloc: StageAllocation | null } {\n if (!this.enabled) {\n return { result: fn(), alloc: null };\n }\n\n // ══ Capture pre-execution state ══\n const startMem = typeof process !== 'undefined' && process.memoryUsage\n ? process.memoryUsage()\n : null;\n // hrtime() returns [seconds, nanoseconds]; performance.now() returns milliseconds\n const startTime = typeof process !== 'undefined' && process.hrtime\n ? process.hrtime()\n : performance.now();\n\n // ══ Execute the pipeline stage ══\n // Errors propagate naturally, track() must not swallow.\n const result = fn();\n\n // ══ Capture post-execution state ══\n const endTime = typeof process !== 'undefined' && process.hrtime\n ? process.hrtime(startTime as [number, number])\n : undefined;\n const endMem = typeof process !== 'undefined' && process.memoryUsage\n ? process.memoryUsage()\n : null;\n\n // Compute wall time:\n // Node.js: endTime is [seconds, nanoseconds] → convert to ns\n // Browser: endTime undefined, startTime is performance.now() → compute delta in ns\n const wallTimeNs: number = endTime\n ? endTime[0] * 1e9 + endTime[1]\n : (performance.now() - (startTime as number)) * 1e6;\n\n const allocBytes: number = startMem && endMem\n ? endMem.heapUsed - startMem.heapUsed\n : 0;\n\n const alloc: StageAllocation = {\n stage,\n allocCount: 0, // Reserved — requires --expose-gc heap snapshots (Phase 2+)\n allocBytes,\n objectCounts: {}, // Reserved — requires heap snapshots (Phase 2+)\n wallTimeNs,\n ...opts,\n };\n\n return { result, alloc };\n }\n\n // ══ Report Generation ══════════════════════════════════════════════════\n\n /**\n * Generate a markdown table from an array of PipelineTelemetry records.\n *\n * Aggregates by stage and outputs mean/min/max wall time, mean alloc bytes,\n * and p50/p95/p99 percentiles.\n *\n * @param telemetry - Array of pipeline telemetry records from multiple runs.\n * @param title - Optional title for the markdown section.\n * @returns A markdown-formatted string with per-stage and total aggregate tables.\n */\n static generateReport(telemetry: PipelineTelemetry[], title?: string): string {\n const lines: string[] = [];\n\n lines.push(title ? `## ${title}` : '## Pipeline Allocation Report');\n lines.push('');\n lines.push(`**Runs:** ${telemetry.length} | **Generated:** ${new Date().toISOString()}`);\n lines.push('');\n\n // Aggregate by stage\n const aggregate = this.aggregate(telemetry);\n\n if (aggregate.length === 0) {\n lines.push('_No telemetry data._');\n return lines.join('\\n');\n }\n\n // Per-stage table\n lines.push('### Per-Stage Breakdown');\n lines.push('');\n lines.push('| Stage | Count | Mean Wall (µs) | Mean Alloc (bytes) | Min (µs) | Max (µs) | p50 (µs) | p95 (µs) | p99 (µs) |');\n lines.push('|-------|:-----:|:--------------:|:------------------:|:--------:|:--------:|:--------:|:--------:|:--------:|');\n\n for (const agg of aggregate) {\n lines.push(\n `| ${agg.stage} | ${agg.count} | ` +\n `${(agg.meanWallTimeNs / 1000).toFixed(2)} | ` +\n `${agg.meanAllocBytes.toFixed(0)} | ` +\n `${(agg.minWallTimeNs / 1000).toFixed(2)} | ` +\n `${(agg.maxWallTimeNs / 1000).toFixed(2)} | ` +\n `${(agg.p50WallTimeNs / 1000).toFixed(2)} | ` +\n `${(agg.p95WallTimeNs / 1000).toFixed(2)} | ` +\n `${(agg.p99WallTimeNs / 1000).toFixed(2)} |`\n );\n }\n\n // Total stats\n const totalAllocBytes = telemetry.reduce((sum, t) => sum + t.totalAllocBytes, 0);\n const totalWallNs = telemetry.reduce((sum, t) => sum + t.totalWallTimeNs, 0);\n const fastPathCount = telemetry.filter(t => t.fastPath).length;\n\n lines.push('');\n lines.push('### Totals');\n lines.push('');\n lines.push(`- **Total wall time:** ${(totalWallNs / 1e6).toFixed(2)} ms (${telemetry.length} runs)`);\n lines.push(`- **Total heap allocated:** ${totalAllocBytes.toLocaleString()} bytes`);\n lines.push(`- **Fast-path runs:** ${fastPathCount}/${telemetry.length} (${((fastPathCount / telemetry.length) * 100).toFixed(0)}%)`);\n lines.push(`- **Mean per-run:** ${(totalWallNs / telemetry.length / 1000).toFixed(2)} µs, ${(totalAllocBytes / telemetry.length).toFixed(0)} bytes`);\n\n return lines.join('\\n');\n }\n\n /**\n * Aggregate PipelineTelemetry records by stage.\n *\n * Computes count, mean/min/max wall time, mean alloc bytes, and\n * p50/p95/p99 percentiles for each pipeline stage.\n */\n static aggregate(telemetry: PipelineTelemetry[]): StageAggregate[] {\n const stageMap = new Map<PipelineStage, StageAllocation[]>();\n\n // Collect all stage allocations by stage\n for (const t of telemetry) {\n for (const s of t.stages) {\n if (!stageMap.has(s.stage)) {\n stageMap.set(s.stage, []);\n }\n stageMap.get(s.stage)!.push(s);\n }\n }\n\n // Compute aggregates\n const result: StageAggregate[] = [];\n for (const [stage, allocations] of stageMap) {\n const wallTimes = allocations.map(a => a.wallTimeNs).sort((a, b) => a - b);\n const allocBytes = allocations.map(a => a.allocBytes);\n const count = allocations.length;\n\n result.push({\n stage,\n count,\n meanAllocBytes: allocBytes.reduce((s, v) => s + v, 0) / count,\n meanWallTimeNs: wallTimes.reduce((s, v) => s + v, 0) / count,\n minWallTimeNs: wallTimes[0],\n maxWallTimeNs: wallTimes[wallTimes.length - 1],\n p50WallTimeNs: percentile(wallTimes, 50),\n p95WallTimeNs: percentile(wallTimes, 95),\n p99WallTimeNs: percentile(wallTimes, 99),\n });\n }\n\n // Sort by stage name for consistent output\n result.sort((a, b) => a.stage.localeCompare(b.stage));\n return result;\n }\n\n /**\n * Create a PipelineTelemetry from a collection of StageAllocations.\n *\n * @param expression - The expression that was evaluated.\n * @param stages - Per-stage allocation data in execution order.\n * @param fastPath - Whether the orchestrator took the fast path.\n */\n static createTelemetry(\n expression: string,\n stages: StageAllocation[],\n fastPath: boolean = false\n ): PipelineTelemetry {\n const totalAllocBytes = stages.reduce((sum, s) => sum + s.allocBytes, 0);\n const totalWallTimeNs = stages.reduce((sum, s) => sum + s.wallTimeNs, 0);\n return { expression, stages, totalAllocBytes, totalWallTimeNs, fastPath };\n }\n}\n\n// ── Helpers ───────────────────────────────────────────────────────────────\n\n/**\n * Compute the nth percentile from a sorted array of numbers.\n * Uses linear interpolation between neighboring values.\n */\nfunction percentile(sorted: number[], p: number): number {\n if (sorted.length === 0) return 0;\n if (sorted.length === 1) return sorted[0];\n\n const index = (p / 100) * (sorted.length - 1);\n const lower = Math.floor(index);\n const upper = Math.ceil(index);\n if (lower === upper) return sorted[lower];\n\n const fraction = index - lower;\n return sorted[lower] * (1 - fraction) + sorted[upper] * fraction;\n}\n","import type { Token } from \"@solve-js/lexer/Token\";\nimport { InlineSolvePosition } from \"@solve-js/types/ParsingResult\";\nimport { ErrorFactory, type EngineError } from \"@solve-js/errors/UnifiedErrorFramework\";\nimport { numberValue, Value } from \"@solve-js/vm/Value\";\nimport { BytecodeProgram } from \"@solve-js/parser/BytecodeBuilder\";\n// Deliberately the shared lexer, not an engine's own.\n//\n// `classifyLine` and `findInlineSolves` are character-level scans for headings,\n// comment markers, code fences and backtick spans. Neither consults the\n// keyword, unit or operator tables, so every lexer returns the same answer and\n// there is nothing per-engine to respect. Pinned by\n// __tests__/lexer/LineClassificationIsVocabularyIndependent.spec.ts, which\n// compares a bare lexer against one carrying extra vocabulary.\n//\n// This matters because these are free functions with no engine to ask. Making\n// them engine-aware would mean changing their signatures and every caller for\n// no behavioural difference.\nimport { sharedLexer } from \"@solve-js/lexer/Lexer\";\nimport { globalDagKey } from \"@solve-js/vm/GlobalVariableStore\";\n\n// ── Validation config ────────────────────────────────────────────────────\n\n/** Bounds applied to input before parsing: length and nesting depth. */\nexport interface ValidationConfig {\n maxExpressionLength: number;\n maxComplexity: number;\n}\n\n// ── Safety result ─────────────────────────────────────────────────────────\n\n/** Whether input passed the safety bounds, and which one it failed. */\nexport interface SafetyCheckResult {\n passed: boolean;\n /**\n * `error.error` (a plain string) exists purely because it's spread\n * directly into `evaluateExpressionWithDiagnostic()`'s own return shape\n * (`{value, tokens, program, error?: string, ...}`), which deliberately\n * keeps errors as display strings for the debug/diagnostic pipeline\n * see that method's own doc comment. `error.engineError` is additive\n * (doesn't replace the string field, so existing consumers of this\n * exported type are unaffected): it carries the real EngineError this\n * check constructed internally, so callers that DO want the original\n * code/category/expected/found/suggestion (prepareExpression(), not the\n * diagnostic pipeline) don't have to reconstruct a generic one from just\n * the flattened message.\n */\n error?: { value: Value; tokens: Token[]; program: BytecodeProgram; error: string; engineError?: EngineError };\n}\n\n// ── Safety checks ─────────────────────────────────────────────────────────\n\n/**\n * Check that the expression doesn't exceed the maximum allowed length.\n */\nexport function checkExpressionLength(\n expression: string,\n config: ValidationConfig\n): SafetyCheckResult {\n if (expression.length > config.maxExpressionLength) {\n const err = ErrorFactory.validation(\n \"EXPRESSION_TOO_LONG\",\n `Expression exceeds max length of ${config.maxExpressionLength} characters (got ${expression.length})`,\n { expressionLength: expression.length, maxLength: config.maxExpressionLength }\n );\n return {\n passed: false,\n error: {\n value: numberValue(0),\n tokens: [],\n program: { opcodes: new Uint8Array(0), numbers: new Float64Array(0), strings: [], hasAsync: false },\n error: err.message,\n engineError: err,\n },\n };\n }\n return { passed: true };\n}\n\n/**\n * Score expression complexity based on token count, function calls, and nesting depth.\n * Returns the complexity score and whether it exceeds the configured maximum.\n */\nexport function checkExpressionComplexity(\n tokens: Token[],\n config: ValidationConfig\n): { passed: boolean; complexityScore: number; errorMessage?: string; engineError?: EngineError } {\n let functionCallCount = 0;\n let nestingDepth = 0;\n let maxParens = 0;\n for (const t of tokens) {\n if (t.type === \"FUNC\") functionCallCount++;\n if (t.value === \"(\" || t.type === \"LPAREN\") { nestingDepth++; maxParens = Math.max(maxParens, nestingDepth); }\n if (t.value === \")\" || t.type === \"RPAREN\") nestingDepth--;\n }\n const complexityScore = tokens.length + functionCallCount * 5 + maxParens * 10;\n if (complexityScore > config.maxComplexity) {\n const err = ErrorFactory.validation(\n \"EXPRESSION_TOO_COMPLEX\",\n `Expression complexity score ${complexityScore} exceeds maximum of ${config.maxComplexity}`,\n { complexity: complexityScore, maxComplexity: config.maxComplexity }\n );\n return { passed: false, complexityScore, errorMessage: err.message, engineError: err };\n }\n return { passed: true, complexityScore };\n}\n\n// ── Read/write extraction ─────────────────────────────────────────────────\n\n/**\n * Guard: true if the token is a valid variable name type.\n * Accepts both IDENT and UNIT tokens, UNIT occurs when the variable name\n * collides with a known unit (e.g., \"b\" for bits, \"s\" for seconds).\n */\nfunction isVarName(t: Token): boolean {\n return t.type === \"IDENT\" || t.type === \"UNIT\";\n}\n\n/**\n * True if a UNIT token at this position is being consumed as a\n * unit-of-measure literal rather than a variable reference, i.e. it's\n * immediately preceded by a value (NUMBER, a closing paren) or a\n * conversion keyword (TO, IN). This mirrors exactly where\n * UomLiteralParselet/ConvertParselet/PercentageChangeParselet accept a\n * UNIT token themselves: `500 EUR`, `(x + y) km`, `to JPY`, `in m`.\n * In all of these the compiler emits PUSH_STRING for the unit name, not\n * LOAD_VAR, so treating them as a DAG read is a false positive, the\n * classic case being any bare currency/unit conversion like\n * \"500 EUR to JPY\", which falsely reported \"EUR\" and \"JPY\" as variable\n * dependencies even though the compiled bytecode never loads a variable.\n */\nfunction isUnitLiteralContext(prev: Token): boolean {\n return prev.type === \"NUMBER\" || prev.type === \"TO\" || prev.type === \"IN\" || prev.type === \"RPAREN\";\n}\n\n/**\n * From an LPAREN token index, scan forward tracking paren depth and return\n * the index of the matching RPAREN, or `null` if unbalanced. Mirrors\n * `PrecedenceParser.ts`'s `findMatchingRParen`, necessarily duplicated\n * here since this file is a standalone, parser-instance-free static token\n * scan (same \"dead-code-but-must-stay-synced mirror\" pattern as\n * `NumberParselet.ts`).\n */\nfunction findMatchingRParenIdx(tokens: Token[], openIdx: number): number | null {\n let depth = 0;\n for (let i = openIdx; i < tokens.length; i++) {\n if (tokens[i].type === \"LPAREN\") depth++;\n else if (tokens[i].type === \"RPAREN\") {\n depth--;\n if (depth === 0) return i;\n }\n }\n return null;\n}\n\n/**\n * Pre-scan for user-defined-function DEFINITION shapes (`name(params) =\n * body`) to collect the set of PARAMETER names that must be excluded from\n * `reads`/`writes` in {@link extractReadsAndWrites} below. Without this, a\n * parameter name colliding with an unrelated document-level `:variable` of\n * the same name would register a spurious DAG dependency, `f(x) = 2*x+1`\n * must not depend on some unrelated `:x` defined elsewhere in the document,\n * and `x` itself must never be reported as a document-level WRITE (the\n * parameter isn't being assigned to at document scope at all). Scoped to a\n * single line's own token stream, matching how `extractReadsAndWrites` is\n * already called per-line, no cross-line interference with an unrelated\n * `:x` on a different line.\n */\nfunction collectFunctionParamNames(tokens: Token[]): Set<string> {\n const excluded = new Set<string>();\n for (let i = 0; i < tokens.length; i++) {\n if (!isVarName(tokens[i])) continue;\n if (i > 0 && tokens[i - 1].type === \"COLON\") continue; // :name(...) is a different grammar entirely\n if (tokens[i + 1]?.type !== \"LPAREN\") continue;\n const closeIdx = findMatchingRParenIdx(tokens, i + 1);\n if (closeIdx === null) continue;\n if (tokens[closeIdx + 1]?.type !== \"EQUALS\") continue; // a CALL, not a DEFINITION — no params to exclude\n for (let j = i + 2; j < closeIdx; j++) {\n if (isVarName(tokens[j])) excluded.add(tokens[j].value);\n }\n }\n return excluded;\n}\n\n/**\n * Extract variable reads and writes from a token stream.\n *\n * Handles both IDENT and UNIT tokens as potential variable references.\n * UNIT tokens occur when the variable name collides with a known unit\n * (e.g., \"b\" for bits, \"s\" for seconds). The colon prefix unambiguously\n * signals a variable definition context (handled by VariableParselet).\n * A standalone UNIT token is only a real variable reference when it\n * isn't in unit-literal position (see {@link isUnitLiteralContext})\n * otherwise it's a quantity/conversion unit name, never LOAD_VAR'd.\n *\n * Also detects user-defined-function DEFINITIONS (`name(params) = body`)\n * as a read+write of the function's own name, mirroring `:name = value`'s\n * existing convention of registering the defined name as both, and\n * excludes the definition's own PARAMETER names from reads/writes\n * entirely (see {@link collectFunctionParamNames}). A function CALL\n * (`name(args)`, no trailing `=`) needs no special detection: the call's\n * own name falls through to the ordinary bare-identifier read-tracking\n * below, the same as any other `LOAD_VAR`-producing identifier. This is\n * already correct once calls compile successfully, no change needed.\n */\nexport function extractReadsAndWrites(tokens: Token[]): { reads: string[]; writes: string[] } {\n const reads: string[] = [];\n const writes: string[] = [];\n const functionParamNames = collectFunctionParamNames(tokens);\n\n for (let i = 0; i < tokens.length; i++) {\n const t = tokens[i];\n if (t.type === \"GLOBAL\") {\n // global :name [= expr], GLOBAL, COLON, IDENT/UNIT are three\n // separate tokens (matching GlobalVariableParselet). Emit a\n // \"global:\"-prefixed synthetic name into THIS document's own\n // DAG (via globalDagKey) so a local :hello and global :hello\n // never collide in this document's own reads/writes tracking\n // the bare-COLON branch below explicitly skips the colon that\n // follows GLOBAL, since it's handled here instead.\n if (i + 2 < tokens.length && tokens[i + 1].type === \"COLON\" && isVarName(tokens[i + 2])) {\n const key = globalDagKey(tokens[i + 2].value);\n reads.push(key);\n if (i + 3 < tokens.length && tokens[i + 3].type === \"EQUALS\") {\n writes.push(key);\n }\n }\n continue;\n }\n if (t.type === \"COLON\") {\n // Skip. This colon belongs to a `global :name` sequence\n // already handled by the GLOBAL branch above.\n if (i > 0 && tokens[i - 1].type === \"GLOBAL\") continue;\n // The moo lexer produces COLON as a bare \":\" token. The variable\n // name follows as a separate IDENT or UNIT token (matching VariableParselet).\n if (i + 1 < tokens.length && isVarName(tokens[i + 1])) {\n const varName = tokens[i + 1].value;\n reads.push(varName);\n // Colon-prefix variable definition: :name = expr\n // COLON + IDENT/UNIT are separate tokens, so EQUALS is at i+2.\n if (i + 2 < tokens.length && tokens[i + 2].type === \"EQUALS\") {\n writes.push(varName);\n }\n }\n }\n if (isVarName(t)) {\n // Skip if already consumed by preceding COLON handler above.\n if (i > 0 && tokens[i - 1].type === \"COLON\") continue;\n // Skip UNIT tokens acting as a quantity/conversion unit name\n // rather than a variable (see isUnitLiteralContext above).\n if (t.type === \"UNIT\" && i > 0 && isUnitLiteralContext(tokens[i - 1])) continue;\n // A user-defined-function's own PARAMETER name, never a\n // document-level read or write (see collectFunctionParamNames).\n if (functionParamNames.has(t.value)) continue;\n // A user-defined-function DEFINITION's own name: `name(params) =\n // body`. Registered as both a read and a write, mirroring\n // `:name = value`'s existing convention just below.\n if (tokens[i + 1]?.type === \"LPAREN\") {\n const closeIdx = findMatchingRParenIdx(tokens, i + 1);\n if (closeIdx !== null && tokens[closeIdx + 1]?.type === \"EQUALS\") {\n reads.push(t.value);\n writes.push(t.value);\n continue;\n }\n // else: a CALL (or malformed), falls through below, same as\n // any other bare identifier read.\n }\n reads.push(t.value);\n // Check if next token is EQUALS -> this is a write. A compound\n // assignment (`total += 5` / `total -= 5`) both reads and writes its\n // own name, so the read above stands and the write is added here too.\n const next = tokens[i + 1]?.type;\n if (next === \"EQUALS\" || next === \"PLUS_EQUALS\" || next === \"MINUS_EQUALS\") {\n writes.push(t.value);\n }\n }\n }\n return { reads, writes };\n}\n\n// ── Line classification ───────────────────────────────────────────────────\n\n/**\n * Check if a line is effectively empty (whitespace only or only markdown syntax).\n *\n * Phase B: Delegates to the ExpressionLexer's character-by-character\n * markdown line scanner, replacing the old regex-based heuristics.\n *\n * Skips lines that contain no evaluable expression:\n * - Whitespace-only lines\n * - Markdown structural markers (headings, blockquotes, lists without inline solves)\n * - Code block fences (```)\n * - MathJax block fences ($$)\n * - Table separator rows (|---|)\n * - Horizontal rules (---, ***, ___)\n * - Standalone wikilinks / embeds ([[...]], ![[...]])\n * - Whole-line comments (a line whose first non-whitespace characters are `//`)\n *\n * Lines containing inline solves (s\\`...\\`) are never considered empty.\n *\n * Note: a trailing `#`/`//` comment in the MIDDLE of an otherwise-evaluable\n * line does NOT make isEmptyLine() return true, that line is still an\n * \"expression\" line (skip: false). The comment is instead stripped at\n * tokenization time (ExpressionLexer's HASH/`//` handling emits a COMMENT\n * token for the rest of the line) and then filtered out of the token\n * stream by ExpressionEngine.prepareExpression() before parsing, so\n * `<expr> // note` evaluates identically to `<expr>` alone.\n */\nexport function isEmptyLine(lineText: string): boolean {\n const classification = sharedLexer.classifyLine(lineText);\n return classification.skip;\n}\n\n/**\n * Find all inline solves in a line with precise coordinate mapping.\n *\n * Phase B: Delegates to the ExpressionLexer's character-by-character\n * scanner (no regex, handles escaped backticks).\n */\nexport function findInlineSolvesInLine(lineText: string, lineNumber: number): InlineSolvePosition[] {\n const spans = sharedLexer.findInlineSolves(lineText);\n return spans.map(s => ({\n start: s.start,\n end: s.end,\n expression: s.expression,\n lineNumber,\n columnNumber: s.columnNumber,\n }));\n}\n","/**\n * Document-scoped user-defined units.\n *\n * A line like `1 sprint = 2 weeks` defines `sprint` as a dimensioned alias for\n * two weeks. Later lines resolve `6 sprints in days` by expanding the name back\n * to its definition, `6 * 2 weeks`, so every downstream feature (arithmetic,\n * `in`/`to` conversion, best-unit) reuses the built-in unit machinery unchanged.\n * Because the base is always a real built-in unit, a defined unit carries that\n * unit's dimension: `6 sprints in days` converts, and `6 sprints in kg` reports\n * incompatible units exactly as `weeks in kg` does.\n *\n * Scope is the document, not the process: the table lives on the engine and is\n * cleared at the start of each `parseDocument` pass, so definitions never leak\n * between documents and a renamed unit does not linger. This mirrors how a\n * user-defined function is scoped to the VM that parsed it.\n *\n * Names are matched case-sensitively (the whole unit system is, `C` is Celsius\n * and `c` is a cup) with a naive trailing-`s` plural, so `sprint` and `sprints`\n * resolve to the same definition and `story point` and `story points` likewise.\n */\n\n/** A resolved user-unit definition: `<ratio> <baseUnit>` per one of the unit. */\nexport interface UserUnitDefinition {\n /** The name as first written, for the `<name> defined` confirmation. */\n readonly displayName: string;\n /**\n * The multiplier, kept as the exact source text the lexer produced rather\n * than a parsed number, so re-emitting it into the token stream stays\n * locale-correct (a comma-decimal locale lexes `2,5`, and that is what must\n * be re-emitted).\n */\n readonly ratioText: string;\n /** The built-in unit the ratio is expressed in (e.g. `weeks`, `hours`). */\n readonly baseUnit: string;\n}\n\n/**\n * De-pluralized, space-joined lookup key for a unit name given as words.\n *\n * Only the final word loses a trailing `s`, so `story points` keys the same as\n * `story point`. Applied identically at definition and lookup, so a name whose\n * singular already ends in `s` still matches itself.\n */\nfunction pluralInsensitiveKey(words: readonly string[]): string {\n const last = words[words.length - 1];\n const singular = last.length > 1 && last.endsWith(\"s\") ? last.slice(0, -1) : last;\n return [...words.slice(0, -1), singular].join(\" \");\n}\n\n/** A registered name matched against a run of identifier tokens. */\nexport interface UserUnitMatch {\n /** The definition to expand to. */\n readonly definition: UserUnitDefinition;\n /** How many identifier words the name consumed (`story point` is 2). */\n readonly wordCount: number;\n}\n\n/** Per-engine, document-scoped store of user-defined units. */\nexport class UserUnitTable {\n private readonly byKey = new Map<string, UserUnitDefinition>();\n private longestName = 0;\n\n /** Whether any unit has been defined, a cheap guard for the hot path. */\n get isEmpty(): boolean {\n return this.byKey.size === 0;\n }\n\n /** The most words any registered name spans, bounding the lookup scan. */\n get maxWordCount(): number {\n return this.longestName;\n }\n\n /**\n * Register (or replace) a unit named by `nameWords`, defined as `ratioText`\n * of `baseUnit`. Re-defining a name overwrites the earlier definition, so a\n * corrected line wins over the one above it.\n */\n define(nameWords: readonly string[], ratioText: string, baseUnit: string): void {\n const key = pluralInsensitiveKey(nameWords);\n this.byKey.set(key, {\n displayName: nameWords.join(\" \"),\n ratioText,\n baseUnit,\n });\n if (nameWords.length > this.longestName) this.longestName = nameWords.length;\n }\n\n /**\n * Longest registered name that a run of identifier `words` begins with, or\n * `null` if none. `words` is the consecutive identifiers following a value,\n * so `story points each` matches the 2-word `story point` and leaves `each`.\n */\n match(words: readonly string[]): UserUnitMatch | null {\n const upper = Math.min(words.length, this.longestName);\n for (let length = upper; length >= 1; length--) {\n const definition = this.byKey.get(pluralInsensitiveKey(words.slice(0, length)));\n if (definition !== undefined) return { definition, wordCount: length };\n }\n return null;\n }\n\n /** Drop every definition, called when a fresh document pass begins. */\n clear(): void {\n this.byKey.clear();\n this.longestName = 0;\n }\n}\n","import type { NormalizerRule, NormalizerMatch } from \"@solve-js/normalizer/NormalizerRule\";\nimport type { Token } from \"@solve-js/lexer/Token\";\nimport { tokenTypeId } from \"@solve-js/lexer/Token\";\nimport { LexerToken } from \"@solve-js/lexer/ExpressionLexer\";\nimport type { UserUnitTable } from \"@solve-js/packages/uom/UserUnitTable\";\n\n/**\n * Expands a document-defined unit back to its definition so the built-in unit\n * machinery handles it: `6 sprints` becomes `6 * 2 weeks` once `1 sprint = 2\n * weeks` is in scope. The multiplication is what carries the dimension, so\n * `6 sprints in days` converts and `6 sprints in kg` reports incompatible units.\n *\n * Bound to the engine's own {@link UserUnitTable}, which is why it is wired in\n * ExpressionEngine rather than shipped in the shared UOM package descriptor: the\n * table is per-document state, and a package descriptor is shared across every\n * engine in the process. Reading the table is side-effect-free, so this stays a\n * pure normalizer rule (the registration side of the feature happens in the\n * engine's own definition-line handling, not here).\n *\n * Deliberately narrow, so a made-up unit name cannot shadow ordinary prose:\n *\n * - It fires only after a value (a NUMBER, or a closing paren), the way a unit\n * always attaches to a quantity. A bare `sprint` on its own is left as an\n * identifier, so a word that happens to match a definition is not rewritten\n * mid-sentence.\n * - It declines when the name is immediately followed by `=`, which is the\n * left side of a (re)definition, not a use.\n *\n * Runs above implicit multiply, so a matched name is expanded whole here rather\n * than first split into `value * name` with the name stranded as a variable.\n */\nexport function userUnitExpansionRule(table: UserUnitTable, priority = 82): NormalizerRule {\n return {\n name: \"uom:user-unit\",\n priority,\n match(tokens: Token[], pos: number): NormalizerMatch | null {\n // Nothing is defined on most lines, so bail before any scanning.\n if (table.isEmpty) return null;\n\n const value = tokens[pos];\n // A user unit attaches to a preceding value, exactly like a built-in one.\n if (value.type !== \"NUMBER\" && value.type !== \"RPAREN\") return null;\n\n // Gather the run of identifiers that could spell a multi-word name,\n // capped at the longest name actually registered.\n const words: string[] = [];\n const maxWords = table.maxWordCount;\n for (let i = pos + 1; i < tokens.length && words.length < maxWords; i++) {\n if (tokens[i].type !== \"IDENT\") break;\n words.push(tokens[i].value);\n }\n if (words.length === 0) return null;\n\n const matched = table.match(words);\n if (matched === null) return null;\n\n // `1 sprint = ...` is a definition's left side, not a use of `sprint`.\n const after = tokens[pos + 1 + matched.wordCount];\n if (after?.type === \"EQUALS\") return null;\n\n const { ratioText, baseUnit } = matched.definition;\n const star = new LexerToken(\"STAR\", tokenTypeId(\"STAR\"), \"*\", \"*\", value.offset, 0, value.line, value.col);\n const ratio = new LexerToken(\"NUMBER\", tokenTypeId(\"NUMBER\"), ratioText, ratioText, value.offset, 0, value.line, value.col);\n const unit = new LexerToken(\"UNIT\", tokenTypeId(\"UNIT\"), baseUnit, baseUnit, value.offset, 0, value.line, value.col);\n\n return {\n consumed: 1 + matched.wordCount,\n replacement: [value, star, ratio, unit],\n ruleName: \"uom:user-unit\",\n };\n },\n };\n}\n","import type { Token } from \"@solve-js/lexer/Token\";\nimport { TokenTypes } from \"@solve-js/lexer/Token\";\nimport type { Value } from \"@solve-js/vm/Value\";\nimport { formatValue } from \"@solve-js/format/FormatEngine\";\nimport { DEFAULT_FORMATTING_SETTINGS } from \"@solve-js/format/FormattingSettings\";\nimport { getLocale } from \"@solve-js/constants/locales\";\nimport type { Explanation, ExplanationStep } from \"./Explanation\";\n\n/**\n * Evaluate a standalone sub-expression and return its value.\n *\n * Supplied by the engine so the explainer reuses real evaluation rather than\n * re-deriving arithmetic: every value in a derivation is the value the engine\n * itself would compute for that piece of the line. It must be side-effect-free\n * with respect to document state (it is only ever handed self-contained\n * sub-expressions of the line being explained).\n */\nexport type EvaluateSpan = (source: string) => Value;\n\n/**\n * Binding powers for the operators the derivation understands, mirrored from\n * the engine's own parser (`parser/BindingPower.ts` and the built-in infix\n * table) so that node boundaries match how the line actually evaluates. A\n * mismatch here would not produce wrong values (each node is re-evaluated\n * through the engine), but it would group the steps in a way that misleads,\n * which is the one thing a derivation must not do.\n */\nconst SUM = 30;\nconst PRODUCT = 40;\nconst EXPONENT = 50;\n/**\n * `on`/`off` bind below arithmetic (the engine's `Conditional` level), so the\n * base is the whole arithmetic expression after the phrase: \"20% off 80 + 20\"\n * is \"20% off (80 + 20)\", not \"(20% off 80) + 20\".\n */\nconst ON_OFF = 24;\n\n/** Left binding power of an infix operator, or 0 when it is not one we derive. */\nfunction infixBindingPower(type: string): number {\n\tswitch (type) {\n\t\tcase TokenTypes.PLUS:\n\t\tcase TokenTypes.MINUS:\n\t\t\treturn SUM;\n\t\tcase TokenTypes.STAR:\n\t\tcase TokenTypes.SLASH:\n\t\tcase TokenTypes.MOD:\n\t\tcase TokenTypes.OF:\n\t\t\treturn PRODUCT;\n\t\tcase TokenTypes.CARET:\n\t\t\treturn EXPONENT;\n\t\tcase TokenTypes.PCT_ON:\n\t\tcase TokenTypes.PCT_OFF:\n\t\t\treturn ON_OFF;\n\t\tdefault:\n\t\t\treturn 0;\n\t}\n}\n\n/** The connective word shown between the two operands of a step. */\nfunction connective(type: string): string {\n\tswitch (type) {\n\t\tcase TokenTypes.PLUS:\n\t\t\treturn \"plus\";\n\t\tcase TokenTypes.MINUS:\n\t\t\treturn \"minus\";\n\t\tcase TokenTypes.STAR:\n\t\t\treturn \"times\";\n\t\tcase TokenTypes.SLASH:\n\t\t\treturn \"divided by\";\n\t\tcase TokenTypes.MOD:\n\t\t\treturn \"mod\";\n\t\tcase TokenTypes.CARET:\n\t\t\treturn \"to the power of\";\n\t\tcase TokenTypes.OF:\n\t\t\treturn \"of\";\n\t\tcase TokenTypes.PCT_ON:\n\t\t\treturn \"plus\";\n\t\tcase TokenTypes.PCT_OFF:\n\t\t\treturn \"less\";\n\t\tdefault:\n\t\t\treturn type.toLowerCase();\n\t}\n}\n\n// A parse node. `leaf` is a run of operand tokens (a number, \"$80\", \"5 km\",\n// \"20%\") shown by its source text. `binary` is an operation that becomes one\n// step. `wrap` is a parenthesised group or a signed group, transparent for step\n// emission but shown by its computed value when it stands as an operand.\ntype Node =\n\t| { kind: \"leaf\"; start: number; end: number }\n\t| { kind: \"binary\"; op: string; left: Node; right: Node; start: number; end: number }\n\t| { kind: \"wrap\"; child: Node; start: number; end: number };\n\n/**\n * End offset of a token in the original source, exclusive.\n *\n * A fused token (a normalized phrase like \"10 frames\") carries `sourceEnd`,\n * because its `value` no longer spans the text it came from; every other token's\n * value does, so its end is `offset + value.length`.\n */\nfunction tokenEnd(t: Token): number {\n\treturn t.sourceEnd ?? t.offset + t.value.length;\n}\n\n/**\n * Token types that make up an operand atom: a value literal or a reference to one\n * (a number, a unit or currency amount, a percentage, a variable, a constant, a\n * boolean). An operand run is the maximal span of these.\n *\n * The set is defined as what an operand *is*, not as what stops one, so anything\n * that is not operand material ends the run: every parenthesis, and every\n * operator, modelled or not. That is the point. An operator the derivation does\n * not model (`==`, `<`, `in`, `to`, `and`, a bitwise or conversion op) is left\n * unconsumed, {@link Parser.parseAll} then sees the leftover token and throws,\n * and the line falls back to reporting its answer with no steps, rather than\n * gluing the operator into a leaf and emitting a misleading arithmetic step whose\n * result is not even the arithmetic kind. Preferring no derivation to a wrong one\n * is the rule the whole slice obeys, so this errs toward the empty fallback: an\n * exotic operand kind left out here loses its breakdown, never its answer.\n */\nconst OPERAND_TOKEN_TYPES: ReadonlySet<string> = new Set([\n\tTokenTypes.NUMBER,\n\tTokenTypes.BIGINT,\n\tTokenTypes.IDENT,\n\tTokenTypes.UNIT,\n\tTokenTypes.PERCENT,\n\tTokenTypes.PI,\n\tTokenTypes.E,\n\tTokenTypes.TRUE,\n\tTokenTypes.FALSE,\n\tTokenTypes.DOLLAR,\n\tTokenTypes.POUND,\n\tTokenTypes.EURO,\n\tTokenTypes.YEN,\n\tTokenTypes.RUBLE,\n\tTokenTypes.WON,\n\tTokenTypes.CURRENCY_SYMBOL,\n]);\n\n/**\n * True for a token that cannot start or continue an operand run: any token that\n * is not operand material ({@link OPERAND_TOKEN_TYPES}). The modelled infix\n * operators and parentheses are boundaries under this rule, and so is every\n * operator the derivation does not model, which is what keeps an unmodelled tail\n * (`== 4`, `in kg`) out of a leaf instead of gluing it into a misleading step.\n */\nfunction isBoundary(type: string): boolean {\n\treturn !OPERAND_TOKEN_TYPES.has(type);\n}\n\n/**\n * A recursive-descent, precedence-climbing parser over the already-normalized\n * token stream, producing a small tree whose nodes each know the span of source\n * they cover. Only the shapes a readable arithmetic derivation needs are\n * modelled; anything else makes {@link parse} throw, and the caller falls back\n * to reporting the answer with no breakdown.\n */\nclass Parser {\n\tprivate pos = 0;\n\n\tconstructor(private readonly tokens: Token[]) {}\n\n\tprivate peek(): Token | undefined {\n\t\treturn this.tokens[this.pos];\n\t}\n\n\tprivate next(): Token {\n\t\treturn this.tokens[this.pos++];\n\t}\n\n\t/** Parse the whole stream, requiring every token to be consumed. */\n\tparseAll(): Node {\n\t\tconst node = this.parseExpression(0);\n\t\tif (this.pos !== this.tokens.length) {\n\t\t\t// Leftover tokens mean the line uses something this slice does not\n\t\t\t// model. Signal a fallback rather than guess at a grouping.\n\t\t\tthrow new Error(\"explain: unconsumed tokens\");\n\t\t}\n\t\treturn node;\n\t}\n\n\tprivate parseExpression(minBindingPower: number): Node {\n\t\tlet left = this.parseOperand();\n\n\t\tfor (;;) {\n\t\t\tconst t = this.peek();\n\t\t\tif (!t) break;\n\t\t\tconst bindingPower = infixBindingPower(t.type);\n\t\t\tif (bindingPower === 0 || bindingPower <= minBindingPower) break;\n\n\t\t\tthis.next(); // consume the operator\n\t\t\t// `^` is the only right-associative operator, matching the engine.\n\t\t\tconst rightBindingPower =\n\t\t\t\tt.type === TokenTypes.CARET ? bindingPower - 1 : bindingPower;\n\t\t\tconst right = this.parseExpression(rightBindingPower);\n\t\t\tleft = {\n\t\t\t\tkind: \"binary\",\n\t\t\t\top: t.type,\n\t\t\t\tleft,\n\t\t\t\tright,\n\t\t\t\tstart: left.start,\n\t\t\t\tend: right.end,\n\t\t\t};\n\t\t}\n\n\t\treturn left;\n\t}\n\n\t/** A parenthesised group, an optional sign, then a run of operand tokens. */\n\tprivate parseOperand(): Node {\n\t\tconst first = this.peek();\n\t\tif (!first) throw new Error(\"explain: expected an operand\");\n\n\t\tif (first.type === TokenTypes.LPAREN) {\n\t\t\treturn this.parseGroup();\n\t\t}\n\n\t\t// A leading sign belongs to the operand it precedes. When that operand\n\t\t// is a group (\"-(2 + 3)\") the sign wraps the group; otherwise it is just\n\t\t// the first character of a signed literal (\"-5\").\n\t\tconst signStart = first.offset;\n\t\tlet sawSign = false;\n\t\twhile (\n\t\t\tthis.peek() &&\n\t\t\t(this.peek()!.type === TokenTypes.PLUS || this.peek()!.type === TokenTypes.MINUS)\n\t\t) {\n\t\t\tthis.next();\n\t\t\tsawSign = true;\n\t\t}\n\n\t\tif (sawSign && this.peek() && this.peek()!.type === TokenTypes.LPAREN) {\n\t\t\tconst group = this.parseGroup();\n\t\t\treturn { kind: \"wrap\", child: group, start: signStart, end: group.end };\n\t\t}\n\n\t\t// Greedy operand run: everything up to the next operator or parenthesis.\n\t\tlet end = -1;\n\t\twhile (this.peek() && !isBoundary(this.peek()!.type)) {\n\t\t\tend = tokenEnd(this.next());\n\t\t}\n\t\tif (end === -1) {\n\t\t\t// No operand material at all (e.g. a stray operator). Fall back.\n\t\t\tthrow new Error(\"explain: expected an operand\");\n\t\t}\n\t\treturn { kind: \"leaf\", start: signStart, end };\n\t}\n\n\tprivate parseGroup(): Node {\n\t\tconst open = this.next(); // LPAREN\n\t\tconst inner = this.parseExpression(0);\n\t\tconst close = this.peek();\n\t\tif (!close || close.type !== TokenTypes.RPAREN) {\n\t\t\tthrow new Error(\"explain: unbalanced parentheses\");\n\t\t}\n\t\tthis.next(); // RPAREN\n\t\treturn { kind: \"wrap\", child: inner, start: open.offset, end: tokenEnd(close) };\n\t}\n}\n\n/**\n * Turn a parse tree into an ordered derivation.\n *\n * Values come from re-evaluating each operation's own span through the engine,\n * cached per node so a span is never evaluated twice. Descriptions read an\n * operand as its source text when it is a literal, or as its running value when\n * it is the result of the steps above it.\n */\nclass Builder {\n\tprivate readonly steps: ExplanationStep[] = [];\n\tprivate readonly resultPrefix: string;\n\n\tconstructor(\n\t\tprivate readonly source: string,\n\t\tprivate readonly evaluate: EvaluateSpan,\n\t\tlocale: string,\n\t) {\n\t\tthis.resultPrefix = getLocale(locale).display.resultPrefix;\n\t}\n\n\tbuild(root: Node): { steps: ExplanationStep[]; result: Value } {\n\t\tthis.emit(root);\n\t\treturn { steps: this.steps, result: this.valueOf(root) };\n\t}\n\n\t/** Walk in evaluation order, emitting one step per operation. */\n\tprivate emit(node: Node): void {\n\t\tif (node.kind === \"leaf\") return;\n\t\tif (node.kind === \"wrap\") {\n\t\t\tthis.emit(node.child);\n\t\t\treturn;\n\t\t}\n\t\t// binary\n\t\tthis.emit(node.left);\n\t\tthis.emit(node.right);\n\t\tthis.steps.push({\n\t\t\tdescription: this.describe(node),\n\t\t\tvalue: this.valueOf(node),\n\t\t});\n\t}\n\n\tprivate describe(node: Extract<Node, { kind: \"binary\" }>): string {\n\t\tconst word = connective(node.op);\n\t\t// `on`/`off` state the rate first (\"20% off 80\") but read best base\n\t\t// first (\"80 less 20%\"), so their operands are shown the other way round.\n\t\tif (node.op === TokenTypes.PCT_ON || node.op === TokenTypes.PCT_OFF) {\n\t\t\treturn `${this.operand(node.right)} ${word} ${this.operand(node.left)}`;\n\t\t}\n\t\treturn `${this.operand(node.left)} ${word} ${this.operand(node.right)}`;\n\t}\n\n\t/** How an operand appears inside a step's description. */\n\tprivate operand(node: Node): string {\n\t\tif (node.kind === \"leaf\") {\n\t\t\treturn this.source.slice(node.start, node.end).trim();\n\t\t}\n\t\t// A group or an operation is shown by the value it carries.\n\t\treturn this.render(this.valueOf(node));\n\t}\n\n\t/** A node's value, evaluated once from its own span and then cached. */\n\tprivate valueOf(node: Node): Value {\n\t\tconst cached = this.cache.get(node);\n\t\tif (cached) return cached;\n\t\tconst value = this.evaluate(this.source.slice(node.start, node.end));\n\t\tthis.cache.set(node, value);\n\t\treturn value;\n\t}\n\tprivate readonly cache = new Map<Node, Value>();\n\n\t/** Format a value for inline display, without the result prefix (\"= \"). */\n\tprivate render(value: Value): string {\n\t\tconst formatted = formatValue(value, DEFAULT_FORMATTING_SETTINGS);\n\t\treturn formatted.startsWith(this.resultPrefix)\n\t\t\t? formatted.slice(this.resultPrefix.length)\n\t\t\t: formatted;\n\t}\n}\n\n/**\n * Build a derivation for a single line.\n *\n * `tokens` are the engine's normalized tokens for `expression` (offsets index\n * back into `expression`), and `evaluate` runs a self-contained sub-expression\n * through the engine. When the line cannot be broken down, the answer is still\n * returned with an empty step list.\n */\nexport function buildExplanation(params: {\n\texpression: string;\n\ttokens: Token[];\n\tevaluate: EvaluateSpan;\n\tlocale: string;\n}): Explanation {\n\tconst { expression, tokens, evaluate, locale } = params;\n\n\tconst terminal = (): Explanation => ({\n\t\texpression,\n\t\tsteps: [],\n\t\tresult: evaluate(expression),\n\t});\n\n\tlet root: Node;\n\ttry {\n\t\troot = new Parser(tokens).parseAll();\n\t} catch {\n\t\t// The line uses a construct this slice does not derive. Report the\n\t\t// answer alone rather than a partial or misleading breakdown.\n\t\treturn terminal();\n\t}\n\n\ttry {\n\t\tconst { steps, result } = new Builder(expression, evaluate, locale).build(root);\n\t\treturn { expression, steps, result };\n\t} catch {\n\t\t// A span failed to evaluate on its own (an unmodelled grouping). The\n\t\t// whole line may still evaluate, so report the answer without steps.\n\t\treturn terminal();\n\t}\n}\n","//#region Imports\n\nimport { VM, type EquationDef, type ScalarEquationDef } from \"@solve-js/vm/OpRegistry\";\nimport { matrixMultiply, inverse } from \"@solve-js/vm/MatrixOps\";\nimport { DependencyGraph } from \"@solve-js/vm/DependencyGraph\";\nimport { LineCache, LineCacheEntry } from \"@solve-js/cache/LineCache\";\nimport { ScopeManager } from \"@solve-js/vm/ScopeManager\";\nimport { Lexer } from \"@solve-js/lexer/Lexer\";\nimport { PrecedenceParser } from \"@solve-js/parser/PrecedenceParser\";\nimport { ParseletRegistry } from \"@solve-js/parser/registry/ParseletRegistry\";\nimport { BytecodeBuilder, type BytecodeProgram } from \"@solve-js/parser/BytecodeBuilder\";\nimport { createVM, executeBytecode } from \"@solve-js/vm/VM\";\nimport { resolveHolidayPredicate } from \"@solve-js/vm/HolidayCalendar\";\nimport type { EvalResult, LineExecutionContext } from \"@solve-js/vm/VM\";\nimport type { DocumentModel } from \"@solve-js/engine/DocumentModel\";\nimport { BackgroundRefreshManager } from \"@solve-js/engine/BackgroundRefreshManager\";\nimport { registerAsConverter, unregisterAsConverter, pluginFunctionIndexFor } from \"@solve-js/vm/VMBuiltins\";\nimport { createEngineContext } from \"@solve-js/engine/EngineContext\";\nimport type { EngineContext } from \"@solve-js/engine/EngineContext\";\nimport { Value, ValueType, numberValue, stringValue, pendingValue, freezeIfDev, errorValue, type MatrixData } from \"@solve-js/vm/Value\";\nimport type { IEnginePackage } from \"@solve-js/api/PackageRegistry\";\nimport { checkPackageCompatibility } from \"@solve-js/api/PackageCompatibility\";\nimport { assertEngineVersionCompatible } from \"@solve-js/api/EngineVersionCompatibility\";\nimport { ENGINE_VERSION } from \"@solve-js/constants/version\";\nimport {\n SNAPSHOT_FORMAT,\n SNAPSHOT_VERSION,\n SnapshotErrorCodes,\n assertRestorable,\n serializeValue,\n deserializeValue,\n serializeBytecode,\n deserializeBytecode,\n serializeUserFunction,\n deserializeUserFunction,\n type EngineSnapshot,\n type SerializedValue,\n type SerializedLineCacheEntry,\n} from \"@solve-js/engine/EngineSnapshot\";\nimport { registerTokenCategory, unregisterTokenCategory } from \"@solve-js/language/TokenCategoryMap\";\nimport type { CompletionItem } from \"@solve-js/language/LanguageService\";\nimport type { LexerVocabulary } from \"@solve-js/lexer/ExpressionLexer\";\nimport { QueryClient } from \"@tanstack/query-core\";\nimport { createQueryClient, setActiveQueryClient, getActiveQueryClient } from \"@solve-js/services/DataQueryService\";\nimport { ErrorFactory, EngineError, normalizeUnknownError } from \"@solve-js/errors/UnifiedErrorFramework\";\nimport { countLines } from \"@solve-js/utilities/Strings\";\nimport {\n\tResolverRegistry,\n\ttype AsyncCheckResult,\n} from \"@solve-js/resolvers/ResolverRegistry\";\nimport {\n\tAsyncResolutionBatcher,\n\ttype AsyncResolutionEvent,\n} from \"@solve-js/engine/AsyncResolutionBatcher\";\nimport { AllocationTracker, type PipelineTelemetry, type StageAllocation } from \"@solve-js/telemetry\";\nimport {\n ParsingResult,\n ParsedLine,\n InlineSolvePosition,\n UnifiedParsingOptions,\n} from \"@solve-js/types/ParsingResult\";\nimport { DiagnosticReportJSON } from \"@solve-js/diagnostics\";\nimport type { Token, ScanLineResult } from \"@solve-js/lexer\";\nimport { DEFAULT_CONFIG, mergeEngineConfig, type EngineConfig, type EngineConfigOverride } from \"@solve-js/constants/Configuration\";\nimport {\n DiagnosticPipeline,\n TimelineDiagnosticCollector,\n DiagnosticEventType\n} from \"@solve-js/diagnostics\";\nimport {\n checkExpressionLength,\n checkExpressionComplexity,\n extractReadsAndWrites,\n} from \"@solve-js/engine/ExpressionEngineSafety\";\nimport { buildTokenLookup } from \"@solve-js/lexer/tokenRegistration\";\nimport { containsSymbolicCall } from \"@solve-js/packages/symbolic\";\nimport { solveEquationValues } from \"@solve-js/vm/SymbolicOps\";\nimport { abortLogger } from \"@solve-js/utilities/AbortControllerLogger\";\nimport { TokenNormalizer, BUILTIN_PHRASES, implicitMultiplyRule } from \"@solve-js/normalizer\";\nimport { createFusedToken } from \"@solve-js/normalizer/TokenNormalizer\";\nimport type { TokenFusion } from \"@solve-js/normalizer\";\nimport { UserUnitTable } from \"@solve-js/packages/uom/UserUnitTable\";\nimport { userUnitExpansionRule } from \"@solve-js/packages/uom/normalizer/UserUnitNormalizerRule\";\nimport { buildExplanation } from \"@solve-js/explain\";\nimport type { Explanation } from \"@solve-js/explain\";\nimport {\n type DiagnosticPipelineResult,\n type PipelineStageResult,\n type StageOutput,\n type InlineSolveSpanInfo,\n type CacheSnapshot,\n type BatcherMetrics,\n type CheckpointSnapshot,\n type BytecodeCacheEntry,\n type LineCacheEntryInfo,\n type AsyncCachePackageInfo,\n} from \"@solve-js/types/DiagnosticPipelineResult\";\n\n// Re-export for consumers (playground imports these from ExpressionEngine)\nexport type { CacheSnapshot, BatcherMetrics, CheckpointSnapshot, BytecodeCacheEntry, LineCacheEntryInfo, AsyncCachePackageInfo };\nexport type { DagSnapshot } from \"@solve-js/vm/DependencyGraph\";\n// The snapshot/restore surface, re-exported so `toJSON`/`fromJSON` callers can\n// import their types from the same module as `ExpressionEngine`.\nexport {\n SNAPSHOT_FORMAT,\n SNAPSHOT_VERSION,\n SnapshotErrorCodes,\n} from \"@solve-js/engine/EngineSnapshot\";\nexport type {\n EngineSnapshot,\n SerializedValue,\n SerializedBytecode,\n SerializedUserFunction,\n SerializedAnonymousBody,\n SerializedLineCacheEntry,\n SerializedDecimal,\n SerializedRational,\n SerializedNumber,\n} from \"@solve-js/engine/EngineSnapshot\";\n\n/**\n * Options for {@link ExpressionEngine.fromJSON}, restoring a snapshot onto a\n * fresh engine.\n */\nexport interface EngineRestoreOptions {\n /**\n * Packages to register on the restored engine. This MUST be the same set\n * the snapshot was taken with: a snapshot carries compiled bytecode whose\n * plugin-function indices and parselet-produced opcodes only line up\n * against the packages that were present when it was written. Registers no\n * packages when omitted, exactly like the constructor's own `packages`\n * parameter, so a host that snapshotted a full engine passes the same\n * `BUILTIN_PACKAGES` here that it constructed with.\n */\n packages?: IEnginePackage[];\n /** Config overrides, merged over `DEFAULT_CONFIG`, as in the constructor. */\n config?: EngineConfigOverride;\n /** Turn on the diagnostic pipeline, as in the constructor's `diagnostics`. */\n diagnostics?: boolean;\n /**\n * Override the locale the snapshot recorded. Rarely needed: the snapshot's\n * own {@link EngineSnapshot.locale} is used by default, so a restored engine\n * lexes the way the one that produced it did.\n */\n locale?: string;\n}\n\n/**\n * Options for constructing an {@link ExpressionEngine}. Every field is optional.\n *\n * An engine registers exactly the {@link EngineOptions.packages} it is given, so\n * a bundler can tree-shake away every built-in a consumer never imports; pass\n * `BUILTIN_PACKAGES` (from `solve-engine/packages`) for the full set, a subset\n * for a slimmer engine, or use {@link createEngine} for the batteries-included\n * convenience.\n */\nexport interface EngineOptions {\n /** BCP-47 locale. Defaults to `\"en\"`. */\n locale?: string;\n /** Packages to register. None when omitted, so nothing but what you pass is bundled. */\n packages?: IEnginePackage[];\n /** Config overrides, merged per section over {@link DEFAULT_CONFIG}. */\n config?: EngineConfigOverride;\n /** Turn on the diagnostic pipeline (per-stage timing and detail). Defaults to `false`. */\n diagnostics?: boolean;\n}\n\n//#endregion\n\n/**\n * Core expression evaluation engine, the top-level orchestrator.\n *\n * Owns the full evaluation pipeline: lexing, parsing, bytecode compilation,\n * VM execution, DAG-based dependency tracking, and async resolution.\n *\n * Key responsibilities:\n * - Pipeline orchestration: lex → parse → compile → execute → cache\n * - Bytecode caching for repeated expressions\n * - DAG-based incremental re-evaluation on variable changes\n * - Async resolution via ResolverRegistry + AsyncResolutionBatcher\n * - Package registration (built-in + external plugins)\n * - Safety validation (length, complexity, nesting)\n * - Diagnostic pipeline integration\n * - Keystroke-level AbortSignal management\n *\n * Each engine instance has its own isolated lexer, registry, parser, and\n * LineCache. The VM uses this engine's own opcode registry, and each engine\n * creates its own VM instance with configurable limits.\n *\n * ## Lifecycle\n *\n * Call {@link ExpressionEngine.clear} when you are finished with an engine that\n * has parsed a document. Dropping your last reference is not sufficient: the\n * async batcher is reachable from the module-level data-query service, so a\n * parsed engine stays retained until `clear()` releases it. Measured per engine\n * after a forced collection, with a 40-line document:\n *\n * | Lifecycle | Retained |\n * | --- | --- |\n * | constructed, never parsed | 8.2KB |\n * | constructed and parsed | 46.9KB |\n * | constructed, parsed, cleared | 10.0KB |\n *\n * This matters for hosts that create one engine per document or per tab, which\n * is the intended usage. Reusing a single engine across documents is also fine:\n * `clear()` resets it for the next one rather than consuming it.\n *\n * The constructor registers only the packages it is given, so a consumer's\n * bundler can tree-shake away every built-in they do not use. For the common\n * \"I want everything\" case, {@link createEngine} registers the full built-in\n * set in one call; pass an explicit package list to the constructor when\n * bundle size matters.\n *\n * @example\n * ```typescript\n * import { createEngine } from \"solve-engine\";\n * const engine = createEngine(); // every built-in package\n * const value = engine.evaluateExpression(\"2 + 2 * 10\");\n * console.log(value.toNumber()); // 22\n * ```\n * @example\n * ```typescript\n * // A slimmer engine: only arithmetic and units reach the bundle.\n * import { ExpressionEngine } from \"solve-engine\";\n * import { ARITHMETIC_PACKAGE, UOM_PACKAGE } from \"solve-engine/packages\";\n * const engine = new ExpressionEngine({ packages: [ARITHMETIC_PACKAGE, UOM_PACKAGE] });\n * ```\n */\n//#region Class: ExpressionEngine\n\nexport class ExpressionEngine {\n //#region Private Properties\n private dag = new DependencyGraph();\n private lineCache = new LineCache();\n /**\n * Names ever used as a running-total target (`total += 5`). A document is\n * re-parsed top-to-bottom on every keystroke, so each accumulator is reset\n * to undefined at the start of a batch pass and re-seeds from its opening\n * `+=`/`-=` this pass, rather than reading its own previous pass's value\n * (which grew the total without bound). See {@link tryCompoundAssignment}.\n */\n private accumulatorNames = new Set<string>();\n private scopeManager = new ScopeManager();\n private lexer: Lexer;\n private registry: ParseletRegistry;\n private parser: PrecedenceParser;\n private localeCode: string;\n private vm: VM;\n /**\n * Registries this engine owns, rather than shares with every other\n * instance in the process. See {@link EngineContext}.\n */\n private readonly context: EngineContext;\n private config: typeof DEFAULT_CONFIG;\n private diagnosticPipeline: DiagnosticPipeline;\n /**\n * Direct reference to the timeline collector registered above (when\n * diagnosticMode is on), kept alongside the generic `diagnosticPipeline`\n * so `evaluateExpressionWithDiagnostic()` can cheaply read its current\n * `parseletMatchCount` as a \"before\" baseline without paying for a full\n * `getReport()` build (which copies the whole cumulative parselets\n * array). See that method's use of it for why a baseline is needed at\n * all, `TimelineDiagnosticCollector`'s state is deliberately cumulative\n * across an entire document pass, not reset per line.\n */\n private timelineCollector?: TimelineDiagnosticCollector;\n /** Registry of async resolvers from registered packages. */\n private resolverRegistry = new ResolverRegistry();\n\n /**\n * Per-package record of contributions made to the engine's registries\n * (plugin functions, resolver namespaces, token categories), so\n * {@link unregisterPackage} can reverse them. Keyed by package name.\n */\n private packageContributions = new Map<string, {\n pluginFunctionIndices: number[];\n pluginFunctionNames: string[];\n resolverNamespaces: string[];\n tokenCategories: string[];\n lexerVocabulary: LexerVocabulary | undefined;\n asConverterNames: string[];\n normalizerRuleNames: string[];\n }>();\n\n /**\n * The actual `IEnginePackage` descriptor of every package currently\n * registered on this engine instance, keyed by name, separate from\n * {@link packageContributions} (which tracks what was WRITTEN into\n * shared registries, not the original descriptor). Used by\n * {@link registerPackage}'s automatic `checkPackageCompatibility()` call\n *. See `api/PackageCompatibility.ts`'s module doc for why this exists.\n */\n private registeredPackages = new Map<string, IEnginePackage>();\n\n /**\n * The `DocumentModel` this engine is currently evaluating, if any\n * `null` for a bare engine with no document (e.g. anything only ever\n * calling `evaluateExpression()`). `ExpressionEngine` doesn't own its\n * `DocumentModel` (`ThreeTierEvaluator` constructs and owns both as\n * siblings). This is set once, via {@link setDocumentModel}, purely so\n * {@link makeLineContext} can answer \"what's line N's cached result\"\n * for cross-line features (`prev`/`line<N>`/aggregation. See\n * `packages/lines/`) without the engine needing to own document\n * lifecycle itself.\n */\n private documentModel: DocumentModel | null = null;\n\n /**\n * How deep goal seek is currently re-entering line evaluation, so a goal\n * seek whose target line is itself a goal seek is refused rather than\n * multiplying the search cost. One goal-seek line already re-runs its\n * target up to `maxGoalSeekIterations` times; allowing a nested one would\n * make that a product. See {@link makeLineContext}'s `evaluateLineWithBinding`.\n */\n private goalSeekDepth = 0;\n\n /** The most nesting {@link makeLineContext}'s `evaluateLineWithBinding` allows before refusing, so the bisection re-runs can never compound. */\n private static readonly GOAL_SEEK_MAX_NESTING_DEPTH = 1;\n\n /**\n * Batch cross-line source, set only for the duration of a\n * `parseDocument`/`evaluateLines` pass (see {@link processScanResults}).\n * The incremental path uses {@link documentModel}; the batch path has no\n * such model, so cross-line closures read earlier lines from the scan and\n * the results array the pass is already building. Both are references to\n * arrays that exist regardless, so a document that uses no cross-line\n * feature pays nothing: the closures are simply never called.\n */\n private batchScanResults: ScanLineResult[] | null = null;\n private batchParsedLines: ParsedLine[] | null = null;\n\n /**\n * Called once by `ThreeTierEvaluator`'s constructor. Not part of the\n * public evaluate-a-document contract, purely internal wiring so\n * {@link makeLineContext} has something to read from.\n */\n setDocumentModel(doc: DocumentModel | null): void {\n this.documentModel = doc;\n }\n\n /**\n * The `DocumentModel` this engine is currently wired to, or `null` when it\n * is not driving one. Lets a caller that borrows the engine for a one-off\n * incremental pass (see {@link evaluateDocument}) put back whatever a host\n * had set, rather than assuming it was `null`.\n */\n getDocumentModel(): DocumentModel | null {\n return this.documentModel;\n }\n\n /**\n * Build the {@link LineExecutionContext} passed to `executeBytecode()`\n * for a given line. `lineNumber = -1` (the existing sentinel\n * `evaluateExpression()`/`evaluateLine(-1, ...)` already use for \"no\n * real document\") naturally produces a context with both closures\n * `undefined`, a cross-line plugin function must check for that itself\n * and return a clear error, never assume line 0 exists.\n */\n private makeLineContext(lineNumber: number): LineExecutionContext {\n const doc = this.documentModel;\n const scan = doc ? null : this.batchScanResults;\n const parsed = doc ? null : this.batchParsedLines;\n return {\n lineIndex: lineNumber,\n getLineResult: doc\n ? (n: number) => doc.getLineAt(n)?.result ?? undefined\n : parsed\n ? (n: number) => parsed[n - 1]?.result ?? undefined\n : undefined,\n isLineBoundary: doc\n ? (n: number) => {\n const state = doc.getLineAt(n);\n if (!state) return true; // out of range counts as a boundary — nothing to aggregate past it\n return state.isEmpty || /^\\s*#/.test(state.text);\n }\n : scan\n ? (n: number) => {\n const sr = scan[n - 1];\n if (!sr) return true;\n return sr.classification.skip || /^\\s*#/.test(sr.text);\n }\n : undefined,\n getLineReads: doc\n ? (n: number) => {\n const state = doc.getLineAt(n);\n // A line with no compiled bytecode has nothing to solve\n // against yet (forward reference, out of range, or\n // markdown), reported as undefined rather than an empty\n // read set so goal seek can tell \"reads nothing\" from\n // \"not ready\".\n if (!state || state.bytecodes.length === 0) return undefined;\n return state.reads;\n }\n : undefined,\n evaluateLineWithBinding: doc\n ? (n: number, variable: string, bound: Value, symbolicTolerant: boolean) =>\n this.evaluateLineWithBinding(n, variable, bound, symbolicTolerant)\n : undefined,\n goalSeekMaxIterations: this.config.vm.maxGoalSeekIterations,\n // Raw source text of a line, for features that read markdown the\n // evaluator skipped (a table's rows). See the tables package. Reads\n // from the document when evaluating incrementally, and from the scan\n // in the batch parseDocument/evaluateLines path, so a table column\n // aggregate resolves the same way through both, matching the other\n // cross-line closures above.\n getLineText: doc\n ? (n: number) => doc.getLineAt(n)?.text\n : scan\n ? (n: number) => scan[n - 1]?.text\n : undefined,\n };\n }\n\n /**\n * Re-evaluate line `targetLine`'s compiled expression with `variable` bound\n * to `bound` for that one run, the primitive goal seek drives while\n * narrowing in on an input. See {@link LineExecutionContext.evaluateLineWithBinding}.\n *\n * The binding is a call frame, so `LOAD_VAR` reads it in preference to the\n * document's own value and the document's value is untouched once the frame\n * is popped, the same shadowing a function parameter gets. The target's\n * bytecode is run as-is, so a line that defines a variable is refused: its\n * `STORE_VAR` would write the probe's candidate into the real variable store\n * as a side effect. The re-entry is bounded three ways, by\n * {@link goalSeekDepth} against nesting, by the VM's own per-run instruction\n * limit, and by the caller's iteration cap.\n *\n * @param targetLine - 1-based line whose expression is re-evaluated.\n * @param variable - The unknown to bind for this run.\n * @param bound - The value to bind it to (a number to probe, a symbolic node to read the relationship in closed form).\n * @param symbolicTolerant - Whether an otherwise-undefined variable reads as a symbolic placeholder, needed for the closed-form read.\n * @returns The line's re-evaluated Value, or an error Value when it cannot be probed.\n */\n private evaluateLineWithBinding(\n targetLine: number,\n variable: string,\n bound: Value,\n symbolicTolerant: boolean,\n ): Value {\n const doc = this.documentModel;\n if (!doc) {\n return errorValue(\"GOAL_SEEK_NO_DOCUMENT\", \"Goal seek needs a document to solve against, which the single-expression entry point does not have.\");\n }\n if (this.goalSeekDepth >= ExpressionEngine.GOAL_SEEK_MAX_NESTING_DEPTH) {\n return errorValue(\"GOAL_SEEK_NESTED\", `A goal-seek line cannot target another goal-seek line, since each already re-runs its target many times.`);\n }\n const state = doc.getLineAt(targetLine);\n if (!state || state.bytecodes.length === 0) {\n return errorValue(\"GOAL_SEEK_LINE_NOT_READY\", `Line ${targetLine} has no evaluated expression to solve (forward reference, out of range, or not an expression).`);\n }\n if (state.isVariableDef) {\n return errorValue(\"GOAL_SEEK_TARGET_IS_DEFINITION\", `Line ${targetLine} defines a variable, so re-running it would overwrite that variable. Target the line that uses ${variable}, not the one that sets a value.`);\n }\n\n const program = state.bytecodes[0];\n this.goalSeekDepth++;\n try {\n const frame = new Map<string, Value>([[variable, bound]]);\n const stackBefore = this.vm.getStack().length;\n this.vm.pushCallFrame(frame);\n try {\n const result = executeBytecode(program, this.vm, undefined, undefined, this.makeLineContext(targetLine), symbolicTolerant);\n if (result.type === 'pending') {\n return errorValue(\"GOAL_SEEK_ASYNC_UNSUPPORTED\", `Line ${targetLine} depends on an async value (weather, stocks, currency, ...), which goal seek cannot re-run.`);\n }\n if (result.type === 'error') {\n return errorValue(result.error.code ?? \"GOAL_SEEK_TARGET_ERROR\", result.error.message);\n }\n return result.value;\n } finally {\n this.vm.popCallFrame();\n // Restore the shared stack to exactly what the outer evaluation\n // left, mirroring executeAndStore()'s own post-run cleanup, so a\n // probe leaves nothing behind for the next one.\n while (this.vm.getStack().length > stackBefore) this.vm.pop();\n }\n } catch (e) {\n // A safety-limit throw from the re-run (instruction/stack/recursion\n // limit) surfaces as a structured error Value rather than escaping\n // the search loop.\n return errorValue(\"GOAL_SEEK_TARGET_ERROR\", normalizeUnknownError(e).message);\n } finally {\n this.goalSeekDepth--;\n }\n }\n\n /**\n * Package-contributed completion candidates (`IEnginePackage.completionItems`),\n * keyed by package name, engine-instance-local, not a shared registry\n * (unlike tokenCategories), so no separate register/unregister module is\n * needed: registerPackage()/unregisterPackage() just set/delete the\n * package's own entry. {@link getPackageCompletionItems} flattens it.\n */\n private packageCompletionItems = new Map<string, CompletionItem[]>();\n\n /**\n * Keystroke-level AbortSignal, set by the UI layer (MarkdownEditorViewPlugin)\n * before each evaluation. When the user types a new keystroke, the old signal\n * is aborted, causing all in-flight async work (fetches, preflight checks,\n * batcher flushes) to be canceled atomically.\n *\n * executeAndStore() and executeRaw() link their local AbortControllers to\n * this signal so that when the keystroke changes, all per-evaluation controllers\n * are aborted together.\n */\n private keystrokeSignal: AbortSignal | null = null;\n\n /**\n * Micro-batcher that collapses multiple async resolutions into a single\n * DAG walk + re-evaluation pass. Replaces the old single-callback pattern.\n */\n private batcher: AsyncResolutionBatcher;\n /**\n * Drives proactive background refresh of live values, or `null` when the\n * host has not enabled it (the default). See {@link BackgroundRefreshManager}.\n */\n private readonly backgroundRefresh: BackgroundRefreshManager | null;\n /**\n * The signal a background re-evaluation is dispatched under. Never aborted\n * (a background refetch is not tied to a keystroke), so the batcher treats\n * its results as current; the manager's own timers are what stop the work.\n */\n private readonly backgroundRefreshSignal = new AbortController().signal;\n /** Post-lexer token normalizer for phrase fusion, implicit multiply, etc. */\n private normalizer: TokenNormalizer;\n /**\n * Units defined by the current document (`1 sprint = 2 weeks`). Read by the\n * user-unit normalizer rule to expand a name back to its definition, written\n * by {@link tryDefineUserUnit} on a definition line. Document-scoped: cleared\n * at the start of every {@link parseDocument} pass, so definitions never\n * cross between documents.\n */\n private readonly userUnits = new UserUnitTable();\n /** TanStack Query client, injected into resolvers for cache reads/writes. */\n readonly queryClient: QueryClient;\n // Bytecode cache, avoids re-parsing identical expressions.\n // Bounded by config.performance.defaultCacheSize: when full, the oldest\n // entry (Map insertion order) is evicted so unique expressions across a\n // long session can't grow memory unboundedly.\n private bytecodeCache: Map<string, BytecodeProgram> = new Map();\n\n /**\n * Insert into the bytecode cache, evicting the oldest entry when full.\n *\n * Bug fix (found during release hardening): this used to check against\n * a hardcoded `BYTECODE_CACHE_MAX_ENTRIES = 2000` constant that never\n * read `config.performance.defaultCacheSize`, despite that field being\n * documented (see `EngineConfig`'s JSDoc example) as exactly this knob.\n * A host raising `defaultCacheSize` for large documents had zero effect;\n * every document beyond ~2000 unique expressions per line silently lost\n * the bytecode-cache benefit on re-evaluation regardless of config.\n */\n private cacheBytecode(expression: string, program: BytecodeProgram): void {\n const maxEntries = this.config.performance.defaultCacheSize;\n if (this.bytecodeCache.size >= maxEntries) {\n const oldest = this.bytecodeCache.keys().next().value;\n if (oldest !== undefined) {\n this.bytecodeCache.delete(oldest);\n }\n }\n this.bytecodeCache.set(expression, program);\n }\n // Maps each registered plugin function's name to the index its handler sits\n // at in this engine's context. Populated by registerPackage, shared by\n // reference with every BytecodeBuilder and the parser so a parselet emits a\n // plugin call by name (builder.emitPluginCall) and never sees the index.\n private pluginFunctionIndexByName = new Map<string, number>();\n // Pre-allocated BytecodeBuilder pool\n private builderPool: BytecodeBuilder[] = [\n new BytecodeBuilder(this.pluginFunctionIndexByName),\n new BytecodeBuilder(this.pluginFunctionIndexByName),\n new BytecodeBuilder(this.pluginFunctionIndexByName),\n new BytecodeBuilder(this.pluginFunctionIndexByName),\n ];\n // Index into the builder pool, incremented modulo pool size.\n private builderPoolIndex = 0;\n // Most recent pipeline telemetry, populated when AllocationTracker.isEnabled().\n private lastTelemetry: PipelineTelemetry | null = null;\n\n //#endregion\n\n //#region Constructor\n constructor(options: EngineOptions = {}) {\n const { locale = \"en\", diagnostics = false, config, packages } = options;\n this.localeCode = locale;\n // Per-section merge, not a top-level shallow spread, overriding one\n // field of a section (e.g. `{ performance: { defaultCacheSize: 500 } }`)\n // used to silently replace the WHOLE section, dropping every other\n // field in it back to `undefined` instead of keeping its default.\n this.config = mergeEngineConfig(DEFAULT_CONFIG, config ?? {});\n this.lexer = new Lexer(locale, buildTokenLookup(locale));\n this.registry = new ParseletRegistry();\n // Before the package loop below, which registers plugin functions into it.\n this.context = createEngineContext();\n\n // Wire the diagnostic pipeline: collect per-stage detail when diagnostics\n // are on, otherwise an empty pipeline whose length check exits with zero\n // overhead in production.\n if (diagnostics) {\n this.diagnosticPipeline = new DiagnosticPipeline();\n this.timelineCollector = new TimelineDiagnosticCollector();\n this.diagnosticPipeline.register(this.timelineCollector);\n } else {\n this.diagnosticPipeline = new DiagnosticPipeline();\n }\n\n // Register providers via IEnginePackage data.\n // Packages are explicit: an engine registers exactly what the caller\n // passes and nothing more, so a consumer's bundler can tree-shake away\n // every built-in package they do not import. Pass `BUILTIN_PACKAGES`\n // (from `solve-engine/packages`) for the full set, or a subset for a\n // slimmer engine; omitting `packages` registers none.\n // Each package's parselets go into the engine's isolated registry\n // (not sharedParseletRegistry), lexer plugins into the engine's\n // isolated lexer, and opcode/variable handlers into shared registries.\n\n // ── Create normalizer BEFORE package registration ──\n // Packages may register phrases and normalizer rules, so the normalizer\n // must exist before registerPackage() is called.\n this.normalizer = new TokenNormalizer();\n\n // Register built-in phrases into the PhraseTrie, single-pass\n // O(depth) matching per position instead of separate rule scans.\n for (const [phrase, tokenType] of Object.entries(BUILTIN_PHRASES)) {\n this.normalizer.addPhrase(phrase, tokenType);\n }\n\n // Register built-in normalizer rules (implicit multiply, etc.)\n // Pass the trie's canStart predicate so the implicit multiply rule\n // stays in sync with package-registered phrases.\n this.normalizer.register(implicitMultiplyRule(\n 50,\n (word) => this.normalizer.canStartPhrase(word),\n ));\n\n // User-defined units (`1 sprint = 2 weeks`). Registered here rather than\n // through the UOM package descriptor because it closes over this\n // engine's own per-document unit table, and a package descriptor is\n // shared across every engine in the process. Priority is above implicit\n // multiply so a defined name is expanded whole (`6 * 2 weeks`) instead\n // of first split into `6 * sprints` with the name stranded as a variable.\n this.normalizer.register(userUnitExpansionRule(this.userUnits));\n\n const pkgList = packages ?? [];\n for (const pkg of pkgList) {\n // Per-package containment: registerPackage() can throw (a\n // lexerVocabulary keyword/operator/unit colliding with a\n // built-in one, ExpressionLexer.registerVocabulary()'s hard\n // guard, the one sub-registration in registerPackage() that\n // isn't already \"warn and proceed\"). Unguarded, that throw used\n // to escape the constructor itself: every package after the\n // offender in pkgList never got registered, `new\n // ExpressionEngine(...)` never returned an instance, and\n // whatever THIS package or earlier ones already wrote into\n // shared module-level registries (pluginFunctionRegistry,\n // TokenCategoryMap, asConverterRegistry)\n // had no owning engine instance left to call\n // unregisterPackage() and clean it up. Same containment shape\n // as AsyncResolutionBatcher.reExecuteMainThread()'s fatal-bug\n // fix: one bad package (most likely a third-party one passed via\n // the `packages` constructor param, not a built-in) is skipped\n // with a clear, verbose error instead of taking the whole engine\n // down.\n try {\n this.registerPackage(pkg);\n } catch (e) {\n const engineError = normalizeUnknownError(e);\n console.error(\n `[ExpressionEngine] Failed to register package \"${pkg.name}\" — skipping it and continuing ` +\n `construction with the remaining packages: ${engineError.format()}`\n );\n }\n }\n\n this.parser = new PrecedenceParser(this.registry, this.config.validation.maxNestingDepth, locale, this.pluginFunctionIndexByName);\n this.vm = createVM(\n this.context.opRegistry,\n this.config.vm.maxStackDepth,\n this.config.vm.maxInstructions,\n undefined,\n this.config.vm.maxCollectionSize,\n this.config.vm.maxAllocatedElements,\n this.config.vm.maxFunctionCalls,\n this.config.date.maxOffsetYears,\n this.config.date.minOffsetYears,\n this.context,\n // Resolved once here, not per evaluation: a host list becomes a\n // Set lookup the walk can run cheaply. Undefined stays undefined,\n // which the VM reads as weekends-only.\n resolveHolidayPredicate(this.config.date.holidays),\n );\n this.queryClient = createQueryClient();\n this.batcher = new AsyncResolutionBatcher(this.dag, this.lineCache, this.vm);\n // Only stand up the background refresher when the host asked for it: a\n // headless or batch host wants no timers. When null, every value stays\n // pull-only, exactly as before. It feeds the same batcher the pull path\n // does, so a resolved background value reaches the host over the existing\n // event stream with no extra wiring.\n this.backgroundRefresh = this.config.backgroundRefresh.enabled\n ? new BackgroundRefreshManager(this.dag, (packageId, queryKey) =>\n this.batcher.add({ queryKey, packageId, signal: this.backgroundRefreshSignal, isError: false }),\n )\n : null;\n\t}\n\n //#endregion\n\n //#region Public API, Event stream\n\n /**\n * Get the native event stream from the batcher for stream-based consumers.\n *\n * Use this instead of `addAsyncListener()` when you need:\n * - **Backpressure**: the stream buffers up to `highWaterMark` events;\n * when full, `enqueue()` blocks until the consumer reads, preventing\n * unbounded memory growth.\n * - **Cancellation**: call `reader.cancel()` or pass an `AbortSignal` to\n * `pipeTo()` to stop receiving events.\n * - **Piping**: use `stream.pipeTo(writable)` or `stream.pipeThrough(transform)`\n * to build a reactive pipeline.\n * - **Teeing**: use `stream.tee()` to serve multiple independent consumers.\n *\n * @returns A {@link ReadableStream} that emits {@link AsyncResolutionEvent}\n * items as the batcher processes async resolutions.\n */\n getEventStream(): ReadableStream<AsyncResolutionEvent> {\n return this.batcher.getEventStream();\n }\n\n /**\n * Get the batcher instance (for test infrastructure).\n *\n * Tests use this to access `batcher._testCaptures` for synchronous\n * event observation without async stream reader timing issues.\n */\n getBatcher(): AsyncResolutionBatcher {\n return this.batcher;\n }\n\n //#endregion\n\n //#region Public API, Package registration\n\n /**\n * Register a package with the engine's isolated registries.\n *\n * Handles all IEnginePackage fields:\n * - `lexerVocabulary` → engine's isolated lexer (via this.lexer.registerVocabulary)\n * - `prefixParselets` → engine's isolated ParseletRegistry\n * - `infixParselets` → engine's isolated ParseletRegistry\n *\n * Built-in packages (ARITHMETIC, FUNCTION, UOM, etc.) are registered\n * via this method during construction. External user packages can also\n * use this method for data-driven registration.\n *\n * @param pkg - The package to register.\n */\n registerPackage(pkg: IEnginePackage): void {\n // Engine-vs-package version gating, checked FIRST, before the\n // duplicate-name guard below. Unlike checkPackageCompatibility()\n // further down (package-vs-package, always advisory, never blocks\n // ARCHITECTURE.md §5.2), an unsatisfied or malformed engineVersion is\n // a hard rejection: throwing here means re-registering an\n // incompatible REPLACEMENT for an already-working package never\n // unregisters the old one first, the engine is never left with\n // neither version registered. See ARCHITECTURE.md §5.3 and\n // api/EngineVersionCompatibility.ts.\n assertEngineVersionCompatible(pkg);\n\n // Guard against double-registration under the same name: without\n // this, a second registerPackage() call for the same pkg.name would\n // overwrite packageContributions' tracked record for the FIRST\n // registration, permanently orphaning its shared-registry\n // contributions (pluginFunctionRegistry entries, variable sources,\n // resolver namespaces, token categories), unreachable and\n // unreversible for the engine's lifetime, since those are shared\n // module-level registries. Mirrors ResolverRegistry.register()'s\n // existing \"destroy old, warn, replace\" pattern for the same class\n // of problem at the resolver-namespace level.\n if (this.packageContributions.has(pkg.name)) {\n console.warn(\n `[ExpressionEngine] Package \"${pkg.name}\" is already registered. ` +\n `Unregistering the previous registration before re-registering.`,\n );\n this.unregisterPackage(pkg.name);\n }\n\n // Load-up resiliency: statically compare this package's declared\n // fields against every OTHER package already on this engine, before\n // touching any shared registry. See api/PackageCompatibility.ts's\n // module doc for the full reasoning and the real bug that motivated\n // it. Non-fatal (matches this codebase's established \"warn and\n // proceed\" convention for collisions elsewhere, ParseletRegistry\n // asConverterRegistry) even for \"error\"-severity conflicts, since a\n // host may have a deliberate reason to accept a collision; the\n // point is making it IMPOSSIBLE to miss, not blocking registration.\n const compatibility = checkPackageCompatibility(pkg, [...this.registeredPackages.values()]);\n for (const conflict of compatibility.conflicts) {\n const log = conflict.severity === \"error\" ? console.error : console.warn;\n log(`[ExpressionEngine] Package compatibility ${conflict.severity} (${conflict.kind}): ${conflict.detail}`);\n }\n\n // Track shared-registry contributions so unregisterPackage() can\n // reverse them. Isolated per-engine registrations (parselets,\n // phrases) die with the engine and don't need tracking. lexerVocabulary\n // IS tracked (unlike before) so its custom keyword/operator token\n // types can be reverted via ExpressionLexer.unregisterVocabulary()\n // previously that method existed and worked correctly but was never\n // called from here, leaving a package's lexer contribution live\n // after \"unregistering\" it. tokenCategories is tracked the same way.\n //\n // normalizerRuleNames is tracked even though the normalizer is\n // per-engine, because unlike phrases these do NOT die with the engine\n // in any useful sense: a phrase goes into a text-keyed trie and\n // registering it twice is idempotent, whereas a rule is pushed onto an\n // array, so a host re-registering a package on every settings change\n // accumulated one more copy of every rule each time and the normalizer\n // tried all of them at every token position for the rest of the\n // engine's life.\n const contribution = {\n pluginFunctionIndices: [] as number[],\n pluginFunctionNames: [] as string[],\n resolverNamespaces: [] as string[],\n tokenCategories: [] as string[],\n lexerVocabulary: pkg.lexerVocabulary,\n asConverterNames: [] as string[],\n normalizerRuleNames: [] as string[],\n };\n\n // Only lexerVocabulary can throw here (built-in keyword/operator/unit\n // collision, ExpressionLexer.registerVocabulary()'s hard guard)\n // every other sub-registration below is already \"warn and proceed\".\n // Deliberately done BEFORE registeredPackages/packageContributions\n // are recorded (see below) so a throw here leaves no phantom\n // entry, the caller's try/catch (registerPackage() itself still\n // throws for a single bad package; ExpressionEngine's constructor\n // catches per-package so one bad package can't take down engine\n // construction, see that loop's own comment) sees a package that\n // registered NOTHING, not a partially-registered one.\n if (pkg.lexerVocabulary) {\n this.lexer.registerVocabulary(pkg.lexerVocabulary);\n }\n if (pkg.prefixParselets) {\n for (const [tokenType, parselet] of Object.entries(pkg.prefixParselets)) {\n this.registry.registerPrefix(tokenType, parselet);\n }\n }\n if (pkg.infixParselets) {\n for (const [tokenType, parselet] of Object.entries(pkg.infixParselets)) {\n this.registry.registerInfix(tokenType, parselet);\n }\n }\n if (pkg.pluginFunctions) {\n for (const [name, handler] of Object.entries(pkg.pluginFunctions)) {\n // The engine assigns the registry index (stable per pkg:name), so\n // the author names the function and the parselet emits by name.\n const index = pluginFunctionIndexFor(`${pkg.name}:${name}`);\n this.context.pluginFunctions[index] = handler;\n this.context.pluginFunctionOwners[index] = pkg.name;\n this.pluginFunctionIndexByName.set(name, index);\n contribution.pluginFunctionIndices.push(index);\n contribution.pluginFunctionNames.push(name);\n }\n }\n if (pkg.asyncResolvers) {\n for (const resolver of pkg.asyncResolvers) {\n this.resolverRegistry.register(resolver);\n contribution.resolverNamespaces.push(resolver.namespace);\n }\n }\n if (pkg.phrases) {\n for (const [phrase, tokenType] of Object.entries(pkg.phrases)) {\n this.normalizer.addPhrase(phrase, tokenType);\n }\n }\n if (pkg.normalizerRules) {\n for (const rule of pkg.normalizerRules) {\n this.normalizer.register(rule);\n contribution.normalizerRuleNames.push(rule.name);\n }\n }\n if (pkg.tokenCategories) {\n for (const [tokenType, category] of Object.entries(pkg.tokenCategories)) {\n registerTokenCategory(tokenType, category);\n contribution.tokenCategories.push(tokenType);\n }\n }\n if (pkg.completionItems) {\n this.packageCompletionItems.set(pkg.name, pkg.completionItems);\n }\n if (pkg.asConverters) {\n for (const [name, handler] of Object.entries(pkg.asConverters)) {\n registerAsConverter(name, handler);\n contribution.asConverterNames.push(name);\n }\n }\n\n this.packageContributions.set(pkg.name, contribution);\n // Recorded LAST, only once every sub-registration above actually\n // succeeded. If this ran up front (as it used to), a mid-function\n // throw from lexerVocabulary would leave a phantom entry: callers\n // checking registeredPackages.has(pkg.name) would see \"registered\"\n // for a package that contributed nothing.\n this.registeredPackages.set(pkg.name, pkg);\n }\n\n /**\n * Unregister a package previously registered via {@link registerPackage}.\n *\n * Reverses the package's contributions to the SHARED registries, plugin\n * functions (pluginFunctionRegistry), variable sources\n * (this engine's variable resolver), async resolvers, and now\n * token highlight categories (TokenCategoryMap), which registerPackage\n * wrote into process-wide state. Also reverts\n * the package's lexer plugin (custom keyword/operator token types\n * revert to generic IDENT/ERROR, matching ExpressionLexer.unregisterVocabulary()'s\n * own contract). This engine-instance-local registration is reversed\n * here too, even though it isn't a \"shared\" registry, so a package's\n * lexer and highlighting contributions clean up together rather than\n * only half-reversing on unregister. Normalizer rules are reversed here\n * for the same reason: they are per-engine, but they live in an ARRAY the\n * normalizer walks at every token position, so re-registering a package\n * appended a second copy of every rule and lexing got slower with every\n * register/unregister cycle.\n *\n * Per-engine parselets and phrases are still left in place: a parselet\n * lives in this engine's isolated registry and a phrase goes into a\n * text-keyed trie where registering the same phrase twice is the same as\n * registering it once, so neither accumulates and both are discarded with\n * the engine instance.\n *\n * Clears the bytecode cache, removing handlers changes what compiled\n * bytecode is valid.\n *\n * @param packageName - The `name` the package was registered under.\n * @returns true if the package was found and unregistered.\n */\n unregisterPackage(packageName: string): boolean {\n const contribution = this.packageContributions.get(packageName);\n if (!contribution) return false;\n\n for (const index of contribution.pluginFunctionIndices) {\n delete this.context.pluginFunctions[index];\n delete this.context.pluginFunctionOwners[index];\n }\n for (const name of contribution.pluginFunctionNames) {\n this.pluginFunctionIndexByName.delete(name);\n }\n for (const namespace of contribution.resolverNamespaces) {\n this.resolverRegistry.unregister(namespace);\n }\n for (const tokenType of contribution.tokenCategories) {\n unregisterTokenCategory(tokenType);\n }\n if (contribution.lexerVocabulary) {\n this.lexer.unregisterVocabulary(contribution.lexerVocabulary);\n }\n for (const name of contribution.asConverterNames) {\n unregisterAsConverter(name);\n }\n for (const ruleName of contribution.normalizerRuleNames) {\n this.normalizer.unregister(ruleName);\n }\n this.packageCompletionItems.delete(packageName);\n\n this.packageContributions.delete(packageName);\n this.registeredPackages.delete(packageName);\n this.bytecodeCache.clear();\n return true;\n }\n\n //#endregion\n\n //#region Public API, Configuration & accessors\n\n /**\n * Get the effective engine configuration currently in use.\n * Includes all defaults merged with any constructor overrides.\n * Useful for introspection, lets consumers see what values are actually\n * in effect after merging with DEFAULT_CONFIG.\n */\n getConfig(): EngineConfig {\n return { ...this.config };\n }\n\n /**\n * Get the underlying diagnostic pipeline for advanced usage.\n */\n getDiagnosticPipeline(): DiagnosticPipeline {\n return this.diagnosticPipeline;\n }\n\n //#endregion\n\n //#region Internal, Execution helpers\n\n /**\n * Store a result in the line cache (with DAG registration).\n * Extracted common pattern from 8 call sites.\n */\n private storeLineResult(\n lineNumber: number,\n result: Value,\n program: BytecodeProgram,\n reads: string[],\n writes: string[],\n expression: string,\n ): void {\n this.lineCache.set(lineNumber, new LineCacheEntry(\n result,\n program,\n reads,\n writes.length > 0 ? writes[0] : null\n ), expression);\n }\n\n /**\n * Execute bytecode and handle the result.\n *\n * Replaces ALL 5 try/catch blocks that previously caught AsyncSuspenseError.\n * Now that executeBytecode returns an EvalResult discriminated union,\n * we simply check result.type instead of catching errors.\n *\n * Sets up AbortController → VM for stale-data prevention.\n * Cleans up the VM stack after execution (success or pending).\n * Fires async resolution via fire-and-forget for pending results.\n *\n * `tracePipeline`/`traceExpression`, when given, are passed straight\n * through to `executeBytecode()`'s own optional VM-step-tracing\n * parameters, used ONLY by {@link evaluateExpressionWithDiagnostic}\n * when `vmTraceEnabled` is on. Omitted by every other caller, with zero\n * behavior change (identical to today's hardcoded `undefined, undefined`).\n */\n private executeAndStore(\n program: BytecodeProgram,\n lineNumber: number,\n expression: string,\n reads: string[],\n writes: string[],\n packageId: string,\n tracePipeline?: DiagnosticPipeline,\n traceExpression?: string,\n ): Value {\n const stackBefore = this.vm.getStack().length;\n\n // Set up AbortController for this evaluation.\n // When the user edits the line before resolution, the old controller\n // is aborted, preventing stale data from surfacing.\n const controller = new AbortController();\n // ── Link to keystroke signal (One AbortController Per Keystroke) ──\n // When the user types a new keystroke, the keystrokeController is aborted,\n // which in turn aborts this local controller, canceling all in-flight\n // async work for this specific evaluation.\n const abortLocal = () => controller.abort();\n this.keystrokeSignal?.addEventListener('abort', abortLocal, { once: true });\n\n abortLogger.localControllerCreated(\"executeAndStore\");\n if (this.keystrokeSignal) {\n abortLogger.signalLinked(\"executeAndStore\");\n }\n\n this.vm.activeSignal = controller.signal;\n this.vm.abortCurrent = () => {\n abortLogger.signalUnlinked(\"executeAndStore\");\n this.keystrokeSignal?.removeEventListener('abort', abortLocal);\n controller.abort();\n };\n\n setActiveQueryClient(this.queryClient);\n const result = executeBytecode(program, this.vm, tracePipeline, traceExpression, this.makeLineContext(lineNumber));\n\n // Single stack cleanup (replaces 10 occurrences)\n while (this.vm.getStack().length > stackBefore) {\n this.vm.pop();\n }\n\n if (result.type === 'pending') {\n // Fire-and-forget async resolution.\n // The keystroke listener stays attached while the async work is\n // in flight so a new keystroke can still cancel it.\n void this.resolveAsync(result);\n\n // Register data source dependency in DAG for re-evaluation tracking\n this.dag.registerLineDataSourceDependency(\n lineNumber,\n result.packageId || packageId,\n [result.queryKey]\n );\n\n const pending = pendingValue(result.queryKey);\n this.storeLineResult(lineNumber, pending, program, reads, writes, expression);\n return pending;\n }\n\n if (result.type === 'error') {\n this.keystrokeSignal?.removeEventListener('abort', abortLocal);\n throw result.error;\n }\n\n // Success path, execution finished synchronously, so unhook the\n // keystroke listener now. Without this, one listener per evaluated\n // line accumulates on the keystroke signal for large documents.\n this.keystrokeSignal?.removeEventListener('abort', abortLocal);\n\n this.dag.registerLine(lineNumber, reads, writes);\n this.storeLineResult(lineNumber, result.value, program, reads, writes, expression);\n return result.value;\n }\n\n /**\n * Execute bytecode and return the raw EvalResult without DAG/LineCache updates.\n * Used by reEvaluateLine, executeCached, and evaluateIncremental which\n * manage their own cache state differently.\n *\n * @param lineNumber - 1-based line this bytecode belongs to, for\n * cross-line features (`prev`/`line<N>`/aggregation. See\n * `makeLineContext()`). Defaults to -1 (the existing \"no real\n * document\" sentinel) for any caller that doesn't have a real line\n * number to pass.\n */\n private executeRaw(program: BytecodeProgram, lineNumber: number = -1): EvalResult {\n const stackBefore = this.vm.getStack().length;\n\n const controller = new AbortController();\n // ── Link to keystroke signal (One AbortController Per Keystroke) ──\n const abortLocal = () => controller.abort();\n this.keystrokeSignal?.addEventListener('abort', abortLocal, { once: true });\n\n abortLogger.localControllerCreated(\"executeRaw\");\n if (this.keystrokeSignal) {\n abortLogger.signalLinked(\"executeRaw\");\n }\n\n this.vm.activeSignal = controller.signal;\n this.vm.abortCurrent = () => {\n abortLogger.signalUnlinked(\"executeRaw\");\n this.keystrokeSignal?.removeEventListener('abort', abortLocal);\n controller.abort();\n };\n\n setActiveQueryClient(this.queryClient);\n const result = executeBytecode(program, this.vm, undefined, undefined, this.makeLineContext(lineNumber));\n\n // Stack cleanup\n while (this.vm.getStack().length > stackBefore) {\n this.vm.pop();\n }\n\n // Sync completion, unhook the keystroke listener to prevent\n // per-evaluation listener accumulation. Pending results keep the\n // listener so in-flight async work stays cancellable.\n if (result.type !== 'pending') {\n this.keystrokeSignal?.removeEventListener('abort', abortLocal);\n }\n\n return result;\n }\n\n /**\n * Fire-and-forget async resolution using async/await.\n *\n * On resolution or error:\n * 1. Checks AbortSignal, if aborted, stale data is discarded.\n * 2. Stores result/error in AsyncResultCache (per-package scoped).\n * 3. Defers re-evaluation to AsyncResolutionBatcher which collapses\n * multiple resolutions into a single DAG walk + re-execution pass\n * and fires typed events to all listeners.\n */\n private async resolveAsync(pending: Extract<EvalResult, { type: 'pending' }>): Promise<void> {\n const { queryKey, resolver, packageId, signal } = pending;\n const effectivePackageId = packageId || '_engine';\n\n // TanStack Query handles dedup + caching automatically via fetchQuery().\n // We just await the resolver and dispatch to the batcher on completion.\n\n try {\n // The resolved value is not needed here, only the fact that it\n // settled: the batcher re-reads it from the cache on re-evaluation.\n await resolver;\n if (signal.aborted) {\n abortLogger.staleDataDiscarded(queryKey, \"signal aborted after resolve\");\n return;\n }\n // Defer re-evaluation to batcher (collapsed across microtask).\n this.batcher.add({\n queryKey,\n packageId: effectivePackageId,\n signal,\n isError: false,\n });\n } catch (err) {\n if (signal.aborted) {\n abortLogger.staleDataDiscarded(queryKey, \"signal aborted after error\");\n return;\n }\n const error = err instanceof Error ? err : new Error(String(err));\n this.batcher.add({\n queryKey,\n packageId: effectivePackageId,\n signal,\n isError: true,\n error,\n });\n }\n }\n\n /**\n * Start refreshing a value in the background if it declared a cadence and the\n * host enabled background refresh. A no-op otherwise, so the pull path is\n * unchanged for a headless host or a value that never wants it.\n */\n private registerBackgroundRefresh(asyncCheck: AsyncCheckResult): void {\n if (!this.backgroundRefresh) return;\n if (asyncCheck.refetchIntervalMs === undefined || !asyncCheck.refetch) return;\n this.backgroundRefresh.register({\n packageId: asyncCheck.packageId || '_engine',\n queryKey: asyncCheck.queryKey,\n intervalMs: asyncCheck.refetchIntervalMs,\n refetch: asyncCheck.refetch,\n });\n }\n\n /**\n * How many live values are currently being refreshed in the background.\n * Zero when the host has not enabled background refresh. For hosts that want\n * to surface it, and for tests.\n */\n getBackgroundRefreshCount(): number {\n return this.backgroundRefresh?.size ?? 0;\n }\n\n //#endregion\n\n //#region Public API, Document parsing\n\n /**\n * Unified parsing method that handles different input types and returns comprehensive results\n * with precise coordinate mapping for inline solves.\n */\n parseDocument(input: string, options: UnifiedParsingOptions = { inputType: 'markdown' }): ParsingResult {\n // Refused before the scan rather than during it. Every limit above this\n // one bounds what a single LINE may ask for, and a document's cost is\n // its line count whatever the lines say: two hundred thousand lines of\n // `1 + 1` exhausted the heap on the per-line records alone, which is a\n // process abort no host can catch. See\n // `constants/Configuration.ts`'s `performance.maxDocumentLines`.\n const maxLines = this.config.performance.maxDocumentLines;\n if (countLines(input, maxLines) > maxLines) {\n throw ErrorFactory.execution(\n \"DOCUMENT_TOO_LARGE\",\n `This document has more than ${maxLines.toLocaleString(\"en-US\")} lines, which is the most the engine will process in one pass`,\n { maxLines },\n );\n }\n // Fresh unit definitions for this pass. A host re-parses the whole\n // document on each keystroke, so rebuilding the table top-to-bottom is\n // what keeps a renamed or deleted definition from lingering. Only drop\n // the bytecode cache when the previous pass actually defined a unit,\n // since its cached programs may have expanded one, a document that never\n // uses the feature keeps its cache and pays nothing here.\n if (!this.userUnits.isEmpty) this.bytecodeCache.clear();\n this.userUnits.clear();\n // Reset running-total accumulators for the same reason units are\n // rebuilt top-to-bottom: a full re-parse must reproduce the first\n // parse. `total += 5` seeds 0 only while the name is undefined, so\n // without this the total reads its own previous pass's value and\n // grows on every keystroke. Cleared here, re-seeded by the line's\n // own `+=`/`-=` as the pass replays it. See resetAccumulators.\n this.resetAccumulators();\n // Scan the entire document in a single pass, bypasses the old\n // split('\\n') → evaluateLines() → join('\\n') → scanDocument()\n // roundtrip. scanDocument() classifies and tokenizes all lines\n // character-by-character with a single Lexer.reset().\n const scanResults = this.lexer.scanDocument(input);\n const processedLines = this.processScanResults(scanResults);\n\n const result: ParsingResult = {\n lines: processedLines,\n totalLines: processedLines.length,\n errors: [],\n };\n\n // Collect errors from processed lines\n for (const line of processedLines) {\n if (line.error) {\n result.errors.push(`Line ${line.lineNumber}: ${line.error}`);\n }\n for (const solve of line.inlineSolves) {\n if (solve.error) {\n result.errors.push(`Line ${line.lineNumber}: ${solve.error}`);\n }\n }\n }\n\n const includeDiagnostics = options.includeDiagnostics ?? false;\n if (includeDiagnostics) {\n const reports = this.diagnosticPipeline.collectReports();\n if (reports.length > 0) {\n result.diagnostics = reports[0].toJSON();\n }\n }\n\n return result;\n }\n\n /**\n * Batch-evaluate an array of lines in a single pass.\n *\n * Uses scanDocument() to classify and tokenize all lines in a single\n * character-by-character walk through the re-joined document text.\n * This eliminates the per-line Lexer.reset() + classifyLine() +\n * findInlineSolvesInLine() overhead from the old three-pass approach.\n *\n * Tokenization results from scanDocument() are passed directly to the\n * parser via evaluateLineWithPreTokenized(), skipping re-lexing.\n */\n /**\n * Batch-evaluate an array of lines in a single pass.\n *\n * Primarily used by tests. For production, prefer parseDocument()\n * which calls scanDocument() directly on the raw document string,\n * bypassing the split→join roundtrip that this method performs.\n */\n evaluateLines(lines: string[]): ParsedLine[] {\n // A whole-document pass, so definitions start empty (see parseDocument).\n if (!this.userUnits.isEmpty) this.bytecodeCache.clear();\n this.userUnits.clear();\n // Reset running-total accumulators for the same reason units are\n // rebuilt top-to-bottom: a full re-parse must reproduce the first\n // parse. `total += 5` seeds 0 only while the name is undefined, so\n // without this the total reads its own previous pass's value and\n // grows on every keystroke. Cleared here, re-seeded by the line's\n // own `+=`/`-=` as the pass replays it. See resetAccumulators.\n this.resetAccumulators();\n // Rejoin lines and scan in a single pass, scanDocument() handles\n // classification + tokenization for all lines in one character walk.\n const documentText = lines.join('\\n');\n const scanResults = this.lexer.scanDocument(documentText);\n return this.processScanResults(scanResults);\n }\n\n /**\n * Process pre-scanned line results into ParsedLine objects.\n *\n * Shared by parseDocument() (which scanDocuments the raw input) and\n * evaluateLines() (which scanDocuments joined line arrays). Handles\n * inline solve extraction, variable assignment detection, and\n * expression evaluation for each non-skipped line.\n */\n private processScanResults(scanResults: ScanLineResult[]): ParsedLine[] {\n const result: ParsedLine[] = [];\n\n // Cross-line features (line references, table columns) read earlier\n // lines' text and results. The incremental `ThreeTierEvaluator` path\n // reads them from `this.documentModel`; the batch path has none, so it\n // reported a no-document error for `total above`, `line N` and\n // `sum of column`. Point the batch cross-line source at the scan and\n // the results array this pass is already building, for the length of\n // the pass, and restore whatever a host had set afterwards. This is\n // reference assignment, not allocation, so a document with no\n // cross-line feature pays nothing (an earlier version built a whole\n // `DocumentModel` per pass and grew the heap measurably).\n const previousBatchScanResults = this.batchScanResults;\n const previousBatchParsedLines = this.batchParsedLines;\n this.batchScanResults = scanResults;\n this.batchParsedLines = result;\n\n try {\n for (const scanResult of scanResults) {\n const lineText = scanResult.text;\n const lineNumber = scanResult.lineNumber;\n const startPosition = scanResult.startOffset;\n const endPosition = scanResult.endOffset;\n const isEmpty = scanResult.classification.skip;\n const inlineSolves: InlineSolvePosition[] = scanResult.inlineSolves.map(s => ({\n start: s.start,\n end: s.end,\n expression: s.expression,\n lineNumber,\n columnNumber: s.columnNumber,\n }));\n const hasInlineSolves = inlineSolves.length > 0;\n\n const parsedLine: ParsedLine = {\n lineNumber,\n text: lineText,\n startPosition,\n endPosition,\n isEmpty,\n hasInlineSolves,\n inlineSolves,\n expression: null,\n result: null,\n error: null,\n };\n\n if (!isEmpty) {\n const isVariableAssignment = lineText.trim().startsWith(':');\n\n if (hasInlineSolves && !isVariableAssignment) {\n for (const solve of inlineSolves) {\n try {\n solve.result = this.evaluateLine(lineNumber, solve.expression);\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n solve.error = errorMessage;\n }\n }\n } else {\n // Sliced from the same offset the tokens were, or the text\n // and the token stream describe different lines.\n const contentOffset = scanResult.classification.contentOffset;\n const evaluable = contentOffset === undefined ? lineText : lineText.slice(contentOffset - startPosition);\n const expression = evaluable.trim();\n if (expression) {\n // Pass pre-tokenized tokens from scanDocument to avoid re-lexing\n try {\n const values = this.evaluateLineWithPreTokenized(\n lineNumber,\n expression,\n scanResult.tokens\n );\n parsedLine.expression = expression;\n parsedLine.result = values[0];\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n parsedLine.error = errorMessage;\n }\n }\n }\n }\n\n // A later line referencing this one reads its result straight from\n // the `result` array above, which already holds it, so nothing more\n // needs recording here.\n result.push(parsedLine);\n }\n } finally {\n this.batchScanResults = previousBatchScanResults;\n this.batchParsedLines = previousBatchParsedLines;\n }\n\n return result;\n }\n\n /**\n * Evaluate a line using pre-tokenized tokens from scanDocument().\n *\n * Skips the lexing step entirely, the tokens are already available\n * from the document-level scan. Only parsing, compilation, and\n * execution are performed.\n *\n * This is the production fast path for evaluateLines(). Note: this\n * path intentionally bypasses the diagnostic pipeline. For diagnostic\n * events, use evaluateExpressionWithDiagnostic() directly.\n */\n private evaluateLineWithPreTokenized(\n lineNumber: number,\n expression: string,\n preTokenized: Token[]\n ): Value[] {\n // Filter markdown tokens as a defensive safety net.\n // ExpressionLexer never produces MD_* tokens, but this guard\n // prevents accidental breakage if the lexer mode changes.\n const tokens: Token[] = [];\n let hasParens = false;\n for (const t of preTokenized) {\n if (t.type === \"LPAREN\" || t.type === \"RPAREN\") hasParens = true;\n tokens.push(t);\n }\n\n // Directly invoke evaluateWithTokens, no lexing needed\n return [this.evaluateWithTokens(lineNumber, expression, tokens, hasParens)];\n }\n\n //#endregion\n\n //#region Internal, Parsing & compilation\n\n /**\n * Route parse+compile to the active parser (PrecedenceParser or Recursive Descent).\n *\n * Sets up the builder on the active parser, loads tokens, and calls\n * parseExpression(). Abstracts the API difference between the two parsers:\n * - PrecedenceParser: parser.setBuilder(builder); parser.parseExpression(0)\n * - RD: parser.builder = builder; parser.parseExpression(0)\n *\n * @param allowLabelFallback - Whether a line that does not parse whole may\n * be retried as \"<label>: <expression>\". True for a real line, false for\n * the retries that fallback makes itself, which is what stops it costing\n * exponential time; see the loop below, and the comment on its recursive\n * call for the measurement.\n */\n private parseExpression(builder: BytecodeBuilder, tokens: Token[], hasParens?: boolean, allowLabelFallback = true): void {\n this.parser.setBuilder(builder);\n // When autoBalanceParens is disabled, skip the O(n) paren-count scan\n // by always passing false, the parser will fail naturally on unmatched\n // parens instead of silently inserting missing closing/opening tokens.\n this.parser.load(tokens, this.config.validation.autoBalanceParens ? hasParens : false);\n this.parser.parseExpression(0);\n\n // parseExpression() stops as soon as it has one complete top-level\n // expression, it never checked whether that consumed the WHOLE\n // token list. Any leftover tokens (a stray trailing number, an\n // unconsumed comma-and-digits from a malformed \"thousands\"-looking\n // literal, a typo'd second operand with a missing operator, ...)\n // were silently discarded rather than surfaced: \"5 3\" evaluated to\n // a confident \"5\", \"1,2345\" to a confident \"1\", with no indication\n // anything was wrong. Requiring full consumption turns every one\n // of those into a real, visible parse error instead.\n const leftover = this.parser.peek();\n if (leftover) {\n // A single trailing bare \"=\" with nothing after it (e.g.\n // \"355/113=\") is tolerated rather than treated as an error.\n // EQUALS is never registered as an infix operator anywhere in\n // this grammar (confirmed, nothing consumes it after a\n // complete expression), so it can't be a legitimate second\n // operand or a typo'd continuation the way a stray number or\n // identifier could be; it's an unambiguous \"show the result\"\n // marker familiar from pocket calculators and other apps in\n // this category (see GitHub issue #65). This is deliberately\n // narrower than tolerating arbitrary trailing tokens, which\n // would reopen the exact silently-wrong-answer bug this same\n // check was added to close (see this function's own doc\n // comment above).\n if (leftover.type === \"EQUALS\" && !this.parser.peekAt(1)) {\n return;\n }\n\n // Labeled-line fallback: \"<label>: <expression>\", e.g. \"pi\n // approximation: 355/113\" (see GitHub issue #65). Only\n // attempted once the whole-line parse has ALREADY failed, so\n // it can never change behavior for a line that already\n // worked. VALID clock times (\"9:30\"), lap times (\"03:04:05\"),\n // and \":name = value\" variable definitions all consume their\n // colon(s) internally during lexing and never produce a real\n // COLON token, confirmed directly against the token stream\n // not assumed, so this can't misfire on any of them. Only a\n // genuine COLON token past position 0 counts (position 0 is\n // reserved for the existing leading-colon variable syntax).\n //\n // The word VALID is load-bearing, and used not to be here. An\n // out-of-range clock time does leave a real COLON token behind,\n // which landed it in this fallback and had it answered with\n // whatever stood to the right of the colon: \"24:00\" answered 0,\n // \"9:60\" answered 60, \"100:5\" answered 5. Those are ordinary\n // things to type (\"24:00\" is a normal way to write the end of a\n // day, \"9:60\" is a normal typo) and every one of them came back\n // as a confident number with no hint that the time had been\n // thrown away, so the numeric case is now refused outright, see\n // the guard in the loop below.\n //\n // Tries every colon position from rightmost to leftmost, not\n // just the last one: a label can itself precede a\n // \":name = value\" definition (\"input value: :x = 5\"), whose\n // OWN leading colon would otherwise be the rightmost colon in\n // the line, slicing right after it strips the colon\n // VariableParselet needs to recognize a definition at all,\n // leaving a bare \"x = 5\" that fails to parse. Falling back to\n // the next colon to the left (\"value:\") keeps \":x = 5\" intact.\n for (let i = allowLabelFallback ? tokens.length - 1 : 0; i >= 1; i--) {\n if (tokens[i].type !== \"COLON\") continue;\n if (i + 1 >= tokens.length) continue;\n\n // Nothing but numbers to the left of the colon means this is\n // not a label at all: it is a time, a lap time or a timecode\n // that the normalizer refused to fuse because one of its\n // fields is out of range. A label is prose (\"pi\n // approximation:\", \"total:\"), and the labelled lines this\n // fallback exists for all have a word in front of the colon.\n // Reading \"24:00\" as the label \"24\" and the expression \"00\"\n // is never what was meant, so it is an error rather than an\n // answer.\n let labelIsAllNumeric = true;\n for (let j = 0; j < i; j++) {\n const type = tokens[j].type;\n if (type !== \"NUMBER\" && type !== \"COLON\") {\n labelIsAllNumeric = false;\n break;\n }\n }\n if (labelIsAllNumeric) {\n // Rebuilt from the tokens rather than sliced out of the\n // source, which this level does not have. Everything up\n // to and including the field after the colon, so\n // \"24:00 + 1\" names \"24:00\" and not the whole line.\n const literal = tokens.slice(0, i + 2).map((t) => t.value).join(\"\");\n throw ErrorFactory.parsing(\n \"INVALID_TIME_LITERAL\",\n `\"${literal}\" is not a valid time`,\n { tokenType: tokens[i].type, tokenValue: literal }\n );\n }\n\n builder.reset();\n try {\n // `false`: the retry gets a plain parse, with no fallback\n // of its own. It used to get the full one, and that made\n // this loop cost exponential time for no extra coverage.\n //\n // A retry on `tokens.slice(i + 1)` that ran its own\n // fallback would try the suffix after each colon j > i,\n // which is `tokens.slice(j + 1)`, which is a slice THIS\n // loop already tried on an earlier iteration, since it\n // walks rightmost-first and j > i. So every level below\n // the first re-attempted parses that had already failed,\n // and each of those levels re-attempted them again: a line\n // with k colons compiled 2^k times. Measured on a\n // 723-character fuzz case with 19 colons: 524,288 parse\n // attempts, 18 seconds, and then the line was REJECTED. A\n // host evaluating per keystroke froze for that long.\n //\n // Nothing is lost by cutting it. The suffixes the deeper\n // levels reached are exactly the ones this loop visits\n // itself, in the same rightmost-first order.\n this.parseExpression(builder, tokens.slice(i + 1), hasParens, false);\n return;\n } catch {\n // This colon's fragment didn't parse cleanly either\n // try the next one to the left before giving up.\n }\n }\n\n throw ErrorFactory.parsing(\n \"UNEXPECTED_TRAILING_TOKEN\",\n `Unexpected token after expression: \"${leftover.value}\"`,\n { tokenType: leftover.type, tokenValue: leftover.value }\n );\n }\n }\n\n //#region Symbolic algebra, `=>` and bare equation-statement grammar\n\n /**\n * Compiles a standalone token list into a fresh, independent\n * `BytecodeProgram`, used for a `=>`-triggered expression and for a\n * bare equation's own right-hand side. Reuses {@link parseExpression}\n * (the SAME \"compile a token list into a builder, then check for\n * leftover trailing tokens\" logic every ordinary line already goes\n * through), just with a throwaway builder instead of the pooled one\n * (this grammar is rare, a per-call allocation here is a non-issue).\n */\n private compileAdHoc(tokens: Token[]): BytecodeProgram {\n const builder = new BytecodeBuilder(this.pluginFunctionIndexByName);\n this.parseExpression(builder, tokens);\n return builder.build();\n }\n\n /**\n * Executes an already-compiled program in symbolic-tolerant mode (an\n * undefined variable becomes a `Symbolic` placeholder instead of\n * throwing `UNDEFINED_VARIABLE`. See `vm/VM.ts`'s `executeBytecode()`\n * doc comment on its own `symbolicTolerant` parameter). Used by both\n * the \"just simplify this\" `=>` mode and bare equation evaluation\n * (a bare assignment's RHS, and an equation's own RHS at solve time)\n *, every one of these needs forward-tolerant reads of not-yet-defined\n * names, which ordinary evaluation deliberately never allows.\n *\n * `lineNumber` is the 1-based document line this program belongs to, so\n * the RHS still receives a {@link makeLineContext}, a bare assignment's\n * right-hand side (`total = prev`, `x = line2`) can therefore read\n * cross-line results exactly as a bare expression line does. Defaults to\n * `-1` (the \"no real document\" sentinel) for the expression-level and\n * `=>`-without-a-document callers, which naturally yields the same\n * `LINE_REF_NO_DOCUMENT` a single-expression eval already returns.\n */\n private executeSymbolicTolerant(program: BytecodeProgram, lineNumber: number = -1): Value {\n const result = executeBytecode(program, this.vm, undefined, undefined, this.makeLineContext(lineNumber), true);\n if (result.type === 'error') throw result.error;\n if (result.type === 'pending') {\n throw ErrorFactory.execution(\n 'THEREFORE_ASYNC_UNSUPPORTED',\n `\"=>\" doesn't support expressions that call an async operation (weather/stocks/currency).`,\n );\n }\n return result.value;\n }\n\n /** Compiles and executes `tokens` in symbolic-tolerant mode, the \"just simplify this\" `=>` fallback when there's no stored equation to solve. `lineNumber` (1-based, `-1` outside a document) is forwarded so a bare assignment's RHS can resolve cross-line references. */\n private simplifySymbolically(tokens: Token[], lineNumber: number = -1): Value {\n return this.executeSymbolicTolerant(this.compileAdHoc(tokens), lineNumber);\n }\n\n /**\n * Parses a bare (colon-less) equation's left-hand side, `factor1 *\n * factor2 * ... * variable`, into an ordered list of bare names, or\n * `null` if `tokens` isn't EXACTLY that shape (an alternating\n * `IDENT/UNIT`, `STAR`, `IDENT/UNIT`, `STAR`, ... sequence with no\n * other token types). Returning `null` means \"don't intercept this\n * line at all\", it falls through to whatever the ordinary expression\n * grammar already does with a bare `=` in it (today: a clear parse\n * error), so this pattern-match can only ever ADD a new capability,\n * never take one away.\n *\n * Requiring `IDENT`/`UNIT` at every name position is what keeps this\n * safe from the reserved-keyword collision risk `VariableParselet.ts`\n * guards against for the colon-prefixed form: a genuinely reserved\n * word (`clamp`, `global`, ...) always lexes as ITS OWN token type,\n * never `IDENT`/`UNIT`, so it can never satisfy this pattern, the\n * same protection, for free, without a duplicated keyword list.\n */\n private parseFactorChain(tokens: Token[]): string[] | null {\n if (tokens.length === 0 || tokens.length % 2 === 0) return null;\n const names: string[] = [];\n for (let i = 0; i < tokens.length; i++) {\n if (i % 2 === 0) {\n if (tokens[i].type !== 'IDENT' && tokens[i].type !== 'UNIT') return null;\n names.push(tokens[i].value);\n } else {\n if (tokens[i].type !== 'STAR') return null;\n }\n }\n return names;\n }\n\n /**\n * Solves a stored equation, `variable = inv(factor1*factor2*...) *\n * rhs`. Every step is symbolic-aware (`vm/MatrixOps.ts`'s\n * `matrixMultiply()`/`inverse()`), so a factor whose OWN cells are\n * still-unassigned free variables (`s = [sx,0,0;...]`) solves\n * correctly, producing a Matrix whose cells are algebraic formulas\n * rather than plain numbers. Errors (a missing factor, a non-Matrix\n * factor/RHS, a singular combined matrix) are returned as `Error`-typed\n * Values, not thrown, matching this engine's established \"matrix\n * errors propagate as values\" convention (DIMENSION_MISMATCH,\n * SINGULAR_MATRIX, ...).\n */\n private solveEquation(equation: EquationDef, lineNumber: number = -1): Value {\n const factorValues: Value[] = [];\n for (const name of equation.factorNames) {\n const v = this.vm.getVar(name);\n if (v === undefined) {\n return errorValue(\n 'EQUATION_FACTOR_UNDEFINED',\n `Cannot solve for \"${equation.variable}\": \"${name}\" is not yet defined.`,\n );\n }\n if (v.type !== ValueType.Matrix) {\n return errorValue(\n 'EQUATION_FACTOR_NOT_MATRIX',\n `Cannot solve for \"${equation.variable}\": \"${name}\" must be a Matrix (got a different value type).`,\n );\n }\n factorValues.push(v);\n }\n\n let combined = factorValues[0].value as MatrixData;\n for (let i = 1; i < factorValues.length; i++) {\n const product = matrixMultiply(combined, factorValues[i].value as MatrixData);\n if (product.type === ValueType.Error) return product;\n combined = product.value as MatrixData;\n }\n\n const inv = inverse(combined);\n if (inv.type === ValueType.Error) return inv;\n\n const rhsValue = this.executeSymbolicTolerant(equation.rhsProgram, lineNumber);\n if (rhsValue.type !== ValueType.Matrix) {\n return errorValue(\n 'EQUATION_RHS_NOT_MATRIX',\n `Cannot solve for \"${equation.variable}\": the right-hand side must be a Matrix.`,\n );\n }\n\n return matrixMultiply(inv.value as MatrixData, rhsValue.value as MatrixData);\n }\n\n /**\n * Detects and handles this session's two new symbolic-algebra grammar\n * shapes on `normalizedTokens`, returning the computed result directly\n * (bypassing ordinary bytecode compilation/caching entirely, since\n * BOTH shapes have effects, a stored equation, a direct variable\n * assignment, that a cached bytecode program can't represent) or\n * `null` if neither shape matches (meaning ordinary processing should\n * proceed exactly as it did before this feature existed):\n *\n * 1. `<bareIdent> =>` or `<expr> =>`, trailing `THEREFORE`. A bare\n * identifier with a STORED equation solves it (see\n * {@link solveEquation}); anything else (including a bare\n * identifier with NO stored equation) runs in symbolic-tolerant\n * mode and simplifies (see {@link simplifySymbolically}), a\n * near-free \"just simplify this\" mode.\n * 2. `factor1*factor2*...*variable = rhs`, a bare (colon-less), NOT\n * already colon/global-prefixed, top-level `EQUALS` whose LHS\n * matches {@link parseFactorChain}'s narrow pattern. A single bare\n * name (`s = [sx,0,0;...]`) is an ORDINARY (colon-less) assignment\n *, its RHS is ALWAYS evaluated symbolic-tolerantly (so a matrix\n * literal with still-unassigned entries assigns successfully,\n * carrying those free variables as real symbolic cells) and stored\n * via `vm.setVar()`. Two or more names (`s*t*v = rhs`) stores a\n * genuine equation keyed by the LAST name (`v`), solved later via\n * shape 1 above.\n *\n * This is a deliberately narrow pattern match, not a general equation\n * solver. See `OpRegistry.ts`'s `EquationDef` doc comment and this\n * session's own Phase H.2 scope decision (full symbolic MATRICES, not\n * a general CAS).\n */\n /**\n * Registers a document-scoped user unit from a `1 <name> = <n> <unit>` line\n * and returns the `<name> defined` confirmation, or `null` when the line is\n * not a unit definition (so ordinary processing continues unchanged).\n *\n * Like the symbolic-grammar shapes it sits beside, this has an effect (a\n * stored definition) that no cached bytecode program could represent, so it\n * short-circuits compilation the same way. See {@link UserUnitTable}.\n *\n * The pattern is kept deliberately narrow so it cannot swallow an equation:\n *\n * - The coefficient must be exactly `1`. `2 x = 10` stays a scalar equation\n * (`x =>` solves it); only the natural `1 sprint = 2 weeks` shape is a\n * definition.\n * - The name is one or more identifiers, never a built-in unit (those lex as\n * UNIT, not IDENT), so a built-in unit cannot be redefined.\n * - The base must be a recognized unit (a UNIT token). A non-unit right side\n * declines here and is left to whatever handled it before, so a defined\n * unit is always dimensioned, never free-standing.\n *\n * `tokens` are already normalized, so the implicit-multiply pass has usually\n * inserted a STAR between the coefficient and the name (`1 * sprint`); it is\n * tolerated and skipped.\n */\n private tryDefineUserUnit(tokens: Token[]): Value | null {\n // Shortest definition is NUMBER IDENT EQUALS NUMBER UNIT.\n if (tokens.length < 5) return null;\n if (tokens[0].type !== 'NUMBER' || Number(tokens[0].value) !== 1) return null;\n\n let i = 1;\n // The implicit-multiply STAR between the coefficient and the name.\n if (tokens[i].type === 'STAR') i++;\n\n const nameWords: string[] = [];\n while (i < tokens.length && tokens[i].type === 'IDENT') {\n nameWords.push(tokens[i].value);\n i++;\n }\n if (nameWords.length === 0) return null;\n\n if (tokens[i]?.type !== 'EQUALS') return null;\n i++;\n if (tokens[i]?.type !== 'NUMBER') return null;\n const ratioToken = tokens[i];\n i++;\n if (tokens[i]?.type !== 'UNIT') return null;\n const baseToken = tokens[i];\n i++;\n // A definition is the whole line: anything trailing means this is some\n // other construct that merely starts the same way.\n if (i !== tokens.length) return null;\n\n this.userUnits.define(nameWords, ratioToken.value, baseToken.value);\n // A user unit is expanded at parse time, so the compiled bytecode for\n // any line using one depends on the definitions in scope, which the\n // cache key (the raw expression text) does not capture. A new or changed\n // definition therefore invalidates every cached program, so a later\n // `6 sprints` recompiles against this definition rather than a stale one.\n // Definition lines are rare, so this clear is not on any hot path.\n this.bytecodeCache.clear();\n return stringValue(`${nameWords.join(' ')} defined`);\n }\n\n /**\n * `name += expr` / `name -= expr`, a running total. The accumulator reads\n * its current value, adds or subtracts the right-hand side, stores the\n * result, and answers with the new value, so a note becomes a live ledger\n * where each line adjusts a balance in place. Returns null to decline\n * anything that is not the compound shape.\n *\n * Handled here, in the same effectful, cache-bypassing channel as\n * {@link tryDefineUserUnit} and the bare `count = 10` assignment (see\n * {@link trySymbolicGrammar}), rather than as a parselet: a bare identifier\n * is a Tier-1 prefix that emits `LOAD_VAR name` before any infix parselet on\n * `+=` could run, and that pre-emitted load throws UNDEFINED_VARIABLE for a\n * first-use accumulator. Seeding 0 for a first `+=`/`-=` is a one-line\n * `getVar`/`setVar` here where it cannot be from a parselet, a deliberate\n * departure from a plain reference, which still reports the undefined name.\n *\n * The right-hand side is parenthesised and run through the ORDINARY (not\n * symbolic-tolerant) path, so `bal += 3 * 4` is `bal + 12`, a genuine typo in\n * it (`total += nope`) is a real UNDEFINED_VARIABLE, and the accumulation\n * goes through the VM's own ADD/SUB: money stays money, a unit stays its\n * unit, and the seed 0 added to a typed right-hand side takes that type on\n * first use. The colon (`:name`) and `global :name` grammars are untouched:\n * they lex their own leading token, never IDENT/UNIT, so they decline here.\n */\n private tryCompoundAssignment(tokens: Token[], lineNumber: number = -1): Value | null {\n if (tokens.length < 2) return null;\n const nameTok = tokens[0];\n const opTok = tokens[1];\n const isName = nameTok.type === 'IDENT' || nameTok.type === 'UNIT';\n const isCompound = opTok.type === 'PLUS_EQUALS' || opTok.type === 'MINUS_EQUALS';\n if (!isName || !isCompound) return null;\n\n const rhs = tokens.slice(2);\n if (rhs.length === 0) {\n throw ErrorFactory.parsing(\n 'COMPOUND_ASSIGN_REQUIRES_EXPRESSION',\n `\"${nameTok.value} ${opTok.value}\" needs an expression on the right, e.g. \"${nameTok.value} ${opTok.value} 10\".`,\n );\n }\n\n const name = nameTok.value;\n // Remember this name is an accumulator, so a batch document pass can\n // reset it before re-evaluating (see parseDocument): the seed below\n // only fires when the name is undefined, which after the first pass it\n // no longer is, so without the reset the total would read its own\n // previous pass's value and double-count on every keystroke.\n this.accumulatorNames.add(name);\n // A first `+=`/`-=` on an unknown name seeds 0, so a ledger can open\n // straight into `spent += 10` without an UNDEFINED_VARIABLE.\n if (this.vm.getVar(name) === undefined) this.vm.setVar(name, numberValue(0));\n\n const op = opTok.type === 'PLUS_EQUALS' ? { type: 'PLUS', text: '+' } : { type: 'MINUS', text: '-' };\n // `name <op> ( rhs )`: the accumulator is read as an ordinary IDENT so a\n // unit-letter name (`b`, `s`) loads its variable rather than a unit, and\n // the parentheses give the right-hand side its own precedence (`bal += 3\n // * 4` is bal + 12, `bal -= 1 + 2` is bal - 3).\n const accTokens: Token[] = [\n createFusedToken('IDENT', name, [nameTok]),\n createFusedToken(op.type, op.text, [opTok]),\n createFusedToken('LPAREN', '(', [opTok]),\n ...rhs,\n createFusedToken('RPAREN', ')', [opTok]),\n ];\n\n const result = executeBytecode(\n this.compileAdHoc(accTokens), this.vm, undefined, undefined, this.makeLineContext(lineNumber), false,\n );\n if (result.type === 'error') throw result.error;\n if (result.type === 'pending') {\n throw ErrorFactory.execution(\n 'COMPOUND_ASSIGN_ASYNC_UNSUPPORTED',\n `A running total (+= / -=) cannot use an async operation (weather/stocks/currency) on its right-hand side.`,\n );\n }\n this.vm.setVar(name, result.value);\n return result.value;\n }\n\n /**\n * Reset every running-total accumulator (`total += 5`) to undefined, and\n * return their names.\n *\n * An accumulator seeds 0 only while its name is undefined, then reads that\n * value on each `+=`/`-=`. A document is re-evaluated top-to-bottom on\n * every keystroke, so unless the name is cleared first the total reads its\n * own previous evaluation's value and grows without bound. The batch\n * document pass (`parseDocument`/`evaluateLines`) calls this at the start\n * of each pass; the incremental {@link ThreeTierEvaluator} calls it and\n * then marks the lines that touch each name dirty, since it re-runs lines\n * selectively rather than replaying the whole document.\n */\n resetAccumulators(): ReadonlySet<string> {\n for (const name of this.accumulatorNames) this.vm.deleteVar(name);\n return this.accumulatorNames;\n }\n\n private trySymbolicGrammar(normalizedTokens: Token[], lineNumber: number = -1): Value | null {\n if (normalizedTokens.length === 0) return null;\n\n const last = normalizedTokens[normalizedTokens.length - 1];\n if (last.type === 'THEREFORE') {\n const beforeTokens = normalizedTokens.slice(0, -1);\n if (beforeTokens.length === 0) {\n throw ErrorFactory.parsing('THEREFORE_REQUIRES_EXPRESSION', `\"=>\" needs an expression or variable name before it.`);\n }\n if (beforeTokens.length === 1 && (beforeTokens[0].type === 'IDENT' || beforeTokens[0].type === 'UNIT')) {\n // The matrix product-chain equation is checked FIRST and its\n // behaviour is unchanged. The scalar kind is only consulted when\n // that finds nothing, so the older path can never be diverted.\n const name = beforeTokens[0].value;\n const equation = this.vm.getEquation(name);\n const scalar = this.vm.getScalarEquation(name);\n if (equation) {\n const solved = this.solveEquation(equation, lineNumber);\n // A product chain of names is stored as a matrix equation\n // on sight, since whether the factors are matrices is only\n // knowable at solve time. When they turn out not to be,\n // `a*n = 10` with a plain numeric `a` is an ordinary scalar\n // equation, so fall through to that rather than leaving the\n // user with \"must be a Matrix\" for a line that has a\n // perfectly good answer. Every other failure (a missing\n // factor, a singular matrix) still surfaces unchanged.\n const isNotMatrix = solved.type === ValueType.Error && solved.value === 'EQUATION_FACTOR_NOT_MATRIX';\n if (!isNotMatrix || !scalar) return solved;\n }\n if (scalar) {\n return this.solveScalarEquation(scalar, lineNumber);\n }\n }\n return this.simplifySymbolically(beforeTokens, lineNumber);\n }\n\n // An algebra verb (`expand(...)`, and the later phases' `factor`/\n // `solve`) is itself a request to work symbolically, so it does not also\n // need a trailing `=>`. Without this, `expand((x+1)*(x+2))` on its own\n // line would hard-throw UNDEFINED_VARIABLE on `x` before ever reaching\n // the builtin. Placed after the THEREFORE branch so an explicit `=>`\n // still wins, and before the COLON/GLOBAL guard so the existing\n // assignment grammars stay untouched.\n if (containsSymbolicCall(normalizedTokens)) {\n return this.simplifySymbolically(normalizedTokens, lineNumber);\n }\n\n // Already the colon-prefixed (`:name = value`) or `global :name`\n // grammar, completely untouched, don't even attempt to match.\n if (normalizedTokens[0].type === 'COLON' || normalizedTokens[0].type === 'GLOBAL') return null;\n\n // A goal-seek line (`solve line N for <var> = <target>`) owns its own\n // `=`: the `= <target>` is part of that grammar, not an equation to\n // store. Declining here lets GoalSeekParselet parse the whole line,\n // rather than the scalar-equation detector below splitting on the `=`\n // and handing `solve line N for <var>` to a parselet that expects the\n // `=` to follow.\n if (normalizedTokens[0].type === 'GOAL_SEEK') return null;\n\n const eqIdx = normalizedTokens.findIndex(t => t.type === 'EQUALS');\n if (eqIdx === -1) return null;\n\n const names = this.parseFactorChain(normalizedTokens.slice(0, eqIdx));\n if (names === null) {\n // Not a product chain. It may still be a general scalar equation\n // (`x^2-4 = 0`), which is a strictly narrower attempt made only\n // after every existing shape has declined. See\n // {@link tryStoreScalarEquation} for what it refuses to swallow.\n return this.tryStoreScalarEquation(normalizedTokens, eqIdx);\n }\n\n const rhsTokens = normalizedTokens.slice(eqIdx + 1);\n\n if (names.length === 1) {\n const result = this.simplifySymbolically(rhsTokens, lineNumber);\n this.vm.setVar(names[0], result);\n return result;\n }\n\n const freeVar = names[names.length - 1];\n const factorNames = names.slice(0, -1);\n this.vm.defineEquation(freeVar, factorNames, this.compileAdHoc(rhsTokens));\n // Also stored as a scalar equation, so that `a*n = 10` with a numeric\n // `a` still has an answer. Which of the two kinds applies depends on\n // whether the factors are matrices, and that is not known until solve\n // time; storing both costs one extra compile of a line the user is\n // about to ask about anyway. The matrix kind is always tried first, so\n // this cannot change what an existing document does.\n this.vm.defineScalarEquation(freeVar, this.compileAdHoc(normalizedTokens.slice(0, eqIdx)), this.compileAdHoc(rhsTokens));\n return stringValue(`${freeVar} stored as an equation — solve with \"${freeVar} =>\"`);\n }\n\n /**\n * Stores a general scalar equation (`x^2 - 4 = 0`) keyed by its unknown, or\n * returns `null` to let ordinary processing continue.\n *\n * This is the riskiest pattern match in the file, because a bare `=` is\n * already claimed by three shipped grammars, and swallowing any of them\n * would break a working feature silently. Each is excluded deliberately:\n *\n * - **A user-defined function definition** (`f(x) = 2*x`). Its left side is\n * a name followed by `(`, which no equation ever is, so a `LPAREN` in\n * second position declines outright. This is the exclusion that matters\n * most: `parseFactorChain` already returns `null` for it, so without this\n * guard the definition grammar would be intercepted before the parser\n * ever saw it.\n * - **A bare assignment** (`a = [1,2;3,4]`) and **a product-chain matrix\n * equation** (`a*x = [60;70]`). Both are handled by `parseFactorChain`\n * above and never reach here.\n * - **A colon-prefixed or global assignment**. Excluded earlier still.\n *\n * Two further conditions narrow it to genuine equations. There must be\n * exactly one top-level `=` (an `==` comparison lexes as `EQUALITY`, a\n * different token, so it cannot collide), and at least one side must carry\n * an unknown. Without that last check `2+2 = 4` would become an equation\n * with no variable and report an identity, where today it is a parse error;\n * changing an unrelated line's behaviour is not this feature's business.\n *\n * @param normalizedTokens - The whole line's normalized tokens.\n * @param eqIdx - Index of the first `EQUALS` token.\n * @returns A confirmation value when stored, or `null` to decline.\n */\n private tryStoreScalarEquation(normalizedTokens: Token[], eqIdx: number): Value | null {\n if (normalizedTokens[1]?.type === 'LPAREN') return null;\n if (eqIdx === 0 || eqIdx === normalizedTokens.length - 1) return null;\n\n const lhsTokens = normalizedTokens.slice(0, eqIdx);\n const rhsTokens = normalizedTokens.slice(eqIdx + 1);\n if (rhsTokens.some(t => t.type === 'EQUALS')) return null;\n\n const unknowns = this.equationUnknowns(lhsTokens, rhsTokens);\n if (unknowns.length !== 1) return null;\n\n const variable = unknowns[0];\n this.vm.defineScalarEquation(variable, this.compileAdHoc(lhsTokens), this.compileAdHoc(rhsTokens));\n return stringValue(`${variable} stored as an equation — solve with \"${variable} =>\"`);\n }\n\n /**\n * The names in an equation that have no value yet, which is what makes them\n * the thing to solve for.\n *\n * A name that already holds a value is not an unknown: in `y = 2` followed\n * by `x + y = 5`, only `x` is being solved for. A name that is a defined\n * function is likewise excluded, so a call to one never looks like an\n * unknown.\n *\n * @param lhsTokens - Left-hand side tokens.\n * @param rhsTokens - Right-hand side tokens.\n * @returns The distinct unassigned names, in first-seen order.\n */\n private equationUnknowns(lhsTokens: Token[], rhsTokens: Token[]): string[] {\n const unknowns: string[] = [];\n for (const token of [...lhsTokens, ...rhsTokens]) {\n if (token.type !== 'IDENT' && token.type !== 'UNIT') continue;\n if (this.vm.getVar(token.value) !== undefined) continue;\n if (this.vm.hasUserFunction(token.value)) continue;\n if (!unknowns.includes(token.value)) unknowns.push(token.value);\n }\n return unknowns;\n }\n\n /**\n * Solves a stored scalar equation via `symbolic/Solve.ts`.\n *\n * Both sides are evaluated symbolic-tolerantly first, so the unknown\n * survives as a `Symbolic` value rather than throwing, and a side that\n * reduces to a plain number is lifted into the symbolic domain to match.\n *\n * @param equation - The stored equation.\n * @returns The solution, rendered by the same helper `solve()` uses, so the\n * two surfaces cannot disagree about how an outcome reads.\n */\n private solveScalarEquation(equation: ScalarEquationDef, lineNumber: number = -1): Value {\n const lhs = this.executeSymbolicTolerant(equation.lhsProgram, lineNumber);\n const rhs = this.executeSymbolicTolerant(equation.rhsProgram, lineNumber);\n return solveEquationValues(lhs, rhs, equation.variable);\n }\n\n //#endregion\n\n /**\n * Lex an expression via `resetExpression` (skips `classifyLine`\n * callers already know this is an expression), filtering out COMMENT\n * tokens (they have no parselet) and tracking whether any paren was\n * seen. Shared by every lex-then-{@link prepareExpression} call site:\n * {@link compileExpression}, {@link tryCompileExpression}, and\n * {@link evaluateExpressionWithDiagnostic}. `onToken`, when given, is\n * called once per emitted (already-filtered) token, used ONLY by the\n * diagnostic path to fire its per-token `TokenEmitted` events; every\n * other caller omits it.\n */\n private lexToTokens(expression: string, onToken?: (t: Token) => void): { tokens: Token[]; hasParens: boolean } {\n const tokens: Token[] = [];\n let hasParens = false;\n this.lexer.resetExpression(expression);\n for (const t of this.lexer) {\n if (t.type === 'COMMENT') continue;\n if (t.type === \"LPAREN\" || t.type === \"RPAREN\") hasParens = true;\n tokens.push(t);\n onToken?.(t);\n }\n return { tokens, hasParens };\n }\n\n /**\n * Shared pipeline front-half: safety checks → COMMENT filter →\n * normalize → complexity → read/write extraction → bytecode cache\n * lookup or parse+compile.\n *\n * Used by {@link evaluateWithTokens} (which continues into preflight +\n * execution) and {@link compileExpression} (compile-only). Previously\n * both carried their own copy of this sequence, which had already\n * drifted. Returns a discriminated union instead of throwing so each\n * caller decides whether/how to re-throw.\n *\n * The `'error'` variant carries the actual `EngineError` each safety\n * check or `parseExpression()` itself already constructed, not just\n * its flattened `.message` (the previous shape). A parse failure in\n * particular can be any of dozens of specific codes (UNDEFINED_VARIABLE,\n * NO_PREFIX_PARSELET, FUNCTION_ARITY_MISMATCH, ...), each with its own\n * `expected`/`found`/`suggestion` detail, callers used to discard all\n * of that and reconstruct a generic EVALUATION_ERROR/PARSE_ERROR wrapper\n * around just the message, which directly worked against this session's\n * \"errors are verbose and easy to understand\" goal. Callers should\n * generally just `throw prep.error` (see {@link evaluateWithTokens},\n * {@link compileExpression}) rather than wrapping it again.\n *\n * `onFusion`, when given, is passed straight through to the normalizer's\n * own optional per-fusion callback, used ONLY by\n * {@link evaluateExpressionWithDiagnostic} to observe individual token\n * fusions for its `normalizer` diagnostic stage. Omitted by every other\n * caller, with zero behavior change (identical to not passing a 2nd\n * argument to `normalizer.normalize()` at all).\n *\n * The `'error'` variant's `normalizedTokens` is populated whenever\n * normalization already ran before the failure (`'complexity'`/`'parse'`\n * stages), `undefined` when it failed before tokens were even considered\n * (`'length'` stage), lets {@link evaluateExpressionWithDiagnostic}\n * reconstruct its own diagnostic-stage payloads (which need the\n * normalized tokens to recompute a display-only complexity score) without\n * re-deriving them by hand.\n *\n * The `'ready'` (uncached) variant's `parserAlloc` is the\n * `AllocationTracker.track('parser', ...)` result for JUST the actual\n * parse+build call (`null` whenever `AllocationTracker.isEnabled()` is\n * false, or on a cache hit, no parsing happened). This has to be\n * measured HERE, not reconstructed by a caller after the fact: unlike\n * every other diagnostic field, a heap-delta measurement only means\n * anything over the EXACT span it's wrapped around, wrapping the\n * whole `prepareExpression()` call from the outside (as\n * {@link evaluateExpressionWithDiagnostic} briefly did) widens that span\n * to also cover normalize/complexity-check/cache-lookup, which measurably\n * produced negative-allocation readings (a GC sweep landing inside the\n * wider window) in `AllocationTracker.spec.ts` well over half the time.\n */\n private prepareExpression(\n expression: string,\n tokens: Token[],\n hasParens: boolean | undefined,\n onFusion?: (fusion: TokenFusion) => void,\n lineNumber: number = -1,\n ):\n | { kind: 'empty' }\n | { kind: 'error'; stage: 'length' | 'complexity' | 'parse'; error: EngineError; reads?: string[]; writes?: string[]; normalizedTokens?: Token[] }\n | { kind: 'ready'; normalizedTokens: Token[]; reads: string[]; writes: string[]; program: BytecodeProgram; cached: boolean; parserAlloc?: StageAllocation | null }\n | { kind: 'symbolic-solve'; normalizedTokens: Token[]; value: Value; reads?: string[]; writes?: string[] } {\n // ══ SAFETY CHECK 1: Expression length limit ══\n const lengthCheck = checkExpressionLength(expression, this.config.validation);\n if (!lengthCheck.passed) {\n return { kind: 'error', stage: 'length', error: lengthCheck.error!.engineError! };\n }\n\n // Filter COMMENT tokens, they have no parselet.\n const exprTokens = tokens.filter(t => t.type !== 'COMMENT');\n if (exprTokens.length === 0) {\n return { kind: 'empty' };\n }\n\n // ══ NORMALIZER ══\n // Phrase fusion, implicit multiply, domain token merging.\n const normalizedTokens = this.normalizer.normalize(exprTokens, onFusion);\n\n // ══ SAFETY CHECK 2: Complexity scoring ══\n const complexityCheck = checkExpressionComplexity(normalizedTokens, this.config.validation);\n if (!complexityCheck.passed) {\n return { kind: 'error', stage: 'complexity', error: complexityCheck.engineError!, normalizedTokens };\n }\n\n // ══ SYMBOLIC ALGEBRA: `=>` / bare equation-statement grammar ══\n // Bypasses bytecode caching entirely, both shapes have effects\n // (a stored equation, a direct vm.setVar()) a cached program can't\n // represent. See trySymbolicGrammar()'s own doc comment.\n // The symbolic grammar parses its own operand sub-ranges (see\n // simplifySymbolically/compileAdHoc), so it can throw the parser's\n // errors from here, ahead of the try/catch guarding the main parse\n // below. Caught into the same 'parse' result every other failure in\n // this method returns, because a throw escaping prepareExpression\n // reaches tryCompileExpression(), which is documented as a\n // non-throwing boolean and is called by LanguageService on every\n // visible line on every keystroke. `total =` is a line half-typed on\n // the way to `total = 5`, and it took the editor down.\n let symbolicResult: Value | null;\n // A compound assignment (`total += 5`) reads and writes its own name,\n // unlike the other symbolic shapes whose effect the DAG deliberately\n // cannot track. It MUST surface those reads/writes: without a write\n // registered, the incremental evaluator never checkpoints the line, so\n // its own value is never reset before a re-run and the running total\n // double-counts on every edit; and dependent lines never re-evaluate.\n let compoundReadsWrites: { reads: string[]; writes: string[] } | null = null;\n try {\n // A user-unit definition (`1 sprint = 2 weeks`) is an effectful line\n // like the symbolic shapes below, so it rides the same non-bytecode\n // channel. Checked first, so it claims its narrow pattern before the\n // scalar-equation grammar sees the bare `=`.\n symbolicResult = this.tryDefineUserUnit(normalizedTokens);\n if (symbolicResult === null) {\n const compound = this.tryCompoundAssignment(normalizedTokens, lineNumber);\n if (compound !== null) {\n symbolicResult = compound;\n compoundReadsWrites = extractReadsAndWrites(normalizedTokens);\n }\n }\n if (symbolicResult === null) {\n symbolicResult = this.trySymbolicGrammar(normalizedTokens, lineNumber);\n }\n } catch (e) {\n // reads/writes supplied for the same reason the main parse's catch\n // supplies them: the line names variables even though it does not\n // yet parse, so a caller tracking dependencies can re-evaluate it\n // once the user finishes typing.\n const { reads, writes } = extractReadsAndWrites(normalizedTokens);\n return { kind: 'error', stage: 'parse', error: normalizeUnknownError(e), reads, writes, normalizedTokens };\n }\n if (symbolicResult !== null) {\n return { kind: 'symbolic-solve', normalizedTokens, value: symbolicResult, reads: compoundReadsWrites?.reads, writes: compoundReadsWrites?.writes };\n }\n\n const { reads, writes } = extractReadsAndWrites(normalizedTokens);\n\n // ══ BYTECODE CACHE / PARSE+COMPILE ══\n const cachedProgram = this.bytecodeCache.get(expression);\n if (cachedProgram) {\n return { kind: 'ready', normalizedTokens, reads, writes, program: cachedProgram, cached: true };\n }\n\n // Get a pooled builder, avoids 4 heap allocations per expression\n const builder = this.builderPool[this.builderPoolIndex++ % this.builderPool.length];\n builder.reset();\n let program: BytecodeProgram;\n let parserAlloc: StageAllocation | null = null;\n try {\n // build() allocates TypedArrays directly from builder arrays\n // a single copy (builder → TypedArray). Wrapped together with\n // parseExpression() under one 'parser' allocation measurement,\n // matching the exact span this file's diagnostic path has always\n // measured (see this method's own doc comment on `parserAlloc`).\n const parseResult = AllocationTracker.track('parser', () => {\n this.parseExpression(builder, normalizedTokens, hasParens);\n return builder.build();\n });\n program = parseResult.result;\n parserAlloc = parseResult.alloc;\n } catch (e) {\n // reads/writes were already extracted above from the full token\n // list (independent of whether parsing succeeds), returned\n // alongside the error (not merged into its context here, since\n // EngineError.context is readonly) so callers that track\n // dependencies (ThreeTierEvaluator's compile-fallback DAG\n // registration, via compileExpression()'s merge below) still\n // learn what this line references and can re-evaluate it once\n // those variables become defined.\n return { kind: 'error', stage: 'parse', error: normalizeUnknownError(e), reads, writes, normalizedTokens };\n }\n\n this.cacheBytecode(expression, program);\n return { kind: 'ready', normalizedTokens, reads, writes, program, cached: false, parserAlloc };\n }\n\n /**\n * Shared async-resolver preflight check, run before VM execution.\n *\n * O(1) guard: skips the O(n) resolver scan when the bytecode has no\n * async opcodes AND no resolvers are registered. Either condition alone\n * is enough to warrant a preflight scan:\n * - program.hasAsync: bytecode contains CALL_PLUGIN (async VM path)\n * - resolverRegistry.size > 0: resolvers may intercept any expression\n * For purely sync expressions (e.g., `2 + 2`) with no resolvers, this is\n * an O(1) fast-path that bypasses the resolver scan entirely.\n *\n * If any registered resolver says \"data not ready\", registers a DAG\n * data-source dependency, stores a Pending result, and fires async\n * resolution (fire-and-forget, resolves later, re-evaluates on\n * completion), the caller should skip VM execution entirely and return\n * the pending Value as-is. Otherwise the caller should proceed to\n * {@link executeAndStore}.\n *\n * Used by both {@link evaluateWithTokens} and\n * {@link evaluateExpressionWithDiagnostic}, previously each carried its\n * own copy of this exact sequence (differing only in a cosmetic\n * abortLogger label), which is how the `=>` grammar shipped silently\n * dead on the diagnostic path earlier this session: a future top-level\n * grammar addition can no longer be wired into only one of the two.\n */\n private preflightAsync(\n normalizedTokens: Token[],\n program: BytecodeProgram,\n lineNumber: number,\n expression: string,\n reads: string[],\n writes: string[],\n ): { kind: 'pending'; value: Value } | { kind: 'proceed' } {\n if (!(program.hasAsync || this.resolverRegistry.size > 0)) {\n return { kind: 'proceed' };\n }\n\n // Check all registered async resolvers BEFORE VM execution.\n // If any resolver says \"data not ready\", skip VM and return Pending.\n // Link the preflight AbortController to the keystroke signal so\n // that in-flight preflight checks are canceled on new keystrokes.\n const preflightController = new AbortController();\n const abortPreflight = () => preflightController.abort();\n this.keystrokeSignal?.addEventListener('abort', abortPreflight, { once: true });\n\n abortLogger.localControllerCreated(\"preflightAsync\");\n if (this.keystrokeSignal) {\n abortLogger.signalLinked(\"preflightAsync\");\n }\n\n const preflightSignal = preflightController.signal;\n const asyncCheck = this.resolverRegistry.preflightAll(\n normalizedTokens, program, '_engine', preflightSignal, this.queryClient\n );\n if (asyncCheck) {\n // Fire-and-forget, resolves asynchronously, re-evaluates on completion\n void this.resolveAsync({\n type: 'pending',\n queryKey: asyncCheck.queryKey,\n resolver: asyncCheck.resolver,\n packageId: asyncCheck.packageId || '_engine',\n signal: asyncCheck.signal,\n });\n\n // Register data source dependency for DAG re-evaluation tracking\n this.dag.registerLineDataSourceDependency(\n lineNumber,\n asyncCheck.packageId || '_engine',\n [asyncCheck.queryKey]\n );\n\n this.registerBackgroundRefresh(asyncCheck);\n\n const pending = pendingValue(asyncCheck.queryKey);\n this.storeLineResult(lineNumber, pending, program, reads, writes, expression);\n return { kind: 'pending', value: pending };\n }\n // Sync path, no async resolution started, so the preflight\n // controller is inert. Unhook its keystroke listener.\n this.keystrokeSignal?.removeEventListener('abort', abortPreflight);\n return { kind: 'proceed' };\n }\n\n /**\n * Evaluate an expression using already-lexed tokens.\n *\n * The lean, non-diagnostic-instrumented path, used by\n * {@link evaluateLineWithPreTokenized} (tokens from `scanDocument()`)\n * and, via {@link compileExpression}/{@link tryCompileExpression},\n * compile-only callers. NOT used by `evaluateLine()`/\n * `evaluateExpression()`, those route through\n * {@link evaluateExpressionWithDiagnostic} instead (evaluateLine ->\n * evaluateLineWithDebug -> evaluateExpressionWithDiagnostic), which does\n * its own lexing and its\n * own diagnostic-instrumented front-half, delegating to the SAME\n * {@link prepareExpression} this method calls. Delegates the front-half\n * to {@link prepareExpression}, then runs async preflight (via\n * {@link preflightAsync}) + VM execution (via {@link executeAndStore}).\n */\n private evaluateWithTokens(\n lineNumber: number,\n expression: string,\n tokens: Token[],\n hasParens?: boolean\n ): Value {\n const prep = this.prepareExpression(expression, tokens, hasParens, undefined, lineNumber);\n\n if (prep.kind === 'empty') {\n const v = numberValue(0);\n this.lineCache.set(lineNumber, new LineCacheEntry(v, { opcodes: new Uint8Array(0), numbers: new Float64Array(0), strings: [], hasAsync: false }, [], null), expression);\n return v;\n }\n if (prep.kind === 'error') {\n // Re-throw the original error as-is, its own code/category\n // (EXPRESSION_TOO_LONG/EXPRESSION_TOO_COMPLEX/whatever the\n // parser actually threw) and expected/found/suggestion detail\n // are more specific and useful than the generic EVALUATION_ERROR\n // wrapper this used to construct around just the message.\n throw prep.error;\n }\n if (prep.kind === 'symbolic-solve') {\n // Most symbolic shapes carry no DAG registration: a stored\n // equation/bare-assignment's effect (vm.equations, vm.setVar) isn't\n // reads/writes-trackable the same way ordinary bytecode is, so the\n // line won't auto-re-evaluate if some unrelated line later changes\n // one of its factor variables. A disclosed limitation of that\n // narrow grammar (see trySymbolicGrammar()'s own doc comment). The\n // exception is a compound assignment, which surfaces real\n // reads/writes (see prepareExpression) so its running total is\n // checkpointed and its dependents re-evaluate.\n this.storeLineResult(lineNumber, prep.value, { opcodes: new Uint8Array(0), numbers: new Float64Array(0), strings: [], hasAsync: false }, prep.reads ?? [], prep.writes ?? [], expression);\n return prep.value;\n }\n\n const { normalizedTokens, reads, writes, program } = prep;\n\n // ══ PRE-FLIGHT ASYNC CHECK ══\n const preflight = this.preflightAsync(normalizedTokens, program, lineNumber, expression, reads, writes);\n if (preflight.kind === 'pending') {\n return preflight.value;\n }\n\n // Execute and handle result, no try/catch needed.\n // executeBytecode now returns EvalResult (discriminated union).\n return this.executeAndStore(program, lineNumber, expression, reads, writes, '_engine');\n }\n\n //#endregion\n\n //#region Public API, Line-level evaluation\n\n\t/**\n\t * Evaluate a single expression line with full DAG and LineCache integration.\n\t *\n\t * @param lineNumber - 1-based line position in the document.\n\t * @param lineText - The raw line text.\n\t * @returns The evaluated {@link Value}.\n\t * @throws {EngineError} On evaluation failure.\n\t */\n\tevaluateLine(\n lineNumber: number,\n lineText: string\n ): Value {\n const result = this.evaluateLineWithDebug(lineNumber, lineText);\n if (result.error) {\n // Re-throw the original error (its own specific code/category/\n // expected/found/suggestion, e.g. CLAMP_EXPECTED_BETWEEN_OR_FROM\n // or UNDEFINED_VARIABLE) rather than the generic EVALUATION_ERROR\n // wrapper this used to always construct around just the message\n //, engineError is only absent if some future failure path in\n // the diagnostic pipeline sets `error` without it, which the\n // fallback below still handles.\n if (result.engineError) {\n throw result.engineError;\n }\n throw ErrorFactory.execution(\n 'EVALUATION_ERROR',\n result.error,\n { lineNumber }\n );\n }\n return freezeIfDev(result.value);\n }\n\n /**\n * Evaluate a line with diagnostic information, supporting both regular expressions and inline solves.\n *\n * This is the primary entry point for the playground's debug/DIagnostic mode.\n * It delegates to {@link evaluateExpressionWithDiagnostic} for all actual evaluation,\n * but first checks for inline solve syntax (`s`expression``) and wraps the result\n * with inline solve position metadata when found.\n *\n * @param lineNumber - 1-based line number in the document.\n * @param lineText - Raw line text, which may be a regular expression or an inline solve.\n * @param inputType - Optional input type hint passed through to the diagnostic pipeline.\n * @returns An object containing the evaluated `value`, the raw `tokens`, the compiled\n * `program`, optional `error` message, optional `debug` report JSON, and optional\n * structured `diagnostic` pipeline result with all 15 pipeline stages.\n */\n evaluateLineWithDebug(\n lineNumber: number,\n lineText: string,\n inputType: string = \"expression\"\n ): { value: Value; tokens: Token[]; program: BytecodeProgram; error?: string; engineError?: EngineError; inlineSolve?: InlineSolvePosition; debug?: DiagnosticReportJSON; diagnostic?: DiagnosticPipelineResult } {\n const inlineSolveMatch = lineText.match(/^s`([^`]*)`$/);\n if (inlineSolveMatch) {\n const expression = inlineSolveMatch[1];\n const result = this.evaluateExpressionWithDiagnostic(expression, lineNumber, inputType);\n return {\n ...result,\n inlineSolve: {\n start: 0,\n end: lineText.length,\n expression,\n lineNumber,\n columnNumber: 1\n }\n };\n }\n return this.evaluateExpressionWithDiagnostic(lineText, lineNumber, inputType);\n }\n\n //#endregion\n\n //#region Diagnostic Pipeline, Structured stage recording\n\n /**\n * Build a single pipeline stage result for the structured diagnostic output.\n *\n * Appends a `PipelineStageResult` to the given `stages` array with the provided\n * metadata. This runs in parallel with the existing event-based diagnostic system\n * (via `DiagnosticPipeline.fire*` methods). Both paths are enabled by the same\n * `hasCollectors` guard so there is no performance impact when `diagnosticMode`\n * is `false`, the stages array stays empty because this method is never called.\n *\n * Each stage captures:\n * - **Identity**: `stage` name (e.g., `\"lexer\"`), display `label`, `icon`, `colorClass`\n * - **Position**: `stepNumber` in the pipeline (0-15)\n * - **Timing**: `elapsedNs` wall-time (overridden by TimelineDiagnosticCollector)\n * - **State**: `skipped` flag for stages bypassed by cache hits or guard conditions\n * - **Payload**: `output`, a discriminated union typed per stage\n *\n * @param stages - Mutable array being accumulated for the final DiagnosticPipelineResult.\n * @param stage - Canonical stage identifier (kebab-case, e.g. `\"async_preflight\"`).\n * @param label - Human-readable stage name for the dashboard.\n * @param icon - Single emoji/character icon for visual identification.\n * @param colorClass - CSS class name for color-coding the stage in the UI.\n * @param stepNumber - Ordinal position in the 15-stage pipeline.\n * @param elapsedNs - Wall-clock time in nanoseconds (0 placeholder; timeline overrides).\n * @param skipped - Whether this stage was bypassed (e.g., cache hit, guard short-circuit).\n * @param output - Stage-specific data payload typed via the StageOutput discriminated union.\n */\n private addDiagnosticStage(\n stages: PipelineStageResult[],\n stage: string,\n label: string,\n icon: string,\n colorClass: string,\n stepNumber: number,\n elapsedNs: number,\n skipped: boolean,\n output: StageOutput,\n ): void {\n stages.push({ stage, label, icon, colorClass, stepNumber, elapsedNs, skipped, output });\n }\n\n /**\n * Core expression evaluation logic with diagnostic pipeline integration.\n *\n * Executes the full 15-stage evaluation pipeline while simultaneously\n * populating two diagnostic data structures:\n *\n * 1. **Event-based**, fires typed events to registered `DiagnosticCollector`\n * instances via `DiagnosticPipeline.fire*()` methods. Supports streaming\n * diagnostics via `TimelineDiagnosticCollector`.\n * 2. **Structured stages**, accumulates a `PipelineStageResult[]` array\n * with per-stage typed payloads (see `DiagnosticPipelineResult.ts`).\n * This is returned as the `diagnostic` field for declarative rendering.\n *\n * The 15 stages, in order:\n * ```\n * 1 pipeline_start, Pipeline initialization + metadata\n * 2 safety_length, Expression length validation\n * 3 lexer, Tokenization via ExpressionLexer\n * 4 normalizer, Token fusion (phrase, implicit multiply)\n * 5 safety_complexity, Token-count & nesting-depth check\n * 6 readwrite, Variable read/write extraction for DAG\n * 7 cache_check, Bytecode cache hit/miss\n * 8 parser, AST construction via PrecedenceParser\n * 9 compiler, Bytecode generation + constant table\n * 10 async_preflight, Async resolver pre-flight check\n * 11 vm_execute, Bytecode execution on the VM\n * 12 dag_registration, DAG node registration for incremental eval\n * 13 linecache, Result stored in LineCache\n * 14 result, Final value + formatting\n * 15 pipeline_end, Completion summary + statistics\n * ```\n *\n * Early-exit paths are taken for safety violations, empty expressions,\n * parse failures, and async pending results. Each early exit still\n * fires relevant pipeline events and records partial stages.\n *\n * When `AllocationTracker.isEnabled()`, each pipeline stage is wrapped\n * with `AllocationTracker.track()` to capture wall-time and heap delta.\n * When disabled (production), `track()` is a zero-overhead passthrough\n * that returns the result directly.\n *\n * The stages above describe OBSERVABLE shape, not a second implementation\n * of the underlying work: normalize/complexity-check/symbolic-grammar/\n * readwrite/cache-lookup/parse/compile are delegated to\n * {@link prepareExpression} (the SAME method the lean\n * {@link evaluateWithTokens} path calls), async preflight to\n * {@link preflightAsync}, and VM execution to {@link executeAndStore}\n * every stage/event below is reconstructed from what those shared\n * methods return, not fired from inside a second hand-duplicated copy\n * of their logic. This matters: a new top-level grammar shape wired\n * into `prepareExpression()` is automatically reachable from BOTH\n * `evaluateLine()`/`evaluateExpression()` (this method) and the lean\n * path, previously they were two independent implementations that had\n * already drifted once (the `=>`/equation-statement grammar shipped\n * dead on this, the real path, until a dedicated test caught it).\n *\n * @param expression - The raw expression string to evaluate.\n * @param lineNumber - 1-based line number for DAG and LineCache entries.\n * @param inputType - Input type hint (default `\"expression\"`), passed to\n * the diagnostic pipeline for metadata.\n * @returns An object with `value`, `tokens`, `program`, optional `error`,\n * optional `debug` report JSON, and optional `diagnostic` containing\n * the full structured pipeline stages array when collectors are active.\n */\n private evaluateExpressionWithDiagnostic(expression: string, lineNumber: number, inputType: string = \"expression\"): { value: Value; tokens: Token[]; program: BytecodeProgram; error?: string; engineError?: EngineError; debug?: DiagnosticReportJSON; diagnostic?: DiagnosticPipelineResult } {\n const pipeline = this.diagnosticPipeline;\n const hasCollectors = pipeline.hasCollectors;\n // Baseline for slicing THIS line's own parselet_matched events out of\n // the timeline collector's cumulative-across-the-document array below\n //. See debug.parselets' construction at the end of this method.\n const parseletsBefore = this.timelineCollector?.parseletMatchCount ?? 0;\n const trackEnabled = AllocationTracker.isEnabled();\n const stageAllocs: StageAllocation[] = [];\n const stages: PipelineStageResult[] = [];\n const zeroElapsed = 0; // Placeholder — timeline collector overrides with real ns\n\n // === SAFETY CHECK 1: Expression length limit ===\n const lengthCheck = checkExpressionLength(expression, this.config.validation);\n if (!lengthCheck.passed) {\n if (hasCollectors) {\n this.addDiagnosticStage(stages, 'safety_length', 'Safety: Length', '🛡️', 'validate', 2, zeroElapsed, false, {\n type: 'safety_length',\n passed: false,\n expressionLength: expression.length,\n maxLength: this.config.validation.maxExpressionLength,\n errorMessage: lengthCheck.error!.error,\n });\n }\n return { ...lengthCheck.error!, debug: undefined, diagnostic: undefined };\n }\n\n // Pipeline event: start + structured stage\n if (hasCollectors) {\n pipeline.firePipelineStart({\n type: DiagnosticEventType.PipelineStart,\n elapsedNs: 0,\n expression,\n inputType,\n });\n this.addDiagnosticStage(stages, 'pipeline_start', 'Pipeline Start', '▶', 'pipeline', 1, zeroElapsed, false, {\n type: 'pipeline_start', expression, inputType,\n });\n this.addDiagnosticStage(stages, 'safety_length', 'Safety: Length', '🛡️', 'validate', 2, zeroElapsed, false, {\n type: 'safety_length',\n passed: true,\n expressionLength: expression.length,\n maxLength: this.config.validation.maxExpressionLength,\n });\n }\n\n // ══ LEXER STAGE ══\n // Lexing with token emission events. This file's shared\n // lexToTokens() (also used by compileExpression/\n // tryCompileExpression) skips redundant classifyLine (caller\n // already knows this is an expression) and filters COMMENT tokens\n // (they have no parselet and would cause \"No prefix parselet\n // found\" errors at the parser); `onToken` fires the per-token\n // TokenEmitted diagnostic event, genuinely specific to this path.\n const onToken = hasCollectors ? (t: Token) => {\n pipeline.fireTokenEmitted({\n type: DiagnosticEventType.TokenEmitted,\n elapsedNs: 0, // zero-cost placeholder (timeline collector overrides)\n expression,\n token: {\n type: t.type,\n value: t.value,\n offset: t.offset || 0,\n line: t.line || lineNumber,\n col: t.col || 0,\n },\n });\n } : undefined;\n const lexResult = AllocationTracker.track('lexer', () => this.lexToTokens(expression, onToken));\n const tokens = lexResult.result.tokens;\n const hasParens = lexResult.result.hasParens;\n if (trackEnabled && lexResult.alloc) stageAllocs.push(lexResult.alloc);\n\n // Structured: lexer stage output\n if (hasCollectors) {\n const tokenTypes: Record<string, number> = {};\n for (const t of tokens) {\n tokenTypes[t.type] = (tokenTypes[t.type] || 0) + 1;\n }\n this.addDiagnosticStage(stages, 'lexer', 'Lexer', '🔤', 'lexer', 3, zeroElapsed, false, {\n type: 'lexer',\n tokenCount: tokens.length,\n tokenTypes,\n hasParens,\n locale: this.localeCode,\n tokens: [...tokens],\n });\n\n // Structured: line classification, detect inline solve spans from token stream\n const inlineSolveSpans: InlineSolveSpanInfo[] = [];\n for (let i = 0; i < tokens.length; i++) {\n const t = tokens[i];\n if (t.type === 'INLINE_SOLVE_START') {\n // Find closing backtick\n let endIdx = -1;\n for (let j = i + 1; j < tokens.length; j++) {\n if (tokens[j].type === 'BACKTICK_OPEN') {\n endIdx = j;\n break;\n }\n }\n if (endIdx > i) {\n const exprTokens = tokens.slice(i + 1, endIdx);\n const expression = exprTokens.map(et => et.value).join('');\n inlineSolveSpans.push({\n startTokenIndex: i,\n endTokenIndex: endIdx,\n expression,\n columnNumber: t.col || 1,\n });\n i = endIdx; // skip past this span\n }\n }\n }\n this.addDiagnosticStage(stages, 'line_classification', 'Line Classification', '📋', 'classify', 3.5, zeroElapsed, false, {\n type: 'line_classification',\n classification: 'expression',\n skip: false,\n hasInlineSolve: inlineSolveSpans.length > 0,\n inlineSolveSpans,\n });\n }\n\n if (tokens.length === 0) {\n const v = numberValue(0);\n this.lineCache.set(lineNumber, new LineCacheEntry(v, { opcodes: new Uint8Array(0), numbers: new Float64Array(0), strings: [], hasAsync: false }, [], null), expression);\n\n if (hasCollectors) {\n pipeline.firePipelineEnd({\n type: DiagnosticEventType.PipelineEnd,\n elapsedNs: 0,\n expression,\n success: true,\n totalTokens: 0,\n totalOpcodes: 0,\n });\n }\n\n return { value: v, tokens, program: { opcodes: new Uint8Array(0), numbers: new Float64Array(0), strings: [], hasAsync: false }, debug: undefined, diagnostic: undefined };\n }\n\n // ══ FRONT-HALF DELEGATION ══\n // normalize -> complexity -> symbolic-grammar -> readwrite -> cache\n // lookup/parse/compile, all via the SAME prepareExpression() the\n // lean path (evaluateWithTokens/compileExpression/\n // tryCompileExpression) already calls. This is the actual fix for\n // the bug found earlier this session (a new top-level grammar\n // shape silently dead on THIS, the real evaluateLine()/\n // evaluateExpression() path): a future addition wired into\n // prepareExpression() now automatically covers both paths, since\n // there is only one implementation left of \"what does this line\n // mean.\" Every stage below is reconstructed from\n // prepareExpression()'s return value, plus a couple of cheap\n // pure, side-effect-free recomputations for display-only fields it\n // doesn't itself carry (the complexity score), instead of being\n // fired from inside a second, hand-duplicated copy of its logic.\n let fusionCount = 0;\n const normalizerFusions: TokenFusion[] = [];\n const normalizerRuleCounts = new Map<string, number>();\n const onFusion = hasCollectors ? (fusion: TokenFusion) => {\n fusionCount++;\n normalizerFusions.push(fusion);\n normalizerRuleCounts.set(fusion.rule, (normalizerRuleCounts.get(fusion.rule) || 0) + 1);\n pipeline.fireTokenFused({\n type: DiagnosticEventType.TokenFused,\n elapsedNs: 0,\n expression,\n ruleName: fusion.rule,\n sourceTokenCount: fusion.sourceTokens.length,\n fusedTokenType: fusion.fusedToken.type,\n fusedTokenValue: fusion.fusedToken.value,\n });\n } : undefined;\n\n if (hasCollectors && this.normalizer.ruleCount > 0) {\n pipeline.fireNormalizerStart({\n type: DiagnosticEventType.NormalizerStart,\n elapsedNs: 0,\n expression,\n inputTokenCount: tokens.length,\n });\n }\n\n // Peeked BEFORE calling prepareExpression() so hit/miss is already\n // known for the stage/event construction below, and so the\n // parser's diagnostic-pipeline reference is only linked when a real\n // parse attempt is actually about to happen, a cache hit never\n // reaches parseExpression() at all, matching the original's own\n // cache-miss-only gating of this same call.\n const cachedBefore = this.bytecodeCache.get(expression);\n if (hasCollectors && !cachedBefore) {\n this.parser.setDiagnosticPipeline(pipeline, expression);\n }\n\n // NOT wrapped in AllocationTracker.track('parser', ...) here\n // prepareExpression() already measures its OWN internal parse+build\n // call under that exact label internally (see its own doc comment\n // on `parserAlloc`) and reports the result back on its 'ready'\n // variant below. Wrapping the whole call from out here would widen\n // the measured span to also cover normalize/complexity-check/cache-\n // lookup, which measurably produced negative-allocation readings (a\n // GC sweep landing inside the wider window) well over half the time.\n const prep = this.prepareExpression(expression, tokens, hasParens, onFusion, lineNumber);\n if (trackEnabled && prep.kind === 'ready' && prep.parserAlloc) {\n stageAllocs.push(prep.parserAlloc);\n }\n\n if (hasCollectors && !cachedBefore) {\n this.parser.setDiagnosticPipeline(undefined, \"\");\n }\n\n // From here on, `prep.normalizedTokens` is always defined, the two\n // variants that lack it ('empty', and 'error' at the 'length'\n // stage) are provably unreachable from this call site: the\n // safety-length check and the raw-tokens-empty check above already\n // handled both cases before prepareExpression() was ever invoked.\n const normalizedTokens: Token[] = prep.kind === 'empty' ? tokens : (prep.normalizedTokens ?? tokens);\n\n if (hasCollectors) {\n if (this.normalizer.ruleCount > 0) {\n pipeline.fireNormalizerEnd({\n type: DiagnosticEventType.NormalizerEnd,\n elapsedNs: 0,\n expression,\n outputTokenCount: normalizedTokens.length,\n fusionsCount: fusionCount,\n });\n this.addDiagnosticStage(stages, 'normalizer', 'Normalizer', '🔄', 'normalizer', 4, zeroElapsed, false, {\n type: 'normalizer',\n inputTokenCount: tokens.length,\n outputTokenCount: normalizedTokens.length,\n fusions: normalizerFusions,\n rulesApplied: [...normalizerRuleCounts.entries()].map(([rule, count]) => ({ rule, count })),\n tokens: [...normalizedTokens],\n phrases: this.normalizer.getPhrases(),\n });\n } else {\n this.addDiagnosticStage(stages, 'normalizer', 'Normalizer', '🔄', 'normalizer', 4, zeroElapsed, true, {\n type: 'normalizer',\n inputTokenCount: tokens.length,\n outputTokenCount: tokens.length,\n fusions: [],\n rulesApplied: [],\n tokens: [...tokens],\n phrases: this.normalizer.getPhrases(),\n });\n }\n }\n\n // ══ 'empty' / 'error'-at-'length' outcomes ══\n // Provably unreachable from this call site (see comment above)\n // handled only so the discriminated union stays exhaustively\n // covered.\n if (prep.kind === 'empty' || (prep.kind === 'error' && prep.stage === 'length')) {\n if (hasCollectors) {\n pipeline.firePipelineEnd({\n type: DiagnosticEventType.PipelineEnd,\n elapsedNs: 0,\n expression,\n success: prep.kind === 'empty',\n totalTokens: tokens.length,\n totalOpcodes: 0,\n });\n }\n if (prep.kind === 'empty') {\n const v = numberValue(0);\n this.lineCache.set(lineNumber, new LineCacheEntry(v, { opcodes: new Uint8Array(0), numbers: new Float64Array(0), strings: [], hasAsync: false }, [], null), expression);\n return { value: v, tokens, program: { opcodes: new Uint8Array(0), numbers: new Float64Array(0), strings: [], hasAsync: false }, debug: undefined, diagnostic: undefined };\n }\n return {\n value: numberValue(0),\n tokens: [],\n program: { opcodes: new Uint8Array(0), numbers: new Float64Array(0), strings: [], hasAsync: false },\n error: prep.error.message,\n engineError: prep.error,\n debug: undefined,\n diagnostic: undefined,\n };\n }\n\n // Recompute the complexity score for display, cheap, pure\n // side-effect-free; prepareExpression() already made the actual\n // pass/fail DECISION, this is purely for the diagnostic stage's own\n // display fields it doesn't itself return.\n const complexityCheck = checkExpressionComplexity(normalizedTokens, this.config.validation);\n\n if (prep.kind === 'error' && prep.stage === 'complexity') {\n if (hasCollectors) {\n this.addDiagnosticStage(stages, 'safety_complexity', 'Safety: Complexity', '🛡️', 'validate', 5, zeroElapsed, false, {\n type: 'safety_complexity',\n passed: false,\n complexityScore: complexityCheck.complexityScore ?? 0,\n maxComplexity: this.config.validation.maxComplexity,\n breakdown: {\n tokenCount: normalizedTokens.length,\n functionCalls: 0,\n nestingDepth: 0,\n },\n errorMessage: complexityCheck.errorMessage!,\n });\n pipeline.firePipelineEnd({\n type: DiagnosticEventType.PipelineEnd,\n elapsedNs: 0,\n expression,\n success: false,\n totalTokens: tokens.length,\n totalOpcodes: 0,\n });\n }\n return {\n value: numberValue(0),\n tokens: [],\n program: { opcodes: new Uint8Array(0), numbers: new Float64Array(0), strings: [], hasAsync: false },\n error: complexityCheck.errorMessage!,\n engineError: complexityCheck.engineError,\n debug: undefined,\n diagnostic: undefined,\n };\n }\n\n if (hasCollectors) {\n this.addDiagnosticStage(stages, 'safety_complexity', 'Safety: Complexity', '🛡️', 'validate', 5, zeroElapsed, false, {\n type: 'safety_complexity',\n passed: true,\n complexityScore: complexityCheck.complexityScore ?? normalizedTokens.length,\n maxComplexity: this.config.validation.maxComplexity,\n breakdown: {\n tokenCount: normalizedTokens.length,\n functionCalls: 0,\n nestingDepth: 0,\n },\n });\n }\n\n if (prep.kind === 'symbolic-solve') {\n if (hasCollectors) {\n pipeline.firePipelineEnd({\n type: DiagnosticEventType.PipelineEnd,\n elapsedNs: 0,\n expression,\n success: true,\n totalTokens: tokens.length,\n totalOpcodes: 0,\n });\n }\n const emptyProgram: BytecodeProgram = { opcodes: new Uint8Array(0), numbers: new Float64Array(0), strings: [], hasAsync: false };\n this.storeLineResult(lineNumber, prep.value, emptyProgram, prep.reads ?? [], prep.writes ?? [], expression);\n return {\n value: prep.value,\n tokens: normalizedTokens,\n program: emptyProgram,\n debug: undefined,\n diagnostic: undefined,\n };\n }\n\n // From here, prep.kind is 'ready' or 'error' at the 'parse' stage\n // both carry `reads`/`writes` (extracted before the cache lookup/\n // parse attempt).\n const reads = prep.reads ?? [];\n const writes = prep.writes ?? [];\n\n if (hasCollectors) {\n this.addDiagnosticStage(stages, 'readwrite', 'Read/Write', '📋', 'readwrite', 6, zeroElapsed, false, {\n type: 'readwrite',\n reads,\n writes,\n isAssignment: writes.length > 0,\n });\n this.addDiagnosticStage(stages, 'cache_check', 'Cache Check', '💾', 'cache', 7, zeroElapsed, false, {\n type: 'cache_check',\n hit: !!cachedBefore,\n cacheSize: this.bytecodeCache.size,\n cacheKey: expression,\n });\n if (cachedBefore) {\n pipeline.fireCacheHit({ type: DiagnosticEventType.CacheHit, elapsedNs: 0, expression, cache: \"bytecode\", key: expression });\n } else {\n pipeline.fireCacheMiss({ type: DiagnosticEventType.CacheMiss, elapsedNs: 0, expression, cache: \"bytecode\", key: expression });\n }\n }\n\n if (prep.kind === 'error' && prep.stage === 'parse') {\n // No 'parser'/'compiler' stage, the parse attempt itself is\n // where this failed, matching the original's exact shape (it\n // only ever got as far as the cache_check stage above before\n // the parse threw).\n if (hasCollectors) {\n pipeline.firePipelineEnd({\n type: DiagnosticEventType.PipelineEnd,\n elapsedNs: 0,\n expression,\n success: false,\n totalTokens: tokens.length,\n totalOpcodes: 0,\n });\n }\n return {\n value: numberValue(0),\n tokens: normalizedTokens,\n program: { opcodes: new Uint8Array(0), numbers: new Float64Array(0), strings: [], hasAsync: false },\n error: prep.error.message,\n engineError: prep.error,\n debug: undefined,\n diagnostic: undefined,\n };\n }\n\n if (prep.kind !== 'ready') {\n // Unreachable: every other variant ('empty', 'error' at any\n // stage, 'symbolic-solve') was already returned above. Kept\n // only so TypeScript's discriminated-union narrowing (which\n // doesn't always simplify a chain of `kind === X || (kind ===\n // Y && stage === Z)` guards perfectly) treats `prep.program`\n // below as definitely accessible, without an `as` cast.\n throw ErrorFactory.internal({\n code: \"UNEXPECTED_ERROR\",\n message: \"Internal error: prepareExpression() returned an unexpected variant after all other cases were handled\",\n });\n }\n const program = prep.program;\n\n if (hasCollectors) {\n this.addDiagnosticStage(stages, 'parser', 'Parser', '🌳', 'parser', 8, zeroElapsed, !!cachedBefore, {\n type: 'parser',\n parselets: [],\n uniqueParseletTypes: [],\n astDepth: 0,\n });\n this.addDiagnosticStage(stages, 'compiler', 'Compiler', '⚙️', 'compiler', 9, zeroElapsed, !!cachedBefore, {\n type: 'compiler',\n opcodeCount: program.opcodes.length,\n numberConstants: program.numbers.length,\n stringConstants: program.strings.length,\n hasAsync: program.hasAsync,\n cached: !!cachedBefore,\n });\n pipeline.fireBytecodeBuilt({\n type: DiagnosticEventType.BytecodeBuilt,\n elapsedNs: 0,\n expression,\n opcodesLength: program.opcodes.length,\n numbersLength: program.numbers.length,\n stringsLength: program.strings.length,\n isCached: !!cachedBefore,\n });\n }\n\n // ══ PRE-FLIGHT ASYNC CHECK ══\n const hasAsyncGuard = program.hasAsync || this.resolverRegistry.size > 0;\n const preflight = this.preflightAsync(normalizedTokens, program, lineNumber, expression, reads, writes);\n\n if (hasCollectors) {\n if (preflight.kind === 'pending') {\n this.addDiagnosticStage(stages, 'async_preflight', 'Async Preflight', '🔮', 'async', 10, zeroElapsed, false, {\n type: 'async_preflight',\n path: 'pending',\n pendingQueryKey: preflight.value.value as string,\n resolverCount: this.resolverRegistry.size,\n skippedGuard: true,\n });\n } else if (hasAsyncGuard) {\n this.addDiagnosticStage(stages, 'async_preflight', 'Async Preflight', '🔮', 'async', 10, zeroElapsed, false, {\n type: 'async_preflight',\n path: 'sync',\n resolverCount: this.resolverRegistry.size,\n skippedGuard: false,\n });\n } else {\n this.addDiagnosticStage(stages, 'async_preflight', 'Async Preflight', '🔮', 'async', 10, zeroElapsed, true, {\n type: 'async_preflight',\n path: 'sync',\n resolverCount: 0,\n skippedGuard: true,\n });\n }\n }\n\n if (preflight.kind === 'pending') {\n if (hasCollectors) {\n pipeline.firePipelineEnd({\n type: DiagnosticEventType.PipelineEnd,\n elapsedNs: 0,\n expression,\n success: true,\n totalTokens: tokens.length,\n totalOpcodes: program.opcodes.length,\n });\n }\n return {\n value: preflight.value,\n tokens: normalizedTokens,\n program,\n debug: undefined,\n diagnostic: hasCollectors ? this.buildDiagnosticResult(stages, preflight.value, normalizedTokens, program, null) : undefined,\n };\n }\n\n // ══ VM STAGE ══\n // Delegates to executeAndStore(), the SAME method the lean path\n // calls, which already handles the AbortController/keystroke-\n // signal linking, stack cleanup, and resolveAsync/DAG-registration/\n // storeLineResult side effects internally. executeAndStore()\n // throws on a VM runtime error (matching the lean path's own\n // contract); caught here and converted to a soft `error` return,\n // exactly as this method's own inline VM-execution block used to\n // do directly, so a caller evaluating a whole multi-line document\n // one line at a time still doesn't have one bad line abort every\n // subsequent line.\n const emitVmTrace = hasCollectors && this.config.diagnostic.vmTraceEnabled === true;\n let result: Value;\n try {\n const vmResult = AllocationTracker.track('vm', () => {\n return this.executeAndStore(program, lineNumber, expression, reads, writes, '_engine', emitVmTrace ? pipeline : undefined, expression);\n }, { cacheHit: !!cachedBefore });\n result = vmResult.result;\n if (trackEnabled && vmResult.alloc) stageAllocs.push(vmResult.alloc);\n } catch (e) {\n const engineError = normalizeUnknownError(e);\n if (hasCollectors) {\n pipeline.firePipelineEnd({\n type: DiagnosticEventType.PipelineEnd,\n elapsedNs: 0,\n expression,\n success: false,\n totalTokens: tokens.length,\n totalOpcodes: program.opcodes.length,\n });\n }\n return {\n value: numberValue(0),\n tokens: normalizedTokens,\n program,\n error: engineError.message,\n engineError,\n debug: undefined,\n diagnostic: undefined,\n };\n }\n\n const isPending = result.type === ValueType.Pending;\n\n if (hasCollectors) {\n const resultValue = isPending ? 'pending' : String(result.value ?? '');\n const resultType = isPending ? 'Pending' : (result.unit ? 'Uom' : 'Number');\n this.addDiagnosticStage(stages, 'vm_execute', 'VM Execute', '⚡', 'vm', 11, zeroElapsed, false, {\n type: 'vm_execute',\n totalInstructions: program.opcodes.length,\n stackDepth: this.vm.getStack().length,\n resultType,\n resultValue,\n isPending,\n });\n }\n\n if (isPending) {\n if (hasCollectors) {\n pipeline.firePipelineEnd({\n type: DiagnosticEventType.PipelineEnd,\n elapsedNs: 0,\n expression,\n success: true,\n totalTokens: tokens.length,\n totalOpcodes: program.opcodes.length,\n });\n }\n return {\n value: result,\n tokens: normalizedTokens,\n program,\n debug: undefined,\n diagnostic: hasCollectors ? this.buildDiagnosticResult(stages, result, normalizedTokens, program, null) : undefined,\n };\n }\n\n // ══ BUILD TELEMETRY ══\n if (trackEnabled && stageAllocs.length > 0) {\n this.lastTelemetry = AllocationTracker.createTelemetry(\n expression,\n stageAllocs,\n !!cachedBefore\n );\n }\n\n // Structured: DAG Registration + LineCache + Result + PipelineEnd\n if (hasCollectors) {\n this.addDiagnosticStage(stages, 'dag_registration', 'DAG Registration', '🔗', 'dag', 12, zeroElapsed, false, {\n type: 'dag_registration',\n readsRegistered: reads,\n writesRegistered: writes,\n dataSourcesRegistered: [],\n });\n this.addDiagnosticStage(stages, 'linecache', 'Line Cache', '📦', 'cache', 13, zeroElapsed, false, {\n type: 'linecache',\n lineNumber,\n expression,\n stored: true,\n });\n this.addDiagnosticStage(stages, 'result', 'Result', '✓', 'result', 14, zeroElapsed, false, {\n type: 'result',\n rawValue: String(result.value),\n formattedValue: String(result.value),\n valueType: result.type === 0 ? 'Number' : 'Value',\n unit: result.unit,\n });\n\n pipeline.fireVmHalt({\n type: DiagnosticEventType.VmHalt,\n elapsedNs: 0,\n expression,\n result: result ? {\n type: result.type,\n value: result.value,\n unit: result.unit,\n } : undefined,\n });\n\n this.addDiagnosticStage(stages, 'pipeline_end', 'Pipeline End', '⏹', 'pipeline', 15, zeroElapsed, false, {\n type: 'pipeline_end',\n success: true,\n totalTokens: tokens.length,\n totalOpcodes: program.opcodes.length,\n cacheHit: !!cachedBefore,\n });\n\n pipeline.firePipelineEnd({\n type: DiagnosticEventType.PipelineEnd,\n elapsedNs: 0,\n expression,\n success: true,\n totalTokens: tokens.length,\n totalOpcodes: program.opcodes.length,\n });\n }\n\n // Build debug info, structured diagnostic report\n if (hasCollectors) {\n const reports = pipeline.collectReports();\n const rawDebug = reports[0]?.toJSON();\n // `rawDebug.parselets` as returned by TimelineDiagnosticCollector\n // is cumulative across the WHOLE document pass (deliberately\n // see onPipelineStart's doc comment), not scoped to this one\n // line. Without this slice, every line after the first reports\n // whichever parselet fired FIRST in the entire session\n // (typically NumberParselet, from the document's very first\n // token) as if it were this line's own, a real, confusing\n // display bug, not evidence that NumberParselet does all the\n // parsing work. Slicing from the pre-parse baseline gives just\n // the events this line's own parse actually fired.\n let debug = rawDebug;\n if (rawDebug) {\n const lineParselets = rawDebug.parselets.slice(parseletsBefore);\n // summary.totalParselets/parseCategories are recomputed from\n // the SAME per-line slice above, for the same reason\n // TimelineDiagnosticCollector's parseCategories Map is\n // cumulative across the whole document pass, so reusing it\n // as-is would report \"distinct categories seen all session\"\n // instead of \"categories this line's own parse used\" (e.g.\n // a document that touches arithmetic/datetime/finance\n // packages across many lines would show totalParselets: 3\n // on EVERY line once all three had been seen once,\n // regardless of what that specific line actually parsed).\n // summary.totalTokens/totalOpcodes/cacheHit/elapsedNs are\n // deliberately left as the collector's session-cumulative\n // values, none of them currently has a UI consumer to\n // validate a per-line reinterpretation against, and\n // equivalent, already-correct per-line values exist\n // elsewhere for tokens/opcodes/cache-hit (see LineResult's\n // own token/opcodeCount/wasCached fields in\n // packages/playground-bridge/src/engine.ts).\n const lineParseCategories: Record<string, number> = {};\n for (const p of lineParselets) {\n lineParseCategories[p.parseletCategory] = (lineParseCategories[p.parseletCategory] ?? 0) + 1;\n }\n debug = {\n ...rawDebug,\n parselets: lineParselets,\n summary: {\n ...rawDebug.summary,\n totalParselets: Object.keys(lineParseCategories).length,\n parseCategories: lineParseCategories,\n },\n };\n }\n return {\n value: result,\n tokens: normalizedTokens,\n program,\n debug,\n diagnostic: this.buildDiagnosticResult(stages, result, normalizedTokens, program, null),\n };\n }\n\n return {\n value: result,\n tokens: normalizedTokens,\n program,\n };\n }\n\n //#endregion\n\n //#region Diagnostic Result, Snapshot population\n\n /**\n * Build a complete DiagnosticPipelineResult with engine-wide snapshot data.\n *\n * Populates dagSnapshot, cacheSnapshot, batcherMetrics, and checkpoints\n * alongside the per-line pipeline stages, value, tokens, and program.\n * Previously the playground made separate engine method calls for each.\n */\n private buildDiagnosticResult(\n stages: PipelineStageResult[],\n value: Value,\n tokens: Token[],\n program: BytecodeProgram,\n error: string | null,\n ): DiagnosticPipelineResult {\n return {\n stages,\n value,\n tokens,\n program,\n error,\n dagSnapshot: this.dag.getSnapshot(),\n cacheSnapshot: this.getCacheSnapshot(),\n batcherMetrics: this.getBatcherMetrics(),\n checkpoints: this.getCheckpoints(),\n };\n }\n\n //#endregion\n\n //#region Incremental Evaluation, DAG-driven re-execution\n\n /**\n * Re-evaluate a cached line without reparsing.\n *\n * Used when a variable referenced by this line has changed. Skips\n * lexing, parsing, and compilation, performs only a pre-flight async\n * check and VM execution against the cached bytecode.\n *\n * Returns `undefined` if the line is not in cache.\n *\n * @param lineNumber - The line to re-evaluate.\n * @param expression - The original expression string (used for cache lookup).\n * @returns The updated `Value`, or `undefined` if uncached.\n */\n reEvaluateLine(lineNumber: number, expression: string): Value | undefined {\n const entry = this.lineCache.get(lineNumber, expression);\n if (!entry) return undefined;\n\n const program = this.bytecodeCache.get(expression);\n if (!program) return undefined;\n\n // ══ PRE-FLIGHT ASYNC CHECK ══\n // O(1) guard: skip the O(n) resolver scan when the bytecode has no\n // async opcodes AND no resolvers are registered.\n if (entry.bytecode.hasAsync || this.resolverRegistry.size > 0) {\n // Pre-flight async check, run before VM even for cached bytecode\n // ── Link to keystroke signal ──\n const preflightController = new AbortController();\n const abortPreflight = () => preflightController.abort();\n this.keystrokeSignal?.addEventListener('abort', abortPreflight, { once: true });\n\n abortLogger.localControllerCreated(\"reEvaluateLine preflight\");\n if (this.keystrokeSignal) {\n abortLogger.signalLinked(\"reEvaluateLine preflight\");\n }\n\n const preflightSignal = preflightController.signal;\n const asyncCheck = this.resolverRegistry.preflightAll(\n [], entry.bytecode, '_engine', preflightSignal, this.queryClient\n );\n if (asyncCheck) {\n void this.resolveAsync({\n type: 'pending',\n queryKey: asyncCheck.queryKey,\n resolver: asyncCheck.resolver,\n packageId: asyncCheck.packageId || '_engine',\n signal: asyncCheck.signal,\n });\n this.registerBackgroundRefresh(asyncCheck);\n return pendingValue(asyncCheck.queryKey);\n }\n // Sync path, unhook the inert preflight controller's keystroke listener.\n this.keystrokeSignal?.removeEventListener('abort', abortPreflight);\n } // end hasAsync guard\n\n // No vm.reset() here: reset() clears the variable table, which would\n // wipe variables defined by other lines that this line's bytecode may\n // read. executeRaw() already snapshots and restores the stack depth.\n const evalResult = this.executeRaw(program, lineNumber);\n\n if (evalResult.type === 'pending') {\n void this.resolveAsync(evalResult);\n return pendingValue(evalResult.queryKey);\n }\n if (evalResult.type === 'error') {\n throw evalResult.error;\n }\n\n const result = evalResult.value;\n entry.result = result;\n\n return result;\n }\n\n getDag(): DependencyGraph {\n return this.dag;\n }\n\n getLineCache(): LineCache {\n return this.lineCache;\n }\n\n getBytecodeCache(): Map<string, BytecodeProgram> {\n return this.bytecodeCache;\n }\n\n /**\n * Get the shared VM instance.\n * Used by VMCheckpointer to create/restore checkpoints.\n */\n getVM(): VM {\n return this.vm;\n }\n\n /**\n * This engine's registries.\n *\n * For introspection: checking what a package registered, or asserting that\n * unregistering removed it. These used to be module-level singletons a\n * caller could import directly, which is exactly the coupling\n * {@link EngineContext} removes, so reaching them now goes through the\n * engine that owns them.\n *\n * @returns The context created for this engine. Mutating what it holds\n * affects this engine's behaviour, so treat it as read-only unless you are\n * deliberately registering something.\n */\n getContext(): EngineContext {\n return this.context;\n }\n\n getScopeManager(): ScopeManager {\n return this.scopeManager;\n }\n\n getLexer(): Lexer {\n return this.lexer;\n }\n\n /**\n * This engine's token normalizer, with every phrase and rule its packages\n * registered.\n *\n * Exposed for the highlighting path. `LanguageService` classifies tokens\n * after the lexer but can only see phrase-fused types (a date literal, a\n * timecode, a package's own fused token) by running the same normalizer\n * evaluation runs. Sharing this instance rather than building a second one\n * is what keeps the two from disagreeing.\n */\n getNormalizer(): TokenNormalizer {\n return this.normalizer;\n }\n\n /**\n * Every completion candidate contributed by currently-registered\n * packages (`IEnginePackage.completionItems`), flattened across all of\n * them. Used by `LanguageService.getCompletions()`.\n */\n getPackageCompletionItems(): CompletionItem[] {\n const items: CompletionItem[] = [];\n for (const pkgItems of this.packageCompletionItems.values()) {\n items.push(...pkgItems);\n }\n return items;\n }\n\n getParseletRegistry(): { prefix: Array<{ tokenType: string; bindingPower: number; category?: string }>; infix: Array<{ tokenType: string; leftBindingPower: number; rightBindingPower: number; category?: string }> } {\n return {\n prefix: this.registry.getAllPrefix(),\n infix: this.registry.getAllInfix(),\n };\n }\n\n /**\n * Lex + normalize (phrase fusion, implicit multiply, domain token\n * merging) `text` WITHOUT parsing or executing it, a cheap way for a\n * host to inspect what token stream a line would actually produce,\n * without paying for a full parse/compile/VM pass.\n *\n * Built for line-classification heuristics like \"does this look like a\n * real expression, or is it prose I shouldn't bother evaluating\", a\n * host that only checks for digits/operators/symbols before deciding\n * whether to evaluate a line will incorrectly skip genuine all-word\n * expressions (`weather in Tokyo`, `time in Paris`, `average of X, Y,\n * Z`), since none of those contain a digit or symbol. Checking whether\n * `tokenizeForClassification(text)[0]?.type` is anything OTHER than the\n * generic `IDENT` fallback is a reliable signal that the lexer/normalizer\n * actually recognized a specific keyword or fused multi-word phrase\n * i.e., this is real, registered vocabulary, not an arbitrary word that\n * merely happens to be lexable (every word lexes as IDENT if nothing\n * more specific claims it, so IDENT alone proves nothing about intent).\n *\n * Assumes the caller has already ruled out markdown-structural lines\n * (headings, code fences, etc.) via `getLexer().classifyLine()`. This\n * always tokenizes as a plain expression line, mirroring\n * `Lexer.resetExpression()`'s own \"caller already knows this is\n * evaluable\" contract.\n */\n tokenizeForClassification(text: string): Token[] {\n this.lexer.resetExpression(text);\n const rawTokens = Array.from(this.lexer);\n const exprTokens = rawTokens.filter(t => t.type !== 'COMMENT');\n if (exprTokens.length === 0) return [];\n return this.normalizer.normalize(exprTokens);\n }\n\n getParser(): PrecedenceParser {\n return this.parser;\n }\n\n isDiagnosticMode(): boolean {\n return this.diagnosticPipeline.hasCollectors;\n }\n\n //#endregion\n\n //#region Public API, Keystroke signal\n\n /**\n * Set the keystroke-level AbortSignal for the current evaluation cycle.\n *\n * Called by the UI layer (via ThreeTierEvaluator) before evaluate() or\n * evaluateAll(). All per-evaluation AbortControllers created during this\n * cycle link to this signal so that when the user types a new keystroke,\n * all in-flight async work is canceled atomically.\n *\n * @param signal The keystroke's AbortSignal, or null to clear.\n */\n setKeystrokeSignal(signal: AbortSignal | null): void {\n if (signal) {\n abortLogger.keystrokeSignalSet(signal.aborted);\n } else {\n abortLogger.keystrokeSignalCleared();\n }\n this.keystrokeSignal = signal;\n }\n\n /**\n * Get a serializable cache snapshot for diagnostic rendering.\n *\n * Returns bytecode cache entries, line cache entries, and async cache\n * packages, all as plain objects with no internal references. Previously\n * the playground accessed this via `(engine as any).getCacheSnapshot?.()`.\n */\n getCacheSnapshot(): CacheSnapshot {\n const bytecode: BytecodeCacheEntry[] = [];\n for (const [expression, program] of this.bytecodeCache) {\n bytecode.push({\n expression,\n opcodesLength: program.opcodes.length,\n numbersLength: program.numbers.length,\n stringsLength: program.strings.length,\n hasAsync: program.hasAsync,\n });\n }\n\n const lineCacheEntries: LineCacheEntryInfo[] = [];\n for (const key of this.lineCache.keys()) {\n // Keys are \"lineNumber\" or \"lineNumber:expression\", parse out both parts.\n const colonIdx = key.indexOf(':');\n const lineNumber = colonIdx > 0\n ? (parseInt(key.slice(0, colonIdx), 10) || 0)\n : (parseInt(key, 10) || 0);\n const expressionPart = colonIdx > 0 ? key.slice(colonIdx + 1) : undefined;\n\n const entry = expressionPart !== undefined\n ? this.lineCache.get(lineNumber, expressionPart)\n : this.lineCache.getEntryForLine(lineNumber);\n if (!entry) continue;\n\n lineCacheEntries.push({\n key,\n lineNumber,\n resultType: String(entry.result?.type ?? ''),\n resultValue: String(entry.result?.value ?? ''),\n reads: entry.readVariables ?? [],\n writeVar: entry.writeVariable ?? null,\n });\n }\n\n // Build async cache snapshot from TanStack Query cache\n const queryCache = this.queryClient.getQueryCache();\n const allQueries = queryCache.getAll();\n const asyncCache = allQueries.map(q => {\n const status = q.state.status === 'success' ? 'resolved' as const\n : q.state.status === 'error' ? 'error' as const\n : 'in_flight' as const;\n return {\n packageId: (q.queryKey[0] as string) ?? 'unknown',\n resolvedCount: q.state.status === 'success' ? 1 : 0,\n inFlightCount: q.state.status !== 'success' && q.state.status !== 'error' ? 1 : 0,\n errorCount: q.state.status === 'error' ? 1 : 0,\n entries: [{ key: q.queryKey.join(':'), status }],\n };\n });\n\n return { bytecode, lineCache: lineCacheEntries, asyncCache };\n }\n\n /**\n * Get serializable batcher metrics for the Workers diagnostic tab.\n *\n * Reads the typed read-only accessors on {@link AsyncResolutionBatcher}\n * (`pendingCount`/`dedupCount`/`workerOffloadCount`/`listenerCount`)\n * instead of reaching into its private fields via `(this.batcher as any)`.\n */\n getBatcherMetrics(): BatcherMetrics {\n return {\n pendingCount: this.batcher.pendingCount,\n dedupCount: this.batcher.dedupCount,\n workerOffloadCount: this.batcher.workerOffloadCount,\n listenerCount: this.batcher.listenerCount,\n };\n }\n\n /**\n * Get a serializable snapshot of VM checkpoints for diagnostics.\n *\n * The checkpointer lives on the ThreeTierEvaluator (not the engine),\n * so this returns an empty array when no checkpointer is available.\n * Previously accessed via `(vm as any).checkpointer.getAllCheckpoints?.()`.\n */\n getCheckpoints(): CheckpointSnapshot[] {\n // ThreeTierEvaluator attaches the checkpointer to the VM at runtime, so\n // it is not on the VM's declared surface. Describing the shape being\n // read, rather than reaching through `any`, keeps the expectation\n // checkable: if getAllCheckpoints' signature moves, this stops\n // compiling instead of failing at the call.\n const vmWithCheckpointer = this.vm as {\n checkpointer?: {\n getAllCheckpoints(): readonly { lineNumber: number; variables: Record<string, unknown> }[];\n };\n };\n const checkpointer = vmWithCheckpointer.checkpointer;\n if (!checkpointer) return [];\n\n const raw = checkpointer.getAllCheckpoints();\n return raw.map(cp => ({\n lineNumber: cp.lineNumber,\n variables: Object.keys(cp.variables),\n variableCount: Object.keys(cp.variables).length,\n }));\n }\n\n /**\n * Get the most recent pipeline telemetry from AllocationTracker.\n *\n * Returns null when AllocationTracker.isEnabled() is false (production\n * zero overhead), or when no expression has been evaluated via\n * evaluateExpressionWithDiagnostic() since the last clear().\n *\n * Use this in test/benchmark suites to inspect per-stage wall-time and\n * heap allocation data without enabling the full diagnostic pipeline.\n */\n getLastTelemetry(): PipelineTelemetry | null {\n return this.lastTelemetry;\n }\n\n //#endregion\n\n //#region Public API, Evaluation\n\n /**\n * Evaluate a raw expression string without line-number context.\n * Returns the {@link Value} result. Throws on error.\n */\n evaluateExpression(expression: string): Value {\n return this.evaluateLine(-1, expression);\n }\n\n /**\n * Explain how a line reached its answer, as a readable derivation.\n *\n * This is a companion to {@link evaluateExpression}, not a replacement:\n * `explainLine` is for the person reading the note, whereas the diagnostic\n * pipeline (`evaluateLineWithDiagnostic`) is for the developer and reports\n * stages, opcodes and timings. A host puts a derivation behind a hover or a\n * disclosure, so this is an API rather than an `explain` keyword: it never\n * consumes a word that a prose line might use, and it annotates a line the\n * host has already chosen to explain.\n *\n * The returned {@link Explanation} walks the line's operations in evaluation\n * order, each with the value it arrives at, and its `result` is identical to\n * what {@link evaluateExpression} returns for the same line. Every value in\n * the derivation is the engine's own, the operations are re-evaluated rather\n * than re-derived, so a step can never disagree with the answer.\n *\n * A line with nothing to break down (a bare literal), or one built from a\n * construct this slice does not derive yet (matrices, dates, function\n * calls), comes back with an empty `steps` array and the answer in\n * `result`, rather than an error.\n *\n * @param expression - The raw line to explain.\n * @returns The ordered derivation and final value.\n * @throws {EngineError} When the line does not evaluate at all, or resolves\n * data asynchronously (a derivation has no meaning for either).\n */\n explainLine(expression: string): Explanation {\n const { tokens } = this.lexToTokens(expression);\n // Normalize exactly as the evaluation path does (COMMENT tokens have no\n // parselet, phrase fusion turns \"off\"/\"of\" into their real operators),\n // so the derivation reads the same token stream the answer came from.\n const exprTokens = tokens.filter((t) => t.type !== \"COMMENT\");\n const normalized = this.normalizer.normalize(exprTokens);\n return buildExplanation({\n expression,\n tokens: normalized,\n evaluate: (source) => this.evaluateIsolated(source),\n locale: this.localeCode,\n });\n }\n\n /**\n * Evaluate a self-contained sub-expression without touching document state.\n *\n * Used only by {@link explainLine}. Unlike `evaluateExpression`, this never\n * writes to the line cache or the dependency graph: it is handed the spans\n * of a single line's own sub-expressions, and evaluating those to build a\n * derivation must not disturb the document the line belongs to. An async\n * (pending) result is rejected, a derivation cannot represent one.\n */\n private evaluateIsolated(expression: string): Value {\n const { tokens, hasParens } = this.lexToTokens(expression);\n const prep = this.prepareExpression(expression, tokens, hasParens, undefined, -1);\n if (prep.kind === \"empty\") return numberValue(0);\n if (prep.kind === \"error\") throw prep.error;\n if (prep.kind === \"symbolic-solve\") return prep.value;\n\n const result = this.executeRaw(prep.program, -1);\n if (result.type === \"error\") throw result.error;\n if (result.type === \"pending\") {\n throw ErrorFactory.execution(\n \"EXPLAIN_ASYNC_UNSUPPORTED\",\n `A derivation cannot be built for a line that resolves data asynchronously: \"${expression}\"`,\n { expression },\n );\n }\n return result.value;\n }\n\n//#endregion\n\n//#region Compilation, Bytecode-only path\n\n /**\n * Compile-only path: lex → parse → bytecode, without execution.\n *\n * Used by Tier 3 (background) evaluation to discover reads/writes\n * for the dependency graph without running display-only expressions.\n *\n * Uses the bytecode cache, repeated compilations of the same expression\n * return the cached program with zero allocation.\n *\n * @param expression - The raw expression string to compile.\n * @returns Object with compiled `program`, lexed `tokens`, and extracted `reads`/`writes`.\n * @throws ErrorFactory on parse failure or safety check failure.\n */\n\tcompileExpression(expression: string): {\n\t\tprogram: BytecodeProgram;\n\t\ttokens: Token[];\n\t\treads: string[];\n\t\twrites: string[];\n\t} {\n\t\tconst { tokens, hasParens } = this.lexToTokens(expression);\n\n\t\t// Shared front-half: safety → normalize → complexity → cache/compile.\n\t\tconst prep = this.prepareExpression(expression, tokens, hasParens);\n\n\t\tif (prep.kind === 'empty') {\n\t\t\treturn {\n\t\t\t\tprogram: { opcodes: new Uint8Array(0), numbers: new Float64Array(0), strings: [], hasAsync: false },\n\t\t\t\ttokens: [],\n\t\t\t\treads: [],\n\t\t\t\twrites: [],\n\t\t\t};\n\t\t}\n\t\tif (prep.kind === 'error') {\n\t\t\tif (prep.stage === 'parse' && (prep.reads?.length || prep.writes?.length)) {\n\t\t\t\t// Preserve the original error's own code/category/expected/\n\t\t\t\t// found/suggestion (whatever the parser actually threw\n\t\t\t\t// UNDEFINED_VARIABLE, FUNCTION_ARITY_MISMATCH, ...) rather\n\t\t\t\t// than the generic PARSE_ERROR wrapper this used to\n\t\t\t\t// construct, but still attach the already-extracted\n\t\t\t\t// reads/writes as context so DAG-registering callers (e.g.\n\t\t\t\t// ThreeTierEvaluator's compile fallback) can track this\n\t\t\t\t// line's dependencies even though it failed to compile.\n\t\t\t\t// EngineError.context is readonly, so this constructs a new\n\t\t\t\t// error carrying every other field through unchanged rather\n\t\t\t\t// than mutating prep.error in place.\n\t\t\t\tthrow new EngineError(prep.error.category, {\n\t\t\t\t\tcode: prep.error.code,\n\t\t\t\t\tmessage: prep.error.message,\n\t\t\t\t\texpected: prep.error.expected,\n\t\t\t\t\tfound: prep.error.found,\n\t\t\t\t\tsuggestion: prep.error.suggestion,\n\t\t\t\t\trecoverable: prep.error.recoverable,\n\t\t\t\t\tspan: prep.error.span,\n\t\t\t\t\tcause: prep.error.cause,\n\t\t\t\t\tcontext: { ...prep.error.context, reads: prep.reads ?? [], writes: prep.writes ?? [] },\n\t\t\t\t});\n\t\t\t}\n\t\t\tthrow prep.error;\n\t\t}\n\t\tif (prep.kind === 'symbolic-solve') {\n\t\t\t// No real bytecode representation for a `=>`/bare-equation line\n\t\t\t// (its effect, a stored equation, a direct vm.setVar(), was\n\t\t\t// already fully computed inside prepareExpression() itself)\n\t\t\t// same \"nothing to compile\" shape as the 'empty' case above.\n\t\t\t// External tooling asking for the compiled program of a `=>`\n\t\t\t// line gets an empty one; a disclosed limitation of this\n\t\t\t// narrow grammar, not an oversight. A compound assignment is the\n\t\t\t// exception: it carries real reads/writes so the incremental\n\t\t\t// evaluator checkpoints its running total and re-runs dependents.\n\t\t\treturn {\n\t\t\t\tprogram: { opcodes: new Uint8Array(0), numbers: new Float64Array(0), strings: [], hasAsync: false },\n\t\t\t\ttokens: prep.normalizedTokens,\n\t\t\t\treads: prep.reads ?? [],\n\t\t\t\twrites: prep.writes ?? [],\n\t\t\t};\n\t\t}\n\n\t\treturn { program: prep.program, tokens, reads: prep.reads, writes: prep.writes };\n\t}\n\n\t/**\n\t * Non-throwing \"does this compile\" check. Same lex → prepare pipeline as\n\t * {@link compileExpression}, but returns a boolean instead of throwing on\n\t * failure.\n\t *\n\t * compileExpression()'s failure path constructs a EngineError via\n\t * ErrorFactory, which calls Error.captureStackTrace(), one of V8's more\n\t * expensive operations. That's fine for genuine execution/compile errors\n\t * (rare, and the caller needs the message), but LanguageService's\n\t * syntax-highlighting gate calls compileExpression() purely to ask \"does\n\t * this parse\", on every visible line, every keystroke, and the common\n\t * case for a real markdown document is prose lines that DON'T parse, not\n\t * the rare case. Benchmarked: constructing-and-throwing that exception on\n\t * every non-matching line was responsible for highlighting an\n\t * unrecognized-prose line costing roughly an order of magnitude more than\n\t * a recognized expression. This skips that construction entirely, still\n\t * reuses the bytecode cache and prepareExpression()'s normal work, just\n\t * never builds an Error object for the \"no\" answer.\n\t *\n\t * Note: this only avoids the outer exception compileExpression() itself\n\t * would construct. A genuinely deep parse failure (an unmatched token\n\t * mid-expression, not just \"stopped early with leftover tokens\") still\n\t * goes through the parser's own throw/catch inside prepareExpression()\n\t * unavoidable without restructuring the parser's failure signaling, which\n\t * is out of scope here.\n\t *\n\t * The \"non-throwing\" in the first line is a contract callers rely on, not\n\t * a description of the happy path, so it is enforced here rather than left\n\t * to every stage below agreeing to return its errors. It had been left to\n\t * them, and they did not all agree: the lexer throws on an unterminated\n\t * string (`\"`), and the symbolic grammar threw on an assignment whose\n\t * right-hand side is still empty (`total =`). LanguageService calls this\n\t * per visible line per keystroke, so both reached CodeMirror's transaction\n\t * dispatch and broke the editor on input that is merely half-typed.\n\t *\n\t * A catch costs nothing on the path that does not throw, so the \"no\" answer\n\t * this method exists to make cheap stays cheap. Anything that does throw\n\t * was already paying for the Error it constructed.\n\t */\n\ttryCompileExpression(expression: string): boolean {\n\t\ttry {\n\t\t\treturn this.tryCompileExpressionUnguarded(expression);\n\t\t} catch {\n\t\t\t// \"Does this compile\" has a truthful answer for every one of these:\n\t\t\t// no. Swallowing is safe precisely because the answer is a boolean\n\t\t\t// with no detail to lose; callers wanting the reason call\n\t\t\t// compileExpression(), which still throws.\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t/** The body of {@link tryCompileExpression}, which owns the contract. */\n\tprivate tryCompileExpressionUnguarded(expression: string): boolean {\n\t\tconst { tokens, hasParens } = this.lexToTokens(expression);\n\t\tconst prep = this.prepareExpression(expression, tokens, hasParens);\n\t\treturn prep.kind !== 'error';\n\t}\n\n\t/**\n\t * Execute pre-compiled bytecode against the engine's shared VM.\n\t * Used by Tier 2 (scroll into view) to re-execute cached bytecode\n\t * without re-lexing, re-parsing, or re-compiling.\n\t *\n\t * Preserves the VM stack, pops any leftover items after execution.\n\t * Does NOT update DAG or LineCache (caller is responsible for state\n\t * management via DocumentModel).\n\t *\n\t * @returns The execution result, or undefined if bytecode is empty.\n\t * @param lineNumber - 1-based line this bytecode belongs to, for\n\t * cross-line features (see `makeLineContext()`). Defaults to -1.\n\t */\n\texecuteCached(program: BytecodeProgram, lineNumber: number = -1): Value {\n\t\tif (program.opcodes.length === 0) {\n\t\t\treturn numberValue(0);\n\t\t}\n\t\tconst evalResult = this.executeRaw(program, lineNumber);\n\n\t\tif (evalResult.type === 'pending') {\n\t\t\tvoid this.resolveAsync(evalResult);\n\t\t\treturn pendingValue(evalResult.queryKey);\n\t\t}\n\t\tif (evalResult.type === 'error') {\n\t\t\t// This is exactly the Tier-2/LOAD_GLOBAL_VAR bypass path\n\t\t\t// ARCHITECTURE.md's P0 item describes, executeCached() never\n\t\t\t// calls preflightAll(), so a global-variable read that should\n\t\t\t// have been guaranteed-resolved by preflight can now surface\n\t\t\t// here as a controlled GLOBAL_VARIABLE_NOT_RESOLVED error\n\t\t\t// (see VM.ts's LOAD_GLOBAL_VAR case) instead of a raw\n\t\t\t// uncaught TypeError. Re-throw so the caller's existing\n\t\t\t// error handling (ThreeTierEvaluator's own per-tier try/catch)\n\t\t\t// handles it exactly like any other executeCached() failure.\n\t\t\tthrow evalResult.error;\n\t\t}\n\n\t\treturn evalResult.value;\n\t}\n\n /**\n * Fast path: evaluate an expression and return a number directly.\n *\n * Skips Value object allocation when only a numeric result is needed.\n * Returns NaN whenever the expression has no numeric answer: a thrown\n * error, a bare undefined variable reference, or a faulted result (an\n * Error or a Pending value).\n *\n * Performs a pre-check for bare identifiers (single-token variable\n * references). If the identifier is not a known variable, returns NaN\n * immediately without attempting evaluation, avoids the ambiguity of\n * \"result === 0\" when a variable might legitimately store the value 0.\n *\n * A faulted result is treated the same way, and for the same reason: an\n * Error or Pending reads as 0 through {@link Value.toNumber}, so returning\n * that 0 would be indistinguishable from a real zero. NaN is this fast\n * path's established \"no value\" signal, so `evaluateNumber(\"5 kg to m\")`\n * (an impossible conversion) is NaN rather than a silent `0`. A caller that\n * needs the fault's detail should use {@link evaluateExpression} and read\n * {@link Value.errorCode}/{@link Value.isPending} off the result.\n *\n * @param expression - The raw expression string to evaluate.\n * @returns The numeric result, or NaN on error / undefined variable / fault.\n */\n evaluateNumber(expression: string): number {\n const trimmed = expression.trim();\n\n // Pre-check: bare identifiers that aren't known variables → NaN.\n // Doing this before evaluation avoids the ambiguity of \"result === 0\"\n // when a variable might legitimately store the value 0.\n if (/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(trimmed)) {\n if (this.vm.getVar(trimmed) === undefined) {\n return NaN;\n }\n }\n\n try {\n const value = this.evaluateLine(-1, expression);\n // A faulted result has no numeric meaning: toNumber() would read it\n // as 0, indistinguishable from a real zero. Surface it as NaN, the\n // same signal the bare-undefined-variable pre-check above returns.\n if (value.isFault()) return NaN;\n return value.toNumber();\n } catch {\n return NaN;\n }\n }\n\n //#endregion\n\n //#region State management, Clear / reset\n\n clear(): void {\n // Cancel pending batcher flushes and clear listeners to prevent\n // stale re-evaluations from in-flight promises that resolve after clear.\n\t\t// This call is what actually releases per-document state. The batcher is\n\t\t// reachable from the module-level data-query service, so an engine that\n\t\t// goes out of scope without clear() stays retained: on the order of\n\t\t// 200KB per engine against 8.2KB for one that never parsed, a figure\n\t\t// that grows with the registered package set. See the class doc.\n\t\tthis.batcher.clearAll();\n\n\t\t// Stop every background-refresh timer before the query cache is emptied\n\t\t// below, so no in-flight tick refetches into a cache that is about to be\n\t\t// cleared. The manager itself outlives clear() and is reused for the next\n\t\t// document.\n\t\tthis.backgroundRefresh?.clearAll();\n\n\t\t// The query cache holds a garbage-collection timer per cached query,\n\t\t// armed for `gcTime` (ten minutes). Those timers keep a Node process\n\t\t// alive on their own, so an engine cleared but not emptied here leaves\n\t\t// the host unable to exit for up to ten minutes after its last live\n\t\t// lookup. That is what it was doing to the test suite: every spec\n\t\t// passed, then Jest sat waiting on timers belonging to engines whose\n\t\t// documents were long gone.\n\t\t//\n\t\t// It also belongs here on its own terms. This method is documented as\n\t\t// the call that releases per-document state, and cached query results\n\t\t// are per-document state.\n\t\tthis.queryClient.clear();\n\n\t\t// The active client is a module-level hand-off for synchronous VM\n\t\t// plugin functions. Leaving ours published after clear() would let a\n\t\t// later execution read a cache this engine no longer owns.\n\t\tif (getActiveQueryClient() === this.queryClient) setActiveQueryClient(null);\n\n this.dag.clear();\n this.lineCache.clear();\n this.scopeManager.clear();\n this.bytecodeCache.clear();\n this.vm.reset();\n this.userUnits.clear();\n this.accumulatorNames.clear();\n this.lastTelemetry = null;\n }\n\n //#endregion\n\n //#region Public API, Snapshot / restore\n\n /**\n * Serialise this engine's session state into a plain, JSON-safe snapshot.\n *\n * Carries the three things a session accumulates in memory: named\n * {@link ExpressionEngine} variables, user-defined functions, and the\n * per-line result/bytecode cache (plus the expression-keyed bytecode cache).\n * Restore it with {@link ExpressionEngine.fromJSON} onto a fresh engine, and\n * later expressions resolve exactly as they would have on the engine that\n * evaluated the document.\n *\n * What is deliberately NOT carried:\n * - **Resolved async values.** Weather, stocks, currency, any package that\n * fetches: those results are point-in-time and must be re-fetched, not\n * restored stale. Every line backed by an async resolver (a DAG\n * data-source dependency, or an async plugin call in its bytecode) is\n * dropped from the line cache, and any variable whose most-recent\n * definition was such a line is dropped too. An in-flight (Pending) value\n * is likewise never written.\n * - **Package-contributed state.** Core state only for v1; a package opt-in\n * is a follow-up.\n * - **Symbolic (algebra) values.** Deferred: a variable holding one makes\n * this method throw {@link SnapshotErrorCodes.SNAPSHOT_UNSUPPORTED_VALUE}\n * (refused by name rather than dropped silently), and a cached line whose\n * result is symbolic is skipped (it re-evaluates on restore, algebra is\n * synchronous).\n *\n * The result survives `JSON.stringify` then `JSON.parse` unchanged.\n *\n * @returns A snapshot safe to store and hand back to `fromJSON`.\n * @throws {@link SnapshotErrorCodes.SNAPSHOT_UNSUPPORTED_VALUE} if a variable\n * holds a value this v1 format cannot represent (a symbolic value).\n */\n toJSON(): EngineSnapshot {\n // Async-backed lines: a line carries a DAG data-source dependency the\n // moment it first goes pending (see executeAndStore's\n // registerLineDataSourceDependency), and an async plugin call sets its\n // bytecode's hasAsync. Either way its result is point-in-time and must\n // be re-fetched rather than restored, so the line and any variable it\n // defines are excluded below.\n const dagSnapshot = this.dag.getSnapshot();\n const asyncLines = new Set<number>();\n for (const key of Object.keys(dagSnapshot.dataSourceDeps)) {\n const line = Number(key);\n if (!Number.isNaN(line)) asyncLines.add(line);\n }\n\n // Only the LAST definition of a variable decides its current value, so a\n // variable is excluded only when its most-recent writer line is async.\n // An earlier async definition later overwritten by a plain one is still\n // carried, matching the value the live VM actually holds.\n const lineEntries = this.lineCache.snapshotEntries();\n const latestWriter = new Map<string, { line: number; async: boolean }>();\n for (const { line, entry } of lineEntries) {\n const isAsync = asyncLines.has(line) || entry.bytecode.hasAsync;\n if (isAsync) asyncLines.add(line);\n const writeVar = entry.writeVariable;\n if (writeVar) {\n const prev = latestWriter.get(writeVar);\n if (!prev || line >= prev.line) latestWriter.set(writeVar, { line, async: isAsync });\n }\n }\n\n const variables: Record<string, SerializedValue> = {};\n for (const [name, value] of this.vm.getVariableEntries()) {\n if (value.type === ValueType.Pending) continue; // in-flight async, not restorable\n if (latestWriter.get(name)?.async) continue; // most recently written by an async line\n try {\n variables[name] = serializeValue(value, `variable \"${name}\"`);\n } catch (e) {\n // A value kind this v1 format defers (a symbolic result, or a\n // split/colour value held in a variable) is skipped rather than\n // aborting the whole snapshot, exactly as the line cache below\n // does. The variable re-establishes when its line re-evaluates\n // on restore; only that one binding is left out of the snapshot.\n if (e instanceof EngineError && e.code === SnapshotErrorCodes.SNAPSHOT_UNSUPPORTED_VALUE) continue;\n throw e;\n }\n }\n\n // A user-defined function body that calls an async plugin is refused at\n // definition time (FUNCTION_BODY_MUST_BE_SYNCHRONOUS), so every stored\n // function is pure compiled bytecode and safe to carry.\n const userFunctions = this.vm.getUserFunctionDefs().map(serializeUserFunction);\n\n const lineCache: SerializedLineCacheEntry[] = [];\n for (const { line, expression, entry } of lineEntries) {\n if (asyncLines.has(line)) continue; // async result, re-fetch on restore\n if (entry.result.type === ValueType.Pending) continue; // still in flight\n let result: SerializedValue;\n try {\n result = serializeValue(entry.result, `line ${line}`);\n } catch (e) {\n // A symbolic (algebra) result is the one value kind this v1 format\n // defers. Skip the cached line rather than aborting the whole\n // snapshot: the line re-evaluates on restore, and algebra is\n // synchronous, so nothing is lost but the cache hit. Any other\n // error is a real problem and propagates.\n if (e instanceof EngineError && e.code === SnapshotErrorCodes.SNAPSHOT_UNSUPPORTED_VALUE) continue;\n throw e;\n }\n lineCache.push({\n line,\n expression,\n result,\n bytecode: serializeBytecode(entry.bytecode),\n reads: entry.readVariables.slice(),\n writeVar: entry.writeVariable,\n });\n }\n\n const bytecodeCache = Array.from(this.bytecodeCache.entries()).map(([expression, program]) => ({\n expression,\n program: serializeBytecode(program),\n }));\n\n return {\n format: SNAPSHOT_FORMAT,\n version: SNAPSHOT_VERSION,\n engineVersion: ENGINE_VERSION,\n locale: this.localeCode,\n variables,\n userFunctions,\n lineCache,\n bytecodeCache,\n };\n }\n\n /**\n * Restore a snapshot produced by {@link ExpressionEngine.toJSON} onto a\n * fresh engine.\n *\n * The version gate runs first: a snapshot whose {@link EngineSnapshot.format}\n * or {@link EngineSnapshot.version} does not match this engine's reader is\n * refused with {@link SnapshotErrorCodes.SNAPSHOT_VERSION_MISMATCH} rather\n * than restored wrongly. The engine is then built with the snapshot's locale\n * (unless overridden) and the given `packages`, and its variable table,\n * user-function registry, line cache, dependency graph, and bytecode cache\n * are rehydrated from the snapshot.\n *\n * @param snapshot - A snapshot object, typically straight from `JSON.parse`.\n * @param options - Packages (must match those the snapshot was taken with),\n * plus optional config, diagnostic mode, and locale override. See\n * {@link EngineRestoreOptions}.\n * @returns A ready engine that behaves as though it had evaluated the\n * original document.\n * @throws {@link SnapshotErrorCodes.SNAPSHOT_VERSION_MISMATCH} for a missing\n * or mismatched envelope, and\n * {@link SnapshotErrorCodes.SNAPSHOT_MALFORMED} for internally\n * inconsistent contents.\n */\n static fromJSON(snapshot: EngineSnapshot, options: EngineRestoreOptions = {}): ExpressionEngine {\n // Refuse an incompatible or non-snapshot object before building anything.\n assertRestorable(snapshot);\n const locale = options.locale ?? snapshot.locale ?? \"en\";\n const engine = new ExpressionEngine({ locale, diagnostics: options.diagnostics ?? false, config: options.config, packages: options.packages });\n engine.restoreSnapshot(snapshot);\n return engine;\n }\n\n /**\n * Rehydrate this engine's state from a snapshot whose envelope has already\n * been validated by {@link assertRestorable}. Instance-private, the public\n * entry point is the static {@link ExpressionEngine.fromJSON}.\n */\n private restoreSnapshot(snapshot: EngineSnapshot): void {\n for (const [name, sv] of Object.entries(snapshot.variables)) {\n this.vm.setVar(name, deserializeValue(sv));\n }\n for (const fn of snapshot.userFunctions) {\n const def = deserializeUserFunction(fn);\n this.vm.defineUserFunction(def.name, def.params, def.program);\n }\n for (const e of snapshot.lineCache) {\n const entry = new LineCacheEntry(\n deserializeValue(e.result),\n deserializeBytecode(e.bytecode),\n e.reads.slice(),\n e.writeVar,\n );\n // The empty-string expression key round-trips to the same\n // expressionless slot LineCache stores it under; a non-empty key\n // restores the same line/expression pairing it was written with.\n this.lineCache.set(e.line, entry, e.expression);\n // Rebuild the dependency graph so incremental re-evaluation\n // (evaluateIncremental) still walks producers before consumers,\n // exactly as it would have on the engine that evaluated the document.\n this.dag.registerLine(e.line, e.reads, e.writeVar ? [e.writeVar] : []);\n }\n for (const { expression, program } of snapshot.bytecodeCache) {\n this.bytecodeCache.set(expression, deserializeBytecode(program));\n }\n }\n\n //#endregion\n\n //#region Public API, Incremental evaluation\n\n /**\n * Incrementally re-evaluate lines affected by a variable change.\n * Walks the DAG from the changed variable to find exactly which lines\n * need re-execution, no dirty-set indirection, no sorting guesswork.\n * Uses Kahn's algorithm for topological ordering: producers always\n * execute before consumers, regardless of document line order.\n */\n evaluateIncremental(variable: string, newValue: number): Map<number, Value> {\n // Phase 1.4 DAG-walk: get affected lines in topological order.\n // This replaces the old approach of markDirtyFromVariable() →\n // getDirtyLines() → ascending sort, which (a) double-iterated,\n // (b) picked up unrelated dirty lines, and (c) failed for\n // non-ascending dependency chains.\n const affectedLines = this.dag.getAffectedLinesInOrder(variable);\n\n // Preserve existing VM state while overriding the changed variable.\n this.vm.setVar(variable, numberValue(newValue));\n\n const updated = new Map<number, Value>();\n\n for (const lineNumber of affectedLines) {\n const entry = this.lineCache.getEntryForLine(lineNumber);\n if (!entry || entry.bytecode.opcodes.length === 0) continue;\n const evalResult = this.executeRaw(entry.bytecode, lineNumber);\n\n if (evalResult.type === 'pending') {\n void this.resolveAsync(evalResult);\n // Don't block, continue processing other affected lines.\n // The pending result will trigger re-evaluation when resolved.\n continue;\n }\n if (evalResult.type === 'error') {\n // Same per-line-containment shape as\n // AsyncResolutionBatcher.reExecuteMainThread()'s fatal-bug\n // fix: this loop re-executes potentially many DAG-affected\n // lines in one pass, a throw here would abort every\n // remaining affected line even though nothing was wrong\n // with them. Record this one line's failure as an Error\n // Value and continue, rather than letting one bad line take\n // out the whole incremental-update batch.\n const value = errorValue(evalResult.error.code, evalResult.error.message);\n updated.set(lineNumber, value);\n entry.result = value;\n continue;\n }\n\n const result = evalResult.value;\n updated.set(lineNumber, result);\n entry.result = result;\n }\n return updated;\n }\n\n //#endregion\n}\n\n//#endregion","/**\n * Engine worker, offloads both compilation and VM execution to a\n * background thread (plan L6: worker consolidation).\n *\n * Previously two separate worker files (compilation.worker.ts,\n * execution.worker.ts) duplicated the Transferable ArrayBuffer protocol,\n * postMessage/onmessage boilerplate, and lazy-init pattern. This file\n * merges them behind a single `self.onmessage` dispatching on `msg.type`\n * the message shapes are UNCHANGED from the two original files, so\n * CompilationWorkerManager and ExecutionPool (the main-thread consumers)\n * require no changes beyond importing this file's factory.\n *\n * Each Worker instance created from this file is used exclusively by ONE\n * consumer (a CompilationWorkerManager sends only COMPILE_BATCH; an\n * ExecutionPool sends only EXECUTE_BATCH), the module-level `engine` and\n * `vm` singletons below are independent lazy state, so there is no\n * cross-contamination between the two roles even though they share code.\n *\n * Message protocol:\n * Main → Worker:\n * { type: \"COMPILE_BATCH\", id, items: CompileItem[] }\n * { type: \"EXECUTE_BATCH\", id, items: ExecuteItem[] }\n * { type: \"TERMINATE\", id }\n *\n * Worker → Main:\n * { id, type: \"COMPILE_RESULT\", results: CompileResult[] }\n * { id, type: \"EXECUTE_RESULT\", results: ExecuteResult[] }\n *\n * Transferable objects: bytecode opcodes/numbers buffers are transferred\n * (zero-copy) in both directions, same pattern as the original files.\n */\n\nimport { ExpressionEngine } from \"../engine/ExpressionEngine\";\nimport type { Bytecode } from \"../vm/VM\";\nimport { createVM, executeBytecode } from \"../vm/VM\";\nimport { sharedOpRegistry } from \"../vm/OpRegistry\";\nimport { ValueType } from \"../vm/Value\";\n\n// ── Compile message types ──────────────────────────────────────────────\n\ninterface CompileItem {\n\tlineId: number;\n\texpression: string;\n\ttextHash: number;\n}\n\ninterface CompileBatchMsg {\n\ttype: \"COMPILE_BATCH\";\n\tid: number;\n\titems: CompileItem[];\n}\n\ninterface CompileResult {\n\tlineId: number;\n\texpression: string;\n\tcompiledAgainstHash: number;\n\topcodesBuffer: ArrayBuffer;\n\tnumbersBuffer: ArrayBuffer;\n\topcodesLength: number;\n\tnumbersLength: number;\n\tstrings: string[];\n\treads: string[];\n\twrites: string[];\n\tisVariableDef: boolean;\n\terror: string | null;\n}\n\n// ── Execute message types ──────────────────────────────────────────────\n\ninterface ExecuteItem {\n\tlineNumber: number;\n\topcodesBuffer: ArrayBuffer;\n\tnumbersBuffer: ArrayBuffer;\n\topcodesLength: number;\n\tnumbersLength: number;\n\tstrings: string[];\n}\n\ninterface ExecuteBatchMsg {\n\ttype: \"EXECUTE_BATCH\";\n\tid: number;\n\titems: ExecuteItem[];\n}\n\ninterface ExecuteResult {\n\tlineNumber: number;\n\tvalueType: ValueType;\n\tvalue: number;\n\tunit?: string;\n\tisPending: boolean;\n\tqueryKey?: string;\n}\n\ninterface TerminateMsg {\n\ttype: \"TERMINATE\";\n\tid: number;\n}\n\ntype EngineWorkerMessage = CompileBatchMsg | ExecuteBatchMsg | TerminateMsg;\n\n// ── Worker body ───────────────────────────────────────────────────────\n\n// A host that builds with esbuild-plugin-inline-worker gets this replaced by a\n// real factory returning a Worker. Nothing else does, the published tsup bundle\n// included, so this stub is a live runtime path rather than a dead sentinel.\n//\n// Throwing is the contract, not a failure to handle the case. Both consumers\n// probe availability by calling this inside a try/catch\n// ({@link ExecutionPool.isAvailable}, and the equivalent in\n// CompilationWorkerManager), so the throw is how they learn workers are\n// unavailable and fall back to the main thread. The message is for a developer\n// reading a stack trace, and is otherwise swallowed by design.\n//\n// The one raw `throw new Error` in the codebase. It stays raw because it is a\n// build-configuration signal rather than an engine error, and routing it\n// through ErrorFactory would imply a caller should inspect its code.\nexport default (() => {\n\tthrow new Error(\"engine.worker.ts was not processed by esbuild-plugin-inline-worker, so worker offload is unavailable\");\n}) as unknown as () => Worker;\n\n// ── Lazy per-role state, independent, only the used one is created ────\n\nlet compileEngine: ExpressionEngine | null = null;\nfunction getCompileEngine(): ExpressionEngine {\n\tif (!compileEngine) {\n\t\tcompileEngine = new ExpressionEngine();\n\t}\n\treturn compileEngine;\n}\n\nlet executeVm: ReturnType<typeof createVM> | null = null;\nfunction getExecuteVm(): ReturnType<typeof createVM> {\n\tif (!executeVm) {\n\t\texecuteVm = createVM(sharedOpRegistry, 200, 50000);\n\t}\n\treturn executeVm;\n}\n\n// ── Compile ──────────────────────────────────────────────────────────\n\n/**\n * Compile a single expression and produce a transfer-ready CompileResult.\n * Extracts ArrayBuffers from the compiled TypedArrays so they can be\n * transferred via postMessage, after this call, the original TypedArrays\n * are detached on the worker side.\n */\nfunction compileOne(item: CompileItem): CompileResult {\n\tconst base: Omit<CompileResult, \"opcodesBuffer\" | \"numbersBuffer\" | \"opcodesLength\" | \"numbersLength\"> = {\n\t\tlineId: item.lineId,\n\t\texpression: item.expression,\n\t\tcompiledAgainstHash: item.textHash,\n\t\tstrings: [],\n\t\treads: [],\n\t\twrites: [],\n\t\tisVariableDef: false,\n\t\terror: null,\n\t};\n\n\ttry {\n\t\tconst eng = getCompileEngine();\n\t\tconst { program, reads, writes } = eng.compileExpression(item.expression);\n\t\tconst isVariableDef = writes.length > 0;\n\n\t\tconst opcodes = program.opcodes;\n\t\tconst numbers = program.numbers;\n\n\t\t// Transfer only the exact used slice of the ArrayBuffer. The engine's\n\t\t// buffer pool is write-only, so detaching the source view is fine.\n\t\t//\n\t\t// The casts narrow ArrayBufferLike to ArrayBuffer. A TypedArray's\n\t\t// `buffer` is typed as the union including SharedArrayBuffer, which\n\t\t// TypeScript 6 enforces where 5.1 did not, and the postMessage\n\t\t// transfer list below accepts only ArrayBuffer. The narrowing is\n\t\t// sound here because these buffers come from the engine's own pool,\n\t\t// which allocates plain ArrayBuffers; a SharedArrayBuffer could not\n\t\t// reach this point, and would not be transferable if it did.\n\t\tconst opcodesBuffer = (opcodes.buffer as ArrayBuffer).slice(\n\t\t\topcodes.byteOffset,\n\t\t\topcodes.byteOffset + opcodes.byteLength\n\t\t);\n\t\tconst numbersBuffer = (numbers.buffer as ArrayBuffer).slice(\n\t\t\tnumbers.byteOffset,\n\t\t\tnumbers.byteOffset + numbers.byteLength\n\t\t);\n\n\t\treturn {\n\t\t\t...base,\n\t\t\topcodesBuffer,\n\t\t\tnumbersBuffer,\n\t\t\topcodesLength: opcodes.length,\n\t\t\tnumbersLength: numbers.length,\n\t\t\tstrings: [...program.strings],\n\t\t\treads,\n\t\t\twrites,\n\t\t\tisVariableDef,\n\t\t};\n\t} catch (e) {\n\t\treturn {\n\t\t\t...base,\n\t\t\topcodesBuffer: new ArrayBuffer(0),\n\t\t\tnumbersBuffer: new ArrayBuffer(0),\n\t\t\topcodesLength: 0,\n\t\t\tnumbersLength: 0,\n\t\t\terror: e instanceof Error ? e.message : String(e),\n\t\t};\n\t}\n}\n\nfunction handleCompileBatch(msg: CompileBatchMsg): void {\n\tconst results: CompileResult[] = [];\n\tconst transferList: ArrayBuffer[] = [];\n\n\tfor (const item of msg.items) {\n\t\tconst result = compileOne(item);\n\t\tresults.push(result);\n\t\tif (result.opcodesBuffer.byteLength > 0) transferList.push(result.opcodesBuffer);\n\t\tif (result.numbersBuffer.byteLength > 0) transferList.push(result.numbersBuffer);\n\t}\n\n\t(self as unknown as Worker).postMessage(\n\t\t{ id: msg.id, type: \"COMPILE_RESULT\", results },\n\t\ttransferList\n\t);\n}\n\n// ── Execute ──────────────────────────────────────────────────────────\n\n/**\n * Execute a single bytecode program and produce a serialized ExecuteResult.\n * Reconstructs TypedArrays from the transferred ArrayBuffers (zero-copy).\n * Resets the worker VM before each execution, no state carries over\n * between lines in a batch.\n */\nfunction executeOne(item: ExecuteItem): ExecuteResult {\n\tconst vmm = getExecuteVm();\n\tvmm.reset();\n\n\tconst opcodes = new Uint8Array(item.opcodesBuffer, 0, item.opcodesLength);\n\tconst numbers = new Float64Array(item.numbersBuffer, 0, item.numbersLength);\n\tconst bytecode: Bytecode = { opcodes, numbers, strings: item.strings };\n\n\ttry {\n\t\tconst result = executeBytecode(bytecode, vmm);\n\n\t\tif (result.type === \"pending\") {\n\t\t\treturn {\n\t\t\t\tlineNumber: item.lineNumber,\n\t\t\t\tvalueType: ValueType.Pending,\n\t\t\t\tvalue: 0,\n\t\t\t\tisPending: true,\n\t\t\t\tqueryKey: result.queryKey,\n\t\t\t};\n\t\t}\n\n\t\tif (result.type === \"error\") {\n\t\t\treturn {\n\t\t\t\tlineNumber: item.lineNumber,\n\t\t\t\tvalueType: ValueType.Error,\n\t\t\t\tvalue: 0,\n\t\t\t\tisPending: false,\n\t\t\t\tunit: result.error.message,\n\t\t\t};\n\t\t}\n\n\t\tconst val = result.value;\n\t\treturn {\n\t\t\tlineNumber: item.lineNumber,\n\t\t\tvalueType: val.type,\n\t\t\tvalue: typeof val.value === \"number\"\n\t\t\t\t? val.value\n\t\t\t\t: typeof val.value === \"bigint\"\n\t\t\t\t\t? Number(val.value)\n\t\t\t\t\t: 0,\n\t\t\tunit: val.unit,\n\t\t\tisPending: false,\n\t\t};\n\t} catch {\n\t\t// Execution error, return error-type value so main thread can\n\t\t// propagate through DAG as errorValue.\n\t\treturn {\n\t\t\tlineNumber: item.lineNumber,\n\t\t\tvalueType: ValueType.Error,\n\t\t\tvalue: 0,\n\t\t\tisPending: false,\n\t\t\tunit: \"Worker execution failed\",\n\t\t};\n\t}\n}\n\nfunction handleExecuteBatch(msg: ExecuteBatchMsg): void {\n\tconst results: ExecuteResult[] = [];\n\tfor (const item of msg.items) {\n\t\tresults.push(executeOne(item));\n\t}\n\t// No transferables needed for the response, results are plain\n\t// objects with numbers and strings (structured-cloned).\n\t(self as unknown as Worker).postMessage({\n\t\tid: msg.id,\n\t\ttype: \"EXECUTE_RESULT\",\n\t\tresults,\n\t});\n}\n\n// ── Message handler ───────────────────────────────────────────────────\n\n/**\n * Whether this module is executing inside a real worker global scope.\n *\n * Only `esbuild-plugin-inline-worker` splits this file into a separate worker\n * bundle. Any other bundler, tsup included, treats it as an ordinary module and\n * inlines the whole body into whatever imported it, which means the code below\n * runs on the main thread or in Node rather than in a worker.\n *\n * Without this guard, importing the published package from Node throws\n * `self is not defined` before a single expression can be evaluated. The check\n * distinguishes the three environments: Node defines neither `self` nor\n * `window`, a browser main thread defines both, and a worker defines only\n * `self`.\n */\nconst inWorkerScope = typeof self !== \"undefined\" && typeof window === \"undefined\";\n\nconst handleMessage = (event: MessageEvent) => {\n\t// A real postMessage always carries a browser-populated origin the\n\t// sender cannot spoof, so this only ever rejects a genuine mismatch. It\n\t// is skipped, not enforced, when either side is unset, which covers the\n\t// test harness driving this handler directly with a plain object and\n\t// no location global (see WorkerIntegration.spec.ts), without opening\n\t// anything a real message could exploit.\n\tif (event.origin && self.location && event.origin !== self.location.origin) return;\n\n\tconst msg = event.data as EngineWorkerMessage;\n\n\tswitch (msg.type) {\n\t\tcase \"COMPILE_BATCH\":\n\t\t\thandleCompileBatch(msg);\n\t\t\tbreak;\n\n\t\tcase \"EXECUTE_BATCH\":\n\t\t\thandleExecuteBatch(msg);\n\t\t\tbreak;\n\n\t\tcase \"TERMINATE\": {\n\t\t\t// Not sent by either production manager today, both call the\n\t\t\t// native Worker.terminate() directly instead. Kept for protocol\n\t\t\t// completeness and future consumers. Clears whichever per-role\n\t\t\t// state this instance happened to create.\n\t\t\tif (compileEngine) {\n\t\t\t\tcompileEngine.clear();\n\t\t\t\tcompileEngine = null;\n\t\t\t}\n\t\t\tif (executeVm) {\n\t\t\t\texecuteVm.reset();\n\t\t\t\texecuteVm = null;\n\t\t\t}\n\t\t\t(self as unknown as Worker).postMessage({\n\t\t\t\tid: msg.id,\n\t\t\t\ttype: \"COMPILE_RESULT\",\n\t\t\t\tresults: [],\n\t\t\t});\n\t\t\tbreak;\n\t\t}\n\n\t\tdefault: {\n\t\t\t(self as unknown as Worker).postMessage({\n\t\t\t\tid: -1,\n\t\t\t\ttype: \"COMPILE_RESULT\",\n\t\t\t\tresults: [],\n\t\t\t\terror: `Unknown message type: ${(msg as { type?: string }).type}`,\n\t\t\t});\n\t\t}\n\t}\n};\n\n// Installed only when genuinely running as a worker. Everywhere else this\n// module has been inlined into a host bundle, where binding a handler would at\n// best be inert and at worst intercept the host's own messages.\nif (inWorkerScope) {\n\tself.onmessage = handleMessage;\n}\n","/**\n * ExecutionPool, manages a pool of execution workers for offloading\n * VM bytecode re-execution when AsyncResolutionBatcher.flush() has >50\n * affected lines.\n *\n * Workers are created lazily (on first dispatch). Each worker runs\n * executeBytecode() with its own isolated VM, no shared state between\n * worker and main thread, no scope leakage.\n *\n * Design decisions:\n * - Pool size: Math.min(navigator.hardwareConcurrency ?? 4, 4). Capped at\n * 4 to avoid excessive thread creation on high-core machines.\n * - Round-robin dispatch distributes batches evenly across workers.\n * - Workers are terminated on pool.clear() (engine clear) and recreated\n * lazily on next dispatch.\n * - Falls back to synchronous main-thread execution when Worker is\n * unavailable (Node.js, SSR, testing without jsdom worker support).\n *\n * Transferable protocol (shares engine.worker.ts with CompilationWorkerManager):\n * - Main thread clones bytecode ArrayBuffers via .slice() per entry\n * - Transfers cloned buffers to worker (zero-copy, detached on main side)\n * - Worker receives buffers, reconstructs TypedArrays, executes, returns\n * serialized results (plain objects with numbers/strings)\n *\n * Message protocol:\n * Pool → Worker: { type: \"EXECUTE_BATCH\", id, items: ExecuteItem[] }\n * Worker → Pool: { id, type: \"EXECUTE_RESULT\", results: ExecuteResult[] }\n */\n\nimport type { LineCacheEntry } from \"@solve-js/cache/LineCache\";\nimport { ValueType } from \"@solve-js/vm/Value\";\nimport { numberValue, uomValue, hexValue, bigIntValue, stringValue, boolValue, datetimeValue, percentageValue, errorValue, pendingValue } from \"@solve-js/vm/Value\";\nimport type { Value } from \"@solve-js/vm/Value\";\n\n/** Timeout for worker batch execution (30s). If exceeded, returns empty results. */\nconst WORKER_BATCH_TIMEOUT_MS = 30_000;\n\n// ── Static import of the inline worker factory ────────────────────────────\n// esbuild-plugin-inline-worker transforms this into a function that\n// returns Worker (using blob URL or equivalent). At build time it's a\n// factory; at dev time it throws.\nimport createExecutionWorker from \"@solve-js/workers/engine.worker\";\n\n// ── Worker message types (mirrors the EXECUTE_* shapes in engine.worker.ts) ──\n\ninterface ExecuteItem {\n\tlineNumber: number;\n\topcodesBuffer: ArrayBuffer;\n\tnumbersBuffer: ArrayBuffer;\n\topcodesLength: number;\n\tnumbersLength: number;\n\tstrings: string[];\n}\n\ninterface ExecuteResult {\n\tlineNumber: number;\n\tvalueType: ValueType;\n\tvalue: number;\n\tunit?: string;\n\tisPending: boolean;\n\tqueryKey?: string;\n}\n\n// ── Batch tracking ────────────────────────────────────────────────────────\n\ninterface PendingBatch {\n\t/** Correlation ID sent to the worker. */\n\tid: number;\n\t/** Line numbers in this batch (in order). Used for result correlation. */\n\tlineNumbers: number[];\n\t/** Resolve when results arrive. */\n\tresolve: (results: ExecuteResult[]) => void;\n}\n\n/** Number of affected lines before we offload to worker pool. */\nexport const WORKER_OFFLOAD_THRESHOLD = 50;\n\n// ── Pool ──────────────────────────────────────────────────────────────────\n\n/**\n * Runs bytecode on background workers instead of the main thread.\n *\n * Used for scroll-driven batches, where evaluating a screenful of lines on the\n * main thread would drop frames. Degrades to the main thread when workers are\n * unavailable, which is the normal case in Node and in any bundle not built\n * with esbuild-plugin-inline-worker. See {@link ExecutionPool.isAvailable}.\n */\nexport class ExecutionPool {\n\tprivate workers: Worker[] = [];\n\tprivate nextWorker = 0;\n\tprivate nextId = 1;\n\tprivate pendingBatches = new Map<number, PendingBatch>();\n\tprivate terminated = false;\n\tprivate poolSize: number;\n\n\tconstructor(poolSize?: number) {\n\t\tthis.poolSize = Math.min(poolSize ?? this.defaultPoolSize(), 4);\n\t}\n\n\tprivate defaultPoolSize(): number {\n\t\tif (typeof navigator !== \"undefined\" && navigator.hardwareConcurrency) {\n\t\t\treturn Math.min(navigator.hardwareConcurrency, 4);\n\t\t}\n\t\treturn 2;\n\t}\n\n\t// ── Public API ────────────────────────────────────────────────────────\n\n\t/** Cached availability flag. Checked once; createExecutionWorker never called again. */\n\tprivate _available: boolean | null = null;\n\n\t/**\n\t * Whether worker-based execution is available.\n\t * Returns false in Node.js / jsdom test environments where Worker\n\t * may be polyfilled but execution workers aren't functional.\n\t */\n\tisAvailable(): boolean {\n\t\tif (this.terminated) return false;\n\t\tif (this._available !== null) return this._available;\n\t\tif (typeof Worker === \"undefined\") {\n\t\t\tthis._available = false;\n\t\t\treturn false;\n\t\t}\n\t\ttry {\n\t\t\t// Create a test worker, then immediately terminate it.\n\t\t\tconst w = createExecutionWorker();\n\t\t\tw.terminate();\n\t\t\tthis._available = true;\n\t\t\treturn true;\n\t\t} catch {\n\t\t\tthis._available = false;\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t/**\n\t * Execute a batch of line entries via the worker pool.\n\t *\n\t * Takes ordered line numbers and their LineCache entries. Clones bytecode\n\t * ArrayBuffers for transfer, dispatches to workers round-robin, and\n\t * returns the serialized results (with 30s timeout fallback).\n\t *\n\t * Falls back to undefined when workers are unavailable, caller should\n\t * use the main-thread path.\n\t *\n\t * @returns ExecuteResult[] on success, undefined if workers unavailable.\n\t */\n\texecuteBatch(\n\t\torderedLineNumbers: number[],\n\t\tentries: Map<number, LineCacheEntry | undefined>,\n\t): Promise<ExecuteResult[]> | undefined {\n\t\tif (!this.isAvailable()) return undefined;\n\t\tif (orderedLineNumbers.length === 0) return Promise.resolve([]);\n\n\t\t// Lazy-initialize workers\n\t\tthis.ensureWorkers();\n\n\t\t// Clone bytecode buffers for transfer. Each worker needs its own\n\t\t// copy because transfer detaches the ArrayBuffer on the sender side.\n\t\tconst items: ExecuteItem[] = [];\n\t\tfor (const lineNumber of orderedLineNumbers) {\n\t\t\tconst entry = entries.get(lineNumber);\n\t\t\tif (!entry || entry.bytecode.opcodes.length === 0) continue;\n\n\t\t\tconst opcodes = entry.bytecode.opcodes;\n\t\t\tconst numbers = entry.bytecode.numbers;\n\n\t\t\t// Clone the exact used slice of each ArrayBuffer for transfer.\n\t\t\t// After transfer, the clone is detached on the main thread\n\t\t\t// the original LineCache entry's buffers are untouched.\n\t\t\tconst opcodesClone = opcodes.buffer.slice(\n\t\t\t\topcodes.byteOffset,\n\t\t\t\topcodes.byteOffset + opcodes.byteLength,\n\t\t\t) as ArrayBuffer;\n\t\t\tconst numbersClone = numbers.buffer.slice(\n\t\t\t\tnumbers.byteOffset,\n\t\t\t\tnumbers.byteOffset + numbers.byteLength,\n\t\t\t) as ArrayBuffer;\n\n\t\t\titems.push({\n\t\t\t\tlineNumber,\n\t\t\t\topcodesBuffer: opcodesClone,\n\t\t\t\tnumbersBuffer: numbersClone,\n\t\t\t\topcodesLength: opcodes.length,\n\t\t\t\tnumbersLength: numbers.length,\n\t\t\t\tstrings: [...entry.bytecode.strings],\n\t\t\t});\n\t\t}\n\n\t\tif (items.length === 0) return Promise.resolve([]);\n\n\t\t// Collect transferable ArrayBuffers for zero-copy postMessage.\n\t\tconst transferList: ArrayBuffer[] = [];\n\t\tfor (const item of items) {\n\t\t\tif (item.opcodesBuffer.byteLength > 0) transferList.push(item.opcodesBuffer);\n\t\t\tif (item.numbersBuffer.byteLength > 0) transferList.push(item.numbersBuffer);\n\t\t}\n\n\t\tconst batchId = this.nextId++;\n\t\tconst worker = this.getNextWorker();\n\n\t\treturn new Promise<ExecuteResult[]>((resolve) => {\n\t\t\t// Timeout guard: if worker hangs (infinite bytecode loop despite\n\t\t\t// VM instruction limit), resolve with empty results after 30s.\n\t\t\tconst timeoutId = setTimeout(() => {\n\t\t\t\tthis.pendingBatches.delete(batchId);\n\t\t\t\tresolve([]);\n\t\t\t}, WORKER_BATCH_TIMEOUT_MS);\n\n\t\t\tthis.pendingBatches.set(batchId, {\n\t\t\t\tid: batchId,\n\t\t\t\tlineNumbers: orderedLineNumbers,\n\t\t\t\tresolve: (results: ExecuteResult[]) => {\n\t\t\t\t\tclearTimeout(timeoutId);\n\t\t\t\t\tresolve(results);\n\t\t\t\t},\n\t\t\t});\n\n\t\t\tworker.postMessage(\n\t\t\t\t{ type: \"EXECUTE_BATCH\", id: batchId, items },\n\t\t\t\ttransferList,\n\t\t\t);\n\t\t});\n\t}\n\n\t/**\n\t * Clean up all workers and pending batches. Called on engine clear.\n\t * Workers are recreated lazily on next dispatch.\n\t */\n\tclear(): void {\n\t\t// Reject all pending batches\n\t\tfor (const [, batch] of this.pendingBatches) {\n\t\t\tbatch.resolve([]);\n\t\t}\n\t\tthis.pendingBatches.clear();\n\n\t\t// Terminate all workers\n\t\tfor (const w of this.workers) {\n\t\t\tw.terminate();\n\t\t}\n\t\tthis.workers = [];\n\t\tthis.nextWorker = 0;\n\t}\n\n\t/**\n\t * Full teardown. After destroy(), the pool is permanently unusable.\n\t */\n\tdestroy(): void {\n\t\tthis.terminated = true;\n\t\tthis.clear();\n\t}\n\n\t// ── Private ────────────────────────────────────────────────────────────\n\n\tprivate ensureWorkers(): void {\n\t\tif (this.workers.length > 0) return;\n\n\t\tfor (let i = 0; i < this.poolSize; i++) {\n\t\t\tconst worker = createExecutionWorker();\n\t\t\tworker.onmessage = (event: MessageEvent) => {\n\t\t\t\tthis.handleWorkerMessage(event.data);\n\t\t\t};\n\t\t\tworker.onerror = (err: ErrorEvent) => {\n\t\t\t\tconsole.error(`[ExecutionPool] Worker ${i} error:`, err.message);\n\t\t\t\t// Resolve ALL pending batches with empty results so callers\n\t\t\t\t// don't hang. Any in-flight execution results are lost, but\n\t\t\t\t// the batcher will re-evaluate on next resolution.\n\t\t\t\tfor (const [id, batch] of this.pendingBatches) {\n\t\t\t\t\tbatch.resolve([]);\n\t\t\t\t\tthis.pendingBatches.delete(id);\n\t\t\t\t}\n\t\t\t};\n\t\t\tthis.workers.push(worker);\n\t\t}\n\t}\n\n\tprivate getNextWorker(): Worker {\n\t\tconst w = this.workers[this.nextWorker];\n\t\tthis.nextWorker = (this.nextWorker + 1) % this.workers.length;\n\t\treturn w;\n\t}\n\n\tprivate handleWorkerMessage(data: { id: number; type: string; results: ExecuteResult[] }): void {\n\t\tif (data.type !== \"EXECUTE_RESULT\") return;\n\n\t\tconst batch = this.pendingBatches.get(data.id);\n\t\tif (!batch) return;\n\n\t\tthis.pendingBatches.delete(data.id);\n\t\tbatch.resolve(data.results);\n\t}\n}\n\n// ── Value reconstruction helpers ──────────────────────────────────────────\n\n/**\n * Reconstruct a Value object from a serialized ExecuteResult.\n *\n * Called on the main thread after worker execution completes.\n * Maps ValueType → appropriate constructor function.\n */\nexport function reconstructValue(result: ExecuteResult): Value {\n\tswitch (result.valueType) {\n\t\tcase ValueType.Number:\n\t\t\treturn numberValue(result.value);\n\t\tcase ValueType.Hex:\n\t\t\treturn hexValue(result.value);\n\t\tcase ValueType.BigInt:\n\t\t\treturn bigIntValue(BigInt(result.value));\n\t\tcase ValueType.String:\n\t\t\treturn stringValue(String(result.value));\n\t\tcase ValueType.Datetime:\n\t\t\treturn datetimeValue(result.value);\n\t\tcase ValueType.Percentage:\n\t\t\treturn percentageValue(result.value);\n\t\tcase ValueType.Uom:\n\t\t\treturn uomValue(result.value, result.unit ?? \"\");\n\t\tcase ValueType.Matrix:\n\t\t\t// Pre-existing simplification carried over from the old Array\n\t\t\t// type: the worker-pool's {valueType, value, unit} serialization\n\t\t\t// has no slot for MatrixData's rows/cols/data shape, so a Matrix\n\t\t\t// result degrades to a plain number here rather than round-\n\t\t\t// tripping intact. Not fixed as part of Matrix support. This\n\t\t\t// gap already existed for vectors before this rename.\n\t\t\treturn numberValue(result.value);\n\t\tcase ValueType.Boolean:\n\t\t\treturn boolValue(result.value !== 0);\n\t\tcase ValueType.Pending:\n\t\t\treturn pendingValue(result.queryKey ?? \"\");\n\t\tcase ValueType.Error:\n\t\t\treturn errorValue(\"WORKER_EXECUTION_ERROR\", result.unit ?? \"Unknown worker error\");\n\t\tdefault:\n\t\t\treturn numberValue(result.value);\n\t}\n}\n","import type { DependencyGraph } from \"@solve-js/vm/DependencyGraph\";\nimport type { LineCache, LineCacheEntry } from \"@solve-js/cache/LineCache\";\nimport { type Value, errorValue } from \"@solve-js/vm/Value\";\nimport { executeBytecode } from \"@solve-js/vm/VM\";\nimport type { VM } from \"@solve-js/vm/OpRegistry\";\nimport { normalizeUnknownError } from \"@solve-js/errors/EngineError\";\nimport {\n\tExecutionPool,\n\tWORKER_OFFLOAD_THRESHOLD,\n\treconstructValue,\n} from \"@solve-js/engine/ExecutionPool\";\n\n// ── Event types ────────────────────────────────────────────────────────\n\n/** Emitted when one or more lines have updated results after async resolution. */\nexport interface LinesUpdatedEvent {\n\ttype: \"lines-updated\";\n\t/** Line numbers whose results changed (1-based). */\n\tlineNumbers: number[];\n\t/** The query keys whose resolution triggered this update. */\n\taffectedQueryKeys: string[];\n}\n\n/** Emitted when an async resolution fails with an error. */\nexport interface AsyncErrorEvent {\n\ttype: \"error\";\n\t/** The query key that failed. */\n\tqueryKey: string;\n\t/** The package whose resolver failed. */\n\tpackageId: string;\n\t/** The error that caused the failure. */\n\terror: Error;\n}\n\n/** Something an async resolution produced: updated lines, or a failure. */\nexport type AsyncResolutionEvent = LinesUpdatedEvent | AsyncErrorEvent;\n\n// ── Internal batch entry ───────────────────────────────────────────────\n\ninterface BatchEntry {\n\t/** The query key that just resolved (or errored). */\n\tqueryKey: string;\n\t/** The package that owns this data. */\n\tpackageId: string;\n\t/** AbortSignal for staleness detection. */\n\tsignal: AbortSignal;\n\t/** Whether this was an error resolution. */\n\tisError: boolean;\n\t/** Error if isError. */\n\terror?: Error;\n}\n\n// ── Batcher ────────────────────────────────────────────────────────────\n\n/**\n * Micro-batches async resolution completions into a single DAG walk + re-evaluation pass.\n *\n * When multiple promises resolve within the same event-loop tick (e.g., 3 currency\n * rates: USD→GBP, USD→EUR, USD→JPY all return within 2ms), this batcher collapses\n * them into ONE DAG walk and ONE re-execution pass instead of 3 separate ones.\n *\n * Lifecycle:\n * - Engine calls `add()` after each `resolveAsync()` completes\n * - `queueMicrotask()` schedules `flush()` for the end of the current tick\n * - `flush()` deduplicates queryKeys, walks DAG once for all resolved keys,\n * topologically sorts affected lines, re-executes, and fires listener events\n *\n * Perf: For N resolutions in a tick, reduces DAG walks from N to 1 and\n * re-executions from N*avgAffected to totalAffected.\n *\n * ## Streaming Architecture\n *\t * Events are published to a native {@link ReadableStream}. Stream-based\n\t * consumers read from the stream via `getReader()`, gaining built-in\n\t * cancellation (`reader.cancel()`), proper resource cleanup\n\t * (`reader.releaseLock()`), and the ability to\n\t * `pipeTo()` / `pipeThrough()` / `tee()` the event flow.\n *\n * The stream uses a configurable {@link CountQueuingStrategy} with a default\n * `highWaterMark` of 64 events to limit the internal buffer size.\n */\nexport class AsyncResolutionBatcher {\n\tprivate pending: BatchEntry[] = [];\n\tprivate scheduled = false;\n\t/** Set to true by clearPending(), flush() checks this to abort stale work. */\n\tprivate cleared = false;\n\n\tprivate dag: DependencyGraph;\n\tprivate lineCache: LineCache;\n\tprivate vm: VM;\n\n\t/**\n\t * Worker pool for offloading VM re-execution when the affected line\n\t * count exceeds WORKER_OFFLOAD_THRESHOLD (50). Lazily created on\n\t * first dispatch; cleared on clearAll().\n\t */\n\tprivate executionPool: ExecutionPool | null = null;\n\n\t/**\n\t * Number of flushes actually dispatched to the worker pool (as opposed\n\t * to falling back to the main thread because Worker is unavailable).\n\t * Exposed via {@link workerOffloadCount} for the Workers diagnostic tab.\n\t */\n\tprivate workerOffloadDispatchCount = 0;\n\n\t// ── Web Streams API integration ──────────────────────────────────\n\n\t/**\n\t * Default high-water mark for the internal event stream.\n\t * Limits the internal buffer size before the stream signals to\n\t * consumers that they need to catch up.\n\t */\n\tprivate static readonly DEFAULT_HIGH_WATER_MARK = 64;\n\n\t/**\n\t * Internal {@link ReadableStream} for async resolution events.\n\t * All events (lines-updated and error) are enqueued here.\n\t */\n\tprivate _eventStream: ReadableStream<AsyncResolutionEvent>;\n\n\t/**\n\t * Controller for the internal event stream. Set during stream\n\t * initialization; cleared on stream cancellation or clearAll().\n\t */\n\tprivate _streamController: ReadableStreamDefaultController<AsyncResolutionEvent> | null = null;\n\n\t/**\n\t * Test-only synchronous capture array. When enabled (non-null), every\n\t * event is synchronously pushed here in addition to the stream.\n\t * Tests read from this array to avoid async stream reader timing issues.\n\t */\n\tpublic _testCaptures: AsyncResolutionEvent[] | null = null;\n\n\t/**\n\t * Called for each line whose result is patched after an async resolution,\n\t * on both the main-thread and worker-pool paths.\n\t *\n\t * **A host that displays async results must set this.** It is the only\n\t * mechanism that moves a resolved value out of the LineCache and into the\n\t * host's own document state. The engine cannot do it itself: it does not own\n\t * a document, the host does, and the batcher has no reference to one.\n\t *\n\t * Nullable rather than a constructor parameter because it is cleared by\n\t * `clearAll()` and re-wired on re-subscribe, so it cannot be readonly. That\n\t * makes it easy to miss, which is why {@link warnIfUnwired} exists: leaving\n\t * it unset means async values resolve into the cache and are never shown,\n\t * with nothing to indicate why. A host that genuinely does not want async\n\t * results should not register async resolvers at all.\n\t */\n\tonLineResult: ((lineNumber: number, value: Value) => void) | null = null;\n\n\t/**\n\t * Whether {@link warnIfUnwired} has already fired.\n\t *\n\t * Once per instance, not once per resolution. A document with fifty live\n\t * data lines would otherwise produce fifty identical warnings on the first\n\t * fetch, which is how a useful warning becomes noise people filter out.\n\t */\n\tprivate warnedAboutMissingHook = false;\n\n\t/**\n\t * Warn once if an async result resolved with no {@link onLineResult} wired.\n\t *\n\t * The failure this catches is silent by nature: the value arrives, the cache\n\t * updates, and the line keeps showing pending forever. Without this a host\n\t * author has no thread to pull on.\n\t */\n\tprivate warnIfUnwired(): void {\n\t\tif (this.onLineResult || this.warnedAboutMissingHook) return;\n\t\tthis.warnedAboutMissingHook = true;\n\t\tconsole.warn(\n\t\t\t\"[solve-engine] An async result resolved but AsyncResolutionBatcher.onLineResult \" +\n\t\t\t\"is not set, so the value cannot reach your document and the line will keep \" +\n\t\t\t\"showing as pending. Set it to mirror resolved values into your own state. \" +\n\t\t\t\"This warning appears once per batcher.\",\n\t\t);\n\t}\n\n\t/** High-water mark used when (re)creating the event stream. */\n\tprivate readonly highWaterMark: number;\n\n\tconstructor(\n\t\tdag: DependencyGraph,\n\t\tlineCache: LineCache,\n\t\tvm: VM,\n\t\thighWaterMark: number = AsyncResolutionBatcher.DEFAULT_HIGH_WATER_MARK,\n\t) {\n\t\tthis.dag = dag;\n\t\tthis.lineCache = lineCache;\n\t\tthis.vm = vm;\n\t\tthis.highWaterMark = highWaterMark;\n\n\t\tthis._eventStream = this.createEventStream();\n\t}\n\n\t/**\n\t * Create a fresh internal event stream and wire its controller.\n\t * Called from the constructor and again from clearAll() so the batcher\n\t * keeps emitting events after an engine clear, the engine instance\n\t * (and this batcher) live on across clear() calls.\n\t */\n\tprivate createEventStream(): ReadableStream<AsyncResolutionEvent> {\n\t\treturn new ReadableStream<AsyncResolutionEvent>({\n\t\t\tstart: (controller) => {\n\t\t\t\tthis._streamController = controller;\n\t\t\t},\n\t\t\tcancel: () => {\n\t\t\t\tthis._streamController = null;\n\t\t\t},\n\t\t}, new CountQueuingStrategy({ highWaterMark: this.highWaterMark }));\n\t}\n\n\t// ── Public API ────────────────────────────────────────────────────\n\n\t/**\n\t * Add a resolved query key to the pending batch.\n\t *\n\t * Called by ExpressionEngine.resolveAsync() after a promise resolves or errors.\n\t * If this is the first entry in the current tick, schedules a microtask flush.\n\t */\n\tadd(entry: BatchEntry): void {\n\t\t// Re-arm after engine clear (clearAll sets cleared=true).\n\t\tthis.cleared = false;\n\n\t\t// Deduplicate: if the same (packageId:queryKey) is already in the batch, skip.\n\t\t// This handles the case where the same data source is resolved multiple times\n\t\t// (e.g., fetch → error → retry) within the same tick.\n\t\tfor (const existing of this.pending) {\n\t\t\tif (existing.packageId === entry.packageId && existing.queryKey === entry.queryKey) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\tthis.pending.push(entry);\n\n\t\tif (!this.scheduled) {\n\t\t\tthis.scheduled = true;\n\t\t\t// Hard backstop, deliberately redundant with reExecuteMainThread()'s\n\t\t\t// own per-line try/catch: this runs inside a bare queueMicrotask\n\t\t\t// callback, which has no caller able to catch anything that escapes\n\t\t\t// it, an uncaught throw here becomes an uncaughtException that can\n\t\t\t// crash the host process. flush() is expected to never throw past\n\t\t\t// its own internal per-line containment, but \"expected to never\" is\n\t\t\t// exactly the assumption that was silently wrong before this pass\n\t\t\t// (see reExecuteMainThread()'s doc comment). This exists so a\n\t\t\t// FUTURE regression in flush()'s own control flow (topologicalSort(),\n\t\t\t// the DAG walk, an error-listener notification) degrades to a\n\t\t\t// logged, contained failure instead of a repeat of that bug.\n\t\t\tqueueMicrotask(() => {\n\t\t\t\ttry {\n\t\t\t\t\tthis.flush();\n\t\t\t\t} catch (e) {\n\t\t\t\t\tconst engineError = normalizeUnknownError(e);\n\t\t\t\t\tconsole.error(`[AsyncResolutionBatcher] flush() failed unexpectedly — this should never happen; please report: ${engineError.format()}`);\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t}\n\n\t/**\n\t * Get the native event stream for stream-based consumers.\n\t *\n\t * Use this for backpressure, cancellation, or the ability\n\t * to `pipeTo()` / `pipeThrough()` the event flow.\n\t *\n\t * @returns A {@link ReadableStream} that emits {@link AsyncResolutionEvent}\n\t * items as the batcher processes async resolutions.\n\t */\n\tgetEventStream(): ReadableStream<AsyncResolutionEvent> {\n\t\treturn this._eventStream;\n\t}\n\n\t/** Number of resolutions currently queued for the next flush. */\n\tget pendingCount(): number {\n\t\treturn this.pending.length;\n\t}\n\n\t/** Number of pending entries collapsed by (packageId, queryKey) deduplication. */\n\tget dedupCount(): number {\n\t\tconst dedup = new Set<string>();\n\t\tfor (const entry of this.pending) {\n\t\t\tdedup.add(`${entry.packageId}:${entry.queryKey}`);\n\t\t}\n\t\treturn Math.max(0, this.pending.length - dedup.size);\n\t}\n\n\t/**\n\t * Whether the internal event stream currently has an active reader.\n\t * `1` if a consumer has called `getEventStream().getReader()` (or\n\t * otherwise locked the stream) and not released it, `0` otherwise.\n\t */\n\tget listenerCount(): number {\n\t\treturn this._eventStream.locked ? 1 : 0;\n\t}\n\n\t/** Number of flushes that were actually dispatched to the worker pool. */\n\tget workerOffloadCount(): number {\n\t\treturn this.workerOffloadDispatchCount;\n\t}\n\n\t/** Remove all listeners and cancel pending batch. Called on engine clear. */\n\tclearAll(): void {\n\t\tthis.pending = [];\n\t\tthis.scheduled = false;\n\t\tthis.cleared = true;\n\n\t\t// Clear test capture to match stream-close semantics, after\n\t\t// clearAll(), no further events reach old subscribers.\n\t\tthis._testCaptures = null;\n\t\tthis.onLineResult = null;\n\n\t\t// Close the old stream gracefully so existing consumers get a clean\n\t\t// done signal, then create a fresh stream. The engine instance (and\n\t\t// this batcher) survive clear(), so getEventStream() must keep\n\t\t// returning a live stream for new subscribers.\n\t\ttry {\n\t\t\tthis._streamController?.close();\n\t\t} catch {\n\t\t\t// Controller may already be closed or errored.\n\t\t}\n\t\tthis._streamController = null;\n\t\tthis._eventStream = this.createEventStream();\n\n\t\tif (this.executionPool) {\n\t\t\tthis.executionPool.clear();\n\t\t\tthis.executionPool = null;\n\t\t}\n\n\t\tthis.workerOffloadDispatchCount = 0;\n\t}\n\n\t// ── Private: flush ────────────────────────────────────────────────\n\n\t/**\n\t * Flush all pending resolutions in a single batched pass.\n\t *\n\t * Called automatically via queueMicrotask. Never called directly.\n\t */\n\tprivate flush(): void {\n\t\tthis.scheduled = false;\n\t\tif (this.cleared) return; // Engine was cleared — abort stale flush\n\t\tif (this.pending.length === 0) return;\n\n\t\t// Take ownership of the pending array (swap with empty).\n\t\tconst batch = this.pending;\n\t\tthis.pending = [];\n\n\t\t// Deduplicate by (packageId, queryKey), keep last entry per key.\n\t\tconst deduped = new Map<string, BatchEntry>();\n\t\tfor (const entry of batch) {\n\t\t\tconst compositeKey = `${entry.packageId}:${entry.queryKey}`;\n\t\t\tdeduped.set(compositeKey, entry);\n\t\t}\n\n\t\t// Step 1: Separate errors from successes, but re-evaluate for BOTH.\n\t\t// Error entries must also trigger DAG re-evaluation so downstream\n\t\t// lines can pick up the Error Value from AsyncResultCache.\n\t\tconst errorEntries: BatchEntry[] = [];\n\t\tconst okEntries: BatchEntry[] = [];\n\t\tfor (const entry of deduped.values()) {\n\t\t\tif (entry.isError) {\n\t\t\t\terrorEntries.push(entry);\n\t\t\t} else {\n\t\t\t\tokEntries.push(entry);\n\t\t\t}\n\t\t}\n\n\t\t// Notify error listeners first (before re-evaluation).\n\t\tfor (const entry of errorEntries) {\n\t\t\tif (entry.signal.aborted) continue;\n\t\t\tthis.notifyListeners({\n\t\t\t\ttype: \"error\",\n\t\t\t\tqueryKey: entry.queryKey,\n\t\t\t\tpackageId: entry.packageId,\n\t\t\t\terror: entry.error ?? new Error(\"Unknown async resolution error\"),\n\t\t\t});\n\t\t}\n\n\t\t// Step 2: Single DAG walk, collect ALL affected lines from ALL resolved\n\t\t// queryKeys (both success AND error). Errors also need re-evaluation so\n\t\t// downstream lines can receive errorValue() results.\n\t\tconst allAffected = new Set<number>();\n\t\tconst allQueryKeys: string[] = [];\n\n\t\tconst allEntries = [...okEntries, ...errorEntries];\n\t\tfor (const entry of allEntries) {\n\t\t\tif (entry.signal.aborted) continue;\n\t\t\tallQueryKeys.push(entry.queryKey);\n\n\t\t\tconst affected = this.dag.getAffectedLinesByDataSource(\n\t\t\t\tentry.packageId,\n\t\t\t\t[entry.queryKey],\n\t\t\t);\n\t\t\tfor (const line of affected) {\n\t\t\t\tallAffected.add(line);\n\t\t\t}\n\t\t}\n\n\t\tif (allAffected.size === 0) {\n\t\t\t// No lines affected, still notify listeners so UI can update\n\t\t\t// (e.g., clear loading indicators).\n\t\t\tthis.notifyListeners({\n\t\t\t\ttype: \"lines-updated\",\n\t\t\t\tlineNumbers: [],\n\t\t\t\taffectedQueryKeys: allQueryKeys,\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\n\t\t// Step 3: Topological sort affected lines.\n\t\t// We need to re-evaluate in dependency order so that variable producers\n\t\t// execute before their consumers. We use getAffectedLinesInOrder() but\n\t\t// that requires a starting variable. Instead, we do our own Kahn's algo\n\t\t// on the subgraph of affected lines.\n\t\tconst ordered = this.topologicalSort(Array.from(allAffected));\n\n\t\t// Step 4: Re-execute all affected lines.\n\t\t// For ≤50 lines: main-thread synchronous loop (fast, no worker overhead).\n\t\t// For >50 lines: offload to worker pool to avoid UI freeze.\n\t\tif (ordered.length > WORKER_OFFLOAD_THRESHOLD) {\n\t\t\t// Build a Map for fast entry lookup in the worker dispatch path.\n\t\t\tconst entryMap = new Map<number, ReturnType<LineCache[\"getEntryForLine\"]>>();\n\t\t\tfor (const lineNumber of ordered) {\n\t\t\t\tentryMap.set(lineNumber, this.lineCache.getEntryForLine(lineNumber));\n\t\t\t}\n\t\t\t// .catch() is required, not optional: reExecuteViaWorkerPool() is an\n\t\t\t// async method dispatched with `void` (fire-and-forget), without a\n\t\t\t// handler here, a rejection (a worker crash, `executionPool.executeBatch`\n\t\t\t// throwing) becomes an unhandled promise rejection, the async\n\t\t\t// equivalent of the uncaught-exception risk `add()`'s queueMicrotask\n\t\t\t// backstop guards against for the synchronous path.\n\t\t\tvoid this.reExecuteViaWorkerPool(ordered, entryMap, allQueryKeys).catch((e) => {\n\t\t\t\tconst engineError = normalizeUnknownError(e);\n\t\t\t\tconsole.error(`[AsyncResolutionBatcher] reExecuteViaWorkerPool() failed unexpectedly: ${engineError.format()}`);\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\n\t\tthis.reExecuteMainThread(ordered, allQueryKeys);\n\t}\n\n\t// ── Private: topological sort ─────────────────────────────────────\n\n\t/**\n\t * Topologically sort affected lines using Kahn's algorithm.\n\t *\n\t * Lines that produce variables come before lines that consume them.\n\t * This ensures correct evaluation order when multiple interdependent\n\t * lines are affected by async resolution.\n\t */\n\tprivate topologicalSort(lines: number[]): number[] {\n\t\tif (lines.length <= 1) return lines;\n\n\t\t// Build in-degree map and producer lookup.\n\t\tconst inDegree = new Map<number, number>();\n\t\tconst adjacency = new Map<number, number[]>();\n\n\t\t// Variable → producing line number (within affected set).\n\t\tconst producerOf = new Map<string, number>();\n\n\t\tfor (const line of lines) {\n\t\t\tinDegree.set(line, 0);\n\t\t\tadjacency.set(line, []);\n\t\t}\n\n\t\t// First pass: identify which variables are produced by which affected lines.\n\t\tfor (const line of lines) {\n\t\t\tconst writes = this.dag.getWrites(line);\n\t\t\tfor (const w of writes) {\n\t\t\t\tproducerOf.set(w, line);\n\t\t\t}\n\t\t}\n\n\t\t// Second pass: build edges from producer → consumer.\n\t\tfor (const line of lines) {\n\t\t\tconst reads = this.dag.getDependencies(line);\n\t\t\tfor (const readVar of reads) {\n\t\t\t\tconst producer = producerOf.get(readVar);\n\t\t\t\tif (producer !== undefined && producer !== line) {\n\t\t\t\t\tadjacency.get(producer)!.push(line);\n\t\t\t\t\tinDegree.set(line, (inDegree.get(line) ?? 0) + 1);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Kahn's algorithm.\n\t\tconst queue: number[] = [];\n\t\tfor (const [line, degree] of inDegree) {\n\t\t\tif (degree === 0) queue.push(line);\n\t\t}\n\n\t\t// Fallback: if all lines have dependencies (cycles), sort by line number.\n\t\tif (queue.length === 0 && lines.length > 0) {\n\t\t\treturn [...lines].sort((a, b) => a - b);\n\t\t}\n\n\t\tconst ordered: number[] = [];\n\t\twhile (queue.length > 0) {\n\t\t\tconst current = queue.shift()!;\n\t\t\tordered.push(current);\n\n\t\t\tfor (const downstream of adjacency.get(current) ?? []) {\n\t\t\t\tconst newDegree = (inDegree.get(downstream) ?? 1) - 1;\n\t\t\t\tinDegree.set(downstream, newDegree);\n\t\t\t\tif (newDegree === 0) queue.push(downstream);\n\t\t\t}\n\t\t}\n\n\t\t// Append unresolvable lines (cycles).\n\t\tif (ordered.length < lines.length) {\n\t\t\tconst remaining = lines\n\t\t\t\t.filter((l) => !ordered.includes(l))\n\t\t\t\t.sort((a, b) => a - b);\n\t\t\tordered.push(...remaining);\n\t\t}\n\n\t\treturn ordered;\n\t}\n\n\t// ── Private: worker-pool re-execution ─────────────────────────────\n\n\t/**\n\t * Offload VM re-execution to the worker pool for large batches.\n\t *\n\t * Called when ordered.length > WORKER_OFFLOAD_THRESHOLD (50).\n\t * Clones bytecode ArrayBuffers, dispatches to workers, and asynchronously\n\t * patches results back into LineCache before notifying listeners.\n\t *\n\t * Handles pending results: lines that return { type: 'pending' } from the\n\t * worker are NOT marked as updated, the engine's resolveAsync will handle\n\t * them when the async resolver completes.\n\t *\n\t * Safety: checks this.cleared before applying results, if the engine was\n\t * cleared while the worker batch was in-flight, results are discarded.\n\t */\n\tprivate async reExecuteViaWorkerPool(\n\t\tordered: number[],\n\t\tentryMap: Map<number, ReturnType<LineCache[\"getEntryForLine\"]>>,\n\t\tallQueryKeys: string[],\n\t): Promise<void> {\n\t\t// Lazily create the pool on first use.\n\t\tif (!this.executionPool) {\n\t\t\tthis.executionPool = new ExecutionPool();\n\t\t}\n\n\t\tconst results = this.executionPool.executeBatch(ordered, entryMap);\n\n\t\t// If workers are unavailable (Node.js, SSR, test env without jsdom\n\t\t// worker support), executeBatch returns undefined. Fall back to\n\t\t// main-thread execution.\n\t\tif (!results) {\n\t\t\tthis.reExecuteMainThread(ordered, allQueryKeys, entryMap);\n\t\t\treturn;\n\t\t}\n\n\t\tthis.workerOffloadDispatchCount++;\n\n\t\t// Await worker results.\n\t\tconst workerResults = await results;\n\n\t\t// Guard: if engine was cleared while the worker batch was in-flight,\n\t\t// discard results, the LineCache/DAG are stale.\n\t\tif (this.cleared) return;\n\n\t\t// Patch results back into LineCache.\n\t\tconst updatedLineNumbers: number[] = [];\n\t\tfor (const wr of workerResults) {\n\t\t\tconst entry = entryMap.get(wr.lineNumber);\n\t\t\tif (!entry) continue;\n\n\t\t\tif (wr.isPending) {\n\t\t\t\t// Don't mark as updated, will be resolved in a future batch.\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// Reconstruct Value from serialized result.\n\t\t\tconst value = reconstructValue(wr);\n\t\t\tentry.result = value;\n\t\t\tthis.warnIfUnwired();\n\t\t\tthis.onLineResult?.(wr.lineNumber, value);\n\t\t\tupdatedLineNumbers.push(wr.lineNumber);\n\t\t}\n\n\t\t// Notify listeners (only if not cleared during await).\n\t\tif (this.cleared) return;\n\t\tif (updatedLineNumbers.length > 0 || allQueryKeys.length > 0) {\n\t\t\tthis.notifyListeners({\n\t\t\t\ttype: \"lines-updated\",\n\t\t\t\tlineNumbers: updatedLineNumbers,\n\t\t\t\taffectedQueryKeys: allQueryKeys,\n\t\t\t});\n\t\t}\n\t}\n\n\t// ── Private: main-thread re-execution ────────────────────────────\n\n\t/**\n\t * Execute ordered lines on the main thread, update LineCache, and notify\n\t * listeners. Returns the list of line numbers that actually changed.\n\t *\n\t * Used by both flush() (≤50 lines) and reExecuteViaWorkerPool() (fallback\n\t * when workers are unavailable). Extracted to avoid code duplication.\n\t *\n\t * **Per-line containment (fatal-bug fix)**: `executeBytecode()` used to\n\t * run here with NO try/catch anywhere in this method's call chain, and\n\t * this whole batch runs inside a bare `queueMicrotask` (see `add()`) with\n\t * no surrounding try/catch at any caller either, so if any ONE line's\n\t * cached bytecode threw (a stack/instruction-limit error, an undefined\n\t * variable, a corrupted-bytecode `TypeError`), the `for` loop aborted\n\t * immediately: every line scheduled AFTER the failure in this batch was\n\t * silently never re-executed or notified even though nothing was wrong\n\t * with them, every line BEFORE it had already had its `entry.result`\n\t * mutated in-place but `notifyListeners()` was never reached (a silent\n\t * `LineCache`/host desync), and, because a bare `queueMicrotask`\n\t * callback has no caller to catch it, the exception was uncatchable:\n\t * an `uncaughtException` that could crash the host process outright.\n\t * (`__tests__/async/AsyncResolutionBatcher.spec.ts`'s topological-sort\n\t * describe block used to have a test skipped specifically because of\n\t * this. See that file, now un-skipped and rewritten.) Each line's\n\t * execution is now its own try/catch: a failure is recorded as an\n\t * `Error` `Value` for THAT line (still counted as \"updated\" so the host\n\t * learns about it and stops showing a stale Pending state) and the loop\n\t * continues, one line's failure can no longer take out its neighbors.\n\t */\n\tprivate reExecuteMainThread(\n\t\tordered: number[],\n\t\tallQueryKeys: string[],\n\t\tentryMap?: Map<number, LineCacheEntry | undefined>,\n\t): number[] {\n\t\tconst updatedLineNumbers: number[] = [];\n\n\t\tfor (const lineNumber of ordered) {\n\t\t\tconst entry = entryMap\n\t\t\t\t? entryMap.get(lineNumber)\n\t\t\t\t: this.lineCache.getEntryForLine(lineNumber);\n\t\t\tif (!entry || entry.bytecode.opcodes.length === 0) continue;\n\n\t\t\t// Do NOT reset the VM here: reset() clears the variable table, which\n\t\t\t// would wipe values produced by earlier lines in this topologically\n\t\t\t// ordered batch (and by unaffected lines outside it). Instead, mirror\n\t\t\t// the engine's execution pattern: snapshot the stack depth and pop\n\t\t\t// back to it after execution.\n\t\t\tconst stackBefore = this.vm.getStack().length;\n\t\t\ttry {\n\t\t\t\tconst result = executeBytecode(entry.bytecode, this.vm);\n\t\t\t\twhile (this.vm.getStack().length > stackBefore) {\n\t\t\t\t\tthis.vm.pop();\n\t\t\t\t}\n\n\t\t\t\tif (result.type === \"value\") {\n\t\t\t\t\tentry.result = result.value;\n\t\t\t\t\tthis.warnIfUnwired();\n\t\t\t\t\tthis.onLineResult?.(lineNumber, result.value);\n\t\t\t\t\tupdatedLineNumbers.push(lineNumber);\n\t\t\t\t} else if (result.type === \"error\") {\n\t\t\t\t\t// executeBytecode() reports controlled failures (undefined\n\t\t\t\t\t// variable, stack/instruction limits, a plugin throw) as this\n\t\t\t\t\t// {type:'error'} return value now, not a thrown exception, the\n\t\t\t\t\t// catch block below only remains as a backstop for whatever\n\t\t\t\t\t// still throws outside that contract (e.g. a bug in the\n\t\t\t\t\t// stack-cleanup loop itself). Without this branch, a VM-level\n\t\t\t\t\t// error here fell through both the \"value\" and \"pending\" cases\n\t\t\t\t\t// silently: no entry.result update, no onLineResult, not counted\n\t\t\t\t\t// in updatedLineNumbers, the same class of silent-drop bug this\n\t\t\t\t\t// method's containment fix exists to prevent, just moved one\n\t\t\t\t\t// level up from \"uncaught exception\" to \"unhandled Result arm\".\n\t\t\t\t\tconst value = errorValue(result.error.code, result.error.message);\n\t\t\t\t\tentry.result = value;\n\t\t\t\t\tthis.warnIfUnwired();\n\t\t\t\t\tthis.warnIfUnwired();\n\t\t\t\tthis.onLineResult?.(lineNumber, value);\n\t\t\t\t\tupdatedLineNumbers.push(lineNumber);\n\t\t\t\t}\n\t\t\t\t// If still pending, don't mark as updated, will be handled by the\n\t\t\t\t// next resolution batch.\n\t\t\t} catch (e) {\n\t\t\t\t// Restore the stack to its pre-execution depth even on failure\n\t\t\t\t// a partially-executed opcode sequence may have pushed values it\n\t\t\t\t// never got to pop, and leaving them would corrupt every\n\t\t\t\t// subsequent line's execution in this same shared VM.\n\t\t\t\twhile (this.vm.getStack().length > stackBefore) {\n\t\t\t\t\tthis.vm.pop();\n\t\t\t\t}\n\t\t\t\tconst engineError = normalizeUnknownError(e);\n\t\t\t\tconst value = errorValue(engineError.code, engineError.message);\n\t\t\t\tentry.result = value;\n\t\t\t\tthis.warnIfUnwired();\n\t\t\t\tthis.onLineResult?.(lineNumber, value);\n\t\t\t\tupdatedLineNumbers.push(lineNumber);\n\t\t\t}\n\t\t}\n\n\t\t// Notify listeners of updated lines.\n\t\tif (updatedLineNumbers.length > 0 || allQueryKeys.length > 0) {\n\t\t\tthis.notifyListeners({\n\t\t\t\ttype: \"lines-updated\",\n\t\t\t\tlineNumbers: updatedLineNumbers,\n\t\t\t\taffectedQueryKeys: allQueryKeys,\n\t\t\t});\n\t\t}\n\n\t\treturn updatedLineNumbers;\n\t}\n\n\t/**\n\t * Notify all consumers of an async resolution event.\n\t *\n\t * Enqueues the event into the internal {@link ReadableStream}.\n\t * If the stream has been closed or errored (consumer cancelled),\n\t * the enqueue silently fails (caught by try/catch).\n\t */\n\tprivate notifyListeners(event: AsyncResolutionEvent): void {\n\t\t// Test capture, synchronous, no timing issues (enabled only in tests).\n\t\tif (this._testCaptures) {\n\t\t\tthis._testCaptures.push(event);\n\t\t}\n\n\t\tif (this._streamController) {\n\t\t\ttry {\n\t\t\t\tthis._streamController.enqueue(event);\n\t\t\t} catch {\n\t\t\t\t// Stream closed or errored, consumer may have cancelled.\n\t\t\t}\n\t\t}\n\t}\n}\n"]}
|