@1771technologies/lytenyte-pro 2.0.4-dev.2 → 2.0.4-dev.4
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/css/components/expression-editor.css +105 -0
- package/dist/components/column-manager/column-manager.d.ts +6 -1
- package/dist/components/column-manager/column-manager.js +23 -2
- package/dist/components/expressions-editor/(expressions)/expression.play.d.ts +4 -0
- package/dist/components/expressions-editor/(expressions)/expression.play.js +69 -0
- package/dist/components/expressions-editor/create-completion-provider.d.ts +3 -0
- package/dist/components/expressions-editor/create-completion-provider.js +161 -0
- package/dist/components/expressions-editor/create-key-down-handler.d.ts +18 -0
- package/dist/components/expressions-editor/create-key-down-handler.js +49 -0
- package/dist/components/expressions-editor/cursor-position/measure-cursor-at-pointer.d.ts +2 -0
- package/dist/components/expressions-editor/cursor-position/measure-cursor-at-pointer.js +56 -0
- package/dist/components/expressions-editor/cursor-position/use-cursor-position.d.ts +5 -0
- package/dist/components/expressions-editor/cursor-position/use-cursor-position.js +17 -0
- package/dist/components/expressions-editor/expression-editor.d.ts +3 -0
- package/dist/components/expressions-editor/expression-editor.js +138 -0
- package/dist/components/expressions-editor/get-indentation.d.ts +1 -0
- package/dist/components/expressions-editor/get-indentation.js +7 -0
- package/dist/components/expressions-editor/handle-completion-key-down.d.ts +2 -0
- package/dist/components/expressions-editor/handle-completion-key-down.js +22 -0
- package/dist/components/expressions-editor/handle-enter-key.d.ts +4 -0
- package/dist/components/expressions-editor/handle-enter-key.js +11 -0
- package/dist/components/expressions-editor/handle-manual-trigger.d.ts +2 -0
- package/dist/components/expressions-editor/handle-manual-trigger.js +3 -0
- package/dist/components/expressions-editor/index.d.ts +17 -0
- package/dist/components/expressions-editor/index.js +11 -0
- package/dist/components/expressions-editor/intellisence/completion-context.d.ts +16 -0
- package/dist/components/expressions-editor/intellisence/completion-context.js +7 -0
- package/dist/components/expressions-editor/intellisence/completion-item.d.ts +5 -0
- package/dist/components/expressions-editor/intellisence/completion-item.js +11 -0
- package/dist/components/expressions-editor/intellisence/completion-list.d.ts +8 -0
- package/dist/components/expressions-editor/intellisence/completion-list.js +18 -0
- package/dist/components/expressions-editor/intellisence/completion-popover.d.ts +1 -0
- package/dist/components/expressions-editor/intellisence/completion-popover.js +30 -0
- package/dist/components/expressions-editor/intellisence/filter-completions-by-prefix.d.ts +2 -0
- package/dist/components/expressions-editor/intellisence/filter-completions-by-prefix.js +6 -0
- package/dist/components/expressions-editor/intellisence/get-word-at-cursor.d.ts +2 -0
- package/dist/components/expressions-editor/intellisence/get-word-at-cursor.js +12 -0
- package/dist/components/expressions-editor/intellisence/use-complete-trigger.d.ts +13 -0
- package/dist/components/expressions-editor/intellisence/use-complete-trigger.js +41 -0
- package/dist/components/expressions-editor/intellisence/use-completions.d.ts +14 -0
- package/dist/components/expressions-editor/intellisence/use-completions.js +78 -0
- package/dist/components/expressions-editor/replace-word-at-cursor.d.ts +5 -0
- package/dist/components/expressions-editor/replace-word-at-cursor.js +7 -0
- package/dist/components/expressions-editor/token-highlighter-default.d.ts +4 -0
- package/dist/components/expressions-editor/token-highlighter-default.js +18 -0
- package/dist/components/expressions-editor/types.d.ts +47 -0
- package/dist/components/expressions-editor/types.js +1 -0
- package/dist/components/expressions-editor/use-keyboard-navigation.d.ts +10 -0
- package/dist/components/expressions-editor/use-keyboard-navigation.js +16 -0
- package/dist/components/pill-manager/container.js +55 -9
- package/dist/components/pill-manager/item.js +15 -1
- package/dist/components/select-all.js +1 -1
- package/dist/components/tree-view/root.d.ts +9 -0
- package/dist/components/tree-view/root.js +4 -2
- package/dist/data-source-client/hooks/use-flattened-groups.js +2 -2
- package/dist/expressions/compiler/compile.d.ts +3 -0
- package/dist/expressions/compiler/compile.js +4 -0
- package/dist/expressions/compiler/eval-constant.d.ts +2 -0
- package/dist/expressions/compiler/eval-constant.js +19 -0
- package/dist/expressions/compiler/is-constant.d.ts +2 -0
- package/dist/expressions/compiler/is-constant.js +6 -0
- package/dist/expressions/compiler/make-constant.d.ts +2 -0
- package/dist/expressions/compiler/make-constant.js +11 -0
- package/dist/expressions/compiler/optimize.d.ts +3 -0
- package/dist/expressions/compiler/optimize.js +47 -0
- package/dist/expressions/compiler/value-of.d.ts +2 -0
- package/dist/expressions/compiler/value-of.js +11 -0
- package/dist/expressions/errors/clamp-offset.d.ts +1 -0
- package/dist/expressions/errors/clamp-offset.js +3 -0
- package/dist/expressions/errors/expression-error.d.ts +10 -0
- package/dist/expressions/errors/expression-error.js +19 -0
- package/dist/expressions/errors/format-error.d.ts +3 -0
- package/dist/expressions/errors/format-error.js +27 -0
- package/dist/expressions/errors/get-line-end.d.ts +1 -0
- package/dist/expressions/errors/get-line-end.js +8 -0
- package/dist/expressions/errors/get-line-start.d.ts +1 -0
- package/dist/expressions/errors/get-line-start.js +8 -0
- package/dist/expressions/errors/index.d.ts +7 -0
- package/dist/expressions/errors/index.js +6 -0
- package/dist/expressions/errors/offset-to-position.d.ts +2 -0
- package/dist/expressions/errors/offset-to-position.js +17 -0
- package/dist/expressions/errors/types.d.ts +10 -0
- package/dist/expressions/errors/types.js +1 -0
- package/dist/expressions/evaluator/evaluate-binary.d.ts +4 -0
- package/dist/expressions/evaluator/evaluate-binary.js +21 -0
- package/dist/expressions/evaluator/evaluate-unary.d.ts +2 -0
- package/dist/expressions/evaluator/evaluate-unary.js +10 -0
- package/dist/expressions/evaluator/evaluate.d.ts +15 -0
- package/dist/expressions/evaluator/evaluate.js +62 -0
- package/dist/expressions/index.d.ts +5 -0
- package/dist/expressions/index.js +3 -0
- package/dist/expressions/lexer/predicates/is-alpha-numeric.d.ts +1 -0
- package/dist/expressions/lexer/predicates/is-alpha-numeric.js +5 -0
- package/dist/expressions/lexer/predicates/is-alpha.d.ts +1 -0
- package/dist/expressions/lexer/predicates/is-alpha.js +3 -0
- package/dist/expressions/lexer/predicates/is-binary-digit.d.ts +1 -0
- package/dist/expressions/lexer/predicates/is-binary-digit.js +3 -0
- package/dist/expressions/lexer/predicates/is-digit.d.ts +1 -0
- package/dist/expressions/lexer/predicates/is-digit.js +3 -0
- package/dist/expressions/lexer/predicates/is-hex-digit.d.ts +1 -0
- package/dist/expressions/lexer/predicates/is-hex-digit.js +4 -0
- package/dist/expressions/lexer/predicates/is-octal-digit.d.ts +1 -0
- package/dist/expressions/lexer/predicates/is-octal-digit.js +3 -0
- package/dist/expressions/lexer/tokenize/consume-digits.d.ts +1 -0
- package/dist/expressions/lexer/tokenize/consume-digits.js +5 -0
- package/dist/expressions/lexer/tokenize/scan-identifier.d.ts +6 -0
- package/dist/expressions/lexer/tokenize/scan-identifier.js +20 -0
- package/dist/expressions/lexer/tokenize/scan-number.d.ts +4 -0
- package/dist/expressions/lexer/tokenize/scan-number.js +32 -0
- package/dist/expressions/lexer/tokenize/scan-operator.d.ts +6 -0
- package/dist/expressions/lexer/tokenize/scan-operator.js +71 -0
- package/dist/expressions/lexer/tokenize/scan-string-literal.d.ts +4 -0
- package/dist/expressions/lexer/tokenize/scan-string-literal.js +22 -0
- package/dist/expressions/lexer/tokenize/scan-string.d.ts +4 -0
- package/dist/expressions/lexer/tokenize/scan-string.js +98 -0
- package/dist/expressions/lexer/tokenize/scan-template-literal.d.ts +4 -0
- package/dist/expressions/lexer/tokenize/scan-template-literal.js +51 -0
- package/dist/expressions/lexer/tokenize/tokenize.d.ts +4 -0
- package/dist/expressions/lexer/tokenize/tokenize.js +99 -0
- package/dist/expressions/lexer/types.d.ts +12 -0
- package/dist/expressions/lexer/types.js +1 -0
- package/dist/expressions/parser/parse-array-literal.d.ts +3 -0
- package/dist/expressions/parser/parse-array-literal.js +15 -0
- package/dist/expressions/parser/parse-expression.d.ts +3 -0
- package/dist/expressions/parser/parse-expression.js +74 -0
- package/dist/expressions/parser/parse-object-literal.d.ts +3 -0
- package/dist/expressions/parser/parse-object-literal.js +69 -0
- package/dist/expressions/parser/parse-pipe-transform.d.ts +3 -0
- package/dist/expressions/parser/parse-pipe-transform.js +26 -0
- package/dist/expressions/parser/parse-postfix.d.ts +3 -0
- package/dist/expressions/parser/parse-postfix.js +23 -0
- package/dist/expressions/parser/parse-primary.d.ts +3 -0
- package/dist/expressions/parser/parse-primary.js +35 -0
- package/dist/expressions/parser/parse-template-literal.d.ts +3 -0
- package/dist/expressions/parser/parse-template-literal.js +41 -0
- package/dist/expressions/parser/parse-unary.d.ts +3 -0
- package/dist/expressions/parser/parse-unary.js +28 -0
- package/dist/expressions/parser/parse.d.ts +3 -0
- package/dist/expressions/parser/parse.js +26 -0
- package/dist/expressions/parser/parser-context.d.ts +12 -0
- package/dist/expressions/parser/parser-context.js +14 -0
- package/dist/expressions/parser/precedence.d.ts +1 -0
- package/dist/expressions/parser/precedence.js +8 -0
- package/dist/expressions/parser/types.d.ts +97 -0
- package/dist/expressions/parser/types.js +1 -0
- package/dist/expressions/plugin.d.ts +20 -0
- package/dist/expressions/plugin.js +1 -0
- package/dist/expressions/plugins/access.d.ts +2 -0
- package/dist/expressions/plugins/access.js +138 -0
- package/dist/expressions/plugins/arrows.d.ts +2 -0
- package/dist/expressions/plugins/arrows.js +83 -0
- package/dist/expressions/plugins/booleans.d.ts +2 -0
- package/dist/expressions/plugins/booleans.js +34 -0
- package/dist/expressions/plugins/collections.d.ts +2 -0
- package/dist/expressions/plugins/collections.js +70 -0
- package/dist/expressions/plugins/comparison.d.ts +2 -0
- package/dist/expressions/plugins/comparison.js +51 -0
- package/dist/expressions/plugins/logical.d.ts +2 -0
- package/dist/expressions/plugins/logical.js +103 -0
- package/dist/expressions/plugins/membership.d.ts +2 -0
- package/dist/expressions/plugins/membership.js +71 -0
- package/dist/expressions/plugins/pipe.d.ts +2 -0
- package/dist/expressions/plugins/pipe.js +57 -0
- package/dist/expressions/plugins/resolved-identifier.d.ts +5 -0
- package/dist/expressions/plugins/resolved-identifier.js +19 -0
- package/dist/expressions/plugins/standard.d.ts +13 -0
- package/dist/expressions/plugins/standard.js +23 -0
- package/dist/expressions/plugins/strings.d.ts +2 -0
- package/dist/expressions/plugins/strings.js +44 -0
- package/dist/expressions/plugins/ternary.d.ts +2 -0
- package/dist/expressions/plugins/ternary.js +58 -0
- package/dist/expressions.d.ts +2 -0
- package/dist/expressions.js +2 -0
- package/dist/index.d.ts +1 -0
- package/package.json +11 -5
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { current, advance, expect } from "../parser/parser-context.js";
|
|
2
|
+
import { parseExpression } from "../parser/parse-expression.js";
|
|
3
|
+
function isArrowParams(ctx) {
|
|
4
|
+
let i = ctx.pos + 1;
|
|
5
|
+
let depth = 1;
|
|
6
|
+
while (i < ctx.tokens.length && depth > 0) {
|
|
7
|
+
const t = ctx.tokens[i];
|
|
8
|
+
if (t.type === "Punctuation" && t.value === "(")
|
|
9
|
+
depth++;
|
|
10
|
+
else if (t.type === "Punctuation" && t.value === ")")
|
|
11
|
+
depth--;
|
|
12
|
+
if (depth > 0)
|
|
13
|
+
i++;
|
|
14
|
+
}
|
|
15
|
+
const after = ctx.tokens[i + 1];
|
|
16
|
+
return after?.type === "Arrow";
|
|
17
|
+
}
|
|
18
|
+
function parseArrowFunction(ctx) {
|
|
19
|
+
const start = current(ctx).start;
|
|
20
|
+
advance(ctx); // consume (
|
|
21
|
+
const params = [];
|
|
22
|
+
while (!(current(ctx).type === "Punctuation" && current(ctx).value === ")")) {
|
|
23
|
+
if (params.length > 0)
|
|
24
|
+
expect(ctx, "Punctuation", ",");
|
|
25
|
+
const param = expect(ctx, "Identifier");
|
|
26
|
+
params.push(param.value);
|
|
27
|
+
}
|
|
28
|
+
expect(ctx, "Punctuation", ")"); // consume )
|
|
29
|
+
advance(ctx); // consume =>
|
|
30
|
+
const body = parseExpression(ctx, 0);
|
|
31
|
+
return {
|
|
32
|
+
type: "ArrowFunctionExpression",
|
|
33
|
+
params,
|
|
34
|
+
body,
|
|
35
|
+
start,
|
|
36
|
+
end: body.end,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
export const arrowsPlugin = {
|
|
40
|
+
name: "arrows",
|
|
41
|
+
parsePrefix: (ctx) => {
|
|
42
|
+
const tok = current(ctx);
|
|
43
|
+
// Single-param arrow: identifier => expr
|
|
44
|
+
if (tok.type === "Identifier" && ctx.tokens[ctx.pos + 1]?.type === "Arrow") {
|
|
45
|
+
advance(ctx); // consume identifier
|
|
46
|
+
advance(ctx); // consume =>
|
|
47
|
+
const body = parseExpression(ctx, 0);
|
|
48
|
+
return {
|
|
49
|
+
type: "ArrowFunctionExpression",
|
|
50
|
+
params: [tok.value],
|
|
51
|
+
body,
|
|
52
|
+
start: tok.start,
|
|
53
|
+
end: body.end,
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
// Multi-param arrow: (a, b) => expr
|
|
57
|
+
if (tok.type === "Punctuation" && tok.value === "(" && isArrowParams(ctx)) {
|
|
58
|
+
return parseArrowFunction(ctx);
|
|
59
|
+
}
|
|
60
|
+
return null;
|
|
61
|
+
},
|
|
62
|
+
optimize: (node, opt) => {
|
|
63
|
+
if (node.type === "ArrowFunctionExpression") {
|
|
64
|
+
return { ...node, body: opt(node.body) };
|
|
65
|
+
}
|
|
66
|
+
return null;
|
|
67
|
+
},
|
|
68
|
+
evaluate: (node, context, evalFn) => {
|
|
69
|
+
if (node.type === "ArrowFunctionExpression") {
|
|
70
|
+
const n = node;
|
|
71
|
+
return {
|
|
72
|
+
value: (...args) => {
|
|
73
|
+
const childContext = { ...context };
|
|
74
|
+
for (let i = 0; i < n.params.length; i++) {
|
|
75
|
+
childContext[n.params[i]] = args[i];
|
|
76
|
+
}
|
|
77
|
+
return evalFn(n.body, childContext);
|
|
78
|
+
},
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
return null;
|
|
82
|
+
},
|
|
83
|
+
};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { current, advance } from "../parser/parser-context.js";
|
|
2
|
+
export const booleansPlugin = {
|
|
3
|
+
name: "booleans",
|
|
4
|
+
parsePrefix: (ctx) => {
|
|
5
|
+
const tok = current(ctx);
|
|
6
|
+
if (tok.type === "Boolean") {
|
|
7
|
+
advance(ctx);
|
|
8
|
+
return {
|
|
9
|
+
type: "BooleanLiteral",
|
|
10
|
+
value: tok.value === "true",
|
|
11
|
+
start: tok.start,
|
|
12
|
+
end: tok.end,
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
if (tok.type === "Null") {
|
|
16
|
+
advance(ctx);
|
|
17
|
+
return { type: "NullLiteral", value: null, start: tok.start, end: tok.end };
|
|
18
|
+
}
|
|
19
|
+
if (tok.type === "Undefined") {
|
|
20
|
+
advance(ctx);
|
|
21
|
+
return { type: "UndefinedLiteral", value: undefined, start: tok.start, end: tok.end };
|
|
22
|
+
}
|
|
23
|
+
return null;
|
|
24
|
+
},
|
|
25
|
+
evaluate: (node) => {
|
|
26
|
+
if (node.type === "BooleanLiteral")
|
|
27
|
+
return { value: node.value };
|
|
28
|
+
if (node.type === "NullLiteral")
|
|
29
|
+
return { value: null };
|
|
30
|
+
if (node.type === "UndefinedLiteral")
|
|
31
|
+
return { value: undefined };
|
|
32
|
+
return null;
|
|
33
|
+
},
|
|
34
|
+
};
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { current, advance } from "../parser/parser-context.js";
|
|
2
|
+
import { parseArrayLiteral } from "../parser/parse-array-literal.js";
|
|
3
|
+
import { parseObjectLiteral } from "../parser/parse-object-literal.js";
|
|
4
|
+
import { parseExpression } from "../parser/parse-expression.js";
|
|
5
|
+
export const collectionsPlugin = {
|
|
6
|
+
name: "collections",
|
|
7
|
+
parsePrefix: (ctx) => {
|
|
8
|
+
const tok = current(ctx);
|
|
9
|
+
// Array literal: [elements]
|
|
10
|
+
if (tok.type === "Punctuation" && tok.value === "[") {
|
|
11
|
+
return parseArrayLiteral(ctx);
|
|
12
|
+
}
|
|
13
|
+
// Object literal: { props }
|
|
14
|
+
if (tok.type === "Punctuation" && tok.value === "{") {
|
|
15
|
+
return parseObjectLiteral(ctx);
|
|
16
|
+
}
|
|
17
|
+
// Spread element: ...expr
|
|
18
|
+
if (tok.type === "Spread") {
|
|
19
|
+
advance(ctx);
|
|
20
|
+
const argument = parseExpression(ctx, 0);
|
|
21
|
+
return { type: "SpreadElement", argument, start: tok.start, end: argument.end };
|
|
22
|
+
}
|
|
23
|
+
return null;
|
|
24
|
+
},
|
|
25
|
+
optimize: (node, opt) => {
|
|
26
|
+
if (node.type === "ArrayLiteral") {
|
|
27
|
+
return { ...node, elements: node.elements.map((e) => opt(e)) };
|
|
28
|
+
}
|
|
29
|
+
if (node.type === "ObjectLiteral") {
|
|
30
|
+
return {
|
|
31
|
+
...node,
|
|
32
|
+
properties: node.properties.map((p) => ({
|
|
33
|
+
...p,
|
|
34
|
+
key: p.computed ? opt(p.key) : p.key,
|
|
35
|
+
value: opt(p.value),
|
|
36
|
+
})),
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
return null;
|
|
40
|
+
},
|
|
41
|
+
evaluate: (node, context, evalFn) => {
|
|
42
|
+
if (node.type === "ArrayLiteral") {
|
|
43
|
+
const result = [];
|
|
44
|
+
for (const element of node.elements) {
|
|
45
|
+
if (element.type === "SpreadElement") {
|
|
46
|
+
const spread = evalFn(element.argument, context);
|
|
47
|
+
result.push(...spread);
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
result.push(evalFn(element, context));
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return { value: result };
|
|
54
|
+
}
|
|
55
|
+
if (node.type === "ObjectLiteral") {
|
|
56
|
+
const result = {};
|
|
57
|
+
for (const prop of node.properties) {
|
|
58
|
+
const key = prop.computed
|
|
59
|
+
? evalFn(prop.key, context)
|
|
60
|
+
: prop.key.type === "Identifier"
|
|
61
|
+
? prop.key.name
|
|
62
|
+
: prop.key.value;
|
|
63
|
+
const value = evalFn(prop.value, context);
|
|
64
|
+
result[key] = value;
|
|
65
|
+
}
|
|
66
|
+
return { value: result };
|
|
67
|
+
}
|
|
68
|
+
return null;
|
|
69
|
+
},
|
|
70
|
+
};
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { current } from "../parser/parser-context.js";
|
|
2
|
+
const COMPARISON_PRECEDENCE = {
|
|
3
|
+
"==": 30,
|
|
4
|
+
"!=": 30,
|
|
5
|
+
"<": 40,
|
|
6
|
+
">": 40,
|
|
7
|
+
"<=": 40,
|
|
8
|
+
">=": 40,
|
|
9
|
+
};
|
|
10
|
+
export const comparisonPlugin = {
|
|
11
|
+
name: "comparison",
|
|
12
|
+
infixPrecedence: (ctx) => {
|
|
13
|
+
const tok = current(ctx);
|
|
14
|
+
if (tok.type === "Operator") {
|
|
15
|
+
return COMPARISON_PRECEDENCE[tok.value];
|
|
16
|
+
}
|
|
17
|
+
return undefined;
|
|
18
|
+
},
|
|
19
|
+
optimize: (node, opt) => {
|
|
20
|
+
if (node.type === "BinaryExpression" && node.operator in COMPARISON_PRECEDENCE) {
|
|
21
|
+
const left = opt(node.left);
|
|
22
|
+
const right = opt(node.right);
|
|
23
|
+
return { ...node, left, right };
|
|
24
|
+
}
|
|
25
|
+
return null;
|
|
26
|
+
},
|
|
27
|
+
evaluate: (node, context, evalFn) => {
|
|
28
|
+
if (node.type === "BinaryExpression") {
|
|
29
|
+
const op = node.operator;
|
|
30
|
+
if (op in COMPARISON_PRECEDENCE) {
|
|
31
|
+
const left = evalFn(node.left, context);
|
|
32
|
+
const right = evalFn(node.right, context);
|
|
33
|
+
switch (op) {
|
|
34
|
+
case "==":
|
|
35
|
+
return { value: left === right };
|
|
36
|
+
case "!=":
|
|
37
|
+
return { value: left !== right };
|
|
38
|
+
case "<":
|
|
39
|
+
return { value: left < right };
|
|
40
|
+
case ">":
|
|
41
|
+
return { value: left > right };
|
|
42
|
+
case "<=":
|
|
43
|
+
return { value: left <= right };
|
|
44
|
+
case ">=":
|
|
45
|
+
return { value: left >= right };
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return null;
|
|
50
|
+
},
|
|
51
|
+
};
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { current, advance } from "../parser/parser-context.js";
|
|
2
|
+
import { parseExpression } from "../parser/parse-expression.js";
|
|
3
|
+
const LOGICAL_PRECEDENCE = {
|
|
4
|
+
"||": 10,
|
|
5
|
+
"&&": 20,
|
|
6
|
+
"??": 25,
|
|
7
|
+
};
|
|
8
|
+
export const logicalPlugin = {
|
|
9
|
+
name: "logical",
|
|
10
|
+
infixPrecedence: (ctx) => {
|
|
11
|
+
const tok = current(ctx);
|
|
12
|
+
if (tok.type === "Operator" && (tok.value === "&&" || tok.value === "||")) {
|
|
13
|
+
return LOGICAL_PRECEDENCE[tok.value];
|
|
14
|
+
}
|
|
15
|
+
if (tok.type === "NullishCoalescing") {
|
|
16
|
+
return LOGICAL_PRECEDENCE["??"];
|
|
17
|
+
}
|
|
18
|
+
return undefined;
|
|
19
|
+
},
|
|
20
|
+
parseInfix: (ctx, left, minPrec) => {
|
|
21
|
+
const tok = current(ctx);
|
|
22
|
+
let op;
|
|
23
|
+
let prec;
|
|
24
|
+
if (tok.type === "Operator" && (tok.value === "&&" || tok.value === "||")) {
|
|
25
|
+
op = tok.value;
|
|
26
|
+
prec = LOGICAL_PRECEDENCE[op];
|
|
27
|
+
}
|
|
28
|
+
else if (tok.type === "NullishCoalescing") {
|
|
29
|
+
op = "??";
|
|
30
|
+
prec = LOGICAL_PRECEDENCE["??"];
|
|
31
|
+
}
|
|
32
|
+
if (op === undefined || prec === undefined || prec < minPrec)
|
|
33
|
+
return null;
|
|
34
|
+
advance(ctx);
|
|
35
|
+
const right = parseExpression(ctx, prec + 1);
|
|
36
|
+
return {
|
|
37
|
+
type: "BinaryExpression",
|
|
38
|
+
operator: op,
|
|
39
|
+
left,
|
|
40
|
+
right,
|
|
41
|
+
start: left.start,
|
|
42
|
+
end: right.end,
|
|
43
|
+
};
|
|
44
|
+
},
|
|
45
|
+
parseUnary: (ctx, parseNext) => {
|
|
46
|
+
const tok = current(ctx);
|
|
47
|
+
if (tok.type === "Operator" && tok.value === "!") {
|
|
48
|
+
advance(ctx);
|
|
49
|
+
const operand = parseNext(ctx);
|
|
50
|
+
return {
|
|
51
|
+
type: "UnaryExpression",
|
|
52
|
+
operator: "!",
|
|
53
|
+
operand,
|
|
54
|
+
start: tok.start,
|
|
55
|
+
end: operand.end,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
return null;
|
|
59
|
+
},
|
|
60
|
+
optimize: (node, opt) => {
|
|
61
|
+
if (node.type === "UnaryExpression" && node.operator === "!") {
|
|
62
|
+
const operand = opt(node.operand);
|
|
63
|
+
if (operand.type === "BooleanLiteral") {
|
|
64
|
+
return {
|
|
65
|
+
type: "BooleanLiteral",
|
|
66
|
+
value: !operand.value,
|
|
67
|
+
start: node.start,
|
|
68
|
+
end: node.end,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
return { ...node, operand };
|
|
72
|
+
}
|
|
73
|
+
if (node.type === "BinaryExpression" &&
|
|
74
|
+
(node.operator === "&&" || node.operator === "||" || node.operator === "??")) {
|
|
75
|
+
const left = opt(node.left);
|
|
76
|
+
const right = opt(node.right);
|
|
77
|
+
return { ...node, left, right };
|
|
78
|
+
}
|
|
79
|
+
return null;
|
|
80
|
+
},
|
|
81
|
+
evaluate: (node, context, evalFn) => {
|
|
82
|
+
if (node.type === "UnaryExpression" && node.operator === "!") {
|
|
83
|
+
const operand = evalFn(node.operand, context);
|
|
84
|
+
return { value: !operand };
|
|
85
|
+
}
|
|
86
|
+
if (node.type === "BinaryExpression") {
|
|
87
|
+
const op = node.operator;
|
|
88
|
+
if (op === "&&") {
|
|
89
|
+
const left = evalFn(node.left, context);
|
|
90
|
+
return { value: left ? evalFn(node.right, context) : left };
|
|
91
|
+
}
|
|
92
|
+
if (op === "||") {
|
|
93
|
+
const left = evalFn(node.left, context);
|
|
94
|
+
return { value: left ? left : evalFn(node.right, context) };
|
|
95
|
+
}
|
|
96
|
+
if (op === "??") {
|
|
97
|
+
const left = evalFn(node.left, context);
|
|
98
|
+
return { value: left != null ? left : evalFn(node.right, context) };
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
return null;
|
|
102
|
+
},
|
|
103
|
+
};
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { current, advance } from "../parser/parser-context.js";
|
|
2
|
+
import { parseExpression } from "../parser/parse-expression.js";
|
|
3
|
+
const MEMBERSHIP_PRECEDENCE = 40;
|
|
4
|
+
export const membershipPlugin = {
|
|
5
|
+
name: "membership",
|
|
6
|
+
infixPrecedence: (ctx) => {
|
|
7
|
+
const tok = current(ctx);
|
|
8
|
+
if (tok.type === "Operator" && tok.value === "in") {
|
|
9
|
+
return MEMBERSHIP_PRECEDENCE;
|
|
10
|
+
}
|
|
11
|
+
if (tok.type === "Operator" && tok.value === "not") {
|
|
12
|
+
const next = ctx.tokens[ctx.pos + 1];
|
|
13
|
+
if (next && next.type === "Operator" && next.value === "in") {
|
|
14
|
+
return MEMBERSHIP_PRECEDENCE;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
return undefined;
|
|
18
|
+
},
|
|
19
|
+
parseInfix: (ctx, left, minPrec) => {
|
|
20
|
+
const tok = current(ctx);
|
|
21
|
+
if (tok.type === "Operator" && tok.value === "in") {
|
|
22
|
+
if (MEMBERSHIP_PRECEDENCE < minPrec)
|
|
23
|
+
return null;
|
|
24
|
+
advance(ctx);
|
|
25
|
+
const right = parseExpression(ctx, MEMBERSHIP_PRECEDENCE + 1);
|
|
26
|
+
return {
|
|
27
|
+
type: "BinaryExpression",
|
|
28
|
+
operator: "in",
|
|
29
|
+
left,
|
|
30
|
+
right,
|
|
31
|
+
start: left.start,
|
|
32
|
+
end: right.end,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
if (tok.type === "Operator" && tok.value === "not") {
|
|
36
|
+
const next = ctx.tokens[ctx.pos + 1];
|
|
37
|
+
if (next && next.type === "Operator" && next.value === "in") {
|
|
38
|
+
if (MEMBERSHIP_PRECEDENCE < minPrec)
|
|
39
|
+
return null;
|
|
40
|
+
advance(ctx); // consume "not"
|
|
41
|
+
advance(ctx); // consume "in"
|
|
42
|
+
const right = parseExpression(ctx, MEMBERSHIP_PRECEDENCE + 1);
|
|
43
|
+
return {
|
|
44
|
+
type: "BinaryExpression",
|
|
45
|
+
operator: "not in",
|
|
46
|
+
left,
|
|
47
|
+
right,
|
|
48
|
+
start: left.start,
|
|
49
|
+
end: right.end,
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return null;
|
|
54
|
+
},
|
|
55
|
+
evaluate: (node, context, evalFn) => {
|
|
56
|
+
if (node.type === "BinaryExpression") {
|
|
57
|
+
const op = node.operator;
|
|
58
|
+
if (op === "in") {
|
|
59
|
+
const left = evalFn(node.left, context);
|
|
60
|
+
const right = evalFn(node.right, context);
|
|
61
|
+
return { value: left in right };
|
|
62
|
+
}
|
|
63
|
+
if (op === "not in") {
|
|
64
|
+
const left = evalFn(node.left, context);
|
|
65
|
+
const right = evalFn(node.right, context);
|
|
66
|
+
return { value: !(left in right) };
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return null;
|
|
70
|
+
},
|
|
71
|
+
};
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { current, advance } from "../parser/parser-context.js";
|
|
2
|
+
import { parsePipeTransform } from "../parser/parse-pipe-transform.js";
|
|
3
|
+
const PIPE_PRECEDENCE = 5;
|
|
4
|
+
export const pipePlugin = {
|
|
5
|
+
name: "pipe",
|
|
6
|
+
infixPrecedence: (ctx) => {
|
|
7
|
+
const tok = current(ctx);
|
|
8
|
+
if (tok.type === "Pipe") {
|
|
9
|
+
return PIPE_PRECEDENCE;
|
|
10
|
+
}
|
|
11
|
+
return undefined;
|
|
12
|
+
},
|
|
13
|
+
parseInfix: (ctx, left, minPrec) => {
|
|
14
|
+
const tok = current(ctx);
|
|
15
|
+
if (tok.type !== "Pipe")
|
|
16
|
+
return null;
|
|
17
|
+
if (PIPE_PRECEDENCE < minPrec)
|
|
18
|
+
return null;
|
|
19
|
+
advance(ctx);
|
|
20
|
+
const transform = parsePipeTransform(ctx);
|
|
21
|
+
return {
|
|
22
|
+
type: "PipeExpression",
|
|
23
|
+
input: left,
|
|
24
|
+
transform,
|
|
25
|
+
start: left.start,
|
|
26
|
+
end: transform.end,
|
|
27
|
+
};
|
|
28
|
+
},
|
|
29
|
+
optimize: (node, opt) => {
|
|
30
|
+
if (node.type === "PipeExpression") {
|
|
31
|
+
const n = node;
|
|
32
|
+
return {
|
|
33
|
+
...node,
|
|
34
|
+
input: opt(n.input),
|
|
35
|
+
transform: opt(n.transform),
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
return null;
|
|
39
|
+
},
|
|
40
|
+
evaluate: (node, context, evalFn) => {
|
|
41
|
+
if (node.type === "PipeExpression") {
|
|
42
|
+
const n = node;
|
|
43
|
+
const input = evalFn(n.input, context);
|
|
44
|
+
// If the transform is a call expression, append input as last argument
|
|
45
|
+
if (n.transform.type === "CallExpression") {
|
|
46
|
+
const args = n.transform.args.map((a) => evalFn(a, context));
|
|
47
|
+
args.push(input);
|
|
48
|
+
const fn = evalFn(n.transform.callee, context);
|
|
49
|
+
return { value: fn(...args) };
|
|
50
|
+
}
|
|
51
|
+
// Otherwise treat as a function and call with input as sole argument
|
|
52
|
+
const fn = evalFn(n.transform, context);
|
|
53
|
+
return { value: fn(input) };
|
|
54
|
+
}
|
|
55
|
+
return null;
|
|
56
|
+
},
|
|
57
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export function createResolvedIdentifierPlugin(options) {
|
|
2
|
+
const identifierSet = new Set(options.identifiers);
|
|
3
|
+
const argKeys = options.args;
|
|
4
|
+
return {
|
|
5
|
+
name: "resolved-identifier",
|
|
6
|
+
evaluate: (node, context) => {
|
|
7
|
+
if (node.type !== "Identifier")
|
|
8
|
+
return null;
|
|
9
|
+
if (!identifierSet.has(node.name))
|
|
10
|
+
return null;
|
|
11
|
+
const fn = context[node.name];
|
|
12
|
+
if (typeof fn !== "function") {
|
|
13
|
+
throw new Error(`Resolved identifier "${node.name}" is not a function in context`);
|
|
14
|
+
}
|
|
15
|
+
const args = argKeys.map((key) => context[key]);
|
|
16
|
+
return { value: fn(...args) };
|
|
17
|
+
},
|
|
18
|
+
};
|
|
19
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { Plugin } from "../plugin.js";
|
|
2
|
+
import { stringsPlugin } from "./strings.js";
|
|
3
|
+
import { booleansPlugin } from "./booleans.js";
|
|
4
|
+
import { comparisonPlugin } from "./comparison.js";
|
|
5
|
+
import { logicalPlugin } from "./logical.js";
|
|
6
|
+
import { ternaryPlugin } from "./ternary.js";
|
|
7
|
+
import { pipePlugin } from "./pipe.js";
|
|
8
|
+
import { membershipPlugin } from "./membership.js";
|
|
9
|
+
import { accessPlugin } from "./access.js";
|
|
10
|
+
import { arrowsPlugin } from "./arrows.js";
|
|
11
|
+
import { collectionsPlugin } from "./collections.js";
|
|
12
|
+
export declare const standardPlugins: Plugin[];
|
|
13
|
+
export { stringsPlugin, booleansPlugin, comparisonPlugin, logicalPlugin, ternaryPlugin, pipePlugin, membershipPlugin, accessPlugin, arrowsPlugin, collectionsPlugin, };
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { stringsPlugin } from "./strings.js";
|
|
2
|
+
import { booleansPlugin } from "./booleans.js";
|
|
3
|
+
import { comparisonPlugin } from "./comparison.js";
|
|
4
|
+
import { logicalPlugin } from "./logical.js";
|
|
5
|
+
import { ternaryPlugin } from "./ternary.js";
|
|
6
|
+
import { pipePlugin } from "./pipe.js";
|
|
7
|
+
import { membershipPlugin } from "./membership.js";
|
|
8
|
+
import { accessPlugin } from "./access.js";
|
|
9
|
+
import { arrowsPlugin } from "./arrows.js";
|
|
10
|
+
import { collectionsPlugin } from "./collections.js";
|
|
11
|
+
export const standardPlugins = [
|
|
12
|
+
arrowsPlugin,
|
|
13
|
+
collectionsPlugin,
|
|
14
|
+
stringsPlugin,
|
|
15
|
+
booleansPlugin,
|
|
16
|
+
comparisonPlugin,
|
|
17
|
+
logicalPlugin,
|
|
18
|
+
membershipPlugin,
|
|
19
|
+
ternaryPlugin,
|
|
20
|
+
pipePlugin,
|
|
21
|
+
accessPlugin,
|
|
22
|
+
];
|
|
23
|
+
export { stringsPlugin, booleansPlugin, comparisonPlugin, logicalPlugin, ternaryPlugin, pipePlugin, membershipPlugin, accessPlugin, arrowsPlugin, collectionsPlugin, };
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { current, advance } from "../parser/parser-context.js";
|
|
2
|
+
import { parseTemplateLiteral } from "../parser/parse-template-literal.js";
|
|
3
|
+
export const stringsPlugin = {
|
|
4
|
+
name: "strings",
|
|
5
|
+
parsePrefix: (ctx) => {
|
|
6
|
+
const tok = current(ctx);
|
|
7
|
+
if (tok.type === "String") {
|
|
8
|
+
advance(ctx);
|
|
9
|
+
return { type: "StringLiteral", value: tok.value.slice(1, -1), start: tok.start, end: tok.end };
|
|
10
|
+
}
|
|
11
|
+
if (tok.type === "TemplateLiteral") {
|
|
12
|
+
return parseTemplateLiteral(ctx);
|
|
13
|
+
}
|
|
14
|
+
return null;
|
|
15
|
+
},
|
|
16
|
+
optimize: (node, opt) => {
|
|
17
|
+
if (node.type === "TemplateLiteral") {
|
|
18
|
+
return {
|
|
19
|
+
...node,
|
|
20
|
+
parts: node.parts.map((p) => (p.type === "StringLiteral" ? p : opt(p))),
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
return null;
|
|
24
|
+
},
|
|
25
|
+
evaluate: (node, context, evalFn) => {
|
|
26
|
+
if (node.type === "StringLiteral") {
|
|
27
|
+
return { value: node.value };
|
|
28
|
+
}
|
|
29
|
+
if (node.type === "TemplateLiteral") {
|
|
30
|
+
const parts = node.parts;
|
|
31
|
+
let result = "";
|
|
32
|
+
for (const part of parts) {
|
|
33
|
+
if (part.type === "StringLiteral") {
|
|
34
|
+
result += part.value;
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
result += String(evalFn(part, context));
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return { value: result };
|
|
41
|
+
}
|
|
42
|
+
return null;
|
|
43
|
+
},
|
|
44
|
+
};
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { current, advance, expect } from "../parser/parser-context.js";
|
|
2
|
+
import { parseExpression } from "../parser/parse-expression.js";
|
|
3
|
+
import { isConstant } from "../compiler/is-constant.js";
|
|
4
|
+
import { valueOf } from "../compiler/value-of.js";
|
|
5
|
+
const TERNARY_PRECEDENCE = 1;
|
|
6
|
+
export const ternaryPlugin = {
|
|
7
|
+
name: "ternary",
|
|
8
|
+
infixPrecedence: (ctx) => {
|
|
9
|
+
const tok = current(ctx);
|
|
10
|
+
if (tok.type === "Punctuation" && tok.value === "?") {
|
|
11
|
+
return TERNARY_PRECEDENCE;
|
|
12
|
+
}
|
|
13
|
+
return undefined;
|
|
14
|
+
},
|
|
15
|
+
parseInfix: (ctx, left, minPrec) => {
|
|
16
|
+
const tok = current(ctx);
|
|
17
|
+
if (tok.type !== "Punctuation" || tok.value !== "?")
|
|
18
|
+
return null;
|
|
19
|
+
if (TERNARY_PRECEDENCE < minPrec)
|
|
20
|
+
return null;
|
|
21
|
+
advance(ctx);
|
|
22
|
+
const consequent = parseExpression(ctx, 0);
|
|
23
|
+
expect(ctx, "Punctuation", ":");
|
|
24
|
+
const alternate = parseExpression(ctx, 0);
|
|
25
|
+
return {
|
|
26
|
+
type: "ConditionalExpression",
|
|
27
|
+
test: left,
|
|
28
|
+
consequent,
|
|
29
|
+
alternate,
|
|
30
|
+
start: left.start,
|
|
31
|
+
end: alternate.end,
|
|
32
|
+
};
|
|
33
|
+
},
|
|
34
|
+
optimize: (node, opt) => {
|
|
35
|
+
if (node.type === "ConditionalExpression") {
|
|
36
|
+
const n = node;
|
|
37
|
+
const test = opt(n.test);
|
|
38
|
+
if (isConstant(test)) {
|
|
39
|
+
return valueOf(test) ? opt(n.consequent) : opt(n.alternate);
|
|
40
|
+
}
|
|
41
|
+
return {
|
|
42
|
+
...node,
|
|
43
|
+
test,
|
|
44
|
+
consequent: opt(n.consequent),
|
|
45
|
+
alternate: opt(n.alternate),
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
return null;
|
|
49
|
+
},
|
|
50
|
+
evaluate: (node, context, evalFn) => {
|
|
51
|
+
if (node.type === "ConditionalExpression") {
|
|
52
|
+
const n = node;
|
|
53
|
+
const test = evalFn(n.test, context);
|
|
54
|
+
return { value: test ? evalFn(n.consequent, context) : evalFn(n.alternate, context) };
|
|
55
|
+
}
|
|
56
|
+
return null;
|
|
57
|
+
},
|
|
58
|
+
};
|