bugfixes etc

This commit is contained in:
Aidan K. Ewart 2020-05-30 22:39:45 +01:00
parent 0d90e7b9e1
commit 1c6bee1947
4 changed files with 30 additions and 10 deletions

View File

@ -1,4 +1,4 @@
import {addDefn, addRPNASTDefn} from './eval.mjs';
import {addDefn, addRPNASTDefn, makeFn} from './eval.mjs';
import {parseExprs} from './parse.mjs';
import {tokenize} from './token.mjs';
@ -43,7 +43,7 @@ const type = (_, args) => {
}
const pair = (_, args) => {
return [{type:"pair", val:{fst:args[0], snd:args[1]}}];
return [{type:"pair", val:{fst:args[1], snd:args[0]}}];
}
const fst = (_, args) => [args[0].fst];
@ -58,6 +58,18 @@ const eq = (_, args) => {
}
}
const arr = (_, args) => {
return [makeFn(args[0], (_, args) => {return [{type:"array", val:args}]})];
}
const index = (_, args) => {
return [args[1][args[0]]];
}
const len = (_, args) => {
return [{type:"int", val:args[0].length}];
}
addDefn("+", ["int", "int"], add);
addDefn("-", ["int", "int"], sub);
addDefn("/", ["int", "int"], div);
@ -69,9 +81,14 @@ addDefn("typeof", 1, type);
addDefn("pair", 2, pair);
addDefn("fst", ["pair"], fst);
addDefn("snd", ["pair"], snd);
addDefn("arr", ["int"], arr);
addDefn("!!", ["int", "array"], index);
addDefn("len", ["array"], len);
addRPNDefn("unit", "(-> 0 arr)");
addRPNDefn("mono", "(-> 1 arr)");
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 ==)");
addRPNDefn("fold", "(x acc fn -> '(-> acc) '(-> x acc fn 'fn fold) 'x \"stop ==)");

View File

@ -40,14 +40,14 @@ const makeEval = (sign, defnarg) => {
}
}
const makeBuiltin = (sign, defnarg) => {
export const makeFn = (sign, defnarg) => {
return {type:"closure", args:[], func:makeEval(sign, defnarg)};
}
let builtinDefn = {};
export const addDefn = (name, sign, func) => {
builtinDefn[name] = makeBuiltin(sign, func);
builtinDefn[name] = makeFn(sign, func);
}
export const addRPNASTDefn = (name, ast) => {
@ -56,9 +56,9 @@ export const addRPNASTDefn = (name, ast) => {
const makeLambda = (lambda) => {
return {nargs:lambda.args.length, defn:(scope, args) => {
let newscope = Object.create(scope); // I am so sorry...
let newscope = Object.create(scope);
for (let i = 0; i < lambda.args.length; i++) {
newscope[lambda.args[i]] = args[i];
newscope[lambda.args[i]] = args[args.length-1-i];
}
return execRPN(newscope, lambda.body).stack;
}};

View File

@ -16,6 +16,8 @@ const show = (elem) => {
return "(args: {" + prettyprint(elem.args) + "} of " + elem.func.nargs + ")"
} else if (elem.type === "string") {
return elem.val
} else if (elem.type === "array") {
return "[" + prettyprint(elem.val) + "]"
}
}
@ -47,5 +49,6 @@ submit.onclick = (event) => {
outbox.innerHTML = "failed to execute";
return;
}
console.log(out);
outbox.innerHTML = prettyprint(out.stack);
}

View File

@ -36,11 +36,11 @@ export function tokenize(input) {
}
}
*/
let splitInput = inputWithAddedSpaces.split(" ");
let splitInput = inputWithAddedSpaces.split(" ").filter((s) => s !== "");
let output = [];
for(i = 0; i<splitInput.length; i++){
if(/^\d+$/.test(splitInput[i])){ // didn't need /[0-9]/, but that would be helpful to stop numbers from being in identifiers, but the ability to call a function "function_add_1" is easier to type than "function_add_one"
output.push({type: "int", val:parseInt(splitInput[i])}); // also, /[a-zA-Z]/ wasn't necessary as my code uses anything that isn't `;() or ->
if(!isNaN(splitInput[i])){ // didn't need /[0-9]/, but that would be helpful to stop numbers from being in identifiers, but the ability to call a function "function_add_1" is easier to type than "function_add_one"
output.push({type: "int", val:Number(splitInput[i])}); // also, /[a-zA-Z]/ wasn't necessary as my code uses anything that isn't `;() or ->
} else if(syntax.test(splitInput[i]) || splitInput[i] === "->"){// needs a || as -> wasn't included in the syntax regexp. it wasn't in because -> uses two characters so i wanted to have separate code for it. (also because regexps are confusing)
output.push({type: "syntax", val:splitInput[i]});
} else if(splitInput[i] != '') { // if syntax is next to the end of the string or other bits of syntax the two spaces are in inputWithAddedSpaces so .split returns '' as one element. this makes sure that it is not read as an identifier