@jbrowse/jexl 3.0.2 → 3.1.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.
Files changed (76) hide show
  1. package/README.md +11 -2
  2. package/dist/Expression.d.ts +16 -6
  3. package/dist/Expression.js +34 -8
  4. package/dist/Expression.js.map +1 -1
  5. package/dist/Jexl.d.ts +13 -12
  6. package/dist/Jexl.js +31 -30
  7. package/dist/Jexl.js.map +1 -1
  8. package/dist/Lexer.d.ts +9 -8
  9. package/dist/Lexer.js +58 -18
  10. package/dist/Lexer.js.map +1 -1
  11. package/dist/evaluator/Evaluator.d.ts +20 -34
  12. package/dist/evaluator/Evaluator.js +19 -64
  13. package/dist/evaluator/Evaluator.js.map +1 -1
  14. package/dist/evaluator/compile.d.ts +27 -0
  15. package/dist/evaluator/compile.js +261 -0
  16. package/dist/evaluator/compile.js.map +1 -0
  17. package/dist/grammar.d.ts +29 -9
  18. package/dist/grammar.js +19 -3
  19. package/dist/grammar.js.map +1 -1
  20. package/dist/parser/Parser.d.ts +5 -7
  21. package/dist/parser/Parser.js +17 -2
  22. package/dist/parser/Parser.js.map +1 -1
  23. package/dist/parser/handlers.d.ts +0 -6
  24. package/dist/parser/handlers.js +54 -46
  25. package/dist/parser/handlers.js.map +1 -1
  26. package/dist/parser/states.d.ts +2 -2
  27. package/dist/parser/states.js +0 -20
  28. package/dist/parser/states.js.map +1 -1
  29. package/dist/types.d.ts +18 -7
  30. package/esm/Expression.d.ts +16 -6
  31. package/esm/Expression.js +34 -8
  32. package/esm/Expression.js.map +1 -1
  33. package/esm/Jexl.d.ts +13 -12
  34. package/esm/Jexl.js +31 -30
  35. package/esm/Jexl.js.map +1 -1
  36. package/esm/Lexer.d.ts +9 -8
  37. package/esm/Lexer.js +58 -18
  38. package/esm/Lexer.js.map +1 -1
  39. package/esm/evaluator/Evaluator.d.ts +20 -34
  40. package/esm/evaluator/Evaluator.js +19 -31
  41. package/esm/evaluator/Evaluator.js.map +1 -1
  42. package/esm/evaluator/compile.d.ts +27 -0
  43. package/esm/evaluator/compile.js +258 -0
  44. package/esm/evaluator/compile.js.map +1 -0
  45. package/esm/grammar.d.ts +29 -9
  46. package/esm/grammar.js +18 -3
  47. package/esm/grammar.js.map +1 -1
  48. package/esm/parser/Parser.d.ts +5 -7
  49. package/esm/parser/Parser.js +17 -2
  50. package/esm/parser/Parser.js.map +1 -1
  51. package/esm/parser/handlers.d.ts +0 -6
  52. package/esm/parser/handlers.js +54 -45
  53. package/esm/parser/handlers.js.map +1 -1
  54. package/esm/parser/states.d.ts +2 -2
  55. package/esm/parser/states.js +0 -20
  56. package/esm/parser/states.js.map +1 -1
  57. package/esm/types.d.ts +18 -7
  58. package/package.json +25 -28
  59. package/src/Expression.ts +33 -13
  60. package/src/Jexl.ts +59 -21
  61. package/src/Lexer.ts +60 -27
  62. package/src/evaluator/Evaluator.ts +27 -44
  63. package/src/evaluator/compile.ts +310 -0
  64. package/src/grammar.ts +66 -17
  65. package/src/parser/Parser.ts +24 -20
  66. package/src/parser/handlers.ts +96 -73
  67. package/src/parser/states.ts +2 -22
  68. package/src/types.ts +22 -7
  69. package/CHANGELOG.md +0 -249
  70. package/dist/evaluator/handlers.d.ts +0 -112
  71. package/dist/evaluator/handlers.js +0 -208
  72. package/dist/evaluator/handlers.js.map +0 -1
  73. package/esm/evaluator/handlers.d.ts +0 -112
  74. package/esm/evaluator/handlers.js +0 -194
  75. package/esm/evaluator/handlers.js.map +0 -1
  76. package/src/evaluator/handlers.ts +0 -212
