@mirascript/mirascript 0.1.33 → 0.1.34

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 (52) hide show
  1. package/dist/{chunk-BMSHG7ON.js → chunk-DNMS3ZEP.js} +2 -2
  2. package/dist/{chunk-NRUNNMNC.js → chunk-GUMBLKWM.js} +18 -20
  3. package/dist/chunk-GUMBLKWM.js.map +6 -0
  4. package/dist/{chunk-UM7PQV4L.js → chunk-KUOYMOEU.js} +116 -115
  5. package/dist/chunk-KUOYMOEU.js.map +6 -0
  6. package/dist/{chunk-VZGKLLRC.js → chunk-VXTRR2CX.js} +2 -2
  7. package/dist/cli/index.js +4 -4
  8. package/dist/compiler/compile-fast.d.ts.map +1 -1
  9. package/dist/compiler/create-script.d.ts +1 -1
  10. package/dist/compiler/create-script.d.ts.map +1 -1
  11. package/dist/compiler/emit/constants.d.ts +1 -1
  12. package/dist/compiler/emit/constants.d.ts.map +1 -1
  13. package/dist/compiler/worker.js +1 -1
  14. package/dist/index.js +3 -3
  15. package/dist/subtle.js +3 -3
  16. package/dist/vm/lib/global/time.d.ts.map +1 -1
  17. package/dist/vm/operations/call.d.ts +7 -3
  18. package/dist/vm/operations/call.d.ts.map +1 -1
  19. package/dist/vm/operations/common.d.ts +2 -1
  20. package/dist/vm/operations/common.d.ts.map +1 -1
  21. package/dist/vm/operations/compound.d.ts +20 -10
  22. package/dist/vm/operations/compound.d.ts.map +1 -1
  23. package/dist/vm/operations/convert.d.ts +8 -4
  24. package/dist/vm/operations/convert.d.ts.map +1 -1
  25. package/dist/vm/operations/helpers.d.ts +8 -6
  26. package/dist/vm/operations/helpers.d.ts.map +1 -1
  27. package/dist/vm/operations/operator.d.ts +44 -22
  28. package/dist/vm/operations/operator.d.ts.map +1 -1
  29. package/dist/vm/operations/slice.d.ts +4 -2
  30. package/dist/vm/operations/slice.d.ts.map +1 -1
  31. package/dist/vm/operations/type-check.d.ts +14 -7
  32. package/dist/vm/operations/type-check.d.ts.map +1 -1
  33. package/dist/vm/types/extern.d.ts +6 -1
  34. package/dist/vm/types/extern.d.ts.map +1 -1
  35. package/package.json +3 -3
  36. package/src/compiler/compile-fast.ts +17 -20
  37. package/src/compiler/create-script.ts +1 -1
  38. package/src/compiler/emit/constants.ts +1 -1
  39. package/src/vm/lib/global/time.ts +6 -5
  40. package/src/vm/operations/call.ts +30 -7
  41. package/src/vm/operations/common.ts +3 -2
  42. package/src/vm/operations/compound.ts +33 -21
  43. package/src/vm/operations/convert.ts +12 -8
  44. package/src/vm/operations/helpers.ts +14 -12
  45. package/src/vm/operations/operator.ts +66 -44
  46. package/src/vm/operations/slice.ts +6 -4
  47. package/src/vm/operations/type-check.ts +21 -14
  48. package/src/vm/types/extern.ts +2 -0
  49. package/dist/chunk-NRUNNMNC.js.map +0 -6
  50. package/dist/chunk-UM7PQV4L.js.map +0 -6
  51. /package/dist/{chunk-BMSHG7ON.js.map → chunk-DNMS3ZEP.js.map} +0 -0
  52. /package/dist/{chunk-VZGKLLRC.js.map → chunk-VXTRR2CX.js.map} +0 -0
@@ -1,9 +1,16 @@
1
1
  import type { TypeName, VmAny, VmArray, VmRecord, VmValue } from '../types/index.js';
