summaryrefslogtreecommitdiff
path: root/src/lib/core
diff options
context:
space:
mode:
authorKai Stevenson <kai@kaistevenson.com>2025-11-02 17:53:39 -0800
committerKai Stevenson <kai@kaistevenson.com>2025-11-02 17:53:39 -0800
commit2353379f9842ccccefb52b4c530bfb113b5d4a18 (patch)
tree36aec42d1cb4e805eef1c675ffa38e52739339e5 /src/lib/core
parent5e0bcc45037b6cf9345ed3e290bd8a4b2c387587 (diff)
add "add"
Diffstat (limited to 'src/lib/core')
-rw-r--r--src/lib/core/eval.ts70
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>;