@codehz/json-expr 0.0.0 → 0.1.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/README.md +30 -1
- package/dist/index.d.mts +36 -1
- package/dist/index.mjs +39 -3
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -25,7 +25,7 @@ bun install @codehz/json-expr
|
|
|
25
25
|
|
|
26
26
|
```typescript
|
|
27
27
|
import { z } from "zod";
|
|
28
|
-
import { variable, expr, compile, evaluate } from "@codehz/json-expr";
|
|
28
|
+
import { variable, expr, compile, evaluate, constant } from "@codehz/json-expr";
|
|
29
29
|
|
|
30
30
|
// 定义类型化变量
|
|
31
31
|
const x = variable(z.number());
|
|
@@ -93,6 +93,35 @@ const compiled = compile(result, { x, y });
|
|
|
93
93
|
|
|
94
94
|
## API 参考
|
|
95
95
|
|
|
96
|
+
### `constant<T>(value: T): Expression<{}, T>`
|
|
97
|
+
|
|
98
|
+
创建一个编译期常量表达式。这是 `expr({})(JSON.stringify(value))` 的快速路径,用于在表达式中嵌入静态值,避免在运行时传入或在多处重复编写。
|
|
99
|
+
|
|
100
|
+
**参数:**
|
|
101
|
+
|
|
102
|
+
- `value` - 要嵌入的常量值(必须是 JSON 可序列化的:string、number、boolean、null、数组或对象)
|
|
103
|
+
|
|
104
|
+
**返回值:** Expression 对象
|
|
105
|
+
|
|
106
|
+
**示例:**
|
|
107
|
+
|
|
108
|
+
```typescript
|
|
109
|
+
import { constant, expr, variable, compile, evaluate } from "@codehz/json-expr";
|
|
110
|
+
import { z } from "zod";
|
|
111
|
+
|
|
112
|
+
// 创建常量
|
|
113
|
+
const PI = constant(3.14159);
|
|
114
|
+
const config = constant({ maxRetries: 3, timeout: 5000 });
|
|
115
|
+
|
|
116
|
+
// 在表达式中使用常量
|
|
117
|
+
const radius = variable(z.number());
|
|
118
|
+
const area = expr({ PI, radius })("PI * radius * radius");
|
|
119
|
+
|
|
120
|
+
const compiled = compile(area, { radius });
|
|
121
|
+
const result = evaluate(compiled, { radius: 2 });
|
|
122
|
+
// => 12.56636
|
|
123
|
+
```
|
|
124
|
+
|
|
96
125
|
### `variable<T>(schema: T): Variable<T>`
|
|
97
126
|
|
|
98
127
|
创建一个类型化变量。
|
package/dist/index.d.mts
CHANGED
|
@@ -101,6 +101,41 @@ type ExpressionContext = Record<string, Variable<z.ZodType> | Expression<Record<
|
|
|
101
101
|
*/
|
|
102
102
|
declare function compile<TResult>(expression: Expression<ExpressionContext, TResult>, variables: Record<string, Variable<z.ZodType>>, options?: CompileOptions): CompiledData;
|
|
103
103
|
//#endregion
|
|
104
|
+
//#region src/constant.d.ts
|
|
105
|
+
/**
|
|
106
|
+
* JSON 可序列化的值类型
|
|
107
|
+
*/
|
|
108
|
+
type JsonValue = string | number | boolean | null | JsonValue[] | {
|
|
109
|
+
[key: string]: JsonValue;
|
|
110
|
+
};
|
|
111
|
+
/**
|
|
112
|
+
* 创建一个编译期常量表达式
|
|
113
|
+
*
|
|
114
|
+
* 这是 `expr({})(JSON.stringify(value))` 的快速路径,
|
|
115
|
+
* 用于在表达式中嵌入静态值,避免在运行时传入或在多处重复编写。
|
|
116
|
+
*
|
|
117
|
+
* @template T - 常量值类型(必须是 JSON 可序列化的)
|
|
118
|
+
* @param value - 要嵌入的常量值
|
|
119
|
+
* @returns 返回一个 Expression 对象,其结果类型为 T
|
|
120
|
+
*
|
|
121
|
+
* @example
|
|
122
|
+
* ```ts
|
|
123
|
+
* // 创建一个数字常量
|
|
124
|
+
* const PI = constant(3.14159)
|
|
125
|
+
*
|
|
126
|
+
* // 创建一个字符串常量
|
|
127
|
+
* const greeting = constant("Hello, World!")
|
|
128
|
+
*
|
|
129
|
+
* // 创建一个对象常量
|
|
130
|
+
* const config = constant({ maxRetries: 3, timeout: 5000 })
|
|
131
|
+
*
|
|
132
|
+
* // 在表达式中使用常量
|
|
133
|
+
* const radius = variable(z.number())
|
|
134
|
+
* const area = expr({ PI, radius })("PI * radius * radius")
|
|
135
|
+
* ```
|
|
136
|
+
*/
|
|
137
|
+
declare function constant<const T extends JsonValue>(value: T): Expression<{}, T>;
|
|
138
|
+
//#endregion
|
|
104
139
|
//#region src/evaluate.d.ts
|
|
105
140
|
/**
|
|
106
141
|
* 执行编译后的表达式
|
|
@@ -361,5 +396,5 @@ declare function expr<TContext extends ExprContext>(context: TContext): <Source
|
|
|
361
396
|
*/
|
|
362
397
|
declare function variable<T extends z.ZodType>(schema: T): Variable<T>;
|
|
363
398
|
//#endregion
|
|
364
|
-
export { type CompileContext, type CompileOptions, type CompiledData, type ContextTypeMap, type ExprNode, type Expression, type ExpressionType, type ExtractType, type InferContextType, type InferExpressionResult, type InferExpressionType, type InferVariableType, type ParseExpression, type ValidateExpression, type Variable, compile, evaluate, expr, variable };
|
|
399
|
+
export { type CompileContext, type CompileOptions, type CompiledData, type ContextTypeMap, type ExprNode, type Expression, type ExpressionType, type ExtractType, type InferContextType, type InferExpressionResult, type InferExpressionType, type InferVariableType, type ParseExpression, type ValidateExpression, type Variable, compile, constant, evaluate, expr, variable };
|
|
365
400
|
//# sourceMappingURL=index.d.mts.map
|
package/dist/index.mjs
CHANGED
|
@@ -836,6 +836,43 @@ function extractVariableNames(source) {
|
|
|
836
836
|
return Array.from(identifiers).filter((name) => !ALLOWED_GLOBALS.has(name));
|
|
837
837
|
}
|
|
838
838
|
|
|
839
|
+
//#endregion
|
|
840
|
+
//#region src/constant.ts
|
|
841
|
+
/**
|
|
842
|
+
* 创建一个编译期常量表达式
|
|
843
|
+
*
|
|
844
|
+
* 这是 `expr({})(JSON.stringify(value))` 的快速路径,
|
|
845
|
+
* 用于在表达式中嵌入静态值,避免在运行时传入或在多处重复编写。
|
|
846
|
+
*
|
|
847
|
+
* @template T - 常量值类型(必须是 JSON 可序列化的)
|
|
848
|
+
* @param value - 要嵌入的常量值
|
|
849
|
+
* @returns 返回一个 Expression 对象,其结果类型为 T
|
|
850
|
+
*
|
|
851
|
+
* @example
|
|
852
|
+
* ```ts
|
|
853
|
+
* // 创建一个数字常量
|
|
854
|
+
* const PI = constant(3.14159)
|
|
855
|
+
*
|
|
856
|
+
* // 创建一个字符串常量
|
|
857
|
+
* const greeting = constant("Hello, World!")
|
|
858
|
+
*
|
|
859
|
+
* // 创建一个对象常量
|
|
860
|
+
* const config = constant({ maxRetries: 3, timeout: 5000 })
|
|
861
|
+
*
|
|
862
|
+
* // 在表达式中使用常量
|
|
863
|
+
* const radius = variable(z.number())
|
|
864
|
+
* const area = expr({ PI, radius })("PI * radius * radius")
|
|
865
|
+
* ```
|
|
866
|
+
*/
|
|
867
|
+
function constant(value) {
|
|
868
|
+
return {
|
|
869
|
+
_tag: "expression",
|
|
870
|
+
context: {},
|
|
871
|
+
source: JSON.stringify(value),
|
|
872
|
+
_type: void 0
|
|
873
|
+
};
|
|
874
|
+
}
|
|
875
|
+
|
|
839
876
|
//#endregion
|
|
840
877
|
//#region src/evaluate.ts
|
|
841
878
|
/**
|
|
@@ -898,8 +935,7 @@ function evaluate(data, values) {
|
|
|
898
935
|
function buildEvaluatorFunctionBody(expressions, variableCount) {
|
|
899
936
|
if (expressions.length === 0) throw new Error("No expressions to evaluate");
|
|
900
937
|
const lines = [];
|
|
901
|
-
lines.push(
|
|
902
|
-
for (let i = 1; i < variableCount; i++) lines.push(`const $${i} = $values[${i}];`);
|
|
938
|
+
for (let i = 0; i < variableCount; i++) lines.push(`const $${i} = $values[${i}];`);
|
|
903
939
|
for (let i = 0; i < expressions.length; i++) {
|
|
904
940
|
const exprSource = expressions[i];
|
|
905
941
|
const resultIndex = variableCount + i;
|
|
@@ -977,5 +1013,5 @@ function variable(schema) {
|
|
|
977
1013
|
}
|
|
978
1014
|
|
|
979
1015
|
//#endregion
|
|
980
|
-
export { compile, evaluate, expr, variable };
|
|
1016
|
+
export { compile, constant, evaluate, expr, variable };
|
|
981
1017
|
//# sourceMappingURL=index.mjs.map
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":[],"sources":["../src/parser.ts","../src/compile.ts","../src/evaluate.ts","../src/expr.ts","../src/variable.ts"],"sourcesContent":["/**\n * JavaScript 表达式解析器\n * 将表达式字符串解析为 AST,支持常见的运算符和语法\n */\n\n// AST 节点类型\nexport type ASTNode =\n | NumberLiteral\n | StringLiteral\n | BooleanLiteral\n | NullLiteral\n | Identifier\n | BinaryExpr\n | UnaryExpr\n | ConditionalExpr\n | MemberExpr\n | CallExpr\n | ArrayExpr\n | ObjectExpr;\n\nexport interface NumberLiteral {\n type: \"NumberLiteral\";\n value: number;\n raw: string;\n}\n\nexport interface StringLiteral {\n type: \"StringLiteral\";\n value: string;\n quote: \"'\" | '\"' | \"`\";\n}\n\nexport interface BooleanLiteral {\n type: \"BooleanLiteral\";\n value: boolean;\n}\n\nexport interface NullLiteral {\n type: \"NullLiteral\";\n}\n\nexport interface Identifier {\n type: \"Identifier\";\n name: string;\n}\n\nexport interface BinaryExpr {\n type: \"BinaryExpr\";\n operator: string;\n left: ASTNode;\n right: ASTNode;\n}\n\nexport interface UnaryExpr {\n type: \"UnaryExpr\";\n operator: string;\n argument: ASTNode;\n prefix: boolean;\n}\n\nexport interface ConditionalExpr {\n type: \"ConditionalExpr\";\n test: ASTNode;\n consequent: ASTNode;\n alternate: ASTNode;\n}\n\nexport interface MemberExpr {\n type: \"MemberExpr\";\n object: ASTNode;\n property: ASTNode;\n computed: boolean;\n optional: boolean;\n}\n\nexport interface CallExpr {\n type: \"CallExpr\";\n callee: ASTNode;\n arguments: ASTNode[];\n optional: boolean;\n}\n\nexport interface ArrayExpr {\n type: \"ArrayExpr\";\n elements: ASTNode[];\n}\n\nexport interface ObjectExpr {\n type: \"ObjectExpr\";\n properties: ObjectProperty[];\n}\n\nexport interface ObjectProperty {\n key: ASTNode;\n value: ASTNode;\n computed: boolean;\n shorthand: boolean;\n}\n\n// 运算符优先级(从低到高)\nconst PRECEDENCE: Record<string, number> = {\n \"||\": 1,\n \"??\": 1,\n \"&&\": 2,\n \"|\": 3,\n \"^\": 4,\n \"&\": 5,\n \"==\": 6,\n \"!=\": 6,\n \"===\": 6,\n \"!==\": 6,\n \"<\": 7,\n \">\": 7,\n \"<=\": 7,\n \">=\": 7,\n in: 7,\n instanceof: 7,\n \"<<\": 8,\n \">>\": 8,\n \">>>\": 8,\n \"+\": 9,\n \"-\": 9,\n \"*\": 10,\n \"/\": 10,\n \"%\": 10,\n \"**\": 11,\n};\n\n// 右结合运算符\nconst RIGHT_ASSOCIATIVE = new Set([\"**\"]);\n\nclass Parser {\n private pos = 0;\n private source: string;\n\n constructor(source: string) {\n this.source = source;\n }\n\n parse(): ASTNode {\n this.skipWhitespace();\n const node = this.parseExpression();\n this.skipWhitespace();\n if (this.pos < this.source.length) {\n throw new Error(`Unexpected token at position ${this.pos}: ${this.source.slice(this.pos, this.pos + 10)}`);\n }\n return node;\n }\n\n private parseExpression(): ASTNode {\n return this.parseConditional();\n }\n\n private parseConditional(): ASTNode {\n let node = this.parseBinary(0);\n\n this.skipWhitespace();\n if (this.peek() === \"?\") {\n this.advance();\n this.skipWhitespace();\n const consequent = this.parseExpression();\n this.skipWhitespace();\n this.expect(\":\");\n this.skipWhitespace();\n const alternate = this.parseExpression();\n node = {\n type: \"ConditionalExpr\",\n test: node,\n consequent,\n alternate,\n };\n }\n\n return node;\n }\n\n private parseBinary(minPrec: number): ASTNode {\n let left = this.parseUnary();\n\n while (true) {\n this.skipWhitespace();\n const op = this.peekOperator();\n if (!op || PRECEDENCE[op] === undefined || PRECEDENCE[op] < minPrec) {\n break;\n }\n\n this.pos += op.length;\n this.skipWhitespace();\n\n const nextMinPrec = RIGHT_ASSOCIATIVE.has(op) ? PRECEDENCE[op] : PRECEDENCE[op] + 1;\n\n const right = this.parseBinary(nextMinPrec);\n\n left = {\n type: \"BinaryExpr\",\n operator: op,\n left,\n right,\n };\n }\n\n return left;\n }\n\n private parseUnary(): ASTNode {\n this.skipWhitespace();\n const ch = this.peek();\n\n if (ch === \"!\" || ch === \"~\" || ch === \"+\" || ch === \"-\") {\n // 检查是否是一元运算符而非二元运算符\n if (ch === \"+\" || ch === \"-\") {\n this.advance();\n this.skipWhitespace();\n const argument = this.parseUnary();\n return {\n type: \"UnaryExpr\",\n operator: ch,\n argument,\n prefix: true,\n };\n }\n this.advance();\n this.skipWhitespace();\n const argument = this.parseUnary();\n return {\n type: \"UnaryExpr\",\n operator: ch,\n argument,\n prefix: true,\n };\n }\n\n if (this.matchKeyword(\"typeof\")) {\n this.skipWhitespace();\n const argument = this.parseUnary();\n return {\n type: \"UnaryExpr\",\n operator: \"typeof\",\n argument,\n prefix: true,\n };\n }\n\n if (this.matchKeyword(\"void\")) {\n this.skipWhitespace();\n const argument = this.parseUnary();\n return {\n type: \"UnaryExpr\",\n operator: \"void\",\n argument,\n prefix: true,\n };\n }\n\n return this.parsePostfix();\n }\n\n private parsePostfix(): ASTNode {\n let node = this.parsePrimary();\n\n while (true) {\n this.skipWhitespace();\n const ch = this.peek();\n\n if (ch === \".\") {\n this.advance();\n this.skipWhitespace();\n const property = this.parseIdentifier();\n node = {\n type: \"MemberExpr\",\n object: node,\n property,\n computed: false,\n optional: false,\n };\n } else if (ch === \"[\") {\n this.advance();\n this.skipWhitespace();\n const property = this.parseExpression();\n this.skipWhitespace();\n this.expect(\"]\");\n node = {\n type: \"MemberExpr\",\n object: node,\n property,\n computed: true,\n optional: false,\n };\n } else if (ch === \"(\") {\n this.advance();\n const args = this.parseArguments();\n this.expect(\")\");\n node = {\n type: \"CallExpr\",\n callee: node,\n arguments: args,\n optional: false,\n };\n } else if (ch === \"?\" && this.peekAt(1) === \".\") {\n this.advance();\n this.advance();\n this.skipWhitespace();\n if (this.peek() === \"[\") {\n this.advance();\n this.skipWhitespace();\n const property = this.parseExpression();\n this.skipWhitespace();\n this.expect(\"]\");\n node = {\n type: \"MemberExpr\",\n object: node,\n property,\n computed: true,\n optional: true,\n };\n } else if (this.peek() === \"(\") {\n this.advance();\n const args = this.parseArguments();\n this.expect(\")\");\n node = {\n type: \"CallExpr\",\n callee: node,\n arguments: args,\n optional: true,\n };\n } else {\n const property = this.parseIdentifier();\n node = {\n type: \"MemberExpr\",\n object: node,\n property,\n computed: false,\n optional: true,\n };\n }\n } else {\n break;\n }\n }\n\n return node;\n }\n\n private parsePrimary(): ASTNode {\n this.skipWhitespace();\n const ch = this.peek();\n\n // 数字\n if (this.isDigit(ch) || (ch === \".\" && this.isDigit(this.peekAt(1)))) {\n return this.parseNumber();\n }\n\n // 字符串\n if (ch === '\"' || ch === \"'\" || ch === \"`\") {\n return this.parseString();\n }\n\n // 数组\n if (ch === \"[\") {\n return this.parseArray();\n }\n\n // 对象\n if (ch === \"{\") {\n return this.parseObject();\n }\n\n // 括号表达式\n if (ch === \"(\") {\n this.advance();\n this.skipWhitespace();\n const expr = this.parseExpression();\n this.skipWhitespace();\n this.expect(\")\");\n return expr;\n }\n\n // 关键字字面量\n if (this.matchKeyword(\"true\")) {\n return { type: \"BooleanLiteral\", value: true };\n }\n if (this.matchKeyword(\"false\")) {\n return { type: \"BooleanLiteral\", value: false };\n }\n if (this.matchKeyword(\"null\")) {\n return { type: \"NullLiteral\" };\n }\n if (this.matchKeyword(\"undefined\")) {\n return { type: \"Identifier\", name: \"undefined\" };\n }\n\n // 标识符\n if (this.isIdentifierStart(ch)) {\n return this.parseIdentifier();\n }\n\n throw new Error(`Unexpected character at position ${this.pos}: ${ch}`);\n }\n\n private parseNumber(): NumberLiteral {\n const start = this.pos;\n\n // 处理十六进制、八进制、二进制\n if (this.peek() === \"0\") {\n const next = this.peekAt(1)?.toLowerCase();\n if (next === \"x\" || next === \"o\" || next === \"b\") {\n this.advance();\n this.advance();\n while (this.isHexDigit(this.peek())) {\n this.advance();\n }\n const raw = this.source.slice(start, this.pos);\n return {\n type: \"NumberLiteral\",\n value: Number(raw),\n raw,\n };\n }\n }\n\n // 整数部分\n while (this.isDigit(this.peek())) {\n this.advance();\n }\n\n // 小数部分\n if (this.peek() === \".\" && this.isDigit(this.peekAt(1))) {\n this.advance();\n while (this.isDigit(this.peek())) {\n this.advance();\n }\n }\n\n // 指数部分\n if (this.peek()?.toLowerCase() === \"e\") {\n this.advance();\n if (this.peek() === \"+\" || this.peek() === \"-\") {\n this.advance();\n }\n while (this.isDigit(this.peek())) {\n this.advance();\n }\n }\n\n const raw = this.source.slice(start, this.pos);\n return {\n type: \"NumberLiteral\",\n value: Number(raw),\n raw,\n };\n }\n\n private parseString(): StringLiteral {\n const quote = this.peek() as \"'\" | '\"' | \"`\";\n this.advance();\n\n let value = \"\";\n while (this.pos < this.source.length && this.peek() !== quote) {\n if (this.peek() === \"\\\\\") {\n this.advance();\n const escaped = this.peek();\n switch (escaped) {\n case \"n\":\n value += \"\\n\";\n break;\n case \"r\":\n value += \"\\r\";\n break;\n case \"t\":\n value += \"\\t\";\n break;\n case \"\\\\\":\n value += \"\\\\\";\n break;\n case \"'\":\n value += \"'\";\n break;\n case '\"':\n value += '\"';\n break;\n case \"`\":\n value += \"`\";\n break;\n default:\n value += escaped;\n }\n this.advance();\n } else {\n value += this.peek();\n this.advance();\n }\n }\n\n this.expect(quote);\n return { type: \"StringLiteral\", value, quote };\n }\n\n private parseArray(): ArrayExpr {\n this.expect(\"[\");\n const elements: ASTNode[] = [];\n\n this.skipWhitespace();\n while (this.peek() !== \"]\") {\n elements.push(this.parseExpression());\n this.skipWhitespace();\n if (this.peek() === \",\") {\n this.advance();\n this.skipWhitespace();\n } else {\n break;\n }\n }\n\n this.expect(\"]\");\n return { type: \"ArrayExpr\", elements };\n }\n\n private parseObject(): ObjectExpr {\n this.expect(\"{\");\n const properties: ObjectProperty[] = [];\n\n this.skipWhitespace();\n while (this.peek() !== \"}\") {\n const prop = this.parseObjectProperty();\n properties.push(prop);\n this.skipWhitespace();\n if (this.peek() === \",\") {\n this.advance();\n this.skipWhitespace();\n } else {\n break;\n }\n }\n\n this.expect(\"}\");\n return { type: \"ObjectExpr\", properties };\n }\n\n private parseObjectProperty(): ObjectProperty {\n this.skipWhitespace();\n let key: ASTNode;\n let computed = false;\n\n if (this.peek() === \"[\") {\n this.advance();\n this.skipWhitespace();\n key = this.parseExpression();\n this.skipWhitespace();\n this.expect(\"]\");\n computed = true;\n } else if (this.peek() === '\"' || this.peek() === \"'\") {\n key = this.parseString();\n } else {\n key = this.parseIdentifier();\n }\n\n this.skipWhitespace();\n if (this.peek() === \":\") {\n this.advance();\n this.skipWhitespace();\n const value = this.parseExpression();\n return { key, value, computed, shorthand: false };\n }\n\n // Shorthand property\n if (key.type !== \"Identifier\") {\n throw new Error(\"Shorthand property must be an identifier\");\n }\n return { key, value: key, computed: false, shorthand: true };\n }\n\n private parseIdentifier(): Identifier {\n const start = this.pos;\n while (this.isIdentifierPart(this.peek())) {\n this.advance();\n }\n const name = this.source.slice(start, this.pos);\n if (!name) {\n throw new Error(`Expected identifier at position ${this.pos}`);\n }\n return { type: \"Identifier\", name };\n }\n\n private parseArguments(): ASTNode[] {\n const args: ASTNode[] = [];\n this.skipWhitespace();\n while (this.peek() !== \")\") {\n args.push(this.parseExpression());\n this.skipWhitespace();\n if (this.peek() === \",\") {\n this.advance();\n this.skipWhitespace();\n } else {\n break;\n }\n }\n return args;\n }\n\n private peekOperator(): string | null {\n // 按长度排序,先匹配长的运算符\n const ops = [\n \">>>\",\n \"===\",\n \"!==\",\n \"instanceof\",\n \"&&\",\n \"||\",\n \"??\",\n \"==\",\n \"!=\",\n \"<=\",\n \">=\",\n \"<<\",\n \">>\",\n \"**\",\n \"in\",\n \"+\",\n \"-\",\n \"*\",\n \"/\",\n \"%\",\n \"<\",\n \">\",\n \"&\",\n \"|\",\n \"^\",\n ];\n\n for (const op of ops) {\n if (this.source.startsWith(op, this.pos)) {\n // 对于 \"in\" 和 \"instanceof\",确保后面不是标识符字符\n if (op === \"in\" || op === \"instanceof\") {\n const nextChar = this.source[this.pos + op.length];\n if (nextChar && this.isIdentifierPart(nextChar)) {\n continue;\n }\n }\n return op;\n }\n }\n return null;\n }\n\n private matchKeyword(keyword: string): boolean {\n if (this.source.startsWith(keyword, this.pos)) {\n const nextChar = this.source[this.pos + keyword.length];\n if (!nextChar || !this.isIdentifierPart(nextChar)) {\n this.pos += keyword.length;\n return true;\n }\n }\n return false;\n }\n\n private peek(): string {\n return this.source[this.pos] || \"\";\n }\n\n private peekAt(offset: number): string {\n return this.source[this.pos + offset] || \"\";\n }\n\n private advance(): string {\n return this.source[this.pos++] || \"\";\n }\n\n private expect(ch: string): void {\n if (this.peek() !== ch) {\n throw new Error(`Expected '${ch}' at position ${this.pos}, got '${this.peek()}'`);\n }\n this.advance();\n }\n\n private skipWhitespace(): void {\n while (/\\s/.test(this.peek())) {\n this.advance();\n }\n }\n\n private isDigit(ch: string): boolean {\n return /[0-9]/.test(ch);\n }\n\n private isHexDigit(ch: string): boolean {\n return /[0-9a-fA-F]/.test(ch);\n }\n\n private isIdentifierStart(ch: string): boolean {\n return /[a-zA-Z_$]/.test(ch);\n }\n\n private isIdentifierPart(ch: string): boolean {\n return /[a-zA-Z0-9_$]/.test(ch);\n }\n}\n\n/**\n * 解析 JavaScript 表达式为 AST\n */\nexport function parse(source: string): ASTNode {\n return new Parser(source).parse();\n}\n\n/**\n * 从 AST 生成规范化的代码\n */\nexport function generate(node: ASTNode): string {\n switch (node.type) {\n case \"NumberLiteral\":\n return node.raw;\n\n case \"StringLiteral\":\n // 使用双引号,转义必要的字符\n return JSON.stringify(node.value);\n\n case \"BooleanLiteral\":\n return node.value ? \"true\" : \"false\";\n\n case \"NullLiteral\":\n return \"null\";\n\n case \"Identifier\":\n return node.name;\n\n case \"BinaryExpr\": {\n const left = wrapIfNeeded(node.left, node, \"left\");\n const right = wrapIfNeeded(node.right, node, \"right\");\n return `${left}${node.operator}${right}`;\n }\n\n case \"UnaryExpr\":\n if (node.prefix) {\n const arg = wrapIfNeeded(node.argument, node, \"argument\");\n // 对于关键字运算符(typeof, void)需要空格\n if (node.operator === \"typeof\" || node.operator === \"void\") {\n return `${node.operator} ${arg}`;\n }\n return `${node.operator}${arg}`;\n }\n return generate(node.argument) + node.operator;\n\n case \"ConditionalExpr\": {\n const test = generate(node.test);\n const consequent = generate(node.consequent);\n const alternate = generate(node.alternate);\n return `${test}?${consequent}:${alternate}`;\n }\n\n case \"MemberExpr\": {\n const object = wrapIfNeeded(node.object, node, \"object\");\n if (node.computed) {\n const property = generate(node.property);\n return node.optional ? `${object}?.[${property}]` : `${object}[${property}]`;\n }\n const property = generate(node.property);\n return node.optional ? `${object}?.${property}` : `${object}.${property}`;\n }\n\n case \"CallExpr\": {\n const callee = wrapIfNeeded(node.callee, node, \"callee\");\n const args = node.arguments.map(generate).join(\",\");\n return node.optional ? `${callee}?.(${args})` : `${callee}(${args})`;\n }\n\n case \"ArrayExpr\":\n return `[${node.elements.map(generate).join(\",\")}]`;\n\n case \"ObjectExpr\": {\n const props = node.properties.map((prop) => {\n if (prop.shorthand) {\n return generate(prop.key);\n }\n const key = prop.computed ? `[${generate(prop.key)}]` : generate(prop.key);\n return `${key}:${generate(prop.value)}`;\n });\n return `{${props.join(\",\")}}`;\n }\n\n default: {\n const unknownNode = node as { type?: string };\n const nodeType = unknownNode.type ?? \"unknown\";\n throw new Error(`Unknown node type: ${nodeType}`);\n }\n }\n}\n\n/**\n * 判断是否需要括号包裹,并生成代码\n */\nfunction wrapIfNeeded(\n child: ASTNode,\n parent: ASTNode,\n position: \"left\" | \"right\" | \"argument\" | \"object\" | \"callee\"\n): string {\n const code = generate(child);\n\n if (needsParens(child, parent, position)) {\n return `(${code})`;\n }\n return code;\n}\n\n/**\n * 判断子节点是否需要括号\n */\nfunction needsParens(child: ASTNode, parent: ASTNode, position: string): boolean {\n // 条件表达式在二元表达式中需要括号\n if (child.type === \"ConditionalExpr\" && parent.type === \"BinaryExpr\") {\n return true;\n }\n\n // 二元表达式嵌套时根据优先级判断\n if (child.type === \"BinaryExpr\" && parent.type === \"BinaryExpr\") {\n const childPrec = PRECEDENCE[child.operator] || 0;\n const parentPrec = PRECEDENCE[parent.operator] || 0;\n\n if (childPrec < parentPrec) {\n return true;\n }\n\n // 相同优先级时,右侧需要括号(除了右结合运算符)\n if (childPrec === parentPrec && position === \"right\") {\n if (!RIGHT_ASSOCIATIVE.has(parent.operator)) {\n return true;\n }\n }\n }\n\n // 一元表达式作为二元表达式右侧且运算符是 ** 时需要括号\n if (child.type === \"UnaryExpr\" && parent.type === \"BinaryExpr\") {\n if (parent.operator === \"**\" && position === \"left\") {\n return true;\n }\n }\n\n return false;\n}\n\n/**\n * 转换 AST 中的标识符\n */\nexport function transformIdentifiers(node: ASTNode, transform: (name: string) => string): ASTNode {\n switch (node.type) {\n case \"Identifier\":\n return { ...node, name: transform(node.name) };\n\n case \"BinaryExpr\":\n return {\n ...node,\n left: transformIdentifiers(node.left, transform),\n right: transformIdentifiers(node.right, transform),\n };\n\n case \"UnaryExpr\":\n return {\n ...node,\n argument: transformIdentifiers(node.argument, transform),\n };\n\n case \"ConditionalExpr\":\n return {\n ...node,\n test: transformIdentifiers(node.test, transform),\n consequent: transformIdentifiers(node.consequent, transform),\n alternate: transformIdentifiers(node.alternate, transform),\n };\n\n case \"MemberExpr\":\n return {\n ...node,\n object: transformIdentifiers(node.object, transform),\n // 只有 computed 属性需要转换\n property: node.computed ? transformIdentifiers(node.property, transform) : node.property,\n };\n\n case \"CallExpr\":\n return {\n ...node,\n callee: transformIdentifiers(node.callee, transform),\n arguments: node.arguments.map((arg) => transformIdentifiers(arg, transform)),\n };\n\n case \"ArrayExpr\":\n return {\n ...node,\n elements: node.elements.map((el) => transformIdentifiers(el, transform)),\n };\n\n case \"ObjectExpr\":\n return {\n ...node,\n properties: node.properties.map((prop) => ({\n ...prop,\n key: prop.computed ? transformIdentifiers(prop.key, transform) : prop.key,\n value: transformIdentifiers(prop.value, transform),\n })),\n };\n\n default:\n return node;\n }\n}\n\n/**\n * 收集 AST 中所有使用的标识符名称\n */\nexport function collectIdentifiers(node: ASTNode): Set<string> {\n const identifiers = new Set<string>();\n\n function visit(n: ASTNode): void {\n switch (n.type) {\n case \"Identifier\":\n identifiers.add(n.name);\n break;\n\n case \"BinaryExpr\":\n visit(n.left);\n visit(n.right);\n break;\n\n case \"UnaryExpr\":\n visit(n.argument);\n break;\n\n case \"ConditionalExpr\":\n visit(n.test);\n visit(n.consequent);\n visit(n.alternate);\n break;\n\n case \"MemberExpr\":\n visit(n.object);\n if (n.computed) {\n visit(n.property);\n }\n break;\n\n case \"CallExpr\":\n visit(n.callee);\n n.arguments.forEach(visit);\n break;\n\n case \"ArrayExpr\":\n n.elements.forEach(visit);\n break;\n\n case \"ObjectExpr\":\n n.properties.forEach((prop) => {\n if (prop.computed) {\n visit(prop.key);\n }\n visit(prop.value);\n });\n break;\n }\n }\n\n visit(node);\n return identifiers;\n}\n","import { z } from \"zod\";\nimport { collectIdentifiers, generate, parse, type ASTNode } from \"./parser\";\nimport type { CompileContext, CompiledData, Expression, ExprNode, Variable } from \"./types\";\n\n/**\n * 编译选项\n */\nexport interface CompileOptions {\n /**\n * 是否启用内联优化\n * 将只被引用一次的子表达式内联到使用位置\n * @default true\n */\n inline?: boolean;\n}\n\n/**\n * 表达式上下文类型约束\n */\ntype ExpressionContext = Record<string, Variable<z.ZodType> | Expression<Record<string, unknown>, unknown>>;\n\n/**\n * 将表达式树编译为可序列化的 JSON 结构\n *\n * @template TResult - 表达式结果类型\n * @param expression - 根表达式\n * @param variables - 所有使用的变量定义\n * @param options - 编译选项\n * @returns 编译后的数据结构 [变量名列表, 表达式1, 表达式2, ...]\n *\n * @throws 如果检测到循环依赖或未定义的变量引用\n *\n * @example\n * ```ts\n * const x = variable(z.number())\n * const y = variable(z.number())\n * const sum = expr({ x, y })<number>(\"x + y\")\n * const result = expr({ sum })<number>(\"sum * 2\")\n * const compiled = compile(result, { x, y })\n * // => [[\"x\", \"y\"], \"($0+$1)*2\"] // 内联优化后\n * ```\n */\nexport function compile<TResult>(\n expression: Expression<ExpressionContext, TResult>,\n variables: Record<string, Variable<z.ZodType>>,\n options: CompileOptions = {}\n): CompiledData {\n const { inline = true } = options;\n // 创建编译上下文\n const context: CompileContext = {\n variableOrder: [],\n nodeToIndex: new Map(),\n expressions: [],\n };\n\n // 第一步:为每个表达式分配唯一 ID\n const exprIdMap = new WeakMap<Expression<Record<string, unknown>, unknown>, symbol>();\n const getExprId = (expr: Expression<Record<string, unknown>, unknown>): symbol => {\n if (!exprIdMap.has(expr)) {\n exprIdMap.set(expr, Symbol(\"expr\"));\n }\n const id = exprIdMap.get(expr);\n if (id === undefined) {\n throw new Error(\"Expression ID not found\");\n }\n return id;\n };\n\n // 为所有变量创建 node\n const nodeMap = new Map<symbol, ExprNode>();\n const variableNodes = new Map<string, ExprNode>();\n const visited = new Set<symbol>();\n const visiting = new Set<symbol>();\n\n for (const [name, variable] of Object.entries(variables)) {\n const id = Symbol(`var:${name}`);\n const node: ExprNode = {\n id,\n tag: \"variable\",\n schema: variable.schema,\n };\n nodeMap.set(id, node);\n variableNodes.set(name, node);\n }\n\n // 第二步:递归收集所有依赖的节点,并检测循环依赖\n const exprNodes = new Map<symbol, ExprNode>();\n const collectNodes = (expr: Expression<Record<string, unknown>, unknown>): ExprNode => {\n const exprId = getExprId(expr);\n\n if (visited.has(exprId)) {\n return nodeMap.get(exprId)!;\n }\n\n if (visiting.has(exprId)) {\n throw new Error(\"Circular dependency detected in expressions\");\n }\n\n visiting.add(exprId);\n\n const contextNodes: Record<string, ExprNode> = {};\n\n // 收集表达式上下文中的所有节点\n for (const [key, contextItem] of Object.entries(expr.context)) {\n const item = contextItem as Variable<z.ZodType> | Expression<Record<string, unknown>, unknown>;\n if (item._tag === \"variable\") {\n const varNode = variableNodes.get(key);\n if (!varNode) {\n throw new Error(`Undefined variable reference: ${key}`);\n }\n contextNodes[key] = varNode;\n } else if (item._tag === \"expression\") {\n contextNodes[key] = collectNodes(item);\n }\n }\n\n const node: ExprNode = {\n id: exprId,\n tag: \"expression\",\n context: contextNodes,\n source: expr.source,\n };\n\n nodeMap.set(exprId, node);\n exprNodes.set(exprId, node);\n visited.add(exprId);\n visiting.delete(exprId);\n\n return node;\n };\n\n // 收集根表达式的所有节点\n const rootNode = collectNodes(expression);\n\n // 第三步:拓扑排序,确保依赖的节点在前\n const sortedExprNodes: ExprNode[] = [];\n const exprVisited = new Set<symbol>();\n\n const topologicalSort = (node: ExprNode) => {\n if (exprVisited.has(node.id)) {\n return;\n }\n\n exprVisited.add(node.id);\n\n if (node.tag === \"expression\" && node.context) {\n for (const contextNode of Object.values(node.context)) {\n topologicalSort(contextNode);\n }\n }\n\n if (node.tag === \"expression\") {\n sortedExprNodes.push(node);\n }\n };\n\n topologicalSort(rootNode);\n\n // 第四步:分配变量索引 0 ~ N-1\n for (const [name, varNode] of variableNodes.entries()) {\n if (!context.nodeToIndex.has(varNode.id)) {\n context.nodeToIndex.set(varNode.id, context.variableOrder.length);\n context.variableOrder.push(name);\n }\n }\n\n // 第五步:计算每个表达式节点的引用次数\n const refCount = new Map<symbol, number>();\n for (const exprNode of sortedExprNodes) {\n refCount.set(exprNode.id, 0);\n }\n\n for (const exprNode of sortedExprNodes) {\n if (exprNode.context) {\n for (const contextNode of Object.values(exprNode.context)) {\n if (contextNode.tag === \"expression\") {\n refCount.set(contextNode.id, (refCount.get(contextNode.id) ?? 0) + 1);\n }\n }\n }\n }\n\n // 判断哪些表达式可以内联(只被引用一次且不是根节点)\n const canInline = (node: ExprNode): boolean => {\n if (!inline) return false;\n if (node.id === rootNode.id) return false; // 根节点不能内联\n return (refCount.get(node.id) ?? 0) === 1;\n };\n\n // 第六步:为所有不能内联的表达式分配索引\n let exprIndex = 0;\n for (const exprNode of sortedExprNodes) {\n if (!canInline(exprNode)) {\n const index = context.variableOrder.length + exprIndex;\n context.nodeToIndex.set(exprNode.id, index);\n exprIndex++;\n }\n }\n\n // 第七步:为每个表达式生成 AST,并根据内联选项处理\n const nodeAstMap = new Map<symbol, ASTNode>();\n\n // 为变量生成 AST(始终是 $N 标识符)\n for (const [, varNode] of variableNodes.entries()) {\n const index = context.nodeToIndex.get(varNode.id)!;\n nodeAstMap.set(varNode.id, { type: \"Identifier\", name: `$${index}` });\n }\n\n // 为每个表达式生成 AST(按拓扑顺序,确保依赖的节点已处理)\n for (const exprNode of sortedExprNodes) {\n if (!exprNode.context || !exprNode.source) {\n throw new Error(\"Invalid expression node\");\n }\n\n // 检查表达式源码中是否引用了未定义的变量\n const usedVariables = extractVariableNames(exprNode.source);\n for (const varName of usedVariables) {\n if (!(varName in exprNode.context)) {\n throw new Error(\n `Undefined variable reference: ${varName} (available: ${Object.keys(exprNode.context).join(\", \")})`\n );\n }\n }\n\n // 解析表达式为 AST\n const ast = parse(exprNode.source);\n\n // 转换标识符:将上下文中的名称替换为对应的 AST 节点\n const transformed = inlineTransform(ast, (name) => {\n const contextNode = exprNode.context![name];\n if (!contextNode) return null;\n\n if (contextNode.tag === \"variable\") {\n // 变量始终替换为 $N\n return nodeAstMap.get(contextNode.id) ?? null;\n } else {\n // 表达式节点:如果可内联,返回其 AST;否则返回 $N\n if (canInline(contextNode)) {\n return nodeAstMap.get(contextNode.id) ?? null;\n } else {\n const index = context.nodeToIndex.get(contextNode.id)!;\n return { type: \"Identifier\", name: `$${index}` } as ASTNode;\n }\n }\n });\n\n nodeAstMap.set(exprNode.id, transformed);\n }\n\n // 第八步:生成最终表达式列表(只包含不能内联的表达式)\n for (const exprNode of sortedExprNodes) {\n if (!canInline(exprNode)) {\n const ast = nodeAstMap.get(exprNode.id)!;\n context.expressions.push(generate(ast));\n }\n }\n\n // 第九步:组合结果\n const result: CompiledData = [context.variableOrder, ...context.expressions];\n\n return result;\n}\n\n/**\n * 将 AST 中的标识符替换为对应的 AST 节点(用于内联优化)\n *\n * @param node - 要转换的 AST 节点\n * @param getReplacementAst - 根据标识符名称返回替换的 AST 节点,返回 null 表示不替换\n * @returns 转换后的 AST 节点\n */\nfunction inlineTransform(node: ASTNode, getReplacementAst: (name: string) => ASTNode | null): ASTNode {\n switch (node.type) {\n case \"Identifier\": {\n const replacement = getReplacementAst(node.name);\n return replacement ?? node;\n }\n\n case \"BinaryExpr\":\n return {\n ...node,\n left: inlineTransform(node.left, getReplacementAst),\n right: inlineTransform(node.right, getReplacementAst),\n };\n\n case \"UnaryExpr\":\n return {\n ...node,\n argument: inlineTransform(node.argument, getReplacementAst),\n };\n\n case \"ConditionalExpr\":\n return {\n ...node,\n test: inlineTransform(node.test, getReplacementAst),\n consequent: inlineTransform(node.consequent, getReplacementAst),\n alternate: inlineTransform(node.alternate, getReplacementAst),\n };\n\n case \"MemberExpr\":\n return {\n ...node,\n object: inlineTransform(node.object, getReplacementAst),\n property: node.computed ? inlineTransform(node.property, getReplacementAst) : node.property,\n };\n\n case \"CallExpr\":\n return {\n ...node,\n callee: inlineTransform(node.callee, getReplacementAst),\n arguments: node.arguments.map((arg) => inlineTransform(arg, getReplacementAst)),\n };\n\n case \"ArrayExpr\":\n return {\n ...node,\n elements: node.elements.map((el) => inlineTransform(el, getReplacementAst)),\n };\n\n case \"ObjectExpr\":\n return {\n ...node,\n properties: node.properties.map((prop) => ({\n ...prop,\n key: prop.computed ? inlineTransform(prop.key, getReplacementAst) : prop.key,\n value: inlineTransform(prop.value, getReplacementAst),\n })),\n };\n\n default:\n return node;\n }\n}\n\n/**\n * 允许在表达式中直接使用的全局对象\n * 这些对象不需要在上下文中定义\n */\nconst ALLOWED_GLOBALS = new Set([\n // Math 对象及其方法\n \"Math\",\n // JSON 对象\n \"JSON\",\n // 基本类型构造函数\n \"Number\",\n \"String\",\n \"Boolean\",\n \"Array\",\n \"Object\",\n // 其他常用全局对象\n \"Date\",\n \"RegExp\",\n // 全局值\n \"undefined\",\n \"NaN\",\n \"Infinity\",\n // 类型检查\n \"isNaN\",\n \"isFinite\",\n \"parseInt\",\n \"parseFloat\",\n]);\n\n/**\n * 从表达式源码中提取所有使用的变量名\n * 通过 AST 解析实现精确提取\n * 排除允许的全局对象\n *\n * @param source - 表达式源码字符串\n * @returns 使用的变量名列表(去重,不含全局对象)\n *\n * @example\n * ```ts\n * extractVariableNames(\"x + y * Math.PI\")\n * // => [\"x\", \"y\"] // Math 被排除\n * ```\n */\nfunction extractVariableNames(source: string): string[] {\n const ast = parse(source);\n const identifiers = collectIdentifiers(ast);\n // 过滤掉允许的全局对象\n return Array.from(identifiers).filter((name) => !ALLOWED_GLOBALS.has(name));\n}\n","import type { CompiledData } from \"./types\";\n\n/**\n * 缓存已构造的求值函数,以提升重复执行性能\n */\nconst evaluatorCache = new Map<string, (values: unknown[]) => unknown>();\n\n/**\n * 执行编译后的表达式\n *\n * @template TResult - 表达式结果类型\n * @param data - 编译后的数据结构 [变量名列表, 表达式1, 表达式2, ...]\n * @param values - 变量值映射,按变量名提供值\n * @returns 最后一个表达式的求值结果\n *\n * @throws 如果运行时类型验证失败或表达式执行出错\n *\n * @example\n * ```ts\n * const compiled = [[\"x\", \"y\"], \"$0+$1\", \"$1*2\"]\n * const result = evaluate<number>(compiled, { x: 2, y: 3 })\n * // => 6 (3 * 2)\n * ```\n */\nexport function evaluate<TResult>(data: CompiledData, values: Record<string, unknown>): TResult {\n if (data.length < 1) {\n throw new Error(\"Invalid compiled data: must have at least variable names\");\n }\n\n const [variableNames, ...expressions] = data;\n\n if (!Array.isArray(variableNames)) {\n throw new Error(\"Invalid compiled data: first element must be variable names array\");\n }\n\n // 验证所有必需的变量都已提供\n for (const varName of variableNames) {\n if (typeof varName !== \"string\") {\n throw new Error(\"Invalid compiled data: variable names must be strings\");\n }\n if (!(varName in values)) {\n throw new Error(`Missing required variable: ${varName}`);\n }\n }\n\n // 创建值数组,按变量名顺序填入传入的值\n const valueArray: unknown[] = [];\n for (const varName of variableNames) {\n valueArray.push(values[varName]);\n }\n\n // 获取或构造求值函数\n const cacheKey = JSON.stringify(data);\n let evaluator = evaluatorCache.get(cacheKey);\n\n if (!evaluator) {\n // 构造求值函数\n const functionBody = buildEvaluatorFunctionBody(expressions, variableNames.length);\n // eslint-disable-next-line @typescript-eslint/no-implied-eval\n evaluator = new Function(\"$values\", functionBody) as (values: unknown[]) => unknown;\n evaluatorCache.set(cacheKey, evaluator);\n }\n\n // 执行求值函数\n try {\n const result = evaluator(valueArray);\n return result as TResult;\n } catch (error) {\n throw new Error(`Failed to evaluate expression: ${error instanceof Error ? error.message : String(error)}`);\n }\n}\n\n/**\n * 构造求值函数体\n *\n * @param expressions - 表达式列表\n * @param variableCount - 变量数量\n * @returns 函数体字符串\n *\n * @example\n * ```ts\n * buildEvaluatorFunctionBody([\"$0+$1\", \"$2*2\"], 2)\n * // 返回执行 $0+$1 并存储到 $values[2],然后执行 $2*2 的函数体\n * ```\n */\nfunction buildEvaluatorFunctionBody(expressions: string[], variableCount: number): string {\n if (expressions.length === 0) {\n throw new Error(\"No expressions to evaluate\");\n }\n\n const lines: string[] = [];\n\n // 为了使 $0, $1 等能在函数体中访问,我们需要创建局部变量\n // 或者使用代理访问值数组\n lines.push(\"const $0 = $values[0];\");\n for (let i = 1; i < variableCount; i++) {\n lines.push(`const $${i} = $values[${i}];`);\n }\n\n // 依次对每个表达式求值,结果追加到值数组\n for (let i = 0; i < expressions.length; i++) {\n const exprSource = expressions[i];\n const resultIndex = variableCount + i;\n\n lines.push(`const $${resultIndex} = ${exprSource};`);\n lines.push(`$values[${resultIndex}] = $${resultIndex};`);\n }\n\n // 返回最后一个表达式的结果(即最后一个元素)\n lines.push(`return $values[$values.length - 1];`);\n\n return lines.join(\"\\n\");\n}\n","import { z } from \"zod\";\nimport type { InferExpressionResult, ValidateExpression } from \"./type-parser\";\nimport type { Expression, Variable } from \"./types\";\n\n/**\n * 表达式上下文类型约束\n */\ntype ExprContext = Record<string, Variable<z.ZodType> | Expression<Record<string, unknown>, unknown>>;\n\n/**\n * 表达式错误类型\n */\ntype ExprError<Msg extends string, Details = unknown> = {\n readonly __error: Msg;\n readonly __details: Details;\n};\n\n/**\n * 验证结果处理:如果验证失败返回错误类型,否则返回推导的结果类型\n */\ntype ExprResult<Source extends string, TContext extends ExprContext> =\n ValidateExpression<Source, TContext> extends true\n ? InferExpressionResult<Source, TContext>\n : ValidateExpression<Source, TContext> extends { error: \"undefined_identifiers\"; identifiers: infer Ids }\n ? ExprError<\"Undefined identifiers in expression\", Ids>\n : ExprError<\"Expression validation failed\", ValidateExpression<Source, TContext>>;\n\n/**\n * 创建一个表达式,支持编译时类型检查和返回类型自动推导\n *\n * @template TContext - 表达式上下文类型(Variable 或 Expression 的映射)\n * @param context - 包含 Variable 或 Expression 的上下文对象\n * @returns 返回一个函数,该函数接收表达式源码字符串并返回 Expression 对象\n *\n * 类型系统会:\n * 1. 验证表达式中使用的所有标识符都在 context 中定义\n * 2. 根据表达式和操作数类型自动推导返回类型\n *\n * @example\n * ```ts\n * const x = variable(z.number())\n * const y = variable(z.number())\n *\n * // 自动推导返回类型为 number\n * const sum = expr({ x, y })(\"x + y\")\n *\n * // 自动推导返回类型为 boolean\n * const isPositive = expr({ sum })(\"sum > 0\")\n *\n * // 编译错误:z 未在 context 中定义\n * // const invalid = expr({ x, y })(\"x + z\")\n * ```\n */\nexport function expr<TContext extends ExprContext>(\n context: TContext\n): <Source extends string>(source: Source) => Expression<TContext, ExprResult<Source, TContext>> {\n return <Source extends string>(source: Source): Expression<TContext, ExprResult<Source, TContext>> => {\n return {\n _tag: \"expression\",\n context,\n source,\n _type: undefined as unknown,\n } as Expression<TContext, ExprResult<Source, TContext>>;\n };\n}\n","import { z } from \"zod\";\nimport type { Variable } from \"./types\";\n\n/**\n * 创建一个类型化变量\n *\n * @template T - Zod schema 类型\n * @param schema - Zod schema 对象,定义变量的类型和验证规则\n * @returns 返回 Variable 对象,包含 _tag 标记和 schema\n *\n * @example\n * ```ts\n * const x = variable(z.number())\n * const name = variable(z.string())\n * const config = variable(z.object({\n * count: z.number(),\n * enabled: z.boolean()\n * }))\n * ```\n */\nexport function variable<T extends z.ZodType>(schema: T): Variable<T> {\n return {\n _tag: \"variable\",\n schema,\n _type: undefined as unknown as z.infer<T>, // 仅用于类型推导,运行时不存在\n } as Variable<T>;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../src/parser.ts","../src/compile.ts","../src/constant.ts","../src/evaluate.ts","../src/expr.ts","../src/variable.ts"],"sourcesContent":["/**\n * JavaScript 表达式解析器\n * 将表达式字符串解析为 AST,支持常见的运算符和语法\n */\n\n// AST 节点类型\nexport type ASTNode =\n | NumberLiteral\n | StringLiteral\n | BooleanLiteral\n | NullLiteral\n | Identifier\n | BinaryExpr\n | UnaryExpr\n | ConditionalExpr\n | MemberExpr\n | CallExpr\n | ArrayExpr\n | ObjectExpr;\n\nexport interface NumberLiteral {\n type: \"NumberLiteral\";\n value: number;\n raw: string;\n}\n\nexport interface StringLiteral {\n type: \"StringLiteral\";\n value: string;\n quote: \"'\" | '\"' | \"`\";\n}\n\nexport interface BooleanLiteral {\n type: \"BooleanLiteral\";\n value: boolean;\n}\n\nexport interface NullLiteral {\n type: \"NullLiteral\";\n}\n\nexport interface Identifier {\n type: \"Identifier\";\n name: string;\n}\n\nexport interface BinaryExpr {\n type: \"BinaryExpr\";\n operator: string;\n left: ASTNode;\n right: ASTNode;\n}\n\nexport interface UnaryExpr {\n type: \"UnaryExpr\";\n operator: string;\n argument: ASTNode;\n prefix: boolean;\n}\n\nexport interface ConditionalExpr {\n type: \"ConditionalExpr\";\n test: ASTNode;\n consequent: ASTNode;\n alternate: ASTNode;\n}\n\nexport interface MemberExpr {\n type: \"MemberExpr\";\n object: ASTNode;\n property: ASTNode;\n computed: boolean;\n optional: boolean;\n}\n\nexport interface CallExpr {\n type: \"CallExpr\";\n callee: ASTNode;\n arguments: ASTNode[];\n optional: boolean;\n}\n\nexport interface ArrayExpr {\n type: \"ArrayExpr\";\n elements: ASTNode[];\n}\n\nexport interface ObjectExpr {\n type: \"ObjectExpr\";\n properties: ObjectProperty[];\n}\n\nexport interface ObjectProperty {\n key: ASTNode;\n value: ASTNode;\n computed: boolean;\n shorthand: boolean;\n}\n\n// 运算符优先级(从低到高)\nconst PRECEDENCE: Record<string, number> = {\n \"||\": 1,\n \"??\": 1,\n \"&&\": 2,\n \"|\": 3,\n \"^\": 4,\n \"&\": 5,\n \"==\": 6,\n \"!=\": 6,\n \"===\": 6,\n \"!==\": 6,\n \"<\": 7,\n \">\": 7,\n \"<=\": 7,\n \">=\": 7,\n in: 7,\n instanceof: 7,\n \"<<\": 8,\n \">>\": 8,\n \">>>\": 8,\n \"+\": 9,\n \"-\": 9,\n \"*\": 10,\n \"/\": 10,\n \"%\": 10,\n \"**\": 11,\n};\n\n// 右结合运算符\nconst RIGHT_ASSOCIATIVE = new Set([\"**\"]);\n\nclass Parser {\n private pos = 0;\n private source: string;\n\n constructor(source: string) {\n this.source = source;\n }\n\n parse(): ASTNode {\n this.skipWhitespace();\n const node = this.parseExpression();\n this.skipWhitespace();\n if (this.pos < this.source.length) {\n throw new Error(`Unexpected token at position ${this.pos}: ${this.source.slice(this.pos, this.pos + 10)}`);\n }\n return node;\n }\n\n private parseExpression(): ASTNode {\n return this.parseConditional();\n }\n\n private parseConditional(): ASTNode {\n let node = this.parseBinary(0);\n\n this.skipWhitespace();\n if (this.peek() === \"?\") {\n this.advance();\n this.skipWhitespace();\n const consequent = this.parseExpression();\n this.skipWhitespace();\n this.expect(\":\");\n this.skipWhitespace();\n const alternate = this.parseExpression();\n node = {\n type: \"ConditionalExpr\",\n test: node,\n consequent,\n alternate,\n };\n }\n\n return node;\n }\n\n private parseBinary(minPrec: number): ASTNode {\n let left = this.parseUnary();\n\n while (true) {\n this.skipWhitespace();\n const op = this.peekOperator();\n if (!op || PRECEDENCE[op] === undefined || PRECEDENCE[op] < minPrec) {\n break;\n }\n\n this.pos += op.length;\n this.skipWhitespace();\n\n const nextMinPrec = RIGHT_ASSOCIATIVE.has(op) ? PRECEDENCE[op] : PRECEDENCE[op] + 1;\n\n const right = this.parseBinary(nextMinPrec);\n\n left = {\n type: \"BinaryExpr\",\n operator: op,\n left,\n right,\n };\n }\n\n return left;\n }\n\n private parseUnary(): ASTNode {\n this.skipWhitespace();\n const ch = this.peek();\n\n if (ch === \"!\" || ch === \"~\" || ch === \"+\" || ch === \"-\") {\n // 检查是否是一元运算符而非二元运算符\n if (ch === \"+\" || ch === \"-\") {\n this.advance();\n this.skipWhitespace();\n const argument = this.parseUnary();\n return {\n type: \"UnaryExpr\",\n operator: ch,\n argument,\n prefix: true,\n };\n }\n this.advance();\n this.skipWhitespace();\n const argument = this.parseUnary();\n return {\n type: \"UnaryExpr\",\n operator: ch,\n argument,\n prefix: true,\n };\n }\n\n if (this.matchKeyword(\"typeof\")) {\n this.skipWhitespace();\n const argument = this.parseUnary();\n return {\n type: \"UnaryExpr\",\n operator: \"typeof\",\n argument,\n prefix: true,\n };\n }\n\n if (this.matchKeyword(\"void\")) {\n this.skipWhitespace();\n const argument = this.parseUnary();\n return {\n type: \"UnaryExpr\",\n operator: \"void\",\n argument,\n prefix: true,\n };\n }\n\n return this.parsePostfix();\n }\n\n private parsePostfix(): ASTNode {\n let node = this.parsePrimary();\n\n while (true) {\n this.skipWhitespace();\n const ch = this.peek();\n\n if (ch === \".\") {\n this.advance();\n this.skipWhitespace();\n const property = this.parseIdentifier();\n node = {\n type: \"MemberExpr\",\n object: node,\n property,\n computed: false,\n optional: false,\n };\n } else if (ch === \"[\") {\n this.advance();\n this.skipWhitespace();\n const property = this.parseExpression();\n this.skipWhitespace();\n this.expect(\"]\");\n node = {\n type: \"MemberExpr\",\n object: node,\n property,\n computed: true,\n optional: false,\n };\n } else if (ch === \"(\") {\n this.advance();\n const args = this.parseArguments();\n this.expect(\")\");\n node = {\n type: \"CallExpr\",\n callee: node,\n arguments: args,\n optional: false,\n };\n } else if (ch === \"?\" && this.peekAt(1) === \".\") {\n this.advance();\n this.advance();\n this.skipWhitespace();\n if (this.peek() === \"[\") {\n this.advance();\n this.skipWhitespace();\n const property = this.parseExpression();\n this.skipWhitespace();\n this.expect(\"]\");\n node = {\n type: \"MemberExpr\",\n object: node,\n property,\n computed: true,\n optional: true,\n };\n } else if (this.peek() === \"(\") {\n this.advance();\n const args = this.parseArguments();\n this.expect(\")\");\n node = {\n type: \"CallExpr\",\n callee: node,\n arguments: args,\n optional: true,\n };\n } else {\n const property = this.parseIdentifier();\n node = {\n type: \"MemberExpr\",\n object: node,\n property,\n computed: false,\n optional: true,\n };\n }\n } else {\n break;\n }\n }\n\n return node;\n }\n\n private parsePrimary(): ASTNode {\n this.skipWhitespace();\n const ch = this.peek();\n\n // 数字\n if (this.isDigit(ch) || (ch === \".\" && this.isDigit(this.peekAt(1)))) {\n return this.parseNumber();\n }\n\n // 字符串\n if (ch === '\"' || ch === \"'\" || ch === \"`\") {\n return this.parseString();\n }\n\n // 数组\n if (ch === \"[\") {\n return this.parseArray();\n }\n\n // 对象\n if (ch === \"{\") {\n return this.parseObject();\n }\n\n // 括号表达式\n if (ch === \"(\") {\n this.advance();\n this.skipWhitespace();\n const expr = this.parseExpression();\n this.skipWhitespace();\n this.expect(\")\");\n return expr;\n }\n\n // 关键字字面量\n if (this.matchKeyword(\"true\")) {\n return { type: \"BooleanLiteral\", value: true };\n }\n if (this.matchKeyword(\"false\")) {\n return { type: \"BooleanLiteral\", value: false };\n }\n if (this.matchKeyword(\"null\")) {\n return { type: \"NullLiteral\" };\n }\n if (this.matchKeyword(\"undefined\")) {\n return { type: \"Identifier\", name: \"undefined\" };\n }\n\n // 标识符\n if (this.isIdentifierStart(ch)) {\n return this.parseIdentifier();\n }\n\n throw new Error(`Unexpected character at position ${this.pos}: ${ch}`);\n }\n\n private parseNumber(): NumberLiteral {\n const start = this.pos;\n\n // 处理十六进制、八进制、二进制\n if (this.peek() === \"0\") {\n const next = this.peekAt(1)?.toLowerCase();\n if (next === \"x\" || next === \"o\" || next === \"b\") {\n this.advance();\n this.advance();\n while (this.isHexDigit(this.peek())) {\n this.advance();\n }\n const raw = this.source.slice(start, this.pos);\n return {\n type: \"NumberLiteral\",\n value: Number(raw),\n raw,\n };\n }\n }\n\n // 整数部分\n while (this.isDigit(this.peek())) {\n this.advance();\n }\n\n // 小数部分\n if (this.peek() === \".\" && this.isDigit(this.peekAt(1))) {\n this.advance();\n while (this.isDigit(this.peek())) {\n this.advance();\n }\n }\n\n // 指数部分\n if (this.peek()?.toLowerCase() === \"e\") {\n this.advance();\n if (this.peek() === \"+\" || this.peek() === \"-\") {\n this.advance();\n }\n while (this.isDigit(this.peek())) {\n this.advance();\n }\n }\n\n const raw = this.source.slice(start, this.pos);\n return {\n type: \"NumberLiteral\",\n value: Number(raw),\n raw,\n };\n }\n\n private parseString(): StringLiteral {\n const quote = this.peek() as \"'\" | '\"' | \"`\";\n this.advance();\n\n let value = \"\";\n while (this.pos < this.source.length && this.peek() !== quote) {\n if (this.peek() === \"\\\\\") {\n this.advance();\n const escaped = this.peek();\n switch (escaped) {\n case \"n\":\n value += \"\\n\";\n break;\n case \"r\":\n value += \"\\r\";\n break;\n case \"t\":\n value += \"\\t\";\n break;\n case \"\\\\\":\n value += \"\\\\\";\n break;\n case \"'\":\n value += \"'\";\n break;\n case '\"':\n value += '\"';\n break;\n case \"`\":\n value += \"`\";\n break;\n default:\n value += escaped;\n }\n this.advance();\n } else {\n value += this.peek();\n this.advance();\n }\n }\n\n this.expect(quote);\n return { type: \"StringLiteral\", value, quote };\n }\n\n private parseArray(): ArrayExpr {\n this.expect(\"[\");\n const elements: ASTNode[] = [];\n\n this.skipWhitespace();\n while (this.peek() !== \"]\") {\n elements.push(this.parseExpression());\n this.skipWhitespace();\n if (this.peek() === \",\") {\n this.advance();\n this.skipWhitespace();\n } else {\n break;\n }\n }\n\n this.expect(\"]\");\n return { type: \"ArrayExpr\", elements };\n }\n\n private parseObject(): ObjectExpr {\n this.expect(\"{\");\n const properties: ObjectProperty[] = [];\n\n this.skipWhitespace();\n while (this.peek() !== \"}\") {\n const prop = this.parseObjectProperty();\n properties.push(prop);\n this.skipWhitespace();\n if (this.peek() === \",\") {\n this.advance();\n this.skipWhitespace();\n } else {\n break;\n }\n }\n\n this.expect(\"}\");\n return { type: \"ObjectExpr\", properties };\n }\n\n private parseObjectProperty(): ObjectProperty {\n this.skipWhitespace();\n let key: ASTNode;\n let computed = false;\n\n if (this.peek() === \"[\") {\n this.advance();\n this.skipWhitespace();\n key = this.parseExpression();\n this.skipWhitespace();\n this.expect(\"]\");\n computed = true;\n } else if (this.peek() === '\"' || this.peek() === \"'\") {\n key = this.parseString();\n } else {\n key = this.parseIdentifier();\n }\n\n this.skipWhitespace();\n if (this.peek() === \":\") {\n this.advance();\n this.skipWhitespace();\n const value = this.parseExpression();\n return { key, value, computed, shorthand: false };\n }\n\n // Shorthand property\n if (key.type !== \"Identifier\") {\n throw new Error(\"Shorthand property must be an identifier\");\n }\n return { key, value: key, computed: false, shorthand: true };\n }\n\n private parseIdentifier(): Identifier {\n const start = this.pos;\n while (this.isIdentifierPart(this.peek())) {\n this.advance();\n }\n const name = this.source.slice(start, this.pos);\n if (!name) {\n throw new Error(`Expected identifier at position ${this.pos}`);\n }\n return { type: \"Identifier\", name };\n }\n\n private parseArguments(): ASTNode[] {\n const args: ASTNode[] = [];\n this.skipWhitespace();\n while (this.peek() !== \")\") {\n args.push(this.parseExpression());\n this.skipWhitespace();\n if (this.peek() === \",\") {\n this.advance();\n this.skipWhitespace();\n } else {\n break;\n }\n }\n return args;\n }\n\n private peekOperator(): string | null {\n // 按长度排序,先匹配长的运算符\n const ops = [\n \">>>\",\n \"===\",\n \"!==\",\n \"instanceof\",\n \"&&\",\n \"||\",\n \"??\",\n \"==\",\n \"!=\",\n \"<=\",\n \">=\",\n \"<<\",\n \">>\",\n \"**\",\n \"in\",\n \"+\",\n \"-\",\n \"*\",\n \"/\",\n \"%\",\n \"<\",\n \">\",\n \"&\",\n \"|\",\n \"^\",\n ];\n\n for (const op of ops) {\n if (this.source.startsWith(op, this.pos)) {\n // 对于 \"in\" 和 \"instanceof\",确保后面不是标识符字符\n if (op === \"in\" || op === \"instanceof\") {\n const nextChar = this.source[this.pos + op.length];\n if (nextChar && this.isIdentifierPart(nextChar)) {\n continue;\n }\n }\n return op;\n }\n }\n return null;\n }\n\n private matchKeyword(keyword: string): boolean {\n if (this.source.startsWith(keyword, this.pos)) {\n const nextChar = this.source[this.pos + keyword.length];\n if (!nextChar || !this.isIdentifierPart(nextChar)) {\n this.pos += keyword.length;\n return true;\n }\n }\n return false;\n }\n\n private peek(): string {\n return this.source[this.pos] || \"\";\n }\n\n private peekAt(offset: number): string {\n return this.source[this.pos + offset] || \"\";\n }\n\n private advance(): string {\n return this.source[this.pos++] || \"\";\n }\n\n private expect(ch: string): void {\n if (this.peek() !== ch) {\n throw new Error(`Expected '${ch}' at position ${this.pos}, got '${this.peek()}'`);\n }\n this.advance();\n }\n\n private skipWhitespace(): void {\n while (/\\s/.test(this.peek())) {\n this.advance();\n }\n }\n\n private isDigit(ch: string): boolean {\n return /[0-9]/.test(ch);\n }\n\n private isHexDigit(ch: string): boolean {\n return /[0-9a-fA-F]/.test(ch);\n }\n\n private isIdentifierStart(ch: string): boolean {\n return /[a-zA-Z_$]/.test(ch);\n }\n\n private isIdentifierPart(ch: string): boolean {\n return /[a-zA-Z0-9_$]/.test(ch);\n }\n}\n\n/**\n * 解析 JavaScript 表达式为 AST\n */\nexport function parse(source: string): ASTNode {\n return new Parser(source).parse();\n}\n\n/**\n * 从 AST 生成规范化的代码\n */\nexport function generate(node: ASTNode): string {\n switch (node.type) {\n case \"NumberLiteral\":\n return node.raw;\n\n case \"StringLiteral\":\n // 使用双引号,转义必要的字符\n return JSON.stringify(node.value);\n\n case \"BooleanLiteral\":\n return node.value ? \"true\" : \"false\";\n\n case \"NullLiteral\":\n return \"null\";\n\n case \"Identifier\":\n return node.name;\n\n case \"BinaryExpr\": {\n const left = wrapIfNeeded(node.left, node, \"left\");\n const right = wrapIfNeeded(node.right, node, \"right\");\n return `${left}${node.operator}${right}`;\n }\n\n case \"UnaryExpr\":\n if (node.prefix) {\n const arg = wrapIfNeeded(node.argument, node, \"argument\");\n // 对于关键字运算符(typeof, void)需要空格\n if (node.operator === \"typeof\" || node.operator === \"void\") {\n return `${node.operator} ${arg}`;\n }\n return `${node.operator}${arg}`;\n }\n return generate(node.argument) + node.operator;\n\n case \"ConditionalExpr\": {\n const test = generate(node.test);\n const consequent = generate(node.consequent);\n const alternate = generate(node.alternate);\n return `${test}?${consequent}:${alternate}`;\n }\n\n case \"MemberExpr\": {\n const object = wrapIfNeeded(node.object, node, \"object\");\n if (node.computed) {\n const property = generate(node.property);\n return node.optional ? `${object}?.[${property}]` : `${object}[${property}]`;\n }\n const property = generate(node.property);\n return node.optional ? `${object}?.${property}` : `${object}.${property}`;\n }\n\n case \"CallExpr\": {\n const callee = wrapIfNeeded(node.callee, node, \"callee\");\n const args = node.arguments.map(generate).join(\",\");\n return node.optional ? `${callee}?.(${args})` : `${callee}(${args})`;\n }\n\n case \"ArrayExpr\":\n return `[${node.elements.map(generate).join(\",\")}]`;\n\n case \"ObjectExpr\": {\n const props = node.properties.map((prop) => {\n if (prop.shorthand) {\n return generate(prop.key);\n }\n const key = prop.computed ? `[${generate(prop.key)}]` : generate(prop.key);\n return `${key}:${generate(prop.value)}`;\n });\n return `{${props.join(\",\")}}`;\n }\n\n default: {\n const unknownNode = node as { type?: string };\n const nodeType = unknownNode.type ?? \"unknown\";\n throw new Error(`Unknown node type: ${nodeType}`);\n }\n }\n}\n\n/**\n * 判断是否需要括号包裹,并生成代码\n */\nfunction wrapIfNeeded(\n child: ASTNode,\n parent: ASTNode,\n position: \"left\" | \"right\" | \"argument\" | \"object\" | \"callee\"\n): string {\n const code = generate(child);\n\n if (needsParens(child, parent, position)) {\n return `(${code})`;\n }\n return code;\n}\n\n/**\n * 判断子节点是否需要括号\n */\nfunction needsParens(child: ASTNode, parent: ASTNode, position: string): boolean {\n // 条件表达式在二元表达式中需要括号\n if (child.type === \"ConditionalExpr\" && parent.type === \"BinaryExpr\") {\n return true;\n }\n\n // 二元表达式嵌套时根据优先级判断\n if (child.type === \"BinaryExpr\" && parent.type === \"BinaryExpr\") {\n const childPrec = PRECEDENCE[child.operator] || 0;\n const parentPrec = PRECEDENCE[parent.operator] || 0;\n\n if (childPrec < parentPrec) {\n return true;\n }\n\n // 相同优先级时,右侧需要括号(除了右结合运算符)\n if (childPrec === parentPrec && position === \"right\") {\n if (!RIGHT_ASSOCIATIVE.has(parent.operator)) {\n return true;\n }\n }\n }\n\n // 一元表达式作为二元表达式右侧且运算符是 ** 时需要括号\n if (child.type === \"UnaryExpr\" && parent.type === \"BinaryExpr\") {\n if (parent.operator === \"**\" && position === \"left\") {\n return true;\n }\n }\n\n return false;\n}\n\n/**\n * 转换 AST 中的标识符\n */\nexport function transformIdentifiers(node: ASTNode, transform: (name: string) => string): ASTNode {\n switch (node.type) {\n case \"Identifier\":\n return { ...node, name: transform(node.name) };\n\n case \"BinaryExpr\":\n return {\n ...node,\n left: transformIdentifiers(node.left, transform),\n right: transformIdentifiers(node.right, transform),\n };\n\n case \"UnaryExpr\":\n return {\n ...node,\n argument: transformIdentifiers(node.argument, transform),\n };\n\n case \"ConditionalExpr\":\n return {\n ...node,\n test: transformIdentifiers(node.test, transform),\n consequent: transformIdentifiers(node.consequent, transform),\n alternate: transformIdentifiers(node.alternate, transform),\n };\n\n case \"MemberExpr\":\n return {\n ...node,\n object: transformIdentifiers(node.object, transform),\n // 只有 computed 属性需要转换\n property: node.computed ? transformIdentifiers(node.property, transform) : node.property,\n };\n\n case \"CallExpr\":\n return {\n ...node,\n callee: transformIdentifiers(node.callee, transform),\n arguments: node.arguments.map((arg) => transformIdentifiers(arg, transform)),\n };\n\n case \"ArrayExpr\":\n return {\n ...node,\n elements: node.elements.map((el) => transformIdentifiers(el, transform)),\n };\n\n case \"ObjectExpr\":\n return {\n ...node,\n properties: node.properties.map((prop) => ({\n ...prop,\n key: prop.computed ? transformIdentifiers(prop.key, transform) : prop.key,\n value: transformIdentifiers(prop.value, transform),\n })),\n };\n\n default:\n return node;\n }\n}\n\n/**\n * 收集 AST 中所有使用的标识符名称\n */\nexport function collectIdentifiers(node: ASTNode): Set<string> {\n const identifiers = new Set<string>();\n\n function visit(n: ASTNode): void {\n switch (n.type) {\n case \"Identifier\":\n identifiers.add(n.name);\n break;\n\n case \"BinaryExpr\":\n visit(n.left);\n visit(n.right);\n break;\n\n case \"UnaryExpr\":\n visit(n.argument);\n break;\n\n case \"ConditionalExpr\":\n visit(n.test);\n visit(n.consequent);\n visit(n.alternate);\n break;\n\n case \"MemberExpr\":\n visit(n.object);\n if (n.computed) {\n visit(n.property);\n }\n break;\n\n case \"CallExpr\":\n visit(n.callee);\n n.arguments.forEach(visit);\n break;\n\n case \"ArrayExpr\":\n n.elements.forEach(visit);\n break;\n\n case \"ObjectExpr\":\n n.properties.forEach((prop) => {\n if (prop.computed) {\n visit(prop.key);\n }\n visit(prop.value);\n });\n break;\n }\n }\n\n visit(node);\n return identifiers;\n}\n","import { z } from \"zod\";\nimport { collectIdentifiers, generate, parse, type ASTNode } from \"./parser\";\nimport type { CompileContext, CompiledData, Expression, ExprNode, Variable } from \"./types\";\n\n/**\n * 编译选项\n */\nexport interface CompileOptions {\n /**\n * 是否启用内联优化\n * 将只被引用一次的子表达式内联到使用位置\n * @default true\n */\n inline?: boolean;\n}\n\n/**\n * 表达式上下文类型约束\n */\ntype ExpressionContext = Record<string, Variable<z.ZodType> | Expression<Record<string, unknown>, unknown>>;\n\n/**\n * 将表达式树编译为可序列化的 JSON 结构\n *\n * @template TResult - 表达式结果类型\n * @param expression - 根表达式\n * @param variables - 所有使用的变量定义\n * @param options - 编译选项\n * @returns 编译后的数据结构 [变量名列表, 表达式1, 表达式2, ...]\n *\n * @throws 如果检测到循环依赖或未定义的变量引用\n *\n * @example\n * ```ts\n * const x = variable(z.number())\n * const y = variable(z.number())\n * const sum = expr({ x, y })<number>(\"x + y\")\n * const result = expr({ sum })<number>(\"sum * 2\")\n * const compiled = compile(result, { x, y })\n * // => [[\"x\", \"y\"], \"($0+$1)*2\"] // 内联优化后\n * ```\n */\nexport function compile<TResult>(\n expression: Expression<ExpressionContext, TResult>,\n variables: Record<string, Variable<z.ZodType>>,\n options: CompileOptions = {}\n): CompiledData {\n const { inline = true } = options;\n // 创建编译上下文\n const context: CompileContext = {\n variableOrder: [],\n nodeToIndex: new Map(),\n expressions: [],\n };\n\n // 第一步:为每个表达式分配唯一 ID\n const exprIdMap = new WeakMap<Expression<Record<string, unknown>, unknown>, symbol>();\n const getExprId = (expr: Expression<Record<string, unknown>, unknown>): symbol => {\n if (!exprIdMap.has(expr)) {\n exprIdMap.set(expr, Symbol(\"expr\"));\n }\n const id = exprIdMap.get(expr);\n if (id === undefined) {\n throw new Error(\"Expression ID not found\");\n }\n return id;\n };\n\n // 为所有变量创建 node\n const nodeMap = new Map<symbol, ExprNode>();\n const variableNodes = new Map<string, ExprNode>();\n const visited = new Set<symbol>();\n const visiting = new Set<symbol>();\n\n for (const [name, variable] of Object.entries(variables)) {\n const id = Symbol(`var:${name}`);\n const node: ExprNode = {\n id,\n tag: \"variable\",\n schema: variable.schema,\n };\n nodeMap.set(id, node);\n variableNodes.set(name, node);\n }\n\n // 第二步:递归收集所有依赖的节点,并检测循环依赖\n const exprNodes = new Map<symbol, ExprNode>();\n const collectNodes = (expr: Expression<Record<string, unknown>, unknown>): ExprNode => {\n const exprId = getExprId(expr);\n\n if (visited.has(exprId)) {\n return nodeMap.get(exprId)!;\n }\n\n if (visiting.has(exprId)) {\n throw new Error(\"Circular dependency detected in expressions\");\n }\n\n visiting.add(exprId);\n\n const contextNodes: Record<string, ExprNode> = {};\n\n // 收集表达式上下文中的所有节点\n for (const [key, contextItem] of Object.entries(expr.context)) {\n const item = contextItem as Variable<z.ZodType> | Expression<Record<string, unknown>, unknown>;\n if (item._tag === \"variable\") {\n const varNode = variableNodes.get(key);\n if (!varNode) {\n throw new Error(`Undefined variable reference: ${key}`);\n }\n contextNodes[key] = varNode;\n } else if (item._tag === \"expression\") {\n contextNodes[key] = collectNodes(item);\n }\n }\n\n const node: ExprNode = {\n id: exprId,\n tag: \"expression\",\n context: contextNodes,\n source: expr.source,\n };\n\n nodeMap.set(exprId, node);\n exprNodes.set(exprId, node);\n visited.add(exprId);\n visiting.delete(exprId);\n\n return node;\n };\n\n // 收集根表达式的所有节点\n const rootNode = collectNodes(expression);\n\n // 第三步:拓扑排序,确保依赖的节点在前\n const sortedExprNodes: ExprNode[] = [];\n const exprVisited = new Set<symbol>();\n\n const topologicalSort = (node: ExprNode) => {\n if (exprVisited.has(node.id)) {\n return;\n }\n\n exprVisited.add(node.id);\n\n if (node.tag === \"expression\" && node.context) {\n for (const contextNode of Object.values(node.context)) {\n topologicalSort(contextNode);\n }\n }\n\n if (node.tag === \"expression\") {\n sortedExprNodes.push(node);\n }\n };\n\n topologicalSort(rootNode);\n\n // 第四步:分配变量索引 0 ~ N-1\n for (const [name, varNode] of variableNodes.entries()) {\n if (!context.nodeToIndex.has(varNode.id)) {\n context.nodeToIndex.set(varNode.id, context.variableOrder.length);\n context.variableOrder.push(name);\n }\n }\n\n // 第五步:计算每个表达式节点的引用次数\n const refCount = new Map<symbol, number>();\n for (const exprNode of sortedExprNodes) {\n refCount.set(exprNode.id, 0);\n }\n\n for (const exprNode of sortedExprNodes) {\n if (exprNode.context) {\n for (const contextNode of Object.values(exprNode.context)) {\n if (contextNode.tag === \"expression\") {\n refCount.set(contextNode.id, (refCount.get(contextNode.id) ?? 0) + 1);\n }\n }\n }\n }\n\n // 判断哪些表达式可以内联(只被引用一次且不是根节点)\n const canInline = (node: ExprNode): boolean => {\n if (!inline) return false;\n if (node.id === rootNode.id) return false; // 根节点不能内联\n return (refCount.get(node.id) ?? 0) === 1;\n };\n\n // 第六步:为所有不能内联的表达式分配索引\n let exprIndex = 0;\n for (const exprNode of sortedExprNodes) {\n if (!canInline(exprNode)) {\n const index = context.variableOrder.length + exprIndex;\n context.nodeToIndex.set(exprNode.id, index);\n exprIndex++;\n }\n }\n\n // 第七步:为每个表达式生成 AST,并根据内联选项处理\n const nodeAstMap = new Map<symbol, ASTNode>();\n\n // 为变量生成 AST(始终是 $N 标识符)\n for (const [, varNode] of variableNodes.entries()) {\n const index = context.nodeToIndex.get(varNode.id)!;\n nodeAstMap.set(varNode.id, { type: \"Identifier\", name: `$${index}` });\n }\n\n // 为每个表达式生成 AST(按拓扑顺序,确保依赖的节点已处理)\n for (const exprNode of sortedExprNodes) {\n if (!exprNode.context || !exprNode.source) {\n throw new Error(\"Invalid expression node\");\n }\n\n // 检查表达式源码中是否引用了未定义的变量\n const usedVariables = extractVariableNames(exprNode.source);\n for (const varName of usedVariables) {\n if (!(varName in exprNode.context)) {\n throw new Error(\n `Undefined variable reference: ${varName} (available: ${Object.keys(exprNode.context).join(\", \")})`\n );\n }\n }\n\n // 解析表达式为 AST\n const ast = parse(exprNode.source);\n\n // 转换标识符:将上下文中的名称替换为对应的 AST 节点\n const transformed = inlineTransform(ast, (name) => {\n const contextNode = exprNode.context![name];\n if (!contextNode) return null;\n\n if (contextNode.tag === \"variable\") {\n // 变量始终替换为 $N\n return nodeAstMap.get(contextNode.id) ?? null;\n } else {\n // 表达式节点:如果可内联,返回其 AST;否则返回 $N\n if (canInline(contextNode)) {\n return nodeAstMap.get(contextNode.id) ?? null;\n } else {\n const index = context.nodeToIndex.get(contextNode.id)!;\n return { type: \"Identifier\", name: `$${index}` } as ASTNode;\n }\n }\n });\n\n nodeAstMap.set(exprNode.id, transformed);\n }\n\n // 第八步:生成最终表达式列表(只包含不能内联的表达式)\n for (const exprNode of sortedExprNodes) {\n if (!canInline(exprNode)) {\n const ast = nodeAstMap.get(exprNode.id)!;\n context.expressions.push(generate(ast));\n }\n }\n\n // 第九步:组合结果\n const result: CompiledData = [context.variableOrder, ...context.expressions];\n\n return result;\n}\n\n/**\n * 将 AST 中的标识符替换为对应的 AST 节点(用于内联优化)\n *\n * @param node - 要转换的 AST 节点\n * @param getReplacementAst - 根据标识符名称返回替换的 AST 节点,返回 null 表示不替换\n * @returns 转换后的 AST 节点\n */\nfunction inlineTransform(node: ASTNode, getReplacementAst: (name: string) => ASTNode | null): ASTNode {\n switch (node.type) {\n case \"Identifier\": {\n const replacement = getReplacementAst(node.name);\n return replacement ?? node;\n }\n\n case \"BinaryExpr\":\n return {\n ...node,\n left: inlineTransform(node.left, getReplacementAst),\n right: inlineTransform(node.right, getReplacementAst),\n };\n\n case \"UnaryExpr\":\n return {\n ...node,\n argument: inlineTransform(node.argument, getReplacementAst),\n };\n\n case \"ConditionalExpr\":\n return {\n ...node,\n test: inlineTransform(node.test, getReplacementAst),\n consequent: inlineTransform(node.consequent, getReplacementAst),\n alternate: inlineTransform(node.alternate, getReplacementAst),\n };\n\n case \"MemberExpr\":\n return {\n ...node,\n object: inlineTransform(node.object, getReplacementAst),\n property: node.computed ? inlineTransform(node.property, getReplacementAst) : node.property,\n };\n\n case \"CallExpr\":\n return {\n ...node,\n callee: inlineTransform(node.callee, getReplacementAst),\n arguments: node.arguments.map((arg) => inlineTransform(arg, getReplacementAst)),\n };\n\n case \"ArrayExpr\":\n return {\n ...node,\n elements: node.elements.map((el) => inlineTransform(el, getReplacementAst)),\n };\n\n case \"ObjectExpr\":\n return {\n ...node,\n properties: node.properties.map((prop) => ({\n ...prop,\n key: prop.computed ? inlineTransform(prop.key, getReplacementAst) : prop.key,\n value: inlineTransform(prop.value, getReplacementAst),\n })),\n };\n\n default:\n return node;\n }\n}\n\n/**\n * 允许在表达式中直接使用的全局对象\n * 这些对象不需要在上下文中定义\n */\nconst ALLOWED_GLOBALS = new Set([\n // Math 对象及其方法\n \"Math\",\n // JSON 对象\n \"JSON\",\n // 基本类型构造函数\n \"Number\",\n \"String\",\n \"Boolean\",\n \"Array\",\n \"Object\",\n // 其他常用全局对象\n \"Date\",\n \"RegExp\",\n // 全局值\n \"undefined\",\n \"NaN\",\n \"Infinity\",\n // 类型检查\n \"isNaN\",\n \"isFinite\",\n \"parseInt\",\n \"parseFloat\",\n]);\n\n/**\n * 从表达式源码中提取所有使用的变量名\n * 通过 AST 解析实现精确提取\n * 排除允许的全局对象\n *\n * @param source - 表达式源码字符串\n * @returns 使用的变量名列表(去重,不含全局对象)\n *\n * @example\n * ```ts\n * extractVariableNames(\"x + y * Math.PI\")\n * // => [\"x\", \"y\"] // Math 被排除\n * ```\n */\nfunction extractVariableNames(source: string): string[] {\n const ast = parse(source);\n const identifiers = collectIdentifiers(ast);\n // 过滤掉允许的全局对象\n return Array.from(identifiers).filter((name) => !ALLOWED_GLOBALS.has(name));\n}\n","import type { Expression } from \"./types\";\n\n/**\n * JSON 可序列化的值类型\n */\ntype JsonValue = string | number | boolean | null | JsonValue[] | { [key: string]: JsonValue };\n\n/**\n * 创建一个编译期常量表达式\n *\n * 这是 `expr({})(JSON.stringify(value))` 的快速路径,\n * 用于在表达式中嵌入静态值,避免在运行时传入或在多处重复编写。\n *\n * @template T - 常量值类型(必须是 JSON 可序列化的)\n * @param value - 要嵌入的常量值\n * @returns 返回一个 Expression 对象,其结果类型为 T\n *\n * @example\n * ```ts\n * // 创建一个数字常量\n * const PI = constant(3.14159)\n *\n * // 创建一个字符串常量\n * const greeting = constant(\"Hello, World!\")\n *\n * // 创建一个对象常量\n * const config = constant({ maxRetries: 3, timeout: 5000 })\n *\n * // 在表达式中使用常量\n * const radius = variable(z.number())\n * const area = expr({ PI, radius })(\"PI * radius * radius\")\n * ```\n */\nexport function constant<const T extends JsonValue>(value: T): Expression<{}, T> {\n return {\n _tag: \"expression\",\n context: {},\n source: JSON.stringify(value),\n _type: undefined as unknown as T,\n };\n}\n","import type { CompiledData } from \"./types\";\n\n/**\n * 缓存已构造的求值函数,以提升重复执行性能\n */\nconst evaluatorCache = new Map<string, (values: unknown[]) => unknown>();\n\n/**\n * 执行编译后的表达式\n *\n * @template TResult - 表达式结果类型\n * @param data - 编译后的数据结构 [变量名列表, 表达式1, 表达式2, ...]\n * @param values - 变量值映射,按变量名提供值\n * @returns 最后一个表达式的求值结果\n *\n * @throws 如果运行时类型验证失败或表达式执行出错\n *\n * @example\n * ```ts\n * const compiled = [[\"x\", \"y\"], \"$0+$1\", \"$1*2\"]\n * const result = evaluate<number>(compiled, { x: 2, y: 3 })\n * // => 6 (3 * 2)\n * ```\n */\nexport function evaluate<TResult>(data: CompiledData, values: Record<string, unknown>): TResult {\n if (data.length < 1) {\n throw new Error(\"Invalid compiled data: must have at least variable names\");\n }\n\n const [variableNames, ...expressions] = data;\n\n if (!Array.isArray(variableNames)) {\n throw new Error(\"Invalid compiled data: first element must be variable names array\");\n }\n\n // 验证所有必需的变量都已提供\n for (const varName of variableNames) {\n if (typeof varName !== \"string\") {\n throw new Error(\"Invalid compiled data: variable names must be strings\");\n }\n if (!(varName in values)) {\n throw new Error(`Missing required variable: ${varName}`);\n }\n }\n\n // 创建值数组,按变量名顺序填入传入的值\n const valueArray: unknown[] = [];\n for (const varName of variableNames) {\n valueArray.push(values[varName]);\n }\n\n // 获取或构造求值函数\n const cacheKey = JSON.stringify(data);\n let evaluator = evaluatorCache.get(cacheKey);\n\n if (!evaluator) {\n // 构造求值函数\n const functionBody = buildEvaluatorFunctionBody(expressions, variableNames.length);\n // eslint-disable-next-line @typescript-eslint/no-implied-eval\n evaluator = new Function(\"$values\", functionBody) as (values: unknown[]) => unknown;\n evaluatorCache.set(cacheKey, evaluator);\n }\n\n // 执行求值函数\n try {\n const result = evaluator(valueArray);\n return result as TResult;\n } catch (error) {\n throw new Error(`Failed to evaluate expression: ${error instanceof Error ? error.message : String(error)}`);\n }\n}\n\n/**\n * 构造求值函数体\n *\n * @param expressions - 表达式列表\n * @param variableCount - 变量数量\n * @returns 函数体字符串\n *\n * @example\n * ```ts\n * buildEvaluatorFunctionBody([\"$0+$1\", \"$2*2\"], 2)\n * // 返回执行 $0+$1 并存储到 $values[2],然后执行 $2*2 的函数体\n * ```\n */\nfunction buildEvaluatorFunctionBody(expressions: string[], variableCount: number): string {\n if (expressions.length === 0) {\n throw new Error(\"No expressions to evaluate\");\n }\n\n const lines: string[] = [];\n\n // 为了使 $0, $1 等能在函数体中访问,我们需要创建局部变量\n // 或者使用代理访问值数组\n for (let i = 0; i < variableCount; i++) {\n lines.push(`const $${i} = $values[${i}];`);\n }\n\n // 依次对每个表达式求值,结果追加到值数组\n for (let i = 0; i < expressions.length; i++) {\n const exprSource = expressions[i];\n const resultIndex = variableCount + i;\n\n lines.push(`const $${resultIndex} = ${exprSource};`);\n lines.push(`$values[${resultIndex}] = $${resultIndex};`);\n }\n\n // 返回最后一个表达式的结果(即最后一个元素)\n lines.push(`return $values[$values.length - 1];`);\n\n return lines.join(\"\\n\");\n}\n","import { z } from \"zod\";\nimport type { InferExpressionResult, ValidateExpression } from \"./type-parser\";\nimport type { Expression, Variable } from \"./types\";\n\n/**\n * 表达式上下文类型约束\n */\ntype ExprContext = Record<string, Variable<z.ZodType> | Expression<Record<string, unknown>, unknown>>;\n\n/**\n * 表达式错误类型\n */\ntype ExprError<Msg extends string, Details = unknown> = {\n readonly __error: Msg;\n readonly __details: Details;\n};\n\n/**\n * 验证结果处理:如果验证失败返回错误类型,否则返回推导的结果类型\n */\ntype ExprResult<Source extends string, TContext extends ExprContext> =\n ValidateExpression<Source, TContext> extends true\n ? InferExpressionResult<Source, TContext>\n : ValidateExpression<Source, TContext> extends { error: \"undefined_identifiers\"; identifiers: infer Ids }\n ? ExprError<\"Undefined identifiers in expression\", Ids>\n : ExprError<\"Expression validation failed\", ValidateExpression<Source, TContext>>;\n\n/**\n * 创建一个表达式,支持编译时类型检查和返回类型自动推导\n *\n * @template TContext - 表达式上下文类型(Variable 或 Expression 的映射)\n * @param context - 包含 Variable 或 Expression 的上下文对象\n * @returns 返回一个函数,该函数接收表达式源码字符串并返回 Expression 对象\n *\n * 类型系统会:\n * 1. 验证表达式中使用的所有标识符都在 context 中定义\n * 2. 根据表达式和操作数类型自动推导返回类型\n *\n * @example\n * ```ts\n * const x = variable(z.number())\n * const y = variable(z.number())\n *\n * // 自动推导返回类型为 number\n * const sum = expr({ x, y })(\"x + y\")\n *\n * // 自动推导返回类型为 boolean\n * const isPositive = expr({ sum })(\"sum > 0\")\n *\n * // 编译错误:z 未在 context 中定义\n * // const invalid = expr({ x, y })(\"x + z\")\n * ```\n */\nexport function expr<TContext extends ExprContext>(\n context: TContext\n): <Source extends string>(source: Source) => Expression<TContext, ExprResult<Source, TContext>> {\n return <Source extends string>(source: Source): Expression<TContext, ExprResult<Source, TContext>> => {\n return {\n _tag: \"expression\",\n context,\n source,\n _type: undefined as unknown,\n } as Expression<TContext, ExprResult<Source, TContext>>;\n };\n}\n","import { z } from \"zod\";\nimport type { Variable } from \"./types\";\n\n/**\n * 创建一个类型化变量\n *\n * @template T - Zod schema 类型\n * @param schema - Zod schema 对象,定义变量的类型和验证规则\n * @returns 返回 Variable 对象,包含 _tag 标记和 schema\n *\n * @example\n * ```ts\n * const x = variable(z.number())\n * const name = variable(z.string())\n * const config = variable(z.object({\n * count: z.number(),\n * enabled: z.boolean()\n * }))\n * ```\n */\nexport function variable<T extends z.ZodType>(schema: T): Variable<T> {\n return {\n _tag: \"variable\",\n schema,\n _type: undefined as unknown as z.infer<T>, // 仅用于类型推导,运行时不存在\n } as Variable<T>;\n}\n"],"mappings":"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"}
|