summaryrefslogtreecommitdiff
path: root/src/js-lang
diff options
context:
space:
mode:
authorKai Stevenson <kai@kaistevenson.com>2025-11-03 23:41:31 -0800
committerKai Stevenson <kai@kaistevenson.com>2025-11-03 23:41:31 -0800
commit8b610f2bcfc223333254ce9679730c42dce6d26e (patch)
treeac1eab726395523f8725bda3d040e22214cba409 /src/js-lang
parent56040f3ff85e77311f0c864a89afd63fcf1bdb50 (diff)
add createFn
Diffstat (limited to 'src/js-lang')
-rw-r--r--src/js-lang/builtin/builtin.ts39
-rw-r--r--src/js-lang/builtin/index.ts2
-rw-r--r--src/js-lang/builtin/sbuiltin.ts46
-rw-r--r--src/js-lang/core/eval.ts83
-rw-r--r--src/js-lang/core/index.ts3
-rw-r--r--src/js-lang/core/lexer.ts46
-rw-r--r--src/js-lang/core/parser.ts132
-rw-r--r--src/js-lang/index.ts1
8 files changed, 0 insertions, 352 deletions
diff --git a/src/js-lang/builtin/builtin.ts b/src/js-lang/builtin/builtin.ts
deleted file mode 100644
index dde91b6..0000000
--- a/src/js-lang/builtin/builtin.ts
+++ /dev/null
@@ -1,39 +0,0 @@
-type BUILTIN = (args: any[]) => any;
-
-export const V_BUILTIN_Arr: BUILTIN = (args) => args;
-
-// FIXME actually implement this properly
-export const V_BUILTIN_ToString: BUILTIN = (args) =>
- args.length === 1 ? JSON.stringify(args[0]) : JSON.stringify(args);
-
-export const V_BUILTIN_Add: BUILTIN = (args) => {
- if (args.every((arg) => ["string", "number"].includes(typeof arg))) {
- return args.reduce(
- (acc, cur) => acc + cur,
- typeof args[0] === "string" ? "" : 0
- );
- }
-
- throw new Error(`Cannot add operands ${JSON.stringify(args, undefined, 2)}`);
-};
-
-export const V_BUILTIN_Mul: BUILTIN = (args) => {
- if (args.every((arg) => typeof arg === "number") && args.length === 2) {
- return args.reduce((acc, cur) => acc * cur, 1);
- }
-
- throw new Error(
- `Can only multiply [number, number], but got ${JSON.stringify(
- args,
- undefined,
- 2
- )}`
- );
-};
-
-export const nameToBUILTIN: Record<string, BUILTIN> = {
- arr: V_BUILTIN_Arr,
- tostring: V_BUILTIN_ToString,
- add: V_BUILTIN_Add,
- mul: V_BUILTIN_Mul,
-};
diff --git a/src/js-lang/builtin/index.ts b/src/js-lang/builtin/index.ts
deleted file mode 100644
index 00e77f7..0000000
--- a/src/js-lang/builtin/index.ts
+++ /dev/null
@@ -1,2 +0,0 @@
-export * from "./builtin";
-export * from "./sbuiltin";
diff --git a/src/js-lang/builtin/sbuiltin.ts b/src/js-lang/builtin/sbuiltin.ts
deleted file mode 100644
index 44c969d..0000000
--- a/src/js-lang/builtin/sbuiltin.ts
+++ /dev/null
@@ -1,46 +0,0 @@
-import { callFn, getEvaluatedChildren } from "../core/eval";
-import { ASTNode, FnPrim, StackFrame } from "../../ts-lang";
-
-type SBUILTIN = (node: ASTNode, frame: StackFrame) => any;
-
-export const V_SBUITLIN_Call: SBUILTIN = (node, frame) => {
- const children = getEvaluatedChildren(node, frame);
- const fn = children[0] as FnPrim | undefined;
-
- if (!fn?.fn) {
- throw new Error(
- `Invalid params for function call: ${JSON.stringify(
- children,
- undefined,
- 2
- )}`
- );
- }
-
- return callFn(fn, children.slice(1), frame);
-};
-
-export const V_SBUILTIN_Map: SBUILTIN = (node, frame) => {
- const children = getEvaluatedChildren(node, frame);
- const fn = children[1] as FnPrim | undefined;
-
- if (!fn?.fn) {
- throw new Error(
- `Invalid params for map: ${JSON.stringify(children, undefined, 2)}`
- );
- }
-
- const values = children[0];
-
- if (!Array.isArray(values)) {
- // add to ts
- throw new Error(`Can't map non-array value: ${values}`);
- }
-
- return values.map((v, i) => callFn(fn, [v, i], frame));
-};
-
-export const nameToSBUILTIN: Record<string, SBUILTIN> = {
- call: V_SBUITLIN_Call,
- map: V_SBUILTIN_Map,
-};
diff --git a/src/js-lang/core/eval.ts b/src/js-lang/core/eval.ts
deleted file mode 100644
index 60a2059..0000000
--- a/src/js-lang/core/eval.ts
+++ /dev/null
@@ -1,83 +0,0 @@
-import {
- ASTNode,
- StackFrame,
- Evaluate,
- EmptyStackFrame,
- NodeType,
- FnPrim,
- SENTINEL_NO_BUILTIN,
-} from "../../ts-lang";
-import { nameToBUILTIN, nameToSBUILTIN, V_SBUILTIN_Map } from "../builtin";
-
-const V_SENTINEL_NO_BUILTIN: SENTINEL_NO_BUILTIN = "__NO_BUILTIN__";
-
-const mapBuiltins = (node: ASTNode, frame: StackFrame): any => {
- if (node.name in nameToSBUILTIN) {
- return nameToSBUILTIN[node.name](node, frame);
- }
- if (node.name in nameToBUILTIN) {
- return nameToBUILTIN[node.name](getEvaluatedChildren(node, frame));
- }
-
- return V_SENTINEL_NO_BUILTIN;
-};
-
-const findInStack = (frame: StackFrame, nameToFind: string) => {
- if (nameToFind in frame.bindings) {
- return frame.bindings[nameToFind];
- }
-
- if (!frame.parent) {
- throw new Error(`Can't find name ${nameToFind} on the stack`);
- }
-
- return findInStack(frame.parent, nameToFind);
-};
-
-const handleFn = (node: ASTNode): FnPrim => {
- const fn = node.children[node.children.length - 1];
-
- return {
- args: node.children.slice(0, node.children.length - 1),
- fn,
- };
-};
-
-const mapZip = (args: ASTNode[], values: any[]) =>
- Object.fromEntries(args.map(({ name }, i) => [name, values[i]]));
-
-export const callFn = (fn: FnPrim, values: any[], frame: StackFrame) =>
- _evaluate(fn.fn, {
- bindings: mapZip(fn.args as ASTNode[], values),
- parent: frame,
- });
-
-export const _evaluate = (node: ASTNode, frame: StackFrame) => {
- if (node.type === NodeType.INT) {
- return node.value;
- }
-
- if (node.type === NodeType.EXT) {
- if (node.name === "fn") {
- return handleFn(node);
- }
-
- const builtinResult = mapBuiltins(node, frame);
- if (builtinResult !== V_SENTINEL_NO_BUILTIN) {
- return builtinResult;
- }
-
- return findInStack(frame, node.name);
- }
-
- throw new Error(`Unhandled node type ${node.type}`);
-};
-
-export const getEvaluatedChildren = (node: ASTNode, frame: StackFrame) =>
- node.children.map((child) => _evaluate(child, frame));
-
-export const emptyStackFrame: EmptyStackFrame = { bindings: {}, parent: null };
-
-export const evaluate = <const Node extends ASTNode>(
- node: Node
-): Evaluate<Node> => _evaluate(node, emptyStackFrame) as Evaluate<Node>;
diff --git a/src/js-lang/core/index.ts b/src/js-lang/core/index.ts
deleted file mode 100644
index 22ac2d2..0000000
--- a/src/js-lang/core/index.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-export * from "./eval";
-export * from "./parser";
-export * from "./lexer";
diff --git a/src/js-lang/core/lexer.ts b/src/js-lang/core/lexer.ts
deleted file mode 100644
index 95e0e19..0000000
--- a/src/js-lang/core/lexer.ts
+++ /dev/null
@@ -1,46 +0,0 @@
-import { TokenType, Lex, Token } from "../../ts-lang";
-
-const WHITESPACE_TOKENS = [
- TokenType.SPACE,
- TokenType.COMMA,
- TokenType.SEMICOLON,
-] as string[];
-
-export const lex = <const Raw extends string>(raw: Raw): Lex<Raw> => {
- let _raw: string = raw;
- let nameCollection = "";
- const tokens: Token[] = [];
-
- while (_raw) {
- const head = _raw[0];
- _raw = _raw.slice(1);
-
- const processNameCollection = () => {
- if (nameCollection) {
- tokens.push({ type: TokenType.NAME, name: nameCollection });
- nameCollection = "";
- }
- };
-
- if (WHITESPACE_TOKENS.includes(head)) {
- processNameCollection();
- continue;
- }
-
- if (head === TokenType.OPEN_PAREN) {
- processNameCollection();
- tokens.push({ type: TokenType.OPEN_PAREN, name: "" });
- continue;
- }
-
- if (head === TokenType.CLOSE_PAREN) {
- processNameCollection();
- tokens.push({ type: TokenType.CLOSE_PAREN, name: "" });
- continue;
- }
-
- nameCollection += head;
- }
-
- return tokens as Lex<Raw>;
-};
diff --git a/src/js-lang/core/parser.ts b/src/js-lang/core/parser.ts
deleted file mode 100644
index f193d6a..0000000
--- a/src/js-lang/core/parser.ts
+++ /dev/null
@@ -1,132 +0,0 @@
-import { Token, Parse, TokenType, ASTNode, NodeType } from "../../ts-lang";
-import { lex } from "./lexer";
-
-const resolveNodeFromToken = (token: Token): ASTNode => {
- // FIXME not correct
- if (!isNaN(Number(token.name))) {
- return {
- type: NodeType.INT,
- name: "",
- value: Number(token.name),
- children: [],
- };
- }
- if (token.name[0] === '"' && token.name[token.name.length - 1] === '"') {
- return {
- type: NodeType.INT,
- name: "",
- value: token.name.slice(1, token.name.length - 1),
- children: [],
- };
- }
- return {
- type: NodeType.EXT,
- name: token.name,
- value: null,
- children: [],
- };
-};
-
-const _parse = ({
- remainingTokens,
- lastToken,
- stack,
-}: {
- remainingTokens: Token[];
- lastToken: Token | null;
- stack: ASTNode[];
-}): ASTNode | null => {
- const head = remainingTokens.shift();
- if (!head) {
- if (lastToken) {
- (stack[stack.length - 1].children as ASTNode[]).push(
- resolveNodeFromToken(lastToken)
- );
-
- return _parse({
- lastToken: null,
- remainingTokens: [],
- stack,
- });
- }
-
- return stack[0] ?? null;
- }
-
- if (lastToken) {
- if (head.type === TokenType.NAME) {
- (stack[stack.length - 1].children as ASTNode[]).push(
- resolveNodeFromToken(lastToken)
- );
- return _parse({
- lastToken: head,
- remainingTokens,
- stack,
- });
- }
-
- if (head.type === TokenType.CLOSE_PAREN) {
- const top = stack.pop()!;
- (top.children as ASTNode[]).push(resolveNodeFromToken(lastToken));
- (stack[stack.length - 1].children as ASTNode[]).push(top);
-
- return _parse({
- lastToken: null,
- remainingTokens,
- stack,
- });
- }
-
- if (head.type === TokenType.OPEN_PAREN) {
- return _parse({
- lastToken: null,
- remainingTokens,
- stack: [...stack, resolveNodeFromToken(lastToken)],
- });
- }
-
- throw new Error(
- `${JSON.stringify({
- lastToken,
- remainingTokens,
- stack,
- })} Was not expecting ${head.type}`
- );
- }
-
- if (head.type === TokenType.NAME) {
- return _parse({
- lastToken: head,
- remainingTokens,
- stack,
- });
- }
-
- if (head.type === TokenType.CLOSE_PAREN) {
- const top = stack.pop()!;
- (stack[stack.length - 1].children as ASTNode[]).push(top);
-
- return _parse({
- lastToken: null,
- remainingTokens,
- stack,
- });
- }
-
- throw new Error(
- `${JSON.stringify({
- lastToken,
- remainingTokens,
- stack,
- })} Expected nextToken to be a name or close paren at ${head.type}`
- );
-};
-
-export const parse = <const Raw extends readonly Token[]>(
- raw: Raw
-): Parse<Raw> =>
- _parse({
- remainingTokens: raw as unknown as Token[],
- lastToken: null,
- stack: [{ type: NodeType.EXT, name: "arr", value: null, children: [] }],
- }) as Parse<Raw>;
diff --git a/src/js-lang/index.ts b/src/js-lang/index.ts
deleted file mode 100644
index 8d119de..0000000
--- a/src/js-lang/index.ts
+++ /dev/null
@@ -1 +0,0 @@
-export * from "./core";