basic: cons is now (!); fixed issue where paren-enclosed statement would spit error on run

This commit is contained in:
minjaesong
2020-11-28 18:30:32 +09:00
parent bdcef683ae
commit ba9925c489
2 changed files with 24 additions and 15 deletions

View File

@@ -1,13 +1,13 @@
1 FOR I = 99 TO 1 1 FOR I = 99 TO 1
2 MODE = 1 2 (MODE = 1)
3 GOSUB 12 3 (GOSUB 12)
4 PRINT(I+" bottle"+BOTTLES$+" of beer on the wall, "+i+" bottle"+BOTTLES$+" of beer.") 4 PRINT(I+" bottle"+BOTTLES$+" of beer on the wall, "+i+" bottle"+BOTTLES$+" of beer.")
5 MODE = 2 5 (MODE = 2)
6 GOSUB 12 6 (GOSUB 12)
7 PRINT("Take one down and pass it around, "+(i-1)+" bottle"+BOTTLES$+" of beer on the wall.") 7 PRINT("Take one down and pass it around, "+(i-1)+" bottle"+BOTTLES$+" of beer on the wall.")
8 NEXT 8 NEXT
9 PRINT "No more bottles of beer on the wall, no more bottles of beer." 9 PRINT "No more bottles of beer on the wall, no more bottles of beer."
10 PRINT "Go to the store and buy some more. 99 bottles of beer on the wall." 10 PRINT "Go to the store and buy some more. 99 bottles of beer on the wall."
11 GOTO 999 11 END
12 IF I == MODE THEN BOTTLES$ = "" ELSE BOTTLES$ = "s" 12 IF I == MODE THEN BOTTLES$ = "" ELSE BOTTLES$ = "s"
13 RETURN 13 RETURN

View File

@@ -248,9 +248,9 @@ let oneArgNum = function(lnum, args, action) {
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);
var rsvArg0 = resolve(args[0]); var rsvArg0 = resolve(args[0]);
if (rsvArg0 === undefined) throw lang.refError(lnum, args[0]); if (rsvArg0 === undefined) throw lang.refError(lnum, "LH:"+Object.entries(args[0]));
var rsvArg1 = resolve(args[1]); var rsvArg1 = resolve(args[1]);
if (rsvArg1 === undefined) throw lang.refError(lnum, 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) {
@@ -394,7 +394,7 @@ if no arg text were given (e.g. "10 NEXT"), args will have zero length
"BXOR" : function(lnum, args) { "BXOR" : function(lnum, args) {
return twoArgNum(lnum, args, function(lh, rh) { return lh ^ rh; }); return twoArgNum(lnum, args, function(lh, rh) { return lh ^ rh; });
}, },
":" : function(lnum, args) { // Haskell-style CONS "!" : function(lnum, args) { // Haskell-style CONS
return twoArg(lnum, args, function(lh, rh) { return twoArg(lnum, args, function(lh, rh) {
if (isNaN(lh)) if (isNaN(lh))
throw lang.illegalType(lnum, lh); // BASIC array is numbers only throw lang.illegalType(lnum, lh); // BASIC array is numbers only
@@ -421,6 +421,9 @@ if no arg text were given (e.g. "10 NEXT"), args will have zero length
return lh.concat(rh); return lh.concat(rh);
}); });
}, },
":" : function(lnum, args) { // functional sequence
// just do nothing
},
"+" : function(lnum, args) { // addition, string concat "+" : function(lnum, args) { // addition, string concat
return twoArg(lnum, args, function(lh, rh) { return lh + rh; }); return twoArg(lnum, args, function(lh, rh) { return lh + rh; });
}, },
@@ -706,9 +709,9 @@ if no arg text were given (e.g. "10 NEXT"), args will have zero length
}; };
Object.freeze(bStatus.builtin); Object.freeze(bStatus.builtin);
let bF = {}; let bF = {};
bF._1os = {":":1,"~":1,"#":1,"<":1,"=":1,">":1,"*":1,"+":1,"-":1,"/":1,"^":1}; bF._1os = {"!":1,"~":1,"#":1,"<":1,"=":1,">":1,"*":1,"+":1,"-":1,"/":1,"^":1,":":1};
bF._2os = {"<":1,"=":1,">":1}; bF._2os = {"<":1,"=":1,">":1};
bF._uos = {"+":1,"-":1,"!":1}; bF._uos = {"+":1,"-":1};
bF._isNum = function(code) { bF._isNum = function(code) {
return (code >= 0x30 && code <= 0x39) || code == 0x5F; return (code >= 0x30 && code <= 0x39) || code == 0x5F;
}; };
@@ -739,6 +742,7 @@ bF._isParen = function(code) {
bF._isSep = function(code) { bF._isSep = function(code) {
return code == 0x2C || code == 0x3B; return code == 0x2C || code == 0x3B;
}; };
// define operator precedence here...
bF._opPrc = { bF._opPrc = {
// function call in itself has highest precedence // function call in itself has highest precedence
"^":1, "^":1,
@@ -756,11 +760,12 @@ bF._opPrc = {
"OR":12, "OR":12,
"TO":13, "TO":13,
"STEP":14, "STEP":14,
":":15,"~":15, // array CONS and PUSH "!":15,"~":15, // array CONS and PUSH
"#": 16, // array concat "#": 16, // array concat
"=":999 "=":999,
":":9999, // instructions separator
}; };
bF._opRh = {"^":1,"=":1,":":1}; bF._opRh = {"^":1,"=":1,"!":1};
bF._keywords = { bF._keywords = {
}; };
@@ -1534,7 +1539,11 @@ bF._executeSyntaxTree = function(lnum, syntaxTree, recDepth) {
if (_debugExec) serial.println(recWedge+"@@ EXECUTE @@"); if (_debugExec) serial.println(recWedge+"@@ EXECUTE @@");
if (syntaxTree === undefined || (recDepth == 0 && syntaxTree.astValue.toUpperCase() == "REM")) if (syntaxTree.astValue == undefined) { // empty meaningless parens
if (syntaxTree.astLeaves.length > 1) throw "WTF";
return bF._executeSyntaxTree(lnum, syntaxTree.astLeaves[0], recDepth);
}
else if (syntaxTree === undefined || (recDepth == 0 && syntaxTree.astValue.toUpperCase() == "REM"))
return new SyntaxTreeReturnObj("null", undefined, lnum + 1); return new SyntaxTreeReturnObj("null", undefined, lnum + 1);
else if (syntaxTree.astType == "function" || syntaxTree.astType == "op") { else if (syntaxTree.astType == "function" || syntaxTree.astType == "op") {
if (_debugExec) serial.println(recWedge+"function|operator"); if (_debugExec) serial.println(recWedge+"function|operator");
@@ -1624,7 +1633,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 = false; var _debugprintHighestLevel = true;
// TOKENISE // TOKENISE
var tokenisedObject = bF._tokenise(lnum, cmd); var tokenisedObject = bF._tokenise(lnum, cmd);