@cloudpss/expression 0.6.0-alpha.8 → 0.6.0-beta.1

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 (157) hide show
  1. package/dist/analyze.d.ts +6 -3
  2. package/dist/analyze.d.ts.map +1 -1
  3. package/dist/analyze.js +13 -33
  4. package/dist/analyze.js.map +1 -1
  5. package/dist/definitions/argument.d.ts +3 -11
  6. package/dist/definitions/argument.d.ts.map +1 -1
  7. package/dist/definitions/constraint.d.ts +2 -2
  8. package/dist/definitions/constraint.d.ts.map +1 -1
  9. package/dist/definitions/constraint.js +1 -1
  10. package/dist/definitions/constraint.js.map +1 -1
  11. package/dist/definitions/parameter-group.js +4 -4
  12. package/dist/definitions/parameter-group.js.map +1 -1
  13. package/dist/definitions/parameter.d.ts +22 -14
  14. package/dist/definitions/parameter.d.ts.map +1 -1
  15. package/dist/definitions/parameter.js +10 -1
  16. package/dist/definitions/parameter.js.map +1 -1
  17. package/dist/definitions/utils.d.ts +28 -0
  18. package/dist/definitions/utils.d.ts.map +1 -0
  19. package/dist/definitions/utils.js +272 -0
  20. package/dist/definitions/utils.js.map +1 -0
  21. package/dist/definitions/variable.js +1 -1
  22. package/dist/definitions/variable.js.map +1 -1
  23. package/dist/definitions.d.ts +1 -2
  24. package/dist/definitions.d.ts.map +1 -1
  25. package/dist/definitions.js +1 -1
  26. package/dist/definitions.js.map +1 -1
  27. package/dist/eval.d.ts +3 -5
  28. package/dist/eval.d.ts.map +1 -1
  29. package/dist/eval.js +12 -20
  30. package/dist/eval.js.map +1 -1
  31. package/dist/expression.d.ts +10 -4
  32. package/dist/expression.d.ts.map +1 -1
  33. package/dist/expression.js +6 -6
  34. package/dist/expression.js.map +1 -1
  35. package/dist/index.d.ts +3 -1
  36. package/dist/index.d.ts.map +1 -1
  37. package/dist/index.js +1 -0
  38. package/dist/index.js.map +1 -1
  39. package/dist/interface.d.ts +30 -0
  40. package/dist/interface.d.ts.map +1 -0
  41. package/dist/interface.js +6 -0
  42. package/dist/interface.js.map +1 -0
  43. package/dist/main.d.ts +41 -28
  44. package/dist/main.d.ts.map +1 -1
  45. package/dist/main.js +165 -149
  46. package/dist/main.js.map +1 -1
  47. package/dist/migrate.d.ts +3 -2
  48. package/dist/migrate.d.ts.map +1 -1
  49. package/dist/migrate.js +25 -3
  50. package/dist/migrate.js.map +1 -1
  51. package/dist/migrator/access.d.ts.map +1 -1
  52. package/dist/migrator/access.js +65 -30
  53. package/dist/migrator/access.js.map +1 -1
  54. package/dist/migrator/call.d.ts.map +1 -1
  55. package/dist/migrator/call.js +298 -201
  56. package/dist/migrator/call.js.map +1 -1
  57. package/dist/migrator/concat.d.ts.map +1 -1
  58. package/dist/migrator/concat.js +15 -2
  59. package/dist/migrator/concat.js.map +1 -1
  60. package/dist/migrator/function.d.ts +6 -0
  61. package/dist/migrator/function.d.ts.map +1 -0
  62. package/dist/migrator/function.js +25 -0
  63. package/dist/migrator/function.js.map +1 -0
  64. package/dist/migrator/interface.d.ts +3 -1
  65. package/dist/migrator/interface.d.ts.map +1 -1
  66. package/dist/migrator/interface.js.map +1 -1
  67. package/dist/migrator/node.d.ts.map +1 -1
  68. package/dist/migrator/node.js +55 -7
  69. package/dist/migrator/node.js.map +1 -1
  70. package/dist/migrator/operator.d.ts.map +1 -1
  71. package/dist/migrator/operator.js +107 -60
  72. package/dist/migrator/operator.js.map +1 -1
  73. package/dist/migrator/serialize.d.ts +4 -0
  74. package/dist/migrator/serialize.d.ts.map +1 -0
  75. package/dist/migrator/serialize.js +21 -0
  76. package/dist/migrator/serialize.js.map +1 -0
  77. package/dist/migrator/special.d.ts.map +1 -1
  78. package/dist/migrator/special.js +31 -0
  79. package/dist/migrator/special.js.map +1 -1
  80. package/dist/migrator/state.d.ts +2 -2
  81. package/dist/migrator/state.d.ts.map +1 -1
  82. package/dist/migrator/state.js +30 -33
  83. package/dist/migrator/state.js.map +1 -1
  84. package/dist/migrator/symbol.d.ts.map +1 -1
  85. package/dist/migrator/symbol.js +34 -12
  86. package/dist/migrator/symbol.js.map +1 -1
  87. package/dist/migrator/to-type.d.ts.map +1 -1
  88. package/dist/migrator/to-type.js +21 -4
  89. package/dist/migrator/to-type.js.map +1 -1
  90. package/dist/migrator/utils.d.ts +6 -0
  91. package/dist/migrator/utils.d.ts.map +1 -1
  92. package/dist/migrator/utils.js +49 -1
  93. package/dist/migrator/utils.js.map +1 -1
  94. package/dist/parser.d.ts +2 -2
  95. package/dist/parser.d.ts.map +1 -1
  96. package/dist/parser.js +27 -8
  97. package/dist/parser.js.map +1 -1
  98. package/dist/re-exports.d.ts +4 -0
  99. package/dist/re-exports.d.ts.map +1 -0
  100. package/dist/re-exports.js +3 -0
  101. package/dist/re-exports.js.map +1 -0
  102. package/dist/scope.d.ts +17 -18
  103. package/dist/scope.d.ts.map +1 -1
  104. package/dist/scope.js +84 -53
  105. package/dist/scope.js.map +1 -1
  106. package/dist/type.d.ts +22 -10
  107. package/dist/type.d.ts.map +1 -1
  108. package/dist/type.js +21 -24
  109. package/dist/type.js.map +1 -1
  110. package/package.json +8 -5
  111. package/src/analyze.ts +20 -39
  112. package/src/definitions/argument.ts +3 -13
  113. package/src/definitions/constraint.ts +3 -3
  114. package/src/definitions/parameter-group.ts +4 -4
  115. package/src/definitions/parameter.ts +47 -24
  116. package/src/definitions/utils.ts +288 -0
  117. package/src/definitions/variable.ts +1 -1
  118. package/src/definitions.ts +1 -28
  119. package/src/eval.ts +16 -25
  120. package/src/expression.ts +16 -8
  121. package/src/index.ts +3 -1
  122. package/src/interface.ts +35 -0
  123. package/src/main.ts +232 -200
  124. package/src/migrate.ts +30 -6
  125. package/src/migrator/access.ts +68 -38
  126. package/src/migrator/call.ts +287 -190
  127. package/src/migrator/concat.ts +15 -2
  128. package/src/migrator/function.ts +27 -0
  129. package/src/migrator/interface.ts +3 -1
  130. package/src/migrator/node.ts +56 -6
  131. package/src/migrator/operator.ts +110 -64
  132. package/src/migrator/serialize.ts +21 -0
  133. package/src/migrator/special.ts +31 -0
  134. package/src/migrator/state.ts +30 -33
  135. package/src/migrator/symbol.ts +33 -12
  136. package/src/migrator/to-type.ts +23 -4
  137. package/src/migrator/utils.ts +49 -1
  138. package/src/parser.ts +33 -8
  139. package/src/re-exports.ts +47 -0
  140. package/src/scope.ts +101 -65
  141. package/src/type.ts +40 -25
  142. package/tests/analyze.ts +45 -6
  143. package/tests/compile.ts +65 -0
  144. package/tests/condition.ts +33 -17
  145. package/tests/definition.ts +237 -18
  146. package/tests/eval-complex.ts +19 -11
  147. package/tests/eval.ts +59 -12
  148. package/tests/import.ts +21 -7
  149. package/tests/main.ts +58 -0
  150. package/tests/migrate.ts +317 -0
  151. package/tests/scope.ts +3 -3
  152. package/tests/template.ts +36 -0
  153. package/dist/context.d.ts +0 -41
  154. package/dist/context.d.ts.map +0 -1
  155. package/dist/context.js +0 -18
  156. package/dist/context.js.map +0 -1
  157. package/src/context.ts +0 -54
