mirror of
https://github.com/curioustorvald/tsvm.git
synced 2026-06-09 06:34:04 +09:00
basic:more helpful errmsgs
This commit is contained in:
@@ -17,6 +17,7 @@ Test Programs:
|
|||||||
*/
|
*/
|
||||||
let INDEX_BASE = 0;
|
let INDEX_BASE = 0;
|
||||||
let TRACEON = false;
|
let TRACEON = false;
|
||||||
|
let DBGON = true;
|
||||||
|
|
||||||
if (system.maxmem() < 8192) {
|
if (system.maxmem() < 8192) {
|
||||||
println("Out of memory. BASIC requires 8K or more User RAM");
|
println("Out of memory. BASIC requires 8K or more User RAM");
|
||||||
@@ -43,10 +44,13 @@ 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) : "");
|
||||||
};
|
};
|
||||||
lang.illegalType = function(line, obj) {
|
lang.illegalType = function(line, obj) {
|
||||||
return "Type mismatch" + ((obj !== undefined) ? ' "' + obj + '"' : "") + ((line !== undefined) ? (" in "+line) : "");
|
return "Type mismatch" + ((obj !== undefined) ? ` "${obj} (typeof ${typeof obj})"` : "") + ((line !== undefined) ? (" in "+line) : "");
|
||||||
};
|
};
|
||||||
lang.refError = function(line, obj) {
|
lang.refError = function(line, obj) {
|
||||||
return "Unresolved reference" + ((obj !== undefined) ? ' "' + obj + '"' : "") + ((line !== undefined) ? (" in "+line) : "");
|
serial.printerr(`${line} Unresolved reference:`);
|
||||||
|
serial.printerr(` object: ${obj}, typeof: ${typeof obj}`);
|
||||||
|
serial.printerr(` entries: ${Object.entries(obj)}`);
|
||||||
|
return "Unresolved reference" + ((obj !== undefined) ? ` "${obj}"` : "") + ((line !== undefined) ? (" in "+line) : "");
|
||||||
};
|
};
|
||||||
lang.nowhereToReturn = function(line) { return "RETURN without GOSUB in " + line; };
|
lang.nowhereToReturn = function(line) { return "RETURN without GOSUB in " + line; };
|
||||||
lang.errorinline = function(line, stmt, errobj) {
|
lang.errorinline = function(line, stmt, errobj) {
|
||||||
@@ -64,10 +68,16 @@ lang.dupDef = function(line, varname) {
|
|||||||
lang.asgnOnConst = function(line, constname) {
|
lang.asgnOnConst = function(line, constname) {
|
||||||
return 'Trying to modify constant "'+constname+'" in '+line;
|
return 'Trying to modify constant "'+constname+'" in '+line;
|
||||||
};
|
};
|
||||||
lang.subscrOutOfRng = function(line, object) {
|
lang.subscrOutOfRng = function(line, object, index, maxlen) {
|
||||||
return "Subscript out of range"+(object !== undefined ? (' for "'+object+'"') : '')+(line !== undefined ? (" in "+line) : "")
|
return "Subscript out of range"+(object !== undefined ? (' for "'+object+'"') : '')+(index !== undefined ? (` (index: ${index}, len: ${maxlen})`) : "")+(line !== undefined ? (" in "+line) : "");
|
||||||
};
|
};
|
||||||
lang.aG = " arguments were given";
|
lang.aG = " arguments were given";
|
||||||
|
lang.ord = function(n) {
|
||||||
|
if (n % 10 == 1 && n % 100 != 11) return n+"st";
|
||||||
|
if (n % 10 == 2 && n % 100 != 12) return n+"nd";
|
||||||
|
if (n % 10 == 3 && n % 100 != 13) return n+"rd";
|
||||||
|
return n+"th";
|
||||||
|
}
|
||||||
Object.freeze(lang);
|
Object.freeze(lang);
|
||||||
|
|
||||||
let fs = {};
|
let fs = {};
|
||||||
@@ -224,34 +234,40 @@ let resolve = function(variable) {
|
|||||||
else
|
else
|
||||||
throw "BasicIntpError: unknown variable with type "+variable.troType+", with value "+variable.troValue
|
throw "BasicIntpError: unknown variable with type "+variable.troType+", with value "+variable.troValue
|
||||||
}
|
}
|
||||||
|
let argCheckErr = function(lnum, o) {
|
||||||
|
if (o === undefined || o.troType == "null") throw lang.refError(lnum, o);
|
||||||
|
if (o.troType == "lit" && bStatus.vars[o.troValue] === undefined) throw lang.refError(lnum, o);
|
||||||
|
if (o.troValue.arrObj !== undefined && o.troValue.arrIndex >= o.troValue.arrObj.length)
|
||||||
|
throw lang.subscrOutOfRng(line, o.troValue.arrName, o.troValue.arrIndex, o.troValue.arrObj.length);
|
||||||
|
}
|
||||||
let oneArg = function(lnum, args, action) {
|
let oneArg = function(lnum, args, action) {
|
||||||
if (args.length != 1) throw lang.syntaxfehler(lnum, args.length+lang.aG);
|
if (args.length != 1) throw lang.syntaxfehler(lnum, args.length+lang.aG);
|
||||||
|
argCheckErr(lnum, args[0]);
|
||||||
var rsvArg0 = resolve(args[0]);
|
var rsvArg0 = resolve(args[0]);
|
||||||
if (rsvArg0 === undefined) throw lang.refError(lnum, args[0]);
|
|
||||||
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+lang.aG);
|
if (args.length != 1) throw lang.syntaxfehler(lnum, args.length+lang.aG);
|
||||||
|
argCheckErr(lnum, args[0]);
|
||||||
var rsvArg0 = resolve(args[0]);
|
var rsvArg0 = resolve(args[0]);
|
||||||
if (rsvArg0 === undefined) throw lang.refError(lnum, args[0]);
|
|
||||||
if (isNaN(rsvArg0)) throw lang.illegalType(lnum, args[0]);
|
if (isNaN(rsvArg0)) throw lang.illegalType(lnum, args[0]);
|
||||||
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+lang.aG);
|
if (args.length != 2) throw lang.syntaxfehler(lnum, args.length+lang.aG);
|
||||||
|
argCheckErr(lnum, args[0]);
|
||||||
var rsvArg0 = resolve(args[0]);
|
var rsvArg0 = resolve(args[0]);
|
||||||
if (rsvArg0 === undefined) throw lang.refError(lnum, "LH:"+Object.entries(args[0]));
|
argCheckErr(lnum, args[1]);
|
||||||
var rsvArg1 = resolve(args[1]);
|
var rsvArg1 = resolve(args[1]);
|
||||||
if (rsvArg1 === undefined) throw lang.refError(lnum, "RH:"+Object.entries(args[1]));
|
|
||||||
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+lang.aG);
|
if (args.length != 2) throw lang.syntaxfehler(lnum, args.length+lang.aG);
|
||||||
|
argCheckErr(lnum, args[0]);
|
||||||
var rsvArg0 = resolve(args[0]);
|
var rsvArg0 = resolve(args[0]);
|
||||||
if (rsvArg0 === undefined) throw lang.refError(lnum, args[0]);
|
|
||||||
if (isNaN(rsvArg0)) throw lang.illegalType(lnum, "LH:"+Object.entries(args[0]));
|
if (isNaN(rsvArg0)) throw lang.illegalType(lnum, "LH:"+Object.entries(args[0]));
|
||||||
|
argCheckErr(lnum, args[1]);
|
||||||
var rsvArg1 = resolve(args[1]);
|
var rsvArg1 = resolve(args[1]);
|
||||||
if (rsvArg1 === undefined) throw lang.refError(lnum, args[1]);
|
|
||||||
if (isNaN(rsvArg1)) throw lang.illegalType(lnum, "RH:"+Object.entries(args[1]));
|
if (isNaN(rsvArg1)) throw lang.illegalType(lnum, "RH:"+Object.entries(args[1]));
|
||||||
return action(rsvArg0, rsvArg1);
|
return action(rsvArg0, rsvArg1);
|
||||||
}
|
}
|
||||||
@@ -382,15 +398,33 @@ bStatus.getArrayIndexFun = function(lnum, arrayName, array) {
|
|||||||
return varArgNum(lnum, args, (dims) => {
|
return varArgNum(lnum, args, (dims) => {
|
||||||
let indexingstr = "";
|
let indexingstr = "";
|
||||||
if (TRACEON) serial.println("ar dims: "+dims);
|
if (TRACEON) serial.println("ar dims: "+dims);
|
||||||
|
|
||||||
|
let dimcnt = 1;
|
||||||
|
let oldIstr = "";
|
||||||
|
let istr = "";
|
||||||
|
// check error beforehand
|
||||||
|
dims.reverse().forEach((d) => {
|
||||||
|
oldIstr = istr;
|
||||||
|
istr += `[${d-INDEX_BASE}]`;
|
||||||
|
// test for index out of bounds
|
||||||
|
if (eval(`array${istr}`) === undefined) {
|
||||||
|
throw lang.subscrOutOfRng(lnum, `${arrayName}${oldIstr} (${lang.ord(dimcnt)} dim)`, d-INDEX_BASE, eval(`array${oldIstr}`).length);
|
||||||
|
}
|
||||||
|
dimcnt += 1;
|
||||||
|
})
|
||||||
|
// actually build indexing string (trust me, indexing fails with code above; test with 'amazing.bas')
|
||||||
dims.forEach((d) => {
|
dims.forEach((d) => {
|
||||||
indexingstr = `[${d-INDEX_BASE}]${indexingstr}`;
|
indexingstr = `[${d-INDEX_BASE}]${indexingstr}`;
|
||||||
})
|
})
|
||||||
if (TRACEON)
|
if (TRACEON)
|
||||||
serial.println("ar indexedValue = "+`/*ar1*/array${indexingstr}`);
|
serial.println("ar indexedValue = "+`/*ar1*/array${indexingstr}`);
|
||||||
|
|
||||||
let indexedValue = eval(`/*ar1*/array${indexingstr}`);
|
let indexedValue = eval(`/*ar1*/array${indexingstr}`);
|
||||||
let index = dims[0]-INDEX_BASE;
|
let index = dims[0]-INDEX_BASE;
|
||||||
|
|
||||||
if (TRACEON)
|
if (TRACEON)
|
||||||
serial.println("ar parentArr = "+`/*ar2*/array${indexingstr.substring(0, indexingstr.length - 2 - (""+index).length)}`);
|
serial.println("ar parentArr = "+`/*ar2*/array${indexingstr.substring(0, indexingstr.length - 2 - (""+index).length)}`);
|
||||||
|
//let parentArr = eval(`/*ar2*/array${oldIndexingStr}`);
|
||||||
let parentArr = eval(`/*ar2*/array${indexingstr.substring(0, indexingstr.length - 2 - (""+index).length)}`);
|
let parentArr = eval(`/*ar2*/array${indexingstr.substring(0, indexingstr.length - 2 - (""+index).length)}`);
|
||||||
|
|
||||||
if (index < 0) throw lang.subscrOutOfRng(lnum, arrayName);
|
if (index < 0) throw lang.subscrOutOfRng(lnum, arrayName);
|
||||||
@@ -888,6 +922,42 @@ if no arg text were given (e.g. "10 NEXT"), args will have zero length
|
|||||||
INDEX_BASE = lh|0;
|
INDEX_BASE = lh|0;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
"RESOLVE" : function(lnum, args) {
|
||||||
|
if (DBGON) {
|
||||||
|
return oneArg(lnum, args, (it) => {
|
||||||
|
println(it);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw lang.syntaxfehler(lnum);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"RESOLVE0" : function(lnum, args) {
|
||||||
|
if (DBGON) {
|
||||||
|
return oneArg(lnum, args, (it) => {
|
||||||
|
println(Object.entries(it));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw lang.syntaxfehler(lnum);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"UNRESOLVE" : function(lnum, args) {
|
||||||
|
if (DBGON) {
|
||||||
|
println(args[0]);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw lang.syntaxfehler(lnum);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"UNRESOLVE0" : function(lnum, args) {
|
||||||
|
if (DBGON) {
|
||||||
|
println(Object.entries(args[0]));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw lang.syntaxfehler(lnum);
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
Object.freeze(bStatus.builtin);
|
Object.freeze(bStatus.builtin);
|
||||||
let bF = {};
|
let bF = {};
|
||||||
@@ -1702,7 +1772,7 @@ let JStoBASICtype = function(object) {
|
|||||||
else if (object.asgnVarName !== undefined) return "internal_assignment_object";
|
else if (object.asgnVarName !== undefined) return "internal_assignment_object";
|
||||||
else if (object.arrValue !== undefined) return "internal_arrindexing_lazy";
|
else if (object.arrValue !== undefined) return "internal_arrindexing_lazy";
|
||||||
// buncha error msgs
|
// buncha error msgs
|
||||||
else if (object.arrIndex-INDEX_BASE >= object.arrObj.length) throw lang.subscrOutOfRng(undefined, `${object.arrName}(${object.arrIndex}, len:${object.arrObj.length})`);
|
else if (object.arrIndex >= object.arrObj.length) throw lang.subscrOutOfRng(undefined, `${object.arrName}(${object.arrIndex}, len:${object.arrObj.length})`);
|
||||||
else throw "BasicIntpError: un-translatable object with typeof "+(typeof object)+",\ntoString = "+object+",\nentries = "+Object.entries(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) {
|
||||||
|
|||||||
Reference in New Issue
Block a user