@mirascript/mirascript 0.1.33 → 0.1.35

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 (71) hide show
  1. package/dist/{chunk-UM7PQV4L.js → chunk-C6YXWSTI.js} +205 -156
  2. package/dist/chunk-C6YXWSTI.js.map +6 -0
  3. package/dist/{chunk-BMSHG7ON.js → chunk-HGARNCSR.js} +2 -2
  4. package/dist/{chunk-NRUNNMNC.js → chunk-PYMZMMRB.js} +18 -20
  5. package/dist/chunk-PYMZMMRB.js.map +6 -0
  6. package/dist/{chunk-VZGKLLRC.js → chunk-SEZII6RI.js} +19 -7
  7. package/dist/chunk-SEZII6RI.js.map +6 -0
  8. package/dist/cli/index.js +4 -4
  9. package/dist/compiler/compile-fast.d.ts.map +1 -1
  10. package/dist/compiler/create-script.d.ts +1 -1
  11. package/dist/compiler/create-script.d.ts.map +1 -1
  12. package/dist/compiler/emit/constants.d.ts +1 -1
  13. package/dist/compiler/emit/constants.d.ts.map +1 -1
  14. package/dist/compiler/worker.js +1 -1
  15. package/dist/helpers/serialize.d.ts +5 -4
  16. package/dist/helpers/serialize.d.ts.map +1 -1
  17. package/dist/index.js +3 -3
  18. package/dist/subtle.js +3 -3
  19. package/dist/vm/lib/global/debug.d.ts +1 -1
  20. package/dist/vm/lib/global/debug.d.ts.map +1 -1
  21. package/dist/vm/lib/global/math-const.d.ts +6 -0
  22. package/dist/vm/lib/global/math-const.d.ts.map +1 -1
  23. package/dist/vm/lib/global/time.d.ts.map +1 -1
  24. package/dist/vm/lib/helpers.d.ts +1 -1
  25. package/dist/vm/lib/helpers.d.ts.map +1 -1
  26. package/dist/vm/operations/call.d.ts +7 -3
  27. package/dist/vm/operations/call.d.ts.map +1 -1
  28. package/dist/vm/operations/common.d.ts +2 -1
  29. package/dist/vm/operations/common.d.ts.map +1 -1
  30. package/dist/vm/operations/compound.d.ts +20 -10
  31. package/dist/vm/operations/compound.d.ts.map +1 -1
  32. package/dist/vm/operations/convert.d.ts +8 -4
  33. package/dist/vm/operations/convert.d.ts.map +1 -1
  34. package/dist/vm/operations/helpers.d.ts +8 -6
  35. package/dist/vm/operations/helpers.d.ts.map +1 -1
  36. package/dist/vm/operations/operator.d.ts +44 -22
  37. package/dist/vm/operations/operator.d.ts.map +1 -1
  38. package/dist/vm/operations/slice.d.ts +4 -2
  39. package/dist/vm/operations/slice.d.ts.map +1 -1
  40. package/dist/vm/operations/type-check.d.ts +14 -7
  41. package/dist/vm/operations/type-check.d.ts.map +1 -1
  42. package/dist/vm/types/boundary.d.ts +2 -0
  43. package/dist/vm/types/boundary.d.ts.map +1 -1
  44. package/dist/vm/types/extern.d.ts +7 -2
  45. package/dist/vm/types/extern.d.ts.map +1 -1
  46. package/dist/vm/types/function.d.ts +6 -0
  47. package/dist/vm/types/function.d.ts.map +1 -1
  48. package/package.json +4 -4
  49. package/src/compiler/compile-fast.ts +17 -20
  50. package/src/compiler/create-script.ts +1 -1
  51. package/src/compiler/emit/constants.ts +1 -1
  52. package/src/helpers/serialize.ts +22 -8
  53. package/src/vm/lib/global/debug.ts +1 -1
  54. package/src/vm/lib/global/math-const.ts +17 -0
  55. package/src/vm/lib/global/time.ts +6 -5
  56. package/src/vm/lib/helpers.ts +2 -1
  57. package/src/vm/operations/call.ts +30 -7
  58. package/src/vm/operations/common.ts +3 -2
  59. package/src/vm/operations/compound.ts +59 -32
  60. package/src/vm/operations/convert.ts +12 -8
  61. package/src/vm/operations/helpers.ts +14 -12
  62. package/src/vm/operations/operator.ts +66 -44
  63. package/src/vm/operations/slice.ts +6 -4
  64. package/src/vm/operations/type-check.ts +21 -14
  65. package/src/vm/types/boundary.ts +27 -11
  66. package/src/vm/types/extern.ts +3 -1
  67. package/src/vm/types/function.ts +4 -0
  68. package/dist/chunk-NRUNNMNC.js.map +0 -6
  69. package/dist/chunk-UM7PQV4L.js.map +0 -6
  70. package/dist/chunk-VZGKLLRC.js.map +0 -6
  71. /package/dist/{chunk-BMSHG7ON.js.map → chunk-HGARNCSR.js.map} +0 -0
