@mirascript/mirascript 0.1.0
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-5FQWUJIY.js +766 -0
- package/dist/chunk-5FQWUJIY.js.map +6 -0
- package/dist/chunk-BTDGMWFK.js +202 -0
- package/dist/chunk-BTDGMWFK.js.map +6 -0
- package/dist/chunk-DCXIWIW5.js +3419 -0
- package/dist/chunk-DCXIWIW5.js.map +6 -0
- package/dist/chunk-RAPJ3XLV.js +10 -0
- package/dist/chunk-RAPJ3XLV.js.map +6 -0
- package/dist/cli/execute.d.ts +4 -0
- package/dist/cli/execute.d.ts.map +1 -0
- package/dist/cli/index.d.ts +2 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +191 -0
- package/dist/cli/index.js.map +6 -0
- package/dist/cli/print.d.ts +4 -0
- package/dist/cli/print.d.ts.map +1 -0
- package/dist/compiler/compile-bytecode.d.ts +12 -0
- package/dist/compiler/compile-bytecode.d.ts.map +1 -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 +7 -0
- package/dist/compiler/create-script.d.ts.map +1 -0
- package/dist/compiler/diagnostic.d.ts +56 -0
- package/dist/compiler/diagnostic.d.ts.map +1 -0
- package/dist/compiler/emit.d.ts +4 -0
- package/dist/compiler/emit.d.ts.map +1 -0
- package/dist/compiler/index.d.ts +13 -0
- package/dist/compiler/index.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 +6 -0
- package/dist/compiler/worker-manager.d.ts.map +1 -0
- package/dist/compiler/worker.d.ts +6 -0
- package/dist/compiler/worker.d.ts.map +1 -0
- package/dist/compiler/worker.js +34 -0
- package/dist/compiler/worker.js.map +6 -0
- package/dist/helpers/constants.d.ts +3 -0
- package/dist/helpers/constants.d.ts.map +1 -0
- package/dist/helpers/serialize.d.ts +45 -0
- package/dist/helpers/serialize.d.ts.map +1 -0
- package/dist/helpers/utils.d.ts +36 -0
- package/dist/helpers/utils.d.ts.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +61 -0
- package/dist/index.js.map +6 -0
- package/dist/subtle.d.ts +7 -0
- package/dist/subtle.d.ts.map +1 -0
- package/dist/subtle.js +30 -0
- package/dist/subtle.js.map +6 -0
- package/dist/vm/env.d.ts +3 -0
- package/dist/vm/env.d.ts.map +1 -0
- package/dist/vm/error.d.ts +11 -0
- package/dist/vm/error.d.ts.map +1 -0
- package/dist/vm/helpers.d.ts +21 -0
- package/dist/vm/helpers.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/_helpers.d.ts +35 -0
- package/dist/vm/lib/_helpers.d.ts.map +1 -0
- package/dist/vm/lib/_loader.d.ts +16 -0
- package/dist/vm/lib/_loader.d.ts.map +1 -0
- package/dist/vm/lib/global/bit.d.ts +9 -0
- package/dist/vm/lib/global/bit.d.ts.map +1 -0
- package/dist/vm/lib/global/debug.d.ts +5 -0
- package/dist/vm/lib/global/debug.d.ts.map +1 -0
- package/dist/vm/lib/global/index.d.ts +10 -0
- package/dist/vm/lib/global/index.d.ts.map +1 -0
- package/dist/vm/lib/global/json.d.ts +4 -0
- package/dist/vm/lib/global/json.d.ts.map +1 -0
- package/dist/vm/lib/global/math-additional.d.ts +3 -0
- package/dist/vm/lib/global/math-additional.d.ts.map +1 -0
- package/dist/vm/lib/global/math-arr.d.ts +8 -0
- package/dist/vm/lib/global/math-arr.d.ts.map +1 -0
- package/dist/vm/lib/global/math-const.d.ts +3 -0
- package/dist/vm/lib/global/math-const.d.ts.map +1 -0
- package/dist/vm/lib/global/math-unary.d.ts +29 -0
- package/dist/vm/lib/global/math-unary.d.ts.map +1 -0
- package/dist/vm/lib/global/math.d.ts +9 -0
- package/dist/vm/lib/global/math.d.ts.map +1 -0
- package/dist/vm/lib/global/mod/index.d.ts +3 -0
- package/dist/vm/lib/global/mod/index.d.ts.map +1 -0
- package/dist/vm/lib/global/mod/matrix.d.ts +16 -0
- package/dist/vm/lib/global/mod/matrix.d.ts.map +1 -0
- package/dist/vm/lib/global/sequence/all-any.d.ts +4 -0
- package/dist/vm/lib/global/sequence/all-any.d.ts.map +1 -0
- package/dist/vm/lib/global/sequence/entries.d.ts +12 -0
- package/dist/vm/lib/global/sequence/entries.d.ts.map +1 -0
- package/dist/vm/lib/global/sequence/find.d.ts +10 -0
- package/dist/vm/lib/global/sequence/find.d.ts.map +1 -0
- package/dist/vm/lib/global/sequence/flatten.d.ts +3 -0
- package/dist/vm/lib/global/sequence/flatten.d.ts.map +1 -0
- package/dist/vm/lib/global/sequence/index.d.ts +12 -0
- package/dist/vm/lib/global/sequence/index.d.ts.map +1 -0
- package/dist/vm/lib/global/sequence/len.d.ts +3 -0
- package/dist/vm/lib/global/sequence/len.d.ts.map +1 -0
- package/dist/vm/lib/global/sequence/map-filter.d.ts +9 -0
- package/dist/vm/lib/global/sequence/map-filter.d.ts.map +1 -0
- package/dist/vm/lib/global/sequence/repeat.d.ts +4 -0
- package/dist/vm/lib/global/sequence/repeat.d.ts.map +1 -0
- package/dist/vm/lib/global/sequence/reverse.d.ts +3 -0
- package/dist/vm/lib/global/sequence/reverse.d.ts.map +1 -0
- package/dist/vm/lib/global/sequence/sort.d.ts +5 -0
- package/dist/vm/lib/global/sequence/sort.d.ts.map +1 -0
- package/dist/vm/lib/global/sequence/with.d.ts +5 -0
- package/dist/vm/lib/global/sequence/with.d.ts.map +1 -0
- package/dist/vm/lib/global/sequence/zip.d.ts +4 -0
- package/dist/vm/lib/global/sequence/zip.d.ts.map +1 -0
- package/dist/vm/lib/global/string.d.ts +12 -0
- package/dist/vm/lib/global/string.d.ts.map +1 -0
- package/dist/vm/lib/global/time.d.ts +15 -0
- package/dist/vm/lib/global/time.d.ts.map +1 -0
- package/dist/vm/lib/global/to-primitive.d.ts +6 -0
- package/dist/vm/lib/global/to-primitive.d.ts.map +1 -0
- package/dist/vm/operations.d.ts +49 -0
- package/dist/vm/operations.d.ts.map +1 -0
- package/dist/vm/types/checker.d.ts +30 -0
- package/dist/vm/types/checker.d.ts.map +1 -0
- package/dist/vm/types/context.d.ts +43 -0
- package/dist/vm/types/context.d.ts.map +1 -0
- package/dist/vm/types/extern.d.ts +32 -0
- package/dist/vm/types/extern.d.ts.map +1 -0
- package/dist/vm/types/function.d.ts +49 -0
- package/dist/vm/types/function.d.ts.map +1 -0
- package/dist/vm/types/index.d.ts +75 -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/script.d.ts +14 -0
- package/dist/vm/types/script.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 +55 -0
- package/src/cli/execute.ts +32 -0
- package/src/cli/index.ts +73 -0
- package/src/cli/print.ts +41 -0
- package/src/compiler/compile-bytecode.ts +65 -0
- package/src/compiler/compile-fast.ts +81 -0
- package/src/compiler/create-script.ts +34 -0
- package/src/compiler/diagnostic.ts +175 -0
- package/src/compiler/emit.ts +764 -0
- package/src/compiler/index.ts +67 -0
- package/src/compiler/types.ts +16 -0
- package/src/compiler/worker-manager.ts +60 -0
- package/src/compiler/worker.ts +37 -0
- package/src/helpers/constants.ts +3 -0
- package/src/helpers/serialize.ts +280 -0
- package/src/helpers/utils.ts +16 -0
- package/src/index.ts +3 -0
- package/src/subtle.ts +6 -0
- package/src/vm/env.ts +16 -0
- package/src/vm/error.ts +22 -0
- package/src/vm/helpers.ts +121 -0
- package/src/vm/index.ts +5 -0
- package/src/vm/lib/_helpers.ts +215 -0
- package/src/vm/lib/_loader.ts +51 -0
- package/src/vm/lib/global/bit.ts +93 -0
- package/src/vm/lib/global/debug.ts +36 -0
- package/src/vm/lib/global/index.ts +9 -0
- package/src/vm/lib/global/json.ts +45 -0
- package/src/vm/lib/global/math-additional.ts +71 -0
- package/src/vm/lib/global/math-arr.ts +62 -0
- package/src/vm/lib/global/math-const.ts +2 -0
- package/src/vm/lib/global/math-unary.ts +171 -0
- package/src/vm/lib/global/math.ts +27 -0
- package/src/vm/lib/global/mod/index.ts +4 -0
- package/src/vm/lib/global/mod/matrix.ts +579 -0
- package/src/vm/lib/global/sequence/all-any.ts +73 -0
- package/src/vm/lib/global/sequence/entries.ts +67 -0
- package/src/vm/lib/global/sequence/find.ts +49 -0
- package/src/vm/lib/global/sequence/flatten.ts +16 -0
- package/src/vm/lib/global/sequence/index.ts +11 -0
- package/src/vm/lib/global/sequence/len.ts +15 -0
- package/src/vm/lib/global/sequence/map-filter.ts +82 -0
- package/src/vm/lib/global/sequence/repeat.ts +28 -0
- package/src/vm/lib/global/sequence/reverse.ts +17 -0
- package/src/vm/lib/global/sequence/sort.ts +88 -0
- package/src/vm/lib/global/sequence/with.ts +43 -0
- package/src/vm/lib/global/sequence/zip.ts +40 -0
- package/src/vm/lib/global/string.ts +149 -0
- package/src/vm/lib/global/time.ts +73 -0
- package/src/vm/lib/global/to-primitive.ts +58 -0
- package/src/vm/operations.ts +497 -0
- package/src/vm/types/checker.ts +164 -0
- package/src/vm/types/context.ts +161 -0
- package/src/vm/types/extern.ts +166 -0
- package/src/vm/types/function.ts +136 -0
- package/src/vm/types/index.ts +124 -0
- package/src/vm/types/module.ts +40 -0
- package/src/vm/types/script.ts +18 -0
- package/src/vm/types/wrapper.ts +28 -0
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
import { VmError } from '../error.js';
|
|
2
|
+
import { $ToNumber, $Type } from '../operations.js';
|
|
3
|
+
import {
|
|
4
|
+
isVmArray,
|
|
5
|
+
isVmExtern,
|
|
6
|
+
isVmFunction,
|
|
7
|
+
type VmExtern,
|
|
8
|
+
type VmFunction,
|
|
9
|
+
type VmAny,
|
|
10
|
+
type VmArray,
|
|
11
|
+
type VmValue,
|
|
12
|
+
isVmRecord,
|
|
13
|
+
type VmRecord,
|
|
14
|
+
type VmModule,
|
|
15
|
+
isVmPrimitive,
|
|
16
|
+
type VmConst,
|
|
17
|
+
isVmConst,
|
|
18
|
+
VM_ARRAY_MAX_LENGTH,
|
|
19
|
+
} from '../types/index.js';
|
|
20
|
+
import type { VmFunctionLike, VmFunctionOption } from '../types/function.js';
|
|
21
|
+
import { Cp } from '../helpers.js';
|
|
22
|
+
import { isNaN, entries, fromEntries } from '../../helpers/utils.js';
|
|
23
|
+
|
|
24
|
+
/** 抛出异常 */
|
|
25
|
+
export function throwError(message: string, recovered: VmAny | (() => VmAny)): never {
|
|
26
|
+
const recoveredValue = typeof recovered === 'function' && !isVmFunction(recovered) ? recovered() : recovered;
|
|
27
|
+
throw new VmError(message, recoveredValue);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/** 抛出预期外类型异常 */
|
|
31
|
+
export function throwUnexpectedTypeError(
|
|
32
|
+
name: string | number,
|
|
33
|
+
expected: string,
|
|
34
|
+
value: VmAny,
|
|
35
|
+
recovered: VmAny | (() => VmAny),
|
|
36
|
+
): never {
|
|
37
|
+
const actual = $Type(value);
|
|
38
|
+
if (typeof name == 'string') throwError(`Expected ${expected} for parameter '${name}', got ${actual}`, recovered);
|
|
39
|
+
const pos = name <= 0 ? 'first' : name <= 1 ? 'second' : name + 1 + 'th';
|
|
40
|
+
throwError(`Expected ${expected} at the ${pos} position, got ${actual}`, recovered);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/** 重新抛出异常 */
|
|
44
|
+
export function rethrowError(prefix: string, error: unknown, recovered: VmAny | (() => VmAny)): never {
|
|
45
|
+
const recoveredValue = typeof recovered === 'function' && !isVmFunction(recovered) ? recovered() : recovered;
|
|
46
|
+
throw VmError.from(prefix, error, recoveredValue);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/** 标记参数为必须项 */
|
|
50
|
+
export function required<const T = VmValue>(
|
|
51
|
+
name: string | number,
|
|
52
|
+
value: T | undefined,
|
|
53
|
+
recovered: VmAny | (() => VmAny),
|
|
54
|
+
): asserts value is T {
|
|
55
|
+
if (value === undefined) {
|
|
56
|
+
if (typeof name == 'string') throwError(`Missing required parameter '${name}'`, recovered);
|
|
57
|
+
const pos = name <= 0 ? 'first' : name <= 1 ? 'second' : name + 1 + 'th';
|
|
58
|
+
throwError(`Missing required parameter at the ${pos} position`, recovered);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/** 标记参数为数组 */
|
|
63
|
+
export function expectArray(
|
|
64
|
+
name: string | number,
|
|
65
|
+
value: VmAny,
|
|
66
|
+
recovered: VmAny | (() => VmAny),
|
|
67
|
+
): asserts value is VmArray {
|
|
68
|
+
required(name, value, recovered);
|
|
69
|
+
if (!isVmArray(value)) {
|
|
70
|
+
throwUnexpectedTypeError(name, 'array', value, recovered);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/** 标记参数为记录 */
|
|
75
|
+
export function expectRecord(
|
|
76
|
+
name: string | number,
|
|
77
|
+
value: VmAny,
|
|
78
|
+
recovered: VmAny | (() => VmAny),
|
|
79
|
+
): asserts value is VmRecord {
|
|
80
|
+
required(name, value, recovered);
|
|
81
|
+
if (!isVmRecord(value)) {
|
|
82
|
+
throwUnexpectedTypeError(name, 'record', value, recovered);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/** 标记参数为数组或记录 */
|
|
87
|
+
export function expectArrayOrRecord(
|
|
88
|
+
name: string | number,
|
|
89
|
+
value: VmAny,
|
|
90
|
+
recovered: VmAny | (() => VmAny),
|
|
91
|
+
): asserts value is VmArray | VmRecord {
|
|
92
|
+
required(name, value, recovered);
|
|
93
|
+
if (!isVmArray(value) && !isVmRecord(value)) {
|
|
94
|
+
throwUnexpectedTypeError(name, 'array | record', value, recovered);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/** 标记参数为复合类型 */
|
|
99
|
+
export function expectCompound(
|
|
100
|
+
name: string | number,
|
|
101
|
+
value: VmAny,
|
|
102
|
+
recovered: VmAny | (() => VmAny),
|
|
103
|
+
): asserts value is VmArray | VmRecord | VmModule | VmExtern {
|
|
104
|
+
required(name, value, recovered);
|
|
105
|
+
if (isVmPrimitive(value) || isVmFunction(value)) {
|
|
106
|
+
throwUnexpectedTypeError(name, 'array | record | module | extern', value, recovered);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/** 标记参数为常量 */
|
|
111
|
+
export function expectConst(
|
|
112
|
+
name: string | number,
|
|
113
|
+
value: VmAny,
|
|
114
|
+
recovered: VmAny | (() => VmAny),
|
|
115
|
+
): asserts value is VmConst {
|
|
116
|
+
required(name, value, recovered);
|
|
117
|
+
if (!isVmConst(value)) {
|
|
118
|
+
throwUnexpectedTypeError(name, 'nil | number | boolean | string | array | record', value, recovered);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/** 标记为可调用 */
|
|
123
|
+
export function expectCallable(
|
|
124
|
+
name: string | number,
|
|
125
|
+
value: VmAny,
|
|
126
|
+
recovered: VmAny | (() => VmAny),
|
|
127
|
+
): asserts value is VmFunction | VmExtern {
|
|
128
|
+
required(name, value, recovered);
|
|
129
|
+
const callable = isVmFunction(value) || isVmExtern(value);
|
|
130
|
+
if (!callable) {
|
|
131
|
+
throwUnexpectedTypeError(name, 'callable', value, recovered);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/** Get numbers from the arguments. */
|
|
136
|
+
export function getNumbers(args: readonly VmAny[]): number[] {
|
|
137
|
+
if (args.length === 0) return [];
|
|
138
|
+
if (args.length === 1 && isVmArray(args[0])) args = args[0];
|
|
139
|
+
const numbers: number[] = [];
|
|
140
|
+
for (const arg of args) {
|
|
141
|
+
if (arg == null) continue;
|
|
142
|
+
numbers.push($ToNumber(arg));
|
|
143
|
+
}
|
|
144
|
+
return numbers;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/** 将值转为数组长度 */
|
|
148
|
+
export function arrayLen(len: number | null | undefined): number {
|
|
149
|
+
if (len == null || isNaN(len) || len <= 0) return 0;
|
|
150
|
+
len = Math.trunc(len);
|
|
151
|
+
if (len > VM_ARRAY_MAX_LENGTH) throwError(`Array length exceeds maximum limit of ${VM_ARRAY_MAX_LENGTH}`, null);
|
|
152
|
+
return len;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/** 应用映射函数 */
|
|
156
|
+
export function map(
|
|
157
|
+
data: VmConst,
|
|
158
|
+
mapper: (value: VmConst, index: number | string | null, data: VmConst) => VmConst | undefined,
|
|
159
|
+
): VmConst {
|
|
160
|
+
if (isVmPrimitive(data)) {
|
|
161
|
+
return mapper(data, null, data) ?? null;
|
|
162
|
+
}
|
|
163
|
+
if (isVmArray(data)) {
|
|
164
|
+
const result: VmConst[] = [];
|
|
165
|
+
const { length } = data;
|
|
166
|
+
for (let i = 0; i < length; i++) {
|
|
167
|
+
Cp();
|
|
168
|
+
const ret = mapper(data[i] ?? null, i, data);
|
|
169
|
+
if (ret === undefined) continue;
|
|
170
|
+
if (isVmConst(ret)) {
|
|
171
|
+
result.push(ret);
|
|
172
|
+
} else {
|
|
173
|
+
result.push(null);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
return result;
|
|
177
|
+
} else {
|
|
178
|
+
const e: Array<[string, VmConst]> = [];
|
|
179
|
+
for (const [key, value] of entries(data)) {
|
|
180
|
+
Cp();
|
|
181
|
+
const ret = mapper(value ?? null, key, data);
|
|
182
|
+
if (ret === undefined) continue;
|
|
183
|
+
if (isVmConst(ret)) {
|
|
184
|
+
e.push([key, ret]);
|
|
185
|
+
} else {
|
|
186
|
+
e.push([key, null]);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
return fromEntries(e);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/** 库函数选项 */
|
|
194
|
+
export type VmLibOption = Pick<
|
|
195
|
+
VmFunctionOption,
|
|
196
|
+
'summary' | 'params' | 'paramsType' | 'returns' | 'returnsType' | 'examples'
|
|
197
|
+
>;
|
|
198
|
+
/** 库函数 */
|
|
199
|
+
export type VmLib<T extends VmFunctionLike = VmFunctionLike> = T & VmLibOption;
|
|
200
|
+
|
|
201
|
+
/** 创建库函数 */
|
|
202
|
+
export function VmLib<T extends VmFunctionLike>(fn: T, option: VmLibOption): VmLib<T> {
|
|
203
|
+
/* c8 ignore next 2 */
|
|
204
|
+
if (typeof fn != 'function') throw new TypeError('Invalid function');
|
|
205
|
+
if (isVmFunction(fn)) throw new TypeError('Cannot create VmLib from a VmFunction');
|
|
206
|
+
|
|
207
|
+
const ret = fn as T & VmLibOption as Writable<VmLibOption>;
|
|
208
|
+
ret.params = option.params;
|
|
209
|
+
ret.paramsType = option.paramsType;
|
|
210
|
+
ret.returns = option.returns;
|
|
211
|
+
ret.returnsType = option.returnsType;
|
|
212
|
+
ret.summary = option.summary;
|
|
213
|
+
ret.examples = option.examples;
|
|
214
|
+
return ret as T & VmLibOption;
|
|
215
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { VmFunction, VmModule, type VmConst, type VmFunctionLike, type VmImmutable } from '../types/index.js';
|
|
2
|
+
import { create, defineProperty, entries } from '../../helpers/utils.js';
|
|
3
|
+
import { VmSharedContext } from '../types/context.js';
|
|
4
|
+
|
|
5
|
+
import type { VmLib, VmLibOption } from './_helpers.js';
|
|
6
|
+
import * as global from './global/index.js';
|
|
7
|
+
|
|
8
|
+
for (const [name, value] of entries(global)) {
|
|
9
|
+
VmSharedContext[name] = wrapEntry(name, value as RawValue);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/** 原始值 */
|
|
13
|
+
type RawValue = VmLib | VmConst | VmModule;
|
|
14
|
+
/** 包装值 */
|
|
15
|
+
type ToWrappedValue<V extends RawValue> = V extends VmFunctionLike ? VmFunction<V> : V;
|
|
16
|
+
/** 包装值 */
|
|
17
|
+
function wrapEntry<const T extends RawValue>(name: string, value: T): ToWrappedValue<T> {
|
|
18
|
+
if (typeof value == 'function') {
|
|
19
|
+
if (value.name !== name) {
|
|
20
|
+
// 如果函数名和导出名不一致,则重命名
|
|
21
|
+
defineProperty(value, 'name', {
|
|
22
|
+
value: name,
|
|
23
|
+
configurable: true,
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
return VmFunction(value, {
|
|
27
|
+
isLib: true,
|
|
28
|
+
injectCp: true,
|
|
29
|
+
fullName: `global.${name}`,
|
|
30
|
+
...(value as VmLibOption),
|
|
31
|
+
}) as ToWrappedValue<T>;
|
|
32
|
+
} else {
|
|
33
|
+
return value as ToWrappedValue<T>;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/** 创建模块 */
|
|
38
|
+
export type ToWrappedModule<T extends Record<string, RawValue>> = VmModule<{
|
|
39
|
+
[key in keyof T]: ToWrappedValue<T[key]>;
|
|
40
|
+
}>;
|
|
41
|
+
|
|
42
|
+
/** 创建模块 */
|
|
43
|
+
export function createModule<const T extends Record<string, RawValue>>(name: string, lib: T): ToWrappedModule<T> {
|
|
44
|
+
const mod = create(null) as Record<string, VmImmutable>;
|
|
45
|
+
for (const [key, value] of entries(lib)) {
|
|
46
|
+
mod[key] = wrapEntry(key, value);
|
|
47
|
+
}
|
|
48
|
+
return new VmModule(name, mod) as ToWrappedModule<T>;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export const lib = global;
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { $ToNumber } from '../../operations.js';
|
|
2
|
+
import { VmLib } from '../_helpers.js';
|
|
3
|
+
|
|
4
|
+
export const b_and = VmLib(
|
|
5
|
+
(x, y) => {
|
|
6
|
+
return $ToNumber(x) & $ToNumber(y);
|
|
7
|
+
},
|
|
8
|
+
{
|
|
9
|
+
summary: '返回两个数的按位与',
|
|
10
|
+
params: { x: '第一个操作数', y: '第二个操作数' },
|
|
11
|
+
paramsType: { x: 'number', y: 'number' },
|
|
12
|
+
returnsType: 'number',
|
|
13
|
+
examples: ['b_and(6, 3) // 2'],
|
|
14
|
+
},
|
|
15
|
+
);
|
|
16
|
+
|
|
17
|
+
export const b_or = VmLib(
|
|
18
|
+
(x, y) => {
|
|
19
|
+
return $ToNumber(x) | $ToNumber(y);
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
summary: '返回两个数的按位或',
|
|
23
|
+
params: { x: '第一个操作数', y: '第二个操作数' },
|
|
24
|
+
paramsType: { x: 'number', y: 'number' },
|
|
25
|
+
returnsType: 'number',
|
|
26
|
+
examples: ['b_or(5, 2) // 7'],
|
|
27
|
+
},
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
export const b_not = VmLib(
|
|
31
|
+
(x) => {
|
|
32
|
+
return ~$ToNumber(x);
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
summary: '返回一个数的按位取反',
|
|
36
|
+
params: { x: '操作数' },
|
|
37
|
+
paramsType: { x: 'number' },
|
|
38
|
+
returnsType: 'number',
|
|
39
|
+
examples: ['b_not(0) // -1'],
|
|
40
|
+
},
|
|
41
|
+
);
|
|
42
|
+
|
|
43
|
+
export const b_xor = VmLib(
|
|
44
|
+
(x, y) => {
|
|
45
|
+
return $ToNumber(x) ^ $ToNumber(y);
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
summary: '返回两个数的按位异或',
|
|
49
|
+
params: { x: '第一个操作数', y: '第二个操作数' },
|
|
50
|
+
paramsType: { x: 'number', y: 'number' },
|
|
51
|
+
returnsType: 'number',
|
|
52
|
+
examples: ['b_xor(5, 3) // 6'],
|
|
53
|
+
},
|
|
54
|
+
);
|
|
55
|
+
|
|
56
|
+
export const shl = VmLib(
|
|
57
|
+
(x, y) => {
|
|
58
|
+
return $ToNumber(x) << $ToNumber(y);
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
summary: '返回第一个操作数左移指定的位数',
|
|
62
|
+
params: { x: '第一个操作数', y: '位数' },
|
|
63
|
+
paramsType: { x: 'number', y: 'number' },
|
|
64
|
+
returnsType: 'number',
|
|
65
|
+
examples: ['shl(3, 2) // 12'],
|
|
66
|
+
},
|
|
67
|
+
);
|
|
68
|
+
|
|
69
|
+
export const sar = VmLib(
|
|
70
|
+
(x, y) => {
|
|
71
|
+
return $ToNumber(x) >> $ToNumber(y);
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
summary: '返回第一个操作数右移指定的位数',
|
|
75
|
+
params: { x: '第一个操作数', y: '位数' },
|
|
76
|
+
paramsType: { x: 'number', y: 'number' },
|
|
77
|
+
returnsType: 'number',
|
|
78
|
+
examples: ['sar(-8, 1) // -4'],
|
|
79
|
+
},
|
|
80
|
+
);
|
|
81
|
+
|
|
82
|
+
export const shr = VmLib(
|
|
83
|
+
(x, y) => {
|
|
84
|
+
return $ToNumber(x) >>> $ToNumber(y);
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
summary: '返回第一个操作数无符号右移指定的位数',
|
|
88
|
+
params: { x: '第一个操作数', y: '位数' },
|
|
89
|
+
paramsType: { x: 'number', y: 'number' },
|
|
90
|
+
returnsType: 'number',
|
|
91
|
+
examples: ['shr(8, 1) // 4'],
|
|
92
|
+
},
|
|
93
|
+
);
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { VmError } from '../../error.js';
|
|
2
|
+
import { $ToString } from '../../operations.js';
|
|
3
|
+
import type { VmAny } from '../../types/index.js';
|
|
4
|
+
import { VmLib } from '../_helpers.js';
|
|
5
|
+
|
|
6
|
+
export const debug_print = VmLib(
|
|
7
|
+
(...args) => {
|
|
8
|
+
// eslint-disable-next-line no-console
|
|
9
|
+
console.log('\u001B[46;30m MiraScript \u001B[0m', ...args);
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
summary: '打印调试信息到控制台',
|
|
13
|
+
params: { '..args': '要打印的调试信息,可以是任意类型' },
|
|
14
|
+
paramsType: { '..args': 'any[]' },
|
|
15
|
+
returnsType: 'nil',
|
|
16
|
+
examples: ['debug_print("value:", 42);'],
|
|
17
|
+
},
|
|
18
|
+
);
|
|
19
|
+
|
|
20
|
+
export const panic = VmLib(
|
|
21
|
+
(message: VmAny) => {
|
|
22
|
+
// eslint-disable-next-line no-console
|
|
23
|
+
if (message === undefined) console.error('\u001B[41;37m MiraScript \u001B[0m');
|
|
24
|
+
// eslint-disable-next-line no-console
|
|
25
|
+
else console.error('\u001B[41;37m MiraScript \u001B[0m', message);
|
|
26
|
+
const error = message == null ? 'panic' : 'panic: ' + $ToString(message);
|
|
27
|
+
throw new VmError(error, undefined);
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
summary: '产生错误,并打印错误信息到控制台',
|
|
31
|
+
params: { message: '要打印的错误信息' },
|
|
32
|
+
paramsType: { message: 'string' },
|
|
33
|
+
returnsType: 'never',
|
|
34
|
+
examples: ['panic("boom");'],
|
|
35
|
+
},
|
|
36
|
+
);
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export * from './math.js';
|
|
2
|
+
export * from './bit.js';
|
|
3
|
+
export * from './sequence/index.js';
|
|
4
|
+
export * from './debug.js';
|
|
5
|
+
export * from './json.js';
|
|
6
|
+
export * from './to-primitive.js';
|
|
7
|
+
export * from './string.js';
|
|
8
|
+
export * from './time.js';
|
|
9
|
+
export * from './mod/index.js';
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { isVmExtern, isVmModule } from '../../types/index.js';
|
|
2
|
+
import { required, rethrowError, VmLib } from '../_helpers.js';
|
|
3
|
+
const { parse, stringify } = JSON;
|
|
4
|
+
|
|
5
|
+
export const to_json = VmLib(
|
|
6
|
+
(data) => {
|
|
7
|
+
required('data', data, null);
|
|
8
|
+
if (isVmExtern(data) || isVmModule(data)) {
|
|
9
|
+
try {
|
|
10
|
+
return stringify(data.value) ?? null;
|
|
11
|
+
} catch (ex) {
|
|
12
|
+
rethrowError('Failed to convert extern to JSON', ex, '{}');
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
if (typeof data == 'function') return null;
|
|
16
|
+
return stringify(data);
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
summary: '将数据转换为 JSON 字符串',
|
|
20
|
+
params: { data: '要转换为 JSON 的数据' },
|
|
21
|
+
paramsType: { data: 'any' },
|
|
22
|
+
returnsType: 'string',
|
|
23
|
+
examples: ['to_json([1, 2, 3]) // "[1,2,3]"'],
|
|
24
|
+
},
|
|
25
|
+
);
|
|
26
|
+
|
|
27
|
+
export const from_json = VmLib(
|
|
28
|
+
(json, fallback) => {
|
|
29
|
+
required('json', json, null);
|
|
30
|
+
if (typeof json != 'string') return json;
|
|
31
|
+
try {
|
|
32
|
+
return parse(json);
|
|
33
|
+
} catch (ex) {
|
|
34
|
+
if (fallback != null) return fallback;
|
|
35
|
+
rethrowError('Invalid JSON', ex, null);
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
summary: '将 JSON 字符串转换为数据',
|
|
40
|
+
params: { json: '要转换的 JSON 字符串', fallback: '如果转换失败,返回的默认值' },
|
|
41
|
+
paramsType: { json: 'string', fallback: 'any' },
|
|
42
|
+
returnsType: 'any',
|
|
43
|
+
examples: [`from_json('{"a":1}') // (a: 1)`],
|
|
44
|
+
},
|
|
45
|
+
);
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/* eslint-disable no-loss-of-precision */
|
|
2
|
+
import { isInteger, isNaN } from '../../../helpers/utils.js';
|
|
3
|
+
import { $ToNumber } from '../../operations.js';
|
|
4
|
+
import { required, VmLib } from '../_helpers.js';
|
|
5
|
+
const { sqrt, pow, exp } = Math;
|
|
6
|
+
|
|
7
|
+
const GAMMA_G = 4.742_187_5;
|
|
8
|
+
|
|
9
|
+
const GAMMA_P = [
|
|
10
|
+
0.999_999_999_999_997_091_82, 57.156_235_665_862_923_517, -59.597_960_355_475_491_248, 14.136_097_974_741_747_174,
|
|
11
|
+
-0.491_913_816_097_620_199_78, 0.339_946_499_848_118_886_99e-4, 0.465_236_289_270_485_756_65e-4,
|
|
12
|
+
-0.983_744_753_048_795_646_77e-4, 0.158_088_703_224_912_488_84e-3, -0.210_264_441_724_104_883_19e-3,
|
|
13
|
+
0.217_439_618_115_212_643_2e-3, -0.164_318_106_536_763_890_22e-3, 0.844_182_239_838_527_432_93e-4,
|
|
14
|
+
-0.261_908_384_015_814_086_7e-4, 0.368_991_826_595_316_227_04e-5,
|
|
15
|
+
];
|
|
16
|
+
|
|
17
|
+
const SQRT_2_PI = sqrt(2 * Math.PI);
|
|
18
|
+
|
|
19
|
+
export const factorial = VmLib(
|
|
20
|
+
(x): number => {
|
|
21
|
+
required('x', x, Number.NaN);
|
|
22
|
+
let n = $ToNumber(x);
|
|
23
|
+
if (isNaN(n) || n < 0) return Number.NaN;
|
|
24
|
+
if (n >= 171) return Number.POSITIVE_INFINITY; // will overflow
|
|
25
|
+
|
|
26
|
+
if (isInteger(n)) {
|
|
27
|
+
if (n === 0 || n === 1) return 1;
|
|
28
|
+
|
|
29
|
+
let r = 1;
|
|
30
|
+
for (let i = 2; i <= n; i++) {
|
|
31
|
+
r *= i;
|
|
32
|
+
}
|
|
33
|
+
return r;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if (n > 85) {
|
|
37
|
+
// Extended Stirling Approx
|
|
38
|
+
n = n + 1;
|
|
39
|
+
const twoN = n * n;
|
|
40
|
+
const threeN = twoN * n;
|
|
41
|
+
const fourN = threeN * n;
|
|
42
|
+
const fiveN = fourN * n;
|
|
43
|
+
return (
|
|
44
|
+
sqrt((2 * Math.PI) / n) *
|
|
45
|
+
pow(n / Math.E, n) *
|
|
46
|
+
(1 +
|
|
47
|
+
1 / (12 * n) +
|
|
48
|
+
1 / (288 * twoN) -
|
|
49
|
+
139 / (51840 * threeN) -
|
|
50
|
+
571 / (2_488_320 * fourN) +
|
|
51
|
+
163_879 / (209_018_880 * fiveN) +
|
|
52
|
+
5_246_819 / (75_246_796_800 * fiveN * n))
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
let p = GAMMA_P[0]!;
|
|
57
|
+
for (let i = 1; i < GAMMA_P.length; ++i) {
|
|
58
|
+
p += GAMMA_P[i]! / (n + i);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const t = n + GAMMA_G + 0.5;
|
|
62
|
+
return SQRT_2_PI * pow(t, n + 0.5) * exp(-t) * p;
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
summary: '返回一个数的阶乘',
|
|
66
|
+
params: { x: '要计算阶乘的数值' },
|
|
67
|
+
paramsType: { x: 'number' },
|
|
68
|
+
returnsType: 'number',
|
|
69
|
+
examples: ['factorial(5) // 120'],
|
|
70
|
+
},
|
|
71
|
+
);
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import type { VmAny } from '../../types/index.js';
|
|
2
|
+
import { getNumbers, VmLib } from '../_helpers.js';
|
|
3
|
+
|
|
4
|
+
/** 生成函数 */
|
|
5
|
+
function build(f: (...values: readonly number[]) => number): (...values: readonly VmAny[]) => number {
|
|
6
|
+
return (...values) => {
|
|
7
|
+
const numbers = getNumbers(values);
|
|
8
|
+
return f(...numbers);
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export const max = VmLib(build(Math.max), {
|
|
13
|
+
summary: '返回一组数中的最大值',
|
|
14
|
+
params: { '..values': '要比较的数值' },
|
|
15
|
+
paramsType: { '..values': 'number[]' },
|
|
16
|
+
returnsType: 'number',
|
|
17
|
+
examples: ['max(3, 7, 2) // 7'],
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
export const min = VmLib(build(Math.min), {
|
|
21
|
+
summary: '返回一组数中的最小值',
|
|
22
|
+
params: { '..values': '要比较的数值' },
|
|
23
|
+
paramsType: { '..values': 'number[]' },
|
|
24
|
+
returnsType: 'number',
|
|
25
|
+
examples: ['min(3, 7, 2) // 2'],
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
export const hypot = VmLib(build(Math.hypot), {
|
|
29
|
+
summary: '返回所有参数平方和的平方根',
|
|
30
|
+
params: { '..values': '要计算的数值' },
|
|
31
|
+
paramsType: { '..values': 'number[]' },
|
|
32
|
+
returnsType: 'number',
|
|
33
|
+
examples: ['hypot(3, 4) // 5'],
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
export const sum = VmLib(
|
|
37
|
+
(...values: readonly VmAny[]) => {
|
|
38
|
+
const numbers = getNumbers(values);
|
|
39
|
+
return numbers.reduce((a, b) => a + b, 0);
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
summary: '返回一组数的总和',
|
|
43
|
+
params: { '..values': '要计算的数值' },
|
|
44
|
+
paramsType: { '..values': 'number[]' },
|
|
45
|
+
returnsType: 'number',
|
|
46
|
+
examples: ['sum(1, 2, 3, 4) // 10'],
|
|
47
|
+
},
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
export const product = VmLib(
|
|
51
|
+
(...values: readonly VmAny[]) => {
|
|
52
|
+
const numbers = getNumbers(values);
|
|
53
|
+
return numbers.reduce((a, b) => a * b, 1);
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
summary: '返回一组数的乘积',
|
|
57
|
+
params: { '..values': '要计算的数值' },
|
|
58
|
+
paramsType: { '..values': 'number[]' },
|
|
59
|
+
returnsType: 'number',
|
|
60
|
+
examples: ['product(2, 3, 4) // 24'],
|
|
61
|
+
},
|
|
62
|
+
);
|