From 0d90e7b9e150cfc9069b050482982cc1d658382b Mon Sep 17 00:00:00 2001 From: "Aidan K. Ewart" Date: Sat, 30 May 2020 21:20:04 +0100 Subject: [PATCH] refactored builtins to own file --- builtin.mjs | 77 +++++++++++++++++++++++++++++++++++++++++++++++++++++ eval.mjs | 60 +++++------------------------------------ index.html | 2 +- main.js | 22 ++------------- parse.mjs | 1 - 5 files changed, 87 insertions(+), 75 deletions(-) create mode 100644 builtin.mjs diff --git a/builtin.mjs b/builtin.mjs new file mode 100644 index 0000000..d9812ac --- /dev/null +++ b/builtin.mjs @@ -0,0 +1,77 @@ +import {addDefn, addRPNASTDefn} from './eval.mjs'; +import {parseExprs} from './parse.mjs'; +import {tokenize} from './token.mjs'; + +const addRPNDefn = (name, def) => { + let toks = tokenize(def); + if (!toks) { + throw 'could not load builtin' + } + let ast = parseExprs(toks); + if (!ast.parsed) { + throw 'could not load builtin' + } + addRPNASTDefn(name, ast.parsed[0]); +} + +const add = (_, args) => { + return [{type:"int", val:args[0] + args[1]}]; +} + +const sub = (_, args) => { + return [{type:"int", val:args[1] - args[0]}]; +} + +const div = (_, args) => { + return [{type:"int", val:args[1] / args[0]}]; +} + +const mult = (_, args) => { + return [{type:"int", val:args[0] * args[1]}]; +} + +const pow = (_, args) => { + return [{type:"int", val:Math.pow(args[1], args[0])}]; +} + +const root = (_, args) => { + return [{type:"int", val:Math.sqrt(args[0])}]; +} + +const type = (_, args) => { + return [{type:"string", val:args[0].type}]; +} + +const pair = (_, args) => { + return [{type:"pair", val:{fst:args[0], snd:args[1]}}]; +} + +const fst = (_, args) => [args[0].fst]; + +const snd = (_, args) => [args[0].snd]; + +const eq = (_, args) => { + if (args[0].type === args[1].type && args[0].val === args[1].val) { + return [{type:"ident", val:"true"}]; + } else { + return [{type:"ident", val:"false"}]; + } +} + +addDefn("+", ["int", "int"], add); +addDefn("-", ["int", "int"], sub); +addDefn("/", ["int", "int"], div); +addDefn("*", ["int", "int"], mult); +addDefn("^", ["int", "int"], pow); +addDefn("sqrt", ["int"], root); +addDefn("==", 2, eq); +addDefn("typeof", 1, type); +addDefn("pair", 2, pair); +addDefn("fst", ["pair"], fst); +addDefn("snd", ["pair"], snd); +addRPNDefn("true", "(a b -> a)"); +addRPNDefn("false", "(a b -> b)"); +addRPNDefn("stop", "(-> \"stop)"); +addRPNDefn("id", "(a -> a)"); +addRPNDefn("inv", "(x -> 1 x /)"); +addRPNDefn("fold", "(fn acc x -> '(-> x acc fn 'fn fold) '(-> acc) 'x \"stop ==)"); \ No newline at end of file diff --git a/eval.mjs b/eval.mjs index 9075094..6f6bf57 100644 --- a/eval.mjs +++ b/eval.mjs @@ -40,64 +40,18 @@ const makeEval = (sign, defnarg) => { } } -const add = (_, args) => { - return [{type:"int", val:args[0] + args[1]}]; +const makeBuiltin = (sign, defnarg) => { + return {type:"closure", args:[], func:makeEval(sign, defnarg)}; } -const sub = (_, args) => { - return [{type:"int", val:args[1] - args[0]}]; -} - -const div = (_, args) => { - return [{type:"int", val:args[1] / args[0]}]; -} - -const mult = (_, args) => { - return [{type:"int", val:args[0] * args[1]}]; -} - -const type = (_, args) => { - return [{type:"string", val:args[0].type}]; -} - -const pair = (_, args) => { - return [{type:"pair", val:{fst:args[0], snd:args[1]}}]; -} - -const fst = (_, args) => [args[0].fst]; - -const snd = (_, args) => [args[0].snd]; - -const eq = (_, args) => { - if (args[0].type === args[1].type && args[0].val === args[1].val) { - return [{type:"ident", val:"true"}]; - } else { - return [{type:"ident", val:"false"}]; - } -} - -const stop = (a, b) => { - return [{type:"string", val:"stop"}]; -} - -let builtinDefn = { - "+": makeEval(["int", "int"], add), - "-": makeEval(["int", "int"], sub), - "/": makeEval(["int", "int"], div), - "*": makeEval(["int", "int"], mult), - "==": makeEval(2, eq), - "typeof": makeEval(1, type), - "pair": makeEval(2, pair), - "fst": makeEval(["pair"], fst), - "snd": makeEval(["pair"], snd) -} +let builtinDefn = {}; export const addDefn = (name, sign, func) => { - builtinDefn[name] = makeEval(sign, func); + builtinDefn[name] = makeBuiltin(sign, func); } export const addRPNASTDefn = (name, ast) => { - builtinDefn[name] = makeLambda(ast); + builtinDefn[name] = makeObj(ast); } const makeLambda = (lambda) => { @@ -137,7 +91,7 @@ const lookupScope = (name, scope) => { } n = builtinDefn[name]; if (n) { - return {type:"closure", args:[], func:n}; + return cloneElem(n); } else { throw "var " + n + " not in scope" } @@ -189,7 +143,7 @@ const defn = (elem, name, stack) => { stack.scope[name] = makeObj(elem); } -export const doStep = (ins, stack) => { +const doStep = (ins, stack) => { let instruction = ins.shift(); if (instruction.type === "push") { pushS(makeObj(instruction.elem), stack); diff --git a/index.html b/index.html index 71caa88..0fad777 100644 --- a/index.html +++ b/index.html @@ -8,7 +8,7 @@ Example Programs:
1 + 2 (v partial -> 'v partial) Evaluate a partial

- +

diff --git a/main.js b/main.js index c72a7ac..9c00d5e 100644 --- a/main.js +++ b/main.js @@ -1,6 +1,7 @@ -import {execRPN, addRPNASTDefn} from './eval.mjs'; +import {execRPN} from './eval.mjs'; import {parseExprs} from './parse.mjs'; import {tokenize} from './token.mjs'; +import './builtin.mjs'; const inbox = document.getElementById("inbox") const outbox = document.getElementById("outbox") @@ -29,25 +30,6 @@ const prettyprint = (out) => { return str; } -const addRPNBuiltin = (name, def) => { - let toks = tokenize(def); - if (!toks) { - throw 'could not load builtin' - } - let ast = parseExprs(toks); - if (!ast.parsed) { - throw 'could not load builtin' - } - console.log(ast); - addRPNASTDefn(name, ast.parsed[0]); -} - -addRPNBuiltin("true", "(a b -> a)"); -addRPNBuiltin("false", "(a b -> b)"); -addRPNBuiltin("stop", "(-> \"stop)"); -addRPNBuiltin("id", "(a -> a)"); -addRPNBuiltin("fold", "(fn acc x -> '(-> x acc fn 'fn fold) '(-> acc) 'x \"stop ==)"); - submit.onclick = (event) => { const input = inbox.value; let toks = tokenize(input); diff --git a/parse.mjs b/parse.mjs index 97b9196..9029456 100644 --- a/parse.mjs +++ b/parse.mjs @@ -48,7 +48,6 @@ const attempt = (parser) => (stream) => { let out = parser(stream); return out; } catch(err) { - console.log(err); return {parsed:null,stream:streamclone}; } }