@mirascript/mirascript 0.1.15 → 0.1.17

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