@cloudpss/expression 0.6.0-alpha.10 → 0.6.0-alpha.11
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/analyze.js +2 -2
- package/dist/analyze.js.map +1 -1
- package/dist/migrate.d.ts.map +1 -1
- package/dist/migrate.js +13 -0
- package/dist/migrate.js.map +1 -1
- package/dist/migrator/access.d.ts.map +1 -1
- package/dist/migrator/access.js +23 -1
- package/dist/migrator/access.js.map +1 -1
- package/dist/migrator/call.d.ts.map +1 -1
- package/dist/migrator/call.js +36 -25
- package/dist/migrator/call.js.map +1 -1
- package/dist/migrator/concat.d.ts.map +1 -1
- package/dist/migrator/concat.js +15 -2
- package/dist/migrator/concat.js.map +1 -1
- package/dist/migrator/operator.js +27 -27
- package/dist/migrator/operator.js.map +1 -1
- package/dist/migrator/to-type.d.ts.map +1 -1
- package/dist/migrator/to-type.js +4 -3
- 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 +8 -1
- package/dist/migrator/utils.js.map +1 -1
- package/package.json +5 -2
- package/src/analyze.ts +3 -3
- package/src/migrate.ts +15 -0
- package/src/migrator/access.ts +29 -7
- package/src/migrator/call.ts +37 -25
- package/src/migrator/concat.ts +15 -2
- package/src/migrator/operator.ts +31 -31
- package/src/migrator/to-type.ts +6 -3
- package/src/migrator/utils.ts +9 -1
- package/tests/migrate.ts +170 -45
package/src/migrator/call.ts
CHANGED
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
} from 'mathjs';
|
|
11
11
|
import type { Options, Result } from './interface.js';
|
|
12
12
|
import type { State } from './state.js';
|
|
13
|
-
import { constantValue, equalText, len, symbolName } from './utils.js';
|
|
13
|
+
import { constantValue, equalText, globalFnName, len, symbolName } from './utils.js';
|
|
14
14
|
import { migrateAtomic, migrateExpr, migrateNode } from './node.js';
|
|
15
15
|
import { concat } from './concat.js';
|
|
16
16
|
import { toNumber, toString } from './to-type.js';
|
|
@@ -63,6 +63,7 @@ function migrateFunctionCall(
|
|
|
63
63
|
): Result {
|
|
64
64
|
const openE = options.format !== 'no-paren' ? '(' : '';
|
|
65
65
|
const closeE = options.format !== 'no-paren' ? ')' : '';
|
|
66
|
+
const g = (fnName: string) => globalFnName(state, fnName);
|
|
66
67
|
|
|
67
68
|
if (EXACT_UNARY_FUNCTION.has(fnName) && args.length === 1) {
|
|
68
69
|
const arg = migrateAtomic(state, args[0]!);
|
|
@@ -80,19 +81,19 @@ function migrateFunctionCall(
|
|
|
80
81
|
} else if (fnName === 'date' && args.length === 1) {
|
|
81
82
|
return {
|
|
82
83
|
type: 'number',
|
|
83
|
-
code:
|
|
84
|
+
code: `${g('to_timestamp')}(${migrateAtomic(state, args[0]!).code})`,
|
|
84
85
|
};
|
|
85
86
|
} else if (fnName === 'size' && args.length === 1) {
|
|
86
87
|
const arg = migrateAtomic(state, args[0]!);
|
|
87
88
|
return {
|
|
88
89
|
type: arg.type,
|
|
89
|
-
code:
|
|
90
|
+
code: `${g('matrix')}.size(${arg.code})`,
|
|
90
91
|
};
|
|
91
92
|
} else if (fnName === 'inv' && args.length === 1) {
|
|
92
93
|
const arg = migrateAtomic(state, args[0]!);
|
|
93
94
|
return {
|
|
94
95
|
type: arg.type,
|
|
95
|
-
code:
|
|
96
|
+
code: `${g('matrix')}.invert(${arg.code})`,
|
|
96
97
|
};
|
|
97
98
|
} else if (fnName === 'count' && args.length === 1) {
|
|
98
99
|
const arg = migrateAtomic(state, args[0]!);
|
|
@@ -104,39 +105,46 @@ function migrateFunctionCall(
|
|
|
104
105
|
const arg = migrateAtomic(state, args[0]!);
|
|
105
106
|
return {
|
|
106
107
|
type: arg.type,
|
|
107
|
-
code:
|
|
108
|
+
code: `${g('matrix')}.transpose(${arg.code})`,
|
|
108
109
|
};
|
|
109
110
|
} else if (fnName === 'diag' && (args.length === 1 || args.length === 2)) {
|
|
110
111
|
const a = args.map((a) => migrateAtomic(state, a).code).join(', ');
|
|
111
112
|
return {
|
|
112
113
|
type: 'array',
|
|
113
|
-
code:
|
|
114
|
+
code: `${g('matrix')}.diagonal(${a})`,
|
|
114
115
|
};
|
|
115
116
|
} else if (fnName === 'zeros' || fnName === 'ones' || fnName === 'identity') {
|
|
116
117
|
return {
|
|
117
118
|
type: 'array',
|
|
118
|
-
code:
|
|
119
|
+
code: `${g('matrix')}.${fnName}(${args.map((a) => migrateAtomic(state, a).code).join(', ')})`,
|
|
119
120
|
};
|
|
120
121
|
} else if (fnName === 'concat') {
|
|
121
122
|
const results = args.map((a) => migrateAtomic(state, a));
|
|
122
123
|
if (results.some((r) => r.type === 'string')) return concat(state, results);
|
|
124
|
+
if (results.some((r) => r.type === 'array')) {
|
|
125
|
+
state.warn(`矩阵连接时结果可能不一致`);
|
|
126
|
+
return {
|
|
127
|
+
type: 'array',
|
|
128
|
+
code: `${g('flatten')}([` + results.map((r) => r.code).join(', ') + `])`,
|
|
129
|
+
};
|
|
130
|
+
}
|
|
123
131
|
} else if (fnName === 'numeric' && args.length === 1) {
|
|
124
132
|
return toNumber(state, args[0]!);
|
|
125
133
|
} else if (fnName === 'flatten' && args.length === 1) {
|
|
126
134
|
return {
|
|
127
135
|
type: 'array',
|
|
128
|
-
code:
|
|
136
|
+
code: `${g('flatten')}(${migrateAtomic(state, args[0]!).code})`,
|
|
129
137
|
};
|
|
130
138
|
} else if (fnName === 'norm' && args.length === 1) {
|
|
131
139
|
if (isArrayNode(args[0])) {
|
|
132
140
|
return {
|
|
133
141
|
type: 'number',
|
|
134
|
-
code:
|
|
142
|
+
code: `${g('hypot')}(${args[0].items.map((a) => migrateAtomic(state, a).code).join(', ')})`,
|
|
135
143
|
};
|
|
136
144
|
}
|
|
137
145
|
return {
|
|
138
146
|
type: 'number',
|
|
139
|
-
code:
|
|
147
|
+
code: `${g('hypot')}(${migrateAtomic(state, args[0]!).code})`,
|
|
140
148
|
};
|
|
141
149
|
} else if (fnName === 'equalText' && args.length === 2) {
|
|
142
150
|
const p = equalText(state, '==', args[0]!, args[1]!);
|
|
@@ -147,11 +155,11 @@ function migrateFunctionCall(
|
|
|
147
155
|
} else if (fnName === 'toJson' && args.length === 1) {
|
|
148
156
|
return {
|
|
149
157
|
type: 'string',
|
|
150
|
-
code:
|
|
158
|
+
code: `${g('to_json')}(${migrateAtomic(state, args[0]!).code})`,
|
|
151
159
|
};
|
|
152
160
|
} else if (fnName === 'fromJson' && args.length === 1) {
|
|
153
161
|
return {
|
|
154
|
-
code:
|
|
162
|
+
code: `${g('from_json')}(${migrateAtomic(state, args[0]!).code})`,
|
|
155
163
|
};
|
|
156
164
|
} else if (fnName === 'is' && args.length === 2 && isConstantNode(args[1])) {
|
|
157
165
|
const t = String((args[1] as ConstantNode<string | number>).value);
|
|
@@ -254,7 +262,7 @@ function migrateFunctionCall(
|
|
|
254
262
|
const inner = migrateAtomic(state, args[0]!);
|
|
255
263
|
return {
|
|
256
264
|
type: 'string',
|
|
257
|
-
code:
|
|
265
|
+
code: `${g('to_string')}(${inner.code})`,
|
|
258
266
|
};
|
|
259
267
|
} else if (
|
|
260
268
|
fnName === 'sum' &&
|
|
@@ -270,7 +278,7 @@ function migrateFunctionCall(
|
|
|
270
278
|
const v = migrateAtomic(state, args[0].items[0].args[1]!);
|
|
271
279
|
return {
|
|
272
280
|
type: 'number',
|
|
273
|
-
code:
|
|
281
|
+
code: `${g('sum')}(${g('map')}(${a.code}, fn { it ${args[0].items[0].op} ${v.code} }))`,
|
|
274
282
|
};
|
|
275
283
|
}
|
|
276
284
|
|
|
@@ -303,10 +311,11 @@ export function migrateCall(state: State, node: FunctionNode<MathNode>, options:
|
|
|
303
311
|
) {
|
|
304
312
|
const thisArg = migrateExpr(state, fn.object);
|
|
305
313
|
const fnName = String(fn.index.dimensions[0].value);
|
|
314
|
+
const g = (fnName: string) => globalFnName(state, fnName);
|
|
306
315
|
if (fnName === 'toString' && args.length === 0) {
|
|
307
316
|
return {
|
|
308
317
|
type: 'string',
|
|
309
|
-
code: `${thisArg.code}
|
|
318
|
+
code: `${thisArg.code}::${g('to_string')}()`,
|
|
310
319
|
};
|
|
311
320
|
} else if (fnName === 'includes' && args.length === 1) {
|
|
312
321
|
if (thisArg.type === 'array') {
|
|
@@ -318,7 +327,7 @@ export function migrateCall(state: State, node: FunctionNode<MathNode>, options:
|
|
|
318
327
|
if (thisArg.type === 'string') {
|
|
319
328
|
return {
|
|
320
329
|
type: 'boolean',
|
|
321
|
-
code: `${thisArg.code}
|
|
330
|
+
code: `${thisArg.code}::${g('contains')}(${migrateAtomic(state, args[0]!).code})`,
|
|
322
331
|
};
|
|
323
332
|
}
|
|
324
333
|
state.helper(
|
|
@@ -331,26 +340,26 @@ export function migrateCall(state: State, node: FunctionNode<MathNode>, options:
|
|
|
331
340
|
} else if ((fnName === 'map' || fnName === 'filter') && args.length === 1) {
|
|
332
341
|
return {
|
|
333
342
|
type: 'array',
|
|
334
|
-
code: `${thisArg.code}::${fnName}(${migrateAtomic(state, args[0]!).code})`,
|
|
343
|
+
code: `${thisArg.code}::${g(fnName)}(${migrateAtomic(state, args[0]!).code})`,
|
|
335
344
|
};
|
|
336
345
|
} else if (fnName === 'find' && args.length === 1) {
|
|
337
346
|
return {
|
|
338
|
-
code: `${thisArg.code}
|
|
347
|
+
code: `${thisArg.code}::${g('find')}(${migrateAtomic(state, args[0]!).code}).1`,
|
|
339
348
|
};
|
|
340
349
|
} else if (fnName === 'findIndex' && args.length === 1) {
|
|
341
350
|
return {
|
|
342
351
|
type: 'number',
|
|
343
|
-
code: `(${thisArg.code}
|
|
352
|
+
code: `(${thisArg.code}::${g('find')}(${migrateAtomic(state, args[0]!).code}).0 ?? -1)`,
|
|
344
353
|
};
|
|
345
354
|
} else if (fnName === 'flatMap' && args.length === 1) {
|
|
346
355
|
return {
|
|
347
356
|
type: 'array',
|
|
348
|
-
code: `${thisArg.code}
|
|
357
|
+
code: `${thisArg.code}::${g('map')}(${migrateAtomic(state, args[0]!).code})::flatten()`,
|
|
349
358
|
};
|
|
350
359
|
} else if (fnName === 'reverse' && args.length === 0) {
|
|
351
360
|
return {
|
|
352
361
|
type: 'array',
|
|
353
|
-
code: `${thisArg.code}
|
|
362
|
+
code: `${thisArg.code}::${g('reverse')}()`,
|
|
354
363
|
};
|
|
355
364
|
} else if ((fnName === 'replaceAll' || fnName === 'replace') && args.length === 2) {
|
|
356
365
|
if (fnName === 'replace') {
|
|
@@ -358,12 +367,12 @@ export function migrateCall(state: State, node: FunctionNode<MathNode>, options:
|
|
|
358
367
|
}
|
|
359
368
|
return {
|
|
360
369
|
type: 'string',
|
|
361
|
-
code: `${thisArg.code}
|
|
370
|
+
code: `${thisArg.code}::${g('replace')}(${migrateAtomic(state, args[0]!).code}, ${migrateAtomic(state, args[1]!).code})`,
|
|
362
371
|
};
|
|
363
372
|
} else if (fnName === 'split' && args.length === 1) {
|
|
364
373
|
return {
|
|
365
374
|
type: 'array',
|
|
366
|
-
code: `${thisArg.code}
|
|
375
|
+
code: `${thisArg.code}::${g('split')}(${migrateAtomic(state, args[0]!).code})`,
|
|
367
376
|
};
|
|
368
377
|
} else if (fnName === 'concat') {
|
|
369
378
|
if (thisArg.type === 'string') {
|
|
@@ -375,7 +384,10 @@ export function migrateCall(state: State, node: FunctionNode<MathNode>, options:
|
|
|
375
384
|
}
|
|
376
385
|
return {
|
|
377
386
|
type: 'array',
|
|
378
|
-
code:
|
|
387
|
+
code:
|
|
388
|
+
`${g('flatten')}([` +
|
|
389
|
+
[fn.object, ...args].map((a) => migrateAtomic(state, a).code).join(', ') +
|
|
390
|
+
`])`,
|
|
379
391
|
};
|
|
380
392
|
} else if (
|
|
381
393
|
fnName === 'toFixed' &&
|
|
@@ -384,7 +396,7 @@ export function migrateCall(state: State, node: FunctionNode<MathNode>, options:
|
|
|
384
396
|
const digits = constantValue(args[0]!) ?? 0;
|
|
385
397
|
return {
|
|
386
398
|
type: 'string',
|
|
387
|
-
code: `${thisArg.code}
|
|
399
|
+
code: `${thisArg.code}::${g('format')}('.${digits}')`,
|
|
388
400
|
};
|
|
389
401
|
} else if (isArrayNode(fn.object) && fnName === 'join' && args.length <= 1) {
|
|
390
402
|
let sep = ',';
|
package/src/migrator/concat.ts
CHANGED
|
@@ -3,18 +3,31 @@ import type { State } from './state.js';
|
|
|
3
3
|
import { migrateNode } from './node.js';
|
|
4
4
|
import { isResult, type Result } from './interface.js';
|
|
5
5
|
|
|
6
|
+
/** 生成转义序列 */
|
|
7
|
+
function escapeString(str: string | number): string {
|
|
8
|
+
return String(str)
|
|
9
|
+
.replaceAll('\\', String.raw`\\`)
|
|
10
|
+
.replaceAll('`', '\\`')
|
|
11
|
+
.replaceAll('$', String.raw`\$`)
|
|
12
|
+
.replaceAll('\n', String.raw`\n`)
|
|
13
|
+
.replaceAll('\r', String.raw`\r`)
|
|
14
|
+
.replaceAll('\t', String.raw`\t`);
|
|
15
|
+
}
|
|
16
|
+
|
|
6
17
|
/** 连接字符串 */
|
|
7
18
|
export function concat(state: State, args: ReadonlyArray<MathNode | string | number | Result>): Result {
|
|
8
19
|
const parts: string[] = [];
|
|
9
20
|
for (const arg of args) {
|
|
10
21
|
if (typeof arg != 'object') {
|
|
11
|
-
parts.push(
|
|
22
|
+
parts.push(escapeString(arg));
|
|
12
23
|
} else if (isConstantNode(arg)) {
|
|
13
|
-
const value = String(arg.value)
|
|
24
|
+
const value = escapeString(String(arg.value));
|
|
14
25
|
parts.push(value);
|
|
15
26
|
} else if (isResult(arg)) {
|
|
16
27
|
if (arg.literal && typeof arg.literal != 'object') {
|
|
17
28
|
parts.push(String(arg.literal).replaceAll('`', '\\`'));
|
|
29
|
+
} else if (arg.type === 'string' && arg.code.startsWith('to_string(') && arg.code.endsWith(')')) {
|
|
30
|
+
parts.push(`$(${arg.code.slice(10, -1)})`);
|
|
18
31
|
} else {
|
|
19
32
|
parts.push(`$(${arg.code})`);
|
|
20
33
|
}
|
package/src/migrator/operator.ts
CHANGED
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
isOperatorNode,
|
|
9
9
|
isNode,
|
|
10
10
|
} from 'mathjs';
|
|
11
|
-
import { symbolName, constantValue, equalText, scalar } from './utils.js';
|
|
11
|
+
import { symbolName, constantValue, equalText, scalar, globalFnName } from './utils.js';
|
|
12
12
|
import type { State } from './state.js';
|
|
13
13
|
import type { Options, Result } from './interface.js';
|
|
14
14
|
import { migrateAtomic, migrateExpr } from './node.js';
|
|
@@ -19,58 +19,58 @@ import { operations, serialize } from '@mirascript/mirascript/subtle';
|
|
|
19
19
|
const BINARY_MATH_OPERATORS = {
|
|
20
20
|
add: [
|
|
21
21
|
' + ',
|
|
22
|
-
(l, r) => ({
|
|
22
|
+
(state, l, r) => ({
|
|
23
23
|
type: l.type === 'array' || r.type === 'array' ? 'array' : l.type && r.type ? 'number' : undefined,
|
|
24
|
-
code:
|
|
24
|
+
code: `${globalFnName(state, 'matrix')}.add(${l.code}, ${r.code})`,
|
|
25
25
|
}),
|
|
26
26
|
],
|
|
27
27
|
subtract: [
|
|
28
28
|
' - ',
|
|
29
|
-
(l, r) => ({
|
|
29
|
+
(state, l, r) => ({
|
|
30
30
|
type: l.type === 'array' || r.type === 'array' ? 'array' : l.type && r.type ? 'number' : undefined,
|
|
31
|
-
code:
|
|
31
|
+
code: `${globalFnName(state, 'matrix')}.subtract(${l.code}, ${r.code})`,
|
|
32
32
|
}),
|
|
33
33
|
],
|
|
34
34
|
multiply: [
|
|
35
35
|
' * ',
|
|
36
|
-
(l, r) => ({
|
|
36
|
+
(state, l, r) => ({
|
|
37
37
|
type: l.type === 'array' || r.type === 'array' ? 'array' : l.type && r.type ? 'number' : undefined,
|
|
38
|
-
code:
|
|
38
|
+
code: `${globalFnName(state, 'matrix')}.multiply(${l.code}, ${r.code})`,
|
|
39
39
|
}),
|
|
40
40
|
],
|
|
41
41
|
dotMultiply: [
|
|
42
42
|
' * ',
|
|
43
|
-
(l, r) => ({
|
|
43
|
+
(state, l, r) => ({
|
|
44
44
|
type: l.type === 'array' || r.type === 'array' ? 'array' : l.type && r.type ? 'number' : undefined,
|
|
45
|
-
code:
|
|
45
|
+
code: `${globalFnName(state, 'matrix')}.entrywise_multiply(${l.code}, ${r.code})`,
|
|
46
46
|
}),
|
|
47
47
|
],
|
|
48
48
|
divide: [
|
|
49
49
|
' / ',
|
|
50
|
-
(l, r) => {
|
|
50
|
+
(state, l, r) => {
|
|
51
51
|
if (r.type === 'array' || !r.type) {
|
|
52
52
|
return {
|
|
53
53
|
type: l.type === 'array' || r.type === 'array' ? 'array' : l.type && r.type ? 'number' : undefined,
|
|
54
|
-
code:
|
|
54
|
+
code: `${globalFnName(state, 'matrix')}.multiply(${l.code}, ${globalFnName(state, 'matrix')}.invert(${r.code}))`,
|
|
55
55
|
};
|
|
56
56
|
}
|
|
57
57
|
return {
|
|
58
58
|
type: l.type === 'array' ? 'array' : l.type ? 'number' : undefined,
|
|
59
|
-
code:
|
|
59
|
+
code: `${globalFnName(state, 'matrix')}.entrywise_divide(${l.code}, ${r.code})`,
|
|
60
60
|
};
|
|
61
61
|
},
|
|
62
62
|
],
|
|
63
63
|
dotDivide: [
|
|
64
64
|
' / ',
|
|
65
|
-
(l, r) => ({
|
|
65
|
+
(state, l, r) => ({
|
|
66
66
|
type: l.type === 'array' || r.type === 'array' ? 'array' : l.type && r.type ? 'number' : undefined,
|
|
67
|
-
code:
|
|
67
|
+
code: `${globalFnName(state, 'matrix')}.entrywise_divide(${l.code}, ${r.code})`,
|
|
68
68
|
}),
|
|
69
69
|
],
|
|
70
70
|
mod: [' % '],
|
|
71
71
|
pow: ['^', false],
|
|
72
72
|
dotPow: ['^'],
|
|
73
|
-
} satisfies Record<string, [op: string, alt?: ((l: Result, r: Result) => Result) | false]>;
|
|
73
|
+
} satisfies Record<string, [op: string, alt?: ((state: State, l: Result, r: Result) => Result) | false]>;
|
|
74
74
|
|
|
75
75
|
const MATH_FUNCTIONS = {
|
|
76
76
|
factorial: 'factorial',
|
|
@@ -107,47 +107,47 @@ function binary(
|
|
|
107
107
|
state: State,
|
|
108
108
|
l: Result,
|
|
109
109
|
r: Result,
|
|
110
|
-
op: (l: Result, r: Result) => Result,
|
|
111
|
-
alt?: (l: Result, r: Result) => Result,
|
|
110
|
+
op: (state: State, l: Result, r: Result) => Result,
|
|
111
|
+
alt?: (state: State, l: Result, r: Result) => Result,
|
|
112
112
|
): Result {
|
|
113
113
|
if (l.type && r.type && l.type !== 'array' && r.type !== 'array') {
|
|
114
|
-
return op(l, r);
|
|
114
|
+
return op(state, l, r);
|
|
115
115
|
}
|
|
116
116
|
if (Array.isArray(l.literal) && l.literal.every((e) => !Array.isArray(e))) {
|
|
117
117
|
return {
|
|
118
118
|
type: 'array',
|
|
119
|
-
code: `${l.code}
|
|
119
|
+
code: `${l.code}::${globalFnName(state, 'map')}(fn { ${op(state, { code: 'it' }, r).code} })`,
|
|
120
120
|
};
|
|
121
121
|
}
|
|
122
122
|
if (Array.isArray(r.literal) && r.literal.every((e) => !Array.isArray(e))) {
|
|
123
123
|
return {
|
|
124
124
|
type: 'array',
|
|
125
|
-
code: `${r.code}
|
|
125
|
+
code: `${r.code}::${globalFnName(state, 'map')}(fn { ${op(state, l, { code: 'it' }).code} })`,
|
|
126
126
|
};
|
|
127
127
|
}
|
|
128
128
|
if (alt) {
|
|
129
|
-
return alt(l, r);
|
|
129
|
+
return alt(state, l, r);
|
|
130
130
|
}
|
|
131
131
|
return {
|
|
132
132
|
type: l.type === 'array' || r.type === 'array' ? 'array' : undefined,
|
|
133
|
-
code:
|
|
133
|
+
code: `${globalFnName(state, 'matrix')}.entrywise(${l.code}, ${r.code}, fn (a, b) { ${op(state, { code: 'a' }, { code: 'b' }).code} })`,
|
|
134
134
|
};
|
|
135
135
|
}
|
|
136
136
|
|
|
137
137
|
/** 一元操作 */
|
|
138
|
-
function unary(state: State, v: Result, op: (v: Result) => Result): Result {
|
|
138
|
+
function unary(state: State, v: Result, op: (state: State, v: Result) => Result): Result {
|
|
139
139
|
if (v.type && v.type !== 'array') {
|
|
140
|
-
return op(v);
|
|
140
|
+
return op(state, v);
|
|
141
141
|
}
|
|
142
142
|
if (Array.isArray(v.literal) && v.literal.every((e) => !Array.isArray(e))) {
|
|
143
143
|
return {
|
|
144
144
|
type: 'array',
|
|
145
|
-
code: `${v.code}
|
|
145
|
+
code: `${v.code}::${globalFnName(state, 'map')}(fn { ${op(state, { code: 'it' }).code} })`,
|
|
146
146
|
};
|
|
147
147
|
}
|
|
148
148
|
return {
|
|
149
149
|
type: 'array',
|
|
150
|
-
code:
|
|
150
|
+
code: `${globalFnName(state, 'matrix')}.entrywise(${v.code}, nil, fn { ${op(state, { code: 'it' }).code} })`,
|
|
151
151
|
};
|
|
152
152
|
}
|
|
153
153
|
|
|
@@ -179,14 +179,14 @@ export function migrateOperator(
|
|
|
179
179
|
state,
|
|
180
180
|
migrateExpr(state, a0),
|
|
181
181
|
migrateExpr(state, a1),
|
|
182
|
-
(l, r) => ({
|
|
182
|
+
(state, l, r) => ({
|
|
183
183
|
type: 'number',
|
|
184
184
|
code: `${l.code}${op}${r.code}`,
|
|
185
185
|
}),
|
|
186
186
|
alt === false
|
|
187
|
-
? (l, r) => {
|
|
187
|
+
? (state, l, r) => {
|
|
188
188
|
state.warn(`'${op.trim()}' 不支持矩阵,计算结果可能不一致`);
|
|
189
|
-
return { code: `${l.code}
|
|
189
|
+
return { code: `${l.code}${op}${r.code}` };
|
|
190
190
|
}
|
|
191
191
|
: alt,
|
|
192
192
|
);
|
|
@@ -205,7 +205,7 @@ export function migrateOperator(
|
|
|
205
205
|
code: serialize(v),
|
|
206
206
|
};
|
|
207
207
|
}
|
|
208
|
-
return unary(state, migrateExpr(state, a0), (v) => ({
|
|
208
|
+
return unary(state, migrateExpr(state, a0), (state, v) => ({
|
|
209
209
|
type: 'number',
|
|
210
210
|
code: `${op}${v.code}`,
|
|
211
211
|
}));
|
|
@@ -315,7 +315,7 @@ export function migrateOperator(
|
|
|
315
315
|
return r;
|
|
316
316
|
};
|
|
317
317
|
|
|
318
|
-
return binary(state, a(a0), a(a1), (l, r) => {
|
|
318
|
+
return binary(state, a(a0), a(a1), (state, l, r) => {
|
|
319
319
|
if (l.type === 'boolean' && r.type === 'boolean') {
|
|
320
320
|
return {
|
|
321
321
|
type: 'boolean',
|
package/src/migrator/to-type.ts
CHANGED
|
@@ -3,11 +3,14 @@ import type { Result } from './interface.js';
|
|
|
3
3
|
import { serialize } from '@mirascript/mirascript/subtle';
|
|
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(
|
|
11
|
+
state.helper(
|
|
12
|
+
"fn @@to_boolean { if it is nil { return nil; } it != '' && it != '0' && it != 0 && it is not nan && !!it }",
|
|
13
|
+
);
|
|
11
14
|
};
|
|
12
15
|
if (!isNode(node)) {
|
|
13
16
|
if (node.type === 'boolean') return node;
|
|
@@ -56,7 +59,7 @@ export function toString(state: State, node: MathNode | Result): Result {
|
|
|
56
59
|
}
|
|
57
60
|
return {
|
|
58
61
|
type: 'string',
|
|
59
|
-
code:
|
|
62
|
+
code: `${globalFnName(state, 'to_string')}(${node.code})`,
|
|
60
63
|
};
|
|
61
64
|
}
|
|
62
65
|
if (isConstantNode(node)) {
|
|
@@ -92,7 +95,7 @@ export function toNumber(state: State, node: MathNode | Result): Result {
|
|
|
92
95
|
}
|
|
93
96
|
return {
|
|
94
97
|
type: 'number',
|
|
95
|
-
code:
|
|
98
|
+
code: `${globalFnName(state, 'to_number')}(${node.code})`,
|
|
96
99
|
};
|
|
97
100
|
}
|
|
98
101
|
if (isConstantNode(node)) {
|
package/src/migrator/utils.ts
CHANGED
|
@@ -4,6 +4,14 @@ import type { State } from './state.js';
|
|
|
4
4
|
import { toString } from './to-type.js';
|
|
5
5
|
import { migrateExpr } from './node.js';
|
|
6
6
|
|
|
7
|
+
/** 获取全局函数的名字 */
|
|
8
|
+
export function globalFnName(state: State, fnName: string): string {
|
|
9
|
+
if (state.locals.has(fnName)) {
|
|
10
|
+
return `global.${fnName}`;
|
|
11
|
+
}
|
|
12
|
+
return fnName;
|
|
13
|
+
}
|
|
14
|
+
|
|
7
15
|
/** 获取 symbol name */
|
|
8
16
|
export function symbolName(node: MathNode): string | undefined {
|
|
9
17
|
if (!isSymbolNode(node)) return undefined;
|
|
@@ -79,7 +87,7 @@ export function len(state: State, obj: Result): Result {
|
|
|
79
87
|
code: `len(${obj.code})`,
|
|
80
88
|
};
|
|
81
89
|
state.helper(
|
|
82
|
-
`fn @@length(x) { if type(x) == 'string' { len(chars(x)) } else if type(x) == 'array' { len(x) }
|
|
90
|
+
`fn @@length(x) { if type(x) == 'string' { len(chars(x)) } else if type(x) == 'array' { len(x) } else { x.length } }`,
|
|
83
91
|
);
|
|
84
92
|
return {
|
|
85
93
|
type: 'number',
|