1
0
mirror of https://github.com/Baidicoot/rpncalc-v4 synced 2024-12-04 23:39:56 +00:00

added definitions and lambda evaluation

This commit is contained in:
Aidan K. Ewart 2020-05-21 16:31:45 +01:00
parent 32db1c77b0
commit ea57cc4cc5
2 changed files with 28 additions and 16 deletions

22
eval.js
View File

@ -13,6 +13,8 @@ types of object on list:
[{type:"int", val:1},{type:"int", val:1},{type:"builtin", op:"+"}]
[{type:"int", val:1},{type:"int", val:1},{type:"func", args:["a"], body:[{type:"ident", val:"a"},{type:"int", val:1},{type:"builtin", op:"+"}]}]
exported functions:
addDefn - adds a builtin function
doStep - consumes instruction stream, stack, outputs stack
@ -77,16 +79,18 @@ let builtinDefn = {
"snd": makeEval(["pair"], snd)
}
export const addDefn = (name, sign, func) => {
const addDefn = (name, sign, func) => {
builtinDefn[name] = makeEval(sign, func);
}
const makeLambda = (lambda) => (scope, args) => {
const makeLambda = (lambda) => {
return {nargs:lambda.args.length, defn:(scope, args) => {
let newscope = Object.create(scope); // I am so sorry...
for (let i = 0; i < lambda.args.length; i++) {
newscope[lambda.args[i]] = args[i];
}
return execRPN(newscope, lambda.body);
return execRPN(newscope, lambda.body).stack;
}};
}
const makeObj = (elem) => {
@ -103,7 +107,7 @@ const makeObj = (elem) => {
const giveArg = (closure, arg, scope) => {
closure.args.push(arg);
if (closure.args.length === closure.func.nargs) {
return closure.func.defn(scope, closure.args)
return closure.func.defn(scope, closure.args);
} else {
return [closure];
}
@ -114,7 +118,7 @@ const apply = (elem, stack) => {
let out = giveArg(elem, stack.stack.pop(), stack.scope);
applyMany(out, stack);
} else if (elem.type === "ident") {
let id = stack.scope[elem.name];
let id = stack.scope[elem.val];
apply(id, stack);
} else {
stack.stack.push(elem);
@ -136,10 +140,16 @@ const pushS = (elem, stack) => {
}
}
export const doStep = (ins, stack) => {
const defn = (elem, name, stack) => {
stack.scope[name] = makeObj(elem);
}
const doStep = (ins, stack) => {
let instruction = ins.shift();
if (instruction.type === "push") {
pushS(makeObj(instruction.elem), stack);
} else if (instruction.type === "defn") {
defn(ins.defn, ins.ident, stack);
} else {
apply(makeObj(instruction), stack);
}

View File

@ -22,7 +22,7 @@ convert:
]
(for c+p)
[{type:"int",val:1},{type:"int",val:2},{type:"ident",name:"+"},{type:"syntax",val:"'"},{type:"syntax",val:"("},{type:"ident",name:"name"},{type:"syntax",val:";"},{type:"ident",name:"args"},{type:"syntax",val:"->"},{type:"int",val:2},{type:"ident",name:"args"},{type:"ident",name:"+"},{type:"syntax",val:")"}]
[{type:"int",val:1},{type:"int",val:2},{type:"ident",name:"+"},{type:"syntax",val:"'"},{type:"syntax",val:"("},{type:"ident",name:"name"},{type:"ident",name:"args"},{type:"syntax",val:"->"},{type:"int",val:2},{type:"ident",name:"args"},{type:"ident",name:"+"},{type:"syntax",val:")"}]
to:
[
@ -30,7 +30,7 @@ to:
{type:"int", val:2},
{type:"builtin", op:"+"},
{type:"push", elem:
{type:"func", name:"name", args:["args"], body:[
{type:"func", args:["args"], body:[
{type:"int", val:1},
{type:"ident", val:"args"},
{type:"builtin", op:"+"},
@ -190,9 +190,6 @@ const parsePush = (stream) => {
/* takes in stream, outputs parsed item or null - FAILABLE */
const parseLambda = (stream) => {
let name = attempt(parseName)(stream);
if (name.parsed === null) {
name.parsed = "";
}
let args = many(parseIdent)(name.stream);
let syn = parseSyntax("->")(args.stream);
if (syn.parsed === null) {
@ -202,7 +199,12 @@ const parseLambda = (stream) => {
if (body.parsed === null) {
throw 'no lambda body found!';
}
return {parsed:{type:"func", name:name.parsed, args:args.parsed.map(x => x.val), body:body.parsed}, stream:body.stream};
let func = {type:"func", args:args.parsed.map(x => x.val), body:body.parsed};
if (name.parsed === null) {
return {parsed:func, stream:body.stream};
} else {
return {type:"defn", ident:name.parsed, defn:func};
}
}
/* takes in stream, outputs parsed item or null */