From f55aa51023c2e094ddfc9a41c00dbb46f2d33b7d Mon Sep 17 00:00:00 2001 From: Joshua Bell Date: Sun, 28 Dec 2014 20:55:23 -0700 Subject: [PATCH] Make line numbers relevant; resolves issue #5 --- README.md | 1 - basic.js | 38 +++++++++++++++++++++++++++++------- samples/sample.unittests.txt | 20 +++++++++++++------ 3 files changed, 45 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index f4338cd..65e9032 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,6 @@ Notes & Known Issues * The BASIC program is compiled to JavaScript before execution. Syntax errors are therefore detected at compile-time rather than at run-time as on a traditional interpreter. For example, the following program would run without errors on an Apple since the erroneous second statement is never reached. `10 END : CHR$(PRINT)` * Handling of BASIC code that does not match the canonical `LIST` output format may not behave as on an Apple: * Keyword parsing differs from Applesoft command line. For example `FOR I = S TO P` doesn't collapse into `FOR I = STOP`. - * The interpreter doesn't actually care about line numbers for statement ordering (just for `GOTO/GOSUB` targets and `IF` statements). So `20 PRINT "A"`, `10 PRINT "B"` will just print `A`, then `B` * Limitations: * Floating point overflow is only detected on variable assignment. * Only a subset of DOS 3.3 and ProDOS useful for basic file I/O are implemented. diff --git a/basic.js b/basic.js index 1c530e8..141b149 100644 --- a/basic.js +++ b/basic.js @@ -2132,24 +2132,48 @@ this.basic = (function() { function parseStatement() { if (test('data')) { program.data = program.data.concat(match('data')); - return; + return undefined; } else if (test('remark', void 0, true)) { - return; + return undefined; } else if (test('reserved') || test('identifier')) { - program.statements.push(mkfun(parseCommand())); + return mkfun(parseCommand()); } else { // So TRACE output is correct - program.statements.push(empty_statement); + return empty_statement; } } // Line = line-number Statement { separator Statement } function parseLine() { - program.statements.push(match('lineNumber')); - parseStatement(); + var num = match('lineNumber'); + var statements = []; + var statement = parseStatement(); + if (statement) statements.push(statement); while (test('separator', ':', true)) { - parseStatement(); + statement = parseStatement(); + if (statement) statements.push(statement); } + insertLine(num, statements); + } + + function insertLine(number, statements) { + var remove = 0; + for (var i = 0, len = program.statements.length; i < len; ++i) { + if (typeof program.statements[i] !== 'number') + continue; + if (program.statements[i] < number) + continue; + if (program.statements[i] === number) { + var n = i; + do { + ++n; + ++remove; + } while (n < len && typeof program.statements[n] !== 'number'); + } + break; + } + var args = [i, remove, number].concat(statements); + program.statements.splice.apply(program.statements, args); } // Program = Line { Line } diff --git a/samples/sample.unittests.txt b/samples/sample.unittests.txt index 977943a..65d1602 100644 --- a/samples/sample.unittests.txt +++ b/samples/sample.unittests.txt @@ -325,8 +325,8 @@ 6000 PRINT : PRINT "Inline Data "; -6010 DATA 1,2,3 -6011 DATA "A","B","C" +6001 DATA 1,2,3 +6002 DATA "A","B","C" 6010 T$ = "READ" : RESTORE @@ -349,7 +349,7 @@ 7010 REM Test GR as part of I/O (sets cursor to window bottom) 7010 REM ************************************************************ -7010 POKE 49232,0 : POKE 49234,0 : POKE 49238,0 +7011 POKE 49232,0 : POKE 49234,0 : POKE 49238,0 7020 T$ = "COLOR=" : T = 0 : U = 0 : FOR I = 0 TO 15 : COLOR= I : PLOT 0,0 : T = T + I : U = U + SCRN(0,0) : NEXT @@ -748,9 +748,9 @@ 17040 T$ = "Sequential Access/ONERR" : PRINT CHR$(4)"OPEN JABBERWOCKY" : PRINT CHR$(4)"READ JABBERWOCKY" -: ONERR GOTO 10742 : N = 0 +: ONERR GOTO 17042 : N = 0 : FOR N = 0 TO 10 : INPUT A$ : NEXT -10742 POKE 216,0 : PRINT CHR$(4)"CLOSE" : S = (N = 4) : GOSUB 1 +17042 POKE 216,0 : PRINT CHR$(4)"CLOSE" : S = (N = 4) : GOSUB 1 17050 T$ = "RENAME" : PRINT CHR$(4)"OPEN TESTDATA" @@ -812,8 +812,16 @@ : T = 2 18071 S = (T=1) AND (PEEK(222)=107) : GOSUB 1 : POKE 216,0 +18080 T$ = "Duplicate Lines" +18081 T = 1 +18082 T = T + 1 : REM Should be overwritten +18082 T = T + 1 +18083 S = (T = 2) : GOSUB 1 - +18090 T$ = "Line Ordering" +18092 T = 2 +18091 T = 1 +18093 S = (T = 2) : GOSUB 1 20000 PRINT : PRINT : PRINT "Executed tests: "; TE 20010 PRINT "Successful tests: "; TS