mirror of
https://github.com/sehugg/8bitworkshop.git
synced 2024-11-25 18:33:11 +00:00
views use SourceLocation/Line to locate code
This commit is contained in:
parent
d5405c4db1
commit
d92cc5542d
@ -1,7 +1,7 @@
|
||||
import { WorkerError, CodeListingMap, SourceLocation } from "../workertypes";
|
||||
import { WorkerError, CodeListingMap, SourceLocation, SourceLine } from "../workertypes";
|
||||
|
||||
export interface SourceLocated {
|
||||
$loc?: SourceLocation;
|
||||
$loc?: SourceLine;
|
||||
}
|
||||
|
||||
class CompileError extends Error {
|
||||
@ -780,8 +780,11 @@ export class BASICParser {
|
||||
var srclines = [];
|
||||
var pc = 0;
|
||||
program.lines.forEach((line, idx) => {
|
||||
srclines.push({offset: pc, line: idx+1});
|
||||
pc += line.stmts.length;
|
||||
line.stmts.forEach((stmt) => {
|
||||
var sl = stmt.$loc;
|
||||
sl.offset = pc++; // TODO: could Statement have offset field?
|
||||
srclines.push(sl);
|
||||
});
|
||||
});
|
||||
return { lines: srclines };
|
||||
}
|
||||
|
@ -9,6 +9,7 @@ export interface SourceLocation {
|
||||
end?: number;
|
||||
}
|
||||
|
||||
// actually it's a kind of SourceSnippet .. can have multiple per line
|
||||
export interface SourceLine extends SourceLocation {
|
||||
offset:number;
|
||||
insns?:string;
|
||||
@ -19,29 +20,29 @@ export interface SourceLine extends SourceLocation {
|
||||
export class SourceFile {
|
||||
lines: SourceLine[];
|
||||
text: string;
|
||||
offset2line: Map<number,number>; //{[offset:number]:number};
|
||||
offset2loc: Map<number,SourceLine>; //{[offset:number]:number};
|
||||
line2offset: Map<number,number>; //{[line:number]:number};
|
||||
|
||||
constructor(lines:SourceLine[], text:string) {
|
||||
lines = lines || [];
|
||||
this.lines = lines;
|
||||
this.text = text;
|
||||
this.offset2line = new Map();
|
||||
this.offset2loc = new Map();
|
||||
this.line2offset = new Map();
|
||||
for (var info of lines) {
|
||||
if (info.offset >= 0) {
|
||||
this.offset2line[info.offset] = info.line;
|
||||
this.offset2loc[info.offset] = info;
|
||||
this.line2offset[info.line] = info.offset;
|
||||
}
|
||||
}
|
||||
}
|
||||
// TODO: smarter about looking for source lines between two addresses
|
||||
findLineForOffset(PC:number, lookbehind:number) {
|
||||
if (this.offset2line) {
|
||||
if (this.offset2loc) {
|
||||
for (var i=0; i<=lookbehind; i++) {
|
||||
var line = this.offset2line[PC];
|
||||
if (line >= 0) {
|
||||
return {line:line, offset:PC};
|
||||
var loc = this.offset2loc[PC];
|
||||
if (loc) {
|
||||
return loc;
|
||||
}
|
||||
PC--;
|
||||
}
|
||||
|
@ -1079,7 +1079,7 @@ function getErrorElement(err : WorkerError) {
|
||||
link.click((ev) => {
|
||||
var wnd = projectWindows.createOrShow(path);
|
||||
if (wnd instanceof Views.SourceEditor) {
|
||||
wnd.setCurrentLine(err.line, true);
|
||||
wnd.setCurrentLine(err, true);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
|
||||
//import CodeMirror = require("codemirror");
|
||||
import { SourceFile, WorkerError, Segment, FileData } from "../common/workertypes";
|
||||
import { SourceFile, WorkerError, Segment, FileData, SourceLocation, SourceLine } from "../common/workertypes";
|
||||
import { Platform, EmuState, lookupSymbol, BaseDebugPlatform, BaseZ80MachinePlatform, BaseZ80Platform, CpuState } from "../common/baseplatform";
|
||||
import { hex, lpad, rpad, safeident, rgb2bgr } from "../common/util";
|
||||
import { CodeAnalyzer } from "../common/analysis";
|
||||
@ -88,7 +88,7 @@ export class SourceEditor implements ProjectView {
|
||||
editor;
|
||||
dirtylisting = true;
|
||||
sourcefile : SourceFile;
|
||||
currentDebugLine : number;
|
||||
currentDebugLine : SourceLocation;
|
||||
errormsgs = [];
|
||||
errorwidgets = [];
|
||||
inspectWidget;
|
||||
@ -327,9 +327,9 @@ export class SourceEditor implements ProjectView {
|
||||
}
|
||||
}
|
||||
|
||||
setCurrentLine(line:number, moveCursor:boolean) {
|
||||
setCurrentLine(line:SourceLocation, moveCursor:boolean) {
|
||||
|
||||
var addCurrentMarker = (line:number) => {
|
||||
var addCurrentMarker = (line:SourceLocation) => {
|
||||
var div = document.createElement("div");
|
||||
div.style.color = '#66ffff';
|
||||
div.appendChild(document.createTextNode("\u25b6"));
|
||||
@ -337,10 +337,14 @@ export class SourceEditor implements ProjectView {
|
||||
}
|
||||
|
||||
this.clearCurrentLine(moveCursor);
|
||||
if (line>0) {
|
||||
addCurrentMarker(line-1);
|
||||
if (moveCursor)
|
||||
this.editor.setSelection({line:line,ch:0}, {line:line-1,ch:0}, {scroll:true});
|
||||
if (line) {
|
||||
addCurrentMarker(line);
|
||||
if (moveCursor) {
|
||||
if (line.start || line.end)
|
||||
this.editor.setSelection({line:line.line-1,ch:line.start}, {line:line.line-1,ch:line.end||line.start+1}, {scroll:true});
|
||||
else
|
||||
this.editor.setSelection({line:line.line-1,ch:0}, {line:line.line,ch:0}, {scroll:true});
|
||||
}
|
||||
this.currentDebugLine = line;
|
||||
}
|
||||
}
|
||||
@ -349,24 +353,23 @@ export class SourceEditor implements ProjectView {
|
||||
if (this.currentDebugLine) {
|
||||
this.editor.clearGutter("gutter-info");
|
||||
if (moveCursor) this.editor.setSelection(this.editor.getCursor());
|
||||
this.currentDebugLine = 0;
|
||||
this.currentDebugLine = null;
|
||||
}
|
||||
}
|
||||
|
||||
getActiveLine() {
|
||||
getActiveLine() : SourceLocation {
|
||||
var state = lastDebugState;
|
||||
if (this.sourcefile && state) {
|
||||
var EPC = (state && state.c && (state.c.EPC || state.c.PC)); // || (platform.getPC && platform.getPC());
|
||||
var res = this.sourcefile.findLineForOffset(EPC, 15);
|
||||
return res && res.line;
|
||||
} else
|
||||
return -1;
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
refreshDebugState(moveCursor:boolean) {
|
||||
this.clearCurrentLine(moveCursor);
|
||||
var line = this.getActiveLine();
|
||||
if (line >= 0) {
|
||||
if (line) {
|
||||
this.setCurrentLine(line, moveCursor);
|
||||
}
|
||||
}
|
||||
|
@ -90,7 +90,8 @@ describe('Store', function () {
|
||||
assert.deepEqual([false], msgs);
|
||||
var lst = buildresult.listings.test;
|
||||
console.log(lst);
|
||||
assert.deepEqual({ line: 3, offset: 61440 }, lst.sourcefile.findLineForOffset(61440 + 15, 15));
|
||||
assert.deepEqual({ line: 3, offset: 61440, insns: 'a9 00', iscode: true },
|
||||
lst.sourcefile.findLineForOffset(61440 + 15, 15));
|
||||
assert.equal(null, lst.sourcefile.findLineForOffset(61440 + 16, 15));
|
||||
assert.equal(null, lst.sourcefile.findLineForOffset(61440 + 1, 0));
|
||||
assert.equal(null, lst.sourcefile.findLineForOffset(61440 - 1, 16));
|
||||
|
@ -48,8 +48,12 @@ function doBuild(msgs, callback, outlen, nlines, nerrors, options) {
|
||||
assert.equal(nerrors, msg.errors.length, "errors");
|
||||
} else {
|
||||
assert.equal(nerrors||0, 0, "errors");
|
||||
assert.equal(msg.output.code?msg.output.code.length:msg.output.length, outlen, "output binary");
|
||||
assert.ok(msg.output.code || msg.output instanceof Uint8Array);
|
||||
if (msg.output.lines) { // AST for BASIC
|
||||
assert.equal(msg.output.lines.length, outlen, "output lines");
|
||||
} else {
|
||||
assert.equal(msg.output.code?msg.output.code.length:msg.output.length, outlen, "output binary");
|
||||
assert.ok(msg.output.code || msg.output instanceof Uint8Array);
|
||||
}
|
||||
if (nlines) {
|
||||
if (typeof nlines === 'number')
|
||||
nlines = [nlines];
|
||||
@ -324,5 +328,15 @@ describe('Worker', function() {
|
||||
});
|
||||
*/
|
||||
// TODO: vectrex, x86
|
||||
it('should compile basic example', function(done) {
|
||||
var csource = ab2str(fs.readFileSync('presets/basic/wumpus.bas'));
|
||||
var msgs = [{code:csource, platform:"basic", tool:"basic", path:'wumpus.bas'}];
|
||||
var done2 = function(err, msg) {
|
||||
var ast = msg.output;
|
||||
assert.ok(ast);
|
||||
done(err, msg);
|
||||
};
|
||||
doBuild(msgs, done2, 222, 0, 0);
|
||||
});
|
||||
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user