diff --git a/assets/basic.js b/assets/basic.js index f273696..dbea20d 100644 --- a/assets/basic.js +++ b/assets/basic.js @@ -16,6 +16,7 @@ Test Programs: */ let INDEX_BASE = 0; +let TRACEON = true; if (system.maxmem() < 8192) { println("Out of memory. BASIC requires 8K or more User RAM"); @@ -327,7 +328,7 @@ let ForGen = function(s,e,t) { // returns undefined if there is no next() this.getNext = function(mutated) { //if (mutated === undefined) throw "InternalError: parametre is missing"; - if (mutated !== undefined) this.current = mutated; + if (mutated !== undefined) this.current = (mutated|0); this.current += this.step; return this.hasNext() ? this.current : undefined; } @@ -575,12 +576,16 @@ if no arg text were given (e.g. "10 NEXT"), args will have zero length var rsvArg = resolve(args[llll]); if (rsvArg === undefined && args[llll] !== undefined && args[llll].troType != "null") throw lang.refError(lnum, args[llll].troValue); + let printstr = ""; if (rsvArg === undefined) - print(""); + printstr = (""); else if (rsvArg.toString !== undefined) - print(rsvArg.toString()); + printstr = (rsvArg.toString()); else - print(rsvArg); + printstr = (rsvArg); + + print(printstr); + if (TRACEON) serial.println("[BASIC.PRINT] "+printstr); } } @@ -731,6 +736,9 @@ if no arg text were given (e.g. "10 NEXT"), args will have zero length if (forVarname === undefined) { throw lang.nextWithoutFor(lnum); } + + if (TRACEON) serial.println("[BASIC.FOR] looping "+forVarname); + var forVar = bStatus.vars["for var "+forVarname].bvLiteral; if (forVar instanceof ForGen) @@ -755,6 +763,18 @@ if no arg text were given (e.g. "10 NEXT"), args will have zero length throw lang.syntaxfehler(lnum, "extra arguments for NEXT"); }, +"BREAKTO" : function(lnum, args) { + return oneArgNum(lnum, args, (lh) => { + var forVarname = bStatus.forStack.pop(); + if (forVarname === undefined) { + throw lang.nextWithoutFor(lnum); + } + if (TRACEON) serial.println(`[BASIC.FOR] breaking from ${forVarname}, jump to ${lh}`); + + if (lh < 0) throw lang.syntaxfehler(lnum, lh); + return lh; + }); +}, /* 10 input;"what is your name";a$ @@ -799,6 +819,8 @@ if no arg text were given (e.g. "10 NEXT"), args will have zero length // print out prompt text print("? "); var rh = sys.read().trim(); + if (rh*1 === (rh|0) || !isNaN(rh)) rh = rh*1 + if (troValue.arrObj !== undefined) { if (isNaN(rh) && !Array.isArray(rh)) throw lang.illegalType(lnum, rh); @@ -1664,7 +1686,7 @@ let SyntaxTreeReturnObj = function(type, value, nextLine) { this.troValue = value; this.troNextLine = nextLine; } -bF._gotoCmds = {GOTO:1,GOSUB:1,RETURN:1,NEXT:1,END:1}; // put nonzero (truthy) value here +bF._gotoCmds = {GOTO:1,GOSUB:1,RETURN:1,NEXT:1,END:1,BREAKTO:1}; // put nonzero (truthy) value here /** * @param lnum line number of BASIC * @param syntaxTree BasicAST @@ -1674,7 +1696,7 @@ bF._gotoCmds = {GOTO:1,GOSUB:1,RETURN:1,NEXT:1,END:1}; // put nonzero (truthy) v */ bF._troNOP = function(lnum) { return new SyntaxTreeReturnObj("null", undefined, lnum + 1); } bF._executeSyntaxTree = function(lnum, syntaxTree, recDepth) { - var _debugExec = true; + var _debugExec = false; var recWedge = "> ".repeat(recDepth); if (_debugExec) serial.println(recWedge+"@@ EXECUTE @@"); @@ -1772,7 +1794,12 @@ 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 bF._interpretLine = function(lnum, cmd) { - var _debugprintHighestLevel = true; + var _debugprintHighestLevel = false; + + if (TRACEON) { + //print(`[${lnum}]`); + serial.println("[BASIC] Line "+lnum); + } if (cmd.toUpperCase().startsWith("REM")) { if (_debugprintHighestLevel) serial.println(lnum+" "+cmd); @@ -1794,13 +1821,16 @@ bF._interpretLine = function(lnum, cmd) { if (_debugprintHighestLevel) serial.println(syntaxTree.toString()); // EXECUTE - //try { + try { var execResult = bF._executeSyntaxTree(lnum, syntaxTree, 0); return execResult.troNextLine; - //} - //catch (e) { - // throw lang.parserError(lnum, e); - //} + } + catch (e) { + serial.println(`ERROR on ${lnum} -- PARSE TREE:`); + serial.println(syntaxTree.toString()); + serial.println("ERROR CONTENTS:"); + println(e); + } }; // end INTERPRETLINE bF._basicList = function(v, i, arr) { if (i < 10) print(" "); @@ -1854,6 +1884,9 @@ bF.renum = function(args) { // RENUM function else if (newcmdbuf[k] !== undefined && newcmdbuf[k].toLowerCase().startsWith("gosub ")) { newcmdbuf[k] = "GOSUB " + linenumRelation[newcmdbuf[k].match(reNum)[0]]; } + else if (newcmdbuf[k] !== undefined && newcmdbuf[k].toLowerCase().startsWith("breakto ")) { + newcmdbuf[k] = "BREAKTO " + linenumRelation[newcmdbuf[k].match(reNum)[0]]; + } } cmdbuf = newcmdbuf.slice(); // make shallow copy diff --git a/assets/blackjack.bas b/assets/blackjack.bas index 5cff2c2..f670266 100644 --- a/assets/blackjack.bas +++ b/assets/blackjack.bas @@ -4,7 +4,6 @@ 6 PRINT 7 PRINT 8 PRINT -10 REM DEFUN A(Q)=Q+11*(Q>=22) 20 HANDS=DIM(15,12) 21 HANDTOTAL=DIM(15) 22 DECK=DIM(52) @@ -22,11 +21,11 @@ 100 REM--SUBROUTINE TO GET A CARD. RESULT IS PUT IN X. 110 IF C<51 THEN GOTO 230 120 PRINT "RESHUFFLING" -130 FOR DI=D TO 1 +130 FOR D=D TO 1 STEP -1 140 C=C-1 -150 DECK(C)=DISCARDECK(DI) +150 DECK(C)=DISCARDECK(D) 160 NEXT -170 FOR C1=52 TO C +170 FOR C1=52 TO C STEP -1 180 C2=INT(RND(1)*(C1-C+1))+C 190 C3=DECK(C2) 200 DECK(C2)=DECK(C1) @@ -124,7 +123,7 @@ 1420 INPUT HSTR 1421 HSTR=LEFT(HSTR,1) 1430 FOR H=1 TO H1 STEP 2 -1440 IF HSTR==MID(ISTR,H,1) THEN GOTO 1480 +1440 IF HSTR==MID(ISTR,H,1) THEN BREAKTO 1480 1450 NEXT 1460 PRINT "TYPE ";MID(ISTR,1,H1-1);" OR ";MID(ISTR,H1,2);" PLEASE"; 1470 GOTO 1420 @@ -132,7 +131,7 @@ 1490 RETURN 1500 REM--PROGRAM STARTS HERE 1510 REM--INITIALIZE -1520 DSTR="N A 2 3 4 5 6 7N 8 9 10 J Q K" +1520 DSTR=" A 2 3 4 5 6 7 8 9 10 J Q K" 1530 ISTR="H,S,D,/," 1540 FOR I=1 TO 13 1550 FOR J=4*I-3 TO 4*I @@ -188,7 +187,7 @@ 1892 INPUT ZARR(I) 1893 NEXT 1900 FOR I=1 TO N -1910 IF ZARR(I)<=0 OR ZARR(I)>500 THEN GOTO 1880 +1910 IF ZARR(I)<=0 OR ZARR(I)>500 THEN BREAKTO 1880 1920 BETS(I)=ZARR(I) 1930 NEXT 1940 PRINT "PLAYER "; @@ -219,7 +218,7 @@ 2172 INPUT ZARR(I) 2173 NEXT 2180 FOR I=1 TO N -2190 IF ZARR(I)<0 OR ZARR(I)>BETS(I)/2 THEN GOTO 2160 +2190 IF ZARR(I)<0 OR ZARR(I)>BETS(I)/2 THEN BREAKTO 2160 2200 NEXT 2210 FOR I=1 TO N 2220 PLRHNDSUM(I)=ZARR(I)*(3*(-(HANDS(D1,2)>=10))-1) @@ -233,7 +232,7 @@ 2255 L2=0 2256 IF L1<>0 OR L2<>0 THEN GOTO 2320 2260 PRINT -2261 PRINT "DEALER HAS A";MID(DSTR,3*HANDS(D1,2)-2,3);" IN THE HOLE "; +2261 PRINT "DEALER HAS";MID(DSTR,3*HANDS(D1,2)-2,3);" IN THE HOLE "; 2270 PRINT "FOR BLACKJACK" 2280 FOR I=1 TO D1 2290 GOSUB 300 @@ -244,8 +243,7 @@ 2340 PRINT 2341 PRINT "NO DEALER BLACKJACK." 2350 REM--NOW PLAY THE HANDS -2360 REM--FOR I=1 TO N-- -2361 I=1 +2360 FOR I=1 TO N 2370 PRINT "PLAYER ";I; 2380 H1=7 2390 GOSUB 1410 @@ -307,20 +305,18 @@ 2870 I=I+D1 2880 IF I==I1 THEN GOTO 2850 2890 I=I1-D1 -2900 REM--NEXT I-- -2901 I=I+1 -2902 IF I<=N THEN GOTO 2370 +2900 NEXT 2910 GOSUB 300 2920 REM--TEST FOR PLAYING DEALER'S HAND 2930 FOR I=1 TO N -2940 IF HANDSLENS(I)>0 OR HANDSLENS(I+D1)>0 THEN GOTO 3010 +2940 IF HANDSLENS(I)>0 OR HANDSLENS(I+D1)>0 THEN BREAKTO 3010 2950 NEXT 2960 PRINT "DEALER HAD A"; 2970 X=HANDS(D1,2) 2980 GOSUB 700 2990 PRINT " CONCEALED." 3000 GOTO 3140 -3010 PRINT "DEALER HAS A";MID(DSTR,3*HANDS(D1,2)-2,3);" CONCEALED "; +3010 PRINT "DEALER HAS";MID(DSTR,3*HANDS(D1,2)-2,3);" CONCEALED "; 3020 I=D1 3030 AA=HANDTOTAL(I) 3031 GOSUB 3400 @@ -333,7 +329,7 @@ 3090 AA=Q 3091 GOSUB 3400 3095 IF Q>0 AND AA<17 THEN GOTO 3060 -3100 HANDTOTAL(I)=Q-(Q<0)/2 +3100 HANDTOTAL(I)=(Q-(Q<0)/2) 3110 IF Q<0 THEN GOTO 3140 3120 AA=Q 3121 GOSUB 3400 @@ -343,8 +339,7 @@ 3150 REM 3160 ZSTR="LOSES PUSHES WINS " 3165 PRINT -3170 REM--FOR I=1 TO N-- -3171 I=1 +3170 FOR I=1 TO N 3180 AA=HANDTOTAL(I) 3181 GOSUB 3400 3182 AB=HANDTOTAL(I+D1) @@ -360,15 +355,13 @@ 3240 GOTO 3260 3250 PRINT ABS(PLRHNDSUM(I)); 3260 PLRSUM(I)=PLRSUM(I)+PLRHNDSUM(I) -3270 PRINT "TOTAL= ";PLRSUM(I) +3270 PRINT "; TOTAL= ";PLRSUM(I) 3280 GOSUB 1200 3290 PLRSUM(D1)=PLRSUM(D1)-PLRHNDSUM(I) 3300 I=I+D1 3310 GOSUB 1200 3320 I=I-D1 -3330 REM--NEXT I-- -3331 I=I+1 -3332 IF I<=N THEN GOTO 3180 +3330 NEXT 3340 PRINT "DEALER'S TOTAL= ";PLRSUM(D1) 3345 PRINT 3350 GOSUB 1200