@cloudpss/expression 0.6.0-alpha.12 → 0.6.0-alpha.14
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/dist/eval.d.ts +2 -2
- package/dist/eval.d.ts.map +1 -1
- package/dist/eval.js +1 -1
- package/dist/eval.js.map +1 -1
- package/dist/migrator/function.d.ts +6 -0
- package/dist/migrator/function.d.ts.map +1 -0
- package/dist/migrator/function.js +25 -0
- package/dist/migrator/function.js.map +1 -0
- package/dist/migrator/node.d.ts.map +1 -1
- package/dist/migrator/node.js +12 -21
- package/dist/migrator/node.js.map +1 -1
- package/dist/migrator/operator.d.ts.map +1 -1
- package/dist/migrator/operator.js +2 -1
- package/dist/migrator/operator.js.map +1 -1
- package/dist/migrator/serialize.d.ts +4 -0
- package/dist/migrator/serialize.d.ts.map +1 -0
- package/dist/migrator/serialize.js +21 -0
- package/dist/migrator/serialize.js.map +1 -0
- package/dist/migrator/state.d.ts.map +1 -1
- package/dist/migrator/state.js +9 -25
- package/dist/migrator/state.js.map +1 -1
- package/dist/migrator/symbol.d.ts.map +1 -1
- package/dist/migrator/symbol.js +4 -3
- package/dist/migrator/symbol.js.map +1 -1
- package/dist/migrator/to-type.js +1 -1
- package/dist/migrator/to-type.js.map +1 -1
- package/dist/migrator/utils.d.ts +2 -0
- package/dist/migrator/utils.d.ts.map +1 -1
- package/dist/migrator/utils.js +10 -0
- package/dist/migrator/utils.js.map +1 -1
- package/dist/parser.d.ts +1 -1
- package/dist/parser.d.ts.map +1 -1
- package/dist/parser.js +4 -2
- package/dist/parser.js.map +1 -1
- package/dist/scope.d.ts +4 -0
- package/dist/scope.d.ts.map +1 -1
- package/dist/scope.js +29 -5
- package/dist/scope.js.map +1 -1
- package/package.json +2 -2
- package/src/eval.ts +7 -3
- package/src/migrator/function.ts +27 -0
- package/src/migrator/node.ts +12 -19
- package/src/migrator/operator.ts +2 -1
- package/src/migrator/serialize.ts +21 -0
- package/src/migrator/state.ts +9 -26
- package/src/migrator/symbol.ts +4 -3
- package/src/migrator/to-type.ts +1 -1
- package/src/migrator/utils.ts +9 -0
- package/src/parser.ts +10 -4
- package/src/scope.ts +27 -5
- package/tests/migrate.ts +30 -0
package/dist/scope.d.ts
CHANGED
|
@@ -18,6 +18,10 @@ export declare class Scope {
|
|
|
18
18
|
throws?: boolean,
|
|
19
19
|
/** 执行环境名称 */
|
|
20
20
|
name?: string);
|
|
21
|
+
/** 枚举环境中的值 */
|
|
22
|
+
enumerator: (() => Iterable<string>) | null | undefined;
|
|
23
|
+
/** 描述环境中的值 */
|
|
24
|
+
describer: ((key: string) => string | undefined) | null | undefined;
|
|
21
25
|
/** 执行器上下文 */
|
|
22
26
|
protected evaluator: Evaluator | null;
|
|
23
27
|
/** 求值计数 */
|
package/dist/scope.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scope.d.ts","sourceRoot":"","sources":["../src/scope.ts"],"names":[],"mappings":"AAAA,OAAO,EAKH,KAAK,SAAS,EAEd,KAAK,OAAO,EAEf,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACH,KAAK,kBAAkB,EACvB,KAAK,UAAU,EACf,KAAK,iBAAiB,EAGzB,MAAM,iBAAiB,CAAC;AAIzB,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AA8D3C,cAAc;AACd,qBAAa,KAAK;IAIV,gBAAgB;IAChB,QAAQ,CAAC,KAAK,EACR,CAAC,CAAC,GAAG,EAAE,MAAM,KAAK,iBAAiB,GAAG,SAAS,CAAC,GAChD,MAAM,CAAC,MAAM,EAAE,iBAAiB,GAAG,SAAS,CAAC,GAC7C,IAAI;IACV,gBAAgB;IAChB,QAAQ,CAAC,MAAM;IACf,aAAa;IACb,QAAQ,CAAC,IAAI;IAXjB,aAAa;IACb,MAAM,CAAC,QAAQ,CAAC,aAAa,OAAO;;IAEhC,gBAAgB;IACP,KAAK,GACR,CAAC,CAAC,GAAG,EAAE,MAAM,KAAK,iBAAiB,GAAG,SAAS,CAAC,GAChD,MAAM,CAAC,MAAM,EAAE,iBAAiB,GAAG,SAAS,CAAC,GAC7C,IAAW;IACjB,gBAAgB;IACP,MAAM,UAAO;IACtB,aAAa;IACJ,IAAI,SAAgB;
|
|
1
|
+
{"version":3,"file":"scope.d.ts","sourceRoot":"","sources":["../src/scope.ts"],"names":[],"mappings":"AAAA,OAAO,EAKH,KAAK,SAAS,EAEd,KAAK,OAAO,EAEf,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACH,KAAK,kBAAkB,EACvB,KAAK,UAAU,EACf,KAAK,iBAAiB,EAGzB,MAAM,iBAAiB,CAAC;AAIzB,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AA8D3C,cAAc;AACd,qBAAa,KAAK;IAIV,gBAAgB;IAChB,QAAQ,CAAC,KAAK,EACR,CAAC,CAAC,GAAG,EAAE,MAAM,KAAK,iBAAiB,GAAG,SAAS,CAAC,GAChD,MAAM,CAAC,MAAM,EAAE,iBAAiB,GAAG,SAAS,CAAC,GAC7C,IAAI;IACV,gBAAgB;IAChB,QAAQ,CAAC,MAAM;IACf,aAAa;IACb,QAAQ,CAAC,IAAI;IAXjB,aAAa;IACb,MAAM,CAAC,QAAQ,CAAC,aAAa,OAAO;;IAEhC,gBAAgB;IACP,KAAK,GACR,CAAC,CAAC,GAAG,EAAE,MAAM,KAAK,iBAAiB,GAAG,SAAS,CAAC,GAChD,MAAM,CAAC,MAAM,EAAE,iBAAiB,GAAG,SAAS,CAAC,GAC7C,IAAW;IACjB,gBAAgB;IACP,MAAM,UAAO;IACtB,aAAa;IACJ,IAAI,SAAgB;IAEjC,cAAc;IACd,UAAU,EAAE,CAAC,MAAM,QAAQ,CAAC,MAAM,CAAC,CAAC,GAAG,IAAI,GAAG,SAAS,CAAQ;IAC/D,cAAc;IACd,SAAS,EAAE,CAAC,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC,GAAG,IAAI,GAAG,SAAS,CAAQ;IAE3E,aAAa;IACb,SAAS,CAAC,SAAS,EAAE,SAAS,GAAG,IAAI,CAAQ;IAC7C,WAAW;IACX,SAAS,CAAC,WAAW,SAAK;IAC1B,YAAY;IACZ,KAAK,CAAC,SAAS,EAAE,SAAS,GAAG,IAAI,GAAG,MAAM,IAAI;IAU9C,mBAAmB;IACnB,SAAS,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAAQ;IAC1C,mBAAmB;IACnB,IAAI,KAAK,IAAI,SAAS,CA4CrB;IAED,oDAAoD;IACpD,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAYzB,kDAAkD;IAClD,GAAG,CAAC,CAAC,SAAS,OAAO,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,GAAG,SAAS;IAalD,cAAc;IACd,IAAI,CAAC,UAAU,EAAE,UAAU,GAAG,kBAAkB,EAAE,IAAI,EAAE,SAAS,WAAW,EAAE,GAAG,OAAO;CA2B3F;AAmBD,eAAe;AACf,wBAAgB,MAAM,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,CAAC,CAErC"}
|
package/dist/scope.js
CHANGED
|
@@ -72,6 +72,10 @@ export class Scope {
|
|
|
72
72
|
this.scope = scope;
|
|
73
73
|
this.throws = throws;
|
|
74
74
|
this.name = name;
|
|
75
|
+
/** 枚举环境中的值 */
|
|
76
|
+
this.enumerator = null;
|
|
77
|
+
/** 描述环境中的值 */
|
|
78
|
+
this.describer = null;
|
|
75
79
|
/** 执行器上下文 */
|
|
76
80
|
this.evaluator = null;
|
|
77
81
|
/** 求值计数 */
|
|
@@ -95,9 +99,13 @@ export class Scope {
|
|
|
95
99
|
if (this._proxy != null)
|
|
96
100
|
return this._proxy;
|
|
97
101
|
let getter;
|
|
98
|
-
|
|
102
|
+
let enumerate;
|
|
103
|
+
let describe;
|
|
104
|
+
const { scope, enumerator, describer } = this;
|
|
99
105
|
if (scope == null) {
|
|
100
106
|
getter = (key) => this.evaluator?.imported.get(key);
|
|
107
|
+
enumerate = () => this.evaluator?.imported.keys() ?? [];
|
|
108
|
+
describe = () => undefined;
|
|
101
109
|
}
|
|
102
110
|
else if (typeof scope == 'function') {
|
|
103
111
|
getter = (key) => {
|
|
@@ -119,7 +127,25 @@ export class Scope {
|
|
|
119
127
|
return createProxy(v, this, [key]);
|
|
120
128
|
};
|
|
121
129
|
}
|
|
122
|
-
|
|
130
|
+
if (typeof enumerator == 'function') {
|
|
131
|
+
enumerate = () => {
|
|
132
|
+
const keys = enumerator();
|
|
133
|
+
const imported = this.evaluator?.imported.keys() ?? [];
|
|
134
|
+
return [...keys, ...imported];
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
else {
|
|
138
|
+
enumerate = () => this.evaluator?.imported.keys() ?? [];
|
|
139
|
+
}
|
|
140
|
+
if (typeof describer == 'function') {
|
|
141
|
+
describe = (key) => {
|
|
142
|
+
const d = describer(key);
|
|
143
|
+
if (d)
|
|
144
|
+
return d;
|
|
145
|
+
return undefined;
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
const proxy = createVmContext(getter, enumerate, describe);
|
|
123
149
|
this._proxy = proxy;
|
|
124
150
|
return proxy;
|
|
125
151
|
}
|
|
@@ -156,6 +182,7 @@ export class Scope {
|
|
|
156
182
|
/** 表达式递归求值 */
|
|
157
183
|
eval(expression, path) {
|
|
158
184
|
if (this.evalCounter >= Scope.MAX_RECURSION) {
|
|
185
|
+
this.evalCounter = 0;
|
|
159
186
|
throw new Error(`Execution recursion exceeds limit`);
|
|
160
187
|
}
|
|
161
188
|
this.evalCounter++;
|
|
@@ -166,9 +193,6 @@ export class Scope {
|
|
|
166
193
|
}
|
|
167
194
|
else {
|
|
168
195
|
const { evaluator } = this;
|
|
169
|
-
if (!evaluator) {
|
|
170
|
-
throw new Error(`Undefined evaluator`);
|
|
171
|
-
}
|
|
172
196
|
const exp = parse(evaluator, expression.source, this.throws, false);
|
|
173
197
|
if (exp.func != null) {
|
|
174
198
|
result = evaluateEval(evaluator, exp, this);
|
package/dist/scope.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scope.js","sourceRoot":"","sources":["../src/scope.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"scope.js","sourceRoot":"","sources":["../src/scope.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cloudpss/expression",
|
|
3
|
-
"version": "0.6.0-alpha.
|
|
3
|
+
"version": "0.6.0-alpha.14",
|
|
4
4
|
"author": "CloudPSS",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
"./*": "./dist/*.js"
|
|
13
13
|
},
|
|
14
14
|
"dependencies": {
|
|
15
|
-
"@mirascript/mirascript": "^0.1.
|
|
15
|
+
"@mirascript/mirascript": "^0.1.13",
|
|
16
16
|
"klona": "^2.0.6",
|
|
17
17
|
"lru-cache": "^11.2.2",
|
|
18
18
|
"mathjs": "^15.1.0",
|
package/src/eval.ts
CHANGED
|
@@ -7,7 +7,7 @@ import type { Evaluator } from './main.js';
|
|
|
7
7
|
* 表达式求值
|
|
8
8
|
*/
|
|
9
9
|
export function evaluateEval<T extends VmValue>(
|
|
10
|
-
evaluator: Evaluator,
|
|
10
|
+
evaluator: Evaluator | null,
|
|
11
11
|
expression: EvalExpressionCache,
|
|
12
12
|
scope: Scope,
|
|
13
13
|
): T | null {
|
|
@@ -17,7 +17,7 @@ export function evaluateEval<T extends VmValue>(
|
|
|
17
17
|
return unwrap(result as T);
|
|
18
18
|
} catch (error: unknown) {
|
|
19
19
|
if (scope.throws) throw error;
|
|
20
|
-
evaluator
|
|
20
|
+
(evaluator?.logger ?? console).warn(
|
|
21
21
|
`Failed to execute expression "${expression.source}": ${(error as Error).message || String(error)}.`,
|
|
22
22
|
{
|
|
23
23
|
error,
|
|
@@ -31,7 +31,11 @@ export function evaluateEval<T extends VmValue>(
|
|
|
31
31
|
/**
|
|
32
32
|
* 表达式求值
|
|
33
33
|
*/
|
|
34
|
-
export function evaluate<T extends VmValue>(
|
|
34
|
+
export function evaluate<T extends VmValue>(
|
|
35
|
+
evaluator: Evaluator | null,
|
|
36
|
+
expression: ExpressionCache,
|
|
37
|
+
scope: Scope,
|
|
38
|
+
): T | null {
|
|
35
39
|
let ret: T | null = null;
|
|
36
40
|
if (expression.func != null) {
|
|
37
41
|
scope ??= new Scope();
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { FunctionAssignmentNode } from 'mathjs';
|
|
2
|
+
import type { Result } from './interface.js';
|
|
3
|
+
import { migrateAtomic } from './node.js';
|
|
4
|
+
import { type State, FunctionState } from './state.js';
|
|
5
|
+
import { migrateSymbolName } from './utils.js';
|
|
6
|
+
|
|
7
|
+
/** 转换函数定义语句 */
|
|
8
|
+
export function migrateFunctionAssignment(state: State, node: FunctionAssignmentNode): Result {
|
|
9
|
+
state.loose();
|
|
10
|
+
const { name, params, expr } = node;
|
|
11
|
+
const fState = new FunctionState(state, params);
|
|
12
|
+
let body = migrateAtomic(fState, expr);
|
|
13
|
+
if (!(body.code.startsWith('{') && body.code.endsWith('}'))) {
|
|
14
|
+
body = { ...body, code: `{ ${body.code} }` };
|
|
15
|
+
}
|
|
16
|
+
if (state.locals.has(name)) {
|
|
17
|
+
state.err(`重复定义函数: '${name}'`);
|
|
18
|
+
}
|
|
19
|
+
state.locals.set(name, {
|
|
20
|
+
type: 'function',
|
|
21
|
+
code: body.code,
|
|
22
|
+
});
|
|
23
|
+
return {
|
|
24
|
+
type: 'function',
|
|
25
|
+
code: `fn ${migrateSymbolName(name, true)}(${params.join(', ')}) ${body.code}`,
|
|
26
|
+
};
|
|
27
|
+
}
|
package/src/migrator/node.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { serializePropName } from '@mirascript/mirascript/subtle';
|
|
2
2
|
import {
|
|
3
3
|
type MathNode,
|
|
4
4
|
isAccessorNode,
|
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
isRelationalNode,
|
|
13
13
|
type OperatorNodeFn,
|
|
14
14
|
isSymbolNode,
|
|
15
|
+
isFunctionAssignmentNode,
|
|
15
16
|
} from 'mathjs';
|
|
16
17
|
import type { State } from './state.js';
|
|
17
18
|
import type { Options, Result } from './interface.js';
|
|
@@ -22,6 +23,8 @@ import { migrateCall } from './call.js';
|
|
|
22
23
|
import { migrateOperator } from './operator.js';
|
|
23
24
|
import { migrateSymbol } from './symbol.js';
|
|
24
25
|
import { migrateCondition } from './condition.js';
|
|
26
|
+
import { migrateFunctionAssignment } from './function.js';
|
|
27
|
+
import { serialize } from './serialize.js';
|
|
25
28
|
|
|
26
29
|
/** 转换 AST */
|
|
27
30
|
export function migrateAtomic(state: State, node: MathNode): Result {
|
|
@@ -41,23 +44,6 @@ export function migrateNode(state: State, node: MathNode, options: Options): Res
|
|
|
41
44
|
if (isConstantNode(node)) {
|
|
42
45
|
const { value } = node;
|
|
43
46
|
if (value == null) return { code: 'nil', literal: null, type: 'nil' };
|
|
44
|
-
if (typeof value === 'number' && Number.isFinite(value) && value !== 0) {
|
|
45
|
-
const p1 = value.toString();
|
|
46
|
-
const p2 = value.toExponential();
|
|
47
|
-
if (p2.length < p1.length) {
|
|
48
|
-
return {
|
|
49
|
-
code: p2,
|
|
50
|
-
literal: value,
|
|
51
|
-
type: 'number',
|
|
52
|
-
};
|
|
53
|
-
} else {
|
|
54
|
-
return {
|
|
55
|
-
code: p1,
|
|
56
|
-
literal: value,
|
|
57
|
-
type: 'number',
|
|
58
|
-
};
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
47
|
return {
|
|
62
48
|
code: serialize(value),
|
|
63
49
|
literal: value,
|
|
@@ -141,8 +127,15 @@ export function migrateNode(state: State, node: MathNode, options: Options): Res
|
|
|
141
127
|
code,
|
|
142
128
|
};
|
|
143
129
|
}
|
|
130
|
+
if (isFunctionAssignmentNode(node)) {
|
|
131
|
+
const result = migrateFunctionAssignment(state, node);
|
|
132
|
+
state.helper(result.code);
|
|
133
|
+
return {
|
|
134
|
+
type: 'function',
|
|
135
|
+
code: node.name,
|
|
136
|
+
};
|
|
137
|
+
}
|
|
144
138
|
// if (isRangeNode(node)) {
|
|
145
139
|
// if (isIndexNode(node)) {
|
|
146
|
-
// if (isFunctionAssignmentNode(node)) {
|
|
147
140
|
return unsupportedNode(state, node);
|
|
148
141
|
}
|
package/src/migrator/operator.ts
CHANGED
|
@@ -8,13 +8,14 @@ import {
|
|
|
8
8
|
isOperatorNode,
|
|
9
9
|
isNode,
|
|
10
10
|
} from 'mathjs';
|
|
11
|
+
import { operations } from '@mirascript/mirascript/subtle';
|
|
11
12
|
import { symbolName, constantValue, equalText, scalar, globalFnName } from './utils.js';
|
|
12
13
|
import type { State } from './state.js';
|
|
13
14
|
import type { Options, Result } from './interface.js';
|
|
14
15
|
import { migrateAtomic, migrateExpr } from './node.js';
|
|
15
16
|
import { toBoolean, toNumber } from './to-type.js';
|
|
16
17
|
import { migrateSymbol } from './symbol.js';
|
|
17
|
-
import {
|
|
18
|
+
import { serialize } from './serialize.js';
|
|
18
19
|
|
|
19
20
|
const BINARY_MATH_OPERATORS = {
|
|
20
21
|
add: [
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { VmValue } from '@mirascript/mirascript';
|
|
2
|
+
import { serialize as s, serializeNumber } from '@mirascript/mirascript/subtle';
|
|
3
|
+
|
|
4
|
+
/** 序列化 */
|
|
5
|
+
export function serialize(value: VmValue): string {
|
|
6
|
+
return s(value, {
|
|
7
|
+
serializeNumber: (value: number): string => {
|
|
8
|
+
if (!Number.isFinite(value) || value === 0) {
|
|
9
|
+
return serializeNumber(value);
|
|
10
|
+
}
|
|
11
|
+
const p1 = value.toString();
|
|
12
|
+
const p2 = value.toExponential();
|
|
13
|
+
// 还是优先选择默认的形式,除非指数形式更短很多
|
|
14
|
+
if (p2.length + 2 < p1.length) {
|
|
15
|
+
return p2;
|
|
16
|
+
} else {
|
|
17
|
+
return p1;
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
});
|
|
21
|
+
}
|
package/src/migrator/state.ts
CHANGED
|
@@ -2,7 +2,6 @@ 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,
|
|
8
7
|
isFunctionAssignmentNode,
|
|
@@ -12,9 +11,10 @@ import {
|
|
|
12
11
|
import type { Result } from './interface.js';
|
|
13
12
|
import { migrateAtomic } from './node.js';
|
|
14
13
|
import { toBoolean } from './to-type.js';
|
|
15
|
-
import { constantValue, symbolName, unsupportedNode } from './utils.js';
|
|
14
|
+
import { constantValue, migrateSymbolName, symbolName, unsupportedNode } from './utils.js';
|
|
16
15
|
import { migrateAccess } from './access.js';
|
|
17
16
|
import { specialMigrate } from './special.js';
|
|
17
|
+
import { migrateFunctionAssignment } from './function.js';
|
|
18
18
|
|
|
19
19
|
/** 转换 AST */
|
|
20
20
|
function migrateLast(state: State, node: MathNode): Result {
|
|
@@ -38,17 +38,20 @@ function migrateAssignment(state: State, node: AssignmentNode): Result {
|
|
|
38
38
|
const { object, index, value } = node;
|
|
39
39
|
const name = symbolName(object);
|
|
40
40
|
if (name && index == null) {
|
|
41
|
-
|
|
41
|
+
const localName = migrateSymbolName(name, true);
|
|
42
42
|
if (state.locals.has(name)) {
|
|
43
|
-
state.err(`不支持局部变量重新赋值: ${name}'`);
|
|
43
|
+
state.err(`不支持局部变量重新赋值: '${name}'`);
|
|
44
44
|
return {
|
|
45
|
-
code: `${
|
|
45
|
+
code: `${localName} = ${migrateAtomic(state, value).code}`,
|
|
46
46
|
};
|
|
47
47
|
}
|
|
48
48
|
const expr = migrateAtomic(state, value);
|
|
49
49
|
state.locals.set(name, expr);
|
|
50
|
+
if (name !== localName) {
|
|
51
|
+
state.warn(`变量名 '${name}' 是 MiraScript 关键字,已转换为 '${localName}'`);
|
|
52
|
+
}
|
|
50
53
|
return {
|
|
51
|
-
code: `let ${
|
|
54
|
+
code: `let ${localName} = ${expr.code};`,
|
|
52
55
|
};
|
|
53
56
|
}
|
|
54
57
|
if (index != null) {
|
|
@@ -60,26 +63,6 @@ function migrateAssignment(state: State, node: AssignmentNode): Result {
|
|
|
60
63
|
}
|
|
61
64
|
return unsupportedNode(state, node);
|
|
62
65
|
}
|
|
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
66
|
|
|
84
67
|
/** 转换状态 */
|
|
85
68
|
export class BaseState {
|
package/src/migrator/symbol.ts
CHANGED
|
@@ -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,14 +11,14 @@ 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
17
|
const global = state.globals.get(name);
|
|
17
18
|
if (global != null) {
|
|
18
19
|
return {
|
|
19
20
|
type: operations.$Type(global),
|
|
20
|
-
code: name,
|
|
21
|
+
code: migrateSymbolName(name, false),
|
|
21
22
|
global,
|
|
22
23
|
};
|
|
23
24
|
}
|
|
@@ -61,6 +62,6 @@ export function migrateSymbol(state: State, node: SymbolNode, migrateConst: bool
|
|
|
61
62
|
}
|
|
62
63
|
state.warn(`符号 '${name}' 未定义`);
|
|
63
64
|
return {
|
|
64
|
-
code: name,
|
|
65
|
+
code: migrateSymbolName(name, false),
|
|
65
66
|
};
|
|
66
67
|
}
|
package/src/migrator/to-type.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { isConstantNode, isNode, type MathNode } from 'mathjs';
|
|
2
2
|
import type { Result } from './interface.js';
|
|
3
|
-
import { serialize } from '
|
|
3
|
+
import { serialize } from './serialize.js';
|
|
4
4
|
import type { State } from './state.js';
|
|
5
5
|
import { migrateNode } from './node.js';
|
|
6
6
|
import { globalFnName } from './utils.js';
|
package/src/migrator/utils.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { type MathNode, isSymbolNode, isConstantNode } 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';
|
|
@@ -18,6 +19,14 @@ export function symbolName(node: MathNode): string | undefined {
|
|
|
18
19
|
return node.name;
|
|
19
20
|
}
|
|
20
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
|
+
|
|
21
30
|
/** 获取 constant value */
|
|
22
31
|
export function constantValue(node: MathNode): number | string | boolean | null | undefined {
|
|
23
32
|
if (!isConstantNode(node)) return undefined;
|
package/src/parser.ts
CHANGED
|
@@ -57,7 +57,8 @@ const kTemplateCache = Symbol('cloudpss.expression.templateCache');
|
|
|
57
57
|
const kExpressionCache = Symbol('cloudpss.expression.expressionCache');
|
|
58
58
|
|
|
59
59
|
/** 获取编译缓存 */
|
|
60
|
-
function getCache(evaluator: Evaluator, template: boolean): LRUCache<string, EvalExpressionCache> {
|
|
60
|
+
function getCache(evaluator: Evaluator | null, template: boolean): LRUCache<string, EvalExpressionCache> | null {
|
|
61
|
+
if (evaluator == null) return null;
|
|
61
62
|
const key = template ? kTemplateCache : kExpressionCache;
|
|
62
63
|
if (!(key in evaluator)) {
|
|
63
64
|
const size = template ? evaluator.options.templateCacheSize : evaluator.options.expressionCacheSize;
|
|
@@ -71,18 +72,23 @@ function getCache(evaluator: Evaluator, template: boolean): LRUCache<string, Eva
|
|
|
71
72
|
/**
|
|
72
73
|
* 解析表达式
|
|
73
74
|
*/
|
|
74
|
-
export function parse(
|
|
75
|
+
export function parse(
|
|
76
|
+
evaluator: Evaluator | null,
|
|
77
|
+
expression: string,
|
|
78
|
+
throws: boolean,
|
|
79
|
+
template: boolean,
|
|
80
|
+
): ExpressionCache {
|
|
75
81
|
if (typeof expression != 'string') {
|
|
76
82
|
throw new TypeError(`${String(expression)} is not a valid expression`);
|
|
77
83
|
}
|
|
78
84
|
const cache = getCache(evaluator, template);
|
|
79
|
-
const cached = cache
|
|
85
|
+
const cached = cache?.get(expression);
|
|
80
86
|
if (cached != null) return cached;
|
|
81
87
|
const complied = compile(expression, template);
|
|
82
88
|
if (complied.error) {
|
|
83
89
|
if (throws) throw complied.error;
|
|
84
90
|
} else {
|
|
85
|
-
cache
|
|
91
|
+
cache?.set(expression, complied);
|
|
86
92
|
}
|
|
87
93
|
return complied;
|
|
88
94
|
}
|
package/src/scope.ts
CHANGED
|
@@ -95,6 +95,10 @@ export class Scope {
|
|
|
95
95
|
/** 执行环境名称 */
|
|
96
96
|
readonly name = '<anonymous>',
|
|
97
97
|
) {}
|
|
98
|
+
/** 枚举环境中的值 */
|
|
99
|
+
enumerator: (() => Iterable<string>) | null | undefined = null;
|
|
100
|
+
/** 描述环境中的值 */
|
|
101
|
+
describer: ((key: string) => string | undefined) | null | undefined = null;
|
|
98
102
|
|
|
99
103
|
/** 执行器上下文 */
|
|
100
104
|
protected evaluator: Evaluator | null = null;
|
|
@@ -117,9 +121,13 @@ export class Scope {
|
|
|
117
121
|
get proxy(): VmContext {
|
|
118
122
|
if (this._proxy != null) return this._proxy;
|
|
119
123
|
let getter: (key: string) => VmAny;
|
|
120
|
-
|
|
124
|
+
let enumerate: () => Iterable<string>;
|
|
125
|
+
let describe: ((key: string) => string | undefined) | undefined;
|
|
126
|
+
const { scope, enumerator, describer } = this;
|
|
121
127
|
if (scope == null) {
|
|
122
128
|
getter = (key) => this.evaluator?.imported.get(key);
|
|
129
|
+
enumerate = () => this.evaluator?.imported.keys() ?? [];
|
|
130
|
+
describe = () => undefined;
|
|
123
131
|
} else if (typeof scope == 'function') {
|
|
124
132
|
getter = (key) => {
|
|
125
133
|
const v = scope(key);
|
|
@@ -135,7 +143,23 @@ export class Scope {
|
|
|
135
143
|
return createProxy(v, this, [key]) as VmValue;
|
|
136
144
|
};
|
|
137
145
|
}
|
|
138
|
-
|
|
146
|
+
if (typeof enumerator == 'function') {
|
|
147
|
+
enumerate = () => {
|
|
148
|
+
const keys = enumerator();
|
|
149
|
+
const imported = this.evaluator?.imported.keys() ?? [];
|
|
150
|
+
return [...keys, ...imported];
|
|
151
|
+
};
|
|
152
|
+
} else {
|
|
153
|
+
enumerate = () => this.evaluator?.imported.keys() ?? [];
|
|
154
|
+
}
|
|
155
|
+
if (typeof describer == 'function') {
|
|
156
|
+
describe = (key) => {
|
|
157
|
+
const d = describer(key);
|
|
158
|
+
if (d) return d;
|
|
159
|
+
return undefined;
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
const proxy = createVmContext(getter, enumerate, describe);
|
|
139
163
|
this._proxy = proxy;
|
|
140
164
|
return proxy;
|
|
141
165
|
}
|
|
@@ -170,6 +194,7 @@ export class Scope {
|
|
|
170
194
|
/** 表达式递归求值 */
|
|
171
195
|
eval(expression: Expression | CompiledExpression, path: readonly PropertyKey[]): VmValue {
|
|
172
196
|
if (this.evalCounter >= Scope.MAX_RECURSION) {
|
|
197
|
+
this.evalCounter = 0;
|
|
173
198
|
throw new Error(`Execution recursion exceeds limit`);
|
|
174
199
|
}
|
|
175
200
|
|
|
@@ -180,9 +205,6 @@ export class Scope {
|
|
|
180
205
|
result = expression(this, this.evaluator!);
|
|
181
206
|
} else {
|
|
182
207
|
const { evaluator } = this;
|
|
183
|
-
if (!evaluator) {
|
|
184
|
-
throw new Error(`Undefined evaluator`);
|
|
185
|
-
}
|
|
186
208
|
const exp = parse(evaluator, expression.source, this.throws, false);
|
|
187
209
|
if (exp.func != null) {
|
|
188
210
|
result = evaluateEval(evaluator, exp, this);
|
package/tests/migrate.ts
CHANGED
|
@@ -17,6 +17,7 @@ const s = new Scope({
|
|
|
17
17
|
x: 1,
|
|
18
18
|
y: 2,
|
|
19
19
|
},
|
|
20
|
+
type: 'keyword',
|
|
20
21
|
});
|
|
21
22
|
const e = new Evaluator();
|
|
22
23
|
|
|
@@ -194,6 +195,35 @@ describe('migrate', () => {
|
|
|
194
195
|
`,
|
|
195
196
|
[1, 1, 2, 3],
|
|
196
197
|
],
|
|
198
|
+
[`equalText(type, "keyword")`, `global.type == 'keyword'`, true],
|
|
199
|
+
[
|
|
200
|
+
`type = { "a": [1,2,3] }; type.a[1]`,
|
|
201
|
+
dedent`
|
|
202
|
+
let __type__ = (a: [1, 2, 3]);
|
|
203
|
+
return @@maybe_chars(__type__.a)[0];
|
|
204
|
+
// # 帮助函数
|
|
205
|
+
fn @@maybe_chars(x) { if type(x) == 'string' { chars(x) } else { x } }
|
|
206
|
+
// # 转换日志
|
|
207
|
+
// - W: 变量名 'type' 是 MiraScript 关键字,已转换为 '__type__'
|
|
208
|
+
// # 原始 math.js 表达式
|
|
209
|
+
// type = { "a": [1,2,3] }; type.a[1]
|
|
210
|
+
`,
|
|
211
|
+
1,
|
|
212
|
+
],
|
|
213
|
+
[
|
|
214
|
+
'[1,2,3].map(f(x,y,z) = x^2)',
|
|
215
|
+
dedent`
|
|
216
|
+
return [1, 2, 3]::map(f);
|
|
217
|
+
// # 帮助函数
|
|
218
|
+
fn f(x, y, z) { x^2 }
|
|
219
|
+
// # 转换日志
|
|
220
|
+
// - W: 使用了非精确转换的语法或函数,结果可能不准确
|
|
221
|
+
// - W: '^' 不支持矩阵,计算结果可能不一致
|
|
222
|
+
// # 原始 math.js 表达式
|
|
223
|
+
// [1,2,3].map(f(x,y,z) = x^2)
|
|
224
|
+
`,
|
|
225
|
+
[1, 4, 9],
|
|
226
|
+
],
|
|
197
227
|
])('should migrate expression: %s', (f, t, r) => {
|
|
198
228
|
const migrated = migrateMathJs(f as ExpressionSource, false, s);
|
|
199
229
|
expect(migrated).toBe(t);
|