@@ -10,7 +10,6 @@ import {
10
10
  isVmModule,
11
11
  isVmRecord,
12
12
  } from './types.js';
13
- import type { VmWrapper } from '../vm/types/wrapper.js';
14
13
 
15
14
  /** 序列化设置 */
16
15
  export interface SerializeOptions {
@@ -302,7 +301,7 @@ export function serialize(value: VmAny, options?: Partial<SerializeOptions>): st
302
301
  return serializeImpl(value, 0, getSerializeOptions(options));
303
302
  }
304
303
 
305
- /** 将 MiraScript function 转化为 MiraScript 字符串 */
304
+ /** 将 MiraScript 函数转化为 MiraScript 字符串 */
306
305
  export function displayFunction(value: VmFunction): string {
307
306
  try {
308
307
  const name = getVmFunctionInfo(value)?.fullName;
@@ -312,12 +311,27 @@ export function displayFunction(value: VmFunction): string {
312
311
  return `<function>`;
313
312
  }
314
313
  }
315
- /** 将 MiraScript module 转化为 MiraScript 字符串 */
316
- export function displayWrapper(value: VmWrapper<object>, useBraces: boolean, fallback: string): string {
314
+ /** 将 MiraScript 模块转化为 MiraScript 字符串 */
315
+ export function displayModule(value: VmModule): string {
317
316
  try {
318
- return value.toString(useBraces);
317
+ return value.toString(true);
318
+ /* c8 ignore next 3 */
319
+ } catch {
320
+ return `<module>`;
321
+ }
322
+ }
323
+ /** 将 MiraScript 外部值转化为 MiraScript 字符串 */
324
+ export function displayExtern(value: VmExtern): string {
325
+ try {
326
+ const tag = `<extern ${value.tag}>`;
327
+ const rep = value.toString(true);
328
+ if (rep === tag || rep.length > 50) {
329
+ return tag;
330
+ }
331
+ return `${tag} ${rep}`;
332
+ /* c8 ignore next 3 */
319
333
  } catch {
320
- return fallback;
334
+ return `<extern>`;
321
335
  }
322
336
  }
323
337
  const DISPLAY_OPTIONS = Object.freeze({
@@ -333,8 +347,8 @@ const DISPLAY_OPTIONS = Object.freeze({
333
347
  serializeRecord,
334
348
  serializePropName: String,
335
349
  serializeFunction: displayFunction,
336
- serializeModule: (value) => displayWrapper(value, true, '<module>'),
337
- serializeExtern: (value) => displayWrapper(value, true, '<extern>'),
350
+ serializeModule: displayModule,
351
+ serializeExtern: displayExtern,
338
352
  } satisfies SerializeOptions);
339
353
  /**
340
354
  * 将 MiraScript 值转化为 MiraScript 字符串。
@@ -114,7 +114,7 @@ export const panic = VmLib(
114
114
  examples: ['panic("boom");'],
115
115
  },
116
116
  {
117
- prefix: ['MiraScript'] as readonly string[],
117
+ prefix: ['MiraScript'] as readonly [prefix: string, ...additional: readonly string[]],
118
118
  serializer: defaultSerializer,
119
119
  },
120
120
  );
@@ -1,3 +1,4 @@
1
+ import { DiagnosticCode } from '@mirascript/constants';
1
2
  import { VmLib } from '../helpers.js';
2
3
 
3
4
  export const PI = VmLib(Math.PI, {
@@ -8,6 +9,22 @@ export const E = VmLib(Math.E, {
8
9
  summary: '自然对数的底数',
9
10
  returnsType: 'number',
10
11
  });
12
+ export const pi = VmLib(Math.PI, {
13
+ summary: '圆周率',
14
+ returnsType: 'number',
15
+ deprecated: {
16
+ use: 'PI',
17
+ message: DiagnosticCode.PreferUppercaseConstant,
18
+ },
19
+ });
20
+ export const e = VmLib(Math.E, {
21
+ summary: '自然对数的底数',
22
+ returnsType: 'number',
23
+ deprecated: {
24
+ use: 'E',
25
+ message: DiagnosticCode.PreferUppercaseConstant,
26
+ },
27
+ });
11
28
  export const SQRT1_2 = VmLib(Math.SQRT1_2, {
12
29
  summary: '1 的平方根除以 2',
13
30
  returnsType: 'number',
@@ -69,21 +69,22 @@ export const to_datetime = VmLib(
69
69
  };
70
70
  },
71
71
  {
72
- summary: '将数据转换为 Date 记录',
72
+ summary: '将数据转换为 DateTime 记录',
73
73
  params: {
74
74
  datetime: '要转换的数据,默认为当前时间',
75
75
  offset: '时区偏移量(单位:小时),默认为 0',
76
76
  fallback: '转换失败时的返回值',
77
77
  },
78
78
  paramsType: { datetime: 'number | string', offset: 'number', fallback: 'any' },
79
- returnsType: 'Date | type(fallback)',
79
+ returnsType: 'DateTime | type(fallback)',
80
80
  examples: [
81
81
  `
82
82
  to_datetime(0)
83
83
  // (
84
- // year: 1970, month: 1, day: 1,
85
- // hour: 0, minute: 0, second: 0,
86
- // millisecond: 0, dayOfWeek: 4, offset: 0
84
+ // year: 1970, month: 1, day: 1,
85
+ // hour: 0, minute: 0, second: 0,
86
+ // millisecond: 0,
87
+ // dayOfWeek: 4, offset: 0
87
88
  // )
88
89
  `.trim(),
89
90
  ],
@@ -274,7 +274,7 @@ export function map(
274
274
  /** 库函数选项 */
275
275
  export type VmLibOption = Pick<
276
276
  VmFunctionOption,
277
- 'summary' | 'params' | 'paramsType' | 'returns' | 'returnsType' | 'examples' | 'injectCp'
277
+ 'summary' | 'params' | 'paramsType' | 'returns' | 'returnsType' | 'examples' | 'injectCp' | 'deprecated'
278
278
  >;
279
279
  /** 库函数 */
280
280
  export type VmLib<T extends VmFunctionLike | VmConst = VmFunctionLike> = (T extends VmFunctionLike ? T : { value: T }) &
@@ -296,5 +296,6 @@ export function VmLib<
296
296
  ret.summary = option.summary;
297
297
  ret.examples = option.examples;
298
298
  ret.injectCp = option.injectCp ?? false;
299
+ ret.deprecated = option.deprecated ?? undefined;
299
300
  return ret as VmLib<T> & P;
300
301
  }
@@ -1,24 +1,47 @@
1
1
  import { VmError } from '../../helpers/error.js';
2
2
  import { display } from '../../helpers/serialize.js';
3
3
  import { isVmFunction, isVmExtern, isVmConst } from '../../helpers/types.js';
4
- import type { VmAny, VmArray, VmValue } from '../types/index.js';
4
+ import type { VmExtern, VmFunction, VmAny, VmArray, VmValue } from '../types/index.js';
5
5
  import { $AssertInit } from './common.js';
6
6
 
7
- export const $Call = (func: VmValue, args: readonly VmAny[]): VmValue => {
7
+ /** 调用返回类型 */
8
+ type CallReturn<T extends VmValue> =
9
+ T extends VmFunction<infer F>
10
+ ? F extends (...args: readonly VmAny[]) => infer R
11
+ ? // eslint-disable-next-line @typescript-eslint/no-invalid-void-type
12
+ R extends void | undefined
13
+ ? null
14
+ : R
15
+ : VmValue
16
+ : T extends VmExtern<infer E>
17
+ ? E extends (...args: readonly VmAny[]) => infer R
18
+ ? // eslint-disable-next-line @typescript-eslint/no-invalid-void-type
19
+ R extends void | undefined
20
+ ? null
21
+ : R extends VmValue
22
+ ? R
23
+ : R extends object
24
+ ? VmExtern<R>
25
+ : VmValue
26
+ : VmValue
27
+ : VmValue;
28
+
29
+ /** 调用函数 */
30
+ export function $Call<T extends VmValue, A extends readonly VmValue[]>(func: T, args: A): CallReturn<T> {
8
31
  for (const a of args) {
9
32
  $AssertInit(a);
10
33
  }
11
34
  if (isVmExtern(func)) {
12
- return func.call(args as readonly VmValue[]) ?? null;
35
+ return (func.call(args as readonly VmValue[]) ?? null) as CallReturn<T>;
13
36
  }
14
37
  if (isVmFunction(func)) {
15
- return func(...(args as readonly VmValue[])) ?? null;
38
+ return (func(...(args as readonly VmValue[])) ?? null) as CallReturn<T>;
16
39
  }
17
40
  throw new VmError(`Value is not callable: ${display(func)}`, null);
18
- };
41
+ }
19
42
 
20
43
  /** 过滤剩余参数数组 */
21
- export const $VArgs = (varags: VmAny[]): VmArray => {
44
+ export function $VArgs(varags: VmAny[]): VmArray {
22
45
  for (let i = 0, l = varags.length; i < l; i++) {
23
46
  const el = varags[i];
24
47
  if (!isVmConst(el)) {
@@ -26,4 +49,4 @@ export const $VArgs = (varags: VmAny[]): VmArray => {
26
49
  }
27
50
  }
28
51
  return varags as VmArray;
29
- };
52
+ }
@@ -1,6 +1,7 @@
1
1
  import { VmError } from '../../helpers/error.js';
2
2
  import type { VmAny, VmValue } from '../types/index.js';
3
3
 
4
- export const $AssertInit: (value: VmAny) => asserts value is VmValue = (value) => {
4
+ /** 断言值已初始化 */
5
+ export function $AssertInit(value: VmAny): asserts value is VmValue {
5
6
  if (value === undefined) throw new VmError(`Uninitialized value`, null);
6
- };
7
+ }
@@ -1,8 +1,9 @@
1
1
  import { VmError } from '../../helpers/error.js';
2
- import { hasOwnEnumerable, isNaN, NotNumber, keys, create } from '../../helpers/utils.js';
2
+ import { hasOwnEnumerable, isNaN, NotNumber, keys, create, isFinite } from '../../helpers/utils.js';
3
3
  import { toNumber, toString } from '../../helpers/convert/index.js';
4
4
  import { display } from '../../helpers/serialize.js';
5
5
  import { isVmPrimitive, isVmArray, isVmRecord, isVmFunction, isVmExtern, isVmWrapper } from '../../helpers/types.js';
6
+ import { wrapToVmConst } from '../types/boundary.js';
6
7
  import type { VmAny, VmRecord, VmValue, VmConst } from '../types/index.js';
7
8
  import { isSame } from './utils.js';
8
9
  import { $AssertInit } from './common.js';
@@ -11,7 +12,8 @@ import { $ToString } from './convert.js';
11
12
  const { trunc } = Math;
12
13
  const { at } = Array.prototype;
13
14
 
14
- export const $In = (value: VmAny, iterable: VmAny): boolean => {
15
+ /** 检查值是否在可迭代对象中 */
16
+ export function $In(value: VmAny, iterable: VmAny): boolean {
15
17
  $AssertInit(value);
16
18
  $AssertInit(iterable);
17
19
  if (iterable == null) return false;
@@ -31,16 +33,20 @@ export const $In = (value: VmAny, iterable: VmAny): boolean => {
31
33
  const key = toString(value, undefined);
32
34
  if (isVmWrapper(iterable)) return iterable.has(key);
33
35
  return hasOwnEnumerable(iterable satisfies VmRecord, key);
34
- };
35
- export const $Length = (value: VmAny): number => {
36
+ }
37
+
38
+ /** 获取值的长度 */
39
+ export function $Length(value: VmAny): number {
36
40
  $AssertInit(value);
37
41
  if (isVmArray(value)) return value.length;
38
42
  if (isVmRecord(value)) return keys(value).length;
39
43
  if (isVmWrapper(value)) return value.keys().length;
40
44
 
41
45
  throw new VmError(`Value has no length: ${display(value)}`, 0);
42
- };
43
- export const $Omit = (value: VmAny, omitted: ReadonlyArray<number | string>): VmRecord => {
46
+ }
47
+
48
+ /** 删除记录中的指定字段 */
49
+ export function $Omit(value: VmAny, omitted: ReadonlyArray<number | string>): VmRecord {
44
50
  $AssertInit(value);
45
51
  if (value == null || !isVmRecord(value)) return {};
46
52
  const result: Record<string, VmConst> = {};
@@ -53,8 +59,10 @@ export const $Omit = (value: VmAny, omitted: ReadonlyArray<number | string>): Vm
53
59
  }
54
60
  }
55
61
  return result;
56
- };
57
- export const $Pick = (value: VmAny, picked: ReadonlyArray<number | string>): VmRecord => {
62
+ }
63
+
64
+ /** 选择记录中的指定字段 */
65
+ export function $Pick(value: VmAny, picked: ReadonlyArray<number | string>): VmRecord {
58
66
  $AssertInit(value);
59
67
  if (value == null || !isVmRecord(value)) return {};
60
68
  const result: Record<string, VmConst> = {};
@@ -65,15 +73,17 @@ export const $Pick = (value: VmAny, picked: ReadonlyArray<number | string>): VmR
65
73
  }
66
74
  }
67
75
  return result;
68
- };
69
- export const $Has = (obj: VmAny, key: VmAny): boolean => {
76
+ }
77
+ /** 检查是否拥有字段 */
78
+ export function $Has(obj: VmAny, key: VmAny): boolean {
70
79
  $AssertInit(obj);
71
80
  const pk = $ToString(key);
72
81
  if (obj == null || typeof obj != 'object') return false;
73
82
  if (isVmWrapper(obj)) return obj.has(pk);
74
83
  return hasOwnEnumerable(obj, pk);
75
- };
76
- export const $Get = (obj: VmAny, key: VmAny): VmValue => {
84
+ }
85
+ /** 获取字段 */
86
+ export function $Get(obj: VmAny, key: VmAny): VmValue {
77
87
  $AssertInit(obj);
78
88
  if (isVmArray(obj)) {
79
89
  $AssertInit(key);
@@ -83,27 +93,39 @@ export const $Get = (obj: VmAny, key: VmAny): VmValue => {
83
93
  }
84
94
  const pk = $ToString(key);
85
95
  if (obj == null || typeof obj != 'object') return null;
86
- if (isVmWrapper(obj)) return obj.get(pk) ?? null;
96
+ if (isVmWrapper(obj)) {
97
+ if (isFinite(key) && isVmExtern(obj) && obj.isArrayLike()) {
98
+ let index = trunc(key as number);
99
+ const { length } = obj.value;
100
+ if (index < 0) index += length;
101
+ if (index >= 0 && index < length) {
102
+ return obj.get(String(index)) ?? null;
103
+ }
104
+ }
105
+ return obj.get(pk) ?? null;
106
+ }
87
107
  if (!hasOwnEnumerable(obj, pk)) return null;
88
108
  return obj[pk] ?? null;
89
- };
90
- export const $Set = (obj: VmAny, key: VmAny, value: VmAny): void => {
109
+ }
110
+ /** 设置字段 */
111
+ export function $Set(obj: VmAny, key: VmAny, value: VmAny): void {
91
112
  $AssertInit(obj);
92
113
  $AssertInit(value);
93
114
  const pk = $ToString(key);
94
115
  if (obj == null) return;
95
116
  if (!isVmExtern(obj)) throw new VmError(`Expected extern, got ${display(obj)}`, undefined);
96
117
  obj.set(pk, value);
97
- };
98
- export const $Iterable = (value: VmAny): Iterable<VmValue | undefined> => {
118
+ }
119
+ /** 获取可迭代对象 */
120
+ export function $Iterable(value: VmAny): Iterable<VmValue | undefined> {
99
121
  $AssertInit(value);
100
122
  if (isVmWrapper(value)) return value.keys();
101
123
  if (isVmArray(value)) return value;
102
124
  if (value != null && typeof value == 'object') return keys(value);
103
125
  throw new VmError(`Value is not iterable: ${display(value)}`, isVmFunction(value) ? [] : [value]);
104
- };
105
-
106
- export const $RecordSpread = (record: VmAny): VmRecord | null => {
126
+ }
127
+ /** 展开记录 */
128
+ export function $RecordSpread(record: VmAny): VmRecord | null {
107
129
  $AssertInit(record);
108
130
  if (record == null || isVmRecord(record)) return record;
109
131
  if (isVmArray(record)) {
@@ -127,23 +149,28 @@ export const $RecordSpread = (record: VmAny): VmRecord | null => {
127
149
  return result;
128
150
  }
129
151
  throw new VmError(`Expected record, array, extern or nil, got ${display(record)}`, null);
130
- };
152
+ }
131
153
 
132
- export const $ArraySpread = (array: VmAny): Iterable<VmConst | undefined> => {
154
+ /** 展开数组 */
155
+ export function $ArraySpread(array: VmAny): Iterable<VmConst | undefined> {
133
156
  $AssertInit(array);
134
157
  if (array == null) return [];
135
158
  if (isVmArray(array)) return array;
136
- if (isVmExtern(array) && typeof (array.value as Iterable<unknown>)[Symbol.iterator] == 'function') {
137
- const result: VmConst[] = [];
138
- for (const item of array.value as Iterable<unknown>) {
139
- // 当前只有 Primitive 不会进行二次包装
140
- if (isVmPrimitive(item)) {
141
- result.push(item);
142
- } else {
143
- result.push(null);
159
+ if (isVmExtern(array)) {
160
+ if (array.isArrayLike()) {
161
+ const result: VmConst[] = [];
162
+ for (let i = 0, len = array.value.length; i < len; i++) {
163
+ const item = array.value[i];
164
+ result.push(wrapToVmConst(item, (v) => array.assumeVmValue(v, i)));
144
165
  }
166
+ return result;
167
+ } else if (typeof (array.value as Iterable<unknown>)[Symbol.iterator] == 'function') {
168
+ const result: VmConst[] = [];
169
+ for (const item of array.value as Iterable<unknown>) {
170
+ result.push(wrapToVmConst(item, (v) => array.assumeVmValue(v, Symbol.iterator as never)));
171
+ }
172
+ return result;
145
173
  }
146
- return result;
147
174
  }
148
175
  throw new VmError(`Expected array, iterable extern or nil, got ${display(array)}`, []);
149
- };
176
+ }
@@ -2,22 +2,26 @@ import { toNumber, toString, toBoolean, toFormat } from '../../helpers/convert/i
2
2
  import type { VmAny } from '../types/index.js';
3
3
  import { $AssertInit } from './common.js';
4
4
 
5
- export const $ToBoolean = (value: VmAny): boolean => {
5
+ /** 转换为布尔值 */
6
+ export function $ToBoolean(value: VmAny): boolean {
6
7
  if (typeof value == 'boolean') return value;
7
8
  $AssertInit(value);
8
9
  return toBoolean(value, undefined);
9
- };
10
- export const $ToString = (value: VmAny): string => {
10
+ }
11
+ /** 转换为字符串 */
12
+ export function $ToString(value: VmAny): string {
11
13
  if (typeof value == 'string') return value;
12
14
  $AssertInit(value);
13
15
  return toString(value, undefined);
14
- };
15
- export const $ToNumber = (value: VmAny): number => {
16
+ }
17
+ /** 转换为数字 */
18
+ export function $ToNumber(value: VmAny): number {
16
19
  if (typeof value == 'number') return value;
17
20
  $AssertInit(value);
18
21
  return toNumber(value, undefined);
19
- };
20
- export const $Format = (value: VmAny, format: string | null): string => {
22
+ }
23
+ /** 格式化值 */
24
+ export function $Format(value: VmAny, format: string | null): string {
21
25
  $AssertInit(value);
22
26
  return toFormat(value, format);
23
- };
27
+ }
@@ -9,31 +9,31 @@ import { $AssertInit } from './common.js';
9
9
  import { $ToNumber } from './convert.js';
10
10
 
11
11
  /** 构造 record | array 元素 */
12
- export const $El = (value: VmAny): VmConst => {
12
+ export function $El(value: VmAny): VmConst {
13
13
  $AssertInit(value);
14
14
  if (!isVmConst(value)) return null;
15
15
  return value;
16
- };
16
+ }
17
17
 
18
18
  const EMPTY = create(null);
19
19
  /** 构造 record 可选元素 */
20
- export const $ElOpt = (key: string, value: VmAny): VmConst => {
20
+ export function $ElOpt(key: string, value: VmAny): VmConst {
21
21
  $AssertInit(value);
22
22
  if (value == null || !isVmConst(value)) return EMPTY;
23
23
  return { __proto__: null, [key]: value };
24
- };
24
+ }
25
25
 
26
26
  /** 构造函数和函数表达式 */
27
- export const $Fn = (name: string | null | undefined, fn: VmFunctionLike): VmFunction => {
27
+ export function $Fn<T extends VmFunctionLike>(name: string | null | undefined, fn: T): VmFunction<T> {
28
28
  defineProperty(fn, 'name', { value: name || VM_FUNCTION_ANONYMOUS_NAME });
29
29
  return VmFunction(fn, { isLib: false, injectCp: false });
30
- };
30
+ }
31
31
 
32
32
  /** 读取闭包上值 */
33
- export const $Upvalue = (value: VmAny): VmValue => {
33
+ export function $Upvalue(value: VmAny): VmValue {
34
34
  $AssertInit(value);
35
35
  return value;
36
- };
36
+ }
37
37
 
38
38
  const assertArrayLength = (start: number, end: number) => {
39
39
  if (end - start > VM_ARRAY_MAX_LENGTH) {
@@ -43,7 +43,8 @@ const assertArrayLength = (start: number, end: number) => {
43
43
  const isEmptyRange = (start: number, end: number) => {
44
44
  return !isFinite(start) || !isFinite(end) || start > end;
45
45
  };
46
- export const $ArrayRange = (start: VmAny, end: VmAny): VmArray => {
46
+ /** 构造范围数组 */
47
+ export function $ArrayRange(start: VmAny, end: VmAny): VmArray {
47
48
  const s = $ToNumber(start);
48
49
  const e = $ToNumber(end);
49
50
  if (isEmptyRange(s, e)) return [];
@@ -53,8 +54,9 @@ export const $ArrayRange = (start: VmAny, end: VmAny): VmArray => {
53
54
  arr.push(i);
54
55
  }
55
56
  return arr;
56
- };
57
- export const $ArrayRangeExclusive = (start: VmAny, end: VmAny): VmArray => {
57
+ }
58
+ /** 构造范围数组(不包含结束值) */
59
+ export function $ArrayRangeExclusive(start: VmAny, end: VmAny): VmArray {
58
60
  const s = $ToNumber(start);
59
61
  const e = $ToNumber(end);
60
62
  if (isEmptyRange(s, e)) return [];
@@ -64,7 +66,7 @@ export const $ArrayRangeExclusive = (start: VmAny, end: VmAny): VmArray => {
64
66
  arr.push(i);
65
67
  }
66
68
  return arr;
67
- };
69
+ }
68
70
 
69
71
  /** 默认执行上下文 */
70
72
  export function $GlobalFallback(): VmContext {
@@ -6,93 +6,112 @@ import { $ToBoolean, $ToNumber, $ToString } from './convert.js';
6
6
  import { isSame, overloadNumberString } from './utils.js';
7
7
 
8
8
  // String operations
9
- export const $Concat = (...args: readonly string[]): string => {
9
+ /** 字符串连接 */
10
+ export function $Concat(...args: readonly string[]): string {
10
11
  return args.map((a) => toFormat(a, null)).join('');
11
- };
12
+ }
12
13
 
13
14
  // Unary operations
14
- export const $Pos = (a: VmAny): number => {
15
+ /** 正号 */
16
+ export function $Pos(a: VmAny): number {
15
17
  return $ToNumber(a);
16
- };
17
- export const $Neg = (a: VmAny): number => {
18
+ }
19
+ /** 负号 */
20
+ export function $Neg(a: VmAny): number {
18
21
  return -$ToNumber(a);
19
- };
20
- export const $Not = (a: VmAny): boolean => {
22
+ }
23
+ /** */
24
+ export function $Not(a: VmAny): boolean {
21
25
  return !$ToBoolean(a);
22
- };
26
+ }
23
27
 
24
28
  // Math operations
25
- export const $Add = (a: VmAny, b: VmAny): number => {
29
+ /** 加法 */
30
+ export function $Add(a: VmAny, b: VmAny): number {
26
31
  return $ToNumber(a) + $ToNumber(b);
27
- };
28
- export const $Sub = (a: VmAny, b: VmAny): number => {
32
+ }
33
+ /** 减法 */
34
+ export function $Sub(a: VmAny, b: VmAny): number {
29
35
  return $ToNumber(a) - $ToNumber(b);
30
- };
31
- export const $Mul = (a: VmAny, b: VmAny): number => {
36
+ }
37
+ /** 乘法 */
38
+ export function $Mul(a: VmAny, b: VmAny): number {
32
39
  return $ToNumber(a) * $ToNumber(b);
33
- };
34
- export const $Div = (a: VmAny, b: VmAny): number => {
40
+ }
41
+ /** 除法 */
42
+ export function $Div(a: VmAny, b: VmAny): number {
35
43
  return $ToNumber(a) / $ToNumber(b);
36
- };
37
- export const $Mod = (a: VmAny, b: VmAny): number => {
44
+ }
45
+ /** 取模 */
46
+ export function $Mod(a: VmAny, b: VmAny): number {
38
47
  return $ToNumber(a) % $ToNumber(b);
39
- };
40
- export const $Pow = (a: VmAny, b: VmAny): number => {
48
+ }
49
+ /** 乘方 */
50
+ export function $Pow(a: VmAny, b: VmAny): number {
41
51
  return $ToNumber(a) ** $ToNumber(b);
42
- };
52
+ }
43
53
 
44
54
  // Logical operations without short-circuiting
45
- export const $And = (a: VmAny, b: VmAny): boolean => {
55
+ /** */
56
+ export function $And(a: VmAny, b: VmAny): boolean {
46
57
  return $ToBoolean(a) && $ToBoolean(b);
47
- };
48
- export const $Or = (a: VmAny, b: VmAny): boolean => {
58
+ }
59
+ /** */
60
+ export function $Or(a: VmAny, b: VmAny): boolean {
49
61
  return $ToBoolean(a) || $ToBoolean(b);
50
- };
62
+ }
51
63
 
52
64
  // Comparison operations
53
- export const $Gt = (a: VmAny, b: VmAny): boolean => {
65
+ /** 大于 */
66
+ export function $Gt(a: VmAny, b: VmAny): boolean {
54
67
  if (overloadNumberString(a, b)) {
55
68
  return $ToNumber(a) > $ToNumber(b);
56
69
  } else {
57
70
  return $ToString(a) > $ToString(b);
58
71
  }
59
- };
60
- export const $Gte = (a: VmAny, b: VmAny): boolean => {
72
+ }
73
+ /** 大于等于 */
74
+ export function $Gte(a: VmAny, b: VmAny): boolean {
61
75
  if (overloadNumberString(a, b)) {
62
76
  return $ToNumber(a) >= $ToNumber(b);
63
77
  } else {
64
78
  return $ToString(a) >= $ToString(b);
65
79
  }
66
- };
67
- export const $Lt = (a: VmAny, b: VmAny): boolean => {
80
+ }
81
+ /** 小于 */
82
+ export function $Lt(a: VmAny, b: VmAny): boolean {
68
83
  if (overloadNumberString(a, b)) {
69
84
  return $ToNumber(a) < $ToNumber(b);
70
85
  } else {
71
86
  return $ToString(a) < $ToString(b);
72
87
  }
73
- };
74
- export const $Lte = (a: VmAny, b: VmAny): boolean => {
88
+ }
89
+ /** 小于等于 */
90
+ export function $Lte(a: VmAny, b: VmAny): boolean {
75
91
  if (overloadNumberString(a, b)) {
76
92
  return $ToNumber(a) <= $ToNumber(b);
77
93
  } else {
78
94
  return $ToString(a) <= $ToString(b);
79
95
  }
80
- };
96
+ }
81
97
 
82
98
  // Equality operations
83
- export const $Eq = (a: VmAny, b: VmAny): boolean => {
99
+ /** 等于 */
100
+ export function $Eq(a: VmAny, b: VmAny): boolean {
84
101
  $AssertInit(a);
85
102
  $AssertInit(b);
86
103
  // Number comparison is a special case to handle NaN correctly
87
104
  if (typeof a == 'number' && typeof b == 'number') return a === b;
88
105
  return isSame(a, b);
89
- };
90
- export const $Neq = (a: VmAny, b: VmAny): boolean => {
106
+ }
107
+ /** 不等于 */
108
+ export function $Neq(a: VmAny, b: VmAny): boolean {
91
109
  return !$Eq(a, b);
92
- };
110
+ }
93
111
 
94
112
  const { abs, min } = Math;
95
- export const $Aeq = (a: VmAny, b: VmAny): boolean => {
113
+ /** 近似等于 */
114
+ export function $Aeq(a: VmAny, b: VmAny): boolean {
96
115
  if (overloadNumberString(a, b)) {
97
116
  const an = $ToNumber(a);
98
117
  const bn = $ToNumber(b);
@@ -116,16 +135,19 @@ export const $Aeq = (a: VmAny, b: VmAny): boolean => {
116
135
  const bn = bi.normalize('NFC');
117
136
  return an === bn;
118
137
  }
119
- };
120
- export const $Naeq = (a: VmAny, b: VmAny): boolean => {
138
+ }
139
+ /** 不近似等于 */
140
+ export function $Naeq(a: VmAny, b: VmAny): boolean {
121
141
  return !$Aeq(a, b);
122
- };
142
+ }
123
143
 
124
- export const $Same = (a: VmAny, b: VmAny): boolean => {
144
+ /** 全等于 */
145
+ export function $Same(a: VmAny, b: VmAny): boolean {
125
146
  $AssertInit(a);
126
147
  $AssertInit(b);
127
148
  return isSame(a, b);
128
- };
129
- export const $Nsame = (a: VmAny, b: VmAny): boolean => {
149
+ }
150
+ /** 不全等于 */
151
+ export function $Nsame(a: VmAny, b: VmAny): boolean {
130
152
  return !$Same(a, b);
131
- };
153
+ }