mirror of
https://github.com/sehugg/8bitworkshop.git
synced 2024-10-30 00:29:53 +00:00
8 lines
81 KiB
Plaintext
8 lines
81 KiB
Plaintext
{
|
|
"version": 3,
|
|
"sources": ["../src/common/basic/runtime.ts", "../src/platform/basic.ts"],
|
|
"sourcesContent": ["\nimport * as basic from \"./compiler\";\nimport { EmuHalt } from \"../emu\";\nimport { SourceLocation } from \"../workertypes\";\nimport { isArray } from \"../util\";\n\nfunction isLiteral(arg: basic.Expr): arg is basic.Literal {\n return (arg as any).value != null;\n}\nfunction isLookup(arg: basic.Expr): arg is basic.IndOp {\n return (arg as any).name != null;\n}\nfunction isBinOp(arg: basic.Expr): arg is basic.BinOp {\n return (arg as any).op != null && (arg as any).left != null && (arg as any).right != null;\n}\nfunction isUnOp(arg: basic.Expr): arg is basic.UnOp {\n return (arg as any).op != null && (arg as any).expr != null;\n}\n\nexport interface InputResponse {\n line: string;\n vals: string[];\n elapsed?: number;\n}\n\n// expr2js() options\nclass ExprOptions {\n isconst?: boolean; // only allow constant operations\n novalid?: boolean; // check for valid values when fetching\n locals?: string[]; // pass local variable names when defining functions\n}\n\ninterface CompiledStatement {\n $run?: () => void;\n}\n\nclass RNG {\n next : () => number;\n seed : (aa,bb,cc,dd) => void;\n seedfloat : (n) => void;\n randomize() {\n this.seed(Math.random()*0x7fffffff, Math.random()*0x7fffffff, Math.random()*0x7fffffff, Math.random()*0x7fffffff);\n }\n constructor() {\n let f = () => {\n var a, b, c, d : number;\n this.seed = function(aa,bb,cc,dd) {\n a = aa; b = bb; c = cc; d = dd;\n }\n this.seedfloat = function(n) {\n this.seed(n, n*4294, n*429496, n*4294967296);\n this.next(); this.next(); this.next();\n }\n this.next = function() {\n // sfc32\n a >>>= 0; b >>>= 0; c >>>= 0; d >>>= 0; \n var t = (a + b) | 0;\n a = b ^ b >>> 9;\n b = c + (c << 3) | 0;\n c = (c << 21 | c >>> 11);\n d = d + 1 | 0;\n t = t + d | 0;\n c = c + t | 0;\n return (t >>> 0) / 4294967296;\n }\n };\n f();\n this.seedfloat(-1);\n }\n};\n\nconst DEFAULT_MAX_ARRAY_ELEMENTS = 1024*1024;\n\nexport class BASICRuntime {\n\n program : basic.BASICProgram;\n allstmts : basic.Statement[];\n pc2label : Map<number,string>;\n label2pc : {[label : string] : number};\n label2dataptr : {[label : string] : number};\n datums : basic.Literal[];\n builtins : {};\n opts : basic.BASICOptions;\n margin : number = 80; // number of columns\n\n curpc : number;\n dataptr : number;\n vars : {[name:string] : any}; // actually Value, but += doesn't work\n globals : {[name:string] : any};\n arrays : {};\n defs : {};\n subroutines : {};\n forLoops : { [varname:string] : { $next:(name:string) => void } };\n forLoopStack: string[];\n whileLoops : number[];\n returnStack : number[];\n column : number;\n rng : RNG;\n\n running : boolean = false;\n exited : boolean = true;\n trace : boolean = false;\n\n load(program: basic.BASICProgram) : boolean {\n // get previous label and offset for hot reload\n let prevlabel = null;\n let prevpcofs = 0;\n if (this.pc2label != null) {\n let pc = this.curpc;\n while (pc > 0 && (prevlabel = this.pc2label.get(pc)) == null) {\n pc--;\n }\n prevpcofs = this.curpc - pc;\n console.log('oldpc=', this.curpc, 'restart @ label', prevlabel, '+', prevpcofs);\n }\n // initialize program\n this.program = program;\n this.opts = program.opts;\n if (!this.opts.maxArrayElements) this.opts.maxArrayElements = DEFAULT_MAX_ARRAY_ELEMENTS;\n this.allstmts = program.stmts;\n this.label2pc = program.labels;\n this.label2dataptr = {};\n this.pc2label = new Map();\n this.datums = [];\n this.subroutines = {};\n this.builtins = this.getBuiltinFunctions();\n // TODO: detect undeclared vars\n // build PC -> label lookup\n for (var label in program.labels) {\n var targetpc = program.labels[label];\n this.pc2label.set(targetpc, label);\n }\n // iterate through all the statements\n this.allstmts.forEach((stmt, pc) => {\n // compile statements ahead of time\n this.curpc = pc + 1; // for error reporting\n this.compileStatement(stmt);\n // parse DATA literals\n if (stmt.command == 'DATA') {\n this.label2dataptr[stmt.$loc.label] = this.datums.length;\n (stmt as basic.DATA_Statement).datums.forEach(datum => {\n this.curpc = stmt.$loc.offset; // for error reporting\n this.datums.push(datum);\n });\n }\n });\n // try to resume where we left off after loading\n if (this.label2pc[prevlabel] != null) {\n this.curpc = this.label2pc[prevlabel] + prevpcofs;\n return true;\n } else {\n this.curpc = 0;\n return false;\n }\n }\n\n reset() {\n this.curpc = 0;\n this.dataptr = 0;\n this.clearVars();\n this.returnStack = [];\n this.column = 0;\n this.running = true;\n this.exited = false;\n }\n clearVars() {\n this.globals = this.vars = {};\n this.arrays = {};\n this.defs = {}; // TODO? only in interpreters\n this.forLoops = {};\n this.forLoopStack = [];\n this.whileLoops = [];\n this.rng = new RNG();\n // initialize arrays?\n if (this.opts && this.opts.staticArrays) {\n this.allstmts.filter((stmt) => stmt.command == 'DIM').forEach((dimstmt: basic.DIM_Statement) => {\n dimstmt.args.forEach( (arg) => this.compileJS(this._DIM(arg))() );\n });\n }\n }\n \n // TODO: saveState(), loadState()\n saveState() {\n // TODO: linked list loop?\n return $.extend(true, {}, this);\n }\n loadState(state) {\n $.extend(true, this, state);\n }\n \n getBuiltinFunctions() {\n var fnames = this.program && this.opts.validFunctions;\n // if no valid function list, look for ABC...() functions in prototype\n if (!fnames) fnames = Object.getOwnPropertyNames(BASICRuntime.prototype).filter((name) => /^[A-Z]{3,}[$]?$/.test(name));\n var dict = {};\n for (var fn of fnames) if (this.supportsFunction(fn)) dict[fn] = this[fn].bind(this);\n return dict;\n }\n supportsFunction(fnname: string) {\n return typeof this[fnname] === 'function';\n }\n\n runtimeError(msg : string) {\n this.curpc--; // we did curpc++ before executing statement\n throw new EmuHalt(msg, this.getCurrentSourceLocation());\n }\n \n dialectError(what : string) {\n this.runtimeError(`I can't ${what} in this dialect of BASIC.`);\n }\n\n getLineForPC(pc:number) {\n var stmt = this.allstmts[pc];\n return stmt && stmt.$loc && stmt.$loc.line;\n }\n\n getLabelForPC(pc:number) {\n var stmt = this.allstmts[pc];\n return stmt && stmt.$loc && stmt.$loc.label;\n }\n\n getCurrentSourceLocation() : SourceLocation {\n var stmt = this.getStatement();\n return stmt && stmt.$loc;\n }\n\n getCurrentLabel() : string {\n var loc = this.getCurrentSourceLocation();\n return loc && loc.label;\n }\n\n getStatement() {\n return this.allstmts[this.curpc];\n }\n\n step() : boolean {\n if (!this.running) return false;\n var stmt = this.getStatement();\n // end of program?\n if (!stmt) {\n this.running = false;\n this.exited = true;\n return false;\n }\n if (this.trace) console.log(this.curpc, stmt, this.vars, Object.keys(this.arrays));\n // skip to next statment\n this.curpc++;\n // compile (unless cached) and execute statement\n this.executeStatement(stmt);\n return this.running;\n }\n\n compileStatement(stmt: basic.Statement & CompiledStatement) {\n if (stmt.$run == null) {\n try {\n var stmtfn = this['do__' + stmt.command];\n if (stmtfn == null) this.runtimeError(`I don't know how to \"${stmt.command}\".`);\n var functext = stmtfn.bind(this)(stmt);\n if (this.trace) console.log(functext);\n stmt.$run = this.compileJS(functext);\n } catch (e) {\n if (functext) console.log(functext);\n throw e;\n }\n }\n }\n compileJS(functext: string) : () => void {\n return new Function(functext).bind(this);\n }\n executeStatement(stmt: basic.Statement & CompiledStatement) {\n // compile (unless cached)\n this.compileStatement(stmt);\n // run compiled statement\n stmt.$run();\n }\n\n // TODO: this only works because each line has a label\n skipToEOL() {\n do {\n this.curpc++;\n } while (this.curpc < this.allstmts.length && !this.pc2label.get(this.curpc));\n }\n\n skipToElse() {\n while (this.curpc < this.allstmts.length) {\n // in Altair BASIC, ELSE is bound to the right-most IF\n // TODO: this is complicated, we should just have nested expressions\n var cmd = this.allstmts[this.curpc].command;\n if (cmd == 'ELSE') { this.curpc++; break; }\n else if (cmd == 'IF') return this.skipToEOL();\n this.curpc++;\n if (this.pc2label.get(this.curpc))\n break;\n }\n }\n\n skipToEOF() {\n this.curpc = this.allstmts.length;\n }\n\n skipToAfterNext(forname: string) : void {\n var pc = this.curpc;\n while (pc < this.allstmts.length) {\n var stmt = this.allstmts[pc];\n if (stmt.command == 'NEXT') {\n var nextlexpr = (stmt as basic.NEXT_Statement).lexpr;\n if (nextlexpr && nextlexpr.name == forname) {\n this.curpc = pc + 1;\n return;\n }\n }\n pc++;\n }\n this.runtimeError(`I couldn't find a matching NEXT ${forname} to skip this for loop.`);\n }\n\n skipToAfterWend() {\n var pc = this.curpc - 1;\n var nesting = 0;\n while (pc < this.allstmts.length) {\n var stmt = this.allstmts[pc];\n //console.log(nesting, pc, stmt);\n if (stmt.command == 'WHILE') {\n nesting++;\n } else if (stmt.command == 'WEND') {\n nesting--;\n if (nesting == 0) {\n this.curpc = pc + 1;\n return;\n }\n }\n pc++;\n }\n this.runtimeError(`I couldn't find a matching WEND for this WHILE.`);\n }\n\n gotoLabel(label) {\n var pc = this.label2pc[label];\n if (pc >= 0) {\n this.curpc = pc;\n } else {\n this.runtimeError(`I tried to go to the label \"${label}\" but couldn't find it.`);\n }\n }\n\n newLocalScope() {\n this.vars = Object.create(this.vars);\n }\n \n popLocalScope() {\n if (this.vars !== this.globals)\n this.vars = Object.getPrototypeOf(this.vars);\n }\n\n gosubLabel(label) {\n if (this.returnStack.length > 32767) // TODO: const?\n this.runtimeError(`I did too many GOSUBs without a RETURN.`)\n this.returnStack.push(this.curpc);\n this.gotoLabel(label);\n }\n\n returnFromGosub() {\n if (this.returnStack.length == 0)\n this.runtimeError(\"I tried to RETURN, but there wasn't a corresponding GOSUB.\"); // RETURN BEFORE GOSUB\n var pc = this.returnStack.pop();\n this.curpc = pc;\n this.popLocalScope();\n }\n\n popReturnStack() {\n if (this.returnStack.length == 0)\n this.runtimeError(\"I tried to POP, but there wasn't a corresponding GOSUB.\");\n this.returnStack.pop();\n }\n\n valueToString(obj:basic.Value, padding:boolean) : string {\n var str;\n if (typeof obj === 'number') {\n var numstr = this.float2str(obj, this.opts.printZoneLength - 4);\n if (!padding)\n return numstr;\n else if (numstr.startsWith('-'))\n return `${numstr} `;\n else\n return ` ${numstr} `;\n } else if (obj == '\\n') {\n this.column = 0;\n str = obj;\n } else if (obj == '\\t') {\n var l = this.opts.printZoneLength;\n var curgroup = Math.floor(this.column / l);\n var nextcol = (curgroup + 1) * this.opts.printZoneLength;\n if (nextcol+l > this.margin) { this.column = 0; str = \"\\n\"; } // return to left margin\n else str = this.TAB(nextcol); // next column\n } else {\n str = `${obj}`;\n }\n return str;\n }\n\n float2str(arg: number, numlen: number) : string {\n var numstr = arg.toString().toUpperCase();\n if (numlen > 0) {\n var prec = numlen;\n while (numstr.length > numlen) {\n numstr = arg.toPrecision(prec--);\n }\n if (numstr.startsWith('0.'))\n numstr = numstr.substr(1);\n else if (numstr.startsWith('-0.'))\n numstr = '-'+numstr.substr(2);\n }\n return numstr;\n }\n\n printExpr(obj) {\n var str = this.valueToString(obj, this.opts.numericPadding);\n this.column += str.length;\n this.print(str);\n }\n\n // override this\n print(str: string) {\n console.log(str);\n }\n\n // override this\n async input(prompt: string, nargs: number) : Promise<InputResponse> {\n return {line:\"\", vals:[]};\n }\n\n // override this\n resume() { }\n\n expr2js(expr: basic.Expr, opts?: ExprOptions) : string {\n if (!opts) opts = {};\n if (isLiteral(expr)) {\n return JSON.stringify(expr.value);\n } else if (isLookup(expr)) {\n if (!expr.args && opts.locals && opts.locals.indexOf(expr.name) >= 0) {\n return expr.name; // local arg in DEF\n } else {\n if (opts.isconst)\n this.runtimeError(`I expected a constant value here.`); // TODO: check at compile-time?\n var s = '';\n var qname = JSON.stringify(expr.name);\n let jsargs = expr.args ? expr.args.map((arg) => this.expr2js(arg, opts)).join(', ') : [];\n if (expr.name.startsWith(\"FN\")) { // is it a user-defined function?\n // TODO: check argument count?\n s += `this.getDef(${qname})(${jsargs})`;\n // TODO: detect recursion?\n } else if (this.builtins[expr.name]) { // is it a built-in function?\n this.checkFuncArgs(expr, this.builtins[expr.name]);\n s += `this.builtins.${expr.name}(${jsargs})`;\n } else if (expr.args) {\n // get array slice (HP BASIC)\n if (this.opts.arraysContainChars && expr.name.endsWith('$'))\n s += `this.getStringSlice(this.vars.${expr.name}, ${jsargs})`;\n else\n s += `this.arrayGet(${qname}, ${jsargs})`;\n } else { // just a variable\n s += `this.vars.${expr.name}`;\n }\n return opts.novalid ? s : `this.checkValue(${s}, ${qname})`;\n }\n } else if (isBinOp(expr)) {\n var left = this.expr2js(expr.left, opts);\n var right = this.expr2js(expr.right, opts);\n return `this.${expr.op}(${left}, ${right})`;\n } else if (isUnOp(expr)) {\n var e = this.expr2js(expr.expr, opts);\n return `this.${expr.op}(${e})`;\n }\n }\n\n assign2js(expr: basic.IndOp, opts?: ExprOptions) : string {\n if (!opts) opts = {};\n var s = '';\n // is it a function? not allowed\n if (expr.name.startsWith(\"FN\") || this.builtins[expr.name])\n this.runtimeError(`I can't call a function here.`);\n // is it a subscript?\n if (expr.args) {\n // TODO: set array slice (HP BASIC)\n if (this.opts.arraysContainChars && expr.name.endsWith('$')) {\n this.runtimeError(`I can't set array slices via this command yet.`);\n } else {\n s += this.array2js(expr, opts);\n }\n } else { // just a variable\n s = `this.globals.${expr.name}`;\n }\n return s;\n }\n\n array2js(expr: basic.IndOp, opts?: ExprOptions) : string {\n var qname = JSON.stringify(expr.name);\n var args = expr.args || [];\n return this.expr2js(expr, {novalid:true}) // check array bounds\n + `;this.getArray(${qname}, ${args.length})`\n + args.map((arg) => '[this.ROUND('+this.expr2js(arg, opts)+')]').join('');\n }\n\n checkFuncArgs(expr: basic.IndOp, fn: Function) {\n // TODO: check types?\n var nargs = expr.args ? expr.args.length : 0;\n // exceptions\n if (expr.name == 'RND' && nargs == 0) return;\n if (expr.name == 'MID$' && nargs == 2) return;\n if (expr.name == 'INSTR' && nargs == 2) return;\n if (fn.length != nargs)\n this.runtimeError(`I expected ${fn.length} arguments for the ${expr.name} function, but I got ${nargs}.`);\n }\n\n startForLoop(forname:string, init:number, targ:number, step?:number, endpc?:number) {\n // save start PC and label in case of hot reload (only works if FOR is first stmt in line)\n var looppc = this.curpc - 1;\n var looplabel = this.pc2label.get(looppc);\n if (!step) step = 1;\n this.vars[forname] = init;\n if (this.trace) console.log(`FOR ${forname} = ${init} TO ${targ} STEP ${step}`);\n // create done function\n var loopdone = () => {\n return step >= 0 ? this.vars[forname] > targ : this.vars[forname] < targ;\n }\n // skip entire for loop before first iteration? (Minimal BASIC)\n if (this.opts.testInitialFor && loopdone()) {\n if (endpc != null)\n this.curpc = endpc+1;\n else\n this.skipToAfterNext(forname);\n }\n // save for var name on stack, remove existing entry\n if (this.forLoopStack[forname] != null)\n this.forLoopStack = this.forLoopStack.filter((n) => n == forname);\n this.forLoopStack.push(forname);\n // create for loop record\n this.forLoops[forname] = {\n $next: (nextname:string) => {\n if (nextname && forname != nextname)\n this.runtimeError(`I executed NEXT \"${nextname}\", but the last FOR was for \"${forname}\".`)\n this.vars[forname] += step;\n var done = loopdone();\n if (done) {\n // delete entry, pop FOR off the stack and continue\n this.forLoopStack.pop();\n delete this.forLoops[forname];\n } else {\n // go back to FOR loop, adjusting for hot reload (fetch pc by label)\n this.curpc = ((looplabel != null && this.label2pc[looplabel]) || looppc) + 1;\n }\n if (this.trace) console.log(`NEXT ${forname}: ${this.vars[forname]} TO ${targ} STEP ${step} DONE=${done}`);\n }\n };\n }\n\n nextForLoop(name) {\n // get FOR loop entry, or get top of stack if NEXT var is optional \n var fl = this.forLoops[name || (this.opts.optionalNextVar && this.forLoopStack[this.forLoopStack.length-1])];\n if (!fl) this.runtimeError(`I couldn't find a matching FOR for this NEXT.`)\n fl.$next(name);\n }\n\n whileLoop(cond) {\n if (cond) {\n this.whileLoops.push(this.curpc-1);\n } else {\n this.skipToAfterWend();\n }\n }\n\n nextWhileLoop() {\n var pc = this.whileLoops.pop();\n if (pc == null) this.runtimeError(`I couldn't find a matching WHILE for this WEND.`);\n else this.curpc = pc;\n }\n\n // converts a variable to string/number based on var name\n assign(name: string, right: number|string, isRead?:boolean) : number|string {\n // convert data? READ always converts if read into string\n if (isRead && name.endsWith(\"$\"))\n return this.checkValue(this.convert(name, right), name);\n // TODO: use options\n if (name.endsWith(\"$\")) {\n return this.convertToString(right, name);\n } else {\n return this.convertToNumber(right, name);\n }\n }\n\n convert(name: string, right: number|string) : number|string {\n if (name.endsWith(\"$\")) {\n return right == null ? \"\" : right.toString();\n } else if (typeof right === 'number') {\n return right;\n } else {\n return parseFloat(right+\"\");\n }\n }\n\n convertToString(right: number|string, name?: string) {\n if (typeof right !== 'string') this.runtimeError(`I can't convert ${right} to a string.`);\n else return right;\n }\n\n convertToNumber(right: number|string, name?: string) {\n if (typeof right !== 'number') this.runtimeError(`I can't convert ${right} to a number.`);\n else return this.checkNum(right);\n }\n\n // dimension array\n dimArray(name: string, ...dims:number[]) {\n // TODO: maybe do this check at compile-time?\n dims = dims.map(Math.round);\n if (this.arrays[name] != null) {\n if (this.opts.staticArrays) return;\n else this.runtimeError(`I already dimensioned this array (${name}) earlier.`)\n }\n var total = this.getTotalArrayLength(dims);\n if (total > this.opts.maxArrayElements)\n this.runtimeError(`I can't create an array with this many elements.`);\n var isstring = name.endsWith('$');\n // if numeric value, we use Float64Array which inits to 0\n var arrcons = isstring ? Array : Float64Array;\n if (dims.length == 1) {\n this.arrays[name] = new arrcons(dims[0]+1);\n } else if (dims.length == 2) {\n this.arrays[name] = new Array(dims[0]+1);\n for (var i=0; i<dims[0]+1; i++) {\n this.arrays[name][i] = new arrcons(dims[1]+1);\n }\n } else {\n this.runtimeError(`I only support arrays of one or two dimensions.`)\n }\n }\n\n getTotalArrayLength(dims:number[]) {\n var n = 1;\n for (var i=0; i<dims.length; i++) {\n if (dims[i] < this.opts.defaultArrayBase)\n this.runtimeError(`I can't create an array with a dimension less than ${this.opts.defaultArrayBase}.`);\n n *= dims[i];\n }\n return n;\n }\n\n getArray(name: string, order: number) : [] {\n if (!this.arrays[name]) {\n if (this.opts.defaultArraySize == 0)\n this.dialectError(`automatically declare arrays without a DIM statement (or did you mean to call a function?)`);\n if (order == 1)\n this.dimArray(name, this.opts.defaultArraySize-1);\n else if (order == 2)\n this.dimArray(name, this.opts.defaultArraySize-1, this.opts.defaultArraySize-1);\n else\n this.runtimeError(`I only support arrays of one or two dimensions.`); // TODO\n }\n return this.arrays[name];\n }\n\n arrayGet(name: string, ...indices: number[]) : basic.Value {\n var arr = this.getArray(name, indices.length);\n indices = indices.map(this.ROUND.bind(this));\n var v = arr;\n for (var i=0; i<indices.length; i++) {\n var idx = indices[i];\n if (!isArray(v))\n this.runtimeError(`I tried to lookup ${name}(${indices}) but used too many dimensions.`);\n if (idx < this.opts.defaultArrayBase)\n this.runtimeError(`I tried to lookup ${name}(${indices}) but an index was less than ${this.opts.defaultArrayBase}.`);\n if (idx >= v.length) // TODO: also can happen when mispelling function name\n this.runtimeError(`I tried to lookup ${name}(${indices}) but it exceeded the dimensions of the array.`);\n v = v[indices[i]];\n }\n if (isArray(v)) // i.e. is an array?\n this.runtimeError(`I tried to lookup ${name}(${indices}) but used too few dimensions.`);\n return (v as any) as basic.Value;\n }\n\n // for HP BASIC string slicing (TODO?)\n modifyStringSlice(orig: string, add: string, start: number, end: number) : string {\n orig = orig || \"\";\n this.checkString(orig);\n this.checkString(add);\n if (!end) end = start;\n start = this.ROUND(start);\n end = this.ROUND(end);\n if (start < 1) this.dialectError(`accept a string slice index less than 1`);\n if (end < start) this.dialectError(`accept a string slice index less than the starting index`);\n return (orig + ' '.repeat(start)).substr(0, start-1) + add.substr(0, end+1-start) + orig.substr(end);\n }\n\n getStringSlice(s: string, start: number, end: number) {\n s = this.checkString(s);\n start = this.ROUND(start);\n if (start < 1) this.dialectError(`accept a string slice index less than 1`);\n if (end != null) {\n end = this.ROUND(end);\n if (end < start) this.dialectError(`accept a string slice index less than the starting index`);\n return s.substr(start-1, end+1-start);\n } else {\n return s.substr(start-1);\n }\n }\n\n checkOnGoto(value: number, labels: string[]) {\n value = this.ROUND(value);\n if (value < 0) // > 255 ?\n this.runtimeError(`I needed a number between 1 and ${labels.length}, but I got ${value}.`);\n if (this.opts.checkOnGotoIndex && (value < 1 || value > labels.length))\n this.runtimeError(`I needed a number between 1 and ${labels.length}, but I got ${value}.`);\n if (value < 1 || value > labels.length)\n return 0;\n return value;\n }\n \n onGotoLabel(value: number, ...labels: string[]) {\n value = this.checkOnGoto(value, labels);\n if (value) this.gotoLabel(labels[value-1]);\n }\n onGosubLabel(value: number, ...labels: string[]) {\n value = this.checkOnGoto(value, labels);\n if (value) this.gosubLabel(labels[value-1]);\n }\n\n nextDatum() : basic.Value {\n if (this.dataptr >= this.datums.length)\n this.runtimeError(\"I tried to READ, but ran out of data.\");\n return this.datums[this.dataptr++].value;\n }\n\n //// STATEMENTS\n\n do__PRINT(stmt : basic.PRINT_Statement) {\n var s = '';\n for (var arg of stmt.args) {\n var expr = this.expr2js(arg);\n var name = (expr as any).name;\n s += `this.printExpr(this.checkValue(${expr}, ${JSON.stringify(name)}));`;\n }\n return s;\n }\n\n preInput() {\n this.running=false;\n this.curpc--;\n }\n\n postInput(valid : boolean) {\n if (valid) this.curpc++;\n this.running = true;\n this.resume();\n }\n\n do__INPUT(stmt : basic.INPUT_Statement) {\n var prompt = stmt.prompt != null ? this.expr2js(stmt.prompt) : '\"\"';\n var elapsed = stmt.elapsed != null ? this.assign2js(stmt.elapsed) : \"let ___\";\n var setvals = '';\n stmt.args.forEach((arg, index) => {\n var lexpr = this.assign2js(arg);\n setvals += `\n var value = this.convert(${JSON.stringify(arg.name)}, response.vals[${index}]);\n valid &= this.isValid(value);\n ${lexpr} = value;\n `\n });\n return `this.preInput();\n this.input(${prompt}, ${stmt.args.length}).then((response) => {\n let valid = 1;\n ${setvals}\n this.postInput(valid);\n this.column = 0; // assume linefeed\n ${elapsed} = response.elapsed;\n })`;\n }\n\n do__LET(stmt : basic.LET_Statement) {\n var right = this.expr2js(stmt.right);\n var s = `let _right = ${right};`;\n for (var lexpr of stmt.lexprs) {\n // HP BASIC string-slice syntax?\n if (this.opts.arraysContainChars && lexpr.args && lexpr.name.endsWith('$')) {\n s += `this.globals.${lexpr.name} = this.modifyStringSlice(this.vars.${lexpr.name}, _right, `\n s += lexpr.args.map((arg) => this.expr2js(arg)).join(', ');\n s += ');';\n } else {\n var ljs = this.assign2js(lexpr);\n s += `${ljs} = this.assign(${JSON.stringify(lexpr.name)}, _right);`;\n }\n }\n return s;\n }\n\n do__FOR(stmt : basic.FOR_Statement) {\n var name = JSON.stringify(stmt.lexpr.name);\n var init = this.expr2js(stmt.initial);\n var targ = this.expr2js(stmt.target);\n var step = stmt.step ? this.expr2js(stmt.step) : 'null';\n return `this.startForLoop(${name}, ${init}, ${targ}, ${step}, ${stmt.endpc})`;\n }\n\n do__NEXT(stmt : basic.NEXT_Statement) {\n var name = stmt.lexpr && JSON.stringify(stmt.lexpr.name);\n return `this.nextForLoop(${name})`;\n }\n\n do__IF(stmt : basic.IF_Statement) {\n var cond = this.expr2js(stmt.cond);\n if (stmt.endpc != null)\n return `if (!(${cond})) { this.curpc = ${stmt.endpc}; }`\n else\n return `if (!(${cond})) { this.skipToElse(); }`\n }\n\n do__ELSE(stmt : basic.ELSE_Statement) {\n if (stmt.endpc != null)\n return `this.curpc = ${stmt.endpc}`\n else\n return `this.skipToEOL()`\n }\n\n do__WHILE(stmt : basic.WHILE_Statement) {\n var cond = this.expr2js(stmt.cond);\n if (stmt.endpc != null)\n return `if (!(${cond})) { this.curpc = ${stmt.endpc+1}; }`;\n else\n return `this.whileLoop(${cond})`;\n }\n\n do__WEND(stmt : basic.WEND_Statement) {\n if (stmt.startpc != null)\n return `this.curpc = ${stmt.startpc}`;\n else\n return `this.nextWhileLoop()`\n }\n\n do__DEF(stmt : basic.DEF_Statement) {\n var args = [];\n for (var arg of stmt.lexpr.args || []) {\n if (isLookup(arg)) {\n args.push(arg.name);\n } else {\n this.runtimeError(\"I found a DEF statement with arguments other than variable names.\");\n }\n }\n var functext = this.expr2js(stmt.def, {locals:args});\n //this.defs[stmt.lexpr.name] = new Function(args.join(','), functext).bind(this);\n return `this.defs.${stmt.lexpr.name} = function(${args.join(',')}) { return ${functext}; }.bind(this)`;\n }\n\n _DIM(dim : basic.IndOp) {\n // HP BASIC doesn't really have string arrays, just strings\n if (this.opts.arraysContainChars && dim.name.endsWith('$'))\n return '';\n // dimension an array\n var argsstr = '';\n for (var arg of dim.args) {\n argsstr += ', ' + this.expr2js(arg, {isconst: this.opts.staticArrays});\n }\n return `this.dimArray(${JSON.stringify(dim.name)}${argsstr});`;\n }\n\n do__DIM(stmt : basic.DIM_Statement) {\n if (this.opts.staticArrays) return; // DIM at reset()\n var s = '';\n stmt.args.forEach((dim) => s += this._DIM(dim));\n return s;\n }\n\n do__GOTO(stmt : basic.GOTO_Statement) {\n var label = this.expr2js(stmt.label);\n return `this.gotoLabel(${label})`;\n }\n\n do__GOSUB(stmt : basic.GOSUB_Statement) {\n var label = this.expr2js(stmt.label);\n return `this.gosubLabel(${label})`;\n }\n\n do__RETURN(stmt : basic.RETURN_Statement) {\n return `this.returnFromGosub()`;\n }\n\n do__ONGOTO(stmt : basic.ONGO_Statement) {\n var expr = this.expr2js(stmt.expr);\n var labels = stmt.labels.map((arg) => this.expr2js(arg, {isconst:true})).join(', ');\n if (stmt.command == 'ONGOTO')\n return `this.onGotoLabel(${expr}, ${labels})`;\n else\n return `this.onGosubLabel(${expr}, ${labels})`;\n }\n\n do__ONGOSUB(stmt : basic.ONGO_Statement) {\n return this.do__ONGOTO(stmt);\n }\n\n do__DATA() {\n // data is preprocessed\n }\n\n do__READ(stmt : basic.READ_Statement) {\n var s = '';\n stmt.args.forEach((arg) => {\n s += `${this.assign2js(arg)} = this.assign(${JSON.stringify(arg.name)}, this.nextDatum(), true);`;\n });\n return s;\n }\n\n do__RESTORE(stmt : basic.RESTORE_Statement) {\n if (stmt.label != null)\n return `this.dataptr = this.label2dataptr[${this.expr2js(stmt.label, {isconst:true})}] || 0`;\n else\n return `this.dataptr = 0`;\n }\n\n do__END() {\n return `this.skipToEOF()`;\n }\n\n do__STOP() {\n return `this.skipToEOF()`;\n }\n\n do__OPTION(stmt: basic.OPTION_Statement) {\n // already parsed in compiler\n }\n\n do__POP() {\n return `this.popReturnStack()`;\n }\n\n do__GET(stmt : basic.GET_Statement) {\n var lexpr = this.assign2js(stmt.lexpr);\n // TODO: single key input\n return `this.preInput();\n this.input().then((vals) => {\n ${lexpr} = this.convert(${JSON.stringify(stmt.lexpr.name)}, vals[0]);\n this.postInput(true);\n })`;\n }\n\n do__CLEAR() {\n return 'this.clearVars()';\n }\n\n do__RANDOMIZE() {\n return `this.rng.randomize()`;\n }\n\n do__CHANGE(stmt : basic.CHANGE_Statement) {\n var arr2str = stmt.dest.name.endsWith('$');\n if (arr2str) { // array -> string\n let arrname = (stmt.src as basic.IndOp).name || this.runtimeError(\"I can only change to a string from an array.\");\n let dest = this.assign2js(stmt.dest);\n return `\n let arrname = ${JSON.stringify(arrname)};\n let len = this.arrayGet(arrname, 0);\n let s = '';\n for (let i=0; i<len; i++) {\n s += String.fromCharCode(this.arrayGet(arrname, i+1));\n }\n ${dest} = s;\n `;\n } else { // string -> array\n let src = this.expr2js(stmt.src);\n let dest = this.array2js(stmt.dest);\n return `\n let src = ${src}+\"\";\n ${dest}[0] = src.length;\n for (let i=0; i<src.length; i++) {\n ${dest}[i+1] = src.charCodeAt(i);\n }\n `;\n }\n }\n\n do__CONVERT(stmt : basic.CONVERT_Statement) {\n var num2str = stmt.dest.name.endsWith('$');\n let src = this.expr2js(stmt.src);\n let dest = this.assign2js(stmt.dest);\n if (num2str) {\n return `${dest} = this.valueToString(${src}, false)`;\n } else {\n return `${dest} = this.VAL(${src})`;\n }\n }\n\n do__SUB(stmt: basic.SUB_Statement) {\n this.subroutines[stmt.lexpr.name] = stmt;\n // skip the SUB definition\n return `this.curpc = ${stmt.endpc}`\n }\n\n do__CALL(stmt: basic.CALL_Statement) {\n var substmt : basic.SUB_Statement = this.subroutines[stmt.call.name];\n if (substmt == null)\n this.runtimeError(`I can't find a subroutine named \"${stmt.call.name}\".`);\n var subargs = substmt.lexpr.args || [];\n var callargs = stmt.call.args || [];\n if (subargs.length != callargs.length)\n this.runtimeError(`I tried to call ${stmt.call.name} with the wrong number of parameters.`);\n var s = '';\n s += `this.gosubLabel(${JSON.stringify(stmt.call.name)});`\n s += `this.newLocalScope();`\n for (var i=0; i<subargs.length; i++) {\n var arg = subargs[i] as basic.IndOp;\n s += `this.vars.${arg.name} = ${this.expr2js(callargs[i])};`\n }\n return s;\n }\n\n // TODO: ONERR, ON ERROR GOTO\n // TODO: memory quota\n // TODO: useless loop (! 4th edition)\n // TODO: other 4th edition errors\n // TODO: ecma55 all-or-none input checking?\n\n // FUNCTIONS\n\n isValid(obj:number|string) : boolean {\n if (typeof obj === 'number' && !isNaN(obj) && (!this.opts.checkOverflow || isFinite(obj)))\n return true;\n else if (typeof obj === 'string')\n return true;\n else\n return false;\n }\n checkValue(obj:number|string, exprname:string) : number|string {\n // check for unreferenced value\n if (typeof obj !== 'number' && typeof obj !== 'string') {\n // assign default value?\n if (obj == null && this.opts.defaultValues) {\n return exprname.endsWith(\"$\") ? \"\" : 0;\n }\n if (exprname != null && obj == null) {\n this.runtimeError(`I haven't assigned a value to ${exprname}.`);\n } else if (exprname != null) {\n this.runtimeError(`I got an invalid value for ${exprname}: ${obj}`);\n } else {\n this.runtimeError(`I got an invalid value: ${obj}`);\n }\n }\n return obj;\n }\n getDef(exprname: string) {\n var fn = this.defs[exprname];\n if (!fn) this.runtimeError(`I haven't run a DEF statement for ${exprname}.`);\n return fn;\n }\n checkNum(n:number) : number {\n this.checkValue(n, 'this');\n if (n === Infinity) this.runtimeError(`I computed a number too big to store.`);\n if (isNaN(n)) this.runtimeError(`I computed an invalid number.`);\n return n;\n }\n checkString(s:string) : string {\n this.checkValue(s, 'this');\n if (typeof s !== 'string')\n this.runtimeError(`I expected a string here.`);\n else if (s.length > this.opts.maxStringLength)\n this.dialectError(`create strings longer than ${this.opts.maxStringLength} characters`);\n return s;\n }\n \n add(a, b) : number|string {\n // TODO: if string-concat\n if (typeof a === 'number' && typeof b === 'number')\n return this.checkNum(a + b);\n else if (this.opts.stringConcat)\n return this.checkString(a + b);\n else\n this.dialectError(`use the \"+\" operator to concatenate strings`)\n }\n sub(a:number, b:number) : number {\n return this.checkNum(a - b);\n }\n mul(a:number, b:number) : number {\n return this.checkNum(a * b);\n }\n div(a:number, b:number) : number {\n if (b == 0) this.runtimeError(`I can't divide by zero.`);\n return this.checkNum(a / b);\n }\n idiv(a:number, b:number) : number {\n return this.FIX(this.INT(a) / this.INT(b));\n }\n mod(a:number, b:number) : number {\n return this.checkNum(a % b);\n }\n pow(a:number, b:number) : number {\n if (a == 0 && b < 0) this.runtimeError(`I can't raise zero to a negative power.`);\n return this.checkNum(Math.pow(a, b));\n }\n band(a:number, b:number) : number {\n return a & b;\n }\n bor(a:number, b:number) : number {\n return a | b;\n }\n bnot(a:number) : number {\n return ~a;\n }\n bxor(a:number, b:number) : number {\n return a ^ b;\n }\n bimp(a:number, b:number) : number {\n return this.bor(this.bnot(a), b);\n }\n beqv(a:number, b:number) : number {\n return this.bnot(this.bxor(a, b));\n }\n land(a:number, b:number) : number {\n return a && b ? (this.opts.bitwiseLogic ? -1 : 1) : 0;\n }\n lor(a:number, b:number) : number {\n return a || b ? (this.opts.bitwiseLogic ? -1 : 1) : 0;\n }\n lnot(a:number) : number {\n return a ? 0 : (this.opts.bitwiseLogic ? -1 : 1);\n }\n neg(a:number) : number {\n return -a;\n }\n eq(a:number, b:number) : number {\n return a == b ? (this.opts.bitwiseLogic ? -1 : 1) : 0;\n }\n ne(a:number, b:number) : number {\n return a != b ? (this.opts.bitwiseLogic ? -1 : 1) : 0;\n }\n lt(a:number, b:number) : number {\n return a < b ? (this.opts.bitwiseLogic ? -1 : 1) : 0;\n }\n gt(a:number, b:number) : number {\n return a > b ? (this.opts.bitwiseLogic ? -1 : 1) : 0;\n }\n le(a:number, b:number) : number {\n return a <= b ? (this.opts.bitwiseLogic ? -1 : 1) : 0;\n }\n ge(a:number, b:number) : number {\n return a >= b ? (this.opts.bitwiseLogic ? -1 : 1) : 0;\n }\n min(a:number, b:number) : number {\n return a < b ? a : b;\n }\n max(a:number, b:number) : number {\n return a > b ? a : b;\n }\n\n // FUNCTIONS (uppercase)\n // TODO: swizzle names for type-checking\n\n ABS(arg : number) : number {\n return this.checkNum(Math.abs(arg));\n }\n ASC(arg : string) : number {\n arg = this.checkString(arg);\n if (arg == '') this.runtimeError(`I tried to call ASC() on an empty string.`);\n return arg.charCodeAt(0);\n }\n ATN(arg : number) : number {\n return this.checkNum(Math.atan(arg));\n }\n CHR$(arg : number) : string {\n return String.fromCharCode(this.checkNum(arg));\n }\n CINT(arg : number) : number {\n return this.ROUND(arg);\n }\n COS(arg : number) : number {\n return this.checkNum(Math.cos(arg));\n }\n COT(arg : number) : number {\n return this.checkNum(1.0 / Math.tan(arg)); // 4th edition only\n }\n CTL(arg : number) : string {\n return this.CHR$(arg);\n }\n EXP(arg : number) : number {\n return this.checkNum(Math.exp(arg));\n }\n FIX(arg : number) : number {\n return this.checkNum(arg < 0 ? Math.ceil(arg) : Math.floor(arg));\n }\n HEX$(arg : number) : string {\n return this.ROUND(arg).toString(16);\n }\n INSTR(a, b, c) : number {\n if (c != null) {\n return this.checkString(b).indexOf(this.checkString(c), this.checkNum(a) - 1) + 1;\n } else {\n return this.checkString(a).indexOf(this.checkString(b)) + 1;\n }\n }\n INT(arg : number) : number {\n return this.checkNum(Math.floor(arg));\n }\n LEFT$(arg : string, count : number) : string {\n arg = this.checkString(arg);\n count = this.ROUND(count);\n return arg.substr(0, count);\n }\n LEN(arg : string) : number {\n return this.checkString(arg).length;\n }\n LIN(arg : number) : string {\n return this.STRING$(arg, '\\n');\n }\n LOG(arg : number) : number {\n if (arg == 0) this.runtimeError(`I can't take the logarithm of zero (${arg}).`)\n if (arg < 0) this.runtimeError(`I can't take the logarithm of a negative number (${arg}).`)\n return this.checkNum(Math.log(arg));\n }\n LOG10(arg : number) : number {\n if (arg == 0) this.runtimeError(`I can't take the logarithm of zero (${arg}).`)\n if (arg < 0) this.runtimeError(`I can't take the logarithm of a negative number (${arg}).`)\n return this.checkNum(Math.log10(arg));\n }\n MID$(arg : string, start : number, count : number) : string {\n arg = this.checkString(arg);\n if (!count) count = arg.length;\n start = this.ROUND(start);\n count = this.ROUND(count);\n if (start < 1) this.runtimeError(`I can't compute MID$ if the starting index is less than 1.`)\n return arg.substr(start-1, count);\n }\n OCT$(arg : number) : string {\n return this.ROUND(arg).toString(8);\n }\n PI() : number {\n return Math.PI;\n }\n // TODO: POS(haystack, needle, start)\n POS(arg1, arg2) { // arg ignored\n if (typeof arg1 == 'string' && typeof arg2 == 'string')\n return arg1.indexOf(arg2) >= 0 + 1;\n else\n return this.column + 1;\n }\n RIGHT$(arg : string, count : number) : string {\n arg = this.checkString(arg);\n count = this.ROUND(count);\n return arg.substr(arg.length - count, count);\n }\n RND(arg : number) : number {\n // TODO: X<0 restart w/ seed, X=0 repeats\n if (arg < 0) this.rng.seedfloat(arg);\n return this.rng.next();\n }\n ROUND(arg : number) : number {\n return this.checkNum(Math.round(arg));\n }\n SGN(arg : number) : number {\n this.checkNum(arg);\n return (arg < 0) ? -1 : (arg > 0) ? 1 : 0;\n }\n SIN(arg : number) : number {\n return this.checkNum(Math.sin(arg));\n }\n SPACE$(arg : number) : string {\n return this.STRING$(arg, ' ');\n }\n SPC(arg : number) : string {\n return this.SPACE$(arg);\n }\n SQR(arg : number) : number {\n if (arg < 0) this.runtimeError(`I can't take the square root of a negative number (${arg}).`)\n return this.checkNum(Math.sqrt(arg));\n }\n STR$(arg : number) : string {\n return this.valueToString(this.checkNum(arg), false);\n }\n STRING$(len : number, chr : number|string) : string {\n len = this.ROUND(len);\n if (len <= 0) return '';\n if (len > this.opts.maxStringLength)\n this.dialectError(`create a string longer than ${this.opts.maxStringLength} characters`);\n if (typeof chr === 'string')\n return chr.substr(0,1).repeat(len);\n else\n return String.fromCharCode(chr).repeat(len);\n }\n TAB(arg : number) : string {\n if (arg < 1) { arg = 1; } // TODO: SYSTEM MESSAGE IDENTIFYING THE EXCEPTION\n var spaces = this.ROUND(arg) - 1 - this.column;\n return this.SPACE$(spaces);\n }\n TAN(arg : number) : number {\n return this.checkNum(Math.tan(arg));\n }\n TIM(arg : number) : number { // only HP BASIC?\n var d = new Date();\n switch (this.ROUND(arg)) {\n case 0: return d.getMinutes();\n case 1: return d.getHours();\n case 2:\n var dayCount = [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334];\n var mn = d.getMonth();\n var dn = d.getDate();\n var dayOfYear = dayCount[mn] + dn;\n var isLeapYear = (d.getFullYear() & 3) == 0; // TODO: wrong\n if(mn > 1 && isLeapYear) dayOfYear++;\n return dayOfYear;\n case 3: return d.getFullYear() % 100; // Y@K!\n case 4: return d.getSeconds();\n default: return 0;\n }\n }\n TIMER() : number {\n return Date.now() / 1000;\n }\n UPS$(arg : string) : string {\n return this.checkString(arg).toUpperCase();\n }\n VAL(arg : string) : number {\n var n = parseFloat(this.checkString(arg));\n return isNaN(n) ? 0 : n; // TODO? altair works this way\n }\n LPAD$(arg : string, len : number) : string {\n arg = this.checkString(arg);\n while (arg.length < len) arg = \" \" + arg;\n return arg;\n }\n RPAD$(arg : string, len : number) : string {\n arg = this.checkString(arg);\n while (arg.length < len) arg = arg + \" \";\n return arg;\n }\n NFORMAT$(arg : number, numlen : number) : string {\n var s = this.float2str(arg, numlen);\n return (numlen > 0) ? this.LPAD$(s, numlen) : this.RPAD$(s, -numlen);\n }\n}\n", "\nimport { Platform, BreakpointCallback, DebugCondition, DebugEvalCondition } from \"../common/baseplatform\";\nimport { PLATFORMS, AnimationTimer, EmuHalt } from \"../common/emu\";\nimport * as editors from \"../ide/views/editors\";\nimport { BASICRuntime } from \"../common/basic/runtime\";\nimport { BASICProgram } from \"../common/basic/compiler\";\nimport { TeleTypeWithKeyboard } from \"../common/teletype\";\nimport { lpad } from \"../common/util\";\nimport { FileData } from \"../common/workertypes\";\nimport { haltEmulation } from \"../ide/ui\"; // TODO: make this a callback\n\nconst BASIC_PRESETS = [\n { id: 'hello.bas', name: 'Hello' },\n { id: 'tutorial.bas', name: 'Tutorial' },\n { id: 'sieve.bas', name: 'Sieve Benchmark' },\n { id: 'mortgage.bas', name: 'Interest Calculator' },\n { id: '23match.bas', name: '23 Matches' },\n { id: 'craps.bas', name: 'Craps' },\n { id: 'lander.bas', name: 'Lander' },\n { id: 'hamurabi.bas', name: 'Hammurabi' },\n { id: 'wumpus.bas', name: 'Hunt The Wumpus' },\n { id: 'startrader.bas', name: 'Star Trader' },\n { id: 'haunted.bas', name: 'Haunted House' },\n];\n\nclass BASICPlatform implements Platform {\n mainElement: HTMLElement;\n program: BASICProgram;\n runtime: BASICRuntime;\n clock: number = 0;\n timer: AnimationTimer;\n tty: TeleTypeWithKeyboard;\n hotReload: boolean = true;\n animcount: number = 0;\n internalFiles : {[path:string] : FileData} = {};\n transcript: string[];\n\n constructor(mainElement: HTMLElement) {\n //super();\n this.mainElement = mainElement;\n mainElement.style.overflowY = 'auto';\n }\n\n async start() {\n // create runtime\n this.runtime = new BASICRuntime();\n this.runtime.reset();\n // create divs\n var parent = this.mainElement;\n // TODO: input line should be always flush left\n var gameport = $('<div id=\"gameport\" style=\"margin-top:calc(100vh - 8em)\"/>').appendTo(parent);\n var windowport = $('<div id=\"windowport\" class=\"transcript transcript-style-2\"/>').appendTo(gameport);\n var inputport = $('<div id=\"inputport\" class=\"transcript-bottom\"/>').appendTo(gameport);\n var inputline = $('<input class=\"transcript-input transcript-style-2\" type=\"text\" style=\"max-width:95%\"/>').appendTo(inputport);\n //var printhead = $('<div id=\"printhead\" class=\"transcript-print-head\"/>').appendTo(parent);\n //var printshield = $('<div id=\"printhead\" class=\"transcript-print-shield\"/>').appendTo(parent);\n this.tty = new TeleTypeWithKeyboard(windowport[0], true, inputline[0] as HTMLInputElement);\n this.tty.keepinput = true; // input stays @ bottom\n this.tty.splitInput = true; // split into arguments\n this.tty.keephandler = false; // set handler each input\n this.tty.hideinput();\n this.tty.scrolldiv = parent;\n this.tty.bell = new Audio('res/ttybell.mp3');\n this.runtime.input = async (prompt:string, nargs:number) => {\n return new Promise( (resolve, reject) => {\n if (prompt != null) {\n this.tty.addtext(prompt, 0);\n this.tty.addtext('? ', 0);\n this.tty.waitingfor = 'line';\n } else {\n this.tty.waitingfor = 'char';\n }\n this.tty.focusinput();\n this.tty.resolveInput = resolve;\n });\n }\n this.timer = new AnimationTimer(60, this.animate.bind(this));\n this.resize = () => {\n this.tty.resize(80);\n }\n this.resize();\n this.runtime.print = (s:string) => {\n // TODO: why null sometimes?\n this.animcount = 0; // exit advance loop when printing\n this.tty.print(s);\n this.transcript.push(s);\n }\n this.runtime.resume = this.resume.bind(this);\n }\n\n animate() {\n if (this.tty.isBusy()) return;\n var ips = this.program.opts.commandsPerSec || 1000;\n this.animcount += ips / 60;\n while (this.runtime.running && this.animcount-- > 0) {\n if (!this.advance())\n break;\n }\n }\n\n // should not depend on tty state\n advance(novideo?: boolean) : number {\n if (this.runtime.running) {\n if (this.checkDebugTrap())\n return 0;\n var more = this.runtime.step();\n if (!more) {\n this.pause();\n if (this.runtime.exited) {\n this.exitmsg();\n this.didExit();\n }\n }\n this.clock++;\n return 1;\n } else {\n return 0;\n }\n }\n \n exitmsg() {\n this.tty.print(\"\\n\\n\");\n this.tty.addtext(\"*** END OF PROGRAM ***\", 1);\n this.tty.showPrintHead(false);\n }\n\n resize: () => void;\n\n loadROM(title, data) {\n // TODO: disable hot reload if error\n // TODO: only hot reload when we hit a label?\n var didExit = this.runtime.exited;\n this.program = data;\n var resumePC = this.runtime.load(data);\n this.tty.uppercaseOnly = true; // this.program.opts.uppercaseOnly; //TODO?\n // map editor to uppercase-only if need be\n editors.textMapFunctions.input = this.program.opts.uppercaseOnly ? (s) => s.toUpperCase() : null;\n // only reset if we exited, or couldn't restart at label (PC reset to 0)\n if (!this.hotReload || didExit || !resumePC)\n this.reset();\n }\n\n getROMExtension() {\n return \".json\";\n }\n\n reset(): void {\n this.tty.clear();\n this.runtime.reset();\n this.clock = 0;\n this.transcript = [];\n }\n\n pause(): void {\n this.timer.stop();\n }\n\n resume(): void {\n if (this.isBlocked()) return;\n this.animcount = 0;\n this.timer.start();\n }\n\n isBlocked() { return this.tty.waitingfor != null || this.runtime.exited; } // is blocked for input?\n isRunning() { return this.timer.isRunning(); }\n getDefaultExtension() { return \".bas\"; }\n getToolForFilename() { return \"basic\"; }\n getPresets() { return BASIC_PRESETS; }\n\n getPC() {\n return this.runtime.curpc;\n }\n getSP() {\n return 0x1000 - this.runtime.returnStack.length;\n }\n isStable() {\n return true;\n } \n getCPUState() {\n return { PC: this.getPC(), SP: this.getSP() }\n }\n saveState() {\n return {\n c: this.getCPUState(),\n rt: this.runtime.saveState(),\n }\n }\n loadState(state) {\n this.runtime.loadState(state);\n }\n getDebugTree() {\n return {\n CurrentLine: this.runtime.getCurrentLabel(),\n Variables: this.runtime.vars,\n Arrays: this.runtime.arrays,\n Functions: this.runtime.defs,\n ForLoops: this.runtime.forLoops,\n WhileLoops: this.runtime.whileLoops,\n ReturnStack: this.runtime.returnStack,\n NextDatum: this.runtime.datums[this.runtime.dataptr],\n Clock: this.clock,\n Options: this.runtime.opts,\n Internals: this.runtime,\n }\n }\n inspect(sym: string) {\n let o = this.runtime.vars[sym];\n if (o != null) return `${sym} = ${o}`;\n }\n showHelp(tool:string, ident:string) {\n window.open(\"https://8bitworkshop.com/docs/platforms/basic/#basicreference\", \"_help\");\n }\n\n getDebugCategories() {\n return ['Variables'];\n }\n getDebugInfo(category:string, state) : string {\n switch (category) {\n case 'Variables': return this.varsToLongString();\n }\n }\n varsToLongString() : string {\n var s = '';\n var vars = Object.keys(this.runtime.vars);\n vars.sort();\n for (var name of vars) {\n var value = this.runtime.vars[name];\n var valstr = JSON.stringify(value);\n if (valstr.length > 24) valstr = `${valstr.substr(0,24)}...(${valstr.length})`;\n s += lpad(name,3) + \" = \" + valstr + \"\\n\";\n }\n return s;\n }\n \n // TODO: debugging (get running state, etc)\n\n onBreakpointHit : BreakpointCallback;\n debugTrap : DebugCondition;\n\n setupDebug(callback : BreakpointCallback) : void {\n this.onBreakpointHit = callback;\n }\n clearDebug() {\n this.onBreakpointHit = null;\n this.debugTrap = null;\n }\n checkDebugTrap() : boolean {\n if (this.debugTrap && this.debugTrap()) {\n this.pause();\n this.break();\n return true;\n }\n return false;\n }\n break() {\n // TODO: why doesn't highlight go away on resume?\n if (this.onBreakpointHit) {\n this.onBreakpointHit(this.saveState());\n }\n }\n step() {\n var prevClock = this.clock;\n this.debugTrap = () => {\n return this.clock > prevClock;\n };\n this.resume();\n }\n stepOver() {\n var stmt = this.runtime.getStatement();\n if (stmt && (stmt.command == 'GOSUB' || stmt.command == 'ONGOSUB')) {\n var nextPC = this.getPC() + 1;\n this.runEval(() => this.getPC() == nextPC);\n } else {\n this.step();\n }\n }\n runUntilReturn() {\n var prevSP = this.getSP();\n this.runEval(() => this.getSP() > prevSP);\n }\n runEval(evalfunc : DebugEvalCondition) {\n this.debugTrap = () => evalfunc(this.getCPUState());\n this.resume();\n }\n restartAtPC?(pc:number) : boolean {\n pc = Math.round(pc);\n if (pc >= 0 && pc < this.runtime.allstmts.length) {\n this.runtime.curpc = pc;\n this.tty.cancelinput();\n this.clock = 0;\n return true;\n } else {\n return false;\n }\n }\n readFile(path: string) : FileData {\n return this.internalFiles[path];\n }\n writeFile(path: string, data: FileData) : boolean {\n this.internalFiles[path] = data;\n return true;\n }\n didExit() {\n this.internalFiles['stdout.txt'] = this.transcript.join(\"\");\n haltEmulation();\n }\n}\n\n//\n\nPLATFORMS['basic'] = BASICPlatform;\n"],
|
|
"mappings": "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",
|
|
"names": []
|
|
}
|