@@ -1,10 +1,10 @@
1
- import { createVmContext, type VmContext } from '@mirascript/mirascript';
1
+ import type { VmContext } from '@mirascript/mirascript';
2
2
  import { parse } from './parser.js';
3
3
  import {
4
4
  type AssignmentNode,
5
- type FunctionAssignmentNode,
6
5
  isAssignmentNode,
7
6
  isBlockNode,
7
+ isConstantNode,
8
8
  isFunctionAssignmentNode,
9
9
  isSymbolNode,
10
10
  type MathNode,
@@ -12,9 +12,10 @@ import {
12
12
  import type { Result } from './interface.js';
13
13
  import { migrateAtomic } from './node.js';
14
14
  import { toBoolean } from './to-type.js';
15
- import { constantValue, symbolName, unsupportedNode } from './utils.js';
15
+ import { constantValue, migrateSymbolName, symbolName, unsupportedNode } from './utils.js';
16
16
  import { migrateAccess } from './access.js';
17
17
  import { specialMigrate } from './special.js';
18
+ import { migrateFunctionAssignment } from './function.js';
18
19
 
19
20
  /** 转换 AST */
20
21
  function migrateLast(state: State, node: MathNode): Result {
@@ -38,17 +39,20 @@ function migrateAssignment(state: State, node: AssignmentNode): Result {
38
39
  const { object, index, value } = node;
39
40
  const name = symbolName(object);
40
41
  if (name && index == null) {
41
- // name = xxx;
42
+ const localName = migrateSymbolName(name, true);
42
43
  if (state.locals.has(name)) {
43
- state.err(`不支持局部变量重新赋值: ${name}'`);
44
+ state.err(`不支持局部变量重新赋值: '${name}'`);
44
45
  return {
45
- code: `${name} = ${migrateAtomic(state, value).code}`,
46
+ code: `${localName} = ${migrateAtomic(state, value).code}`,
46
47
  };
47
48
  }
48
49
  const expr = migrateAtomic(state, value);
49
50
  state.locals.set(name, expr);
51
+ if (name !== localName) {
52
+ state.warn(`变量名 '${name}' 是 MiraScript 关键字,已转换为 '${localName}'`);
53
+ }
50
54
  return {
51
- code: `let ${name} = ${expr.code};`,
55
+ code: `let ${localName} = ${expr.code};`,
52
56
  };
53
57
  }
54
58
  if (index != null) {
@@ -60,26 +64,6 @@ function migrateAssignment(state: State, node: AssignmentNode): Result {
60
64
  }
61
65
  return unsupportedNode(state, node);
62
66
  }
63
- /** 转换函数定义语句 */
64
- function migrateFunctionAssignment(state: State, node: FunctionAssignmentNode): Result {
65
- state.loose();
66
- const { name, params, expr } = node;
67
- if (state.locals.has(name)) {
68
- state.err(`重复定义函数: ${name}`);
69
- }
70
- const fState = new FunctionState(state, params);
71
- let body = migrateAtomic(fState, expr);
72
- if (!(body.code.startsWith('{') && body.code.endsWith('}'))) {
73
- body = { ...body, code: `{ ${body.code} }` };
74
- }
75
- state.locals.set(name, {
76
- type: 'function',
77
- code: body.code,
78
- });
79
- return {
80
- code: `fn ${name}(${params.join(', ')}) ${body.code}`,
81
- };
82
- }
83
67
 
84
68
  /** 转换状态 */
85
69
  export class BaseState {
@@ -87,7 +71,7 @@ export class BaseState {
87
71
  private readonly expr: string,
88
72
  readonly condition: boolean,
89
73
  /** 可识别的全局环境 */
90
- readonly globals: VmContext = createVmContext(),
74
+ readonly globals: VmContext,
91
75
  ) {}
92
76
  /** 帮助函数 */
93
77
  private readonly helpers = new Set<string>();
@@ -126,7 +110,7 @@ export class BaseState {
126
110
  const r = isFunc ? migrateFunctionAssignment(this, node) : migrator(this, node);
127
111
  let { code } = r;
128
112
  if (stmt && !isFunc && !code.endsWith(';')) code += ';';
129
- if (node.comment) code += ' //' + node.comment;
113
+ if (node.comment) code += ' //' + node.comment.slice(1);
130
114
  this.ret.push(code);
131
115
  }
132
116
  /** 转换 */
@@ -143,7 +127,6 @@ export class BaseState {
143
127
  const sp = specialMigrate(this.expr, ast);
144
128
  if (sp != null) {
145
129
  this.ret.push(sp);
146
- this.loose();
147
130
  return;
148
131
  }
149
132
  if (isBlockNode(ast)) {
@@ -160,6 +143,8 @@ export class BaseState {
160
143
  }
161
144
  }
162
145
  return;
146
+ } else if (isConstantNode(ast) && ast.value === undefined && ast.comment) {
147
+ this.ret.push(`//${ast.comment.slice(1)}`);
163
148
  } else {
164
149
  this.migrateStmt(migrateLast, false, ast);
165
150
  return;
@@ -178,21 +163,33 @@ export class BaseState {
178
163
  // 写入原始 math.js 作为注释
179
164
  const lines = this.expr.split('\n').map((line) => `// ${line}`);
180
165
  lines.unshift(`// # 原始 math.js 表达式`);
166
+ const addComment = (prefix: string, item: string) => {
167
+ if (!item.includes('\n')) {
168
+ lines.unshift(`// ${prefix}: ${item}`);
169
+ return;
170
+ }
171
+ const l = item.split('\n');
172
+ const indent = ' '.repeat(prefix.length + 2);
173
+ for (let i = l.length - 1; i >= 1; i--) {
174
+ lines.unshift(`// ${indent}${l[i]}`);
175
+ }
176
+ lines.unshift(`// ${prefix}: ${l[0]}`);
177
+ };
181
178
  if (this.errors.size || this.warnings.size || this.critical.size) {
182
179
  const warnings = [...this.warnings];
183
180
  for (let i = warnings.length - 1; i >= 0; i--) {
184
181
  const warn = warnings[i]!;
185
- lines.unshift(`// - W: ${warn}`);
182
+ addComment('- W', warn);
186
183
  }
187
184
  const errors = [...this.errors];
188
185
  for (let i = errors.length - 1; i >= 0; i--) {
189
186
  const err = errors[i]!;
190
- lines.unshift(`// - E: ${err}`);
187
+ addComment('- E', err);
191
188
  }
192
189
  const critical = [...this.critical];
193
190
  for (let i = critical.length - 1; i >= 0; i--) {
194
191
  const crit = critical[i]!;
195
- lines.unshift(`// - C: ${crit}`);
192
+ addComment('- C', crit);
196
193
  }
197
194
  lines.unshift(`// # 转换日志`);
198
195
  }
@@ -2,6 +2,7 @@ import type { SymbolNode } from 'mathjs';
2
2
  import type { Result } from './interface.js';
3
3
  import type { State } from './state.js';
4
4
  import { operations } from '@mirascript/mirascript/subtle';
5
+ import { migrateSymbolName } from './utils.js';
5
6
 
6
7
  /** 处理符号名称 */
7
8
  export function migrateSymbol(state: State, node: SymbolNode, migrateConst: boolean): Result {
@@ -10,15 +11,23 @@ export function migrateSymbol(state: State, node: SymbolNode, migrateConst: bool
10
11
  if (local) {
11
12
  return {
12
13
  ...local,
13
- code: name,
14
+ code: migrateSymbolName(name, true),
14
15
  };
15
16
  }
16
- const global = state.globals.get(name);
17
- if (global != null) {
18
- return {
19
- type: operations.$Type(global),
20
- code: name,
21
- };
17
+ if (state.globals.has(name)) {
18
+ try {
19
+ const global = state.globals.get(name);
20
+ return {
21
+ type: operations.$Type(global),
22
+ code: migrateSymbolName(name, false),
23
+ global,
24
+ };
25
+ } catch {
26
+ return {
27
+ type: undefined,
28
+ code: migrateSymbolName(name, false),
29
+ };
30
+ }
22
31
  }
23
32
  if (name.startsWith('$') || name.startsWith('@')) {
24
33
  return {
@@ -33,21 +42,33 @@ export function migrateSymbol(state: State, node: SymbolNode, migrateConst: bool
33
42
  code: `i`,
34
43
  };
35
44
  }
36
- if (name === 'pi' || name === 'PI') {
45
+ if (name === 'pi') {
37
46
  return {
38
47
  type: 'number',
39
- code: `@pi`,
48
+ code: `PI`,
40
49
  };
41
50
  }
42
- if (name === 'e' || name === 'E') {
51
+ if (name === 'e') {
43
52
  return {
44
53
  type: 'number',
45
- code: `@e`,
54
+ code: `E`,
55
+ };
56
+ }
57
+ if (name === '__PREVIEW') {
58
+ return {
59
+ type: 'boolean',
60
+ code: '@PREVIEW',
61
+ };
62
+ }
63
+ if (name === '__ICON') {
64
+ return {
65
+ type: 'boolean',
66
+ code: '@ICON',
46
67
  };
47
68
  }
48
69
  }
49
70
  state.warn(`符号 '${name}' 未定义`);
50
71
  return {
51
- code: name,
72
+ code: migrateSymbolName(name, false),
52
73
  };
53
74
  }
@@ -1,13 +1,16 @@
1
1
  import { isConstantNode, isNode, type MathNode } from 'mathjs';
2
2
  import type { Result } from './interface.js';
3
- import { serialize } from '@mirascript/mirascript/subtle';
3
+ import { serialize } from './serialize.js';
4
4
  import type { State } from './state.js';
5
5
  import { migrateNode } from './node.js';
6
+ import { globalFnName } from './utils.js';
6
7
 
7
8
  /** 转换 AST */
8
9
  export function toBoolean(state: State, node: MathNode | Result): Result {
9
10
  const helper = (): void => {
10
- state.helper("fn @@to_boolean { it != '' && it != 0 && it is not nan && !!it }");
11
+ state.helper(
12
+ "fn @@to_boolean { if it is nil { nil } else { it != '' && it != '0' && it != 0 && it is not nan && it != false } }",
13
+ );
11
14
  };
12
15
  if (!isNode(node)) {
13
16
  if (node.type === 'boolean') return node;
@@ -46,9 +49,17 @@ export function toString(state: State, node: MathNode | Result): Result {
46
49
  code: node.as_string,
47
50
  };
48
51
  }
52
+ if (node.type === 'number' && node.literal !== undefined) {
53
+ const lit = String(node.literal);
54
+ return {
55
+ type: 'string',
56
+ literal: lit,
57
+ code: serialize(lit),
58
+ };
59
+ }
49
60
  return {
50
61
  type: 'string',
51
- code: `to_string(${node.code})`,
62
+ code: `${globalFnName(state, 'to_string')}(${node.code})`,
52
63
  };
53
64
  }
54
65
  if (isConstantNode(node)) {
@@ -74,9 +85,17 @@ export function toNumber(state: State, node: MathNode | Result): Result {
74
85
  code: node.as_number,
75
86
  };
76
87
  }
88
+ if ((node.type === 'string' || node.type === 'boolean') && node.literal !== undefined) {
89
+ const lit = Number(node.literal);
90
+ return {
91
+ type: 'number',
92
+ literal: lit,
93
+ code: serialize(lit),
94
+ };
95
+ }
77
96
  return {
78
97
  type: 'number',
79
- code: `to_number(${node.code})`,
98
+ code: `${globalFnName(state, 'to_number')}(${node.code})`,
80
99
  };
81
100
  }
82
101
  if (isConstantNode(node)) {
@@ -1,17 +1,44 @@
1
- import { type MathNode, isSymbolNode, isConstantNode } from 'mathjs';
1
+ import { type MathNode, isSymbolNode, isConstantNode, isOperatorNode } from 'mathjs';
2
+ import { keywords } from '@mirascript/mirascript/subtle';
2
3
  import type { Result } from './interface.js';
3
4
  import type { State } from './state.js';
4
5
  import { toString } from './to-type.js';
5
6
  import { migrateExpr } from './node.js';
6
7
 
8
+ /** 获取全局函数的名字 */
9
+ export function globalFnName(state: State, fnName: string): string {
10
+ if (state.locals.has(fnName)) {
11
+ return `global.${fnName}`;
12
+ }
13
+ return fnName;
14
+ }
15
+
7
16
  /** 获取 symbol name */
8
17
  export function symbolName(node: MathNode): string | undefined {
9
18
  if (!isSymbolNode(node)) return undefined;
10
19
  return node.name;
11
20
  }
12
21
 
22
+ const kw = new Set(keywords());
23
+ /** 转换为 mirascript 符号 */
24
+ export function migrateSymbolName(name: string, local: boolean): string {
25
+ if (!kw.has(name)) return name;
26
+ if (local) return `__${name}__`;
27
+ return `global.${name}`;
28
+ }
29
+
13
30
  /** 获取 constant value */
14
31
  export function constantValue(node: MathNode): number | string | boolean | null | undefined {
32
+ if (isOperatorNode(node) && node.args.length === 1) {
33
+ if (node.op === '+') {
34
+ const val = constantValue(node.args[0]!);
35
+ if (typeof val === 'number') return val;
36
+ } else if (node.op === '-') {
37
+ const val = constantValue(node.args[0]!);
38
+ if (typeof val === 'number') return -val;
39
+ }
40
+ return undefined;
41
+ }
15
42
  if (!isConstantNode(node)) return undefined;
16
43
  return node.value ?? null;
17
44
  }
@@ -65,3 +92,24 @@ export function equalText(state: State, op: '==' | '!=', l: MathNode, r: MathNod
65
92
  code: `${toString(state, lr).code} ${op} ${toString(state, rr).code}`,
66
93
  };
67
94
  }
95
+
96
+ /** 计算长度 */
97
+ export function len(state: State, obj: Result): Result {
98
+ if (obj.type === 'string')
99
+ return {
100
+ type: 'number',
101
+ code: `len(chars(${obj.code}))`,
102
+ };
103
+ if (obj.type === 'array')
104
+ return {
105
+ type: 'number',
106
+ code: `len(${obj.code})`,
107
+ };
108
+ state.helper(
109
+ `fn @@length(x) { if type(x) == 'string' { len(chars(x)) } else if type(x) == 'array' { len(x) } else { x.length } }`,
110
+ );
111
+ return {
112
+ type: 'number',
113
+ code: `@@length(${obj.code})`,
114
+ };
115
+ }
package/src/parser.ts CHANGED
@@ -1,5 +1,7 @@
1
1
  import { compileSync, type VmScript } from '@mirascript/mirascript';
2
- import type { Context } from './context.js';
2
+ import { LRUCache } from 'lru-cache';
3
+ import type { Evaluator } from './main.js';
4
+
3
5
  /** 一般表达式 */
4
6
  export interface EvalExpressionCache {
5
7
  /**
@@ -38,12 +40,12 @@ export type ExpressionCache = ErrorExpressionCache | EvalExpressionCache;
38
40
  /**
39
41
  * 编译表达式
40
42
  */
41
- function compile(expression: string): ExpressionCache {
43
+ function compile(expression: string, template: boolean): ExpressionCache {
42
44
  const compiled = {
43
45
  source: expression,
44
46
  } as ExpressionCache;
45
47
  try {
46
- const script = compileSync(expression);
48
+ const script = compileSync(expression, { input_mode: template ? 'Template' : 'Script' });
47
49
  compiled.func = script;
48
50
  } catch (ex) {
49
51
  compiled.error = ex as Error;
@@ -51,19 +53,42 @@ function compile(expression: string): ExpressionCache {
51
53
  return compiled;
52
54
  }
53
55
 
56
+ const kTemplateCache = Symbol('cloudpss.expression.templateCache');
57
+ const kExpressionCache = Symbol('cloudpss.expression.expressionCache');
58
+
59
+ /** 获取编译缓存 */
60
+ function getCache(evaluator: Evaluator | null, template: boolean): LRUCache<string, EvalExpressionCache> | null {
61
+ if (evaluator == null) return null;
62
+ const key = template ? kTemplateCache : kExpressionCache;
63
+ if (!(key in evaluator)) {
64
+ const size = template ? evaluator.options.templateCacheSize : evaluator.options.expressionCacheSize;
65
+ Object.defineProperty(evaluator, key, {
66
+ value: new LRUCache<string, EvalExpressionCache>({ max: size! || 50 }),
67
+ });
68
+ }
69
+ return (evaluator as Evaluator & Record<typeof key, LRUCache<string, EvalExpressionCache>>)[key];
70
+ }
71
+
54
72
  /**
55
73
  * 解析表达式
56
74
  */
57
- export function parse(context: Context, expression: string, throws: boolean): ExpressionCache {
75
+ export function parse(
76
+ evaluator: Evaluator | null,
77
+ expression: string,
78
+ throws: boolean,
79
+ template: boolean,
80
+ ): ExpressionCache {
58
81
  if (typeof expression != 'string') {
59
82
  throw new TypeError(`${String(expression)} is not a valid expression`);
60
83
  }
61
- const v = context.expressionCache.get(expression);
62
- if (v) return v;
63
- const complied = compile(expression);
84
+ const cache = getCache(evaluator, template);
85
+ const cached = cache?.get(expression);
86
+ if (cached != null) return cached;
87
+ const complied = compile(expression, template);
64
88
  if (complied.error) {
65
89
  if (throws) throw complied.error;
90
+ } else {
91
+ cache?.set(expression, complied);
66
92
  }
67
- context.expressionCache.set(expression, complied);
68
93
  return complied;
69
94
  }
@@ -0,0 +1,47 @@
1
+ export {
2
+ isVmAny,
3
+ isVmArray,
4
+ isVmConst,
5
+ isVmContext,
6
+ isVmExtern,
7
+ isVmFunction,
8
+ isVmImmutable,
9
+ isVmModule,
10
+ isVmPrimitive,
11
+ isVmRecord,
12
+ isVmArrayLikeRecord,
13
+ isVmArrayLikeRecordByEntires,
14
+ isVmArrayLikeRecordByKeys,
15
+ isVmCallable,
16
+ isVmScript,
17
+ isVmWrapper,
18
+ isVmValue,
19
+ VmExtern,
20
+ VmFunction,
21
+ VmModule,
22
+ VmError,
23
+ defineVmContextValue,
24
+ } from '@mirascript/mirascript';
25
+ export type {
26
+ VmScript,
27
+ VmValueMap,
28
+ VmAny,
29
+ VmArray,
30
+ VmConst,
31
+ VmContext,
32
+ VmImmutable,
33
+ VmPrimitive,
34
+ VmRecord,
35
+ VmUninitialized,
36
+ VmValue,
37
+ } from '@mirascript/mirascript';
38
+ export {
39
+ serialize,
40
+ serializeRecordKey,
41
+ serializeString,
42
+ type SerializeOptions,
43
+ constants,
44
+ DefaultVmContext,
45
+ lib,
46
+ operations,
47
+ } from '@mirascript/mirascript/subtle';