From 615db3b2ad97f0598accf51e93b5dcac92deab43 Mon Sep 17 00:00:00 2001 From: minjaesong Date: Tue, 15 Dec 2020 21:19:39 +0900 Subject: [PATCH] basic: LABEL statement for GOTO/SUB --- assets/basic.js | 51 +++++++++++++++++++++++++++++++++++------------- assets/labeltest | 12 ++++++++++++ 2 files changed, 49 insertions(+), 14 deletions(-) create mode 100644 assets/labeltest diff --git a/assets/basic.js b/assets/basic.js index 9d5ed96..fbf1c98 100644 --- a/assets/basic.js +++ b/assets/basic.js @@ -36,6 +36,7 @@ if (system.maxmem() < 8192) { let vmemsize = system.maxmem() - 5236; let cmdbuf = []; // index: line number +let gotoLabels = {}; let cmdbufMemFootPrint = 0; let prompt = "Ok"; @@ -770,18 +771,24 @@ if no arg text were given (e.g. "10 NEXT"), args will have zero length return oneArgNum(lnum, stmtnum, args, (lh) => sys.peek(lh)); }, "GOTO" : function(lnum, stmtnum, args) { - return oneArgNum(lnum, stmtnum, args, (lh) => { - if (lh < 0) throw lang.syntaxfehler(lnum, lh); - return new JumpObj(lh, 0, lnum, lh); - }); + // search from gotoLabels first + let line = gotoLabels[args[0].troValue]; + // if not found, use resolved variable + if (line === undefined) line = resolve(args[0]); + if (line < 0) throw lang.syntaxfehler(lnum, line); + + return new JumpObj(line, 0, lnum, line); }, "GOSUB" : function(lnum, stmtnum, args) { - return oneArgNum(lnum, stmtnum, args, (lh) => { - if (lh < 0) throw lang.syntaxfehler(lnum, lh); - bStatus.gosubStack.push([lnum, stmtnum + 1]); - //println(lnum+" GOSUB into "+lh); - return new JumpObj(lh, 0, lnum, lh); - }); + // search from gotoLabels first + let line = gotoLabels[args[0].troValue]; + // if not found, use resolved variable + if (line === undefined) line = resolve(args[0]); + if (line < 0) throw lang.syntaxfehler(lnum, line); + + bStatus.gosubStack.push([lnum, stmtnum + 1]); + //println(lnum+" GOSUB into "+lh); + return new JumpObj(line, 0, lnum, line); }, "RETURN" : function(lnum, stmtnum, args) { var r = bStatus.gosubStack.pop(); @@ -1110,6 +1117,12 @@ if no arg text were given (e.g. "10 NEXT"), args will have zero length //return resolve(args[args.length - 1]); return undefined; }, +"LABEL" : function(lnum, stmtnum, args) { + let labelname = args[0].troValue; + + if (labelname === undefined) throw lang.syntaxfehler(lnum, "empty LABEL"); + gotoLabels[labelname] = lnum; +}, "OPTIONDEBUG" : function(lnum, stmtnum, args) { return oneArgNum(lnum, stmtnum, args, (lh) => { if (lh != 0 && lh != 1) throw lang.syntaxfehler(line); @@ -2686,8 +2699,9 @@ bF.system = function(args) { // SYSTEM function tbasexit = true; }; bF.new = function(args) { // NEW function + if (args) cmdbuf = []; bStatus.vars = initBvars(); - cmdbuf = []; + gotoLabels = {}; }; bF.renum = function(args) { // RENUM function var newcmdbuf = []; @@ -2729,11 +2743,21 @@ bF.tron = function(args) { bF.troff = function(args) { TRACEON = false; }; +bF.prescanStmts = ["DATA","LABEL"]; bF.run = function(args) { // RUN function + bF.new(false); + // pre-build the trees let programTrees = []; cmdbuf.forEach((linestr, linenum) => { - programTrees[linenum] = bF._interpretLine(linenum, linestr.trim()); + let trees = bF._interpretLine(linenum, linestr.trim()); + programTrees[linenum] = trees + // do prescan job (data, label, etc) + trees.forEach((t, i) => { + if (bF.prescanStmts.includes(t.astValue)) { + bF._executeAndGet(linenum, i, t); + } + }) }); // actually execute the program @@ -2795,8 +2819,7 @@ bF.load = function(args) { // LOAD function var prg = fs.readAll(); // reset the environment - cmdbuf = []; - bStatus.vars = initBvars(); + bF.new(true); // read the source prg.split('\n').forEach((line) => { diff --git a/assets/labeltest b/assets/labeltest new file mode 100644 index 0000000..a79dadd --- /dev/null +++ b/assets/labeltest @@ -0,0 +1,12 @@ +10 GOSUB PRINTHELLO +20 GOSUB PRINTHAI +30 GOSUB PRINTBYE +40 END +100 LABEL PRINTHELLO +110 PRINT "HELLO" +120 RETURN +200 LABEL PRINTHAI +210 PRINT "HAI" +220 RETURN +230 PRINT "BYE":LABEL PRINTBYE +240 RETURN