math-expression-compiler 4.3.3 → 4.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -5,12 +5,14 @@
5
5
  [![NPM downloads][badge-npm-downloads]][url-npm]
6
6
  [![NPM Unpacked Size (with version)][badge-npm-unpacked-size]][url-npm]
7
7
 
8
- Math expressions compiled once into a function of plain numbers, in mathjs's numeric language and held to mathjs's recorded answers. A formula is parsed into a tree, the tree is compiled into a function of its variables' values, and that function is called once per row with no parsing or lookup per call.
8
+ This package compiles math expressions once, each into a function of plain numbers. They use mathjs's numeric language and match mathjs's recorded answers.
9
+
10
+ Design notes live in [the specs](https://github.com/Esposter/Esposter/tree/main/openspec/specs/math-expression-compiler).
9
11
 
10
12
  ## Table of Contents
11
13
 
12
14
  - 🚀 [Getting Started](#getting-started)
13
- - 📖 [Documentation](#documentation)
15
+ - 🧩 [Key Exports](#key-exports)
14
16
  - ⚖️ [License](#license)
15
17
 
16
18
  ---
@@ -32,27 +34,16 @@ const evaluate = parseMathExpression("col0 * (1 - col1)").match(
32
34
  evaluate([10, 0.25]); // 7.5
33
35
  ```
34
36
 
37
+ ## <a name="key-exports">🧩 Key Exports</a>
38
+
35
39
  | Export | What it does |
36
40
  | :-------------------------- | :----------------------------------------------------------------------------------------------------------------------------- |
37
- | `parseMathExpression` | A formula to its tree, or a `Result` holding the first error with its position |
38
41
  | `compileMathExpression` | A tree and its variable names to a function of the variables' values, which yields `NaN` where a formula has no numeric answer |
39
42
  | `getMathExpressionNames` | The names a tree reads that it does not assign itself and that are not constants |
40
- | `MathExpressionFunctionMap` | Each function of the language by its mathjs name, as the signatures it takes: argument kinds, arities and computation |
41
43
  | `MathExpressionConstantMap` | The named constants of the language |
42
44
  | `MathExpressionError` | The error a parse returns |
43
-
44
- ## <a name="documentation">📖 Documentation</a>
45
-
46
- We highly recommend you take a look at the [documentation](https://github.com/Esposter/Esposter/tree/main/openspec/specs) to level up.
47
-
48
- ## Commands
49
-
50
- | Command | What it does |
51
- | :--------------- | :--------------------------------------- |
52
- | `pnpm build` | Builds `dist` and regenerates the barrel |
53
- | `pnpm test` | Runs the tests |
54
- | `pnpm lint:fix` | Lints the package and fixes what it can |
55
- | `pnpm typecheck` | Typechecks the package |
45
+ | `MathExpressionFunctionMap` | Each function of the language by its mathjs name, as the signatures it takes: argument kinds, arities and computation |
46
+ | `parseMathExpression` | A formula to its tree, or a `Result` holding the first error with its position |
56
47
 
57
48
  ## <a name="license">⚖️ License</a>
58
49
 
package/dist/index.d.ts CHANGED
@@ -1,4 +1,8 @@
1
1
  import { Result } from "neverthrow";
2
+ export declare enum MathExpressionBitwiseAbsorption {
3
+ BitAnd = "bitAnd",
4
+ BitOr = "bitOr"
5
+ }
2
6
  export type MathExpressionResult = null | number;
3
7
  export type MathExpressionEvaluator = (values: readonly number[], locals: MathExpressionResult[]) => MathExpressionResult;
4
8
  export interface MathExpressionCompiled {
@@ -122,6 +126,31 @@ export type MathExpressionBinaryOperator = MathExpressionBinaryFunctionOperator
122
126
  power: number;
123
127
  type: MathExpressionNodeType.Logical;
124
128
  };
129
+ export declare enum MathExpressionBinaryOperatorSymbol {
130
+ Add = "+",
131
+ And = "and",
132
+ BitwiseAnd = "&",
133
+ BitwiseOr = "|",
134
+ BitwiseXor = "^|",
135
+ Divide = "/",
136
+ ElementwiseDivide = "./",
137
+ ElementwiseMultiply = ".*",
138
+ Equal = "==",
139
+ GreaterThan = ">",
140
+ GreaterThanOrEqual = ">=",
141
+ LessThan = "<",
142
+ LessThanOrEqual = "<=",
143
+ Mod = "mod",
144
+ Modulo = "%",
145
+ Multiply = "*",
146
+ NotEqual = "!=",
147
+ Or = "or",
148
+ ShiftLeft = "<<",
149
+ ShiftRight = ">>",
150
+ Subtract = "-",
151
+ UnsignedShiftRight = ">>>",
152
+ Xor = "xor"
153
+ }
125
154
  export declare enum MathExpressionGrammarRule {
126
155
  Assignment = "Assignment",
127
156
  Binary = "Binary",
@@ -156,13 +185,11 @@ export interface MathExpressionParserState {
156
185
  }
157
186
  export type MathExpressionParse = (state: MathExpressionParserState, rule: MathExpressionGrammarRule) => MathExpressionNode;
158
187
  export type MathExpressionRuleParser = (state: MathExpressionParserState, parse: MathExpressionParse) => MathExpressionNode;
159
- export declare const MathExpressionBitwiseAbsorptionMap: Readonly<Record<string, {
160
- absorbs: number;
161
- result: number;
162
- }>>;
163
- export declare const MathExpressionNodeCompileMap: { [T in MathExpressionNodeType]: (node: Extract<MathExpressionNode, {
164
- type: T;
165
- }>, context: MathExpressionCompileContext) => MathExpressionCompiled; };
188
+ export declare enum MathExpressionRadix {
189
+ Binary = "b",
190
+ Hexadecimal = "x",
191
+ Octal = "o"
192
+ }
166
193
  export declare const checkIsPercentageExpression: (node: MathExpressionNode) => boolean;
167
194
  export declare const collectMathExpressionAssignedNames: (node: MathExpressionNode, names: Set<string>) => void;
168
195
  export declare const compileArgument: (node: MathExpressionNode, context: MathExpressionCompileContext) => MathExpressionCompiledArgument;
@@ -175,6 +202,13 @@ export declare const ADDITIVE_NAMES: readonly string[];
175
202
  export declare const getMathExpressionConstant: (name: string) => number | undefined;
176
203
  export declare const getMathExpressionOuterValue: (outer: MathExpressionOuterBinding, values: readonly number[]) => MathExpressionResult;
177
204
  export declare const getMathExpressionScalarCompute: <Key extends keyof MathExpressionScalarCompute>(name: string, key: Key) => NonNullable<MathExpressionScalarCompute[Key]>;
205
+ export declare const MathExpressionBitwiseAbsorptionMap: Readonly<Record<string, {
206
+ absorbs: number;
207
+ result: number;
208
+ }>>;
209
+ export declare const MathExpressionNodeCompileMap: { [T in MathExpressionNodeType]: (node: Extract<MathExpressionNode, {
210
+ type: T;
211
+ }>, context: MathExpressionCompileContext) => MathExpressionCompiled; };
178
212
  export declare const compileAssignment: (node: Extract<MathExpressionNode, {
179
213
  type: MathExpressionNodeType.Assignment;
180
214
  }>, context: MathExpressionCompileContext) => MathExpressionCompiled;
@@ -209,7 +243,6 @@ export declare const compilePercentage: (node: Extract<MathExpressionNode, {
209
243
  export declare const compileUnary: (node: Extract<MathExpressionNode, {
210
244
  type: MathExpressionNodeType.Unary;
211
245
  }>, context: MathExpressionCompileContext) => MathExpressionCompiled;
212
- export declare const MathExpressionFunctionMap: Record<string, MathExpressionSignature[]>;
213
246
  export declare const checkIsLarger: (left: number, right: number) => boolean;
214
247
  export declare const checkIsMillerRabinPassing: (candidate: bigint, base: bigint, oddPart: bigint, twos: number) => boolean;
215
248
  export declare const checkIsNearlyEqual: (left: number, right: number) => boolean;
@@ -241,12 +274,12 @@ export declare const computeInverseCoth: (value: number) => number;
241
274
  export declare const computeKullbackLeibler: (distribution: readonly number[], reference: readonly number[]) => null | number;
242
275
  export declare const computeLeastCommonMultiple: (left: number, right: number) => null | number;
243
276
  export declare const computeListComparison: (left: number[], right: number[]) => number;
277
+ export declare const computeLogarithm: (value: number, base?: number) => number;
244
278
  export declare const computeLogGamma: (value: number) => number;
245
279
  export declare const computeLogGammaOfPositive: (value: number) => {
246
280
  logGamma: number;
247
281
  product: number;
248
282
  };
249
- export declare const computeLogarithm: (value: number, base?: number) => number;
250
283
  export declare const computeMean: (values: readonly number[]) => number;
251
284
  export declare const computeMedian: (values: readonly number[]) => number;
252
285
  export declare const computeMedianAbsoluteDeviation: (values: readonly number[]) => number;
@@ -290,6 +323,7 @@ export declare const STIRLING_THRESHOLD = 15;
290
323
  export declare const STIRLING_TERMS: readonly number[];
291
324
  export declare const EULER_MACLAURIN_COEFFICIENTS: readonly number[];
292
325
  export declare const SUMMATION_LIMIT = 10;
326
+ export declare const MathExpressionFunctionMap: Record<string, MathExpressionSignature[]>;
293
327
  export declare const multiplyPair: (left: MathExpressionValue, right: MathExpressionValue) => MathExpressionValue | null;
294
328
  export declare const roundToDigits: (rounder: (value: number) => number, value: number, digits: number) => null | number;
295
329
  export declare const scaleList: (list: number[], scalar: number) => number[];
@@ -318,17 +352,6 @@ export declare const createUnarySignatures: (compute: MathExpressionUnaryCompute
318
352
  export declare const createVariadicSignatures: (minArity: number, compute: MathExpressionNumberCompute, computeBinary?: MathExpressionBinaryCompute) => MathExpressionSignature[];
319
353
  export declare const getMathExpressionNames: (node: MathExpressionNode) => string[];
320
354
  export declare const walkNode: (node: MathExpressionNode, bound: Set<string>, free: Set<string>) => void;
321
- export declare const MathExpressionBinaryOperatorMap: {
322
- readonly "*": MathExpressionBinaryFunctionOperator;
323
- readonly "/": MathExpressionBinaryFunctionOperator;
324
- readonly [token: string]: MathExpressionBinaryOperator;
325
- };
326
- export declare const MathExpressionOperatorMap: {
327
- [MathExpressionGrammarRule.Nullish]: Readonly<Record<string, MathExpressionLogicalOperator>>;
328
- [MathExpressionGrammarRule.Power]: Readonly<Record<string, string>>;
329
- [MathExpressionGrammarRule.Unary]: Readonly<Record<string, string>>;
330
- };
331
- export declare const MathExpressionRuleParserMap: Record<MathExpressionGrammarRule, MathExpressionRuleParser>;
332
355
  export declare const checkCanMathExpressionNest: (state: MathExpressionParserState) => boolean;
333
356
  export declare const checkIsNameToken: (state: MathExpressionParserState) => boolean;
334
357
  export declare const checkIsOperatorOperand: (node: MathExpressionNode) => boolean;
@@ -348,6 +371,17 @@ export declare const getMathExpressionArityMessage: (name: string, minArity: num
348
371
  export declare const getMathExpressionColumn: (state: MathExpressionParserState) => number;
349
372
  export declare const getMathExpressionSignatureError: (name: string, signatures: readonly MathExpressionSignature[], parameterTypes: MathExpressionParameterType[]) => string;
350
373
  export declare const getMathExpressionToken: (state: MathExpressionParserState) => void;
374
+ export declare const MathExpressionBinaryOperatorMap: {
375
+ readonly "*": MathExpressionBinaryFunctionOperator;
376
+ readonly "/": MathExpressionBinaryFunctionOperator;
377
+ readonly [token: string]: MathExpressionBinaryOperator;
378
+ };
379
+ export declare const MathExpressionOperatorMap: {
380
+ [MathExpressionGrammarRule.Nullish]: Readonly<Record<string, MathExpressionLogicalOperator>>;
381
+ [MathExpressionGrammarRule.Power]: Readonly<Record<string, string>>;
382
+ [MathExpressionGrammarRule.Unary]: Readonly<Record<string, string>>;
383
+ };
384
+ export declare const MathExpressionRuleParserMap: Record<MathExpressionGrammarRule, MathExpressionRuleParser>;
351
385
  export declare const parseArgument: (state: MathExpressionParserState, parse: MathExpressionParse) => MathExpressionNode;
352
386
  export declare const parseBinaryOperators: (state: MathExpressionParserState, parse: MathExpressionParse, minimumPower: number) => MathExpressionNode;
353
387
  export declare const parseCall: (state: MathExpressionParserState, name: string, column: number, parse: MathExpressionParse) => MathExpressionNode;
@@ -366,10 +400,6 @@ export declare const parsePercentage: MathExpressionRuleParser;
366
400
  export declare const parsePower: MathExpressionRuleParser;
367
401
  export declare const parseSymbol: MathExpressionRuleParser;
368
402
  export declare const parseUnary: MathExpressionRuleParser;
369
- export declare const MathExpressionRadixMap: Readonly<Record<string, {
370
- digit: RegExp;
371
- radix: number;
372
- }>>;
373
403
  export declare const checkIsDecimalMark: (character: string, nextCharacter: string) => boolean;
374
404
  export declare const checkIsDigitCharacter: (character: string) => boolean;
375
405
  export declare const checkIsWordCharacter: (character: string) => boolean;
@@ -385,6 +415,10 @@ export declare const WORD_START_REGEX: RegExp;
385
415
  export declare const WORD_CHARACTER_REGEX: RegExp;
386
416
  export declare const failExponent: (state: MathExpressionParserState, text: string) => void;
387
417
  export declare const getMathExpressionCharacter: (state: MathExpressionParserState, offset: number) => string;
418
+ export declare const MathExpressionRadixMap: Readonly<Record<string, {
419
+ digit: RegExp;
420
+ radix: number;
421
+ }>>;
388
422
  export declare const readMathExpressionDelimiter: (state: MathExpressionParserState) => number;
389
423
  export declare const readMathExpressionNumber: (state: MathExpressionParserState) => void;
390
424
  export declare const readMathExpressionWord: (state: MathExpressionParserState) => void;
@@ -392,7 +426,6 @@ export declare const readRadixNumber: (state: MathExpressionParserState, prefix:
392
426
  export declare const skipMathExpressionSpaces: (state: MathExpressionParserState) => void;
393
427
  export declare const takeExponent: (state: MathExpressionParserState, text: string) => string;
394
428
  export declare const takeMathExpressionMatching: (state: MathExpressionParserState, checkCharacter: (character: string) => boolean) => string;
395
- export declare const MathExpressionConstantMap: Record<string, number>;
396
429
  export declare const checkIsMatching: (signature: MathExpressionSignature, parameterTypes: MathExpressionParameterType[]) => boolean;
397
430
  export declare const checkIsMatchingKind: (parameterType: MathExpressionParameterType | undefined, argumentType: MathExpressionParameterType) => boolean;
398
431
  export declare const checkIsTruthy: (value: number) => boolean;
@@ -402,4 +435,5 @@ export declare const getMathExpressionSignatures: (name: string) => MathExpressi
402
435
  export declare const getOwnValue: <T>(record: Readonly<Record<string, T>>, key: string) => T | undefined;
403
436
  export declare const getParameterType: (signature: MathExpressionSignature, index: number) => MathExpressionParameterType | undefined;
404
437
  export declare const matchMathExpressionSignature: (signatures: readonly MathExpressionSignature[], parameterTypes: MathExpressionParameterType[]) => MathExpressionSignature | undefined;
438
+ export declare const MathExpressionConstantMap: Record<string, number>;
405
439
  export declare const toNumber: (flag: boolean) => number;
package/dist/index.js CHANGED
@@ -1,5 +1,11 @@
1
1
  import { exhaustiveGuard } from "@esposter/shared";
2
2
  import { err, ok } from "neverthrow";
3
+ // src/models/compiler/MathExpressionBitwiseAbsorption.ts
4
+ let MathExpressionBitwiseAbsorption = /* @__PURE__ */ function(MathExpressionBitwiseAbsorption) {
5
+ MathExpressionBitwiseAbsorption["BitAnd"] = "bitAnd";
6
+ MathExpressionBitwiseAbsorption["BitOr"] = "bitOr";
7
+ return MathExpressionBitwiseAbsorption;
8
+ }({});
3
9
  // src/models/function/MathExpressionFunctionName.ts
4
10
  let MathExpressionFunctionName = /* @__PURE__ */ function(MathExpressionFunctionName) {
5
11
  MathExpressionFunctionName["CTranspose"] = "ctranspose";
@@ -15,6 +21,33 @@ let MathExpressionParameterType = /* @__PURE__ */ function(MathExpressionParamet
15
21
  MathExpressionParameterType["Number"] = "number";
16
22
  return MathExpressionParameterType;
17
23
  }({});
24
+ // src/models/parser/MathExpressionBinaryOperatorSymbol.ts
25
+ let MathExpressionBinaryOperatorSymbol = /* @__PURE__ */ function(MathExpressionBinaryOperatorSymbol) {
26
+ MathExpressionBinaryOperatorSymbol["Add"] = "+";
27
+ MathExpressionBinaryOperatorSymbol["And"] = "and";
28
+ MathExpressionBinaryOperatorSymbol["BitwiseAnd"] = "&";
29
+ MathExpressionBinaryOperatorSymbol["BitwiseOr"] = "|";
30
+ MathExpressionBinaryOperatorSymbol["BitwiseXor"] = "^|";
31
+ MathExpressionBinaryOperatorSymbol["Divide"] = "/";
32
+ MathExpressionBinaryOperatorSymbol["ElementwiseDivide"] = "./";
33
+ MathExpressionBinaryOperatorSymbol["ElementwiseMultiply"] = ".*";
34
+ MathExpressionBinaryOperatorSymbol["Equal"] = "==";
35
+ MathExpressionBinaryOperatorSymbol["GreaterThan"] = ">";
36
+ MathExpressionBinaryOperatorSymbol["GreaterThanOrEqual"] = ">=";
37
+ MathExpressionBinaryOperatorSymbol["LessThan"] = "<";
38
+ MathExpressionBinaryOperatorSymbol["LessThanOrEqual"] = "<=";
39
+ MathExpressionBinaryOperatorSymbol["Mod"] = "mod";
40
+ MathExpressionBinaryOperatorSymbol["Modulo"] = "%";
41
+ MathExpressionBinaryOperatorSymbol["Multiply"] = "*";
42
+ MathExpressionBinaryOperatorSymbol["NotEqual"] = "!=";
43
+ MathExpressionBinaryOperatorSymbol["Or"] = "or";
44
+ MathExpressionBinaryOperatorSymbol["ShiftLeft"] = "<<";
45
+ MathExpressionBinaryOperatorSymbol["ShiftRight"] = ">>";
46
+ MathExpressionBinaryOperatorSymbol["Subtract"] = "-";
47
+ MathExpressionBinaryOperatorSymbol["UnsignedShiftRight"] = ">>>";
48
+ MathExpressionBinaryOperatorSymbol["Xor"] = "xor";
49
+ return MathExpressionBinaryOperatorSymbol;
50
+ }({});
18
51
  // src/models/parser/MathExpressionGrammarRule.ts
19
52
  let MathExpressionGrammarRule = /* @__PURE__ */ function(MathExpressionGrammarRule) {
20
53
  MathExpressionGrammarRule["Assignment"] = "Assignment";
@@ -39,6 +72,13 @@ let MathExpressionTokenType = /* @__PURE__ */ function(MathExpressionTokenType)
39
72
  MathExpressionTokenType["Unknown"] = "unknown";
40
73
  return MathExpressionTokenType;
41
74
  }({});
75
+ // src/models/parser/token/MathExpressionRadix.ts
76
+ let MathExpressionRadix = /* @__PURE__ */ function(MathExpressionRadix) {
77
+ MathExpressionRadix["Binary"] = "b";
78
+ MathExpressionRadix["Hexadecimal"] = "x";
79
+ MathExpressionRadix["Octal"] = "o";
80
+ return MathExpressionRadix;
81
+ }({});
42
82
  // src/models/shared/MathExpressionError.ts
43
83
  var MathExpressionError = class extends Error {
44
84
  constructor(message) {
@@ -69,17 +109,65 @@ let MathExpressionNodeType = /* @__PURE__ */ function(MathExpressionNodeType) {
69
109
  MathExpressionNodeType["Unary"] = "unary";
70
110
  return MathExpressionNodeType;
71
111
  }({});
72
- // src/services/compiler/MathExpressionBitwiseAbsorptionMap.ts
73
- const MathExpressionBitwiseAbsorptionMap = {
74
- bitAnd: {
75
- absorbs: 0,
76
- result: 0
77
- },
78
- bitOr: {
79
- absorbs: -1,
80
- result: -1
112
+ // src/services/compiler/constants.ts
113
+ const NO_VALUES = [];
114
+ const NO_LOCALS = [];
115
+ const ADDITIVE_NAMES = ["add", "subtract"];
116
+ // src/services/compiler/checkIsPercentageExpression.ts
117
+ const checkIsPercentageExpression = (node) => {
118
+ if (node.type === "percentage") return true;
119
+ if (node.type !== "binary") return false;
120
+ if (!ADDITIVE_NAMES.includes(node.name)) return false;
121
+ return checkIsPercentageExpression(node.left) && checkIsPercentageExpression(node.right);
122
+ };
123
+ // src/services/shared/getMathExpressionChildren.ts
124
+ const getMathExpressionChildren = (node) => {
125
+ switch (node.type) {
126
+ case "assignment": return [node.value];
127
+ case "binary":
128
+ case "logical": return [node.left, node.right];
129
+ case "call": return node.arguments;
130
+ case "comparison": return node.operands;
131
+ case "conditional": return [
132
+ node.condition,
133
+ node.whenTrue,
134
+ node.whenFalse
135
+ ];
136
+ case "group":
137
+ case "percentage":
138
+ case "unary": return [node.operand];
139
+ case "list": return node.elements;
140
+ case "name":
141
+ case "number": return [];
142
+ default: return exhaustiveGuard(node);
81
143
  }
82
144
  };
145
+ // src/services/compiler/collectMathExpressionAssignedNames.ts
146
+ const collectMathExpressionAssignedNames = (node, names) => {
147
+ if (node.type === "assignment") names.add(node.name);
148
+ for (const child of getMathExpressionChildren(node)) collectMathExpressionAssignedNames(child, names);
149
+ };
150
+ // src/services/compiler/compileList.ts
151
+ const compileList = (elements, context) => {
152
+ const compiledElements = elements.map((element) => context.compile(element));
153
+ return {
154
+ evaluate: (values, locals) => {
155
+ const numbers = [];
156
+ for (const element of compiledElements) {
157
+ const elementValue = element.evaluate(values, locals);
158
+ if (elementValue === null) return null;
159
+ numbers.push(elementValue);
160
+ }
161
+ return numbers;
162
+ },
163
+ isConstant: compiledElements.every((element) => element.isConstant)
164
+ };
165
+ };
166
+ // src/services/compiler/compileArgument.ts
167
+ const compileArgument = (node, context) => {
168
+ if (node.type === "list") return compileList(node.elements, context);
169
+ return context.compile(node);
170
+ };
83
171
  // src/services/compiler/node/compileAssignment.ts
84
172
  const compileAssignment = (node, context) => {
85
173
  const slot = context.assignedSlots.get(node.name) ?? 0;
@@ -93,17 +181,6 @@ const compileAssignment = (node, context) => {
93
181
  isConstant: false
94
182
  };
95
183
  };
96
- // src/services/compiler/constants.ts
97
- const NO_VALUES = [];
98
- const NO_LOCALS = [];
99
- const ADDITIVE_NAMES = ["add", "subtract"];
100
- // src/services/compiler/checkIsPercentageExpression.ts
101
- const checkIsPercentageExpression = (node) => {
102
- if (node.type === "percentage") return true;
103
- if (node.type !== "binary") return false;
104
- if (!ADDITIVE_NAMES.includes(node.name)) return false;
105
- return checkIsPercentageExpression(node.left) && checkIsPercentageExpression(node.right);
106
- };
107
184
  // src/services/function/constants.ts
108
185
  const MATH_EXPRESSION_RELATIVE_TOLERANCE = 1e-12;
109
186
  const MATH_EXPRESSION_ABSOLUTE_TOLERANCE = 1e-15;
@@ -961,6 +1038,17 @@ const getMathExpressionScalarCompute = (name, key) => {
961
1038
  if (scalarCompute !== void 0) return scalarCompute;
962
1039
  return (...values) => signature.compute(values);
963
1040
  };
1041
+ // src/services/compiler/MathExpressionBitwiseAbsorptionMap.ts
1042
+ const MathExpressionBitwiseAbsorptionMap = {
1043
+ ["bitAnd"]: {
1044
+ absorbs: 0,
1045
+ result: 0
1046
+ },
1047
+ ["bitOr"]: {
1048
+ absorbs: -1,
1049
+ result: -1
1050
+ }
1051
+ };
964
1052
  // src/services/compiler/node/compileBinary.ts
965
1053
  const compileBinary = (node, context) => {
966
1054
  const { left, name, right } = node;
@@ -995,27 +1083,6 @@ const compileBinary = (node, context) => {
995
1083
  isConstant: compiledLeft.isConstant && compiledRight.isConstant
996
1084
  };
997
1085
  };
998
- // src/services/compiler/compileList.ts
999
- const compileList = (elements, context) => {
1000
- const compiledElements = elements.map((element) => context.compile(element));
1001
- return {
1002
- evaluate: (values, locals) => {
1003
- const numbers = [];
1004
- for (const element of compiledElements) {
1005
- const elementValue = element.evaluate(values, locals);
1006
- if (elementValue === null) return null;
1007
- numbers.push(elementValue);
1008
- }
1009
- return numbers;
1010
- },
1011
- isConstant: compiledElements.every((element) => element.isConstant)
1012
- };
1013
- };
1014
- // src/services/compiler/compileArgument.ts
1015
- const compileArgument = (node, context) => {
1016
- if (node.type === "list") return compileList(node.elements, context);
1017
- return context.compile(node);
1018
- };
1019
1086
  // src/services/shared/getMathExpressionParameterType.ts
1020
1087
  const getMathExpressionParameterType = (node) => node.type === "list" ? "list" : "number";
1021
1088
  // src/services/shared/checkIsMatchingKind.ts
@@ -1228,33 +1295,6 @@ const MathExpressionNodeCompileMap = {
1228
1295
  ["percentage"]: compilePercentage,
1229
1296
  ["unary"]: compileUnary
1230
1297
  };
1231
- // src/services/shared/getMathExpressionChildren.ts
1232
- const getMathExpressionChildren = (node) => {
1233
- switch (node.type) {
1234
- case "assignment": return [node.value];
1235
- case "binary":
1236
- case "logical": return [node.left, node.right];
1237
- case "call": return node.arguments;
1238
- case "comparison": return node.operands;
1239
- case "conditional": return [
1240
- node.condition,
1241
- node.whenTrue,
1242
- node.whenFalse
1243
- ];
1244
- case "group":
1245
- case "percentage":
1246
- case "unary": return [node.operand];
1247
- case "list": return node.elements;
1248
- case "name":
1249
- case "number": return [];
1250
- default: return exhaustiveGuard(node);
1251
- }
1252
- };
1253
- // src/services/compiler/collectMathExpressionAssignedNames.ts
1254
- const collectMathExpressionAssignedNames = (node, names) => {
1255
- if (node.type === "assignment") names.add(node.name);
1256
- for (const child of getMathExpressionChildren(node)) collectMathExpressionAssignedNames(child, names);
1257
- };
1258
1298
  // src/services/compiler/compileMathExpressionNode.ts
1259
1299
  const compileMathExpressionNode = (node, context) => {
1260
1300
  const compileOfType = MathExpressionNodeCompileMap[node.type];
@@ -1347,138 +1387,6 @@ const getMathExpressionNames = (node) => {
1347
1387
  walkNode(node, bound, free);
1348
1388
  return [...free].filter((name) => getMathExpressionConstant(name) === void 0);
1349
1389
  };
1350
- // src/services/parser/MathExpressionBinaryOperatorMap.ts
1351
- const MathExpressionBinaryOperatorMap = {
1352
- "!=": {
1353
- name: "unequal",
1354
- power: 7,
1355
- type: "comparison"
1356
- },
1357
- "%": {
1358
- name: "mod",
1359
- power: 10,
1360
- type: "binary"
1361
- },
1362
- "&": {
1363
- name: "bitAnd",
1364
- power: 6,
1365
- type: "binary"
1366
- },
1367
- "*": {
1368
- name: "multiply",
1369
- power: 10,
1370
- type: "binary"
1371
- },
1372
- "+": {
1373
- name: "add",
1374
- power: 9,
1375
- type: "binary"
1376
- },
1377
- "-": {
1378
- name: "subtract",
1379
- power: 9,
1380
- type: "binary"
1381
- },
1382
- ".*": {
1383
- name: "dotMultiply",
1384
- power: 10,
1385
- type: "binary"
1386
- },
1387
- "./": {
1388
- name: "dotDivide",
1389
- power: 10,
1390
- type: "binary"
1391
- },
1392
- "/": {
1393
- name: "divide",
1394
- power: 10,
1395
- type: "binary"
1396
- },
1397
- "<": {
1398
- name: "smaller",
1399
- power: 7,
1400
- type: "comparison"
1401
- },
1402
- "<<": {
1403
- name: "leftShift",
1404
- power: 8,
1405
- type: "binary"
1406
- },
1407
- "<=": {
1408
- name: "smallerEq",
1409
- power: 7,
1410
- type: "comparison"
1411
- },
1412
- "==": {
1413
- name: "equal",
1414
- power: 7,
1415
- type: "comparison"
1416
- },
1417
- ">": {
1418
- name: "larger",
1419
- power: 7,
1420
- type: "comparison"
1421
- },
1422
- ">=": {
1423
- name: "largerEq",
1424
- power: 7,
1425
- type: "comparison"
1426
- },
1427
- ">>": {
1428
- name: "rightArithShift",
1429
- power: 8,
1430
- type: "binary"
1431
- },
1432
- ">>>": {
1433
- name: "rightLogShift",
1434
- power: 8,
1435
- type: "binary"
1436
- },
1437
- "^|": {
1438
- name: "bitXor",
1439
- power: 5,
1440
- type: "binary"
1441
- },
1442
- and: {
1443
- operator: "and",
1444
- power: 3,
1445
- type: "logical"
1446
- },
1447
- mod: {
1448
- name: "mod",
1449
- power: 10,
1450
- type: "binary"
1451
- },
1452
- or: {
1453
- operator: "or",
1454
- power: 1,
1455
- type: "logical"
1456
- },
1457
- xor: {
1458
- name: "xor",
1459
- power: 2,
1460
- type: "binary"
1461
- },
1462
- "|": {
1463
- name: "bitOr",
1464
- power: 4,
1465
- type: "binary"
1466
- }
1467
- };
1468
- // src/services/parser/MathExpressionOperatorMap.ts
1469
- const MathExpressionOperatorMap = {
1470
- ["Nullish"]: { "??": "nullish" },
1471
- ["Power"]: {
1472
- ".^": "dotPow",
1473
- "^": "pow"
1474
- },
1475
- ["Unary"]: {
1476
- "+": "unaryPlus",
1477
- "-": "unaryMinus",
1478
- not: "not",
1479
- "~": "bitNot"
1480
- }
1481
- };
1482
1390
  // src/services/parser/constants.ts
1483
1391
  const MAX_MATH_EXPRESSION_DEPTH = 64;
1484
1392
  const PLACEHOLDER = {
@@ -1493,70 +1401,166 @@ const failMathExpressionAt = (state, message, column) => {
1493
1401
  // src/services/parser/getMathExpressionColumn.ts
1494
1402
  const getMathExpressionColumn = (state) => state.index - state.token.length + 1;
1495
1403
  // src/services/parser/failMathExpression.ts
1496
- const failMathExpression = (state, message) => failMathExpressionAt(state, message, getMathExpressionColumn(state));
1404
+ const failMathExpression = (state, message) => {
1405
+ failMathExpressionAt(state, message, getMathExpressionColumn(state));
1406
+ };
1497
1407
  // src/services/parser/checkCanMathExpressionNest.ts
1498
1408
  const checkCanMathExpressionNest = (state) => {
1499
1409
  if (state.depth < 64) return true;
1500
1410
  failMathExpression(state, `Formula nests deeper than 64 levels`);
1501
1411
  return false;
1502
1412
  };
1503
- // src/services/parser/checkIsToken.ts
1504
- const checkIsToken = (state, token) => state.token === token;
1505
- // src/services/parser/token/checkIsDigitCharacter.ts
1506
- const checkIsDigitCharacter = (character) => character >= "0" && character <= "9";
1507
- // src/services/parser/token/constants.ts
1508
- const DELIMITERS_OF_THREE = /* @__PURE__ */ new Set([">>>"]);
1509
- const DELIMITERS_OF_TWO = /* @__PURE__ */ new Set([
1510
- "!=",
1511
- ".*",
1512
- "./",
1513
- ".^",
1514
- "<<",
1515
- "<=",
1516
- "==",
1517
- ">=",
1518
- ">>",
1519
- "??",
1520
- "^|"
1521
- ]);
1522
- const DELIMITERS_OF_ONE = /* @__PURE__ */ new Set([
1523
- "!",
1524
- "%",
1525
- "&",
1526
- "'",
1413
+ // src/services/parser/checkIsNameToken.ts
1414
+ const checkIsNameToken = (state) => state.tokenType === "symbol" || state.tokenType === "delimiter" && getMathExpressionSignatures(state.token) !== void 0;
1415
+ // src/services/parser/checkIsOperatorOperand.ts
1416
+ const checkIsOperatorOperand = (node) => {
1417
+ if (node.type === "unary") return node.name !== "factorial";
1418
+ return node.type === "binary" || node.type === "comparison" || node.type === "logical";
1419
+ };
1420
+ // src/services/parser/checkIsSignedNumber.ts
1421
+ const checkIsSignedNumber = (node) => {
1422
+ if (node.type === "number") return true;
1423
+ return node.type === "unary" && (node.name === "unaryMinus" || node.name === "unaryPlus") && node.operand.type === "number";
1424
+ };
1425
+ // src/services/parser/checkIsToken.ts
1426
+ const checkIsToken = (state, token) => state.token === token;
1427
+ // src/services/parser/MathExpressionOperatorMap.ts
1428
+ const MathExpressionOperatorMap = {
1429
+ ["Nullish"]: { "??": "nullish" },
1430
+ ["Power"]: {
1431
+ ".^": "dotPow",
1432
+ "^": "pow"
1433
+ },
1434
+ ["Unary"]: {
1435
+ "+": "unaryPlus",
1436
+ "-": "unaryMinus",
1437
+ not: "not",
1438
+ "~": "bitNot"
1439
+ }
1440
+ };
1441
+ // src/services/parser/checkIsUnaryStart.ts
1442
+ const checkIsUnaryStart = (state) => state.tokenType === "number" || checkIsNameToken(state) || checkIsToken(state, "(") || getOwnValue(MathExpressionOperatorMap["Unary"], state.token) !== void 0;
1443
+ // src/services/parser/token/MathExpressionRadixMap.ts
1444
+ const MathExpressionRadixMap = {
1445
+ ["b"]: {
1446
+ digit: /^[01]$/u,
1447
+ radix: 2
1448
+ },
1449
+ ["x"]: {
1450
+ digit: /^[0-9a-fA-F]$/u,
1451
+ radix: 16
1452
+ },
1453
+ ["o"]: {
1454
+ digit: /^[0-7]$/u,
1455
+ radix: 8
1456
+ }
1457
+ };
1458
+ // src/services/parser/computeNumberLiteral.ts
1459
+ const computeNumberLiteral = (token) => {
1460
+ const radixEntry = MathExpressionRadixMap[token.charAt(1)];
1461
+ if (!token.startsWith("0") || radixEntry === void 0) return Number(token);
1462
+ const { radix } = radixEntry;
1463
+ const [digits = "", wordSize] = token.slice(2).split("i");
1464
+ const [integerDigits = "", fractionDigits = ""] = digits.split(".");
1465
+ let value = 0;
1466
+ for (const digit of integerDigits) value = value * radix + Number.parseInt(digit, radix);
1467
+ let scale = 1 / radix;
1468
+ for (const digit of fractionDigits) {
1469
+ value += Number.parseInt(digit, radix) * scale;
1470
+ scale /= radix;
1471
+ }
1472
+ if (wordSize === void 0) return value;
1473
+ const bits = Number(wordSize);
1474
+ if (value > 2 ** bits - 1) return null;
1475
+ return value >= 2 ** (bits - 1) ? value - 2 ** bits : value;
1476
+ };
1477
+ // src/services/parser/createBinaryNode.ts
1478
+ const createBinaryNode = (left, name, right) => ({
1479
+ left,
1480
+ name,
1481
+ right,
1482
+ type: "binary"
1483
+ });
1484
+ // src/services/parser/createLogicalNode.ts
1485
+ const createLogicalNode = (left, operator, right) => ({
1486
+ left,
1487
+ operator,
1488
+ right,
1489
+ type: "logical"
1490
+ });
1491
+ // src/services/parser/createBinaryOperation.ts
1492
+ const createBinaryOperation = (left, operator, right) => {
1493
+ if (operator.type === "logical") return createLogicalNode(left, operator.operator, right);
1494
+ if (operator.type === "binary") return createBinaryNode(left, operator.name, right);
1495
+ if (left.type === "comparison") {
1496
+ left.names.push(operator.name);
1497
+ left.operands.push(right);
1498
+ return left;
1499
+ }
1500
+ return {
1501
+ names: [operator.name],
1502
+ operands: [left, right],
1503
+ type: "comparison"
1504
+ };
1505
+ };
1506
+ // src/services/parser/getArgumentCountText.ts
1507
+ const getArgumentCountText = (count) => `${count} ${count === 1 ? "argument" : "arguments"}`;
1508
+ // src/services/parser/getMathExpressionArityMessage.ts
1509
+ const getMathExpressionArityMessage = (name, minArity, maxArity) => {
1510
+ if (maxArity === Number.POSITIVE_INFINITY) return `"${name}" takes at least ${getArgumentCountText(minArity)}`;
1511
+ if (minArity === maxArity) return `"${name}" takes ${getArgumentCountText(minArity)}`;
1512
+ return `"${name}" takes ${minArity} or ${maxArity} arguments`;
1513
+ };
1514
+ // src/services/parser/getMathExpressionSignatureError.ts
1515
+ const getMathExpressionSignatureError = (name, signatures, parameterTypes) => {
1516
+ const count = parameterTypes.length;
1517
+ if (signatures.filter((signature) => count >= signature.minArity && count <= signature.maxArity).length === 0) return getMathExpressionArityMessage(name, Math.min(...signatures.map((signature) => signature.minArity)), Math.max(...signatures.map((signature) => signature.maxArity)));
1518
+ if (parameterTypes.includes("list")) return `"${name}" does not take a list argument`;
1519
+ return `"${name}" takes a list argument`;
1520
+ };
1521
+ // src/services/parser/token/checkIsDigitCharacter.ts
1522
+ const checkIsDigitCharacter = (character) => character >= "0" && character <= "9";
1523
+ // src/services/parser/token/constants.ts
1524
+ const SYMBOLIC_BINARY_SYMBOLS = Object.values(MathExpressionBinaryOperatorSymbol).filter((symbol) => !/\p{L}/u.test(symbol));
1525
+ const SYMBOLIC_BINARY_SYMBOLS_OF_THREE = SYMBOLIC_BINARY_SYMBOLS.filter((symbol) => symbol.length === 3);
1526
+ const SYMBOLIC_BINARY_SYMBOLS_OF_TWO = SYMBOLIC_BINARY_SYMBOLS.filter((symbol) => symbol.length === 2);
1527
+ const SYMBOLIC_BINARY_SYMBOLS_OF_ONE = SYMBOLIC_BINARY_SYMBOLS.filter((symbol) => symbol.length === 1);
1528
+ const DELIMITERS_OF_THREE = new Set(SYMBOLIC_BINARY_SYMBOLS_OF_THREE);
1529
+ const DELIMITERS_OF_TWO = /* @__PURE__ */ new Set([
1530
+ ...SYMBOLIC_BINARY_SYMBOLS_OF_TWO,
1531
+ ".^",
1532
+ "??"
1533
+ ]);
1534
+ const DELIMITERS_OF_ONE = /* @__PURE__ */ new Set([
1535
+ ...SYMBOLIC_BINARY_SYMBOLS_OF_ONE,
1536
+ "!",
1537
+ "'",
1527
1538
  "(",
1528
1539
  ")",
1529
- "*",
1530
- "+",
1531
1540
  ",",
1532
- "-",
1533
- "/",
1534
1541
  ":",
1535
- "<",
1536
1542
  "=",
1537
- ">",
1538
1543
  "?",
1539
1544
  "[",
1540
1545
  "]",
1541
1546
  "^",
1542
- "|",
1543
1547
  "~"
1544
1548
  ]);
1545
1549
  const FIRST_CHARACTERS_OF_THREE = new Set(Array.from(DELIMITERS_OF_THREE, (delimiter) => delimiter.charAt(0)));
1546
1550
  const FIRST_CHARACTERS_OF_TWO = new Set(Array.from(DELIMITERS_OF_TWO, (delimiter) => delimiter.charAt(0)));
1547
1551
  const NAMED_DELIMITERS = /* @__PURE__ */ new Set([
1548
- "and",
1549
1552
  "in",
1553
+ "and",
1550
1554
  "mod",
1551
- "not",
1552
1555
  "or",
1553
- "to",
1554
- "xor"
1556
+ "xor",
1557
+ "not",
1558
+ "to"
1555
1559
  ]);
1556
1560
  const DECIMAL_MARK_OPERATOR_FOLLOWERS = /* @__PURE__ */ new Set([
1557
- "*",
1561
+ "^",
1558
1562
  "/",
1559
- "^"
1563
+ "*"
1560
1564
  ]);
1561
1565
  const WORD_START_REGEX = /^[\p{L}_$]$/u;
1562
1566
  const WORD_CHARACTER_REGEX = /^[\p{L}\p{Nd}_$]$/u;
@@ -1582,21 +1586,6 @@ const readMathExpressionDelimiter = (state) => {
1582
1586
  if ([")", "]"].includes(state.token)) state.nestingLevel--;
1583
1587
  return length;
1584
1588
  };
1585
- // src/services/parser/token/MathExpressionRadixMap.ts
1586
- const MathExpressionRadixMap = {
1587
- b: {
1588
- digit: /^[01]$/u,
1589
- radix: 2
1590
- },
1591
- o: {
1592
- digit: /^[0-7]$/u,
1593
- radix: 8
1594
- },
1595
- x: {
1596
- digit: /^[0-9a-fA-F]$/u,
1597
- radix: 16
1598
- }
1599
- };
1600
1589
  // src/services/parser/token/takeMathExpressionMatching.ts
1601
1590
  const takeMathExpressionMatching = (state, checkCharacter) => {
1602
1591
  const start = state.index;
@@ -1715,6 +1704,124 @@ const getMathExpressionToken = (state) => {
1715
1704
  state.tokenType = "unknown";
1716
1705
  }
1717
1706
  };
1707
+ // src/services/parser/MathExpressionBinaryOperatorMap.ts
1708
+ const MathExpressionBinaryOperatorMap = {
1709
+ ["+"]: {
1710
+ name: "add",
1711
+ power: 9,
1712
+ type: "binary"
1713
+ },
1714
+ ["and"]: {
1715
+ operator: "and",
1716
+ power: 3,
1717
+ type: "logical"
1718
+ },
1719
+ ["&"]: {
1720
+ name: "bitAnd",
1721
+ power: 6,
1722
+ type: "binary"
1723
+ },
1724
+ ["|"]: {
1725
+ name: "bitOr",
1726
+ power: 4,
1727
+ type: "binary"
1728
+ },
1729
+ ["^|"]: {
1730
+ name: "bitXor",
1731
+ power: 5,
1732
+ type: "binary"
1733
+ },
1734
+ ["/"]: {
1735
+ name: "divide",
1736
+ power: 10,
1737
+ type: "binary"
1738
+ },
1739
+ ["./"]: {
1740
+ name: "dotDivide",
1741
+ power: 10,
1742
+ type: "binary"
1743
+ },
1744
+ [".*"]: {
1745
+ name: "dotMultiply",
1746
+ power: 10,
1747
+ type: "binary"
1748
+ },
1749
+ ["=="]: {
1750
+ name: "equal",
1751
+ power: 7,
1752
+ type: "comparison"
1753
+ },
1754
+ [">"]: {
1755
+ name: "larger",
1756
+ power: 7,
1757
+ type: "comparison"
1758
+ },
1759
+ [">="]: {
1760
+ name: "largerEq",
1761
+ power: 7,
1762
+ type: "comparison"
1763
+ },
1764
+ ["<"]: {
1765
+ name: "smaller",
1766
+ power: 7,
1767
+ type: "comparison"
1768
+ },
1769
+ ["<="]: {
1770
+ name: "smallerEq",
1771
+ power: 7,
1772
+ type: "comparison"
1773
+ },
1774
+ ["mod"]: {
1775
+ name: "mod",
1776
+ power: 10,
1777
+ type: "binary"
1778
+ },
1779
+ ["%"]: {
1780
+ name: "mod",
1781
+ power: 10,
1782
+ type: "binary"
1783
+ },
1784
+ ["*"]: {
1785
+ name: "multiply",
1786
+ power: 10,
1787
+ type: "binary"
1788
+ },
1789
+ ["!="]: {
1790
+ name: "unequal",
1791
+ power: 7,
1792
+ type: "comparison"
1793
+ },
1794
+ ["or"]: {
1795
+ operator: "or",
1796
+ power: 1,
1797
+ type: "logical"
1798
+ },
1799
+ ["<<"]: {
1800
+ name: "leftShift",
1801
+ power: 8,
1802
+ type: "binary"
1803
+ },
1804
+ [">>"]: {
1805
+ name: "rightArithShift",
1806
+ power: 8,
1807
+ type: "binary"
1808
+ },
1809
+ ["-"]: {
1810
+ name: "subtract",
1811
+ power: 9,
1812
+ type: "binary"
1813
+ },
1814
+ [">>>"]: {
1815
+ name: "rightLogShift",
1816
+ power: 8,
1817
+ type: "binary"
1818
+ },
1819
+ ["xor"]: {
1820
+ name: "xor",
1821
+ power: 2,
1822
+ type: "binary"
1823
+ }
1824
+ };
1718
1825
  // src/services/parser/rule/parseAssignment.ts
1719
1826
  const parseAssignment = (state, parse) => {
1720
1827
  if (!checkCanMathExpressionNest(state)) return PLACEHOLDER;
@@ -1733,35 +1840,6 @@ const parseAssignment = (state, parse) => {
1733
1840
  state.depth--;
1734
1841
  return node;
1735
1842
  };
1736
- // src/services/parser/createBinaryNode.ts
1737
- const createBinaryNode = (left, name, right) => ({
1738
- left,
1739
- name,
1740
- right,
1741
- type: "binary"
1742
- });
1743
- // src/services/parser/createLogicalNode.ts
1744
- const createLogicalNode = (left, operator, right) => ({
1745
- left,
1746
- operator,
1747
- right,
1748
- type: "logical"
1749
- });
1750
- // src/services/parser/createBinaryOperation.ts
1751
- const createBinaryOperation = (left, operator, right) => {
1752
- if (operator.type === "logical") return createLogicalNode(left, operator.operator, right);
1753
- if (operator.type === "binary") return createBinaryNode(left, operator.name, right);
1754
- if (left.type === "comparison") {
1755
- left.names.push(operator.name);
1756
- left.operands.push(right);
1757
- return left;
1758
- }
1759
- return {
1760
- names: [operator.name],
1761
- operands: [left, right],
1762
- type: "comparison"
1763
- };
1764
- };
1765
1843
  // src/services/parser/parseBinaryOperators.ts
1766
1844
  const parseBinaryOperators = (state, parse, minimumPower) => {
1767
1845
  let node = parse(state, "ImplicitProduct");
@@ -1789,18 +1867,16 @@ const parseConditional = (state, parse) => {
1789
1867
  if (state.error === null && !checkIsToken(state, ":")) failMathExpression(state, "False part of conditional expression expected");
1790
1868
  if (state.error !== null) return PLACEHOLDER;
1791
1869
  getMathExpressionToken(state);
1870
+ state.depth++;
1871
+ const whenFalse = parse(state, "Conditional");
1872
+ state.depth--;
1792
1873
  return {
1793
1874
  condition,
1794
1875
  type: "conditional",
1795
- whenFalse: parse(state, "Conditional"),
1876
+ whenFalse,
1796
1877
  whenTrue
1797
1878
  };
1798
1879
  };
1799
- // src/services/parser/checkIsSignedNumber.ts
1800
- const checkIsSignedNumber = (node) => {
1801
- if (node.type === "number") return true;
1802
- return node.type === "unary" && (node.name === "unaryMinus" || node.name === "unaryPlus") && node.operand.type === "number";
1803
- };
1804
1880
  // src/services/parser/rule/parseDivisionBeforeProduct.ts
1805
1881
  const parseDivisionBeforeProduct = (state, parse) => {
1806
1882
  const dividend = parse(state, "Percentage");
@@ -1817,11 +1893,6 @@ const parseDivisionBeforeProduct = (state, parse) => {
1817
1893
  Object.assign(state, snapshot);
1818
1894
  return dividend;
1819
1895
  };
1820
- // src/services/parser/checkIsOperatorOperand.ts
1821
- const checkIsOperatorOperand = (node) => {
1822
- if (node.type === "unary") return node.name !== "factorial";
1823
- return node.type === "binary" || node.type === "comparison" || node.type === "logical";
1824
- };
1825
1896
  // src/services/parser/rule/parseImplicitProduct.ts
1826
1897
  const parseImplicitProduct = (state, parse) => {
1827
1898
  let node = parse(state, "DivisionBeforeProduct");
@@ -1860,10 +1931,6 @@ const parseNullish = (state, parse) => {
1860
1931
  }
1861
1932
  return node;
1862
1933
  };
1863
- // src/services/parser/checkIsNameToken.ts
1864
- const checkIsNameToken = (state) => state.tokenType === "symbol" || state.tokenType === "delimiter" && getMathExpressionSignatures(state.token) !== void 0;
1865
- // src/services/parser/checkIsUnaryStart.ts
1866
- const checkIsUnaryStart = (state) => state.tokenType === "number" || checkIsNameToken(state) || checkIsToken(state, "(") || getOwnValue(MathExpressionOperatorMap["Unary"], state.token) !== void 0;
1867
1934
  // src/services/parser/rule/parsePercentage.ts
1868
1935
  const parsePercentage = (state, parse) => {
1869
1936
  const node = parse(state, "Unary");
@@ -1884,44 +1951,13 @@ const parsePower = (state, parse) => {
1884
1951
  const base = parse(state, "Nullish");
1885
1952
  const name = getOwnValue(MathExpressionOperatorMap["Power"], state.token);
1886
1953
  if (state.error !== null || name === void 0) return base;
1954
+ if (!checkCanMathExpressionNest(state)) return PLACEHOLDER;
1887
1955
  getMathExpressionToken(state);
1956
+ state.depth++;
1888
1957
  const exponent = parse(state, "Unary");
1958
+ state.depth--;
1889
1959
  return createBinaryNode(base, name, exponent);
1890
1960
  };
1891
- // src/services/parser/computeNumberLiteral.ts
1892
- const computeNumberLiteral = (token) => {
1893
- const radixEntry = MathExpressionRadixMap[token.charAt(1)];
1894
- if (!token.startsWith("0") || radixEntry === void 0) return Number(token);
1895
- const { radix } = radixEntry;
1896
- const [digits = "", wordSize] = token.slice(2).split("i");
1897
- const [integerDigits = "", fractionDigits = ""] = digits.split(".");
1898
- let value = 0;
1899
- for (const digit of integerDigits) value = value * radix + Number.parseInt(digit, radix);
1900
- let scale = 1 / radix;
1901
- for (const digit of fractionDigits) {
1902
- value += Number.parseInt(digit, radix) * scale;
1903
- scale /= radix;
1904
- }
1905
- if (wordSize === void 0) return value;
1906
- const bits = Number(wordSize);
1907
- if (value > 2 ** bits - 1) return null;
1908
- return value >= 2 ** (bits - 1) ? value - 2 ** bits : value;
1909
- };
1910
- // src/services/parser/getArgumentCountText.ts
1911
- const getArgumentCountText = (count) => `${count} ${count === 1 ? "argument" : "arguments"}`;
1912
- // src/services/parser/getMathExpressionArityMessage.ts
1913
- const getMathExpressionArityMessage = (name, minArity, maxArity) => {
1914
- if (maxArity === Number.POSITIVE_INFINITY) return `"${name}" takes at least ${getArgumentCountText(minArity)}`;
1915
- if (minArity === maxArity) return `"${name}" takes ${getArgumentCountText(minArity)}`;
1916
- return `"${name}" takes ${minArity} or ${maxArity} arguments`;
1917
- };
1918
- // src/services/parser/getMathExpressionSignatureError.ts
1919
- const getMathExpressionSignatureError = (name, signatures, parameterTypes) => {
1920
- const count = parameterTypes.length;
1921
- if (signatures.filter((signature) => count >= signature.minArity && count <= signature.maxArity).length === 0) return getMathExpressionArityMessage(name, Math.min(...signatures.map((signature) => signature.minArity)), Math.max(...signatures.map((signature) => signature.maxArity)));
1922
- if (parameterTypes.includes("list")) return `"${name}" does not take a list argument`;
1923
- return `"${name}" takes a list argument`;
1924
- };
1925
1961
  // src/services/parser/parseSequence.ts
1926
1962
  const parseSequence = (state, closing, parseItem) => {
1927
1963
  const nodes = [];
@@ -2056,4 +2092,4 @@ const parseMathExpression = (formula) => {
2056
2092
  if (state.error === null && !checkIsToken(state, "")) failMathExpression(state, state.tokenType === "delimiter" ? `Unexpected operator ${state.token}` : `Unexpected part "${state.token}"`);
2057
2093
  return state.error === null ? ok(node) : err(state.error);
2058
2094
  };
2059
- export { ADDITIVE_NAMES, BERNOULLI_CLOSED_FORM_INDEX, DECIMAL_MARK_OPERATOR_FOLLOWERS, DELIMITERS_OF_ONE, DELIMITERS_OF_THREE, DELIMITERS_OF_TWO, EULER_MACLAURIN_COEFFICIENTS, FIRST_CHARACTERS_OF_THREE, FIRST_CHARACTERS_OF_TWO, HIGH_TAIL_COEFFICIENTS, LAST_FACTORIAL_ARGUMENT, LOW_TAIL_COEFFICIENTS, MATH_EXPRESSION_ABSOLUTE_TOLERANCE, MATH_EXPRESSION_RELATIVE_TOLERANCE, MAXIMUM_DIGITS, MAXIMUM_STIRLING_WORK, MAX_MATH_EXPRESSION_DEPTH, MILLER_RABIN_BASES, MathExpressionBinaryOperatorMap, MathExpressionBitwiseAbsorptionMap, MathExpressionConstantMap, MathExpressionError, MathExpressionFunctionMap, MathExpressionFunctionName, MathExpressionGrammarRule, MathExpressionLogicalOperator, MathExpressionNodeCompileMap, MathExpressionNodeType, MathExpressionOperatorMap, MathExpressionParameterType, MathExpressionRadixMap, MathExpressionRuleParserMap, MathExpressionTokenType, NAMED_DELIMITERS, NO_LOCALS, NO_VALUES, OVERFLOW_ARGUMENT, PLACEHOLDER, REFINEMENT_STEPS, SQRT_PI, STIRLING_TERMS, STIRLING_THRESHOLD, SUMMATION_LIMIT, WORD_CHARACTER_REGEX, WORD_START_REGEX, checkCanMathExpressionNest, checkIsDecimalMark, checkIsDigitCharacter, checkIsLarger, checkIsMatching, checkIsMatchingKind, checkIsMillerRabinPassing, checkIsNameToken, checkIsNearlyEqual, checkIsOperatorOperand, checkIsPercentageExpression, checkIsPrime, checkIsSignedNumber, checkIsSmaller, checkIsToken, checkIsTruthy, checkIsUnaryStart, checkIsWordCharacter, checkIsWordStartCharacter, collectMathExpressionAssignedNames, compareNumbers, compileArgument, compileAssignment, compileBinary, compileCall, compileComparison, compileConditional, compileGroup, compileList, compileListNode, compileLogical, compileMathExpression, compileMathExpressionNode, compileName, compileNumber, compilePercentage, compileUnary, computeBellNumber, computeBernoulliNumber, computeBitwiseAnd, computeBitwiseOr, computeCatalan, computeCombinations, computeComparison, computeCompositions, computeCorrelation, computeDeterminant, computeDistance, computeDotProduct, computeErf, computeErfInverse, computeExtreme, computeFactorial, computeGamma, computeGreatestCommonDivisor, computeHypotenuse, computeInitialGuess, computeIntegerGreatestCommonDivisor, computeInverseCoth, computeKullbackLeibler, computeLeastCommonMultiple, computeListComparison, computeLogGamma, computeLogGammaOfPositive, computeLogarithm, computeMean, computeMedian, computeMedianAbsoluteDeviation, computeModularInverse, computeModularPower, computeModulo, computeMultinomial, computeNorm, computeNthRoot, computeNumberLiteral, computePartitionSelect, computePermutations, computePointToLine2D, computePointToLine3D, computePolynomial, computeProduct, computeProductOfRange, computeQuantile, computeStirlingColumn, computeStirlingDiagonal, computeStirlingLogGamma, computeStirlingSecondKind, computeSum, computeSummedZeta, computeTruthyCount, computeVariance, computeVectorNorm, computeZeta, createBinaryNode, createBinaryOperation, createBinarySignatures, createBitwiseFold, createBitwisePair, createDigitSignatures, createExtremeSignatures, createIdentitySignatures, createIntegerBinarySignatures, createIntegerUnarySignatures, createListFirstCompute, createListPairCompute, createListPairSignature, createListSignature, createLogicalNode, createNonEmptyCompute, createNumberSignature, createNumericCompute, createOrderedListSignatures, createRangedSignatures, createSignature, createSingletonListSignature, createSpreadSignatures, createUnarySignatures, createVariadicSignatures, failExponent, failMathExpression, failMathExpressionAt, getArgumentCountText, getMathExpressionArityMessage, getMathExpressionCharacter, getMathExpressionChildren, getMathExpressionColumn, getMathExpressionConstant, getMathExpressionNames, getMathExpressionOuterValue, getMathExpressionParameterType, getMathExpressionScalarCompute, getMathExpressionSignatureError, getMathExpressionSignatures, getMathExpressionToken, getOwnValue, getParameterType, matchMathExpressionSignature, multiplyPair, parseArgument, parseAssignment, parseBinary, parseBinaryOperators, parseCall, parseConditional, parseDivisionBeforeProduct, parseImplicitProduct, parseLeftHand, parseList, parseMathExpression, parseMathExpressionRule, parseNullish, parsePercentage, parsePower, parseSequence, parseSymbol, parseUnary, readMathExpressionDelimiter, readMathExpressionNumber, readMathExpressionWord, readRadixNumber, roundToDigits, scaleList, shiftDecimalPlaces, skipMathExpressionSpaces, takeExponent, takeMathExpressionMatching, toNumber, walkNode };
2095
+ export { ADDITIVE_NAMES, BERNOULLI_CLOSED_FORM_INDEX, DECIMAL_MARK_OPERATOR_FOLLOWERS, DELIMITERS_OF_ONE, DELIMITERS_OF_THREE, DELIMITERS_OF_TWO, EULER_MACLAURIN_COEFFICIENTS, FIRST_CHARACTERS_OF_THREE, FIRST_CHARACTERS_OF_TWO, HIGH_TAIL_COEFFICIENTS, LAST_FACTORIAL_ARGUMENT, LOW_TAIL_COEFFICIENTS, MATH_EXPRESSION_ABSOLUTE_TOLERANCE, MATH_EXPRESSION_RELATIVE_TOLERANCE, MAXIMUM_DIGITS, MAXIMUM_STIRLING_WORK, MAX_MATH_EXPRESSION_DEPTH, MILLER_RABIN_BASES, MathExpressionBinaryOperatorMap, MathExpressionBinaryOperatorSymbol, MathExpressionBitwiseAbsorption, MathExpressionBitwiseAbsorptionMap, MathExpressionConstantMap, MathExpressionError, MathExpressionFunctionMap, MathExpressionFunctionName, MathExpressionGrammarRule, MathExpressionLogicalOperator, MathExpressionNodeCompileMap, MathExpressionNodeType, MathExpressionOperatorMap, MathExpressionParameterType, MathExpressionRadix, MathExpressionRadixMap, MathExpressionRuleParserMap, MathExpressionTokenType, NAMED_DELIMITERS, NO_LOCALS, NO_VALUES, OVERFLOW_ARGUMENT, PLACEHOLDER, REFINEMENT_STEPS, SQRT_PI, STIRLING_TERMS, STIRLING_THRESHOLD, SUMMATION_LIMIT, WORD_CHARACTER_REGEX, WORD_START_REGEX, checkCanMathExpressionNest, checkIsDecimalMark, checkIsDigitCharacter, checkIsLarger, checkIsMatching, checkIsMatchingKind, checkIsMillerRabinPassing, checkIsNameToken, checkIsNearlyEqual, checkIsOperatorOperand, checkIsPercentageExpression, checkIsPrime, checkIsSignedNumber, checkIsSmaller, checkIsToken, checkIsTruthy, checkIsUnaryStart, checkIsWordCharacter, checkIsWordStartCharacter, collectMathExpressionAssignedNames, compareNumbers, compileArgument, compileAssignment, compileBinary, compileCall, compileComparison, compileConditional, compileGroup, compileList, compileListNode, compileLogical, compileMathExpression, compileMathExpressionNode, compileName, compileNumber, compilePercentage, compileUnary, computeBellNumber, computeBernoulliNumber, computeBitwiseAnd, computeBitwiseOr, computeCatalan, computeCombinations, computeComparison, computeCompositions, computeCorrelation, computeDeterminant, computeDistance, computeDotProduct, computeErf, computeErfInverse, computeExtreme, computeFactorial, computeGamma, computeGreatestCommonDivisor, computeHypotenuse, computeInitialGuess, computeIntegerGreatestCommonDivisor, computeInverseCoth, computeKullbackLeibler, computeLeastCommonMultiple, computeListComparison, computeLogGamma, computeLogGammaOfPositive, computeLogarithm, computeMean, computeMedian, computeMedianAbsoluteDeviation, computeModularInverse, computeModularPower, computeModulo, computeMultinomial, computeNorm, computeNthRoot, computeNumberLiteral, computePartitionSelect, computePermutations, computePointToLine2D, computePointToLine3D, computePolynomial, computeProduct, computeProductOfRange, computeQuantile, computeStirlingColumn, computeStirlingDiagonal, computeStirlingLogGamma, computeStirlingSecondKind, computeSum, computeSummedZeta, computeTruthyCount, computeVariance, computeVectorNorm, computeZeta, createBinaryNode, createBinaryOperation, createBinarySignatures, createBitwiseFold, createBitwisePair, createDigitSignatures, createExtremeSignatures, createIdentitySignatures, createIntegerBinarySignatures, createIntegerUnarySignatures, createListFirstCompute, createListPairCompute, createListPairSignature, createListSignature, createLogicalNode, createNonEmptyCompute, createNumberSignature, createNumericCompute, createOrderedListSignatures, createRangedSignatures, createSignature, createSingletonListSignature, createSpreadSignatures, createUnarySignatures, createVariadicSignatures, failExponent, failMathExpression, failMathExpressionAt, getArgumentCountText, getMathExpressionArityMessage, getMathExpressionCharacter, getMathExpressionChildren, getMathExpressionColumn, getMathExpressionConstant, getMathExpressionNames, getMathExpressionOuterValue, getMathExpressionParameterType, getMathExpressionScalarCompute, getMathExpressionSignatureError, getMathExpressionSignatures, getMathExpressionToken, getOwnValue, getParameterType, matchMathExpressionSignature, multiplyPair, parseArgument, parseAssignment, parseBinary, parseBinaryOperators, parseCall, parseConditional, parseDivisionBeforeProduct, parseImplicitProduct, parseLeftHand, parseList, parseMathExpression, parseMathExpressionRule, parseNullish, parsePercentage, parsePower, parseSequence, parseSymbol, parseUnary, readMathExpressionDelimiter, readMathExpressionNumber, readMathExpressionWord, readRadixNumber, roundToDigits, scaleList, shiftDecimalPlaces, skipMathExpressionSpaces, takeExponent, takeMathExpressionMatching, toNumber, walkNode };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "math-expression-compiler",
3
- "version": "4.3.3",
4
- "description": "Math expressions compiled once into a function of plain numbers — mathjs's numeric language, held to parity with its recorded answers",
3
+ "version": "4.5.0",
4
+ "description": "Math expressions compiled once into a function of plain numbers — mathjs's numeric language, checked against its recorded answers with every deliberate difference listed",
5
5
  "keywords": [
6
6
  "typescript"
7
7
  ],
@@ -37,16 +37,16 @@
37
37
  "lint": "eslint .",
38
38
  "lint:fix": "eslint --fix .",
39
39
  "test": "vitest",
40
- "typecheck": "tsc"
40
+ "typecheck": "tsrs --fast"
41
41
  },
42
42
  "dependencies": {
43
- "@esposter/shared": "4.3.3",
43
+ "@esposter/shared": "4.5.0",
44
44
  "neverthrow": "^8.2.0"
45
45
  },
46
46
  "devDependencies": {
47
- "@esposter/configuration": "4.3.3",
48
- "@esposter/shared-node": "4.3.3",
49
- "tsdown": "^0.23.1"
47
+ "@esposter/configuration": "4.5.0",
48
+ "@esposter/shared-node": "4.5.0",
49
+ "tsdown": "^0.23.5"
50
50
  },
51
- "gitHead": "955bbc130ad9b28877fd4ae8efc73a045141ce01"
51
+ "gitHead": "e30c001f3b4b15693e75fb53092d62a97ade4d2b"
52
52
  }