diff options
Diffstat (limited to 'src/lib/core')
| -rw-r--r-- | src/lib/core/eval.ts | 70 |
1 files changed, 56 insertions, 14 deletions
diff --git a/src/lib/core/eval.ts b/src/lib/core/eval.ts index 74801bf..65e4788 100644 --- a/src/lib/core/eval.ts +++ b/src/lib/core/eval.ts @@ -26,25 +26,67 @@ export type UnarrayIfOnlyHead<T extends readonly any[]> = T extends [ ? Head : T; -export type BUILTIN_ARR<Args extends readonly ASTNode[]> = { - [Idx in keyof Args]: Args[Idx] extends ASTNode ? Evaluate<Args[Idx]> : never; -}; +export type NumberToArray< + Number extends number, + Carry extends readonly any[] = [] +> = Number extends Carry["length"] + ? Carry + : NumberToArray<Number, [...Carry, any]>; -export type BUILTIN_ToString<Args extends readonly ASTNode[]> = ToStringInner< +export type NumbersToArray< + Numbers extends readonly number[], + Carry extends readonly any[] = [] +> = Numbers extends [ + infer Head extends number, + ...infer Tail extends readonly number[] +] + ? NumbersToArray<Tail, [...Carry, ...NumberToArray<Head>]> + : Carry; + +export type AddNumbers<Numbers extends readonly number[]> = + NumbersToArray<Numbers> extends infer T extends readonly any[] + ? T["length"] + : never; + +export type AddStrings< + Strings extends readonly string[], + Carry extends string = "" +> = Strings extends [infer Head extends string, ...infer Tail extends string[]] + ? AddStrings<Tail, `${Carry}${Head}`> + : Carry; + +export type BUILTIN_Arr<Args extends readonly any[]> = Args; + +export type BUILTIN_ToString<Args extends readonly any[]> = ToStringInner< UnarrayIfOnlyHead<{ - [Idx in keyof Args]: Args[Idx] extends ASTNode - ? ToStringInner<Evaluate<Args[Idx]>> - : never; + [Idx in keyof Args]: ToStringInner<Args[Idx]>; }> >; -// export type BUILTIN_Print<Args extends readonly ASTNode[]> + +export type BUILTIN_Add<Args extends readonly any[]> = + Args extends readonly string[] + ? AddStrings<Args> + : Args extends readonly number[] + ? AddNumbers<Args> + : FnError<`Cannot add operands ${ToStringInner<Args>}`>; export type SENTINEL_NO_BUILTIN = "__NO_BUILTIN__"; -export type MapBuiltins<Node extends ASTNode> = Node["name"] extends "tostring" - ? BUILTIN_ToString<Node["children"]> - : Node["name"] extends "arr" - ? BUILTIN_ARR<Node["children"]> - : SENTINEL_NO_BUILTIN; +export type MapBuiltins<Node extends ASTNode> = + Node["children"] extends infer Children extends readonly ASTNode[] + ? { + [Idx in keyof Children]: Children[Idx] extends ASTNode + ? Evaluate<Children[Idx]> + : never; + } extends infer Args extends readonly any[] + ? Node["name"] extends "tostring" + ? BUILTIN_ToString<Args> + : Node["name"] extends "arr" + ? BUILTIN_Arr<Args> + : Node["name"] extends "add" + ? BUILTIN_Add<Args> + : SENTINEL_NO_BUILTIN + : never + : never; export type EvalError<T extends string> = `Eval error: ${T}`; @@ -54,7 +96,7 @@ export type Evaluate<Node extends ASTNode> = Node["type"] extends NodeType.INT ? MapBuiltins<Node> : EvalError<`Unhandled node type ${Node["type"]}`>; -const input = `5, arr(5000)` as const; +const input = `add(1,2,3,4,5)` as const; const lex_result = null as unknown as Lex<typeof input>; const parse_result = null as unknown as Parse<typeof lex_result>; const eval_result = null as unknown as Evaluate<typeof parse_result>; |
