@mirascript/mirascript 0.1.76 → 0.1.79
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/{chunk-ZRLBJK6A.js → chunk-BPFOJ4Q6.js} +499 -470
- package/dist/chunk-BPFOJ4Q6.js.map +6 -0
- package/dist/{chunk-VI74OKFU.js → chunk-LSPCAN32.js} +291 -226
- package/dist/chunk-LSPCAN32.js.map +6 -0
- package/dist/compiler/emit/constants.d.ts +1 -1
- package/dist/compiler/emit/constants.d.ts.map +1 -1
- package/dist/compiler/emit/consts.d.ts.map +1 -1
- package/dist/compiler/emit/index.d.ts.map +1 -1
- package/dist/compiler/emit-script.d.ts.map +1 -1
- package/dist/compiler/worker.js +1 -1
- package/dist/helpers/convert/{to-boolean.d.ts → boolean.d.ts} +1 -1
- package/dist/helpers/convert/boolean.d.ts.map +1 -0
- package/dist/helpers/convert/{to-format.d.ts → format.d.ts} +1 -1
- package/dist/helpers/convert/format.d.ts.map +1 -0
- package/dist/helpers/convert/index.d.ts +4 -4
- package/dist/helpers/convert/index.d.ts.map +1 -1
- package/dist/helpers/convert/{to-number.d.ts → number.d.ts} +1 -1
- package/dist/helpers/convert/number.d.ts.map +1 -0
- package/dist/helpers/convert/{to-string.d.ts → string.d.ts} +3 -1
- package/dist/helpers/convert/string.d.ts.map +1 -0
- package/dist/helpers/error.d.ts +1 -0
- package/dist/helpers/error.d.ts.map +1 -1
- package/dist/helpers/serialize.d.ts.map +1 -1
- package/dist/helpers/types/array-like.d.ts +8 -0
- package/dist/helpers/types/array-like.d.ts.map +1 -0
- package/dist/helpers/types/basic.d.ts +26 -0
- package/dist/helpers/types/basic.d.ts.map +1 -0
- package/dist/helpers/types/composed.d.ts +12 -0
- package/dist/helpers/types/composed.d.ts.map +1 -0
- package/dist/helpers/types/const.d.ts +6 -0
- package/dist/helpers/types/const.d.ts.map +1 -0
- package/dist/helpers/types/get-type.d.ts +6 -0
- package/dist/helpers/types/get-type.d.ts.map +1 -0
- package/dist/helpers/types/index.d.ts +6 -0
- package/dist/helpers/types/index.d.ts.map +1 -0
- package/dist/helpers/types/proto.d.ts +5 -0
- package/dist/helpers/types/proto.d.ts.map +1 -0
- package/dist/helpers/utils.d.ts +9 -0
- package/dist/helpers/utils.d.ts.map +1 -1
- package/dist/index.js +3 -3
- package/dist/index.js.map +1 -1
- package/dist/subtle.js +3 -3
- package/dist/vm/lib/global/debug.d.ts.map +1 -1
- package/dist/vm/lib/global/json.d.ts +3 -2
- package/dist/vm/lib/global/json.d.ts.map +1 -1
- package/dist/vm/lib/global/math/tgamma.d.ts.map +1 -1
- package/dist/vm/lib/global/sequence/entries.d.ts +1 -1
- package/dist/vm/lib/global/sequence/entries.d.ts.map +1 -1
- package/dist/vm/lib/global/sequence/fold.d.ts +3 -0
- package/dist/vm/lib/global/sequence/fold.d.ts.map +1 -0
- package/dist/vm/lib/global/sequence/group.d.ts +3 -0
- package/dist/vm/lib/global/sequence/group.d.ts.map +1 -0
- package/dist/vm/lib/global/sequence/index.d.ts +2 -0
- package/dist/vm/lib/global/sequence/index.d.ts.map +1 -1
- package/dist/vm/lib/global/sequence/new.d.ts.map +1 -1
- package/dist/vm/lib/global/sequence/zip.d.ts +2 -2
- package/dist/vm/lib/global/sequence/zip.d.ts.map +1 -1
- package/dist/vm/lib/helpers.d.ts +2 -2
- package/dist/vm/lib/helpers.d.ts.map +1 -1
- package/dist/vm/lib/mod/index.d.ts +1 -1
- package/dist/vm/lib/mod/index.d.ts.map +1 -1
- package/dist/vm/lib/mod/matrix/bin-ops.d.ts +8 -0
- package/dist/vm/lib/mod/matrix/bin-ops.d.ts.map +1 -0
- package/dist/vm/lib/mod/matrix/fill.d.ts +6 -0
- package/dist/vm/lib/mod/matrix/fill.d.ts.map +1 -0
- package/dist/vm/lib/mod/matrix/helpers.d.ts +6 -0
- package/dist/vm/lib/mod/matrix/helpers.d.ts.map +1 -0
- package/dist/vm/lib/mod/matrix/index.d.ts +6 -0
- package/dist/vm/lib/mod/matrix/index.d.ts.map +1 -0
- package/dist/vm/lib/mod/matrix/invert.d.ts +3 -0
- package/dist/vm/lib/mod/matrix/invert.d.ts.map +1 -0
- package/dist/vm/lib/mod/matrix/size.d.ts +2 -0
- package/dist/vm/lib/mod/matrix/size.d.ts.map +1 -0
- package/dist/vm/lib/mod/matrix/transpose.d.ts +2 -0
- package/dist/vm/lib/mod/matrix/transpose.d.ts.map +1 -0
- package/dist/vm/operations/array-range.d.ts +3 -3
- package/dist/vm/operations/array-range.d.ts.map +1 -1
- package/dist/vm/operations/call.d.ts +1 -1
- package/dist/vm/operations/call.d.ts.map +1 -1
- package/dist/vm/operations/compound.d.ts +1 -13
- package/dist/vm/operations/compound.d.ts.map +1 -1
- package/dist/vm/operations/index.d.ts +3 -0
- package/dist/vm/operations/index.d.ts.map +1 -1
- package/dist/vm/operations/iterable.d.ts +6 -0
- package/dist/vm/operations/iterable.d.ts.map +1 -0
- package/dist/vm/operations/record.d.ts +6 -0
- package/dist/vm/operations/record.d.ts.map +1 -0
- package/dist/vm/operations/slice.d.ts.map +1 -1
- package/dist/vm/operations/spread.d.ts +6 -0
- package/dist/vm/operations/spread.d.ts.map +1 -0
- package/dist/vm/operations/utils.d.ts.map +1 -1
- package/dist/vm/types/extern/access.d.ts +5 -0
- package/dist/vm/types/extern/access.d.ts.map +1 -0
- package/dist/vm/types/{extern.d.ts → extern/index.d.ts} +3 -3
- package/dist/vm/types/extern/index.d.ts.map +1 -0
- package/dist/vm/types/extern/tag.d.ts +3 -0
- package/dist/vm/types/extern/tag.d.ts.map +1 -0
- package/dist/vm/types/extern/utils.d.ts +13 -0
- package/dist/vm/types/extern/utils.d.ts.map +1 -0
- package/dist/vm/types/index.d.ts +3 -3
- package/dist/vm/types/index.d.ts.map +1 -1
- package/package.json +6 -6
- package/src/compiler/compile-fast.ts +1 -1
- package/src/compiler/diagnostic.ts +2 -2
- package/src/compiler/emit/constants.ts +1 -1
- package/src/compiler/emit/consts.ts +0 -1
- package/src/compiler/emit/index.ts +1 -7
- package/src/compiler/emit/sourcemap.ts +1 -1
- package/src/compiler/emit-script.ts +1 -0
- package/src/compiler/load-module.ts +5 -1
- package/src/helpers/convert/{to-boolean.ts → boolean.ts} +1 -1
- package/src/helpers/convert/{to-format.ts → format.ts} +1 -1
- package/src/helpers/convert/index.ts +4 -4
- package/src/helpers/convert/{to-number.ts → number.ts} +16 -32
- package/src/helpers/convert/{to-string.ts → string.ts} +5 -4
- package/src/helpers/error.ts +3 -1
- package/src/helpers/serialize.ts +45 -44
- package/src/helpers/types/array-like.ts +32 -0
- package/src/helpers/types/basic.ts +82 -0
- package/src/helpers/types/composed.ts +27 -0
- package/src/helpers/types/const.ts +44 -0
- package/src/helpers/types/get-type.ts +16 -0
- package/src/helpers/types/index.ts +5 -0
- package/src/helpers/types/proto.ts +21 -0
- package/src/helpers/utils.ts +33 -0
- package/src/vm/lib/global/debug.ts +4 -8
- package/src/vm/lib/global/json.ts +21 -9
- package/src/vm/lib/global/math/tgamma.ts +8 -14
- package/src/vm/lib/global/sequence/all-any.ts +1 -1
- package/src/vm/lib/global/sequence/entries.ts +6 -1
- package/src/vm/lib/global/sequence/find.ts +1 -1
- package/src/vm/lib/global/sequence/fold.ts +30 -0
- package/src/vm/lib/global/sequence/group.ts +37 -0
- package/src/vm/lib/global/sequence/index.ts +2 -0
- package/src/vm/lib/global/sequence/map-filter.ts +3 -3
- package/src/vm/lib/global/sequence/new.ts +9 -3
- package/src/vm/lib/global/sequence/sort.ts +1 -1
- package/src/vm/lib/global/sequence/unique.ts +1 -1
- package/src/vm/lib/global/sequence/with.ts +5 -5
- package/src/vm/lib/global/sequence/zip.ts +21 -10
- package/src/vm/lib/global/time.ts +1 -1
- package/src/vm/lib/helpers.ts +12 -5
- package/src/vm/lib/mod/index.ts +1 -1
- package/src/vm/lib/mod/matrix/bin-ops.ts +291 -0
- package/src/vm/lib/mod/matrix/fill.ts +109 -0
- package/src/vm/lib/mod/matrix/helpers.ts +26 -0
- package/src/vm/lib/mod/matrix/index.ts +5 -0
- package/src/vm/lib/mod/matrix/invert.ts +122 -0
- package/src/vm/lib/mod/matrix/size.ts +15 -0
- package/src/vm/lib/mod/matrix/transpose.ts +32 -0
- package/src/vm/operations/array-range.ts +15 -27
- package/src/vm/operations/call.ts +2 -2
- package/src/vm/operations/compound.ts +5 -125
- package/src/vm/operations/helpers.ts +1 -1
- package/src/vm/operations/index.ts +3 -0
- package/src/vm/operations/iterable.ts +40 -0
- package/src/vm/operations/record.ts +33 -0
- package/src/vm/operations/slice.ts +23 -22
- package/src/vm/operations/spread.ts +57 -0
- package/src/vm/operations/type-check.ts +1 -1
- package/src/vm/operations/utils.ts +45 -37
- package/src/vm/types/boundary.ts +2 -2
- package/src/vm/types/extern/access.ts +24 -0
- package/src/vm/types/extern/index.ts +124 -0
- package/src/vm/types/extern/tag.ts +58 -0
- package/src/vm/types/extern/utils.ts +55 -0
- package/src/vm/types/function.ts +1 -1
- package/src/vm/types/index.ts +3 -3
- package/dist/chunk-VI74OKFU.js.map +0 -6
- package/dist/chunk-ZRLBJK6A.js.map +0 -6
- package/dist/helpers/convert/to-boolean.d.ts.map +0 -1
- package/dist/helpers/convert/to-format.d.ts.map +0 -1
- package/dist/helpers/convert/to-number.d.ts.map +0 -1
- package/dist/helpers/convert/to-string.d.ts.map +0 -1
- package/dist/helpers/types.d.ts +0 -58
- package/dist/helpers/types.d.ts.map +0 -1
- package/dist/vm/lib/mod/matrix.d.ts +0 -15
- package/dist/vm/lib/mod/matrix.d.ts.map +0 -1
- package/dist/vm/types/extern.d.ts.map +0 -1
- package/src/helpers/types.ts +0 -283
- package/src/vm/lib/mod/matrix.ts +0 -590
- package/src/vm/types/extern.ts +0 -197
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import type { VmConst } from '../../../types/index.js';
|
|
2
|
+
import { size, num } from './helpers.js';
|
|
3
|
+
import { VmLib, expectConst, throwError, iterate } from '../../helpers.js';
|
|
4
|
+
|
|
5
|
+
export const invert = VmLib(
|
|
6
|
+
(a) => {
|
|
7
|
+
expectConst('a', a, null);
|
|
8
|
+
const [rows, cols] = size(a);
|
|
9
|
+
if (rows == null) return 1 / num(a); // 标量取倒数
|
|
10
|
+
if (cols == null) return iterate(a, (v) => 1 / num(v)); // 向量按元素取倒数
|
|
11
|
+
|
|
12
|
+
if (rows !== cols) throwError(`Matrix must be square`, a);
|
|
13
|
+
const m = a as VmConst[][];
|
|
14
|
+
// https://github.com/josdejong/mathjs
|
|
15
|
+
if (rows === 1) {
|
|
16
|
+
// 1x1 矩阵
|
|
17
|
+
const e = num(m[0]?.[0]);
|
|
18
|
+
// if (e === 0) {
|
|
19
|
+
// throwError(`Matrix is singular`, null);
|
|
20
|
+
// }
|
|
21
|
+
return [[1 / e]];
|
|
22
|
+
}
|
|
23
|
+
if (rows === 2) {
|
|
24
|
+
// 2x2 矩阵
|
|
25
|
+
const a = num(m[0]?.[0]);
|
|
26
|
+
const b = num(m[0]?.[1]);
|
|
27
|
+
const c = num(m[1]?.[0]);
|
|
28
|
+
const d = num(m[1]?.[1]);
|
|
29
|
+
|
|
30
|
+
const det = a * d - b * c;
|
|
31
|
+
// if (det === 0) throwError(`Matrix is singular`, null);
|
|
32
|
+
return [
|
|
33
|
+
[d / det, -b / det],
|
|
34
|
+
[-c / det, a / det],
|
|
35
|
+
];
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// 更高阶矩阵 使用高斯消元法
|
|
39
|
+
|
|
40
|
+
// 初始化输入
|
|
41
|
+
const A: number[][] = [];
|
|
42
|
+
// 初始化结果为单位矩阵
|
|
43
|
+
const B: number[][] = [];
|
|
44
|
+
for (let r = 0; r < rows; r++) {
|
|
45
|
+
const Ar: number[] = [];
|
|
46
|
+
const Br: number[] = [];
|
|
47
|
+
A[r] = Ar;
|
|
48
|
+
B[r] = Br;
|
|
49
|
+
for (let c = 0; c < cols; c++) {
|
|
50
|
+
Ar[c] = num(m[r]?.[c]);
|
|
51
|
+
Br[c] = r === c ? 1 : 0;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// loop over all columns, and perform row reductions
|
|
56
|
+
for (let c = 0; c < cols; c++) {
|
|
57
|
+
// Pivoting: Swap row c with row r, where row r contains the largest element A[r][c]
|
|
58
|
+
let ABig = Math.abs(A[c]![c]!);
|
|
59
|
+
let rBig = c;
|
|
60
|
+
let r = c + 1;
|
|
61
|
+
while (r < rows) {
|
|
62
|
+
if (Math.abs(A[r]![c]!) > ABig) {
|
|
63
|
+
ABig = Math.abs(A[r]![c]!);
|
|
64
|
+
rBig = r;
|
|
65
|
+
}
|
|
66
|
+
r++;
|
|
67
|
+
}
|
|
68
|
+
// if (ABig === 0) {
|
|
69
|
+
// throwError(`Matrix is singular`, null);
|
|
70
|
+
// }
|
|
71
|
+
r = rBig;
|
|
72
|
+
if (r !== c) {
|
|
73
|
+
const temp1 = A[c]!;
|
|
74
|
+
A[c] = A[r]!;
|
|
75
|
+
A[r] = temp1;
|
|
76
|
+
const temp2 = B[c]!;
|
|
77
|
+
B[c] = B[r]!;
|
|
78
|
+
B[r] = temp2;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// eliminate non-zero values on the other rows at column c
|
|
82
|
+
const Ac = A[c]!;
|
|
83
|
+
const Bc = B[c]!;
|
|
84
|
+
for (r = 0; r < rows; r++) {
|
|
85
|
+
const Ar = A[r]!;
|
|
86
|
+
const Br = B[r]!;
|
|
87
|
+
if (r !== c) {
|
|
88
|
+
// eliminate value at column c and row r
|
|
89
|
+
if (Ar[c] !== 0) {
|
|
90
|
+
const f = -Ar[c]! / Ac[c]!;
|
|
91
|
+
|
|
92
|
+
// add (f * row c) to row r to eliminate the value
|
|
93
|
+
// at column c
|
|
94
|
+
for (let s = c; s < cols; s++) {
|
|
95
|
+
Ar[s] = Ar[s]! + f * Ac[s]!;
|
|
96
|
+
}
|
|
97
|
+
for (let s = 0; s < cols; s++) {
|
|
98
|
+
Br[s] = Br[s]! + f * Bc[s]!;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
} else {
|
|
102
|
+
// normalize value at Acc to 1,
|
|
103
|
+
// divide each value on row r with the value at Acc
|
|
104
|
+
const f = Ac[c]!;
|
|
105
|
+
for (let s = c; s < cols; s++) {
|
|
106
|
+
Ar[s] = Ar[s]! / f;
|
|
107
|
+
}
|
|
108
|
+
for (let s = 0; s < cols; s++) {
|
|
109
|
+
Br[s] = Br[s]! / f;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
return B;
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
summary: '矩阵求逆',
|
|
118
|
+
params: { a: { type: 'number | number[][]', description: '待求逆的矩阵' } },
|
|
119
|
+
returns: { type: 'number | number[][]' },
|
|
120
|
+
examples: ['matrix.invert([[1, 2], [3, 4]]) // [[-2, 1], [1.5, -0.5]]'],
|
|
121
|
+
},
|
|
122
|
+
);
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { VmLib, required } from '../../helpers.js';
|
|
2
|
+
import { size as sizeImpl } from './helpers.js';
|
|
3
|
+
|
|
4
|
+
export const size = VmLib(
|
|
5
|
+
(matrix) => {
|
|
6
|
+
required('matrix', matrix, []);
|
|
7
|
+
return sizeImpl(matrix);
|
|
8
|
+
},
|
|
9
|
+
{
|
|
10
|
+
summary: '获取矩阵尺寸',
|
|
11
|
+
params: { matrix: { type: 'any[][]', description: '要获取尺寸的矩阵' } },
|
|
12
|
+
returns: { type: '[number, number]' },
|
|
13
|
+
examples: ['matrix.size([[1, 2], [3, 4]]) // [2, 2]'],
|
|
14
|
+
},
|
|
15
|
+
);
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { Cp } from '../../../checkpoint.js';
|
|
2
|
+
import type { VmConst } from '../../../types/index.js';
|
|
3
|
+
import { VmLib, required } from '../../helpers.js';
|
|
4
|
+
import { size } from './helpers.js';
|
|
5
|
+
|
|
6
|
+
export const transpose = VmLib(
|
|
7
|
+
(matrix) => {
|
|
8
|
+
required('matrix', matrix, []);
|
|
9
|
+
const [numRows, numCols] = size(matrix);
|
|
10
|
+
if (numRows == null || numCols == null) return matrix; // 一维数组或空数组无需转置
|
|
11
|
+
|
|
12
|
+
const m = matrix as VmConst[][];
|
|
13
|
+
const transposed: VmConst[][] = [];
|
|
14
|
+
for (let j = 0; j < numCols; j++) {
|
|
15
|
+
Cp();
|
|
16
|
+
const tj = [];
|
|
17
|
+
for (let i = 0; i < numRows; i++) {
|
|
18
|
+
const row = m[i] ?? null;
|
|
19
|
+
const item = row?.[j] ?? null;
|
|
20
|
+
tj[i] = item;
|
|
21
|
+
}
|
|
22
|
+
transposed[j] = tj;
|
|
23
|
+
}
|
|
24
|
+
return transposed;
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
summary: '转置矩阵',
|
|
28
|
+
params: { matrix: { type: 'any[][]', description: '要转置的矩阵' } },
|
|
29
|
+
returns: { type: 'any[][]' },
|
|
30
|
+
examples: ['matrix.transpose([[1, 2], [3, 4]]) // [[1, 3], [2, 4]]'],
|
|
31
|
+
},
|
|
32
|
+
);
|
|
@@ -1,41 +1,29 @@
|
|
|
1
1
|
import { isFinite } from '../../helpers/utils.js';
|
|
2
2
|
import { VM_ARRAY_MAX_LENGTH } from '../../helpers/constants.js';
|
|
3
|
-
import type { VmAny
|
|
3
|
+
import type { VmAny } from '../types/index.js';
|
|
4
4
|
import { $ToNumber } from './convert.js';
|
|
5
5
|
|
|
6
|
-
const
|
|
7
|
-
if (len > VM_ARRAY_MAX_LENGTH) {
|
|
8
|
-
throw new RangeError(`Array length exceeds maximum limit of ${VM_ARRAY_MAX_LENGTH}`);
|
|
9
|
-
}
|
|
10
|
-
};
|
|
11
|
-
const isEmptyRange = (start: number, end: number) => {
|
|
12
|
-
return !isFinite(start) || !isFinite(end) || start > end;
|
|
13
|
-
};
|
|
14
|
-
/** 构造范围数组 */
|
|
15
|
-
export const $ArrayRange = (start: VmAny, end: VmAny): VmArray => {
|
|
6
|
+
const makeArray = (start: VmAny, end: VmAny, exclusive: boolean): number[] => {
|
|
16
7
|
const s = $ToNumber(start);
|
|
17
8
|
const e = $ToNumber(end);
|
|
18
|
-
if (
|
|
19
|
-
|
|
20
|
-
|
|
9
|
+
if (!isFinite(s) || !isFinite(e) || s > e) {
|
|
10
|
+
return [];
|
|
11
|
+
}
|
|
12
|
+
const n = exclusive ? Math.ceil(e - s) : Math.floor(e - s + 1);
|
|
13
|
+
if (n > VM_ARRAY_MAX_LENGTH) {
|
|
14
|
+
throw new RangeError(`Array length exceeds maximum limit of ${VM_ARRAY_MAX_LENGTH}`);
|
|
15
|
+
}
|
|
21
16
|
const arr = [];
|
|
22
|
-
arr.length = n;
|
|
23
17
|
for (let i = 0; i < n; i++) {
|
|
24
18
|
arr[i] = s + i;
|
|
25
19
|
}
|
|
26
20
|
return arr;
|
|
27
21
|
};
|
|
22
|
+
/** 构造范围数组 */
|
|
23
|
+
export const $ArrayRange = (start: VmAny, end: VmAny): number[] => {
|
|
24
|
+
return makeArray(start, end, false);
|
|
25
|
+
};
|
|
28
26
|
/** 构造范围数组(不包含结束值) */
|
|
29
|
-
export const $ArrayRangeExclusive = (start: VmAny, end: VmAny):
|
|
30
|
-
|
|
31
|
-
const e = $ToNumber(end);
|
|
32
|
-
if (isEmptyRange(s, e)) return [];
|
|
33
|
-
const n = Math.ceil(e - s);
|
|
34
|
-
assertArrayLength(n);
|
|
35
|
-
const arr = [];
|
|
36
|
-
arr.length = n;
|
|
37
|
-
for (let i = 0; i < n; i++) {
|
|
38
|
-
arr[i] = s + i;
|
|
39
|
-
}
|
|
40
|
-
return arr;
|
|
27
|
+
export const $ArrayRangeExclusive = (start: VmAny, end: VmAny): number[] => {
|
|
28
|
+
return makeArray(start, end, true);
|
|
41
29
|
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { VmError } from '../../helpers/error.js';
|
|
2
2
|
import { display } from '../../helpers/serialize.js';
|
|
3
|
-
import { isVmExtern, isVmConst } from '../../helpers/types.js';
|
|
3
|
+
import { isVmExtern, isVmConst } from '../../helpers/types/index.js';
|
|
4
4
|
import type { VmExtern, VmFunction, VmAny, VmArray, VmValue } from '../types/index.js';
|
|
5
5
|
import { $AssertInit } from './common.js';
|
|
6
6
|
|
|
@@ -27,7 +27,7 @@ type CallReturn<T extends VmValue> =
|
|
|
27
27
|
: VmValue;
|
|
28
28
|
|
|
29
29
|
/** 调用函数 */
|
|
30
|
-
export function $Call<T extends VmValue, A extends readonly VmValue[]>(func: T, args: A): CallReturn<T> {
|
|
30
|
+
export function $Call<T extends VmValue, const A extends readonly VmValue[]>(func: T, args: A): CallReturn<T> {
|
|
31
31
|
const argsLen = args.length;
|
|
32
32
|
for (let i = 0; i < argsLen; i++) {
|
|
33
33
|
$AssertInit(args[i]);
|
|
@@ -1,19 +1,9 @@
|
|
|
1
1
|
import { VmError } from '../../helpers/error.js';
|
|
2
|
-
import { hasOwnEnumerable, NotNumber,
|
|
3
|
-
import { toNumber
|
|
2
|
+
import { hasOwnEnumerable, NotNumber, isFinite, getRecord, keysLength } from '../../helpers/utils.js';
|
|
3
|
+
import { toNumber } from '../../helpers/convert/index.js';
|
|
4
4
|
import { display } from '../../helpers/serialize.js';
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
isVmArray,
|
|
8
|
-
isVmRecord,
|
|
9
|
-
isVmFunction,
|
|
10
|
-
isVmExtern,
|
|
11
|
-
isVmWrapper,
|
|
12
|
-
isVmConst,
|
|
13
|
-
} from '../../helpers/types.js';
|
|
14
|
-
import { wrapToVmConst } from '../types/boundary.js';
|
|
15
|
-
import type { VmAny, VmRecord, VmValue, VmConst } from '../types/index.js';
|
|
16
|
-
import { isSame } from './utils.js';
|
|
5
|
+
import { isVmArray, isVmRecord, isVmExtern, isVmWrapper } from '../../helpers/types/index.js';
|
|
6
|
+
import type { VmAny, VmValue } from '../types/index.js';
|
|
17
7
|
import { $AssertInit } from './common.js';
|
|
18
8
|
import { $ToString } from './convert.js';
|
|
19
9
|
import { $El } from './helpers.js';
|
|
@@ -21,29 +11,6 @@ import { $El } from './helpers.js';
|
|
|
21
11
|
const { trunc } = Math;
|
|
22
12
|
const { at } = Array.prototype;
|
|
23
13
|
|
|
24
|
-
/** 检查值是否在可迭代对象中 */
|
|
25
|
-
export const $In = (value: VmAny, iterable: VmAny): boolean => {
|
|
26
|
-
$AssertInit(value);
|
|
27
|
-
$AssertInit(iterable);
|
|
28
|
-
if (iterable == null) return false;
|
|
29
|
-
if (typeof iterable != 'object') return false;
|
|
30
|
-
if (isVmArray(iterable)) {
|
|
31
|
-
if (value == null) {
|
|
32
|
-
// array may have empty slots
|
|
33
|
-
for (const item of iterable) if (item == null) return true;
|
|
34
|
-
return false;
|
|
35
|
-
}
|
|
36
|
-
// JS %SameValueZero is same with `isSame` in this context
|
|
37
|
-
if (isVmPrimitive(value)) return iterable.includes(value);
|
|
38
|
-
// value is not null here, so it's ok to skip empty slots, since `isSame(null, something)` is always false
|
|
39
|
-
return iterable.some((item = null) => isSame(item, value satisfies NonNullable<VmValue>));
|
|
40
|
-
}
|
|
41
|
-
// iterable is a record or an extern here, value should be a string
|
|
42
|
-
const key = toString(value, undefined);
|
|
43
|
-
if (isVmWrapper(iterable)) return iterable.has(key);
|
|
44
|
-
return hasOwnEnumerable(iterable satisfies VmRecord, key);
|
|
45
|
-
};
|
|
46
|
-
|
|
47
14
|
/** 获取值的长度 */
|
|
48
15
|
export const $Length = (value: VmAny): number => {
|
|
49
16
|
$AssertInit(value);
|
|
@@ -54,35 +21,6 @@ export const $Length = (value: VmAny): number => {
|
|
|
54
21
|
throw new VmError(`Value has no length: ${display(value)}`, 0);
|
|
55
22
|
};
|
|
56
23
|
|
|
57
|
-
/** 删除记录中的指定字段 */
|
|
58
|
-
export const $Omit = (value: VmAny, omitted: ReadonlyArray<number | string>): VmRecord => {
|
|
59
|
-
$AssertInit(value);
|
|
60
|
-
if (!isVmRecord(value)) return {};
|
|
61
|
-
const result: Record<string, VmConst> = {};
|
|
62
|
-
const valueKeys = keys(value);
|
|
63
|
-
const omittedSet = new Set(omitted.map($ToString));
|
|
64
|
-
for (const key of valueKeys) {
|
|
65
|
-
if (!omittedSet.has(key)) {
|
|
66
|
-
/* c8 ignore next */
|
|
67
|
-
result[key] = value[key] ?? null;
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
return result;
|
|
71
|
-
};
|
|
72
|
-
|
|
73
|
-
/** 选择记录中的指定字段 */
|
|
74
|
-
export const $Pick = (value: VmAny, picked: ReadonlyArray<number | string>): VmRecord => {
|
|
75
|
-
$AssertInit(value);
|
|
76
|
-
if (!isVmRecord(value)) return {};
|
|
77
|
-
const result: Record<string, VmConst> = {};
|
|
78
|
-
for (const key of picked) {
|
|
79
|
-
const k = $ToString(key);
|
|
80
|
-
if (hasOwnEnumerable(value, k)) {
|
|
81
|
-
result[k] = value[k] ?? null;
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
return result;
|
|
85
|
-
};
|
|
86
24
|
/** 检查是否拥有字段 */
|
|
87
25
|
export const $Has = (obj: VmAny, key: VmAny): boolean => {
|
|
88
26
|
$AssertInit(obj);
|
|
@@ -114,8 +52,7 @@ export const $Get = (obj: VmAny, key: VmAny): VmValue => {
|
|
|
114
52
|
}
|
|
115
53
|
return obj.get(pk) ?? null;
|
|
116
54
|
}
|
|
117
|
-
|
|
118
|
-
return $El(obj[pk] ?? null);
|
|
55
|
+
return $El(getRecord(obj, pk) ?? null);
|
|
119
56
|
};
|
|
120
57
|
/** 设置字段 */
|
|
121
58
|
export const $Set = (obj: VmAny, key: VmAny, value: VmAny): void => {
|
|
@@ -125,60 +62,3 @@ export const $Set = (obj: VmAny, key: VmAny, value: VmAny): void => {
|
|
|
125
62
|
if (!isVmExtern(obj)) throw new VmError(`Expected extern, got ${display(obj)}`, undefined);
|
|
126
63
|
obj.set(pk, value);
|
|
127
64
|
};
|
|
128
|
-
/** 获取可迭代对象 */
|
|
129
|
-
export const $Iterable = (value: VmAny): Iterable<VmValue | undefined> => {
|
|
130
|
-
$AssertInit(value);
|
|
131
|
-
if (isVmWrapper(value)) return value.keys();
|
|
132
|
-
if (isVmArray(value)) return value;
|
|
133
|
-
if (value != null && typeof value == 'object') return keys(value);
|
|
134
|
-
throw new VmError(`Value is not iterable: ${display(value)}`, isVmFunction(value) ? [] : [value]);
|
|
135
|
-
};
|
|
136
|
-
/** 展开记录 */
|
|
137
|
-
export const $RecordSpread = (record: VmAny): VmRecord | null => {
|
|
138
|
-
$AssertInit(record);
|
|
139
|
-
if (record == null || isVmRecord(record)) return record;
|
|
140
|
-
if (isVmArray(record)) {
|
|
141
|
-
const result: Record<string, VmConst> = {};
|
|
142
|
-
const len = record.length;
|
|
143
|
-
for (let i = 0; i < len; i++) {
|
|
144
|
-
const item = record[i];
|
|
145
|
-
result[i] = item ?? null;
|
|
146
|
-
}
|
|
147
|
-
return result;
|
|
148
|
-
}
|
|
149
|
-
if (isVmExtern(record)) {
|
|
150
|
-
const result: Record<string, VmConst> = create(null);
|
|
151
|
-
for (const key of record.keys()) {
|
|
152
|
-
const value = record.get(key) ?? null;
|
|
153
|
-
if (isVmConst(value)) {
|
|
154
|
-
result[key] = value;
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
return result;
|
|
158
|
-
}
|
|
159
|
-
throw new VmError(`Expected record, array, extern or nil, got ${display(record)}`, null);
|
|
160
|
-
};
|
|
161
|
-
|
|
162
|
-
/** 展开数组 */
|
|
163
|
-
export const $ArraySpread = (array: VmAny): Iterable<VmConst | undefined> => {
|
|
164
|
-
$AssertInit(array);
|
|
165
|
-
if (array == null) return [];
|
|
166
|
-
if (isVmArray(array)) return array;
|
|
167
|
-
if (isVmExtern(array)) {
|
|
168
|
-
if (array.isArrayLike()) {
|
|
169
|
-
const result: VmConst[] = [];
|
|
170
|
-
for (let i = 0, len = array.value.length; i < len; i++) {
|
|
171
|
-
const item = array.value[i];
|
|
172
|
-
result.push(wrapToVmConst(item, (v) => array.assumeVmValue(v, i)));
|
|
173
|
-
}
|
|
174
|
-
return result;
|
|
175
|
-
} else if (typeof (array.value as Iterable<unknown>)[Symbol.iterator] == 'function') {
|
|
176
|
-
const result: VmConst[] = [];
|
|
177
|
-
for (const item of array.value as Iterable<unknown>) {
|
|
178
|
-
result.push(wrapToVmConst(item, (v) => array.assumeVmValue(v, Symbol.iterator as never)));
|
|
179
|
-
}
|
|
180
|
-
return result;
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
throw new VmError(`Expected array, iterable extern or nil, got ${display(array)}`, []);
|
|
184
|
-
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { create, defineProperty, entries } from '../../helpers/utils.js';
|
|
2
2
|
import { VM_FUNCTION_ANONYMOUS_NAME } from '../../helpers/constants.js';
|
|
3
|
-
import { isVmConst } from '../../helpers/types.js';
|
|
3
|
+
import { isVmConst } from '../../helpers/types/index.js';
|
|
4
4
|
import type { VmFunctionLike } from '../types/function.js';
|
|
5
5
|
import { DefaultVmContext, type VmContext } from '../types/context.js';
|
|
6
6
|
import type { VmConst, VmAny, VmValue, VmImmutable } from '../types/index.js';
|
|
@@ -5,6 +5,9 @@ export * from './operator.js';
|
|
|
5
5
|
export * from './slice.js';
|
|
6
6
|
export * from './helpers.js';
|
|
7
7
|
export * from './compound.js';
|
|
8
|
+
export * from './spread.js';
|
|
9
|
+
export * from './record.js';
|
|
10
|
+
export * from './iterable.js';
|
|
8
11
|
export * from './cp.js';
|
|
9
12
|
export * from './call.js';
|
|
10
13
|
export * from './array-range.js';
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { VmError } from '../../helpers/error.js';
|
|
2
|
+
import { hasOwnEnumerable, keys } from '../../helpers/utils.js';
|
|
3
|
+
import { toString } from '../../helpers/convert/index.js';
|
|
4
|
+
import { display } from '../../helpers/serialize.js';
|
|
5
|
+
import { isVmPrimitive, isVmArray, isVmFunction, isVmWrapper } from '../../helpers/types/index.js';
|
|
6
|
+
import type { VmAny, VmRecord, VmValue } from '../types/index.js';
|
|
7
|
+
import { isSame } from './utils.js';
|
|
8
|
+
import { $AssertInit } from './common.js';
|
|
9
|
+
|
|
10
|
+
/** 检查值是否在可迭代对象中 */
|
|
11
|
+
export const $In = (value: VmAny, iterable: VmAny): boolean => {
|
|
12
|
+
$AssertInit(value);
|
|
13
|
+
$AssertInit(iterable);
|
|
14
|
+
if (iterable == null) return false;
|
|
15
|
+
if (typeof iterable != 'object') return false;
|
|
16
|
+
if (isVmArray(iterable)) {
|
|
17
|
+
if (value == null) {
|
|
18
|
+
// array may have empty slots
|
|
19
|
+
for (const item of iterable) if (item == null) return true;
|
|
20
|
+
return false;
|
|
21
|
+
}
|
|
22
|
+
// JS %SameValueZero is same with `isSame` in this context
|
|
23
|
+
if (isVmPrimitive(value)) return iterable.includes(value);
|
|
24
|
+
// value is not null here, so it's ok to skip empty slots, since `isSame(null, something)` is always false
|
|
25
|
+
return iterable.some((item = null) => isSame(item, value satisfies NonNullable<VmValue>));
|
|
26
|
+
}
|
|
27
|
+
// iterable is a record or an extern here, value should be a string
|
|
28
|
+
const key = toString(value, undefined);
|
|
29
|
+
if (isVmWrapper(iterable)) return iterable.has(key);
|
|
30
|
+
return hasOwnEnumerable(iterable satisfies VmRecord, key);
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
/** 获取可迭代对象 */
|
|
34
|
+
export const $Iterable = (value: VmAny): Iterable<VmValue | undefined> => {
|
|
35
|
+
$AssertInit(value);
|
|
36
|
+
if (isVmWrapper(value)) return value.keys();
|
|
37
|
+
if (isVmArray(value)) return value;
|
|
38
|
+
if (value != null && typeof value == 'object') return keys(value);
|
|
39
|
+
throw new VmError(`Value is not iterable: ${display(value)}`, isVmFunction(value) ? [] : [value]);
|
|
40
|
+
};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { hasOwnEnumerable, keys, setRecord } from '../../helpers/utils.js';
|
|
2
|
+
import { isVmRecord } from '../../helpers/types/index.js';
|
|
3
|
+
import type { VmAny, VmRecord, VmConst } from '../types/index.js';
|
|
4
|
+
import { $AssertInit } from './common.js';
|
|
5
|
+
|
|
6
|
+
/** 删除记录中的指定字段 */
|
|
7
|
+
export const $Omit = (value: VmAny, omitted: ReadonlyArray<number | string>): VmRecord => {
|
|
8
|
+
$AssertInit(value);
|
|
9
|
+
if (!isVmRecord(value)) return {};
|
|
10
|
+
const result: Record<string, VmConst> = {};
|
|
11
|
+
const valueKeys = keys(value);
|
|
12
|
+
const omittedSet = new Set(omitted.map(String));
|
|
13
|
+
for (const key of valueKeys) {
|
|
14
|
+
if (!omittedSet.has(key)) {
|
|
15
|
+
setRecord(result, key, value[key]);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
return result;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
/** 选择记录中的指定字段 */
|
|
22
|
+
export const $Pick = (value: VmAny, picked: ReadonlyArray<number | string>): VmRecord => {
|
|
23
|
+
$AssertInit(value);
|
|
24
|
+
if (!isVmRecord(value)) return {};
|
|
25
|
+
const result: Record<string, VmConst> = {};
|
|
26
|
+
for (const key of picked) {
|
|
27
|
+
const k = String(key);
|
|
28
|
+
if (hasOwnEnumerable(value, k)) {
|
|
29
|
+
setRecord(result, k, value[k]);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
@@ -1,44 +1,45 @@
|
|
|
1
1
|
import { VmError } from '../../helpers/error.js';
|
|
2
2
|
import { display } from '../../helpers/serialize.js';
|
|
3
|
+
import { toNumber } from '../../helpers/convert/number.js';
|
|
3
4
|
import { isNaN, isSafeInteger } from '../../helpers/utils.js';
|
|
4
|
-
import { isVmArray } from '../../helpers/types.js';
|
|
5
|
+
import { isVmArray } from '../../helpers/types/index.js';
|
|
5
6
|
import type { VmAny, VmArray } from '../types/index.js';
|
|
6
7
|
import { $AssertInit } from './common.js';
|
|
7
|
-
import { $ToNumber } from './convert.js';
|
|
8
8
|
const { ceil } = Math;
|
|
9
9
|
const { slice } = Array.prototype;
|
|
10
10
|
|
|
11
|
-
const sliceCore = (value:
|
|
11
|
+
const sliceCore = (value: VmAny, start: VmAny, end: VmAny, exclusive: boolean): VmArray => {
|
|
12
|
+
$AssertInit(value);
|
|
13
|
+
$AssertInit(start);
|
|
14
|
+
$AssertInit(end);
|
|
15
|
+
|
|
16
|
+
if (!isVmArray(value)) {
|
|
17
|
+
throw new VmError(`Expected array, got ${display(value)}`, []);
|
|
18
|
+
}
|
|
12
19
|
const { length } = value;
|
|
20
|
+
let s = start != null ? toNumber(start) : 0;
|
|
21
|
+
let e = end != null ? toNumber(end) : length - (exclusive ? 0 : 1);
|
|
13
22
|
|
|
14
|
-
if (isNaN(
|
|
15
|
-
else if (
|
|
23
|
+
if (isNaN(s)) s = 0;
|
|
24
|
+
else if (s < 0) s = length + s;
|
|
16
25
|
|
|
17
|
-
if (isNaN(
|
|
18
|
-
else if (
|
|
26
|
+
if (isNaN(e)) e = exclusive ? length : length - 1;
|
|
27
|
+
else if (e < 0) e = length + e;
|
|
19
28
|
|
|
20
|
-
|
|
21
|
-
if (exclusive || !isSafeInteger(
|
|
22
|
-
|
|
29
|
+
s = ceil(s);
|
|
30
|
+
if (exclusive || !isSafeInteger(e)) {
|
|
31
|
+
e = ceil(e);
|
|
23
32
|
} else {
|
|
24
|
-
|
|
33
|
+
e = e + 1;
|
|
25
34
|
}
|
|
26
|
-
return slice.call(value,
|
|
35
|
+
return slice.call(value, s, e) satisfies unknown[] as VmArray;
|
|
27
36
|
};
|
|
28
37
|
|
|
29
38
|
/** 获取数组切片 */
|
|
30
39
|
export const $Slice = (value: VmAny, start: VmAny, end: VmAny): VmArray => {
|
|
31
|
-
|
|
32
|
-
if (!isVmArray(value)) throw new VmError(`Expected array, got ${display(value)}`, []);
|
|
33
|
-
const s = start != null ? $ToNumber(start) : 0;
|
|
34
|
-
const e = end != null ? $ToNumber(end) : value.length - 1;
|
|
35
|
-
return sliceCore(value, s, e, false);
|
|
40
|
+
return sliceCore(value, start, end, false);
|
|
36
41
|
};
|
|
37
42
|
/** 获取数组切片(不包含结束位置) */
|
|
38
43
|
export const $SliceExclusive = (value: VmAny, start: VmAny, end: VmAny): VmArray => {
|
|
39
|
-
|
|
40
|
-
if (!isVmArray(value)) throw new VmError(`Expected array, got ${display(value)}`, []);
|
|
41
|
-
const s = start != null ? $ToNumber(start) : 0;
|
|
42
|
-
const e = end != null ? $ToNumber(end) : value.length;
|
|
43
|
-
return sliceCore(value, s, e, true);
|
|
44
|
+
return sliceCore(value, start, end, true);
|
|
44
45
|
};
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { VmError } from '../../helpers/error.js';
|
|
2
|
+
import { create } from '../../helpers/utils.js';
|
|
3
|
+
import { display } from '../../helpers/serialize.js';
|
|
4
|
+
import { isVmArray, isVmRecord, isVmExtern, isVmConst } from '../../helpers/types/index.js';
|
|
5
|
+
import { wrapToVmConst } from '../types/boundary.js';
|
|
6
|
+
import type { VmAny, VmRecord, VmConst } from '../types/index.js';
|
|
7
|
+
import { $AssertInit } from './common.js';
|
|
8
|
+
|
|
9
|
+
/** 展开记录 */
|
|
10
|
+
export const $RecordSpread = (record: VmAny): VmRecord | null => {
|
|
11
|
+
$AssertInit(record);
|
|
12
|
+
if (record == null || isVmRecord(record)) return record;
|
|
13
|
+
if (isVmArray(record)) {
|
|
14
|
+
const result: Record<string, VmConst> = {};
|
|
15
|
+
const len = record.length;
|
|
16
|
+
for (let i = 0; i < len; i++) {
|
|
17
|
+
const item = record[i];
|
|
18
|
+
result[i] = item ?? null;
|
|
19
|
+
}
|
|
20
|
+
return result;
|
|
21
|
+
}
|
|
22
|
+
if (isVmExtern(record)) {
|
|
23
|
+
const result: Record<string, VmConst> = create(null);
|
|
24
|
+
for (const key of record.keys()) {
|
|
25
|
+
const value = record.get(key) ?? null;
|
|
26
|
+
if (isVmConst(value)) {
|
|
27
|
+
result[key] = value;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return result;
|
|
31
|
+
}
|
|
32
|
+
throw new VmError(`Expected record, array, extern or nil, got ${display(record)}`, null);
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
/** 展开数组 */
|
|
36
|
+
export const $ArraySpread = (array: VmAny): Iterable<VmConst | undefined> => {
|
|
37
|
+
$AssertInit(array);
|
|
38
|
+
if (array == null) return [];
|
|
39
|
+
if (isVmArray(array)) return array;
|
|
40
|
+
if (isVmExtern(array)) {
|
|
41
|
+
if (array.isArrayLike()) {
|
|
42
|
+
const result: VmConst[] = [];
|
|
43
|
+
for (let i = 0, len = array.value.length; i < len; i++) {
|
|
44
|
+
const item = array.value[i];
|
|
45
|
+
result.push(wrapToVmConst(item, (v) => array.assumeVmValue(v, i)));
|
|
46
|
+
}
|
|
47
|
+
return result;
|
|
48
|
+
} else if (typeof (array.value as Iterable<unknown>)[Symbol.iterator] == 'function') {
|
|
49
|
+
const result: VmConst[] = [];
|
|
50
|
+
for (const item of array.value as Iterable<unknown>) {
|
|
51
|
+
result.push(wrapToVmConst(item, (v) => array.assumeVmValue(v, Symbol.iterator as never)));
|
|
52
|
+
}
|
|
53
|
+
return result;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
throw new VmError(`Expected array, iterable extern or nil, got ${display(array)}`, []);
|
|
57
|
+
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { VmError } from '../../helpers/error.js';
|
|
2
|
-
import { getVmType, isVmArray, isVmRecord } from '../../helpers/types.js';
|
|
2
|
+
import { getVmType, isVmArray, isVmRecord } from '../../helpers/types/index.js';
|
|
3
3
|
import type { VmTypeName, VmAny, VmArray, VmRecord, VmValue } from '../types/index.js';
|
|
4
4
|
import { $AssertInit } from './common.js';
|
|
5
5
|
|