basic:FOR works with limited function of NEXT

This commit is contained in:
minjaesong
2020-11-18 11:46:24 +09:00
parent 89c4f9ac6f
commit 8568a721ff
2 changed files with 37 additions and 18 deletions

View File

@@ -33,6 +33,9 @@ lang.badFunctionCallFormat = "Illegal function call";
lang.unmatchedBrackets = "Unmatched brackets"; lang.unmatchedBrackets = "Unmatched brackets";
lang.missingOperand = "Missing operand"; lang.missingOperand = "Missing operand";
lang.noSuchFile = "No such file"; lang.noSuchFile = "No such file";
lang.nextWithoutFor = function(line) {
return "NEXT without FOR in "+line;
};
lang.syntaxfehler = function(line, reason) { lang.syntaxfehler = function(line, reason) {
return "Syntax error" + ((line !== undefined) ? (" in "+line) : "") + ((reason !== undefined) ? (": "+reason) : ""); return "Syntax error" + ((line !== undefined) ? (" in "+line) : "") + ((reason !== undefined) ? (": "+reason) : "");
}; };
@@ -195,7 +198,7 @@ let BasicAST = function() {
this.toString = function() { this.toString = function() {
var sb = ""; var sb = "";
var marker = ("literal" == this.astTpe) ? i : var marker = ("literal" == this.astType) ? "i" :
("operator" == this.astType) ? String.fromCharCode(177) : ("operator" == this.astType) ? String.fromCharCode(177) :
("string" == this.astType) ? String.fromCharCode(182) : ("string" == this.astType) ? String.fromCharCode(182) :
("number" == this.astType) ? String.fromCharCode(162) : ("number" == this.astType) ? String.fromCharCode(162) :
@@ -444,12 +447,13 @@ if no arg text were given (e.g. "10 NEXT"), args will have zero length
if (seps[llll - 1] == ",") print("\t"); if (seps[llll - 1] == ",") print("\t");
} }
var rsvArg = resolve(args[llll]) || ""; var rsvArg = resolve(args[llll]);
if (rsvArg === undefined && args[llll].troType != "null") throw lang.refError(lnum, args[llll].troValue);
if (args[llll].troType == "number") if (args[llll].troType == "number")
print(" "+rsvArg+" "); print(" "+rsvArg+" ");
else else
print(rsvArg); print(rsvArg || "");
} }
} }
@@ -556,24 +560,39 @@ if no arg text were given (e.g. "10 NEXT"), args will have zero length
if (!Array.isArray(asgnObj.asgnValue)) throw lang.illegalType(lnum, asgnObj); if (!Array.isArray(asgnObj.asgnValue)) throw lang.illegalType(lnum, asgnObj);
let varname = asgnObj.asgnVarName let varname = asgnObj.asgnVarName
// check for variable name collision (e.g. 10 K=1TO10 \n 20 FOR I=K should work but 20 FOR K=K must not)
if (bStatus.vars[varname] !== undefined) throw lang.dupDef(lnum, varname);
// assign new variable // assign new variable
bStatus.vars[varname] = asgnObj.asgnValue // the var itself will have head of the array, and the head itself will be removed from the array
bStatus.vars[varname] = new BasicVar(asgnObj.asgnValue[0], JStoBASICtype(asgnObj.asgnValue.shift()));
// stores entire array (sans head) into temporary storage
bStatus.vars["for var "+varname] = new BasicVar(asgnObj.asgnValue, "array");
// put the varname to forstack // put the varname to forstack
bStatus.forLnums[asgnObj.asgnVarName] = lnum; bStatus.forLnums[asgnObj.asgnVarName] = lnum;
bStatus.push(asgnObj.asgnVarName); bStatus.forStack.push(asgnObj.asgnVarName);
}, },
"NEXT" : function(lnum, args) { "NEXT" : function(lnum, args) {
// if no args were given // if no args were given
if (args.length == 0 || (args.length == 1 && args.troType == "null")) { //if (args.length == 0 || (args.length == 1 && args.troType == "null")) {
// go to most recent FOR // go to most recent FOR
let forVarname = bStatus.forStack.pop();
return; //serial.println(lnum+" NEXT > forVarname = "+forVarname);
} if (forVarname === undefined) {
throw lang.nextWithoutFor(lnum);
}
bStatus.vars[forVarname].bvLiteral = bStatus.vars["for var "+forVarname].bvLiteral.shift();
let rsvArgs = args.map(function(it) { resolve(it) }); if ((bStatus.vars[forVarname].bvLiteral !== undefined)) {
// feed popped value back, we're not done yet
bStatus.forStack.push(forVarname);
return bStatus.forLnums[forVarname] + 1;
}
else {
bStatus.vars[forVarname] === undefined; // unregister the variable
return lnum + 1;
}
//}
//let rsvArgs = args.map(function(it) { resolve(it) });
} }
}; };
@@ -1092,7 +1111,7 @@ for input "DEFUN sinc(x) = sin(x) / x"
"quote" == state || "number" == state || "bool" == state || "literal" == state; "quote" == state || "number" == state || "bool" == state || "literal" == state;
} }
var _debugSyntaxAnalysis = true; var _debugSyntaxAnalysis = false;
if (_debugSyntaxAnalysis) serial.println("@@ SYNTAX ANALYSIS @@"); if (_debugSyntaxAnalysis) serial.println("@@ SYNTAX ANALYSIS @@");
@@ -1379,7 +1398,7 @@ let SyntaxTreeReturnObj = function(type, value, nextLine) {
this.troValue = value; this.troValue = value;
this.troNextLine = nextLine; this.troNextLine = nextLine;
} }
bF._gotoCmds = { GOTO:1, GOSUB:1 }; // put nonzero (truthy) value here bF._gotoCmds = { GOTO:1, GOSUB:1, NEXT:1 }; // put nonzero (truthy) value here
/** /**
* @param lnum line number of BASIC * @param lnum line number of BASIC
* @param syntaxTree BasicAST * @param syntaxTree BasicAST
@@ -1431,7 +1450,7 @@ bF._executeSyntaxTree = function(lnum, syntaxTree, recDepth) {
if (_debugExec) { if (_debugExec) {
serial.println(recWedge+"fn call name: "+funcName); serial.println(recWedge+"fn call name: "+funcName);
serial.println(recWedge+"fn call args: "+(args.map(function(it) { return it.astType+" "+it.astValue; })).join(", ")); serial.println(recWedge+"fn call args: "+(args.map(function(it) { return it.troType+" "+it.troValue; })).join(", "));
} }
// func not in builtins (e.g. array access, user-defined function defuns) // func not in builtins (e.g. array access, user-defined function defuns)
@@ -1481,7 +1500,7 @@ bF._executeSyntaxTree = function(lnum, syntaxTree, recDepth) {
}; };
// @returns: line number for the next command, normally (lnum + 1); if GOTO or GOSUB was met, returns its line number // @returns: line number for the next command, normally (lnum + 1); if GOTO or GOSUB was met, returns its line number
bF._interpretLine = function(lnum, cmd) { bF._interpretLine = function(lnum, cmd) {
var _debugprintHighestLevel = true; var _debugprintHighestLevel = false;
// TOKENISE // TOKENISE
var tokenisedObject = bF._tokenise(lnum, cmd); var tokenisedObject = bF._tokenise(lnum, cmd);

View File

@@ -30,8 +30,8 @@ public class AppLoader {
// val vm = VM(64.kB(), TheRealWorld(), arrayOf(GenericBios)) // val vm = VM(64.kB(), TheRealWorld(), arrayOf(GenericBios))
VM vm = new VM(64 << 10, new TheRealWorld(), new VMProgramRom[]{GenericBios.INSTANCE}); //VM vm = new VM(64 << 10, new TheRealWorld(), new VMProgramRom[]{GenericBios.INSTANCE});
//VM vm = new VM(64 << 10, new TheRealWorld(), new VMProgramRom[]{BasicBios.INSTANCE, BasicRom.INSTANCE}); VM vm = new VM(64 << 10, new TheRealWorld(), new VMProgramRom[]{BasicBios.INSTANCE, BasicRom.INSTANCE});
new LwjglApplication(new VMGUI(vm, appConfig), appConfig); new LwjglApplication(new VMGUI(vm, appConfig), appConfig);
} }