8bitworkshop/src/common/workertypes.ts

167 lines
3.9 KiB
TypeScript

export type FileData = string | Uint8Array;
export interface SourceLocation {
line: number;
label?: string;
path?: string; // TODO: make mandatory?
start?: number;
end?: number;
segment?:string;
func?:string;
}
// actually it's a kind of SourceSnippet .. can have multiple per line
export interface SourceLine extends SourceLocation {
offset:number;
insns?:string;
iscode?:boolean;
cycles?:number;
}
// objects that have source code position info
export interface SourceLocated {
$loc?: SourceLocation;
}
// statements also have the 'offset' (pc) field from SourceLine
export interface SourceLineLocated {
$loc?: SourceLine;
}
export class SourceFile {
lines: SourceLine[];
text: string;
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.offset2loc = new Map();
this.line2offset = new Map();
for (var info of lines) {
if (info.offset >= 0) {
// first line wins (is assigned to offset)
// TODO: handle macros/includes w/ multiple offsets per line
if (!this.offset2loc[info.offset])
this.offset2loc[info.offset] = info;
if (!this.line2offset[info.line])
this.line2offset[info.line] = info.offset;
}
}
}
// TODO: smarter about looking for source lines between two addresses
findLineForOffset(PC:number, lookbehind:number) : SourceLine {
if (this.offset2loc) {
for (var i=0; i<=lookbehind; i++) {
var loc = this.offset2loc[PC];
if (loc) {
return loc;
}
PC--;
}
}
return null;
}
lineCount():number { return this.lines.length; }
}
export interface Dependency {
path:string
filename:string
link:boolean
data:FileData // TODO: or binary?
}
export interface WorkerFileUpdate {
path:string
data:FileData
};
export interface WorkerBuildStep {
path?:string
files?:string[]
platform:string
tool:string
mainfile?:boolean
};
export interface WorkerItemUpdate {
key:string
value:object
};
// TODO: split into different msg types
export interface WorkerMessage {
preload?:string
platform?:string
tool?:string
updates:WorkerFileUpdate[]
buildsteps:WorkerBuildStep[]
reset?:boolean
code?:string
setitems?:WorkerItemUpdate[]
}
export interface WorkerError extends SourceLocation {
msg:string,
}
export interface CodeListing {
lines:SourceLine[]
asmlines?:SourceLine[]
text?:string
sourcefile?:SourceFile // not returned by worker
assemblyfile?:SourceFile // not returned by worker
}
export type CodeListingMap = {[path:string]:CodeListing};
// TODO
export type VerilogOutput =
{program_rom_variable:string, program_rom:Uint8Array, code:string, name:string, ports:any[], signals:any[]};
export type Segment = {
name:string,
start:number,
size:number,
last?:number,
type?:string,
source?:'native'|'linker'
};
export type WorkerResult = WorkerErrorResult | WorkerOutputResult<any> | WorkerUnchangedResult;
export interface WorkerUnchangedResult {
unchanged: true;
}
export interface WorkerErrorResult {
errors: WorkerError[]
listings?: CodeListingMap
}
export interface WorkerOutputResult<T> {
output: T
listings?: CodeListingMap
symbolmap?: {[sym:string]:number}
params?: {}
segments?: Segment[]
debuginfo?: {} // optional info
}
export function isUnchanged(result: WorkerResult) : result is WorkerUnchangedResult {
return ('unchanged' in result);
}
export function isErrorResult(result: WorkerResult) : result is WorkerErrorResult {
return ('errors' in result);
}
export function isOutputResult(result: WorkerResult) : result is WorkerOutputResult<any> {
return ('output' in result);
}
export interface WorkingStore {
getFileData(path:string) : FileData;
}