2
- export declare const $Type: (value: VmAny) => TypeName;
3
- export declare const $IsBoolean: (value: VmAny) => value is boolean;
4
- export declare const $IsNumber: (value: VmAny) => value is number;
5
- export declare const $IsString: (value: VmAny) => value is string;
6
- export declare const $IsRecord: (value: VmAny) => value is VmRecord;
7
- export declare const $IsArray: (value: VmAny) => value is VmArray;
8
- export declare const $AssertNonNil: (value: VmAny) => asserts value is NonNullable<VmValue>;
2
+ /** 获取值的类型名称 */
3
+ export declare function $Type(value: VmAny): TypeName;
4
+ /** 判断值是否为布尔值 */
5
+ export declare function $IsBoolean(value: VmAny): value is boolean;
6
+ /** 判断值是否为数字 */
7
+ export declare function $IsNumber(value: VmAny): value is number;
8
+ /** 判断值是否为字符串 */
9
+ export declare function $IsString(value: VmAny): value is string;
10
+ /** 判断值是否为记录 */
11
+ export declare function $IsRecord(value: VmAny): value is VmRecord;
12
+ /** 判断值是否为数组 */
13
+ export declare function $IsArray(value: VmAny): value is VmArray;
14
+ /** 断言值非 nil */
15
+ export declare function $AssertNonNil(value: VmAny): asserts value is NonNullable<VmValue>;
9
16
  //# sourceMappingURL=type-check.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"type-check.d.ts","sourceRoot":"","sources":["../../../src/vm/operations/type-check.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAGrF,eAAO,MAAM,KAAK,GAAI,OAAO,KAAK,KAAG,QAOpC,CAAC;AACF,eAAO,MAAM,UAAU,GAAI,OAAO,KAAK,KAAG,KAAK,IAAI,OAGlD,CAAC;AACF,eAAO,MAAM,SAAS,GAAI,OAAO,KAAK,KAAG,KAAK,IAAI,MAGjD,CAAC;AACF,eAAO,MAAM,SAAS,GAAI,OAAO,KAAK,KAAG,KAAK,IAAI,MAGjD,CAAC;AACF,eAAO,MAAM,SAAS,GAAI,OAAO,KAAK,KAAG,KAAK,IAAI,QAGjD,CAAC;AACF,eAAO,MAAM,QAAQ,GAAI,OAAO,KAAK,KAAG,KAAK,IAAI,OAGhD,CAAC;AACF,eAAO,MAAM,aAAa,GAAI,OAAO,KAAK,KAAG,QAAQ,KAAK,IAAI,WAAW,CAAC,OAAO,CAIhF,CAAC"}
