mirror of
https://github.com/Baidicoot/rpncalc-v4
synced 2024-06-14 09:16:51 +00:00
added definitions and lambda evaluation
This commit is contained in:
parent
32db1c77b0
commit
ea57cc4cc5
30
eval.js
30
eval.js
|
@ -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:"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:
|
exported functions:
|
||||||
addDefn - adds a builtin function
|
addDefn - adds a builtin function
|
||||||
doStep - consumes instruction stream, stack, outputs stack
|
doStep - consumes instruction stream, stack, outputs stack
|
||||||
|
@ -77,16 +79,18 @@ let builtinDefn = {
|
||||||
"snd": makeEval(["pair"], snd)
|
"snd": makeEval(["pair"], snd)
|
||||||
}
|
}
|
||||||
|
|
||||||
export const addDefn = (name, sign, func) => {
|
const addDefn = (name, sign, func) => {
|
||||||
builtinDefn[name] = makeEval(sign, func);
|
builtinDefn[name] = makeEval(sign, func);
|
||||||
}
|
}
|
||||||
|
|
||||||
const makeLambda = (lambda) => (scope, args) => {
|
const makeLambda = (lambda) => {
|
||||||
let newscope = Object.create(scope); // I am so sorry...
|
return {nargs:lambda.args.length, defn:(scope, args) => {
|
||||||
for (let i = 0; i < lambda.args.length; i++) {
|
let newscope = Object.create(scope); // I am so sorry...
|
||||||
newscope[lambda.args[i]] = args[i];
|
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) => {
|
const makeObj = (elem) => {
|
||||||
|
@ -103,7 +107,7 @@ const makeObj = (elem) => {
|
||||||
const giveArg = (closure, arg, scope) => {
|
const giveArg = (closure, arg, scope) => {
|
||||||
closure.args.push(arg);
|
closure.args.push(arg);
|
||||||
if (closure.args.length === closure.func.nargs) {
|
if (closure.args.length === closure.func.nargs) {
|
||||||
return closure.func.defn(scope, closure.args)
|
return closure.func.defn(scope, closure.args);
|
||||||
} else {
|
} else {
|
||||||
return [closure];
|
return [closure];
|
||||||
}
|
}
|
||||||
|
@ -114,7 +118,7 @@ const apply = (elem, stack) => {
|
||||||
let out = giveArg(elem, stack.stack.pop(), stack.scope);
|
let out = giveArg(elem, stack.stack.pop(), stack.scope);
|
||||||
applyMany(out, stack);
|
applyMany(out, stack);
|
||||||
} else if (elem.type === "ident") {
|
} else if (elem.type === "ident") {
|
||||||
let id = stack.scope[elem.name];
|
let id = stack.scope[elem.val];
|
||||||
apply(id, stack);
|
apply(id, stack);
|
||||||
} else {
|
} else {
|
||||||
stack.stack.push(elem);
|
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();
|
let instruction = ins.shift();
|
||||||
if (instruction.type === "push") {
|
if (instruction.type === "push") {
|
||||||
pushS(makeObj(instruction.elem), stack);
|
pushS(makeObj(instruction.elem), stack);
|
||||||
|
} else if (instruction.type === "defn") {
|
||||||
|
defn(ins.defn, ins.ident, stack);
|
||||||
} else {
|
} else {
|
||||||
apply(makeObj(instruction), stack);
|
apply(makeObj(instruction), stack);
|
||||||
}
|
}
|
||||||
|
|
14
parse.js
14
parse.js
|
@ -22,7 +22,7 @@ convert:
|
||||||
]
|
]
|
||||||
|
|
||||||
(for c+p)
|
(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:
|
to:
|
||||||
[
|
[
|
||||||
|
@ -30,7 +30,7 @@ to:
|
||||||
{type:"int", val:2},
|
{type:"int", val:2},
|
||||||
{type:"builtin", op:"+"},
|
{type:"builtin", op:"+"},
|
||||||
{type:"push", elem:
|
{type:"push", elem:
|
||||||
{type:"func", name:"name", args:["args"], body:[
|
{type:"func", args:["args"], body:[
|
||||||
{type:"int", val:1},
|
{type:"int", val:1},
|
||||||
{type:"ident", val:"args"},
|
{type:"ident", val:"args"},
|
||||||
{type:"builtin", op:"+"},
|
{type:"builtin", op:"+"},
|
||||||
|
@ -190,9 +190,6 @@ const parsePush = (stream) => {
|
||||||
/* takes in stream, outputs parsed item or null - FAILABLE */
|
/* takes in stream, outputs parsed item or null - FAILABLE */
|
||||||
const parseLambda = (stream) => {
|
const parseLambda = (stream) => {
|
||||||
let name = attempt(parseName)(stream);
|
let name = attempt(parseName)(stream);
|
||||||
if (name.parsed === null) {
|
|
||||||
name.parsed = "";
|
|
||||||
}
|
|
||||||
let args = many(parseIdent)(name.stream);
|
let args = many(parseIdent)(name.stream);
|
||||||
let syn = parseSyntax("->")(args.stream);
|
let syn = parseSyntax("->")(args.stream);
|
||||||
if (syn.parsed === null) {
|
if (syn.parsed === null) {
|
||||||
|
@ -202,7 +199,12 @@ const parseLambda = (stream) => {
|
||||||
if (body.parsed === null) {
|
if (body.parsed === null) {
|
||||||
throw 'no lambda body found!';
|
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 */
|
/* takes in stream, outputs parsed item or null */
|
||||||
|
|
Loading…
Reference in New Issue
Block a user