@mirascript/mirascript 0.1.15 → 0.1.17
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-JG3D67GF.js +1625 -0
- package/dist/chunk-JG3D67GF.js.map +6 -0
- package/dist/chunk-RIT53WVY.js +1 -0
- package/dist/chunk-RLWIIOH5.js +12 -0
- package/dist/chunk-RLWIIOH5.js.map +6 -0
- package/dist/{chunk-NT235HY3.js → chunk-W2I5XPIE.js} +1490 -608
- package/dist/chunk-W2I5XPIE.js.map +6 -0
- package/dist/cli/index.js +11 -67
- package/dist/cli/index.js.map +2 -2
- package/dist/compiler/compile-fast.d.ts +1 -1
- package/dist/compiler/compile-fast.d.ts.map +1 -1
- package/dist/compiler/create-script.d.ts +10 -1
- package/dist/compiler/create-script.d.ts.map +1 -1
- package/dist/compiler/diagnostic.d.ts +1 -1
- package/dist/compiler/diagnostic.d.ts.map +1 -1
- package/dist/compiler/emit/constants.d.ts +3 -0
- package/dist/compiler/emit/constants.d.ts.map +1 -0
- package/dist/compiler/emit/consts.d.ts +6 -0
- package/dist/compiler/emit/consts.d.ts.map +1 -0
- package/dist/compiler/emit/globals.d.ts +17 -0
- package/dist/compiler/emit/globals.d.ts.map +1 -0
- package/dist/compiler/emit/index.d.ts +58 -0
- package/dist/compiler/emit/index.d.ts.map +1 -0
- package/dist/compiler/emit/sourcemap.d.ts +6 -0
- package/dist/compiler/emit/sourcemap.d.ts.map +1 -0
- package/dist/compiler/index.d.ts +3 -2
- package/dist/compiler/index.d.ts.map +1 -1
- package/dist/compiler/worker.js +1 -1
- package/dist/helpers/constants.d.ts +10 -0
- package/dist/helpers/constants.d.ts.map +1 -1
- package/dist/helpers/convert/index.d.ts +5 -0
- package/dist/helpers/convert/index.d.ts.map +1 -0
- package/dist/helpers/convert/to-boolean.d.ts +4 -0
- package/dist/helpers/convert/to-boolean.d.ts.map +1 -0
- package/dist/helpers/convert/to-format.d.ts +4 -0
- package/dist/helpers/convert/to-format.d.ts.map +1 -0
- package/dist/helpers/convert/to-number.d.ts +4 -0
- package/dist/helpers/convert/to-number.d.ts.map +1 -0
- package/dist/helpers/convert/to-string.d.ts +6 -0
- package/dist/helpers/convert/to-string.d.ts.map +1 -0
- package/dist/{vm → helpers}/error.d.ts +1 -1
- package/dist/helpers/error.d.ts.map +1 -0
- package/dist/helpers/serialize.d.ts +13 -4
- package/dist/helpers/serialize.d.ts.map +1 -1
- package/dist/helpers/types.d.ts +54 -0
- package/dist/helpers/types.d.ts.map +1 -0
- package/dist/index.js +11 -17
- package/dist/subtle.d.ts +4 -3
- package/dist/subtle.d.ts.map +1 -1
- package/dist/subtle.js +20 -16
- package/dist/vm/checkpoint.d.ts +9 -0
- package/dist/vm/checkpoint.d.ts.map +1 -0
- package/dist/vm/helpers.d.ts +4 -10
- package/dist/vm/helpers.d.ts.map +1 -1
- package/dist/vm/index.d.ts +3 -3
- package/dist/vm/index.d.ts.map +1 -1
- package/dist/vm/lib/global/bit.d.ts +7 -7
- package/dist/vm/lib/global/bit.d.ts.map +1 -1
- package/dist/vm/lib/global/debug.d.ts +2 -2
- package/dist/vm/lib/global/debug.d.ts.map +1 -1
- package/dist/vm/lib/global/index.d.ts +0 -1
- package/dist/vm/lib/global/index.d.ts.map +1 -1
- package/dist/vm/lib/global/json.d.ts +2 -2
- package/dist/vm/lib/global/json.d.ts.map +1 -1
- package/dist/vm/lib/global/math-additional.d.ts +1 -1
- package/dist/vm/lib/global/math-additional.d.ts.map +1 -1
- package/dist/vm/lib/global/math-arr.d.ts +5 -5
- package/dist/vm/lib/global/math-arr.d.ts.map +1 -1
- package/dist/vm/lib/global/math-unary.d.ts +26 -26
- package/dist/vm/lib/global/math-unary.d.ts.map +1 -1
- package/dist/vm/lib/global/math.d.ts +3 -3
- package/dist/vm/lib/global/math.d.ts.map +1 -1
- package/dist/vm/lib/global/sequence/all-any.d.ts +2 -2
- package/dist/vm/lib/global/sequence/all-any.d.ts.map +1 -1
- package/dist/vm/lib/global/sequence/entries.d.ts +5 -5
- package/dist/vm/lib/global/sequence/entries.d.ts.map +1 -1
- package/dist/vm/lib/global/sequence/find.d.ts +3 -3
- package/dist/vm/lib/global/sequence/find.d.ts.map +1 -1
- package/dist/vm/lib/global/sequence/flatten.d.ts +1 -1
- package/dist/vm/lib/global/sequence/flatten.d.ts.map +1 -1
- package/dist/vm/lib/global/sequence/len.d.ts +1 -1
- package/dist/vm/lib/global/sequence/len.d.ts.map +1 -1
- package/dist/vm/lib/global/sequence/map-filter.d.ts +3 -3
- package/dist/vm/lib/global/sequence/map-filter.d.ts.map +1 -1
- package/dist/vm/lib/global/sequence/repeat.d.ts +1 -1
- package/dist/vm/lib/global/sequence/repeat.d.ts.map +1 -1
- package/dist/vm/lib/global/sequence/reverse.d.ts +1 -1
- package/dist/vm/lib/global/sequence/reverse.d.ts.map +1 -1
- package/dist/vm/lib/global/sequence/sort.d.ts +2 -2
- package/dist/vm/lib/global/sequence/sort.d.ts.map +1 -1
- package/dist/vm/lib/global/sequence/with.d.ts +2 -2
- package/dist/vm/lib/global/sequence/with.d.ts.map +1 -1
- package/dist/vm/lib/global/sequence/zip.d.ts +1 -1
- package/dist/vm/lib/global/sequence/zip.d.ts.map +1 -1
- package/dist/vm/lib/global/string.d.ts +10 -10
- package/dist/vm/lib/global/string.d.ts.map +1 -1
- package/dist/vm/lib/global/time.d.ts +3 -13
- package/dist/vm/lib/global/time.d.ts.map +1 -1
- package/dist/vm/lib/global/to-primitive.d.ts +4 -4
- package/dist/vm/lib/global/to-primitive.d.ts.map +1 -1
- package/dist/vm/lib/helpers.d.ts +53 -0
- package/dist/vm/lib/helpers.d.ts.map +1 -0
- package/dist/vm/lib/index.d.ts +4 -0
- package/dist/vm/lib/index.d.ts.map +1 -0
- package/dist/vm/lib/{_loader.d.ts → loader.d.ts} +5 -5
- package/dist/vm/lib/loader.d.ts.map +1 -0
- package/dist/vm/lib/mod/index.d.ts +2 -0
- package/dist/vm/lib/mod/index.d.ts.map +1 -0
- package/dist/vm/lib/mod/matrix.d.ts +15 -0
- package/dist/vm/lib/mod/matrix.d.ts.map +1 -0
- package/dist/vm/operations.d.ts +2 -4
- package/dist/vm/operations.d.ts.map +1 -1
- package/dist/vm/types/boundary.d.ts +1 -1
- package/dist/vm/types/boundary.d.ts.map +1 -1
- package/dist/vm/types/context.d.ts +4 -17
- package/dist/vm/types/context.d.ts.map +1 -1
- package/dist/vm/types/extern.d.ts +1 -3
- package/dist/vm/types/extern.d.ts.map +1 -1
- package/dist/vm/types/function.d.ts +1 -6
- package/dist/vm/types/function.d.ts.map +1 -1
- package/dist/vm/types/index.d.ts +31 -17
- package/dist/vm/types/index.d.ts.map +1 -1
- package/dist/vm/types/module.d.ts +2 -4
- package/dist/vm/types/module.d.ts.map +1 -1
- package/dist/vm/types/wrapper.d.ts +0 -2
- package/dist/vm/types/wrapper.d.ts.map +1 -1
- package/package.json +7 -3
- package/src/cli/index.ts +1 -1
- package/src/compiler/compile-fast.ts +1 -2
- package/src/compiler/create-script.ts +12 -2
- package/src/compiler/diagnostic.ts +17 -8
- package/src/compiler/emit/constants.ts +2 -0
- package/src/compiler/emit/consts.ts +47 -0
- package/src/compiler/emit/globals.ts +39 -0
- package/src/compiler/{emit.ts → emit/index.ts} +16 -200
- package/src/compiler/emit/sourcemap.ts +168 -0
- package/src/compiler/index.ts +9 -9
- package/src/compiler/worker.ts +1 -1
- package/src/helpers/constants.ts +12 -0
- package/src/helpers/convert/index.ts +4 -0
- package/src/helpers/convert/to-boolean.ts +12 -0
- package/src/helpers/convert/to-format.ts +37 -0
- package/src/helpers/convert/to-number.ts +35 -0
- package/src/helpers/convert/to-string.ts +55 -0
- package/src/{vm → helpers}/error.ts +1 -1
- package/src/helpers/serialize.ts +72 -24
- package/src/helpers/types.ts +267 -0
- package/src/subtle.ts +4 -2
- package/src/vm/checkpoint.ts +42 -0
- package/src/vm/helpers.ts +9 -53
- package/src/vm/index.ts +3 -3
- package/src/vm/lib/global/bit.ts +8 -9
- package/src/vm/lib/global/debug.ts +5 -4
- package/src/vm/lib/global/index.ts +0 -1
- package/src/vm/lib/global/json.ts +2 -2
- package/src/vm/lib/global/math-additional.ts +2 -4
- package/src/vm/lib/global/math-arr.ts +1 -1
- package/src/vm/lib/global/math-unary.ts +2 -4
- package/src/vm/lib/global/math.ts +3 -4
- package/src/vm/lib/global/sequence/all-any.ts +11 -6
- package/src/vm/lib/global/sequence/entries.ts +1 -1
- package/src/vm/lib/global/sequence/find.ts +4 -3
- package/src/vm/lib/global/sequence/flatten.ts +2 -3
- package/src/vm/lib/global/sequence/len.ts +1 -1
- package/src/vm/lib/global/sequence/map-filter.ts +4 -3
- package/src/vm/lib/global/sequence/repeat.ts +2 -4
- package/src/vm/lib/global/sequence/reverse.ts +1 -1
- package/src/vm/lib/global/sequence/sort.ts +6 -5
- package/src/vm/lib/global/sequence/with.ts +21 -20
- package/src/vm/lib/global/sequence/zip.ts +3 -3
- package/src/vm/lib/global/string.ts +16 -27
- package/src/vm/lib/global/time.ts +59 -30
- package/src/vm/lib/global/to-primitive.ts +27 -18
- package/src/vm/lib/{_helpers.ts → helpers.ts} +132 -44
- package/src/vm/lib/index.ts +16 -0
- package/src/vm/lib/{_loader.ts → loader.ts} +3 -11
- package/src/vm/lib/mod/index.ts +1 -0
- package/src/vm/lib/{global/mod → mod}/matrix.ts +9 -7
- package/src/vm/operations.ts +41 -137
- package/src/vm/types/boundary.ts +10 -13
- package/src/vm/types/context.ts +31 -50
- package/src/vm/types/extern.ts +8 -15
- package/src/vm/types/function.ts +4 -19
- package/src/vm/types/index.ts +47 -25
- package/src/vm/types/module.ts +3 -7
- package/src/vm/types/wrapper.ts +1 -5
- package/dist/chunk-35JGBXRE.js +0 -1
- package/dist/chunk-JVFUK7AN.js +0 -2324
- package/dist/chunk-JVFUK7AN.js.map +0 -6
- package/dist/chunk-NT235HY3.js.map +0 -6
- package/dist/compiler/emit.d.ts +0 -5
- package/dist/compiler/emit.d.ts.map +0 -1
- package/dist/vm/error.d.ts.map +0 -1
- package/dist/vm/lib/_helpers.d.ts +0 -35
- package/dist/vm/lib/_helpers.d.ts.map +0 -1
- package/dist/vm/lib/_loader.d.ts.map +0 -1
- package/dist/vm/lib/global/mod/index.d.ts +0 -3
- package/dist/vm/lib/global/mod/index.d.ts.map +0 -1
- package/dist/vm/lib/global/mod/matrix.d.ts +0 -15
- package/dist/vm/lib/global/mod/matrix.d.ts.map +0 -1
- package/dist/vm/types/any.d.ts +0 -10
- package/dist/vm/types/any.d.ts.map +0 -1
- package/dist/vm/types/array.d.ts +0 -12
- package/dist/vm/types/array.d.ts.map +0 -1
- package/dist/vm/types/callable.d.ts +0 -5
- package/dist/vm/types/callable.d.ts.map +0 -1
- package/dist/vm/types/const.d.ts +0 -15
- package/dist/vm/types/const.d.ts.map +0 -1
- package/dist/vm/types/immutable.d.ts +0 -15
- package/dist/vm/types/immutable.d.ts.map +0 -1
- package/dist/vm/types/primitive.d.ts +0 -7
- package/dist/vm/types/primitive.d.ts.map +0 -1
- package/dist/vm/types/record.d.ts +0 -20
- package/dist/vm/types/record.d.ts.map +0 -1
- package/dist/vm/types/script.d.ts +0 -14
- package/dist/vm/types/script.d.ts.map +0 -1
- package/dist/vm/types/value.d.ts +0 -14
- package/dist/vm/types/value.d.ts.map +0 -1
- package/src/vm/lib/global/mod/index.ts +0 -4
- package/src/vm/types/any.ts +0 -33
- package/src/vm/types/array.ts +0 -19
- package/src/vm/types/callable.ts +0 -10
- package/src/vm/types/const.ts +0 -109
- package/src/vm/types/immutable.ts +0 -22
- package/src/vm/types/primitive.ts +0 -14
- package/src/vm/types/record.ts +0 -53
- package/src/vm/types/script.ts +0 -18
- package/src/vm/types/value.ts +0 -22
- /package/dist/{chunk-35JGBXRE.js.map → chunk-RIT53WVY.js.map} +0 -0
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
1
|
+
import { toNumber } from '../../../helpers/convert/to-number.js';
|
|
2
|
+
import { isArray } from '../../../helpers/utils.js';
|
|
3
|
+
import { Cp } from '../../helpers.js';
|
|
4
|
+
import { $Add, $Call, $Div, $Mul, $Sub } from '../../operations.js';
|
|
5
|
+
import { isVmArray, isVmConst, type VmAny, type VmArray, type VmConst, type VmValue } from '../../types/index.js';
|
|
5
6
|
import {
|
|
6
7
|
VmLib,
|
|
7
8
|
expectArray,
|
|
@@ -12,7 +13,8 @@ import {
|
|
|
12
13
|
getNumbers,
|
|
13
14
|
arrayLen,
|
|
14
15
|
map,
|
|
15
|
-
|
|
16
|
+
expectInteger,
|
|
17
|
+
} from '../helpers.js';
|
|
16
18
|
|
|
17
19
|
/** 计算尺寸 */
|
|
18
20
|
function sizeImpl(matrix: VmValue): [] | [number] | [number, number] {
|
|
@@ -35,7 +37,7 @@ function sizeImpl(matrix: VmValue): [] | [number] | [number, number] {
|
|
|
35
37
|
|
|
36
38
|
/** 数组元素转为 number */
|
|
37
39
|
function num(v: VmConst | undefined): number {
|
|
38
|
-
return
|
|
40
|
+
return toNumber(v, undefined);
|
|
39
41
|
}
|
|
40
42
|
|
|
41
43
|
export const size = VmLib(
|
|
@@ -535,7 +537,7 @@ export const identity = VmLib(
|
|
|
535
537
|
export const diagonal = VmLib(
|
|
536
538
|
(x, k = 0) => {
|
|
537
539
|
expectArray('x', x, []);
|
|
538
|
-
const fk =
|
|
540
|
+
const fk = expectInteger('k', k);
|
|
539
541
|
if (x.every((e) => isArray(e))) {
|
|
540
542
|
// 获取对角线元素
|
|
541
543
|
const diag: VmConst[] = [];
|
package/src/vm/operations.ts
CHANGED
|
@@ -1,28 +1,12 @@
|
|
|
1
|
-
import { VmError } from '
|
|
2
|
-
import {
|
|
3
|
-
isVmPrimitive,
|
|
4
|
-
isVmArray,
|
|
5
|
-
isVmRecord,
|
|
6
|
-
isVmFunction,
|
|
7
|
-
isVmExtern,
|
|
8
|
-
isVmModule,
|
|
9
|
-
isVmWrapper,
|
|
10
|
-
getVmFunctionInfo,
|
|
11
|
-
type TypeName,
|
|
12
|
-
type VmAny,
|
|
13
|
-
type VmImmutable,
|
|
14
|
-
type VmRecord,
|
|
15
|
-
type VmValue,
|
|
16
|
-
type VmArray,
|
|
17
|
-
type VmConst,
|
|
18
|
-
type VmPrimitive,
|
|
19
|
-
type VmFunction,
|
|
20
|
-
} from './types/index.js';
|
|
1
|
+
import { VmError } from '../helpers/error.js';
|
|
21
2
|
import { hasOwnEnumerable, isNaN, isSafeInteger, keys, create } from '../helpers/utils.js';
|
|
3
|
+
import { toNumber, toString, toBoolean, toFormat } from '../helpers/convert/index.js';
|
|
4
|
+
import { display } from '../helpers/serialize.js';
|
|
5
|
+
import { isVmPrimitive, isVmArray, isVmRecord, isVmFunction, isVmExtern, isVmWrapper } from '../helpers/types.js';
|
|
6
|
+
import type { TypeName, VmAny, VmImmutable, VmRecord, VmValue, VmArray, VmConst } from './types/index.js';
|
|
22
7
|
|
|
23
8
|
const { abs, min, trunc, ceil } = Math;
|
|
24
9
|
const { slice, at } = Array.prototype;
|
|
25
|
-
const { POSITIVE_INFINITY, NEGATIVE_INFINITY } = Number;
|
|
26
10
|
|
|
27
11
|
const isSame = (a: VmValue, b: VmValue): boolean => {
|
|
28
12
|
// Check for NaN
|
|
@@ -60,7 +44,10 @@ const isSame = (a: VmValue, b: VmValue): boolean => {
|
|
|
60
44
|
if (!hasOwnEnumerable(b, key)) {
|
|
61
45
|
return false;
|
|
62
46
|
}
|
|
63
|
-
|
|
47
|
+
/* c8 ignore next 2 */
|
|
48
|
+
const av = a[key] ?? null;
|
|
49
|
+
const bv = b[key] ?? null;
|
|
50
|
+
if (!isSame(av, bv)) {
|
|
64
51
|
return false;
|
|
65
52
|
}
|
|
66
53
|
}
|
|
@@ -180,28 +167,25 @@ export const $In = (value: VmAny, iterable: VmAny): boolean => {
|
|
|
180
167
|
$AssertInit(value);
|
|
181
168
|
$AssertInit(iterable);
|
|
182
169
|
if (iterable == null) return false;
|
|
170
|
+
if (typeof iterable != 'object') return false;
|
|
183
171
|
if (isVmArray(iterable)) {
|
|
184
172
|
if (value == null) {
|
|
185
173
|
// array may have empty slots
|
|
186
|
-
for (const item of iterable)
|
|
187
|
-
if (item == null) return true;
|
|
188
|
-
}
|
|
174
|
+
for (const item of iterable) if (item == null) return true;
|
|
189
175
|
return false;
|
|
190
176
|
}
|
|
191
177
|
// JS %SameValueZero is same with `isSame` in this context
|
|
192
178
|
if (isVmPrimitive(value)) return iterable.includes(value);
|
|
193
179
|
// value is not null here, so it's ok to skip empty slots, since `isSame(null, something)` is always false
|
|
194
|
-
value satisfies NonNullable<VmValue
|
|
195
|
-
return iterable.some((item = null) => isSame(item, value));
|
|
180
|
+
return iterable.some((item = null) => isSame(item, value satisfies NonNullable<VmValue>));
|
|
196
181
|
}
|
|
197
182
|
// iterable is a record or an extern here, value should be a string
|
|
198
|
-
|
|
199
|
-
if (
|
|
200
|
-
iterable satisfies
|
|
201
|
-
return false;
|
|
183
|
+
const key = toString(value, undefined);
|
|
184
|
+
if (isVmWrapper(iterable)) return iterable.has(key);
|
|
185
|
+
return hasOwnEnumerable(iterable satisfies VmRecord, key);
|
|
202
186
|
};
|
|
203
|
-
export const $Concat = (...args: string[]): string => {
|
|
204
|
-
return args.map(
|
|
187
|
+
export const $Concat = (...args: readonly string[]): string => {
|
|
188
|
+
return args.map((a) => toFormat(a, null)).join('');
|
|
205
189
|
};
|
|
206
190
|
export const $Pos = (a: VmAny): number => {
|
|
207
191
|
return $ToNumber(a);
|
|
@@ -216,10 +200,9 @@ export const $Length = (value: VmAny): number => {
|
|
|
216
200
|
$AssertInit(value);
|
|
217
201
|
if (isVmArray(value)) return value.length;
|
|
218
202
|
if (isVmRecord(value)) return keys(value).length;
|
|
219
|
-
if (isVmWrapper(value))
|
|
220
|
-
|
|
221
|
-
}
|
|
222
|
-
return Number.NaN;
|
|
203
|
+
if (isVmWrapper(value)) return value.keys().length;
|
|
204
|
+
|
|
205
|
+
throw new VmError(`Value has no length: ${display(value)}`, 0);
|
|
223
206
|
};
|
|
224
207
|
export const $Omit = (value: VmAny, omitted: ReadonlyArray<number | string>): VmRecord => {
|
|
225
208
|
$AssertInit(value);
|
|
@@ -229,6 +212,7 @@ export const $Omit = (value: VmAny, omitted: ReadonlyArray<number | string>): Vm
|
|
|
229
212
|
const omittedSet = new Set(omitted.map($ToString));
|
|
230
213
|
for (const key of valueKeys) {
|
|
231
214
|
if (!omittedSet.has(key)) {
|
|
215
|
+
/* c8 ignore next */
|
|
232
216
|
result[key] = value[key] ?? null;
|
|
233
217
|
}
|
|
234
218
|
}
|
|
@@ -265,14 +249,14 @@ const sliceCore = (value: VmArray, start: number, end: number, exclusive: boolea
|
|
|
265
249
|
};
|
|
266
250
|
export const $Slice = (value: VmAny, start: VmAny, end: VmAny): VmArray => {
|
|
267
251
|
$AssertInit(value);
|
|
268
|
-
if (!isVmArray(value)) throw new VmError(`Expected array, got ${
|
|
252
|
+
if (!isVmArray(value)) throw new VmError(`Expected array, got ${display(value)}`, []);
|
|
269
253
|
const s = start != null ? $ToNumber(start) : 0;
|
|
270
254
|
const e = end != null ? $ToNumber(end) : value.length - 1;
|
|
271
255
|
return sliceCore(value, s, e, false);
|
|
272
256
|
};
|
|
273
257
|
export const $SliceExclusive = (value: VmAny, start: VmAny, end: VmAny): VmArray => {
|
|
274
258
|
$AssertInit(value);
|
|
275
|
-
if (!isVmArray(value)) throw new VmError(`Expected array, got ${
|
|
259
|
+
if (!isVmArray(value)) throw new VmError(`Expected array, got ${display(value)}`, []);
|
|
276
260
|
const s = start != null ? $ToNumber(start) : 0;
|
|
277
261
|
const e = end != null ? $ToNumber(end) : value.length;
|
|
278
262
|
return sliceCore(value, s, e, true);
|
|
@@ -290,82 +274,30 @@ export const $Call = (func: VmValue, args: readonly VmAny[]): VmValue => {
|
|
|
290
274
|
if (isVmFunction(func)) {
|
|
291
275
|
return func(...(args as readonly VmValue[])) ?? null;
|
|
292
276
|
}
|
|
293
|
-
throw new VmError(`
|
|
277
|
+
throw new VmError(`Value is not callable: ${display(func)}`, null);
|
|
294
278
|
};
|
|
295
279
|
export const $Type = (value: VmAny): TypeName => {
|
|
296
|
-
|
|
297
|
-
if (
|
|
298
|
-
if (
|
|
280
|
+
// 允许未初始化值通过
|
|
281
|
+
if (value == null) return 'nil';
|
|
282
|
+
if (isVmWrapper(value)) return value.type;
|
|
299
283
|
if (isVmArray(value)) return 'array';
|
|
300
284
|
if (typeof value == 'object') return 'record';
|
|
301
285
|
return typeof value as TypeName;
|
|
302
286
|
};
|
|
303
287
|
export const $ToBoolean = (value: VmAny): boolean => {
|
|
288
|
+
if (typeof value == 'boolean') return value;
|
|
304
289
|
$AssertInit(value);
|
|
305
|
-
return value
|
|
306
|
-
};
|
|
307
|
-
/** 将值转为字符串 */
|
|
308
|
-
function numberToString(value: number): string {
|
|
309
|
-
if (isNaN(value)) return 'nan';
|
|
310
|
-
if (value === Infinity) return 'inf';
|
|
311
|
-
if (value === -Infinity) return '-inf';
|
|
312
|
-
return String(value);
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
/** 将值转为字符串 */
|
|
316
|
-
export function $InnerToString(value: VmAny, useBraces: boolean): string {
|
|
317
|
-
if (value == null) return 'nil';
|
|
318
|
-
if (isVmWrapper(value)) return value.toString(useBraces);
|
|
319
|
-
if (typeof value == 'function') {
|
|
320
|
-
const name = getVmFunctionInfo(value)?.fullName;
|
|
321
|
-
return name ? `<function ${name}>` : `<function>`;
|
|
322
|
-
}
|
|
323
|
-
if (isVmArray(value)) {
|
|
324
|
-
const strings: string[] = [];
|
|
325
|
-
for (const item of value) {
|
|
326
|
-
strings.push($InnerToString(item, true));
|
|
327
|
-
}
|
|
328
|
-
// 在 join 过程中会自动把 null/undefined 和 empty slot 转为 ''
|
|
329
|
-
// 与 innerToString 行为不一致
|
|
330
|
-
const results = strings.join(', ');
|
|
331
|
-
if (!useBraces) return results;
|
|
332
|
-
return `[${results}]`;
|
|
333
|
-
}
|
|
334
|
-
if (typeof value == 'object') {
|
|
335
|
-
const entries = keys(value)
|
|
336
|
-
.map((key) => `${key}: ${$InnerToString(value[key], true)}`)
|
|
337
|
-
.join(', ');
|
|
338
|
-
if (!useBraces) return entries;
|
|
339
|
-
return `(${entries})`;
|
|
340
|
-
}
|
|
341
|
-
if (typeof value == 'number') {
|
|
342
|
-
return numberToString(value);
|
|
343
|
-
}
|
|
344
|
-
return String(value);
|
|
345
|
-
}
|
|
290
|
+
return toBoolean(value, undefined);
|
|
291
|
+
};
|
|
346
292
|
export const $ToString = (value: VmAny): string => {
|
|
347
|
-
$AssertInit(value);
|
|
348
293
|
if (typeof value == 'string') return value;
|
|
349
|
-
|
|
350
|
-
return
|
|
294
|
+
$AssertInit(value);
|
|
295
|
+
return toString(value, undefined);
|
|
351
296
|
};
|
|
352
297
|
export const $ToNumber = (value: VmAny): number => {
|
|
353
|
-
$AssertInit(value);
|
|
354
298
|
if (typeof value == 'number') return value;
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
value = value.trim();
|
|
358
|
-
if (value === '') return 0;
|
|
359
|
-
if (value === 'inf' || value === '+inf' || value === 'Infinity' || value === '+Infinity') {
|
|
360
|
-
return POSITIVE_INFINITY;
|
|
361
|
-
}
|
|
362
|
-
if (value === '-inf' || value === '-Infinity') {
|
|
363
|
-
return NEGATIVE_INFINITY;
|
|
364
|
-
}
|
|
365
|
-
return Number(value);
|
|
366
|
-
}
|
|
367
|
-
if (typeof value == 'boolean') return value ? 1 : 0;
|
|
368
|
-
return Number.NaN;
|
|
299
|
+
$AssertInit(value);
|
|
300
|
+
return toNumber(value, undefined);
|
|
369
301
|
};
|
|
370
302
|
export const $IsBoolean = (value: VmAny): value is boolean => {
|
|
371
303
|
$AssertInit(value);
|
|
@@ -390,7 +322,7 @@ export const $IsArray = (value: VmAny): value is VmArray => {
|
|
|
390
322
|
export const $AssertNonNil = (value: VmAny): asserts value is NonNullable<VmValue> => {
|
|
391
323
|
$AssertInit(value);
|
|
392
324
|
if (value !== null) return;
|
|
393
|
-
throw new VmError(
|
|
325
|
+
throw new VmError(`Expected non-nil value`, null);
|
|
394
326
|
};
|
|
395
327
|
export const $Has = (obj: VmAny, key: VmAny): boolean => {
|
|
396
328
|
$AssertInit(obj);
|
|
@@ -417,7 +349,7 @@ export const $Set = (obj: VmAny, key: VmAny, value: VmAny): void => {
|
|
|
417
349
|
$AssertInit(value);
|
|
418
350
|
const pk = $ToString(key);
|
|
419
351
|
if (obj == null) return;
|
|
420
|
-
if (!isVmExtern(obj)) throw new VmError(`Expected extern, got ${
|
|
352
|
+
if (!isVmExtern(obj)) throw new VmError(`Expected extern, got ${display(obj)}`, undefined);
|
|
421
353
|
obj.set(pk, value);
|
|
422
354
|
};
|
|
423
355
|
export const $Iterable = (value: VmAny): Iterable<VmValue | undefined> => {
|
|
@@ -425,7 +357,7 @@ export const $Iterable = (value: VmAny): Iterable<VmValue | undefined> => {
|
|
|
425
357
|
if (isVmWrapper(value)) return value.keys();
|
|
426
358
|
if (isVmArray(value)) return value;
|
|
427
359
|
if (value != null && typeof value == 'object') return keys(value);
|
|
428
|
-
throw new VmError(`Value is not iterable`, isVmFunction(value) ? [] : [value]);
|
|
360
|
+
throw new VmError(`Value is not iterable: ${display(value)}`, isVmFunction(value) ? [] : [value]);
|
|
429
361
|
};
|
|
430
362
|
|
|
431
363
|
export const $RecordSpread = (record: VmAny): VmRecord | null => {
|
|
@@ -451,7 +383,7 @@ export const $RecordSpread = (record: VmAny): VmRecord | null => {
|
|
|
451
383
|
}
|
|
452
384
|
return result;
|
|
453
385
|
}
|
|
454
|
-
throw new VmError(`Expected record, array, extern or nil, got ${
|
|
386
|
+
throw new VmError(`Expected record, array, extern or nil, got ${display(record)}`, null);
|
|
455
387
|
};
|
|
456
388
|
|
|
457
389
|
export const $ArraySpread = (array: VmAny): Iterable<VmConst | undefined> => {
|
|
@@ -470,39 +402,11 @@ export const $ArraySpread = (array: VmAny): Iterable<VmConst | undefined> => {
|
|
|
470
402
|
}
|
|
471
403
|
return result;
|
|
472
404
|
}
|
|
473
|
-
throw new VmError(`Expected array, iterable extern or nil, got ${
|
|
405
|
+
throw new VmError(`Expected array, iterable extern or nil, got ${display(array)}`, []);
|
|
474
406
|
};
|
|
475
407
|
|
|
476
|
-
/** 渲染数字 */
|
|
477
|
-
function formatNumber(value: number): string {
|
|
478
|
-
if (!Number.isFinite(value)) return numberToString(value);
|
|
479
|
-
if (value === 0) return '0';
|
|
480
|
-
const s = value.toString();
|
|
481
|
-
let ps;
|
|
482
|
-
const abs = Math.abs(value);
|
|
483
|
-
if (abs >= 1000 || abs < 0.001) {
|
|
484
|
-
const ps1 = value.toExponential();
|
|
485
|
-
const ps2 = value.toExponential(5);
|
|
486
|
-
ps = ps1.length < ps2.length ? ps1 : ps2;
|
|
487
|
-
} else {
|
|
488
|
-
ps = value.toPrecision(6);
|
|
489
|
-
}
|
|
490
|
-
return ps.length < s.length ? ps : s;
|
|
491
|
-
}
|
|
492
|
-
|
|
493
408
|
export const $Format = (value: VmAny, format: VmAny): string => {
|
|
494
409
|
$AssertInit(value);
|
|
495
|
-
const f = format == null ? '' :
|
|
496
|
-
|
|
497
|
-
if (typeof value == 'number') {
|
|
498
|
-
if (/^\.\d+$/.test(f)) {
|
|
499
|
-
let digits = Math.trunc(Number(f.slice(1)));
|
|
500
|
-
if (!(digits <= 100)) digits = 100;
|
|
501
|
-
return value.toFixed(digits);
|
|
502
|
-
} else {
|
|
503
|
-
return formatNumber(value);
|
|
504
|
-
}
|
|
505
|
-
}
|
|
506
|
-
|
|
507
|
-
return $ToString(value);
|
|
410
|
+
const f = format == null ? '' : $ToString(format);
|
|
411
|
+
return toFormat(value, f);
|
|
508
412
|
};
|
package/src/vm/types/boundary.ts
CHANGED
|
@@ -1,17 +1,14 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { isVmExtern,
|
|
3
|
-
import {
|
|
1
|
+
import { defineProperty, apply } from '../../helpers/utils.js';
|
|
2
|
+
import { isVmExtern, isVmFunction, isVmWrapper } from '../../helpers/types.js';
|
|
3
|
+
import { kVmFunctionProxy } from '../../helpers/constants.js';
|
|
4
|
+
import type { VmFunctionLike, VmFunction } from './function.js';
|
|
5
|
+
import { VmExtern } from './extern.js';
|
|
4
6
|
import type { VmAny, VmConst, VmModule, VmPrimitive, VmValue } from './index.js';
|
|
5
7
|
import { $Call } from '../operations.js';
|
|
6
|
-
import { defineProperty, apply } from '../../helpers/utils.js';
|
|
7
|
-
|
|
8
|
-
const kProxy = Symbol.for('mirascript.vm.function.proxy');
|
|
9
8
|
|
|
10
9
|
/** 创建 Mirascript 函数在宿主语言运行的代理 */
|
|
11
10
|
export function toVmFunctionProxy<T extends VmFunctionLike>(fn: VmFunction<T>): T {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
const cached = (fn as unknown as { [kProxy]?: T })[kProxy];
|
|
11
|
+
const cached = (fn as unknown as { [kVmFunctionProxy]?: T })[kVmFunctionProxy];
|
|
15
12
|
if (cached != null) return cached;
|
|
16
13
|
|
|
17
14
|
const proxy = (...args: unknown[]) => {
|
|
@@ -22,8 +19,8 @@ export function toVmFunctionProxy<T extends VmFunctionLike>(fn: VmFunction<T>):
|
|
|
22
19
|
);
|
|
23
20
|
return unwrapFromVmValue(ret);
|
|
24
21
|
};
|
|
25
|
-
defineProperty(fn,
|
|
26
|
-
defineProperty(proxy,
|
|
22
|
+
defineProperty(fn, kVmFunctionProxy, { value: proxy });
|
|
23
|
+
defineProperty(proxy, kVmFunctionProxy, { value: fn });
|
|
27
24
|
defineProperty(proxy, 'name', {
|
|
28
25
|
value: fn.name,
|
|
29
26
|
configurable: true,
|
|
@@ -35,7 +32,7 @@ export function toVmFunctionProxy<T extends VmFunctionLike>(fn: VmFunction<T>):
|
|
|
35
32
|
export function fromVmFunctionProxy<T extends VmFunctionLike>(fn: T): VmFunction<T> | undefined {
|
|
36
33
|
if (isVmFunction(fn)) return fn;
|
|
37
34
|
|
|
38
|
-
const original = (fn as unknown as { [
|
|
35
|
+
const original = (fn as unknown as { [kVmFunctionProxy]?: VmFunction<T> })[kVmFunctionProxy];
|
|
39
36
|
if (original && isVmFunction(original)) return original;
|
|
40
37
|
|
|
41
38
|
return undefined;
|
|
@@ -76,7 +73,7 @@ export function wrapToVmValue(
|
|
|
76
73
|
|
|
77
74
|
/** 取消宿主语言的值的 Mirascript 包装 */
|
|
78
75
|
export function unwrapFromVmValue(value: VmAny): unknown {
|
|
79
|
-
if (
|
|
76
|
+
if (isVmFunction(value)) {
|
|
80
77
|
return toVmFunctionProxy(value);
|
|
81
78
|
}
|
|
82
79
|
if (value == null || typeof value != 'object') return value;
|
package/src/vm/types/context.ts
CHANGED
|
@@ -1,35 +1,18 @@
|
|
|
1
|
-
import {
|
|
2
|
-
VmFunction,
|
|
3
|
-
type VmAny,
|
|
4
|
-
type VmImmutable,
|
|
5
|
-
type VmValue,
|
|
6
|
-
wrapToVmValue,
|
|
7
|
-
isVmAny,
|
|
8
|
-
type VmFunctionLike,
|
|
9
|
-
} from './index.js';
|
|
10
1
|
import { create, entries, keys } from '../../helpers/utils.js';
|
|
11
|
-
import
|
|
12
|
-
import { VmError } from '
|
|
2
|
+
import { isVmAny } from '../../helpers/types.js';
|
|
3
|
+
import { VmError } from '../../helpers/error.js';
|
|
4
|
+
import { kVmContext } from '../../helpers/constants.js';
|
|
5
|
+
import type { VmAny, VmImmutable, VmValue } from './index.js';
|
|
6
|
+
import { wrapToVmValue } from './boundary.js';
|
|
7
|
+
import { VmFunction } from './function.js';
|
|
8
|
+
const { freeze } = Object;
|
|
13
9
|
|
|
14
|
-
/** 全局导入的标准库 */
|
|
15
|
-
type GlobalKeys = keyof typeof global;
|
|
16
|
-
/** 全局导入的标准库值 */
|
|
17
|
-
type ToGlobalValue<T extends GlobalKeys> = (typeof global)[T] extends VmFunctionLike
|
|
18
|
-
? VmFunction<(typeof global)[T]>
|
|
19
|
-
: (typeof global)[T];
|
|
20
|
-
/** 全局导入的标准库 */
|
|
21
|
-
type VmContextBase = {
|
|
22
|
-
[key in GlobalKeys]: ToGlobalValue<key>;
|
|
23
|
-
};
|
|
24
|
-
const kVmContext = Symbol.for('mirascript.vm.context');
|
|
25
|
-
/** MiraScript 执行上下文的基础,仅包含标准库 */
|
|
26
|
-
export type VmSharedContext = VmContextBase & Record<string, VmImmutable>;
|
|
27
10
|
/** MiraScript 执行上下文 */
|
|
28
11
|
export interface VmContext {
|
|
29
12
|
/** 内部标识符 */
|
|
30
13
|
readonly [kVmContext]: true;
|
|
31
14
|
/** 枚举所有 key,仅在 LSP 中使用 */
|
|
32
|
-
keys():
|
|
15
|
+
keys(): readonly string[];
|
|
33
16
|
/** 描述值,返回 MarkDown 文本,仅在 LSP 中使用 */
|
|
34
17
|
describe?(key: string): string | undefined;
|
|
35
18
|
/**
|
|
@@ -44,9 +27,9 @@ export interface VmContext {
|
|
|
44
27
|
export type VmContextRecord = Record<string, VmValue>;
|
|
45
28
|
/** MiraScript 执行上下文 */
|
|
46
29
|
export type VmContextRecordLoose = Record<string, VmValue | undefined>;
|
|
47
|
-
export const
|
|
48
|
-
|
|
49
|
-
let
|
|
30
|
+
export const VM_SHARED_CONTEXT: Record<string, VmImmutable> = create(null);
|
|
31
|
+
/** 缓存 {@link VM_SHARED_CONTEXT} 的 keys */
|
|
32
|
+
let VM_SHARED_CONTEXT_KEYS: readonly string[] | null = null;
|
|
50
33
|
|
|
51
34
|
/** 全局变量未找到 */
|
|
52
35
|
function globalVarNotFound(name: string): never {
|
|
@@ -59,7 +42,7 @@ export function defineVmContextValue(
|
|
|
59
42
|
value: VmImmutable | ((...args: VmAny[]) => VmAny),
|
|
60
43
|
override = false,
|
|
61
44
|
): void {
|
|
62
|
-
if (!override && name in
|
|
45
|
+
if (!override && name in VM_SHARED_CONTEXT) throw new Error(`Global variable '${name}' is already defined.`);
|
|
63
46
|
let v: VmImmutable;
|
|
64
47
|
if (typeof value == 'function') {
|
|
65
48
|
v = VmFunction(value, {
|
|
@@ -69,38 +52,42 @@ export function defineVmContextValue(
|
|
|
69
52
|
} else {
|
|
70
53
|
v = value;
|
|
71
54
|
}
|
|
72
|
-
|
|
73
|
-
|
|
55
|
+
VM_SHARED_CONTEXT[name] = v ?? null;
|
|
56
|
+
VM_SHARED_CONTEXT_KEYS = null;
|
|
74
57
|
}
|
|
75
58
|
|
|
76
59
|
/** 无后备的实现 */
|
|
77
|
-
export const DefaultVmContext: VmContext =
|
|
60
|
+
export const DefaultVmContext: VmContext = freeze({
|
|
78
61
|
[kVmContext]: true as const,
|
|
79
62
|
/** @inheritdoc */
|
|
80
|
-
keys():
|
|
81
|
-
|
|
82
|
-
return
|
|
63
|
+
keys(): readonly string[] {
|
|
64
|
+
VM_SHARED_CONTEXT_KEYS ??= freeze(keys(VM_SHARED_CONTEXT));
|
|
65
|
+
return VM_SHARED_CONTEXT_KEYS;
|
|
83
66
|
},
|
|
84
67
|
/** @inheritdoc */
|
|
85
68
|
get(key: string): VmValue {
|
|
86
|
-
const val =
|
|
69
|
+
const val = VM_SHARED_CONTEXT[key];
|
|
87
70
|
if (val === undefined) globalVarNotFound(key);
|
|
88
71
|
return val;
|
|
89
72
|
},
|
|
90
73
|
/** @inheritdoc */
|
|
91
74
|
has(key: string): boolean {
|
|
92
|
-
return key in
|
|
75
|
+
return key in VM_SHARED_CONTEXT;
|
|
93
76
|
},
|
|
94
77
|
});
|
|
95
78
|
|
|
96
79
|
/** 以值为后备的实现 */
|
|
97
80
|
class ValueVmContext implements VmContext {
|
|
98
81
|
readonly [kVmContext] = true;
|
|
99
|
-
private cachedKeys: readonly string[] | null = null;
|
|
82
|
+
private cachedKeys: readonly [def: readonly string[], all: readonly string[]] | null = null;
|
|
100
83
|
/** @inheritdoc */
|
|
101
|
-
keys():
|
|
102
|
-
|
|
103
|
-
|
|
84
|
+
keys(): readonly string[] {
|
|
85
|
+
const defaultKeys = DefaultVmContext.keys();
|
|
86
|
+
if (this.cachedKeys?.[0] !== defaultKeys) {
|
|
87
|
+
const allKeys = freeze([...keys(this.env), ...defaultKeys]);
|
|
88
|
+
this.cachedKeys = freeze([defaultKeys, allKeys]);
|
|
89
|
+
}
|
|
90
|
+
return this.cachedKeys[1];
|
|
104
91
|
}
|
|
105
92
|
/** @inheritdoc */
|
|
106
93
|
get(key: string): VmValue {
|
|
@@ -123,9 +110,9 @@ class ValueVmContext implements VmContext {
|
|
|
123
110
|
class FactoryVmContext implements VmContext {
|
|
124
111
|
readonly [kVmContext] = true;
|
|
125
112
|
/** @inheritdoc */
|
|
126
|
-
keys():
|
|
113
|
+
keys(): readonly string[] {
|
|
127
114
|
if (!this.enumerator) return DefaultVmContext.keys();
|
|
128
|
-
return [...this.enumerator(), ...DefaultVmContext.keys()];
|
|
115
|
+
return freeze([...this.enumerator(), ...DefaultVmContext.keys()]);
|
|
129
116
|
}
|
|
130
117
|
/** @inheritdoc */
|
|
131
118
|
get(key: string): VmValue {
|
|
@@ -170,7 +157,7 @@ export function createVmContext(...args: CreateVmContextWithValues | CreateVmCon
|
|
|
170
157
|
}
|
|
171
158
|
|
|
172
159
|
const [vmValues, externValues, describer] = args as CreateVmContextWithValues;
|
|
173
|
-
const env = create(
|
|
160
|
+
const env: VmContextRecord = create(VM_SHARED_CONTEXT);
|
|
174
161
|
if (vmValues) {
|
|
175
162
|
for (const [key, value] of entries(vmValues)) {
|
|
176
163
|
if (!isVmAny(value, false)) continue;
|
|
@@ -184,9 +171,3 @@ export function createVmContext(...args: CreateVmContextWithValues | CreateVmCon
|
|
|
184
171
|
}
|
|
185
172
|
return new ValueVmContext(env, describer ?? undefined);
|
|
186
173
|
}
|
|
187
|
-
|
|
188
|
-
/** 检查是否为执行上下文 */
|
|
189
|
-
export function isVmContext(context: unknown): context is VmContext {
|
|
190
|
-
if (context == null || typeof context != 'object') return false;
|
|
191
|
-
return (context as VmContext)[kVmContext] === true;
|
|
192
|
-
}
|
package/src/vm/types/extern.ts
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
import { VmError } from '
|
|
2
|
-
import { VmWrapper } from './wrapper.js';
|
|
3
|
-
import type { TypeName, VmAny, VmConst, VmPrimitive, VmValue } from './index.js';
|
|
1
|
+
import { VmError } from '../../helpers/error.js';
|
|
4
2
|
import { getPrototypeOf, hasOwn, apply, isArray } from '../../helpers/utils.js';
|
|
3
|
+
import { innerToString } from '../../helpers/convert/to-string.js';
|
|
4
|
+
import { isVmExtern } from '../../helpers/types.js';
|
|
5
|
+
import { kVmExtern } from '../../helpers/constants.js';
|
|
6
|
+
import type { TypeName, VmAny, VmConst, VmPrimitive, VmValue } from './index.js';
|
|
7
|
+
import { VmWrapper } from './wrapper.js';
|
|
5
8
|
import { unwrapFromVmValue, wrapToVmValue } from './boundary.js';
|
|
6
|
-
import { $InnerToString } from '../operations.js';
|
|
7
9
|
|
|
8
10
|
const ObjectPrototype = Object.prototype;
|
|
9
11
|
// eslint-disable-next-line @typescript-eslint/unbound-method
|
|
@@ -100,17 +102,13 @@ export class VmExtern<const T extends object = object> extends VmWrapper<T> {
|
|
|
100
102
|
if (toString === ArrayToString && isArray(this.value)) {
|
|
101
103
|
const mapped = ArrayMap.call(this.value, (item: unknown) => {
|
|
102
104
|
if (item === undefined) return '';
|
|
103
|
-
return
|
|
105
|
+
return innerToString(wrapToVmValue(item ?? null, null), true);
|
|
104
106
|
});
|
|
105
107
|
const str = mapped.join(', ');
|
|
106
108
|
if (useBraces) return `[${str}]`;
|
|
107
109
|
return str;
|
|
108
110
|
}
|
|
109
|
-
|
|
110
|
-
return String(this.value);
|
|
111
|
-
} catch {
|
|
112
|
-
return super.toString(useBraces);
|
|
113
|
-
}
|
|
111
|
+
return String(this.value);
|
|
114
112
|
}
|
|
115
113
|
/** @inheritdoc */
|
|
116
114
|
override get type(): TypeName {
|
|
@@ -157,9 +155,4 @@ export class VmExtern<const T extends object = object> extends VmWrapper<T> {
|
|
|
157
155
|
}
|
|
158
156
|
}
|
|
159
157
|
|
|
160
|
-
const kVmExtern = Symbol.for('mirascript.vm.extern');
|
|
161
158
|
Object.defineProperty(VmExtern.prototype, kVmExtern, { value: true });
|
|
162
|
-
/** 检查值是否为 Mirascript 外部值 */
|
|
163
|
-
export function isVmExtern<T extends object>(value: unknown): value is VmExtern<T> {
|
|
164
|
-
return value != null && typeof value == 'object' && kVmExtern in value;
|
|
165
|
-
}
|
package/src/vm/types/function.ts
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import type { Writable } from 'type-fest';
|
|
2
2
|
import { defineProperty } from '../../helpers/utils.js';
|
|
3
|
-
import {
|
|
3
|
+
import { kVmFunction, VM_FUNCTION_ANONYMOUS_NAME } from '../../helpers/constants.js';
|
|
4
4
|
import type { VmAny, VmValue } from './index.js';
|
|
5
5
|
import { fromVmFunctionProxy } from './boundary.js';
|
|
6
|
-
|
|
7
|
-
const kVmFunction = Symbol.for('mirascript.vm.function');
|
|
6
|
+
import { CpEnter, CpExit } from '../checkpoint.js';
|
|
8
7
|
|
|
9
8
|
/**
|
|
10
9
|
* Mirascript 函数签名
|
|
@@ -46,17 +45,6 @@ export type VmFunctionOption = Partial<
|
|
|
46
45
|
}
|
|
47
46
|
>;
|
|
48
47
|
|
|
49
|
-
/** 检查是否为 Mirascript 函数 */
|
|
50
|
-
export function isVmFunction<T extends VmFunctionLike>(value: unknown): value is VmFunction<T> {
|
|
51
|
-
return getVmFunctionInfo(value) != null;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
/** 检查是否为 Mirascript 函数,并获取其信息 */
|
|
55
|
-
export function getVmFunctionInfo(value: unknown): VmFunctionInfo | undefined {
|
|
56
|
-
if (typeof value != 'function') return undefined;
|
|
57
|
-
return (value as VmFunction)[kVmFunction];
|
|
58
|
-
}
|
|
59
|
-
|
|
60
48
|
/** 创建 Mirascript 函数 */
|
|
61
49
|
export function VmFunction<T extends VmFunctionLike>(fn: T, option: VmFunctionOption = {}): VmFunction<T> {
|
|
62
50
|
if (typeof fn != 'function') {
|
|
@@ -68,7 +56,7 @@ export function VmFunction<T extends VmFunctionLike>(fn: T, option: VmFunctionOp
|
|
|
68
56
|
if (exists) return exists;
|
|
69
57
|
|
|
70
58
|
const info: Writable<VmFunctionInfo> = {
|
|
71
|
-
fullName: option.fullName ?? fn.name,
|
|
59
|
+
fullName: option.fullName ?? (fn.name === VM_FUNCTION_ANONYMOUS_NAME ? '' : fn.name),
|
|
72
60
|
isLib: option.isLib ?? false,
|
|
73
61
|
summary: option.summary || undefined,
|
|
74
62
|
params: option.params,
|
|
@@ -89,10 +77,7 @@ export function VmFunction<T extends VmFunctionLike>(fn: T, option: VmFunctionOp
|
|
|
89
77
|
CpExit();
|
|
90
78
|
}
|
|
91
79
|
}) as typeof fn;
|
|
92
|
-
defineProperty(fn, 'name', {
|
|
93
|
-
value: original.name,
|
|
94
|
-
configurable: true,
|
|
95
|
-
});
|
|
80
|
+
defineProperty(fn, 'name', { value: original.name });
|
|
96
81
|
}
|
|
97
82
|
defineProperty(fn, kVmFunction, {
|
|
98
83
|
value: Object.freeze(info),
|