diff --git a/src/common/basic/compiler.ts b/src/common/basic/compiler.ts index b6936c05..cf107bae 100644 --- a/src/common/basic/compiler.ts +++ b/src/common/basic/compiler.ts @@ -262,6 +262,7 @@ export class BASICParser { decls: { [name: string]: SourceLocation }; // declared/set vars refs: { [name: string]: SourceLocation }; // references + path : string; lineno : number; tokens: Token[]; eol: Token; @@ -281,7 +282,7 @@ export class BASICParser { compileError(msg: string, loc?: SourceLocation) { if (!loc) loc = this.peekToken().$loc; // TODO: pass SourceLocation to errors - this.errors.push({line:loc.line, msg:msg}); + this.errors.push({path:loc.path, line:loc.line, msg:msg}); throw new CompileError(`${msg} (line ${loc.line})`); // TODO: label too? } dialectError(what: string, loc?: SourceLocation) { @@ -336,6 +337,7 @@ export class BASICParser { } } parseFile(file: string, path: string) : BASICProgram { + this.path = path; var pgmlines = file.split("\n").map((line) => this.parseLine(line)); var program = { opts: this.opts, lines: pgmlines }; this.checkAll(program); @@ -369,13 +371,13 @@ export class BASICParser { this.tokens.push({ str: s, type: i, - $loc: { line: this.lineno, start: m.index, end: m.index+s.length } + $loc: { path: this.path, line: this.lineno, start: m.index, end: m.index+s.length } }); break; } } } - this.eol = { type: TokenType.EOL, str: "", $loc: { line: this.lineno, start: line.length } }; + this.eol = { type: TokenType.EOL, str: "", $loc: { path: this.path, line: this.lineno, start: line.length } }; } parse() : BASICLine { var line = {label: null, stmts: []}; @@ -444,7 +446,7 @@ export class BASICParser { this.compileError(`There should be a command here.`); return null; } - if (stmt) stmt.$loc = { line: cmdtok.$loc.line, start: cmdtok.$loc.start, end: this.peekToken().$loc.start }; + if (stmt) stmt.$loc = { path: cmdtok.$loc.path, line: cmdtok.$loc.line, start: cmdtok.$loc.start, end: this.peekToken().$loc.start }; return stmt; } parseVarSubscriptOrFunc(): IndOp { diff --git a/src/common/basic/runtime.ts b/src/common/basic/runtime.ts index 4acdc551..adc5c62f 100644 --- a/src/common/basic/runtime.ts +++ b/src/common/basic/runtime.ts @@ -1,6 +1,7 @@ import * as basic from "./compiler"; import { EmuHalt } from "../emu"; +import { SourceLocation } from "../workertypes"; function isLiteral(arg: basic.Expr): arg is basic.Literal { return (arg as any).value != null; @@ -110,9 +111,9 @@ export class BASICRuntime { runtimeError(msg : string) { this.curpc--; // we did curpc++ before executing statement - // TODO: pass source location to error - throw new EmuHalt(`${msg} (line ${this.getLabelForPC(this.curpc)})`); + throw new EmuHalt(msg, this.getCurrentSourceLocation()); } + dialectError(what : string) { this.runtimeError(`I can't ${what} in this dialect of BASIC.`); } @@ -132,6 +133,11 @@ export class BASICRuntime { return pgmline ? pgmline.label : '?'; } + getCurrentSourceLocation() : SourceLocation { + var stmt = this.getStatement(); + return stmt && stmt.$loc; + } + getStatement() { return this.allstmts[this.curpc]; } diff --git a/src/common/emu.ts b/src/common/emu.ts index d0ff10dc..5288e951 100644 --- a/src/common/emu.ts +++ b/src/common/emu.ts @@ -1,6 +1,7 @@ "use strict"; import { hex, clamp, lpad } from "./util"; +import { SourceLocation } from "./workertypes"; // external modules declare var jt, Javatari; @@ -225,8 +226,10 @@ export class RAM { } export class EmuHalt extends Error { - constructor(msg:string) { + $loc : SourceLocation; + constructor(msg: string, loc?: SourceLocation) { super(msg); + this.$loc = loc; Object.setPrototypeOf(this, EmuHalt.prototype); } } diff --git a/src/common/workertypes.ts b/src/common/workertypes.ts index 88d201e2..e635b4e3 100644 --- a/src/common/workertypes.ts +++ b/src/common/workertypes.ts @@ -3,13 +3,14 @@ export type FileData = string | Uint8Array; export interface SourceLocation { line: number; + label?: string; + path?: string; // TODO: make mandatory? start?: number; end?: number; } -export interface SourceLine { +export interface SourceLine extends SourceLocation { offset:number; - line:number; insns?:string; iscode?:boolean; cycles?:number; diff --git a/src/ide/ui.ts b/src/ide/ui.ts index 6b5e66db..a2eb32d6 100644 --- a/src/ide/ui.ts +++ b/src/ide/ui.ts @@ -1884,7 +1884,12 @@ function globalErrorHandler(msgevent) { if (msg.indexOf("QuotaExceededError") >= 0) { requestPersistPermission(false, false); } else { - showErrorAlert([{msg:msg,line:0}]); + var err = msgevent.error; + var werr : WorkerError = {msg:msg, line:0}; + if (err instanceof EmuHalt && err.$loc) { + werr = {msg:msg, path:err.$loc.path, line:err.$loc.line}; // TODO: get start/end columns + } + showErrorAlert([werr]); } }