@codehz/json-expr 0.5.6 → 0.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- //#region src/ast-types.ts
1
+ //#region src/types/ast-types.ts
2
2
  const PRECEDENCE = {
3
3
  "||": 1,
4
4
  "??": 1,
@@ -50,7 +50,7 @@ const BUILTIN_CONSTRUCTORS = new Set([
50
50
  ]);
51
51
 
52
52
  //#endregion
53
- //#region src/generate.ts
53
+ //#region src/core/generate.ts
54
54
  /**
55
55
  * 创建新的生成上下文
56
56
  */
@@ -316,586 +316,412 @@ function transformPlaceholders(node, transform) {
316
316
  }
317
317
 
318
318
  //#endregion
319
- //#region src/proxy-metadata.ts
319
+ //#region src/core/parser/constants.ts
320
320
  /**
321
- * 全局 WeakMap 存储
322
- */
323
- const proxyMetadata = /* @__PURE__ */ new WeakMap();
324
- /**
325
- * 设置 Proxy 元数据
321
+ * 解析器常量定义
326
322
  */
327
- function setProxyMetadata(proxy, metadata) {
328
- proxyMetadata.set(proxy, metadata);
329
- }
330
323
  /**
331
- * 获取 Proxy 元数据
324
+ * 运算符列表,按长度排序(长的在前)以确保正确匹配
332
325
  */
333
- function getProxyMetadata(proxy) {
334
- return proxyMetadata.get(proxy);
335
- }
336
-
337
- //#endregion
338
- //#region src/proxy-variable.ts
339
- const typedArrayConstructors = [
340
- "Int8Array",
341
- "Uint8Array",
342
- "Uint8ClampedArray",
343
- "Int16Array",
344
- "Uint16Array",
345
- "Int32Array",
346
- "Uint32Array",
347
- "Float32Array",
348
- "Float64Array",
349
- "BigInt64Array",
350
- "BigUint64Array"
326
+ const OPERATORS = [
327
+ "instanceof",
328
+ ">>>",
329
+ "===",
330
+ "!==",
331
+ "&&",
332
+ "||",
333
+ "??",
334
+ "==",
335
+ "!=",
336
+ "<=",
337
+ ">=",
338
+ "<<",
339
+ ">>",
340
+ "**",
341
+ "in",
342
+ "+",
343
+ "-",
344
+ "*",
345
+ "/",
346
+ "%",
347
+ "<",
348
+ ">",
349
+ "&",
350
+ "|",
351
+ "^"
351
352
  ];
352
353
  /**
353
- * 创建占位符 AST 节点
354
+ * 关键字运算符(需要后面不能跟标识符字符)
354
355
  */
355
- function placeholder(id) {
356
- return {
357
- type: "Placeholder",
358
- id
359
- };
360
- }
356
+ const KEYWORD_OPERATORS = new Set(["in", "instanceof"]);
361
357
  /**
362
- * 创建标识符 AST 节点
358
+ * 转义字符映射
363
359
  */
364
- function identifier(name) {
365
- return {
366
- type: "Identifier",
367
- name
368
- };
369
- }
360
+ const ESCAPE_CHARS = {
361
+ n: "\n",
362
+ r: "\r",
363
+ t: " ",
364
+ "\\": "\\",
365
+ "'": "'",
366
+ "\"": "\"",
367
+ "`": "`"
368
+ };
369
+
370
+ //#endregion
371
+ //#region src/core/parser/utils.ts
370
372
  /**
371
- * 创建数字字面量 AST 节点
373
+ * 解析器工具函数
372
374
  */
373
- function numberLiteral(value) {
374
- return {
375
- type: "NumberLiteral",
376
- value,
377
- raw: String(value)
378
- };
379
- }
380
375
  /**
381
- * 创建字符串字面量 AST 节点
376
+ * 判断字符是否为数字 0-9
382
377
  */
383
- function stringLiteral(value, quote = "\"") {
384
- return {
385
- type: "StringLiteral",
386
- value,
387
- quote
388
- };
378
+ function isDigit(ch) {
379
+ const code = ch.charCodeAt(0);
380
+ return code >= 48 && code <= 57;
389
381
  }
390
382
  /**
391
- * 创建成员表达式 AST 节点
383
+ * 判断字符是否为十六进制数字 0-9, A-F, a-f
392
384
  */
393
- function memberExpr(object, property) {
394
- return {
395
- type: "MemberExpr",
396
- object,
397
- property,
398
- computed: false,
399
- optional: false
400
- };
385
+ function isHexDigit(ch) {
386
+ const code = ch.charCodeAt(0);
387
+ return code >= 48 && code <= 57 || code >= 65 && code <= 70 || code >= 97 && code <= 102;
401
388
  }
402
389
  /**
403
- * 创建调用表达式 AST 节点
390
+ * 判断字符是否可以作为标识符的开头(字母、下划线、$)
404
391
  */
405
- function callExpr(callee, arguments_) {
406
- return {
407
- type: "CallExpr",
408
- callee,
409
- arguments: arguments_,
410
- optional: false
411
- };
392
+ function isIdentifierStart(ch) {
393
+ const code = ch.charCodeAt(0);
394
+ return code >= 65 && code <= 90 || code >= 97 && code <= 122 || code === 95 || code === 36;
412
395
  }
413
396
  /**
414
- * 创建数组表达式 AST 节点
397
+ * 判断字符是否可以作为标识符的一部分(字母、数字、下划线、$)
415
398
  */
416
- function arrayExpr(elements) {
417
- return {
418
- type: "ArrayExpr",
419
- elements
420
- };
399
+ function isIdentifierPart(ch) {
400
+ const code = ch.charCodeAt(0);
401
+ return code >= 65 && code <= 90 || code >= 97 && code <= 122 || code >= 48 && code <= 57 || code === 95 || code === 36;
421
402
  }
403
+
404
+ //#endregion
405
+ //#region src/core/parser/tokenizer.ts
422
406
  /**
423
- * 检查对象是否为 TypedArray 实例
407
+ * 词法分析器 - 负责源代码的逐字符扫描和标记识别
424
408
  */
425
- function getTypedArrayConstructor(value) {
426
- for (const constructorName of typedArrayConstructors) {
427
- const Constructor = globalThis[constructorName];
428
- if (Constructor && value instanceof Constructor) return Constructor;
429
- }
430
- return null;
431
- }
432
409
  /**
433
- * 序列化参数为 AST 节点
434
- * - Proxy Variable/Expression:使用 ast 或占位符标识符
435
- * - 数组:返回 ArrayExpr 节点
436
- * - 对象:返回 ObjectExpr 节点
437
- * - 原始值:返回对应的字面量节点
438
- * - Date, RegExp, BigInt, URL, URLSearchParams, Map, Set, TypedArray, DataView: 构造函数调用
410
+ * Tokenizer - 提供词法分析的基础功能
439
411
  */
440
- function serializeArgumentToAST(arg) {
441
- if ((typeof arg === "object" || typeof arg === "function") && arg !== null) {
442
- const meta = getProxyMetadata(arg);
443
- if (meta) {
444
- if (meta.ast) return meta.ast;
445
- if (meta.rootVariable) return placeholder(meta.rootVariable);
446
- }
412
+ var Tokenizer = class {
413
+ pos = 0;
414
+ source;
415
+ constructor(source) {
416
+ this.source = source;
447
417
  }
448
- if (Array.isArray(arg)) return arrayExpr(arg.map(serializeArgumentToAST));
449
- if (typeof arg === "object" && arg !== null) {
450
- if (arg instanceof Date) return callExpr(identifier("Date"), [numberLiteral(arg.getTime())]);
451
- if (arg instanceof RegExp) {
452
- const args = [stringLiteral(arg.source)];
453
- if (arg.flags) args.push(stringLiteral(arg.flags));
454
- return callExpr(identifier("RegExp"), args);
418
+ /**
419
+ * 查看当前位置的字符,不移动位置
420
+ */
421
+ peek() {
422
+ return this.source[this.pos] || "";
423
+ }
424
+ /**
425
+ * 查看指定偏移量位置的字符,不移动位置
426
+ */
427
+ peekAt(offset) {
428
+ return this.source[this.pos + offset] || "";
429
+ }
430
+ /**
431
+ * 前进一个字符并返回该字符
432
+ */
433
+ advance() {
434
+ return this.source[this.pos++] || "";
435
+ }
436
+ /**
437
+ * 期望当前字符是指定字符,否则抛出错误
438
+ */
439
+ expect(ch) {
440
+ if (this.peek() !== ch) throw new Error(`Expected '${ch}' at position ${this.pos}, got '${this.peek()}'`);
441
+ this.advance();
442
+ }
443
+ /**
444
+ * 跳过空白字符
445
+ */
446
+ skipWhitespace() {
447
+ while (/\s/.test(this.peek())) this.advance();
448
+ }
449
+ /**
450
+ * 尝试匹配并消费运算符
451
+ * 返回匹配到的运算符,如果没有匹配则返回 null
452
+ */
453
+ peekOperator() {
454
+ for (const op of OPERATORS) {
455
+ if (!this.source.startsWith(op, this.pos)) continue;
456
+ if (KEYWORD_OPERATORS.has(op)) {
457
+ const nextChar = this.source[this.pos + op.length];
458
+ if (nextChar && isIdentifierPart(nextChar)) continue;
459
+ }
460
+ return op;
455
461
  }
456
- if (typeof URL !== "undefined" && arg instanceof URL) return callExpr(identifier("URL"), [stringLiteral(arg.href)]);
457
- if (typeof URLSearchParams !== "undefined" && arg instanceof URLSearchParams) {
458
- const entries = [];
459
- arg.forEach((value, key) => {
460
- entries.push(arrayExpr([stringLiteral(key), stringLiteral(value)]));
461
- });
462
- return callExpr(identifier("URLSearchParams"), [arrayExpr(entries)]);
462
+ return null;
463
+ }
464
+ /**
465
+ * 尝试匹配并消费关键字
466
+ * 如果匹配成功则移动位置并返回 true,否则返回 false
467
+ */
468
+ matchKeyword(keyword) {
469
+ if (this.source.startsWith(keyword, this.pos)) {
470
+ const nextChar = this.source[this.pos + keyword.length];
471
+ if (!nextChar || !isIdentifierPart(nextChar)) {
472
+ this.pos += keyword.length;
473
+ return true;
474
+ }
463
475
  }
464
- if (arg instanceof Map) {
465
- const entries = [];
466
- arg.forEach((value, key) => {
467
- entries.push(arrayExpr([serializeArgumentToAST(key), serializeArgumentToAST(value)]));
468
- });
469
- return callExpr(identifier("Map"), [arrayExpr(entries)]);
476
+ return false;
477
+ }
478
+ };
479
+
480
+ //#endregion
481
+ //#region src/core/parser/primary-parser.ts
482
+ /**
483
+ * PrimaryParser 类 - 继承 Tokenizer,提供基本类型的解析功能
484
+ */
485
+ var PrimaryParser = class extends Tokenizer {
486
+ /**
487
+ * 解析数字字面量
488
+ */
489
+ parseNumber() {
490
+ const start = this.pos;
491
+ if (this.peek() === "0") {
492
+ const next = this.peekAt(1)?.toLowerCase();
493
+ if (next === "x" || next === "o" || next === "b") {
494
+ this.advance();
495
+ this.advance();
496
+ while (isHexDigit(this.peek())) this.advance();
497
+ const raw = this.source.slice(start, this.pos);
498
+ return {
499
+ type: "NumberLiteral",
500
+ value: Number(raw),
501
+ raw
502
+ };
503
+ }
470
504
  }
471
- if (arg instanceof Set) {
472
- const values = [];
473
- arg.forEach((value) => values.push(serializeArgumentToAST(value)));
474
- return callExpr(identifier("Set"), [arrayExpr(values)]);
505
+ while (isDigit(this.peek())) this.advance();
506
+ if (this.peek() === "." && isDigit(this.peekAt(1))) {
507
+ this.advance();
508
+ while (isDigit(this.peek())) this.advance();
475
509
  }
476
- const typedArrayConstructor = getTypedArrayConstructor(arg);
477
- if (typedArrayConstructor) {
478
- const values = [...arg].map(serializeArgumentToAST);
479
- const constructorName = typedArrayConstructor.name;
480
- return callExpr(identifier(constructorName), [arrayExpr(values)]);
510
+ if (this.peek()?.toLowerCase() === "e") {
511
+ this.advance();
512
+ if (this.peek() === "+" || this.peek() === "-") this.advance();
513
+ while (isDigit(this.peek())) this.advance();
481
514
  }
482
- if (arg instanceof ArrayBuffer) {
483
- const uint8Array = new Uint8Array(arg);
484
- const values = Array.from(uint8Array).map(numberLiteral);
485
- return memberExpr(callExpr(identifier("Uint8Array"), [arrayExpr(values)]), identifier("buffer"));
515
+ const raw = this.source.slice(start, this.pos);
516
+ return {
517
+ type: "NumberLiteral",
518
+ value: Number(raw),
519
+ raw
520
+ };
521
+ }
522
+ /**
523
+ * 解析字符串字面量
524
+ */
525
+ parseString() {
526
+ const quote = this.peek();
527
+ this.advance();
528
+ let value = "";
529
+ while (this.pos < this.source.length && this.peek() !== quote) if (this.peek() === "\\") {
530
+ this.advance();
531
+ const escaped = this.peek();
532
+ value += ESCAPE_CHARS[escaped] ?? escaped;
533
+ this.advance();
534
+ } else {
535
+ value += this.peek();
536
+ this.advance();
486
537
  }
487
- if (arg instanceof DataView) return callExpr(identifier("DataView"), [serializeArgumentToAST(arg.buffer)]);
538
+ this.expect(quote);
488
539
  return {
489
- type: "ObjectExpr",
490
- properties: Object.entries(arg).map(([k, v]) => {
491
- return {
492
- key: /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(k) ? identifier(k) : stringLiteral(k),
493
- value: serializeArgumentToAST(v),
494
- computed: false,
495
- shorthand: false
496
- };
497
- })
540
+ type: "StringLiteral",
541
+ value,
542
+ quote
498
543
  };
499
544
  }
500
- if (arg === null) return { type: "NullLiteral" };
501
- if (arg === void 0) return identifier("undefined");
502
- if (typeof arg === "boolean") return {
503
- type: "BooleanLiteral",
504
- value: arg
505
- };
506
- if (typeof arg === "number") return numberLiteral(arg);
507
- if (typeof arg === "string") return stringLiteral(arg);
508
- if (typeof arg === "bigint") return callExpr(identifier("BigInt"), [stringLiteral(arg.toString())]);
509
- throw new Error(`Unsupported argument type: ${typeof arg}`);
510
- }
511
- /**
512
- * 从参数中收集依赖的 Symbol
513
- * 递归遍历数组和对象,收集所有 Proxy 的依赖
514
- */
515
- function collectDepsFromArgs(args, deps) {
516
- for (const arg of args) if ((typeof arg === "object" || typeof arg === "function") && arg !== null) {
517
- const meta = getProxyMetadata(arg);
518
- if (meta?.dependencies) for (const dep of meta.dependencies) deps.add(dep);
519
- else if (Array.isArray(arg)) collectDepsFromArgs(arg, deps);
520
- else if (typeof arg === "object") collectDepsFromArgs(Object.values(arg), deps);
521
- }
522
- }
523
- /**
524
- * 创建 Proxy 的公共 handler
525
- */
526
- function createProxyHandler(ast, deps) {
527
- return {
528
- get(_target, prop) {
529
- if (typeof prop === "symbol") return void 0;
530
- return createProxyExpressionWithAST(memberExpr(ast, identifier(String(prop))), deps);
531
- },
532
- apply(_target, _thisArg, args) {
533
- const callAst = callExpr(ast, args.map(serializeArgumentToAST));
534
- const newDeps = new Set(deps);
535
- collectDepsFromArgs(args, newDeps);
536
- return createProxyExpressionWithAST(callAst, newDeps);
537
- }
538
- };
539
- }
540
- /**
541
- * 创建根 Variable Proxy
542
- * 拦截属性访问,返回新的 expression proxy
543
- * 不可直接调用(apply 应该只在链式调用后可用)
544
- *
545
- * @param id - 变量的唯一标识 Symbol
546
- * @returns Proxy 包装的 Variable
547
- */
548
- function createProxyVariable(id) {
549
- const deps = new Set([id]);
550
- const ast = placeholder(id);
551
- const proxy = new Proxy(function() {}, createProxyHandler(ast, deps));
552
- setProxyMetadata(proxy, {
553
- type: "variable",
554
- rootVariable: id,
555
- dependencies: deps
556
- });
557
- return proxy;
558
- }
559
- /**
560
- * 创建带完整 AST 的 Proxy(方法调用后)
561
- * 可以继续链式访问和调用
562
- *
563
- * @param ast - 完整的表达式 AST
564
- * @param deps - 依赖集合
565
- * @returns Proxy 包装的 Expression
566
- */
567
- function createProxyExpressionWithAST(ast, deps) {
568
- const proxy = new Proxy(function() {}, createProxyHandler(ast, deps));
569
- setProxyMetadata(proxy, {
570
- type: "expression",
571
- ast,
572
- dependencies: deps
573
- });
574
- return proxy;
575
- }
576
-
577
- //#endregion
578
- //#region src/variable.ts
579
- /**
580
- * 跟踪每个 variable 的唯一 Symbol ID
581
- */
582
- const variableIds = /* @__PURE__ */ new WeakMap();
583
- /**
584
- * 计数器用于生成唯一变量 ID
585
- */
586
- let variableCounter = 0;
587
- /**
588
- * 创建一个类型化变量
589
- * 返回 Proxy 对象,支持链式属性访问和方法调用
590
- *
591
- * @example
592
- * ```ts
593
- * const x = variable<number>();
594
- * const config = variable<{ timeout: number }>();
595
- * const timeout = config.timeout; // Proxy expression
596
- * ```
597
- */
598
- function variable() {
599
- const id = Symbol(`var_${variableCounter++}`);
600
- const proxy = createProxyVariable(id);
601
- variableIds.set(proxy, id);
602
- return proxy;
603
- }
604
- /**
605
- * 获取 variable 的唯一 Symbol ID
606
- */
607
- function getVariableId(variable) {
608
- if (typeof variable !== "object" && typeof variable !== "function" || variable === null) return void 0;
609
- return variableIds.get(variable);
610
- }
611
-
612
- //#endregion
613
- //#region src/compile.ts
614
- const ALLOWED_GLOBALS = new Set([
615
- "Math",
616
- "JSON",
617
- "Date",
618
- "RegExp",
619
- "Number",
620
- "String",
621
- "Boolean",
622
- "Array",
623
- "Object",
624
- "undefined",
625
- "NaN",
626
- "Infinity",
627
- "isNaN",
628
- "isFinite",
629
- "parseInt",
630
- "parseFloat",
631
- "BigInt",
632
- "URL",
633
- "URLSearchParams",
634
- "Map",
635
- "Set",
636
- "Int8Array",
637
- "Uint8Array",
638
- "Uint8ClampedArray",
639
- "Int16Array",
640
- "Uint16Array",
641
- "Int32Array",
642
- "Uint32Array",
643
- "Float32Array",
644
- "Float64Array",
645
- "BigInt64Array",
646
- "BigUint64Array",
647
- "ArrayBuffer",
648
- "DataView"
649
- ]);
650
- /**
651
- * 将 Proxy Expression 编译为可序列化的 JSON 结构
652
- *
653
- * @template TResult - 表达式结果类型
654
- * @param expression - Proxy Expression,或包含 Proxy 的对象/数组/原始值
655
- * @param variables - 所有使用的变量定义
656
- * @param options - 编译选项
657
- * @returns 编译后的数据结构 [变量名列表, 表达式1, 表达式2, ...]
658
- *
659
- * @throws 如果传入无效的表达式或未定义的变量引用
660
- *
661
- * @example
662
- * ```ts
663
- * const x = variable<number>()
664
- * const y = variable<number>()
665
- * const sum = expr({ x, y })("x + y")
666
- * const result = expr({ sum, x })("sum * x")
667
- * const compiled = compile(result, { x, y })
668
- * // => [["x", "y"], "($0+$1)*$0"]
669
- * ```
670
- */
671
- function compile(expression, variables, options = {}) {
672
- const { shortCircuit = true } = options;
673
- const ast = serializeArgumentToAST(expression);
674
- const variableOrder = [];
675
- const variableToIndex = /* @__PURE__ */ new Map();
676
- const symbolToName = /* @__PURE__ */ new Map();
677
- for (const [name, value] of Object.entries(variables)) {
678
- if (!variableToIndex.has(name)) {
679
- variableToIndex.set(name, variableOrder.length);
680
- variableOrder.push(name);
545
+ /**
546
+ * 解析数组字面量
547
+ */
548
+ parseArray() {
549
+ this.expect("[");
550
+ const elements = [];
551
+ this.skipWhitespace();
552
+ while (this.peek() !== "]") {
553
+ elements.push(this.parseExpression());
554
+ this.skipWhitespace();
555
+ if (this.peek() === ",") {
556
+ this.advance();
557
+ this.skipWhitespace();
558
+ } else break;
681
559
  }
682
- const id = getVariableId(value);
683
- if (id) symbolToName.set(id, name);
684
- }
685
- const placeholderTransformed = transformPlaceholders(ast, (id) => {
686
- const name = symbolToName.get(id);
687
- if (!name) return null;
688
- const index = variableToIndex.get(name);
689
- if (index === void 0) return null;
690
- return `$${index}`;
691
- });
692
- const undefinedVars = [];
693
- const transformed = transformIdentifiers(placeholderTransformed, (name) => {
694
- if (name.startsWith("$") && /^\$\d+$/.test(name)) return name;
695
- const index = variableToIndex.get(name);
696
- if (index !== void 0) return `$${index}`;
697
- if (!ALLOWED_GLOBALS.has(name)) undefinedVars.push(name);
698
- return name;
699
- });
700
- if (undefinedVars.length > 0) {
701
- const uniqueVars = [...new Set(undefinedVars)];
702
- throw new Error(`Undefined variable(s): ${uniqueVars.join(", ")}`);
560
+ this.expect("]");
561
+ return {
562
+ type: "ArrayExpr",
563
+ elements
564
+ };
703
565
  }
704
- const expressions = [];
705
- if (shortCircuit) {
706
- let nextIndex = variableOrder.length;
707
- function compileAst(node) {
708
- if (node.type === "BinaryExpr" && (node.operator === "||" || node.operator === "&&" || node.operator === "??")) return compileShortCircuit(node);
709
- if (node.type === "ConditionalExpr") return compileConditional(node);
710
- const exprStr = generate(node);
711
- expressions.push(exprStr);
712
- return nextIndex++;
566
+ /**
567
+ * 解析对象字面量
568
+ */
569
+ parseObject() {
570
+ this.expect("{");
571
+ const properties = [];
572
+ this.skipWhitespace();
573
+ while (this.peek() !== "}") {
574
+ const prop = this.parseObjectProperty();
575
+ properties.push(prop);
576
+ this.skipWhitespace();
577
+ if (this.peek() === ",") {
578
+ this.advance();
579
+ this.skipWhitespace();
580
+ } else break;
713
581
  }
714
- function compileShortCircuit(node) {
715
- const leftIdx = compileAst(node.left);
716
- const branchConditions = {
717
- "||": `$${leftIdx}`,
718
- "&&": `!$${leftIdx}`,
719
- "??": `$${leftIdx}!=null`
582
+ this.expect("}");
583
+ return {
584
+ type: "ObjectExpr",
585
+ properties
586
+ };
587
+ }
588
+ /**
589
+ * 解析对象属性
590
+ */
591
+ parseObjectProperty() {
592
+ this.skipWhitespace();
593
+ let key;
594
+ let computed = false;
595
+ if (this.peek() === "[") {
596
+ this.advance();
597
+ this.skipWhitespace();
598
+ key = this.parseExpression();
599
+ this.skipWhitespace();
600
+ this.expect("]");
601
+ computed = true;
602
+ } else if (this.peek() === "\"" || this.peek() === "'") key = this.parseString();
603
+ else key = this.parseIdentifier();
604
+ this.skipWhitespace();
605
+ if (this.peek() === ":") {
606
+ this.advance();
607
+ this.skipWhitespace();
608
+ const value = this.parseExpression();
609
+ return {
610
+ key,
611
+ value,
612
+ computed,
613
+ shorthand: false
720
614
  };
721
- const branchIdx = expressions.length;
722
- expressions.push([
723
- "br",
724
- branchConditions[node.operator],
725
- 0
726
- ]);
727
- nextIndex++;
728
- compileAst(node.right);
729
- const skipCount = expressions.length - branchIdx - 1;
730
- expressions[branchIdx][2] = skipCount;
731
- const phiIdx = nextIndex++;
732
- expressions.push(["phi"]);
733
- return phiIdx;
734
615
  }
735
- function compileConditional(node) {
736
- const testIdx = compileAst(node.test);
737
- const branchIdx = expressions.length;
738
- expressions.push([
739
- "br",
740
- `$${testIdx}`,
741
- 0
742
- ]);
743
- nextIndex++;
744
- compileAst(node.alternate);
745
- const jmpIdx = expressions.length;
746
- expressions.push(["jmp", 0]);
747
- nextIndex++;
748
- compileAst(node.consequent);
749
- const thenEndIdx = expressions.length;
750
- expressions[branchIdx][2] = jmpIdx - branchIdx;
751
- expressions[jmpIdx][1] = thenEndIdx - jmpIdx - 1;
752
- const phiIdx = nextIndex++;
753
- expressions.push(["phi"]);
754
- return phiIdx;
755
- }
756
- compileAst(transformed);
757
- } else expressions.push(generate(transformed));
758
- return [variableOrder, ...expressions];
759
- }
760
-
761
- //#endregion
762
- //#region src/evaluate.ts
763
- /**
764
- * 缓存已构造的求值函数,以提升重复执行性能
765
- */
766
- const evaluatorCache = /* @__PURE__ */ new Map();
767
- /**
768
- * 检测编译数据是否包含控制流节点(V2 格式)
769
- */
770
- function isV2Format(expressions) {
771
- return expressions.some((expr) => Array.isArray(expr));
772
- }
773
- /**
774
- * 执行编译后的表达式
775
- *
776
- * @template TResult - 表达式结果类型
777
- * @param data - 编译后的数据结构 [变量名列表, 表达式1, 表达式2, ...]
778
- * @param values - 变量值映射,按变量名提供值
779
- * @returns 最后一个表达式的求值结果
780
- *
781
- * @throws 如果运行时类型验证失败或表达式执行出错
782
- *
783
- * @example
784
- * ```ts
785
- * const compiled = [["x", "y"], "$0+$1", "$1*2"]
786
- * const result = evaluate<number>(compiled, { x: 2, y: 3 })
787
- * // => 6 (3 * 2)
788
- * ```
789
- */
790
- function evaluate(data, values) {
791
- if (data.length < 1) throw new Error("Invalid compiled data: must have at least variable names");
792
- const [variableNames, ...expressions] = data;
793
- if (!Array.isArray(variableNames)) throw new Error("Invalid compiled data: first element must be variable names array");
794
- for (const varName of variableNames) {
795
- if (typeof varName !== "string") throw new Error("Invalid compiled data: variable names must be strings");
796
- if (!(varName in values)) throw new Error(`Missing required variable: ${varName}`);
616
+ if (key.type !== "Identifier") throw new Error("Shorthand property must be an identifier");
617
+ return {
618
+ key,
619
+ value: key,
620
+ computed: false,
621
+ shorthand: true
622
+ };
797
623
  }
798
- const valueArray = [];
799
- for (const varName of variableNames) valueArray.push(values[varName]);
800
- const cacheKey = JSON.stringify(data);
801
- let evaluator = evaluatorCache.get(cacheKey);
802
- if (!evaluator) {
803
- const functionBody = isV2Format(expressions) ? buildEvaluatorFunctionBodyV2(expressions, variableNames.length) : buildEvaluatorFunctionBody(expressions, variableNames.length);
804
- evaluator = new Function("$values", functionBody);
805
- evaluatorCache.set(cacheKey, evaluator);
624
+ /**
625
+ * 解析标识符
626
+ */
627
+ parseIdentifier() {
628
+ const start = this.pos;
629
+ while (isIdentifierPart(this.peek())) this.advance();
630
+ const name = this.source.slice(start, this.pos);
631
+ if (!name) throw new Error(`Expected identifier at position ${this.pos}`);
632
+ return {
633
+ type: "Identifier",
634
+ name
635
+ };
806
636
  }
807
- try {
808
- return evaluator(valueArray);
809
- } catch (error) {
810
- throw new Error(`Failed to evaluate expression: ${error instanceof Error ? error.message : String(error)}`);
637
+ /**
638
+ * 解析表达式 - 需要在子类中实现
639
+ */
640
+ parseExpression() {
641
+ throw new Error("parseExpression must be implemented in subclass");
811
642
  }
812
- }
813
- /**
814
- * 构造求值函数体
815
- *
816
- * @param expressions - 表达式列表
817
- * @param variableCount - 变量数量
818
- * @returns 函数体字符串
819
- *
820
- * @example
821
- * ```ts
822
- * buildEvaluatorFunctionBody(["$0+$1", "$2*2"], 2)
823
- * // 返回执行 $0+$1 并存储到 $values[2],然后执行 $2*2 的函数体
824
- * ```
825
- */
826
- function buildEvaluatorFunctionBody(expressions, variableCount) {
827
- if (expressions.length === 0) throw new Error("No expressions to evaluate");
828
- return [
829
- ...Array.from({ length: variableCount }, (_, i) => `const $${i} = $values[${i}];`),
830
- ...expressions.map((expr, i) => {
831
- const idx = variableCount + i;
832
- return `const $${idx} = ${expr}; $values[${idx}] = $${idx};`;
833
- }),
834
- `return $values[$values.length - 1];`
835
- ].join("\n");
836
- }
643
+ };
644
+
645
+ //#endregion
646
+ //#region src/core/parser/arrow-function-parser.ts
837
647
  /**
838
- * 构造带控制流支持的求值函数体(V2 格式)
839
- *
840
- * @param expressions - 表达式列表(可包含控制流节点)
841
- * @param variableCount - 变量数量
842
- * @returns 函数体字符串
648
+ * ArrowFunctionParser 类 - 继承 PrimaryParser,添加箭头函数解析功能
843
649
  */
844
- function buildEvaluatorFunctionBodyV2(expressions, variableCount) {
845
- if (expressions.length === 0) throw new Error("No expressions to evaluate");
846
- const lines = [
847
- ...Array.from({ length: variableCount }, (_, i) => `const $${i} = $values[${i}];`),
848
- "let $pc = 0;",
849
- "let $lastValue;",
850
- ...expressions.map((_, i) => `let $${variableCount + i};`),
851
- `while ($pc < ${expressions.length}) {`,
852
- " switch ($pc) {"
853
- ];
854
- expressions.forEach((expr, i) => {
855
- const idx = variableCount + i;
856
- lines.push(` case ${i}: {`);
857
- if (typeof expr === "string") {
858
- lines.push(` $${idx} = $lastValue = ${expr};`);
859
- lines.push(` $values[${idx}] = $${idx};`);
860
- lines.push(" $pc++; break;");
861
- } else {
862
- const [type] = expr;
863
- switch (type) {
864
- case "br":
865
- lines.push(` if (${expr[1]}) { $pc += ${expr[2] + 1}; } else { $pc++; } break;`);
866
- break;
867
- case "jmp":
868
- lines.push(` $pc += ${expr[1] + 1}; break;`);
869
- break;
870
- case "phi":
871
- lines.push(` $${idx} = $values[${idx}] = $lastValue; $pc++; break;`);
872
- break;
650
+ var ArrowFunctionParser = class extends PrimaryParser {
651
+ /**
652
+ * 尝试解析带括号的箭头函数: (a, b) => expr
653
+ * 使用回溯机制
654
+ */
655
+ tryParseArrowFunction() {
656
+ const savedPos = this.pos;
657
+ try {
658
+ this.expect("(");
659
+ this.skipWhitespace();
660
+ const params = [];
661
+ while (this.peek() !== ")") {
662
+ if (!isIdentifierStart(this.peek())) throw new Error("Expected identifier");
663
+ params.push(this.parseIdentifier());
664
+ this.skipWhitespace();
665
+ if (this.peek() === ",") {
666
+ this.advance();
667
+ this.skipWhitespace();
668
+ } else break;
873
669
  }
670
+ this.expect(")");
671
+ this.skipWhitespace();
672
+ if (this.source.slice(this.pos, this.pos + 2) !== "=>") throw new Error("Expected =>");
673
+ this.pos += 2;
674
+ this.skipWhitespace();
675
+ return {
676
+ type: "ArrowFunctionExpr",
677
+ params,
678
+ body: this.parseExpression()
679
+ };
680
+ } catch {
681
+ this.pos = savedPos;
682
+ return null;
874
683
  }
875
- lines.push(" }");
876
- });
877
- lines.push(" }", "}", "return $values[$values.length - 1];");
878
- return lines.join("\n");
879
- }
684
+ }
685
+ /**
686
+ * 尝试解析单参数无括号的箭头函数: a => expr
687
+ * 使用回溯机制
688
+ */
689
+ tryParseSingleParamArrowFunction() {
690
+ const savedPos = this.pos;
691
+ try {
692
+ const param = this.parseIdentifier();
693
+ this.skipWhitespace();
694
+ if (this.source.slice(this.pos, this.pos + 2) !== "=>") throw new Error("Expected =>");
695
+ this.pos += 2;
696
+ this.skipWhitespace();
697
+ const body = this.parseExpression();
698
+ return {
699
+ type: "ArrowFunctionExpr",
700
+ params: [param],
701
+ body
702
+ };
703
+ } catch {
704
+ this.pos = savedPos;
705
+ return null;
706
+ }
707
+ }
708
+ };
880
709
 
881
710
  //#endregion
882
- //#region src/parser.ts
883
- var Parser = class Parser {
884
- pos = 0;
885
- source;
886
- constructor(source) {
887
- this.source = source;
888
- }
889
- parse() {
890
- this.skipWhitespace();
891
- const node = this.parseExpression();
892
- this.skipWhitespace();
893
- if (this.pos < this.source.length) throw new Error(`Unexpected token at position ${this.pos}: ${this.source.slice(this.pos, this.pos + 10)}`);
894
- return node;
895
- }
711
+ //#region src/core/parser/expression-parser.ts
712
+ /**
713
+ * ExpressionParser 类 - 继承 ArrowFunctionParser,实现完整的表达式解析功能
714
+ */
715
+ var ExpressionParser = class extends ArrowFunctionParser {
716
+ /**
717
+ * 解析表达式的入口
718
+ */
896
719
  parseExpression() {
897
720
  return this.parseConditional();
898
721
  }
722
+ /**
723
+ * 解析条件(三元)表达式: test ? consequent : alternate
724
+ */
899
725
  parseConditional() {
900
726
  let node = this.parseBinary(0);
901
727
  this.skipWhitespace();
@@ -916,6 +742,9 @@ var Parser = class Parser {
916
742
  }
917
743
  return node;
918
744
  }
745
+ /**
746
+ * 解析二元表达式,使用优先级爬升算法
747
+ */
919
748
  parseBinary(minPrec) {
920
749
  let left = this.parseUnary();
921
750
  while (true) {
@@ -935,6 +764,9 @@ var Parser = class Parser {
935
764
  }
936
765
  return left;
937
766
  }
767
+ /**
768
+ * 解析一元表达式
769
+ */
938
770
  parseUnary() {
939
771
  this.skipWhitespace();
940
772
  const ch = this.peek();
@@ -959,6 +791,9 @@ var Parser = class Parser {
959
791
  }
960
792
  return this.parsePostfix();
961
793
  }
794
+ /**
795
+ * 解析后缀表达式(成员访问、函数调用、可选链等)
796
+ */
962
797
  parsePostfix() {
963
798
  let node = this.parsePrimary();
964
799
  while (true) {
@@ -1039,10 +874,13 @@ var Parser = class Parser {
1039
874
  }
1040
875
  return node;
1041
876
  }
877
+ /**
878
+ * 解析基本表达式(字面量、标识符、括号表达式、箭头函数等)
879
+ */
1042
880
  parsePrimary() {
1043
881
  this.skipWhitespace();
1044
882
  const ch = this.peek();
1045
- if (this.isDigit(ch) || ch === "." && this.isDigit(this.peekAt(1))) return this.parseNumber();
883
+ if (isDigit(ch) || ch === "." && isDigit(this.peekAt(1))) return this.parseNumber();
1046
884
  if (ch === "\"" || ch === "'" || ch === "`") return this.parseString();
1047
885
  if (ch === "[") return this.parseArray();
1048
886
  if (ch === "{") return this.parseObject();
@@ -1069,316 +907,354 @@ var Parser = class Parser {
1069
907
  type: "Identifier",
1070
908
  name: "undefined"
1071
909
  };
1072
- if (this.isIdentifierStart(ch)) {
910
+ if (isIdentifierStart(ch)) {
1073
911
  const arrowFunc = this.tryParseSingleParamArrowFunction();
1074
912
  if (arrowFunc) return arrowFunc;
1075
913
  return this.parseIdentifier();
1076
914
  }
1077
915
  throw new Error(`Unexpected character at position ${this.pos}: ${ch}`);
1078
916
  }
1079
- parseNumber() {
1080
- const start = this.pos;
1081
- if (this.peek() === "0") {
1082
- const next = this.peekAt(1)?.toLowerCase();
1083
- if (next === "x" || next === "o" || next === "b") {
1084
- this.advance();
1085
- this.advance();
1086
- while (this.isHexDigit(this.peek())) this.advance();
1087
- const raw = this.source.slice(start, this.pos);
1088
- return {
1089
- type: "NumberLiteral",
1090
- value: Number(raw),
1091
- raw
1092
- };
1093
- }
1094
- }
1095
- while (this.isDigit(this.peek())) this.advance();
1096
- if (this.peek() === "." && this.isDigit(this.peekAt(1))) {
1097
- this.advance();
1098
- while (this.isDigit(this.peek())) this.advance();
1099
- }
1100
- if (this.peek()?.toLowerCase() === "e") {
1101
- this.advance();
1102
- if (this.peek() === "+" || this.peek() === "-") this.advance();
1103
- while (this.isDigit(this.peek())) this.advance();
1104
- }
1105
- const raw = this.source.slice(start, this.pos);
1106
- return {
1107
- type: "NumberLiteral",
1108
- value: Number(raw),
1109
- raw
1110
- };
1111
- }
1112
- static ESCAPE_CHARS = {
1113
- n: "\n",
1114
- r: "\r",
1115
- t: " ",
1116
- "\\": "\\",
1117
- "'": "'",
1118
- "\"": "\"",
1119
- "`": "`"
1120
- };
1121
- parseString() {
1122
- const quote = this.peek();
1123
- this.advance();
1124
- let value = "";
1125
- while (this.pos < this.source.length && this.peek() !== quote) if (this.peek() === "\\") {
1126
- this.advance();
1127
- const escaped = this.peek();
1128
- value += Parser.ESCAPE_CHARS[escaped] ?? escaped;
1129
- this.advance();
1130
- } else {
1131
- value += this.peek();
1132
- this.advance();
1133
- }
1134
- this.expect(quote);
1135
- return {
1136
- type: "StringLiteral",
1137
- value,
1138
- quote
1139
- };
1140
- }
1141
- parseArray() {
1142
- this.expect("[");
1143
- const elements = [];
1144
- this.skipWhitespace();
1145
- while (this.peek() !== "]") {
1146
- elements.push(this.parseExpression());
1147
- this.skipWhitespace();
1148
- if (this.peek() === ",") {
1149
- this.advance();
1150
- this.skipWhitespace();
1151
- } else break;
1152
- }
1153
- this.expect("]");
1154
- return {
1155
- type: "ArrayExpr",
1156
- elements
1157
- };
1158
- }
1159
- parseObject() {
1160
- this.expect("{");
1161
- const properties = [];
917
+ /**
918
+ * 解析函数调用参数列表
919
+ */
920
+ parseArguments() {
921
+ const args = [];
1162
922
  this.skipWhitespace();
1163
- while (this.peek() !== "}") {
1164
- const prop = this.parseObjectProperty();
1165
- properties.push(prop);
923
+ while (this.peek() !== ")") {
924
+ args.push(this.parseExpression());
1166
925
  this.skipWhitespace();
1167
926
  if (this.peek() === ",") {
1168
927
  this.advance();
1169
928
  this.skipWhitespace();
1170
929
  } else break;
1171
930
  }
1172
- this.expect("}");
1173
- return {
1174
- type: "ObjectExpr",
1175
- properties
1176
- };
931
+ return args;
1177
932
  }
1178
- parseObjectProperty() {
933
+ };
934
+
935
+ //#endregion
936
+ //#region src/core/parser/parser.ts
937
+ /**
938
+ * Parser 类 - 完整的 JavaScript 表达式解析器
939
+ */
940
+ var Parser = class extends ExpressionParser {
941
+ /**
942
+ * 解析表达式字符串为 AST
943
+ */
944
+ parse() {
1179
945
  this.skipWhitespace();
1180
- let key;
1181
- let computed = false;
1182
- if (this.peek() === "[") {
1183
- this.advance();
1184
- this.skipWhitespace();
1185
- key = this.parseExpression();
1186
- this.skipWhitespace();
1187
- this.expect("]");
1188
- computed = true;
1189
- } else if (this.peek() === "\"" || this.peek() === "'") key = this.parseString();
1190
- else key = this.parseIdentifier();
946
+ const node = this.parseExpression();
1191
947
  this.skipWhitespace();
1192
- if (this.peek() === ":") {
1193
- this.advance();
1194
- this.skipWhitespace();
1195
- const value = this.parseExpression();
1196
- return {
1197
- key,
1198
- value,
1199
- computed,
1200
- shorthand: false
1201
- };
1202
- }
1203
- if (key.type !== "Identifier") throw new Error("Shorthand property must be an identifier");
1204
- return {
1205
- key,
1206
- value: key,
1207
- computed: false,
1208
- shorthand: true
1209
- };
948
+ if (this.pos < this.source.length) throw new Error(`Unexpected token at position ${this.pos}: ${this.source.slice(this.pos, this.pos + 10)}`);
949
+ return node;
1210
950
  }
1211
- parseIdentifier() {
1212
- const start = this.pos;
1213
- while (this.isIdentifierPart(this.peek())) this.advance();
1214
- const name = this.source.slice(start, this.pos);
1215
- if (!name) throw new Error(`Expected identifier at position ${this.pos}`);
1216
- return {
1217
- type: "Identifier",
1218
- name
1219
- };
951
+ };
952
+
953
+ //#endregion
954
+ //#region src/core/parser/index.ts
955
+ /**
956
+ * 解析 JavaScript 表达式为 AST
957
+ */
958
+ function parse(source) {
959
+ return new Parser(source).parse();
960
+ }
961
+
962
+ //#endregion
963
+ //#region src/proxy/proxy-metadata.ts
964
+ /**
965
+ * 全局 WeakMap 存储
966
+ */
967
+ const proxyMetadata = /* @__PURE__ */ new WeakMap();
968
+ /**
969
+ * 设置 Proxy 元数据
970
+ */
971
+ function setProxyMetadata(proxy, metadata) {
972
+ proxyMetadata.set(proxy, metadata);
973
+ }
974
+ /**
975
+ * 获取 Proxy 元数据
976
+ */
977
+ function getProxyMetadata(proxy) {
978
+ return proxyMetadata.get(proxy);
979
+ }
980
+
981
+ //#endregion
982
+ //#region src/proxy/proxy-variable.ts
983
+ const typedArrayConstructors = [
984
+ "Int8Array",
985
+ "Uint8Array",
986
+ "Uint8ClampedArray",
987
+ "Int16Array",
988
+ "Uint16Array",
989
+ "Int32Array",
990
+ "Uint32Array",
991
+ "Float32Array",
992
+ "Float64Array",
993
+ "BigInt64Array",
994
+ "BigUint64Array"
995
+ ];
996
+ /**
997
+ * 创建占位符 AST 节点
998
+ */
999
+ function placeholder(id) {
1000
+ return {
1001
+ type: "Placeholder",
1002
+ id
1003
+ };
1004
+ }
1005
+ /**
1006
+ * 创建标识符 AST 节点
1007
+ */
1008
+ function identifier(name) {
1009
+ return {
1010
+ type: "Identifier",
1011
+ name
1012
+ };
1013
+ }
1014
+ /**
1015
+ * 创建数字字面量 AST 节点
1016
+ */
1017
+ function numberLiteral(value) {
1018
+ return {
1019
+ type: "NumberLiteral",
1020
+ value,
1021
+ raw: String(value)
1022
+ };
1023
+ }
1024
+ /**
1025
+ * 创建字符串字面量 AST 节点
1026
+ */
1027
+ function stringLiteral(value, quote = "\"") {
1028
+ return {
1029
+ type: "StringLiteral",
1030
+ value,
1031
+ quote
1032
+ };
1033
+ }
1034
+ /**
1035
+ * 创建成员表达式 AST 节点
1036
+ */
1037
+ function memberExpr(object, property) {
1038
+ return {
1039
+ type: "MemberExpr",
1040
+ object,
1041
+ property,
1042
+ computed: false,
1043
+ optional: false
1044
+ };
1045
+ }
1046
+ /**
1047
+ * 创建调用表达式 AST 节点
1048
+ */
1049
+ function callExpr(callee, arguments_) {
1050
+ return {
1051
+ type: "CallExpr",
1052
+ callee,
1053
+ arguments: arguments_,
1054
+ optional: false
1055
+ };
1056
+ }
1057
+ /**
1058
+ * 创建数组表达式 AST 节点
1059
+ */
1060
+ function arrayExpr(elements) {
1061
+ return {
1062
+ type: "ArrayExpr",
1063
+ elements
1064
+ };
1065
+ }
1066
+ /**
1067
+ * 检查对象是否为 TypedArray 实例
1068
+ */
1069
+ function getTypedArrayConstructor(value) {
1070
+ for (const constructorName of typedArrayConstructors) {
1071
+ const Constructor = globalThis[constructorName];
1072
+ if (Constructor && value instanceof Constructor) return Constructor;
1220
1073
  }
1221
- /**
1222
- * 尝试解析带括号的箭头函数: (a, b) => expr
1223
- * 使用回溯机制
1224
- */
1225
- tryParseArrowFunction() {
1226
- const savedPos = this.pos;
1227
- try {
1228
- this.expect("(");
1229
- this.skipWhitespace();
1230
- const params = [];
1231
- while (this.peek() !== ")") {
1232
- if (!this.isIdentifierStart(this.peek())) throw new Error("Expected identifier");
1233
- params.push(this.parseIdentifier());
1234
- this.skipWhitespace();
1235
- if (this.peek() === ",") {
1236
- this.advance();
1237
- this.skipWhitespace();
1238
- } else break;
1239
- }
1240
- this.expect(")");
1241
- this.skipWhitespace();
1242
- if (this.source.slice(this.pos, this.pos + 2) !== "=>") throw new Error("Expected =>");
1243
- this.pos += 2;
1244
- this.skipWhitespace();
1245
- return {
1246
- type: "ArrowFunctionExpr",
1247
- params,
1248
- body: this.parseExpression()
1249
- };
1250
- } catch {
1251
- this.pos = savedPos;
1252
- return null;
1074
+ return null;
1075
+ }
1076
+ /**
1077
+ * 序列化参数为 AST 节点
1078
+ * - Proxy Variable/Expression:使用 ast 或占位符标识符
1079
+ * - 数组:返回 ArrayExpr 节点
1080
+ * - 对象:返回 ObjectExpr 节点
1081
+ * - 原始值:返回对应的字面量节点
1082
+ * - Date, RegExp, BigInt, URL, URLSearchParams, Map, Set, TypedArray, DataView: 构造函数调用
1083
+ */
1084
+ function serializeArgumentToAST(arg) {
1085
+ if ((typeof arg === "object" || typeof arg === "function") && arg !== null) {
1086
+ const meta = getProxyMetadata(arg);
1087
+ if (meta) {
1088
+ if (meta.ast) return meta.ast;
1089
+ if (meta.rootVariable) return placeholder(meta.rootVariable);
1253
1090
  }
1254
1091
  }
1255
- /**
1256
- * 尝试解析单参数无括号的箭头函数: a => expr
1257
- * 使用回溯机制
1258
- */
1259
- tryParseSingleParamArrowFunction() {
1260
- const savedPos = this.pos;
1261
- try {
1262
- const param = this.parseIdentifier();
1263
- this.skipWhitespace();
1264
- if (this.source.slice(this.pos, this.pos + 2) !== "=>") throw new Error("Expected =>");
1265
- this.pos += 2;
1266
- this.skipWhitespace();
1267
- const body = this.parseExpression();
1268
- return {
1269
- type: "ArrowFunctionExpr",
1270
- params: [param],
1271
- body
1272
- };
1273
- } catch {
1274
- this.pos = savedPos;
1275
- return null;
1092
+ if (Array.isArray(arg)) return arrayExpr(arg.map(serializeArgumentToAST));
1093
+ if (typeof arg === "object" && arg !== null) {
1094
+ if (arg instanceof Date) return callExpr(identifier("Date"), [numberLiteral(arg.getTime())]);
1095
+ if (arg instanceof RegExp) {
1096
+ const args = [stringLiteral(arg.source)];
1097
+ if (arg.flags) args.push(stringLiteral(arg.flags));
1098
+ return callExpr(identifier("RegExp"), args);
1276
1099
  }
1277
- }
1278
- parseArguments() {
1279
- const args = [];
1280
- this.skipWhitespace();
1281
- while (this.peek() !== ")") {
1282
- args.push(this.parseExpression());
1283
- this.skipWhitespace();
1284
- if (this.peek() === ",") {
1285
- this.advance();
1286
- this.skipWhitespace();
1287
- } else break;
1100
+ if (typeof URL !== "undefined" && arg instanceof URL) return callExpr(identifier("URL"), [stringLiteral(arg.href)]);
1101
+ if (typeof URLSearchParams !== "undefined" && arg instanceof URLSearchParams) {
1102
+ const entries = [];
1103
+ arg.forEach((value, key) => {
1104
+ entries.push(arrayExpr([stringLiteral(key), stringLiteral(value)]));
1105
+ });
1106
+ return callExpr(identifier("URLSearchParams"), [arrayExpr(entries)]);
1288
1107
  }
1289
- return args;
1290
- }
1291
- static OPERATORS = [
1292
- "instanceof",
1293
- ">>>",
1294
- "===",
1295
- "!==",
1296
- "&&",
1297
- "||",
1298
- "??",
1299
- "==",
1300
- "!=",
1301
- "<=",
1302
- ">=",
1303
- "<<",
1304
- ">>",
1305
- "**",
1306
- "in",
1307
- "+",
1308
- "-",
1309
- "*",
1310
- "/",
1311
- "%",
1312
- "<",
1313
- ">",
1314
- "&",
1315
- "|",
1316
- "^"
1317
- ];
1318
- static KEYWORD_OPERATORS = new Set(["in", "instanceof"]);
1319
- peekOperator() {
1320
- for (const op of Parser.OPERATORS) {
1321
- if (!this.source.startsWith(op, this.pos)) continue;
1322
- if (Parser.KEYWORD_OPERATORS.has(op)) {
1323
- const nextChar = this.source[this.pos + op.length];
1324
- if (nextChar && this.isIdentifierPart(nextChar)) continue;
1325
- }
1326
- return op;
1108
+ if (arg instanceof Map) {
1109
+ const entries = [];
1110
+ arg.forEach((value, key) => {
1111
+ entries.push(arrayExpr([serializeArgumentToAST(key), serializeArgumentToAST(value)]));
1112
+ });
1113
+ return callExpr(identifier("Map"), [arrayExpr(entries)]);
1327
1114
  }
1328
- return null;
1329
- }
1330
- matchKeyword(keyword) {
1331
- if (this.source.startsWith(keyword, this.pos)) {
1332
- const nextChar = this.source[this.pos + keyword.length];
1333
- if (!nextChar || !this.isIdentifierPart(nextChar)) {
1334
- this.pos += keyword.length;
1335
- return true;
1336
- }
1115
+ if (arg instanceof Set) {
1116
+ const values = [];
1117
+ arg.forEach((value) => values.push(serializeArgumentToAST(value)));
1118
+ return callExpr(identifier("Set"), [arrayExpr(values)]);
1337
1119
  }
1338
- return false;
1339
- }
1340
- peek() {
1341
- return this.source[this.pos] || "";
1342
- }
1343
- peekAt(offset) {
1344
- return this.source[this.pos + offset] || "";
1345
- }
1346
- advance() {
1347
- return this.source[this.pos++] || "";
1348
- }
1349
- expect(ch) {
1350
- if (this.peek() !== ch) throw new Error(`Expected '${ch}' at position ${this.pos}, got '${this.peek()}'`);
1351
- this.advance();
1352
- }
1353
- skipWhitespace() {
1354
- while (/\s/.test(this.peek())) this.advance();
1355
- }
1356
- isDigit(ch) {
1357
- const code = ch.charCodeAt(0);
1358
- return code >= 48 && code <= 57;
1359
- }
1360
- isHexDigit(ch) {
1361
- const code = ch.charCodeAt(0);
1362
- return code >= 48 && code <= 57 || code >= 65 && code <= 70 || code >= 97 && code <= 102;
1363
- }
1364
- isIdentifierStart(ch) {
1365
- const code = ch.charCodeAt(0);
1366
- return code >= 65 && code <= 90 || code >= 97 && code <= 122 || code === 95 || code === 36;
1120
+ const typedArrayConstructor = getTypedArrayConstructor(arg);
1121
+ if (typedArrayConstructor) {
1122
+ const values = [...arg].map(serializeArgumentToAST);
1123
+ const constructorName = typedArrayConstructor.name;
1124
+ return callExpr(identifier(constructorName), [arrayExpr(values)]);
1125
+ }
1126
+ if (arg instanceof ArrayBuffer) {
1127
+ const uint8Array = new Uint8Array(arg);
1128
+ const values = Array.from(uint8Array).map(numberLiteral);
1129
+ return memberExpr(callExpr(identifier("Uint8Array"), [arrayExpr(values)]), identifier("buffer"));
1130
+ }
1131
+ if (arg instanceof DataView) return callExpr(identifier("DataView"), [serializeArgumentToAST(arg.buffer)]);
1132
+ return {
1133
+ type: "ObjectExpr",
1134
+ properties: Object.entries(arg).map(([k, v]) => {
1135
+ return {
1136
+ key: /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(k) ? identifier(k) : stringLiteral(k),
1137
+ value: serializeArgumentToAST(v),
1138
+ computed: false,
1139
+ shorthand: false
1140
+ };
1141
+ })
1142
+ };
1367
1143
  }
1368
- isIdentifierPart(ch) {
1369
- const code = ch.charCodeAt(0);
1370
- return code >= 65 && code <= 90 || code >= 97 && code <= 122 || code >= 48 && code <= 57 || code === 95 || code === 36;
1144
+ if (arg === null) return { type: "NullLiteral" };
1145
+ if (arg === void 0) return identifier("undefined");
1146
+ if (typeof arg === "boolean") return {
1147
+ type: "BooleanLiteral",
1148
+ value: arg
1149
+ };
1150
+ if (typeof arg === "number") return numberLiteral(arg);
1151
+ if (typeof arg === "string") return stringLiteral(arg);
1152
+ if (typeof arg === "bigint") return callExpr(identifier("BigInt"), [stringLiteral(arg.toString())]);
1153
+ throw new Error(`Unsupported argument type: ${typeof arg}`);
1154
+ }
1155
+ /**
1156
+ * 从参数中收集依赖的 Symbol
1157
+ * 递归遍历数组和对象,收集所有 Proxy 的依赖
1158
+ */
1159
+ function collectDepsFromArgs(args, deps) {
1160
+ for (const arg of args) if ((typeof arg === "object" || typeof arg === "function") && arg !== null) {
1161
+ const meta = getProxyMetadata(arg);
1162
+ if (meta?.dependencies) for (const dep of meta.dependencies) deps.add(dep);
1163
+ else if (Array.isArray(arg)) collectDepsFromArgs(arg, deps);
1164
+ else if (typeof arg === "object") collectDepsFromArgs(Object.values(arg), deps);
1371
1165
  }
1372
- };
1166
+ }
1167
+ /**
1168
+ * 创建 Proxy 的公共 handler
1169
+ */
1170
+ function createProxyHandler(ast, deps) {
1171
+ return {
1172
+ get(_target, prop) {
1173
+ if (typeof prop === "symbol") return void 0;
1174
+ return createProxyExpressionWithAST(memberExpr(ast, identifier(String(prop))), deps);
1175
+ },
1176
+ apply(_target, _thisArg, args) {
1177
+ const callAst = callExpr(ast, args.map(serializeArgumentToAST));
1178
+ const newDeps = new Set(deps);
1179
+ collectDepsFromArgs(args, newDeps);
1180
+ return createProxyExpressionWithAST(callAst, newDeps);
1181
+ }
1182
+ };
1183
+ }
1184
+ /**
1185
+ * 创建根 Variable Proxy
1186
+ * 拦截属性访问,返回新的 expression proxy
1187
+ * 不可直接调用(apply 应该只在链式调用后可用)
1188
+ *
1189
+ * @param id - 变量的唯一标识 Symbol
1190
+ * @returns Proxy 包装的 Variable
1191
+ */
1192
+ function createProxyVariable(id) {
1193
+ const deps = new Set([id]);
1194
+ const ast = placeholder(id);
1195
+ const proxy = new Proxy(function() {}, createProxyHandler(ast, deps));
1196
+ setProxyMetadata(proxy, {
1197
+ type: "variable",
1198
+ rootVariable: id,
1199
+ dependencies: deps
1200
+ });
1201
+ return proxy;
1202
+ }
1203
+ /**
1204
+ * 创建带完整 AST 的 Proxy(方法调用后)
1205
+ * 可以继续链式访问和调用
1206
+ *
1207
+ * @param ast - 完整的表达式 AST
1208
+ * @param deps - 依赖集合
1209
+ * @returns Proxy 包装的 Expression
1210
+ */
1211
+ function createProxyExpressionWithAST(ast, deps) {
1212
+ const proxy = new Proxy(function() {}, createProxyHandler(ast, deps));
1213
+ setProxyMetadata(proxy, {
1214
+ type: "expression",
1215
+ ast,
1216
+ dependencies: deps
1217
+ });
1218
+ return proxy;
1219
+ }
1220
+
1221
+ //#endregion
1222
+ //#region src/api/variable.ts
1373
1223
  /**
1374
- * 解析 JavaScript 表达式为 AST
1224
+ * 跟踪每个 variable 的唯一 Symbol ID
1375
1225
  */
1376
- function parse(source) {
1377
- return new Parser(source).parse();
1226
+ const variableIds = /* @__PURE__ */ new WeakMap();
1227
+ /**
1228
+ * 计数器用于生成唯一变量 ID
1229
+ */
1230
+ let variableCounter = 0;
1231
+ /**
1232
+ * 创建一个类型化变量
1233
+ * 返回 Proxy 对象,支持链式属性访问和方法调用
1234
+ *
1235
+ * @example
1236
+ * ```ts
1237
+ * const x = variable<number>();
1238
+ * const config = variable<{ timeout: number }>();
1239
+ * const timeout = config.timeout; // Proxy expression
1240
+ * ```
1241
+ */
1242
+ function variable() {
1243
+ const id = Symbol(`var_${variableCounter++}`);
1244
+ const proxy = createProxyVariable(id);
1245
+ variableIds.set(proxy, id);
1246
+ return proxy;
1247
+ }
1248
+ /**
1249
+ * 获取 variable 的唯一 Symbol ID
1250
+ */
1251
+ function getVariableId(variable) {
1252
+ if (typeof variable !== "object" && typeof variable !== "function" || variable === null) return void 0;
1253
+ return variableIds.get(variable);
1378
1254
  }
1379
1255
 
1380
1256
  //#endregion
1381
- //#region src/expr.ts
1257
+ //#region src/api/expr.ts
1382
1258
  /**
1383
1259
  * 创建表达式
1384
1260
  * 返回 Proxy Expression,可以继续链式调用
@@ -1444,7 +1320,7 @@ function expr(context) {
1444
1320
  }
1445
1321
 
1446
1322
  //#endregion
1447
- //#region src/lambda.ts
1323
+ //#region src/api/lambda.ts
1448
1324
  /**
1449
1325
  * Lambda 参数计数器,用于生成唯一 ID
1450
1326
  */
@@ -1555,7 +1431,7 @@ function filterClosureDeps(bodyDeps, paramSymbols) {
1555
1431
  }
1556
1432
 
1557
1433
  //#endregion
1558
- //#region src/template.ts
1434
+ //#region src/api/template.ts
1559
1435
  /**
1560
1436
  * Tagged template 函数,用于创建包含变量的字符串表达式
1561
1437
  *
@@ -1604,34 +1480,7 @@ function t(strings, ...values) {
1604
1480
  }
1605
1481
 
1606
1482
  //#endregion
1607
- //#region src/test-helper.ts
1608
- /**
1609
- * 编译并求值表达式
1610
- * 自动推导变量类型和返回类型
1611
- *
1612
- * @template TResult - 表达式求值结果类型
1613
- * @template TVars - 变量映射类型
1614
- * @param expr - 要编译的表达式
1615
- * @param variables - 变量定义映射
1616
- * @param values - 变量值映射
1617
- * @returns 表达式求值结果
1618
- *
1619
- * @example
1620
- * ```ts
1621
- * const callback = variable<(f: (x: number) => number) => number>();
1622
- * const result = compileAndEvaluate(
1623
- * myExpr,
1624
- * { callback },
1625
- * { callback: (fn) => fn(5) }
1626
- * );
1627
- * ```
1628
- */
1629
- function compileAndEvaluate(expr, variables, values, options) {
1630
- return evaluate(compile(expr, variables, options), values);
1631
- }
1632
-
1633
- //#endregion
1634
- //#region src/wrap.ts
1483
+ //#region src/api/wrap.ts
1635
1484
  /**
1636
1485
  * 将静态值包装为 Proxy Expression
1637
1486
  * 返回的 Proxy 可以像 Variable 一样调用方法和访问属性
@@ -1661,5 +1510,434 @@ function wrap(value) {
1661
1510
  }
1662
1511
 
1663
1512
  //#endregion
1664
- export { compile, compileAndEvaluate, evaluate, expr, lambda, t, variable, wrap };
1513
+ //#region src/core/compile.ts
1514
+ const ALLOWED_GLOBALS = new Set([
1515
+ "Math",
1516
+ "JSON",
1517
+ "Date",
1518
+ "RegExp",
1519
+ "Number",
1520
+ "String",
1521
+ "Boolean",
1522
+ "Array",
1523
+ "Object",
1524
+ "undefined",
1525
+ "NaN",
1526
+ "Infinity",
1527
+ "isNaN",
1528
+ "isFinite",
1529
+ "parseInt",
1530
+ "parseFloat",
1531
+ "BigInt",
1532
+ "URL",
1533
+ "URLSearchParams",
1534
+ "Map",
1535
+ "Set",
1536
+ "Int8Array",
1537
+ "Uint8Array",
1538
+ "Uint8ClampedArray",
1539
+ "Int16Array",
1540
+ "Uint16Array",
1541
+ "Int32Array",
1542
+ "Uint32Array",
1543
+ "Float32Array",
1544
+ "Float64Array",
1545
+ "BigInt64Array",
1546
+ "BigUint64Array",
1547
+ "ArrayBuffer",
1548
+ "DataView"
1549
+ ]);
1550
+ /**
1551
+ * 短路运算符对应的分支条件
1552
+ */
1553
+ const BRANCH_CONDITIONS = {
1554
+ "||": (idx) => `$[${idx}]`,
1555
+ "&&": (idx) => `!$[${idx}]`,
1556
+ "??": (idx) => `$[${idx}]!=null`
1557
+ };
1558
+ /**
1559
+ * 将 Proxy Expression 编译为可序列化的 JSON 结构
1560
+ *
1561
+ * @template TResult - 表达式结果类型
1562
+ * @param expression - Proxy Expression,或包含 Proxy 的对象/数组/原始值
1563
+ * @param variables - 所有使用的变量定义
1564
+ * @param options - 编译选项
1565
+ * @returns 编译后的数据结构 [变量名列表, 表达式1, 表达式2, ...]
1566
+ *
1567
+ * @throws 如果传入无效的表达式或未定义的变量引用
1568
+ *
1569
+ * @example
1570
+ * ```ts
1571
+ * const x = variable<number>()
1572
+ * const y = variable<number>()
1573
+ * const sum = expr({ x, y })("x + y")
1574
+ * const result = expr({ sum, x })("sum * x")
1575
+ * const compiled = compile(result, { x, y })
1576
+ * // => [["x", "y"], "($[0]+$[1])*$[0]"]
1577
+ * ```
1578
+ */
1579
+ function compile(expression, variables, _options = {}) {
1580
+ const ast = serializeArgumentToAST(expression);
1581
+ const variableOrder = [];
1582
+ const variableToIndex = /* @__PURE__ */ new Map();
1583
+ const symbolToName = /* @__PURE__ */ new Map();
1584
+ for (const [name, value] of Object.entries(variables)) {
1585
+ if (!variableToIndex.has(name)) {
1586
+ const index = variableOrder.length;
1587
+ variableToIndex.set(name, index);
1588
+ variableOrder.push(name);
1589
+ }
1590
+ const id = getVariableId(value);
1591
+ if (id) symbolToName.set(id, name);
1592
+ }
1593
+ const placeholderTransformed = transformPlaceholders(ast, (id) => {
1594
+ const name = symbolToName.get(id);
1595
+ if (!name) return null;
1596
+ const index = variableToIndex.get(name);
1597
+ return index !== void 0 ? `$[${index}]` : null;
1598
+ });
1599
+ const undefinedVars = [];
1600
+ const transformed = transformIdentifiers(placeholderTransformed, (name) => {
1601
+ if (/^\$\[\d+\]$/.test(name)) return name;
1602
+ if (/^_\d+$/.test(name)) return name;
1603
+ const index = variableToIndex.get(name);
1604
+ if (index !== void 0) return `$[${index}]`;
1605
+ if (!ALLOWED_GLOBALS.has(name)) undefinedVars.push(name);
1606
+ return name;
1607
+ });
1608
+ if (undefinedVars.length > 0) throw new Error(`Undefined variable(s): ${[...new Set(undefinedVars)].join(", ")}`);
1609
+ const topLevelExprs = [];
1610
+ compileAst(transformed, {
1611
+ nextParamIndex: 0,
1612
+ expressionStack: [topLevelExprs],
1613
+ nextIndex: variableOrder.length,
1614
+ variableCount: variableOrder.length
1615
+ });
1616
+ return [variableOrder, ...topLevelExprs];
1617
+ }
1618
+ /**
1619
+ * 获取当前表达式列表
1620
+ */
1621
+ function currentExprs(ctx) {
1622
+ return ctx.expressionStack[ctx.expressionStack.length - 1];
1623
+ }
1624
+ /**
1625
+ * 提取 AST 中所有 ArrowFunctionExpr 节点,编译为 FnNode,
1626
+ * 并将原始位置替换为 $[N] 标识符引用。
1627
+ */
1628
+ function extractAndCompileArrowFunctions(node, ctx) {
1629
+ switch (node.type) {
1630
+ case "ArrowFunctionExpr": return {
1631
+ type: "Identifier",
1632
+ name: `$[${compileArrowFunction(node, ctx)}]`
1633
+ };
1634
+ case "BinaryExpr": return {
1635
+ ...node,
1636
+ left: extractAndCompileArrowFunctions(node.left, ctx),
1637
+ right: extractAndCompileArrowFunctions(node.right, ctx)
1638
+ };
1639
+ case "UnaryExpr": return {
1640
+ ...node,
1641
+ argument: extractAndCompileArrowFunctions(node.argument, ctx)
1642
+ };
1643
+ case "ConditionalExpr": return {
1644
+ ...node,
1645
+ test: extractAndCompileArrowFunctions(node.test, ctx),
1646
+ consequent: extractAndCompileArrowFunctions(node.consequent, ctx),
1647
+ alternate: extractAndCompileArrowFunctions(node.alternate, ctx)
1648
+ };
1649
+ case "MemberExpr": return {
1650
+ ...node,
1651
+ object: extractAndCompileArrowFunctions(node.object, ctx),
1652
+ property: node.computed ? extractAndCompileArrowFunctions(node.property, ctx) : node.property
1653
+ };
1654
+ case "CallExpr": return {
1655
+ ...node,
1656
+ callee: extractAndCompileArrowFunctions(node.callee, ctx),
1657
+ arguments: node.arguments.map((arg) => extractAndCompileArrowFunctions(arg, ctx))
1658
+ };
1659
+ case "ArrayExpr": return {
1660
+ ...node,
1661
+ elements: node.elements.map((el) => extractAndCompileArrowFunctions(el, ctx))
1662
+ };
1663
+ case "ObjectExpr": return {
1664
+ ...node,
1665
+ properties: node.properties.map((prop) => ({
1666
+ ...prop,
1667
+ key: prop.computed ? extractAndCompileArrowFunctions(prop.key, ctx) : prop.key,
1668
+ value: extractAndCompileArrowFunctions(prop.value, ctx)
1669
+ }))
1670
+ };
1671
+ default: return node;
1672
+ }
1673
+ }
1674
+ function compileAst(node, ctx) {
1675
+ if (node.type === "BinaryExpr" && (node.operator === "||" || node.operator === "&&" || node.operator === "??")) return compileShortCircuit(node, ctx);
1676
+ if (node.type === "ConditionalExpr") return compileConditional(node, ctx);
1677
+ if (node.type === "ArrowFunctionExpr") return compileArrowFunction(node, ctx);
1678
+ const exprStr = generate(extractAndCompileArrowFunctions(node, ctx));
1679
+ currentExprs(ctx).push(exprStr);
1680
+ return ctx.nextIndex++;
1681
+ }
1682
+ function compileShortCircuit(node, ctx) {
1683
+ const exprs = currentExprs(ctx);
1684
+ const leftIdx = compileAst(node.left, ctx);
1685
+ const condition = BRANCH_CONDITIONS[node.operator]?.(leftIdx);
1686
+ if (!condition) throw new Error(`Unexpected operator: ${node.operator}`);
1687
+ const branchIdx = exprs.length;
1688
+ exprs.push([
1689
+ "br",
1690
+ condition,
1691
+ 0
1692
+ ]);
1693
+ ctx.nextIndex++;
1694
+ compileAst(node.right, ctx);
1695
+ const skipCount = exprs.length - branchIdx - 1;
1696
+ exprs[branchIdx][2] = skipCount;
1697
+ const phiIdx = ctx.nextIndex++;
1698
+ exprs.push(["phi"]);
1699
+ return phiIdx;
1700
+ }
1701
+ function compileConditional(node, ctx) {
1702
+ const exprs = currentExprs(ctx);
1703
+ const testIdx = compileAst(node.test, ctx);
1704
+ const branchIdx = exprs.length;
1705
+ exprs.push([
1706
+ "br",
1707
+ `$[${testIdx}]`,
1708
+ 0
1709
+ ]);
1710
+ ctx.nextIndex++;
1711
+ compileAst(node.alternate, ctx);
1712
+ const jmpIdx = exprs.length;
1713
+ exprs.push(["jmp", 0]);
1714
+ ctx.nextIndex++;
1715
+ compileAst(node.consequent, ctx);
1716
+ const thenEndIdx = exprs.length;
1717
+ exprs[branchIdx][2] = jmpIdx - branchIdx;
1718
+ exprs[jmpIdx][1] = thenEndIdx - jmpIdx - 1;
1719
+ const phiIdx = ctx.nextIndex++;
1720
+ exprs.push(["phi"]);
1721
+ return phiIdx;
1722
+ }
1723
+ function compileArrowFunction(node, ctx) {
1724
+ const fnIndex = ctx.nextIndex++;
1725
+ const paramMapping = /* @__PURE__ */ new Map();
1726
+ for (const param of node.params) if (param.type === "Placeholder") paramMapping.set(param.id, `_${ctx.nextParamIndex++}`);
1727
+ const transformedBody = transformPlaceholders(node.body, (id) => paramMapping.get(id) ?? null);
1728
+ const lambdaStmts = [];
1729
+ ctx.expressionStack.push(lambdaStmts);
1730
+ compileAst(transformedBody, ctx);
1731
+ ctx.expressionStack.pop();
1732
+ const fnNode = [
1733
+ "fn",
1734
+ node.params.length,
1735
+ ...lambdaStmts
1736
+ ];
1737
+ currentExprs(ctx).push(fnNode);
1738
+ return fnIndex;
1739
+ }
1740
+
1741
+ //#endregion
1742
+ //#region src/core/evaluate.ts
1743
+ /**
1744
+ * 缓存已构造的求值函数,以提升重复执行性能
1745
+ */
1746
+ const evaluatorCache = /* @__PURE__ */ new Map();
1747
+ /**
1748
+ * 判断是否是 FnNode
1749
+ */
1750
+ function isFnNode(expr) {
1751
+ return Array.isArray(expr) && expr[0] === "fn" && typeof expr[1] === "number";
1752
+ }
1753
+ /**
1754
+ * 判断是否是控制流节点
1755
+ */
1756
+ function isControlFlowNode(expr) {
1757
+ return Array.isArray(expr) && (expr[0] === "br" || expr[0] === "jmp" || expr[0] === "phi");
1758
+ }
1759
+ /**
1760
+ * 生成 lambda 函数代码
1761
+ *
1762
+ * @param fnNode - FnNode 节点
1763
+ * @param indexCounter - 全局索引计数器
1764
+ * @param paramCounter - 参数计数器
1765
+ * @returns lambda 函数代码字符串
1766
+ */
1767
+ function generateLambdaCode(fnNode, indexCounter, paramCounter) {
1768
+ const [, paramCount, ...stmts] = fnNode;
1769
+ const paramStartIndex = paramCounter.value;
1770
+ paramCounter.value += paramCount;
1771
+ return `(${Array.from({ length: paramCount }, (_, i) => `_${paramStartIndex + i}`).join(",")})=>{${translateStmts(stmts, indexCounter, paramCounter)}}`;
1772
+ }
1773
+ /**
1774
+ * 翻译表达式列表为 JavaScript 代码
1775
+ * 使用全局索引计数器分配 $[N] 槽位
1776
+ */
1777
+ function translateStmts(expressions, indexCounter, paramCounter) {
1778
+ for (let i = 0; i < expressions.length; i++) {
1779
+ const expr = expressions[i];
1780
+ if (!expr) continue;
1781
+ if (isControlFlowNode(expr)) {
1782
+ const [type, , offset] = expr;
1783
+ if ((type === "br" || type === "jmp") && offset !== void 0) {
1784
+ const target = i + offset + 1;
1785
+ if (target < 0 || target > expressions.length) throw new Error(`Unable to translate: invalid jump target at index ${i}. Target would be ${target}, but expression length is ${expressions.length}`);
1786
+ }
1787
+ }
1788
+ }
1789
+ const lines = ["let $lastValue;"];
1790
+ const indexMap = [];
1791
+ const savedStart = indexCounter.value;
1792
+ for (let i = 0; i < expressions.length; i++) {
1793
+ indexMap.push(indexCounter.value);
1794
+ const expr = expressions[i];
1795
+ if (isFnNode(expr)) {
1796
+ indexCounter.value++;
1797
+ countFnNodeIndices(expr, indexCounter);
1798
+ } else indexCounter.value++;
1799
+ }
1800
+ indexCounter.value = savedStart;
1801
+ const processed = /* @__PURE__ */ new Set();
1802
+ function translateRange(start, end, indent = "") {
1803
+ let i = start;
1804
+ while (i < end) {
1805
+ if (processed.has(i)) {
1806
+ i++;
1807
+ continue;
1808
+ }
1809
+ const expr = expressions[i];
1810
+ if (!expr) {
1811
+ i++;
1812
+ continue;
1813
+ }
1814
+ const varIdx = indexMap[i];
1815
+ if (isFnNode(expr)) {
1816
+ processed.add(i);
1817
+ indexCounter.value++;
1818
+ const lambdaCode = generateLambdaCode(expr, indexCounter, paramCounter);
1819
+ lines.push(`${indent}$[${varIdx}] = $lastValue = ${lambdaCode};`);
1820
+ i++;
1821
+ } else if (typeof expr === "string") {
1822
+ processed.add(i);
1823
+ indexCounter.value++;
1824
+ lines.push(`${indent}$[${varIdx}] = $lastValue = ${expr};`);
1825
+ i++;
1826
+ } else if (!Array.isArray(expr)) i++;
1827
+ else {
1828
+ const [type] = expr;
1829
+ if (type === "br") {
1830
+ processed.add(i);
1831
+ indexCounter.value++;
1832
+ const [, condition, skipCount] = expr;
1833
+ const falseBlockEnd = i + skipCount;
1834
+ let jmpIdx = -1;
1835
+ let trueBlockEnd = falseBlockEnd + 1;
1836
+ if (falseBlockEnd < expressions.length) {
1837
+ const lastInFalseBranch = expressions[falseBlockEnd];
1838
+ if (Array.isArray(lastInFalseBranch) && lastInFalseBranch[0] === "jmp") {
1839
+ jmpIdx = falseBlockEnd;
1840
+ const jmpOffset = lastInFalseBranch[1];
1841
+ trueBlockEnd = jmpIdx + jmpOffset;
1842
+ processed.add(jmpIdx);
1843
+ }
1844
+ }
1845
+ const hasElse = jmpIdx >= 0;
1846
+ lines.push(`${indent}if (!(${condition})) {`);
1847
+ translateRange(i + 1, falseBlockEnd + 1, indent + " ");
1848
+ if (hasElse) {
1849
+ lines.push(`${indent}} else {`);
1850
+ translateRange(jmpIdx + 1, trueBlockEnd + 1, indent + " ");
1851
+ lines.push(`${indent}}`);
1852
+ i = trueBlockEnd + 1;
1853
+ } else {
1854
+ lines.push(`${indent}}`);
1855
+ i = falseBlockEnd + 1;
1856
+ }
1857
+ } else if (type === "phi") {
1858
+ processed.add(i);
1859
+ indexCounter.value++;
1860
+ lines.push(`${indent}$[${varIdx}] = $lastValue;`);
1861
+ i++;
1862
+ } else if (type === "jmp") {
1863
+ indexCounter.value++;
1864
+ throw new Error(`Unable to translate: unexpected jmp at index ${i}. This should have been paired with a preceding br. Unsupported control flow structure.`);
1865
+ } else throw new Error(`Unable to translate: unknown control flow node type.`);
1866
+ }
1867
+ }
1868
+ }
1869
+ translateRange(0, expressions.length);
1870
+ lines.push("return $lastValue;");
1871
+ return lines.join("\n");
1872
+ }
1873
+ /**
1874
+ * 计算 FnNode 内部 stmts 占用的索引数量(递归)
1875
+ */
1876
+ function countFnNodeIndices(fnNode, indexCounter) {
1877
+ const [, , ...stmts] = fnNode;
1878
+ for (const stmt of stmts) if (isFnNode(stmt)) {
1879
+ indexCounter.value++;
1880
+ countFnNodeIndices(stmt, indexCounter);
1881
+ } else indexCounter.value++;
1882
+ }
1883
+ /**
1884
+ * 分析并验证控制流结构,将 br/jmp/phi 翻译为 if-else 语句
1885
+ */
1886
+ function translateControlFlow(expressions, variableCount) {
1887
+ return translateStmts(expressions, { value: variableCount }, { value: 0 });
1888
+ }
1889
+ /**
1890
+ * 执行编译后的表达式
1891
+ *
1892
+ * @template TResult - 表达式结果类型
1893
+ * @param data - 编译后的数据结构 [变量名列表, 表达式1, 表达式2, ...]
1894
+ * @param values - 变量值映射,按变量名提供值
1895
+ * @returns 最后一个表达式的求值结果
1896
+ *
1897
+ * @throws 如果运行时类型验证失败或表达式执行出错
1898
+ *
1899
+ * @example
1900
+ * ```ts
1901
+ * const compiled = [["x", "y"], "$[0]+$[1]", "$[1]*2"]
1902
+ * const result = evaluate<number>(compiled, { x: 2, y: 3 })
1903
+ * // => 6 (3 * 2)
1904
+ * ```
1905
+ */
1906
+ function evaluate(data, values) {
1907
+ if (data.length < 1) throw new Error("Invalid compiled data: must have at least variable names");
1908
+ const [variableNames, ...expressions] = data;
1909
+ if (!Array.isArray(variableNames)) throw new Error("Invalid compiled data: first element must be variable names array");
1910
+ for (const varName of variableNames) {
1911
+ if (typeof varName !== "string") throw new Error("Invalid compiled data: variable names must be strings");
1912
+ if (!(varName in values)) throw new Error(`Missing required variable: ${varName}`);
1913
+ }
1914
+ const valueArray = [];
1915
+ for (const varName of variableNames) valueArray.push(values[varName]);
1916
+ const cacheKey = JSON.stringify(data);
1917
+ let evaluator = evaluatorCache.get(cacheKey);
1918
+ if (!evaluator) {
1919
+ const functionBody = buildEvaluatorFunctionBody(expressions, variableNames.length);
1920
+ evaluator = new Function("$", functionBody);
1921
+ evaluatorCache.set(cacheKey, evaluator);
1922
+ }
1923
+ try {
1924
+ return evaluator(valueArray);
1925
+ } catch (error) {
1926
+ throw new Error(`Failed to evaluate expression: ${error instanceof Error ? error.message : String(error)}`);
1927
+ }
1928
+ }
1929
+ /**
1930
+ * 构造求值函数体
1931
+ *
1932
+ * @param expressions - 表达式列表(可包含控制流节点和 FnNode)
1933
+ * @param variableCount - 变量数量
1934
+ * @returns 函数体字符串
1935
+ */
1936
+ function buildEvaluatorFunctionBody(expressions, variableCount) {
1937
+ if (expressions.length === 0) throw new Error("No expressions to evaluate");
1938
+ return translateControlFlow(expressions, variableCount);
1939
+ }
1940
+
1941
+ //#endregion
1942
+ export { compile, evaluate, expr, lambda, t, variable, wrap };
1665
1943
  //# sourceMappingURL=index.mjs.map