From ac9087f7bfd4051b7b5fdd731fd1ed17cf8f2721 Mon Sep 17 00:00:00 2001 From: minjaesong Date: Wed, 9 Dec 2020 17:18:11 +0900 Subject: [PATCH] basic: 'barely working' map function --- assets/basic.js | 53 ++++++++++++++++++++++++++++++++++++----------- assets/facmap.bas | 3 +++ 2 files changed, 44 insertions(+), 12 deletions(-) create mode 100644 assets/facmap.bas diff --git a/assets/basic.js b/assets/basic.js index e30313d..370b54a 100644 --- a/assets/basic.js +++ b/assets/basic.js @@ -226,7 +226,7 @@ let BasicAST = function() { this.astLeaves = []; this.astSeps = []; this.astValue = undefined; - this.astType = "null"; // literal, operator, string, number, array, function, null, defun_args + this.astType = "null"; // literal, operator, string, number, array, function, null, defun_args (! NOT usrdefun !) } let literalTypes = ["string", "num", "bool", "array", "generator"]; /* @@ -235,7 +235,18 @@ let literalTypes = ["string", "num", "bool", "array", "generator"]; BASIC variable table and return the literal value of the BasicVar; undefined will be returned if no such var exists. */ let resolve = function(variable) { - if (variable.troType === "internal_arrindexing_lazy") + // head error checking + if (variable.troType === undefined) { + // primitves types somehow injected from elsewhere (main culprit: MAP) + //throw Error(`BasicIntpError: trying to resolve unknown object '${variable}' with entries ${Object.entries(variable)}`); + + if (isNumable(variable)) return variable*1; + if (Array.isArray(variable)) return variable; + if (typeof variabe == "object") + throw Error(`BasicIntpError: trying to resolve unknown object '${variable}' with entries ${Object.entries(variable)}`); + return variable; + } + else if (variable.troType === "internal_arrindexing_lazy") return eval("variable.troValue.arrFull"+variable.troValue.arrKey); else if (literalTypes.includes(variable.troType) || variable.troType.startsWith("internal_")) return variable.troValue; @@ -246,6 +257,7 @@ let resolve = function(variable) { } else if (variable.troType == "null") return undefined; + // tail error checking else throw Error("BasicIntpError: unknown variable with type "+variable.troType+", with value "+variable.troValue); } @@ -449,7 +461,7 @@ bStatus.getArrayIndexFun = function(lnum, arrayName, array) { }; }; bStatus.getDefunThunk = function(lnum, exprTree) { - let tree = JSON.parse(JSON.stringify(exprTree)); + let tree = JSON.parse(JSON.stringify(exprTree)); // ALWAYS create new tree instance! return function(lnum, args, seps) { let argsMap = []; args.map(it => { @@ -1045,6 +1057,18 @@ if no arg text were given (e.g. "10 NEXT"), args will have zero length }); }, "DATA" : function() { /*DATA must do nothing when encountered; they must be pre-processed*/ }, +"MAP" : function(lnum, args) { + return twoArg(lnum, args, (fn, functor) => { + // TODO test only works with DEFUN'd functions + if (fn.astLeaves === undefined) throw lang.badFunctionCallFormat("Only works with DEFUN'd functions yet"); + if (functor.toArray === undefined && !isArray(functor)) throw lang.syntaxfehler(lnum, functor); + + // generator? + if (functor.toArray) functor = functor.toArray(); + + return functor.map(it => bStatus.getDefunThunk(lnum, fn)(lnum, [it])); + }); +}, "OPTIONDEBUG" : function(lnum, args) { return oneArgNum(lnum, args, (lh) => { if (lh != 0 && lh != 1) throw lang.syntaxfehler(line); @@ -1153,9 +1177,8 @@ bF._opPrc = { "IN":1000 }; bF._opRh = {"^":1,"=":1,"!":1,"IN":1}; -bF._keywords = { - -}; +// these names appear on executeSyntaxTree as "exceptional terms" on parsing (regular function calls are not "exceptional terms") +bF._keywords = {"IF":1,"THEN":1,"ELSE":1,"DEFUN":1}; bF._tokenise = function(lnum, cmd) { var _debugprintStateTransition = false; var k; @@ -1933,10 +1956,16 @@ bF._gotoCmds = {GOTO:1,GOSUB:1,RETURN:1,NEXT:1,END:1,BREAKTO:1}; // put nonzero */ bF._troNOP = function(lnum) { return new SyntaxTreeReturnObj("null", undefined, lnum + 1); } bF._executeSyntaxTree = function(lnum, syntaxTree, recDepth) { - var _debugExec = false; - var recWedge = "> ".repeat(recDepth); + let _debugExec = true; + let _debugPrintCurrentLine = true; + let recWedge = "> ".repeat(recDepth); + + if (_debugExec || _debugPrintCurrentLine) serial.println(recWedge+"@@ EXECUTE @@"); + if (_debugPrintCurrentLine && recDepth == 0) { + serial.println("Syntax Tree in "+lnum+":"); + serial.println(astToString(syntaxTree)); + } - if (_debugExec) serial.println(recWedge+"@@ EXECUTE @@"); if (syntaxTree == undefined) return bF._troNOP(lnum); else if (syntaxTree.astValue == undefined) { // empty meaningless parens @@ -1975,7 +2004,7 @@ bF._executeSyntaxTree = function(lnum, syntaxTree, recDepth) { } } else if ("DEFUN" == funcName) { - if (recDepth > 0) throw lang.badFunctionCallFormat(); // nested DEFUN is TODO and it involves currying and de bruijn indexing + //if (recDepth > 0) throw lang.badFunctionCallFormat(); // nested DEFUN is TODO and it involves currying and de bruijn indexing if (syntaxTree.astLeaves.length !== 1) throw lang.syntaxfehler(lnum, "DEFUN 1"); if (syntaxTree.astLeaves[0].astValue !== "=") throw lang.syntaxfehler(lnum, "DEFUN 2 -- "+syntaxTree.astLeaves[0].astValue); if (syntaxTree.astLeaves[0].astLeaves.length !== 2) throw lang.syntaxfehler(lnum, "DEFUN 3"); @@ -2023,7 +2052,7 @@ bF._executeSyntaxTree = function(lnum, syntaxTree, recDepth) { // finally assign the function to the variable table bStatus.vars[defunName] = new BasicVar(exprTree, "usrdefun"); - return bF._troNOP(lnum); + return new SyntaxTreeReturnObj("function", exprTree, lnum + 1); } else { var args = syntaxTree.astLeaves.map(it => bF._executeSyntaxTree(lnum, it, recDepth + 1)); @@ -2064,7 +2093,7 @@ bF._executeSyntaxTree = function(lnum, syntaxTree, recDepth) { ); } catch (eeeee) { - throw lang.errorinline(lnum, funcName || "undefined", eeeee || "undefined"); + throw lang.errorinline(lnum, (funcName === undefined) ? "undefined" : funcName, (eeeee === undefined) ? "undefined" : eeeee); } } } diff --git a/assets/facmap.bas b/assets/facmap.bas new file mode 100644 index 0000000..854a003 --- /dev/null +++ b/assets/facmap.bas @@ -0,0 +1,3 @@ +10 DEFUN FAC(N)=IF N==0 THEN 1 ELSE N*FAC(N-1) +20 K=MAP FAC, 1 TO 10 +30 PRINT K