@mirascript/mirascript 0.1.62-alpha.7 → 0.1.62-alpha.8
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-6CAGNGY6.js +3980 -0
- package/dist/chunk-6CAGNGY6.js.map +6 -0
- package/dist/chunk-VRGQ23AK.js +1815 -0
- package/dist/chunk-VRGQ23AK.js.map +6 -0
- package/dist/compiler/compile-fast.d.ts +7 -0
- package/dist/compiler/compile-fast.d.ts.map +1 -0
- package/dist/compiler/create-script.d.ts +20 -0
- package/dist/compiler/create-script.d.ts.map +1 -0
- package/dist/compiler/diagnostic.d.ts +71 -0
- package/dist/compiler/diagnostic.d.ts.map +1 -0
- package/dist/compiler/emit/constants.d.ts +5 -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/index.d.ts +62 -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/emit-script.d.ts +10 -0
- package/dist/compiler/emit-script.d.ts.map +1 -0
- package/dist/compiler/generate-bytecode.d.ts +12 -0
- package/dist/compiler/generate-bytecode.d.ts.map +1 -0
- package/dist/compiler/index.d.ts +14 -0
- package/dist/compiler/index.d.ts.map +1 -0
- package/dist/compiler/load-module.d.ts +2 -0
- package/dist/compiler/load-module.d.ts.map +1 -0
- package/dist/compiler/types.d.ts +16 -0
- package/dist/compiler/types.d.ts.map +1 -0
- package/dist/compiler/worker-manager.d.ts +11 -0
- package/dist/compiler/worker-manager.d.ts.map +1 -0
- package/dist/compiler/worker.d.ts +10 -0
- package/dist/compiler/worker.d.ts.map +1 -0
- package/dist/compiler/worker.js +31 -0
- package/dist/compiler/worker.js.map +6 -0
- package/dist/helpers/analyze.d.ts +8 -0
- package/dist/helpers/analyze.d.ts.map +1 -0
- package/dist/helpers/constants.d.ts +20 -0
- package/dist/helpers/constants.d.ts.map +1 -0
- 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/helpers/error.d.ts +11 -0
- package/dist/helpers/error.d.ts.map +1 -0
- package/dist/helpers/serialize.d.ts +63 -0
- package/dist/helpers/serialize.d.ts.map +1 -0
- package/dist/helpers/types.d.ts +54 -0
- package/dist/helpers/types.d.ts.map +1 -0
- package/dist/helpers/utils.d.ts +37 -0
- package/dist/helpers/utils.d.ts.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +243 -0
- package/dist/index.js.map +6 -0
- package/dist/subtle.d.ts +14 -0
- package/dist/subtle.d.ts.map +1 -0
- package/dist/subtle.js +122 -0
- package/dist/subtle.js.map +6 -0
- package/dist/vm/checkpoint.d.ts +9 -0
- package/dist/vm/checkpoint.d.ts.map +1 -0
- package/dist/vm/index.d.ts +5 -0
- package/dist/vm/index.d.ts.map +1 -0
- package/dist/vm/lib/global/bit.d.ts +8 -0
- package/dist/vm/lib/global/bit.d.ts.map +1 -0
- package/dist/vm/lib/global/debug.d.ts +38 -0
- package/dist/vm/lib/global/debug.d.ts.map +1 -0
- package/dist/vm/lib/global/index.d.ts +9 -0
- package/dist/vm/lib/global/index.d.ts.map +1 -0
- package/dist/vm/lib/global/json.d.ts +3 -0
- package/dist/vm/lib/global/json.d.ts.map +1 -0
- package/dist/vm/lib/global/math/arr.d.ts +7 -0
- package/dist/vm/lib/global/math/arr.d.ts.map +1 -0
- package/dist/vm/lib/global/math/const.d.ts +31 -0
- package/dist/vm/lib/global/math/const.d.ts.map +1 -0
- package/dist/vm/lib/global/math/gamma.d.ts +3 -0
- package/dist/vm/lib/global/math/gamma.d.ts.map +1 -0
- package/dist/vm/lib/global/math/index.d.ts +9 -0
- package/dist/vm/lib/global/math/index.d.ts.map +1 -0
- package/dist/vm/lib/global/math/round.d.ts +6 -0
- package/dist/vm/lib/global/math/round.d.ts.map +1 -0
- package/dist/vm/lib/global/math/unary.d.ts +24 -0
- package/dist/vm/lib/global/math/unary.d.ts.map +1 -0
- package/dist/vm/lib/global/sequence/all-any.d.ts +3 -0
- package/dist/vm/lib/global/sequence/all-any.d.ts.map +1 -0
- package/dist/vm/lib/global/sequence/entries.d.ts +11 -0
- package/dist/vm/lib/global/sequence/entries.d.ts.map +1 -0
- package/dist/vm/lib/global/sequence/find.d.ts +9 -0
- package/dist/vm/lib/global/sequence/find.d.ts.map +1 -0
- package/dist/vm/lib/global/sequence/flatten.d.ts +2 -0
- package/dist/vm/lib/global/sequence/flatten.d.ts.map +1 -0
- package/dist/vm/lib/global/sequence/index.d.ts +14 -0
- package/dist/vm/lib/global/sequence/index.d.ts.map +1 -0
- package/dist/vm/lib/global/sequence/len.d.ts +2 -0
- package/dist/vm/lib/global/sequence/len.d.ts.map +1 -0
- package/dist/vm/lib/global/sequence/map-filter.d.ts +8 -0
- package/dist/vm/lib/global/sequence/map-filter.d.ts.map +1 -0
- package/dist/vm/lib/global/sequence/new.d.ts +4 -0
- package/dist/vm/lib/global/sequence/new.d.ts.map +1 -0
- package/dist/vm/lib/global/sequence/repeat.d.ts +3 -0
- package/dist/vm/lib/global/sequence/repeat.d.ts.map +1 -0
- package/dist/vm/lib/global/sequence/reverse.d.ts +2 -0
- package/dist/vm/lib/global/sequence/reverse.d.ts.map +1 -0
- package/dist/vm/lib/global/sequence/sort.d.ts +4 -0
- package/dist/vm/lib/global/sequence/sort.d.ts.map +1 -0
- package/dist/vm/lib/global/sequence/unique.d.ts +4 -0
- package/dist/vm/lib/global/sequence/unique.d.ts.map +1 -0
- package/dist/vm/lib/global/sequence/with.d.ts +4 -0
- package/dist/vm/lib/global/sequence/with.d.ts.map +1 -0
- package/dist/vm/lib/global/sequence/zip.d.ts +3 -0
- package/dist/vm/lib/global/sequence/zip.d.ts.map +1 -0
- package/dist/vm/lib/global/string/case.d.ts +3 -0
- package/dist/vm/lib/global/string/case.d.ts.map +1 -0
- package/dist/vm/lib/global/string/index.d.ts +8 -0
- package/dist/vm/lib/global/string/index.d.ts.map +1 -0
- package/dist/vm/lib/global/string/search.d.ts +4 -0
- package/dist/vm/lib/global/string/search.d.ts.map +1 -0
- package/dist/vm/lib/global/string/trim.d.ts +4 -0
- package/dist/vm/lib/global/string/trim.d.ts.map +1 -0
- package/dist/vm/lib/global/time.d.ts +4 -0
- package/dist/vm/lib/global/time.d.ts.map +1 -0
- package/dist/vm/lib/global/to-primitive.d.ts +4 -0
- package/dist/vm/lib/global/to-primitive.d.ts.map +1 -0
- package/dist/vm/lib/helpers.d.ts +57 -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 +23 -0
- 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/call.d.ts +9 -0
- package/dist/vm/operations/call.d.ts.map +1 -0
- package/dist/vm/operations/common.d.ts +4 -0
- package/dist/vm/operations/common.d.ts.map +1 -0
- package/dist/vm/operations/compound.d.ts +22 -0
- package/dist/vm/operations/compound.d.ts.map +1 -0
- package/dist/vm/operations/convert.d.ts +10 -0
- package/dist/vm/operations/convert.d.ts.map +1 -0
- package/dist/vm/operations/cp.d.ts +2 -0
- package/dist/vm/operations/cp.d.ts.map +1 -0
- package/dist/vm/operations/helpers.d.ts +24 -0
- package/dist/vm/operations/helpers.d.ts.map +1 -0
- package/dist/vm/operations/index.d.ts +10 -0
- package/dist/vm/operations/index.d.ts.map +1 -0
- package/dist/vm/operations/operator.d.ts +46 -0
- package/dist/vm/operations/operator.d.ts.map +1 -0
- package/dist/vm/operations/slice.d.ts +6 -0
- package/dist/vm/operations/slice.d.ts.map +1 -0
- package/dist/vm/operations/type-check.d.ts +16 -0
- package/dist/vm/operations/type-check.d.ts.map +1 -0
- package/dist/vm/operations/utils.d.ts +11 -0
- package/dist/vm/operations/utils.d.ts.map +1 -0
- package/dist/vm/types/boundary.d.ts +13 -0
- package/dist/vm/types/boundary.d.ts.map +1 -0
- package/dist/vm/types/context.d.ts +33 -0
- package/dist/vm/types/context.d.ts.map +1 -0
- package/dist/vm/types/extern.d.ts +44 -0
- package/dist/vm/types/extern.d.ts.map +1 -0
- package/dist/vm/types/function.d.ts +50 -0
- package/dist/vm/types/function.d.ts.map +1 -0
- package/dist/vm/types/index.d.ts +58 -0
- package/dist/vm/types/index.d.ts.map +1 -0
- package/dist/vm/types/module.d.ts +25 -0
- package/dist/vm/types/module.d.ts.map +1 -0
- package/dist/vm/types/wrapper.d.ts +25 -0
- package/dist/vm/types/wrapper.d.ts.map +1 -0
- package/package.json +3 -3
|
@@ -0,0 +1,3980 @@
|
|
|
1
|
+
import {
|
|
2
|
+
DiagnosticCode,
|
|
3
|
+
NegativeInfinity,
|
|
4
|
+
NotNumber,
|
|
5
|
+
PositiveInfinity,
|
|
6
|
+
VM_ARRAY_MAX_LENGTH,
|
|
7
|
+
VM_FUNCTION_ANONYMOUS_NAME,
|
|
8
|
+
VM_SCRIPT_NAME,
|
|
9
|
+
VmError,
|
|
10
|
+
__export,
|
|
11
|
+
apply,
|
|
12
|
+
create,
|
|
13
|
+
defineProperty,
|
|
14
|
+
display,
|
|
15
|
+
emit,
|
|
16
|
+
entries,
|
|
17
|
+
formatDiagnostics,
|
|
18
|
+
fromEntries,
|
|
19
|
+
getOwnPropertyNames,
|
|
20
|
+
getPrototypeOf,
|
|
21
|
+
hasOwn,
|
|
22
|
+
hasOwnEnumerable,
|
|
23
|
+
innerToString,
|
|
24
|
+
isArray,
|
|
25
|
+
isFinite,
|
|
26
|
+
isInteger,
|
|
27
|
+
isNaN,
|
|
28
|
+
isSafeInteger,
|
|
29
|
+
isVmArray,
|
|
30
|
+
isVmCallable,
|
|
31
|
+
isVmConst,
|
|
32
|
+
isVmExtern,
|
|
33
|
+
isVmFunction,
|
|
34
|
+
isVmModule,
|
|
35
|
+
isVmPrimitive,
|
|
36
|
+
isVmRecord,
|
|
37
|
+
isVmWrapper,
|
|
38
|
+
kVmContext,
|
|
39
|
+
kVmExtern,
|
|
40
|
+
kVmFunction,
|
|
41
|
+
kVmFunctionProxy,
|
|
42
|
+
kVmModule,
|
|
43
|
+
kVmScript,
|
|
44
|
+
kVmWrapper,
|
|
45
|
+
keys,
|
|
46
|
+
parseDiagnostics,
|
|
47
|
+
toString,
|
|
48
|
+
values
|
|
49
|
+
} from "./chunk-VRGQ23AK.js";
|
|
50
|
+
|
|
51
|
+
// src/compiler/load-module.ts
|
|
52
|
+
import { loadModule } from "@mirascript/bindings";
|
|
53
|
+
await loadModule();
|
|
54
|
+
|
|
55
|
+
// src/helpers/convert/index.ts
|
|
56
|
+
var convert_exports = {};
|
|
57
|
+
__export(convert_exports, {
|
|
58
|
+
toBoolean: () => toBoolean,
|
|
59
|
+
toFormat: () => toFormat,
|
|
60
|
+
toNumber: () => toNumber,
|
|
61
|
+
toString: () => toString
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
// src/helpers/convert/to-number.ts
|
|
65
|
+
function parseNumericLiteral(value) {
|
|
66
|
+
if (value === "") return null;
|
|
67
|
+
const ch0 = value.charAt(0);
|
|
68
|
+
if (ch0 < "0" || ch0 > "9") {
|
|
69
|
+
return null;
|
|
70
|
+
}
|
|
71
|
+
if (/^0[bB][01]+$/.test(value)) {
|
|
72
|
+
const num2 = Number.parseInt(value.slice(2), 2);
|
|
73
|
+
return isNaN(num2) ? null : num2;
|
|
74
|
+
}
|
|
75
|
+
if (/^0[oO][0-7]+$/.test(value)) {
|
|
76
|
+
const num2 = Number.parseInt(value.slice(2), 8);
|
|
77
|
+
return isNaN(num2) ? null : num2;
|
|
78
|
+
}
|
|
79
|
+
if (/^0[xX][0-9a-fA-F]+$/.test(value)) {
|
|
80
|
+
const num2 = Number.parseInt(value.slice(2), 16);
|
|
81
|
+
return isNaN(num2) ? null : num2;
|
|
82
|
+
}
|
|
83
|
+
if (/^[0-9]+(\.[0-9]+)?([eE][+-]?[0-9]+)?$/.test(value)) {
|
|
84
|
+
const num2 = Number.parseFloat(value);
|
|
85
|
+
return isNaN(num2) ? null : num2;
|
|
86
|
+
}
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
function stringToNumber(value) {
|
|
90
|
+
value = value.trim();
|
|
91
|
+
if (value === "") return null;
|
|
92
|
+
if (value === "inf" || value === "+inf" || value === "Infinity" || value === "+Infinity") {
|
|
93
|
+
return PositiveInfinity;
|
|
94
|
+
}
|
|
95
|
+
if (value === "-inf" || value === "-Infinity") {
|
|
96
|
+
return NegativeInfinity;
|
|
97
|
+
}
|
|
98
|
+
if (value === "nan" || value === "NaN") {
|
|
99
|
+
return NotNumber;
|
|
100
|
+
}
|
|
101
|
+
if (value.startsWith("-")) {
|
|
102
|
+
const num2 = parseNumericLiteral(value.slice(1));
|
|
103
|
+
if (num2 !== null) return -num2;
|
|
104
|
+
return null;
|
|
105
|
+
} else if (value.startsWith("+")) {
|
|
106
|
+
return parseNumericLiteral(value.slice(1));
|
|
107
|
+
} else {
|
|
108
|
+
return parseNumericLiteral(value);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
function toNumber(value, fallback) {
|
|
112
|
+
if (typeof value === "number") return value;
|
|
113
|
+
if (typeof value == "boolean") return value ? 1 : 0;
|
|
114
|
+
if (typeof value == "string") {
|
|
115
|
+
const num2 = stringToNumber(value);
|
|
116
|
+
if (num2 !== null) return num2;
|
|
117
|
+
}
|
|
118
|
+
if (fallback === void 0) {
|
|
119
|
+
throw new VmError(`Failed to convert value to number: ${display(value)}`, NotNumber);
|
|
120
|
+
}
|
|
121
|
+
return fallback;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// src/helpers/convert/to-format.ts
|
|
125
|
+
function formatNumber(finite) {
|
|
126
|
+
if (finite === 0) return "0";
|
|
127
|
+
const s2 = finite.toString();
|
|
128
|
+
let ps;
|
|
129
|
+
const abs3 = Math.abs(finite);
|
|
130
|
+
if (abs3 >= 1e3 || abs3 < 1e-3) {
|
|
131
|
+
const ps1 = finite.toExponential();
|
|
132
|
+
const ps2 = finite.toExponential(5);
|
|
133
|
+
ps = ps1.length < ps2.length ? ps1 : ps2;
|
|
134
|
+
} else {
|
|
135
|
+
ps = finite.toPrecision(6);
|
|
136
|
+
}
|
|
137
|
+
return ps.length < s2.length ? ps : s2;
|
|
138
|
+
}
|
|
139
|
+
function toFormat(value, format2) {
|
|
140
|
+
const f = format2 == null ? "" : format2.trim();
|
|
141
|
+
if (typeof value == "number") {
|
|
142
|
+
if (!isFinite(value)) {
|
|
143
|
+
return toString(value, void 0);
|
|
144
|
+
}
|
|
145
|
+
if (/^\.\d+$/.test(f)) {
|
|
146
|
+
let digits = Math.trunc(Number(f.slice(1)));
|
|
147
|
+
if (!(digits <= 100)) digits = 100;
|
|
148
|
+
return value.toFixed(digits);
|
|
149
|
+
} else {
|
|
150
|
+
return formatNumber(value);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
return toString(value, void 0);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// src/helpers/convert/to-boolean.ts
|
|
157
|
+
function toBoolean(value, fallback) {
|
|
158
|
+
if (typeof value === "boolean") return value;
|
|
159
|
+
if (fallback === void 0) {
|
|
160
|
+
throw new VmError(`Failed to convert value to boolean: ${display(value)}`, false);
|
|
161
|
+
}
|
|
162
|
+
return fallback;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// src/vm/types/wrapper.ts
|
|
166
|
+
var VmWrapper = class {
|
|
167
|
+
constructor(value) {
|
|
168
|
+
this.value = value;
|
|
169
|
+
}
|
|
170
|
+
/** 描述键对应的值 */
|
|
171
|
+
describe(key) {
|
|
172
|
+
return void 0;
|
|
173
|
+
}
|
|
174
|
+
/** 转为字符串 */
|
|
175
|
+
toString(useBraces) {
|
|
176
|
+
const { type, tag } = this;
|
|
177
|
+
if (!tag) return `<${type}>`;
|
|
178
|
+
return `<${type} ${tag}>`;
|
|
179
|
+
}
|
|
180
|
+
};
|
|
181
|
+
Object.defineProperty(VmWrapper.prototype, kVmWrapper, { value: true });
|
|
182
|
+
|
|
183
|
+
// src/vm/operations/common.ts
|
|
184
|
+
function $AssertInit(value) {
|
|
185
|
+
if (value === void 0) throw new VmError(`Uninitialized value`, null);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// src/vm/operations/call.ts
|
|
189
|
+
function $Call(func, args) {
|
|
190
|
+
for (const a of args) {
|
|
191
|
+
$AssertInit(a);
|
|
192
|
+
}
|
|
193
|
+
if (isVmExtern(func)) {
|
|
194
|
+
return func.call(args) ?? null;
|
|
195
|
+
}
|
|
196
|
+
if (isVmFunction(func)) {
|
|
197
|
+
return func(...args) ?? null;
|
|
198
|
+
}
|
|
199
|
+
throw new VmError(`Value is not callable: ${display(func)}`, null);
|
|
200
|
+
}
|
|
201
|
+
function $VArgs(varags) {
|
|
202
|
+
for (let i = 0, l = varags.length; i < l; i++) {
|
|
203
|
+
const el = varags[i];
|
|
204
|
+
if (!isVmConst(el)) {
|
|
205
|
+
varags[i] = null;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
return varags;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// src/vm/types/boundary.ts
|
|
212
|
+
function toVmFunctionProxy(fn) {
|
|
213
|
+
const cached = fn[kVmFunctionProxy];
|
|
214
|
+
if (cached != null) return cached;
|
|
215
|
+
const proxy = (...args) => {
|
|
216
|
+
const ret = $Call(
|
|
217
|
+
fn,
|
|
218
|
+
// 作为函数参数传入的值一定丢失了它的 this
|
|
219
|
+
args.map((v) => wrapToVmValue(v, null, null))
|
|
220
|
+
);
|
|
221
|
+
return unwrapFromVmValue(ret, true);
|
|
222
|
+
};
|
|
223
|
+
defineProperty(fn, kVmFunctionProxy, { value: proxy });
|
|
224
|
+
defineProperty(proxy, kVmFunctionProxy, { value: fn });
|
|
225
|
+
defineProperty(proxy, "name", {
|
|
226
|
+
value: fn.name,
|
|
227
|
+
configurable: true
|
|
228
|
+
});
|
|
229
|
+
return proxy;
|
|
230
|
+
}
|
|
231
|
+
function fromVmFunctionProxy(fn) {
|
|
232
|
+
if (isVmFunction(fn)) return fn;
|
|
233
|
+
const original = fn[kVmFunctionProxy];
|
|
234
|
+
if (original && isVmFunction(original)) return original;
|
|
235
|
+
return null;
|
|
236
|
+
}
|
|
237
|
+
function wrapToVmConst(value, assumeVmValue = null) {
|
|
238
|
+
if (value == null) return null;
|
|
239
|
+
switch (typeof value) {
|
|
240
|
+
case "function":
|
|
241
|
+
return null;
|
|
242
|
+
case "object": {
|
|
243
|
+
if (isVmWrapper(value)) return null;
|
|
244
|
+
if (value instanceof Date) return value.valueOf();
|
|
245
|
+
if (assumeVmValue?.(value)) return value;
|
|
246
|
+
return null;
|
|
247
|
+
}
|
|
248
|
+
case "string":
|
|
249
|
+
case "number":
|
|
250
|
+
case "boolean":
|
|
251
|
+
return value;
|
|
252
|
+
case "bigint":
|
|
253
|
+
return Number(value);
|
|
254
|
+
case "symbol":
|
|
255
|
+
case "undefined":
|
|
256
|
+
default:
|
|
257
|
+
return null;
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
function wrapToVmValue(value, thisArg = null, assumeVmValue = null) {
|
|
261
|
+
if (value == null) return null;
|
|
262
|
+
if (typeof value == "function") {
|
|
263
|
+
const unwrapped = fromVmFunctionProxy(value);
|
|
264
|
+
if (unwrapped != null) return unwrapped;
|
|
265
|
+
return new VmExtern(value, thisArg);
|
|
266
|
+
}
|
|
267
|
+
const constValue = wrapToVmConst(value, assumeVmValue);
|
|
268
|
+
if (constValue != null) return constValue;
|
|
269
|
+
if (typeof value == "object") {
|
|
270
|
+
if (isVmWrapper(value)) return value;
|
|
271
|
+
return new VmExtern(value);
|
|
272
|
+
}
|
|
273
|
+
return null;
|
|
274
|
+
}
|
|
275
|
+
function bindThis(fn, thisArg) {
|
|
276
|
+
if (thisArg == null) return fn;
|
|
277
|
+
return new Proxy(fn, {
|
|
278
|
+
apply(target, _thisArg, args) {
|
|
279
|
+
return apply(target, thisArg, args);
|
|
280
|
+
}
|
|
281
|
+
});
|
|
282
|
+
}
|
|
283
|
+
function unwrapFromVmValue(value, bindThisArg = true) {
|
|
284
|
+
if (isVmFunction(value)) {
|
|
285
|
+
return toVmFunctionProxy(value);
|
|
286
|
+
}
|
|
287
|
+
if (value == null || typeof value != "object") return value;
|
|
288
|
+
if (!isVmExtern(value)) return value;
|
|
289
|
+
if (value.thisArg == null || typeof value.value != "function") {
|
|
290
|
+
return value.value;
|
|
291
|
+
}
|
|
292
|
+
const f = value;
|
|
293
|
+
return bindThisArg ? bindThis(f.value, f.thisArg) : f.value;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
// src/vm/types/extern.ts
|
|
297
|
+
var ObjectPrototype = Object.prototype;
|
|
298
|
+
var ObjectToString = ObjectPrototype.toString;
|
|
299
|
+
var FunctionToString = Function.prototype.toString;
|
|
300
|
+
var ArrayToString = Array.prototype.toString;
|
|
301
|
+
var ArrayMap = Array.prototype.map;
|
|
302
|
+
var TypedArrayToString = Uint8Array.prototype.toString;
|
|
303
|
+
function classNameOf(kls) {
|
|
304
|
+
const { displayName } = kls;
|
|
305
|
+
if (typeof displayName === "string" && displayName.trim()) {
|
|
306
|
+
return displayName.trim();
|
|
307
|
+
}
|
|
308
|
+
const { name } = kls;
|
|
309
|
+
if (typeof name == "string" && name.length > 2) {
|
|
310
|
+
return name;
|
|
311
|
+
}
|
|
312
|
+
return null;
|
|
313
|
+
}
|
|
314
|
+
var VmExtern = class extends VmWrapper {
|
|
315
|
+
constructor(value, thisArg = null) {
|
|
316
|
+
super(value);
|
|
317
|
+
this.thisArg = thisArg;
|
|
318
|
+
}
|
|
319
|
+
/**
|
|
320
|
+
* Check if the object has a property
|
|
321
|
+
* This method will be used in {@link get}, {@link set}, {@link has}, and {@link keys} methods
|
|
322
|
+
*/
|
|
323
|
+
access(key, read) {
|
|
324
|
+
if (key.startsWith("_")) return false;
|
|
325
|
+
if (typeof this.value == "function" && (key === "prototype" || key === "arguments" || key === "caller"))
|
|
326
|
+
return false;
|
|
327
|
+
if (hasOwn(this.value, key)) return true;
|
|
328
|
+
if (!read) return true;
|
|
329
|
+
if (!(key in this.value)) return false;
|
|
330
|
+
if (key === "constructor") return false;
|
|
331
|
+
const prop = this.value[key];
|
|
332
|
+
if (key in Function.prototype && prop === Function.prototype[key]) return false;
|
|
333
|
+
if (key in Array.prototype && prop === Array.prototype[key]) return false;
|
|
334
|
+
if (key in Object.prototype && prop === Object.prototype[key]) return false;
|
|
335
|
+
return true;
|
|
336
|
+
}
|
|
337
|
+
/** 决定是否对属性进行包装 */
|
|
338
|
+
assumeVmValue(value, key) {
|
|
339
|
+
return false;
|
|
340
|
+
}
|
|
341
|
+
/** @inheritdoc */
|
|
342
|
+
has(key) {
|
|
343
|
+
return this.access(key, true);
|
|
344
|
+
}
|
|
345
|
+
/** @inheritdoc */
|
|
346
|
+
get(key) {
|
|
347
|
+
if (!(key in this.value)) return void 0;
|
|
348
|
+
if (!this.access(key, true)) return void 0;
|
|
349
|
+
const prop = this.value[key];
|
|
350
|
+
return wrapToVmValue(prop, this.value, (v) => this.assumeVmValue(v, key));
|
|
351
|
+
}
|
|
352
|
+
/** Set a property on the object */
|
|
353
|
+
set(key, value) {
|
|
354
|
+
if (!this.access(key, false)) return false;
|
|
355
|
+
const prop = unwrapFromVmValue(value, true);
|
|
356
|
+
this.value[key] = prop;
|
|
357
|
+
return true;
|
|
358
|
+
}
|
|
359
|
+
/** Call extern value */
|
|
360
|
+
call(args) {
|
|
361
|
+
const { value } = this;
|
|
362
|
+
if (typeof value != "function") {
|
|
363
|
+
throw VmError.from(`Not a callable extern`, null, null);
|
|
364
|
+
}
|
|
365
|
+
const caller = this.thisArg;
|
|
366
|
+
const unwrappedArgs = args.map((arg) => unwrapFromVmValue(arg, true));
|
|
367
|
+
let ret;
|
|
368
|
+
try {
|
|
369
|
+
ret = apply(value, caller, unwrappedArgs);
|
|
370
|
+
} catch (ex) {
|
|
371
|
+
throw VmError.from(`Callable extern`, ex, null);
|
|
372
|
+
}
|
|
373
|
+
return wrapToVmValue(ret, null, (obj) => this.assumeVmValue(obj, void 0));
|
|
374
|
+
}
|
|
375
|
+
/** @inheritdoc */
|
|
376
|
+
keys(includeNonEnumerable = false) {
|
|
377
|
+
if (!includeNonEnumerable) {
|
|
378
|
+
const keys4 = [];
|
|
379
|
+
for (const key in this.value) {
|
|
380
|
+
if (this.access(key, true)) keys4.push(key);
|
|
381
|
+
}
|
|
382
|
+
return keys4;
|
|
383
|
+
} else {
|
|
384
|
+
const keys4 = /* @__PURE__ */ new Set();
|
|
385
|
+
let e2 = this.value;
|
|
386
|
+
while (e2 != null && (typeof e2 == "object" || typeof e2 == "function")) {
|
|
387
|
+
for (const key of getOwnPropertyNames(e2)) {
|
|
388
|
+
keys4.add(key);
|
|
389
|
+
}
|
|
390
|
+
e2 = getPrototypeOf(e2);
|
|
391
|
+
}
|
|
392
|
+
return Array.from(keys4).filter((key) => this.access(key, true));
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
/** @inheritdoc */
|
|
396
|
+
same(other) {
|
|
397
|
+
if (!isVmExtern(other)) return false;
|
|
398
|
+
return this.value === other.value && this.thisArg === other.thisArg;
|
|
399
|
+
}
|
|
400
|
+
/**
|
|
401
|
+
* Should this extern be treated as array-like?
|
|
402
|
+
*
|
|
403
|
+
* By default, this method returns true if the wrapped value is an Array or a TypedArray.
|
|
404
|
+
*/
|
|
405
|
+
isArrayLike() {
|
|
406
|
+
return isArray(this.value) || ArrayBuffer.isView(this.value) && "length" in this.value;
|
|
407
|
+
}
|
|
408
|
+
/** @inheritdoc */
|
|
409
|
+
toString(useBraces) {
|
|
410
|
+
const { toString: toString2 } = this.value;
|
|
411
|
+
if (typeof toString2 != "function" || toString2 === ObjectToString || toString2 === FunctionToString) {
|
|
412
|
+
return super.toString(useBraces);
|
|
413
|
+
}
|
|
414
|
+
if ((toString2 === ArrayToString || toString2 === TypedArrayToString) && this.isArrayLike()) {
|
|
415
|
+
const mapped = ArrayMap.call(this.value, (item) => {
|
|
416
|
+
if (item === void 0) return "";
|
|
417
|
+
return innerToString(wrapToVmValue(item ?? null, null, null), true);
|
|
418
|
+
});
|
|
419
|
+
const str = mapped.join(", ");
|
|
420
|
+
if (useBraces) return `[${str}]`;
|
|
421
|
+
return str;
|
|
422
|
+
}
|
|
423
|
+
return String(this.value);
|
|
424
|
+
}
|
|
425
|
+
/** @inheritdoc */
|
|
426
|
+
get type() {
|
|
427
|
+
return "extern";
|
|
428
|
+
}
|
|
429
|
+
/** @inheritdoc */
|
|
430
|
+
get tag() {
|
|
431
|
+
const tag = ObjectToString.call(this.value).slice(8, -1);
|
|
432
|
+
if (this.isArrayLike()) {
|
|
433
|
+
return `${tag}(${this.value.length})`;
|
|
434
|
+
} else if (tag === "Object") {
|
|
435
|
+
const proto = getPrototypeOf(this.value);
|
|
436
|
+
if (proto === ObjectPrototype) {
|
|
437
|
+
return "Object";
|
|
438
|
+
}
|
|
439
|
+
if (proto == null) {
|
|
440
|
+
return "Object: null prototype";
|
|
441
|
+
}
|
|
442
|
+
if (typeof proto.constructor === "function") {
|
|
443
|
+
return classNameOf(proto.constructor) ?? "Object";
|
|
444
|
+
}
|
|
445
|
+
} else if (tag === "Function" && "prototype" in this.value && typeof this.value.prototype == "object") {
|
|
446
|
+
const className = classNameOf(this.value);
|
|
447
|
+
if (!className) return `class`;
|
|
448
|
+
return `class ${className}`;
|
|
449
|
+
} else if (tag === "Function") {
|
|
450
|
+
return `function`;
|
|
451
|
+
} else if (tag === "AsyncFunction") {
|
|
452
|
+
return `async function`;
|
|
453
|
+
} else if (tag === "GeneratorFunction") {
|
|
454
|
+
return `function*`;
|
|
455
|
+
} else if (tag === "AsyncGeneratorFunction") {
|
|
456
|
+
return `async function*`;
|
|
457
|
+
}
|
|
458
|
+
return tag;
|
|
459
|
+
}
|
|
460
|
+
};
|
|
461
|
+
Object.defineProperty(VmExtern.prototype, kVmExtern, { value: true });
|
|
462
|
+
|
|
463
|
+
// src/vm/checkpoint.ts
|
|
464
|
+
var { now } = Date;
|
|
465
|
+
var TIME_ORIGIN = now() - 1e3 * 3600 * 12;
|
|
466
|
+
var timestamp = () => now() - TIME_ORIGIN | 0;
|
|
467
|
+
var CP_DEFAULT_INTERVAL = 100;
|
|
468
|
+
var MAX_DEPTH = 128;
|
|
469
|
+
var CP_UNSET = -1;
|
|
470
|
+
var CP_DEFAULT_TIMEOUT = 100;
|
|
471
|
+
var cpTimeout = CP_DEFAULT_TIMEOUT | 0;
|
|
472
|
+
var cpInterval = CP_DEFAULT_INTERVAL | 0;
|
|
473
|
+
var cpDepth = 0;
|
|
474
|
+
var cp = CP_UNSET | 0;
|
|
475
|
+
var cpCounter = 0;
|
|
476
|
+
function Cp() {
|
|
477
|
+
if ((cpCounter = cpCounter + 1 | 0) % (cpInterval | 0) !== 0) {
|
|
478
|
+
return;
|
|
479
|
+
}
|
|
480
|
+
cpCounter = 0;
|
|
481
|
+
if ((cp | 0) === (CP_UNSET | 0)) {
|
|
482
|
+
cp = timestamp() | 0;
|
|
483
|
+
} else if ((timestamp() | 0) - (cp | 0) >= (cpTimeout | 0)) {
|
|
484
|
+
throw new RangeError("Execution timed out");
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
function CpEnter() {
|
|
488
|
+
cpDepth = (cpDepth | 0) + 1;
|
|
489
|
+
if ((cpDepth | 0) <= 1) {
|
|
490
|
+
cp = CP_UNSET | 0;
|
|
491
|
+
cpCounter = 0;
|
|
492
|
+
cpDepth = 1;
|
|
493
|
+
} else if ((cpDepth | 0) > MAX_DEPTH) {
|
|
494
|
+
throw new RangeError("Maximum call depth exceeded");
|
|
495
|
+
} else {
|
|
496
|
+
Cp();
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
function CpExit() {
|
|
500
|
+
cpDepth = (cpDepth | 0) - 1;
|
|
501
|
+
if ((cpDepth | 0) < 1) {
|
|
502
|
+
cp = CP_UNSET | 0;
|
|
503
|
+
cpCounter = 0;
|
|
504
|
+
cpDepth = 0;
|
|
505
|
+
} else {
|
|
506
|
+
Cp();
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
var INT_MAX = 2147483647;
|
|
510
|
+
function configCheckpoint(timeout = CP_DEFAULT_TIMEOUT, checkInterval = CP_DEFAULT_INTERVAL) {
|
|
511
|
+
if (typeof timeout !== "number" || timeout <= 0 || isNaN(timeout)) {
|
|
512
|
+
throw new RangeError("Invalid timeout value");
|
|
513
|
+
} else if (timeout > INT_MAX) {
|
|
514
|
+
timeout = INT_MAX;
|
|
515
|
+
}
|
|
516
|
+
if (typeof checkInterval !== "number" || checkInterval <= 0 || isNaN(checkInterval)) {
|
|
517
|
+
throw new RangeError("Invalid check interval value");
|
|
518
|
+
} else if (checkInterval > INT_MAX) {
|
|
519
|
+
checkInterval = INT_MAX;
|
|
520
|
+
}
|
|
521
|
+
cpTimeout = timeout | 0;
|
|
522
|
+
cpInterval = checkInterval | 0;
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
// src/vm/types/function.ts
|
|
526
|
+
var nameIfNotAnonymous = ({ name }, fallback) => {
|
|
527
|
+
if (!name) return fallback;
|
|
528
|
+
if (name === VM_FUNCTION_ANONYMOUS_NAME) return fallback;
|
|
529
|
+
return name;
|
|
530
|
+
};
|
|
531
|
+
function VmFunction(fn, option = {}) {
|
|
532
|
+
if (typeof fn != "function") {
|
|
533
|
+
throw new TypeError("Invalid function");
|
|
534
|
+
}
|
|
535
|
+
const exists = fromVmFunctionProxy(fn);
|
|
536
|
+
if (exists) return exists;
|
|
537
|
+
let opt;
|
|
538
|
+
if (isVmFunction(option)) {
|
|
539
|
+
opt = { ...option[kVmFunction], name: nameIfNotAnonymous(option, null) };
|
|
540
|
+
} else if (typeof option == "function") {
|
|
541
|
+
opt = {
|
|
542
|
+
...option,
|
|
543
|
+
isLib: true,
|
|
544
|
+
injectCp: false,
|
|
545
|
+
name: nameIfNotAnonymous(option, null)
|
|
546
|
+
};
|
|
547
|
+
} else {
|
|
548
|
+
opt = option;
|
|
549
|
+
}
|
|
550
|
+
const info = {
|
|
551
|
+
__proto__: null,
|
|
552
|
+
fullName: opt.fullName ?? nameIfNotAnonymous(fn, ""),
|
|
553
|
+
isLib: opt.isLib ?? false,
|
|
554
|
+
summary: opt.summary || void 0,
|
|
555
|
+
params: opt.params,
|
|
556
|
+
paramsType: opt.paramsType,
|
|
557
|
+
returns: opt.returns || void 0,
|
|
558
|
+
returnsType: opt.returnsType || void 0,
|
|
559
|
+
examples: opt.examples?.length ? opt.examples : void 0,
|
|
560
|
+
deprecated: opt.deprecated ?? void 0
|
|
561
|
+
};
|
|
562
|
+
const name = opt.name ?? fn.name;
|
|
563
|
+
if (opt.injectCp) {
|
|
564
|
+
const original = fn;
|
|
565
|
+
info.original = original;
|
|
566
|
+
fn = ((...args) => {
|
|
567
|
+
try {
|
|
568
|
+
CpEnter();
|
|
569
|
+
const ret = original(...args);
|
|
570
|
+
return ret;
|
|
571
|
+
} finally {
|
|
572
|
+
CpExit();
|
|
573
|
+
}
|
|
574
|
+
});
|
|
575
|
+
}
|
|
576
|
+
defineProperty(fn, "name", { value: name, configurable: true });
|
|
577
|
+
defineProperty(fn, kVmFunction, { value: Object.freeze(info) });
|
|
578
|
+
return fn;
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
// src/vm/types/context.ts
|
|
582
|
+
var { freeze } = Object;
|
|
583
|
+
var VM_SHARED_CONTEXT = create(null);
|
|
584
|
+
var VM_SHARED_CONTEXT_DESCRIPTIONS = create(null);
|
|
585
|
+
var VM_SHARED_CONTEXT_KEYS = null;
|
|
586
|
+
function globalVarNotFound(name) {
|
|
587
|
+
throw new VmError(`Global variable '${name}' is not defined.`, null);
|
|
588
|
+
}
|
|
589
|
+
function defineVmContextValue(name, value, override = false, description = void 0) {
|
|
590
|
+
if (!override && name in VM_SHARED_CONTEXT) throw new Error(`Global variable '${name}' is already defined.`);
|
|
591
|
+
let v;
|
|
592
|
+
if (typeof value == "function") {
|
|
593
|
+
v = VmFunction(value, {
|
|
594
|
+
name,
|
|
595
|
+
isLib: true,
|
|
596
|
+
fullName: `global.${name}`
|
|
597
|
+
});
|
|
598
|
+
} else {
|
|
599
|
+
v = value;
|
|
600
|
+
}
|
|
601
|
+
VM_SHARED_CONTEXT[name] = v ?? null;
|
|
602
|
+
if (description) VM_SHARED_CONTEXT_DESCRIPTIONS[name] = description;
|
|
603
|
+
VM_SHARED_CONTEXT_KEYS = null;
|
|
604
|
+
}
|
|
605
|
+
var DefaultVmContext = freeze({
|
|
606
|
+
__proto__: null,
|
|
607
|
+
[kVmContext]: true,
|
|
608
|
+
/** @inheritdoc */
|
|
609
|
+
keys() {
|
|
610
|
+
VM_SHARED_CONTEXT_KEYS ??= freeze(keys(VM_SHARED_CONTEXT));
|
|
611
|
+
return VM_SHARED_CONTEXT_KEYS;
|
|
612
|
+
},
|
|
613
|
+
/** @inheritdoc */
|
|
614
|
+
get(key) {
|
|
615
|
+
const val = VM_SHARED_CONTEXT[key];
|
|
616
|
+
if (val !== void 0) return val;
|
|
617
|
+
return globalVarNotFound(key);
|
|
618
|
+
},
|
|
619
|
+
/** @inheritdoc */
|
|
620
|
+
has(key) {
|
|
621
|
+
return key in VM_SHARED_CONTEXT;
|
|
622
|
+
},
|
|
623
|
+
/** @inheritdoc */
|
|
624
|
+
describe(key) {
|
|
625
|
+
return VM_SHARED_CONTEXT_DESCRIPTIONS[key];
|
|
626
|
+
}
|
|
627
|
+
});
|
|
628
|
+
var ValueVmContext = class {
|
|
629
|
+
constructor(env, describer) {
|
|
630
|
+
this.env = env;
|
|
631
|
+
this.describer = describer;
|
|
632
|
+
}
|
|
633
|
+
/** @inheritdoc */
|
|
634
|
+
keys() {
|
|
635
|
+
return [...keys(this.env), ...DefaultVmContext.keys()];
|
|
636
|
+
}
|
|
637
|
+
/** @inheritdoc */
|
|
638
|
+
get(key) {
|
|
639
|
+
if (hasOwn(this.env, key)) return this.env[key] ?? null;
|
|
640
|
+
{
|
|
641
|
+
const val = VM_SHARED_CONTEXT[key];
|
|
642
|
+
if (val !== void 0) return val;
|
|
643
|
+
return globalVarNotFound(key);
|
|
644
|
+
}
|
|
645
|
+
}
|
|
646
|
+
/** @inheritdoc */
|
|
647
|
+
has(key) {
|
|
648
|
+
return hasOwn(this.env, key) || key in VM_SHARED_CONTEXT;
|
|
649
|
+
}
|
|
650
|
+
/** @inheritdoc */
|
|
651
|
+
describe(key) {
|
|
652
|
+
if (hasOwn(this.env, key)) return this.describer?.(key);
|
|
653
|
+
return VM_SHARED_CONTEXT_DESCRIPTIONS[key];
|
|
654
|
+
}
|
|
655
|
+
};
|
|
656
|
+
defineProperty(ValueVmContext.prototype, kVmContext, { value: true });
|
|
657
|
+
freeze(ValueVmContext.prototype);
|
|
658
|
+
var Value2VmContext = class {
|
|
659
|
+
constructor(env, extern, describer) {
|
|
660
|
+
this.env = env;
|
|
661
|
+
this.extern = extern;
|
|
662
|
+
this.describer = describer;
|
|
663
|
+
this.externCache = /* @__PURE__ */ new WeakMap();
|
|
664
|
+
}
|
|
665
|
+
/** @inheritdoc */
|
|
666
|
+
keys() {
|
|
667
|
+
return [...this.env == null ? [] : keys(this.env), ...keys(this.extern), ...DefaultVmContext.keys()];
|
|
668
|
+
}
|
|
669
|
+
/** @inheritdoc */
|
|
670
|
+
get(key) {
|
|
671
|
+
if (this.env != null && hasOwn(this.env, key)) return this.env[key] ?? null;
|
|
672
|
+
if (hasOwn(this.extern, key)) {
|
|
673
|
+
const val2 = this.extern[key];
|
|
674
|
+
if (val2 == null) return null;
|
|
675
|
+
if (typeof val2 != "object" && typeof val2 != "function") {
|
|
676
|
+
return wrapToVmValue(val2, null, null);
|
|
677
|
+
}
|
|
678
|
+
let cached = this.externCache.get(val2);
|
|
679
|
+
if (cached == null) {
|
|
680
|
+
cached = wrapToVmValue(val2, null, null);
|
|
681
|
+
this.externCache.set(val2, cached);
|
|
682
|
+
}
|
|
683
|
+
return cached;
|
|
684
|
+
}
|
|
685
|
+
const val = VM_SHARED_CONTEXT[key];
|
|
686
|
+
if (val !== void 0) return val;
|
|
687
|
+
return globalVarNotFound(key);
|
|
688
|
+
}
|
|
689
|
+
/** @inheritdoc */
|
|
690
|
+
has(key) {
|
|
691
|
+
return this.env != null && hasOwn(this.env, key) || hasOwn(this.extern, key) || key in VM_SHARED_CONTEXT;
|
|
692
|
+
}
|
|
693
|
+
/** @inheritdoc */
|
|
694
|
+
describe(key) {
|
|
695
|
+
if (this.env != null && hasOwn(this.env, key) || hasOwn(this.extern, key)) return this.describer?.(key);
|
|
696
|
+
return VM_SHARED_CONTEXT_DESCRIPTIONS[key];
|
|
697
|
+
}
|
|
698
|
+
};
|
|
699
|
+
defineProperty(Value2VmContext.prototype, kVmContext, { value: true });
|
|
700
|
+
freeze(Value2VmContext.prototype);
|
|
701
|
+
var FactoryVmContext = class {
|
|
702
|
+
constructor(getter, enumerator, describer) {
|
|
703
|
+
this.getter = getter;
|
|
704
|
+
this.enumerator = enumerator;
|
|
705
|
+
this.describer = describer;
|
|
706
|
+
}
|
|
707
|
+
/** @inheritdoc */
|
|
708
|
+
keys() {
|
|
709
|
+
if (!this.enumerator) return DefaultVmContext.keys();
|
|
710
|
+
return [...this.enumerator(), ...DefaultVmContext.keys()];
|
|
711
|
+
}
|
|
712
|
+
/** @inheritdoc */
|
|
713
|
+
get(key) {
|
|
714
|
+
const value = this.getter(key);
|
|
715
|
+
if (value !== void 0) return value;
|
|
716
|
+
const val = VM_SHARED_CONTEXT[key];
|
|
717
|
+
if (val !== void 0) return val;
|
|
718
|
+
return globalVarNotFound(key);
|
|
719
|
+
}
|
|
720
|
+
/** @inheritdoc */
|
|
721
|
+
has(key) {
|
|
722
|
+
return this.getter(key) !== void 0 || key in VM_SHARED_CONTEXT;
|
|
723
|
+
}
|
|
724
|
+
/** @inheritdoc */
|
|
725
|
+
describe(key) {
|
|
726
|
+
if (this.getter(key) !== void 0) return this.describer?.(key);
|
|
727
|
+
return VM_SHARED_CONTEXT_DESCRIPTIONS[key];
|
|
728
|
+
}
|
|
729
|
+
};
|
|
730
|
+
defineProperty(FactoryVmContext.prototype, kVmContext, { value: true });
|
|
731
|
+
freeze(FactoryVmContext.prototype);
|
|
732
|
+
function createVmContext(arg0 = null, arg1 = null, describer = null) {
|
|
733
|
+
if (typeof arg0 == "function") {
|
|
734
|
+
const getter = arg0;
|
|
735
|
+
const enumerator = arg1;
|
|
736
|
+
return new FactoryVmContext(getter, enumerator, describer);
|
|
737
|
+
}
|
|
738
|
+
const vmValues = arg0;
|
|
739
|
+
const externValues = arg1;
|
|
740
|
+
if (externValues == null) {
|
|
741
|
+
if (vmValues == null) {
|
|
742
|
+
return DefaultVmContext;
|
|
743
|
+
}
|
|
744
|
+
return new ValueVmContext(vmValues, describer);
|
|
745
|
+
}
|
|
746
|
+
return new Value2VmContext(vmValues, externValues, describer);
|
|
747
|
+
}
|
|
748
|
+
|
|
749
|
+
// src/vm/types/module.ts
|
|
750
|
+
var VmModule = class extends VmWrapper {
|
|
751
|
+
constructor(name, value) {
|
|
752
|
+
super(value);
|
|
753
|
+
this.name = name;
|
|
754
|
+
}
|
|
755
|
+
/** @inheritdoc */
|
|
756
|
+
has(key) {
|
|
757
|
+
return hasOwnEnumerable(this.value, key);
|
|
758
|
+
}
|
|
759
|
+
/** @inheritdoc */
|
|
760
|
+
get(key) {
|
|
761
|
+
if (!this.has(key)) return void 0;
|
|
762
|
+
return this.value[key] ?? null;
|
|
763
|
+
}
|
|
764
|
+
/** @inheritdoc */
|
|
765
|
+
keys() {
|
|
766
|
+
return keys(this.value);
|
|
767
|
+
}
|
|
768
|
+
/** @inheritdoc */
|
|
769
|
+
same(other) {
|
|
770
|
+
return this === other;
|
|
771
|
+
}
|
|
772
|
+
/** @inheritdoc */
|
|
773
|
+
get type() {
|
|
774
|
+
return "module";
|
|
775
|
+
}
|
|
776
|
+
/** @inheritdoc */
|
|
777
|
+
get tag() {
|
|
778
|
+
return this.name;
|
|
779
|
+
}
|
|
780
|
+
};
|
|
781
|
+
Object.defineProperty(VmModule.prototype, kVmModule, { value: true });
|
|
782
|
+
|
|
783
|
+
// src/vm/operations/index.ts
|
|
784
|
+
var operations_exports = {};
|
|
785
|
+
__export(operations_exports, {
|
|
786
|
+
$Add: () => $Add,
|
|
787
|
+
$Aeq: () => $Aeq,
|
|
788
|
+
$And: () => $And,
|
|
789
|
+
$ArrayRange: () => $ArrayRange,
|
|
790
|
+
$ArrayRangeExclusive: () => $ArrayRangeExclusive,
|
|
791
|
+
$ArraySpread: () => $ArraySpread,
|
|
792
|
+
$AssertInit: () => $AssertInit,
|
|
793
|
+
$AssertNonNil: () => $AssertNonNil,
|
|
794
|
+
$Call: () => $Call,
|
|
795
|
+
$Concat: () => $Concat,
|
|
796
|
+
$Cp: () => Cp,
|
|
797
|
+
$CpEnter: () => CpEnter,
|
|
798
|
+
$CpExit: () => CpExit,
|
|
799
|
+
$Div: () => $Div,
|
|
800
|
+
$El: () => $El,
|
|
801
|
+
$ElOpt: () => $ElOpt,
|
|
802
|
+
$Eq: () => $Eq,
|
|
803
|
+
$Fn: () => $Fn,
|
|
804
|
+
$Format: () => $Format,
|
|
805
|
+
$Get: () => $Get,
|
|
806
|
+
$GlobalFallback: () => $GlobalFallback,
|
|
807
|
+
$Gt: () => $Gt,
|
|
808
|
+
$Gte: () => $Gte,
|
|
809
|
+
$Has: () => $Has,
|
|
810
|
+
$In: () => $In,
|
|
811
|
+
$IsArray: () => $IsArray,
|
|
812
|
+
$IsBoolean: () => $IsBoolean,
|
|
813
|
+
$IsNumber: () => $IsNumber,
|
|
814
|
+
$IsRecord: () => $IsRecord,
|
|
815
|
+
$IsString: () => $IsString,
|
|
816
|
+
$Iterable: () => $Iterable,
|
|
817
|
+
$Length: () => $Length,
|
|
818
|
+
$Lt: () => $Lt,
|
|
819
|
+
$Lte: () => $Lte,
|
|
820
|
+
$Mod: () => $Mod,
|
|
821
|
+
$Module: () => $Module,
|
|
822
|
+
$Mul: () => $Mul,
|
|
823
|
+
$Naeq: () => $Naeq,
|
|
824
|
+
$Neg: () => $Neg,
|
|
825
|
+
$Neq: () => $Neq,
|
|
826
|
+
$Not: () => $Not,
|
|
827
|
+
$Nsame: () => $Nsame,
|
|
828
|
+
$Omit: () => $Omit,
|
|
829
|
+
$Or: () => $Or,
|
|
830
|
+
$Pick: () => $Pick,
|
|
831
|
+
$Pos: () => $Pos,
|
|
832
|
+
$Pow: () => $Pow,
|
|
833
|
+
$RecordSpread: () => $RecordSpread,
|
|
834
|
+
$Same: () => $Same,
|
|
835
|
+
$Set: () => $Set,
|
|
836
|
+
$Slice: () => $Slice,
|
|
837
|
+
$SliceExclusive: () => $SliceExclusive,
|
|
838
|
+
$Sub: () => $Sub,
|
|
839
|
+
$ToBoolean: () => $ToBoolean,
|
|
840
|
+
$ToNumber: () => $ToNumber,
|
|
841
|
+
$ToString: () => $ToString,
|
|
842
|
+
$Type: () => $Type,
|
|
843
|
+
$Upvalue: () => $Upvalue,
|
|
844
|
+
$VArgs: () => $VArgs
|
|
845
|
+
});
|
|
846
|
+
|
|
847
|
+
// src/vm/operations/convert.ts
|
|
848
|
+
function $ToBoolean(value) {
|
|
849
|
+
if (typeof value == "boolean") return value;
|
|
850
|
+
$AssertInit(value);
|
|
851
|
+
return toBoolean(value, void 0);
|
|
852
|
+
}
|
|
853
|
+
function $ToString(value) {
|
|
854
|
+
if (typeof value == "string") return value;
|
|
855
|
+
$AssertInit(value);
|
|
856
|
+
return toString(value, void 0);
|
|
857
|
+
}
|
|
858
|
+
function $ToNumber(value) {
|
|
859
|
+
if (typeof value == "number") return value;
|
|
860
|
+
$AssertInit(value);
|
|
861
|
+
return toNumber(value, void 0);
|
|
862
|
+
}
|
|
863
|
+
function $Format(value, format2) {
|
|
864
|
+
$AssertInit(value);
|
|
865
|
+
return toFormat(value, format2);
|
|
866
|
+
}
|
|
867
|
+
|
|
868
|
+
// src/vm/operations/type-check.ts
|
|
869
|
+
function $Type(value) {
|
|
870
|
+
if (value == null) return "nil";
|
|
871
|
+
if (isVmWrapper(value)) return value.type;
|
|
872
|
+
if (isVmArray(value)) return "array";
|
|
873
|
+
if (typeof value == "object") return "record";
|
|
874
|
+
return typeof value;
|
|
875
|
+
}
|
|
876
|
+
function $IsBoolean(value) {
|
|
877
|
+
$AssertInit(value);
|
|
878
|
+
return typeof value == "boolean";
|
|
879
|
+
}
|
|
880
|
+
function $IsNumber(value) {
|
|
881
|
+
$AssertInit(value);
|
|
882
|
+
return typeof value == "number";
|
|
883
|
+
}
|
|
884
|
+
function $IsString(value) {
|
|
885
|
+
$AssertInit(value);
|
|
886
|
+
return typeof value == "string";
|
|
887
|
+
}
|
|
888
|
+
function $IsRecord(value) {
|
|
889
|
+
$AssertInit(value);
|
|
890
|
+
return isVmRecord(value);
|
|
891
|
+
}
|
|
892
|
+
function $IsArray(value) {
|
|
893
|
+
$AssertInit(value);
|
|
894
|
+
return isVmArray(value);
|
|
895
|
+
}
|
|
896
|
+
function $AssertNonNil(value) {
|
|
897
|
+
$AssertInit(value);
|
|
898
|
+
if (value !== null) return;
|
|
899
|
+
throw new VmError(`Expected non-nil value`, null);
|
|
900
|
+
}
|
|
901
|
+
|
|
902
|
+
// src/vm/operations/utils.ts
|
|
903
|
+
function overloadNumberString(a, b) {
|
|
904
|
+
if (typeof a == "number" || typeof b == "number") return true;
|
|
905
|
+
if (typeof a == "string" || typeof b == "string") return false;
|
|
906
|
+
return true;
|
|
907
|
+
}
|
|
908
|
+
function isSame(a, b) {
|
|
909
|
+
if (typeof a == "number" && typeof b == "number") {
|
|
910
|
+
return a === b || isNaN(a) && isNaN(b);
|
|
911
|
+
}
|
|
912
|
+
if (a === b) return true;
|
|
913
|
+
if (a == null || typeof a != "object" || b == null || typeof b != "object") return false;
|
|
914
|
+
if (isVmWrapper(a)) return a.same(b);
|
|
915
|
+
if (isVmWrapper(b)) return b.same(a);
|
|
916
|
+
if (isVmArray(a) && isVmArray(b)) {
|
|
917
|
+
const len2 = a.length;
|
|
918
|
+
if (len2 !== b.length) {
|
|
919
|
+
return false;
|
|
920
|
+
}
|
|
921
|
+
for (let i = 0; i < len2; i++) {
|
|
922
|
+
if (!isSame(a[i] ?? null, b[i] ?? null)) {
|
|
923
|
+
return false;
|
|
924
|
+
}
|
|
925
|
+
}
|
|
926
|
+
return true;
|
|
927
|
+
}
|
|
928
|
+
if (!isVmArray(a) && !isVmArray(b)) {
|
|
929
|
+
const aKeys = keys(a);
|
|
930
|
+
const bKeys = keys(b);
|
|
931
|
+
const len2 = aKeys.length;
|
|
932
|
+
if (len2 !== bKeys.length) return false;
|
|
933
|
+
if (len2 === 0) return true;
|
|
934
|
+
let i = len2;
|
|
935
|
+
while (i--) {
|
|
936
|
+
const key = aKeys[i];
|
|
937
|
+
if (!hasOwnEnumerable(b, key)) return false;
|
|
938
|
+
const av = a[key] ?? null;
|
|
939
|
+
const bv = b[key] ?? null;
|
|
940
|
+
if (!isSame(av, bv)) return false;
|
|
941
|
+
}
|
|
942
|
+
return true;
|
|
943
|
+
}
|
|
944
|
+
return false;
|
|
945
|
+
}
|
|
946
|
+
|
|
947
|
+
// src/vm/operations/operator.ts
|
|
948
|
+
function $Concat(...args) {
|
|
949
|
+
return args.map((a) => toFormat(a, null)).join("");
|
|
950
|
+
}
|
|
951
|
+
function $Pos(a) {
|
|
952
|
+
return $ToNumber(a);
|
|
953
|
+
}
|
|
954
|
+
function $Neg(a) {
|
|
955
|
+
return -$ToNumber(a);
|
|
956
|
+
}
|
|
957
|
+
function $Not(a) {
|
|
958
|
+
return !$ToBoolean(a);
|
|
959
|
+
}
|
|
960
|
+
function $Add(a, b) {
|
|
961
|
+
return $ToNumber(a) + $ToNumber(b);
|
|
962
|
+
}
|
|
963
|
+
function $Sub(a, b) {
|
|
964
|
+
return $ToNumber(a) - $ToNumber(b);
|
|
965
|
+
}
|
|
966
|
+
function $Mul(a, b) {
|
|
967
|
+
return $ToNumber(a) * $ToNumber(b);
|
|
968
|
+
}
|
|
969
|
+
function $Div(a, b) {
|
|
970
|
+
return $ToNumber(a) / $ToNumber(b);
|
|
971
|
+
}
|
|
972
|
+
function $Mod(a, b) {
|
|
973
|
+
return $ToNumber(a) % $ToNumber(b);
|
|
974
|
+
}
|
|
975
|
+
function $Pow(a, b) {
|
|
976
|
+
return $ToNumber(a) ** $ToNumber(b);
|
|
977
|
+
}
|
|
978
|
+
function $And(a, b) {
|
|
979
|
+
return $ToBoolean(a) && $ToBoolean(b);
|
|
980
|
+
}
|
|
981
|
+
function $Or(a, b) {
|
|
982
|
+
return $ToBoolean(a) || $ToBoolean(b);
|
|
983
|
+
}
|
|
984
|
+
function $Gt(a, b) {
|
|
985
|
+
if (overloadNumberString(a, b)) {
|
|
986
|
+
return $ToNumber(a) > $ToNumber(b);
|
|
987
|
+
} else {
|
|
988
|
+
return $ToString(a) > $ToString(b);
|
|
989
|
+
}
|
|
990
|
+
}
|
|
991
|
+
function $Gte(a, b) {
|
|
992
|
+
if (overloadNumberString(a, b)) {
|
|
993
|
+
return $ToNumber(a) >= $ToNumber(b);
|
|
994
|
+
} else {
|
|
995
|
+
return $ToString(a) >= $ToString(b);
|
|
996
|
+
}
|
|
997
|
+
}
|
|
998
|
+
function $Lt(a, b) {
|
|
999
|
+
if (overloadNumberString(a, b)) {
|
|
1000
|
+
return $ToNumber(a) < $ToNumber(b);
|
|
1001
|
+
} else {
|
|
1002
|
+
return $ToString(a) < $ToString(b);
|
|
1003
|
+
}
|
|
1004
|
+
}
|
|
1005
|
+
function $Lte(a, b) {
|
|
1006
|
+
if (overloadNumberString(a, b)) {
|
|
1007
|
+
return $ToNumber(a) <= $ToNumber(b);
|
|
1008
|
+
} else {
|
|
1009
|
+
return $ToString(a) <= $ToString(b);
|
|
1010
|
+
}
|
|
1011
|
+
}
|
|
1012
|
+
function $Eq(a, b) {
|
|
1013
|
+
$AssertInit(a);
|
|
1014
|
+
$AssertInit(b);
|
|
1015
|
+
if (typeof a == "number" && typeof b == "number") return a === b;
|
|
1016
|
+
return isSame(a, b);
|
|
1017
|
+
}
|
|
1018
|
+
function $Neq(a, b) {
|
|
1019
|
+
return !$Eq(a, b);
|
|
1020
|
+
}
|
|
1021
|
+
var { abs, min } = Math;
|
|
1022
|
+
function $Aeq(a, b) {
|
|
1023
|
+
if (overloadNumberString(a, b)) {
|
|
1024
|
+
const an = $ToNumber(a);
|
|
1025
|
+
const bn = $ToNumber(b);
|
|
1026
|
+
const EPS = 1e-15;
|
|
1027
|
+
if (isNaN(an) || isNaN(bn)) return false;
|
|
1028
|
+
if (an === bn) return true;
|
|
1029
|
+
const absoluteDifference = abs(an - bn);
|
|
1030
|
+
if (absoluteDifference < EPS) return true;
|
|
1031
|
+
const base = min(abs(an), abs(bn));
|
|
1032
|
+
return absoluteDifference < base * EPS;
|
|
1033
|
+
} else {
|
|
1034
|
+
const as = $ToString(a);
|
|
1035
|
+
const bs = $ToString(b);
|
|
1036
|
+
if (as === bs) return true;
|
|
1037
|
+
const ai = as.toLowerCase();
|
|
1038
|
+
const bi = bs.toLowerCase();
|
|
1039
|
+
if (ai === bi) return true;
|
|
1040
|
+
const an = ai.normalize("NFC");
|
|
1041
|
+
const bn = bi.normalize("NFC");
|
|
1042
|
+
return an === bn;
|
|
1043
|
+
}
|
|
1044
|
+
}
|
|
1045
|
+
function $Naeq(a, b) {
|
|
1046
|
+
return !$Aeq(a, b);
|
|
1047
|
+
}
|
|
1048
|
+
function $Same(a, b) {
|
|
1049
|
+
$AssertInit(a);
|
|
1050
|
+
$AssertInit(b);
|
|
1051
|
+
return isSame(a, b);
|
|
1052
|
+
}
|
|
1053
|
+
function $Nsame(a, b) {
|
|
1054
|
+
return !$Same(a, b);
|
|
1055
|
+
}
|
|
1056
|
+
|
|
1057
|
+
// src/vm/operations/slice.ts
|
|
1058
|
+
var { ceil } = Math;
|
|
1059
|
+
var { slice } = Array.prototype;
|
|
1060
|
+
var sliceCore = (value, start, end, exclusive) => {
|
|
1061
|
+
const { length } = value;
|
|
1062
|
+
if (isNaN(start)) start = 0;
|
|
1063
|
+
else if (start < 0) start = length + start;
|
|
1064
|
+
if (isNaN(end)) end = exclusive ? length : length - 1;
|
|
1065
|
+
else if (end < 0) end = length + end;
|
|
1066
|
+
start = ceil(start);
|
|
1067
|
+
if (exclusive || !isSafeInteger(end)) {
|
|
1068
|
+
end = ceil(end);
|
|
1069
|
+
} else {
|
|
1070
|
+
end = end + 1;
|
|
1071
|
+
}
|
|
1072
|
+
return slice.call(value, start, end);
|
|
1073
|
+
};
|
|
1074
|
+
function $Slice(value, start, end) {
|
|
1075
|
+
$AssertInit(value);
|
|
1076
|
+
if (!isVmArray(value)) throw new VmError(`Expected array, got ${display(value)}`, []);
|
|
1077
|
+
const s2 = start != null ? $ToNumber(start) : 0;
|
|
1078
|
+
const e2 = end != null ? $ToNumber(end) : value.length - 1;
|
|
1079
|
+
return sliceCore(value, s2, e2, false);
|
|
1080
|
+
}
|
|
1081
|
+
function $SliceExclusive(value, start, end) {
|
|
1082
|
+
$AssertInit(value);
|
|
1083
|
+
if (!isVmArray(value)) throw new VmError(`Expected array, got ${display(value)}`, []);
|
|
1084
|
+
const s2 = start != null ? $ToNumber(start) : 0;
|
|
1085
|
+
const e2 = end != null ? $ToNumber(end) : value.length;
|
|
1086
|
+
return sliceCore(value, s2, e2, true);
|
|
1087
|
+
}
|
|
1088
|
+
|
|
1089
|
+
// src/vm/operations/helpers.ts
|
|
1090
|
+
function $Module(name, body) {
|
|
1091
|
+
const mod = create(null);
|
|
1092
|
+
for (const [key, get] of entries(body)) {
|
|
1093
|
+
defineProperty(mod, key, { __proto__: null, get, enumerable: true });
|
|
1094
|
+
}
|
|
1095
|
+
return new VmModule(name, mod);
|
|
1096
|
+
}
|
|
1097
|
+
function $El(value) {
|
|
1098
|
+
$AssertInit(value);
|
|
1099
|
+
if (!isVmConst(value)) return null;
|
|
1100
|
+
return value;
|
|
1101
|
+
}
|
|
1102
|
+
var EMPTY = create(null);
|
|
1103
|
+
function $ElOpt(key, value) {
|
|
1104
|
+
$AssertInit(value);
|
|
1105
|
+
if (value == null || !isVmConst(value)) return EMPTY;
|
|
1106
|
+
return { __proto__: null, [key]: value };
|
|
1107
|
+
}
|
|
1108
|
+
function $Fn(name, fn) {
|
|
1109
|
+
return VmFunction(fn, { isLib: false, injectCp: false, name: name || VM_FUNCTION_ANONYMOUS_NAME });
|
|
1110
|
+
}
|
|
1111
|
+
function $Upvalue(value) {
|
|
1112
|
+
$AssertInit(value);
|
|
1113
|
+
return value;
|
|
1114
|
+
}
|
|
1115
|
+
var assertArrayLength = (len2) => {
|
|
1116
|
+
if (len2 > VM_ARRAY_MAX_LENGTH) {
|
|
1117
|
+
throw new RangeError(`Array length exceeds maximum limit of ${VM_ARRAY_MAX_LENGTH}`);
|
|
1118
|
+
}
|
|
1119
|
+
};
|
|
1120
|
+
var isEmptyRange = (start, end) => {
|
|
1121
|
+
return !isFinite(start) || !isFinite(end) || start > end;
|
|
1122
|
+
};
|
|
1123
|
+
function $ArrayRange(start, end) {
|
|
1124
|
+
const s2 = $ToNumber(start);
|
|
1125
|
+
const e2 = $ToNumber(end);
|
|
1126
|
+
if (isEmptyRange(s2, e2)) return [];
|
|
1127
|
+
assertArrayLength(e2 - s2 + 1);
|
|
1128
|
+
const arr = [];
|
|
1129
|
+
for (let i = s2; i <= e2; i++) {
|
|
1130
|
+
arr.push(i);
|
|
1131
|
+
}
|
|
1132
|
+
return arr;
|
|
1133
|
+
}
|
|
1134
|
+
function $ArrayRangeExclusive(start, end) {
|
|
1135
|
+
const s2 = $ToNumber(start);
|
|
1136
|
+
const e2 = $ToNumber(end);
|
|
1137
|
+
if (isEmptyRange(s2, e2)) return [];
|
|
1138
|
+
assertArrayLength(e2 - s2);
|
|
1139
|
+
const arr = [];
|
|
1140
|
+
for (let i = s2; i < e2; i++) {
|
|
1141
|
+
arr.push(i);
|
|
1142
|
+
}
|
|
1143
|
+
return arr;
|
|
1144
|
+
}
|
|
1145
|
+
function $GlobalFallback() {
|
|
1146
|
+
return DefaultVmContext;
|
|
1147
|
+
}
|
|
1148
|
+
|
|
1149
|
+
// src/vm/operations/compound.ts
|
|
1150
|
+
var { trunc } = Math;
|
|
1151
|
+
var { at } = Array.prototype;
|
|
1152
|
+
function $In(value, iterable) {
|
|
1153
|
+
$AssertInit(value);
|
|
1154
|
+
$AssertInit(iterable);
|
|
1155
|
+
if (iterable == null) return false;
|
|
1156
|
+
if (typeof iterable != "object") return false;
|
|
1157
|
+
if (isVmArray(iterable)) {
|
|
1158
|
+
if (value == null) {
|
|
1159
|
+
for (const item of iterable) if (item == null) return true;
|
|
1160
|
+
return false;
|
|
1161
|
+
}
|
|
1162
|
+
if (isVmPrimitive(value)) return iterable.includes(value);
|
|
1163
|
+
return iterable.some((item = null) => isSame(item, value));
|
|
1164
|
+
}
|
|
1165
|
+
const key = toString(value, void 0);
|
|
1166
|
+
if (isVmWrapper(iterable)) return iterable.has(key);
|
|
1167
|
+
return hasOwnEnumerable(iterable, key);
|
|
1168
|
+
}
|
|
1169
|
+
function $Length(value) {
|
|
1170
|
+
$AssertInit(value);
|
|
1171
|
+
if (isVmArray(value)) return value.length;
|
|
1172
|
+
if (isVmRecord(value)) return keys(value).length;
|
|
1173
|
+
if (isVmWrapper(value)) return value.keys().length;
|
|
1174
|
+
throw new VmError(`Value has no length: ${display(value)}`, 0);
|
|
1175
|
+
}
|
|
1176
|
+
function $Omit(value, omitted) {
|
|
1177
|
+
$AssertInit(value);
|
|
1178
|
+
if (value == null || !isVmRecord(value)) return {};
|
|
1179
|
+
const result = {};
|
|
1180
|
+
const valueKeys = keys(value);
|
|
1181
|
+
const omittedSet = new Set(omitted.map($ToString));
|
|
1182
|
+
for (const key of valueKeys) {
|
|
1183
|
+
if (!omittedSet.has(key)) {
|
|
1184
|
+
result[key] = value[key] ?? null;
|
|
1185
|
+
}
|
|
1186
|
+
}
|
|
1187
|
+
return result;
|
|
1188
|
+
}
|
|
1189
|
+
function $Pick(value, picked) {
|
|
1190
|
+
$AssertInit(value);
|
|
1191
|
+
if (value == null || !isVmRecord(value)) return {};
|
|
1192
|
+
const result = {};
|
|
1193
|
+
for (const key of picked) {
|
|
1194
|
+
const k = $ToString(key);
|
|
1195
|
+
if (hasOwnEnumerable(value, k)) {
|
|
1196
|
+
result[k] = value[k] ?? null;
|
|
1197
|
+
}
|
|
1198
|
+
}
|
|
1199
|
+
return result;
|
|
1200
|
+
}
|
|
1201
|
+
function $Has(obj, key) {
|
|
1202
|
+
$AssertInit(obj);
|
|
1203
|
+
const pk = $ToString(key);
|
|
1204
|
+
if (obj == null || typeof obj != "object") return false;
|
|
1205
|
+
if (isVmWrapper(obj)) return obj.has(pk);
|
|
1206
|
+
return hasOwnEnumerable(obj, pk);
|
|
1207
|
+
}
|
|
1208
|
+
function $Get(obj, key) {
|
|
1209
|
+
$AssertInit(obj);
|
|
1210
|
+
if (isVmArray(obj)) {
|
|
1211
|
+
$AssertInit(key);
|
|
1212
|
+
const index = toNumber(key, NotNumber);
|
|
1213
|
+
if (isNaN(index)) return null;
|
|
1214
|
+
return $El(at.call(obj, trunc(index)) ?? null);
|
|
1215
|
+
}
|
|
1216
|
+
const pk = $ToString(key);
|
|
1217
|
+
if (obj == null || typeof obj != "object") return null;
|
|
1218
|
+
if (isVmWrapper(obj)) {
|
|
1219
|
+
if (isFinite(key) && isVmExtern(obj) && obj.isArrayLike()) {
|
|
1220
|
+
let index = trunc(key);
|
|
1221
|
+
const { length } = obj.value;
|
|
1222
|
+
if (index < 0) index += length;
|
|
1223
|
+
if (index >= 0 && index < length) {
|
|
1224
|
+
return obj.get(String(index)) ?? null;
|
|
1225
|
+
}
|
|
1226
|
+
}
|
|
1227
|
+
return obj.get(pk) ?? null;
|
|
1228
|
+
}
|
|
1229
|
+
if (!hasOwnEnumerable(obj, pk)) return null;
|
|
1230
|
+
return $El(obj[pk] ?? null);
|
|
1231
|
+
}
|
|
1232
|
+
function $Set(obj, key, value) {
|
|
1233
|
+
$AssertInit(obj);
|
|
1234
|
+
$AssertInit(value);
|
|
1235
|
+
const pk = $ToString(key);
|
|
1236
|
+
if (obj == null) return;
|
|
1237
|
+
if (!isVmExtern(obj)) throw new VmError(`Expected extern, got ${display(obj)}`, void 0);
|
|
1238
|
+
obj.set(pk, value);
|
|
1239
|
+
}
|
|
1240
|
+
function $Iterable(value) {
|
|
1241
|
+
$AssertInit(value);
|
|
1242
|
+
if (isVmWrapper(value)) return value.keys();
|
|
1243
|
+
if (isVmArray(value)) return value;
|
|
1244
|
+
if (value != null && typeof value == "object") return keys(value);
|
|
1245
|
+
throw new VmError(`Value is not iterable: ${display(value)}`, isVmFunction(value) ? [] : [value]);
|
|
1246
|
+
}
|
|
1247
|
+
function $RecordSpread(record) {
|
|
1248
|
+
$AssertInit(record);
|
|
1249
|
+
if (record == null || isVmRecord(record)) return record;
|
|
1250
|
+
if (isVmArray(record)) {
|
|
1251
|
+
const result = {};
|
|
1252
|
+
const len2 = record.length;
|
|
1253
|
+
for (let i = 0; i < len2; i++) {
|
|
1254
|
+
const item = record[i];
|
|
1255
|
+
result[i] = item ?? null;
|
|
1256
|
+
}
|
|
1257
|
+
return result;
|
|
1258
|
+
}
|
|
1259
|
+
if (isVmExtern(record)) {
|
|
1260
|
+
const result = create(null);
|
|
1261
|
+
for (const key of record.keys()) {
|
|
1262
|
+
const value = record.get(key) ?? null;
|
|
1263
|
+
if (isVmConst(value)) {
|
|
1264
|
+
result[key] = value;
|
|
1265
|
+
}
|
|
1266
|
+
}
|
|
1267
|
+
return result;
|
|
1268
|
+
}
|
|
1269
|
+
throw new VmError(`Expected record, array, extern or nil, got ${display(record)}`, null);
|
|
1270
|
+
}
|
|
1271
|
+
function $ArraySpread(array) {
|
|
1272
|
+
$AssertInit(array);
|
|
1273
|
+
if (array == null) return [];
|
|
1274
|
+
if (isVmArray(array)) return array;
|
|
1275
|
+
if (isVmExtern(array)) {
|
|
1276
|
+
if (array.isArrayLike()) {
|
|
1277
|
+
const result = [];
|
|
1278
|
+
for (let i = 0, len2 = array.value.length; i < len2; i++) {
|
|
1279
|
+
const item = array.value[i];
|
|
1280
|
+
result.push(wrapToVmConst(item, (v) => array.assumeVmValue(v, i)));
|
|
1281
|
+
}
|
|
1282
|
+
return result;
|
|
1283
|
+
} else if (typeof array.value[Symbol.iterator] == "function") {
|
|
1284
|
+
const result = [];
|
|
1285
|
+
for (const item of array.value) {
|
|
1286
|
+
result.push(wrapToVmConst(item, (v) => array.assumeVmValue(v, Symbol.iterator)));
|
|
1287
|
+
}
|
|
1288
|
+
return result;
|
|
1289
|
+
}
|
|
1290
|
+
}
|
|
1291
|
+
throw new VmError(`Expected array, iterable extern or nil, got ${display(array)}`, []);
|
|
1292
|
+
}
|
|
1293
|
+
|
|
1294
|
+
// src/compiler/create-script.ts
|
|
1295
|
+
function wrapScript(source, mode, script) {
|
|
1296
|
+
if (kVmScript in script) {
|
|
1297
|
+
return script;
|
|
1298
|
+
}
|
|
1299
|
+
defineProperty(script, "name", { value: VM_SCRIPT_NAME });
|
|
1300
|
+
defineProperty(script, kVmScript, { value: mode });
|
|
1301
|
+
if (typeof source === "string") {
|
|
1302
|
+
defineProperty(script, "source", { value: source });
|
|
1303
|
+
} else if (source instanceof Uint8Array) {
|
|
1304
|
+
defineProperty(script, "source", { value: "<buffer>" });
|
|
1305
|
+
}
|
|
1306
|
+
return script;
|
|
1307
|
+
}
|
|
1308
|
+
var [keys2, values2] = (() => {
|
|
1309
|
+
const keys4 = [];
|
|
1310
|
+
const values4 = [];
|
|
1311
|
+
for (const [key, value] of entries(operations_exports)) {
|
|
1312
|
+
keys4.push(key);
|
|
1313
|
+
values4.push(value);
|
|
1314
|
+
}
|
|
1315
|
+
return [keys4.join(","), values4];
|
|
1316
|
+
})();
|
|
1317
|
+
function createScript(source, mode, code) {
|
|
1318
|
+
let script;
|
|
1319
|
+
try {
|
|
1320
|
+
script = new Function(keys2, `'use strict';
|
|
1321
|
+
return ${code}`)(...values2);
|
|
1322
|
+
} catch (error) {
|
|
1323
|
+
throw new Error(`Failed to create script`, { cause: error });
|
|
1324
|
+
}
|
|
1325
|
+
return wrapScript(source, mode, script);
|
|
1326
|
+
}
|
|
1327
|
+
|
|
1328
|
+
// src/compiler/emit-script.ts
|
|
1329
|
+
function reportDiagnostic(source, diagnostics, fileName) {
|
|
1330
|
+
const parsed = parseDiagnostics(source, diagnostics);
|
|
1331
|
+
const messages = formatDiagnostics(parsed.errors, source, fileName);
|
|
1332
|
+
throw new Error(`Failed to compile:
|
|
1333
|
+
${messages.join("\n")}`);
|
|
1334
|
+
}
|
|
1335
|
+
function emitScript(source, [code, diagnostics], options) {
|
|
1336
|
+
if (!code) {
|
|
1337
|
+
reportDiagnostic(source, diagnostics, options.fileName);
|
|
1338
|
+
}
|
|
1339
|
+
const sourcemaps = options.sourceMap ? parseDiagnostics(source, diagnostics, (c) => c === DiagnosticCode.SourceMap).sourcemaps : [];
|
|
1340
|
+
const target = emit(source, code, sourcemaps, options);
|
|
1341
|
+
return createScript(source, options.input_mode ?? "Script", target);
|
|
1342
|
+
}
|
|
1343
|
+
|
|
1344
|
+
// src/vm/lib/global/index.ts
|
|
1345
|
+
var global_exports = {};
|
|
1346
|
+
__export(global_exports, {
|
|
1347
|
+
E: () => E,
|
|
1348
|
+
LN10: () => LN10,
|
|
1349
|
+
LN2: () => LN2,
|
|
1350
|
+
LOG10E: () => LOG10E,
|
|
1351
|
+
LOG2E: () => LOG2E,
|
|
1352
|
+
PI: () => PI,
|
|
1353
|
+
SQRT1_2: () => SQRT1_2,
|
|
1354
|
+
SQRT2: () => SQRT2,
|
|
1355
|
+
abs: () => abs2,
|
|
1356
|
+
acos: () => acos,
|
|
1357
|
+
acosh: () => acosh,
|
|
1358
|
+
all: () => all,
|
|
1359
|
+
any: () => any,
|
|
1360
|
+
asin: () => asin,
|
|
1361
|
+
asinh: () => asinh,
|
|
1362
|
+
atan: () => atan,
|
|
1363
|
+
atan2: () => atan2,
|
|
1364
|
+
atanh: () => atanh,
|
|
1365
|
+
b_and: () => b_and,
|
|
1366
|
+
b_not: () => b_not,
|
|
1367
|
+
b_or: () => b_or,
|
|
1368
|
+
b_xor: () => b_xor,
|
|
1369
|
+
cbrt: () => cbrt,
|
|
1370
|
+
ceil: () => ceil2,
|
|
1371
|
+
chars: () => chars,
|
|
1372
|
+
contains: () => contains,
|
|
1373
|
+
cos: () => cos,
|
|
1374
|
+
cosh: () => cosh,
|
|
1375
|
+
debug_print: () => debug_print,
|
|
1376
|
+
e: () => e,
|
|
1377
|
+
ends_with: () => ends_with,
|
|
1378
|
+
entries: () => entries2,
|
|
1379
|
+
exp: () => exp,
|
|
1380
|
+
expm1: () => expm1,
|
|
1381
|
+
factorial: () => factorial,
|
|
1382
|
+
filter: () => filter,
|
|
1383
|
+
filter_map: () => filter_map,
|
|
1384
|
+
find: () => find,
|
|
1385
|
+
flatten: () => flatten,
|
|
1386
|
+
floor: () => floor,
|
|
1387
|
+
format: () => format,
|
|
1388
|
+
from_json: () => from_json,
|
|
1389
|
+
gamma: () => gamma,
|
|
1390
|
+
hypot: () => hypot,
|
|
1391
|
+
join: () => join,
|
|
1392
|
+
keys: () => keys3,
|
|
1393
|
+
len: () => len,
|
|
1394
|
+
log: () => log,
|
|
1395
|
+
log10: () => log10,
|
|
1396
|
+
log1p: () => log1p,
|
|
1397
|
+
log2: () => log2,
|
|
1398
|
+
map: () => map2,
|
|
1399
|
+
max: () => max,
|
|
1400
|
+
min: () => min2,
|
|
1401
|
+
new_array: () => new_array,
|
|
1402
|
+
new_record: () => new_record,
|
|
1403
|
+
panic: () => panic,
|
|
1404
|
+
pi: () => pi,
|
|
1405
|
+
pow: () => pow2,
|
|
1406
|
+
product: () => product,
|
|
1407
|
+
random: () => random,
|
|
1408
|
+
repeat: () => repeat,
|
|
1409
|
+
replace: () => replace,
|
|
1410
|
+
reverse: () => reverse,
|
|
1411
|
+
round: () => round,
|
|
1412
|
+
sar: () => sar,
|
|
1413
|
+
shl: () => shl,
|
|
1414
|
+
shr: () => shr,
|
|
1415
|
+
sign: () => sign,
|
|
1416
|
+
sin: () => sin,
|
|
1417
|
+
sinh: () => sinh,
|
|
1418
|
+
sort: () => sort,
|
|
1419
|
+
sort_by: () => sort_by,
|
|
1420
|
+
split: () => split,
|
|
1421
|
+
sqrt: () => sqrt,
|
|
1422
|
+
starts_with: () => starts_with,
|
|
1423
|
+
sum: () => sum,
|
|
1424
|
+
tan: () => tan,
|
|
1425
|
+
tanh: () => tanh,
|
|
1426
|
+
to_datetime: () => to_datetime,
|
|
1427
|
+
to_iso8601: () => to_iso8601,
|
|
1428
|
+
to_json: () => to_json,
|
|
1429
|
+
to_lowercase: () => to_lowercase,
|
|
1430
|
+
to_number: () => to_number,
|
|
1431
|
+
to_string: () => to_string,
|
|
1432
|
+
to_timestamp: () => to_timestamp,
|
|
1433
|
+
to_uppercase: () => to_uppercase,
|
|
1434
|
+
trim: () => trim,
|
|
1435
|
+
trim_end: () => trim_end,
|
|
1436
|
+
trim_start: () => trim_start,
|
|
1437
|
+
trunc: () => trunc2,
|
|
1438
|
+
unique: () => unique,
|
|
1439
|
+
unique_by: () => unique_by,
|
|
1440
|
+
values: () => values3,
|
|
1441
|
+
with: () => _with,
|
|
1442
|
+
zip: () => zip
|
|
1443
|
+
});
|
|
1444
|
+
|
|
1445
|
+
// src/vm/lib/helpers.ts
|
|
1446
|
+
function throwError(message, recovered) {
|
|
1447
|
+
const recoveredValue = typeof recovered === "function" && !isVmFunction(recovered) ? recovered() : recovered;
|
|
1448
|
+
throw new VmError(message, recoveredValue);
|
|
1449
|
+
}
|
|
1450
|
+
function describeParam(name) {
|
|
1451
|
+
if (name == null) return "Value";
|
|
1452
|
+
if (typeof name == "string") {
|
|
1453
|
+
if (!name) return "Argument";
|
|
1454
|
+
return `Argument '${name}'`;
|
|
1455
|
+
}
|
|
1456
|
+
const pos = name <= 0 ? "first" : name <= 1 ? "second" : `${name + 1}th`;
|
|
1457
|
+
return `Argument at the ${pos} position`;
|
|
1458
|
+
}
|
|
1459
|
+
function throwUnexpectedTypeError(name, expected, value, recovered) {
|
|
1460
|
+
throwError(`${describeParam(name)} is not ${expected}: ${display(value)}`, recovered);
|
|
1461
|
+
}
|
|
1462
|
+
function throwUnconvertedTypeError(name, expected, value, recovered) {
|
|
1463
|
+
throwError(`${describeParam(name)} cannot be converted to ${expected}: ${display(value)}`, recovered);
|
|
1464
|
+
}
|
|
1465
|
+
function rethrowError(prefix, error, recovered) {
|
|
1466
|
+
const recoveredValue = typeof recovered === "function" && !isVmFunction(recovered) ? recovered() : recovered;
|
|
1467
|
+
throw VmError.from(prefix, error, recoveredValue);
|
|
1468
|
+
}
|
|
1469
|
+
function required(name, value, recovered) {
|
|
1470
|
+
if (value === void 0) {
|
|
1471
|
+
throwError(`${describeParam(name)} is required`, recovered);
|
|
1472
|
+
}
|
|
1473
|
+
}
|
|
1474
|
+
function expectNumber(name, value) {
|
|
1475
|
+
required(name, value, NotNumber);
|
|
1476
|
+
const v = toNumber(value, null);
|
|
1477
|
+
if (v == null) {
|
|
1478
|
+
throwUnconvertedTypeError(name, "number", value, NotNumber);
|
|
1479
|
+
}
|
|
1480
|
+
return v;
|
|
1481
|
+
}
|
|
1482
|
+
function expectNumberRange(name, value, min3, max2) {
|
|
1483
|
+
const v = expectNumber(name, value);
|
|
1484
|
+
if (!isFinite(v)) {
|
|
1485
|
+
throwError(`${describeParam(name)} is not a finite number: ${display(value)}`, NotNumber);
|
|
1486
|
+
}
|
|
1487
|
+
if (v < min3) {
|
|
1488
|
+
throwError(`${describeParam(name)} is less than minimum value ${min3}: ${display(value)}`, min3);
|
|
1489
|
+
}
|
|
1490
|
+
if (v > max2) {
|
|
1491
|
+
throwError(`${describeParam(name)} is greater than maximum value ${max2}: ${display(value)}`, max2);
|
|
1492
|
+
}
|
|
1493
|
+
return v;
|
|
1494
|
+
}
|
|
1495
|
+
function expectIntegerRange(name, value, min3, max2) {
|
|
1496
|
+
const i = expectInteger(name, value);
|
|
1497
|
+
if (i < min3) {
|
|
1498
|
+
throwError(`${describeParam(name)} is less than minimum value ${min3}: ${display(value)}`, min3);
|
|
1499
|
+
}
|
|
1500
|
+
if (i > max2) {
|
|
1501
|
+
throwError(`${describeParam(name)} is greater than maximum value ${max2}: ${display(value)}`, max2);
|
|
1502
|
+
}
|
|
1503
|
+
return i;
|
|
1504
|
+
}
|
|
1505
|
+
function expectInteger(name, value) {
|
|
1506
|
+
required(name, value, 0);
|
|
1507
|
+
const v = toNumber(value, null);
|
|
1508
|
+
if (v == null) {
|
|
1509
|
+
throwUnconvertedTypeError(name, "integer", value, 0);
|
|
1510
|
+
}
|
|
1511
|
+
const i = Math.trunc(v);
|
|
1512
|
+
if (!isSafeInteger(i)) {
|
|
1513
|
+
throwUnconvertedTypeError(name, "integer", value, 0);
|
|
1514
|
+
}
|
|
1515
|
+
return i;
|
|
1516
|
+
}
|
|
1517
|
+
function expectString(name, value) {
|
|
1518
|
+
required(name, value, "");
|
|
1519
|
+
const v = toString(value, null);
|
|
1520
|
+
if (v == null) {
|
|
1521
|
+
throwUnconvertedTypeError(name, "string", value, "");
|
|
1522
|
+
}
|
|
1523
|
+
return v;
|
|
1524
|
+
}
|
|
1525
|
+
function expectArray(name, value, recovered) {
|
|
1526
|
+
required(name, value, recovered);
|
|
1527
|
+
if (!isVmArray(value)) {
|
|
1528
|
+
throwUnexpectedTypeError(name, "array", value, recovered);
|
|
1529
|
+
}
|
|
1530
|
+
}
|
|
1531
|
+
function expectArrayOrRecord(name, value, recovered) {
|
|
1532
|
+
required(name, value, recovered);
|
|
1533
|
+
if (!isVmArray(value) && !isVmRecord(value)) {
|
|
1534
|
+
throwUnexpectedTypeError(name, "array | record", value, recovered);
|
|
1535
|
+
}
|
|
1536
|
+
}
|
|
1537
|
+
function expectCompound(name, value, recovered) {
|
|
1538
|
+
required(name, value, recovered);
|
|
1539
|
+
if (isVmPrimitive(value) || isVmFunction(value)) {
|
|
1540
|
+
throwUnexpectedTypeError(name, "array | record | module | extern", value, recovered);
|
|
1541
|
+
}
|
|
1542
|
+
}
|
|
1543
|
+
function expectConst(name, value, recovered) {
|
|
1544
|
+
required(name, value, recovered);
|
|
1545
|
+
if (!isVmConst(value)) {
|
|
1546
|
+
throwUnexpectedTypeError(name, "nil | number | boolean | string | array | record", value, recovered);
|
|
1547
|
+
}
|
|
1548
|
+
}
|
|
1549
|
+
function expectCallable(name, value, recovered) {
|
|
1550
|
+
required(name, value, recovered);
|
|
1551
|
+
if (!isVmCallable(value)) {
|
|
1552
|
+
throwUnexpectedTypeError(name, "callable", value, recovered);
|
|
1553
|
+
}
|
|
1554
|
+
}
|
|
1555
|
+
function getNumbers(args) {
|
|
1556
|
+
if (args.length === 0) return [];
|
|
1557
|
+
let useFirst = false;
|
|
1558
|
+
if (args.length === 1 && isVmArray(args[0])) {
|
|
1559
|
+
args = args[0];
|
|
1560
|
+
useFirst = true;
|
|
1561
|
+
}
|
|
1562
|
+
const numbers = [];
|
|
1563
|
+
for (let len2 = args.length, i = 0; i < len2; i++) {
|
|
1564
|
+
numbers.push(expectNumber(useFirst ? null : i, args[i]));
|
|
1565
|
+
}
|
|
1566
|
+
return numbers;
|
|
1567
|
+
}
|
|
1568
|
+
function arrayLen(len2) {
|
|
1569
|
+
if (len2 == null || isNaN(len2) || len2 <= -1) {
|
|
1570
|
+
throwError("Array length must be a non-negative integer", null);
|
|
1571
|
+
}
|
|
1572
|
+
len2 = Math.trunc(len2);
|
|
1573
|
+
if (len2 > VM_ARRAY_MAX_LENGTH) {
|
|
1574
|
+
throwError(`Array length exceeds maximum limit of ${VM_ARRAY_MAX_LENGTH}`, null);
|
|
1575
|
+
}
|
|
1576
|
+
return len2;
|
|
1577
|
+
}
|
|
1578
|
+
function map(data, mapper) {
|
|
1579
|
+
if (isVmPrimitive(data)) {
|
|
1580
|
+
return mapper(data, null, data) ?? null;
|
|
1581
|
+
}
|
|
1582
|
+
if (isVmArray(data)) {
|
|
1583
|
+
const result = [];
|
|
1584
|
+
const { length } = data;
|
|
1585
|
+
for (let i = 0; i < length; i++) {
|
|
1586
|
+
Cp();
|
|
1587
|
+
const ret = mapper(data[i] ?? null, i, data);
|
|
1588
|
+
if (ret === void 0) continue;
|
|
1589
|
+
result.push(ret);
|
|
1590
|
+
}
|
|
1591
|
+
return result;
|
|
1592
|
+
} else {
|
|
1593
|
+
const e2 = [];
|
|
1594
|
+
for (const [key, value] of entries(data)) {
|
|
1595
|
+
Cp();
|
|
1596
|
+
const ret = mapper(value ?? null, key, data);
|
|
1597
|
+
if (ret === void 0) continue;
|
|
1598
|
+
e2.push([key, ret]);
|
|
1599
|
+
}
|
|
1600
|
+
return fromEntries(e2);
|
|
1601
|
+
}
|
|
1602
|
+
}
|
|
1603
|
+
function VmLib(value, option, properties) {
|
|
1604
|
+
if (isVmFunction(value)) throw new TypeError("Cannot create VmLib from a VmFunction");
|
|
1605
|
+
const ret = typeof value == "function" ? value : { __proto__: null, value };
|
|
1606
|
+
Object.defineProperties(ret, {
|
|
1607
|
+
summary: { enumerable: true, value: option.summary },
|
|
1608
|
+
params: { enumerable: true, value: option.params },
|
|
1609
|
+
paramsType: { enumerable: true, value: option.paramsType },
|
|
1610
|
+
returns: { enumerable: true, value: option.returns },
|
|
1611
|
+
returnsType: { enumerable: true, value: option.returnsType },
|
|
1612
|
+
examples: { enumerable: true, value: option.examples },
|
|
1613
|
+
deprecated: { enumerable: true, value: option.deprecated ?? void 0 }
|
|
1614
|
+
});
|
|
1615
|
+
Object.assign(ret, properties);
|
|
1616
|
+
return ret;
|
|
1617
|
+
}
|
|
1618
|
+
|
|
1619
|
+
// src/vm/lib/global/math/arr.ts
|
|
1620
|
+
function build(f) {
|
|
1621
|
+
return (...values4) => {
|
|
1622
|
+
const numbers = getNumbers(values4);
|
|
1623
|
+
return f(...numbers);
|
|
1624
|
+
};
|
|
1625
|
+
}
|
|
1626
|
+
var max = VmLib(build(Math.max), {
|
|
1627
|
+
summary: "返回一组数中的最大值",
|
|
1628
|
+
params: { "..values": "要比较的数值" },
|
|
1629
|
+
paramsType: { "..values": "number[]" },
|
|
1630
|
+
returnsType: "number",
|
|
1631
|
+
examples: ["max(3, 7, 2) // 7"]
|
|
1632
|
+
});
|
|
1633
|
+
var min2 = VmLib(build(Math.min), {
|
|
1634
|
+
summary: "返回一组数中的最小值",
|
|
1635
|
+
params: { "..values": "要比较的数值" },
|
|
1636
|
+
paramsType: { "..values": "number[]" },
|
|
1637
|
+
returnsType: "number",
|
|
1638
|
+
examples: ["min(3, 7, 2) // 2"]
|
|
1639
|
+
});
|
|
1640
|
+
var hypot = VmLib(build(Math.hypot), {
|
|
1641
|
+
summary: "返回所有参数平方和的平方根",
|
|
1642
|
+
params: { "..values": "要计算的数值" },
|
|
1643
|
+
paramsType: { "..values": "number[]" },
|
|
1644
|
+
returnsType: "number",
|
|
1645
|
+
examples: ["hypot(3, 4) // 5"]
|
|
1646
|
+
});
|
|
1647
|
+
var sum = VmLib(
|
|
1648
|
+
(...values4) => {
|
|
1649
|
+
const numbers = getNumbers(values4);
|
|
1650
|
+
return numbers.reduce((a, b) => a + b, -0);
|
|
1651
|
+
},
|
|
1652
|
+
{
|
|
1653
|
+
summary: "返回一组数的总和",
|
|
1654
|
+
params: { "..values": "要计算的数值" },
|
|
1655
|
+
paramsType: { "..values": "number[]" },
|
|
1656
|
+
returnsType: "number",
|
|
1657
|
+
examples: ["sum(1, 2, 3, 4) // 10"]
|
|
1658
|
+
}
|
|
1659
|
+
);
|
|
1660
|
+
var product = VmLib(
|
|
1661
|
+
(...values4) => {
|
|
1662
|
+
const numbers = getNumbers(values4);
|
|
1663
|
+
return numbers.reduce((a, b) => a * b, 1);
|
|
1664
|
+
},
|
|
1665
|
+
{
|
|
1666
|
+
summary: "返回一组数的乘积",
|
|
1667
|
+
params: { "..values": "要计算的数值" },
|
|
1668
|
+
paramsType: { "..values": "number[]" },
|
|
1669
|
+
returnsType: "number",
|
|
1670
|
+
examples: ["product(2, 3, 4) // 24"]
|
|
1671
|
+
}
|
|
1672
|
+
);
|
|
1673
|
+
|
|
1674
|
+
// src/vm/lib/global/math/const.ts
|
|
1675
|
+
import { DiagnosticCode as DiagnosticCode2 } from "@mirascript/constants";
|
|
1676
|
+
var PI = VmLib(Math.PI, {
|
|
1677
|
+
summary: "圆周率",
|
|
1678
|
+
returnsType: "number"
|
|
1679
|
+
});
|
|
1680
|
+
var E = VmLib(Math.E, {
|
|
1681
|
+
summary: "自然对数的底数",
|
|
1682
|
+
returnsType: "number"
|
|
1683
|
+
});
|
|
1684
|
+
var pi = VmLib(Math.PI, {
|
|
1685
|
+
summary: "圆周率",
|
|
1686
|
+
returnsType: "number",
|
|
1687
|
+
deprecated: {
|
|
1688
|
+
use: "PI",
|
|
1689
|
+
message: DiagnosticCode2.PreferUppercaseConstant
|
|
1690
|
+
}
|
|
1691
|
+
});
|
|
1692
|
+
var e = VmLib(Math.E, {
|
|
1693
|
+
summary: "自然对数的底数",
|
|
1694
|
+
returnsType: "number",
|
|
1695
|
+
deprecated: {
|
|
1696
|
+
use: "E",
|
|
1697
|
+
message: DiagnosticCode2.PreferUppercaseConstant
|
|
1698
|
+
}
|
|
1699
|
+
});
|
|
1700
|
+
var SQRT1_2 = VmLib(Math.SQRT1_2, {
|
|
1701
|
+
summary: "½ 的平方根",
|
|
1702
|
+
returnsType: "number"
|
|
1703
|
+
});
|
|
1704
|
+
var SQRT2 = VmLib(Math.SQRT2, {
|
|
1705
|
+
summary: "2 的平方根",
|
|
1706
|
+
returnsType: "number"
|
|
1707
|
+
});
|
|
1708
|
+
var LN2 = VmLib(Math.LN2, {
|
|
1709
|
+
summary: "2 的自然对数",
|
|
1710
|
+
returnsType: "number"
|
|
1711
|
+
});
|
|
1712
|
+
var LN10 = VmLib(Math.LN10, {
|
|
1713
|
+
summary: "10 的自然对数",
|
|
1714
|
+
returnsType: "number"
|
|
1715
|
+
});
|
|
1716
|
+
var LOG2E = VmLib(Math.LOG2E, {
|
|
1717
|
+
summary: "e 以 2 为底的对数",
|
|
1718
|
+
returnsType: "number"
|
|
1719
|
+
});
|
|
1720
|
+
var LOG10E = VmLib(Math.LOG10E, {
|
|
1721
|
+
summary: "e 以 10 为底的对数",
|
|
1722
|
+
returnsType: "number"
|
|
1723
|
+
});
|
|
1724
|
+
|
|
1725
|
+
// src/vm/lib/global/math/unary.ts
|
|
1726
|
+
function build2(f) {
|
|
1727
|
+
return (x) => {
|
|
1728
|
+
return f(expectNumber("x", x));
|
|
1729
|
+
};
|
|
1730
|
+
}
|
|
1731
|
+
var sign = VmLib(build2(Math.sign), {
|
|
1732
|
+
summary: "返回数值的符号(正数为 1,负数为 -1,零为 0)",
|
|
1733
|
+
params: { x: "要判断符号的数" },
|
|
1734
|
+
paramsType: { x: "number" },
|
|
1735
|
+
returnsType: "number"
|
|
1736
|
+
});
|
|
1737
|
+
var abs2 = VmLib(build2(Math.abs), {
|
|
1738
|
+
summary: "返回数值的绝对值",
|
|
1739
|
+
params: { x: "要取绝对值的数" },
|
|
1740
|
+
paramsType: { x: "number" },
|
|
1741
|
+
returnsType: "number"
|
|
1742
|
+
});
|
|
1743
|
+
var acos = VmLib(build2(Math.acos), {
|
|
1744
|
+
summary: "返回数值的反余弦值(弧度)",
|
|
1745
|
+
params: { x: "要计算反余弦的数" },
|
|
1746
|
+
paramsType: { x: "number" },
|
|
1747
|
+
returnsType: "number"
|
|
1748
|
+
});
|
|
1749
|
+
var acosh = VmLib(build2(Math.acosh), {
|
|
1750
|
+
summary: "返回数值的反双曲余弦值",
|
|
1751
|
+
params: { x: "要计算反双曲余弦的数" },
|
|
1752
|
+
paramsType: { x: "number" },
|
|
1753
|
+
returnsType: "number"
|
|
1754
|
+
});
|
|
1755
|
+
var asin = VmLib(build2(Math.asin), {
|
|
1756
|
+
summary: "返回数值的反正弦值(弧度)",
|
|
1757
|
+
params: { x: "要计算反正弦的数" },
|
|
1758
|
+
paramsType: { x: "number" },
|
|
1759
|
+
returnsType: "number"
|
|
1760
|
+
});
|
|
1761
|
+
var asinh = VmLib(build2(Math.asinh), {
|
|
1762
|
+
summary: "返回数值的反双曲正弦值",
|
|
1763
|
+
params: { x: "要计算反双曲正弦的数" },
|
|
1764
|
+
paramsType: { x: "number" },
|
|
1765
|
+
returnsType: "number"
|
|
1766
|
+
});
|
|
1767
|
+
var atan = VmLib(build2(Math.atan), {
|
|
1768
|
+
summary: "返回数值的反正切值(弧度)",
|
|
1769
|
+
params: { x: "要计算反正切的数" },
|
|
1770
|
+
paramsType: { x: "number" },
|
|
1771
|
+
returnsType: "number"
|
|
1772
|
+
});
|
|
1773
|
+
var atanh = VmLib(build2(Math.atanh), {
|
|
1774
|
+
summary: "返回数值的反双曲正切值",
|
|
1775
|
+
params: { x: "要计算反双曲正切的数" },
|
|
1776
|
+
paramsType: { x: "number" },
|
|
1777
|
+
returnsType: "number"
|
|
1778
|
+
});
|
|
1779
|
+
var cos = VmLib(build2(Math.cos), {
|
|
1780
|
+
summary: "返回数值的余弦值",
|
|
1781
|
+
params: { x: "要计算余弦的数(弧度)" },
|
|
1782
|
+
paramsType: { x: "number" },
|
|
1783
|
+
returnsType: "number"
|
|
1784
|
+
});
|
|
1785
|
+
var cosh = VmLib(build2(Math.cosh), {
|
|
1786
|
+
summary: "返回数值的双曲余弦值",
|
|
1787
|
+
params: { x: "要计算双曲余弦的数" },
|
|
1788
|
+
paramsType: { x: "number" },
|
|
1789
|
+
returnsType: "number"
|
|
1790
|
+
});
|
|
1791
|
+
var sin = VmLib(build2(Math.sin), {
|
|
1792
|
+
summary: "返回数值的正弦值",
|
|
1793
|
+
params: { x: "要计算正弦的数(弧度)" },
|
|
1794
|
+
paramsType: { x: "number" },
|
|
1795
|
+
returnsType: "number"
|
|
1796
|
+
});
|
|
1797
|
+
var sinh = VmLib(build2(Math.sinh), {
|
|
1798
|
+
summary: "返回数值的双曲正弦值",
|
|
1799
|
+
params: { x: "要计算双曲正弦的数" },
|
|
1800
|
+
paramsType: { x: "number" },
|
|
1801
|
+
returnsType: "number"
|
|
1802
|
+
});
|
|
1803
|
+
var tan = VmLib(build2(Math.tan), {
|
|
1804
|
+
summary: "返回数值的正切值",
|
|
1805
|
+
params: { x: "要计算正切的数(弧度)" },
|
|
1806
|
+
paramsType: { x: "number" },
|
|
1807
|
+
returnsType: "number"
|
|
1808
|
+
});
|
|
1809
|
+
var tanh = VmLib(build2(Math.tanh), {
|
|
1810
|
+
summary: "返回数值的双曲正切值",
|
|
1811
|
+
params: { x: "要计算双曲正切的数" },
|
|
1812
|
+
paramsType: { x: "number" },
|
|
1813
|
+
returnsType: "number"
|
|
1814
|
+
});
|
|
1815
|
+
var exp = VmLib(build2(Math.exp), {
|
|
1816
|
+
summary: "返回 e 的指定次幂",
|
|
1817
|
+
params: { x: "指数" },
|
|
1818
|
+
paramsType: { x: "number" },
|
|
1819
|
+
returnsType: "number"
|
|
1820
|
+
});
|
|
1821
|
+
var expm1 = VmLib(build2(Math.expm1), {
|
|
1822
|
+
summary: "返回 e 的 x 次幂减 1",
|
|
1823
|
+
params: { x: "指数" },
|
|
1824
|
+
paramsType: { x: "number" },
|
|
1825
|
+
returnsType: "number"
|
|
1826
|
+
});
|
|
1827
|
+
var log = VmLib(build2(Math.log), {
|
|
1828
|
+
summary: "返回数值的自然对数(以 e 为底)",
|
|
1829
|
+
params: { x: "要取对数的数" },
|
|
1830
|
+
paramsType: { x: "number" },
|
|
1831
|
+
returnsType: "number"
|
|
1832
|
+
});
|
|
1833
|
+
var log10 = VmLib(build2(Math.log10), {
|
|
1834
|
+
summary: "返回数值的以 10 为底的对数",
|
|
1835
|
+
params: { x: "要取对数的数" },
|
|
1836
|
+
paramsType: { x: "number" },
|
|
1837
|
+
returnsType: "number"
|
|
1838
|
+
});
|
|
1839
|
+
var log1p = VmLib(build2(Math.log1p), {
|
|
1840
|
+
summary: "返回 1 加上数值的自然对数",
|
|
1841
|
+
params: { x: "要取对数的数" },
|
|
1842
|
+
paramsType: { x: "number" },
|
|
1843
|
+
returnsType: "number"
|
|
1844
|
+
});
|
|
1845
|
+
var log2 = VmLib(build2(Math.log2), {
|
|
1846
|
+
summary: "返回数值的以 2 为底的对数",
|
|
1847
|
+
params: { x: "要取对数的数" },
|
|
1848
|
+
paramsType: { x: "number" },
|
|
1849
|
+
returnsType: "number"
|
|
1850
|
+
});
|
|
1851
|
+
var sqrt = VmLib(build2(Math.sqrt), {
|
|
1852
|
+
summary: "返回数值的平方根",
|
|
1853
|
+
params: { x: "要开平方的数" },
|
|
1854
|
+
paramsType: { x: "number" },
|
|
1855
|
+
returnsType: "number"
|
|
1856
|
+
});
|
|
1857
|
+
var cbrt = VmLib(build2(Math.cbrt), {
|
|
1858
|
+
summary: "返回数值的立方根",
|
|
1859
|
+
params: { x: "要计算立方根的数" },
|
|
1860
|
+
paramsType: { x: "number" },
|
|
1861
|
+
returnsType: "number"
|
|
1862
|
+
});
|
|
1863
|
+
|
|
1864
|
+
// src/vm/lib/global/math/round.ts
|
|
1865
|
+
function build3(f) {
|
|
1866
|
+
return (x, n) => {
|
|
1867
|
+
const xn = expectNumber("x", x);
|
|
1868
|
+
const nn = n != null ? expectIntegerRange("n", n, 0, 15) : 0;
|
|
1869
|
+
if (!nn) return f(xn);
|
|
1870
|
+
const factor = 10 ** nn;
|
|
1871
|
+
return f(xn * factor) / factor;
|
|
1872
|
+
};
|
|
1873
|
+
}
|
|
1874
|
+
var trunc2 = VmLib(build3(Math.trunc), {
|
|
1875
|
+
summary: "向零方向舍入数值",
|
|
1876
|
+
params: { x: "要舍入的数", n: "小数位数,默认为 0" },
|
|
1877
|
+
paramsType: { x: "number", n: "number | nil" },
|
|
1878
|
+
returnsType: "number"
|
|
1879
|
+
});
|
|
1880
|
+
var floor = VmLib(build3(Math.floor), {
|
|
1881
|
+
summary: "向下舍入数值",
|
|
1882
|
+
params: { x: "要舍入的数", n: "小数位数,默认为 0" },
|
|
1883
|
+
paramsType: { x: "number", n: "number | nil" },
|
|
1884
|
+
returnsType: "number"
|
|
1885
|
+
});
|
|
1886
|
+
var ceil2 = VmLib(build3(Math.ceil), {
|
|
1887
|
+
summary: "向上舍入数值",
|
|
1888
|
+
params: { x: "要舍入的数", n: "小数位数,默认为 0" },
|
|
1889
|
+
paramsType: { x: "number", n: "number | nil" },
|
|
1890
|
+
returnsType: "number"
|
|
1891
|
+
});
|
|
1892
|
+
var _round = Math.round;
|
|
1893
|
+
var _abs = Math.abs;
|
|
1894
|
+
var round = VmLib(
|
|
1895
|
+
build3((x) => {
|
|
1896
|
+
let rounded = _round(x);
|
|
1897
|
+
if (_abs(x - rounded) === 0.5) {
|
|
1898
|
+
rounded = 2 * _round(x / 2);
|
|
1899
|
+
}
|
|
1900
|
+
return rounded;
|
|
1901
|
+
}),
|
|
1902
|
+
{
|
|
1903
|
+
summary: "四舍五入数值",
|
|
1904
|
+
params: { x: "要舍入的数", n: "小数位数,默认为 0" },
|
|
1905
|
+
paramsType: { x: "number", n: "number" },
|
|
1906
|
+
returnsType: "number"
|
|
1907
|
+
}
|
|
1908
|
+
);
|
|
1909
|
+
|
|
1910
|
+
// src/vm/lib/global/math/gamma.ts
|
|
1911
|
+
var { PI: PI2, exp: exp2, floor: floor2, cos: cos2, sin: sin2, pow, trunc: trunc3 } = Math;
|
|
1912
|
+
var MEM = new DataView(new ArrayBuffer(8));
|
|
1913
|
+
function f64ToBits(value) {
|
|
1914
|
+
MEM.setFloat64(0, value, false);
|
|
1915
|
+
return MEM.getBigUint64(0, false);
|
|
1916
|
+
}
|
|
1917
|
+
function f64FromBits(bits) {
|
|
1918
|
+
MEM.setBigUint64(0, bits, false);
|
|
1919
|
+
return MEM.getFloat64(0, false);
|
|
1920
|
+
}
|
|
1921
|
+
function sinpi(x) {
|
|
1922
|
+
x = x * 0.5;
|
|
1923
|
+
x = 2 * (x - floor2(x));
|
|
1924
|
+
let n = trunc3(4 * x);
|
|
1925
|
+
n = trunc3((n + 1) / 2);
|
|
1926
|
+
x -= n * 0.5;
|
|
1927
|
+
x *= PI2;
|
|
1928
|
+
switch (n) {
|
|
1929
|
+
case 1:
|
|
1930
|
+
return cos2(x);
|
|
1931
|
+
case 2:
|
|
1932
|
+
return sin2(-x);
|
|
1933
|
+
case 3:
|
|
1934
|
+
return -cos2(x);
|
|
1935
|
+
default:
|
|
1936
|
+
return sin2(x);
|
|
1937
|
+
}
|
|
1938
|
+
}
|
|
1939
|
+
var N = 12;
|
|
1940
|
+
var GMHALF = 5.52468004077673;
|
|
1941
|
+
var SNUM = [
|
|
1942
|
+
2353137688041076e-5,
|
|
1943
|
+
429198036426491e-4,
|
|
1944
|
+
3571195923735567e-5,
|
|
1945
|
+
1792103442603721e-5,
|
|
1946
|
+
6039542586352028e-6,
|
|
1947
|
+
14397204073117216e-7,
|
|
1948
|
+
24887455786205417e-8,
|
|
1949
|
+
31426415585400194e-9,
|
|
1950
|
+
2.8763706289353725e6,
|
|
1951
|
+
186056.26539522348,
|
|
1952
|
+
8071.672002365816,
|
|
1953
|
+
210.82427775157936,
|
|
1954
|
+
2.5066282746310002
|
|
1955
|
+
];
|
|
1956
|
+
var SDEN = [
|
|
1957
|
+
0,
|
|
1958
|
+
39916800,
|
|
1959
|
+
120543840,
|
|
1960
|
+
150917976,
|
|
1961
|
+
105258076,
|
|
1962
|
+
45995730,
|
|
1963
|
+
13339535,
|
|
1964
|
+
2637558,
|
|
1965
|
+
357423,
|
|
1966
|
+
32670,
|
|
1967
|
+
1925,
|
|
1968
|
+
66,
|
|
1969
|
+
1
|
|
1970
|
+
];
|
|
1971
|
+
function s(x) {
|
|
1972
|
+
let num2 = 0;
|
|
1973
|
+
let den = 0;
|
|
1974
|
+
if (x < 8) {
|
|
1975
|
+
for (let i = N; i >= 0; i--) {
|
|
1976
|
+
num2 = num2 * x + SNUM[i];
|
|
1977
|
+
den = den * x + SDEN[i];
|
|
1978
|
+
}
|
|
1979
|
+
} else {
|
|
1980
|
+
for (let i = 0; i <= N; i++) {
|
|
1981
|
+
num2 = num2 / x + SNUM[i];
|
|
1982
|
+
den = den / x + SDEN[i];
|
|
1983
|
+
}
|
|
1984
|
+
}
|
|
1985
|
+
return num2 / den;
|
|
1986
|
+
}
|
|
1987
|
+
function tgamma(x) {
|
|
1988
|
+
const u = f64ToBits(x);
|
|
1989
|
+
const ix = Number(u >> 32n & 0x7fffffffn);
|
|
1990
|
+
const sign2 = u >> 63n !== 0n;
|
|
1991
|
+
if (ix >= 2146435072) {
|
|
1992
|
+
return x + PositiveInfinity;
|
|
1993
|
+
}
|
|
1994
|
+
if (ix < 1023 - 54 << 20) {
|
|
1995
|
+
return 1 / x;
|
|
1996
|
+
}
|
|
1997
|
+
if (x === floor2(x)) {
|
|
1998
|
+
if (sign2) {
|
|
1999
|
+
return NotNumber;
|
|
2000
|
+
}
|
|
2001
|
+
if (x <= FACT_MAX) {
|
|
2002
|
+
return fact(trunc3(x) - 1);
|
|
2003
|
+
}
|
|
2004
|
+
}
|
|
2005
|
+
if (ix >= 1080492032) {
|
|
2006
|
+
if (sign2) {
|
|
2007
|
+
if (floor2(x) * 0.5 === floor2(x * 0.5)) {
|
|
2008
|
+
return 0;
|
|
2009
|
+
} else {
|
|
2010
|
+
return -0;
|
|
2011
|
+
}
|
|
2012
|
+
}
|
|
2013
|
+
const x1p1023 = f64FromBits(0x7fe0000000000000n);
|
|
2014
|
+
return x * x1p1023;
|
|
2015
|
+
}
|
|
2016
|
+
const absx = sign2 ? -x : x;
|
|
2017
|
+
const y = absx + GMHALF;
|
|
2018
|
+
let dy;
|
|
2019
|
+
if (absx > GMHALF) {
|
|
2020
|
+
dy = y - absx;
|
|
2021
|
+
dy -= GMHALF;
|
|
2022
|
+
} else {
|
|
2023
|
+
dy = y - GMHALF;
|
|
2024
|
+
dy -= absx;
|
|
2025
|
+
}
|
|
2026
|
+
let z = absx - 0.5;
|
|
2027
|
+
let r = s(absx) * exp2(-y);
|
|
2028
|
+
if (x < 0) {
|
|
2029
|
+
r = -PI2 / (sinpi(absx) * absx * r);
|
|
2030
|
+
dy = -dy;
|
|
2031
|
+
z = -z;
|
|
2032
|
+
}
|
|
2033
|
+
r += dy * (GMHALF + 0.5) * r / y;
|
|
2034
|
+
const zHalf = pow(y, 0.5 * z);
|
|
2035
|
+
return r * zHalf * zHalf;
|
|
2036
|
+
}
|
|
2037
|
+
var gamma = VmLib(
|
|
2038
|
+
(x) => {
|
|
2039
|
+
const n = expectNumber("x", x);
|
|
2040
|
+
return tgamma(n);
|
|
2041
|
+
},
|
|
2042
|
+
{
|
|
2043
|
+
summary: "返回 Gamma 函数的值",
|
|
2044
|
+
params: { x: "要计算 Gamma 函数的数值" },
|
|
2045
|
+
paramsType: { x: "number" },
|
|
2046
|
+
returnsType: "number",
|
|
2047
|
+
examples: ["gamma(5) // 24"]
|
|
2048
|
+
}
|
|
2049
|
+
);
|
|
2050
|
+
var FACT_MAX = 171;
|
|
2051
|
+
var FACT = [1, 1];
|
|
2052
|
+
function fact(n) {
|
|
2053
|
+
const cached = FACT[n];
|
|
2054
|
+
if (cached != null) return cached;
|
|
2055
|
+
let r = 1n;
|
|
2056
|
+
for (let i = 2; i <= n; i++) {
|
|
2057
|
+
r *= BigInt(i);
|
|
2058
|
+
FACT[i] = Number(r);
|
|
2059
|
+
}
|
|
2060
|
+
return FACT[n];
|
|
2061
|
+
}
|
|
2062
|
+
var factorial = VmLib(
|
|
2063
|
+
(x) => {
|
|
2064
|
+
const n = expectNumber("x", x);
|
|
2065
|
+
if (isNaN(n) || n < 0) return NotNumber;
|
|
2066
|
+
return tgamma(n + 1);
|
|
2067
|
+
},
|
|
2068
|
+
{
|
|
2069
|
+
summary: "返回一个数的阶乘",
|
|
2070
|
+
params: { x: "要计算阶乘的数值" },
|
|
2071
|
+
paramsType: { x: "number" },
|
|
2072
|
+
returnsType: "number",
|
|
2073
|
+
examples: ["factorial(5) // 120"]
|
|
2074
|
+
}
|
|
2075
|
+
);
|
|
2076
|
+
|
|
2077
|
+
// src/vm/lib/global/math/index.ts
|
|
2078
|
+
var { atan2: _atan2, pow: _pow, random: _random } = Math;
|
|
2079
|
+
var atan2 = VmLib((x, y) => _atan2(expectNumber(0, x), expectNumber(1, y)), {
|
|
2080
|
+
summary: "返回从原点到点 (x, y) 的角度(弧度)",
|
|
2081
|
+
params: { x: "x 坐标", y: "y 坐标" },
|
|
2082
|
+
paramsType: { x: "number", y: "number" },
|
|
2083
|
+
returnsType: "number"
|
|
2084
|
+
});
|
|
2085
|
+
var pow2 = VmLib((x, y) => _pow(expectNumber(0, x), expectNumber(1, y)), {
|
|
2086
|
+
summary: "返回 x 的 y 次幂",
|
|
2087
|
+
params: { x: "底数", y: "指数" },
|
|
2088
|
+
paramsType: { x: "number", y: "number" },
|
|
2089
|
+
returnsType: "number"
|
|
2090
|
+
});
|
|
2091
|
+
var random = VmLib(() => _random(), {
|
|
2092
|
+
summary: "返回 [0, 1) 之间的伪随机数",
|
|
2093
|
+
params: {},
|
|
2094
|
+
paramsType: {},
|
|
2095
|
+
returnsType: "number"
|
|
2096
|
+
});
|
|
2097
|
+
|
|
2098
|
+
// src/vm/lib/global/bit.ts
|
|
2099
|
+
var b_and = VmLib(
|
|
2100
|
+
(x, y) => {
|
|
2101
|
+
return expectNumber(0, x) & expectNumber(1, y);
|
|
2102
|
+
},
|
|
2103
|
+
{
|
|
2104
|
+
summary: "返回两个数的按位与",
|
|
2105
|
+
params: { x: "第一个操作数", y: "第二个操作数" },
|
|
2106
|
+
paramsType: { x: "number", y: "number" },
|
|
2107
|
+
returnsType: "number",
|
|
2108
|
+
examples: ["b_and(6, 3) // 2"]
|
|
2109
|
+
}
|
|
2110
|
+
);
|
|
2111
|
+
var b_or = VmLib(
|
|
2112
|
+
(x, y) => {
|
|
2113
|
+
return expectNumber(0, x) | expectNumber(1, y);
|
|
2114
|
+
},
|
|
2115
|
+
{
|
|
2116
|
+
summary: "返回两个数的按位或",
|
|
2117
|
+
params: { x: "第一个操作数", y: "第二个操作数" },
|
|
2118
|
+
paramsType: { x: "number", y: "number" },
|
|
2119
|
+
returnsType: "number",
|
|
2120
|
+
examples: ["b_or(5, 2) // 7"]
|
|
2121
|
+
}
|
|
2122
|
+
);
|
|
2123
|
+
var b_not = VmLib(
|
|
2124
|
+
(x) => {
|
|
2125
|
+
return ~expectNumber("x", x);
|
|
2126
|
+
},
|
|
2127
|
+
{
|
|
2128
|
+
summary: "返回一个数的按位取反",
|
|
2129
|
+
params: { x: "操作数" },
|
|
2130
|
+
paramsType: { x: "number" },
|
|
2131
|
+
returnsType: "number",
|
|
2132
|
+
examples: ["b_not(0) // -1"]
|
|
2133
|
+
}
|
|
2134
|
+
);
|
|
2135
|
+
var b_xor = VmLib(
|
|
2136
|
+
(x, y) => {
|
|
2137
|
+
return expectNumber(0, x) ^ expectNumber(1, y);
|
|
2138
|
+
},
|
|
2139
|
+
{
|
|
2140
|
+
summary: "返回两个数的按位异或",
|
|
2141
|
+
params: { x: "第一个操作数", y: "第二个操作数" },
|
|
2142
|
+
paramsType: { x: "number", y: "number" },
|
|
2143
|
+
returnsType: "number",
|
|
2144
|
+
examples: ["b_xor(5, 3) // 6"]
|
|
2145
|
+
}
|
|
2146
|
+
);
|
|
2147
|
+
var shl = VmLib(
|
|
2148
|
+
(x, y) => {
|
|
2149
|
+
return expectNumber(0, x) << expectNumber(1, y);
|
|
2150
|
+
},
|
|
2151
|
+
{
|
|
2152
|
+
summary: "返回第一个操作数左移指定的位数",
|
|
2153
|
+
params: { x: "第一个操作数", y: "位数" },
|
|
2154
|
+
paramsType: { x: "number", y: "number" },
|
|
2155
|
+
returnsType: "number",
|
|
2156
|
+
examples: ["shl(3, 2) // 12"]
|
|
2157
|
+
}
|
|
2158
|
+
);
|
|
2159
|
+
var sar = VmLib(
|
|
2160
|
+
(x, y) => {
|
|
2161
|
+
return expectNumber(0, x) >> expectNumber(1, y);
|
|
2162
|
+
},
|
|
2163
|
+
{
|
|
2164
|
+
summary: "返回第一个操作数右移指定的位数",
|
|
2165
|
+
params: { x: "第一个操作数", y: "位数" },
|
|
2166
|
+
paramsType: { x: "number", y: "number" },
|
|
2167
|
+
returnsType: "number",
|
|
2168
|
+
examples: ["sar(-8, 1) // -4"]
|
|
2169
|
+
}
|
|
2170
|
+
);
|
|
2171
|
+
var shr = VmLib(
|
|
2172
|
+
(x, y) => {
|
|
2173
|
+
return expectNumber(0, x) >>> expectNumber(1, y);
|
|
2174
|
+
},
|
|
2175
|
+
{
|
|
2176
|
+
summary: "返回第一个操作数无符号右移指定的位数",
|
|
2177
|
+
params: { x: "第一个操作数", y: "位数" },
|
|
2178
|
+
paramsType: { x: "number", y: "number" },
|
|
2179
|
+
returnsType: "number",
|
|
2180
|
+
examples: ["shr(8, 1) // 4"]
|
|
2181
|
+
}
|
|
2182
|
+
);
|
|
2183
|
+
|
|
2184
|
+
// src/vm/lib/global/sequence/with.ts
|
|
2185
|
+
var arrIndex = (index) => {
|
|
2186
|
+
const idx = Math.trunc(toNumber(index, NotNumber));
|
|
2187
|
+
if (isNaN(idx) || idx < 0) {
|
|
2188
|
+
throwError("Array index must be a non-negative integer", index);
|
|
2189
|
+
}
|
|
2190
|
+
if (idx >= VM_ARRAY_MAX_LENGTH) {
|
|
2191
|
+
throwError(`Array index exceeds maximum limit of ${VM_ARRAY_MAX_LENGTH}`, index);
|
|
2192
|
+
}
|
|
2193
|
+
return idx;
|
|
2194
|
+
};
|
|
2195
|
+
var isArrIndex = (key) => {
|
|
2196
|
+
if (typeof key != "number") return false;
|
|
2197
|
+
return isInteger(key) && key >= 0 && key < VM_ARRAY_MAX_LENGTH;
|
|
2198
|
+
};
|
|
2199
|
+
var withInner = (obj, key, keyIndex, value) => {
|
|
2200
|
+
if (keyIndex >= key.length) {
|
|
2201
|
+
return value;
|
|
2202
|
+
}
|
|
2203
|
+
const k = key[keyIndex];
|
|
2204
|
+
let result;
|
|
2205
|
+
if (isVmArray(obj)) {
|
|
2206
|
+
result = [...obj];
|
|
2207
|
+
} else if (isVmRecord(obj)) {
|
|
2208
|
+
result = { ...obj };
|
|
2209
|
+
} else if (isArrIndex(k)) {
|
|
2210
|
+
result = [];
|
|
2211
|
+
} else {
|
|
2212
|
+
result = {};
|
|
2213
|
+
}
|
|
2214
|
+
if (isArray(result)) {
|
|
2215
|
+
const index = arrIndex(k);
|
|
2216
|
+
while (index > result.length) {
|
|
2217
|
+
result.push(null);
|
|
2218
|
+
}
|
|
2219
|
+
result[index] = withInner(result[index], key, keyIndex + 1, value);
|
|
2220
|
+
} else {
|
|
2221
|
+
const prop = toString(k, void 0);
|
|
2222
|
+
result[prop] = withInner(result[prop], key, keyIndex + 1, value);
|
|
2223
|
+
}
|
|
2224
|
+
return result;
|
|
2225
|
+
};
|
|
2226
|
+
var normalizeEntries = (data, entries3) => {
|
|
2227
|
+
if (entries3.length % 2 !== 0) {
|
|
2228
|
+
throwError("Expected even number of entries", data);
|
|
2229
|
+
}
|
|
2230
|
+
const entryData = /* @__PURE__ */ new Map();
|
|
2231
|
+
for (let i = 0; i < entries3.length; i += 2) {
|
|
2232
|
+
let key = entries3[i];
|
|
2233
|
+
expectConst("key", key, data);
|
|
2234
|
+
if (key == null) {
|
|
2235
|
+
continue;
|
|
2236
|
+
}
|
|
2237
|
+
if (isVmArray(key)) {
|
|
2238
|
+
if (key.length === 0 || key.includes(null) || key.includes(void 0)) {
|
|
2239
|
+
continue;
|
|
2240
|
+
} else if (key.length === 1) {
|
|
2241
|
+
key = key[0];
|
|
2242
|
+
}
|
|
2243
|
+
}
|
|
2244
|
+
const value = entries3[i + 1];
|
|
2245
|
+
entryData.set(key, $El(value));
|
|
2246
|
+
}
|
|
2247
|
+
return entryData;
|
|
2248
|
+
};
|
|
2249
|
+
var _with = VmLib(
|
|
2250
|
+
(data, ...entries3) => {
|
|
2251
|
+
expectArrayOrRecord("data", data, data);
|
|
2252
|
+
if (entries3.length === 0) {
|
|
2253
|
+
return data;
|
|
2254
|
+
}
|
|
2255
|
+
const entryData = normalizeEntries(data, entries3);
|
|
2256
|
+
if (isVmArray(data)) {
|
|
2257
|
+
const result = [...data];
|
|
2258
|
+
for (const [key, value] of entryData) {
|
|
2259
|
+
let index;
|
|
2260
|
+
let val;
|
|
2261
|
+
if (isVmArray(key)) {
|
|
2262
|
+
index = arrIndex(key[0]);
|
|
2263
|
+
val = withInner(result[index], key, 1, value);
|
|
2264
|
+
} else {
|
|
2265
|
+
index = arrIndex(key);
|
|
2266
|
+
val = value;
|
|
2267
|
+
}
|
|
2268
|
+
while (index > result.length) {
|
|
2269
|
+
result.push(null);
|
|
2270
|
+
}
|
|
2271
|
+
result[index] = val;
|
|
2272
|
+
}
|
|
2273
|
+
return result;
|
|
2274
|
+
} else {
|
|
2275
|
+
const result = { ...data };
|
|
2276
|
+
for (const [key, value] of entryData) {
|
|
2277
|
+
let prop;
|
|
2278
|
+
let val;
|
|
2279
|
+
if (isVmArray(key)) {
|
|
2280
|
+
const firstKey = key[0];
|
|
2281
|
+
prop = toString(firstKey, void 0);
|
|
2282
|
+
val = withInner(result[prop], key, 1, value);
|
|
2283
|
+
} else {
|
|
2284
|
+
prop = toString(key, void 0);
|
|
2285
|
+
val = value;
|
|
2286
|
+
}
|
|
2287
|
+
result[prop] = val;
|
|
2288
|
+
}
|
|
2289
|
+
return result;
|
|
2290
|
+
}
|
|
2291
|
+
},
|
|
2292
|
+
{
|
|
2293
|
+
summary: "在数组或记录中设置多个键值对",
|
|
2294
|
+
params: {
|
|
2295
|
+
data: "要设置的数组或记录",
|
|
2296
|
+
"..entries": "要设置的键值对,成对出现;键可以是一个值或一个数组(表示嵌套路径)"
|
|
2297
|
+
},
|
|
2298
|
+
paramsType: {
|
|
2299
|
+
data: "array | record",
|
|
2300
|
+
"..entries": `[..[number | string | (number | string)[], any][]]`
|
|
2301
|
+
},
|
|
2302
|
+
returnsType: "type(data)",
|
|
2303
|
+
examples: [
|
|
2304
|
+
`with([10, 20], 2, 99, 3 ,100) // [10, 20, 99, 100]`,
|
|
2305
|
+
`(a: 1)::with(["b", 1], 2) // (a: 1, b: [nil, 2])`
|
|
2306
|
+
]
|
|
2307
|
+
}
|
|
2308
|
+
);
|
|
2309
|
+
|
|
2310
|
+
// src/vm/lib/global/sequence/entries.ts
|
|
2311
|
+
var keys3 = VmLib(
|
|
2312
|
+
(data) => {
|
|
2313
|
+
expectCompound("data", data, []);
|
|
2314
|
+
if (isVmArray(data)) {
|
|
2315
|
+
const arr = [];
|
|
2316
|
+
const len2 = data.length;
|
|
2317
|
+
for (let i = 0; i < len2; i++) {
|
|
2318
|
+
arr.push(i);
|
|
2319
|
+
}
|
|
2320
|
+
return arr;
|
|
2321
|
+
}
|
|
2322
|
+
if (isVmRecord(data)) {
|
|
2323
|
+
return keys(data);
|
|
2324
|
+
}
|
|
2325
|
+
return data.keys();
|
|
2326
|
+
},
|
|
2327
|
+
{
|
|
2328
|
+
summary: "返回数组、记录、外部对象或模块的键列表",
|
|
2329
|
+
params: { data: "要获取键的数组、记录、外部对象或模块" },
|
|
2330
|
+
paramsType: { data: "array | record | extern | module" },
|
|
2331
|
+
returnsType: "number[] | string[]",
|
|
2332
|
+
examples: ["keys([10, 20]) // [0, 1]", 'keys((10, 20)) // ["0", "1"]']
|
|
2333
|
+
}
|
|
2334
|
+
);
|
|
2335
|
+
var values3 = VmLib(
|
|
2336
|
+
(data) => {
|
|
2337
|
+
expectArrayOrRecord("data", data, []);
|
|
2338
|
+
if (isVmArray(data)) {
|
|
2339
|
+
return data;
|
|
2340
|
+
}
|
|
2341
|
+
return values(data);
|
|
2342
|
+
},
|
|
2343
|
+
{
|
|
2344
|
+
summary: "返回数组或记录的值列表",
|
|
2345
|
+
params: { data: "要获取值的数组或记录" },
|
|
2346
|
+
paramsType: { data: "array | record" },
|
|
2347
|
+
returnsType: "array",
|
|
2348
|
+
examples: ["values((a: 1, b: 2)) // [1, 2]"]
|
|
2349
|
+
}
|
|
2350
|
+
);
|
|
2351
|
+
var entries2 = VmLib(
|
|
2352
|
+
(data) => {
|
|
2353
|
+
expectArrayOrRecord("data", data, []);
|
|
2354
|
+
if (isVmArray(data)) {
|
|
2355
|
+
const arr = [];
|
|
2356
|
+
const len2 = data.length;
|
|
2357
|
+
for (let i = 0; i < len2; i++) {
|
|
2358
|
+
arr.push({ 0: i, 1: data[i] ?? null });
|
|
2359
|
+
}
|
|
2360
|
+
return arr;
|
|
2361
|
+
}
|
|
2362
|
+
return entries(data).map(([key, value]) => ({ 0: key, 1: value ?? null }));
|
|
2363
|
+
},
|
|
2364
|
+
{
|
|
2365
|
+
summary: "返回数组或记录的键值对列表",
|
|
2366
|
+
params: { data: "要获取键值对的数组或记录" },
|
|
2367
|
+
paramsType: { data: "array | record" },
|
|
2368
|
+
returnsType: "(number, any)[] | (string, any)[]",
|
|
2369
|
+
examples: ["entries([1]) // [(0, 1)]", 'entries((a: 1)) // [("a", 1)]']
|
|
2370
|
+
}
|
|
2371
|
+
);
|
|
2372
|
+
|
|
2373
|
+
// src/vm/lib/global/sequence/len.ts
|
|
2374
|
+
var len = VmLib(
|
|
2375
|
+
(arr) => {
|
|
2376
|
+
if (isVmExtern(arr)) {
|
|
2377
|
+
if (!arr.isArrayLike()) {
|
|
2378
|
+
throwUnexpectedTypeError("arr", "array-like extern", arr, NotNumber);
|
|
2379
|
+
}
|
|
2380
|
+
return arr.value.length;
|
|
2381
|
+
}
|
|
2382
|
+
expectArray("arr", arr, NotNumber);
|
|
2383
|
+
return arr.length;
|
|
2384
|
+
},
|
|
2385
|
+
{
|
|
2386
|
+
summary: "返回数组的长度",
|
|
2387
|
+
params: { arr: "要求长度的数组" },
|
|
2388
|
+
paramsType: { arr: "array | extern" },
|
|
2389
|
+
returnsType: "number",
|
|
2390
|
+
examples: ["len([1, 2, 3]) // 3"]
|
|
2391
|
+
}
|
|
2392
|
+
);
|
|
2393
|
+
|
|
2394
|
+
// src/vm/lib/global/sequence/map-filter.ts
|
|
2395
|
+
function mapImplWrapped(data, fnName, fn, mapper) {
|
|
2396
|
+
expectConst("data", data, null);
|
|
2397
|
+
expectCallable(fnName, fn, data);
|
|
2398
|
+
return map(data, (value, index, data2) => {
|
|
2399
|
+
const ret = mapper(fn, value, index, data2);
|
|
2400
|
+
if (ret === void 0 || isVmConst(ret)) return ret;
|
|
2401
|
+
return null;
|
|
2402
|
+
});
|
|
2403
|
+
}
|
|
2404
|
+
var map2 = VmLib(
|
|
2405
|
+
(data, f) => mapImplWrapped(data, "f", f, (fn, value, key, data2) => $Call(fn, [value, key, data2])),
|
|
2406
|
+
{
|
|
2407
|
+
summary: "对数组或记录中的每个元素应用函数,并返回结果",
|
|
2408
|
+
params: {
|
|
2409
|
+
data: "要映射的数组或记录",
|
|
2410
|
+
f: "应用于每个元素的函数"
|
|
2411
|
+
},
|
|
2412
|
+
paramsType: {
|
|
2413
|
+
data: "array | record",
|
|
2414
|
+
f: "fn(value: any, key: number | string, input: type(data)) -> any"
|
|
2415
|
+
},
|
|
2416
|
+
returnsType: "type(data)",
|
|
2417
|
+
examples: ["map([1, 2, 3], fn (v) { v * v }) // [1, 4, 9]"]
|
|
2418
|
+
}
|
|
2419
|
+
);
|
|
2420
|
+
var filter = VmLib(
|
|
2421
|
+
(data, predicate) => mapImplWrapped(data, "predicate", predicate, (fn, value, key, data2) => {
|
|
2422
|
+
const ret = $Call(fn, [value, key, data2]);
|
|
2423
|
+
return toBoolean(ret, void 0) ? value : void 0;
|
|
2424
|
+
}),
|
|
2425
|
+
{
|
|
2426
|
+
summary: "过滤数组或记录中的元素,返回满足条件的元素",
|
|
2427
|
+
params: {
|
|
2428
|
+
data: "要过滤的数组或记录",
|
|
2429
|
+
predicate: "用于测试每个元素的函数"
|
|
2430
|
+
},
|
|
2431
|
+
paramsType: {
|
|
2432
|
+
data: "array | record",
|
|
2433
|
+
predicate: "fn(value: any, key: number | string, input: type(data)) -> boolean"
|
|
2434
|
+
},
|
|
2435
|
+
returnsType: "type(data)",
|
|
2436
|
+
examples: ["filter([1, 2, 3, 4], fn (v) { v % 2 == 0 }) // [2, 4]"]
|
|
2437
|
+
}
|
|
2438
|
+
);
|
|
2439
|
+
var filter_map = VmLib(
|
|
2440
|
+
(data, f) => mapImplWrapped(data, "f", f, (fn, value, key, data2) => {
|
|
2441
|
+
const ret = $Call(fn, [value, key, data2]);
|
|
2442
|
+
return ret ?? void 0;
|
|
2443
|
+
}),
|
|
2444
|
+
{
|
|
2445
|
+
summary: "对数组或记录中的每个元素应用函数,并返回非 nil 的结果",
|
|
2446
|
+
params: {
|
|
2447
|
+
data: "要映射的数组或记录",
|
|
2448
|
+
f: "应用于每个元素的函数"
|
|
2449
|
+
},
|
|
2450
|
+
paramsType: {
|
|
2451
|
+
data: "array | record",
|
|
2452
|
+
f: "fn(value: any, key: number | string, input: type(data)) -> any | nil"
|
|
2453
|
+
},
|
|
2454
|
+
returnsType: "type(data)",
|
|
2455
|
+
examples: ["filter_map([1, 2, 3], fn (v) { if v % 2 == 0 { v * v } else { nil } }) // [4]"]
|
|
2456
|
+
}
|
|
2457
|
+
);
|
|
2458
|
+
|
|
2459
|
+
// src/vm/lib/global/sequence/find.ts
|
|
2460
|
+
var find = VmLib(
|
|
2461
|
+
(data, predicate) => {
|
|
2462
|
+
expectArrayOrRecord("data", data, null);
|
|
2463
|
+
required("predicate", predicate, null);
|
|
2464
|
+
const p = isVmCallable(predicate) ? (value, key, data2) => {
|
|
2465
|
+
const ret = $Call(predicate, [value, key, data2]);
|
|
2466
|
+
return toBoolean(ret, void 0);
|
|
2467
|
+
} : (value) => $Same(predicate, value);
|
|
2468
|
+
if (isVmArray(data)) {
|
|
2469
|
+
const { length } = data;
|
|
2470
|
+
for (let i = 0; i < length; i++) {
|
|
2471
|
+
Cp();
|
|
2472
|
+
const value = data[i] ?? null;
|
|
2473
|
+
const ret = p(value, i, data);
|
|
2474
|
+
if (!ret) continue;
|
|
2475
|
+
return { 0: i, 1: value };
|
|
2476
|
+
}
|
|
2477
|
+
return null;
|
|
2478
|
+
} else {
|
|
2479
|
+
for (const [key, v] of entries(data)) {
|
|
2480
|
+
Cp();
|
|
2481
|
+
const value = v ?? null;
|
|
2482
|
+
const ret = p(value, key, data);
|
|
2483
|
+
if (!ret) continue;
|
|
2484
|
+
return { 0: key, 1: value };
|
|
2485
|
+
}
|
|
2486
|
+
return null;
|
|
2487
|
+
}
|
|
2488
|
+
},
|
|
2489
|
+
{
|
|
2490
|
+
summary: "查找数组或记录中的键值对,返回第一个满足条件的键值对",
|
|
2491
|
+
params: {
|
|
2492
|
+
data: "要查找的数组或记录",
|
|
2493
|
+
predicate: "用于测试每个键值对的函数,或要查找的值"
|
|
2494
|
+
},
|
|
2495
|
+
paramsType: {
|
|
2496
|
+
data: "array | record",
|
|
2497
|
+
predicate: "(fn(value: any, key: number | string, input: type(data)) -> boolean) | any"
|
|
2498
|
+
},
|
|
2499
|
+
returnsType: "(number | string, any) | nil",
|
|
2500
|
+
examples: ["find([3, 5, 8], fn (v) { v % 2 == 0 }) // (2, 8)", `find((x: 1, y: 2, z: 3), 2) // ('y', 2)`]
|
|
2501
|
+
}
|
|
2502
|
+
);
|
|
2503
|
+
|
|
2504
|
+
// src/vm/lib/global/sequence/flatten.ts
|
|
2505
|
+
var flatten = VmLib(
|
|
2506
|
+
(data, depth = 1) => {
|
|
2507
|
+
expectArray("data", data, data);
|
|
2508
|
+
return data.flat(expectNumber("depth", depth));
|
|
2509
|
+
},
|
|
2510
|
+
{
|
|
2511
|
+
summary: "将数组扁平化",
|
|
2512
|
+
params: { data: "要扁平化的数组", depth: "扁平化的深度,默认为 1" },
|
|
2513
|
+
paramsType: { data: "array", depth: "number" },
|
|
2514
|
+
returnsType: "array",
|
|
2515
|
+
examples: ["flatten([[1, 2], [3, [4]]], 2) // [1, 2, 3, 4]"]
|
|
2516
|
+
}
|
|
2517
|
+
);
|
|
2518
|
+
|
|
2519
|
+
// src/vm/lib/global/sequence/reverse.ts
|
|
2520
|
+
var reverse = VmLib(
|
|
2521
|
+
(arr) => {
|
|
2522
|
+
expectArray("arr", arr, null);
|
|
2523
|
+
const dup = [...arr];
|
|
2524
|
+
dup.reverse();
|
|
2525
|
+
return dup;
|
|
2526
|
+
},
|
|
2527
|
+
{
|
|
2528
|
+
summary: "返回数组的反转副本",
|
|
2529
|
+
params: { arr: "要反转的数组" },
|
|
2530
|
+
paramsType: { arr: "array" },
|
|
2531
|
+
returnsType: "array",
|
|
2532
|
+
examples: ["reverse([1, 2, 3]) // [3, 2, 1]"]
|
|
2533
|
+
}
|
|
2534
|
+
);
|
|
2535
|
+
|
|
2536
|
+
// src/vm/lib/global/sequence/zip.ts
|
|
2537
|
+
var zip = VmLib(
|
|
2538
|
+
(data) => {
|
|
2539
|
+
const ets = entries2(data);
|
|
2540
|
+
let len2 = 0;
|
|
2541
|
+
for (const { 0: key, 1: arr } of ets) {
|
|
2542
|
+
if (!isVmArray(arr)) {
|
|
2543
|
+
throwError(`data[${display(key)}] is not an array: ${display(arr)}`, null);
|
|
2544
|
+
}
|
|
2545
|
+
len2 = Math.max(len2, arr.length);
|
|
2546
|
+
}
|
|
2547
|
+
if (len2 === 0) return [];
|
|
2548
|
+
const result = [];
|
|
2549
|
+
const isArr = isVmArray(data);
|
|
2550
|
+
for (let i = 0; i < len2; i++) {
|
|
2551
|
+
Cp();
|
|
2552
|
+
const obj = isArr ? [] : {};
|
|
2553
|
+
for (const { 0: key, 1: arr } of ets) {
|
|
2554
|
+
obj[key] = arr[i] ?? null;
|
|
2555
|
+
}
|
|
2556
|
+
result.push(obj);
|
|
2557
|
+
}
|
|
2558
|
+
return result;
|
|
2559
|
+
},
|
|
2560
|
+
{
|
|
2561
|
+
summary: "将数组的数组/记录转换为数组/记录的数组",
|
|
2562
|
+
params: { data: "要转换的数组/记录" },
|
|
2563
|
+
paramsType: { data: "array | record" },
|
|
2564
|
+
returnsType: "(array | record)[]",
|
|
2565
|
+
examples: [
|
|
2566
|
+
'zip((x: [1, 2], y: ["a", "b"])) // [(x: 1, y: "a"), (x: 2, y: "b")]',
|
|
2567
|
+
`zip([[1, 2], ["a", "b"]]) // [[1, "a"], [2, "b"]]`
|
|
2568
|
+
]
|
|
2569
|
+
}
|
|
2570
|
+
);
|
|
2571
|
+
|
|
2572
|
+
// src/vm/lib/global/sequence/all-any.ts
|
|
2573
|
+
var all = VmLib(
|
|
2574
|
+
(data, predicate) => {
|
|
2575
|
+
expectArrayOrRecord("data", data, null);
|
|
2576
|
+
expectCallable("predicate", predicate, data);
|
|
2577
|
+
if (isVmArray(data)) {
|
|
2578
|
+
for (let i = 0; i < data.length; i++) {
|
|
2579
|
+
Cp();
|
|
2580
|
+
const value = data[i] ?? null;
|
|
2581
|
+
const ret = $Call(predicate, [value, i, data]);
|
|
2582
|
+
if (!toBoolean(ret, void 0)) return false;
|
|
2583
|
+
}
|
|
2584
|
+
return true;
|
|
2585
|
+
} else {
|
|
2586
|
+
for (const [key, v] of entries(data)) {
|
|
2587
|
+
Cp();
|
|
2588
|
+
const value = v ?? null;
|
|
2589
|
+
const ret = $Call(predicate, [value, key, data]);
|
|
2590
|
+
if (!toBoolean(ret, void 0)) return false;
|
|
2591
|
+
}
|
|
2592
|
+
return true;
|
|
2593
|
+
}
|
|
2594
|
+
},
|
|
2595
|
+
{
|
|
2596
|
+
summary: "检查数组或记录中的所有键值对是否都满足条件",
|
|
2597
|
+
params: { data: "要检查的数组或记录", predicate: "用于测试每个键值对的函数,返回 true 或 false" },
|
|
2598
|
+
paramsType: {
|
|
2599
|
+
data: "array | record",
|
|
2600
|
+
predicate: "fn(value: any, key: number | string, input: type(data)) -> boolean"
|
|
2601
|
+
},
|
|
2602
|
+
returnsType: "boolean",
|
|
2603
|
+
examples: ["all([1, 2, 3], fn { it > 0 }) // true"]
|
|
2604
|
+
}
|
|
2605
|
+
);
|
|
2606
|
+
var any = VmLib(
|
|
2607
|
+
(data, predicate) => {
|
|
2608
|
+
expectArrayOrRecord("data", data, null);
|
|
2609
|
+
expectCallable("predicate", predicate, data);
|
|
2610
|
+
if (isVmArray(data)) {
|
|
2611
|
+
for (let i = 0; i < data.length; i++) {
|
|
2612
|
+
Cp();
|
|
2613
|
+
const value = data[i] ?? null;
|
|
2614
|
+
const ret = $Call(predicate, [value, i, data]);
|
|
2615
|
+
if (toBoolean(ret, void 0)) return true;
|
|
2616
|
+
}
|
|
2617
|
+
return false;
|
|
2618
|
+
} else {
|
|
2619
|
+
for (const [key, v] of entries(data)) {
|
|
2620
|
+
Cp();
|
|
2621
|
+
const value = v ?? null;
|
|
2622
|
+
const ret = $Call(predicate, [value, key, data]);
|
|
2623
|
+
if (toBoolean(ret, void 0)) return true;
|
|
2624
|
+
}
|
|
2625
|
+
return false;
|
|
2626
|
+
}
|
|
2627
|
+
},
|
|
2628
|
+
{
|
|
2629
|
+
summary: "检查数组或记录中的是否存在满足条件的键值对",
|
|
2630
|
+
params: { data: "要检查的数组或记录", predicate: "用于测试每个键值对的函数,返回 true 或 false" },
|
|
2631
|
+
paramsType: {
|
|
2632
|
+
data: "array | record",
|
|
2633
|
+
predicate: "fn(value: any, key: number | string, input: type(data)) -> boolean"
|
|
2634
|
+
},
|
|
2635
|
+
returnsType: "boolean",
|
|
2636
|
+
examples: ["any([0, 1, 2], fn { it > 1 }) // true"]
|
|
2637
|
+
}
|
|
2638
|
+
);
|
|
2639
|
+
|
|
2640
|
+
// src/vm/lib/global/sequence/sort.ts
|
|
2641
|
+
function defaultCompare(a = null, b = null) {
|
|
2642
|
+
if (Object.is(a, b)) return 0;
|
|
2643
|
+
if ((typeof a == "string" || a == null) && (typeof b == "string" || b == null)) {
|
|
2644
|
+
a ??= "";
|
|
2645
|
+
b ??= "";
|
|
2646
|
+
if (a < b) return -1;
|
|
2647
|
+
if (a > b) return 1;
|
|
2648
|
+
return 0;
|
|
2649
|
+
}
|
|
2650
|
+
const an = toNumber(a, 0) || 0;
|
|
2651
|
+
const bn = toNumber(b, 0) || 0;
|
|
2652
|
+
if (an < bn) return -1;
|
|
2653
|
+
if (an > bn) return 1;
|
|
2654
|
+
return 0;
|
|
2655
|
+
}
|
|
2656
|
+
function cmp(comparator, recovered) {
|
|
2657
|
+
if (comparator == null) return defaultCompare;
|
|
2658
|
+
expectCallable("comparator", comparator, recovered);
|
|
2659
|
+
return (a = null, b = null) => {
|
|
2660
|
+
const ret = $Call(comparator, [a, b]);
|
|
2661
|
+
return toNumber(ret, void 0);
|
|
2662
|
+
};
|
|
2663
|
+
}
|
|
2664
|
+
var sort = VmLib(
|
|
2665
|
+
(data, comparator) => {
|
|
2666
|
+
expectArray("data", data, null);
|
|
2667
|
+
const compare = cmp(comparator, data);
|
|
2668
|
+
const arr = [];
|
|
2669
|
+
for (const v of data) {
|
|
2670
|
+
arr.push(v ?? null);
|
|
2671
|
+
}
|
|
2672
|
+
arr.sort(compare);
|
|
2673
|
+
return arr;
|
|
2674
|
+
},
|
|
2675
|
+
{
|
|
2676
|
+
summary: "对数组中的元素进行排序,并返回排序后的结果",
|
|
2677
|
+
params: {
|
|
2678
|
+
data: "要排序的数组",
|
|
2679
|
+
comparator: "用于比较两个元素的函数,返回一个数字,表示它们的相对顺序,默认按升序排列"
|
|
2680
|
+
},
|
|
2681
|
+
paramsType: {
|
|
2682
|
+
data: "array",
|
|
2683
|
+
comparator: "fn(a: any, b: any) -> number"
|
|
2684
|
+
},
|
|
2685
|
+
returnsType: "array",
|
|
2686
|
+
examples: ['sort(["c", "a", "b"]) // ["a", "b", "c"]']
|
|
2687
|
+
}
|
|
2688
|
+
);
|
|
2689
|
+
var sort_by = VmLib(
|
|
2690
|
+
(data, key, comparator) => {
|
|
2691
|
+
expectArray("data", data, null);
|
|
2692
|
+
expectCallable("key", key, data);
|
|
2693
|
+
const compare = cmp(comparator, data);
|
|
2694
|
+
const arr = [];
|
|
2695
|
+
const len2 = data.length;
|
|
2696
|
+
for (let i = 0; i < len2; i++) {
|
|
2697
|
+
const v = data[i] ?? null;
|
|
2698
|
+
arr.push({
|
|
2699
|
+
o: v,
|
|
2700
|
+
k: $Call(key, [v, i, data])
|
|
2701
|
+
});
|
|
2702
|
+
}
|
|
2703
|
+
arr.sort((a, b) => compare(a.k, b.k));
|
|
2704
|
+
return arr.map((e2) => e2.o);
|
|
2705
|
+
},
|
|
2706
|
+
{
|
|
2707
|
+
summary: "根据键函数对数组中的元素进行排序,并返回排序后的结果",
|
|
2708
|
+
params: {
|
|
2709
|
+
data: "要排序的数组",
|
|
2710
|
+
key: "用于提取排序键的函数,接受一个元素并返回其排序键",
|
|
2711
|
+
comparator: "用于比较两个排序键的函数,返回一个数字,表示它们的相对顺序,默认按升序排列"
|
|
2712
|
+
},
|
|
2713
|
+
paramsType: {
|
|
2714
|
+
data: "array",
|
|
2715
|
+
key: "fn(value: any, index: number, arr: type(data)) -> any",
|
|
2716
|
+
comparator: "fn(a: any, b: any) -> number"
|
|
2717
|
+
},
|
|
2718
|
+
returnsType: "array",
|
|
2719
|
+
examples: ['sort_by([(0, "x"), (2, "y"), (1, "z")], fn (item) { item[0] }) // [(0, "x"), (1, "z"), (2, "y")]']
|
|
2720
|
+
}
|
|
2721
|
+
);
|
|
2722
|
+
|
|
2723
|
+
// src/vm/lib/global/sequence/unique.ts
|
|
2724
|
+
function defaultEqual(a = null, b = null) {
|
|
2725
|
+
return isSame(a, b);
|
|
2726
|
+
}
|
|
2727
|
+
function eq(equaler, recovered) {
|
|
2728
|
+
if (equaler == null) return defaultEqual;
|
|
2729
|
+
expectCallable("equal", equaler, recovered);
|
|
2730
|
+
return (a = null, b = null) => {
|
|
2731
|
+
const ret = $Call(equaler, [a, b]);
|
|
2732
|
+
return toBoolean(ret, void 0);
|
|
2733
|
+
};
|
|
2734
|
+
}
|
|
2735
|
+
var unique = VmLib(
|
|
2736
|
+
(data, equal) => {
|
|
2737
|
+
expectArray("data", data, null);
|
|
2738
|
+
const e2 = eq(equal, data);
|
|
2739
|
+
const arr = [];
|
|
2740
|
+
for (const v of data) {
|
|
2741
|
+
let found = false;
|
|
2742
|
+
for (const u of arr) {
|
|
2743
|
+
if (e2(v, u)) {
|
|
2744
|
+
found = true;
|
|
2745
|
+
break;
|
|
2746
|
+
}
|
|
2747
|
+
}
|
|
2748
|
+
if (!found) arr.push(v ?? null);
|
|
2749
|
+
}
|
|
2750
|
+
return arr;
|
|
2751
|
+
},
|
|
2752
|
+
{
|
|
2753
|
+
summary: "对数组中的元素进行去重,并返回去重后的结果",
|
|
2754
|
+
params: {
|
|
2755
|
+
data: "要去重的数组",
|
|
2756
|
+
equal: "用于判等两个元素的函数,返回一个布尔值,默认使用严格相等比较"
|
|
2757
|
+
},
|
|
2758
|
+
paramsType: {
|
|
2759
|
+
data: "array",
|
|
2760
|
+
equal: "fn(a: any, b: any) -> boolean"
|
|
2761
|
+
},
|
|
2762
|
+
returnsType: "array",
|
|
2763
|
+
examples: ["unique([1, 2, 2, 3]) // [1, 2, 3]"]
|
|
2764
|
+
}
|
|
2765
|
+
);
|
|
2766
|
+
var unique_by = VmLib(
|
|
2767
|
+
(data, key, equal) => {
|
|
2768
|
+
expectArray("data", data, null);
|
|
2769
|
+
expectCallable("key", key, data);
|
|
2770
|
+
const e2 = eq(equal, data);
|
|
2771
|
+
const arr = [];
|
|
2772
|
+
const keys4 = [];
|
|
2773
|
+
const len2 = data.length;
|
|
2774
|
+
for (let i = 0; i < len2; i++) {
|
|
2775
|
+
const v = data[i] ?? null;
|
|
2776
|
+
const k = $Call(key, [v, i, data]);
|
|
2777
|
+
let found = false;
|
|
2778
|
+
const keysLen = keys4.length;
|
|
2779
|
+
for (let j = 0; j < keysLen; j++) {
|
|
2780
|
+
if (e2(k, keys4[j])) {
|
|
2781
|
+
found = true;
|
|
2782
|
+
break;
|
|
2783
|
+
}
|
|
2784
|
+
}
|
|
2785
|
+
if (!found) {
|
|
2786
|
+
arr.push(v);
|
|
2787
|
+
keys4.push(k);
|
|
2788
|
+
}
|
|
2789
|
+
}
|
|
2790
|
+
return arr;
|
|
2791
|
+
},
|
|
2792
|
+
{
|
|
2793
|
+
summary: "根据键函数对数组中的元素进行去重,并返回去重后的结果",
|
|
2794
|
+
params: {
|
|
2795
|
+
data: "要去重的数组",
|
|
2796
|
+
key: "用于提取去重键的函数,接受一个元素并返回其去重键",
|
|
2797
|
+
equal: "用于判同两个元素的函数,返回一个布尔值,默认使用严格相等比较"
|
|
2798
|
+
},
|
|
2799
|
+
paramsType: {
|
|
2800
|
+
data: "array",
|
|
2801
|
+
key: "fn(value: any, index: number, arr: type(data)) -> any",
|
|
2802
|
+
equal: "fn(a: any, b: any) -> boolean"
|
|
2803
|
+
},
|
|
2804
|
+
returnsType: "array",
|
|
2805
|
+
examples: ['unique_by(["apple", "banana", "apricot"], fn { chars(it)[0] }) // ["apple", "banana"]']
|
|
2806
|
+
}
|
|
2807
|
+
);
|
|
2808
|
+
|
|
2809
|
+
// src/vm/lib/global/sequence/repeat.ts
|
|
2810
|
+
var repeat = VmLib(
|
|
2811
|
+
(data, times) => {
|
|
2812
|
+
expectConst("data", data, []);
|
|
2813
|
+
const n = arrayLen(expectNumber("times", times));
|
|
2814
|
+
const result = [];
|
|
2815
|
+
result.length = n;
|
|
2816
|
+
result.fill(data);
|
|
2817
|
+
return result;
|
|
2818
|
+
},
|
|
2819
|
+
{
|
|
2820
|
+
summary: "创建一个包含重复元素的数组",
|
|
2821
|
+
params: {
|
|
2822
|
+
data: "要重复的元素",
|
|
2823
|
+
times: "重复的次数,必须是非负整数"
|
|
2824
|
+
},
|
|
2825
|
+
paramsType: {
|
|
2826
|
+
data: "any",
|
|
2827
|
+
times: "number"
|
|
2828
|
+
},
|
|
2829
|
+
returnsType: "type(data)[]",
|
|
2830
|
+
examples: ["repeat(0, 5) // [0, 0, 0, 0, 0]", 'repeat("a", 3) // ["a", "a", "a"]']
|
|
2831
|
+
}
|
|
2832
|
+
);
|
|
2833
|
+
|
|
2834
|
+
// src/vm/lib/global/sequence/new.ts
|
|
2835
|
+
var new_record = VmLib(
|
|
2836
|
+
(size2, generator) => {
|
|
2837
|
+
const n = expectIntegerRange("size", size2, 0, PositiveInfinity);
|
|
2838
|
+
expectCallable("generator", generator, null);
|
|
2839
|
+
const result = {};
|
|
2840
|
+
for (let i = 0; i < n; i++) {
|
|
2841
|
+
const entry = $Call(generator, [i]);
|
|
2842
|
+
if (entry == null) continue;
|
|
2843
|
+
const key = $Get(entry, 0);
|
|
2844
|
+
const value = $El($Get(entry, 1));
|
|
2845
|
+
result[toString(key)] = value;
|
|
2846
|
+
}
|
|
2847
|
+
return result;
|
|
2848
|
+
},
|
|
2849
|
+
{
|
|
2850
|
+
summary: "根据生成器函数创建一个记录",
|
|
2851
|
+
params: { size: "记录的大小", generator: "生成器函数,返回键值对或 nil(表示跳过该条目)" },
|
|
2852
|
+
paramsType: { size: "number", generator: "fn(index: number) -> (string, any) | nil" },
|
|
2853
|
+
returnsType: "record",
|
|
2854
|
+
examples: ["new_record(3, fn { (it, it * 2) }) // (0, 2, 4)"]
|
|
2855
|
+
}
|
|
2856
|
+
);
|
|
2857
|
+
var new_array = VmLib(
|
|
2858
|
+
(length, generator) => {
|
|
2859
|
+
const n = expectIntegerRange("length", length, 0, VM_ARRAY_MAX_LENGTH);
|
|
2860
|
+
expectCallable("generator", generator, null);
|
|
2861
|
+
const result = [];
|
|
2862
|
+
for (let i = 0; i < n; i++) {
|
|
2863
|
+
result.push($El($Call(generator, [i])));
|
|
2864
|
+
}
|
|
2865
|
+
return result;
|
|
2866
|
+
},
|
|
2867
|
+
{
|
|
2868
|
+
summary: "根据生成器函数创建一个数组",
|
|
2869
|
+
params: { length: "数组的长度", generator: "生成器函数,返回数组元素的值" },
|
|
2870
|
+
paramsType: { length: "number", generator: "fn(index: number) -> any" },
|
|
2871
|
+
returnsType: "array",
|
|
2872
|
+
examples: ["new_array(5, fn { it * it }) // [0, 1, 4, 9, 16]"]
|
|
2873
|
+
}
|
|
2874
|
+
);
|
|
2875
|
+
|
|
2876
|
+
// src/vm/lib/global/debug.ts
|
|
2877
|
+
import supportsColor from "supports-color";
|
|
2878
|
+
function defaultSerializer(arg, format2) {
|
|
2879
|
+
return null;
|
|
2880
|
+
}
|
|
2881
|
+
function serializeValue(options, arg, format2) {
|
|
2882
|
+
const { serializer } = options;
|
|
2883
|
+
if (serializer == null || serializer === defaultSerializer) {
|
|
2884
|
+
return defaultSerializer(arg, format2);
|
|
2885
|
+
}
|
|
2886
|
+
try {
|
|
2887
|
+
return serializer.call(options, arg, format2);
|
|
2888
|
+
} catch {
|
|
2889
|
+
return defaultSerializer(arg, format2);
|
|
2890
|
+
}
|
|
2891
|
+
}
|
|
2892
|
+
function buildFormatString(options, args) {
|
|
2893
|
+
const [prefix, ...additional] = options.prefix;
|
|
2894
|
+
if (typeof args[0] != "string" || !args[0].includes("%")) {
|
|
2895
|
+
return [prefix || "", [...additional, ...args]];
|
|
2896
|
+
} else {
|
|
2897
|
+
const [arg0, ...argsRest] = args;
|
|
2898
|
+
const values4 = [...additional, ...argsRest];
|
|
2899
|
+
if (!prefix) {
|
|
2900
|
+
return [arg0, argsRest];
|
|
2901
|
+
} else {
|
|
2902
|
+
return [`${prefix} ${arg0}`, values4];
|
|
2903
|
+
}
|
|
2904
|
+
}
|
|
2905
|
+
}
|
|
2906
|
+
var printParser = function(args) {
|
|
2907
|
+
const [format2, values4] = buildFormatString(this, args);
|
|
2908
|
+
const templates = [];
|
|
2909
|
+
const formats = [];
|
|
2910
|
+
let valIndex = 0;
|
|
2911
|
+
if (format2.includes("%")) {
|
|
2912
|
+
const parts = format2.split(/(%[%\w])/g);
|
|
2913
|
+
let prevIsTemplate = true;
|
|
2914
|
+
for (let i = 0; i < parts.length; i++) {
|
|
2915
|
+
if (i % 2 === 0) {
|
|
2916
|
+
if (prevIsTemplate && templates.length) {
|
|
2917
|
+
templates[templates.length - 1] += parts[i];
|
|
2918
|
+
} else {
|
|
2919
|
+
templates.push(parts[i]);
|
|
2920
|
+
}
|
|
2921
|
+
prevIsTemplate = true;
|
|
2922
|
+
continue;
|
|
2923
|
+
}
|
|
2924
|
+
let specifier = parts[i];
|
|
2925
|
+
if (specifier === "%%" || valIndex >= values4.length) {
|
|
2926
|
+
if (specifier === "%%") specifier = "%";
|
|
2927
|
+
if (!templates.length) {
|
|
2928
|
+
templates.push(specifier);
|
|
2929
|
+
} else {
|
|
2930
|
+
templates[templates.length - 1] += specifier;
|
|
2931
|
+
}
|
|
2932
|
+
prevIsTemplate = true;
|
|
2933
|
+
continue;
|
|
2934
|
+
}
|
|
2935
|
+
prevIsTemplate = false;
|
|
2936
|
+
formats.push(specifier);
|
|
2937
|
+
valIndex++;
|
|
2938
|
+
}
|
|
2939
|
+
} else if (format2) {
|
|
2940
|
+
templates.push(format2);
|
|
2941
|
+
}
|
|
2942
|
+
if (valIndex < values4.length) {
|
|
2943
|
+
if (templates.length) {
|
|
2944
|
+
templates[templates.length - 1] += " ";
|
|
2945
|
+
} else {
|
|
2946
|
+
templates.push("");
|
|
2947
|
+
}
|
|
2948
|
+
for (let i = valIndex; i < values4.length; i++) {
|
|
2949
|
+
formats.push("");
|
|
2950
|
+
templates.push(i < values4.length - 1 ? " " : "");
|
|
2951
|
+
}
|
|
2952
|
+
valIndex++;
|
|
2953
|
+
}
|
|
2954
|
+
return {
|
|
2955
|
+
templates,
|
|
2956
|
+
values: values4,
|
|
2957
|
+
formats
|
|
2958
|
+
};
|
|
2959
|
+
};
|
|
2960
|
+
var printFormatter = function({
|
|
2961
|
+
templates,
|
|
2962
|
+
formats,
|
|
2963
|
+
values: values4
|
|
2964
|
+
}) {
|
|
2965
|
+
let format2 = "";
|
|
2966
|
+
const formattedValues = [];
|
|
2967
|
+
let needAwait = false;
|
|
2968
|
+
for (let i = 0; i < templates.length; i++) {
|
|
2969
|
+
format2 += templates[i].replaceAll("%", "%%");
|
|
2970
|
+
if (i < values4.length) {
|
|
2971
|
+
const f = formats[i] ?? "";
|
|
2972
|
+
const v = values4[i];
|
|
2973
|
+
const serialized = serializeValue(this, v, f);
|
|
2974
|
+
if (serialized == null) {
|
|
2975
|
+
format2 += f || (typeof v == "string" ? "%s" : "%o");
|
|
2976
|
+
formattedValues.push(v);
|
|
2977
|
+
} else if (typeof serialized == "string") {
|
|
2978
|
+
format2 += "%s";
|
|
2979
|
+
formattedValues.push(serialized);
|
|
2980
|
+
} else {
|
|
2981
|
+
needAwait = true;
|
|
2982
|
+
format2 += "%s";
|
|
2983
|
+
formattedValues.push(serialized);
|
|
2984
|
+
}
|
|
2985
|
+
}
|
|
2986
|
+
}
|
|
2987
|
+
if (!needAwait) {
|
|
2988
|
+
return [format2, ...formattedValues];
|
|
2989
|
+
} else {
|
|
2990
|
+
return Promise.all(formattedValues).then((resolvedValues) => {
|
|
2991
|
+
return [format2, ...resolvedValues];
|
|
2992
|
+
});
|
|
2993
|
+
}
|
|
2994
|
+
};
|
|
2995
|
+
var createPrintOptions = (consoleMethod) => {
|
|
2996
|
+
return {
|
|
2997
|
+
prefix: ["MiraScript"],
|
|
2998
|
+
serializer: defaultSerializer,
|
|
2999
|
+
parser: printParser,
|
|
3000
|
+
formatter: printFormatter,
|
|
3001
|
+
logger: consoleMethod
|
|
3002
|
+
};
|
|
3003
|
+
};
|
|
3004
|
+
function doPrint(opt, args) {
|
|
3005
|
+
const formatResult = opt.parser(args);
|
|
3006
|
+
void Promise.resolve(opt.formatter(formatResult)).then((printed) => opt.logger(...printed));
|
|
3007
|
+
}
|
|
3008
|
+
var debug_print = VmLib(
|
|
3009
|
+
(...args) => {
|
|
3010
|
+
doPrint(debug_print, args);
|
|
3011
|
+
},
|
|
3012
|
+
{
|
|
3013
|
+
summary: "打印调试信息到控制台",
|
|
3014
|
+
params: { "..args": "要打印的调试信息,可以是任意类型" },
|
|
3015
|
+
paramsType: { "..args": "any[]" },
|
|
3016
|
+
returnsType: "nil",
|
|
3017
|
+
examples: ['debug_print("value:", 42);']
|
|
3018
|
+
},
|
|
3019
|
+
// eslint-disable-next-line no-console
|
|
3020
|
+
createPrintOptions(console.log.bind(console))
|
|
3021
|
+
);
|
|
3022
|
+
var panic = VmLib(
|
|
3023
|
+
(message) => {
|
|
3024
|
+
doPrint(panic, message === void 0 ? [] : [message]);
|
|
3025
|
+
const mgsStr = toString(message, null);
|
|
3026
|
+
const error = !mgsStr ? "panic" : "panic: " + mgsStr;
|
|
3027
|
+
throw new VmError(error, void 0);
|
|
3028
|
+
},
|
|
3029
|
+
{
|
|
3030
|
+
summary: "产生错误,并打印错误信息到控制台",
|
|
3031
|
+
params: { message: "要打印的错误信息" },
|
|
3032
|
+
paramsType: { message: "string" },
|
|
3033
|
+
returnsType: "never",
|
|
3034
|
+
examples: ['panic("boom");']
|
|
3035
|
+
},
|
|
3036
|
+
// eslint-disable-next-line no-console
|
|
3037
|
+
createPrintOptions(console.error.bind(console))
|
|
3038
|
+
);
|
|
3039
|
+
if (typeof location != "undefined") {
|
|
3040
|
+
const badge = "%cMiraScript%c";
|
|
3041
|
+
const common = "display: inline-block; padding: 1px 4px; border-radius: 3px;";
|
|
3042
|
+
const reset = "";
|
|
3043
|
+
debug_print.prefix = [badge, `${common} background: #007acc; color: #fff;`, reset];
|
|
3044
|
+
panic.prefix = [badge, `${common} background: #d23d3d; color: #fff;`, reset];
|
|
3045
|
+
} else {
|
|
3046
|
+
if (supportsColor.stdout) {
|
|
3047
|
+
debug_print.prefix = ["\x1B[44;37m MiraScript \x1B[0m"];
|
|
3048
|
+
}
|
|
3049
|
+
if (supportsColor.stderr) {
|
|
3050
|
+
panic.prefix = ["\x1B[41;37m MiraScript \x1B[0m"];
|
|
3051
|
+
}
|
|
3052
|
+
}
|
|
3053
|
+
|
|
3054
|
+
// src/vm/lib/global/json.ts
|
|
3055
|
+
var { parse, stringify } = JSON;
|
|
3056
|
+
var to_json = VmLib(
|
|
3057
|
+
(data) => {
|
|
3058
|
+
required("data", data, null);
|
|
3059
|
+
if (isVmExtern(data) || isVmModule(data)) {
|
|
3060
|
+
try {
|
|
3061
|
+
return stringify(data.value) ?? null;
|
|
3062
|
+
} catch (ex) {
|
|
3063
|
+
rethrowError("Failed to convert extern to JSON", ex, "{}");
|
|
3064
|
+
}
|
|
3065
|
+
}
|
|
3066
|
+
if (typeof data == "function") return null;
|
|
3067
|
+
return stringify(data);
|
|
3068
|
+
},
|
|
3069
|
+
{
|
|
3070
|
+
summary: "将数据转换为 JSON 字符串",
|
|
3071
|
+
params: { data: "要转换为 JSON 的数据" },
|
|
3072
|
+
paramsType: { data: "any" },
|
|
3073
|
+
returnsType: "string",
|
|
3074
|
+
examples: ['to_json([1, 2, 3]) // "[1,2,3]"']
|
|
3075
|
+
}
|
|
3076
|
+
);
|
|
3077
|
+
var from_json = VmLib(
|
|
3078
|
+
(json, fallback) => {
|
|
3079
|
+
const j = expectString("json", json);
|
|
3080
|
+
try {
|
|
3081
|
+
return parse(j);
|
|
3082
|
+
} catch (ex) {
|
|
3083
|
+
if (fallback !== void 0) return fallback;
|
|
3084
|
+
rethrowError("Invalid JSON", ex, null);
|
|
3085
|
+
}
|
|
3086
|
+
},
|
|
3087
|
+
{
|
|
3088
|
+
summary: "将 JSON 字符串转换为数据",
|
|
3089
|
+
params: { json: "要转换的 JSON 字符串", fallback: "如果转换失败,返回的默认值" },
|
|
3090
|
+
paramsType: { json: "string", fallback: "any" },
|
|
3091
|
+
returnsType: "any",
|
|
3092
|
+
examples: [`from_json('{"a":1}') // (a: 1)`]
|
|
3093
|
+
}
|
|
3094
|
+
);
|
|
3095
|
+
|
|
3096
|
+
// src/vm/lib/global/to-primitive.ts
|
|
3097
|
+
var to_string = VmLib(
|
|
3098
|
+
(data, fallback) => {
|
|
3099
|
+
required("data", data, "");
|
|
3100
|
+
return toString(data, fallback);
|
|
3101
|
+
},
|
|
3102
|
+
{
|
|
3103
|
+
summary: "将数据转换为字符串",
|
|
3104
|
+
params: {
|
|
3105
|
+
data: "要转换的数据",
|
|
3106
|
+
fallback: "转换失败时的返回值"
|
|
3107
|
+
},
|
|
3108
|
+
paramsType: { data: "any", fallback: "any" },
|
|
3109
|
+
returnsType: "string | type(fallback)",
|
|
3110
|
+
examples: ['to_string([1, 2]) // "1, 2"']
|
|
3111
|
+
}
|
|
3112
|
+
);
|
|
3113
|
+
var to_number = VmLib(
|
|
3114
|
+
(data, fallback) => {
|
|
3115
|
+
required("data", data, NotNumber);
|
|
3116
|
+
return toNumber(data, fallback);
|
|
3117
|
+
},
|
|
3118
|
+
{
|
|
3119
|
+
summary: "将数据转换为数字",
|
|
3120
|
+
params: {
|
|
3121
|
+
data: "要转换的数据",
|
|
3122
|
+
fallback: "转换失败时的返回值"
|
|
3123
|
+
},
|
|
3124
|
+
paramsType: { data: "string | number | boolean", fallback: "any" },
|
|
3125
|
+
returnsType: "number | type(fallback)",
|
|
3126
|
+
examples: ['to_number("1.5") // 1.5']
|
|
3127
|
+
}
|
|
3128
|
+
);
|
|
3129
|
+
var format = VmLib(
|
|
3130
|
+
(data, format2) => {
|
|
3131
|
+
required("data", data, "");
|
|
3132
|
+
return toFormat(data, expectString("format", format2));
|
|
3133
|
+
},
|
|
3134
|
+
{
|
|
3135
|
+
summary: "将数据格式化为指定格式的字符串",
|
|
3136
|
+
params: { data: "要格式化的数据", format: "格式字符串" },
|
|
3137
|
+
paramsType: { data: "any", format: "string" },
|
|
3138
|
+
returnsType: "string",
|
|
3139
|
+
examples: ['format(12, ".3") // "12.000"']
|
|
3140
|
+
}
|
|
3141
|
+
);
|
|
3142
|
+
|
|
3143
|
+
// src/vm/lib/global/string/trim.ts
|
|
3144
|
+
var trim_start = VmLib(
|
|
3145
|
+
(str) => {
|
|
3146
|
+
return expectString("str", str).trimStart();
|
|
3147
|
+
},
|
|
3148
|
+
{
|
|
3149
|
+
summary: "去除字符串开头的空白字符",
|
|
3150
|
+
params: { str: "要处理的字符串" },
|
|
3151
|
+
paramsType: { str: "string" },
|
|
3152
|
+
returnsType: "string",
|
|
3153
|
+
examples: ['trim_start(" mira") // "mira"']
|
|
3154
|
+
}
|
|
3155
|
+
);
|
|
3156
|
+
var trim_end = VmLib(
|
|
3157
|
+
(str) => {
|
|
3158
|
+
return expectString("str", str).trimEnd();
|
|
3159
|
+
},
|
|
3160
|
+
{
|
|
3161
|
+
summary: "去除字符串结尾的空白字符",
|
|
3162
|
+
params: { str: "要处理的字符串" },
|
|
3163
|
+
paramsType: { str: "string" },
|
|
3164
|
+
returnsType: "string",
|
|
3165
|
+
examples: ['trim_end("mira ") // "mira"']
|
|
3166
|
+
}
|
|
3167
|
+
);
|
|
3168
|
+
var trim = VmLib(
|
|
3169
|
+
(str) => {
|
|
3170
|
+
return expectString("str", str).trim();
|
|
3171
|
+
},
|
|
3172
|
+
{
|
|
3173
|
+
summary: "去除字符串两端的空白字符",
|
|
3174
|
+
params: { str: "要处理的字符串" },
|
|
3175
|
+
paramsType: { str: "string" },
|
|
3176
|
+
returnsType: "string",
|
|
3177
|
+
examples: ['trim(" mira ") // "mira"']
|
|
3178
|
+
}
|
|
3179
|
+
);
|
|
3180
|
+
|
|
3181
|
+
// src/vm/lib/global/string/case.ts
|
|
3182
|
+
var to_uppercase = VmLib(
|
|
3183
|
+
(str) => {
|
|
3184
|
+
return expectString("str", str).toUpperCase();
|
|
3185
|
+
},
|
|
3186
|
+
{
|
|
3187
|
+
summary: "将字符串转换为大写",
|
|
3188
|
+
params: { str: "要转换的字符串" },
|
|
3189
|
+
paramsType: { str: "string" },
|
|
3190
|
+
returnsType: "string",
|
|
3191
|
+
examples: ['to_uppercase("mira") // "MIRA"']
|
|
3192
|
+
}
|
|
3193
|
+
);
|
|
3194
|
+
var to_lowercase = VmLib(
|
|
3195
|
+
(str) => {
|
|
3196
|
+
return expectString("str", str).toLowerCase();
|
|
3197
|
+
},
|
|
3198
|
+
{
|
|
3199
|
+
summary: "将字符串转换为小写",
|
|
3200
|
+
params: { str: "要转换的字符串" },
|
|
3201
|
+
paramsType: { str: "string" },
|
|
3202
|
+
returnsType: "string",
|
|
3203
|
+
examples: ['to_lowercase("MIRA") // "mira"']
|
|
3204
|
+
}
|
|
3205
|
+
);
|
|
3206
|
+
|
|
3207
|
+
// src/vm/lib/global/string/search.ts
|
|
3208
|
+
var starts_with = VmLib(
|
|
3209
|
+
(str, search) => {
|
|
3210
|
+
return expectString("str", str).startsWith(expectString("search", search));
|
|
3211
|
+
},
|
|
3212
|
+
{
|
|
3213
|
+
summary: "检查字符串是否以指定子串开头",
|
|
3214
|
+
params: { str: "要检查的字符串", search: "要匹配的子串" },
|
|
3215
|
+
paramsType: { str: "string", search: "string" },
|
|
3216
|
+
returnsType: "boolean",
|
|
3217
|
+
examples: ['starts_with("mira", "mi") // true']
|
|
3218
|
+
}
|
|
3219
|
+
);
|
|
3220
|
+
var ends_with = VmLib(
|
|
3221
|
+
(str, search) => {
|
|
3222
|
+
return expectString("str", str).endsWith(expectString("search", search));
|
|
3223
|
+
},
|
|
3224
|
+
{
|
|
3225
|
+
summary: "检查字符串是否以指定子串结尾",
|
|
3226
|
+
params: { str: "要检查的字符串", search: "要匹配的子串" },
|
|
3227
|
+
paramsType: { str: "string", search: "string" },
|
|
3228
|
+
returnsType: "boolean",
|
|
3229
|
+
examples: ['ends_with("mira", "ra") // true']
|
|
3230
|
+
}
|
|
3231
|
+
);
|
|
3232
|
+
var contains = VmLib(
|
|
3233
|
+
(str, search) => {
|
|
3234
|
+
return expectString("str", str).includes(expectString("search", search));
|
|
3235
|
+
},
|
|
3236
|
+
{
|
|
3237
|
+
summary: "检查字符串是否包含指定子串",
|
|
3238
|
+
params: { str: "要检查的字符串", search: "要匹配的子串" },
|
|
3239
|
+
paramsType: { str: "string", search: "string" },
|
|
3240
|
+
returnsType: "boolean",
|
|
3241
|
+
examples: ['contains("hello", "ll") // true']
|
|
3242
|
+
}
|
|
3243
|
+
);
|
|
3244
|
+
|
|
3245
|
+
// src/vm/lib/global/string/index.ts
|
|
3246
|
+
var chars = VmLib(
|
|
3247
|
+
(str) => {
|
|
3248
|
+
return Array.from(expectString("str", str));
|
|
3249
|
+
},
|
|
3250
|
+
{
|
|
3251
|
+
summary: "将字符串转换为字符数组",
|
|
3252
|
+
params: { str: "要转换的字符串" },
|
|
3253
|
+
paramsType: { str: "string" },
|
|
3254
|
+
returnsType: "string[]",
|
|
3255
|
+
examples: ['chars("Mira") // ["M", "i", "r", "a"]']
|
|
3256
|
+
}
|
|
3257
|
+
);
|
|
3258
|
+
var replace = VmLib(
|
|
3259
|
+
(str, search, replacement = "") => {
|
|
3260
|
+
return expectString("str", str).replaceAll(
|
|
3261
|
+
expectString("search", search),
|
|
3262
|
+
expectString("replacement", replacement)
|
|
3263
|
+
);
|
|
3264
|
+
},
|
|
3265
|
+
{
|
|
3266
|
+
summary: "替换字符串中的指定子串",
|
|
3267
|
+
params: { str: "要处理的字符串", search: "要替换的子串", replacement: "替换后的字符串" },
|
|
3268
|
+
paramsType: { str: "string", search: "string", replacement: "string" },
|
|
3269
|
+
returnsType: "string",
|
|
3270
|
+
examples: ['replace("foo bar foo", "foo", "baz") // "baz bar baz"']
|
|
3271
|
+
}
|
|
3272
|
+
);
|
|
3273
|
+
var split = VmLib(
|
|
3274
|
+
(str, separator = "") => {
|
|
3275
|
+
const s2 = expectString("str", str);
|
|
3276
|
+
const p = expectString("separator", separator);
|
|
3277
|
+
if (!p) return [...s2];
|
|
3278
|
+
return s2.split(p);
|
|
3279
|
+
},
|
|
3280
|
+
{
|
|
3281
|
+
summary: "将字符串拆分为子串数组",
|
|
3282
|
+
params: { str: "要拆分的字符串", separator: "分隔符" },
|
|
3283
|
+
paramsType: { str: "string", separator: "string" },
|
|
3284
|
+
returnsType: "string[]",
|
|
3285
|
+
examples: ['split("a,b,c", ",") // ["a", "b", "c"]']
|
|
3286
|
+
}
|
|
3287
|
+
);
|
|
3288
|
+
var join = VmLib(
|
|
3289
|
+
(arr, separator = "") => {
|
|
3290
|
+
expectArray("arr", arr, null);
|
|
3291
|
+
const s2 = expectString("separator", separator);
|
|
3292
|
+
return arr.map((v) => expectString(null, v)).join(s2);
|
|
3293
|
+
},
|
|
3294
|
+
{
|
|
3295
|
+
summary: "将字符串数组连接为单个字符串",
|
|
3296
|
+
params: { arr: "要连接的字符串数组", separator: "分隔符" },
|
|
3297
|
+
paramsType: { arr: "string[]", separator: "string" },
|
|
3298
|
+
returnsType: "string",
|
|
3299
|
+
examples: ['join(["a", "b", "c"], "-") // "a-b-c"']
|
|
3300
|
+
}
|
|
3301
|
+
);
|
|
3302
|
+
|
|
3303
|
+
// src/vm/lib/global/time.ts
|
|
3304
|
+
var fromNumber = (datetime, fallback) => {
|
|
3305
|
+
const n = new Date(datetime).getTime();
|
|
3306
|
+
if (isFinite(n)) return n;
|
|
3307
|
+
if (fallback) return null;
|
|
3308
|
+
throwError(`${describeParam("datetime")} is an invalid timestamp: ${display(datetime)}`, NotNumber);
|
|
3309
|
+
};
|
|
3310
|
+
var getTimestamp = (datetime, fallback) => {
|
|
3311
|
+
if (datetime == null) {
|
|
3312
|
+
return Date.now();
|
|
3313
|
+
}
|
|
3314
|
+
if (typeof datetime == "number") {
|
|
3315
|
+
return fromNumber(datetime, fallback);
|
|
3316
|
+
}
|
|
3317
|
+
if (typeof datetime != "string") {
|
|
3318
|
+
if (fallback) return null;
|
|
3319
|
+
throwUnexpectedTypeError("datetime", "number | string", datetime, NotNumber);
|
|
3320
|
+
}
|
|
3321
|
+
const num2 = toNumber(datetime, NotNumber);
|
|
3322
|
+
if (!isNaN(num2)) {
|
|
3323
|
+
return fromNumber(num2, fallback);
|
|
3324
|
+
}
|
|
3325
|
+
const parsed = Date.parse(datetime);
|
|
3326
|
+
if (isFinite(parsed)) return parsed;
|
|
3327
|
+
if (fallback) return null;
|
|
3328
|
+
throwError(`${describeParam("datetime")} cannot be parsed as datetime: ${display(datetime)}`, NotNumber);
|
|
3329
|
+
};
|
|
3330
|
+
var to_timestamp = VmLib(
|
|
3331
|
+
(datetime, fallback) => {
|
|
3332
|
+
const timestamp2 = getTimestamp(datetime, fallback !== void 0);
|
|
3333
|
+
if (timestamp2 == null) return fallback;
|
|
3334
|
+
return timestamp2;
|
|
3335
|
+
},
|
|
3336
|
+
{
|
|
3337
|
+
summary: "将数据转换为 Unix 毫秒时间戳",
|
|
3338
|
+
params: {
|
|
3339
|
+
datetime: "要转换的数据,默认为当前时间",
|
|
3340
|
+
fallback: "转换失败时的返回值"
|
|
3341
|
+
},
|
|
3342
|
+
paramsType: { datetime: "number | string | nil", fallback: "any" },
|
|
3343
|
+
returnsType: "number | type(fallback)",
|
|
3344
|
+
examples: ['to_timestamp("1970-01-01T00:00:00Z") // 0']
|
|
3345
|
+
}
|
|
3346
|
+
);
|
|
3347
|
+
var to_datetime = VmLib(
|
|
3348
|
+
(datetime, offset, fallback) => {
|
|
3349
|
+
const timestamp2 = getTimestamp(datetime, fallback !== void 0);
|
|
3350
|
+
if (timestamp2 == null) return fallback;
|
|
3351
|
+
const o = expectNumberRange("offset", offset ?? 0, -24, 24);
|
|
3352
|
+
const dateOffset = new Date(timestamp2 + o * 1e3 * 60 * 60);
|
|
3353
|
+
return {
|
|
3354
|
+
year: dateOffset.getUTCFullYear(),
|
|
3355
|
+
month: dateOffset.getUTCMonth() + 1,
|
|
3356
|
+
day: dateOffset.getUTCDate(),
|
|
3357
|
+
hour: dateOffset.getUTCHours(),
|
|
3358
|
+
minute: dateOffset.getUTCMinutes(),
|
|
3359
|
+
second: dateOffset.getUTCSeconds(),
|
|
3360
|
+
millisecond: dateOffset.getUTCMilliseconds(),
|
|
3361
|
+
dayOfWeek: dateOffset.getUTCDay(),
|
|
3362
|
+
offset: o
|
|
3363
|
+
};
|
|
3364
|
+
},
|
|
3365
|
+
{
|
|
3366
|
+
summary: "将数据转换为 DateTime 记录",
|
|
3367
|
+
params: {
|
|
3368
|
+
datetime: "要转换的数据,默认为当前时间",
|
|
3369
|
+
offset: "时区偏移量(单位:小时),默认为 0",
|
|
3370
|
+
fallback: "转换失败时的返回值"
|
|
3371
|
+
},
|
|
3372
|
+
paramsType: { datetime: "number | string | nil", offset: "number | nil", fallback: "any" },
|
|
3373
|
+
returnsType: "DateTime | type(fallback)",
|
|
3374
|
+
examples: [
|
|
3375
|
+
`
|
|
3376
|
+
to_datetime(0)
|
|
3377
|
+
// (
|
|
3378
|
+
// year: 1970, month: 1, day: 1,
|
|
3379
|
+
// hour: 0, minute: 0, second: 0,
|
|
3380
|
+
// millisecond: 0,
|
|
3381
|
+
// dayOfWeek: 4, offset: 0
|
|
3382
|
+
// )
|
|
3383
|
+
`.trim()
|
|
3384
|
+
]
|
|
3385
|
+
}
|
|
3386
|
+
);
|
|
3387
|
+
var to_iso8601 = VmLib(
|
|
3388
|
+
(datetime, fallback) => {
|
|
3389
|
+
const timestamp2 = getTimestamp(datetime, fallback !== void 0);
|
|
3390
|
+
if (timestamp2 == null) return fallback;
|
|
3391
|
+
return new Date(timestamp2).toISOString();
|
|
3392
|
+
},
|
|
3393
|
+
{
|
|
3394
|
+
summary: "将数据转换为 ISO 8601 格式的字符串",
|
|
3395
|
+
params: {
|
|
3396
|
+
datetime: "要转换的数据,默认为当前时间",
|
|
3397
|
+
fallback: "转换失败时的返回值"
|
|
3398
|
+
},
|
|
3399
|
+
paramsType: { datetime: "number | string | nil", fallback: "any" },
|
|
3400
|
+
returnsType: "string | type(fallback)",
|
|
3401
|
+
examples: ['to_iso8601(0) // "1970-01-01T00:00:00.000Z"']
|
|
3402
|
+
}
|
|
3403
|
+
);
|
|
3404
|
+
|
|
3405
|
+
// src/vm/lib/mod/index.ts
|
|
3406
|
+
var mod_exports = {};
|
|
3407
|
+
__export(mod_exports, {
|
|
3408
|
+
matrix: () => matrix_exports
|
|
3409
|
+
});
|
|
3410
|
+
|
|
3411
|
+
// src/vm/lib/mod/matrix.ts
|
|
3412
|
+
var matrix_exports = {};
|
|
3413
|
+
__export(matrix_exports, {
|
|
3414
|
+
add: () => add,
|
|
3415
|
+
diagonal: () => diagonal,
|
|
3416
|
+
entrywise: () => entrywise,
|
|
3417
|
+
entrywise_divide: () => entrywise_divide,
|
|
3418
|
+
entrywise_multiply: () => entrywise_multiply,
|
|
3419
|
+
identity: () => identity,
|
|
3420
|
+
invert: () => invert,
|
|
3421
|
+
multiply: () => multiply,
|
|
3422
|
+
ones: () => ones,
|
|
3423
|
+
size: () => size,
|
|
3424
|
+
subtract: () => subtract,
|
|
3425
|
+
transpose: () => transpose,
|
|
3426
|
+
zeros: () => zeros
|
|
3427
|
+
});
|
|
3428
|
+
function sizeImpl(matrix) {
|
|
3429
|
+
if (!isVmArray(matrix)) return [];
|
|
3430
|
+
if (matrix.length === 0) return [0];
|
|
3431
|
+
const numRows = matrix.length;
|
|
3432
|
+
let numCols = 0;
|
|
3433
|
+
for (const row of matrix) {
|
|
3434
|
+
if (isVmArray(row)) {
|
|
3435
|
+
numCols = Math.max(numCols, row.length);
|
|
3436
|
+
} else {
|
|
3437
|
+
return [numRows];
|
|
3438
|
+
}
|
|
3439
|
+
}
|
|
3440
|
+
return [numRows, numCols];
|
|
3441
|
+
}
|
|
3442
|
+
function num(v) {
|
|
3443
|
+
return toNumber(v, void 0);
|
|
3444
|
+
}
|
|
3445
|
+
var size = VmLib(
|
|
3446
|
+
(matrix) => {
|
|
3447
|
+
required("matrix", matrix, []);
|
|
3448
|
+
return sizeImpl(matrix);
|
|
3449
|
+
},
|
|
3450
|
+
{
|
|
3451
|
+
summary: "获取矩阵尺寸",
|
|
3452
|
+
params: { matrix: "要获取尺寸的矩阵" },
|
|
3453
|
+
paramsType: { matrix: "any[][]" },
|
|
3454
|
+
returnsType: "[number, number]",
|
|
3455
|
+
examples: ["matrix.size([[1, 2], [3, 4]]) // [2, 2]"]
|
|
3456
|
+
}
|
|
3457
|
+
);
|
|
3458
|
+
var transpose = VmLib(
|
|
3459
|
+
(matrix) => {
|
|
3460
|
+
required("matrix", matrix, []);
|
|
3461
|
+
const [numRows, numCols] = sizeImpl(matrix);
|
|
3462
|
+
if (numRows == null || numCols == null) return matrix;
|
|
3463
|
+
const transposed = [];
|
|
3464
|
+
for (let j = 0; j < numCols; j++) {
|
|
3465
|
+
Cp();
|
|
3466
|
+
const tj = [];
|
|
3467
|
+
for (let i = 0; i < numRows; i++) {
|
|
3468
|
+
const row = matrix[i] ?? null;
|
|
3469
|
+
const item = row?.[j] ?? null;
|
|
3470
|
+
tj[i] = item;
|
|
3471
|
+
}
|
|
3472
|
+
transposed[j] = tj;
|
|
3473
|
+
}
|
|
3474
|
+
return transposed;
|
|
3475
|
+
},
|
|
3476
|
+
{
|
|
3477
|
+
summary: "转置矩阵",
|
|
3478
|
+
params: { matrix: "要转置的矩阵" },
|
|
3479
|
+
paramsType: { matrix: "any[][]" },
|
|
3480
|
+
returnsType: "any[][]",
|
|
3481
|
+
examples: ["matrix.transpose([[1, 2], [3, 4]]) // [[1, 3], [2, 4]]"]
|
|
3482
|
+
}
|
|
3483
|
+
);
|
|
3484
|
+
function entrywiseImpl(a, b, f, vvf, mmf, vmf, mvf) {
|
|
3485
|
+
let [ar, ac] = sizeImpl(a);
|
|
3486
|
+
let [br, bc] = sizeImpl(b);
|
|
3487
|
+
if (ar == null) {
|
|
3488
|
+
if (br == null) {
|
|
3489
|
+
return f(a, b);
|
|
3490
|
+
} else if (bc == null) {
|
|
3491
|
+
const result2 = [];
|
|
3492
|
+
for (let r = 0; r < br; r++) {
|
|
3493
|
+
const bItem = b[r] ?? null;
|
|
3494
|
+
result2[r] = f(a, bItem);
|
|
3495
|
+
}
|
|
3496
|
+
return result2;
|
|
3497
|
+
} else {
|
|
3498
|
+
const result2 = [];
|
|
3499
|
+
for (let r = 0; r < br; r++) {
|
|
3500
|
+
const bRow = b[r] ?? [];
|
|
3501
|
+
const rRow = [];
|
|
3502
|
+
result2[r] = rRow;
|
|
3503
|
+
for (let c = 0; c < bc; c++) {
|
|
3504
|
+
const bItem = bRow[c] ?? null;
|
|
3505
|
+
rRow[c] = f(a, bItem);
|
|
3506
|
+
}
|
|
3507
|
+
}
|
|
3508
|
+
return result2;
|
|
3509
|
+
}
|
|
3510
|
+
}
|
|
3511
|
+
if (br == null) {
|
|
3512
|
+
if (ac == null) {
|
|
3513
|
+
const result2 = [];
|
|
3514
|
+
for (let r = 0; r < ar; r++) {
|
|
3515
|
+
const aItem = a[r] ?? null;
|
|
3516
|
+
result2[r] = f(aItem, b);
|
|
3517
|
+
}
|
|
3518
|
+
return result2;
|
|
3519
|
+
} else {
|
|
3520
|
+
const result2 = [];
|
|
3521
|
+
for (let r = 0; r < ar; r++) {
|
|
3522
|
+
const aRow = a[r] ?? [];
|
|
3523
|
+
const rRow = [];
|
|
3524
|
+
result2[r] = rRow;
|
|
3525
|
+
for (let c = 0; c < ac; c++) {
|
|
3526
|
+
const aItem = aRow[c] ?? null;
|
|
3527
|
+
rRow[c] = f(aItem, b);
|
|
3528
|
+
}
|
|
3529
|
+
}
|
|
3530
|
+
return result2;
|
|
3531
|
+
}
|
|
3532
|
+
}
|
|
3533
|
+
if (ac == null && bc == null) {
|
|
3534
|
+
if (vvf != null) {
|
|
3535
|
+
return vvf(a, b, ar, br);
|
|
3536
|
+
}
|
|
3537
|
+
const rr2 = Math.max(ar, br);
|
|
3538
|
+
const result2 = [];
|
|
3539
|
+
for (let r = 0; r < rr2; r++) {
|
|
3540
|
+
const aItem = a[r] ?? null;
|
|
3541
|
+
const bItem = b[r] ?? null;
|
|
3542
|
+
result2[r] = f(aItem, bItem);
|
|
3543
|
+
}
|
|
3544
|
+
return result2;
|
|
3545
|
+
}
|
|
3546
|
+
if (ac == null) {
|
|
3547
|
+
if (vmf != null) {
|
|
3548
|
+
return vmf(a, b, ar, br, bc);
|
|
3549
|
+
}
|
|
3550
|
+
ac = ar;
|
|
3551
|
+
ar = 1;
|
|
3552
|
+
a = [a];
|
|
3553
|
+
}
|
|
3554
|
+
if (bc == null) {
|
|
3555
|
+
if (mvf != null) {
|
|
3556
|
+
return mvf(a, b, ar, ac, br);
|
|
3557
|
+
}
|
|
3558
|
+
bc = br;
|
|
3559
|
+
br = 1;
|
|
3560
|
+
b = [b];
|
|
3561
|
+
}
|
|
3562
|
+
if (mmf != null) {
|
|
3563
|
+
return mmf(a, b, ar, ac, br, bc);
|
|
3564
|
+
}
|
|
3565
|
+
const rr = Math.max(ar, br);
|
|
3566
|
+
const rc = Math.max(ac, bc);
|
|
3567
|
+
const result = [];
|
|
3568
|
+
for (let r = 0; r < rr; r++) {
|
|
3569
|
+
const rRow = [];
|
|
3570
|
+
result[r] = rRow;
|
|
3571
|
+
for (let c = 0; c < rc; c++) {
|
|
3572
|
+
const aItem = a[ar === 1 ? 0 : r]?.[ac === 1 ? 0 : c] ?? null;
|
|
3573
|
+
const bItem = b[br === 1 ? 0 : r]?.[bc === 1 ? 0 : c] ?? null;
|
|
3574
|
+
rRow[c] = f(aItem, bItem);
|
|
3575
|
+
}
|
|
3576
|
+
}
|
|
3577
|
+
return result;
|
|
3578
|
+
}
|
|
3579
|
+
var entrywise = VmLib(
|
|
3580
|
+
(a, b, f) => {
|
|
3581
|
+
expectConst("a", a, null);
|
|
3582
|
+
expectConst("b", b, null);
|
|
3583
|
+
expectCallable("f", f, null);
|
|
3584
|
+
return entrywiseImpl(a, b, (a2, b2) => {
|
|
3585
|
+
Cp();
|
|
3586
|
+
const ret = $Call(f, [a2, b2]);
|
|
3587
|
+
if (!isVmConst(ret)) return null;
|
|
3588
|
+
return ret;
|
|
3589
|
+
});
|
|
3590
|
+
},
|
|
3591
|
+
{
|
|
3592
|
+
summary: "逐项操作",
|
|
3593
|
+
params: { a: "第一个操作数", b: "第二个操作数", f: "操作函数" },
|
|
3594
|
+
paramsType: { a: "any | any[] | any[][]", b: "any | any[] | any[][]", f: "fn(a: any, b: any) -> any" },
|
|
3595
|
+
returnsType: "any | any[] | any[][]",
|
|
3596
|
+
examples: [`matrix.entrywise([1, 2], [3, 4], fn (x, y) { x + y }) // [4, 6]`]
|
|
3597
|
+
}
|
|
3598
|
+
);
|
|
3599
|
+
var add = VmLib(
|
|
3600
|
+
(a, b) => {
|
|
3601
|
+
expectConst("a", a, null);
|
|
3602
|
+
expectConst("b", b, null);
|
|
3603
|
+
return entrywiseImpl(a, b, $Add);
|
|
3604
|
+
},
|
|
3605
|
+
{
|
|
3606
|
+
summary: "逐项相加",
|
|
3607
|
+
params: { a: "第一个操作数", b: "第二个操作数" },
|
|
3608
|
+
paramsType: { a: "number | number[] | number[][]", b: "number | number[] | number[][]" },
|
|
3609
|
+
returnsType: "number | number[] | number[][]",
|
|
3610
|
+
examples: ["matrix.add([1, 2], [3, 4]) // [4, 6]"]
|
|
3611
|
+
}
|
|
3612
|
+
);
|
|
3613
|
+
var subtract = VmLib(
|
|
3614
|
+
(a, b) => {
|
|
3615
|
+
expectConst("a", a, null);
|
|
3616
|
+
expectConst("b", b, null);
|
|
3617
|
+
return entrywiseImpl(a, b, $Sub);
|
|
3618
|
+
},
|
|
3619
|
+
{
|
|
3620
|
+
summary: "逐项相减",
|
|
3621
|
+
params: { a: "第一个操作数", b: "第二个操作数" },
|
|
3622
|
+
paramsType: { a: "number | number[] | number[][]", b: "number | number[] | number[][]" },
|
|
3623
|
+
returnsType: "number | number[] | number[][]",
|
|
3624
|
+
examples: ["matrix.subtract([3, 4], [1, 2]) // [2, 2]"]
|
|
3625
|
+
}
|
|
3626
|
+
);
|
|
3627
|
+
var entrywise_multiply = VmLib(
|
|
3628
|
+
(a, b) => {
|
|
3629
|
+
expectConst("a", a, null);
|
|
3630
|
+
expectConst("b", b, null);
|
|
3631
|
+
return entrywiseImpl(a, b, $Mul);
|
|
3632
|
+
},
|
|
3633
|
+
{
|
|
3634
|
+
summary: "逐项相乘",
|
|
3635
|
+
params: { a: "第一个操作数", b: "第二个操作数" },
|
|
3636
|
+
paramsType: { a: "number | number[] | number[][]", b: "number | number[] | number[][]" },
|
|
3637
|
+
returnsType: "number | number[] | number[][]",
|
|
3638
|
+
examples: ["matrix.entrywise_multiply([1, 2], [3, 4]) // [3, 8]"]
|
|
3639
|
+
}
|
|
3640
|
+
);
|
|
3641
|
+
var entrywise_divide = VmLib(
|
|
3642
|
+
(a, b) => {
|
|
3643
|
+
expectConst("a", a, null);
|
|
3644
|
+
expectConst("b", b, null);
|
|
3645
|
+
return entrywiseImpl(a, b, $Div);
|
|
3646
|
+
},
|
|
3647
|
+
{
|
|
3648
|
+
summary: "逐项相除",
|
|
3649
|
+
params: { a: "第一个操作数", b: "第二个操作数" },
|
|
3650
|
+
paramsType: { a: "number | number[] | number[][]", b: "number | number[] | number[][]" },
|
|
3651
|
+
returnsType: "number | number[] | number[][]",
|
|
3652
|
+
examples: ["matrix.entrywise_divide([4, 6], [2, 3]) // [2, 2]"]
|
|
3653
|
+
}
|
|
3654
|
+
);
|
|
3655
|
+
var multiply = VmLib(
|
|
3656
|
+
(a, b) => {
|
|
3657
|
+
expectConst("a", a, null);
|
|
3658
|
+
expectConst("b", b, null);
|
|
3659
|
+
return entrywiseImpl(
|
|
3660
|
+
a,
|
|
3661
|
+
b,
|
|
3662
|
+
$Mul,
|
|
3663
|
+
(a2, b2, al, bl) => {
|
|
3664
|
+
const l = Math.max(al, bl);
|
|
3665
|
+
let s2 = 0;
|
|
3666
|
+
for (let i = 0; i < l; i++) {
|
|
3667
|
+
s2 += num(a2[i]) * num(b2[i]);
|
|
3668
|
+
}
|
|
3669
|
+
return s2;
|
|
3670
|
+
},
|
|
3671
|
+
(a2, b2, ar, ac, br, bc) => {
|
|
3672
|
+
if (ac !== br) throwError(`Incompatible matrix dimensions`, null);
|
|
3673
|
+
const result = [];
|
|
3674
|
+
for (let r = 0; r < ar; r++) {
|
|
3675
|
+
const rRow = [];
|
|
3676
|
+
result[r] = rRow;
|
|
3677
|
+
for (let c = 0; c < bc; c++) {
|
|
3678
|
+
let item = 0;
|
|
3679
|
+
for (let k = 0; k < ac; k++) {
|
|
3680
|
+
item += num(a2[r]?.[k]) * num(b2[k]?.[c]);
|
|
3681
|
+
}
|
|
3682
|
+
rRow[c] = item;
|
|
3683
|
+
}
|
|
3684
|
+
}
|
|
3685
|
+
return result;
|
|
3686
|
+
},
|
|
3687
|
+
(a2, b2, al, br, bc) => {
|
|
3688
|
+
if (al !== br) throwError(`Incompatible matrix dimensions`, null);
|
|
3689
|
+
const result = [];
|
|
3690
|
+
for (let c = 0; c < bc; c++) {
|
|
3691
|
+
let item = 0;
|
|
3692
|
+
for (let k = 0; k < al; k++) {
|
|
3693
|
+
item += num(a2[k]) * num(b2[k]?.[c]);
|
|
3694
|
+
}
|
|
3695
|
+
result[c] = item;
|
|
3696
|
+
}
|
|
3697
|
+
return result;
|
|
3698
|
+
},
|
|
3699
|
+
(a2, b2, ar, ac, bl) => {
|
|
3700
|
+
if (ac !== bl) throwError(`Incompatible matrix dimensions`, null);
|
|
3701
|
+
const result = [];
|
|
3702
|
+
for (let r = 0; r < ar; r++) {
|
|
3703
|
+
let item = 0;
|
|
3704
|
+
for (let k = 0; k < ac; k++) {
|
|
3705
|
+
item += num(a2[r]?.[k]) * num(b2[k]);
|
|
3706
|
+
}
|
|
3707
|
+
result[r] = item;
|
|
3708
|
+
}
|
|
3709
|
+
return result;
|
|
3710
|
+
}
|
|
3711
|
+
);
|
|
3712
|
+
},
|
|
3713
|
+
{
|
|
3714
|
+
summary: "矩阵相乘",
|
|
3715
|
+
params: { a: "第一个操作数", b: "第二个操作数" },
|
|
3716
|
+
paramsType: { a: "number | number[] | number[][]", b: "number | number[] | number[][]" },
|
|
3717
|
+
returnsType: "number | number[] | number[][]",
|
|
3718
|
+
examples: ["matrix.multiply([[1, 2], [3, 4]], [5, 6]) // [17, 39]"]
|
|
3719
|
+
}
|
|
3720
|
+
);
|
|
3721
|
+
var invert = VmLib(
|
|
3722
|
+
(a) => {
|
|
3723
|
+
expectConst("a", a, null);
|
|
3724
|
+
const [rows, cols] = sizeImpl(a);
|
|
3725
|
+
if (rows == null) return 1 / num(a);
|
|
3726
|
+
if (cols == null) return map(a, (v) => 1 / num(v));
|
|
3727
|
+
if (rows !== cols) throwError(`Matrix must be square`, a);
|
|
3728
|
+
const m = a;
|
|
3729
|
+
if (rows === 1) {
|
|
3730
|
+
const e2 = num(m[0]?.[0]);
|
|
3731
|
+
return [[1 / e2]];
|
|
3732
|
+
}
|
|
3733
|
+
if (rows === 2) {
|
|
3734
|
+
const a2 = num(m[0]?.[0]);
|
|
3735
|
+
const b = num(m[0]?.[1]);
|
|
3736
|
+
const c = num(m[1]?.[0]);
|
|
3737
|
+
const d = num(m[1]?.[1]);
|
|
3738
|
+
const det = a2 * d - b * c;
|
|
3739
|
+
return [
|
|
3740
|
+
[d / det, -b / det],
|
|
3741
|
+
[-c / det, a2 / det]
|
|
3742
|
+
];
|
|
3743
|
+
}
|
|
3744
|
+
const A = [];
|
|
3745
|
+
const B = [];
|
|
3746
|
+
for (let r = 0; r < rows; r++) {
|
|
3747
|
+
const Ar = [];
|
|
3748
|
+
const Br = [];
|
|
3749
|
+
A[r] = Ar;
|
|
3750
|
+
B[r] = Br;
|
|
3751
|
+
for (let c = 0; c < cols; c++) {
|
|
3752
|
+
Ar[c] = num(m[r]?.[c]);
|
|
3753
|
+
Br[c] = r === c ? 1 : 0;
|
|
3754
|
+
}
|
|
3755
|
+
}
|
|
3756
|
+
for (let c = 0; c < cols; c++) {
|
|
3757
|
+
let ABig = Math.abs(A[c][c]);
|
|
3758
|
+
let rBig = c;
|
|
3759
|
+
let r = c + 1;
|
|
3760
|
+
while (r < rows) {
|
|
3761
|
+
if (Math.abs(A[r][c]) > ABig) {
|
|
3762
|
+
ABig = Math.abs(A[r][c]);
|
|
3763
|
+
rBig = r;
|
|
3764
|
+
}
|
|
3765
|
+
r++;
|
|
3766
|
+
}
|
|
3767
|
+
r = rBig;
|
|
3768
|
+
if (r !== c) {
|
|
3769
|
+
const temp1 = A[c];
|
|
3770
|
+
A[c] = A[r];
|
|
3771
|
+
A[r] = temp1;
|
|
3772
|
+
const temp2 = B[c];
|
|
3773
|
+
B[c] = B[r];
|
|
3774
|
+
B[r] = temp2;
|
|
3775
|
+
}
|
|
3776
|
+
const Ac = A[c];
|
|
3777
|
+
const Bc = B[c];
|
|
3778
|
+
for (r = 0; r < rows; r++) {
|
|
3779
|
+
const Ar = A[r];
|
|
3780
|
+
const Br = B[r];
|
|
3781
|
+
if (r !== c) {
|
|
3782
|
+
if (Ar[c] !== 0) {
|
|
3783
|
+
const f = -Ar[c] / Ac[c];
|
|
3784
|
+
for (let s2 = c; s2 < cols; s2++) {
|
|
3785
|
+
Ar[s2] = Ar[s2] + f * Ac[s2];
|
|
3786
|
+
}
|
|
3787
|
+
for (let s2 = 0; s2 < cols; s2++) {
|
|
3788
|
+
Br[s2] = Br[s2] + f * Bc[s2];
|
|
3789
|
+
}
|
|
3790
|
+
}
|
|
3791
|
+
} else {
|
|
3792
|
+
const f = Ac[c];
|
|
3793
|
+
for (let s2 = c; s2 < cols; s2++) {
|
|
3794
|
+
Ar[s2] = Ar[s2] / f;
|
|
3795
|
+
}
|
|
3796
|
+
for (let s2 = 0; s2 < cols; s2++) {
|
|
3797
|
+
Br[s2] = Br[s2] / f;
|
|
3798
|
+
}
|
|
3799
|
+
}
|
|
3800
|
+
}
|
|
3801
|
+
}
|
|
3802
|
+
return B;
|
|
3803
|
+
},
|
|
3804
|
+
{
|
|
3805
|
+
summary: "矩阵求逆",
|
|
3806
|
+
params: { a: "待求逆的矩阵" },
|
|
3807
|
+
paramsType: { a: "number | number[][]" },
|
|
3808
|
+
returnsType: "number | number[][]",
|
|
3809
|
+
examples: ["matrix.invert([[1, 2], [3, 4]]) // [[-2, 1], [1.5, -0.5]]"]
|
|
3810
|
+
}
|
|
3811
|
+
);
|
|
3812
|
+
function filled(size2, value) {
|
|
3813
|
+
const s2 = getNumbers(size2);
|
|
3814
|
+
if (s2.length === 0) return [];
|
|
3815
|
+
while (s2.length > 0) {
|
|
3816
|
+
const repeat2 = arrayLen(s2.pop());
|
|
3817
|
+
Cp();
|
|
3818
|
+
const data = [];
|
|
3819
|
+
data.length = repeat2;
|
|
3820
|
+
data.fill(value);
|
|
3821
|
+
value = data;
|
|
3822
|
+
}
|
|
3823
|
+
return value;
|
|
3824
|
+
}
|
|
3825
|
+
var zeros = VmLib((...size2) => filled(size2, 0), {
|
|
3826
|
+
summary: "创建一个全零的矩阵",
|
|
3827
|
+
params: { "..size": "矩阵的维度" },
|
|
3828
|
+
paramsType: { "..size": "number[]" },
|
|
3829
|
+
returnsType: "number[][]",
|
|
3830
|
+
examples: ["matrix.zeros(2, 3) // [[0, 0, 0], [0, 0, 0]]"]
|
|
3831
|
+
});
|
|
3832
|
+
var ones = VmLib((...size2) => filled(size2, 1), {
|
|
3833
|
+
summary: "创建一个全一的矩阵",
|
|
3834
|
+
params: { "..size": "矩阵的维度" },
|
|
3835
|
+
paramsType: { "..size": "number[]" },
|
|
3836
|
+
returnsType: "number[][]",
|
|
3837
|
+
examples: ["matrix.ones(2, 2) // [[1, 1], [1, 1]]"]
|
|
3838
|
+
});
|
|
3839
|
+
var identity = VmLib(
|
|
3840
|
+
(...size2) => {
|
|
3841
|
+
let s2 = getNumbers(size2);
|
|
3842
|
+
if (s2.length === 0) return [];
|
|
3843
|
+
if (s2.length > 2) throwError("Invalid matrix size", []);
|
|
3844
|
+
if (s2.length === 1) s2 = [s2[0], s2[0]];
|
|
3845
|
+
const m = arrayLen(s2[0]);
|
|
3846
|
+
const n = arrayLen(s2[1]);
|
|
3847
|
+
const ret = [];
|
|
3848
|
+
for (let i = 0; i < m; i++) {
|
|
3849
|
+
const row = [];
|
|
3850
|
+
ret[i] = row;
|
|
3851
|
+
row.length = n;
|
|
3852
|
+
row.fill(0);
|
|
3853
|
+
if (i < n) row[i] = 1;
|
|
3854
|
+
}
|
|
3855
|
+
return ret;
|
|
3856
|
+
},
|
|
3857
|
+
{
|
|
3858
|
+
summary: "创建一个单位矩阵",
|
|
3859
|
+
params: { "..size": "矩阵的维度" },
|
|
3860
|
+
paramsType: { "..size": "[number] | [number, number]" },
|
|
3861
|
+
returnsType: "number[][]",
|
|
3862
|
+
examples: ["matrix.identity(3) // [[1, 0, 0], [0, 1, 0], [0, 0, 1]]"]
|
|
3863
|
+
}
|
|
3864
|
+
);
|
|
3865
|
+
var diagonal = VmLib(
|
|
3866
|
+
(x, k = 0) => {
|
|
3867
|
+
expectArray("x", x, []);
|
|
3868
|
+
const fk = expectInteger("k", k);
|
|
3869
|
+
if (x.every((e2) => isArray(e2))) {
|
|
3870
|
+
const diag = [];
|
|
3871
|
+
for (let i = 0; i < x.length; i++) {
|
|
3872
|
+
const row = x[i];
|
|
3873
|
+
const r = i + fk;
|
|
3874
|
+
if (r < 0) continue;
|
|
3875
|
+
if (!row || r >= row.length) break;
|
|
3876
|
+
diag.push(row[r] ?? null);
|
|
3877
|
+
}
|
|
3878
|
+
return diag;
|
|
3879
|
+
}
|
|
3880
|
+
const l = x.length;
|
|
3881
|
+
const m = arrayLen(fk < 0 ? l - fk : l);
|
|
3882
|
+
const n = arrayLen(fk > 0 ? l + fk : l);
|
|
3883
|
+
const result = [];
|
|
3884
|
+
for (let i = 0; i < m; i++) {
|
|
3885
|
+
const row = [];
|
|
3886
|
+
result[i] = row;
|
|
3887
|
+
row.length = n;
|
|
3888
|
+
row.fill(0);
|
|
3889
|
+
for (let j = 0; j < n; j++) {
|
|
3890
|
+
if (i + fk === j) {
|
|
3891
|
+
row[j] = x[fk >= 0 ? i : j] ?? null;
|
|
3892
|
+
}
|
|
3893
|
+
}
|
|
3894
|
+
}
|
|
3895
|
+
return result;
|
|
3896
|
+
},
|
|
3897
|
+
{
|
|
3898
|
+
summary: "创建一个对角矩阵或获取矩阵的对角线",
|
|
3899
|
+
params: { x: "对角线元素或要获取对角线的矩阵", k: "对角线偏移量,默认为 0" },
|
|
3900
|
+
paramsType: { x: "number[] | number[][]", k: "number" },
|
|
3901
|
+
returnsType: "number[][] | number[]",
|
|
3902
|
+
examples: [
|
|
3903
|
+
"matrix.diagonal([1, 2, 3]) // [[1, 0, 0], [0, 2, 0], [0, 0, 3]]",
|
|
3904
|
+
"matrix.diagonal([[1, 2], [3, 4]]) // [1, 4]"
|
|
3905
|
+
]
|
|
3906
|
+
}
|
|
3907
|
+
);
|
|
3908
|
+
|
|
3909
|
+
// src/vm/lib/loader.ts
|
|
3910
|
+
var VmBuiltinModule = class extends VmModule {
|
|
3911
|
+
constructor(name, value, descriptions) {
|
|
3912
|
+
super(name, value);
|
|
3913
|
+
this.descriptions = descriptions;
|
|
3914
|
+
}
|
|
3915
|
+
/** @inheritdoc */
|
|
3916
|
+
describe(key) {
|
|
3917
|
+
return this.descriptions[key];
|
|
3918
|
+
}
|
|
3919
|
+
};
|
|
3920
|
+
function wrapEntry(name, value, module) {
|
|
3921
|
+
if (isVmModule(value)) {
|
|
3922
|
+
return [value, void 0];
|
|
3923
|
+
}
|
|
3924
|
+
if (typeof value != "function") {
|
|
3925
|
+
if (value == null || typeof value != "object" || !("value" in value)) {
|
|
3926
|
+
throw new TypeError(`Cannot wrap non-function, non-const value: ${name} in module ${module}`);
|
|
3927
|
+
}
|
|
3928
|
+
return [value.value, value.summary || void 0];
|
|
3929
|
+
}
|
|
3930
|
+
if (value.name !== name) {
|
|
3931
|
+
defineProperty(value, "name", { value: name });
|
|
3932
|
+
}
|
|
3933
|
+
defineProperty(value, "fullName", { enumerable: true, value: `${module}.${name}` });
|
|
3934
|
+
return [VmFunction(value, value), value.summary || void 0];
|
|
3935
|
+
}
|
|
3936
|
+
function createModule(name, lib2) {
|
|
3937
|
+
const mod = create(null);
|
|
3938
|
+
const descriptions = create(null);
|
|
3939
|
+
for (const [key, value] of entries(lib2)) {
|
|
3940
|
+
const [wrappedValue, description] = wrapEntry(key, value, name);
|
|
3941
|
+
mod[key] = wrappedValue;
|
|
3942
|
+
descriptions[key] = description;
|
|
3943
|
+
}
|
|
3944
|
+
return new VmBuiltinModule(name, mod, descriptions);
|
|
3945
|
+
}
|
|
3946
|
+
|
|
3947
|
+
// src/vm/lib/index.ts
|
|
3948
|
+
for (const [name, value] of entries(global_exports)) {
|
|
3949
|
+
const [wrappedValue, description] = wrapEntry(name, value, "global");
|
|
3950
|
+
VM_SHARED_CONTEXT[name] = wrappedValue;
|
|
3951
|
+
VM_SHARED_CONTEXT_DESCRIPTIONS[name] = description;
|
|
3952
|
+
}
|
|
3953
|
+
for (const [name, value] of entries(mod_exports)) {
|
|
3954
|
+
const mod = createModule(name, value);
|
|
3955
|
+
const [wrappedValue, description] = wrapEntry(name, mod, "global");
|
|
3956
|
+
VM_SHARED_CONTEXT[name] = wrappedValue;
|
|
3957
|
+
VM_SHARED_CONTEXT_DESCRIPTIONS[name] = description;
|
|
3958
|
+
}
|
|
3959
|
+
var lib = Object.freeze(Object.assign(create(null), global_exports, mod_exports));
|
|
3960
|
+
|
|
3961
|
+
export {
|
|
3962
|
+
convert_exports,
|
|
3963
|
+
VmExtern,
|
|
3964
|
+
wrapToVmValue,
|
|
3965
|
+
unwrapFromVmValue,
|
|
3966
|
+
configCheckpoint,
|
|
3967
|
+
VmFunction,
|
|
3968
|
+
defineVmContextValue,
|
|
3969
|
+
DefaultVmContext,
|
|
3970
|
+
createVmContext,
|
|
3971
|
+
VmModule,
|
|
3972
|
+
$GlobalFallback,
|
|
3973
|
+
operations_exports,
|
|
3974
|
+
wrapScript,
|
|
3975
|
+
createScript,
|
|
3976
|
+
reportDiagnostic,
|
|
3977
|
+
emitScript,
|
|
3978
|
+
lib
|
|
3979
|
+
};
|
|
3980
|
+
//# sourceMappingURL=chunk-6CAGNGY6.js.map
|