diff --git a/src/common/workertypes.ts b/src/common/workertypes.ts index b1aca757..2d364e9c 100644 --- a/src/common/workertypes.ts +++ b/src/common/workertypes.ts @@ -100,18 +100,36 @@ export type CodeListingMap = {[path:string]:CodeListing}; export type VerilogOutput = {program_rom_variable:string, program_rom:Uint8Array, code:string, name:string, ports:any[], signals:any[]}; -export type WorkerOutput = Uint8Array | VerilogOutput; - export type Segment = {name:string, start:number, size:number, last?:number, type?:string}; -export interface WorkerResult { - errors:WorkerError[] - output?:WorkerOutput - listings?:CodeListingMap - symbolmap?:{[sym:string]:number} - params?:{} - segments?:Segment[] - unchanged?:boolean - debuginfo?:{} // optional info +export type WorkerResult = WorkerErrorResult | WorkerOutputResult | WorkerUnchangedResult; + +export interface WorkerUnchangedResult { + unchanged: true; } +export interface WorkerErrorResult { + errors: WorkerError[] + listings?: CodeListingMap +} + +export interface WorkerOutputResult { + 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 { + return ('output' in result); +} diff --git a/src/ide/project.ts b/src/ide/project.ts index 290c8a64..d70ff6a9 100644 --- a/src/ide/project.ts +++ b/src/ide/project.ts @@ -1,5 +1,5 @@ -import { FileData, Dependency, SourceLine, SourceFile, CodeListing, CodeListingMap, WorkerError, Segment, WorkerResult } from "../common/workertypes"; +import { FileData, Dependency, SourceLine, SourceFile, CodeListing, CodeListingMap, WorkerError, Segment, WorkerResult, WorkerOutputResult, isUnchanged, isOutputResult } from "../common/workertypes"; import { getFilenamePrefix, getFolderForPath, isProbablyBinary, getBasePlatform, getWithBinary } from "../common/util"; import { Platform } from "../common/baseplatform"; import localforage from "localforage"; @@ -126,7 +126,7 @@ export class CodeProject { this.isCompiling = false; this.pendingWorkerMessages = 0; } - if (data && !data.unchanged) { + if (data && isOutputResult(data)) { this.processBuildResult(data); } this.callbackBuildResult(data); @@ -362,7 +362,7 @@ export class CodeProject { this.sendBuild(); } - processBuildResult(data:WorkerResult) { + processBuildResult(data: WorkerOutputResult) { // TODO: link listings with source files if (data.listings) { this.listings = data.listings; diff --git a/src/ide/ui.ts b/src/ide/ui.ts index 63bda420..1a3f9f2a 100644 --- a/src/ide/ui.ts +++ b/src/ide/ui.ts @@ -3,7 +3,7 @@ import * as localforage from "localforage"; import { CodeProject, createNewPersistentStore, LocalForageFilesystem, OverlayFilesystem, ProjectFilesystem, WebPresetsFileSystem } from "./project"; -import { WorkerResult, WorkerOutput, WorkerError, FileData } from "../common/workertypes"; +import { WorkerResult, WorkerOutputResult, WorkerError, FileData, WorkerErrorResult } from "../common/workertypes"; import { ProjectWindows } from "./windows"; import { Platform, Preset, DebugSymbols, DebugEvalCondition, isDebuggable, EmuState } from "../common/baseplatform"; import { PLATFORMS, EmuHalt, Toolbar } from "../common/emu"; @@ -71,7 +71,7 @@ var stateRecorder : StateRecorderImpl; var userPaused : boolean; // did user explicitly pause? -var current_output : WorkerOutput; // current ROM +var current_output : any; // current ROM (or other object) var current_preset : Preset; // current preset object (if selected) var store : LocalForage; // persistent store @@ -1294,7 +1294,7 @@ function measureBuildTime() { async function setCompileOutput(data: WorkerResult) { // errors? mark them in editor - if (data && data.errors && data.errors.length > 0) { + if ('errors' in data && data.errors.length > 0) { toolbar.addClass("has-errors"); projectWindows.setErrors(data.errors); refreshWindowList(); // to make sure windows are created for showErrorAlert() @@ -1304,13 +1304,15 @@ async function setCompileOutput(data: WorkerResult) { projectWindows.setErrors(null); hideErrorAlerts(); // exit if compile output unchanged - if (data == null || data.unchanged) return; + if (data == null || ('unchanged' in data && data.unchanged)) return; + // make sure it's a WorkerOutputResult + if (!('output' in data)) return; // process symbol map platform.debugSymbols = new DebugSymbols(data.symbolmap, data.debuginfo); compparams = data.params; // load ROM var rom = data.output; - if (rom) { + if (rom != null) { try { clearBreakpoint(); // so we can replace memory (TODO: change toolbar btn) _resetRecording(); diff --git a/src/worker/workermain.ts b/src/worker/workermain.ts index a2d05b34..7b76550e 100644 --- a/src/worker/workermain.ts +++ b/src/worker/workermain.ts @@ -1,6 +1,6 @@ /// -import type { WorkerResult, WorkerFileUpdate, WorkerBuildStep, WorkerMessage, WorkerError, Dependency, SourceLine, CodeListing, CodeListingMap, Segment, WorkerOutput, SourceLocation } from "../common/workertypes"; +import type { WorkerResult, WorkerBuildStep, WorkerMessage, WorkerError, SourceLine, CodeListingMap, Segment, SourceLocation } from "../common/workertypes"; import { getBasePlatform, getRootBasePlatform, hex } from "../common/util"; import { Assembler } from "./assembler"; import * as vxmlparser from '../common/hdl/vxmlparser'; @@ -372,13 +372,24 @@ type BuildOptions = { }; // TODO +export type BuildStepResult = WorkerResult | WorkerNextToolResult; + +export interface WorkerNextToolResult { + nexttool?: string + linktool?: string + path?: string + args: string[] + files: string[] + bblines?: boolean +} + interface BuildStep extends WorkerBuildStep { files? : string[] args? : string[] nextstep? : BuildStep linkstep? : BuildStep params? - result? // : WorkerResult | BuildStep ? + result? : BuildStepResult code? prefix? maxts? @@ -460,18 +471,18 @@ class Builder { return {errors:[{line:0, msg:e+""}]}; // TODO: catch errors already generated? } if (step.result) { - step.result.params = step.params; + (step.result as any).params = step.params; // TODO: type check // errors? return them - if (step.result.errors && step.result.errors.length) { + if ('errors' in step.result && step.result.errors.length) { applyDefaultErrorPath(step.result.errors, step.path); return step.result; } // if we got some output, return it immediately - if (step.result.output) { + if ('output' in step.result && step.result.output) { return step.result; } // combine files with a link tool? - if (step.result.linktool) { + if ('linktool' in step.result) { if (linkstep) { linkstep.files = linkstep.files.concat(step.result.files); linkstep.args = linkstep.args.concat(step.result.args); @@ -485,10 +496,12 @@ class Builder { } } // process with another tool? - if (step.result.nexttool) { - var asmstep : BuildStep = step.result; - asmstep.tool = step.result.nexttool; - asmstep.platform = platform; + if ('nexttool' in step.result) { + var asmstep : BuildStep = { + tool: step.result.nexttool, + platform: platform, + ...step.result + } this.steps.push(asmstep); } // process final step? @@ -1004,7 +1017,7 @@ function parseDASMListing(lstpath:string, lsttext:string, listings:CodeListingMa } } -function assembleDASM(step:BuildStep) { +function assembleDASM(step:BuildStep) : BuildStepResult { load("dasm"); var re_usl = /(\w+)\s+0000\s+[?][?][?][?]/; var unresolved = {}; @@ -1195,7 +1208,7 @@ function parseCA65Listing(code, symbols, params, dbg) { return lines; } -function assembleCA65(step:BuildStep) { +function assembleCA65(step:BuildStep) : BuildStepResult { loadNative("ca65"); var errors = []; gatherFiles(step, {mainFilePath:"main.s"}); @@ -1234,7 +1247,7 @@ function assembleCA65(step:BuildStep) { }; } -function linkLD65(step:BuildStep) { +function linkLD65(step:BuildStep) : BuildStepResult { loadNative("ld65"); var params = step.params; gatherFiles(step); @@ -1382,7 +1395,7 @@ function fixParamsWithDefines(path:string, params){ } } -function compileCC65(step:BuildStep) { +function compileCC65(step:BuildStep) : BuildStepResult { loadNative("cc65"); var params = step.params; // stderr @@ -1483,7 +1496,7 @@ function parseIHX(ihx, rom_start, rom_size, errors) { return output; } -function assembleSDASZ80(step:BuildStep) { +function assembleSDASZ80(step:BuildStep) : BuildStepResult { loadNative("sdasz80"); var objout, lstout, symout; var errors = []; @@ -1654,7 +1667,7 @@ function linkSDLDZ80(step:BuildStep) } } -function compileSDCC(step:BuildStep) { +function compileSDCC(step:BuildStep) : BuildStepResult { gatherFiles(step, { mainFilePath:"main.c" // not used @@ -1677,7 +1690,9 @@ function compileSDCC(step:BuildStep) { // load source file and preprocess var code = getWorkFileAsString(step.path); var preproc = preprocessMCPP(step, 'sdcc'); - if (preproc.errors) return preproc; + if (preproc.errors) { + return { errors: preproc.errors }; + } else code = preproc.code; // pipe file to stdin setupStdin(FS, code); @@ -1860,7 +1875,7 @@ function compileJSASM(asmcode:string, platform, options, is_inline) { } } -function compileJSASMStep(step:BuildStep) { +function compileJSASMStep(step:BuildStep) : BuildStepResult { gatherFiles(step); var code = getWorkFileAsString(step.path); var platform = step.platform || 'verilog'; @@ -1900,7 +1915,7 @@ function compileInlineASM(code:string, platform, options, errors, asmlines) { return code; } -function compileVerilator(step:BuildStep) { +function compileVerilator(step:BuildStep) : BuildStepResult { loadNative("verilator_bin"); var platform = step.platform || 'verilog'; var errors : WorkerError[] = []; @@ -1991,7 +2006,7 @@ function compileVerilator(step:BuildStep) { } // TODO: test -function compileYosys(step:BuildStep) { +function compileYosys(step:BuildStep) : BuildStepResult { loadNative("yosys"); var code = step.code; var errors = []; @@ -2022,14 +2037,14 @@ function compileYosys(step:BuildStep) { var json_file = FS.readFile(topmod+".json", {encoding:'utf8'}); var json = JSON.parse(json_file); console.log(json); - return {yosys_json:json, errors:errors}; // TODO + return {output:json, errors:errors}; // TODO } catch(e) { console.log(e); return {errors:errors}; } } -function assembleZMAC(step:BuildStep) { +function assembleZMAC(step:BuildStep) : BuildStepResult { loadNative("zmac"); var hexout, lstout, binout; var errors = []; @@ -2112,7 +2127,7 @@ function preprocessBatariBasic(code:string) : string { return bbout; } -function compileBatariBasic(step:BuildStep) { +function compileBatariBasic(step:BuildStep) : BuildStepResult { load("bb2600basic"); var params = step.params; // stdout @@ -2202,7 +2217,7 @@ function setupRequireFunction() { } } -function translateShowdown(step:BuildStep) { +function translateShowdown(step:BuildStep) : BuildStepResult { setupRequireFunction(); load("showdown.min"); var showdown = emglobal['showdown']; @@ -2221,7 +2236,7 @@ function translateShowdown(step:BuildStep) { } // http://datapipe-blackbeltsystems.com/windows/flex/asm09.html -function assembleXASM6809(step:BuildStep) { +function assembleXASM6809(step:BuildStep) : BuildStepResult { load("xasm6809"); var alst = ""; var lasterror = null; @@ -2282,7 +2297,7 @@ function assembleXASM6809(step:BuildStep) { } // http://www.nespowerpak.com/nesasm/ -function assembleNESASM(step:BuildStep) { +function assembleNESASM(step:BuildStep) : BuildStepResult { loadNative("nesasm"); var re_filename = /\#\[(\d+)\]\s+(\S+)/; var re_insn = /\s+(\d+)\s+([0-9A-F]+):([0-9A-F]+)/; @@ -2378,7 +2393,7 @@ function assembleNESASM(step:BuildStep) { }; } -function compileCMOC(step:BuildStep) { +function compileCMOC(step:BuildStep) : BuildStepResult { loadNative("cmoc"); var params = step.params; // stderr @@ -2414,7 +2429,9 @@ function compileCMOC(step:BuildStep) { // load source file and preprocess var code = getWorkFileAsString(step.path); var preproc = preprocessMCPP(step, null); - if (preproc.errors) return preproc; + if (preproc.errors) { + return {errors: preproc.errors} + } else code = preproc.code; // set up filesystem var FS = CMOC.FS; @@ -2439,7 +2456,7 @@ function compileCMOC(step:BuildStep) { }; } -function assembleLWASM(step:BuildStep) { +function assembleLWASM(step:BuildStep) : BuildStepResult { loadNative("lwasm"); var errors = []; gatherFiles(step, {mainFilePath:"main.s"}); @@ -2474,7 +2491,7 @@ function assembleLWASM(step:BuildStep) { }; } -function linkLWLINK(step:BuildStep) { +function linkLWLINK(step:BuildStep) : BuildStepResult { loadNative("lwlink"); var params = step.params; gatherFiles(step); @@ -2565,7 +2582,7 @@ function linkLWLINK(step:BuildStep) { } // http://www.techhelpmanual.com/829-program_startup___exit.html -function compileSmallerC(step:BuildStep) { +function compileSmallerC(step:BuildStep) : BuildStepResult { loadNative("smlrc"); var params = step.params; // stderr @@ -2603,7 +2620,9 @@ function compileSmallerC(step:BuildStep) { // load source file and preprocess var code = getWorkFileAsString(step.path); var preproc = preprocessMCPP(step, null); - if (preproc.errors) return preproc; + if (preproc.errors) { + return {errors: preproc.errors}; + } else code = preproc.code; // set up filesystem var FS = smlrc.FS; @@ -2627,7 +2646,8 @@ function compileSmallerC(step:BuildStep) { files:[destpath], }; } -function assembleYASM(step:BuildStep) { + +function assembleYASM(step:BuildStep) : BuildStepResult { loadNative("yasm"); var errors = []; gatherFiles(step, {mainFilePath:"main.asm"}); @@ -2708,7 +2728,7 @@ function parseXMLPoorly(s: string) : XMLNode { return top; } -function compileInform6(step:BuildStep) { +function compileInform6(step:BuildStep) : BuildStepResult { loadNative("inform"); var errors = []; gatherFiles(step, {mainFilePath:"main.inf"}); @@ -2812,7 +2832,7 @@ function compileInform6(step:BuildStep) { => Creating Output file 'pcs.bin_S01__Output.txt' */ -function assembleMerlin32(step:BuildStep) { +function assembleMerlin32(step:BuildStep) : BuildStepResult { loadNative("merlin32"); var errors = []; var lstfiles = []; @@ -2898,7 +2918,7 @@ function assembleMerlin32(step:BuildStep) { } // README.md:2:5: parse error, expected: statement or variable assignment, integer variable, variable assignment -function compileFastBasic(step:BuildStep) { +function compileFastBasic(step:BuildStep) : BuildStepResult { // TODO: fastbasic-fp? loadNative("fastbasic-int"); var params = step.params; @@ -2935,7 +2955,7 @@ function compileFastBasic(step:BuildStep) { }; } -function compileBASIC(step:BuildStep) { +function compileBASIC(step:BuildStep) : WorkerResult { var jsonpath = step.path + ".json"; gatherFiles(step); if (staleFiles(step, [jsonpath])) { @@ -2960,7 +2980,7 @@ function compileBASIC(step:BuildStep) { } } -function compileSilice(step:BuildStep) { +function compileSilice(step:BuildStep) : BuildStepResult { loadNative("silice"); var params = step.params; gatherFiles(step, {mainFilePath:"main.ice"}); @@ -3021,7 +3041,7 @@ function compileSilice(step:BuildStep) { }; } -function compileWiz(step:BuildStep) { +function compileWiz(step:BuildStep) : WorkerResult { loadNative("wiz"); var params = step.params; gatherFiles(step, {mainFilePath:"main.wiz"}); @@ -3072,7 +3092,7 @@ function compileWiz(step:BuildStep) { } } -function assembleARMIPS(step:BuildStep) { +function assembleARMIPS(step:BuildStep) : WorkerResult { loadNative("armips"); var errors = []; gatherFiles(step, {mainFilePath:"main.asm"}); @@ -3162,7 +3182,7 @@ function assembleARMIPS(step:BuildStep) { } } -function assembleVASMARM(step:BuildStep) { +function assembleVASMARM(step:BuildStep) : BuildStepResult { loadNative("vasmarm_std"); /// error 2 in line 8 of "gfxtest.c": unknown mnemonic /// error 3007: undefined symbol @@ -3371,7 +3391,7 @@ var TOOL_PRELOADFS = { 'wiz': 'wiz', } -function handleMessage(data : WorkerMessage) : WorkerResult | {unchanged:true} { +function handleMessage(data : WorkerMessage) : WorkerResult { // preload file system if (data.preload) { var fs = TOOL_PRELOADFS[data.preload]; diff --git a/test/cli/teststore.js b/test/cli/teststore.js index 7ccb7ffa..855d9c07 100644 --- a/test/cli/teststore.js +++ b/test/cli/teststore.js @@ -82,6 +82,7 @@ describe('Store', function () { project.callbackBuildStatus = function (b) { msgs.push(b) }; project.callbackBuildResult = function (b) { msgs.push(1) }; var buildresult = { + output: [0], listings: { test: { lines: [{ line: 3, offset: 61440, insns: 'a9 00', iscode: true }] diff --git a/test/web/testallpresets.js b/test/web/testallpresets.js index df6a557b..51740169 100644 --- a/test/web/testallpresets.js +++ b/test/web/testallpresets.js @@ -94,7 +94,7 @@ testPlatform(ex, 'vcs', 'Atari 2600', 35); testPlatform(ex, 'nes', 'NES', 30); testPlatform(ex, 'vicdual', 'VIC Dual', 7); testPlatform(ex, 'mw8080bw', 'Midway 8080', 3); -testPlatform(ex, 'galaxian-scramble', 'Galaxian/Scramble', 3); +testPlatform(ex, 'galaxian-scramble', 'Galaxian/Scramble', 2); testPlatform(ex, 'vector-z80color', 'Atari Color Vector (Z80)', 3); testPlatform(ex, 'williams-z80', 'Williams (Z80)', 3); // TODO testPlatform(ex, 'sound_williams-z80', 'Williams Sound (Z80)', 1);