@mirascript/mirascript 0.1.14 → 0.1.16
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-Q74RKZ7O.js → chunk-LU4ZKFF6.js} +1420 -607
- package/dist/chunk-LU4ZKFF6.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-55FKP56O.js → chunk-YZGL3D7L.js} +741 -1361
- package/dist/chunk-YZGL3D7L.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 +15 -0
- package/dist/helpers/constants.d.ts.map +1 -1
- package/dist/helpers/convert.d.ts +12 -0
- package/dist/helpers/convert.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 +14 -5
- 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 +3 -2
- package/dist/subtle.d.ts.map +1 -1
- package/dist/subtle.js +21 -15
- 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 +4 -6
- 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 +18 -12
- 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} +18 -202
- package/src/compiler/emit/sourcemap.ts +163 -0
- package/src/compiler/index.ts +9 -9
- package/src/compiler/worker.ts +1 -1
- package/src/helpers/constants.ts +18 -1
- package/src/helpers/convert.ts +128 -0
- package/src/{vm → helpers}/error.ts +1 -1
- package/src/helpers/serialize.ts +72 -25
- package/src/helpers/types.ts +267 -0
- package/src/subtle.ts +3 -1
- 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 +3 -3
- package/src/vm/lib/global/sequence/find.ts +8 -7
- 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 +7 -6
- 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 +22 -21
- package/src/vm/lib/global/sequence/zip.ts +4 -4
- 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} +129 -41
- 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 +33 -128
- package/src/vm/types/boundary.ts +10 -13
- package/src/vm/types/context.ts +36 -28
- 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-55FKP56O.js.map +0 -6
- package/dist/chunk-Q74RKZ7O.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,10 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { expectArray, required, VmLib } from '../_helpers.js';
|
|
1
|
+
import { expectArray, expectString, VmLib } from '../helpers.js';
|
|
3
2
|
|
|
4
3
|
export const chars = VmLib(
|
|
5
4
|
(str) => {
|
|
6
|
-
|
|
7
|
-
return [...$ToString(str)];
|
|
5
|
+
return [...expectString('str', str)];
|
|
8
6
|
},
|
|
9
7
|
{
|
|
10
8
|
summary: '将字符串转换为字符数组',
|
|
@@ -17,9 +15,7 @@ export const chars = VmLib(
|
|
|
17
15
|
|
|
18
16
|
export const starts_with = VmLib(
|
|
19
17
|
(str, search) => {
|
|
20
|
-
|
|
21
|
-
required('search', search, null);
|
|
22
|
-
return $ToString(str).startsWith($ToString(search));
|
|
18
|
+
return expectString('str', str).startsWith(expectString('search', search));
|
|
23
19
|
},
|
|
24
20
|
{
|
|
25
21
|
summary: '检查字符串是否以指定子串开头',
|
|
@@ -31,9 +27,7 @@ export const starts_with = VmLib(
|
|
|
31
27
|
);
|
|
32
28
|
export const ends_with = VmLib(
|
|
33
29
|
(str, search) => {
|
|
34
|
-
|
|
35
|
-
required('search', search, null);
|
|
36
|
-
return $ToString(str).endsWith($ToString(search));
|
|
30
|
+
return expectString('str', str).endsWith(expectString('search', search));
|
|
37
31
|
},
|
|
38
32
|
{
|
|
39
33
|
summary: '检查字符串是否以指定子串结尾',
|
|
@@ -46,9 +40,7 @@ export const ends_with = VmLib(
|
|
|
46
40
|
|
|
47
41
|
export const contains = VmLib(
|
|
48
42
|
(str, search) => {
|
|
49
|
-
|
|
50
|
-
required('search', search, null);
|
|
51
|
-
return $ToString(str).includes($ToString(search));
|
|
43
|
+
return expectString('str', str).includes(expectString('search', search));
|
|
52
44
|
},
|
|
53
45
|
{
|
|
54
46
|
summary: '检查字符串是否包含指定子串',
|
|
@@ -61,8 +53,7 @@ export const contains = VmLib(
|
|
|
61
53
|
|
|
62
54
|
export const trim_start = VmLib(
|
|
63
55
|
(str) => {
|
|
64
|
-
|
|
65
|
-
return $ToString(str).trimStart();
|
|
56
|
+
return expectString('str', str).trimStart();
|
|
66
57
|
},
|
|
67
58
|
{
|
|
68
59
|
summary: '去除字符串开头的空白字符',
|
|
@@ -75,8 +66,7 @@ export const trim_start = VmLib(
|
|
|
75
66
|
|
|
76
67
|
export const trim_end = VmLib(
|
|
77
68
|
(str) => {
|
|
78
|
-
|
|
79
|
-
return $ToString(str).trimEnd();
|
|
69
|
+
return expectString('str', str).trimEnd();
|
|
80
70
|
},
|
|
81
71
|
{
|
|
82
72
|
summary: '去除字符串结尾的空白字符',
|
|
@@ -89,8 +79,7 @@ export const trim_end = VmLib(
|
|
|
89
79
|
|
|
90
80
|
export const trim = VmLib(
|
|
91
81
|
(str) => {
|
|
92
|
-
|
|
93
|
-
return $ToString(str).trim();
|
|
82
|
+
return expectString('str', str).trim();
|
|
94
83
|
},
|
|
95
84
|
{
|
|
96
85
|
summary: '去除字符串两端的空白字符',
|
|
@@ -103,9 +92,10 @@ export const trim = VmLib(
|
|
|
103
92
|
|
|
104
93
|
export const replace = VmLib(
|
|
105
94
|
(str, search, replacement = '') => {
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
95
|
+
return expectString('str', str).replaceAll(
|
|
96
|
+
expectString('search', search),
|
|
97
|
+
expectString('replacement', replacement),
|
|
98
|
+
);
|
|
109
99
|
},
|
|
110
100
|
{
|
|
111
101
|
summary: '替换字符串中的指定子串',
|
|
@@ -118,9 +108,8 @@ export const replace = VmLib(
|
|
|
118
108
|
|
|
119
109
|
export const split = VmLib(
|
|
120
110
|
(str, separator = '') => {
|
|
121
|
-
|
|
122
|
-
const
|
|
123
|
-
const p = $ToString(separator);
|
|
111
|
+
const s = expectString('str', str);
|
|
112
|
+
const p = expectString('separator', separator);
|
|
124
113
|
if (!p) return [...s];
|
|
125
114
|
return s.split(p);
|
|
126
115
|
},
|
|
@@ -136,8 +125,8 @@ export const split = VmLib(
|
|
|
136
125
|
export const join = VmLib(
|
|
137
126
|
(arr, separator = '') => {
|
|
138
127
|
expectArray('arr', arr, null);
|
|
139
|
-
const s =
|
|
140
|
-
return arr.map((v) =>
|
|
128
|
+
const s = expectString('separator', separator);
|
|
129
|
+
return arr.map((v) => expectString(null, v)).join(s);
|
|
141
130
|
},
|
|
142
131
|
{
|
|
143
132
|
summary: '将字符串数组连接为单个字符串',
|
|
@@ -1,35 +1,60 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { describeParam, expectNumberRange, throwError, throwUnexpectedTypeError, VmLib } from '../helpers.js';
|
|
2
|
+
import { isNaN, isFinite } from '../../../helpers/utils.js';
|
|
3
|
+
import { toNumber } from '../../../helpers/convert.js';
|
|
4
|
+
import { display } from '../../../helpers/serialize.js';
|
|
5
|
+
import type { VmAny } from '../../types/index.js';
|
|
6
|
+
|
|
7
|
+
const fromNumber = (datetime: number, fallback: boolean): number | null => {
|
|
8
|
+
const n = new Date(datetime).getTime();
|
|
9
|
+
if (isFinite(n)) return n;
|
|
10
|
+
if (fallback) return null;
|
|
11
|
+
throwError(`${describeParam('datetime')} is an invalid timestamp: ${display(datetime)}`, Number.NaN);
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
const getTimestamp = (datetime: VmAny, fallback: boolean): number | null => {
|
|
15
|
+
if (datetime == null) {
|
|
16
|
+
return Date.now();
|
|
17
|
+
}
|
|
18
|
+
if (typeof datetime == 'number') {
|
|
19
|
+
return fromNumber(datetime, fallback);
|
|
20
|
+
}
|
|
21
|
+
if (typeof datetime != 'string') {
|
|
22
|
+
if (fallback) return null;
|
|
23
|
+
throwUnexpectedTypeError('datetime', 'number | string', datetime, Number.NaN);
|
|
24
|
+
}
|
|
25
|
+
const num = toNumber(datetime, Number.NaN);
|
|
26
|
+
if (!isNaN(num)) {
|
|
27
|
+
return fromNumber(num, fallback);
|
|
28
|
+
}
|
|
29
|
+
const parsed = Date.parse(datetime);
|
|
30
|
+
if (isFinite(parsed)) return parsed;
|
|
31
|
+
if (fallback) return null;
|
|
32
|
+
throwError(`${describeParam('datetime')} cannot be parsed as datetime: ${display(datetime)}`, Number.NaN);
|
|
33
|
+
};
|
|
4
34
|
|
|
5
35
|
export const to_timestamp = VmLib(
|
|
6
|
-
(datetime) => {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
if (typeof datetime == 'number') {
|
|
11
|
-
return new Date(datetime).getTime();
|
|
12
|
-
}
|
|
13
|
-
const str = $ToString(datetime);
|
|
14
|
-
if (!str) return Number.NaN;
|
|
15
|
-
const num = $ToNumber(str);
|
|
16
|
-
if (isFinite(num)) return num;
|
|
17
|
-
return Date.parse(str);
|
|
36
|
+
(datetime, fallback) => {
|
|
37
|
+
const timestamp = getTimestamp(datetime, fallback !== undefined);
|
|
38
|
+
if (timestamp == null) return fallback;
|
|
39
|
+
return timestamp;
|
|
18
40
|
},
|
|
19
41
|
{
|
|
20
42
|
summary: '将数据转换为 Unix 毫秒时间戳',
|
|
21
|
-
params: {
|
|
22
|
-
|
|
23
|
-
|
|
43
|
+
params: {
|
|
44
|
+
datetime: '要转换的数据,默认为当前时间',
|
|
45
|
+
fallback: '转换失败时的返回值',
|
|
46
|
+
},
|
|
47
|
+
paramsType: { datetime: 'number | string', fallback: 'any' },
|
|
48
|
+
returnsType: 'number | type(fallback)',
|
|
24
49
|
examples: ['to_timestamp("1970-01-01T00:00:00Z") // 0'],
|
|
25
50
|
},
|
|
26
51
|
);
|
|
27
52
|
|
|
28
53
|
export const to_datetime = VmLib(
|
|
29
|
-
(datetime, offset) => {
|
|
30
|
-
const timestamp =
|
|
31
|
-
if (
|
|
32
|
-
const o =
|
|
54
|
+
(datetime, offset, fallback) => {
|
|
55
|
+
const timestamp = getTimestamp(datetime, fallback !== undefined);
|
|
56
|
+
if (timestamp == null) return fallback;
|
|
57
|
+
const o = expectNumberRange('offset', offset ?? 0, -24, 24);
|
|
33
58
|
const dateOffset = new Date(timestamp + o * 1000 * 60 * 60);
|
|
34
59
|
return {
|
|
35
60
|
year: dateOffset.getUTCFullYear(),
|
|
@@ -48,9 +73,10 @@ export const to_datetime = VmLib(
|
|
|
48
73
|
params: {
|
|
49
74
|
datetime: '要转换的数据,默认为当前时间',
|
|
50
75
|
offset: '时区偏移量(单位:小时),默认为 0',
|
|
76
|
+
fallback: '转换失败时的返回值',
|
|
51
77
|
},
|
|
52
|
-
paramsType: { datetime: '
|
|
53
|
-
returnsType: 'Date',
|
|
78
|
+
paramsType: { datetime: 'number | string', offset: 'number', fallback: 'any' },
|
|
79
|
+
returnsType: 'Date | type(fallback)',
|
|
54
80
|
examples: [
|
|
55
81
|
`
|
|
56
82
|
to_datetime(0)
|
|
@@ -65,16 +91,19 @@ to_datetime(0)
|
|
|
65
91
|
);
|
|
66
92
|
|
|
67
93
|
export const to_iso8601 = VmLib(
|
|
68
|
-
(datetime) => {
|
|
69
|
-
const timestamp =
|
|
70
|
-
if (
|
|
94
|
+
(datetime, fallback) => {
|
|
95
|
+
const timestamp = getTimestamp(datetime, fallback !== undefined);
|
|
96
|
+
if (timestamp == null) return fallback;
|
|
71
97
|
return new Date(timestamp).toISOString();
|
|
72
98
|
},
|
|
73
99
|
{
|
|
74
100
|
summary: '将数据转换为 ISO 8601 格式的字符串',
|
|
75
|
-
params: {
|
|
76
|
-
|
|
77
|
-
|
|
101
|
+
params: {
|
|
102
|
+
datetime: '要转换的数据,默认为当前时间',
|
|
103
|
+
fallback: '转换失败时的返回值',
|
|
104
|
+
},
|
|
105
|
+
paramsType: { datetime: 'number | string', fallback: 'any' },
|
|
106
|
+
returnsType: 'string | type(fallback)',
|
|
78
107
|
examples: ['to_iso8601(0) // "1970-01-01T00:00:00.000Z"'],
|
|
79
108
|
},
|
|
80
109
|
);
|
|
@@ -1,44 +1,53 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { required, VmLib } from '../
|
|
1
|
+
import { toBoolean, toFormat, toNumber, toString } from '../../../helpers/convert.js';
|
|
2
|
+
import { expectString, required, VmLib } from '../helpers.js';
|
|
3
3
|
|
|
4
4
|
export const to_string = VmLib(
|
|
5
|
-
(data) => {
|
|
5
|
+
(data, fallback) => {
|
|
6
6
|
required('data', data, '');
|
|
7
|
-
return
|
|
7
|
+
return toString(data, fallback);
|
|
8
8
|
},
|
|
9
9
|
{
|
|
10
10
|
summary: '将数据转换为字符串',
|
|
11
|
-
params: {
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
params: {
|
|
12
|
+
data: '要转换的数据',
|
|
13
|
+
fallback: '转换失败时的返回值',
|
|
14
|
+
},
|
|
15
|
+
paramsType: { data: 'any', fallback: 'any' },
|
|
16
|
+
returnsType: 'string | type(fallback)',
|
|
14
17
|
examples: ['to_string([1, 2]) // "1, 2"'],
|
|
15
18
|
},
|
|
16
19
|
);
|
|
17
20
|
|
|
18
21
|
export const to_number = VmLib(
|
|
19
|
-
(data) => {
|
|
22
|
+
(data, fallback) => {
|
|
20
23
|
required('data', data, Number.NaN);
|
|
21
|
-
return
|
|
24
|
+
return toNumber(data, fallback);
|
|
22
25
|
},
|
|
23
26
|
{
|
|
24
27
|
summary: '将数据转换为数字',
|
|
25
|
-
params: {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
+
params: {
|
|
29
|
+
data: '要转换的数据',
|
|
30
|
+
fallback: '转换失败时的返回值',
|
|
31
|
+
},
|
|
32
|
+
paramsType: { data: 'any', fallback: 'any' },
|
|
33
|
+
returnsType: 'number | type(fallback)',
|
|
28
34
|
examples: ['to_number("1.5") // 1.5'],
|
|
29
35
|
},
|
|
30
36
|
);
|
|
31
37
|
|
|
32
38
|
export const to_boolean = VmLib(
|
|
33
|
-
(data) => {
|
|
39
|
+
(data, fallback) => {
|
|
34
40
|
required('data', data, false);
|
|
35
|
-
return
|
|
41
|
+
return toBoolean(data, fallback);
|
|
36
42
|
},
|
|
37
43
|
{
|
|
38
44
|
summary: '将数据转换为布尔值',
|
|
39
|
-
params: {
|
|
40
|
-
|
|
41
|
-
|
|
45
|
+
params: {
|
|
46
|
+
data: '要转换的数据',
|
|
47
|
+
fallback: '转换失败时的返回值',
|
|
48
|
+
},
|
|
49
|
+
paramsType: { data: 'any', fallback: 'any' },
|
|
50
|
+
returnsType: 'boolean | type(fallback)',
|
|
42
51
|
examples: ['to_boolean(nil) // false'],
|
|
43
52
|
},
|
|
44
53
|
);
|
|
@@ -46,7 +55,7 @@ export const to_boolean = VmLib(
|
|
|
46
55
|
export const format = VmLib(
|
|
47
56
|
(data, format) => {
|
|
48
57
|
required('data', data, '');
|
|
49
|
-
return
|
|
58
|
+
return toFormat(data, expectString('format', format));
|
|
50
59
|
},
|
|
51
60
|
{
|
|
52
61
|
summary: '将数据格式化为指定格式的字符串',
|
|
@@ -1,44 +1,59 @@
|
|
|
1
1
|
import type { Writable } from 'type-fest';
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
isVmCallable,
|
|
2
|
+
import { VM_ARRAY_MAX_LENGTH } from '../../helpers/constants.js';
|
|
3
|
+
import { isNaN, entries, fromEntries, isSafeInteger, isFinite } from '../../helpers/utils.js';
|
|
4
|
+
import { toBoolean, toNumber, toString } from '../../helpers/convert.js';
|
|
5
|
+
import { display } from '../../helpers/serialize.js';
|
|
6
|
+
import { isVmArray, isVmFunction, isVmPrimitive, isVmConst, isVmCallable, isVmRecord } from '../../helpers/types.js';
|
|
7
|
+
import { VmError } from '../../helpers/error.js';
|
|
8
|
+
import type {
|
|
9
|
+
VmExtern,
|
|
10
|
+
VmFunction,
|
|
11
|
+
VmAny,
|
|
12
|
+
VmArray,
|
|
13
|
+
VmValue,
|
|
14
|
+
VmRecord,
|
|
15
|
+
VmModule,
|
|
16
|
+
VmConst,
|
|
17
|
+
VmFunctionLike,
|
|
18
|
+
VmFunctionOption,
|
|
20
19
|
} from '../types/index.js';
|
|
21
|
-
import type { VmFunctionLike, VmFunctionOption } from '../types/function.js';
|
|
22
20
|
import { Cp } from '../helpers.js';
|
|
23
|
-
import { isNaN, entries, fromEntries } from '../../helpers/utils.js';
|
|
24
21
|
|
|
25
22
|
/** 抛出异常 */
|
|
26
23
|
export function throwError(message: string, recovered: VmAny | (() => VmAny)): never {
|
|
27
24
|
const recoveredValue = typeof recovered === 'function' && !isVmFunction(recovered) ? recovered() : recovered;
|
|
28
25
|
throw new VmError(message, recoveredValue);
|
|
29
26
|
}
|
|
27
|
+
/** 描述参数 */
|
|
28
|
+
type ParamIndex = number | string | null;
|
|
29
|
+
/** 描述参数 */
|
|
30
|
+
export function describeParam(name: ParamIndex): string {
|
|
31
|
+
if (name == null) return 'Value';
|
|
32
|
+
if (typeof name == 'string') {
|
|
33
|
+
if (!name) return 'Argument';
|
|
34
|
+
return `Argument '${name}'`;
|
|
35
|
+
}
|
|
36
|
+
const pos = name <= 0 ? 'first' : name <= 1 ? 'second' : `${name + 1}th`;
|
|
37
|
+
return `Argument at the ${pos} position`;
|
|
38
|
+
}
|
|
30
39
|
|
|
31
40
|
/** 抛出预期外类型异常 */
|
|
32
41
|
export function throwUnexpectedTypeError(
|
|
33
|
-
name:
|
|
42
|
+
name: ParamIndex,
|
|
43
|
+
expected: string,
|
|
44
|
+
value: VmAny,
|
|
45
|
+
recovered: VmAny | (() => VmAny),
|
|
46
|
+
): never {
|
|
47
|
+
throwError(`${describeParam(name)} is not ${expected}: ${display(value)}`, recovered);
|
|
48
|
+
}
|
|
49
|
+
/** 抛出预期外类型异常 */
|
|
50
|
+
export function throwUnconvertedTypeError(
|
|
51
|
+
name: ParamIndex,
|
|
34
52
|
expected: string,
|
|
35
53
|
value: VmAny,
|
|
36
54
|
recovered: VmAny | (() => VmAny),
|
|
37
55
|
): never {
|
|
38
|
-
|
|
39
|
-
if (typeof name == 'string') throwError(`Expected ${expected} for parameter '${name}', got ${actual}`, recovered);
|
|
40
|
-
const pos = name <= 0 ? 'first' : name <= 1 ? 'second' : name + 1 + 'th';
|
|
41
|
-
throwError(`Expected ${expected} at the ${pos} position, got ${actual}`, recovered);
|
|
56
|
+
throwError(`${describeParam(name)} cannot be converted to ${expected}: ${display(value)}`, recovered);
|
|
42
57
|
}
|
|
43
58
|
|
|
44
59
|
/** 重新抛出异常 */
|
|
@@ -49,20 +64,86 @@ export function rethrowError(prefix: string, error: unknown, recovered: VmAny |
|
|
|
49
64
|
|
|
50
65
|
/** 标记参数为必须项 */
|
|
51
66
|
export function required<const T = VmValue>(
|
|
52
|
-
name:
|
|
67
|
+
name: ParamIndex,
|
|
53
68
|
value: T | undefined,
|
|
54
69
|
recovered: VmAny | (() => VmAny),
|
|
55
70
|
): asserts value is T {
|
|
56
71
|
if (value === undefined) {
|
|
57
|
-
|
|
58
|
-
const pos = name <= 0 ? 'first' : name <= 1 ? 'second' : name + 1 + 'th';
|
|
59
|
-
throwError(`Missing required parameter at the ${pos} position`, recovered);
|
|
72
|
+
throwError(`${describeParam(name)} is required`, recovered);
|
|
60
73
|
}
|
|
61
74
|
}
|
|
62
75
|
|
|
76
|
+
/** 标记并转换参数为数字 */
|
|
77
|
+
export function expectNumber(name: ParamIndex, value: VmAny): number {
|
|
78
|
+
required(name, value, Number.NaN);
|
|
79
|
+
const v = toNumber(value, null);
|
|
80
|
+
if (v == null) {
|
|
81
|
+
throwUnconvertedTypeError(name, 'number', value, Number.NaN);
|
|
82
|
+
}
|
|
83
|
+
return v;
|
|
84
|
+
}
|
|
85
|
+
/** 标记并转换参数为数字 */
|
|
86
|
+
export function expectNumberRange(name: ParamIndex, value: VmAny, min: number, max: number): number {
|
|
87
|
+
const v = expectNumber(name, value);
|
|
88
|
+
if (!isFinite(v)) {
|
|
89
|
+
throwError(`${describeParam(name)} is not a finite number: ${display(value)}`, Number.NaN);
|
|
90
|
+
}
|
|
91
|
+
if (v < min) {
|
|
92
|
+
throwError(`${describeParam(name)} is less than minimum value ${min}: ${display(value)}`, min);
|
|
93
|
+
}
|
|
94
|
+
if (v > max) {
|
|
95
|
+
throwError(`${describeParam(name)} is greater than maximum value ${max}: ${display(value)}`, max);
|
|
96
|
+
}
|
|
97
|
+
return v;
|
|
98
|
+
}
|
|
99
|
+
/** 标记并转换参数为整数 */
|
|
100
|
+
export function expectIntegerRange(name: ParamIndex, value: VmAny, min: number, max: number): number {
|
|
101
|
+
const i = expectInteger(name, value);
|
|
102
|
+
if (i < min) {
|
|
103
|
+
throwError(`${describeParam(name)} is less than minimum value ${min}: ${display(value)}`, min);
|
|
104
|
+
}
|
|
105
|
+
if (i > max) {
|
|
106
|
+
throwError(`${describeParam(name)} is greater than maximum value ${max}: ${display(value)}`, max);
|
|
107
|
+
}
|
|
108
|
+
return i;
|
|
109
|
+
}
|
|
110
|
+
/** 标记并转换参数为整数 */
|
|
111
|
+
export function expectInteger(name: ParamIndex, value: VmAny): number {
|
|
112
|
+
required(name, value, 0);
|
|
113
|
+
const v = toNumber(value, null);
|
|
114
|
+
if (v == null) {
|
|
115
|
+
throwUnconvertedTypeError(name, 'integer', value, 0);
|
|
116
|
+
}
|
|
117
|
+
const i = Math.trunc(v);
|
|
118
|
+
if (!isSafeInteger(i)) {
|
|
119
|
+
throwUnconvertedTypeError(name, 'integer', value, 0);
|
|
120
|
+
}
|
|
121
|
+
return i;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/** 标记并转换参数为布尔值 */
|
|
125
|
+
export function expectBoolean(name: ParamIndex, value: VmAny): boolean {
|
|
126
|
+
required(name, value, false);
|
|
127
|
+
const v = toBoolean(value, null);
|
|
128
|
+
if (v == null) {
|
|
129
|
+
throwUnconvertedTypeError(name, 'boolean', value, false);
|
|
130
|
+
}
|
|
131
|
+
return v;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/** 标记并转换参数为字符串 */
|
|
135
|
+
export function expectString(name: ParamIndex, value: VmAny): string {
|
|
136
|
+
required(name, value, '');
|
|
137
|
+
const v = toString(value, null);
|
|
138
|
+
if (v == null) {
|
|
139
|
+
throwUnconvertedTypeError(name, 'string', value, '');
|
|
140
|
+
}
|
|
141
|
+
return v;
|
|
142
|
+
}
|
|
143
|
+
|
|
63
144
|
/** 标记参数为数组 */
|
|
64
145
|
export function expectArray(
|
|
65
|
-
name:
|
|
146
|
+
name: ParamIndex,
|
|
66
147
|
value: VmAny,
|
|
67
148
|
recovered: VmAny | (() => VmAny),
|
|
68
149
|
): asserts value is VmArray {
|
|
@@ -74,7 +155,7 @@ export function expectArray(
|
|
|
74
155
|
|
|
75
156
|
/** 标记参数为记录 */
|
|
76
157
|
export function expectRecord(
|
|
77
|
-
name:
|
|
158
|
+
name: ParamIndex,
|
|
78
159
|
value: VmAny,
|
|
79
160
|
recovered: VmAny | (() => VmAny),
|
|
80
161
|
): asserts value is VmRecord {
|
|
@@ -86,7 +167,7 @@ export function expectRecord(
|
|
|
86
167
|
|
|
87
168
|
/** 标记参数为数组或记录 */
|
|
88
169
|
export function expectArrayOrRecord(
|
|
89
|
-
name:
|
|
170
|
+
name: ParamIndex,
|
|
90
171
|
value: VmAny,
|
|
91
172
|
recovered: VmAny | (() => VmAny),
|
|
92
173
|
): asserts value is VmArray | VmRecord {
|
|
@@ -98,7 +179,7 @@ export function expectArrayOrRecord(
|
|
|
98
179
|
|
|
99
180
|
/** 标记参数为复合类型 */
|
|
100
181
|
export function expectCompound(
|
|
101
|
-
name:
|
|
182
|
+
name: ParamIndex,
|
|
102
183
|
value: VmAny,
|
|
103
184
|
recovered: VmAny | (() => VmAny),
|
|
104
185
|
): asserts value is VmArray | VmRecord | VmModule | VmExtern {
|
|
@@ -110,7 +191,7 @@ export function expectCompound(
|
|
|
110
191
|
|
|
111
192
|
/** 标记参数为常量 */
|
|
112
193
|
export function expectConst(
|
|
113
|
-
name:
|
|
194
|
+
name: ParamIndex,
|
|
114
195
|
value: VmAny,
|
|
115
196
|
recovered: VmAny | (() => VmAny),
|
|
116
197
|
): asserts value is VmConst {
|
|
@@ -122,7 +203,7 @@ export function expectConst(
|
|
|
122
203
|
|
|
123
204
|
/** 标记为可调用 */
|
|
124
205
|
export function expectCallable(
|
|
125
|
-
name:
|
|
206
|
+
name: ParamIndex,
|
|
126
207
|
value: VmAny,
|
|
127
208
|
recovered: VmAny | (() => VmAny),
|
|
128
209
|
): asserts value is VmFunction | VmExtern {
|
|
@@ -135,20 +216,27 @@ export function expectCallable(
|
|
|
135
216
|
/** Get numbers from the arguments. */
|
|
136
217
|
export function getNumbers(args: readonly VmAny[]): number[] {
|
|
137
218
|
if (args.length === 0) return [];
|
|
138
|
-
|
|
219
|
+
let useFirst = false;
|
|
220
|
+
if (args.length === 1 && isVmArray(args[0])) {
|
|
221
|
+
args = args[0];
|
|
222
|
+
useFirst = true;
|
|
223
|
+
}
|
|
139
224
|
const numbers: number[] = [];
|
|
140
|
-
for (
|
|
141
|
-
|
|
142
|
-
numbers.push($ToNumber(arg));
|
|
225
|
+
for (let len = args.length, i = 0; i < len; i++) {
|
|
226
|
+
numbers.push(expectNumber(useFirst ? null : i, args[i]));
|
|
143
227
|
}
|
|
144
228
|
return numbers;
|
|
145
229
|
}
|
|
146
230
|
|
|
147
231
|
/** 将值转为数组长度 */
|
|
148
232
|
export function arrayLen(len: number | null | undefined): number {
|
|
149
|
-
if (len == null || isNaN(len) || len <=
|
|
233
|
+
if (len == null || isNaN(len) || len <= -1) {
|
|
234
|
+
throwError('Array length must be a non-negative integer', null);
|
|
235
|
+
}
|
|
150
236
|
len = Math.trunc(len);
|
|
151
|
-
if (len > VM_ARRAY_MAX_LENGTH)
|
|
237
|
+
if (len > VM_ARRAY_MAX_LENGTH) {
|
|
238
|
+
throwError(`Array length exceeds maximum limit of ${VM_ARRAY_MAX_LENGTH}`, null);
|
|
239
|
+
}
|
|
152
240
|
return len;
|
|
153
241
|
}
|
|
154
242
|
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import * as global from './global/index.js';
|
|
2
|
+
import * as mods from './mod/index.js';
|
|
3
|
+
import { VmSharedContext } from '../types/context.js';
|
|
4
|
+
import { create, entries } from '../../helpers/utils.js';
|
|
5
|
+
import { createModule, wrapEntry, type RawValue } from './loader.js';
|
|
6
|
+
|
|
7
|
+
for (const [name, value] of entries(global)) {
|
|
8
|
+
VmSharedContext[name] = wrapEntry(name, value as RawValue, 'global');
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
for (const [name, value] of entries(mods)) {
|
|
12
|
+
const mod = createModule(name, value as Record<string, RawValue>);
|
|
13
|
+
VmSharedContext[name] = wrapEntry(name, mod, 'global');
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export const lib = Object.freeze(Object.assign(create(null), global, mods));
|
|
@@ -1,20 +1,14 @@
|
|
|
1
1
|
import { VmFunction, VmModule, type VmConst, type VmFunctionLike, type VmImmutable } from '../types/index.js';
|
|
2
2
|
import { create, defineProperty, entries } from '../../helpers/utils.js';
|
|
3
|
-
import { VmSharedContext } from '../types/context.js';
|
|
4
3
|
|
|
5
|
-
import type { VmLib, VmLibOption } from './
|
|
6
|
-
import * as global from './global/index.js';
|
|
7
|
-
|
|
8
|
-
for (const [name, value] of entries(global)) {
|
|
9
|
-
VmSharedContext[name] = wrapEntry(name, value as RawValue, 'global');
|
|
10
|
-
}
|
|
4
|
+
import type { VmLib, VmLibOption } from './helpers.js';
|
|
11
5
|
|
|
12
6
|
/** 原始值 */
|
|
13
|
-
type RawValue = VmLib | VmConst | VmModule;
|
|
7
|
+
export type RawValue = VmLib | VmConst | VmModule;
|
|
14
8
|
/** 包装值 */
|
|
15
9
|
type ToWrappedValue<V extends RawValue> = V extends VmFunctionLike ? VmFunction<V> : V;
|
|
16
10
|
/** 包装值 */
|
|
17
|
-
function wrapEntry<const T extends RawValue>(name: string, value: T, module: string): ToWrappedValue<T> {
|
|
11
|
+
export function wrapEntry<const T extends RawValue>(name: string, value: T, module: string): ToWrappedValue<T> {
|
|
18
12
|
if (typeof value == 'function') {
|
|
19
13
|
if (value.name !== name) {
|
|
20
14
|
// 如果函数名和导出名不一致,则重命名
|
|
@@ -47,5 +41,3 @@ export function createModule<const T extends Record<string, RawValue>>(name: str
|
|
|
47
41
|
}
|
|
48
42
|
return new VmModule(name, mod) as ToWrappedModule<T>;
|
|
49
43
|
}
|
|
50
|
-
|
|
51
|
-
export const lib = global;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * as matrix from './matrix.js';
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
1
|
+
import { toNumber } from '../../../helpers/convert.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[] = [];
|