package/esm/Jexl.js CHANGED
@@ -3,6 +3,7 @@
3
3
  * Copyright 2020 Tom Shawver
4
4
  */
5
5
  import Expression from "./Expression.js";
6
+ import Lexer from "./Lexer.js";
6
7
  import { getGrammar } from "./grammar.js";
7
8
  /**
8
9
  * Jexl is the Javascript Expression Language, capable of parsing and
@@ -11,35 +12,25 @@ import { getGrammar } from "./grammar.js";
11
12
  * @constructor
12
13
  */
13
14
  class Jexl {
15
+ _grammar;
16
+ // shared by every Expression this instance creates, so that the expensive
17
+ // element-splitting regex is built once rather than per compile
18
+ _lexer;
14
19
  constructor() {
15
20
  this._grammar = getGrammar();
21
+ this._lexer = new Lexer(this._grammar);
16
22
  this.expr = this.expr.bind(this);
17
23
  }
18
- /**
19
- * Adds a binary operator to Jexl at the specified precedence. The higher the
20
- * precedence, the earlier the operator is applied in the order of operations.
21
- * For example, * has a higher precedence than +, because multiplication comes
22
- * before division.
23
- *
24
- * Please see grammar.js for a listing of all default operators and their
25
- * precedence values in order to choose the appropriate precedence for the
26
- * new operator.
27
- * @param {string} operator The operator string to be added
28
- * @param {number} precedence The operator's precedence
29
- * @param {function} fn A function to run to calculate the result. The function
30
- * will be called with two arguments: left and right, denoting the values
31
- * on either side of the operator. It should return the resulting value.
32
- * @param {boolean} [manualEval] If true, the `left` and `right` arguments
33
- * will be wrapped in objects with an `eval` function. Calling
34
- * left.eval() or right.eval() will return that operand's actual value.
35
- * This is useful to conditionally evaluate operands.
36
- */
37
24
  addBinaryOp(operator, precedence, fn, manualEval) {
38
- this._addGrammarElement(operator, {
39
- type: 'binaryOp',
40
- precedence: precedence,
41
- [manualEval ? 'evalOnDemand' : 'eval']: fn
42
- });
25
+ // the overloads above pair `fn` with `manualEval`; the implementation
26
+ // signature can't express that correlation, hence the assertions
27
+ this._addGrammarElement(operator, manualEval
28
+ ? {
29
+ type: 'binaryOp',
30
+ precedence,
31
+ evalOnDemand: fn
32
+ }
33
+ : { type: 'binaryOp', precedence, eval: fn });
43
34
  }
44
35
  /**
45
36
  * Adds or replaces an expression function in this Jexl instance.
@@ -72,7 +63,7 @@ class Jexl {
72
63
  addUnaryOp(operator, fn) {
73
64
  this._addGrammarElement(operator, {
74
65
  type: 'unaryOp',
75
- weight: Infinity,
66
+ precedence: Infinity,
76
67
  eval: fn
77
68
  });
78
69
  }
@@ -95,7 +86,7 @@ class Jexl {
95
86
  * @returns {Expression} The Expression object representing the given string
96
87
  */
97
88
  createExpression(expression) {
98
- return new Expression(this._grammar, expression);
89
+ return new Expression(this._grammar, expression, this._lexer);
99
90
  }
100
91
  /**
101
92
  * Retrieves a previously set expression function.
@@ -125,10 +116,18 @@ class Jexl {
125
116
  */
126
117
  expr(strs, ...args) {
127
118
  let exprStr = '';
128
- for (let idx = 0; idx < strs.length; idx++) {
129
- exprStr += strs[idx];
119
+ for (const [idx, str] of strs.entries()) {
120
+ exprStr += str;
130
121
  if (idx < args.length) {
131
- exprStr += args[idx];
122
+ const arg = args[idx];
123
+ if (typeof arg === 'string' ||
124
+ typeof arg === 'number' ||
125
+ typeof arg === 'boolean') {
126
+ exprStr += String(arg);
127
+ }
128
+ else if (arg != null) {
129
+ exprStr += JSON.stringify(arg);
130
+ }
132
131
  }
133
132
  }
134
133
  return this.createExpression(exprStr);
@@ -139,8 +138,9 @@ class Jexl {
139
138
  */
140
139
  removeOp(operator) {
141
140
  const elem = this._grammar.elements[operator];
142
- if (elem && (elem.type === 'binaryOp' || elem.type === 'unaryOp')) {
141
+ if (elem?.type === 'binaryOp' || elem?.type === 'unaryOp') {
143
142
  Reflect.deleteProperty(this._grammar.elements, operator);
143
+ this._lexer._clearCache();
144
144
  }
145
145
  }
146
146
  /**
@@ -152,6 +152,7 @@ class Jexl {
152
152
  */
153
153
  _addGrammarElement(str, obj) {
154
154
  this._grammar.elements[str] = obj;
155
+ this._lexer._clearCache();
155
156
  }
156
157
  }
157
158
  const jexlInstance = new Jexl();
package/esm/Jexl.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"Jexl.js","sourceRoot":"","sources":["../src/Jexl.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Jexl.js","sourceRoot":"","sources":["../src/Jexl.ts"],"names":[],"mappings":"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"}
package/esm/Lexer.d.ts CHANGED
@@ -1,7 +1,5 @@
1
- import type { Token } from './types.ts';
2
- interface Grammar {
3
- elements: Record<string, any>;
4
- }
1
+ import type { Grammar } from './grammar.ts';
2
+ import type { TemplatePart, Token } from './types.ts';
5
3
  /**
6
4
  * Lexer is a collection of stateless, statically-accessed functions for the
7
5
  * lexical parsing of a Jexl string. Its responsibility is to identify the
@@ -17,6 +15,12 @@ declare class Lexer {
17
15
  _splitRegex?: RegExp;
18
16
  _escQuoteRegexCache: Map<string, RegExp>;
19
17
  constructor(grammar: Grammar);
18
+ /**
19
+ * Discards the memoized split regex, so that it is rebuilt on the next
20
+ * tokenize. Must be called whenever the grammar's elements change, since the
21
+ * regex is derived from their keys.
22
+ */
23
+ _clearCache(): void;
20
24
  /**
21
25
  * Splits a Jexl expression string into an array of expression elements.
22
26
  * @param {string} str A Jexl expression string
@@ -121,10 +125,7 @@ declare class Lexer {
121
125
  * @private
122
126
  */
123
127
  _unquote(str: string): string;
124
- _parseTemplateString(str: string): {
125
- type: "static" | "interpolation";
126
- value: string;
127
- }[];
128
+ _parseTemplateString(str: string): TemplatePart[];
128
129
  _unescapeTemplateString(str: string): string;
129
130
  }
130
131
  export default Lexer;
package/esm/Lexer.js CHANGED
@@ -4,7 +4,7 @@
4
4
  */
5
5
  const numericRegex = /^-?(?:(?:[0-9]*\.[0-9]+)|[0-9]+)$/;
6
6
  const identRegex = /^[a-zA-Zа-яА-Я_\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u00FF$][a-zA-Zа-яА-Я0-9_\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u00FF$]*$/;
7
- const escEscRegex = /\\\\/;
7
+ const escEscRegex = /\\\\/g;
8
8
  const whitespaceRegex = /^\s*$/;
9
9
  const preOpRegexElems = [
10
10
  // Template strings
@@ -24,6 +24,11 @@ const postOpRegexElems = [
24
24
  // Numerics (without negative symbol)
25
25
  String.raw `(?:(?:[0-9]*\.[0-9]+)|[0-9]+)`
26
26
  ];
27
+ const unaryMinusToken = () => ({
28
+ type: 'unaryOp',
29
+ value: '-',
30
+ raw: '-'
31
+ });
27
32
  const minusNegatesAfter = new Set([
28
33
  'binaryOp',
29
34
  'unaryOp',
@@ -45,10 +50,20 @@ const minusNegatesAfter = new Set([
45
50
  * @type {{}}
46
51
  */
47
52
  class Lexer {
53
+ _grammar;
54
+ _splitRegex;
55
+ _escQuoteRegexCache = new Map();
48
56
  constructor(grammar) {
49
- this._escQuoteRegexCache = new Map();
50
57
  this._grammar = grammar;
51
58
  }
59
+ /**
60
+ * Discards the memoized split regex, so that it is rebuilt on the next
61
+ * tokenize. Must be called whenever the grammar's elements change, since the
62
+ * regex is derived from their keys.
63
+ */
64
+ _clearCache() {
65
+ this._splitRegex = undefined;
66
+ }
52
67
  /**
53
68
  * Splits a Jexl expression string into an array of expression elements.
54
69
  * @param {string} str A Jexl expression string
@@ -72,21 +87,35 @@ class Lexer {
72
87
  getTokens(elements) {
73
88
  const tokens = [];
74
89
  let negate = false;
75
- for (let i = 0; i < elements.length; i++) {
76
- if (this._isWhitespace(elements[i])) {
77
- if (tokens.length) {
78
- tokens[tokens.length - 1].raw += elements[i];
90
+ for (const element of elements) {
91
+ if (this._isWhitespace(element)) {
92
+ const last = tokens.at(-1);
93
+ if (last) {
94
+ last.raw += element;
79
95
  }
80
96
  }
81
- else if (elements[i] === '-' && this._isNegative(tokens)) {
97
+ else if (element === '-' && this._isNegative(tokens)) {
98
+ // a second prefix minus in a row ("- -x"): emit the pending one as a
99
+ // unary operator so this one can negate whatever comes next
100
+ if (negate) {
101
+ tokens.push(unaryMinusToken());
102
+ }
82
103
  negate = true;
83
104
  }
84
- else {
85
- if (negate) {
86
- elements[i] = '-' + elements[i];
87
- negate = false;
105
+ else if (negate) {
106
+ negate = false;
107
+ if (numericRegex.exec(element)) {
108
+ // fold the sign into the number, so "-1" stays a single literal
109
+ tokens.push(this._createToken('-' + element));
110
+ }
111
+ else {
112
+ // anything else gets a standalone prefix operator, letting "-x",
113
+ // "-(a + b)" and "-foo.bar" negate a computed value
114
+ tokens.push(unaryMinusToken(), this._createToken(element));
88
115
  }
89
- tokens.push(this._createToken(elements[i]));
116
+ }
117
+ else {
118
+ tokens.push(this._createToken(element));
90
119
  }
91
120
  }
92
121
  // Catch a - at the end of the string. Let the parser handle that issue.
@@ -156,7 +185,7 @@ class Lexer {
156
185
  else if (element === 'true' || element === 'false') {
157
186
  token.value = element === 'true';
158
187
  }
159
- else if (this._grammar.elements[element]) {
188
+ else if (Object.hasOwn(this._grammar.elements, element)) {
160
189
  token.type = this._grammar.elements[element].type;
161
190
  }
162
191
  else if (identRegex.exec(element)) {
@@ -254,8 +283,8 @@ class Lexer {
254
283
  }
255
284
  return str
256
285
  .slice(1, -1)
257
- .replace(escQuoteRegex, quote)
258
- .replace(escEscRegex, '\\');
286
+ .replaceAll(escQuoteRegex, quote)
287
+ .replaceAll(escEscRegex, '\\');
259
288
  }
260
289
  _parseTemplateString(str) {
261
290
  const parts = [];
@@ -277,14 +306,25 @@ class Lexer {
277
306
  const interpStart = current + 2;
278
307
  current += 2;
279
308
  while (current < str.length && braceDepth > 0) {
280
- if (str[current] === '\\') {
309
+ const char = str[current];
310
+ if (char === '\\') {
281
311
  current += 2;
282
312
  continue;
283
313
  }
284
- if (str[current] === '{') {
314
+ // skip over string literals so that braces inside them, as in
315
+ // `${ f('}') }`, don't unbalance the depth count
316
+ if (char === '"' || char === "'") {
317
+ current++;
318
+ while (current < str.length && str[current] !== char) {
319
+ current += str[current] === '\\' ? 2 : 1;
320
+ }
321
+ current++;
322
+ continue;
323
+ }
324
+ if (char === '{') {
285
325
  braceDepth++;
286
326
  }
287
- if (str[current] === '}') {
327
+ else if (char === '}') {
288
328
  braceDepth--;
289
329
  }
290
330
  current++;
package/esm/Lexer.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"Lexer.js","sourceRoot":"","sources":["../src/Lexer.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Lexer.js","sourceRoot":"","sources":["../src/Lexer.ts"],"names":[],"mappings":"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"}
@@ -1,16 +1,17 @@
1
- import type { AstNode } from '../types.ts';
2
- interface Grammar {
3
- elements: Record<string, any>;
4
- [key: string]: any;
5
- }
1
+ import type { Grammar } from '../grammar.ts';
2
+ import type { AstNode, JexlValue } from '../types.ts';
6
3
  /**
7
- * The Evaluator takes a Jexl expression tree as generated by the
8
- * {@link Parser} and calculates its value within a given context. The
9
- * collection of transforms, context, and a relative context to be used as the
10
- * root for relative identifiers, are all specific to an Evaluator instance.
11
- * When any of these things change, a new instance is required. However, a
12
- * single instance can be used to simultaneously evaluate many different
4
+ * The Evaluator carries everything an expression is evaluated against: the
5
+ * grammar, the context, and a relative context to be used as the root for
6
+ * relative identifiers. When any of these change, a new instance is required.
7
+ * However, a single instance can be used to evaluate many different
13
8
  * expressions, and does not have to be reinstantiated for each.
9
+ *
10
+ * The work of evaluation itself lives in {@link compileAst}, which lowers a
11
+ * tree to closures. Prefer compiling once and reusing the result — that is what
12
+ * {@link Expression} does — over calling {@link #eval}, which compiles the tree
13
+ * it is given every time.
14
+ *
14
15
  * @param {{}} grammar A grammar object against which to evaluate the expression
15
16
  * tree
16
17
  * @param {{}} [context] A map of variable keys to their values. This will be
@@ -20,32 +21,17 @@ interface Grammar {
20
21
  */
21
22
  declare class Evaluator {
22
23
  _grammar: Grammar;
23
- _context: any;
24
- _relContext: any;
25
- constructor(grammar: Grammar, context?: any, relativeContext?: any);
24
+ _context: Record<string, JexlValue>;
25
+ _relContext: Record<string, JexlValue>;
26
+ constructor(grammar: Grammar, context?: Record<string, JexlValue>, relativeContext?: Record<string, JexlValue>);
26
27
  /**
27
- * Evaluates an expression tree within the configured context.
28
+ * Compiles and evaluates an expression tree within the configured context.
29
+ * Convenient for a one-shot evaluation; for repeated evaluation of the same
30
+ * tree, hold onto the closure from {@link compileAst} instead so the tree is
31
+ * only lowered once.
28
32
  * @param {{}} ast An expression tree object
29
33
  * @returns {*} the resulting value of the expression.
30
34
  */
31
- eval(ast: AstNode): any;
32
- /**
33
- * Evaluates each expression within an array, and delivers the response as an
34
- * array with the resulting values at the same indexes as their originating
35
- * expressions.
36
- * @param {Array<string>} arr An array of expression strings to be evaluated
37
- * @returns {Array<{}>} the result array
38
- */
39
- evalArray(arr: AstNode[]): any[];
40
- /**
41
- * Evaluates each expression within a map, and delivers the response as a map
42
- * with the same keys, but with the evaluated result for each as their value.
43
- * @param {{}} map A map of expression names to expression trees to be
44
- * evaluated
45
- * @returns {{}} the result map.
46
- */
47
- evalMap(map: Record<string, AstNode>): {
48
- [k: string]: any;
49
- };
35
+ eval(ast: AstNode): JexlValue;
50
36
  }
51
37
  export default Evaluator;
@@ -2,15 +2,19 @@
2
2
  * Jexl
3
3
  * Copyright 2020 Tom Shawver
4
4
  */
5
- import * as handlers from "./handlers.js";
5
+ import { compileAst } from "./compile.js";
6
6
  /**
7
- * The Evaluator takes a Jexl expression tree as generated by the
8
- * {@link Parser} and calculates its value within a given context. The
9
- * collection of transforms, context, and a relative context to be used as the
10
- * root for relative identifiers, are all specific to an Evaluator instance.
11
- * When any of these things change, a new instance is required. However, a
12
- * single instance can be used to simultaneously evaluate many different
7
+ * The Evaluator carries everything an expression is evaluated against: the
8
+ * grammar, the context, and a relative context to be used as the root for
9
+ * relative identifiers. When any of these change, a new instance is required.
10
+ * However, a single instance can be used to evaluate many different
13
11
  * expressions, and does not have to be reinstantiated for each.
12
+ *
13
+ * The work of evaluation itself lives in {@link compileAst}, which lowers a
14
+ * tree to closures. Prefer compiling once and reusing the result — that is what
15
+ * {@link Expression} does — over calling {@link #eval}, which compiles the tree
16
+ * it is given every time.
17
+ *
14
18
  * @param {{}} grammar A grammar object against which to evaluate the expression
15
19
  * tree
16
20
  * @param {{}} [context] A map of variable keys to their values. This will be
@@ -19,40 +23,24 @@ import * as handlers from "./handlers.js";
19
23
  * to resolve the value of a relative identifier.
20
24
  */
21
25
  class Evaluator {
26
+ _grammar;
27
+ _context;
28
+ _relContext;
22
29
  constructor(grammar, context, relativeContext) {
23
30
  this._grammar = grammar;
24
31
  this._context = context || {};
25
32
  this._relContext = relativeContext || this._context;
26
33
  }
27
34
  /**
28
- * Evaluates an expression tree within the configured context.
35
+ * Compiles and evaluates an expression tree within the configured context.
36
+ * Convenient for a one-shot evaluation; for repeated evaluation of the same
37
+ * tree, hold onto the closure from {@link compileAst} instead so the tree is
38
+ * only lowered once.
29
39
  * @param {{}} ast An expression tree object
30
40
  * @returns {*} the resulting value of the expression.
31
41
  */
32
42
  eval(ast) {
33
- return handlers[ast.type].call(this, ast);
34
- }
35
- /**
36
- * Evaluates each expression within an array, and delivers the response as an
37
- * array with the resulting values at the same indexes as their originating
38
- * expressions.
39
- * @param {Array<string>} arr An array of expression strings to be evaluated
40
- * @returns {Array<{}>} the result array
41
- */
42
- evalArray(arr) {
43
- return arr.map((elem) => this.eval(elem));
44
- }
45
- /**
46
- * Evaluates each expression within a map, and delivers the response as a map
47
- * with the same keys, but with the evaluated result for each as their value.
48
- * @param {{}} map A map of expression names to expression trees to be
49
- * evaluated
50
- * @returns {{}} the result map.
51
- */
52
- evalMap(map) {
53
- const entries = Object.entries(map);
54
- const vals = entries.map(([_, ast]) => this.eval(ast));
55
- return Object.fromEntries(entries.map(([key], idx) => [key, vals[idx]]));
43
+ return compileAst(ast, this._grammar)(this);
56
44
  }
57
45
  }
58
46
  export default Evaluator;
@@ -1 +1 @@
1
- {"version":3,"file":"Evaluator.js","sourceRoot":"","sources":["../../src/evaluator/Evaluator.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,QAAQ,MAAM,eAAe,CAAA;AASzC;;;;;;;;;;;;;;GAcG;AACH,MAAM,SAAS;IAKb,YAAY,OAAgB,EAAE,OAAa,EAAE,eAAqB;QAChE,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAA;QACvB,IAAI,CAAC,QAAQ,GAAG,OAAO,IAAI,EAAE,CAAA;QAC7B,IAAI,CAAC,WAAW,GAAG,eAAe,IAAI,IAAI,CAAC,QAAQ,CAAA;IACrD,CAAC;IAED;;;;OAIG;IACH,IAAI,CAAC,GAAY;QACf,OAAQ,QAAgB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;IACpD,CAAC;IAED;;;;;;OAMG;IACH,SAAS,CAAC,GAAc;QACtB,OAAO,GAAG,CAAC,GAAG,CAAC,CAAC,IAAa,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAA;IACpD,CAAC;IAED;;;;;;OAMG;IACH,OAAO,CAAC,GAA4B;QAClC,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;QACnC,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAA;QACtD,OAAO,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAA;IAC1E,CAAC;CACF;AAED,eAAe,SAAS,CAAA"}
1
+ {"version":3,"file":"Evaluator.js","sourceRoot":"","sources":["../../src/evaluator/Evaluator.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AAKzC;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,SAAS;IACb,QAAQ,CAAS;IACjB,QAAQ,CAA2B;IACnC,WAAW,CAA2B;IAEtC,YACE,OAAgB,EAChB,OAAmC,EACnC,eAA2C;QAE3C,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAA;QACvB,IAAI,CAAC,QAAQ,GAAG,OAAO,IAAI,EAAE,CAAA;QAC7B,IAAI,CAAC,WAAW,GAAG,eAAe,IAAI,IAAI,CAAC,QAAQ,CAAA;IACrD,CAAC;IAED;;;;;;;OAOG;IACH,IAAI,CAAC,GAAY;QACf,OAAO,UAAU,CAAC,GAAG,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAA;IAC7C,CAAC;CACF;AAED,eAAe,SAAS,CAAA"}
@@ -0,0 +1,27 @@
1
+ import type { Grammar } from '../grammar.ts';
2
+ import type { AstNode, JexlValue } from '../types.ts';
3
+ import type Evaluator from './Evaluator.ts';
4
+ /**
5
+ * An AST node lowered to a closure. Calling it with an Evaluator (which carries
6
+ * the context and grammar) produces the node's value.
7
+ */
8
+ export type CompiledNode = (ev: Evaluator) => JexlValue;
9
+ /**
10
+ * Lowers an expression tree into a tree of closures, resolving each node's type
11
+ * and its operator's implementation once, at compile time, rather than
12
+ * re-dispatching on `node.type` for every node on every evaluation. An
13
+ * expression compiled once and evaluated per-item — the usual shape for
14
+ * per-feature config callbacks — pays the dispatch cost once instead of N
15
+ * times.
16
+ *
17
+ * Operators are bound here, so a grammar change after compilation requires
18
+ * recompiling, which is what {@link Expression#compile} already documents.
19
+ * Functions are looked up per call, since they are commonly registered after
20
+ * an expression has been compiled.
21
+ *
22
+ * @param {{}} ast An expression tree, as produced by the Parser
23
+ * @param {{}} grammar The grammar to resolve operators against
24
+ * @returns {function} a closure returning the expression's value
25
+ * @throws {Error} if the tree contains an unrecognized node type
26
+ */
27
+ export declare function compileAst(ast: AstNode, grammar: Grammar): CompiledNode;