mirror of
https://github.com/sehugg/8bitworkshop.git
synced 2024-11-26 10:49:17 +00:00
basic: ON..GOSUB, CLEAR, rearranged platform menu
This commit is contained in:
parent
cf39cd4f58
commit
946037a1c9
19
index.html
19
index.html
@ -191,6 +191,7 @@ if (window.location.host.endsWith('8bitworkshop.com')) {
|
||||
<li><a class="dropdown-item" href="?platform=msx-libcv">MSX (libCV)</a></li>
|
||||
<li><a class="dropdown-item" href="?platform=apple2">Apple ][+</a></li>
|
||||
<li><a class="dropdown-item" href="?platform=zx">ZX Spectrum</a></li>
|
||||
<li><a class="dropdown-item" href="?platform=x86">x86 (FreeDOS)</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown dropdown-submenu">
|
||||
@ -200,6 +201,7 @@ if (window.location.host.endsWith('8bitworkshop.com')) {
|
||||
<li><a class="dropdown-item" href="?platform=mw8080bw">Midway 8080</a></li>
|
||||
<li><a class="dropdown-item" href="?platform=galaxian-scramble">Galaxian/Scramble</a></li>
|
||||
<li><a class="dropdown-item" href="?platform=vector-z80color">Atari Color Vector (Z80)</a></li>
|
||||
<li><a class="dropdown-item" href="?platform=vector-ataricolor">Atari Color Vector (6502)</a></li>
|
||||
<li><a class="dropdown-item" href="?platform=williams-z80">Williams (Z80)</a></li>
|
||||
<li><a class="dropdown-item" href="?platform=sound_williams-z80">Williams Sound (Z80)</a></li>
|
||||
</ul>
|
||||
@ -211,6 +213,14 @@ if (window.location.host.endsWith('8bitworkshop.com')) {
|
||||
<li><a class="dropdown-item" href="?platform=verilog-vga">Verilog (VGA @ 25 Mhz)</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown dropdown-submenu">
|
||||
<a tabindex="-1" href="#">Text-Based</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a class="dropdown-item" href="?platform=basic">BASIC</a></li>
|
||||
<li><a class="dropdown-item" href="?platform=zmachine">Z-Machine</a></li>
|
||||
<li><a class="dropdown-item" href="?platform=markdown">Markdown Text Editor</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown dropdown-submenu">
|
||||
<a tabindex="-1" href="#">MAME Emulators</a>
|
||||
<ul class="dropdown-menu">
|
||||
@ -222,15 +232,6 @@ if (window.location.host.endsWith('8bitworkshop.com')) {
|
||||
<li><a class="dropdown-item" href="?platform=nes.mame">NES (MAME)</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown dropdown-submenu">
|
||||
<a tabindex="-1" href="#">Other</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a class="dropdown-item" href="?platform=vector-ataricolor">Atari Color Vector (6502)</a></li>
|
||||
<li><a class="dropdown-item" href="?platform=x86">x86 (FreeDOS)</a></li>
|
||||
<li><a class="dropdown-item" href="?platform=zmachine">Z-Machine</a></li>
|
||||
<li><a class="dropdown-item" href="?platform=markdown">Markdown Text Editor</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</span>
|
||||
|
||||
|
@ -88,7 +88,7 @@ export interface RETURN_Statement {
|
||||
}
|
||||
|
||||
export interface ONGOTO_Statement {
|
||||
command: "ONGOTO";
|
||||
command: "ONGOTO" | "ONGOSUB";
|
||||
expr: Expr;
|
||||
labels: Expr[];
|
||||
}
|
||||
@ -706,9 +706,11 @@ export class BASICParser {
|
||||
}
|
||||
stmt__ON() : ONGOTO_Statement {
|
||||
var expr = this.parseExpr();
|
||||
this.expectToken('GOTO');
|
||||
var gotok = this.consumeToken();
|
||||
var cmd = {GOTO:'ONGOTO', GOSUB:'ONGOSUB'}[gotok.str];
|
||||
if (!cmd) this.compileError(`There should be a GOTO or GOSUB here.`);
|
||||
var labels = this.parseLabelList();
|
||||
return { command:'ONGOTO', expr:expr, labels:labels };
|
||||
return { command:cmd, expr:expr, labels:labels };
|
||||
}
|
||||
stmt__DEF() : DEF_Statement {
|
||||
var lexpr = this.parseVarSubscriptOrFunc();
|
||||
@ -728,6 +730,9 @@ export class BASICParser {
|
||||
this.decls[lexpr.name] = this.lasttoken.$loc;
|
||||
return { command:'GET', lexpr:lexpr };
|
||||
}
|
||||
stmt__CLEAR() : NoArgStatement {
|
||||
return { command:'CLEAR' };
|
||||
}
|
||||
// TODO: CHANGE A TO A$ (4th edition, A(0) is len and A(1..) are chars)
|
||||
stmt__OPTION() : OPTION_Statement {
|
||||
var tokname = this.consumeToken();
|
||||
@ -826,7 +831,7 @@ export const ECMA55_MINIMAL : BASICOptions = {
|
||||
validKeywords : ['BASE','DATA','DEF','DIM','END',
|
||||
'FOR','GO','GOSUB','GOTO','IF','INPUT','LET','NEXT','ON','OPTION','PRINT',
|
||||
'RANDOMIZE','READ','REM','RESTORE','RETURN','STEP','STOP','SUB','THEN','TO'
|
||||
],
|
||||
], // TODO: no ON...GOSUB
|
||||
validFunctions : ['ABS','ATN','COS','EXP','INT','LOG','RND','SGN','SIN','SQR','TAB','TAN'],
|
||||
validOperators : ['=', '<>', '<', '>', '<=', '>=', '+', '-', '*', '/', '^'],
|
||||
printZoneLength : 15,
|
||||
@ -857,7 +862,7 @@ export const ALTAIR_BASIC40 : BASICOptions = {
|
||||
tickComments : false,
|
||||
validKeywords : null, // all
|
||||
validFunctions : null, // all
|
||||
validOperators : null, // all ['\\','MOD','NOT','AND','OR','XOR','EQV','IMP'],
|
||||
validOperators : null, // all
|
||||
printZoneLength : 15,
|
||||
numericPadding : true,
|
||||
checkOverflow : true,
|
||||
@ -884,10 +889,19 @@ export const APPLESOFT_BASIC : BASICOptions = {
|
||||
maxStringLength : 255,
|
||||
sparseArrays : false,
|
||||
tickComments : false,
|
||||
validKeywords : null, // all
|
||||
validFunctions : ['ABS','ATN','COS','EXP','INT','LOG','RND','SGN','SIN','SQR','TAN',
|
||||
validKeywords : [
|
||||
'CLEAR','LET','DIM','DEF','FN','GOTO','GOSUB','RETURN','ON','POP',
|
||||
'FOR','TO','NEXT','IF','THEN','END','STOP','ONERR','RESUME',
|
||||
'PRINT','INPUT','GET','HOME','HTAB','VTAB',
|
||||
'INVERSE','FLASH','NORMAL','TEXT',
|
||||
'GR','COLOR','PLOT','HLIN','VLIN',
|
||||
'HGR','HGR2','HPLOT','HCOLOR','AT',
|
||||
'DATA','READ','RESTORE',
|
||||
'REM','TRACE','NOTRACE'],
|
||||
validFunctions : [
|
||||
'ABS','ATN','COS','EXP','INT','LOG','RND','SGN','SIN','SQR','TAN',
|
||||
'LEN','LEFT$','MID$','RIGHT$','STR$','VAL','CHR$','ASC',
|
||||
'FRE','SCRN','PDL','PEEK'], // TODO
|
||||
'FRE','SCRN','PDL','PEEK','POS'],
|
||||
validOperators : ['=', '<>', '<', '>', '<=', '>=', '+', '-', '*', '/', '^', 'AND', 'NOT', 'OR'],
|
||||
printZoneLength : 16,
|
||||
numericPadding : false,
|
||||
|
@ -90,15 +90,18 @@ export class BASICRuntime {
|
||||
reset() {
|
||||
this.curpc = 0;
|
||||
this.dataptr = 0;
|
||||
this.vars = {};
|
||||
this.arrays = {};
|
||||
this.defs = {};
|
||||
this.clearVars();
|
||||
this.forLoops = [];
|
||||
this.returnStack = [];
|
||||
this.column = 0;
|
||||
this.running = true;
|
||||
this.exited = false;
|
||||
}
|
||||
clearVars() {
|
||||
this.vars = {};
|
||||
this.arrays = {};
|
||||
this.defs = {}; // TODO? only in interpreters
|
||||
}
|
||||
|
||||
getBuiltinFunctions() {
|
||||
var fnames = this.program && this.opts.validFunctions;
|
||||
@ -119,18 +122,13 @@ export class BASICRuntime {
|
||||
}
|
||||
|
||||
getLineForPC(pc:number) {
|
||||
var line;
|
||||
do {
|
||||
line = this.pc2line.get(pc);
|
||||
if (line != null) break;
|
||||
} while (--pc >= 0);
|
||||
return line;
|
||||
var stmt = this.allstmts[pc];
|
||||
return stmt && stmt.$loc && stmt.$loc.line;
|
||||
}
|
||||
|
||||
getLabelForPC(pc:number) {
|
||||
var lineno = this.getLineForPC(pc);
|
||||
var pgmline = this.program.lines[lineno];
|
||||
return pgmline ? pgmline.label : '?';
|
||||
var stmt = this.allstmts[pc];
|
||||
return stmt && stmt.$loc && stmt.$loc.label;
|
||||
}
|
||||
|
||||
getCurrentSourceLocation() : SourceLocation {
|
||||
@ -138,6 +136,11 @@ export class BASICRuntime {
|
||||
return stmt && stmt.$loc;
|
||||
}
|
||||
|
||||
getCurrentLabel() : string {
|
||||
var loc = this.getCurrentSourceLocation();
|
||||
return loc && loc.label;
|
||||
}
|
||||
|
||||
getStatement() {
|
||||
return this.allstmts[this.curpc];
|
||||
}
|
||||
@ -439,6 +442,13 @@ export class BASICRuntime {
|
||||
if (value < 1 || value > labels.length)
|
||||
this.runtimeError(`I needed a number between 1 and ${labels.length}, but I got ${value}.`);
|
||||
this.gotoLabel(labels[value-1]);
|
||||
|
||||
}
|
||||
onGosubLabel(value: number, ...labels: string[]) {
|
||||
value = this.ROUND(value);
|
||||
if (value < 1 || value > labels.length)
|
||||
this.runtimeError(`I needed a number between 1 and ${labels.length}, but I got ${value}.`);
|
||||
this.gosubLabel(labels[value-1]);
|
||||
}
|
||||
|
||||
nextDatum() : basic.Value {
|
||||
@ -550,7 +560,10 @@ export class BASICRuntime {
|
||||
do__ONGOTO(stmt : basic.ONGOTO_Statement) {
|
||||
var expr = this.expr2js(stmt.expr);
|
||||
var labels = stmt.labels.map((arg) => this.expr2js(arg, {isconst:true})).join(', ');
|
||||
if (stmt.command == 'ONGOTO')
|
||||
return `this.onGotoLabel(${expr}, ${labels})`;
|
||||
else
|
||||
return `this.onGosubLabel(${expr}, ${labels})`;
|
||||
}
|
||||
|
||||
do__DATA() {
|
||||
@ -596,6 +609,10 @@ export class BASICRuntime {
|
||||
})`;
|
||||
}
|
||||
|
||||
do__CLEAR() {
|
||||
return 'this.clearVars()';
|
||||
}
|
||||
|
||||
// TODO: ONERR, ON ERROR GOTO
|
||||
// TODO: "SUBSCRIPT ERROR" (range check)
|
||||
// TODO: gosubs nested too deeply
|
||||
|
@ -173,7 +173,17 @@ class BASICPlatform implements Platform {
|
||||
$.extend(true, this.runtime, state);
|
||||
}
|
||||
getDebugTree() {
|
||||
return this.runtime;
|
||||
return {
|
||||
Variables: this.runtime.vars,
|
||||
Arrays: this.runtime.arrays,
|
||||
Functions: this.runtime.defs,
|
||||
ForLoops: this.runtime.forLoops,
|
||||
ReturnStack: this.runtime.returnStack,
|
||||
CurrentLine: this.runtime.getCurrentLabel(),
|
||||
NextDatum: this.runtime.datums[this.runtime.dataptr],
|
||||
Dialect: this.runtime.opts,
|
||||
Internals: this.runtime,
|
||||
}
|
||||
}
|
||||
inspect(sym: string) {
|
||||
var o = this.runtime.vars[sym];
|
||||
|
Loading…
Reference in New Issue
Block a user