solve-engine 2.38.15 → 2.38.17

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.
Files changed (86) hide show
  1. package/dist/{PackageCompatibility-C-3vPMKp.d.cts → PackageCompatibility-DFpkrlUp.d.cts} +1 -1
  2. package/dist/{PackageCompatibility-zdsKvwQI.d.ts → PackageCompatibility-DwZ8-NYu.d.ts} +1 -1
  3. package/dist/{PackageRegistry-CStmqgw_.d.ts → PackageRegistry-BF6WA6w6.d.ts} +97 -1
  4. package/dist/{PackageRegistry-DiHxyxrn.d.cts → PackageRegistry-bOwZZ3Co.d.cts} +97 -1
  5. package/dist/{VMBuiltins-BwqFO2TY.d.cts → VMBuiltins-8xIW2gTv.d.cts} +13 -2
  6. package/dist/{VMBuiltins-h09nijID.d.ts → VMBuiltins-ChJ7Joj0.d.ts} +13 -2
  7. package/dist/{chunk-44BWHZ5V.js → chunk-2YHOWQ43.js} +2 -2
  8. package/dist/chunk-2YHOWQ43.js.map +1 -0
  9. package/dist/{chunk-IUCUBHFW.js → chunk-3A3GT46U.js} +2 -2
  10. package/dist/{chunk-IUCUBHFW.js.map → chunk-3A3GT46U.js.map} +1 -1
  11. package/dist/chunk-3ZLMMX25.js +2 -0
  12. package/dist/{chunk-ZXNM355C.js.map → chunk-3ZLMMX25.js.map} +1 -1
  13. package/dist/chunk-4BNV5KTW.cjs +5 -0
  14. package/dist/chunk-4BNV5KTW.cjs.map +1 -0
  15. package/dist/{chunk-HFES6BF5.cjs → chunk-K2OUNZZG.cjs} +2 -2
  16. package/dist/chunk-K2OUNZZG.cjs.map +1 -0
  17. package/dist/chunk-KE6SELT2.js +3 -0
  18. package/dist/{chunk-4LMPCB2V.js.map → chunk-KE6SELT2.js.map} +1 -1
  19. package/dist/{chunk-KVONXXPJ.cjs → chunk-KEUEXSHE.cjs} +3 -3
  20. package/dist/{chunk-KVONXXPJ.cjs.map → chunk-KEUEXSHE.cjs.map} +1 -1
  21. package/dist/{chunk-BIV4K7B2.js → chunk-KEZIXLRU.js} +2 -2
  22. package/dist/{chunk-BIV4K7B2.js.map → chunk-KEZIXLRU.js.map} +1 -1
  23. package/dist/chunk-MLYKA4XG.js +3 -0
  24. package/dist/chunk-MLYKA4XG.js.map +1 -0
  25. package/dist/{chunk-DTOSRC6E.cjs → chunk-NEK3QTWY.cjs} +2 -2
  26. package/dist/{chunk-DTOSRC6E.cjs.map → chunk-NEK3QTWY.cjs.map} +1 -1
  27. package/dist/chunk-PXHGWBUG.js +5 -0
  28. package/dist/chunk-PXHGWBUG.js.map +1 -0
  29. package/dist/{chunk-U54BIYXO.cjs → chunk-RKNUCZ6P.cjs} +2 -2
  30. package/dist/{chunk-U54BIYXO.cjs.map → chunk-RKNUCZ6P.cjs.map} +1 -1
  31. package/dist/{chunk-A3CNNRFM.cjs → chunk-T65HJSSB.cjs} +2 -2
  32. package/dist/{chunk-A3CNNRFM.cjs.map → chunk-T65HJSSB.cjs.map} +1 -1
  33. package/dist/chunk-TWXUJJVP.cjs +3 -0
  34. package/dist/chunk-TWXUJJVP.cjs.map +1 -0
  35. package/dist/chunk-WRKDFQXE.cjs +2 -0
  36. package/dist/chunk-WRKDFQXE.cjs.map +1 -0
  37. package/dist/chunk-XKUYR2ZK.js +2 -0
  38. package/dist/chunk-XKUYR2ZK.js.map +1 -0
  39. package/dist/constants.cjs +1 -1
  40. package/dist/constants.js +1 -1
  41. package/dist/engine.cjs +1 -1
  42. package/dist/engine.d.cts +42 -4
  43. package/dist/engine.d.ts +42 -4
  44. package/dist/engine.js +1 -1
  45. package/dist/engine.worker.cjs +1 -1
  46. package/dist/engine.worker.js +1 -1
  47. package/dist/engine.worker.js.map +1 -1
  48. package/dist/index.cjs +1 -1
  49. package/dist/index.d.cts +4 -4
  50. package/dist/index.d.ts +4 -4
  51. package/dist/index.js +1 -1
  52. package/dist/language.d.cts +3 -3
  53. package/dist/language.d.ts +3 -3
  54. package/dist/packages.cjs +1 -1
  55. package/dist/packages.d.cts +2 -2
  56. package/dist/packages.d.ts +2 -2
  57. package/dist/packages.js +1 -1
  58. package/dist/testing.cjs +2 -2
  59. package/dist/testing.d.cts +3 -3
  60. package/dist/testing.d.ts +3 -3
  61. package/dist/testing.js +1 -1
  62. package/dist/vm.cjs +1 -1
  63. package/dist/vm.d.cts +1 -1
  64. package/dist/vm.d.ts +1 -1
  65. package/dist/vm.js +1 -1
  66. package/dist/worker.cjs +2 -2
  67. package/dist/worker.d.cts +2 -2
  68. package/dist/worker.d.ts +2 -2
  69. package/dist/worker.js +1 -1
  70. package/package.json +1 -1
  71. package/dist/chunk-44BWHZ5V.js.map +0 -1
  72. package/dist/chunk-4LMPCB2V.js +0 -3
  73. package/dist/chunk-6ADFAXTZ.cjs +0 -2
  74. package/dist/chunk-6ADFAXTZ.cjs.map +0 -1
  75. package/dist/chunk-6UW4JJZV.cjs +0 -3
  76. package/dist/chunk-6UW4JJZV.cjs.map +0 -1
  77. package/dist/chunk-AFNK2LUO.js +0 -2
  78. package/dist/chunk-AFNK2LUO.js.map +0 -1
  79. package/dist/chunk-ENLFOXF3.js +0 -5
  80. package/dist/chunk-ENLFOXF3.js.map +0 -1
  81. package/dist/chunk-HFES6BF5.cjs.map +0 -1
  82. package/dist/chunk-ZGA7X625.cjs +0 -5
  83. package/dist/chunk-ZGA7X625.cjs.map +0 -1
  84. package/dist/chunk-ZXNM355C.js +0 -2
  85. package/dist/chunk-ZYXFJ4X2.js +0 -3
  86. package/dist/chunk-ZYXFJ4X2.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/packages/symbolic/parselets/ExpandParselet.ts","../src/packages/symbolic/parselets/FactorParselet.ts","../src/packages/symbolic/parselets/VariableArgument.ts","../src/packages/symbolic/parselets/SolveParselet.ts","../src/packages/symbolic/parselets/DerParselet.ts","../src/packages/symbolic/parselets/IntegralParselet.ts","../src/packages/symbolic/parselets/TaylorParselet.ts","../src/packages/symbolic/parselets/JacobianParselet.ts","../src/packages/symbolic/parselets/ImaginaryParselet.ts","../src/packages/symbolic/parselets/ConjParselet.ts","../src/packages/symbolic/parselets/ReParselet.ts","../src/packages/symbolic/parselets/ImParselet.ts","../src/packages/symbolic/parselets/CancelParselet.ts","../src/packages/symbolic/parselets/ApartParselet.ts","../src/packages/symbolic/normalizer/ImaginaryLiteralNormalizerRule.ts","../src/packages/symbolic/normalizer/SymbolicCallNormalizerRule.ts","../src/packages/symbolic/SymbolicPackage.ts","../src/packages/tags/TagScanner.ts","../src/packages/datetime/Iso8601.ts","../src/calendar/HostLocale.ts","../src/packages/datetime/DateReading.ts","../src/packages/datetime/normalizer/DateLiteralNormalizerRule.ts"],"names":["ExpandParselet","parser","_token","builder","BindingPower","FactorParselet","readVariableName","verb","token","ErrorFactory","emitVariableName","name","parseBoundExpression","inner","BytecodeBuilder","program","emitBoundExpression","index","SolveParselet","left","right","variable","DerParselet","expression","IntegralParselet","TaylorParselet","JacobianParselet","count","ImaginaryParselet","_parser","ConjParselet","ReParselet","ImParselet","CancelParselet","ApartParselet","imaginaryLiteralNormalizerRule","priority","tokens","pos","number","suffix","LexerToken","tokenTypeId","SYMBOLIC_WORD_TO_TOKEN_TYPE","symbolicCallNormalizerRule","tokenType","SYMBOLIC_FUNCTIONS","SYMBOLIC_PACKAGE","SYMBOLIC_TOKEN_TYPES","fn","containsSymbolicCall","tagEdgeKey","tag","edgeKey","escapeTag","AGGREGATE_OPENER","OPENER_WINDOW","ANY_TAG","withTagEdges","rawText","reads","writes","tags","tagEdgesOf","memberTagsOf","members","i","queries","firstContent","m","hashIndex","lineCarriesTag","re","ISO8601_PATTERN","parseIso8601","s","calendar","trimmed","ms","ISO8601_GRAIN_PATTERN","iso8601Grain","text","matched","offset","encodeFixedOffset","sign","digits","minutes","formatIso8601Local","epochMs","d","pad","n","year","month","day","hours","seconds","offsetMinutesTotal","absOffset","offsetHours","offsetMinutes","MS_TIMESTAMP_THRESHOLD","unixTimestampToEpochMs","PROBE_INSTANT","memoisedAgainst","trustworthy","orderByTag","currentIntl","freshenMemo","current","isTrustworthyIntl","probe","hostLocale","orderFromLocale","cached","resolved","probeOrder","parts","sequence","part","DatetimeErrorCodes","isLocaleTag","resolveDateOrderPolicy","date","requestedLocale","onAmbiguous","order","inferred","MONTH_NAMES","DAY_OR_MONTH_GROUP","FULL_YEAR_GROUP","classifyRun","g0","g1","g2","separator","shortFirst","shortMiddle","shortLast","resolveYearGroup","yy","isRealCalendarDay","daysInMonth","describeUnrealDay","spellDay","isoOf","rolesFor","orderInWords","separatorOrder","readNumericDate","run","shape","canFallThrough","refusing","notACalendarDay","shortYear","orderMismatchUnderYearFirst","chosen","other","chosenRoles","otherRoles","alternative","dayFirst","monthFirst","dayFirstReal","monthFirstReal","opening","sameDay","roles","which","sourceInWords","facts","spellIso","iso","composeReadingNote","refusal","note","completeDateReading","splitNumericRun","separated","dotted","DATETIME_LITERAL_TYPE","DATETIME_LITERAL_TYPE_ID","DATETIME_LITERAL_UNREADABLE_TYPE","DATETIME_LITERAL_UNREADABLE_TYPE_ID","PLAIN_INTEGER","DOT_DAY_MONTH","DOT_LEADING_YEAR","writtenAsOneRun","buildDateToken","sourceTokens","ruleName","built","first","t","fusedToken","runText","out","previousEnd","faultMatch","code","message","ISO_TIMESTAMP","ISO_TOKEN_TYPES","ISO_MAX_TOKENS","fuseIsoTimestamp","runEnd","window","next","consumed","covered","dateLiteralNormalizerRule","getInputOrder","getCalendar","DATE_CALENDAR","getOnAmbiguous","t0","t1","second","dotRun","dotReading","timestamp","sep1","sep2","t2","reading"],"mappings":"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","file":"chunk-U54BIYXO.cjs","sourcesContent":["import { PrefixParselet } from \"@solve-js/parser/Parselet\";\nimport { Parser } from \"@solve-js/parser/Parser\";\nimport { Token } from \"@solve-js/lexer/Token\";\nimport { BytecodeBuilder } from \"@solve-js/parser/BytecodeBuilder\";\nimport { OpCode } from \"@solve-js/parser/OpCode\";\nimport { BindingPower } from \"@solve-js/parser/BindingPower\";\nimport { SYMBOLIC_BUILTIN_EXPAND } from \"@solve-js/packages/symbolic/SymbolicBuiltinIndex\";\n\n/**\n * `expand(expr)`, multiplying out every product and power.\n *\n * A dedicated parselet rather than a `builtinNameToIndex` entry reached through\n * the ordinary `FunctionCallParselet`, because that route needs the lexer to\n * emit `FUNC` for the word, which means a `keywordMap` entry, which would stop\n * `expand` working as an ordinary variable name. See\n * `normalizer/SymbolicCallNormalizerRule.ts`.\n *\n * The emitted bytecode is an ordinary `CALL_BUILTIN`, so no new opcode and no\n * new VM dispatch arm is involved.\n */\nexport class ExpandParselet implements PrefixParselet {\n\treadonly category = \"Symbolic\";\n\n\tparse(parser: Parser, _token: Token, builder: BytecodeBuilder): void {\n\t\tparser.consume(\"LPAREN\");\n\t\tparser.parseExpression(BindingPower.Lowest, builder);\n\t\tparser.consume(\"RPAREN\");\n\n\t\tbuilder.emitOpcode(OpCode.CALL_BUILTIN);\n\t\tbuilder.emitIndex(SYMBOLIC_BUILTIN_EXPAND);\n\t\tbuilder.emitIndex(1);\n\t}\n}\n","import { PrefixParselet } from \"@solve-js/parser/Parselet\";\nimport { Parser } from \"@solve-js/parser/Parser\";\nimport { Token } from \"@solve-js/lexer/Token\";\nimport { BytecodeBuilder } from \"@solve-js/parser/BytecodeBuilder\";\nimport { OpCode } from \"@solve-js/parser/OpCode\";\nimport { BindingPower } from \"@solve-js/parser/BindingPower\";\nimport { SYMBOLIC_BUILTIN_FACTOR } from \"@solve-js/packages/symbolic/SymbolicBuiltinIndex\";\n\n/**\n * `factor(expr)`, writing a polynomial as a product of irreducible factors over the rationals.\n *\n * A dedicated parselet rather than a `builtinNameToIndex` entry reached through\n * the ordinary `FunctionCallParselet`, because that route needs the lexer to\n * emit `FUNC` for the word, which means a `keywordMap` entry, which would stop\n * `expand` working as an ordinary variable name. See\n * `normalizer/SymbolicCallNormalizerRule.ts`.\n *\n * The emitted bytecode is an ordinary `CALL_BUILTIN`, so no new opcode and no\n * new VM dispatch arm is involved.\n */\nexport class FactorParselet implements PrefixParselet {\n\treadonly category = \"Symbolic\";\n\n\tparse(parser: Parser, _token: Token, builder: BytecodeBuilder): void {\n\t\tparser.consume(\"LPAREN\");\n\t\tparser.parseExpression(BindingPower.Lowest, builder);\n\t\tparser.consume(\"RPAREN\");\n\n\t\tbuilder.emitOpcode(OpCode.CALL_BUILTIN);\n\t\tbuilder.emitIndex(SYMBOLIC_BUILTIN_FACTOR);\n\t\tbuilder.emitIndex(1);\n\t}\n}\n","import { Parser } from \"@solve-js/parser/Parser\";\nimport { BytecodeBuilder, type BytecodeProgram } from \"@solve-js/parser/BytecodeBuilder\";\nimport { OpCode } from \"@solve-js/parser/OpCode\";\nimport { BindingPower } from \"@solve-js/parser/BindingPower\";\nimport { ErrorFactory } from \"@solve-js/errors/UnifiedErrorFramework\";\n\n/**\n * Reads a bare variable name argument and returns it, consuming the token.\n *\n * Shared by every algebra verb that takes \"which unknown\" as an argument.\n * Compiling the name as an ordinary variable read would require it to already\n * have a value, which is precisely what differentiating or solving with respect\n * to it says it does not.\n *\n * Requiring `IDENT` or `UNIT` here gives the same reserved-word protection\n * `VariableParselet` relies on: a keyword always lexes as its own token type,\n * so it can never reach this position and be taken for a variable name.\n *\n * @param parser - The parser, positioned at the name.\n * @param verb - The calling verb's name, for the error message.\n * @returns The name as written.\n * @throws {EngineError} `SYMBOLIC_REQUIRES_VARIABLE_NAME` when the next token is\n * not a bare name.\n */\nexport function readVariableName(parser: Parser, verb: string): string {\n\tconst token = parser.peek();\n\tif (!token || (token.type !== \"IDENT\" && token.type !== \"UNIT\")) {\n\t\tthrow ErrorFactory.parsing(\n\t\t\t\"SYMBOLIC_REQUIRES_VARIABLE_NAME\",\n\t\t\t`${verb} needs the name of an unknown here, as in ${verb}(x^2, x).`,\n\t\t\t{ found: token?.type ?? \"end of input\" },\n\t\t);\n\t}\n\tparser.consume();\n\treturn token.value;\n}\n\n/** Emits an already-read unknown's name as the String argument the algebra builtins read it as. */\nexport function emitVariableName(builder: BytecodeBuilder, name: string): void {\n\tbuilder.emitOpcode(OpCode.PUSH_STRING);\n\tbuilder.emitString(name);\n}\n\n/**\n * Parses an algebra verb's expression argument into its own independent\n * program, rather than emitting it inline.\n *\n * The verb names its unknown AFTER the expression (`der(x^2, x)`), so the\n * expression has to be held rather than emitted: only once the name is known\n * can it be paired with {@link emitBoundExpression}, which is what makes the\n * name shadow any document value it happens to share. Compiled into an\n * isolated builder exactly like a user-defined function body or a map/reduce\n * transform, and `parseExpression` leaves `parser.builder` pointing at the\n * isolated one with no automatic restore, so the caller's builder is put back\n * before returning.\n *\n * @param parser - The parser, positioned at the start of the expression.\n * @param builder - The builder to restore afterwards.\n * @param verb - The calling verb's name, for the error message.\n * @returns The compiled expression, to be handed to {@link emitBoundExpression}.\n */\nexport function parseBoundExpression(parser: Parser, builder: BytecodeBuilder, verb: string): BytecodeProgram {\n\tconst inner = new BytecodeBuilder(builder.pluginIndexMap);\n\tparser.parseExpression(BindingPower.Lowest, inner);\n\tparser.setBuilder(builder);\n\tconst program = inner.build();\n\tif (program.hasAsync) {\n\t\t// Same v1 restriction every other deferred body carries (user-defined\n\t\t// functions, map/reduce transforms): a reentrant execution cannot\n\t\t// suspend and resume the outer expression around an async result.\n\t\tthrow ErrorFactory.parsing(\n\t\t\t\"SYMBOLIC_ARGUMENT_MUST_BE_SYNCHRONOUS\",\n\t\t\t`${verb}'s expression must be synchronous (no weather/stocks/currency calls).`,\n\t\t);\n\t}\n\treturn program;\n}\n\n/**\n * Emits a held expression so that it evaluates with `name` bound to itself.\n *\n * This is what makes `der(x^2, x)` mean the derivative of a square rather than\n * the derivative of a constant on a page that also says `:x = 5`. Naming `x` as\n * the verb's argument declares it bound, so within the expression it is an\n * unknown and nothing else, exactly the way a function's parameter shadows a\n * document variable of the same name inside its body. Before this, the\n * expression was compiled inline and its `x` was an ordinary variable read, so\n * the verb received 25 and answered 0 with no indication that it had not been\n * asked the question the user wrote.\n *\n * @param builder - The builder to emit into.\n * @param program - The expression, from {@link parseBoundExpression}.\n * @param name - The unknown the verb named, bound for the expression's evaluation.\n */\nexport function emitBoundExpression(builder: BytecodeBuilder, program: BytecodeProgram, name: string): void {\n\tconst index = builder.emitAnonymousBody([name], program);\n\tbuilder.emitOpcode(OpCode.BIND_UNKNOWN);\n\tbuilder.emitIndex(index);\n}\n","import { PrefixParselet } from \"@solve-js/parser/Parselet\";\nimport { Parser } from \"@solve-js/parser/Parser\";\nimport { Token } from \"@solve-js/lexer/Token\";\nimport { BytecodeBuilder } from \"@solve-js/parser/BytecodeBuilder\";\nimport { OpCode } from \"@solve-js/parser/OpCode\";\nimport { ErrorFactory } from \"@solve-js/errors/UnifiedErrorFramework\";\nimport { SYMBOLIC_BUILTIN_SOLVE } from \"@solve-js/packages/symbolic/SymbolicBuiltinIndex\";\nimport { emitVariableName, parseBoundExpression, emitBoundExpression } from \"@solve-js/packages/symbolic/parselets/VariableArgument\";\n\n/**\n * `solve(equation, variable)`, for example `solve(x^2-4=0, x)`.\n *\n * Two things here cannot go through the ordinary function-call grammar, which\n * is why this is a hand-written parselet.\n *\n * The first argument contains a bare `=`, which no infix parselet consumes, so\n * an ordinary argument list would fail to parse it. This reads the two sides\n * separately and lets a missing right-hand side default to zero, so\n * `solve(x^2-4, x)` means the same as `solve(x^2-4=0, x)`.\n *\n * The second argument is a *name*, not a value. Compiling it as a `LOAD_VAR`\n * would demand that the variable already exist, which is exactly what solving\n * for it says it does not. Emitting it as a `PUSH_STRING` instead means the\n * builtin receives a plain String value and the VM needs no change at all.\n *\n * Both sides of the equation are held until that name has been read, so each\n * evaluates with the unknown bound to itself rather than to whatever value the\n * document may already have given it. See {@link emitBoundExpression}: with\n * `:x = 5` above it, `solve(x^2-4=0, x)` was solving `21 = 0` and reporting,\n * accurately for the question it was asked and uselessly for the one written,\n * that there is no solution.\n */\nexport class SolveParselet implements PrefixParselet {\n\treadonly category = \"Symbolic\";\n\n\tparse(parser: Parser, _token: Token, builder: BytecodeBuilder): void {\n\t\tparser.consume(\"LPAREN\");\n\t\tconst left = parseBoundExpression(parser, builder, \"solve\");\n\t\tconst right = parser.match(\"EQUALS\") ? parseBoundExpression(parser, builder, \"solve\") : null;\n\n\t\tparser.consume(\"COMMA\");\n\t\t// Requiring IDENT or UNIT here is the same protection VariableParselet\n\t\t// relies on: a reserved word always lexes as its own token type, so it\n\t\t// can never reach this position and be mistaken for a variable name.\n\t\tconst variable = parser.peek();\n\t\tif (!variable || (variable.type !== \"IDENT\" && variable.type !== \"UNIT\")) {\n\t\t\tthrow ErrorFactory.parsing(\n\t\t\t\t\"SOLVE_REQUIRES_VARIABLE_NAME\",\n\t\t\t\t`solve's second argument must be the name of the unknown to solve for, as in solve(x^2-4=0, x).`,\n\t\t\t\t{ found: variable?.type ?? \"end of input\" },\n\t\t\t);\n\t\t}\n\t\tparser.consume();\n\n\t\temitBoundExpression(builder, left, variable.value);\n\t\tif (right) {\n\t\t\temitBoundExpression(builder, right, variable.value);\n\t\t} else {\n\t\t\t// No `=` written, so the equation is \"this expression equals zero\".\n\t\t\tbuilder.emitOpcode(OpCode.PUSH_NUMBER);\n\t\t\tbuilder.emitNumber(0);\n\t\t}\n\t\temitVariableName(builder, variable.value);\n\n\t\tparser.consume(\"RPAREN\");\n\n\t\tbuilder.emitOpcode(OpCode.CALL_BUILTIN);\n\t\tbuilder.emitIndex(SYMBOLIC_BUILTIN_SOLVE);\n\t\tbuilder.emitIndex(3);\n\t}\n}\n","import { PrefixParselet } from \"@solve-js/parser/Parselet\";\nimport { Parser } from \"@solve-js/parser/Parser\";\nimport { Token } from \"@solve-js/lexer/Token\";\nimport { BytecodeBuilder } from \"@solve-js/parser/BytecodeBuilder\";\nimport { OpCode } from \"@solve-js/parser/OpCode\";\nimport { BindingPower } from \"@solve-js/parser/BindingPower\";\nimport { SYMBOLIC_BUILTIN_DER } from \"@solve-js/packages/symbolic/SymbolicBuiltinIndex\";\nimport { readVariableName, emitVariableName, parseBoundExpression, emitBoundExpression } from \"@solve-js/packages/symbolic/parselets/VariableArgument\";\n\n/**\n * `der(expr, variable)` and `der(expr, variable, order)`, the symbolic\n * derivative. `derivative` is accepted as the same thing.\n *\n * The variable is emitted as a string rather than compiled as a variable read,\n * for the reason given in {@link readVariableName}, and `expr` is held until\n * that name is known so it can be evaluated with the name bound. See\n * {@link emitBoundExpression}.\n */\nexport class DerParselet implements PrefixParselet {\n\treadonly category = \"Symbolic\";\n\n\tparse(parser: Parser, _token: Token, builder: BytecodeBuilder): void {\n\t\tparser.consume(\"LPAREN\");\n\t\tconst expression = parseBoundExpression(parser, builder, \"der\");\n\t\tparser.consume(\"COMMA\");\n\t\tconst variable = readVariableName(parser, \"der\");\n\t\temitBoundExpression(builder, expression, variable);\n\t\temitVariableName(builder, variable);\n\n\t\t// The order is optional and defaults to a first derivative.\n\t\tif (parser.match(\"COMMA\")) {\n\t\t\tparser.parseExpression(BindingPower.Lowest, builder);\n\t\t} else {\n\t\t\tbuilder.emitOpcode(OpCode.PUSH_NUMBER);\n\t\t\tbuilder.emitNumber(1);\n\t\t}\n\t\tparser.consume(\"RPAREN\");\n\n\t\tbuilder.emitOpcode(OpCode.CALL_BUILTIN);\n\t\tbuilder.emitIndex(SYMBOLIC_BUILTIN_DER);\n\t\tbuilder.emitIndex(3);\n\t}\n}\n","import { PrefixParselet } from \"@solve-js/parser/Parselet\";\nimport { Parser } from \"@solve-js/parser/Parser\";\nimport { Token } from \"@solve-js/lexer/Token\";\nimport { BytecodeBuilder } from \"@solve-js/parser/BytecodeBuilder\";\nimport { OpCode } from \"@solve-js/parser/OpCode\";\nimport { SYMBOLIC_BUILTIN_INTEGRAL } from \"@solve-js/packages/symbolic/SymbolicBuiltinIndex\";\nimport { readVariableName, emitVariableName, parseBoundExpression, emitBoundExpression } from \"@solve-js/packages/symbolic/parselets/VariableArgument\";\n\n/**\n * `integral(expr, variable)`, the indefinite integral, without a constant of\n * integration. `expr` is held until the variable is read so that the named\n * unknown shadows any document value of the same name, see\n * {@link emitBoundExpression}.\n */\nexport class IntegralParselet implements PrefixParselet {\n\treadonly category = \"Symbolic\";\n\n\tparse(parser: Parser, _token: Token, builder: BytecodeBuilder): void {\n\t\tparser.consume(\"LPAREN\");\n\t\tconst expression = parseBoundExpression(parser, builder, \"integral\");\n\t\tparser.consume(\"COMMA\");\n\t\tconst variable = readVariableName(parser, \"integral\");\n\t\temitBoundExpression(builder, expression, variable);\n\t\temitVariableName(builder, variable);\n\t\tparser.consume(\"RPAREN\");\n\n\t\tbuilder.emitOpcode(OpCode.CALL_BUILTIN);\n\t\tbuilder.emitIndex(SYMBOLIC_BUILTIN_INTEGRAL);\n\t\tbuilder.emitIndex(2);\n\t}\n}\n","import { PrefixParselet } from \"@solve-js/parser/Parselet\";\nimport { Parser } from \"@solve-js/parser/Parser\";\nimport { Token } from \"@solve-js/lexer/Token\";\nimport { BytecodeBuilder } from \"@solve-js/parser/BytecodeBuilder\";\nimport { OpCode } from \"@solve-js/parser/OpCode\";\nimport { BindingPower } from \"@solve-js/parser/BindingPower\";\nimport { SYMBOLIC_BUILTIN_TAYLOR } from \"@solve-js/packages/symbolic/SymbolicBuiltinIndex\";\nimport { readVariableName, emitVariableName, parseBoundExpression, emitBoundExpression } from \"@solve-js/packages/symbolic/parselets/VariableArgument\";\n\n/**\n * `taylor(expr, variable = point, degree)`, matching Calca's own spelling.\n *\n * The `variable = point` argument is why this needs a hand-written parselet:\n * `EQUALS` has no infix parselet, so an ordinary argument list cannot parse it.\n * Reading the name and the point separately also means the name never has to\n * exist as a variable, and `expr` is held until the name is known so that the\n * name shadows any document value it shares (see {@link emitBoundExpression}).\n * The expansion point is an ordinary value expression and is not shadowed: it\n * is a number, not the unknown.\n */\nexport class TaylorParselet implements PrefixParselet {\n\treadonly category = \"Symbolic\";\n\n\tparse(parser: Parser, _token: Token, builder: BytecodeBuilder): void {\n\t\tparser.consume(\"LPAREN\");\n\t\tconst expression = parseBoundExpression(parser, builder, \"taylor\");\n\t\tparser.consume(\"COMMA\");\n\t\tconst variable = readVariableName(parser, \"taylor\");\n\t\temitBoundExpression(builder, expression, variable);\n\t\temitVariableName(builder, variable);\n\t\tparser.consume(\"EQUALS\");\n\t\tparser.parseExpression(BindingPower.Lowest, builder);\n\t\tparser.consume(\"COMMA\");\n\t\tparser.parseExpression(BindingPower.Lowest, builder);\n\t\tparser.consume(\"RPAREN\");\n\n\t\tbuilder.emitOpcode(OpCode.CALL_BUILTIN);\n\t\tbuilder.emitIndex(SYMBOLIC_BUILTIN_TAYLOR);\n\t\tbuilder.emitIndex(4);\n\t}\n}\n","import { PrefixParselet } from \"@solve-js/parser/Parselet\";\nimport { Parser } from \"@solve-js/parser/Parser\";\nimport { Token } from \"@solve-js/lexer/Token\";\nimport { BytecodeBuilder } from \"@solve-js/parser/BytecodeBuilder\";\nimport { OpCode } from \"@solve-js/parser/OpCode\";\nimport { BindingPower } from \"@solve-js/parser/BindingPower\";\nimport { SYMBOLIC_BUILTIN_JACOBIAN } from \"@solve-js/packages/symbolic/SymbolicBuiltinIndex\";\n\n/**\n * `jacobian(f1, f2, ...)`, the matrix of partial derivatives.\n *\n * Variadic, and the variables are not named: they are taken from the union of\n * the functions' own unknowns, sorted, which is what Calca does. Row `i` is the\n * gradient of the `i`-th function.\n */\nexport class JacobianParselet implements PrefixParselet {\n\treadonly category = \"Symbolic\";\n\n\tparse(parser: Parser, _token: Token, builder: BytecodeBuilder): void {\n\t\tparser.consume(\"LPAREN\");\n\t\tlet count = 0;\n\t\tdo {\n\t\t\tparser.parseExpression(BindingPower.Lowest, builder);\n\t\t\tcount++;\n\t\t} while (parser.match(\"COMMA\"));\n\t\tparser.consume(\"RPAREN\");\n\n\t\tbuilder.emitOpcode(OpCode.CALL_BUILTIN);\n\t\tbuilder.emitIndex(SYMBOLIC_BUILTIN_JACOBIAN);\n\t\tbuilder.emitIndex(count);\n\t}\n}\n","import { PrefixParselet } from \"@solve-js/parser/Parselet\";\nimport { Parser } from \"@solve-js/parser/Parser\";\nimport { Token } from \"@solve-js/lexer/Token\";\nimport { BytecodeBuilder } from \"@solve-js/parser/BytecodeBuilder\";\nimport { OpCode } from \"@solve-js/parser/OpCode\";\nimport { SYMBOLIC_BUILTIN_IMAGINARY } from \"@solve-js/packages/symbolic/SymbolicBuiltinIndex\";\n\n/**\n * An imaginary literal, `3i`, fused by\n * `normalizer/ImaginaryLiteralNormalizerRule.ts`.\n *\n * The token carries the numeric part as its value; this pushes that number and\n * lets the builtin turn it into an exact imaginary value. Going through a\n * builtin rather than a dedicated opcode keeps the VM dispatch table untouched,\n * the same choice every other algebra verb made.\n */\nexport class ImaginaryParselet implements PrefixParselet {\n\treadonly category = \"Symbolic\";\n\n\tparse(_parser: Parser, token: Token, builder: BytecodeBuilder): void {\n\t\tbuilder.emitOpcode(OpCode.PUSH_NUMBER);\n\t\tbuilder.emitNumber(Number(token.value));\n\t\tbuilder.emitOpcode(OpCode.CALL_BUILTIN);\n\t\tbuilder.emitIndex(SYMBOLIC_BUILTIN_IMAGINARY);\n\t\tbuilder.emitIndex(1);\n\t}\n}\n","import { PrefixParselet } from \"@solve-js/parser/Parselet\";\nimport { Parser } from \"@solve-js/parser/Parser\";\nimport { Token } from \"@solve-js/lexer/Token\";\nimport { BytecodeBuilder } from \"@solve-js/parser/BytecodeBuilder\";\nimport { OpCode } from \"@solve-js/parser/OpCode\";\nimport { BindingPower } from \"@solve-js/parser/BindingPower\";\nimport { SYMBOLIC_BUILTIN_CONJ } from \"@solve-js/packages/symbolic/SymbolicBuiltinIndex\";\n\n/**\n * `conj(z)`, the complex conjugate.\n *\n * A dedicated parselet rather than a keywordMap entry, for the reason given in\n * `normalizer/SymbolicCallNormalizerRule.ts`: `re` and `im` are short words a\n * person may well use as variable names.\n */\nexport class ConjParselet implements PrefixParselet {\n\treadonly category = \"Symbolic\";\n\n\tparse(parser: Parser, _token: Token, builder: BytecodeBuilder): void {\n\t\tparser.consume(\"LPAREN\");\n\t\tparser.parseExpression(BindingPower.Lowest, builder);\n\t\tparser.consume(\"RPAREN\");\n\n\t\tbuilder.emitOpcode(OpCode.CALL_BUILTIN);\n\t\tbuilder.emitIndex(SYMBOLIC_BUILTIN_CONJ);\n\t\tbuilder.emitIndex(1);\n\t}\n}\n","import { PrefixParselet } from \"@solve-js/parser/Parselet\";\nimport { Parser } from \"@solve-js/parser/Parser\";\nimport { Token } from \"@solve-js/lexer/Token\";\nimport { BytecodeBuilder } from \"@solve-js/parser/BytecodeBuilder\";\nimport { OpCode } from \"@solve-js/parser/OpCode\";\nimport { BindingPower } from \"@solve-js/parser/BindingPower\";\nimport { SYMBOLIC_BUILTIN_RE } from \"@solve-js/packages/symbolic/SymbolicBuiltinIndex\";\n\n/**\n * `re(z)`, the real part of a complex value.\n *\n * A dedicated parselet rather than a keywordMap entry, for the reason given in\n * `normalizer/SymbolicCallNormalizerRule.ts`: `re` and `im` are short words a\n * person may well use as variable names.\n */\nexport class ReParselet implements PrefixParselet {\n\treadonly category = \"Symbolic\";\n\n\tparse(parser: Parser, _token: Token, builder: BytecodeBuilder): void {\n\t\tparser.consume(\"LPAREN\");\n\t\tparser.parseExpression(BindingPower.Lowest, builder);\n\t\tparser.consume(\"RPAREN\");\n\n\t\tbuilder.emitOpcode(OpCode.CALL_BUILTIN);\n\t\tbuilder.emitIndex(SYMBOLIC_BUILTIN_RE);\n\t\tbuilder.emitIndex(1);\n\t}\n}\n","import { PrefixParselet } from \"@solve-js/parser/Parselet\";\nimport { Parser } from \"@solve-js/parser/Parser\";\nimport { Token } from \"@solve-js/lexer/Token\";\nimport { BytecodeBuilder } from \"@solve-js/parser/BytecodeBuilder\";\nimport { OpCode } from \"@solve-js/parser/OpCode\";\nimport { BindingPower } from \"@solve-js/parser/BindingPower\";\nimport { SYMBOLIC_BUILTIN_IM } from \"@solve-js/packages/symbolic/SymbolicBuiltinIndex\";\n\n/**\n * `im(z)`, the imaginary part of a complex value.\n *\n * A dedicated parselet rather than a keywordMap entry, for the reason given in\n * `normalizer/SymbolicCallNormalizerRule.ts`: `re` and `im` are short words a\n * person may well use as variable names.\n */\nexport class ImParselet implements PrefixParselet {\n\treadonly category = \"Symbolic\";\n\n\tparse(parser: Parser, _token: Token, builder: BytecodeBuilder): void {\n\t\tparser.consume(\"LPAREN\");\n\t\tparser.parseExpression(BindingPower.Lowest, builder);\n\t\tparser.consume(\"RPAREN\");\n\n\t\tbuilder.emitOpcode(OpCode.CALL_BUILTIN);\n\t\tbuilder.emitIndex(SYMBOLIC_BUILTIN_IM);\n\t\tbuilder.emitIndex(1);\n\t}\n}\n","import { PrefixParselet } from \"@solve-js/parser/Parselet\";\nimport { Parser } from \"@solve-js/parser/Parser\";\nimport { Token } from \"@solve-js/lexer/Token\";\nimport { BytecodeBuilder } from \"@solve-js/parser/BytecodeBuilder\";\nimport { OpCode } from \"@solve-js/parser/OpCode\";\nimport { BindingPower } from \"@solve-js/parser/BindingPower\";\nimport { SYMBOLIC_BUILTIN_CANCEL } from \"@solve-js/packages/symbolic/SymbolicBuiltinIndex\";\n\n/**\n * `cancel(expr)`, reducing a quotient of polynomials to lowest terms.\n *\n * The simplifier already cancels a common factor automatically; this is the\n * explicit form, for when the intent is to reduce a fraction rather than to\n * evaluate something that happens to contain one.\n */\nexport class CancelParselet implements PrefixParselet {\n\treadonly category = \"Symbolic\";\n\n\tparse(parser: Parser, _token: Token, builder: BytecodeBuilder): void {\n\t\tparser.consume(\"LPAREN\");\n\t\tparser.parseExpression(BindingPower.Lowest, builder);\n\t\tparser.consume(\"RPAREN\");\n\n\t\tbuilder.emitOpcode(OpCode.CALL_BUILTIN);\n\t\tbuilder.emitIndex(SYMBOLIC_BUILTIN_CANCEL);\n\t\tbuilder.emitIndex(1);\n\t}\n}\n","import { PrefixParselet } from \"@solve-js/parser/Parselet\";\nimport { Parser } from \"@solve-js/parser/Parser\";\nimport { Token } from \"@solve-js/lexer/Token\";\nimport { BytecodeBuilder } from \"@solve-js/parser/BytecodeBuilder\";\nimport { OpCode } from \"@solve-js/parser/OpCode\";\nimport { BindingPower } from \"@solve-js/parser/BindingPower\";\nimport { SYMBOLIC_BUILTIN_APART } from \"@solve-js/packages/symbolic/SymbolicBuiltinIndex\";\n\n/**\n * `apart(expr)`, splitting a rational function into partial fractions.\n *\n * The inverse of putting a sum of fractions over a common denominator, and the\n * step that makes a rational function integrable.\n */\nexport class ApartParselet implements PrefixParselet {\n\treadonly category = \"Symbolic\";\n\n\tparse(parser: Parser, _token: Token, builder: BytecodeBuilder): void {\n\t\tparser.consume(\"LPAREN\");\n\t\tparser.parseExpression(BindingPower.Lowest, builder);\n\t\tparser.consume(\"RPAREN\");\n\n\t\tbuilder.emitOpcode(OpCode.CALL_BUILTIN);\n\t\tbuilder.emitIndex(SYMBOLIC_BUILTIN_APART);\n\t\tbuilder.emitIndex(1);\n\t}\n}\n","import type { Token } from \"@solve-js/lexer/Token\";\nimport { tokenTypeId } from \"@solve-js/lexer/Token\";\nimport { LexerToken } from \"@solve-js/lexer/ExpressionLexer\";\nimport type { NormalizerRule, NormalizerMatch } from \"@solve-js/normalizer/NormalizerRule\";\n\n/**\n * Fuses `3i` into a single imaginary literal, but only when the `i` is written\n * flush against the number.\n *\n * `i` is not claimed as a keyword, and deliberately so. It is one of the most\n * common variable names there is, and this engine's whole trigger-word policy\n * exists to avoid taking words a person would reasonably assign to. `:i = 5`\n * has to keep working, and after this rule it does: the rule only fires on a\n * number immediately followed by the letter, which is the same shape the\n * magnitude suffixes use, and `2.5k` set that precedent.\n *\n * Adjacency is checked by source offset rather than by token order, so `3i` is\n * an imaginary literal while `3 i` and `3 * i` are a number multiplied by a\n * variable named `i`. That is the distinction that keeps both readings\n * available, and it is the reason a bare `i` on its own is still a variable.\n * Write `1i` for the imaginary unit alone.\n */\nexport function imaginaryLiteralNormalizerRule(priority = 75): NormalizerRule {\n\treturn {\n\t\tname: \"symbolic:imaginary-literal\",\n\t\tpriority,\n\t\t// Derived from this rule's own opening guards; see RuleSlot on why an\n\t\t// over-broad slot is safe and an over-narrow one is not.\n\t\tshape: [{ types: [\"NUMBER\"] }, { types: [\"IDENT\"], values: [\"i\"] }],\n\t\tmatch(tokens: Token[], pos: number): NormalizerMatch | null {\n\t\t\tconst number = tokens[pos];\n\t\t\tif (!number || number.type !== \"NUMBER\") return null;\n\n\t\t\tconst suffix = tokens[pos + 1];\n\t\t\tif (!suffix || suffix.type !== \"IDENT\" || suffix.value !== \"i\") return null;\n\n\t\t\t// Flush against the number, with no space between them.\n\t\t\tif (suffix.offset !== number.offset + number.value.length) return null;\n\n\t\t\t// A following `(` would make this a call, as in `3i(x)`, which is not a\n\t\t\t// shape this claims.\n\t\t\tif (tokens[pos + 2]?.type === \"LPAREN\") return null;\n\n\t\t\treturn {\n\t\t\t\tconsumed: 2,\n\t\t\t\treplacement: [\n\t\t\t\t\tnew LexerToken(\n\t\t\t\t\t\t\"IMAGINARY\",\n\t\t\t\t\t\ttokenTypeId(\"IMAGINARY\"),\n\t\t\t\t\t\tnumber.value,\n\t\t\t\t\t\tnumber.value,\n\t\t\t\t\t\tnumber.offset,\n\t\t\t\t\t\t0,\n\t\t\t\t\t\tnumber.line,\n\t\t\t\t\t\tnumber.col,\n\t\t\t\t\t),\n\t\t\t\t],\n\t\t\t\truleName: \"symbolic:imaginary-literal\",\n\t\t\t};\n\t\t},\n\t};\n}\n","import type { Token } from \"@solve-js/lexer/Token\";\nimport { tokenTypeId } from \"@solve-js/lexer/Token\";\nimport { LexerToken } from \"@solve-js/lexer/ExpressionLexer\";\nimport type { NormalizerRule, NormalizerMatch } from \"@solve-js/normalizer/NormalizerRule\";\n\n/**\n * The algebra verbs, mapped to the token type each becomes when it is being\n * called.\n *\n * Kept in one place so {@link SYMBOLIC_FUNCTIONS} in `SymbolicPackage.ts` and\n * this rule cannot disagree about which words the package claims.\n */\nexport const SYMBOLIC_WORD_TO_TOKEN_TYPE: Readonly<Record<string, string>> = {\n\texpand: \"EXPAND_FN\",\n\tfactor: \"FACTOR_FN\",\n\tsolve: \"SOLVE_FN\",\n\tder: \"DER_FN\",\n\tderivative: \"DER_FN\",\n\tintegral: \"INTEGRAL_FN\",\n\ttaylor: \"TAYLOR_FN\",\n\tjacobian: \"JACOBIAN_FN\",\n\tconj: \"CONJ_FN\",\n\tre: \"RE_FN\",\n\tim: \"IM_FN\",\n\tcancel: \"CANCEL_FN\",\n\tapart: \"APART_FN\",\n};\n\n/**\n * Fuses an algebra verb into its own token type, but only when the bare word is\n * immediately followed by `(`.\n *\n * None of these words may be a plain `keywordMap` entry, and the reason is\n * concrete rather than stylistic. A `keywordMap` entry makes the lexer emit a\n * reserved token type everywhere the word appears, which would break\n * `:factor = 1.5` and `:solve = 2` as ordinary variable names. `solve` is also\n * the product's own name and `factor` is an everyday English noun, so both are\n * words a user will reasonably assign to.\n *\n * Mirrors `packages/mapreduce/normalizer/MapReduceCallNormalizerRule.ts`, which\n * exists for exactly this reason for `map`/`reduce`/`sum`/`prod`.\n *\n * @param priority - Rule ordering within the normalizer, defaulting to the same\n * band the map/reduce call rule uses.\n * @returns The normalizer rule.\n */\nexport function symbolicCallNormalizerRule(priority = 80): NormalizerRule {\n\treturn {\n\t\tname: \"symbolic:call\",\n\t\tpriority,\n\t\t// Derived from this rule's own opening guards; see RuleSlot on why an\n\t\t// over-broad slot is safe and an over-narrow one is not.\n\t\tshape: [{ types: [\"IDENT\"], values: Object.keys(SYMBOLIC_WORD_TO_TOKEN_TYPE) }, { types: [\"LPAREN\"] }],\n\t\tmatch(tokens: Token[], pos: number): NormalizerMatch | null {\n\t\t\tconst token = tokens[pos];\n\t\t\tif (!token || token.type !== \"IDENT\") return null;\n\t\t\tconst tokenType = SYMBOLIC_WORD_TO_TOKEN_TYPE[token.value.toLowerCase()];\n\t\t\tif (!tokenType) return null;\n\t\t\tif (tokens[pos + 1]?.type !== \"LPAREN\") return null;\n\n\t\t\treturn {\n\t\t\t\tconsumed: 1,\n\t\t\t\treplacement: [\n\t\t\t\t\tnew LexerToken(tokenType, tokenTypeId(tokenType), token.value, token.value, token.offset, 0, token.line, token.col),\n\t\t\t\t],\n\t\t\t\truleName: \"symbolic:call\",\n\t\t\t};\n\t\t},\n\t};\n}\n","import type { IEnginePackage } from \"@solve-js/api/PackageRegistry\";\nimport { ExpandParselet } from \"./parselets/ExpandParselet\";\nimport { FactorParselet } from \"./parselets/FactorParselet\";\nimport { SolveParselet } from \"./parselets/SolveParselet\";\nimport { DerParselet } from \"./parselets/DerParselet\";\nimport { IntegralParselet } from \"./parselets/IntegralParselet\";\nimport { TaylorParselet } from \"./parselets/TaylorParselet\";\nimport { JacobianParselet } from \"./parselets/JacobianParselet\";\nimport { ImaginaryParselet } from \"./parselets/ImaginaryParselet\";\nimport { ConjParselet } from \"./parselets/ConjParselet\";\nimport { ReParselet } from \"./parselets/ReParselet\";\nimport { ImParselet } from \"./parselets/ImParselet\";\nimport { CancelParselet } from \"./parselets/CancelParselet\";\nimport { ApartParselet } from \"./parselets/ApartParselet\";\nimport { imaginaryLiteralNormalizerRule } from \"./normalizer/ImaginaryLiteralNormalizerRule\";\nimport { symbolicCallNormalizerRule } from \"./normalizer/SymbolicCallNormalizerRule\";\nimport {\n\tSYMBOLIC_BUILTIN_EXPAND,\n\tSYMBOLIC_BUILTIN_FACTOR,\n\tSYMBOLIC_BUILTIN_SOLVE,\n\tSYMBOLIC_BUILTIN_DER,\n\tSYMBOLIC_BUILTIN_INTEGRAL,\n\tSYMBOLIC_BUILTIN_TAYLOR,\n\tSYMBOLIC_BUILTIN_JACOBIAN,\n\tSYMBOLIC_BUILTIN_CONJ,\n\tSYMBOLIC_BUILTIN_RE,\n\tSYMBOLIC_BUILTIN_IM,\n\tSYMBOLIC_BUILTIN_CANCEL,\n\tSYMBOLIC_BUILTIN_APART,\n} from \"./SymbolicBuiltinIndex\";\n\n/**\n * One algebra verb's whole surface, in a single row.\n *\n * Everything a verb needs in order to work is listed here rather than being\n * spread across the normalizer, the parselet registry, the builtin table and\n * the docs, so `__tests__/engine/SymbolicSurfaceParity.spec.ts` can check the\n * pieces actually agree. Shipping a verb whose index has no implementation, or\n * whose parselet is registered under a token type the normalizer never mints,\n * then becomes a failing test rather than a silent dead feature.\n */\nexport interface SymbolicFunctionSurface {\n\t/** The bare word a user types. */\n\treadonly word: string;\n\t/** The token type the normalizer fuses it into when it is followed by `(`. */\n\treadonly tokenType: string;\n\t/** The `CALL_BUILTIN` index its parselet emits. */\n\treadonly builtinIndex: number;\n\t/** A working example, executed by the parity spec through every public entry point. */\n\treadonly example: string;\n\t/** That example's expected formatted result. */\n\treadonly expected: string;\n\t/** The documentation page under `docs/src/content/docs/syntax/` that must show it. */\n\treadonly docPage: string;\n}\n\n/** Every algebra verb this package registers. */\nexport const SYMBOLIC_FUNCTIONS: readonly SymbolicFunctionSurface[] = [\n\t{\n\t\tword: \"expand\",\n\t\ttokenType: \"EXPAND_FN\",\n\t\tbuiltinIndex: SYMBOLIC_BUILTIN_EXPAND,\n\t\texample: \"expand((x+1)*(x+2))\",\n\t\texpected: \"x^2+3x+2\",\n\t\tdocPage: \"expanding.md\",\n\t},\n\t{\n\t\tword: \"factor\",\n\t\ttokenType: \"FACTOR_FN\",\n\t\tbuiltinIndex: SYMBOLIC_BUILTIN_FACTOR,\n\t\texample: \"factor(x^2-4)\",\n\t\texpected: \"(x-2)*(x+2)\",\n\t\tdocPage: \"factoring.md\",\n\t},\n\t{\n\t\tword: \"solve\",\n\t\ttokenType: \"SOLVE_FN\",\n\t\tbuiltinIndex: SYMBOLIC_BUILTIN_SOLVE,\n\t\texample: \"solve(x^2-4=0, x)\",\n\t\texpected: \"= [-2, 2]\",\n\t\tdocPage: \"solving-equations.md\",\n\t},\n\t{\n\t\tword: \"der\",\n\t\ttokenType: \"DER_FN\",\n\t\tbuiltinIndex: SYMBOLIC_BUILTIN_DER,\n\t\texample: \"der(x^3, x)\",\n\t\texpected: \"3x^2\",\n\t\tdocPage: \"calculus.md\",\n\t},\n\t{\n\t\tword: \"integral\",\n\t\ttokenType: \"INTEGRAL_FN\",\n\t\tbuiltinIndex: SYMBOLIC_BUILTIN_INTEGRAL,\n\t\texample: \"integral(x^2, x)\",\n\t\texpected: \"1/3x^3\",\n\t\tdocPage: \"calculus.md\",\n\t},\n\t{\n\t\tword: \"taylor\",\n\t\ttokenType: \"TAYLOR_FN\",\n\t\tbuiltinIndex: SYMBOLIC_BUILTIN_TAYLOR,\n\t\texample: \"taylor(exp(x), x=0, 3)\",\n\t\texpected: \"1/6x^3+0.5x^2+x+1\",\n\t\tdocPage: \"calculus.md\",\n\t},\n\t{\n\t\tword: \"jacobian\",\n\t\ttokenType: \"JACOBIAN_FN\",\n\t\tbuiltinIndex: SYMBOLIC_BUILTIN_JACOBIAN,\n\t\texample: \"jacobian(x*y, x+y)\",\n\t\texpected: \"= [y, x; 1, 1]\",\n\t\tdocPage: \"calculus.md\",\n\t},\n\t{\n\t\tword: \"conj\",\n\t\ttokenType: \"CONJ_FN\",\n\t\tbuiltinIndex: SYMBOLIC_BUILTIN_CONJ,\n\t\texample: \"conj(2+3i)\",\n\t\texpected: \"2-3i\",\n\t\tdocPage: \"complex.md\",\n\t},\n\t{\n\t\tword: \"re\",\n\t\ttokenType: \"RE_FN\",\n\t\tbuiltinIndex: SYMBOLIC_BUILTIN_RE,\n\t\texample: \"re(2+3i)\",\n\t\texpected: \"= 2\",\n\t\tdocPage: \"complex.md\",\n\t},\n\t{\n\t\tword: \"im\",\n\t\ttokenType: \"IM_FN\",\n\t\tbuiltinIndex: SYMBOLIC_BUILTIN_IM,\n\t\texample: \"im(2+3i)\",\n\t\texpected: \"= 3\",\n\t\tdocPage: \"complex.md\",\n\t},\n\t{\n\t\tword: \"cancel\",\n\t\ttokenType: \"CANCEL_FN\",\n\t\tbuiltinIndex: SYMBOLIC_BUILTIN_CANCEL,\n\t\texample: \"cancel((x^2-1)/(x-1))\",\n\t\texpected: \"x+1\",\n\t\tdocPage: \"cancelling-fractions.md\",\n\t},\n\t{\n\t\tword: \"apart\",\n\t\ttokenType: \"APART_FN\",\n\t\tbuiltinIndex: SYMBOLIC_BUILTIN_APART,\n\t\texample: \"apart((3x+5)/(x^2-1))\",\n\t\texpected: \"4/(x-1)-1/(x+1)\",\n\t\tdocPage: \"splitting-fractions.md\",\n\t},\n];\n\n/**\n * Symbolic algebra verbs: multiplying out, and (in later phases) factoring,\n * solving and calculus.\n *\n * The algebra itself lives in `symbolic/`, which is pure mathematics over the\n * expression tree. This package is only the grammar surface: which words become\n * which tokens, and which parselet emits which builtin call.\n *\n * None of these words is a bare `keywordMap` entry. See\n * `normalizer/SymbolicCallNormalizerRule.ts` for why that matters.\n */\nexport const SYMBOLIC_PACKAGE: IEnginePackage = {\n\tname: \"solve-symbolic\",\n\tnormalizerRules: [symbolicCallNormalizerRule(), imaginaryLiteralNormalizerRule()],\n\tprefixParselets: {\n\t\tEXPAND_FN: new ExpandParselet(),\n\t\tFACTOR_FN: new FactorParselet(),\n\t\tSOLVE_FN: new SolveParselet(),\n\t\tDER_FN: new DerParselet(),\n\t\tINTEGRAL_FN: new IntegralParselet(),\n\t\tTAYLOR_FN: new TaylorParselet(),\n\t\tJACOBIAN_FN: new JacobianParselet(),\n\t\tIMAGINARY: new ImaginaryParselet(),\n\t\tCONJ_FN: new ConjParselet(),\n\t\tRE_FN: new ReParselet(),\n\t\tIM_FN: new ImParselet(),\n\t\tCANCEL_FN: new CancelParselet(),\n\t\tAPART_FN: new ApartParselet(),\n\t},\n\ttokenCategories: {\n\t\tEXPAND_FN: \"keyword\",\n\t\tFACTOR_FN: \"keyword\",\n\t\tSOLVE_FN: \"keyword\",\n\t\tDER_FN: \"keyword\",\n\t\tINTEGRAL_FN: \"keyword\",\n\t\tTAYLOR_FN: \"keyword\",\n\t\tJACOBIAN_FN: \"keyword\",\n\t\tIMAGINARY: \"number\",\n\t\tCONJ_FN: \"keyword\",\n\t\tRE_FN: \"keyword\",\n\t\tIM_FN: \"keyword\",\n\t\tCANCEL_FN: \"keyword\",\n\t\tAPART_FN: \"keyword\",\n\t},\n};\n\n/** The token types the algebra verbs fuse into, for the engine's own \"is this line symbolic\" check. */\nconst SYMBOLIC_TOKEN_TYPES: ReadonlySet<string> = new Set(SYMBOLIC_FUNCTIONS.map(fn => fn.tokenType));\n\n/**\n * Whether a normalized token list calls an algebra verb.\n *\n * `engine/ExpressionEngine.ts` uses this to evaluate such a line in\n * symbolic-tolerant mode without requiring a trailing `=>`, since asking to\n * expand or factor something is already a statement that its unknowns are meant\n * to stay unknown.\n *\n * @param tokens - The normalized tokens for one line.\n * @returns True when any token is an algebra verb.\n */\nexport function containsSymbolicCall(tokens: readonly { type: string }[]): boolean {\n\treturn tokens.some(token => SYMBOLIC_TOKEN_TYPES.has(token.type));\n}\n","/**\n * Pure `#tag` detection on a raw line, kept engine-free so it is unit-testable\n * in isolation, the same design {@link TableReader} draws.\n */\n\nimport { edgeKey } from \"@solve-js/vm/DependencyGraph\";\n\n/**\n * The key a category tag takes in the dependency graph.\n *\n * Lower-cased, because {@link lineCarriesTag} reads a tag case-insensitively:\n * `#Food` and `total of #food` are one group to a reader, so they have to be\n * one key here too, or the aggregate would not be hooked to its members.\n */\nconst tagEdgeKey = (tag: string): string => edgeKey(\"tag\", tag.toLowerCase());\n\n/** Escapes any regex-special character a tag name could carry. */\nexport function escapeTag(name: string): string {\n return name.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\n\n/**\n * The aggregate openers, immediately before the tag they read.\n *\n * `total of #food` names the group; it does not join it. Anchored at the end,\n * so it is asking what sits directly in front of this particular `#`.\n */\nconst AGGREGATE_OPENER = /(?:total|sum|average|count)\\s+of\\s+$/i;\n\n/**\n * How much text before a `#` is examined for an opener.\n *\n * The pattern is anchored at its end, so only the characters immediately in\n * front of the `#` can match it, and testing a fixed window is the same answer\n * as testing the whole line up to the point where the whitespace runs long.\n * The longest opener is `average of `, eleven characters, which leaves\n * fifty-three here for whitespace between the words.\n *\n * Testing the whole prefix instead is what made this quadratic: the pattern is\n * anchored at the end but not the start, so the engine scans from every\n * position, and a line whose every occurrence is a query pays that once per\n * occurrence. A 192 KB line of repeated `total of #a` took 2.1 seconds.\n *\n * Past the window an opener is not recognised, so its line is read as a member\n * rather than as a query, which is what it was before any of this existed.\n */\nconst OPENER_WINDOW = 64;\n\n/** Any `#tag`, for the scan that reads a line's whole membership rather than asking about one name. */\nconst ANY_TAG = /(?:^|[^0-9A-Za-z_])#([0-9A-Za-z_-]+)(?![0-9A-Za-z_-])/g;\n\n/**\n * A line's edges, with the groups its text joins and asks about folded in.\n *\n * A category tag is an edge like any other: a line carrying `#food` writes that\n * group and `total of #food` reads it, so registering them alongside the\n * variables is what lets an edit to a tagged line dirty only the aggregates over\n * that tag.\n *\n * Every place that registers a line calls this rather than adding tags itself.\n * There are five of them, across the engine and the evaluator, and a line\n * registered twice with different edge sets loses whichever went first: that is\n * exactly how tag edges were being written and then silently wiped within the\n * same pass.\n *\n * Returns the arrays it was given when the line carries no tags, which is most\n * lines, so the common path allocates nothing.\n */\nexport function withTagEdges(\n\trawText: string,\n\treads: readonly string[],\n\twrites: readonly string[],\n): { reads: string[]; writes: string[] } {\n\tconst tags = tagEdgesOf(rawText);\n\tif (tags.members.length === 0 && tags.queries.length === 0) {\n\t\treturn { reads: reads as string[], writes: writes as string[] };\n\t}\n\treturn {\n\t\treads: tags.queries.length === 0 ? (reads as string[]) : [...reads, ...tags.queries.map(tagEdgeKey)],\n\t\twrites: tags.members.length === 0 ? (writes as string[]) : [...writes, ...tags.members.map(tagEdgeKey)],\n\t};\n}\n\n/**\n * The groups a line joins, lower-cased, in the form an index keys on.\n *\n * The membership half of {@link tagEdgesOf}, case-folded the way\n * {@link lineCarriesTag} reads a name, so a lookup by tag and a scan of the\n * line answer the same question.\n */\nexport function memberTagsOf(rawText: string): string[] {\n\tconst members = tagEdgesOf(rawText).members;\n\tfor (let i = 0; i < members.length; i++) members[i] = members[i].toLowerCase();\n\treturn members;\n}\n\n/**\n * Every group a line joins, and every group it asks about.\n *\n * The same reading {@link lineCarriesTag} gives, in the shape an index wants:\n * one pass over the line naming both sides, rather than one pass per candidate\n * tag asking a yes-or-no question. They must not drift, so the rules live here\n * once and that function is the single-tag view of this one.\n *\n * A tag can appear on both sides of the same line, which is why these are two\n * lists rather than a partition of one: `total of #food #food` asks about the\n * group and joins it.\n */\nexport function tagEdgesOf(rawText: string): { members: string[]; queries: string[] } {\n\tconst members: string[] = [];\n\tconst queries: string[] = [];\n\t// Whether anything precedes a `#` is one property of the line.\n\tconst firstContent = rawText.search(/\\S/);\n\tANY_TAG.lastIndex = 0;\n\tfor (let m = ANY_TAG.exec(rawText); m !== null; m = ANY_TAG.exec(rawText)) {\n\t\tconst hashIndex = m.index + m[0].indexOf(\"#\");\n\t\t// The line's first non-whitespace token: a heading, not a tagged line.\n\t\tif (firstContent === hashIndex) continue;\n\t\tconst name = m[1];\n\t\tif (AGGREGATE_OPENER.test(rawText.slice(Math.max(0, hashIndex - OPENER_WINDOW), hashIndex))) {\n\t\t\tqueries.push(name);\n\t\t\tcontinue;\n\t\t}\n\t\tmembers.push(name);\n\t}\n\treturn { members, queries };\n}\n\n/**\n * Whether `rawText` carries `#tag` as a mid-line annotation, case-insensitively.\n *\n * The tag must not be part of a longer word before (`a#tag`) or after\n * (`#housingcost` is not `#housing`), and must not be the line's first\n * non-whitespace token, since a line starting with `#` is a heading, not a\n * tagged data line.\n *\n * Nor may it be the object of an aggregate. A `#tag` after `total of` names the\n * group rather than joining it, and reading it as membership is what made two\n * aggregates over one tag unreadable: each walked the other, found a line still\n * being evaluated, and reported it. The querying line's own text was already\n * skipped by line number, so this only extends that to the other queries, and\n * says the same thing about all of them.\n *\n * Every occurrence is examined rather than only the first, since one line can\n * hold both: `total of #food #reviewed` asks about one group and joins another.\n */\nexport function lineCarriesTag(rawText: string, tag: string): boolean {\n if (tag === \"\") return false;\n const re = new RegExp(`(?:^|[^0-9A-Za-z_])#${escapeTag(tag)}(?![0-9A-Za-z_-])`, \"gi\");\n // Whether anything precedes a `#` is one property of the line, so it is found\n // once here rather than by copying the prefix at every occurrence.\n const firstContent = rawText.search(/\\S/);\n for (let m = re.exec(rawText); m !== null; m = re.exec(rawText)) {\n // The `#` sits inside the match.\n const hashIndex = m.index + m[0].indexOf(\"#\");\n // The line's first non-whitespace token: a heading, not a tagged data line.\n if (firstContent === hashIndex) continue;\n if (AGGREGATE_OPENER.test(rawText.slice(Math.max(0, hashIndex - OPENER_WINDOW), hashIndex))) continue;\n return true;\n }\n return false;\n}\n","/**\n * ISO8601 string <-> epoch-ms helpers backing the datetime package's\n * `<ISO8601 string> to date` and `<date/time> as iso8601` features.\n *\n * SCOPE, revised in 1.0.0: {@link parseIso8601} is now reached by BOTH input\n * shapes. A quoted string literal (`\"2019-04-01T15:30:00+11:00\" to date`)\n * always came here; the bare, unquoted form now does too, fused into one\n * DATETIME_LITERAL by `normalizer/DateLiteralNormalizerRule.ts` before the\n * parser sees it.\n *\n * This file used to record that the bare form was out of scope because it is\n * ambiguous with arithmetic (`2019 - 04 - 01` reads as two subtractions) and\n * would need a dedicated lexer change. The date half of that ambiguity was\n * already settled by the normalizer rule, and the differential run against\n * 1.0.0-beta.6 showed what leaving the other half cost: a bare\n * `2019-04-01T15:30:00+11:00` read its `+11:00` as a clock time being ADDED to\n * the date, and answered TODAY at 11:00. Not the instant, not an error, and\n * formatted as a date, which is the most convincing way to be wrong. The two\n * spellings now answer identically, which is the only defensible arrangement\n * when one of them was always right.\n */\n\nimport type { CalendarBackend } from \"@solve-js/calendar/CalendarBackend\";\nimport { encodeFixedOffset } from \"@solve-js/calendar/IntlZone\";\nimport type { DatetimeGrain } from \"@solve-js/vm/Value\";\n\n/**\n * Matches a (reasonably) well-formed ISO8601 date or date-time string:\n * `YYYY-MM-DD` optionally followed by `THH:MM[:SS[.fff]][Z|+HH:MM|-HH:MM]`.\n * Deliberately stricter than the native `Date` constructor's very lenient\n * parsing (which also accepts things like `\"April 1, 2019\"`), only a\n * string actually ISO8601-shaped is accepted here, so `\"not a date\" to\n * date` fails loudly instead of silently parsing as `Invalid Date` (or,\n * worse, something the native parser guesses at).\n */\nconst ISO8601_PATTERN =\n /^\\d{4}-\\d{2}-\\d{2}(T\\d{2}:\\d{2}(:\\d{2}(\\.\\d+)?)?(Z|[+-]\\d{2}:?\\d{2})?)?$/;\n\n/**\n * Parse an ISO8601-shaped string into epoch milliseconds.\n *\n * Delegates the actual parsing to the calendar backend, whose `Date`\n * implementation is the native constructor: it fully implements the ISO8601\n * extended format (including \"Z\"/\"+HH:MM\" offsets and a fractional-seconds\n * component) per the ECMA-262 Date Time String Format spec, so no custom\n * parsing logic is needed, just a stricter shape gate in front of it (see\n * {@link ISO8601_PATTERN}'s doc comment).\n *\n * A date-only string (`\"2019-04-01\"`) parses as UTC midnight; a date-time\n * with no offset and no \"Z\" (`\"2019-04-01T15:30:00\"`) parses in the HOST\n * SYSTEM's local timezone, both are the native `Date` constructor's own\n * spec-mandated behavior, which every backend reproduces, not something this\n * function adds.\n *\n * @param s - The text to parse, with or without surrounding double quotes.\n * @param calendar - The backend that parses the shape-checked string.\n * @returns epoch ms, or `null` if `s` isn't ISO8601-shaped or doesn't\n * parse to a valid instant.\n */\nexport function parseIso8601(s: string, calendar: CalendarBackend): number | null {\n // A `ValueType.String` Value's `.value` used to retain its original\n // surrounding double-quotes, because `tokenizeString()` set the token's\n // value to the raw source slice and `OpCode.PUSH_STRING` pushed that\n // verbatim. It no longer does: the token's `value` is the payload and its\n // `text` is the quoted slice. The strip below stays because this function\n // is also reachable with text that came from somewhere other than a\n // literal, and stripping a pair that is not there is a no-op.\n let trimmed = s.trim();\n if (trimmed.length >= 2 && trimmed.startsWith('\"') && trimmed.endsWith('\"')) {\n trimmed = trimmed.slice(1, -1);\n }\n if (!ISO8601_PATTERN.test(trimmed)) return null;\n const ms = calendar.parseIso8601(trimmed);\n return Number.isNaN(ms) ? null : ms;\n}\n\n/**\n * The same shape as {@link ISO8601_PATTERN}, with the two parts that decide\n * the grain captured: the time of day, and the `Z` or `±HH:MM` after it.\n *\n * Kept beside the pattern it mirrors so the two cannot drift. The offset group\n * is only reachable after a time group has matched, which is what stops\n * `12-25-2023` being read as a date with a `-20:23` offset.\n */\nconst ISO8601_GRAIN_PATTERN =\n /^\\d{4}-\\d{2}-\\d{2}(T\\d{2}:\\d{2}(?::\\d{2}(?:\\.\\d+)?)?(Z|[+-]\\d{2}:?\\d{2})?)?$/;\n\n/**\n * What an ISO 8601 literal's text says its instant anchors, and the zone it\n * named, if any.\n *\n * The three answers are the three spellings, decided from the text rather than\n * from the instant, because the instant cannot tell them apart: under `TZ=UTC`\n * the nine o'clock in `2026-04-03T09:00:00+09:00` IS midnight, so a reading\n * that tested the time fields would call it a calendar day and lose the hour\n * the reader typed.\n *\n * - No time of day, or text this pattern does not match at all (`03/04/2026`,\n * `3 April 2026`, `25.12.2023`): a calendar day.\n * - A time of day and nothing after it: a wall-clock reading, in whatever zone\n * the calendar backend reads as local.\n * - A time of day and a `Z` or an offset: a fixed instant, carrying that offset\n * as its zone. An offset is recorded as an offset (`\"UTCOFFSET:540\"`) and\n * never widened to a zone: `+09:00` says nothing about Tokyo's\n * daylight-saving rules and must not be made to.\n *\n * @param text - The literal as it was written.\n * @returns The grain, and the zone reference when the literal named one.\n */\nexport function iso8601Grain(text: string): { grain: DatetimeGrain; zone?: string } {\n const matched = ISO8601_GRAIN_PATTERN.exec(text.trim());\n if (matched === null || matched[1] === undefined) return { grain: \"date\" };\n const offset = matched[2];\n if (offset === undefined) return { grain: \"datetime\" };\n if (offset === \"Z\") return { grain: \"instant\", zone: encodeFixedOffset(0) };\n const sign = offset[0] === \"-\" ? -1 : 1;\n const digits = offset.slice(1).replace(\":\", \"\");\n const minutes = Number(digits.slice(0, 2)) * 60 + Number(digits.slice(2));\n return { grain: \"instant\", zone: encodeFixedOffset(sign * minutes) };\n}\n\n/**\n * Format epoch milliseconds as an ISO8601 string with an explicit\n * `+HH:MM`/`-HH:MM` offset, e.g. `\"2019-04-01T15:30:00+11:00\"`.\n *\n * DESIGN NOTE: uses the HOST SYSTEM's local timezone offset for the\n * offset component. This engine's `Datetime` representation is a bare\n * epoch-ms number with no zone tag (see `packages/time/TimePackage.ts`'s\n * doc comment for the same limitation affecting timezone conversion), so\n * there is no per-expression timezone context to draw on otherwise, the\n * backend's own local offset (`CalendarBackend.utcOffsetMinutes`, the\n * process's for the `Date` backend) is the only notion of \"local\" available.\n * No milliseconds component is emitted, matching the precision of the\n * task's own worked example.\n *\n * @param epochMs - The instant to format.\n * @param calendar - The backend whose local fields and offset are written out.\n * @returns The ISO 8601 string with an explicit offset.\n */\nexport function formatIso8601Local(epochMs: number, calendar: CalendarBackend): string {\n const d = calendar.fields(epochMs);\n const pad = (n: number) => String(n).padStart(2, \"0\");\n\n const year = d.year;\n const month = pad(d.month0 + 1);\n const day = pad(d.day);\n const hours = pad(d.hour);\n const minutes = pad(d.minute);\n const seconds = pad(d.second);\n\n // Positive when ahead of UTC, the \"+HH:MM\" reading the display wants.\n const offsetMinutesTotal = calendar.utcOffsetMinutes(epochMs);\n const sign = offsetMinutesTotal >= 0 ? \"+\" : \"-\";\n const absOffset = Math.abs(offsetMinutesTotal);\n const offsetHours = pad(Math.floor(absOffset / 60));\n const offsetMinutes = pad(absOffset % 60);\n\n return `${year}-${month}-${day}T${hours}:${minutes}:${seconds}${sign}${offsetHours}:${offsetMinutes}`;\n}\n\n/**\n * Magnitude threshold distinguishing a millisecond Unix timestamp from a\n * second Unix timestamp: values at or above this are treated as\n * milliseconds, below it as seconds.\n *\n * Chosen so that \"now\" in EITHER unit sits comfortably on its own side:\n * seconds-since-epoch for the foreseeable future stays in the ~1.7-2.5\n * billion range (1e9-1e10-ish), nowhere near 1e12, while the SAME\n * instant in milliseconds is ~1000x larger, comfortably past 1e12\n * (e.g. \"2024-12-10\" is ~1.73e9 seconds or ~1.73e12 ms). 1e12 sits well\n * clear of both real-world ranges for at least the next few centuries of\n * second-timestamps, so this is a safe, simple magnitude gate rather than\n * a fragile exact boundary.\n */\nconst MS_TIMESTAMP_THRESHOLD = 1e12;\n\n/**\n * Interpret a bare numeric Unix timestamp as epoch milliseconds, applying\n * the magnitude-based seconds-vs-milliseconds disambiguation described by\n * {@link MS_TIMESTAMP_THRESHOLD}.\n */\nexport function unixTimestampToEpochMs(n: number): number {\n return Math.abs(n) >= MS_TIMESTAMP_THRESHOLD ? n : n * 1000;\n}\n","/**\n * What the host's own locale says about the order the three groups of a\n * numeric date are written in.\n *\n * A reader who types `03/04/2026` means one of two days, and which one is a\n * question about where they are rather than about the characters. The engine\n * has never had an answer to that question, so `date.inputOrder` made the host\n * state it. This module is how a host can instead ask the machine, and it asks\n * exactly one thing: the day/month/year field order. Never the calendar\n * system, never the numbering system, never the display language, all of which\n * the engine decides for itself elsewhere.\n *\n * Asked of `Intl` rather than answered from a table of locales. A table goes\n * stale, and worse, it disagrees with the host's own date pickers on the same\n * machine: `Intl` is where the operating system's answer already lives, so it\n * is the only answer that can agree with everything else the reader sees.\n *\n * Pure `Intl`, importing nothing of the engine's. That is the constraint\n * `engine/EngineContext.ts` states for this directory: `calendar/` is imported\n * by `vm/`, which `engine/` imports, so anything here reaching back into\n * `engine/` closes a cycle. It sits beside `IntlZone.ts`, already the shared\n * \"ask Intl about zones\" module under the same rule.\n *\n * Nothing here is called unless a host asked for it. `date.inputOrder` still\n * defaults to `'auto'`, and only the value `'locale'` reaches this module, so\n * a default engine constructs no `Intl.DateTimeFormat` on this path at all.\n *\n * @module HostLocale\n */\n\n/**\n * The three field orders a Gregorian numeric date can be written in.\n *\n * Declared here rather than imported from `constants/Configuration.ts` because\n * this module may not import from the engine's layers (see the module note),\n * and because it is a narrower set than `DateInputOrder`: an inference can\n * only ever produce a concrete order, never `'auto'` and never `'locale'`.\n */\nexport type DateFieldOrder = \"DMY\" | \"MDY\" | \"YMD\";\n\n/**\n * The instant the order probe is taken on: 3 April 2026, formatted in UTC.\n *\n * A fixed instant rather than \"now\", so the probe cannot drift with the\n * machine clock or its zone, and a day and a month that are both unambiguous\n * as digits (3 and 4) so a formatter's output can be read back by field type\n * without the two being confusable.\n */\nconst PROBE_INSTANT = Date.UTC(2026, 3, 3);\n\n/**\n * The memo table, and the `Intl.DateTimeFormat` it was built against.\n *\n * The answer to both probes cannot change within one process, and the order\n * probe would otherwise run on every engine construction, so both are cached.\n * The cache is keyed on the constructor it was filled from: a test that swaps\n * `globalThis.Intl`, or a host that installs a polyfill after the first\n * engine, gets a fresh answer about the implementation it actually has rather\n * than a remembered one about a different implementation.\n */\nlet memoisedAgainst: unknown = undefined;\nlet trustworthy: boolean | undefined = undefined;\nconst orderByTag = new Map<string, DateFieldOrder | null>();\n\n/** The `Intl.DateTimeFormat` this runtime currently has, or undefined where there is none. */\nfunction currentIntl(): unknown {\n return typeof Intl === \"object\" && Intl !== null ? (Intl as { DateTimeFormat?: unknown }).DateTimeFormat : undefined;\n}\n\n/** Drops the memo table when the runtime's `Intl.DateTimeFormat` is not the one it was filled from. */\nfunction freshenMemo(): void {\n const current = currentIntl();\n if (current === memoisedAgainst) return;\n memoisedAgainst = current;\n trustworthy = undefined;\n orderByTag.clear();\n}\n\n/**\n * Whether this runtime's `Intl` carries the host's own locale data, rather\n * than one language's data answering for every locale.\n *\n * A small-ICU build resolves every requested locale to `en-US` whatever the\n * operating system says, and it does so silently: `new\n * Intl.DateTimeFormat('ja-JP')` returns a formatter that writes American\n * dates. The obvious guard, `Intl.DateTimeFormat.supportedLocalesOf([tag])`,\n * catches an unknown tag (it answers `[]` for `zz-ZZ`, while\n * `new Intl.DateTimeFormat('xx-YY').resolvedOptions().locale` cheerfully\n * answers this host's `en-GB`), but it cannot catch small ICU on the path that\n * matters: there the tag came from `resolvedOptions().locale` and is supported\n * by construction.\n *\n * So the probe asks for a locale that is certainly not English and checks what\n * comes back. A runtime that substitutes `en-US` for `ja-JP` has data that is\n * not the host's, and the caller falls back to today's behaviour rather than\n * to a fabricated month-first reading.\n *\n * @returns `true` when a Japanese request is answered in Japanese.\n */\nexport function isTrustworthyIntl(): boolean {\n freshenMemo();\n if (trustworthy !== undefined) return trustworthy;\n try {\n const probe = new Intl.DateTimeFormat(\"ja-JP\").resolvedOptions().locale;\n trustworthy = typeof probe === \"string\" && probe.startsWith(\"ja\");\n } catch {\n trustworthy = false;\n }\n return trustworthy;\n}\n\n/**\n * The BCP-47 tag this machine resolves to, `\"en-GB\"` on a UK host.\n *\n * @returns The host's tag, or `null` where `Intl` is absent or refuses to\n * answer. `null` means \"no inference is available\", never \"assume English\".\n */\nexport function hostLocale(): string | null {\n if (typeof Intl !== \"object\" || Intl === null || typeof Intl.DateTimeFormat !== \"function\") return null;\n try {\n const tag = new Intl.DateTimeFormat().resolvedOptions().locale;\n return typeof tag === \"string\" && tag.length > 0 ? tag : null;\n } catch {\n return null;\n }\n}\n\n/**\n * The day/month/year order a BCP-47 tag writes a numeric date in.\n *\n * The Gregorian calendar and Latin digits are pinned so that a locale whose\n * default calendar is Persian, Buddhist or a Japanese era still contributes\n * its field ORDER and never its calendar system or its digits: the engine\n * computes in Gregorian throughout (`calendar/Gregorian.ts`, the month names,\n * the leap-year check), so a probe about another calendar would be an answer\n * to a question the engine never asks.\n *\n * Verified on this machine (Node 24.16.0, full ICU): `en-GB` DMY, `en-US` MDY,\n * `de-DE` DMY, `fr-FR` DMY, `ja-JP` YMD, `hu-HU` YMD, `en-CA` YMD, `fa-IR`\n * YMD.\n *\n * Two guards, because they catch different lies. `supportedLocalesOf` catches\n * a tag this runtime has no data for: it answers `[]` for `zz-ZZ` and `und`\n * while `new Intl.DateTimeFormat('zz-ZZ').resolvedOptions().locale` cheerfully\n * answers this host's `en-GB`, so without it a host naming a locale the\n * runtime does not carry would be given a stranger's order. {@link\n * isTrustworthyIntl} catches the case that guard cannot see, a small-ICU build\n * answering `en-US` for everything on a tag that IS supported.\n *\n * @param tag - A BCP-47 tag, from `date.inputLocale` or from {@link hostLocale}.\n * @returns The order, or `null` where `Intl` is absent, has no data for the\n * tag, is untrustworthy ({@link isTrustworthyIntl}), throws, or produces a\n * parts list missing any of the three fields. Every one of those means the\n * same thing to the caller: there is no inference here, so keep the behaviour\n * the engine already has.\n */\nexport function orderFromLocale(tag: string): DateFieldOrder | null {\n freshenMemo();\n const cached = orderByTag.get(tag);\n if (cached !== undefined) return cached;\n const resolved = probeOrder(tag);\n orderByTag.set(tag, resolved);\n return resolved;\n}\n\n/** The uncached probe behind {@link orderFromLocale}. */\nfunction probeOrder(tag: string): DateFieldOrder | null {\n if (typeof Intl !== \"object\" || Intl === null || typeof Intl.DateTimeFormat !== \"function\") return null;\n if (!isTrustworthyIntl()) return null;\n try {\n if (typeof Intl.DateTimeFormat.supportedLocalesOf === \"function\" && Intl.DateTimeFormat.supportedLocalesOf([tag]).length === 0) {\n return null;\n }\n const parts = new Intl.DateTimeFormat(tag, {\n calendar: \"gregory\",\n numberingSystem: \"latn\",\n timeZone: \"UTC\",\n year: \"numeric\",\n month: \"numeric\",\n day: \"numeric\",\n }).formatToParts(PROBE_INSTANT);\n if (!Array.isArray(parts)) return null;\n const sequence = parts\n .filter((part) => part.type === \"year\" || part.type === \"month\" || part.type === \"day\")\n .map((part) => part.type[0].toUpperCase())\n .join(\"\");\n return sequence === \"DMY\" || sequence === \"MDY\" || sequence === \"YMD\" ? sequence : null;\n } catch {\n return null;\n }\n}\n","/**\n * How this engine reads a numeric date literal, decided once and reported.\n *\n * `03/04/2026` names one of two days, and the engine has to pick one. Which it\n * picks has always been settled by `date.inputOrder`, but nothing said so: the\n * answer came back as a date with no account of how it was read, and a host\n * had no way to show the reader \"day first\" or to discover that its own\n * setting was the reason a document looked wrong.\n *\n * This module is the one place that decision is made, so the normaliser that\n * fuses a literal and the surfaces that explain one cannot disagree about it.\n * Two halves:\n *\n * - The engine-wide one, {@link resolveDateOrderPolicy}, run once per engine\n * and reported through `ExpressionEngine.getDateReading()`. It names the\n * order AND where the order came from.\n * - The per-literal one, {@link classifyRun} and {@link readNumericDate},\n * which decide what one run of digits means under that order, and, where it\n * means nothing, whether saying so is better than answering the arithmetic\n * the run is spelled like.\n * - The sentence, {@link composeReadingNote}, which says the same thing to a\n * reader. Composed here so that five hosts do not write five different\n * sentences about one fact, and so the note a hover shows and the message a\n * refusal carries cannot drift apart.\n *\n * @module DateReading\n */\n\nimport type { DateAmbiguity, DateConfig } from \"@solve-js/constants/Configuration\";\nimport { ErrorFactory } from \"@solve-js/errors/UnifiedErrorFramework\";\nimport { hostLocale, orderFromLocale, type DateFieldOrder } from \"@solve-js/calendar/HostLocale\";\nimport type { CalendarBackend } from \"@solve-js/calendar/CalendarBackend\";\nimport { daysInMonth } from \"@solve-js/calendar/Gregorian\";\n\n/** Scoped error codes the datetime package owns (see `errors/ErrorCode.ts` convention). */\nexport const DatetimeErrorCodes = {\n /**\n * `date.inputLocale` is not a BCP-47 locale tag (`\"en_US\"` with an\n * underscore is the usual mistake). Raised at engine construction, because a\n * locale that is silently ignored is a date order that is silently wrong.\n */\n DATE_INPUT_LOCALE_INVALID: \"DATE_INPUT_LOCALE_INVALID\",\n /**\n * A date-shaped run the resolved order cannot read, which another supported\n * order can (`12/25/2026` on a day-first engine), or a year-last run on a\n * year-first engine, which has no day and month roles to apply to it. The\n * message names the order actually used, the group that broke, the reading\n * that would work, and the two ways out. A recoverable Error VALUE, never a\n * throw, and suppressed by `date.onAmbiguous: 'arithmetic'`.\n */\n DATE_ORDER_MISMATCH: \"DATE_ORDER_MISMATCH\",\n /**\n * A run whose shape is unmistakably a date attempt and which names no real\n * day under any reading: `31/04/2026`, `29/02/2026`, `13/13/2026`,\n * `2026-02-29`, `2026-13-01`. Separate from {@link DATE_ORDER_MISMATCH}\n * because no change of order fixes it, so the message must not suggest one.\n */\n DATE_NOT_A_CALENDAR_DAY: \"DATE_NOT_A_CALENDAR_DAY\",\n} as const;\n\n/** Every error code the datetime package's date-reading rules can produce. */\nexport type DatetimeErrorCode = (typeof DatetimeErrorCodes)[keyof typeof DatetimeErrorCodes];\n\n/**\n * An order a literal can actually be read under: the three concrete field\n * orders, plus `'auto'` for the historic per-separator reading.\n *\n * Narrower than `DateInputOrder` on purpose. `'locale'` is a request for an\n * inference, not an order, and it is resolved away by\n * {@link resolveDateOrderPolicy} before anything that reads a literal sees it,\n * so the word cannot reach the normaliser, a worker or a snapshot.\n */\nexport type ResolvedDateOrder = \"auto\" | DateFieldOrder;\n\n/**\n * Where a resolved order came from, which is the part a reader needs and a\n * bug report should carry.\n *\n * - `'config'`: the host named `'DMY'`, `'MDY'` or `'YMD'` outright. No\n * inference ran and `date.inputLocale` was not consulted.\n * - `'locale'`: inferred from the tag the host gave in `date.inputLocale`.\n * - `'host-locale'`: inferred from the tag this machine resolves to.\n * - `'separator'`: `'auto'`, the historic reading, where a slash date is\n * day-first and a hyphen date month-first unless it is ISO-shaped.\n * - `'fallback'`: an inference was asked for and could not be made, so the\n * engine reads dates exactly as an `'auto'` engine does. Visible on purpose:\n * this is the case where a host should offer the reader a manual choice.\n */\nexport type DateOrderSource = \"config\" | \"locale\" | \"host-locale\" | \"separator\" | \"fallback\";\n\n/**\n * The reading policy one engine applies to every numeric date literal in every\n * line it evaluates.\n *\n * Resolved once, in the `ExpressionEngine` constructor, and then carried\n * rather than re-derived: the normaliser rule runs on every keystroke, so an\n * `Intl` call per literal would be a per-keystroke cost for an answer that\n * cannot change, and a per-expression bytecode cache keyed on text would go\n * stale against an order that could.\n */\nexport interface DateReadingPolicy {\n /** The order every ambiguous numeric literal is read under. Never `'locale'`. */\n readonly order: ResolvedDateOrder;\n /** Where {@link order} came from. See {@link DateOrderSource}. */\n readonly orderSource: DateOrderSource;\n /** The BCP-47 tag the order was inferred from, when it was inferred from one. */\n readonly locale?: string;\n /** What a run no order can read does: refuse it, or leave it to arithmetic. From `date.onAmbiguous`. */\n readonly onAmbiguous: DateAmbiguity;\n}\n\n/**\n * Whether a string is a locale tag `Intl` will accept.\n *\n * Checked through `Intl.getCanonicalLocales`, which throws a `RangeError` for\n * a malformed tag (`\"en_US\"`) and accepts one it merely has no data for.\n * That is the right line to draw here: a tag with no data is a reader whose\n * locale this runtime cannot describe, which the inference already handles by\n * falling back, whereas a malformed tag is a typo in the host's own code.\n *\n * A runtime with no `Intl.getCanonicalLocales` at all accepts everything,\n * because refusing a host's configuration on the grounds that the engine\n * cannot check it would fail in the one environment least able to react.\n */\nfunction isLocaleTag(tag: string): boolean {\n if (typeof Intl !== \"object\" || Intl === null || typeof Intl.getCanonicalLocales !== \"function\") return true;\n try {\n Intl.getCanonicalLocales(tag);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Resolves a host's `date` configuration into the concrete reading policy this\n * engine applies.\n *\n * The precedence is strict, and each step decides on its own: there is no\n * merge and no \"infer, then adjust\". An override beats an inference because\n * the inference is reached only through the one value that asks for it.\n *\n * 1. `'DMY'`, `'MDY'` or `'YMD'`: that order, outright, `'config'`. No `Intl`\n * call happens and `inputLocale` is not read at all.\n * 2. `'locale'` with `inputLocale` set: the order that tag writes, `'locale'`.\n * 3. `'locale'` with `inputLocale` unset: the order this machine's tag writes,\n * `'host-locale'`.\n * 4. `'locale'` where no inference could be made: `'auto'`, `'fallback'`. This\n * is today's behaviour, which is the only safe thing to fail to.\n * 5. `'auto'`: the historic per-separator reading, `'separator'`.\n *\n * `inputLocale` is inert unless `inputOrder` is `'locale'`. Setting it beside\n * `'auto'` changes no result, because a field that quietly switched inference\n * on would turn the predictable host mistake into a wrong reading rather than\n * no change. Its SHAPE is still checked wherever it is set, since a malformed\n * tag is a typo either way and the reader is better served by hearing about it\n * at construction than by never hearing about it.\n *\n * @param date - The engine's merged `date` configuration.\n * @returns The policy, frozen.\n * @throws {EngineError} `DATE_INPUT_LOCALE_INVALID` when `inputLocale` is set\n * and is not a tag `Intl` accepts.\n */\nexport function resolveDateOrderPolicy(date: DateConfig): DateReadingPolicy {\n const requestedLocale = date.inputLocale;\n if (requestedLocale !== undefined && !isLocaleTag(requestedLocale)) {\n throw ErrorFactory.config(\n DatetimeErrorCodes.DATE_INPUT_LOCALE_INVALID,\n `date.inputLocale \"${requestedLocale}\" is not a BCP-47 locale tag. Use a tag Intl accepts, for example \"en-US\".`,\n { inputLocale: requestedLocale },\n );\n }\n\n const onAmbiguous = date.onAmbiguous;\n const order = date.inputOrder;\n if (order === \"DMY\" || order === \"MDY\" || order === \"YMD\") {\n return Object.freeze({ order, orderSource: \"config\" as const, onAmbiguous });\n }\n\n if (order === \"locale\") {\n const tag = requestedLocale ?? hostLocale();\n if (tag !== null && tag !== undefined) {\n const inferred = orderFromLocale(tag);\n if (inferred !== null) {\n return Object.freeze({\n order: inferred,\n orderSource: requestedLocale !== undefined ? (\"locale\" as const) : (\"host-locale\" as const),\n locale: tag,\n onAmbiguous,\n });\n }\n }\n // No Intl, an Intl that answers for a locale that is not the host's, or a\n // tag it cannot describe. Fall back to what the engine already does rather\n // than to a guess, and say so, so a host can tell a decision from a guess.\n return Object.freeze({ order: \"auto\" as const, orderSource: \"fallback\" as const, onAmbiguous });\n }\n\n return Object.freeze({ order: \"auto\" as const, orderSource: \"separator\" as const, onAmbiguous });\n}\n\n/**\n * Month names, in English, used to say what is wrong with a date that names no\n * real day (\"February 2026 has 28 days\").\n *\n * English-only for the same reason `DatetimeTimestampPluginFunctions.ts`'s\n * weekday names are: every `explainLine` description and every structured\n * error message in the engine is English, and localising one sentence in the\n * middle of that would be less coherent than localising none.\n */\nexport const MONTH_NAMES = [\n \"January\", \"February\", \"March\", \"April\", \"May\", \"June\",\n \"July\", \"August\", \"September\", \"October\", \"November\", \"December\",\n];\n\n/** The separator a numeric date run was written with. */\nexport type NumericDateSeparator = \"slash\" | \"hyphen\" | \"dot\";\n\n/**\n * The shape of a three-group numeric run, decided by the digit counts alone\n * before any order is consulted.\n *\n * The shape is what decides whether an unreadable run refuses or falls through\n * to arithmetic, and the asymmetry between the two four-digit shapes is\n * deliberate and measured:\n *\n * - `'iso'`: a hyphen run with a four-digit LEADING group, `2026-04-03`. One\n * reading, whatever the order, and nothing configurable applies.\n * - `'year-last-4'`: `03/04/2026`, `12-25-2026`. Refuses when no reading\n * works, because nobody writes a two-step division ending in a four-digit\n * denominator: `03/04/2026` as arithmetic is 0.0004.\n * - `'year-first-4'`: `2026/04/03`, `1000/10/5`. A date under `'YMD'` alone\n * and ordinary arithmetic under every other order, exactly as today. This is\n * where division is protected: `1000/10/5` is 20, `1024/8/2` is 64,\n * `1000/12/4` is 20.83 and `2000/12/25` is 6.67, and a rule that claimed\n * them would be a worse bug than the one being fixed.\n * - `'short'`: every group one or two digits, `1/2/3`, `12/13/14`,\n * `25/12/23`. Today's reading exactly, falling through to arithmetic when it\n * does not resolve, because a two-digit year is too weak a signal to hang a\n * refusal on.\n * - `'none'`: `100/25/2`, `1000-500-200`. Never a date.\n */\nexport type NumericDateShape = \"iso\" | \"year-last-4\" | \"year-first-4\" | \"short\" | \"none\";\n\n/** One or two digits: a day or a month group. */\nconst DAY_OR_MONTH_GROUP = /^\\d{1,2}$/;\n/** Exactly four digits: a written-out year. */\nconst FULL_YEAR_GROUP = /^\\d{4}$/;\n\n/**\n * Classifies a three-group numeric run by its digit counts and separator.\n *\n * Decided before any order is consulted, so the same run has the same shape on\n * every engine and only what the shape MEANS depends on configuration.\n *\n * @param g0 - The first group, as typed.\n * @param g1 - The second group.\n * @param g2 - The third group.\n * @param separator - The separator between them.\n * @returns The shape. See {@link NumericDateShape}.\n */\nexport function classifyRun(\n g0: string,\n g1: string,\n g2: string,\n separator: NumericDateSeparator,\n): NumericDateShape {\n const shortFirst = DAY_OR_MONTH_GROUP.test(g0);\n const shortMiddle = DAY_OR_MONTH_GROUP.test(g1);\n const shortLast = DAY_OR_MONTH_GROUP.test(g2);\n if (separator === \"hyphen\" && FULL_YEAR_GROUP.test(g0) && shortMiddle && shortLast) return \"iso\";\n if (shortFirst && shortMiddle && FULL_YEAR_GROUP.test(g2)) return \"year-last-4\";\n if (separator === \"slash\" && FULL_YEAR_GROUP.test(g0) && shortMiddle && shortLast) return \"year-first-4\";\n if (shortFirst && shortMiddle && shortLast) return \"short\";\n return \"none\";\n}\n\n/** The three groups of a numeric run, with the text they were typed as. */\nexport interface NumericDateRun {\n /** The run exactly as typed, `\"03/04/2026\"`, for the message. */\n readonly text: string;\n /** The three groups, left to right, as typed. */\n readonly groups: readonly [string, string, string];\n readonly separator: NumericDateSeparator;\n}\n\n/**\n * What reading a numeric run came to: a real day, a refusal to report, or a\n * decision to leave the run to ordinary arithmetic.\n */\nexport type NumericDateRead =\n | {\n readonly kind: \"date\";\n readonly day: number;\n readonly month: number;\n readonly year: number;\n /** The order actually applied: one of the three, or `'ISO'` for a run that settled itself. */\n readonly order: DateFieldOrder | \"ISO\";\n /** Whether a two-digit year was windowed to a century. */\n readonly shortYear: boolean;\n /** The ISO of the reading NOT taken, when the other order names a DIFFERENT real day. */\n readonly alternative?: string;\n }\n | { readonly kind: \"refuse\"; readonly code: DatetimeErrorCode; readonly message: string }\n | { readonly kind: \"arithmetic\" };\n\n/**\n * A two-digit year, windowed to a century by the common glibc\n * `strptime(\"%y\")` convention: 00-68 is 2000-2068, 69-99 is 1969-1999. Four\n * digits are taken as written; any other count is not a year shape at all.\n */\nfunction resolveYearGroup(digits: string): number | null {\n if (digits.length === 4) return Number(digits);\n if (digits.length === 2) {\n const yy = Number(digits);\n return yy <= 68 ? 2000 + yy : 1900 + yy;\n }\n return null;\n}\n\n/**\n * Whether a day/month/year triple names a day the calendar actually has.\n *\n * Checked through the backend rather than by arithmetic here, so a run is\n * judged by the same calendar the literal would be built with. February 30\n * rolls over to March 2 in every implementation, and a rollover is how a\n * triple that is not a date announces itself.\n *\n * @param day - Day of the month, from 1.\n * @param month - Month, from 1.\n * @param year - The full year.\n * @param calendar - The backend the literal would be built with.\n * @returns `true` when the triple reads back unchanged.\n */\nexport function isRealCalendarDay(day: number, month: number, year: number): boolean {\n // Counted rather than round-tripped through the backend. Building the day\n // and reading it back went through `Date`'s two-digit-year window, which\n // maps year 26 to 1926, so every year below 100 was declared unreal and\n // `0026-04-03` was refused with \"April 0026 has 30 days\", which is true and\n // is exactly why it should have been accepted.\n if (month < 1 || month > 12 || day < 1) return false;\n return day <= daysInMonth(year, month - 1);\n}\n\n/**\n * Why a day/month/year triple names no real day, as the clause a message ends\n * with: \"there is no month 25\", \"February 2026 has 28 days\".\n *\n * @param day - Day of the month.\n * @param month - Month, from 1.\n * @param year - The full year.\n * @returns The clause. Callers check {@link isRealCalendarDay} first; a triple\n * that IS a real day is described by its month's true length, which says\n * nothing wrong but says nothing useful either.\n */\nexport function describeUnrealDay(day: number, month: number, year: number): string {\n if (month < 1 || month > 12) return `there is no month ${month}`;\n if (day < 1) return `there is no day ${day}`;\n return `${MONTH_NAMES[month - 1]} ${year} has ${daysInMonth(year, month - 1)} days`;\n}\n\n/** A day/month/year triple written out for a reader: \"3 April 2026\". */\nfunction spellDay(day: number, month: number, year: number): string {\n return `${day} ${MONTH_NAMES[month - 1]} ${year}`;\n}\n\n/**\n * A day/month/year triple as an ISO date, `\"2026-04-03\"`: the one spelling\n * every order reads the same way, which is what a refusal points at.\n *\n * @param day - Day of the month.\n * @param month - Month, from 1.\n * @param year - The full year.\n * @returns The ISO date.\n */\nexport function isoOf(day: number, month: number, year: number): string {\n const pad = (n: number) => String(n).padStart(2, \"0\");\n return `${String(year).padStart(4, \"0\")}-${pad(month)}-${pad(day)}`;\n}\n\n/** The day and month a two-role order assigns to the first two groups. */\nfunction rolesFor(order: DateFieldOrder, g0: string, g1: string): { day: number; month: number } {\n return order === \"DMY\"\n ? { day: Number(g0), month: Number(g1) }\n : { day: Number(g1), month: Number(g0) };\n}\n\n/** \"day first\" / \"month first\" / \"year first\", the way a message names an order. */\nfunction orderInWords(order: DateFieldOrder): string {\n if (order === \"DMY\") return \"day first\";\n if (order === \"MDY\") return \"month first\";\n return \"year first\";\n}\n\n/**\n * The order `'auto'` reads a two-role run in, which is the historic\n * per-separator behaviour: a slash date is day-first (`25/12/2023`), a hyphen\n * date is month-first (`12-25-2023`), and a dot date is day-first\n * (`25.12.2023`), which is what each of those spellings meant before an order\n * could be configured at all.\n */\nfunction separatorOrder(separator: NumericDateSeparator): DateFieldOrder {\n return separator === \"hyphen\" ? \"MDY\" : \"DMY\";\n}\n\n/**\n * Reads a three-group numeric run under one engine's resolved order.\n *\n * The one place the decision is made, so the normaliser that fuses a literal\n * and the surfaces that explain one cannot disagree about it.\n *\n * A run that no reading resolves is either refused or left to arithmetic, and\n * which of the two is a question about the SHAPE rather than about which guard\n * declined it. See {@link NumericDateShape} for the four shapes and the\n * measurements behind the asymmetry.\n *\n * @param run - The run, its groups and its separator.\n * @param order - This engine's resolved order. Never `'locale'`.\n * @param onAmbiguous - Whether a refusal is reported or suppressed. A dot run\n * ignores `'arithmetic'`, because its fall-through is a parse error rather\n * than a number, and an error is not an answer; for the same reason a dot run\n * of the `'short'` shape refuses too, where a slash or hyphen one falls\n * through.\n * @param calendar - The backend the literal would be built with.\n * @returns The reading, a refusal, or a decision to leave the run alone.\n */\nexport function readNumericDate(\n run: NumericDateRun,\n order: ResolvedDateOrder,\n onAmbiguous: DateAmbiguity,\n calendar: CalendarBackend,\n): NumericDateRead {\n const [g0, g1, g2] = run.groups;\n const shape = classifyRun(g0, g1, g2, run.separator);\n // A dot run has nothing to fall through TO. The lexer has already merged\n // `25.12` into one float-shaped token, so a dot run that is not a date is a\n // parse error rather than a number, and the house rule forbids an error as\n // an answer. Both escapes therefore close for it: `onAmbiguous` cannot\n // restore an answer that never existed, and the `'short'` shape's\n // fall-through has no arithmetic to protect (`12.13.14` written with dots is\n // not a fraction chain, it is a parse error).\n const canFallThrough = run.separator !== \"dot\";\n const refusing = onAmbiguous === \"refuse\" || !canFallThrough;\n\n if (shape === \"none\") return { kind: \"arithmetic\" };\n\n if (shape === \"iso\") {\n const year = Number(g0);\n const month = Number(g1);\n const day = Number(g2);\n if (isRealCalendarDay(day, month, year)) {\n return { kind: \"date\", day, month, year, order: \"ISO\", shortYear: false };\n }\n // The shape has one reading and no other to fall to, so a rollover here is\n // a date attempt that failed rather than arithmetic that looked like one.\n return refusing ? notACalendarDay(run.text, day, month, year) : { kind: \"arithmetic\" };\n }\n\n if (shape === \"year-first-4\") {\n if (order !== \"YMD\") return { kind: \"arithmetic\" };\n const year = Number(g0);\n const month = Number(g1);\n const day = Number(g2);\n // Still arithmetic when it is not a real day: a four-digit numerator is\n // ordinary division, and this shape is where that is protected.\n return isRealCalendarDay(day, month, year)\n ? { kind: \"date\", day, month, year, order: \"YMD\", shortYear: false }\n : { kind: \"arithmetic\" };\n }\n\n // 'year-last-4' and 'short' share their readings and differ only in what\n // happens when none of them works.\n const year = resolveYearGroup(g2);\n if (year === null) return { kind: \"arithmetic\" };\n const shortYear = g2.length === 2;\n\n if (order === \"YMD\") {\n // A year-last run has no year-first reading at all, so there are no roles\n // that failed, there are no roles to apply.\n if (!refusing || (shape === \"short\" && canFallThrough)) return { kind: \"arithmetic\" };\n return orderMismatchUnderYearFirst(run.text, g0, g1, year, calendar);\n }\n\n const chosen = order === \"auto\" ? separatorOrder(run.separator) : order;\n const other: DateFieldOrder = chosen === \"DMY\" ? \"MDY\" : \"DMY\";\n const chosenRoles = rolesFor(chosen, g0, g1);\n const otherRoles = rolesFor(other, g0, g1);\n\n if (isRealCalendarDay(chosenRoles.day, chosenRoles.month, year)) {\n // The other reading only counts as an alternative when it names a\n // DIFFERENT day. `01/01/2026` reads the same way round either way, so it\n // is not a choice the reader needs to be told about.\n const differs = otherRoles.day !== chosenRoles.day || otherRoles.month !== chosenRoles.month;\n const alternative = differs && isRealCalendarDay(otherRoles.day, otherRoles.month, year)\n ? isoOf(otherRoles.day, otherRoles.month, year)\n : undefined;\n return { kind: \"date\", day: chosenRoles.day, month: chosenRoles.month, year, order: chosen, shortYear, alternative };\n }\n\n if (!refusing || (shape === \"short\" && canFallThrough)) return { kind: \"arithmetic\" };\n\n if (isRealCalendarDay(otherRoles.day, otherRoles.month, year)) {\n return {\n kind: \"refuse\",\n code: DatetimeErrorCodes.DATE_ORDER_MISMATCH,\n message:\n `\"${run.text}\" is not a date read ${orderInWords(chosen)}: ` +\n `${describeUnrealDay(chosenRoles.day, chosenRoles.month, year)}. ` +\n `Read ${orderInWords(other)} it is ${spellDay(otherRoles.day, otherRoles.month, year)}. ` +\n `Set date.inputOrder to \"${other}\" to read numeric dates ${orderInWords(other)}.`,\n };\n }\n\n // Neither order names a real day, so no change of order fixes it and the\n // message must not suggest one.\n return notACalendarDay(run.text, chosenRoles.day, chosenRoles.month, year);\n}\n\n/** The DATE_NOT_A_CALENDAR_DAY refusal, worded from the reading that was attempted. */\nfunction notACalendarDay(text: string, day: number, month: number, year: number): NumericDateRead {\n return {\n kind: \"refuse\",\n code: DatetimeErrorCodes.DATE_NOT_A_CALENDAR_DAY,\n message: `\"${text}\" is not a real date: ${describeUnrealDay(day, month, year)}.`,\n };\n}\n\n/**\n * The refusal for a year-last run on a year-first engine, which has no roles\n * to apply to it. Names whichever of the two readings are real days, and the\n * ISO spelling that reads the same way on every engine.\n */\nfunction orderMismatchUnderYearFirst(\n text: string,\n g0: string,\n g1: string,\n year: number,\n calendar: CalendarBackend,\n): NumericDateRead {\n const dayFirst = rolesFor(\"DMY\", g0, g1);\n const monthFirst = rolesFor(\"MDY\", g0, g1);\n const dayFirstReal = isRealCalendarDay(dayFirst.day, dayFirst.month, year);\n const monthFirstReal = isRealCalendarDay(monthFirst.day, monthFirst.month, year);\n\n if (!dayFirstReal && !monthFirstReal) {\n return notACalendarDay(text, dayFirst.day, dayFirst.month, year);\n }\n\n const opening = `\"${text}\" is not a date read year first.`;\n // Both readings can name the SAME day (`03/03/2026`), and offering it twice\n // read as a bug in the sentence rather than as advice. One reading, said once.\n const sameDay = dayFirst.day === monthFirst.day && dayFirst.month === monthFirst.month;\n if (dayFirstReal && monthFirstReal && !sameDay) {\n return {\n kind: \"refuse\",\n code: DatetimeErrorCodes.DATE_ORDER_MISMATCH,\n message:\n `${opening} Read day first it is ${spellDay(dayFirst.day, dayFirst.month, year)} ` +\n `and month first ${spellDay(monthFirst.day, monthFirst.month, year)}. ` +\n `Write it as ${isoOf(dayFirst.day, dayFirst.month, year)}, ` +\n `or set date.inputOrder to \"DMY\" or \"MDY\".`,\n };\n }\n\n const roles = dayFirstReal ? dayFirst : monthFirst;\n const which: DateFieldOrder = dayFirstReal ? \"DMY\" : \"MDY\";\n return {\n kind: \"refuse\",\n code: DatetimeErrorCodes.DATE_ORDER_MISMATCH,\n message:\n `${opening} Read ${orderInWords(which)} it is ${spellDay(roles.day, roles.month, year)}. ` +\n `Write it as ${isoOf(roles.day, roles.month, year)}, or set date.inputOrder to \"${which}\".`,\n };\n}\n\n/**\n * How one date literal in one line was read, with the span it occupies and a\n * sentence a host can show.\n *\n * Derived, never stored. A line can hold two literals\n * (`31/12/2026 - 01/01/2026`), which one value cannot represent, and a derived\n * date (`03/04/2026 + 1 day`) is no longer the literal that was read, so a\n * reading recorded on the answer would be right for the common line and\n * quietly wrong for the rest. It costs a re-lex of the lines a reader actually\n * asks about, and nothing at all on the rest.\n */\nexport interface DateReading {\n /** The literal exactly as typed, `\"03/04/2026\"`. */\n readonly text: string;\n /** Offset of the first character in the line, for an editor underline. */\n readonly start: number;\n /** Offset one past the last character. */\n readonly end: number;\n /** The day it was read as, `\"2026-04-03\"`, or null when the literal was refused. */\n readonly iso: string | null;\n /** The order actually applied, or null when no order could be. */\n readonly order: DateFieldOrder | \"ISO\" | \"spelled\" | null;\n /** Where that order came from. `'iso'` and `'spelled'` mean the literal settled itself. */\n readonly orderSource: DateOrderSource | \"iso\" | \"spelled\";\n /** The BCP-47 tag the order was inferred from, when it was inferred from one. */\n readonly locale?: string;\n /** Whether the other order also names a real day, so the reading is a genuine choice. */\n readonly contested: boolean;\n /** Whether a two-digit year was windowed to a century. */\n readonly shortYear: boolean;\n /** The ISO of the reading not taken, when {@link contested}. */\n readonly alternative?: string;\n /** The error code, when the literal was refused. */\n readonly problem?: DatetimeErrorCode;\n /**\n * The sentence a host shows, composed here rather than assembled by each\n * host from the parts, so five hosts do not write five different sentences\n * about one fact.\n */\n readonly note: string;\n /**\n * Whether the note is worth showing: the reading was contested, a two-digit\n * year was windowed, or the literal was refused. A boolean the engine\n * computes rather than a judgement each host re-derives, which is what stops\n * the note being either wallpaper or absent.\n */\n readonly needsNote: boolean;\n}\n\n/** Everything about a reading except the two fields composed from the rest. */\nexport type DateReadingFacts = Omit<DateReading, \"note\" | \"needsNote\">;\n\n/**\n * How the reading came to be, as the clause that follows the day in a note.\n *\n * The separator is named only where the order came from it, because that is\n * the one case where the reader's next question is \"why day first\" and the\n * honest answer is \"because you wrote a slash\".\n */\nfunction sourceInWords(facts: DateReadingFacts, separator: NumericDateSeparator): string {\n if (facts.orderSource === \"iso\") return \"ISO\";\n if (facts.orderSource === \"spelled\") return \"with the month spelled out\";\n // A refused literal has no order to name, and the two shapes that settle\n // themselves have already returned, so this only guards the type.\n const order = facts.order === null || facts.order === \"ISO\" || facts.order === \"spelled\"\n ? \"as written\"\n : orderInWords(facts.order);\n switch (facts.orderSource) {\n case \"config\":\n return `${order}, from date.inputOrder`;\n case \"locale\":\n return `${order}, from the locale ${facts.locale}`;\n case \"host-locale\":\n return `${order}, from the host locale ${facts.locale}`;\n case \"fallback\":\n return `${order}, the default for a ${separator} date, because the host locale could not be read`;\n default:\n return `${order}, the default for a ${separator} date`;\n }\n}\n\n/** An ISO date written out for a reader: `\"2026-03-04\"` becomes `\"4 March 2026\"`. */\nfunction spellIso(iso: string): string {\n const [year, month, day] = iso.split(\"-\").map(Number);\n return spellDay(day, month, year);\n}\n\n/**\n * Composes the sentence a host shows for one reading.\n *\n * In the house voice and in one place, so the note a hover shows and the\n * message a refusal carries are one story told in two situations rather than\n * two mechanisms that can drift:\n *\n * 03/04/2026 read as 3 April 2026, day first, from the host locale en-GB.\n * Month first would be 4 March 2026.\n *\n * @param facts - The decided reading.\n * @param separator - The separator the literal was written with, for the\n * `'auto'` wording.\n * @param refusal - The refusal message, when the literal was refused. It IS\n * the note in that case: there is no reading to describe.\n * @returns The sentence.\n */\nexport function composeReadingNote(\n facts: DateReadingFacts,\n separator: NumericDateSeparator,\n refusal?: string,\n): string {\n if (facts.iso === null) return refusal ?? `\"${facts.text}\" is not a date this engine can read.`;\n let note = `${facts.text} read as ${spellIso(facts.iso)}, ${sourceInWords(facts, separator)}.`;\n if (facts.alternative !== undefined && facts.order !== null && facts.order !== \"ISO\" && facts.order !== \"spelled\") {\n const other = facts.order === \"DMY\" ? \"Month first\" : \"Day first\";\n note += ` ${other} would be ${spellIso(facts.alternative)}.`;\n }\n if (facts.shortYear) {\n note += ` The two-digit year ${facts.text.slice(-2)} was read as ${facts.iso.slice(0, 4)}.`;\n }\n return note;\n}\n\n/**\n * Completes a reading with the two fields derived from the rest: the sentence\n * and whether it is worth showing.\n *\n * @param facts - The decided reading.\n * @param separator - The separator the literal was written with.\n * @param refusal - The refusal message, when the literal was refused.\n * @returns The whole record.\n */\nexport function completeDateReading(\n facts: DateReadingFacts,\n separator: NumericDateSeparator,\n refusal?: string,\n): DateReading {\n return {\n ...facts,\n note: composeReadingNote(facts, separator, refusal),\n needsNote: facts.contested || facts.shortYear || facts.iso === null,\n };\n}\n\n/**\n * Splits a fused literal's source text back into the groups and separator\n * {@link readNumericDate} takes, or null where the text is not a three-group\n * numeric run at all (a spelled-out month, an ISO timestamp).\n *\n * Reading the text back rather than remembering the groups is what lets the\n * explanation surfaces reach the same answer through the same function the\n * normaliser used, with no reading table carried on the bytecode and no\n * snapshot format change.\n *\n * @param text - The literal exactly as typed.\n * @returns The run, or null.\n */\nexport function splitNumericRun(text: string): NumericDateRun | null {\n const separated = /^(\\d+)([/-])(\\d+)\\2(\\d+)$/.exec(text);\n if (separated !== null) {\n return {\n text,\n groups: [separated[1], separated[3], separated[4]],\n separator: separated[2] === \"-\" ? \"hyphen\" : \"slash\",\n };\n }\n const dotted = /^(\\d{1,2})\\.(\\d{1,2})\\.(\\d{2}|\\d{4})$/.exec(text);\n if (dotted !== null) {\n return { text, groups: [dotted[1], dotted[2], dotted[3]], separator: \"dot\" };\n }\n return null;\n}\n","import type { Token } from \"@solve-js/lexer/Token\";\nimport { tokenTypeId } from \"@solve-js/lexer/Token\";\nimport { LexerToken } from \"@solve-js/lexer/ExpressionLexer\";\nimport type { NormalizerRule, NormalizerMatch } from \"@solve-js/normalizer/NormalizerRule\";\nimport { parseIso8601 } from \"@solve-js/packages/datetime/Iso8601\";\nimport {\n readNumericDate,\n type DatetimeErrorCode,\n type NumericDateSeparator,\n type ResolvedDateOrder,\n} from \"../DateReading\";\nimport type { DateAmbiguity } from \"@solve-js/constants/Configuration\";\nimport type { CalendarBackend } from \"@solve-js/calendar/CalendarBackend\";\nimport { DATE_CALENDAR } from \"@solve-js/calendar/DateCalendar\";\n\n/**\n * Token type a fused date literal is rewritten to.\n *\n * One type covers every supported ordering, so the parselet handles the shape\n * rather than the locale.\n */\nexport const DATETIME_LITERAL_TYPE = \"DATETIME_LITERAL\";\nconst DATETIME_LITERAL_TYPE_ID = tokenTypeId(DATETIME_LITERAL_TYPE);\n\n/**\n * Token type a date-shaped run that no configured order can read is rewritten\n * to, carrying the code and the message rather than a value.\n *\n * A separate type rather than a flag on the literal above, so the parselet for\n * each is the shape of what it does: one pushes a date, the other reports a\n * fault. `UnreadableDateParselet` compiles it to a plugin call returning an\n * Error VALUE, which is what keeps a refusal off the throwing path and out of\n * the bytecode format: no new opcode, no operand change, and\n * `SNAPSHOT_VERSION` untouched.\n */\nexport const DATETIME_LITERAL_UNREADABLE_TYPE = \"DATETIME_LITERAL_UNREADABLE\";\nconst DATETIME_LITERAL_UNREADABLE_TYPE_ID = tokenTypeId(DATETIME_LITERAL_UNREADABLE_TYPE);\n\n/** A pure digit string, guards against fusing hex/scientific/bigint-suffixed NUMBER tokens. */\nconst PLAIN_INTEGER = /^\\d+$/;\n\n/** First NUMBER token of a dot-separated literal: the lexer's decimal scanner\n * merges \"DD.MM\" into one float-shaped token (see module doc below). */\nconst DOT_DAY_MONTH = /^\\d{1,2}\\.\\d{1,2}$/;\n\n/** Second NUMBER token of a dot-separated literal: the lexer re-enters\n * tokenizeNumber() AT the second dot, so the year keeps its leading dot. */\nconst DOT_LEADING_YEAR = /^\\.(\\d{2}|\\d{4})$/;\n\n/**\n * Whether every token in a run touches the next one in the source text, with\n * no whitespace anywhere between the first character and the last.\n *\n * This is the whole basis for telling a date literal apart from the\n * arithmetic it is spelled identically to. A date is written as one\n * uninterrupted run (\"2024-5-3\"); a subtraction chain is written with spaces\n * around its operators (\"2024 - 5 - 3\"). The lexer records that difference in\n * the token offsets and nowhere else, since the tokens themselves are the same\n * five either way:\n *\n * 2024-5-3 NUMBER@0 MINUS@4 NUMBER@5 MINUS@6 NUMBER@7\n * 2024 - 5 - 3 NUMBER@0 MINUS@5 NUMBER@7 MINUS@9 NUMBER@11\n *\n * The same technique, for the same reason, is what tells \"5k\" from \"5 k\" in\n * `arithmetic/normalizer/LargeNumberSuffixNormalizerRule.ts`.\n *\n * ## Why this replaced a zero-padding requirement on the ISO branch\n * The ISO branch briefly required its month and day groups to be padded to two\n * digits, which did stop \"2024 - 5 - 3\" being answered as \"Friday, May 3,\n * 2024\" but also stopped \"2024-5-3\" being a date at all. Padding was never the\n * real distinction, and the rule's own US branch is the proof: it has always\n * accepted unpadded groups, so \"1-1-2020\" and \"12-25-2023\" are both dates\n * today. Requiring padding on one branch of the two was therefore an\n * inconsistency between two spellings of one rule rather than a policy.\n *\n * The US branch's own guard is a 2-or-4-digit trailing year plus the calendar\n * check, and it is NOT safe against spaced arithmetic on its own: before this\n * check existed, \"12 - 25 - 2023\" answered Christmas 2023 instead of -2036,\n * and \"1 - 1 - 2020\" answered New Year's Day instead of -2020. Applying\n * adjacency to the whole run rather than to one branch fixes that at the same\n * time and leaves both branches resting on the same reason.\n *\n * ## Padded but spaced\n * \"2024 - 05 - 03\" is subtraction under this check, and that is the intended\n * reading. Nobody types the spaces when they mean the date, so the spacing is\n * the clearest signal available about which was meant, and the padding is not:\n * a person subtracting may well write \"05\" for the same reason they write\n * \"05\" anywhere else. Choosing the date there would mean no spelling of that\n * subtraction existed.\n *\n * `sourceEnd` is preferred over `text.length` where it is set, because a token\n * an earlier rule fused carries replacement text rather than source text and\n * only `sourceEnd` still describes the span it covers (see\n * `normalizer/TokenNormalizer.ts`'s `createFusedToken`).\n */\nfunction writtenAsOneRun(tokens: Token[]): boolean {\n for (let i = 0; i < tokens.length - 1; i++) {\n const token = tokens[i];\n const end = token.sourceEnd ?? token.offset + token.text.length;\n if (end !== tokens[i + 1].offset) return false;\n }\n return true;\n}\n\n/**\n * Converts a validated day/month/year triple into a fused DATETIME_LITERAL\n * token, or null if the triple isn't a real calendar date (e.g. \"30\" for\n * February), letting the caller fall back to treating the source tokens\n * as ordinary arithmetic instead of a date.\n *\n * `calendar` is the backend the literal's local midnight is built with.\n */\nexport function buildDateToken(\n day: number,\n month: number,\n year: number,\n sourceTokens: Token[],\n ruleName: string,\n calendar: CalendarBackend,\n): NormalizerMatch | null {\n if (month < 1 || month > 12 || day < 1 || day > 31) return null;\n\n // Local midnight, consistent with formatDatetime()'s display and the\n // DATE_NOW epoch, both of which are local-time.\n const epochMs = calendar.localMidnight(year, month - 1, day);\n // Reject calendar rollover (e.g. day=30 in February) rather than silently\n // normalizing to March 2, a rollover almost always means the tokens were\n // never a date to begin with (e.g. \"2-30-5\" as chained subtraction).\n const built = calendar.fields(epochMs);\n if (built.year !== year || built.month0 !== month - 1 || built.day !== day) {\n return null;\n }\n\n const first = sourceTokens[0];\n const text = sourceTokens.map((t) => t.value).join(\"\");\n const fusedToken = new LexerToken(\n DATETIME_LITERAL_TYPE,\n DATETIME_LITERAL_TYPE_ID,\n String(epochMs),\n text,\n first.offset,\n 0,\n first.line,\n first.col,\n );\n\n return { consumed: sourceTokens.length, replacement: [fusedToken], ruleName };\n}\n\n/**\n * The source text a run of tokens covers, with one space wherever the tokens\n * were not written touching.\n *\n * Reconstructed from the token offsets because a normaliser rule is handed\n * tokens rather than the line they came from, and a refusal has to quote what\n * the reader typed: `\"29 February 2026\"` and `\"March 9, 2024\"` read back the\n * way they were written, while an adjacent run like `\"03/04/2026\"` reads back\n * with nothing added.\n *\n * @param tokens - The run.\n * @returns The reconstructed text.\n */\nexport function runText(tokens: Token[]): string {\n let out = \"\";\n let previousEnd = -1;\n for (const token of tokens) {\n const text = token.text ?? token.value;\n if (previousEnd >= 0 && token.offset > previousEnd) out += \" \";\n out += text;\n previousEnd = token.sourceEnd ?? token.offset + text.length;\n }\n return out;\n}\n\n/**\n * Fuses a run that names no readable date into one\n * {@link DATETIME_LITERAL_UNREADABLE_TYPE} token carrying the refusal.\n *\n * The code and message travel as JSON in the token's `value`, which is the\n * only field a fused token has to carry a payload in, and `text` keeps the\n * run exactly as typed so an editor still underlines what the reader wrote.\n *\n * Consuming the run rather than declining it is the whole point: declining\n * would hand the same five tokens back to the parser, which reads them as the\n * division they are spelled like, and answering 0.0004 for a date is the\n * behaviour being fixed.\n *\n * @param code - The refusal's error code.\n * @param message - The sentence the reader sees.\n * @param sourceTokens - The run being replaced.\n * @param ruleName - The rule name, for normaliser bookkeeping.\n * @returns The match.\n */\nexport function faultMatch(\n code: DatetimeErrorCode,\n message: string,\n sourceTokens: Token[],\n ruleName: string,\n): NormalizerMatch {\n const first = sourceTokens[0];\n const text = runText(sourceTokens);\n const fusedToken = new LexerToken(\n DATETIME_LITERAL_UNREADABLE_TYPE,\n DATETIME_LITERAL_UNREADABLE_TYPE_ID,\n text,\n text,\n first.offset,\n 0,\n first.line,\n first.col,\n );\n // The reason travels on the token: `value` is what a parse error and the\n // editor token API print, and a reader shown the engine's JSON is being\n // shown its internals.\n fusedToken.fault = { code, message };\n return { consumed: sourceTokens.length, replacement: [fusedToken], ruleName };\n}\n\n/**\n * A full ISO 8601 timestamp: an ISO date with a time of day, optionally\n * carrying a UTC offset or the `Z` that means one of zero.\n *\n * Anchored at the start and deliberately greedy about the offset, so\n * `...T15:30:00+11:00` matches through the offset rather than stopping at the\n * seconds and leaving `+11:00` behind as an addition. That is what the bare\n * form used to do: `2019-04-01T15:30:00+11:00` read the offset as a clock time\n * being ADDED to the date on its left, and answered today at 11:00. Both\n * halves of that were wrong and neither was visible, which is worse than the\n * bare form simply not being supported.\n *\n * The time of day is required. Without it this would match what the date-only\n * branches below already handle, and they carry the ambiguity rules\n * (adjacency, group shapes) that keep a subtraction chain a subtraction.\n *\n * Matched against reconstructed source text rather than token by token. The\n * lexer has no idea this is one literal, so it emits nine to fourteen tokens\n * for it with the shape depending on the spelling (`T15` arrives as an\n * identifier, `Z` as another, an offset as a PLUS or MINUS with two more\n * numbers), and enumerating those permutations in token patterns is how a\n * spelling gets missed.\n *\n * `T` and `Z` are uppercase only, matching `Iso8601.ts`'s own pattern, which is\n * what actually parses the match. Accepting a spelling here that the parser\n * then refuses would mean the bare form supported more shapes than the quoted\n * one, for no reason a reader could infer.\n */\nconst ISO_TIMESTAMP = /^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}(:\\d{2}(\\.\\d+)?)?(Z|[+-]\\d{2}:?\\d{2})?/;\n\n/**\n * Token types a run of ISO 8601 timestamp text can lex into. Anything else\n * ends the run, so the reconstruction below can never reach across an operator\n * or a word that is not part of the literal.\n */\nconst ISO_TOKEN_TYPES = new Set([\"NUMBER\", \"MINUS\", \"PLUS\", \"COLON\", \"IDENT\"]);\n\n/**\n * How many tokens the longest supported spelling occupies. `2019-04-01T15:30:00.123+11:00`\n * is fourteen; the cap only bounds the walk, since the match itself decides\n * where the literal ends.\n */\nconst ISO_MAX_TOKENS = 16;\n\n/**\n * Fuses a bare (unquoted) ISO 8601 timestamp into one DATETIME_LITERAL.\n *\n * `Iso8601.ts` could always parse this shape, and still does the parsing here;\n * what it said could not be done without \"a much larger, dedicated lexer\n * change\" was recognising the bare form, on the grounds that it is ambiguous\n * with arithmetic. The date half of that ambiguity was settled by the rule this\n * helper sits inside (a date is written as one uninterrupted run, so\n * `2024 - 5 - 3` stays arithmetic), and the time half is not ambiguous at all:\n * no chain of subtractions contains a `T15:30`.\n *\n * Contiguity in the SOURCE is what makes that true, the same test\n * {@link writtenAsOneRun} applies to the date-only orderings. Every token has\n * to begin exactly where the previous one ended, so `2019-04-01 T15:30` with a\n * space in it, or `2019-04-01 + 11:00` with the offset written as an addition,\n * are left alone: the user who typed a space typed two things.\n *\n * A token an earlier normalizer rule already fused ends the run rather than\n * joining it. Its `text` is replacement text rather than source text (see\n * `normalizer/TokenNormalizer.ts`'s `createFusedToken`), so concatenating it\n * would reconstruct something the user never typed, and nothing that has\n * already been fused into a phrase is part of a timestamp anyway.\n *\n * @returns The fused match, or null when the tokens at `pos` are not a\n * timestamp, when the match would end mid-token, or when the shape is\n * ISO-like but names no real instant (`2019-04-01T25:00:00`).\n */\nfunction fuseIsoTimestamp(tokens: Token[], pos: number, ruleName: string, calendar: CalendarBackend): NormalizerMatch | null {\n const first = tokens[pos];\n if (first.sourceEnd !== undefined) return null;\n let text = first.text;\n let runEnd = first.offset + first.text.length;\n const window: Token[] = [first];\n for (let i = pos + 1; i < tokens.length && window.length < ISO_MAX_TOKENS; i++) {\n const next = tokens[i];\n if (next.sourceEnd !== undefined) break;\n if (next.offset !== runEnd || !ISO_TOKEN_TYPES.has(next.type)) break;\n text += next.text;\n runEnd = next.offset + next.text.length;\n window.push(next);\n }\n\n const matched = ISO_TIMESTAMP.exec(text);\n if (matched === null) return null;\n\n // The literal has to end where a token ends. A match that stopped halfway\n // through one would leave the parser holding a token whose text has already\n // been consumed, so decline and let the ordinary rules have it.\n let consumed = 0;\n let covered = 0;\n for (const token of window) {\n covered += token.text.length;\n consumed++;\n if (covered >= matched[0].length) break;\n }\n if (covered !== matched[0].length) return null;\n\n // The instant comes from the same parser the quoted form uses, so the two\n // spellings cannot drift apart: an offset means what it means there, and a\n // timestamp with no offset is local time, exactly as a bare date literal is\n // local midnight.\n const epochMs = parseIso8601(matched[0], calendar);\n if (epochMs === null) return null;\n\n const fusedToken = new LexerToken(\n DATETIME_LITERAL_TYPE,\n DATETIME_LITERAL_TYPE_ID,\n String(epochMs),\n matched[0],\n first.offset,\n 0,\n first.line,\n first.col,\n first.offset + matched[0].length,\n );\n return { consumed, replacement: [fusedToken], ruleName };\n}\n\n/**\n * NormalizerRule that fuses numeric date literals into a single\n * DATETIME_LITERAL token, per the documented \"Datetime Formats\":\n * - European: DD/MM/YYYY (5 tokens: NUMBER SLASH NUMBER SLASH NUMBER)\n * - US: MM-DD-YYYY (5 tokens: NUMBER MINUS NUMBER MINUS NUMBER)\n * - ISO 8601: YYYY-MM-DD (same 5-token shape as US, disambiguated by the\n * first group being exactly 4 digits)\n * - Dot: DD.MM.YYYY (2 tokens. See below)\n *\n * ## Why the dot format is a 2-token window, not 5\n * ExpressionLexer's tokenizeNumber() treats \".\" adjacent to digits on both\n * sides as a decimal point, not a separator. For \"25.12.2023\" the lexer\n * itself emits only two NUMBER tokens: \"25.12\" (day+month merged into one\n * float-shaped literal) and \".2023\" (the lexer re-enters number scanning\n * AT the second dot, so the year keeps a leading dot). There is no 5-token\n * NUMBER-DOT-NUMBER-DOT-NUMBER shape to match against, the fusion has to\n * happen post-hoc from that 2-token shape instead. This only works for the\n * literal typed with no internal whitespace (e.g. \"25.12.2023\"); a spaced\n * variant (\"25 .12 .2023\") produces three separate leading-dot tokens and\n * is intentionally not supported, out of scope for the documented format.\n *\n * ## Ambiguity with existing arithmetic\n * A date-shaped SLASH or MINUS chain (e.g. \"25/12/2023\" or \"12-25-2023\")\n * previously parsed as chained division/subtraction. This rule\n * deliberately reinterprets any such chain that resolves to a real\n * calendar date as a date literal instead, matching the documented\n * behavior. Chains that aren't valid dates (out-of-range day/month, a\n * February 30, a non-2/4-digit year) fall through unchanged.\n *\n * That reinterpretation only ever claims a chain written as one\n * uninterrupted run of characters. \"25/12/2023\" and \"12-25-2023\" are dates;\n * \"25 / 12 / 2023\" and \"12 - 25 - 2023\", written with the spaces an operator\n * normally gets, stay division and subtraction. {@link writtenAsOneRun}\n * carries the full reasoning, including why this is checked instead of\n * requiring an ISO date's zero-padding.\n *\n * ## Relationship to Iso8601.ts / DatePhrase.ts\n * This is the general-purpose \"bare numeric date literal\" implementation\n * those two files' doc comments referenced as landing on a sibling branch\n * (`feat/safety-limits-datetime-literals`), now ported here. It's\n * intentionally independent of both: `Iso8601.ts` only parses QUOTED\n * STRING literals (`\"2019-04-01...\" to date`), and the Stocks package's\n * `DatePhrase.ts` is a narrower, deliberately-diverging grammar (US-style\n * bare SLASH dates, 4-digit-year-only) scoped to stock-history queries\n * neither of those needed to change for this to land.\n *\n * ## What a run no order can read does\n * A date-shaped run the resolved order cannot read is REFUSED rather than\n * handed back to the parser as division: `12/25/2026` on a day-first engine\n * reports that there is no month 25 instead of answering 0.00, and\n * `31/02/2026 + 1 day` reports that February 2026 has 28 days instead of\n * answering \"1.01 day\". Which runs refuse and which still fall through to\n * arithmetic is decided by shape, in `DateReading.ts`'s `classifyRun`, and the\n * boundary is measured rather than aesthetic: a four-digit DENOMINATOR ends\n * nothing anybody writes, while a four-digit NUMERATOR is ordinary division\n * (`1000/10/5` is 20, `1024/8/2` is 64), so the two are treated differently on\n * purpose. `date.onAmbiguous: 'arithmetic'` restores every previous value.\n *\n * `getCalendar` supplies the calendar backend the literal is built with, read\n * per match so it follows the engine that registered the rule; the default\n * is the built-in `Date` backend, for a rule registered outside an engine.\n * `getOnAmbiguous` supplies that engine's refusal policy the same way.\n */\nexport function dateLiteralNormalizerRule(\n getInputOrder: () => ResolvedDateOrder = () => \"auto\",\n getCalendar: () => CalendarBackend = () => DATE_CALENDAR,\n getOnAmbiguous: () => DateAmbiguity = () => \"refuse\",\n): NormalizerRule {\n return {\n name: \"datetime:date-literal\",\n priority: 70,\n // Derived from this rule's own opening guards; see RuleSlot on why an\n // over-broad slot is safe and an over-narrow one is not.\n shape: [{ types: [\"NUMBER\"] }],\n match(tokens: Token[], pos: number): NormalizerMatch | null {\n const t0 = tokens[pos];\n if (t0.type !== \"NUMBER\") return null;\n const calendar = getCalendar();\n\n // ── Dot format: 2-token window (see module doc) ──────────────────\n // The lexer merged the day and month into one float-shaped token, but\n // the boundary is still there in the text, so the same reading, the same\n // shapes and the same refusals apply here as to the separator forms. It\n // used to ignore `date.inputOrder` outright: `03.04.2026` on a\n // month-first engine answered 3 April, silently reading it the other\n // way round, and `12.25.2026` answered nothing at all.\n if (DOT_DAY_MONTH.test(t0.value)) {\n const t1 = tokens[pos + 1];\n if (t1 && t1.type === \"NUMBER\" && DOT_LEADING_YEAR.test(t1.value)) {\n const [first, second] = t0.value.split(\".\");\n const dotRun = {\n text: `${t0.value}${t1.value}`,\n groups: [first, second, t1.value.slice(1)] as const,\n separator: \"dot\" as NumericDateSeparator,\n };\n const dotReading = readNumericDate(dotRun, getInputOrder(), getOnAmbiguous(), calendar);\n if (dotReading.kind === \"date\") {\n return buildDateToken(\n dotReading.day, dotReading.month, dotReading.year,\n [t0, t1], \"datetime:date-literal:dot\", calendar,\n );\n }\n if (dotReading.kind === \"refuse\") {\n return faultMatch(dotReading.code, dotReading.message, [t0, t1], \"datetime:date-literal:dot:unreadable\");\n }\n }\n return null;\n }\n\n // ── ISO 8601 timestamp: as many tokens as the spelling takes ─────\n // Tried before the date-only windows below, which would otherwise fuse\n // the date half of a timestamp and leave the time half to be read as\n // arithmetic. See fuseIsoTimestamp().\n if (t0.value.length === 4 && PLAIN_INTEGER.test(t0.value)) {\n const timestamp = fuseIsoTimestamp(tokens, pos, \"datetime:date-literal:iso-timestamp\", calendar);\n if (timestamp) return timestamp;\n }\n\n // ── Slash / minus format: 5-token window ─────────────────────────\n if (!PLAIN_INTEGER.test(t0.value)) return null;\n const sep1 = tokens[pos + 1];\n if (!sep1 || (sep1.type !== \"SLASH\" && sep1.type !== \"MINUS\")) return null;\n const t1 = tokens[pos + 2];\n const sep2 = tokens[pos + 3];\n const t2 = tokens[pos + 4];\n if (!t1 || t1.type !== \"NUMBER\" || !PLAIN_INTEGER.test(t1.value)) return null;\n if (!sep2 || sep2.type !== sep1.type) return null;\n if (!t2 || t2.type !== \"NUMBER\" || !PLAIN_INTEGER.test(t2.value)) return null;\n\n const sourceTokens = [t0, sep1, t1, sep2, t2];\n // The one check that separates every reading below from the arithmetic\n // it is spelled identically to, and the only one that applies to all of\n // them equally. Adjacency still decides date-versus-arithmetic before\n // any shape or order is considered, so `2024 - 5 - 3` is 2,016 and no\n // setting makes it a date. See writtenAsOneRun.\n if (!writtenAsOneRun(sourceTokens)) return null;\n\n // The reading, the refusal and the decision to leave the run alone all\n // come from one function, so this rule and the surfaces that explain a\n // literal cannot word or decide the same fact differently. See\n // `DateReading.ts`, which carries the four shapes and why two of them\n // refuse while the other two fall through.\n const run = {\n text: sourceTokens.map((token) => token.value).join(\"\"),\n groups: [t0.value, t1.value, t2.value] as const,\n separator: (sep1.type === \"MINUS\" ? \"hyphen\" : \"slash\") as NumericDateSeparator,\n };\n const reading = readNumericDate(run, getInputOrder(), getOnAmbiguous(), calendar);\n if (reading.kind === \"arithmetic\") return null;\n if (reading.kind === \"refuse\") {\n return faultMatch(reading.code, reading.message, sourceTokens, \"datetime:date-literal:unreadable\");\n }\n return buildDateToken(\n reading.day, reading.month, reading.year, sourceTokens,\n `datetime:date-literal:${reading.order.toLowerCase()}`, calendar,\n );\n },\n };\n}\n"]}
1
+ {"version":3,"sources":["../src/packages/symbolic/parselets/ExpandParselet.ts","../src/packages/symbolic/parselets/FactorParselet.ts","../src/packages/symbolic/parselets/VariableArgument.ts","../src/packages/symbolic/parselets/SolveParselet.ts","../src/packages/symbolic/parselets/DerParselet.ts","../src/packages/symbolic/parselets/IntegralParselet.ts","../src/packages/symbolic/parselets/TaylorParselet.ts","../src/packages/symbolic/parselets/JacobianParselet.ts","../src/packages/symbolic/parselets/ImaginaryParselet.ts","../src/packages/symbolic/parselets/ConjParselet.ts","../src/packages/symbolic/parselets/ReParselet.ts","../src/packages/symbolic/parselets/ImParselet.ts","../src/packages/symbolic/parselets/CancelParselet.ts","../src/packages/symbolic/parselets/ApartParselet.ts","../src/packages/symbolic/normalizer/ImaginaryLiteralNormalizerRule.ts","../src/packages/symbolic/normalizer/SymbolicCallNormalizerRule.ts","../src/packages/symbolic/SymbolicPackage.ts","../src/packages/tags/TagScanner.ts","../src/packages/datetime/Iso8601.ts","../src/calendar/HostLocale.ts","../src/packages/datetime/DateReading.ts","../src/packages/datetime/normalizer/DateLiteralNormalizerRule.ts"],"names":["ExpandParselet","parser","_token","builder","BindingPower","FactorParselet","readVariableName","verb","token","ErrorFactory","emitVariableName","name","parseBoundExpression","inner","BytecodeBuilder","program","emitBoundExpression","index","SolveParselet","left","right","variable","DerParselet","expression","IntegralParselet","TaylorParselet","JacobianParselet","count","ImaginaryParselet","_parser","ConjParselet","ReParselet","ImParselet","CancelParselet","ApartParselet","imaginaryLiteralNormalizerRule","priority","tokens","pos","number","suffix","LexerToken","tokenTypeId","SYMBOLIC_WORD_TO_TOKEN_TYPE","symbolicCallNormalizerRule","tokenType","SYMBOLIC_FUNCTIONS","SYMBOLIC_PACKAGE","SYMBOLIC_TOKEN_TYPES","fn","containsSymbolicCall","tagEdgeKey","tag","edgeKey","escapeTag","AGGREGATE_OPENER","OPENER_WINDOW","ANY_TAG","withTagEdges","rawText","reads","writes","tags","tagEdgesOf","memberTagsOf","members","i","queries","firstContent","m","hashIndex","lineCarriesTag","re","ISO8601_PATTERN","parseIso8601","s","calendar","trimmed","ms","ISO8601_GRAIN_PATTERN","iso8601Grain","text","matched","offset","encodeFixedOffset","sign","digits","minutes","formatIso8601Local","epochMs","d","pad","n","year","month","day","hours","seconds","offsetMinutesTotal","absOffset","offsetHours","offsetMinutes","MS_TIMESTAMP_THRESHOLD","unixTimestampToEpochMs","PROBE_INSTANT","memoisedAgainst","trustworthy","orderByTag","currentIntl","freshenMemo","current","isTrustworthyIntl","probe","hostLocale","orderFromLocale","cached","resolved","probeOrder","parts","sequence","part","DatetimeErrorCodes","isLocaleTag","resolveDateOrderPolicy","date","requestedLocale","onAmbiguous","order","inferred","MONTH_NAMES","DAY_OR_MONTH_GROUP","FULL_YEAR_GROUP","classifyRun","g0","g1","g2","separator","shortFirst","shortMiddle","shortLast","resolveYearGroup","yy","isRealCalendarDay","daysInMonth","describeUnrealDay","spellDay","isoOf","rolesFor","orderInWords","separatorOrder","readNumericDate","run","shape","canFallThrough","refusing","notACalendarDay","shortYear","orderMismatchUnderYearFirst","chosen","other","chosenRoles","otherRoles","alternative","dayFirst","monthFirst","dayFirstReal","monthFirstReal","opening","sameDay","roles","which","sourceInWords","facts","spellIso","iso","composeReadingNote","refusal","note","completeDateReading","splitNumericRun","separated","dotted","DATETIME_LITERAL_TYPE","DATETIME_LITERAL_TYPE_ID","DATETIME_LITERAL_UNREADABLE_TYPE","DATETIME_LITERAL_UNREADABLE_TYPE_ID","PLAIN_INTEGER","DOT_DAY_MONTH","DOT_LEADING_YEAR","writtenAsOneRun","buildDateToken","sourceTokens","ruleName","built","first","t","fusedToken","runText","out","previousEnd","faultMatch","code","message","ISO_TIMESTAMP","ISO_TOKEN_TYPES","ISO_MAX_TOKENS","fuseIsoTimestamp","runEnd","window","next","consumed","covered","dateLiteralNormalizerRule","getInputOrder","getCalendar","DATE_CALENDAR","getOnAmbiguous","t0","t1","second","dotRun","dotReading","timestamp","sep1","sep2","t2","reading"],"mappings":"+WAoBO,IAAMA,CAAAA,CAAN,KAA+C,CAA/C,WAAA,EAAA,CACN,IAAA,CAAS,QAAA,CAAW,WAAA,CAEpB,KAAA,CAAMC,CAAAA,CAAgBC,CAAAA,CAAeC,CAAAA,CAAgC,CACpEF,CAAAA,CAAO,OAAA,CAAQ,QAAQ,CAAA,CACvBA,CAAAA,CAAO,eAAA,CAAgBG,mBAAAA,CAAa,MAAA,CAAQD,CAAO,CAAA,CACnDF,CAAAA,CAAO,OAAA,CAAQ,QAAQ,CAAA,CAEvBE,CAAAA,CAAQ,UAAA,CAAA,EAA8B,CAAA,CACtCA,CAAAA,CAAQ,SAAA,CAAU,EAAuB,CAAA,CACzCA,CAAAA,CAAQ,SAAA,CAAU,CAAC,EACpB,CACD,CAAA,CCZO,IAAME,CAAAA,CAAN,KAA+C,CAA/C,WAAA,EAAA,CACN,IAAA,CAAS,QAAA,CAAW,WAAA,CAEpB,KAAA,CAAMJ,CAAAA,CAAgBC,CAAAA,CAAeC,CAAAA,CAAgC,CACpEF,CAAAA,CAAO,OAAA,CAAQ,QAAQ,CAAA,CACvBA,CAAAA,CAAO,eAAA,CAAgBG,mBAAAA,CAAa,MAAA,CAAQD,CAAO,CAAA,CACnDF,CAAAA,CAAO,OAAA,CAAQ,QAAQ,CAAA,CAEvBE,CAAAA,CAAQ,UAAA,CAAA,EAA8B,CAAA,CACtCA,CAAAA,CAAQ,SAAA,CAAU,EAAuB,CAAA,CACzCA,CAAAA,CAAQ,SAAA,CAAU,CAAC,EACpB,CACD,CAAA,CCRO,SAASG,CAAAA,CAAiBL,CAAAA,CAAgBM,CAAAA,CAAsB,CACtE,IAAMC,CAAAA,CAAQP,CAAAA,CAAO,IAAA,EAAK,CAC1B,GAAI,CAACO,CAAAA,EAAUA,CAAAA,CAAM,IAAA,GAAS,OAAA,EAAWA,CAAAA,CAAM,IAAA,GAAS,MAAA,CACvD,MAAMC,mBAAAA,CAAa,OAAA,CAClB,iCAAA,CACA,CAAA,EAAGF,CAAI,CAAA,0CAAA,EAA6CA,CAAI,CAAA,SAAA,CAAA,CACxD,CAAE,KAAA,CAAOC,CAAAA,EAAO,IAAA,EAAQ,cAAe,CACxC,CAAA,CAED,OAAAP,CAAAA,CAAO,OAAA,EAAQ,CACRO,CAAAA,CAAM,KACd,CAGO,SAASE,CAAAA,CAAiBP,CAAAA,CAA0BQ,CAAAA,CAAoB,CAC9ER,CAAAA,CAAQ,UAAA,CAAA,EAA6B,CAAA,CACrCA,CAAAA,CAAQ,UAAA,CAAWQ,CAAI,EACxB,CAoBO,SAASC,CAAAA,CAAqBX,CAAAA,CAAgBE,CAAAA,CAA0BI,CAAAA,CAA+B,CAC7G,IAAMM,CAAAA,CAAQ,IAAIC,mBAAAA,CAAgBX,CAAAA,CAAQ,cAAc,CAAA,CACxDF,CAAAA,CAAO,eAAA,CAAgBG,mBAAAA,CAAa,MAAA,CAAQS,CAAK,CAAA,CACjDZ,CAAAA,CAAO,UAAA,CAAWE,CAAO,CAAA,CACzB,IAAMY,CAAAA,CAAUF,CAAAA,CAAM,KAAA,EAAM,CAC5B,GAAIE,CAAAA,CAAQ,QAAA,CAIX,MAAMN,mBAAAA,CAAa,OAAA,CAClB,uCAAA,CACA,CAAA,EAAGF,CAAI,CAAA,qEAAA,CACR,CAAA,CAED,OAAOQ,CACR,CAkBO,SAASC,CAAAA,CAAoBb,CAAAA,CAA0BY,CAAAA,CAA0BJ,CAAAA,CAAoB,CAC3G,IAAMM,CAAAA,CAAQd,CAAAA,CAAQ,iBAAA,CAAkB,CAACQ,CAAI,CAAA,CAAGI,CAAO,CAAA,CACvDZ,CAAAA,CAAQ,UAAA,CAAA,GAA8B,CAAA,CACtCA,CAAAA,CAAQ,SAAA,CAAUc,CAAK,EACxB,CClEO,IAAMC,CAAAA,CAAN,KAA8C,CAA9C,WAAA,EAAA,CACN,IAAA,CAAS,QAAA,CAAW,WAAA,CAEpB,KAAA,CAAMjB,CAAAA,CAAgBC,CAAAA,CAAeC,CAAAA,CAAgC,CACpEF,CAAAA,CAAO,OAAA,CAAQ,QAAQ,CAAA,CACvB,IAAMkB,CAAAA,CAAOP,CAAAA,CAAqBX,CAAAA,CAAQE,CAAAA,CAAS,OAAO,CAAA,CACpDiB,CAAAA,CAAQnB,CAAAA,CAAO,KAAA,CAAM,QAAQ,CAAA,CAAIW,CAAAA,CAAqBX,CAAAA,CAAQE,CAAAA,CAAS,OAAO,CAAA,CAAI,IAAA,CAExFF,CAAAA,CAAO,OAAA,CAAQ,OAAO,CAAA,CAItB,IAAMoB,CAAAA,CAAWpB,CAAAA,CAAO,IAAA,EAAK,CAC7B,GAAI,CAACoB,CAAAA,EAAaA,CAAAA,CAAS,IAAA,GAAS,OAAA,EAAWA,CAAAA,CAAS,IAAA,GAAS,MAAA,CAChE,MAAMZ,mBAAAA,CAAa,OAAA,CAClB,8BAAA,CACA,gGAAA,CACA,CAAE,KAAA,CAAOY,CAAAA,EAAU,IAAA,EAAQ,cAAe,CAC3C,CAAA,CAEDpB,CAAAA,CAAO,OAAA,EAAQ,CAEfe,CAAAA,CAAoBb,CAAAA,CAASgB,CAAAA,CAAME,CAAAA,CAAS,KAAK,CAAA,CAC7CD,CAAAA,CACHJ,CAAAA,CAAoBb,CAAAA,CAASiB,CAAAA,CAAOC,CAAAA,CAAS,KAAK,CAAA,EAGlDlB,CAAAA,CAAQ,UAAA,CAAA,EAA6B,CAAA,CACrCA,CAAAA,CAAQ,UAAA,CAAW,CAAC,CAAA,CAAA,CAErBO,CAAAA,CAAiBP,CAAAA,CAASkB,CAAAA,CAAS,KAAK,CAAA,CAExCpB,CAAAA,CAAO,OAAA,CAAQ,QAAQ,CAAA,CAEvBE,CAAAA,CAAQ,UAAA,CAAA,EAA8B,CAAA,CACtCA,CAAAA,CAAQ,SAAA,CAAU,EAAsB,CAAA,CACxCA,CAAAA,CAAQ,SAAA,CAAU,CAAC,EACpB,CACD,CAAA,CCpDO,IAAMmB,CAAAA,CAAN,KAA4C,CAA5C,WAAA,EAAA,CACN,IAAA,CAAS,QAAA,CAAW,WAAA,CAEpB,KAAA,CAAMrB,CAAAA,CAAgBC,CAAAA,CAAeC,CAAAA,CAAgC,CACpEF,CAAAA,CAAO,OAAA,CAAQ,QAAQ,CAAA,CACvB,IAAMsB,CAAAA,CAAaX,CAAAA,CAAqBX,CAAAA,CAAQE,CAAAA,CAAS,KAAK,CAAA,CAC9DF,CAAAA,CAAO,OAAA,CAAQ,OAAO,CAAA,CACtB,IAAMoB,CAAAA,CAAWf,CAAAA,CAAiBL,CAAAA,CAAQ,KAAK,CAAA,CAC/Ce,CAAAA,CAAoBb,CAAAA,CAASoB,CAAAA,CAAYF,CAAQ,CAAA,CACjDX,CAAAA,CAAiBP,CAAAA,CAASkB,CAAQ,CAAA,CAG9BpB,CAAAA,CAAO,KAAA,CAAM,OAAO,CAAA,CACvBA,CAAAA,CAAO,eAAA,CAAgBG,mBAAAA,CAAa,MAAA,CAAQD,CAAO,CAAA,EAEnDA,CAAAA,CAAQ,UAAA,CAAA,EAA6B,CAAA,CACrCA,CAAAA,CAAQ,UAAA,CAAW,CAAC,CAAA,CAAA,CAErBF,CAAAA,CAAO,OAAA,CAAQ,QAAQ,CAAA,CAEvBE,CAAAA,CAAQ,UAAA,CAAA,EAA8B,CAAA,CACtCA,CAAAA,CAAQ,SAAA,CAAU,EAAoB,CAAA,CACtCA,CAAAA,CAAQ,SAAA,CAAU,CAAC,EACpB,CACD,CAAA,CC5BO,IAAMqB,CAAAA,CAAN,KAAiD,CAAjD,WAAA,EAAA,CACN,IAAA,CAAS,QAAA,CAAW,WAAA,CAEpB,KAAA,CAAMvB,CAAAA,CAAgBC,CAAAA,CAAeC,CAAAA,CAAgC,CACpEF,CAAAA,CAAO,OAAA,CAAQ,QAAQ,CAAA,CACvB,IAAMsB,CAAAA,CAAaX,CAAAA,CAAqBX,CAAAA,CAAQE,CAAAA,CAAS,UAAU,CAAA,CACnEF,CAAAA,CAAO,OAAA,CAAQ,OAAO,CAAA,CACtB,IAAMoB,CAAAA,CAAWf,CAAAA,CAAiBL,CAAAA,CAAQ,UAAU,CAAA,CACpDe,CAAAA,CAAoBb,CAAAA,CAASoB,CAAAA,CAAYF,CAAQ,CAAA,CACjDX,CAAAA,CAAiBP,CAAAA,CAASkB,CAAQ,CAAA,CAClCpB,CAAAA,CAAO,OAAA,CAAQ,QAAQ,CAAA,CAEvBE,CAAAA,CAAQ,UAAA,CAAA,EAA8B,CAAA,CACtCA,CAAAA,CAAQ,SAAA,CAAU,EAAyB,CAAA,CAC3CA,CAAAA,CAAQ,SAAA,CAAU,CAAC,EACpB,CACD,CAAA,CCVO,IAAMsB,CAAAA,CAAN,KAA+C,CAA/C,WAAA,EAAA,CACN,IAAA,CAAS,QAAA,CAAW,WAAA,CAEpB,KAAA,CAAMxB,CAAAA,CAAgBC,CAAAA,CAAeC,CAAAA,CAAgC,CACpEF,CAAAA,CAAO,OAAA,CAAQ,QAAQ,CAAA,CACvB,IAAMsB,CAAAA,CAAaX,CAAAA,CAAqBX,CAAAA,CAAQE,CAAAA,CAAS,QAAQ,CAAA,CACjEF,CAAAA,CAAO,OAAA,CAAQ,OAAO,CAAA,CACtB,IAAMoB,CAAAA,CAAWf,CAAAA,CAAiBL,CAAAA,CAAQ,QAAQ,CAAA,CAClDe,CAAAA,CAAoBb,CAAAA,CAASoB,CAAAA,CAAYF,CAAQ,CAAA,CACjDX,CAAAA,CAAiBP,CAAAA,CAASkB,CAAQ,CAAA,CAClCpB,CAAAA,CAAO,OAAA,CAAQ,QAAQ,CAAA,CACvBA,CAAAA,CAAO,eAAA,CAAgBG,mBAAAA,CAAa,MAAA,CAAQD,CAAO,CAAA,CACnDF,CAAAA,CAAO,OAAA,CAAQ,OAAO,CAAA,CACtBA,CAAAA,CAAO,eAAA,CAAgBG,mBAAAA,CAAa,MAAA,CAAQD,CAAO,CAAA,CACnDF,CAAAA,CAAO,OAAA,CAAQ,QAAQ,CAAA,CAEvBE,CAAAA,CAAQ,UAAA,CAAA,EAA8B,CAAA,CACtCA,CAAAA,CAAQ,SAAA,CAAU,EAAuB,CAAA,CACzCA,CAAAA,CAAQ,SAAA,CAAU,CAAC,EACpB,CACD,CAAA,CCzBO,IAAMuB,CAAAA,CAAN,KAAiD,CAAjD,WAAA,EAAA,CACN,IAAA,CAAS,QAAA,CAAW,WAAA,CAEpB,KAAA,CAAMzB,CAAAA,CAAgBC,CAAAA,CAAeC,CAAAA,CAAgC,CACpEF,CAAAA,CAAO,OAAA,CAAQ,QAAQ,CAAA,CACvB,IAAI0B,CAAAA,CAAQ,CAAA,CACZ,GACC1B,CAAAA,CAAO,eAAA,CAAgBG,mBAAAA,CAAa,MAAA,CAAQD,CAAO,CAAA,CACnDwB,CAAAA,EAAAA,CAAAA,MACQ1B,CAAAA,CAAO,KAAA,CAAM,OAAO,CAAA,EAC7BA,CAAAA,CAAO,OAAA,CAAQ,QAAQ,CAAA,CAEvBE,CAAAA,CAAQ,UAAA,CAAA,EAA8B,CAAA,CACtCA,CAAAA,CAAQ,SAAA,CAAU,EAAyB,CAAA,CAC3CA,CAAAA,CAAQ,SAAA,CAAUwB,CAAK,EACxB,CACD,CAAA,CCfO,IAAMC,CAAAA,CAAN,KAAkD,CAAlD,WAAA,EAAA,CACN,IAAA,CAAS,QAAA,CAAW,WAAA,CAEpB,KAAA,CAAMC,CAAAA,CAAiBrB,CAAAA,CAAcL,CAAAA,CAAgC,CACpEA,CAAAA,CAAQ,UAAA,CAAA,EAA6B,CAAA,CACrCA,CAAAA,CAAQ,UAAA,CAAW,MAAA,CAAOK,CAAAA,CAAM,KAAK,CAAC,CAAA,CACtCL,CAAAA,CAAQ,UAAA,CAAA,EAA8B,CAAA,CACtCA,CAAAA,CAAQ,SAAA,CAAU,EAA0B,CAAA,CAC5CA,CAAAA,CAAQ,SAAA,CAAU,CAAC,EACpB,CACD,CAAA,CCXO,IAAM2B,CAAAA,CAAN,KAA6C,CAA7C,WAAA,EAAA,CACN,IAAA,CAAS,QAAA,CAAW,WAAA,CAEpB,KAAA,CAAM7B,CAAAA,CAAgBC,CAAAA,CAAeC,CAAAA,CAAgC,CACpEF,CAAAA,CAAO,OAAA,CAAQ,QAAQ,CAAA,CACvBA,CAAAA,CAAO,eAAA,CAAgBG,mBAAAA,CAAa,MAAA,CAAQD,CAAO,CAAA,CACnDF,CAAAA,CAAO,OAAA,CAAQ,QAAQ,CAAA,CAEvBE,CAAAA,CAAQ,UAAA,CAAA,EAA8B,CAAA,CACtCA,CAAAA,CAAQ,SAAA,CAAU,EAAqB,CAAA,CACvCA,CAAAA,CAAQ,SAAA,CAAU,CAAC,EACpB,CACD,CAAA,CCZO,IAAM4B,CAAAA,CAAN,KAA2C,CAA3C,WAAA,EAAA,CACN,IAAA,CAAS,QAAA,CAAW,WAAA,CAEpB,KAAA,CAAM9B,CAAAA,CAAgBC,CAAAA,CAAeC,CAAAA,CAAgC,CACpEF,CAAAA,CAAO,OAAA,CAAQ,QAAQ,CAAA,CACvBA,CAAAA,CAAO,eAAA,CAAgBG,mBAAAA,CAAa,MAAA,CAAQD,CAAO,CAAA,CACnDF,CAAAA,CAAO,OAAA,CAAQ,QAAQ,CAAA,CAEvBE,CAAAA,CAAQ,UAAA,CAAA,EAA8B,CAAA,CACtCA,CAAAA,CAAQ,SAAA,CAAU,EAAmB,CAAA,CACrCA,CAAAA,CAAQ,SAAA,CAAU,CAAC,EACpB,CACD,CAAA,CCZO,IAAM6B,CAAAA,CAAN,KAA2C,CAA3C,WAAA,EAAA,CACN,IAAA,CAAS,QAAA,CAAW,WAAA,CAEpB,KAAA,CAAM/B,CAAAA,CAAgBC,CAAAA,CAAeC,CAAAA,CAAgC,CACpEF,CAAAA,CAAO,OAAA,CAAQ,QAAQ,CAAA,CACvBA,CAAAA,CAAO,eAAA,CAAgBG,mBAAAA,CAAa,MAAA,CAAQD,CAAO,CAAA,CACnDF,CAAAA,CAAO,OAAA,CAAQ,QAAQ,CAAA,CAEvBE,CAAAA,CAAQ,UAAA,CAAA,EAA8B,CAAA,CACtCA,CAAAA,CAAQ,SAAA,CAAU,EAAmB,CAAA,CACrCA,CAAAA,CAAQ,SAAA,CAAU,CAAC,EACpB,CACD,CAAA,CCZO,IAAM8B,CAAAA,CAAN,KAA+C,CAA/C,WAAA,EAAA,CACN,IAAA,CAAS,QAAA,CAAW,WAAA,CAEpB,KAAA,CAAMhC,CAAAA,CAAgBC,CAAAA,CAAeC,CAAAA,CAAgC,CACpEF,CAAAA,CAAO,OAAA,CAAQ,QAAQ,CAAA,CACvBA,CAAAA,CAAO,eAAA,CAAgBG,mBAAAA,CAAa,MAAA,CAAQD,CAAO,CAAA,CACnDF,CAAAA,CAAO,OAAA,CAAQ,QAAQ,CAAA,CAEvBE,CAAAA,CAAQ,UAAA,CAAA,EAA8B,CAAA,CACtCA,CAAAA,CAAQ,SAAA,CAAU,EAAuB,CAAA,CACzCA,CAAAA,CAAQ,SAAA,CAAU,CAAC,EACpB,CACD,CAAA,CCbO,IAAM+B,CAAAA,CAAN,KAA8C,CAA9C,WAAA,EAAA,CACN,IAAA,CAAS,QAAA,CAAW,WAAA,CAEpB,KAAA,CAAMjC,CAAAA,CAAgBC,CAAAA,CAAeC,CAAAA,CAAgC,CACpEF,CAAAA,CAAO,OAAA,CAAQ,QAAQ,CAAA,CACvBA,CAAAA,CAAO,eAAA,CAAgBG,mBAAAA,CAAa,MAAA,CAAQD,CAAO,CAAA,CACnDF,CAAAA,CAAO,OAAA,CAAQ,QAAQ,CAAA,CAEvBE,CAAAA,CAAQ,UAAA,CAAA,EAA8B,CAAA,CACtCA,CAAAA,CAAQ,SAAA,CAAU,EAAsB,CAAA,CACxCA,CAAAA,CAAQ,SAAA,CAAU,CAAC,EACpB,CACD,CAAA,CCJO,SAASgC,EAAAA,CAA+BC,CAAAA,CAAW,EAAA,CAAoB,CAC7E,OAAO,CACN,IAAA,CAAM,4BAAA,CACN,QAAA,CAAAA,CAAAA,CAGA,KAAA,CAAO,CAAC,CAAE,KAAA,CAAO,CAAC,QAAQ,CAAE,CAAA,CAAG,CAAE,KAAA,CAAO,CAAC,OAAO,CAAA,CAAG,MAAA,CAAQ,CAAC,GAAG,CAAE,CAAC,CAAA,CAClE,KAAA,CAAMC,CAAAA,CAAiBC,CAAAA,CAAqC,CAC3D,IAAMC,CAAAA,CAASF,CAAAA,CAAOC,CAAG,CAAA,CACzB,GAAI,CAACC,CAAAA,EAAUA,CAAAA,CAAO,IAAA,GAAS,QAAA,CAAU,OAAO,IAAA,CAEhD,IAAMC,CAAAA,CAASH,CAAAA,CAAOC,CAAAA,CAAM,CAAC,CAAA,CAQ7B,OAPI,CAACE,CAAAA,EAAUA,CAAAA,CAAO,IAAA,GAAS,OAAA,EAAWA,CAAAA,CAAO,KAAA,GAAU,GAAA,EAGvDA,CAAAA,CAAO,MAAA,GAAWD,CAAAA,CAAO,MAAA,CAASA,CAAAA,CAAO,KAAA,CAAM,MAAA,EAI/CF,CAAAA,CAAOC,CAAAA,CAAM,CAAC,CAAA,EAAG,IAAA,GAAS,QAAA,CAAiB,IAAA,CAExC,CACN,QAAA,CAAU,CAAA,CACV,WAAA,CAAa,CACZ,IAAIG,mBAAAA,CACH,WAAA,CACAC,mBAAAA,CAAY,WAAW,CAAA,CACvBH,CAAAA,CAAO,KAAA,CACPA,CAAAA,CAAO,KAAA,CACPA,CAAAA,CAAO,MAAA,CACP,CAAA,CACAA,CAAAA,CAAO,IAAA,CACPA,CAAAA,CAAO,GACR,CACD,CAAA,CACA,QAAA,CAAU,4BACX,CACD,CACD,CACD,CCjDO,IAAMI,EAAAA,CAAgE,CAC5E,MAAA,CAAQ,WAAA,CACR,MAAA,CAAQ,WAAA,CACR,KAAA,CAAO,UAAA,CACP,GAAA,CAAK,QAAA,CACL,UAAA,CAAY,QAAA,CACZ,QAAA,CAAU,aAAA,CACV,MAAA,CAAQ,WAAA,CACR,QAAA,CAAU,aAAA,CACV,IAAA,CAAM,SAAA,CACN,EAAA,CAAI,OAAA,CACJ,EAAA,CAAI,OAAA,CACJ,MAAA,CAAQ,WAAA,CACR,KAAA,CAAO,UACR,CAAA,CAoBO,SAASC,EAAAA,CAA2BR,CAAAA,CAAW,EAAA,CAAoB,CACzE,OAAO,CACN,IAAA,CAAM,eAAA,CACN,QAAA,CAAAA,CAAAA,CAGA,KAAA,CAAO,CAAC,CAAE,KAAA,CAAO,CAAC,OAAO,CAAA,CAAG,MAAA,CAAQ,MAAA,CAAO,IAAA,CAAKO,EAA2B,CAAE,CAAA,CAAG,CAAE,KAAA,CAAO,CAAC,QAAQ,CAAE,CAAC,CAAA,CACrG,KAAA,CAAMN,CAAAA,CAAiBC,CAAAA,CAAqC,CAC3D,IAAM9B,CAAAA,CAAQ6B,CAAAA,CAAOC,CAAG,CAAA,CACxB,GAAI,CAAC9B,CAAAA,EAASA,CAAAA,CAAM,IAAA,GAAS,OAAA,CAAS,OAAO,IAAA,CAC7C,IAAMqC,CAAAA,CAAYF,EAAAA,CAA4BnC,CAAAA,CAAM,KAAA,CAAM,WAAA,EAAa,CAAA,CAEvE,OADI,CAACqC,CAAAA,EACDR,CAAAA,CAAOC,CAAAA,CAAM,CAAC,CAAA,EAAG,IAAA,GAAS,QAAA,CAAiB,IAAA,CAExC,CACN,QAAA,CAAU,CAAA,CACV,WAAA,CAAa,CACZ,IAAIG,mBAAAA,CAAWI,CAAAA,CAAWH,oBAAYG,CAAS,CAAA,CAAGrC,CAAAA,CAAM,KAAA,CAAOA,CAAAA,CAAM,KAAA,CAAOA,CAAAA,CAAM,MAAA,CAAQ,CAAA,CAAGA,CAAAA,CAAM,IAAA,CAAMA,CAAAA,CAAM,GAAG,CACnH,CAAA,CACA,QAAA,CAAU,eACX,CACD,CACD,CACD,CCZO,IAAMsC,EAAAA,CAAyD,CACrE,CACC,IAAA,CAAM,QAAA,CACN,SAAA,CAAW,WAAA,CACX,YAAA,CAAc,EAAA,CACd,OAAA,CAAS,qBAAA,CACT,QAAA,CAAU,UAAA,CACV,OAAA,CAAS,cACV,CAAA,CACA,CACC,IAAA,CAAM,QAAA,CACN,SAAA,CAAW,WAAA,CACX,YAAA,CAAc,EAAA,CACd,OAAA,CAAS,eAAA,CACT,QAAA,CAAU,aAAA,CACV,OAAA,CAAS,cACV,CAAA,CACA,CACC,IAAA,CAAM,OAAA,CACN,SAAA,CAAW,UAAA,CACX,YAAA,CAAc,EAAA,CACd,OAAA,CAAS,mBAAA,CACT,QAAA,CAAU,WAAA,CACV,OAAA,CAAS,sBACV,CAAA,CACA,CACC,IAAA,CAAM,KAAA,CACN,SAAA,CAAW,QAAA,CACX,YAAA,CAAc,EAAA,CACd,OAAA,CAAS,aAAA,CACT,QAAA,CAAU,MAAA,CACV,OAAA,CAAS,aACV,CAAA,CACA,CACC,IAAA,CAAM,UAAA,CACN,SAAA,CAAW,aAAA,CACX,YAAA,CAAc,EAAA,CACd,OAAA,CAAS,kBAAA,CACT,QAAA,CAAU,QAAA,CACV,OAAA,CAAS,aACV,CAAA,CACA,CACC,IAAA,CAAM,QAAA,CACN,SAAA,CAAW,WAAA,CACX,YAAA,CAAc,EAAA,CACd,OAAA,CAAS,wBAAA,CACT,QAAA,CAAU,mBAAA,CACV,OAAA,CAAS,aACV,CAAA,CACA,CACC,IAAA,CAAM,UAAA,CACN,SAAA,CAAW,aAAA,CACX,YAAA,CAAc,EAAA,CACd,OAAA,CAAS,oBAAA,CACT,QAAA,CAAU,gBAAA,CACV,OAAA,CAAS,aACV,CAAA,CACA,CACC,IAAA,CAAM,MAAA,CACN,SAAA,CAAW,SAAA,CACX,YAAA,CAAc,EAAA,CACd,OAAA,CAAS,YAAA,CACT,QAAA,CAAU,MAAA,CACV,OAAA,CAAS,YACV,CAAA,CACA,CACC,IAAA,CAAM,IAAA,CACN,SAAA,CAAW,OAAA,CACX,YAAA,CAAc,EAAA,CACd,OAAA,CAAS,UAAA,CACT,QAAA,CAAU,KAAA,CACV,OAAA,CAAS,YACV,CAAA,CACA,CACC,IAAA,CAAM,IAAA,CACN,SAAA,CAAW,OAAA,CACX,YAAA,CAAc,EAAA,CACd,OAAA,CAAS,UAAA,CACT,QAAA,CAAU,KAAA,CACV,OAAA,CAAS,YACV,CAAA,CACA,CACC,IAAA,CAAM,QAAA,CACN,SAAA,CAAW,WAAA,CACX,YAAA,CAAc,EAAA,CACd,OAAA,CAAS,uBAAA,CACT,QAAA,CAAU,KAAA,CACV,OAAA,CAAS,yBACV,CAAA,CACA,CACC,IAAA,CAAM,OAAA,CACN,SAAA,CAAW,UAAA,CACX,YAAA,CAAc,EAAA,CACd,OAAA,CAAS,uBAAA,CACT,QAAA,CAAU,iBAAA,CACV,OAAA,CAAS,wBACV,CACD,CAAA,CAaaC,EAAAA,CAAmC,CAC/C,IAAA,CAAM,gBAAA,CACN,eAAA,CAAiB,CAACH,EAAAA,EAA2B,CAAGT,EAAAA,EAAgC,CAAA,CAChF,eAAA,CAAiB,CAChB,SAAA,CAAW,IAAInC,CAAAA,CACf,SAAA,CAAW,IAAIK,CAAAA,CACf,QAAA,CAAU,IAAIa,CAAAA,CACd,MAAA,CAAQ,IAAII,CAAAA,CACZ,WAAA,CAAa,IAAIE,CAAAA,CACjB,SAAA,CAAW,IAAIC,CAAAA,CACf,WAAA,CAAa,IAAIC,CAAAA,CACjB,SAAA,CAAW,IAAIE,CAAAA,CACf,OAAA,CAAS,IAAIE,CAAAA,CACb,KAAA,CAAO,IAAIC,CAAAA,CACX,KAAA,CAAO,IAAIC,CAAAA,CACX,SAAA,CAAW,IAAIC,CAAAA,CACf,QAAA,CAAU,IAAIC,CACf,CAAA,CACA,eAAA,CAAiB,CAChB,SAAA,CAAW,SAAA,CACX,SAAA,CAAW,SAAA,CACX,QAAA,CAAU,SAAA,CACV,MAAA,CAAQ,SAAA,CACR,WAAA,CAAa,SAAA,CACb,SAAA,CAAW,SAAA,CACX,WAAA,CAAa,SAAA,CACb,SAAA,CAAW,QAAA,CACX,OAAA,CAAS,SAAA,CACT,KAAA,CAAO,SAAA,CACP,KAAA,CAAO,SAAA,CACP,SAAA,CAAW,SAAA,CACX,QAAA,CAAU,SACX,CACD,CAAA,CAGMc,EAAAA,CAA4C,IAAI,GAAA,CAAIF,EAAAA,CAAmB,GAAA,CAAIG,CAAAA,EAAMA,CAAAA,CAAG,SAAS,CAAC,EAa7F,SAASC,EAAAA,CAAqBb,CAAAA,CAA8C,CAClF,OAAOA,CAAAA,CAAO,IAAA,CAAK7B,CAAAA,EAASwC,EAAAA,CAAqB,GAAA,CAAIxC,CAAAA,CAAM,IAAI,CAAC,CACjE,CC5MA,IAAM2C,EAAAA,CAAcC,CAAAA,EAAwBC,mBAAAA,CAAQ,KAAA,CAAOD,CAAAA,CAAI,WAAA,EAAa,CAAA,CAGrE,SAASE,EAAAA,CAAU3C,CAAAA,CAAsB,CAC9C,OAAOA,CAAAA,CAAK,OAAA,CAAQ,qBAAA,CAAuB,MAAM,CACnD,CAQA,IAAM4C,EAAAA,CAAmB,uCAAA,CAmBnBC,EAAAA,CAAgB,EAAA,CAGhBC,CAAAA,CAAU,wDAAA,CAmBT,SAASC,EAAAA,CACfC,CAAAA,CACAC,CAAAA,CACAC,CAAAA,CACwC,CACxC,IAAMC,CAAAA,CAAOC,EAAAA,CAAWJ,CAAO,CAAA,CAC/B,OAAIG,CAAAA,CAAK,OAAA,CAAQ,MAAA,GAAW,CAAA,EAAKA,CAAAA,CAAK,OAAA,CAAQ,MAAA,GAAW,CAAA,CACjD,CAAE,KAAA,CAAOF,CAAAA,CAAmB,MAAA,CAAQC,CAAmB,CAAA,CAExD,CACN,KAAA,CAAOC,CAAAA,CAAK,OAAA,CAAQ,MAAA,GAAW,CAAA,CAAKF,CAAAA,CAAqB,CAAC,GAAGA,CAAAA,CAAO,GAAGE,CAAAA,CAAK,OAAA,CAAQ,GAAA,CAAIX,EAAU,CAAC,CAAA,CACnG,MAAA,CAAQW,CAAAA,CAAK,OAAA,CAAQ,MAAA,GAAW,CAAA,CAAKD,CAAAA,CAAsB,CAAC,GAAGA,CAAAA,CAAQ,GAAGC,CAAAA,CAAK,OAAA,CAAQ,GAAA,CAAIX,EAAU,CAAC,CACvG,CACD,CASO,SAASa,EAAAA,CAAaL,CAAAA,CAA2B,CACvD,IAAMM,CAAAA,CAAUF,EAAAA,CAAWJ,CAAO,CAAA,CAAE,OAAA,CACpC,IAAA,IAASO,CAAAA,CAAI,CAAA,CAAGA,CAAAA,CAAID,CAAAA,CAAQ,MAAA,CAAQC,CAAAA,EAAAA,CAAKD,CAAAA,CAAQC,CAAC,CAAA,CAAID,CAAAA,CAAQC,CAAC,CAAA,CAAE,WAAA,EAAY,CAC7E,OAAOD,CACR,CAcO,SAASF,EAAAA,CAAWJ,CAAAA,CAA2D,CACrF,IAAMM,CAAAA,CAAoB,EAAC,CACrBE,CAAAA,CAAoB,EAAC,CAErBC,CAAAA,CAAeT,CAAAA,CAAQ,MAAA,CAAO,IAAI,CAAA,CACxCF,CAAAA,CAAQ,SAAA,CAAY,CAAA,CACpB,IAAA,IAASY,CAAAA,CAAIZ,CAAAA,CAAQ,IAAA,CAAKE,CAAO,CAAA,CAAGU,CAAAA,GAAM,IAAA,CAAMA,CAAAA,CAAIZ,CAAAA,CAAQ,IAAA,CAAKE,CAAO,CAAA,CAAG,CAC1E,IAAMW,CAAAA,CAAYD,CAAAA,CAAE,KAAA,CAAQA,CAAAA,CAAE,CAAC,CAAA,CAAE,OAAA,CAAQ,GAAG,CAAA,CAE5C,GAAID,CAAAA,GAAiBE,CAAAA,CAAW,SAChC,IAAM3D,CAAAA,CAAO0D,CAAAA,CAAE,CAAC,CAAA,CAChB,GAAId,EAAAA,CAAiB,IAAA,CAAKI,CAAAA,CAAQ,KAAA,CAAM,IAAA,CAAK,GAAA,CAAI,CAAA,CAAGW,CAAAA,CAAYd,EAAa,CAAA,CAAGc,CAAS,CAAC,CAAA,CAAG,CAC5FH,CAAAA,CAAQ,IAAA,CAAKxD,CAAI,CAAA,CACjB,QACD,CACAsD,CAAAA,CAAQ,IAAA,CAAKtD,CAAI,EAClB,CACA,OAAO,CAAE,OAAA,CAAAsD,CAAAA,CAAS,OAAA,CAAAE,CAAQ,CAC3B,CAoBO,SAASI,EAAAA,CAAeZ,CAAAA,CAAiBP,CAAAA,CAAsB,CACpE,GAAIA,CAAAA,GAAQ,EAAA,CAAI,OAAO,MAAA,CACvB,IAAMoB,CAAAA,CAAK,IAAI,MAAA,CAAO,CAAA,oBAAA,EAAuBlB,EAAAA,CAAUF,CAAG,CAAC,CAAA,iBAAA,CAAA,CAAqB,IAAI,CAAA,CAG9EgB,CAAAA,CAAeT,CAAAA,CAAQ,MAAA,CAAO,IAAI,CAAA,CACxC,IAAA,IAASU,CAAAA,CAAIG,CAAAA,CAAG,IAAA,CAAKb,CAAO,CAAA,CAAGU,CAAAA,GAAM,IAAA,CAAMA,CAAAA,CAAIG,CAAAA,CAAG,IAAA,CAAKb,CAAO,CAAA,CAAG,CAE/D,IAAMW,CAAAA,CAAYD,CAAAA,CAAE,KAAA,CAAQA,CAAAA,CAAE,CAAC,CAAA,CAAE,OAAA,CAAQ,GAAG,CAAA,CAE5C,GAAID,CAAAA,GAAiBE,CAAAA,EACjB,CAAAf,EAAAA,CAAiB,IAAA,CAAKI,CAAAA,CAAQ,KAAA,CAAM,IAAA,CAAK,GAAA,CAAI,CAAA,CAAGW,CAAAA,CAAYd,EAAa,CAAA,CAAGc,CAAS,CAAC,CAAA,CAC1F,OAAO,KACT,CACA,OAAO,MACT,CC9HA,IAAMG,EAAAA,CACJ,0EAAA,CAuBK,SAASC,EAAAA,CAAaC,CAAAA,CAAWC,CAAAA,CAA0C,CAQhF,IAAIC,CAAAA,CAAUF,CAAAA,CAAE,IAAA,EAAK,CAIrB,GAHIE,CAAAA,CAAQ,MAAA,EAAU,CAAA,EAAKA,CAAAA,CAAQ,UAAA,CAAW,GAAG,CAAA,EAAKA,CAAAA,CAAQ,QAAA,CAAS,GAAG,CAAA,GACxEA,CAAAA,CAAUA,CAAAA,CAAQ,KAAA,CAAM,CAAA,CAAG,EAAE,CAAA,CAAA,CAE3B,CAACJ,EAAAA,CAAgB,IAAA,CAAKI,CAAO,CAAA,CAAG,OAAO,IAAA,CAC3C,IAAMC,CAAAA,CAAKF,CAAAA,CAAS,YAAA,CAAaC,CAAO,CAAA,CACxC,OAAO,MAAA,CAAO,KAAA,CAAMC,CAAE,CAAA,CAAI,IAAA,CAAOA,CACnC,CAUA,IAAMC,EAAAA,CACJ,8EAAA,CAwBK,SAASC,EAAAA,CAAaC,CAAAA,CAAuD,CAClF,IAAMC,CAAAA,CAAUH,EAAAA,CAAsB,IAAA,CAAKE,CAAAA,CAAK,IAAA,EAAM,CAAA,CACtD,GAAIC,CAAAA,GAAY,IAAA,EAAQA,CAAAA,CAAQ,CAAC,CAAA,GAAM,MAAA,CAAW,OAAO,CAAE,KAAA,CAAO,MAAO,CAAA,CACzE,IAAMC,CAAAA,CAASD,CAAAA,CAAQ,CAAC,CAAA,CACxB,GAAIC,CAAAA,GAAW,MAAA,CAAW,OAAO,CAAE,KAAA,CAAO,UAAW,CAAA,CACrD,GAAIA,CAAAA,GAAW,GAAA,CAAK,OAAO,CAAE,KAAA,CAAO,SAAA,CAAW,IAAA,CAAMC,mBAAAA,CAAkB,CAAC,CAAE,CAAA,CAC1E,IAAMC,CAAAA,CAAOF,CAAAA,CAAO,CAAC,CAAA,GAAM,GAAA,CAAM,EAAA,CAAK,CAAA,CAChCG,CAAAA,CAASH,CAAAA,CAAO,KAAA,CAAM,CAAC,CAAA,CAAE,OAAA,CAAQ,GAAA,CAAK,EAAE,CAAA,CACxCI,CAAAA,CAAU,MAAA,CAAOD,CAAAA,CAAO,KAAA,CAAM,CAAA,CAAG,CAAC,CAAC,CAAA,CAAI,EAAA,CAAK,MAAA,CAAOA,CAAAA,CAAO,KAAA,CAAM,CAAC,CAAC,CAAA,CACxE,OAAO,CAAE,KAAA,CAAO,SAAA,CAAW,IAAA,CAAMF,mBAAAA,CAAkBC,CAAAA,CAAOE,CAAO,CAAE,CACrE,CAoBO,SAASC,EAAAA,CAAmBC,CAAAA,CAAiBb,CAAAA,CAAmC,CACrF,IAAMc,CAAAA,CAAId,CAAAA,CAAS,MAAA,CAAOa,CAAO,CAAA,CAC3BE,CAAAA,CAAOC,CAAAA,EAAc,MAAA,CAAOA,CAAC,CAAA,CAAE,QAAA,CAAS,CAAA,CAAG,GAAG,CAAA,CAE9CC,CAAAA,CAAOH,CAAAA,CAAE,IAAA,CACTI,CAAAA,CAAQH,CAAAA,CAAID,CAAAA,CAAE,MAAA,CAAS,CAAC,CAAA,CACxBK,CAAAA,CAAMJ,CAAAA,CAAID,CAAAA,CAAE,GAAG,CAAA,CACfM,CAAAA,CAAQL,CAAAA,CAAID,CAAAA,CAAE,IAAI,CAAA,CAClBH,CAAAA,CAAUI,CAAAA,CAAID,CAAAA,CAAE,MAAM,CAAA,CACtBO,CAAAA,CAAUN,CAAAA,CAAID,CAAAA,CAAE,MAAM,CAAA,CAGtBQ,CAAAA,CAAqBtB,CAAAA,CAAS,gBAAA,CAAiBa,CAAO,CAAA,CACtDJ,CAAAA,CAAOa,CAAAA,EAAsB,CAAA,CAAI,GAAA,CAAM,GAAA,CACvCC,CAAAA,CAAY,IAAA,CAAK,GAAA,CAAID,CAAkB,CAAA,CACvCE,CAAAA,CAAcT,CAAAA,CAAI,IAAA,CAAK,KAAA,CAAMQ,CAAAA,CAAY,EAAE,CAAC,CAAA,CAC5CE,CAAAA,CAAgBV,CAAAA,CAAIQ,CAAAA,CAAY,EAAE,CAAA,CAExC,OAAO,CAAA,EAAGN,CAAI,CAAA,CAAA,EAAIC,CAAK,CAAA,CAAA,EAAIC,CAAG,CAAA,CAAA,EAAIC,CAAK,CAAA,CAAA,EAAIT,CAAO,CAAA,CAAA,EAAIU,CAAO,CAAA,EAAGZ,CAAI,CAAA,EAAGe,CAAW,CAAA,CAAA,EAAIC,CAAa,CAAA,CACrG,CAgBA,IAAMC,EAAAA,CAAyB,IAAA,CAOxB,SAASC,EAAAA,CAAuBX,CAAAA,CAAmB,CACxD,OAAO,IAAA,CAAK,GAAA,CAAIA,CAAC,CAAA,EAAKU,EAAAA,CAAyBV,CAAAA,CAAIA,CAAAA,CAAI,GACzD,CCvIA,IAAMY,EAAAA,CAAgB,IAAA,CAAK,GAAA,CAAI,IAAA,CAAM,CAAA,CAAG,CAAC,CAAA,CAYrCC,EAAAA,CACAC,CAAAA,CACEC,CAAAA,CAAa,IAAI,GAAA,CAGvB,SAASC,EAAAA,EAAuB,CAC9B,OAAO,OAAO,IAAA,EAAS,QAAA,EAAY,IAAA,GAAS,IAAA,CAAQ,IAAA,CAAsC,cAAA,CAAiB,MAC7G,CAGA,SAASC,EAAAA,EAAoB,CAC3B,IAAMC,CAAAA,CAAUF,EAAAA,EAAY,CACxBE,CAAAA,GAAYL,EAAAA,GAChBA,EAAAA,CAAkBK,CAAAA,CAClBJ,CAAAA,CAAc,MAAA,CACdC,CAAAA,CAAW,KAAA,EAAM,EACnB,CAuBO,SAASI,EAAAA,EAA6B,CAE3C,GADAF,EAAAA,EAAY,CACRH,CAAAA,GAAgB,MAAA,CAAW,OAAOA,CAAAA,CACtC,GAAI,CACF,IAAMM,CAAAA,CAAQ,IAAI,IAAA,CAAK,cAAA,CAAe,OAAO,CAAA,CAAE,eAAA,EAAgB,CAAE,MAAA,CACjEN,CAAAA,CAAc,OAAOM,CAAAA,EAAU,QAAA,EAAYA,CAAAA,CAAM,UAAA,CAAW,IAAI,EAClE,CAAA,KAAQ,CACNN,CAAAA,CAAc,MAChB,CACA,OAAOA,CACT,CAQO,SAASO,EAAAA,EAA4B,CAC1C,GAAI,OAAO,IAAA,EAAS,QAAA,EAAY,IAAA,GAAS,IAAA,EAAQ,OAAO,IAAA,CAAK,cAAA,EAAmB,UAAA,CAAY,OAAO,IAAA,CACnG,GAAI,CACF,IAAM7D,CAAAA,CAAM,IAAI,IAAA,CAAK,cAAA,EAAe,CAAE,eAAA,EAAgB,CAAE,MAAA,CACxD,OAAO,OAAOA,CAAAA,EAAQ,QAAA,EAAYA,CAAAA,CAAI,MAAA,CAAS,CAAA,CAAIA,CAAAA,CAAM,IAC3D,CAAA,KAAQ,CACN,OAAO,IACT,CACF,CA+BO,SAAS8D,EAAAA,CAAgB9D,CAAAA,CAAoC,CAClEyD,EAAAA,EAAY,CACZ,IAAMM,CAAAA,CAASR,CAAAA,CAAW,GAAA,CAAIvD,CAAG,CAAA,CACjC,GAAI+D,CAAAA,GAAW,MAAA,CAAW,OAAOA,CAAAA,CACjC,IAAMC,CAAAA,CAAWC,EAAAA,CAAWjE,CAAG,CAAA,CAC/B,OAAAuD,CAAAA,CAAW,GAAA,CAAIvD,CAAAA,CAAKgE,CAAQ,CAAA,CACrBA,CACT,CAGA,SAASC,EAAAA,CAAWjE,CAAAA,CAAoC,CAEtD,GADI,OAAO,IAAA,EAAS,QAAA,EAAY,IAAA,GAAS,IAAA,EAAQ,OAAO,IAAA,CAAK,cAAA,EAAmB,UAAA,EAC5E,CAAC2D,EAAAA,EAAkB,CAAG,OAAO,IAAA,CACjC,GAAI,CACF,GAAI,OAAO,IAAA,CAAK,cAAA,CAAe,kBAAA,EAAuB,UAAA,EAAc,IAAA,CAAK,cAAA,CAAe,kBAAA,CAAmB,CAAC3D,CAAG,CAAC,CAAA,CAAE,MAAA,GAAW,CAAA,CAC3H,OAAO,IAAA,CAET,IAAMkE,CAAAA,CAAQ,IAAI,IAAA,CAAK,cAAA,CAAelE,CAAAA,CAAK,CACzC,QAAA,CAAU,SAAA,CACV,eAAA,CAAiB,MAAA,CACjB,QAAA,CAAU,KAAA,CACV,IAAA,CAAM,SAAA,CACN,KAAA,CAAO,SAAA,CACP,GAAA,CAAK,SACP,CAAC,CAAA,CAAE,aAAA,CAAcoD,EAAa,CAAA,CAC9B,GAAI,CAAC,KAAA,CAAM,OAAA,CAAQc,CAAK,CAAA,CAAG,OAAO,IAAA,CAClC,IAAMC,CAAAA,CAAWD,CAAAA,CACd,MAAA,CAAQE,CAAAA,EAASA,CAAAA,CAAK,IAAA,GAAS,MAAA,EAAUA,CAAAA,CAAK,IAAA,GAAS,OAAA,EAAWA,CAAAA,CAAK,IAAA,GAAS,KAAK,CAAA,CACrF,GAAA,CAAKA,CAAAA,EAASA,CAAAA,CAAK,IAAA,CAAK,CAAC,CAAA,CAAE,WAAA,EAAa,CAAA,CACxC,IAAA,CAAK,EAAE,CAAA,CACV,OAAOD,CAAAA,GAAa,KAAA,EAASA,CAAAA,GAAa,KAAA,EAASA,CAAAA,GAAa,KAAA,CAAQA,CAAAA,CAAW,IACrF,CAAA,KAAQ,CACN,OAAO,IACT,CACF,CC3JO,IAAME,CAAAA,CAAqB,CAMhC,yBAAA,CAA2B,2BAAA,CAS3B,mBAAA,CAAqB,qBAAA,CAOrB,uBAAA,CAAyB,yBAC3B,EAkEA,SAASC,EAAAA,CAAYtE,CAAAA,CAAsB,CACzC,GAAI,OAAO,IAAA,EAAS,QAAA,EAAY,IAAA,GAAS,IAAA,EAAQ,OAAO,IAAA,CAAK,mBAAA,EAAwB,UAAA,CAAY,OAAO,KAAA,CACxG,GAAI,CACF,OAAA,IAAA,CAAK,mBAAA,CAAoBA,CAAG,CAAA,CACrB,CAAA,CACT,CAAA,KAAQ,CACN,OAAO,MACT,CACF,CA+BO,SAASuE,EAAAA,CAAuBC,CAAAA,CAAqC,CAC1E,IAAMC,CAAAA,CAAkBD,CAAAA,CAAK,WAAA,CAC7B,GAAIC,CAAAA,GAAoB,MAAA,EAAa,CAACH,EAAAA,CAAYG,CAAe,CAAA,CAC/D,MAAMpH,mBAAAA,CAAa,MAAA,CACjBgH,CAAAA,CAAmB,yBAAA,CACnB,CAAA,kBAAA,EAAqBI,CAAe,CAAA,0EAAA,CAAA,CACpC,CAAE,WAAA,CAAaA,CAAgB,CACjC,CAAA,CAGF,IAAMC,CAAAA,CAAcF,CAAAA,CAAK,WAAA,CACnBG,CAAAA,CAAQH,CAAAA,CAAK,UAAA,CACnB,GAAIG,CAAAA,GAAU,KAAA,EAASA,CAAAA,GAAU,KAAA,EAASA,CAAAA,GAAU,KAAA,CAClD,OAAO,MAAA,CAAO,MAAA,CAAO,CAAE,KAAA,CAAAA,CAAAA,CAAO,WAAA,CAAa,QAAA,CAAmB,WAAA,CAAAD,CAAY,CAAC,CAAA,CAG7E,GAAIC,CAAAA,GAAU,QAAA,CAAU,CACtB,IAAM3E,CAAAA,CAAMyE,CAAAA,EAAmBZ,EAAAA,EAAW,CAC1C,GAAI7D,CAAAA,EAAQ,IAAA,CAA2B,CACrC,IAAM4E,CAAAA,CAAWd,EAAAA,CAAgB9D,CAAG,CAAA,CACpC,GAAI4E,CAAAA,GAAa,IAAA,CACf,OAAO,MAAA,CAAO,MAAA,CAAO,CACnB,KAAA,CAAOA,CAAAA,CACP,WAAA,CAAaH,CAAAA,GAAoB,MAAA,CAAa,QAAA,CAAsB,aAAA,CACpE,MAAA,CAAQzE,CAAAA,CACR,WAAA,CAAA0E,CACF,CAAC,CAEL,CAIA,OAAO,MAAA,CAAO,MAAA,CAAO,CAAE,KAAA,CAAO,MAAA,CAAiB,WAAA,CAAa,UAAA,CAAqB,WAAA,CAAAA,CAAY,CAAC,CAChG,CAEA,OAAO,MAAA,CAAO,MAAA,CAAO,CAAE,KAAA,CAAO,MAAA,CAAiB,WAAA,CAAa,WAAA,CAAsB,WAAA,CAAAA,CAAY,CAAC,CACjG,CAWO,IAAMG,EAAAA,CAAc,CACzB,SAAA,CAAW,UAAA,CAAY,OAAA,CAAS,OAAA,CAAS,KAAA,CAAO,MAAA,CAChD,MAAA,CAAQ,QAAA,CAAU,WAAA,CAAa,SAAA,CAAW,UAAA,CAAY,UACxD,CAAA,CAgCMC,CAAAA,CAAqB,WAAA,CAErBC,CAAAA,CAAkB,SAAA,CAcjB,SAASC,EAAAA,CACdC,CAAAA,CACAC,CAAAA,CACAC,CAAAA,CACAC,CAAAA,CACkB,CAClB,IAAMC,CAAAA,CAAaP,CAAAA,CAAmB,IAAA,CAAKG,CAAE,CAAA,CACvCK,CAAAA,CAAcR,CAAAA,CAAmB,IAAA,CAAKI,CAAE,CAAA,CACxCK,CAAAA,CAAYT,CAAAA,CAAmB,IAAA,CAAKK,CAAE,CAAA,CAC5C,OAAIC,CAAAA,GAAc,QAAA,EAAYL,CAAAA,CAAgB,IAAA,CAAKE,CAAE,CAAA,EAAKK,CAAAA,EAAeC,CAAAA,CAAkB,KAAA,CACvFF,CAAAA,EAAcC,CAAAA,EAAeP,CAAAA,CAAgB,IAAA,CAAKI,CAAE,CAAA,CAAU,aAAA,CAC9DC,CAAAA,GAAc,OAAA,EAAWL,CAAAA,CAAgB,IAAA,CAAKE,CAAE,CAAA,EAAKK,CAAAA,EAAeC,CAAAA,CAAkB,cAAA,CACtFF,CAAAA,EAAcC,CAAAA,EAAeC,CAAAA,CAAkB,OAAA,CAC5C,MACT,CAoCA,SAASC,EAAAA,CAAiBtD,CAAAA,CAA+B,CACvD,GAAIA,CAAAA,CAAO,MAAA,GAAW,CAAA,CAAG,OAAO,MAAA,CAAOA,CAAM,CAAA,CAC7C,GAAIA,CAAAA,CAAO,MAAA,GAAW,CAAA,CAAG,CACvB,IAAMuD,CAAAA,CAAK,MAAA,CAAOvD,CAAM,CAAA,CACxB,OAAOuD,CAAAA,EAAM,EAAA,CAAK,GAAA,CAAOA,CAAAA,CAAK,IAAA,CAAOA,CACvC,CACA,OAAO,IACT,CAgBO,SAASC,CAAAA,CAAkB/C,CAAAA,CAAaD,CAAAA,CAAeD,CAAAA,CAAuB,CAMnF,OAAIC,CAAAA,CAAQ,CAAA,EAAKA,CAAAA,CAAQ,EAAA,EAAMC,CAAAA,CAAM,CAAA,CAAU,KAAA,CACxCA,CAAAA,EAAOgD,mBAAAA,CAAYlD,CAAAA,CAAMC,CAAAA,CAAQ,CAAC,CAC3C,CAaO,SAASkD,EAAAA,CAAkBjD,CAAAA,CAAaD,CAAAA,CAAeD,CAAAA,CAAsB,CAClF,OAAIC,CAAAA,CAAQ,CAAA,EAAKA,CAAAA,CAAQ,EAAA,CAAW,CAAA,kBAAA,EAAqBA,CAAK,CAAA,CAAA,CAC1DC,CAAAA,CAAM,CAAA,CAAU,CAAA,gBAAA,EAAmBA,CAAG,CAAA,CAAA,CACnC,CAAA,EAAGkC,EAAAA,CAAYnC,CAAAA,CAAQ,CAAC,CAAC,CAAA,CAAA,EAAID,CAAI,CAAA,KAAA,EAAQkD,mBAAAA,CAAYlD,CAAAA,CAAMC,CAAAA,CAAQ,CAAC,CAAC,CAAA,KAAA,CAC9E,CAGA,SAASmD,CAAAA,CAASlD,CAAAA,CAAaD,CAAAA,CAAeD,CAAAA,CAAsB,CAClE,OAAO,CAAA,EAAGE,CAAG,CAAA,CAAA,EAAIkC,EAAAA,CAAYnC,CAAAA,CAAQ,CAAC,CAAC,CAAA,CAAA,EAAID,CAAI,CAAA,CACjD,CAWO,SAASqD,CAAAA,CAAMnD,CAAAA,CAAaD,CAAAA,CAAeD,CAAAA,CAAsB,CACtE,IAAMF,CAAAA,CAAO,CAAA,EAAc,MAAA,CAAO,CAAC,CAAA,CAAE,QAAA,CAAS,CAAA,CAAG,GAAG,CAAA,CACpD,OAAO,CAAA,EAAG,MAAA,CAAOE,CAAI,CAAA,CAAE,QAAA,CAAS,CAAA,CAAG,GAAG,CAAC,CAAA,CAAA,EAAIF,CAAAA,CAAIG,CAAK,CAAC,CAAA,CAAA,EAAIH,CAAAA,CAAII,CAAG,CAAC,CAAA,CACnE,CAGA,SAASoD,CAAAA,CAASpB,CAAAA,CAAuBM,CAAAA,CAAYC,CAAAA,CAA4C,CAC/F,OAAOP,CAAAA,GAAU,KAAA,CACb,CAAE,GAAA,CAAK,MAAA,CAAOM,CAAE,CAAA,CAAG,KAAA,CAAO,MAAA,CAAOC,CAAE,CAAE,CAAA,CACrC,CAAE,GAAA,CAAK,MAAA,CAAOA,CAAE,CAAA,CAAG,KAAA,CAAO,MAAA,CAAOD,CAAE,CAAE,CAC3C,CAGA,SAASe,CAAAA,CAAarB,CAAAA,CAA+B,CACnD,OAAIA,CAAAA,GAAU,KAAA,CAAc,WAAA,CACxBA,CAAAA,GAAU,KAAA,CAAc,aAAA,CACrB,YACT,CASA,SAASsB,EAAAA,CAAeb,CAAAA,CAAiD,CACvE,OAAOA,CAAAA,GAAc,QAAA,CAAW,KAAA,CAAQ,KAC1C,CAuBO,SAASc,EAAAA,CACdC,CAAAA,CACAxB,CAAAA,CACAD,CAAAA,CACAlD,CAAAA,CACiB,CACjB,GAAM,CAACyD,CAAAA,CAAIC,CAAAA,CAAIC,CAAE,CAAA,CAAIgB,CAAAA,CAAI,MAAA,CACnBC,CAAAA,CAAQpB,EAAAA,CAAYC,CAAAA,CAAIC,CAAAA,CAAIC,CAAAA,CAAIgB,CAAAA,CAAI,SAAS,CAAA,CAQ7CE,CAAAA,CAAiBF,CAAAA,CAAI,SAAA,GAAc,KAAA,CACnCG,CAAAA,CAAW5B,CAAAA,GAAgB,QAAA,EAAY,CAAC2B,CAAAA,CAE9C,GAAID,CAAAA,GAAU,MAAA,CAAQ,OAAO,CAAE,IAAA,CAAM,YAAa,CAAA,CAElD,GAAIA,CAAAA,GAAU,KAAA,CAAO,CACnB,IAAM3D,CAAAA,CAAO,MAAA,CAAOwC,CAAE,CAAA,CAChBvC,CAAAA,CAAQ,MAAA,CAAOwC,CAAE,CAAA,CACjBvC,CAAAA,CAAM,MAAA,CAAOwC,CAAE,CAAA,CACrB,OAAIO,CAAAA,CAAkB/C,CAAAA,CAAKD,CAAAA,CAAOD,CAAI,CAAA,CAC7B,CAAE,IAAA,CAAM,MAAA,CAAQ,GAAA,CAAAE,CAAAA,CAAK,KAAA,CAAAD,CAAAA,CAAO,IAAA,CAAAD,CAAAA,CAAM,KAAA,CAAO,KAAA,CAAO,SAAA,CAAW,KAAM,CAAA,CAInE6D,CAAAA,CAAWC,EAAAA,CAAgBJ,CAAAA,CAAI,IAAA,CAAMxD,CAAAA,CAAKD,CAAAA,CAAOD,CAAI,CAAA,CAAI,CAAE,IAAA,CAAM,YAAa,CACvF,CAEA,GAAI2D,CAAAA,GAAU,cAAA,CAAgB,CAC5B,GAAIzB,CAAAA,GAAU,KAAA,CAAO,OAAO,CAAE,IAAA,CAAM,YAAa,CAAA,CACjD,IAAMlC,CAAAA,CAAO,MAAA,CAAOwC,CAAE,CAAA,CAChBvC,CAAAA,CAAQ,MAAA,CAAOwC,CAAE,CAAA,CACjBvC,CAAAA,CAAM,MAAA,CAAOwC,CAAE,CAAA,CAGrB,OAAOO,CAAAA,CAAkB/C,CAAAA,CAAKD,CAAAA,CAAOD,CAAI,CAAA,CACrC,CAAE,IAAA,CAAM,MAAA,CAAQ,GAAA,CAAAE,CAAAA,CAAK,KAAA,CAAAD,CAAAA,CAAO,IAAA,CAAAD,CAAAA,CAAM,KAAA,CAAO,KAAA,CAAO,SAAA,CAAW,KAAM,CAAA,CACjE,CAAE,IAAA,CAAM,YAAa,CAC3B,CAIA,IAAMA,CAAAA,CAAO+C,EAAAA,CAAiBL,CAAE,CAAA,CAChC,GAAI1C,CAAAA,GAAS,IAAA,CAAM,OAAO,CAAE,IAAA,CAAM,YAAa,CAAA,CAC/C,IAAM+D,CAAAA,CAAYrB,CAAAA,CAAG,MAAA,GAAW,CAAA,CAEhC,GAAIR,CAAAA,GAAU,KAAA,CAGZ,OAAI,CAAC2B,CAAAA,EAAaF,CAAAA,GAAU,OAAA,EAAWC,CAAAA,CAAwB,CAAE,IAAA,CAAM,YAAa,CAAA,CAC7EI,EAAAA,CAA4BN,CAAAA,CAAI,IAAA,CAAMlB,CAAAA,CAAIC,CAAAA,CAAIzC,CAAc,CAAA,CAGrE,IAAMiE,CAAAA,CAAS/B,CAAAA,GAAU,MAAA,CAASsB,EAAAA,CAAeE,CAAAA,CAAI,SAAS,CAAA,CAAIxB,CAAAA,CAC5DgC,CAAAA,CAAwBD,CAAAA,GAAW,KAAA,CAAQ,KAAA,CAAQ,KAAA,CACnDE,CAAAA,CAAcb,CAAAA,CAASW,CAAAA,CAAQzB,CAAAA,CAAIC,CAAE,CAAA,CACrC2B,CAAAA,CAAad,CAAAA,CAASY,CAAAA,CAAO1B,CAAAA,CAAIC,CAAE,CAAA,CAEzC,GAAIQ,CAAAA,CAAkBkB,CAAAA,CAAY,GAAA,CAAKA,CAAAA,CAAY,KAAA,CAAOnE,CAAI,CAAA,CAAG,CAK/D,IAAMqE,CAAAA,CAAAA,CADUD,CAAAA,CAAW,GAAA,GAAQD,CAAAA,CAAY,GAAA,EAAOC,CAAAA,CAAW,KAAA,GAAUD,CAAAA,CAAY,KAAA,GACxDlB,CAAAA,CAAkBmB,CAAAA,CAAW,GAAA,CAAKA,CAAAA,CAAW,KAAA,CAAOpE,CAAI,CAAA,CACnFqD,CAAAA,CAAMe,CAAAA,CAAW,GAAA,CAAKA,CAAAA,CAAW,KAAA,CAAOpE,CAAI,CAAA,CAC5C,MAAA,CACJ,OAAO,CAAE,IAAA,CAAM,MAAA,CAAQ,GAAA,CAAKmE,CAAAA,CAAY,GAAA,CAAK,KAAA,CAAOA,CAAAA,CAAY,KAAA,CAAO,IAAA,CAAAnE,CAAAA,CAAM,KAAA,CAAOiE,CAAAA,CAAQ,SAAA,CAAAF,CAAAA,CAAW,WAAA,CAAAM,CAAY,CACrH,CAEA,OAAI,CAACR,CAAAA,EAAaF,CAAAA,GAAU,OAAA,EAAWC,CAAAA,CAAwB,CAAE,IAAA,CAAM,YAAa,CAAA,CAEhFX,CAAAA,CAAkBmB,CAAAA,CAAW,GAAA,CAAKA,CAAAA,CAAW,KAAA,CAAOpE,CAAI,CAAA,CACnD,CACL,IAAA,CAAM,QAAA,CACN,IAAA,CAAM4B,CAAAA,CAAmB,mBAAA,CACzB,OAAA,CACE,CAAA,CAAA,EAAI8B,CAAAA,CAAI,IAAI,CAAA,qBAAA,EAAwBH,CAAAA,CAAaU,CAAM,CAAC,CAAA,EAAA,EACrDd,EAAAA,CAAkBgB,CAAAA,CAAY,GAAA,CAAKA,CAAAA,CAAY,KAAA,CAAOnE,CAAI,CAAC,CAAA,OAAA,EACtDuD,CAAAA,CAAaW,CAAK,CAAC,CAAA,OAAA,EAAUd,CAAAA,CAASgB,CAAAA,CAAW,GAAA,CAAKA,CAAAA,CAAW,KAAA,CAAOpE,CAAI,CAAC,CAAA,0BAAA,EAC1DkE,CAAK,CAAA,wBAAA,EAA2BX,CAAAA,CAAaW,CAAK,CAAC,CAAA,CAAA,CAClF,CAAA,CAKKJ,EAAAA,CAAgBJ,CAAAA,CAAI,IAAA,CAAMS,CAAAA,CAAY,GAAA,CAAKA,CAAAA,CAAY,KAAA,CAAOnE,CAAI,CAC3E,CAGA,SAAS8D,EAAAA,CAAgB1E,CAAAA,CAAcc,CAAAA,CAAaD,CAAAA,CAAeD,CAAAA,CAA+B,CAChG,OAAO,CACL,IAAA,CAAM,QAAA,CACN,IAAA,CAAM4B,CAAAA,CAAmB,uBAAA,CACzB,OAAA,CAAS,CAAA,CAAA,EAAIxC,CAAI,CAAA,sBAAA,EAAyB+D,EAAAA,CAAkBjD,CAAAA,CAAKD,CAAAA,CAAOD,CAAI,CAAC,CAAA,CAAA,CAC/E,CACF,CAOA,SAASgE,EAAAA,CACP5E,CAAAA,CACAoD,CAAAA,CACAC,CAAAA,CACAzC,CAAAA,CACAjB,CAAAA,CACiB,CACjB,IAAMuF,CAAAA,CAAWhB,CAAAA,CAAS,KAAA,CAAOd,CAAAA,CAAIC,CAAE,CAAA,CACjC8B,CAAAA,CAAajB,CAAAA,CAAS,KAAA,CAAOd,CAAAA,CAAIC,CAAE,CAAA,CACnC+B,CAAAA,CAAevB,CAAAA,CAAkBqB,CAAAA,CAAS,GAAA,CAAKA,CAAAA,CAAS,KAAA,CAAOtE,CAAI,CAAA,CACnEyE,CAAAA,CAAiBxB,CAAAA,CAAkBsB,CAAAA,CAAW,GAAA,CAAKA,CAAAA,CAAW,KAAA,CAAOvE,CAAI,CAAA,CAE/E,GAAI,CAACwE,CAAAA,EAAgB,CAACC,CAAAA,CACpB,OAAOX,EAAAA,CAAgB1E,CAAAA,CAAMkF,CAAAA,CAAS,GAAA,CAAKA,CAAAA,CAAS,KAAA,CAAOtE,CAAI,CAAA,CAGjE,IAAM0E,CAAAA,CAAU,CAAA,CAAA,EAAItF,CAAI,CAAA,gCAAA,CAAA,CAGlBuF,CAAAA,CAAUL,CAAAA,CAAS,GAAA,GAAQC,CAAAA,CAAW,GAAA,EAAOD,CAAAA,CAAS,KAAA,GAAUC,CAAAA,CAAW,KAAA,CACjF,GAAIC,CAAAA,EAAgBC,CAAAA,EAAkB,CAACE,CAAAA,CACrC,OAAO,CACL,IAAA,CAAM,QAAA,CACN,IAAA,CAAM/C,CAAAA,CAAmB,mBAAA,CACzB,OAAA,CACE,CAAA,EAAG8C,CAAO,CAAA,sBAAA,EAAyBtB,CAAAA,CAASkB,CAAAA,CAAS,GAAA,CAAKA,CAAAA,CAAS,KAAA,CAAOtE,CAAI,CAAC,CAAA,iBAAA,EAC5DoD,CAAAA,CAASmB,CAAAA,CAAW,GAAA,CAAKA,CAAAA,CAAW,KAAA,CAAOvE,CAAI,CAAC,CAAA,cAAA,EACpDqD,CAAAA,CAAMiB,CAAAA,CAAS,GAAA,CAAKA,CAAAA,CAAS,KAAA,CAAOtE,CAAI,CAAC,CAAA,2CAAA,CAE5D,CAAA,CAGF,IAAM4E,CAAAA,CAAQJ,CAAAA,CAAeF,CAAAA,CAAWC,CAAAA,CAClCM,CAAAA,CAAwBL,CAAAA,CAAe,KAAA,CAAQ,KAAA,CACrD,OAAO,CACL,IAAA,CAAM,QAAA,CACN,IAAA,CAAM5C,CAAAA,CAAmB,mBAAA,CACzB,OAAA,CACE,CAAA,EAAG8C,CAAO,CAAA,MAAA,EAASnB,CAAAA,CAAasB,CAAK,CAAC,CAAA,OAAA,EAAUzB,CAAAA,CAASwB,CAAAA,CAAM,GAAA,CAAKA,CAAAA,CAAM,KAAA,CAAO5E,CAAI,CAAC,CAAA,cAAA,EACvEqD,CAAAA,CAAMuB,CAAAA,CAAM,GAAA,CAAKA,CAAAA,CAAM,KAAA,CAAO5E,CAAI,CAAC,CAAA,6BAAA,EAAgC6E,CAAK,CAAA,EAAA,CAC3F,CACF,CA6DA,SAASC,EAAAA,CAAcC,CAAAA,CAAyBpC,CAAAA,CAAyC,CACvF,GAAIoC,CAAAA,CAAM,WAAA,GAAgB,KAAA,CAAO,OAAO,KAAA,CACxC,GAAIA,CAAAA,CAAM,WAAA,GAAgB,SAAA,CAAW,OAAO,4BAAA,CAG5C,IAAM7C,CAAAA,CAAQ6C,CAAAA,CAAM,KAAA,GAAU,IAAA,EAAQA,CAAAA,CAAM,KAAA,GAAU,KAAA,EAASA,CAAAA,CAAM,KAAA,GAAU,SAAA,CAC3E,YAAA,CACAxB,CAAAA,CAAawB,CAAAA,CAAM,KAAK,CAAA,CAC5B,OAAQA,CAAAA,CAAM,WAAA,EACZ,KAAK,QAAA,CACH,OAAO,CAAA,EAAG7C,CAAK,CAAA,sBAAA,CAAA,CACjB,KAAK,QAAA,CACH,OAAO,CAAA,EAAGA,CAAK,CAAA,kBAAA,EAAqB6C,CAAAA,CAAM,MAAM,CAAA,CAAA,CAClD,KAAK,aAAA,CACH,OAAO,CAAA,EAAG7C,CAAK,CAAA,uBAAA,EAA0B6C,CAAAA,CAAM,MAAM,CAAA,CAAA,CACvD,KAAK,UAAA,CACH,OAAO,CAAA,EAAG7C,CAAK,CAAA,oBAAA,EAAuBS,CAAS,CAAA,gDAAA,CAAA,CACjD,QACE,OAAO,CAAA,EAAGT,CAAK,CAAA,oBAAA,EAAuBS,CAAS,CAAA,KAAA,CACnD,CACF,CAGA,SAASqC,EAAAA,CAASC,CAAAA,CAAqB,CACrC,GAAM,CAACjF,CAAAA,CAAMC,CAAAA,CAAOC,CAAG,CAAA,CAAI+E,CAAAA,CAAI,KAAA,CAAM,GAAG,CAAA,CAAE,GAAA,CAAI,MAAM,CAAA,CACpD,OAAO7B,CAAAA,CAASlD,CAAAA,CAAKD,CAAAA,CAAOD,CAAI,CAClC,CAmBO,SAASkF,EAAAA,CACdH,CAAAA,CACApC,CAAAA,CACAwC,CAAAA,CACQ,CACR,GAAIJ,CAAAA,CAAM,GAAA,GAAQ,IAAA,CAAM,OAAOI,CAAAA,EAAW,CAAA,CAAA,EAAIJ,CAAAA,CAAM,IAAI,CAAA,qCAAA,CAAA,CACxD,IAAIK,CAAAA,CAAO,CAAA,EAAGL,CAAAA,CAAM,IAAI,CAAA,SAAA,EAAYC,EAAAA,CAASD,CAAAA,CAAM,GAAG,CAAC,CAAA,EAAA,EAAKD,EAAAA,CAAcC,CAAAA,CAAOpC,CAAS,CAAC,CAAA,CAAA,CAAA,CAC3F,GAAIoC,CAAAA,CAAM,WAAA,GAAgB,MAAA,EAAaA,CAAAA,CAAM,KAAA,GAAU,IAAA,EAAQA,CAAAA,CAAM,KAAA,GAAU,KAAA,EAASA,CAAAA,CAAM,KAAA,GAAU,SAAA,CAAW,CACjH,IAAMb,CAAAA,CAAQa,CAAAA,CAAM,KAAA,GAAU,KAAA,CAAQ,aAAA,CAAgB,WAAA,CACtDK,CAAAA,EAAQ,CAAA,CAAA,EAAIlB,CAAK,CAAA,UAAA,EAAac,EAAAA,CAASD,CAAAA,CAAM,WAAW,CAAC,CAAA,CAAA,EAC3D,CACA,OAAIA,CAAAA,CAAM,SAAA,GACRK,CAAAA,EAAQ,CAAA,oBAAA,EAAuBL,CAAAA,CAAM,IAAA,CAAK,KAAA,CAAM,EAAE,CAAC,CAAA,aAAA,EAAgBA,CAAAA,CAAM,GAAA,CAAI,KAAA,CAAM,CAAA,CAAG,CAAC,CAAC,CAAA,CAAA,CAAA,CAAA,CAEnFK,CACT,CAWO,SAASC,EAAAA,CACdN,CAAAA,CACApC,CAAAA,CACAwC,CAAAA,CACa,CACb,OAAO,CACL,GAAGJ,CAAAA,CACH,IAAA,CAAMG,EAAAA,CAAmBH,CAAAA,CAAOpC,CAAAA,CAAWwC,CAAO,CAAA,CAClD,SAAA,CAAWJ,CAAAA,CAAM,SAAA,EAAaA,CAAAA,CAAM,SAAA,EAAaA,CAAAA,CAAM,GAAA,GAAQ,IACjE,CACF,CAeO,SAASO,EAAAA,CAAgBlG,CAAAA,CAAqC,CACnE,IAAMmG,CAAAA,CAAY,2BAAA,CAA4B,IAAA,CAAKnG,CAAI,CAAA,CACvD,GAAImG,CAAAA,GAAc,IAAA,CAChB,OAAO,CACL,IAAA,CAAAnG,CAAAA,CACA,MAAA,CAAQ,CAACmG,CAAAA,CAAU,CAAC,CAAA,CAAGA,CAAAA,CAAU,CAAC,CAAA,CAAGA,CAAAA,CAAU,CAAC,CAAC,CAAA,CACjD,SAAA,CAAWA,CAAAA,CAAU,CAAC,CAAA,GAAM,GAAA,CAAM,QAAA,CAAW,OAC/C,CAAA,CAEF,IAAMC,CAAAA,CAAS,uCAAA,CAAwC,IAAA,CAAKpG,CAAI,CAAA,CAChE,OAAIoG,CAAAA,GAAW,IAAA,CACN,CAAE,IAAA,CAAApG,CAAAA,CAAM,MAAA,CAAQ,CAACoG,CAAAA,CAAO,CAAC,CAAA,CAAGA,CAAAA,CAAO,CAAC,CAAA,CAAGA,CAAAA,CAAO,CAAC,CAAC,CAAA,CAAG,SAAA,CAAW,KAAM,CAAA,CAEtE,IACT,CCntBO,IAAMC,EAAAA,CAAwB,kBAAA,CAC/BC,EAAAA,CAA2B7I,mBAAAA,CAAY4I,EAAqB,CAAA,CAarDE,EAAAA,CAAmC,6BAAA,CAC1CC,EAAAA,CAAsC/I,mBAAAA,CAAY8I,EAAgC,CAAA,CAGlFE,CAAAA,CAAgB,OAAA,CAIhBC,EAAAA,CAAgB,oBAAA,CAIhBC,EAAAA,CAAmB,oBAgDzB,SAASC,EAAAA,CAAgBxJ,CAAAA,CAA0B,CACjD,IAAA,IAAS6B,CAAAA,CAAI,CAAA,CAAGA,CAAAA,CAAI7B,CAAAA,CAAO,MAAA,CAAS,CAAA,CAAG6B,CAAAA,EAAAA,CAAK,CAC1C,IAAM1D,CAAAA,CAAQ6B,CAAAA,CAAO6B,CAAC,CAAA,CAEtB,GAAA,CADY1D,CAAAA,CAAM,SAAA,EAAaA,CAAAA,CAAM,MAAA,CAASA,CAAAA,CAAM,IAAA,CAAK,MAAA,IAC7C6B,CAAAA,CAAO6B,CAAAA,CAAI,CAAC,CAAA,CAAE,MAAA,CAAQ,OAAO,MAC3C,CACA,OAAO,KACT,CAUO,SAAS4H,EAAAA,CACd/F,CAAAA,CACAD,CAAAA,CACAD,CAAAA,CACAkG,CAAAA,CACAC,CAAAA,CACApH,CAAAA,CACwB,CACxB,GAAIkB,CAAAA,CAAQ,CAAA,EAAKA,CAAAA,CAAQ,EAAA,EAAMC,CAAAA,CAAM,CAAA,EAAKA,CAAAA,CAAM,EAAA,CAAI,OAAO,IAAA,CAI3D,IAAMN,CAAAA,CAAUb,CAAAA,CAAS,aAAA,CAAciB,CAAAA,CAAMC,CAAAA,CAAQ,CAAA,CAAGC,CAAG,CAAA,CAIrDkG,CAAAA,CAAQrH,CAAAA,CAAS,MAAA,CAAOa,CAAO,CAAA,CACrC,GAAIwG,CAAAA,CAAM,IAAA,GAASpG,CAAAA,EAAQoG,CAAAA,CAAM,MAAA,GAAWnG,CAAAA,CAAQ,CAAA,EAAKmG,CAAAA,CAAM,GAAA,GAAQlG,CAAAA,CACrE,OAAO,IAAA,CAGT,IAAMmG,CAAAA,CAAQH,CAAAA,CAAa,CAAC,CAAA,CACtB9G,CAAAA,CAAO8G,CAAAA,CAAa,GAAA,CAAKI,CAAAA,EAAMA,CAAAA,CAAE,KAAK,CAAA,CAAE,IAAA,CAAK,EAAE,CAAA,CAC/CC,CAAAA,CAAa,IAAI3J,mBAAAA,CACrB6I,EAAAA,CACAC,EAAAA,CACA,MAAA,CAAO9F,CAAO,CAAA,CACdR,CAAAA,CACAiH,CAAAA,CAAM,MAAA,CACN,CAAA,CACAA,CAAAA,CAAM,IAAA,CACNA,CAAAA,CAAM,GACR,CAAA,CAEA,OAAO,CAAE,QAAA,CAAUH,CAAAA,CAAa,MAAA,CAAQ,WAAA,CAAa,CAACK,CAAU,CAAA,CAAG,QAAA,CAAAJ,CAAS,CAC9E,CAeO,SAASK,EAAAA,CAAQhK,CAAAA,CAAyB,CAC/C,IAAIiK,CAAAA,CAAM,EAAA,CACNC,CAAAA,CAAc,EAAA,CAClB,IAAA,IAAW/L,CAAAA,IAAS6B,CAAAA,CAAQ,CAC1B,IAAM4C,CAAAA,CAAOzE,CAAAA,CAAM,IAAA,EAAQA,CAAAA,CAAM,KAAA,CAC7B+L,CAAAA,EAAe,CAAA,EAAK/L,CAAAA,CAAM,MAAA,CAAS+L,CAAAA,GAAaD,CAAAA,EAAO,GAAA,CAAA,CAC3DA,CAAAA,EAAOrH,CAAAA,CACPsH,CAAAA,CAAc/L,CAAAA,CAAM,SAAA,EAAaA,CAAAA,CAAM,MAAA,CAASyE,CAAAA,CAAK,OACvD,CACA,OAAOqH,CACT,CAqBO,SAASE,EAAAA,CACdC,CAAAA,CACAC,CAAAA,CACAX,CAAAA,CACAC,CAAAA,CACiB,CACjB,IAAME,CAAAA,CAAQH,CAAAA,CAAa,CAAC,CAAA,CACtB9G,CAAAA,CAAOoH,EAAAA,CAAQN,CAAY,CAAA,CAC3BK,CAAAA,CAAa,IAAI3J,mBAAAA,CACrB+I,EAAAA,CACAC,EAAAA,CACAxG,CAAAA,CACAA,CAAAA,CACAiH,CAAAA,CAAM,MAAA,CACN,CAAA,CACAA,CAAAA,CAAM,IAAA,CACNA,CAAAA,CAAM,GACR,CAAA,CAIA,OAAAE,CAAAA,CAAW,KAAA,CAAQ,CAAE,IAAA,CAAAK,CAAAA,CAAM,OAAA,CAAAC,CAAQ,CAAA,CAC5B,CAAE,QAAA,CAAUX,CAAAA,CAAa,MAAA,CAAQ,WAAA,CAAa,CAACK,CAAU,CAAA,CAAG,QAAA,CAAAJ,CAAS,CAC9E,CA8BA,IAAMW,EAAAA,CAAgB,sEAAA,CAOhBC,EAAAA,CAAkB,IAAI,GAAA,CAAI,CAAC,QAAA,CAAU,OAAA,CAAS,MAAA,CAAQ,OAAA,CAAS,OAAO,CAAC,CAAA,CAOvEC,EAAAA,CAAiB,EAAA,CA6BvB,SAASC,EAAAA,CAAiBzK,CAAAA,CAAiBC,CAAAA,CAAa0J,CAAAA,CAAkBpH,CAAAA,CAAmD,CAC3H,IAAMsH,CAAAA,CAAQ7J,CAAAA,CAAOC,CAAG,CAAA,CACxB,GAAI4J,CAAAA,CAAM,SAAA,GAAc,MAAA,CAAW,OAAO,IAAA,CAC1C,IAAIjH,CAAAA,CAAOiH,CAAAA,CAAM,IAAA,CACba,CAAAA,CAASb,CAAAA,CAAM,MAAA,CAASA,CAAAA,CAAM,IAAA,CAAK,MAAA,CACjCc,CAAAA,CAAkB,CAACd,CAAK,CAAA,CAC9B,IAAA,IAAShI,CAAAA,CAAI5B,CAAAA,CAAM,CAAA,CAAG4B,CAAAA,CAAI7B,CAAAA,CAAO,MAAA,EAAU2K,CAAAA,CAAO,MAAA,CAASH,EAAAA,CAAgB3I,CAAAA,EAAAA,CAAK,CAC9E,IAAM+I,CAAAA,CAAO5K,CAAAA,CAAO6B,CAAC,CAAA,CAErB,GADI+I,CAAAA,CAAK,SAAA,GAAc,MAAA,EACnBA,CAAAA,CAAK,MAAA,GAAWF,CAAAA,EAAU,CAACH,EAAAA,CAAgB,GAAA,CAAIK,CAAAA,CAAK,IAAI,CAAA,CAAG,MAC/DhI,CAAAA,EAAQgI,CAAAA,CAAK,IAAA,CACbF,CAAAA,CAASE,CAAAA,CAAK,MAAA,CAASA,CAAAA,CAAK,IAAA,CAAK,MAAA,CACjCD,CAAAA,CAAO,IAAA,CAAKC,CAAI,EAClB,CAEA,IAAM/H,CAAAA,CAAUyH,EAAAA,CAAc,IAAA,CAAK1H,CAAI,CAAA,CACvC,GAAIC,CAAAA,GAAY,IAAA,CAAM,OAAO,IAAA,CAK7B,IAAIgI,CAAAA,CAAW,CAAA,CACXC,CAAAA,CAAU,CAAA,CACd,IAAA,IAAW3M,CAAAA,IAASwM,CAAAA,CAGlB,GAFAG,CAAAA,EAAW3M,CAAAA,CAAM,IAAA,CAAK,MAAA,CACtB0M,CAAAA,EAAAA,CACIC,CAAAA,EAAWjI,CAAAA,CAAQ,CAAC,CAAA,CAAE,MAAA,CAAQ,MAEpC,GAAIiI,CAAAA,GAAYjI,CAAAA,CAAQ,CAAC,CAAA,CAAE,MAAA,CAAQ,OAAO,IAAA,CAM1C,IAAMO,CAAAA,CAAUf,EAAAA,CAAaQ,CAAAA,CAAQ,CAAC,CAAA,CAAGN,CAAQ,CAAA,CACjD,GAAIa,CAAAA,GAAY,IAAA,CAAM,OAAO,IAAA,CAE7B,IAAM2G,CAAAA,CAAa,IAAI3J,mBAAAA,CACrB6I,EAAAA,CACAC,EAAAA,CACA,MAAA,CAAO9F,CAAO,CAAA,CACdP,CAAAA,CAAQ,CAAC,CAAA,CACTgH,CAAAA,CAAM,MAAA,CACN,CAAA,CACAA,CAAAA,CAAM,IAAA,CACNA,CAAAA,CAAM,GAAA,CACNA,CAAAA,CAAM,MAAA,CAAShH,CAAAA,CAAQ,CAAC,CAAA,CAAE,MAC5B,CAAA,CACA,OAAO,CAAE,QAAA,CAAAgI,CAAAA,CAAU,WAAA,CAAa,CAACd,CAAU,CAAA,CAAG,QAAA,CAAAJ,CAAS,CACzD,CAiEO,SAASoB,EAAAA,CACdC,CAAAA,CAAyC,IAAM,MAAA,CAC/CC,CAAAA,CAAqC,IAAMC,mBAAAA,CAC3CC,CAAAA,CAAsC,IAAM,QAAA,CAC5B,CAChB,OAAO,CACL,IAAA,CAAM,uBAAA,CACN,QAAA,CAAU,EAAA,CAGV,KAAA,CAAO,CAAC,CAAE,KAAA,CAAO,CAAC,QAAQ,CAAE,CAAC,CAAA,CAC7B,KAAA,CAAMnL,CAAAA,CAAiBC,CAAAA,CAAqC,CAC1D,IAAMmL,CAAAA,CAAKpL,CAAAA,CAAOC,CAAG,CAAA,CACrB,GAAImL,CAAAA,CAAG,IAAA,GAAS,QAAA,CAAU,OAAO,IAAA,CACjC,IAAM7I,CAAAA,CAAW0I,CAAAA,EAAY,CAS7B,GAAI3B,EAAAA,CAAc,IAAA,CAAK8B,CAAAA,CAAG,KAAK,CAAA,CAAG,CAChC,IAAMC,CAAAA,CAAKrL,CAAAA,CAAOC,CAAAA,CAAM,CAAC,CAAA,CACzB,GAAIoL,CAAAA,EAAMA,CAAAA,CAAG,IAAA,GAAS,QAAA,EAAY9B,EAAAA,CAAiB,IAAA,CAAK8B,CAAAA,CAAG,KAAK,CAAA,CAAG,CACjE,GAAM,CAACxB,CAAAA,CAAOyB,CAAM,CAAA,CAAIF,CAAAA,CAAG,KAAA,CAAM,KAAA,CAAM,GAAG,CAAA,CACpCG,CAAAA,CAAS,CACb,IAAA,CAAM,CAAA,EAAGH,CAAAA,CAAG,KAAK,CAAA,EAAGC,CAAAA,CAAG,KAAK,CAAA,CAAA,CAC5B,MAAA,CAAQ,CAACxB,CAAAA,CAAOyB,CAAAA,CAAQD,CAAAA,CAAG,KAAA,CAAM,KAAA,CAAM,CAAC,CAAC,CAAA,CACzC,SAAA,CAAW,KACb,CAAA,CACMG,CAAAA,CAAavE,EAAAA,CAAgBsE,CAAAA,CAAQP,CAAAA,EAAc,CAAGG,CAAAA,EAA0B,CAAA,CACtF,GAAIK,CAAAA,CAAW,IAAA,GAAS,MAAA,CACtB,OAAO/B,EAAAA,CACL+B,CAAAA,CAAW,GAAA,CAAKA,CAAAA,CAAW,KAAA,CAAOA,CAAAA,CAAW,IAAA,CAC7C,CAACJ,CAAAA,CAAIC,CAAE,CAAA,CAAG,2BAAA,CAA6B9I,CACzC,CAAA,CAEF,GAAIiJ,CAAAA,CAAW,IAAA,GAAS,QAAA,CACtB,OAAOrB,EAAAA,CAAWqB,CAAAA,CAAW,IAAA,CAAMA,CAAAA,CAAW,OAAA,CAAS,CAACJ,CAAAA,CAAIC,CAAE,CAAA,CAAG,sCAAsC,CAE3G,CACA,OAAO,IACT,CAMA,GAAID,CAAAA,CAAG,KAAA,CAAM,MAAA,GAAW,CAAA,EAAK/B,CAAAA,CAAc,IAAA,CAAK+B,CAAAA,CAAG,KAAK,CAAA,CAAG,CACzD,IAAMK,CAAAA,CAAYhB,EAAAA,CAAiBzK,CAAAA,CAAQC,CAAAA,CAAK,qCAAA,CAAuCsC,CAAQ,CAAA,CAC/F,GAAIkJ,CAAAA,CAAW,OAAOA,CACxB,CAGA,GAAI,CAACpC,CAAAA,CAAc,IAAA,CAAK+B,CAAAA,CAAG,KAAK,CAAA,CAAG,OAAO,IAAA,CAC1C,IAAMM,CAAAA,CAAO1L,CAAAA,CAAOC,CAAAA,CAAM,CAAC,CAAA,CAC3B,GAAI,CAACyL,CAAAA,EAASA,CAAAA,CAAK,IAAA,GAAS,OAAA,EAAWA,CAAAA,CAAK,IAAA,GAAS,OAAA,CAAU,OAAO,IAAA,CACtE,IAAML,CAAAA,CAAKrL,CAAAA,CAAOC,CAAAA,CAAM,CAAC,CAAA,CACnB0L,CAAAA,CAAO3L,CAAAA,CAAOC,CAAAA,CAAM,CAAC,CAAA,CACrB2L,CAAAA,CAAK5L,CAAAA,CAAOC,CAAAA,CAAM,CAAC,CAAA,CAGzB,GAFI,CAACoL,CAAAA,EAAMA,CAAAA,CAAG,IAAA,GAAS,QAAA,EAAY,CAAChC,CAAAA,CAAc,IAAA,CAAKgC,CAAAA,CAAG,KAAK,CAAA,EAC3D,CAACM,CAAAA,EAAQA,CAAAA,CAAK,IAAA,GAASD,CAAAA,CAAK,IAAA,EAC5B,CAACE,CAAAA,EAAMA,CAAAA,CAAG,IAAA,GAAS,QAAA,EAAY,CAACvC,CAAAA,CAAc,IAAA,CAAKuC,CAAAA,CAAG,KAAK,CAAA,CAAG,OAAO,IAAA,CAEzE,IAAMlC,CAAAA,CAAe,CAAC0B,CAAAA,CAAIM,CAAAA,CAAML,CAAAA,CAAIM,CAAAA,CAAMC,CAAE,CAAA,CAM5C,GAAI,CAACpC,EAAAA,CAAgBE,CAAY,CAAA,CAAG,OAAO,IAAA,CAO3C,IAAMxC,CAAAA,CAAM,CACV,IAAA,CAAMwC,CAAAA,CAAa,GAAA,CAAKvL,CAAAA,EAAUA,CAAAA,CAAM,KAAK,CAAA,CAAE,IAAA,CAAK,EAAE,CAAA,CACtD,MAAA,CAAQ,CAACiN,CAAAA,CAAG,KAAA,CAAOC,CAAAA,CAAG,KAAA,CAAOO,CAAAA,CAAG,KAAK,CAAA,CACrC,SAAA,CAAYF,CAAAA,CAAK,IAAA,GAAS,OAAA,CAAU,QAAA,CAAW,OACjD,CAAA,CACMG,CAAAA,CAAU5E,EAAAA,CAAgBC,CAAAA,CAAK8D,CAAAA,EAAc,CAAGG,CAAAA,EAA0B,CAAA,CAChF,OAAIU,CAAAA,CAAQ,IAAA,GAAS,YAAA,CAAqB,IAAA,CACtCA,CAAAA,CAAQ,IAAA,GAAS,QAAA,CACZ1B,EAAAA,CAAW0B,CAAAA,CAAQ,IAAA,CAAMA,CAAAA,CAAQ,OAAA,CAASnC,CAAAA,CAAc,kCAAkC,CAAA,CAE5FD,EAAAA,CACLoC,CAAAA,CAAQ,GAAA,CAAKA,CAAAA,CAAQ,KAAA,CAAOA,CAAAA,CAAQ,IAAA,CAAMnC,CAAAA,CAC1C,CAAA,sBAAA,EAAyBmC,CAAAA,CAAQ,KAAA,CAAM,WAAA,EAAa,CAAA,CAAA,CAAItJ,CAC1D,CACF,CACF,CACF","file":"chunk-RKNUCZ6P.cjs","sourcesContent":["import { PrefixParselet } from \"@solve-js/parser/Parselet\";\nimport { Parser } from \"@solve-js/parser/Parser\";\nimport { Token } from \"@solve-js/lexer/Token\";\nimport { BytecodeBuilder } from \"@solve-js/parser/BytecodeBuilder\";\nimport { OpCode } from \"@solve-js/parser/OpCode\";\nimport { BindingPower } from \"@solve-js/parser/BindingPower\";\nimport { SYMBOLIC_BUILTIN_EXPAND } from \"@solve-js/packages/symbolic/SymbolicBuiltinIndex\";\n\n/**\n * `expand(expr)`, multiplying out every product and power.\n *\n * A dedicated parselet rather than a `builtinNameToIndex` entry reached through\n * the ordinary `FunctionCallParselet`, because that route needs the lexer to\n * emit `FUNC` for the word, which means a `keywordMap` entry, which would stop\n * `expand` working as an ordinary variable name. See\n * `normalizer/SymbolicCallNormalizerRule.ts`.\n *\n * The emitted bytecode is an ordinary `CALL_BUILTIN`, so no new opcode and no\n * new VM dispatch arm is involved.\n */\nexport class ExpandParselet implements PrefixParselet {\n\treadonly category = \"Symbolic\";\n\n\tparse(parser: Parser, _token: Token, builder: BytecodeBuilder): void {\n\t\tparser.consume(\"LPAREN\");\n\t\tparser.parseExpression(BindingPower.Lowest, builder);\n\t\tparser.consume(\"RPAREN\");\n\n\t\tbuilder.emitOpcode(OpCode.CALL_BUILTIN);\n\t\tbuilder.emitIndex(SYMBOLIC_BUILTIN_EXPAND);\n\t\tbuilder.emitIndex(1);\n\t}\n}\n","import { PrefixParselet } from \"@solve-js/parser/Parselet\";\nimport { Parser } from \"@solve-js/parser/Parser\";\nimport { Token } from \"@solve-js/lexer/Token\";\nimport { BytecodeBuilder } from \"@solve-js/parser/BytecodeBuilder\";\nimport { OpCode } from \"@solve-js/parser/OpCode\";\nimport { BindingPower } from \"@solve-js/parser/BindingPower\";\nimport { SYMBOLIC_BUILTIN_FACTOR } from \"@solve-js/packages/symbolic/SymbolicBuiltinIndex\";\n\n/**\n * `factor(expr)`, writing a polynomial as a product of irreducible factors over the rationals.\n *\n * A dedicated parselet rather than a `builtinNameToIndex` entry reached through\n * the ordinary `FunctionCallParselet`, because that route needs the lexer to\n * emit `FUNC` for the word, which means a `keywordMap` entry, which would stop\n * `expand` working as an ordinary variable name. See\n * `normalizer/SymbolicCallNormalizerRule.ts`.\n *\n * The emitted bytecode is an ordinary `CALL_BUILTIN`, so no new opcode and no\n * new VM dispatch arm is involved.\n */\nexport class FactorParselet implements PrefixParselet {\n\treadonly category = \"Symbolic\";\n\n\tparse(parser: Parser, _token: Token, builder: BytecodeBuilder): void {\n\t\tparser.consume(\"LPAREN\");\n\t\tparser.parseExpression(BindingPower.Lowest, builder);\n\t\tparser.consume(\"RPAREN\");\n\n\t\tbuilder.emitOpcode(OpCode.CALL_BUILTIN);\n\t\tbuilder.emitIndex(SYMBOLIC_BUILTIN_FACTOR);\n\t\tbuilder.emitIndex(1);\n\t}\n}\n","import { Parser } from \"@solve-js/parser/Parser\";\nimport { BytecodeBuilder, type BytecodeProgram } from \"@solve-js/parser/BytecodeBuilder\";\nimport { OpCode } from \"@solve-js/parser/OpCode\";\nimport { BindingPower } from \"@solve-js/parser/BindingPower\";\nimport { ErrorFactory } from \"@solve-js/errors/UnifiedErrorFramework\";\n\n/**\n * Reads a bare variable name argument and returns it, consuming the token.\n *\n * Shared by every algebra verb that takes \"which unknown\" as an argument.\n * Compiling the name as an ordinary variable read would require it to already\n * have a value, which is precisely what differentiating or solving with respect\n * to it says it does not.\n *\n * Requiring `IDENT` or `UNIT` here gives the same reserved-word protection\n * `VariableParselet` relies on: a keyword always lexes as its own token type,\n * so it can never reach this position and be taken for a variable name.\n *\n * @param parser - The parser, positioned at the name.\n * @param verb - The calling verb's name, for the error message.\n * @returns The name as written.\n * @throws {EngineError} `SYMBOLIC_REQUIRES_VARIABLE_NAME` when the next token is\n * not a bare name.\n */\nexport function readVariableName(parser: Parser, verb: string): string {\n\tconst token = parser.peek();\n\tif (!token || (token.type !== \"IDENT\" && token.type !== \"UNIT\")) {\n\t\tthrow ErrorFactory.parsing(\n\t\t\t\"SYMBOLIC_REQUIRES_VARIABLE_NAME\",\n\t\t\t`${verb} needs the name of an unknown here, as in ${verb}(x^2, x).`,\n\t\t\t{ found: token?.type ?? \"end of input\" },\n\t\t);\n\t}\n\tparser.consume();\n\treturn token.value;\n}\n\n/** Emits an already-read unknown's name as the String argument the algebra builtins read it as. */\nexport function emitVariableName(builder: BytecodeBuilder, name: string): void {\n\tbuilder.emitOpcode(OpCode.PUSH_STRING);\n\tbuilder.emitString(name);\n}\n\n/**\n * Parses an algebra verb's expression argument into its own independent\n * program, rather than emitting it inline.\n *\n * The verb names its unknown AFTER the expression (`der(x^2, x)`), so the\n * expression has to be held rather than emitted: only once the name is known\n * can it be paired with {@link emitBoundExpression}, which is what makes the\n * name shadow any document value it happens to share. Compiled into an\n * isolated builder exactly like a user-defined function body or a map/reduce\n * transform, and `parseExpression` leaves `parser.builder` pointing at the\n * isolated one with no automatic restore, so the caller's builder is put back\n * before returning.\n *\n * @param parser - The parser, positioned at the start of the expression.\n * @param builder - The builder to restore afterwards.\n * @param verb - The calling verb's name, for the error message.\n * @returns The compiled expression, to be handed to {@link emitBoundExpression}.\n */\nexport function parseBoundExpression(parser: Parser, builder: BytecodeBuilder, verb: string): BytecodeProgram {\n\tconst inner = new BytecodeBuilder(builder.pluginIndexMap);\n\tparser.parseExpression(BindingPower.Lowest, inner);\n\tparser.setBuilder(builder);\n\tconst program = inner.build();\n\tif (program.hasAsync) {\n\t\t// Same v1 restriction every other deferred body carries (user-defined\n\t\t// functions, map/reduce transforms): a reentrant execution cannot\n\t\t// suspend and resume the outer expression around an async result.\n\t\tthrow ErrorFactory.parsing(\n\t\t\t\"SYMBOLIC_ARGUMENT_MUST_BE_SYNCHRONOUS\",\n\t\t\t`${verb}'s expression must be synchronous (no weather/stocks/currency calls).`,\n\t\t);\n\t}\n\treturn program;\n}\n\n/**\n * Emits a held expression so that it evaluates with `name` bound to itself.\n *\n * This is what makes `der(x^2, x)` mean the derivative of a square rather than\n * the derivative of a constant on a page that also says `:x = 5`. Naming `x` as\n * the verb's argument declares it bound, so within the expression it is an\n * unknown and nothing else, exactly the way a function's parameter shadows a\n * document variable of the same name inside its body. Before this, the\n * expression was compiled inline and its `x` was an ordinary variable read, so\n * the verb received 25 and answered 0 with no indication that it had not been\n * asked the question the user wrote.\n *\n * @param builder - The builder to emit into.\n * @param program - The expression, from {@link parseBoundExpression}.\n * @param name - The unknown the verb named, bound for the expression's evaluation.\n */\nexport function emitBoundExpression(builder: BytecodeBuilder, program: BytecodeProgram, name: string): void {\n\tconst index = builder.emitAnonymousBody([name], program);\n\tbuilder.emitOpcode(OpCode.BIND_UNKNOWN);\n\tbuilder.emitIndex(index);\n}\n","import { PrefixParselet } from \"@solve-js/parser/Parselet\";\nimport { Parser } from \"@solve-js/parser/Parser\";\nimport { Token } from \"@solve-js/lexer/Token\";\nimport { BytecodeBuilder } from \"@solve-js/parser/BytecodeBuilder\";\nimport { OpCode } from \"@solve-js/parser/OpCode\";\nimport { ErrorFactory } from \"@solve-js/errors/UnifiedErrorFramework\";\nimport { SYMBOLIC_BUILTIN_SOLVE } from \"@solve-js/packages/symbolic/SymbolicBuiltinIndex\";\nimport { emitVariableName, parseBoundExpression, emitBoundExpression } from \"@solve-js/packages/symbolic/parselets/VariableArgument\";\n\n/**\n * `solve(equation, variable)`, for example `solve(x^2-4=0, x)`.\n *\n * Two things here cannot go through the ordinary function-call grammar, which\n * is why this is a hand-written parselet.\n *\n * The first argument contains a bare `=`, which no infix parselet consumes, so\n * an ordinary argument list would fail to parse it. This reads the two sides\n * separately and lets a missing right-hand side default to zero, so\n * `solve(x^2-4, x)` means the same as `solve(x^2-4=0, x)`.\n *\n * The second argument is a *name*, not a value. Compiling it as a `LOAD_VAR`\n * would demand that the variable already exist, which is exactly what solving\n * for it says it does not. Emitting it as a `PUSH_STRING` instead means the\n * builtin receives a plain String value and the VM needs no change at all.\n *\n * Both sides of the equation are held until that name has been read, so each\n * evaluates with the unknown bound to itself rather than to whatever value the\n * document may already have given it. See {@link emitBoundExpression}: with\n * `:x = 5` above it, `solve(x^2-4=0, x)` was solving `21 = 0` and reporting,\n * accurately for the question it was asked and uselessly for the one written,\n * that there is no solution.\n */\nexport class SolveParselet implements PrefixParselet {\n\treadonly category = \"Symbolic\";\n\n\tparse(parser: Parser, _token: Token, builder: BytecodeBuilder): void {\n\t\tparser.consume(\"LPAREN\");\n\t\tconst left = parseBoundExpression(parser, builder, \"solve\");\n\t\tconst right = parser.match(\"EQUALS\") ? parseBoundExpression(parser, builder, \"solve\") : null;\n\n\t\tparser.consume(\"COMMA\");\n\t\t// Requiring IDENT or UNIT here is the same protection VariableParselet\n\t\t// relies on: a reserved word always lexes as its own token type, so it\n\t\t// can never reach this position and be mistaken for a variable name.\n\t\tconst variable = parser.peek();\n\t\tif (!variable || (variable.type !== \"IDENT\" && variable.type !== \"UNIT\")) {\n\t\t\tthrow ErrorFactory.parsing(\n\t\t\t\t\"SOLVE_REQUIRES_VARIABLE_NAME\",\n\t\t\t\t`solve's second argument must be the name of the unknown to solve for, as in solve(x^2-4=0, x).`,\n\t\t\t\t{ found: variable?.type ?? \"end of input\" },\n\t\t\t);\n\t\t}\n\t\tparser.consume();\n\n\t\temitBoundExpression(builder, left, variable.value);\n\t\tif (right) {\n\t\t\temitBoundExpression(builder, right, variable.value);\n\t\t} else {\n\t\t\t// No `=` written, so the equation is \"this expression equals zero\".\n\t\t\tbuilder.emitOpcode(OpCode.PUSH_NUMBER);\n\t\t\tbuilder.emitNumber(0);\n\t\t}\n\t\temitVariableName(builder, variable.value);\n\n\t\tparser.consume(\"RPAREN\");\n\n\t\tbuilder.emitOpcode(OpCode.CALL_BUILTIN);\n\t\tbuilder.emitIndex(SYMBOLIC_BUILTIN_SOLVE);\n\t\tbuilder.emitIndex(3);\n\t}\n}\n","import { PrefixParselet } from \"@solve-js/parser/Parselet\";\nimport { Parser } from \"@solve-js/parser/Parser\";\nimport { Token } from \"@solve-js/lexer/Token\";\nimport { BytecodeBuilder } from \"@solve-js/parser/BytecodeBuilder\";\nimport { OpCode } from \"@solve-js/parser/OpCode\";\nimport { BindingPower } from \"@solve-js/parser/BindingPower\";\nimport { SYMBOLIC_BUILTIN_DER } from \"@solve-js/packages/symbolic/SymbolicBuiltinIndex\";\nimport { readVariableName, emitVariableName, parseBoundExpression, emitBoundExpression } from \"@solve-js/packages/symbolic/parselets/VariableArgument\";\n\n/**\n * `der(expr, variable)` and `der(expr, variable, order)`, the symbolic\n * derivative. `derivative` is accepted as the same thing.\n *\n * The variable is emitted as a string rather than compiled as a variable read,\n * for the reason given in {@link readVariableName}, and `expr` is held until\n * that name is known so it can be evaluated with the name bound. See\n * {@link emitBoundExpression}.\n */\nexport class DerParselet implements PrefixParselet {\n\treadonly category = \"Symbolic\";\n\n\tparse(parser: Parser, _token: Token, builder: BytecodeBuilder): void {\n\t\tparser.consume(\"LPAREN\");\n\t\tconst expression = parseBoundExpression(parser, builder, \"der\");\n\t\tparser.consume(\"COMMA\");\n\t\tconst variable = readVariableName(parser, \"der\");\n\t\temitBoundExpression(builder, expression, variable);\n\t\temitVariableName(builder, variable);\n\n\t\t// The order is optional and defaults to a first derivative.\n\t\tif (parser.match(\"COMMA\")) {\n\t\t\tparser.parseExpression(BindingPower.Lowest, builder);\n\t\t} else {\n\t\t\tbuilder.emitOpcode(OpCode.PUSH_NUMBER);\n\t\t\tbuilder.emitNumber(1);\n\t\t}\n\t\tparser.consume(\"RPAREN\");\n\n\t\tbuilder.emitOpcode(OpCode.CALL_BUILTIN);\n\t\tbuilder.emitIndex(SYMBOLIC_BUILTIN_DER);\n\t\tbuilder.emitIndex(3);\n\t}\n}\n","import { PrefixParselet } from \"@solve-js/parser/Parselet\";\nimport { Parser } from \"@solve-js/parser/Parser\";\nimport { Token } from \"@solve-js/lexer/Token\";\nimport { BytecodeBuilder } from \"@solve-js/parser/BytecodeBuilder\";\nimport { OpCode } from \"@solve-js/parser/OpCode\";\nimport { SYMBOLIC_BUILTIN_INTEGRAL } from \"@solve-js/packages/symbolic/SymbolicBuiltinIndex\";\nimport { readVariableName, emitVariableName, parseBoundExpression, emitBoundExpression } from \"@solve-js/packages/symbolic/parselets/VariableArgument\";\n\n/**\n * `integral(expr, variable)`, the indefinite integral, without a constant of\n * integration. `expr` is held until the variable is read so that the named\n * unknown shadows any document value of the same name, see\n * {@link emitBoundExpression}.\n */\nexport class IntegralParselet implements PrefixParselet {\n\treadonly category = \"Symbolic\";\n\n\tparse(parser: Parser, _token: Token, builder: BytecodeBuilder): void {\n\t\tparser.consume(\"LPAREN\");\n\t\tconst expression = parseBoundExpression(parser, builder, \"integral\");\n\t\tparser.consume(\"COMMA\");\n\t\tconst variable = readVariableName(parser, \"integral\");\n\t\temitBoundExpression(builder, expression, variable);\n\t\temitVariableName(builder, variable);\n\t\tparser.consume(\"RPAREN\");\n\n\t\tbuilder.emitOpcode(OpCode.CALL_BUILTIN);\n\t\tbuilder.emitIndex(SYMBOLIC_BUILTIN_INTEGRAL);\n\t\tbuilder.emitIndex(2);\n\t}\n}\n","import { PrefixParselet } from \"@solve-js/parser/Parselet\";\nimport { Parser } from \"@solve-js/parser/Parser\";\nimport { Token } from \"@solve-js/lexer/Token\";\nimport { BytecodeBuilder } from \"@solve-js/parser/BytecodeBuilder\";\nimport { OpCode } from \"@solve-js/parser/OpCode\";\nimport { BindingPower } from \"@solve-js/parser/BindingPower\";\nimport { SYMBOLIC_BUILTIN_TAYLOR } from \"@solve-js/packages/symbolic/SymbolicBuiltinIndex\";\nimport { readVariableName, emitVariableName, parseBoundExpression, emitBoundExpression } from \"@solve-js/packages/symbolic/parselets/VariableArgument\";\n\n/**\n * `taylor(expr, variable = point, degree)`, matching Calca's own spelling.\n *\n * The `variable = point` argument is why this needs a hand-written parselet:\n * `EQUALS` has no infix parselet, so an ordinary argument list cannot parse it.\n * Reading the name and the point separately also means the name never has to\n * exist as a variable, and `expr` is held until the name is known so that the\n * name shadows any document value it shares (see {@link emitBoundExpression}).\n * The expansion point is an ordinary value expression and is not shadowed: it\n * is a number, not the unknown.\n */\nexport class TaylorParselet implements PrefixParselet {\n\treadonly category = \"Symbolic\";\n\n\tparse(parser: Parser, _token: Token, builder: BytecodeBuilder): void {\n\t\tparser.consume(\"LPAREN\");\n\t\tconst expression = parseBoundExpression(parser, builder, \"taylor\");\n\t\tparser.consume(\"COMMA\");\n\t\tconst variable = readVariableName(parser, \"taylor\");\n\t\temitBoundExpression(builder, expression, variable);\n\t\temitVariableName(builder, variable);\n\t\tparser.consume(\"EQUALS\");\n\t\tparser.parseExpression(BindingPower.Lowest, builder);\n\t\tparser.consume(\"COMMA\");\n\t\tparser.parseExpression(BindingPower.Lowest, builder);\n\t\tparser.consume(\"RPAREN\");\n\n\t\tbuilder.emitOpcode(OpCode.CALL_BUILTIN);\n\t\tbuilder.emitIndex(SYMBOLIC_BUILTIN_TAYLOR);\n\t\tbuilder.emitIndex(4);\n\t}\n}\n","import { PrefixParselet } from \"@solve-js/parser/Parselet\";\nimport { Parser } from \"@solve-js/parser/Parser\";\nimport { Token } from \"@solve-js/lexer/Token\";\nimport { BytecodeBuilder } from \"@solve-js/parser/BytecodeBuilder\";\nimport { OpCode } from \"@solve-js/parser/OpCode\";\nimport { BindingPower } from \"@solve-js/parser/BindingPower\";\nimport { SYMBOLIC_BUILTIN_JACOBIAN } from \"@solve-js/packages/symbolic/SymbolicBuiltinIndex\";\n\n/**\n * `jacobian(f1, f2, ...)`, the matrix of partial derivatives.\n *\n * Variadic, and the variables are not named: they are taken from the union of\n * the functions' own unknowns, sorted, which is what Calca does. Row `i` is the\n * gradient of the `i`-th function.\n */\nexport class JacobianParselet implements PrefixParselet {\n\treadonly category = \"Symbolic\";\n\n\tparse(parser: Parser, _token: Token, builder: BytecodeBuilder): void {\n\t\tparser.consume(\"LPAREN\");\n\t\tlet count = 0;\n\t\tdo {\n\t\t\tparser.parseExpression(BindingPower.Lowest, builder);\n\t\t\tcount++;\n\t\t} while (parser.match(\"COMMA\"));\n\t\tparser.consume(\"RPAREN\");\n\n\t\tbuilder.emitOpcode(OpCode.CALL_BUILTIN);\n\t\tbuilder.emitIndex(SYMBOLIC_BUILTIN_JACOBIAN);\n\t\tbuilder.emitIndex(count);\n\t}\n}\n","import { PrefixParselet } from \"@solve-js/parser/Parselet\";\nimport { Parser } from \"@solve-js/parser/Parser\";\nimport { Token } from \"@solve-js/lexer/Token\";\nimport { BytecodeBuilder } from \"@solve-js/parser/BytecodeBuilder\";\nimport { OpCode } from \"@solve-js/parser/OpCode\";\nimport { SYMBOLIC_BUILTIN_IMAGINARY } from \"@solve-js/packages/symbolic/SymbolicBuiltinIndex\";\n\n/**\n * An imaginary literal, `3i`, fused by\n * `normalizer/ImaginaryLiteralNormalizerRule.ts`.\n *\n * The token carries the numeric part as its value; this pushes that number and\n * lets the builtin turn it into an exact imaginary value. Going through a\n * builtin rather than a dedicated opcode keeps the VM dispatch table untouched,\n * the same choice every other algebra verb made.\n */\nexport class ImaginaryParselet implements PrefixParselet {\n\treadonly category = \"Symbolic\";\n\n\tparse(_parser: Parser, token: Token, builder: BytecodeBuilder): void {\n\t\tbuilder.emitOpcode(OpCode.PUSH_NUMBER);\n\t\tbuilder.emitNumber(Number(token.value));\n\t\tbuilder.emitOpcode(OpCode.CALL_BUILTIN);\n\t\tbuilder.emitIndex(SYMBOLIC_BUILTIN_IMAGINARY);\n\t\tbuilder.emitIndex(1);\n\t}\n}\n","import { PrefixParselet } from \"@solve-js/parser/Parselet\";\nimport { Parser } from \"@solve-js/parser/Parser\";\nimport { Token } from \"@solve-js/lexer/Token\";\nimport { BytecodeBuilder } from \"@solve-js/parser/BytecodeBuilder\";\nimport { OpCode } from \"@solve-js/parser/OpCode\";\nimport { BindingPower } from \"@solve-js/parser/BindingPower\";\nimport { SYMBOLIC_BUILTIN_CONJ } from \"@solve-js/packages/symbolic/SymbolicBuiltinIndex\";\n\n/**\n * `conj(z)`, the complex conjugate.\n *\n * A dedicated parselet rather than a keywordMap entry, for the reason given in\n * `normalizer/SymbolicCallNormalizerRule.ts`: `re` and `im` are short words a\n * person may well use as variable names.\n */\nexport class ConjParselet implements PrefixParselet {\n\treadonly category = \"Symbolic\";\n\n\tparse(parser: Parser, _token: Token, builder: BytecodeBuilder): void {\n\t\tparser.consume(\"LPAREN\");\n\t\tparser.parseExpression(BindingPower.Lowest, builder);\n\t\tparser.consume(\"RPAREN\");\n\n\t\tbuilder.emitOpcode(OpCode.CALL_BUILTIN);\n\t\tbuilder.emitIndex(SYMBOLIC_BUILTIN_CONJ);\n\t\tbuilder.emitIndex(1);\n\t}\n}\n","import { PrefixParselet } from \"@solve-js/parser/Parselet\";\nimport { Parser } from \"@solve-js/parser/Parser\";\nimport { Token } from \"@solve-js/lexer/Token\";\nimport { BytecodeBuilder } from \"@solve-js/parser/BytecodeBuilder\";\nimport { OpCode } from \"@solve-js/parser/OpCode\";\nimport { BindingPower } from \"@solve-js/parser/BindingPower\";\nimport { SYMBOLIC_BUILTIN_RE } from \"@solve-js/packages/symbolic/SymbolicBuiltinIndex\";\n\n/**\n * `re(z)`, the real part of a complex value.\n *\n * A dedicated parselet rather than a keywordMap entry, for the reason given in\n * `normalizer/SymbolicCallNormalizerRule.ts`: `re` and `im` are short words a\n * person may well use as variable names.\n */\nexport class ReParselet implements PrefixParselet {\n\treadonly category = \"Symbolic\";\n\n\tparse(parser: Parser, _token: Token, builder: BytecodeBuilder): void {\n\t\tparser.consume(\"LPAREN\");\n\t\tparser.parseExpression(BindingPower.Lowest, builder);\n\t\tparser.consume(\"RPAREN\");\n\n\t\tbuilder.emitOpcode(OpCode.CALL_BUILTIN);\n\t\tbuilder.emitIndex(SYMBOLIC_BUILTIN_RE);\n\t\tbuilder.emitIndex(1);\n\t}\n}\n","import { PrefixParselet } from \"@solve-js/parser/Parselet\";\nimport { Parser } from \"@solve-js/parser/Parser\";\nimport { Token } from \"@solve-js/lexer/Token\";\nimport { BytecodeBuilder } from \"@solve-js/parser/BytecodeBuilder\";\nimport { OpCode } from \"@solve-js/parser/OpCode\";\nimport { BindingPower } from \"@solve-js/parser/BindingPower\";\nimport { SYMBOLIC_BUILTIN_IM } from \"@solve-js/packages/symbolic/SymbolicBuiltinIndex\";\n\n/**\n * `im(z)`, the imaginary part of a complex value.\n *\n * A dedicated parselet rather than a keywordMap entry, for the reason given in\n * `normalizer/SymbolicCallNormalizerRule.ts`: `re` and `im` are short words a\n * person may well use as variable names.\n */\nexport class ImParselet implements PrefixParselet {\n\treadonly category = \"Symbolic\";\n\n\tparse(parser: Parser, _token: Token, builder: BytecodeBuilder): void {\n\t\tparser.consume(\"LPAREN\");\n\t\tparser.parseExpression(BindingPower.Lowest, builder);\n\t\tparser.consume(\"RPAREN\");\n\n\t\tbuilder.emitOpcode(OpCode.CALL_BUILTIN);\n\t\tbuilder.emitIndex(SYMBOLIC_BUILTIN_IM);\n\t\tbuilder.emitIndex(1);\n\t}\n}\n","import { PrefixParselet } from \"@solve-js/parser/Parselet\";\nimport { Parser } from \"@solve-js/parser/Parser\";\nimport { Token } from \"@solve-js/lexer/Token\";\nimport { BytecodeBuilder } from \"@solve-js/parser/BytecodeBuilder\";\nimport { OpCode } from \"@solve-js/parser/OpCode\";\nimport { BindingPower } from \"@solve-js/parser/BindingPower\";\nimport { SYMBOLIC_BUILTIN_CANCEL } from \"@solve-js/packages/symbolic/SymbolicBuiltinIndex\";\n\n/**\n * `cancel(expr)`, reducing a quotient of polynomials to lowest terms.\n *\n * The simplifier already cancels a common factor automatically; this is the\n * explicit form, for when the intent is to reduce a fraction rather than to\n * evaluate something that happens to contain one.\n */\nexport class CancelParselet implements PrefixParselet {\n\treadonly category = \"Symbolic\";\n\n\tparse(parser: Parser, _token: Token, builder: BytecodeBuilder): void {\n\t\tparser.consume(\"LPAREN\");\n\t\tparser.parseExpression(BindingPower.Lowest, builder);\n\t\tparser.consume(\"RPAREN\");\n\n\t\tbuilder.emitOpcode(OpCode.CALL_BUILTIN);\n\t\tbuilder.emitIndex(SYMBOLIC_BUILTIN_CANCEL);\n\t\tbuilder.emitIndex(1);\n\t}\n}\n","import { PrefixParselet } from \"@solve-js/parser/Parselet\";\nimport { Parser } from \"@solve-js/parser/Parser\";\nimport { Token } from \"@solve-js/lexer/Token\";\nimport { BytecodeBuilder } from \"@solve-js/parser/BytecodeBuilder\";\nimport { OpCode } from \"@solve-js/parser/OpCode\";\nimport { BindingPower } from \"@solve-js/parser/BindingPower\";\nimport { SYMBOLIC_BUILTIN_APART } from \"@solve-js/packages/symbolic/SymbolicBuiltinIndex\";\n\n/**\n * `apart(expr)`, splitting a rational function into partial fractions.\n *\n * The inverse of putting a sum of fractions over a common denominator, and the\n * step that makes a rational function integrable.\n */\nexport class ApartParselet implements PrefixParselet {\n\treadonly category = \"Symbolic\";\n\n\tparse(parser: Parser, _token: Token, builder: BytecodeBuilder): void {\n\t\tparser.consume(\"LPAREN\");\n\t\tparser.parseExpression(BindingPower.Lowest, builder);\n\t\tparser.consume(\"RPAREN\");\n\n\t\tbuilder.emitOpcode(OpCode.CALL_BUILTIN);\n\t\tbuilder.emitIndex(SYMBOLIC_BUILTIN_APART);\n\t\tbuilder.emitIndex(1);\n\t}\n}\n","import type { Token } from \"@solve-js/lexer/Token\";\nimport { tokenTypeId } from \"@solve-js/lexer/Token\";\nimport { LexerToken } from \"@solve-js/lexer/ExpressionLexer\";\nimport type { NormalizerRule, NormalizerMatch } from \"@solve-js/normalizer/NormalizerRule\";\n\n/**\n * Fuses `3i` into a single imaginary literal, but only when the `i` is written\n * flush against the number.\n *\n * `i` is not claimed as a keyword, and deliberately so. It is one of the most\n * common variable names there is, and this engine's whole trigger-word policy\n * exists to avoid taking words a person would reasonably assign to. `:i = 5`\n * has to keep working, and after this rule it does: the rule only fires on a\n * number immediately followed by the letter, which is the same shape the\n * magnitude suffixes use, and `2.5k` set that precedent.\n *\n * Adjacency is checked by source offset rather than by token order, so `3i` is\n * an imaginary literal while `3 i` and `3 * i` are a number multiplied by a\n * variable named `i`. That is the distinction that keeps both readings\n * available, and it is the reason a bare `i` on its own is still a variable.\n * Write `1i` for the imaginary unit alone.\n */\nexport function imaginaryLiteralNormalizerRule(priority = 75): NormalizerRule {\n\treturn {\n\t\tname: \"symbolic:imaginary-literal\",\n\t\tpriority,\n\t\t// Derived from this rule's own opening guards; see RuleSlot on why an\n\t\t// over-broad slot is safe and an over-narrow one is not.\n\t\tshape: [{ types: [\"NUMBER\"] }, { types: [\"IDENT\"], values: [\"i\"] }],\n\t\tmatch(tokens: Token[], pos: number): NormalizerMatch | null {\n\t\t\tconst number = tokens[pos];\n\t\t\tif (!number || number.type !== \"NUMBER\") return null;\n\n\t\t\tconst suffix = tokens[pos + 1];\n\t\t\tif (!suffix || suffix.type !== \"IDENT\" || suffix.value !== \"i\") return null;\n\n\t\t\t// Flush against the number, with no space between them.\n\t\t\tif (suffix.offset !== number.offset + number.value.length) return null;\n\n\t\t\t// A following `(` would make this a call, as in `3i(x)`, which is not a\n\t\t\t// shape this claims.\n\t\t\tif (tokens[pos + 2]?.type === \"LPAREN\") return null;\n\n\t\t\treturn {\n\t\t\t\tconsumed: 2,\n\t\t\t\treplacement: [\n\t\t\t\t\tnew LexerToken(\n\t\t\t\t\t\t\"IMAGINARY\",\n\t\t\t\t\t\ttokenTypeId(\"IMAGINARY\"),\n\t\t\t\t\t\tnumber.value,\n\t\t\t\t\t\tnumber.value,\n\t\t\t\t\t\tnumber.offset,\n\t\t\t\t\t\t0,\n\t\t\t\t\t\tnumber.line,\n\t\t\t\t\t\tnumber.col,\n\t\t\t\t\t),\n\t\t\t\t],\n\t\t\t\truleName: \"symbolic:imaginary-literal\",\n\t\t\t};\n\t\t},\n\t};\n}\n","import type { Token } from \"@solve-js/lexer/Token\";\nimport { tokenTypeId } from \"@solve-js/lexer/Token\";\nimport { LexerToken } from \"@solve-js/lexer/ExpressionLexer\";\nimport type { NormalizerRule, NormalizerMatch } from \"@solve-js/normalizer/NormalizerRule\";\n\n/**\n * The algebra verbs, mapped to the token type each becomes when it is being\n * called.\n *\n * Kept in one place so {@link SYMBOLIC_FUNCTIONS} in `SymbolicPackage.ts` and\n * this rule cannot disagree about which words the package claims.\n */\nexport const SYMBOLIC_WORD_TO_TOKEN_TYPE: Readonly<Record<string, string>> = {\n\texpand: \"EXPAND_FN\",\n\tfactor: \"FACTOR_FN\",\n\tsolve: \"SOLVE_FN\",\n\tder: \"DER_FN\",\n\tderivative: \"DER_FN\",\n\tintegral: \"INTEGRAL_FN\",\n\ttaylor: \"TAYLOR_FN\",\n\tjacobian: \"JACOBIAN_FN\",\n\tconj: \"CONJ_FN\",\n\tre: \"RE_FN\",\n\tim: \"IM_FN\",\n\tcancel: \"CANCEL_FN\",\n\tapart: \"APART_FN\",\n};\n\n/**\n * Fuses an algebra verb into its own token type, but only when the bare word is\n * immediately followed by `(`.\n *\n * None of these words may be a plain `keywordMap` entry, and the reason is\n * concrete rather than stylistic. A `keywordMap` entry makes the lexer emit a\n * reserved token type everywhere the word appears, which would break\n * `:factor = 1.5` and `:solve = 2` as ordinary variable names. `solve` is also\n * the product's own name and `factor` is an everyday English noun, so both are\n * words a user will reasonably assign to.\n *\n * Mirrors `packages/mapreduce/normalizer/MapReduceCallNormalizerRule.ts`, which\n * exists for exactly this reason for `map`/`reduce`/`sum`/`prod`.\n *\n * @param priority - Rule ordering within the normalizer, defaulting to the same\n * band the map/reduce call rule uses.\n * @returns The normalizer rule.\n */\nexport function symbolicCallNormalizerRule(priority = 80): NormalizerRule {\n\treturn {\n\t\tname: \"symbolic:call\",\n\t\tpriority,\n\t\t// Derived from this rule's own opening guards; see RuleSlot on why an\n\t\t// over-broad slot is safe and an over-narrow one is not.\n\t\tshape: [{ types: [\"IDENT\"], values: Object.keys(SYMBOLIC_WORD_TO_TOKEN_TYPE) }, { types: [\"LPAREN\"] }],\n\t\tmatch(tokens: Token[], pos: number): NormalizerMatch | null {\n\t\t\tconst token = tokens[pos];\n\t\t\tif (!token || token.type !== \"IDENT\") return null;\n\t\t\tconst tokenType = SYMBOLIC_WORD_TO_TOKEN_TYPE[token.value.toLowerCase()];\n\t\t\tif (!tokenType) return null;\n\t\t\tif (tokens[pos + 1]?.type !== \"LPAREN\") return null;\n\n\t\t\treturn {\n\t\t\t\tconsumed: 1,\n\t\t\t\treplacement: [\n\t\t\t\t\tnew LexerToken(tokenType, tokenTypeId(tokenType), token.value, token.value, token.offset, 0, token.line, token.col),\n\t\t\t\t],\n\t\t\t\truleName: \"symbolic:call\",\n\t\t\t};\n\t\t},\n\t};\n}\n","import type { IEnginePackage } from \"@solve-js/api/PackageRegistry\";\nimport { ExpandParselet } from \"./parselets/ExpandParselet\";\nimport { FactorParselet } from \"./parselets/FactorParselet\";\nimport { SolveParselet } from \"./parselets/SolveParselet\";\nimport { DerParselet } from \"./parselets/DerParselet\";\nimport { IntegralParselet } from \"./parselets/IntegralParselet\";\nimport { TaylorParselet } from \"./parselets/TaylorParselet\";\nimport { JacobianParselet } from \"./parselets/JacobianParselet\";\nimport { ImaginaryParselet } from \"./parselets/ImaginaryParselet\";\nimport { ConjParselet } from \"./parselets/ConjParselet\";\nimport { ReParselet } from \"./parselets/ReParselet\";\nimport { ImParselet } from \"./parselets/ImParselet\";\nimport { CancelParselet } from \"./parselets/CancelParselet\";\nimport { ApartParselet } from \"./parselets/ApartParselet\";\nimport { imaginaryLiteralNormalizerRule } from \"./normalizer/ImaginaryLiteralNormalizerRule\";\nimport { symbolicCallNormalizerRule } from \"./normalizer/SymbolicCallNormalizerRule\";\nimport {\n\tSYMBOLIC_BUILTIN_EXPAND,\n\tSYMBOLIC_BUILTIN_FACTOR,\n\tSYMBOLIC_BUILTIN_SOLVE,\n\tSYMBOLIC_BUILTIN_DER,\n\tSYMBOLIC_BUILTIN_INTEGRAL,\n\tSYMBOLIC_BUILTIN_TAYLOR,\n\tSYMBOLIC_BUILTIN_JACOBIAN,\n\tSYMBOLIC_BUILTIN_CONJ,\n\tSYMBOLIC_BUILTIN_RE,\n\tSYMBOLIC_BUILTIN_IM,\n\tSYMBOLIC_BUILTIN_CANCEL,\n\tSYMBOLIC_BUILTIN_APART,\n} from \"./SymbolicBuiltinIndex\";\n\n/**\n * One algebra verb's whole surface, in a single row.\n *\n * Everything a verb needs in order to work is listed here rather than being\n * spread across the normalizer, the parselet registry, the builtin table and\n * the docs, so `__tests__/engine/SymbolicSurfaceParity.spec.ts` can check the\n * pieces actually agree. Shipping a verb whose index has no implementation, or\n * whose parselet is registered under a token type the normalizer never mints,\n * then becomes a failing test rather than a silent dead feature.\n */\nexport interface SymbolicFunctionSurface {\n\t/** The bare word a user types. */\n\treadonly word: string;\n\t/** The token type the normalizer fuses it into when it is followed by `(`. */\n\treadonly tokenType: string;\n\t/** The `CALL_BUILTIN` index its parselet emits. */\n\treadonly builtinIndex: number;\n\t/** A working example, executed by the parity spec through every public entry point. */\n\treadonly example: string;\n\t/** That example's expected formatted result. */\n\treadonly expected: string;\n\t/** The documentation page under `docs/src/content/docs/syntax/` that must show it. */\n\treadonly docPage: string;\n}\n\n/** Every algebra verb this package registers. */\nexport const SYMBOLIC_FUNCTIONS: readonly SymbolicFunctionSurface[] = [\n\t{\n\t\tword: \"expand\",\n\t\ttokenType: \"EXPAND_FN\",\n\t\tbuiltinIndex: SYMBOLIC_BUILTIN_EXPAND,\n\t\texample: \"expand((x+1)*(x+2))\",\n\t\texpected: \"x^2+3x+2\",\n\t\tdocPage: \"expanding.md\",\n\t},\n\t{\n\t\tword: \"factor\",\n\t\ttokenType: \"FACTOR_FN\",\n\t\tbuiltinIndex: SYMBOLIC_BUILTIN_FACTOR,\n\t\texample: \"factor(x^2-4)\",\n\t\texpected: \"(x-2)*(x+2)\",\n\t\tdocPage: \"factoring.md\",\n\t},\n\t{\n\t\tword: \"solve\",\n\t\ttokenType: \"SOLVE_FN\",\n\t\tbuiltinIndex: SYMBOLIC_BUILTIN_SOLVE,\n\t\texample: \"solve(x^2-4=0, x)\",\n\t\texpected: \"= [-2, 2]\",\n\t\tdocPage: \"solving-equations.md\",\n\t},\n\t{\n\t\tword: \"der\",\n\t\ttokenType: \"DER_FN\",\n\t\tbuiltinIndex: SYMBOLIC_BUILTIN_DER,\n\t\texample: \"der(x^3, x)\",\n\t\texpected: \"3x^2\",\n\t\tdocPage: \"calculus.md\",\n\t},\n\t{\n\t\tword: \"integral\",\n\t\ttokenType: \"INTEGRAL_FN\",\n\t\tbuiltinIndex: SYMBOLIC_BUILTIN_INTEGRAL,\n\t\texample: \"integral(x^2, x)\",\n\t\texpected: \"1/3x^3\",\n\t\tdocPage: \"calculus.md\",\n\t},\n\t{\n\t\tword: \"taylor\",\n\t\ttokenType: \"TAYLOR_FN\",\n\t\tbuiltinIndex: SYMBOLIC_BUILTIN_TAYLOR,\n\t\texample: \"taylor(exp(x), x=0, 3)\",\n\t\texpected: \"1/6x^3+0.5x^2+x+1\",\n\t\tdocPage: \"calculus.md\",\n\t},\n\t{\n\t\tword: \"jacobian\",\n\t\ttokenType: \"JACOBIAN_FN\",\n\t\tbuiltinIndex: SYMBOLIC_BUILTIN_JACOBIAN,\n\t\texample: \"jacobian(x*y, x+y)\",\n\t\texpected: \"= [y, x; 1, 1]\",\n\t\tdocPage: \"calculus.md\",\n\t},\n\t{\n\t\tword: \"conj\",\n\t\ttokenType: \"CONJ_FN\",\n\t\tbuiltinIndex: SYMBOLIC_BUILTIN_CONJ,\n\t\texample: \"conj(2+3i)\",\n\t\texpected: \"2-3i\",\n\t\tdocPage: \"complex.md\",\n\t},\n\t{\n\t\tword: \"re\",\n\t\ttokenType: \"RE_FN\",\n\t\tbuiltinIndex: SYMBOLIC_BUILTIN_RE,\n\t\texample: \"re(2+3i)\",\n\t\texpected: \"= 2\",\n\t\tdocPage: \"complex.md\",\n\t},\n\t{\n\t\tword: \"im\",\n\t\ttokenType: \"IM_FN\",\n\t\tbuiltinIndex: SYMBOLIC_BUILTIN_IM,\n\t\texample: \"im(2+3i)\",\n\t\texpected: \"= 3\",\n\t\tdocPage: \"complex.md\",\n\t},\n\t{\n\t\tword: \"cancel\",\n\t\ttokenType: \"CANCEL_FN\",\n\t\tbuiltinIndex: SYMBOLIC_BUILTIN_CANCEL,\n\t\texample: \"cancel((x^2-1)/(x-1))\",\n\t\texpected: \"x+1\",\n\t\tdocPage: \"cancelling-fractions.md\",\n\t},\n\t{\n\t\tword: \"apart\",\n\t\ttokenType: \"APART_FN\",\n\t\tbuiltinIndex: SYMBOLIC_BUILTIN_APART,\n\t\texample: \"apart((3x+5)/(x^2-1))\",\n\t\texpected: \"4/(x-1)-1/(x+1)\",\n\t\tdocPage: \"splitting-fractions.md\",\n\t},\n];\n\n/**\n * Symbolic algebra verbs: multiplying out, and (in later phases) factoring,\n * solving and calculus.\n *\n * The algebra itself lives in `symbolic/`, which is pure mathematics over the\n * expression tree. This package is only the grammar surface: which words become\n * which tokens, and which parselet emits which builtin call.\n *\n * None of these words is a bare `keywordMap` entry. See\n * `normalizer/SymbolicCallNormalizerRule.ts` for why that matters.\n */\nexport const SYMBOLIC_PACKAGE: IEnginePackage = {\n\tname: \"solve-symbolic\",\n\tnormalizerRules: [symbolicCallNormalizerRule(), imaginaryLiteralNormalizerRule()],\n\tprefixParselets: {\n\t\tEXPAND_FN: new ExpandParselet(),\n\t\tFACTOR_FN: new FactorParselet(),\n\t\tSOLVE_FN: new SolveParselet(),\n\t\tDER_FN: new DerParselet(),\n\t\tINTEGRAL_FN: new IntegralParselet(),\n\t\tTAYLOR_FN: new TaylorParselet(),\n\t\tJACOBIAN_FN: new JacobianParselet(),\n\t\tIMAGINARY: new ImaginaryParselet(),\n\t\tCONJ_FN: new ConjParselet(),\n\t\tRE_FN: new ReParselet(),\n\t\tIM_FN: new ImParselet(),\n\t\tCANCEL_FN: new CancelParselet(),\n\t\tAPART_FN: new ApartParselet(),\n\t},\n\ttokenCategories: {\n\t\tEXPAND_FN: \"keyword\",\n\t\tFACTOR_FN: \"keyword\",\n\t\tSOLVE_FN: \"keyword\",\n\t\tDER_FN: \"keyword\",\n\t\tINTEGRAL_FN: \"keyword\",\n\t\tTAYLOR_FN: \"keyword\",\n\t\tJACOBIAN_FN: \"keyword\",\n\t\tIMAGINARY: \"number\",\n\t\tCONJ_FN: \"keyword\",\n\t\tRE_FN: \"keyword\",\n\t\tIM_FN: \"keyword\",\n\t\tCANCEL_FN: \"keyword\",\n\t\tAPART_FN: \"keyword\",\n\t},\n};\n\n/** The token types the algebra verbs fuse into, for the engine's own \"is this line symbolic\" check. */\nconst SYMBOLIC_TOKEN_TYPES: ReadonlySet<string> = new Set(SYMBOLIC_FUNCTIONS.map(fn => fn.tokenType));\n\n/**\n * Whether a normalized token list calls an algebra verb.\n *\n * `engine/ExpressionEngine.ts` uses this to evaluate such a line in\n * symbolic-tolerant mode without requiring a trailing `=>`, since asking to\n * expand or factor something is already a statement that its unknowns are meant\n * to stay unknown.\n *\n * @param tokens - The normalized tokens for one line.\n * @returns True when any token is an algebra verb.\n */\nexport function containsSymbolicCall(tokens: readonly { type: string }[]): boolean {\n\treturn tokens.some(token => SYMBOLIC_TOKEN_TYPES.has(token.type));\n}\n","/**\n * Pure `#tag` detection on a raw line, kept engine-free so it is unit-testable\n * in isolation, the same design {@link TableReader} draws.\n */\n\nimport { edgeKey } from \"@solve-js/vm/DependencyGraph\";\n\n/**\n * The key a category tag takes in the dependency graph.\n *\n * Lower-cased, because {@link lineCarriesTag} reads a tag case-insensitively:\n * `#Food` and `total of #food` are one group to a reader, so they have to be\n * one key here too, or the aggregate would not be hooked to its members.\n */\nconst tagEdgeKey = (tag: string): string => edgeKey(\"tag\", tag.toLowerCase());\n\n/** Escapes any regex-special character a tag name could carry. */\nexport function escapeTag(name: string): string {\n return name.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\n\n/**\n * The aggregate openers, immediately before the tag they read.\n *\n * `total of #food` names the group; it does not join it. Anchored at the end,\n * so it is asking what sits directly in front of this particular `#`.\n */\nconst AGGREGATE_OPENER = /(?:total|sum|average|count)\\s+of\\s+$/i;\n\n/**\n * How much text before a `#` is examined for an opener.\n *\n * The pattern is anchored at its end, so only the characters immediately in\n * front of the `#` can match it, and testing a fixed window is the same answer\n * as testing the whole line up to the point where the whitespace runs long.\n * The longest opener is `average of `, eleven characters, which leaves\n * fifty-three here for whitespace between the words.\n *\n * Testing the whole prefix instead is what made this quadratic: the pattern is\n * anchored at the end but not the start, so the engine scans from every\n * position, and a line whose every occurrence is a query pays that once per\n * occurrence. A 192 KB line of repeated `total of #a` took 2.1 seconds.\n *\n * Past the window an opener is not recognised, so its line is read as a member\n * rather than as a query, which is what it was before any of this existed.\n */\nconst OPENER_WINDOW = 64;\n\n/** Any `#tag`, for the scan that reads a line's whole membership rather than asking about one name. */\nconst ANY_TAG = /(?:^|[^0-9A-Za-z_])#([0-9A-Za-z_-]+)(?![0-9A-Za-z_-])/g;\n\n/**\n * A line's edges, with the groups its text joins and asks about folded in.\n *\n * A category tag is an edge like any other: a line carrying `#food` writes that\n * group and `total of #food` reads it, so registering them alongside the\n * variables is what lets an edit to a tagged line dirty only the aggregates over\n * that tag.\n *\n * Every place that registers a line calls this rather than adding tags itself.\n * There are five of them, across the engine and the evaluator, and a line\n * registered twice with different edge sets loses whichever went first: that is\n * exactly how tag edges were being written and then silently wiped within the\n * same pass.\n *\n * Returns the arrays it was given when the line carries no tags, which is most\n * lines, so the common path allocates nothing.\n */\nexport function withTagEdges(\n\trawText: string,\n\treads: readonly string[],\n\twrites: readonly string[],\n): { reads: string[]; writes: string[] } {\n\tconst tags = tagEdgesOf(rawText);\n\tif (tags.members.length === 0 && tags.queries.length === 0) {\n\t\treturn { reads: reads as string[], writes: writes as string[] };\n\t}\n\treturn {\n\t\treads: tags.queries.length === 0 ? (reads as string[]) : [...reads, ...tags.queries.map(tagEdgeKey)],\n\t\twrites: tags.members.length === 0 ? (writes as string[]) : [...writes, ...tags.members.map(tagEdgeKey)],\n\t};\n}\n\n/**\n * The groups a line joins, lower-cased, in the form an index keys on.\n *\n * The membership half of {@link tagEdgesOf}, case-folded the way\n * {@link lineCarriesTag} reads a name, so a lookup by tag and a scan of the\n * line answer the same question.\n */\nexport function memberTagsOf(rawText: string): string[] {\n\tconst members = tagEdgesOf(rawText).members;\n\tfor (let i = 0; i < members.length; i++) members[i] = members[i].toLowerCase();\n\treturn members;\n}\n\n/**\n * Every group a line joins, and every group it asks about.\n *\n * The same reading {@link lineCarriesTag} gives, in the shape an index wants:\n * one pass over the line naming both sides, rather than one pass per candidate\n * tag asking a yes-or-no question. They must not drift, so the rules live here\n * once and that function is the single-tag view of this one.\n *\n * A tag can appear on both sides of the same line, which is why these are two\n * lists rather than a partition of one: `total of #food #food` asks about the\n * group and joins it.\n */\nexport function tagEdgesOf(rawText: string): { members: string[]; queries: string[] } {\n\tconst members: string[] = [];\n\tconst queries: string[] = [];\n\t// Whether anything precedes a `#` is one property of the line.\n\tconst firstContent = rawText.search(/\\S/);\n\tANY_TAG.lastIndex = 0;\n\tfor (let m = ANY_TAG.exec(rawText); m !== null; m = ANY_TAG.exec(rawText)) {\n\t\tconst hashIndex = m.index + m[0].indexOf(\"#\");\n\t\t// The line's first non-whitespace token: a heading, not a tagged line.\n\t\tif (firstContent === hashIndex) continue;\n\t\tconst name = m[1];\n\t\tif (AGGREGATE_OPENER.test(rawText.slice(Math.max(0, hashIndex - OPENER_WINDOW), hashIndex))) {\n\t\t\tqueries.push(name);\n\t\t\tcontinue;\n\t\t}\n\t\tmembers.push(name);\n\t}\n\treturn { members, queries };\n}\n\n/**\n * Whether `rawText` carries `#tag` as a mid-line annotation, case-insensitively.\n *\n * The tag must not be part of a longer word before (`a#tag`) or after\n * (`#housingcost` is not `#housing`), and must not be the line's first\n * non-whitespace token, since a line starting with `#` is a heading, not a\n * tagged data line.\n *\n * Nor may it be the object of an aggregate. A `#tag` after `total of` names the\n * group rather than joining it, and reading it as membership is what made two\n * aggregates over one tag unreadable: each walked the other, found a line still\n * being evaluated, and reported it. The querying line's own text was already\n * skipped by line number, so this only extends that to the other queries, and\n * says the same thing about all of them.\n *\n * Every occurrence is examined rather than only the first, since one line can\n * hold both: `total of #food #reviewed` asks about one group and joins another.\n */\nexport function lineCarriesTag(rawText: string, tag: string): boolean {\n if (tag === \"\") return false;\n const re = new RegExp(`(?:^|[^0-9A-Za-z_])#${escapeTag(tag)}(?![0-9A-Za-z_-])`, \"gi\");\n // Whether anything precedes a `#` is one property of the line, so it is found\n // once here rather than by copying the prefix at every occurrence.\n const firstContent = rawText.search(/\\S/);\n for (let m = re.exec(rawText); m !== null; m = re.exec(rawText)) {\n // The `#` sits inside the match.\n const hashIndex = m.index + m[0].indexOf(\"#\");\n // The line's first non-whitespace token: a heading, not a tagged data line.\n if (firstContent === hashIndex) continue;\n if (AGGREGATE_OPENER.test(rawText.slice(Math.max(0, hashIndex - OPENER_WINDOW), hashIndex))) continue;\n return true;\n }\n return false;\n}\n","/**\n * ISO8601 string <-> epoch-ms helpers backing the datetime package's\n * `<ISO8601 string> to date` and `<date/time> as iso8601` features.\n *\n * SCOPE, revised in 1.0.0: {@link parseIso8601} is now reached by BOTH input\n * shapes. A quoted string literal (`\"2019-04-01T15:30:00+11:00\" to date`)\n * always came here; the bare, unquoted form now does too, fused into one\n * DATETIME_LITERAL by `normalizer/DateLiteralNormalizerRule.ts` before the\n * parser sees it.\n *\n * This file used to record that the bare form was out of scope because it is\n * ambiguous with arithmetic (`2019 - 04 - 01` reads as two subtractions) and\n * would need a dedicated lexer change. The date half of that ambiguity was\n * already settled by the normalizer rule, and the differential run against\n * 1.0.0-beta.6 showed what leaving the other half cost: a bare\n * `2019-04-01T15:30:00+11:00` read its `+11:00` as a clock time being ADDED to\n * the date, and answered TODAY at 11:00. Not the instant, not an error, and\n * formatted as a date, which is the most convincing way to be wrong. The two\n * spellings now answer identically, which is the only defensible arrangement\n * when one of them was always right.\n */\n\nimport type { CalendarBackend } from \"@solve-js/calendar/CalendarBackend\";\nimport { encodeFixedOffset } from \"@solve-js/calendar/IntlZone\";\nimport type { DatetimeGrain } from \"@solve-js/vm/Value\";\n\n/**\n * Matches a (reasonably) well-formed ISO8601 date or date-time string:\n * `YYYY-MM-DD` optionally followed by `THH:MM[:SS[.fff]][Z|+HH:MM|-HH:MM]`.\n * Deliberately stricter than the native `Date` constructor's very lenient\n * parsing (which also accepts things like `\"April 1, 2019\"`), only a\n * string actually ISO8601-shaped is accepted here, so `\"not a date\" to\n * date` fails loudly instead of silently parsing as `Invalid Date` (or,\n * worse, something the native parser guesses at).\n */\nconst ISO8601_PATTERN =\n /^\\d{4}-\\d{2}-\\d{2}(T\\d{2}:\\d{2}(:\\d{2}(\\.\\d+)?)?(Z|[+-]\\d{2}:?\\d{2})?)?$/;\n\n/**\n * Parse an ISO8601-shaped string into epoch milliseconds.\n *\n * Delegates the actual parsing to the calendar backend, whose `Date`\n * implementation is the native constructor: it fully implements the ISO8601\n * extended format (including \"Z\"/\"+HH:MM\" offsets and a fractional-seconds\n * component) per the ECMA-262 Date Time String Format spec, so no custom\n * parsing logic is needed, just a stricter shape gate in front of it (see\n * {@link ISO8601_PATTERN}'s doc comment).\n *\n * A date-only string (`\"2019-04-01\"`) parses as UTC midnight; a date-time\n * with no offset and no \"Z\" (`\"2019-04-01T15:30:00\"`) parses in the HOST\n * SYSTEM's local timezone, both are the native `Date` constructor's own\n * spec-mandated behavior, which every backend reproduces, not something this\n * function adds.\n *\n * @param s - The text to parse, with or without surrounding double quotes.\n * @param calendar - The backend that parses the shape-checked string.\n * @returns epoch ms, or `null` if `s` isn't ISO8601-shaped or doesn't\n * parse to a valid instant.\n */\nexport function parseIso8601(s: string, calendar: CalendarBackend): number | null {\n // A `ValueType.String` Value's `.value` used to retain its original\n // surrounding double-quotes, because `tokenizeString()` set the token's\n // value to the raw source slice and `OpCode.PUSH_STRING` pushed that\n // verbatim. It no longer does: the token's `value` is the payload and its\n // `text` is the quoted slice. The strip below stays because this function\n // is also reachable with text that came from somewhere other than a\n // literal, and stripping a pair that is not there is a no-op.\n let trimmed = s.trim();\n if (trimmed.length >= 2 && trimmed.startsWith('\"') && trimmed.endsWith('\"')) {\n trimmed = trimmed.slice(1, -1);\n }\n if (!ISO8601_PATTERN.test(trimmed)) return null;\n const ms = calendar.parseIso8601(trimmed);\n return Number.isNaN(ms) ? null : ms;\n}\n\n/**\n * The same shape as {@link ISO8601_PATTERN}, with the two parts that decide\n * the grain captured: the time of day, and the `Z` or `±HH:MM` after it.\n *\n * Kept beside the pattern it mirrors so the two cannot drift. The offset group\n * is only reachable after a time group has matched, which is what stops\n * `12-25-2023` being read as a date with a `-20:23` offset.\n */\nconst ISO8601_GRAIN_PATTERN =\n /^\\d{4}-\\d{2}-\\d{2}(T\\d{2}:\\d{2}(?::\\d{2}(?:\\.\\d+)?)?(Z|[+-]\\d{2}:?\\d{2})?)?$/;\n\n/**\n * What an ISO 8601 literal's text says its instant anchors, and the zone it\n * named, if any.\n *\n * The three answers are the three spellings, decided from the text rather than\n * from the instant, because the instant cannot tell them apart: under `TZ=UTC`\n * the nine o'clock in `2026-04-03T09:00:00+09:00` IS midnight, so a reading\n * that tested the time fields would call it a calendar day and lose the hour\n * the reader typed.\n *\n * - No time of day, or text this pattern does not match at all (`03/04/2026`,\n * `3 April 2026`, `25.12.2023`): a calendar day.\n * - A time of day and nothing after it: a wall-clock reading, in whatever zone\n * the calendar backend reads as local.\n * - A time of day and a `Z` or an offset: a fixed instant, carrying that offset\n * as its zone. An offset is recorded as an offset (`\"UTCOFFSET:540\"`) and\n * never widened to a zone: `+09:00` says nothing about Tokyo's\n * daylight-saving rules and must not be made to.\n *\n * @param text - The literal as it was written.\n * @returns The grain, and the zone reference when the literal named one.\n */\nexport function iso8601Grain(text: string): { grain: DatetimeGrain; zone?: string } {\n const matched = ISO8601_GRAIN_PATTERN.exec(text.trim());\n if (matched === null || matched[1] === undefined) return { grain: \"date\" };\n const offset = matched[2];\n if (offset === undefined) return { grain: \"datetime\" };\n if (offset === \"Z\") return { grain: \"instant\", zone: encodeFixedOffset(0) };\n const sign = offset[0] === \"-\" ? -1 : 1;\n const digits = offset.slice(1).replace(\":\", \"\");\n const minutes = Number(digits.slice(0, 2)) * 60 + Number(digits.slice(2));\n return { grain: \"instant\", zone: encodeFixedOffset(sign * minutes) };\n}\n\n/**\n * Format epoch milliseconds as an ISO8601 string with an explicit\n * `+HH:MM`/`-HH:MM` offset, e.g. `\"2019-04-01T15:30:00+11:00\"`.\n *\n * DESIGN NOTE: uses the HOST SYSTEM's local timezone offset for the\n * offset component. This engine's `Datetime` representation is a bare\n * epoch-ms number with no zone tag (see `packages/time/TimePackage.ts`'s\n * doc comment for the same limitation affecting timezone conversion), so\n * there is no per-expression timezone context to draw on otherwise, the\n * backend's own local offset (`CalendarBackend.utcOffsetMinutes`, the\n * process's for the `Date` backend) is the only notion of \"local\" available.\n * No milliseconds component is emitted, matching the precision of the\n * task's own worked example.\n *\n * @param epochMs - The instant to format.\n * @param calendar - The backend whose local fields and offset are written out.\n * @returns The ISO 8601 string with an explicit offset.\n */\nexport function formatIso8601Local(epochMs: number, calendar: CalendarBackend): string {\n const d = calendar.fields(epochMs);\n const pad = (n: number) => String(n).padStart(2, \"0\");\n\n const year = d.year;\n const month = pad(d.month0 + 1);\n const day = pad(d.day);\n const hours = pad(d.hour);\n const minutes = pad(d.minute);\n const seconds = pad(d.second);\n\n // Positive when ahead of UTC, the \"+HH:MM\" reading the display wants.\n const offsetMinutesTotal = calendar.utcOffsetMinutes(epochMs);\n const sign = offsetMinutesTotal >= 0 ? \"+\" : \"-\";\n const absOffset = Math.abs(offsetMinutesTotal);\n const offsetHours = pad(Math.floor(absOffset / 60));\n const offsetMinutes = pad(absOffset % 60);\n\n return `${year}-${month}-${day}T${hours}:${minutes}:${seconds}${sign}${offsetHours}:${offsetMinutes}`;\n}\n\n/**\n * Magnitude threshold distinguishing a millisecond Unix timestamp from a\n * second Unix timestamp: values at or above this are treated as\n * milliseconds, below it as seconds.\n *\n * Chosen so that \"now\" in EITHER unit sits comfortably on its own side:\n * seconds-since-epoch for the foreseeable future stays in the ~1.7-2.5\n * billion range (1e9-1e10-ish), nowhere near 1e12, while the SAME\n * instant in milliseconds is ~1000x larger, comfortably past 1e12\n * (e.g. \"2024-12-10\" is ~1.73e9 seconds or ~1.73e12 ms). 1e12 sits well\n * clear of both real-world ranges for at least the next few centuries of\n * second-timestamps, so this is a safe, simple magnitude gate rather than\n * a fragile exact boundary.\n */\nconst MS_TIMESTAMP_THRESHOLD = 1e12;\n\n/**\n * Interpret a bare numeric Unix timestamp as epoch milliseconds, applying\n * the magnitude-based seconds-vs-milliseconds disambiguation described by\n * {@link MS_TIMESTAMP_THRESHOLD}.\n */\nexport function unixTimestampToEpochMs(n: number): number {\n return Math.abs(n) >= MS_TIMESTAMP_THRESHOLD ? n : n * 1000;\n}\n","/**\n * What the host's own locale says about the order the three groups of a\n * numeric date are written in.\n *\n * A reader who types `03/04/2026` means one of two days, and which one is a\n * question about where they are rather than about the characters. The engine\n * has never had an answer to that question, so `date.inputOrder` made the host\n * state it. This module is how a host can instead ask the machine, and it asks\n * exactly one thing: the day/month/year field order. Never the calendar\n * system, never the numbering system, never the display language, all of which\n * the engine decides for itself elsewhere.\n *\n * Asked of `Intl` rather than answered from a table of locales. A table goes\n * stale, and worse, it disagrees with the host's own date pickers on the same\n * machine: `Intl` is where the operating system's answer already lives, so it\n * is the only answer that can agree with everything else the reader sees.\n *\n * Pure `Intl`, importing nothing of the engine's. That is the constraint\n * `engine/EngineContext.ts` states for this directory: `calendar/` is imported\n * by `vm/`, which `engine/` imports, so anything here reaching back into\n * `engine/` closes a cycle. It sits beside `IntlZone.ts`, already the shared\n * \"ask Intl about zones\" module under the same rule.\n *\n * Nothing here is called unless a host asked for it. `date.inputOrder` still\n * defaults to `'auto'`, and only the value `'locale'` reaches this module, so\n * a default engine constructs no `Intl.DateTimeFormat` on this path at all.\n *\n * @module HostLocale\n */\n\n/**\n * The three field orders a Gregorian numeric date can be written in.\n *\n * Declared here rather than imported from `constants/Configuration.ts` because\n * this module may not import from the engine's layers (see the module note),\n * and because it is a narrower set than `DateInputOrder`: an inference can\n * only ever produce a concrete order, never `'auto'` and never `'locale'`.\n */\nexport type DateFieldOrder = \"DMY\" | \"MDY\" | \"YMD\";\n\n/**\n * The instant the order probe is taken on: 3 April 2026, formatted in UTC.\n *\n * A fixed instant rather than \"now\", so the probe cannot drift with the\n * machine clock or its zone, and a day and a month that are both unambiguous\n * as digits (3 and 4) so a formatter's output can be read back by field type\n * without the two being confusable.\n */\nconst PROBE_INSTANT = Date.UTC(2026, 3, 3);\n\n/**\n * The memo table, and the `Intl.DateTimeFormat` it was built against.\n *\n * The answer to both probes cannot change within one process, and the order\n * probe would otherwise run on every engine construction, so both are cached.\n * The cache is keyed on the constructor it was filled from: a test that swaps\n * `globalThis.Intl`, or a host that installs a polyfill after the first\n * engine, gets a fresh answer about the implementation it actually has rather\n * than a remembered one about a different implementation.\n */\nlet memoisedAgainst: unknown = undefined;\nlet trustworthy: boolean | undefined = undefined;\nconst orderByTag = new Map<string, DateFieldOrder | null>();\n\n/** The `Intl.DateTimeFormat` this runtime currently has, or undefined where there is none. */\nfunction currentIntl(): unknown {\n return typeof Intl === \"object\" && Intl !== null ? (Intl as { DateTimeFormat?: unknown }).DateTimeFormat : undefined;\n}\n\n/** Drops the memo table when the runtime's `Intl.DateTimeFormat` is not the one it was filled from. */\nfunction freshenMemo(): void {\n const current = currentIntl();\n if (current === memoisedAgainst) return;\n memoisedAgainst = current;\n trustworthy = undefined;\n orderByTag.clear();\n}\n\n/**\n * Whether this runtime's `Intl` carries the host's own locale data, rather\n * than one language's data answering for every locale.\n *\n * A small-ICU build resolves every requested locale to `en-US` whatever the\n * operating system says, and it does so silently: `new\n * Intl.DateTimeFormat('ja-JP')` returns a formatter that writes American\n * dates. The obvious guard, `Intl.DateTimeFormat.supportedLocalesOf([tag])`,\n * catches an unknown tag (it answers `[]` for `zz-ZZ`, while\n * `new Intl.DateTimeFormat('xx-YY').resolvedOptions().locale` cheerfully\n * answers this host's `en-GB`), but it cannot catch small ICU on the path that\n * matters: there the tag came from `resolvedOptions().locale` and is supported\n * by construction.\n *\n * So the probe asks for a locale that is certainly not English and checks what\n * comes back. A runtime that substitutes `en-US` for `ja-JP` has data that is\n * not the host's, and the caller falls back to today's behaviour rather than\n * to a fabricated month-first reading.\n *\n * @returns `true` when a Japanese request is answered in Japanese.\n */\nexport function isTrustworthyIntl(): boolean {\n freshenMemo();\n if (trustworthy !== undefined) return trustworthy;\n try {\n const probe = new Intl.DateTimeFormat(\"ja-JP\").resolvedOptions().locale;\n trustworthy = typeof probe === \"string\" && probe.startsWith(\"ja\");\n } catch {\n trustworthy = false;\n }\n return trustworthy;\n}\n\n/**\n * The BCP-47 tag this machine resolves to, `\"en-GB\"` on a UK host.\n *\n * @returns The host's tag, or `null` where `Intl` is absent or refuses to\n * answer. `null` means \"no inference is available\", never \"assume English\".\n */\nexport function hostLocale(): string | null {\n if (typeof Intl !== \"object\" || Intl === null || typeof Intl.DateTimeFormat !== \"function\") return null;\n try {\n const tag = new Intl.DateTimeFormat().resolvedOptions().locale;\n return typeof tag === \"string\" && tag.length > 0 ? tag : null;\n } catch {\n return null;\n }\n}\n\n/**\n * The day/month/year order a BCP-47 tag writes a numeric date in.\n *\n * The Gregorian calendar and Latin digits are pinned so that a locale whose\n * default calendar is Persian, Buddhist or a Japanese era still contributes\n * its field ORDER and never its calendar system or its digits: the engine\n * computes in Gregorian throughout (`calendar/Gregorian.ts`, the month names,\n * the leap-year check), so a probe about another calendar would be an answer\n * to a question the engine never asks.\n *\n * Verified on this machine (Node 24.16.0, full ICU): `en-GB` DMY, `en-US` MDY,\n * `de-DE` DMY, `fr-FR` DMY, `ja-JP` YMD, `hu-HU` YMD, `en-CA` YMD, `fa-IR`\n * YMD.\n *\n * Two guards, because they catch different lies. `supportedLocalesOf` catches\n * a tag this runtime has no data for: it answers `[]` for `zz-ZZ` and `und`\n * while `new Intl.DateTimeFormat('zz-ZZ').resolvedOptions().locale` cheerfully\n * answers this host's `en-GB`, so without it a host naming a locale the\n * runtime does not carry would be given a stranger's order. {@link\n * isTrustworthyIntl} catches the case that guard cannot see, a small-ICU build\n * answering `en-US` for everything on a tag that IS supported.\n *\n * @param tag - A BCP-47 tag, from `date.inputLocale` or from {@link hostLocale}.\n * @returns The order, or `null` where `Intl` is absent, has no data for the\n * tag, is untrustworthy ({@link isTrustworthyIntl}), throws, or produces a\n * parts list missing any of the three fields. Every one of those means the\n * same thing to the caller: there is no inference here, so keep the behaviour\n * the engine already has.\n */\nexport function orderFromLocale(tag: string): DateFieldOrder | null {\n freshenMemo();\n const cached = orderByTag.get(tag);\n if (cached !== undefined) return cached;\n const resolved = probeOrder(tag);\n orderByTag.set(tag, resolved);\n return resolved;\n}\n\n/** The uncached probe behind {@link orderFromLocale}. */\nfunction probeOrder(tag: string): DateFieldOrder | null {\n if (typeof Intl !== \"object\" || Intl === null || typeof Intl.DateTimeFormat !== \"function\") return null;\n if (!isTrustworthyIntl()) return null;\n try {\n if (typeof Intl.DateTimeFormat.supportedLocalesOf === \"function\" && Intl.DateTimeFormat.supportedLocalesOf([tag]).length === 0) {\n return null;\n }\n const parts = new Intl.DateTimeFormat(tag, {\n calendar: \"gregory\",\n numberingSystem: \"latn\",\n timeZone: \"UTC\",\n year: \"numeric\",\n month: \"numeric\",\n day: \"numeric\",\n }).formatToParts(PROBE_INSTANT);\n if (!Array.isArray(parts)) return null;\n const sequence = parts\n .filter((part) => part.type === \"year\" || part.type === \"month\" || part.type === \"day\")\n .map((part) => part.type[0].toUpperCase())\n .join(\"\");\n return sequence === \"DMY\" || sequence === \"MDY\" || sequence === \"YMD\" ? sequence : null;\n } catch {\n return null;\n }\n}\n","/**\n * How this engine reads a numeric date literal, decided once and reported.\n *\n * `03/04/2026` names one of two days, and the engine has to pick one. Which it\n * picks has always been settled by `date.inputOrder`, but nothing said so: the\n * answer came back as a date with no account of how it was read, and a host\n * had no way to show the reader \"day first\" or to discover that its own\n * setting was the reason a document looked wrong.\n *\n * This module is the one place that decision is made, so the normaliser that\n * fuses a literal and the surfaces that explain one cannot disagree about it.\n * Two halves:\n *\n * - The engine-wide one, {@link resolveDateOrderPolicy}, run once per engine\n * and reported through `ExpressionEngine.getDateReading()`. It names the\n * order AND where the order came from.\n * - The per-literal one, {@link classifyRun} and {@link readNumericDate},\n * which decide what one run of digits means under that order, and, where it\n * means nothing, whether saying so is better than answering the arithmetic\n * the run is spelled like.\n * - The sentence, {@link composeReadingNote}, which says the same thing to a\n * reader. Composed here so that five hosts do not write five different\n * sentences about one fact, and so the note a hover shows and the message a\n * refusal carries cannot drift apart.\n *\n * @module DateReading\n */\n\nimport type { DateAmbiguity, DateConfig } from \"@solve-js/constants/Configuration\";\nimport { ErrorFactory } from \"@solve-js/errors/UnifiedErrorFramework\";\nimport { hostLocale, orderFromLocale, type DateFieldOrder } from \"@solve-js/calendar/HostLocale\";\nimport type { CalendarBackend } from \"@solve-js/calendar/CalendarBackend\";\nimport { daysInMonth } from \"@solve-js/calendar/Gregorian\";\n\n/** Scoped error codes the datetime package owns (see `errors/ErrorCode.ts` convention). */\nexport const DatetimeErrorCodes = {\n /**\n * `date.inputLocale` is not a BCP-47 locale tag (`\"en_US\"` with an\n * underscore is the usual mistake). Raised at engine construction, because a\n * locale that is silently ignored is a date order that is silently wrong.\n */\n DATE_INPUT_LOCALE_INVALID: \"DATE_INPUT_LOCALE_INVALID\",\n /**\n * A date-shaped run the resolved order cannot read, which another supported\n * order can (`12/25/2026` on a day-first engine), or a year-last run on a\n * year-first engine, which has no day and month roles to apply to it. The\n * message names the order actually used, the group that broke, the reading\n * that would work, and the two ways out. A recoverable Error VALUE, never a\n * throw, and suppressed by `date.onAmbiguous: 'arithmetic'`.\n */\n DATE_ORDER_MISMATCH: \"DATE_ORDER_MISMATCH\",\n /**\n * A run whose shape is unmistakably a date attempt and which names no real\n * day under any reading: `31/04/2026`, `29/02/2026`, `13/13/2026`,\n * `2026-02-29`, `2026-13-01`. Separate from {@link DATE_ORDER_MISMATCH}\n * because no change of order fixes it, so the message must not suggest one.\n */\n DATE_NOT_A_CALENDAR_DAY: \"DATE_NOT_A_CALENDAR_DAY\",\n} as const;\n\n/** Every error code the datetime package's date-reading rules can produce. */\nexport type DatetimeErrorCode = (typeof DatetimeErrorCodes)[keyof typeof DatetimeErrorCodes];\n\n/**\n * An order a literal can actually be read under: the three concrete field\n * orders, plus `'auto'` for the historic per-separator reading.\n *\n * Narrower than `DateInputOrder` on purpose. `'locale'` is a request for an\n * inference, not an order, and it is resolved away by\n * {@link resolveDateOrderPolicy} before anything that reads a literal sees it,\n * so the word cannot reach the normaliser, a worker or a snapshot.\n */\nexport type ResolvedDateOrder = \"auto\" | DateFieldOrder;\n\n/**\n * Where a resolved order came from, which is the part a reader needs and a\n * bug report should carry.\n *\n * - `'config'`: the host named `'DMY'`, `'MDY'` or `'YMD'` outright. No\n * inference ran and `date.inputLocale` was not consulted.\n * - `'locale'`: inferred from the tag the host gave in `date.inputLocale`.\n * - `'host-locale'`: inferred from the tag this machine resolves to.\n * - `'separator'`: `'auto'`, the historic reading, where a slash date is\n * day-first and a hyphen date month-first unless it is ISO-shaped.\n * - `'fallback'`: an inference was asked for and could not be made, so the\n * engine reads dates exactly as an `'auto'` engine does. Visible on purpose:\n * this is the case where a host should offer the reader a manual choice.\n */\nexport type DateOrderSource = \"config\" | \"locale\" | \"host-locale\" | \"separator\" | \"fallback\";\n\n/**\n * The reading policy one engine applies to every numeric date literal in every\n * line it evaluates.\n *\n * Resolved once, in the `ExpressionEngine` constructor, and then carried\n * rather than re-derived: the normaliser rule runs on every keystroke, so an\n * `Intl` call per literal would be a per-keystroke cost for an answer that\n * cannot change, and a per-expression bytecode cache keyed on text would go\n * stale against an order that could.\n */\nexport interface DateReadingPolicy {\n /** The order every ambiguous numeric literal is read under. Never `'locale'`. */\n readonly order: ResolvedDateOrder;\n /** Where {@link order} came from. See {@link DateOrderSource}. */\n readonly orderSource: DateOrderSource;\n /** The BCP-47 tag the order was inferred from, when it was inferred from one. */\n readonly locale?: string;\n /** What a run no order can read does: refuse it, or leave it to arithmetic. From `date.onAmbiguous`. */\n readonly onAmbiguous: DateAmbiguity;\n}\n\n/**\n * Whether a string is a locale tag `Intl` will accept.\n *\n * Checked through `Intl.getCanonicalLocales`, which throws a `RangeError` for\n * a malformed tag (`\"en_US\"`) and accepts one it merely has no data for.\n * That is the right line to draw here: a tag with no data is a reader whose\n * locale this runtime cannot describe, which the inference already handles by\n * falling back, whereas a malformed tag is a typo in the host's own code.\n *\n * A runtime with no `Intl.getCanonicalLocales` at all accepts everything,\n * because refusing a host's configuration on the grounds that the engine\n * cannot check it would fail in the one environment least able to react.\n */\nfunction isLocaleTag(tag: string): boolean {\n if (typeof Intl !== \"object\" || Intl === null || typeof Intl.getCanonicalLocales !== \"function\") return true;\n try {\n Intl.getCanonicalLocales(tag);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Resolves a host's `date` configuration into the concrete reading policy this\n * engine applies.\n *\n * The precedence is strict, and each step decides on its own: there is no\n * merge and no \"infer, then adjust\". An override beats an inference because\n * the inference is reached only through the one value that asks for it.\n *\n * 1. `'DMY'`, `'MDY'` or `'YMD'`: that order, outright, `'config'`. No `Intl`\n * call happens and `inputLocale` is not read at all.\n * 2. `'locale'` with `inputLocale` set: the order that tag writes, `'locale'`.\n * 3. `'locale'` with `inputLocale` unset: the order this machine's tag writes,\n * `'host-locale'`.\n * 4. `'locale'` where no inference could be made: `'auto'`, `'fallback'`. This\n * is today's behaviour, which is the only safe thing to fail to.\n * 5. `'auto'`: the historic per-separator reading, `'separator'`.\n *\n * `inputLocale` is inert unless `inputOrder` is `'locale'`. Setting it beside\n * `'auto'` changes no result, because a field that quietly switched inference\n * on would turn the predictable host mistake into a wrong reading rather than\n * no change. Its SHAPE is still checked wherever it is set, since a malformed\n * tag is a typo either way and the reader is better served by hearing about it\n * at construction than by never hearing about it.\n *\n * @param date - The engine's merged `date` configuration.\n * @returns The policy, frozen.\n * @throws {EngineError} `DATE_INPUT_LOCALE_INVALID` when `inputLocale` is set\n * and is not a tag `Intl` accepts.\n */\nexport function resolveDateOrderPolicy(date: DateConfig): DateReadingPolicy {\n const requestedLocale = date.inputLocale;\n if (requestedLocale !== undefined && !isLocaleTag(requestedLocale)) {\n throw ErrorFactory.config(\n DatetimeErrorCodes.DATE_INPUT_LOCALE_INVALID,\n `date.inputLocale \"${requestedLocale}\" is not a BCP-47 locale tag. Use a tag Intl accepts, for example \"en-US\".`,\n { inputLocale: requestedLocale },\n );\n }\n\n const onAmbiguous = date.onAmbiguous;\n const order = date.inputOrder;\n if (order === \"DMY\" || order === \"MDY\" || order === \"YMD\") {\n return Object.freeze({ order, orderSource: \"config\" as const, onAmbiguous });\n }\n\n if (order === \"locale\") {\n const tag = requestedLocale ?? hostLocale();\n if (tag !== null && tag !== undefined) {\n const inferred = orderFromLocale(tag);\n if (inferred !== null) {\n return Object.freeze({\n order: inferred,\n orderSource: requestedLocale !== undefined ? (\"locale\" as const) : (\"host-locale\" as const),\n locale: tag,\n onAmbiguous,\n });\n }\n }\n // No Intl, an Intl that answers for a locale that is not the host's, or a\n // tag it cannot describe. Fall back to what the engine already does rather\n // than to a guess, and say so, so a host can tell a decision from a guess.\n return Object.freeze({ order: \"auto\" as const, orderSource: \"fallback\" as const, onAmbiguous });\n }\n\n return Object.freeze({ order: \"auto\" as const, orderSource: \"separator\" as const, onAmbiguous });\n}\n\n/**\n * Month names, in English, used to say what is wrong with a date that names no\n * real day (\"February 2026 has 28 days\").\n *\n * English-only for the same reason `DatetimeTimestampPluginFunctions.ts`'s\n * weekday names are: every `explainLine` description and every structured\n * error message in the engine is English, and localising one sentence in the\n * middle of that would be less coherent than localising none.\n */\nexport const MONTH_NAMES = [\n \"January\", \"February\", \"March\", \"April\", \"May\", \"June\",\n \"July\", \"August\", \"September\", \"October\", \"November\", \"December\",\n];\n\n/** The separator a numeric date run was written with. */\nexport type NumericDateSeparator = \"slash\" | \"hyphen\" | \"dot\";\n\n/**\n * The shape of a three-group numeric run, decided by the digit counts alone\n * before any order is consulted.\n *\n * The shape is what decides whether an unreadable run refuses or falls through\n * to arithmetic, and the asymmetry between the two four-digit shapes is\n * deliberate and measured:\n *\n * - `'iso'`: a hyphen run with a four-digit LEADING group, `2026-04-03`. One\n * reading, whatever the order, and nothing configurable applies.\n * - `'year-last-4'`: `03/04/2026`, `12-25-2026`. Refuses when no reading\n * works, because nobody writes a two-step division ending in a four-digit\n * denominator: `03/04/2026` as arithmetic is 0.0004.\n * - `'year-first-4'`: `2026/04/03`, `1000/10/5`. A date under `'YMD'` alone\n * and ordinary arithmetic under every other order, exactly as today. This is\n * where division is protected: `1000/10/5` is 20, `1024/8/2` is 64,\n * `1000/12/4` is 20.83 and `2000/12/25` is 6.67, and a rule that claimed\n * them would be a worse bug than the one being fixed.\n * - `'short'`: every group one or two digits, `1/2/3`, `12/13/14`,\n * `25/12/23`. Today's reading exactly, falling through to arithmetic when it\n * does not resolve, because a two-digit year is too weak a signal to hang a\n * refusal on.\n * - `'none'`: `100/25/2`, `1000-500-200`. Never a date.\n */\nexport type NumericDateShape = \"iso\" | \"year-last-4\" | \"year-first-4\" | \"short\" | \"none\";\n\n/** One or two digits: a day or a month group. */\nconst DAY_OR_MONTH_GROUP = /^\\d{1,2}$/;\n/** Exactly four digits: a written-out year. */\nconst FULL_YEAR_GROUP = /^\\d{4}$/;\n\n/**\n * Classifies a three-group numeric run by its digit counts and separator.\n *\n * Decided before any order is consulted, so the same run has the same shape on\n * every engine and only what the shape MEANS depends on configuration.\n *\n * @param g0 - The first group, as typed.\n * @param g1 - The second group.\n * @param g2 - The third group.\n * @param separator - The separator between them.\n * @returns The shape. See {@link NumericDateShape}.\n */\nexport function classifyRun(\n g0: string,\n g1: string,\n g2: string,\n separator: NumericDateSeparator,\n): NumericDateShape {\n const shortFirst = DAY_OR_MONTH_GROUP.test(g0);\n const shortMiddle = DAY_OR_MONTH_GROUP.test(g1);\n const shortLast = DAY_OR_MONTH_GROUP.test(g2);\n if (separator === \"hyphen\" && FULL_YEAR_GROUP.test(g0) && shortMiddle && shortLast) return \"iso\";\n if (shortFirst && shortMiddle && FULL_YEAR_GROUP.test(g2)) return \"year-last-4\";\n if (separator === \"slash\" && FULL_YEAR_GROUP.test(g0) && shortMiddle && shortLast) return \"year-first-4\";\n if (shortFirst && shortMiddle && shortLast) return \"short\";\n return \"none\";\n}\n\n/** The three groups of a numeric run, with the text they were typed as. */\nexport interface NumericDateRun {\n /** The run exactly as typed, `\"03/04/2026\"`, for the message. */\n readonly text: string;\n /** The three groups, left to right, as typed. */\n readonly groups: readonly [string, string, string];\n readonly separator: NumericDateSeparator;\n}\n\n/**\n * What reading a numeric run came to: a real day, a refusal to report, or a\n * decision to leave the run to ordinary arithmetic.\n */\nexport type NumericDateRead =\n | {\n readonly kind: \"date\";\n readonly day: number;\n readonly month: number;\n readonly year: number;\n /** The order actually applied: one of the three, or `'ISO'` for a run that settled itself. */\n readonly order: DateFieldOrder | \"ISO\";\n /** Whether a two-digit year was windowed to a century. */\n readonly shortYear: boolean;\n /** The ISO of the reading NOT taken, when the other order names a DIFFERENT real day. */\n readonly alternative?: string;\n }\n | { readonly kind: \"refuse\"; readonly code: DatetimeErrorCode; readonly message: string }\n | { readonly kind: \"arithmetic\" };\n\n/**\n * A two-digit year, windowed to a century by the common glibc\n * `strptime(\"%y\")` convention: 00-68 is 2000-2068, 69-99 is 1969-1999. Four\n * digits are taken as written; any other count is not a year shape at all.\n */\nfunction resolveYearGroup(digits: string): number | null {\n if (digits.length === 4) return Number(digits);\n if (digits.length === 2) {\n const yy = Number(digits);\n return yy <= 68 ? 2000 + yy : 1900 + yy;\n }\n return null;\n}\n\n/**\n * Whether a day/month/year triple names a day the calendar actually has.\n *\n * Checked through the backend rather than by arithmetic here, so a run is\n * judged by the same calendar the literal would be built with. February 30\n * rolls over to March 2 in every implementation, and a rollover is how a\n * triple that is not a date announces itself.\n *\n * @param day - Day of the month, from 1.\n * @param month - Month, from 1.\n * @param year - The full year.\n * @param calendar - The backend the literal would be built with.\n * @returns `true` when the triple reads back unchanged.\n */\nexport function isRealCalendarDay(day: number, month: number, year: number): boolean {\n // Counted rather than round-tripped through the backend. Building the day\n // and reading it back went through `Date`'s two-digit-year window, which\n // maps year 26 to 1926, so every year below 100 was declared unreal and\n // `0026-04-03` was refused with \"April 0026 has 30 days\", which is true and\n // is exactly why it should have been accepted.\n if (month < 1 || month > 12 || day < 1) return false;\n return day <= daysInMonth(year, month - 1);\n}\n\n/**\n * Why a day/month/year triple names no real day, as the clause a message ends\n * with: \"there is no month 25\", \"February 2026 has 28 days\".\n *\n * @param day - Day of the month.\n * @param month - Month, from 1.\n * @param year - The full year.\n * @returns The clause. Callers check {@link isRealCalendarDay} first; a triple\n * that IS a real day is described by its month's true length, which says\n * nothing wrong but says nothing useful either.\n */\nexport function describeUnrealDay(day: number, month: number, year: number): string {\n if (month < 1 || month > 12) return `there is no month ${month}`;\n if (day < 1) return `there is no day ${day}`;\n return `${MONTH_NAMES[month - 1]} ${year} has ${daysInMonth(year, month - 1)} days`;\n}\n\n/** A day/month/year triple written out for a reader: \"3 April 2026\". */\nfunction spellDay(day: number, month: number, year: number): string {\n return `${day} ${MONTH_NAMES[month - 1]} ${year}`;\n}\n\n/**\n * A day/month/year triple as an ISO date, `\"2026-04-03\"`: the one spelling\n * every order reads the same way, which is what a refusal points at.\n *\n * @param day - Day of the month.\n * @param month - Month, from 1.\n * @param year - The full year.\n * @returns The ISO date.\n */\nexport function isoOf(day: number, month: number, year: number): string {\n const pad = (n: number) => String(n).padStart(2, \"0\");\n return `${String(year).padStart(4, \"0\")}-${pad(month)}-${pad(day)}`;\n}\n\n/** The day and month a two-role order assigns to the first two groups. */\nfunction rolesFor(order: DateFieldOrder, g0: string, g1: string): { day: number; month: number } {\n return order === \"DMY\"\n ? { day: Number(g0), month: Number(g1) }\n : { day: Number(g1), month: Number(g0) };\n}\n\n/** \"day first\" / \"month first\" / \"year first\", the way a message names an order. */\nfunction orderInWords(order: DateFieldOrder): string {\n if (order === \"DMY\") return \"day first\";\n if (order === \"MDY\") return \"month first\";\n return \"year first\";\n}\n\n/**\n * The order `'auto'` reads a two-role run in, which is the historic\n * per-separator behaviour: a slash date is day-first (`25/12/2023`), a hyphen\n * date is month-first (`12-25-2023`), and a dot date is day-first\n * (`25.12.2023`), which is what each of those spellings meant before an order\n * could be configured at all.\n */\nfunction separatorOrder(separator: NumericDateSeparator): DateFieldOrder {\n return separator === \"hyphen\" ? \"MDY\" : \"DMY\";\n}\n\n/**\n * Reads a three-group numeric run under one engine's resolved order.\n *\n * The one place the decision is made, so the normaliser that fuses a literal\n * and the surfaces that explain one cannot disagree about it.\n *\n * A run that no reading resolves is either refused or left to arithmetic, and\n * which of the two is a question about the SHAPE rather than about which guard\n * declined it. See {@link NumericDateShape} for the four shapes and the\n * measurements behind the asymmetry.\n *\n * @param run - The run, its groups and its separator.\n * @param order - This engine's resolved order. Never `'locale'`.\n * @param onAmbiguous - Whether a refusal is reported or suppressed. A dot run\n * ignores `'arithmetic'`, because its fall-through is a parse error rather\n * than a number, and an error is not an answer; for the same reason a dot run\n * of the `'short'` shape refuses too, where a slash or hyphen one falls\n * through.\n * @param calendar - The backend the literal would be built with.\n * @returns The reading, a refusal, or a decision to leave the run alone.\n */\nexport function readNumericDate(\n run: NumericDateRun,\n order: ResolvedDateOrder,\n onAmbiguous: DateAmbiguity,\n calendar: CalendarBackend,\n): NumericDateRead {\n const [g0, g1, g2] = run.groups;\n const shape = classifyRun(g0, g1, g2, run.separator);\n // A dot run has nothing to fall through TO. The lexer has already merged\n // `25.12` into one float-shaped token, so a dot run that is not a date is a\n // parse error rather than a number, and the house rule forbids an error as\n // an answer. Both escapes therefore close for it: `onAmbiguous` cannot\n // restore an answer that never existed, and the `'short'` shape's\n // fall-through has no arithmetic to protect (`12.13.14` written with dots is\n // not a fraction chain, it is a parse error).\n const canFallThrough = run.separator !== \"dot\";\n const refusing = onAmbiguous === \"refuse\" || !canFallThrough;\n\n if (shape === \"none\") return { kind: \"arithmetic\" };\n\n if (shape === \"iso\") {\n const year = Number(g0);\n const month = Number(g1);\n const day = Number(g2);\n if (isRealCalendarDay(day, month, year)) {\n return { kind: \"date\", day, month, year, order: \"ISO\", shortYear: false };\n }\n // The shape has one reading and no other to fall to, so a rollover here is\n // a date attempt that failed rather than arithmetic that looked like one.\n return refusing ? notACalendarDay(run.text, day, month, year) : { kind: \"arithmetic\" };\n }\n\n if (shape === \"year-first-4\") {\n if (order !== \"YMD\") return { kind: \"arithmetic\" };\n const year = Number(g0);\n const month = Number(g1);\n const day = Number(g2);\n // Still arithmetic when it is not a real day: a four-digit numerator is\n // ordinary division, and this shape is where that is protected.\n return isRealCalendarDay(day, month, year)\n ? { kind: \"date\", day, month, year, order: \"YMD\", shortYear: false }\n : { kind: \"arithmetic\" };\n }\n\n // 'year-last-4' and 'short' share their readings and differ only in what\n // happens when none of them works.\n const year = resolveYearGroup(g2);\n if (year === null) return { kind: \"arithmetic\" };\n const shortYear = g2.length === 2;\n\n if (order === \"YMD\") {\n // A year-last run has no year-first reading at all, so there are no roles\n // that failed, there are no roles to apply.\n if (!refusing || (shape === \"short\" && canFallThrough)) return { kind: \"arithmetic\" };\n return orderMismatchUnderYearFirst(run.text, g0, g1, year, calendar);\n }\n\n const chosen = order === \"auto\" ? separatorOrder(run.separator) : order;\n const other: DateFieldOrder = chosen === \"DMY\" ? \"MDY\" : \"DMY\";\n const chosenRoles = rolesFor(chosen, g0, g1);\n const otherRoles = rolesFor(other, g0, g1);\n\n if (isRealCalendarDay(chosenRoles.day, chosenRoles.month, year)) {\n // The other reading only counts as an alternative when it names a\n // DIFFERENT day. `01/01/2026` reads the same way round either way, so it\n // is not a choice the reader needs to be told about.\n const differs = otherRoles.day !== chosenRoles.day || otherRoles.month !== chosenRoles.month;\n const alternative = differs && isRealCalendarDay(otherRoles.day, otherRoles.month, year)\n ? isoOf(otherRoles.day, otherRoles.month, year)\n : undefined;\n return { kind: \"date\", day: chosenRoles.day, month: chosenRoles.month, year, order: chosen, shortYear, alternative };\n }\n\n if (!refusing || (shape === \"short\" && canFallThrough)) return { kind: \"arithmetic\" };\n\n if (isRealCalendarDay(otherRoles.day, otherRoles.month, year)) {\n return {\n kind: \"refuse\",\n code: DatetimeErrorCodes.DATE_ORDER_MISMATCH,\n message:\n `\"${run.text}\" is not a date read ${orderInWords(chosen)}: ` +\n `${describeUnrealDay(chosenRoles.day, chosenRoles.month, year)}. ` +\n `Read ${orderInWords(other)} it is ${spellDay(otherRoles.day, otherRoles.month, year)}. ` +\n `Set date.inputOrder to \"${other}\" to read numeric dates ${orderInWords(other)}.`,\n };\n }\n\n // Neither order names a real day, so no change of order fixes it and the\n // message must not suggest one.\n return notACalendarDay(run.text, chosenRoles.day, chosenRoles.month, year);\n}\n\n/** The DATE_NOT_A_CALENDAR_DAY refusal, worded from the reading that was attempted. */\nfunction notACalendarDay(text: string, day: number, month: number, year: number): NumericDateRead {\n return {\n kind: \"refuse\",\n code: DatetimeErrorCodes.DATE_NOT_A_CALENDAR_DAY,\n message: `\"${text}\" is not a real date: ${describeUnrealDay(day, month, year)}.`,\n };\n}\n\n/**\n * The refusal for a year-last run on a year-first engine, which has no roles\n * to apply to it. Names whichever of the two readings are real days, and the\n * ISO spelling that reads the same way on every engine.\n */\nfunction orderMismatchUnderYearFirst(\n text: string,\n g0: string,\n g1: string,\n year: number,\n calendar: CalendarBackend,\n): NumericDateRead {\n const dayFirst = rolesFor(\"DMY\", g0, g1);\n const monthFirst = rolesFor(\"MDY\", g0, g1);\n const dayFirstReal = isRealCalendarDay(dayFirst.day, dayFirst.month, year);\n const monthFirstReal = isRealCalendarDay(monthFirst.day, monthFirst.month, year);\n\n if (!dayFirstReal && !monthFirstReal) {\n return notACalendarDay(text, dayFirst.day, dayFirst.month, year);\n }\n\n const opening = `\"${text}\" is not a date read year first.`;\n // Both readings can name the SAME day (`03/03/2026`), and offering it twice\n // read as a bug in the sentence rather than as advice. One reading, said once.\n const sameDay = dayFirst.day === monthFirst.day && dayFirst.month === monthFirst.month;\n if (dayFirstReal && monthFirstReal && !sameDay) {\n return {\n kind: \"refuse\",\n code: DatetimeErrorCodes.DATE_ORDER_MISMATCH,\n message:\n `${opening} Read day first it is ${spellDay(dayFirst.day, dayFirst.month, year)} ` +\n `and month first ${spellDay(monthFirst.day, monthFirst.month, year)}. ` +\n `Write it as ${isoOf(dayFirst.day, dayFirst.month, year)}, ` +\n `or set date.inputOrder to \"DMY\" or \"MDY\".`,\n };\n }\n\n const roles = dayFirstReal ? dayFirst : monthFirst;\n const which: DateFieldOrder = dayFirstReal ? \"DMY\" : \"MDY\";\n return {\n kind: \"refuse\",\n code: DatetimeErrorCodes.DATE_ORDER_MISMATCH,\n message:\n `${opening} Read ${orderInWords(which)} it is ${spellDay(roles.day, roles.month, year)}. ` +\n `Write it as ${isoOf(roles.day, roles.month, year)}, or set date.inputOrder to \"${which}\".`,\n };\n}\n\n/**\n * How one date literal in one line was read, with the span it occupies and a\n * sentence a host can show.\n *\n * Derived, never stored. A line can hold two literals\n * (`31/12/2026 - 01/01/2026`), which one value cannot represent, and a derived\n * date (`03/04/2026 + 1 day`) is no longer the literal that was read, so a\n * reading recorded on the answer would be right for the common line and\n * quietly wrong for the rest. It costs a re-lex of the lines a reader actually\n * asks about, and nothing at all on the rest.\n */\nexport interface DateReading {\n /** The literal exactly as typed, `\"03/04/2026\"`. */\n readonly text: string;\n /** Offset of the first character in the line, for an editor underline. */\n readonly start: number;\n /** Offset one past the last character. */\n readonly end: number;\n /** The day it was read as, `\"2026-04-03\"`, or null when the literal was refused. */\n readonly iso: string | null;\n /** The order actually applied, or null when no order could be. */\n readonly order: DateFieldOrder | \"ISO\" | \"spelled\" | null;\n /** Where that order came from. `'iso'` and `'spelled'` mean the literal settled itself. */\n readonly orderSource: DateOrderSource | \"iso\" | \"spelled\";\n /** The BCP-47 tag the order was inferred from, when it was inferred from one. */\n readonly locale?: string;\n /** Whether the other order also names a real day, so the reading is a genuine choice. */\n readonly contested: boolean;\n /** Whether a two-digit year was windowed to a century. */\n readonly shortYear: boolean;\n /** The ISO of the reading not taken, when {@link contested}. */\n readonly alternative?: string;\n /** The error code, when the literal was refused. */\n readonly problem?: DatetimeErrorCode;\n /**\n * The sentence a host shows, composed here rather than assembled by each\n * host from the parts, so five hosts do not write five different sentences\n * about one fact.\n */\n readonly note: string;\n /**\n * Whether the note is worth showing: the reading was contested, a two-digit\n * year was windowed, or the literal was refused. A boolean the engine\n * computes rather than a judgement each host re-derives, which is what stops\n * the note being either wallpaper or absent.\n */\n readonly needsNote: boolean;\n}\n\n/** Everything about a reading except the two fields composed from the rest. */\nexport type DateReadingFacts = Omit<DateReading, \"note\" | \"needsNote\">;\n\n/**\n * How the reading came to be, as the clause that follows the day in a note.\n *\n * The separator is named only where the order came from it, because that is\n * the one case where the reader's next question is \"why day first\" and the\n * honest answer is \"because you wrote a slash\".\n */\nfunction sourceInWords(facts: DateReadingFacts, separator: NumericDateSeparator): string {\n if (facts.orderSource === \"iso\") return \"ISO\";\n if (facts.orderSource === \"spelled\") return \"with the month spelled out\";\n // A refused literal has no order to name, and the two shapes that settle\n // themselves have already returned, so this only guards the type.\n const order = facts.order === null || facts.order === \"ISO\" || facts.order === \"spelled\"\n ? \"as written\"\n : orderInWords(facts.order);\n switch (facts.orderSource) {\n case \"config\":\n return `${order}, from date.inputOrder`;\n case \"locale\":\n return `${order}, from the locale ${facts.locale}`;\n case \"host-locale\":\n return `${order}, from the host locale ${facts.locale}`;\n case \"fallback\":\n return `${order}, the default for a ${separator} date, because the host locale could not be read`;\n default:\n return `${order}, the default for a ${separator} date`;\n }\n}\n\n/** An ISO date written out for a reader: `\"2026-03-04\"` becomes `\"4 March 2026\"`. */\nfunction spellIso(iso: string): string {\n const [year, month, day] = iso.split(\"-\").map(Number);\n return spellDay(day, month, year);\n}\n\n/**\n * Composes the sentence a host shows for one reading.\n *\n * In the house voice and in one place, so the note a hover shows and the\n * message a refusal carries are one story told in two situations rather than\n * two mechanisms that can drift:\n *\n * 03/04/2026 read as 3 April 2026, day first, from the host locale en-GB.\n * Month first would be 4 March 2026.\n *\n * @param facts - The decided reading.\n * @param separator - The separator the literal was written with, for the\n * `'auto'` wording.\n * @param refusal - The refusal message, when the literal was refused. It IS\n * the note in that case: there is no reading to describe.\n * @returns The sentence.\n */\nexport function composeReadingNote(\n facts: DateReadingFacts,\n separator: NumericDateSeparator,\n refusal?: string,\n): string {\n if (facts.iso === null) return refusal ?? `\"${facts.text}\" is not a date this engine can read.`;\n let note = `${facts.text} read as ${spellIso(facts.iso)}, ${sourceInWords(facts, separator)}.`;\n if (facts.alternative !== undefined && facts.order !== null && facts.order !== \"ISO\" && facts.order !== \"spelled\") {\n const other = facts.order === \"DMY\" ? \"Month first\" : \"Day first\";\n note += ` ${other} would be ${spellIso(facts.alternative)}.`;\n }\n if (facts.shortYear) {\n note += ` The two-digit year ${facts.text.slice(-2)} was read as ${facts.iso.slice(0, 4)}.`;\n }\n return note;\n}\n\n/**\n * Completes a reading with the two fields derived from the rest: the sentence\n * and whether it is worth showing.\n *\n * @param facts - The decided reading.\n * @param separator - The separator the literal was written with.\n * @param refusal - The refusal message, when the literal was refused.\n * @returns The whole record.\n */\nexport function completeDateReading(\n facts: DateReadingFacts,\n separator: NumericDateSeparator,\n refusal?: string,\n): DateReading {\n return {\n ...facts,\n note: composeReadingNote(facts, separator, refusal),\n needsNote: facts.contested || facts.shortYear || facts.iso === null,\n };\n}\n\n/**\n * Splits a fused literal's source text back into the groups and separator\n * {@link readNumericDate} takes, or null where the text is not a three-group\n * numeric run at all (a spelled-out month, an ISO timestamp).\n *\n * Reading the text back rather than remembering the groups is what lets the\n * explanation surfaces reach the same answer through the same function the\n * normaliser used, with no reading table carried on the bytecode and no\n * snapshot format change.\n *\n * @param text - The literal exactly as typed.\n * @returns The run, or null.\n */\nexport function splitNumericRun(text: string): NumericDateRun | null {\n const separated = /^(\\d+)([/-])(\\d+)\\2(\\d+)$/.exec(text);\n if (separated !== null) {\n return {\n text,\n groups: [separated[1], separated[3], separated[4]],\n separator: separated[2] === \"-\" ? \"hyphen\" : \"slash\",\n };\n }\n const dotted = /^(\\d{1,2})\\.(\\d{1,2})\\.(\\d{2}|\\d{4})$/.exec(text);\n if (dotted !== null) {\n return { text, groups: [dotted[1], dotted[2], dotted[3]], separator: \"dot\" };\n }\n return null;\n}\n","import type { Token } from \"@solve-js/lexer/Token\";\nimport { tokenTypeId } from \"@solve-js/lexer/Token\";\nimport { LexerToken } from \"@solve-js/lexer/ExpressionLexer\";\nimport type { NormalizerRule, NormalizerMatch } from \"@solve-js/normalizer/NormalizerRule\";\nimport { parseIso8601 } from \"@solve-js/packages/datetime/Iso8601\";\nimport {\n readNumericDate,\n type DatetimeErrorCode,\n type NumericDateSeparator,\n type ResolvedDateOrder,\n} from \"../DateReading\";\nimport type { DateAmbiguity } from \"@solve-js/constants/Configuration\";\nimport type { CalendarBackend } from \"@solve-js/calendar/CalendarBackend\";\nimport { DATE_CALENDAR } from \"@solve-js/calendar/DateCalendar\";\n\n/**\n * Token type a fused date literal is rewritten to.\n *\n * One type covers every supported ordering, so the parselet handles the shape\n * rather than the locale.\n */\nexport const DATETIME_LITERAL_TYPE = \"DATETIME_LITERAL\";\nconst DATETIME_LITERAL_TYPE_ID = tokenTypeId(DATETIME_LITERAL_TYPE);\n\n/**\n * Token type a date-shaped run that no configured order can read is rewritten\n * to, carrying the code and the message rather than a value.\n *\n * A separate type rather than a flag on the literal above, so the parselet for\n * each is the shape of what it does: one pushes a date, the other reports a\n * fault. `UnreadableDateParselet` compiles it to a plugin call returning an\n * Error VALUE, which is what keeps a refusal off the throwing path and out of\n * the bytecode format: no new opcode, no operand change, and\n * `SNAPSHOT_VERSION` untouched.\n */\nexport const DATETIME_LITERAL_UNREADABLE_TYPE = \"DATETIME_LITERAL_UNREADABLE\";\nconst DATETIME_LITERAL_UNREADABLE_TYPE_ID = tokenTypeId(DATETIME_LITERAL_UNREADABLE_TYPE);\n\n/** A pure digit string, guards against fusing hex/scientific/bigint-suffixed NUMBER tokens. */\nconst PLAIN_INTEGER = /^\\d+$/;\n\n/** First NUMBER token of a dot-separated literal: the lexer's decimal scanner\n * merges \"DD.MM\" into one float-shaped token (see module doc below). */\nconst DOT_DAY_MONTH = /^\\d{1,2}\\.\\d{1,2}$/;\n\n/** Second NUMBER token of a dot-separated literal: the lexer re-enters\n * tokenizeNumber() AT the second dot, so the year keeps its leading dot. */\nconst DOT_LEADING_YEAR = /^\\.(\\d{2}|\\d{4})$/;\n\n/**\n * Whether every token in a run touches the next one in the source text, with\n * no whitespace anywhere between the first character and the last.\n *\n * This is the whole basis for telling a date literal apart from the\n * arithmetic it is spelled identically to. A date is written as one\n * uninterrupted run (\"2024-5-3\"); a subtraction chain is written with spaces\n * around its operators (\"2024 - 5 - 3\"). The lexer records that difference in\n * the token offsets and nowhere else, since the tokens themselves are the same\n * five either way:\n *\n * 2024-5-3 NUMBER@0 MINUS@4 NUMBER@5 MINUS@6 NUMBER@7\n * 2024 - 5 - 3 NUMBER@0 MINUS@5 NUMBER@7 MINUS@9 NUMBER@11\n *\n * The same technique, for the same reason, is what tells \"5k\" from \"5 k\" in\n * `arithmetic/normalizer/LargeNumberSuffixNormalizerRule.ts`.\n *\n * ## Why this replaced a zero-padding requirement on the ISO branch\n * The ISO branch briefly required its month and day groups to be padded to two\n * digits, which did stop \"2024 - 5 - 3\" being answered as \"Friday, May 3,\n * 2024\" but also stopped \"2024-5-3\" being a date at all. Padding was never the\n * real distinction, and the rule's own US branch is the proof: it has always\n * accepted unpadded groups, so \"1-1-2020\" and \"12-25-2023\" are both dates\n * today. Requiring padding on one branch of the two was therefore an\n * inconsistency between two spellings of one rule rather than a policy.\n *\n * The US branch's own guard is a 2-or-4-digit trailing year plus the calendar\n * check, and it is NOT safe against spaced arithmetic on its own: before this\n * check existed, \"12 - 25 - 2023\" answered Christmas 2023 instead of -2036,\n * and \"1 - 1 - 2020\" answered New Year's Day instead of -2020. Applying\n * adjacency to the whole run rather than to one branch fixes that at the same\n * time and leaves both branches resting on the same reason.\n *\n * ## Padded but spaced\n * \"2024 - 05 - 03\" is subtraction under this check, and that is the intended\n * reading. Nobody types the spaces when they mean the date, so the spacing is\n * the clearest signal available about which was meant, and the padding is not:\n * a person subtracting may well write \"05\" for the same reason they write\n * \"05\" anywhere else. Choosing the date there would mean no spelling of that\n * subtraction existed.\n *\n * `sourceEnd` is preferred over `text.length` where it is set, because a token\n * an earlier rule fused carries replacement text rather than source text and\n * only `sourceEnd` still describes the span it covers (see\n * `normalizer/TokenNormalizer.ts`'s `createFusedToken`).\n */\nfunction writtenAsOneRun(tokens: Token[]): boolean {\n for (let i = 0; i < tokens.length - 1; i++) {\n const token = tokens[i];\n const end = token.sourceEnd ?? token.offset + token.text.length;\n if (end !== tokens[i + 1].offset) return false;\n }\n return true;\n}\n\n/**\n * Converts a validated day/month/year triple into a fused DATETIME_LITERAL\n * token, or null if the triple isn't a real calendar date (e.g. \"30\" for\n * February), letting the caller fall back to treating the source tokens\n * as ordinary arithmetic instead of a date.\n *\n * `calendar` is the backend the literal's local midnight is built with.\n */\nexport function buildDateToken(\n day: number,\n month: number,\n year: number,\n sourceTokens: Token[],\n ruleName: string,\n calendar: CalendarBackend,\n): NormalizerMatch | null {\n if (month < 1 || month > 12 || day < 1 || day > 31) return null;\n\n // Local midnight, consistent with formatDatetime()'s display and the\n // DATE_NOW epoch, both of which are local-time.\n const epochMs = calendar.localMidnight(year, month - 1, day);\n // Reject calendar rollover (e.g. day=30 in February) rather than silently\n // normalizing to March 2, a rollover almost always means the tokens were\n // never a date to begin with (e.g. \"2-30-5\" as chained subtraction).\n const built = calendar.fields(epochMs);\n if (built.year !== year || built.month0 !== month - 1 || built.day !== day) {\n return null;\n }\n\n const first = sourceTokens[0];\n const text = sourceTokens.map((t) => t.value).join(\"\");\n const fusedToken = new LexerToken(\n DATETIME_LITERAL_TYPE,\n DATETIME_LITERAL_TYPE_ID,\n String(epochMs),\n text,\n first.offset,\n 0,\n first.line,\n first.col,\n );\n\n return { consumed: sourceTokens.length, replacement: [fusedToken], ruleName };\n}\n\n/**\n * The source text a run of tokens covers, with one space wherever the tokens\n * were not written touching.\n *\n * Reconstructed from the token offsets because a normaliser rule is handed\n * tokens rather than the line they came from, and a refusal has to quote what\n * the reader typed: `\"29 February 2026\"` and `\"March 9, 2024\"` read back the\n * way they were written, while an adjacent run like `\"03/04/2026\"` reads back\n * with nothing added.\n *\n * @param tokens - The run.\n * @returns The reconstructed text.\n */\nexport function runText(tokens: Token[]): string {\n let out = \"\";\n let previousEnd = -1;\n for (const token of tokens) {\n const text = token.text ?? token.value;\n if (previousEnd >= 0 && token.offset > previousEnd) out += \" \";\n out += text;\n previousEnd = token.sourceEnd ?? token.offset + text.length;\n }\n return out;\n}\n\n/**\n * Fuses a run that names no readable date into one\n * {@link DATETIME_LITERAL_UNREADABLE_TYPE} token carrying the refusal.\n *\n * The code and message travel as JSON in the token's `value`, which is the\n * only field a fused token has to carry a payload in, and `text` keeps the\n * run exactly as typed so an editor still underlines what the reader wrote.\n *\n * Consuming the run rather than declining it is the whole point: declining\n * would hand the same five tokens back to the parser, which reads them as the\n * division they are spelled like, and answering 0.0004 for a date is the\n * behaviour being fixed.\n *\n * @param code - The refusal's error code.\n * @param message - The sentence the reader sees.\n * @param sourceTokens - The run being replaced.\n * @param ruleName - The rule name, for normaliser bookkeeping.\n * @returns The match.\n */\nexport function faultMatch(\n code: DatetimeErrorCode,\n message: string,\n sourceTokens: Token[],\n ruleName: string,\n): NormalizerMatch {\n const first = sourceTokens[0];\n const text = runText(sourceTokens);\n const fusedToken = new LexerToken(\n DATETIME_LITERAL_UNREADABLE_TYPE,\n DATETIME_LITERAL_UNREADABLE_TYPE_ID,\n text,\n text,\n first.offset,\n 0,\n first.line,\n first.col,\n );\n // The reason travels on the token: `value` is what a parse error and the\n // editor token API print, and a reader shown the engine's JSON is being\n // shown its internals.\n fusedToken.fault = { code, message };\n return { consumed: sourceTokens.length, replacement: [fusedToken], ruleName };\n}\n\n/**\n * A full ISO 8601 timestamp: an ISO date with a time of day, optionally\n * carrying a UTC offset or the `Z` that means one of zero.\n *\n * Anchored at the start and deliberately greedy about the offset, so\n * `...T15:30:00+11:00` matches through the offset rather than stopping at the\n * seconds and leaving `+11:00` behind as an addition. That is what the bare\n * form used to do: `2019-04-01T15:30:00+11:00` read the offset as a clock time\n * being ADDED to the date on its left, and answered today at 11:00. Both\n * halves of that were wrong and neither was visible, which is worse than the\n * bare form simply not being supported.\n *\n * The time of day is required. Without it this would match what the date-only\n * branches below already handle, and they carry the ambiguity rules\n * (adjacency, group shapes) that keep a subtraction chain a subtraction.\n *\n * Matched against reconstructed source text rather than token by token. The\n * lexer has no idea this is one literal, so it emits nine to fourteen tokens\n * for it with the shape depending on the spelling (`T15` arrives as an\n * identifier, `Z` as another, an offset as a PLUS or MINUS with two more\n * numbers), and enumerating those permutations in token patterns is how a\n * spelling gets missed.\n *\n * `T` and `Z` are uppercase only, matching `Iso8601.ts`'s own pattern, which is\n * what actually parses the match. Accepting a spelling here that the parser\n * then refuses would mean the bare form supported more shapes than the quoted\n * one, for no reason a reader could infer.\n */\nconst ISO_TIMESTAMP = /^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}(:\\d{2}(\\.\\d+)?)?(Z|[+-]\\d{2}:?\\d{2})?/;\n\n/**\n * Token types a run of ISO 8601 timestamp text can lex into. Anything else\n * ends the run, so the reconstruction below can never reach across an operator\n * or a word that is not part of the literal.\n */\nconst ISO_TOKEN_TYPES = new Set([\"NUMBER\", \"MINUS\", \"PLUS\", \"COLON\", \"IDENT\"]);\n\n/**\n * How many tokens the longest supported spelling occupies. `2019-04-01T15:30:00.123+11:00`\n * is fourteen; the cap only bounds the walk, since the match itself decides\n * where the literal ends.\n */\nconst ISO_MAX_TOKENS = 16;\n\n/**\n * Fuses a bare (unquoted) ISO 8601 timestamp into one DATETIME_LITERAL.\n *\n * `Iso8601.ts` could always parse this shape, and still does the parsing here;\n * what it said could not be done without \"a much larger, dedicated lexer\n * change\" was recognising the bare form, on the grounds that it is ambiguous\n * with arithmetic. The date half of that ambiguity was settled by the rule this\n * helper sits inside (a date is written as one uninterrupted run, so\n * `2024 - 5 - 3` stays arithmetic), and the time half is not ambiguous at all:\n * no chain of subtractions contains a `T15:30`.\n *\n * Contiguity in the SOURCE is what makes that true, the same test\n * {@link writtenAsOneRun} applies to the date-only orderings. Every token has\n * to begin exactly where the previous one ended, so `2019-04-01 T15:30` with a\n * space in it, or `2019-04-01 + 11:00` with the offset written as an addition,\n * are left alone: the user who typed a space typed two things.\n *\n * A token an earlier normalizer rule already fused ends the run rather than\n * joining it. Its `text` is replacement text rather than source text (see\n * `normalizer/TokenNormalizer.ts`'s `createFusedToken`), so concatenating it\n * would reconstruct something the user never typed, and nothing that has\n * already been fused into a phrase is part of a timestamp anyway.\n *\n * @returns The fused match, or null when the tokens at `pos` are not a\n * timestamp, when the match would end mid-token, or when the shape is\n * ISO-like but names no real instant (`2019-04-01T25:00:00`).\n */\nfunction fuseIsoTimestamp(tokens: Token[], pos: number, ruleName: string, calendar: CalendarBackend): NormalizerMatch | null {\n const first = tokens[pos];\n if (first.sourceEnd !== undefined) return null;\n let text = first.text;\n let runEnd = first.offset + first.text.length;\n const window: Token[] = [first];\n for (let i = pos + 1; i < tokens.length && window.length < ISO_MAX_TOKENS; i++) {\n const next = tokens[i];\n if (next.sourceEnd !== undefined) break;\n if (next.offset !== runEnd || !ISO_TOKEN_TYPES.has(next.type)) break;\n text += next.text;\n runEnd = next.offset + next.text.length;\n window.push(next);\n }\n\n const matched = ISO_TIMESTAMP.exec(text);\n if (matched === null) return null;\n\n // The literal has to end where a token ends. A match that stopped halfway\n // through one would leave the parser holding a token whose text has already\n // been consumed, so decline and let the ordinary rules have it.\n let consumed = 0;\n let covered = 0;\n for (const token of window) {\n covered += token.text.length;\n consumed++;\n if (covered >= matched[0].length) break;\n }\n if (covered !== matched[0].length) return null;\n\n // The instant comes from the same parser the quoted form uses, so the two\n // spellings cannot drift apart: an offset means what it means there, and a\n // timestamp with no offset is local time, exactly as a bare date literal is\n // local midnight.\n const epochMs = parseIso8601(matched[0], calendar);\n if (epochMs === null) return null;\n\n const fusedToken = new LexerToken(\n DATETIME_LITERAL_TYPE,\n DATETIME_LITERAL_TYPE_ID,\n String(epochMs),\n matched[0],\n first.offset,\n 0,\n first.line,\n first.col,\n first.offset + matched[0].length,\n );\n return { consumed, replacement: [fusedToken], ruleName };\n}\n\n/**\n * NormalizerRule that fuses numeric date literals into a single\n * DATETIME_LITERAL token, per the documented \"Datetime Formats\":\n * - European: DD/MM/YYYY (5 tokens: NUMBER SLASH NUMBER SLASH NUMBER)\n * - US: MM-DD-YYYY (5 tokens: NUMBER MINUS NUMBER MINUS NUMBER)\n * - ISO 8601: YYYY-MM-DD (same 5-token shape as US, disambiguated by the\n * first group being exactly 4 digits)\n * - Dot: DD.MM.YYYY (2 tokens. See below)\n *\n * ## Why the dot format is a 2-token window, not 5\n * ExpressionLexer's tokenizeNumber() treats \".\" adjacent to digits on both\n * sides as a decimal point, not a separator. For \"25.12.2023\" the lexer\n * itself emits only two NUMBER tokens: \"25.12\" (day+month merged into one\n * float-shaped literal) and \".2023\" (the lexer re-enters number scanning\n * AT the second dot, so the year keeps a leading dot). There is no 5-token\n * NUMBER-DOT-NUMBER-DOT-NUMBER shape to match against, the fusion has to\n * happen post-hoc from that 2-token shape instead. This only works for the\n * literal typed with no internal whitespace (e.g. \"25.12.2023\"); a spaced\n * variant (\"25 .12 .2023\") produces three separate leading-dot tokens and\n * is intentionally not supported, out of scope for the documented format.\n *\n * ## Ambiguity with existing arithmetic\n * A date-shaped SLASH or MINUS chain (e.g. \"25/12/2023\" or \"12-25-2023\")\n * previously parsed as chained division/subtraction. This rule\n * deliberately reinterprets any such chain that resolves to a real\n * calendar date as a date literal instead, matching the documented\n * behavior. Chains that aren't valid dates (out-of-range day/month, a\n * February 30, a non-2/4-digit year) fall through unchanged.\n *\n * That reinterpretation only ever claims a chain written as one\n * uninterrupted run of characters. \"25/12/2023\" and \"12-25-2023\" are dates;\n * \"25 / 12 / 2023\" and \"12 - 25 - 2023\", written with the spaces an operator\n * normally gets, stay division and subtraction. {@link writtenAsOneRun}\n * carries the full reasoning, including why this is checked instead of\n * requiring an ISO date's zero-padding.\n *\n * ## Relationship to Iso8601.ts / DatePhrase.ts\n * This is the general-purpose \"bare numeric date literal\" implementation\n * those two files' doc comments referenced as landing on a sibling branch\n * (`feat/safety-limits-datetime-literals`), now ported here. It's\n * intentionally independent of both: `Iso8601.ts` only parses QUOTED\n * STRING literals (`\"2019-04-01...\" to date`), and the Stocks package's\n * `DatePhrase.ts` is a narrower, deliberately-diverging grammar (US-style\n * bare SLASH dates, 4-digit-year-only) scoped to stock-history queries\n * neither of those needed to change for this to land.\n *\n * ## What a run no order can read does\n * A date-shaped run the resolved order cannot read is REFUSED rather than\n * handed back to the parser as division: `12/25/2026` on a day-first engine\n * reports that there is no month 25 instead of answering 0.00, and\n * `31/02/2026 + 1 day` reports that February 2026 has 28 days instead of\n * answering \"1.01 day\". Which runs refuse and which still fall through to\n * arithmetic is decided by shape, in `DateReading.ts`'s `classifyRun`, and the\n * boundary is measured rather than aesthetic: a four-digit DENOMINATOR ends\n * nothing anybody writes, while a four-digit NUMERATOR is ordinary division\n * (`1000/10/5` is 20, `1024/8/2` is 64), so the two are treated differently on\n * purpose. `date.onAmbiguous: 'arithmetic'` restores every previous value.\n *\n * `getCalendar` supplies the calendar backend the literal is built with, read\n * per match so it follows the engine that registered the rule; the default\n * is the built-in `Date` backend, for a rule registered outside an engine.\n * `getOnAmbiguous` supplies that engine's refusal policy the same way.\n */\nexport function dateLiteralNormalizerRule(\n getInputOrder: () => ResolvedDateOrder = () => \"auto\",\n getCalendar: () => CalendarBackend = () => DATE_CALENDAR,\n getOnAmbiguous: () => DateAmbiguity = () => \"refuse\",\n): NormalizerRule {\n return {\n name: \"datetime:date-literal\",\n priority: 70,\n // Derived from this rule's own opening guards; see RuleSlot on why an\n // over-broad slot is safe and an over-narrow one is not.\n shape: [{ types: [\"NUMBER\"] }],\n match(tokens: Token[], pos: number): NormalizerMatch | null {\n const t0 = tokens[pos];\n if (t0.type !== \"NUMBER\") return null;\n const calendar = getCalendar();\n\n // ── Dot format: 2-token window (see module doc) ──────────────────\n // The lexer merged the day and month into one float-shaped token, but\n // the boundary is still there in the text, so the same reading, the same\n // shapes and the same refusals apply here as to the separator forms. It\n // used to ignore `date.inputOrder` outright: `03.04.2026` on a\n // month-first engine answered 3 April, silently reading it the other\n // way round, and `12.25.2026` answered nothing at all.\n if (DOT_DAY_MONTH.test(t0.value)) {\n const t1 = tokens[pos + 1];\n if (t1 && t1.type === \"NUMBER\" && DOT_LEADING_YEAR.test(t1.value)) {\n const [first, second] = t0.value.split(\".\");\n const dotRun = {\n text: `${t0.value}${t1.value}`,\n groups: [first, second, t1.value.slice(1)] as const,\n separator: \"dot\" as NumericDateSeparator,\n };\n const dotReading = readNumericDate(dotRun, getInputOrder(), getOnAmbiguous(), calendar);\n if (dotReading.kind === \"date\") {\n return buildDateToken(\n dotReading.day, dotReading.month, dotReading.year,\n [t0, t1], \"datetime:date-literal:dot\", calendar,\n );\n }\n if (dotReading.kind === \"refuse\") {\n return faultMatch(dotReading.code, dotReading.message, [t0, t1], \"datetime:date-literal:dot:unreadable\");\n }\n }\n return null;\n }\n\n // ── ISO 8601 timestamp: as many tokens as the spelling takes ─────\n // Tried before the date-only windows below, which would otherwise fuse\n // the date half of a timestamp and leave the time half to be read as\n // arithmetic. See fuseIsoTimestamp().\n if (t0.value.length === 4 && PLAIN_INTEGER.test(t0.value)) {\n const timestamp = fuseIsoTimestamp(tokens, pos, \"datetime:date-literal:iso-timestamp\", calendar);\n if (timestamp) return timestamp;\n }\n\n // ── Slash / minus format: 5-token window ─────────────────────────\n if (!PLAIN_INTEGER.test(t0.value)) return null;\n const sep1 = tokens[pos + 1];\n if (!sep1 || (sep1.type !== \"SLASH\" && sep1.type !== \"MINUS\")) return null;\n const t1 = tokens[pos + 2];\n const sep2 = tokens[pos + 3];\n const t2 = tokens[pos + 4];\n if (!t1 || t1.type !== \"NUMBER\" || !PLAIN_INTEGER.test(t1.value)) return null;\n if (!sep2 || sep2.type !== sep1.type) return null;\n if (!t2 || t2.type !== \"NUMBER\" || !PLAIN_INTEGER.test(t2.value)) return null;\n\n const sourceTokens = [t0, sep1, t1, sep2, t2];\n // The one check that separates every reading below from the arithmetic\n // it is spelled identically to, and the only one that applies to all of\n // them equally. Adjacency still decides date-versus-arithmetic before\n // any shape or order is considered, so `2024 - 5 - 3` is 2,016 and no\n // setting makes it a date. See writtenAsOneRun.\n if (!writtenAsOneRun(sourceTokens)) return null;\n\n // The reading, the refusal and the decision to leave the run alone all\n // come from one function, so this rule and the surfaces that explain a\n // literal cannot word or decide the same fact differently. See\n // `DateReading.ts`, which carries the four shapes and why two of them\n // refuse while the other two fall through.\n const run = {\n text: sourceTokens.map((token) => token.value).join(\"\"),\n groups: [t0.value, t1.value, t2.value] as const,\n separator: (sep1.type === \"MINUS\" ? \"hyphen\" : \"slash\") as NumericDateSeparator,\n };\n const reading = readNumericDate(run, getInputOrder(), getOnAmbiguous(), calendar);\n if (reading.kind === \"arithmetic\") return null;\n if (reading.kind === \"refuse\") {\n return faultMatch(reading.code, reading.message, sourceTokens, \"datetime:date-literal:unreadable\");\n }\n return buildDateToken(\n reading.day, reading.month, reading.year, sourceTokens,\n `datetime:date-literal:${reading.order.toLowerCase()}`, calendar,\n );\n },\n };\n}\n"]}