basic: for loop init

This commit is contained in:
minjaesong
2020-11-15 22:52:29 +09:00
parent a077247825
commit 88ad549553

View File

@@ -52,6 +52,9 @@ lang.parserError = function(line, errorobj) {
lang.outOfMem = function(line) { lang.outOfMem = function(line) {
return "Out of memory in " + line; return "Out of memory in " + line;
}; };
lang.dupDef = function(line, varname) {
return "Duplicate definition"+((varname !== undefined) ? (" on "+varname) : "")+" in "+line;
};
Object.freeze(lang); Object.freeze(lang);
let fs = {}; let fs = {};
@@ -223,7 +226,7 @@ let literalTypes = ["string", "number", "bool", "array"];
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 (literalTypes.includes(variable.troType)) if (literalTypes.includes(variable.troType) || variable.troType.startsWith("internal_"))
return variable.troValue; return variable.troValue;
else if (variable.troType == "literal") { else if (variable.troType == "literal") {
var basicVar = bStatus.vars[parseSigil(variable.troValue).sgName]; var basicVar = bStatus.vars[parseSigil(variable.troValue).sgName];
@@ -237,60 +240,60 @@ let resolve = function(variable) {
let oneArg = function(lnum, args, action) { let oneArg = function(lnum, args, action) {
if (args.length != 1) throw lang.syntaxfehler(lnum, args.length + " arguments were given"); if (args.length != 1) throw lang.syntaxfehler(lnum, args.length + " arguments were given");
var rsvArg0 = resolve(args[0]); var rsvArg0 = resolve(args[0]);
if (rsvArg0 === undefined) throw lang.refError(lnum, rsvArg0.value); if (rsvArg0 === undefined) throw lang.refError(lnum, rsvArg0);
return action(rsvArg0); return action(rsvArg0);
} }
let oneArgNum = function(lnum, args, action) { let oneArgNum = function(lnum, args, action) {
if (args.length != 1) throw lang.syntaxfehler(lnum, args.length + " arguments were given"); if (args.length != 1) throw lang.syntaxfehler(lnum, args.length + " arguments were given");
var rsvArg0 = resolve(args[0]); var rsvArg0 = resolve(args[0]);
if (rsvArg0 === undefined) throw lang.refError(lnum, rsvArg0.value); if (rsvArg0 === undefined) throw lang.refError(lnum, rsvArg0);
if (isNaN(rsvArg0)) throw lang.illegalType(lnum, rsvArg0.value); if (isNaN(rsvArg0)) throw lang.illegalType(lnum, rsvArg0);
return action(rsvArg0); return action(rsvArg0);
} }
let twoArg = function(lnum, args, action) { let twoArg = function(lnum, args, action) {
if (args.length != 2) throw lang.syntaxfehler(lnum, args.length + " arguments were given"); if (args.length != 2) throw lang.syntaxfehler(lnum, args.length + " arguments were given");
var rsvArg0 = resolve(args[0]); var rsvArg0 = resolve(args[0]);
if (rsvArg0 === undefined) throw lang.refError(lnum, rsvArg0.value); if (rsvArg0 === undefined) throw lang.refError(lnum, rsvArg0);
var rsvArg1 = resolve(args[1]); var rsvArg1 = resolve(args[1]);
if (rsvArg1 === undefined) throw lang.refError(lnum, rsvArg1.value); if (rsvArg1 === undefined) throw lang.refError(lnum, rsvArg1);
return action(rsvArg0, rsvArg1); return action(rsvArg0, rsvArg1);
} }
let twoArgNum = function(lnum, args, action) { let twoArgNum = function(lnum, args, action) {
if (args.length != 2) throw lang.syntaxfehler(lnum, args.length + " arguments were given"); if (args.length != 2) throw lang.syntaxfehler(lnum, args.length + " arguments were given");
var rsvArg0 = resolve(args[0]); var rsvArg0 = resolve(args[0]);
if (rsvArg0 === undefined) throw lang.refError(lnum, rsvArg0.value); if (rsvArg0 === undefined) throw lang.refError(lnum, rsvArg0);
if (isNaN(rsvArg0)) throw lang.illegalType(lnum, rsvArg0.value); if (isNaN(rsvArg0)) throw lang.illegalType(lnum, rsvArg0);
var rsvArg1 = resolve(args[1]); var rsvArg1 = resolve(args[1]);
if (rsvArg1 === undefined) throw lang.refError(lnum, rsvArg1.value); if (rsvArg1 === undefined) throw lang.refError(lnum, rsvArg1);
if (isNaN(rsvArg1)) throw lang.illegalType(lnum, rsvArg1.value); if (isNaN(rsvArg1)) throw lang.illegalType(lnum, rsvArg1);
return action(rsvArg0, rsvArg1); return action(rsvArg0, rsvArg1);
} }
let threeArg = function(lnum, args, action) { let threeArg = function(lnum, args, action) {
if (args.length != 3) throw lang.syntaxfehler(lnum, args.length + " arguments were given"); if (args.length != 3) throw lang.syntaxfehler(lnum, args.length + " arguments were given");
var rsvArg0 = resolve(args[0]); var rsvArg0 = resolve(args[0]);
if (rsvArg0 === undefined) throw lang.refError(lnum, rsvArg0.value); if (rsvArg0 === undefined) throw lang.refError(lnum, rsvArg0);
var rsvArg1 = resolve(args[1]); var rsvArg1 = resolve(args[1]);
if (rsvArg1 === undefined) throw lang.refError(lnum, rsvArg1.value); if (rsvArg1 === undefined) throw lang.refError(lnum, rsvArg1);
var rsvArg2 = resolve(args[2]); var rsvArg2 = resolve(args[2]);
if (rsvArg2 === undefined) throw lang.refError(lnum, rsvArg2.value); if (rsvArg2 === undefined) throw lang.refError(lnum, rsvArg2);
return action(rsvArg0, rsvArg1, rsvArg2); return action(rsvArg0, rsvArg1, rsvArg2);
} }
let threeArgNum = function(lnum, args, action) { let threeArgNum = function(lnum, args, action) {
if (args.length != 3) throw lang.syntaxfehler(lnum, args.length + " arguments were given"); if (args.length != 3) throw lang.syntaxfehler(lnum, args.length + " arguments were given");
var rsvArg0 = resolve(args[0]); var rsvArg0 = resolve(args[0]);
if (rsvArg0 === undefined) throw lang.refError(lnum, rsvArg0.value); if (rsvArg0 === undefined) throw lang.refError(lnum, rsvArg0);
if (isNaN(rsvArg0)) throw lang.illegalType(lnum, rsvArg0.value); if (isNaN(rsvArg0)) throw lang.illegalType(lnum, rsvArg0);
var rsvArg1 = resolve(args[1]); var rsvArg1 = resolve(args[1]);
if (rsvArg1 === undefined) throw lang.refError(lnum, rsvArg1.value); if (rsvArg1 === undefined) throw lang.refError(lnum, rsvArg1);
if (isNaN(rsvArg1)) throw lang.illegalType(lnum, rsvArg1.value); if (isNaN(rsvArg1)) throw lang.illegalType(lnum, rsvArg1);
var rsvArg2 = resolve(args[2]); var rsvArg2 = resolve(args[2]);
if (rsvArg2 === undefined) throw lang.refError(lnum, rsvArg2.value); if (rsvArg2 === undefined) throw lang.refError(lnum, rsvArg2);
if (isNaN(rsvArg2)) throw lang.illegalType(lnum, rsvArg2.value); if (isNaN(rsvArg2)) throw lang.illegalType(lnum, rsvArg2);
return action(rsvArg0, rsvArg1, rsvArg2); return action(rsvArg0, rsvArg1, rsvArg2);
} }
let bStatus = {}; let bStatus = {};
bStatus.gosubStack = []; bStatus.gosubStack = [];
bStatus.forStack = {}; bStatus.forStack = {}; // key: forVar, value: linenum
bStatus.vars = {}; // contains instances of BasicVars bStatus.vars = {}; // contains instances of BasicVars
bStatus.defuns = {}; bStatus.defuns = {};
bStatus.rnd = 0; // stores mantissa (23 bits long) of single precision floating point number bStatus.rnd = 0; // stores mantissa (23 bits long) of single precision floating point number
@@ -299,8 +302,8 @@ bStatus.getArrayIndexFun = function(lnum, array) {
// TODO test 1-d array // TODO test 1-d array
// NOTE: BASIC arrays are index in column-major order, which is OPPOSITE of C/JS/etc. // NOTE: BASIC arrays are index in column-major order, which is OPPOSITE of C/JS/etc.
var rsvArg0 = resolve(args[0]); var rsvArg0 = resolve(args[0]);
if (rsvArg0 === undefined) throw lang.refError(lnum, rsvArg0.value); if (rsvArg0 === undefined) throw lang.refError(lnum, rsvArg0);
if (isNaN(rsvArg0)) throw lang.illegalType(lnum, rsvArg0.value); if (isNaN(rsvArg0)) throw lang.illegalType(lnum, rsvArg0);
return array[rsvArg0]; return array[rsvArg0];
}; };
@@ -318,7 +321,7 @@ bStatus.builtin = {
if (rh === undefined) throw lang.refError(lnum, args[1].troValue); if (rh === undefined) throw lang.refError(lnum, args[1].troValue);
var type = sigil.sgType || JStoBASICtype(rh); var type = sigil.sgType || JStoBASICtype(rh);
bStatus.vars[sigil.sgName] = new BasicVar(rh, type); bStatus.vars[sigil.sgName] = new BasicVar(rh, type);
return rh; return {asgnVarName: sigil.sgName, asgnValue: rh};
}, },
"==" : function(lnum, args) { "==" : function(lnum, args) {
return twoArg(lnum, args, function(lh, rh) { return lh == rh; }); return twoArg(lnum, args, function(lh, rh) { return lh == rh; });
@@ -406,11 +409,11 @@ bStatus.builtin = {
"STEP" : function(lnum, args) { "STEP" : function(lnum, args) {
if (args.length != 2) throw lang.syntaxfehler(lnum, args.length + " arguments were given"); if (args.length != 2) throw lang.syntaxfehler(lnum, args.length + " arguments were given");
var rsvArg0 = resolve(args[0]); var rsvArg0 = resolve(args[0]);
if (rsvArg0 === undefined) throw lang.refError(lnum, rsvArg0.value); if (rsvArg0 === undefined) throw lang.refError(lnum, rsvArg0);
if (!Array.isArray(rsvArg0)) throw lang.illegalType(lnum, rsvArg0.value); if (!Array.isArray(rsvArg0)) throw lang.illegalType(lnum, rsvArg0);
var rsvArg1 = resolve(args[1]); var rsvArg1 = resolve(args[1]);
if (rsvArg1 === undefined) throw lang.refError(lnum, rsvArg1.value); if (rsvArg1 === undefined) throw lang.refError(lnum, rsvArg1);
if (isNaN(rsvArg1)) throw lang.illegalType(lnum, rsvArg1.value); if (isNaN(rsvArg1)) throw lang.illegalType(lnum, rsvArg1);
let a = []; let stepcnt = 0; let a = []; let stepcnt = 0;
rsvArg0.forEach(function(v,i) { rsvArg0.forEach(function(v,i) {
if (stepcnt == 0) a.push(v); if (stepcnt == 0) a.push(v);
@@ -487,11 +490,11 @@ bStatus.builtin = {
if (args.length != 2) throw lang.syntaxfehler(lnum, args.length + " arguments were given"); if (args.length != 2) throw lang.syntaxfehler(lnum, args.length + " arguments were given");
var rsvArg = args.map(function(it) { return resolve(it); }); var rsvArg = args.map(function(it) { return resolve(it); });
rsvArg.forEach(function(v) { rsvArg.forEach(function(v) {
if (v === undefined) throw lang.refError(lnum, v.value); if (v === undefined) throw lang.refError(lnum, v);
if (typeof v !== "boolean") throw lang.illegalType(lnum, v.value); if (typeof v !== "boolean") throw lang.illegalType(lnum, v);
}); });
var argum = rsvArg.map(function(it) { var argum = rsvArg.map(function(it) {
if (it === undefined) throw lang.refError(lnum, it.value); if (it === undefined) throw lang.refError(lnum, it);
return it; return it;
}); });
return argum[0] && argum[1]; return argum[0] && argum[1];
@@ -501,10 +504,10 @@ bStatus.builtin = {
var rsvArg = args.map(function(it) { return resolve(it); }); var rsvArg = args.map(function(it) { return resolve(it); });
rsvArg.forEach(function(v) { rsvArg.forEach(function(v) {
if (v === undefined) throw lang.refError(lnum, v.value); if (v === undefined) throw lang.refError(lnum, v.value);
if (typeof v !== "boolean") throw lang.illegalType(lnum, v.value); if (typeof v !== "boolean") throw lang.illegalType(lnum, v);
}); });
var argum = rsvArg.map(function(it) { var argum = rsvArg.map(function(it) {
if (it === undefined) throw lang.refError(lnum, it.value); if (it === undefined) throw lang.refError(lnum, it);
return it; return it;
}); });
return argum[0] || argum[1]; return argum[0] || argum[1];
@@ -539,9 +542,19 @@ bStatus.builtin = {
return resolve(args[0]); return resolve(args[0]);
}, },
"FOR" : function(lnum, args) { "FOR" : function(lnum, args) {
throw TODO(); let asgnObj = resolve(args[0]);
// use bStatus.forStack // type check
bStatus.forStack.push(lnum); if (asgnObj === undefined) throw lang.syntaxfehler(lnum);
if (!Array.isArray(asgnObj.asgnValue)) throw lang.illegalType(lnum, asgnObj);
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
bStatus.vars[varname] = asgnObj.asgnValue
// put the varname to forstack
bStatus.forStack[asgnObj.asgnVarName] = lnum;
}, },
"NEXT" : function(lnum, args) { "NEXT" : function(lnum, args) {
throw TODO(); throw TODO();
@@ -1323,7 +1336,8 @@ let JStoBASICtype = function(object) {
else if (!isNaN(object)) return "number"; else if (!isNaN(object)) return "number";
else if (typeof object === "string" || object instanceof String) return "string"; else if (typeof object === "string" || object instanceof String) return "string";
else if (object === undefined) return "null"; else if (object === undefined) return "null";
else throw "BasicIntpError: un-translatable object with typeof "+(typeof object)+"\n"+object+"\n"+Object.entries(object); else if (object.asgnVarName !== undefined) return "internal_assignment_object";
else throw "BasicIntpError: un-translatable object with typeof "+(typeof object)+",\ntoString = "+object+",\nentries = "+Object.entries(object);
} }
let SyntaxTreeReturnObj = function(type, value, nextLine) { let SyntaxTreeReturnObj = function(type, value, nextLine) {
this.troType = type; this.troType = type;