1
+ {"version":3,"file":"type-check.d.ts","sourceRoot":"","sources":["../../../src/vm/operations/type-check.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAGrF,eAAe;AACf,wBAAgB,KAAK,CAAC,KAAK,EAAE,KAAK,GAAG,QAAQ,CAO5C;AACD,gBAAgB;AAChB,wBAAgB,UAAU,CAAC,KAAK,EAAE,KAAK,GAAG,KAAK,IAAI,OAAO,CAGzD;AACD,eAAe;AACf,wBAAgB,SAAS,CAAC,KAAK,EAAE,KAAK,GAAG,KAAK,IAAI,MAAM,CAGvD;AACD,gBAAgB;AAChB,wBAAgB,SAAS,CAAC,KAAK,EAAE,KAAK,GAAG,KAAK,IAAI,MAAM,CAGvD;AACD,eAAe;AACf,wBAAgB,SAAS,CAAC,KAAK,EAAE,KAAK,GAAG,KAAK,IAAI,QAAQ,CAGzD;AACD,eAAe;AACf,wBAAgB,QAAQ,CAAC,KAAK,EAAE,KAAK,GAAG,KAAK,IAAI,OAAO,CAGvD;AACD,eAAe;AACf,wBAAgB,aAAa,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,WAAW,CAAC,OAAO,CAAC,CAIjF"}
@@ -2,8 +2,13 @@ import type { TypeName, VmAny, VmConst, VmPrimitive, VmValue } from './index.js'
2
2
  import { VmWrapper } from './wrapper.js';
3
3
  /** 包装 Mirascript `extern` 类型的对象 */
4
4
  export declare class VmExtern<const T extends object = object> extends VmWrapper<T> {
5
+ /** 当 {@link value} 是函数时,绑定的 this 参数 */
5
6
  readonly thisArg: ThisParameterType<T> | null;
6
- constructor(value: T, thisArg?: ThisParameterType<T> | null);
7
+ constructor(
8
+ /** 包装值 */
9
+ value: T,
10
+ /** 当 {@link value} 是函数时,绑定的 this 参数 */
11
+ thisArg?: ThisParameterType<T> | null);
7
12
  /** Check if the object has a property */
8
13
  protected access(key: string, read: boolean): boolean;
9
14
  /** 决定是否对属性进行包装 */
@@ -1 +1 @@
1
- {"version":3,"file":"extern.d.ts","sourceRoot":"","sources":["../../../src/vm/types/extern.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AACjF,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAwBzC,mCAAmC;AACnC,qBAAa,QAAQ,CAAC,KAAK,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,CAAE,SAAQ,SAAS,CAAC,CAAC,CAAC;IAGnE,QAAQ,CAAC,OAAO,EAAE,iBAAiB,CAAC,CAAC,CAAC,GAAG,IAAI;gBAD7C,KAAK,EAAE,CAAC,EACC,OAAO,GAAE,iBAAiB,CAAC,CAAC,CAAC,GAAG,IAAW;IAKxD,yCAAyC;IACzC,SAAS,CAAC,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,OAAO;IAiBrD,kBAAkB;IAClB,SAAS,CAAC,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,CAAC,GAAG,SAAS,GAAG,KAAK,IAAI,OAAO,CAAC,OAAO,EAAE,WAAW,CAAC;IAIxG,kBAAkB;IACT,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAGlC,kBAAkB;IACT,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,KAAK;IAMhC,mCAAmC;IACnC,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO;IAMzC,wBAAwB;IACxB,IAAI,CAAC,IAAI,EAAE,SAAS,OAAO,EAAE,GAAG,KAAK;IAerC,kBAAkB;IACT,IAAI,CAAC,oBAAoB,UAAQ,GAAG,MAAM,EAAE;IAqBrD,kBAAkB;IACT,IAAI,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO;IAIpC,kBAAkB;IAClB,WAAW,IAAI,IAAI,IAAI,QAAQ,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;IAGnD,kBAAkB;IACT,QAAQ,CAAC,SAAS,EAAE,OAAO,GAAG,MAAM;IAiB7C,kBAAkB;IAClB,IAAa,IAAI,IAAI,QAAQ,CAE5B;IACD,kBAAkB;IAClB,IAAa,GAAG,IAAI,MAAM,CA6BzB;CACJ"}
1
+ {"version":3,"file":"extern.d.ts","sourceRoot":"","sources":["../../../src/vm/types/extern.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AACjF,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAwBzC,mCAAmC;AACnC,qBAAa,QAAQ,CAAC,KAAK,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,CAAE,SAAQ,SAAS,CAAC,CAAC,CAAC;IAInE,uCAAuC;IACvC,QAAQ,CAAC,OAAO,EAAE,iBAAiB,CAAC,CAAC,CAAC,GAAG,IAAI;;IAH7C,UAAU;IACV,KAAK,EAAE,CAAC;IACR,uCAAuC;IAC9B,OAAO,GAAE,iBAAiB,CAAC,CAAC,CAAC,GAAG,IAAW;IAKxD,yCAAyC;IACzC,SAAS,CAAC,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,OAAO;IAiBrD,kBAAkB;IAClB,SAAS,CAAC,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,CAAC,GAAG,SAAS,GAAG,KAAK,IAAI,OAAO,CAAC,OAAO,EAAE,WAAW,CAAC;IAIxG,kBAAkB;IACT,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAGlC,kBAAkB;IACT,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,KAAK;IAMhC,mCAAmC;IACnC,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO;IAMzC,wBAAwB;IACxB,IAAI,CAAC,IAAI,EAAE,SAAS,OAAO,EAAE,GAAG,KAAK;IAerC,kBAAkB;IACT,IAAI,CAAC,oBAAoB,UAAQ,GAAG,MAAM,EAAE;IAqBrD,kBAAkB;IACT,IAAI,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO;IAIpC,kBAAkB;IAClB,WAAW,IAAI,IAAI,IAAI,QAAQ,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;IAGnD,kBAAkB;IACT,QAAQ,CAAC,SAAS,EAAE,OAAO,GAAG,MAAM;IAiB7C,kBAAkB;IAClB,IAAa,IAAI,IAAI,QAAQ,CAE5B;IACD,kBAAkB;IAClB,IAAa,GAAG,IAAI,MAAM,CA6BzB;CACJ"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mirascript/mirascript",
3
- "version": "0.1.33",
3
+ "version": "0.1.34",
4
4
  "author": "CloudPSS",
5
5
  "license": "MIT",
6
6
  "description": "An expression based scripting language.",
@@ -36,8 +36,8 @@
36
36
  "commander": "^14.0.2",
37
37
  "source-map-js": "^1.2.1",
38
38
  "supports-color": "^10.2.2",
39
- "@mirascript/bindings": "~0.1.33",
40
- "@mirascript/constants": "~0.1.33"
39
+ "@mirascript/constants": "~0.1.34",
40
+ "@mirascript/bindings": "~0.1.34"
41
41
  },
42
42
  "devDependencies": {
43
43
  "@types/node": "^25.0.3",
@@ -1,8 +1,7 @@
1
1
  import { isKeyword } from '@mirascript/constants';
2
- import { wrapScript, type VmScript } from './create-script.js';
2
+ import { wrapScript, type VmScript, type VmScriptLike } from './create-script.js';
3
3
  import type { TranspileOptions } from './types.js';
4
4
  import { $GlobalFallback } from '../vm/operations/index.js';
5
- import type { VmContext, VmValue } from '../vm/index.js';
6
5
  import { defineProperty, isFinite } from '../helpers/utils.js';
7
6
 
8
7
  const REG_NUMBER_FULL = /^(?:[+-])?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?$/;
@@ -82,11 +81,11 @@ function nil(): () => null {
82
81
  }
83
82
 
84
83
  /** 构造返回全局变量的函数 */
85
- function globalVariable(id: string): (global: VmContext | undefined) => VmValue {
86
- const f = (global = $GlobalFallback()): VmValue => global.get(id);
84
+ function globalVariable(id: string): VmScriptLike {
85
+ const f: VmScriptLike = (global) => (global ?? $GlobalFallback()).get(id);
87
86
  defineProperty(f, 'toString', {
88
87
  value: () => {
89
- return `(global = $GlobalFallback()) => global.get(${JSON.stringify(id)});`;
88
+ return `(global) => (global ?? $GlobalFallback()).get(${JSON.stringify(id)});`;
90
89
  },
91
90
  writable: false,
92
91
  enumerable: false,
@@ -98,27 +97,26 @@ function globalVariable(id: string): (global: VmContext | undefined) => VmValue
98
97
  /**
99
98
  * 对短代码进行编译
100
99
  */
101
- function compileScriptFast(code: string, options: TranspileOptions): VmScript | undefined {
100
+ function compileScriptFast(code: string): VmScript | undefined {
102
101
  if (code.length > FAST_SCRIPT_MAX_LEN) return undefined; // 超过长度限制,直接返回 undefined
103
- const mode = options.input_mode ?? 'Script';
104
102
  const trimmedCode = code.trim();
105
103
  if (!trimmedCode) {
106
- return wrapScript(code, mode, nil());
104
+ return wrapScript(code, 'Script', nil());
107
105
  }
108
106
  switch (trimmedCode) {
109
107
  case 'nil':
110
- return wrapScript(code, mode, nil());
108
+ return wrapScript(code, 'Script', nil());
111
109
  case 'true':
112
- return wrapScript(code, mode, constantBoolean(true));
110
+ return wrapScript(code, 'Script', constantBoolean(true));
113
111
  case 'false':
114
- return wrapScript(code, mode, constantBoolean(false));
112
+ return wrapScript(code, 'Script', constantBoolean(false));
115
113
  case 'nan':
116
- return wrapScript(code, mode, nan());
114
+ return wrapScript(code, 'Script', nan());
117
115
  case 'inf':
118
116
  case '+inf':
119
- return wrapScript(code, mode, posInf());
117
+ return wrapScript(code, 'Script', posInf());
120
118
  case '-inf':
121
- return wrapScript(code, mode, negInf());
119
+ return wrapScript(code, 'Script', negInf());
122
120
  }
123
121
  if (REG_IDENTIFIER_FAST.test(trimmedCode)) {
124
122
  // 直接返回标识符
@@ -126,13 +124,13 @@ function compileScriptFast(code: string, options: TranspileOptions): VmScript |
126
124
  if (isKeyword(id)) {
127
125
  return undefined; // 关键字不处理
128
126
  }
129
- return wrapScript(code, mode, globalVariable(id));
127
+ return wrapScript(code, 'Script', globalVariable(id));
130
128
  }
131
129
  if (REG_NUMBER_FULL.test(trimmedCode)) {
132
130
  const num = Number(trimmedCode);
133
131
  if (!isFinite(num)) return undefined;
134
132
  // 直接返回数字
135
- return wrapScript(code, mode, constantFiniteNumber(num));
133
+ return wrapScript(code, 'Script', constantFiniteNumber(num));
136
134
  }
137
135
  return undefined;
138
136
  }
@@ -142,13 +140,12 @@ const FAST_TEMPLATE_MAX_LEN = 1024;
142
140
  /**
143
141
  * 对短代码进行编译
144
142
  */
145
- function compileTemplateFast(code: string, options: TranspileOptions): VmScript | undefined {
143
+ function compileTemplateFast(code: string): VmScript | undefined {
146
144
  if (code.length > FAST_TEMPLATE_MAX_LEN) return undefined; // 超过长度限制,直接返回 undefined
147
145
 
148
146
  if (!code.includes('$')) {
149
- const mode = options.input_mode ?? 'Template';
150
147
  // 不包含插值的模板
151
- return wrapScript(code, mode, constantString(code));
148
+ return wrapScript(code, 'Template', constantString(code));
152
149
  }
153
150
  return undefined;
154
151
  }
@@ -158,5 +155,5 @@ function compileTemplateFast(code: string, options: TranspileOptions): VmScript
158
155
  */
159
156
  export function compileFast(code: string, options: TranspileOptions): VmScript | undefined {
160
157
  if (options.sourceMap) return undefined; // 不支持源映射
161
- return (options.input_mode === 'Template' ? compileTemplateFast : compileScriptFast)(code, options);
158
+ return (options.input_mode === 'Template' ? compileTemplateFast : compileScriptFast)(code);
162
159
  }
@@ -5,7 +5,7 @@ import type { VmValue, VmContext } from '../vm/types/index.js';
5
5
  import type { InputMode, ScriptInput } from './types.js';
6
6
 
7
7
  /** Mirascript 脚本 */
8
- export type VmScriptLike = (global?: VmContext) => VmValue;
8
+ export type VmScriptLike = (global?: VmContext | null) => VmValue;
9
9
 
10
10
  /** Mirascript 脚本 */
11
11
  export type VmScript = VmScriptLike & {
@@ -1 +1 @@
1
- export const SCRIPT_PREFIX = `((global = $GlobalFallback()) => { try { $CpEnter();`;
1
+ export const SCRIPT_PREFIX = `((global) => { global ??= $GlobalFallback(); try { $CpEnter();`;
@@ -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
  ],
@@ -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
+ }
@@ -11,7 +11,8 @@ import { $ToString } from './convert.js';
11
11
  const { trunc } = Math;
12
12
  const { at } = Array.prototype;
13
13
 
14
- export const $In = (value: VmAny, iterable: VmAny): boolean => {
14
+ /** 检查值是否在可迭代对象中 */
15
+ export function $In(value: VmAny, iterable: VmAny): boolean {
15
16
  $AssertInit(value);
16
17
  $AssertInit(iterable);
17
18
  if (iterable == null) return false;
@@ -31,16 +32,20 @@ export const $In = (value: VmAny, iterable: VmAny): boolean => {
31
32
  const key = toString(value, undefined);
32
33
  if (isVmWrapper(iterable)) return iterable.has(key);
33
34
  return hasOwnEnumerable(iterable satisfies VmRecord, key);
34
- };
35
- export const $Length = (value: VmAny): number => {
35
+ }
36
+
37
+ /** 获取值的长度 */
38
+ export function $Length(value: VmAny): number {
36
39
  $AssertInit(value);
37
40
  if (isVmArray(value)) return value.length;
38
41
  if (isVmRecord(value)) return keys(value).length;
39
42
  if (isVmWrapper(value)) return value.keys().length;
40
43
 
41
44
  throw new VmError(`Value has no length: ${display(value)}`, 0);
42
- };
43
- export const $Omit = (value: VmAny, omitted: ReadonlyArray<number | string>): VmRecord => {
45
+ }
46
+
47
+ /** 删除记录中的指定字段 */
48
+ export function $Omit(value: VmAny, omitted: ReadonlyArray<number | string>): VmRecord {
44
49
  $AssertInit(value);
45
50
  if (value == null || !isVmRecord(value)) return {};
46
51
  const result: Record<string, VmConst> = {};
@@ -53,8 +58,10 @@ export const $Omit = (value: VmAny, omitted: ReadonlyArray<number | string>): Vm
53
58
  }
54
59
  }
55
60
  return result;
56
- };
57
- export const $Pick = (value: VmAny, picked: ReadonlyArray<number | string>): VmRecord => {
61
+ }
62
+
63
+ /** 选择记录中的指定字段 */
64
+ export function $Pick(value: VmAny, picked: ReadonlyArray<number | string>): VmRecord {
58
65
  $AssertInit(value);
59
66
  if (value == null || !isVmRecord(value)) return {};
60
67
  const result: Record<string, VmConst> = {};
@@ -65,15 +72,17 @@ export const $Pick = (value: VmAny, picked: ReadonlyArray<number | string>): VmR
65
72
  }
66
73
  }
67
74
  return result;
68
- };
69
- export const $Has = (obj: VmAny, key: VmAny): boolean => {
75
+ }
76
+ /** 检查是否拥有字段 */
77
+ export function $Has(obj: VmAny, key: VmAny): boolean {
70
78
  $AssertInit(obj);
71
79
  const pk = $ToString(key);
72
80
  if (obj == null || typeof obj != 'object') return false;
73
81
  if (isVmWrapper(obj)) return obj.has(pk);
74
82
  return hasOwnEnumerable(obj, pk);
75
- };
76
- export const $Get = (obj: VmAny, key: VmAny): VmValue => {
83
+ }
84
+ /** 获取字段 */
85
+ export function $Get(obj: VmAny, key: VmAny): VmValue {
77
86
  $AssertInit(obj);
78
87
  if (isVmArray(obj)) {
79
88
  $AssertInit(key);
@@ -86,24 +95,26 @@ export const $Get = (obj: VmAny, key: VmAny): VmValue => {
86
95
  if (isVmWrapper(obj)) return obj.get(pk) ?? null;
87
96
  if (!hasOwnEnumerable(obj, pk)) return null;
88
97
  return obj[pk] ?? null;
89
- };
90
- export const $Set = (obj: VmAny, key: VmAny, value: VmAny): void => {
98
+ }
99
+ /** 设置字段 */
100
+ export function $Set(obj: VmAny, key: VmAny, value: VmAny): void {
91
101
  $AssertInit(obj);
92
102
  $AssertInit(value);
93
103
  const pk = $ToString(key);
94
104
  if (obj == null) return;
95
105
  if (!isVmExtern(obj)) throw new VmError(`Expected extern, got ${display(obj)}`, undefined);
96
106
  obj.set(pk, value);
97
- };
98
- export const $Iterable = (value: VmAny): Iterable<VmValue | undefined> => {
107
+ }
108
+ /** 获取可迭代对象 */
109
+ export function $Iterable(value: VmAny): Iterable<VmValue | undefined> {
99
110
  $AssertInit(value);
100
111
  if (isVmWrapper(value)) return value.keys();
101
112
  if (isVmArray(value)) return value;
102
113
  if (value != null && typeof value == 'object') return keys(value);
103
114
  throw new VmError(`Value is not iterable: ${display(value)}`, isVmFunction(value) ? [] : [value]);
104
- };
105
-
106
- export const $RecordSpread = (record: VmAny): VmRecord | null => {
115
+ }
116
+ /** 展开记录 */
117
+ export function $RecordSpread(record: VmAny): VmRecord | null {
107
118
  $AssertInit(record);
108
119
  if (record == null || isVmRecord(record)) return record;
109
120
  if (isVmArray(record)) {
@@ -127,9 +138,10 @@ export const $RecordSpread = (record: VmAny): VmRecord | null => {
127
138
  return result;
128
139
  }
129
140
  throw new VmError(`Expected record, array, extern or nil, got ${display(record)}`, null);
130
- };
141
+ }
131
142
 
132
- export const $ArraySpread = (array: VmAny): Iterable<VmConst | undefined> => {
143
+ /** 展开数组 */
144
+ export function $ArraySpread(array: VmAny): Iterable<VmConst | undefined> {
133
145
  $AssertInit(array);
134
146
  if (array == null) return [];
135
147
  if (isVmArray(array)) return array;
@@ -146,4 +158,4 @@ export const $ArraySpread = (array: VmAny): Iterable<VmConst | undefined> => {
146
158
  return result;
147
159
  }
148
160
  throw new VmError(`Expected array, iterable extern or nil, got ${display(array)}`, []);
149
- };
161
+ }
@@ -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 {