mirror of
https://github.com/curioustorvald/tsvm.git
synced 2026-06-12 23:54:04 +09:00
basic: 'barely working' map function
This commit is contained in:
@@ -226,7 +226,7 @@ let BasicAST = function() {
|
|||||||
this.astLeaves = [];
|
this.astLeaves = [];
|
||||||
this.astSeps = [];
|
this.astSeps = [];
|
||||||
this.astValue = undefined;
|
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"];
|
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.
|
BASIC variable table and return the literal value of the BasicVar; undefined will be returned if no such var exists.
|
||||||
*/
|
*/
|
||||||
let resolve = function(variable) {
|
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);
|
return eval("variable.troValue.arrFull"+variable.troValue.arrKey);
|
||||||
else if (literalTypes.includes(variable.troType) || variable.troType.startsWith("internal_"))
|
else if (literalTypes.includes(variable.troType) || variable.troType.startsWith("internal_"))
|
||||||
return variable.troValue;
|
return variable.troValue;
|
||||||
@@ -246,6 +257,7 @@ let resolve = function(variable) {
|
|||||||
}
|
}
|
||||||
else if (variable.troType == "null")
|
else if (variable.troType == "null")
|
||||||
return undefined;
|
return undefined;
|
||||||
|
// tail error checking
|
||||||
else
|
else
|
||||||
throw Error("BasicIntpError: unknown variable with type "+variable.troType+", with value "+variable.troValue);
|
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) {
|
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) {
|
return function(lnum, args, seps) {
|
||||||
let argsMap = [];
|
let argsMap = [];
|
||||||
args.map(it => {
|
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*/ },
|
"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) {
|
"OPTIONDEBUG" : function(lnum, args) {
|
||||||
return oneArgNum(lnum, args, (lh) => {
|
return oneArgNum(lnum, args, (lh) => {
|
||||||
if (lh != 0 && lh != 1) throw lang.syntaxfehler(line);
|
if (lh != 0 && lh != 1) throw lang.syntaxfehler(line);
|
||||||
@@ -1153,9 +1177,8 @@ bF._opPrc = {
|
|||||||
"IN":1000
|
"IN":1000
|
||||||
};
|
};
|
||||||
bF._opRh = {"^":1,"=":1,"!":1,"IN":1};
|
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) {
|
bF._tokenise = function(lnum, cmd) {
|
||||||
var _debugprintStateTransition = false;
|
var _debugprintStateTransition = false;
|
||||||
var k;
|
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._troNOP = function(lnum) { return new SyntaxTreeReturnObj("null", undefined, lnum + 1); }
|
||||||
bF._executeSyntaxTree = function(lnum, syntaxTree, recDepth) {
|
bF._executeSyntaxTree = function(lnum, syntaxTree, recDepth) {
|
||||||
var _debugExec = false;
|
let _debugExec = true;
|
||||||
var recWedge = "> ".repeat(recDepth);
|
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);
|
if (syntaxTree == undefined) return bF._troNOP(lnum);
|
||||||
else if (syntaxTree.astValue == undefined) { // empty meaningless parens
|
else if (syntaxTree.astValue == undefined) { // empty meaningless parens
|
||||||
@@ -1975,7 +2004,7 @@ bF._executeSyntaxTree = function(lnum, syntaxTree, recDepth) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if ("DEFUN" == funcName) {
|
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.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].astValue !== "=") throw lang.syntaxfehler(lnum, "DEFUN 2 -- "+syntaxTree.astLeaves[0].astValue);
|
||||||
if (syntaxTree.astLeaves[0].astLeaves.length !== 2) throw lang.syntaxfehler(lnum, "DEFUN 3");
|
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
|
// finally assign the function to the variable table
|
||||||
bStatus.vars[defunName] = new BasicVar(exprTree, "usrdefun");
|
bStatus.vars[defunName] = new BasicVar(exprTree, "usrdefun");
|
||||||
|
|
||||||
return bF._troNOP(lnum);
|
return new SyntaxTreeReturnObj("function", exprTree, lnum + 1);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
var args = syntaxTree.astLeaves.map(it => bF._executeSyntaxTree(lnum, it, recDepth + 1));
|
var args = syntaxTree.astLeaves.map(it => bF._executeSyntaxTree(lnum, it, recDepth + 1));
|
||||||
@@ -2064,7 +2093,7 @@ bF._executeSyntaxTree = function(lnum, syntaxTree, recDepth) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
catch (eeeee) {
|
catch (eeeee) {
|
||||||
throw lang.errorinline(lnum, funcName || "undefined", eeeee || "undefined");
|
throw lang.errorinline(lnum, (funcName === undefined) ? "undefined" : funcName, (eeeee === undefined) ? "undefined" : eeeee);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
3
assets/facmap.bas
Normal file
3
assets/facmap.bas
Normal file
@@ -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
|
||||||
Reference in New Issue
Block a user