mirror of
https://github.com/Baidicoot/rpncalc-v4
synced 2025-01-09 07:10:29 +00:00
debugged eval.js, added exports
This commit is contained in:
parent
6742bede47
commit
32db1c77b0
47
eval.js
47
eval.js
@ -11,26 +11,28 @@ types of object on list:
|
|||||||
{type:"closure", args:[], func:{}}
|
{type:"closure", args:[], func:{}}
|
||||||
{type:"pair", val:{fst:{}, snd:{}}}
|
{type:"pair", val:{fst:{}, snd:{}}}
|
||||||
|
|
||||||
|
[{type:"int", val:1},{type:"int", val:1},{type:"builtin", op:"+"}]
|
||||||
|
|
||||||
exported functions:
|
exported functions:
|
||||||
makeEval - lifts a function to a function definition object
|
addDefn - adds a builtin function
|
||||||
doStep - consumes instruction stream, stack, outputs stack
|
doStep - consumes instruction stream, stack, outputs stack
|
||||||
execRPN - consumes scope, instruction stream, outputs stack
|
execRPN - consumes scope, instruction stream, outputs stack
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const makeEval = (sign, defn) => {
|
const makeEval = (sign, defnarg) => {
|
||||||
if (typeof sign === "number") {
|
if (typeof sign === "number") {
|
||||||
return {nargs:sign, defn:defn};
|
return {nargs:sign, defn:defnarg};
|
||||||
} else {
|
} else {
|
||||||
return {nargs:sign.length, defn:(scope, args) => {
|
return {nargs:sign.length, defn:(scope, args) => {
|
||||||
let stripped = [];
|
let stripped = [];
|
||||||
for (let i = 0; i < sign.length; i++) {
|
for (let i = 0; i < sign.length; i++) {
|
||||||
if (args[i].type === sign[i].type) {
|
if (args[i].type === sign[i]) {
|
||||||
stripped.push(args[i].val);
|
stripped.push(args[i].val);
|
||||||
} else {
|
} else {
|
||||||
throw 'typeerror'
|
throw 'typeerror'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
defn(scope, stripped);
|
return defnarg(scope, stripped);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -64,7 +66,7 @@ const fst = (args) => [args[0].fst];
|
|||||||
|
|
||||||
const snd = (args) => [args[0].snd];
|
const snd = (args) => [args[0].snd];
|
||||||
|
|
||||||
const builtinDefn = {
|
let builtinDefn = {
|
||||||
"+": makeEval(["int", "int"], add),
|
"+": makeEval(["int", "int"], add),
|
||||||
"-": makeEval(["int", "int"], sub),
|
"-": makeEval(["int", "int"], sub),
|
||||||
"/": makeEval(["int", "int"], div),
|
"/": makeEval(["int", "int"], div),
|
||||||
@ -75,6 +77,10 @@ const builtinDefn = {
|
|||||||
"snd": makeEval(["pair"], snd)
|
"snd": makeEval(["pair"], snd)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const addDefn = (name, sign, func) => {
|
||||||
|
builtinDefn[name] = makeEval(sign, func);
|
||||||
|
}
|
||||||
|
|
||||||
const makeLambda = (lambda) => (scope, args) => {
|
const makeLambda = (lambda) => (scope, args) => {
|
||||||
let newscope = Object.create(scope); // I am so sorry...
|
let newscope = Object.create(scope); // I am so sorry...
|
||||||
for (let i = 0; i < lambda.args.length; i++) {
|
for (let i = 0; i < lambda.args.length; i++) {
|
||||||
@ -97,7 +103,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.defn(scope, closure.args)
|
return closure.func.defn(scope, closure.args)
|
||||||
} else {
|
} else {
|
||||||
return [closure];
|
return [closure];
|
||||||
}
|
}
|
||||||
@ -105,10 +111,13 @@ const giveArg = (closure, arg, scope) => {
|
|||||||
|
|
||||||
const apply = (elem, stack) => {
|
const apply = (elem, stack) => {
|
||||||
if (elem.type === "closure") {
|
if (elem.type === "closure") {
|
||||||
let out = elem.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") {
|
||||||
|
let id = stack.scope[elem.name];
|
||||||
|
apply(id, stack);
|
||||||
} else {
|
} else {
|
||||||
stack.push(elem);
|
stack.stack.push(elem);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -118,9 +127,22 @@ const applyMany = (outstack, stack) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const doStep = (ins, stack) => {
|
const pushS = (elem, stack) => {
|
||||||
let elem = makeObj(ins.pop());
|
if (elem.type === "ident") {
|
||||||
apply(elem, stack);
|
let id = stack.scope[elem.name];
|
||||||
|
stack.stack.push(id);
|
||||||
|
} else {
|
||||||
|
stack.stack.push(elem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const doStep = (ins, stack) => {
|
||||||
|
let instruction = ins.shift();
|
||||||
|
if (instruction.type === "push") {
|
||||||
|
pushS(makeObj(instruction.elem), stack);
|
||||||
|
} else {
|
||||||
|
apply(makeObj(instruction), stack);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const execRPN = (scope, ins) => {
|
const execRPN = (scope, ins) => {
|
||||||
@ -128,4 +150,5 @@ const execRPN = (scope, ins) => {
|
|||||||
while (ins.length > 0) {
|
while (ins.length > 0) {
|
||||||
doStep(ins, stack);
|
doStep(ins, stack);
|
||||||
}
|
}
|
||||||
|
return stack;
|
||||||
}
|
}
|
4
parse.js
4
parse.js
@ -38,7 +38,7 @@ to:
|
|||||||
]
|
]
|
||||||
|
|
||||||
EXPORTED FUNCTIONS:
|
EXPORTED FUNCTIONS:
|
||||||
parse - takes in tokenstream, outputs AST
|
parseExprs - takes in tokenstream, outputs AST
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const builtin = [
|
const builtin = [
|
||||||
@ -209,4 +209,4 @@ const parseLambda = (stream) => {
|
|||||||
const parseExpr = or(parseBuiltin, or(parseIdent, or(parseInteger, or(parsePush, attempt(parens(parseLambda))))));
|
const parseExpr = or(parseBuiltin, or(parseIdent, or(parseInteger, or(parsePush, attempt(parens(parseLambda))))));
|
||||||
|
|
||||||
/* takes in stream, outputs parsed items */
|
/* takes in stream, outputs parsed items */
|
||||||
const parseExprs = many(parseExpr);
|
export const parseExprs = many(parseExpr);
|
Loading…
Reference in New Issue
Block a user