1
0
mirror of https://github.com/sehugg/8bitworkshop.git synced 2024-06-12 18:42:14 +00:00

converted workermain to ts, needs loader.js

This commit is contained in:
Steven Hugg 2018-10-05 09:47:15 -04:00
parent 398103c3b9
commit c687006684
5 changed files with 147 additions and 102 deletions

View File

@ -50,7 +50,7 @@ var TOOL_TO_SOURCE_STYLE = {
} }
function newWorker() : Worker { function newWorker() : Worker {
return new Worker("./src/worker/workermain.js"); return new Worker("./src/worker/loader.js");
} }
var userPaused : boolean; // did user explicitly pause? var userPaused : boolean; // did user explicitly pause?

5
src/worker/loader.js Normal file
View File

@ -0,0 +1,5 @@
"use strict";
var exports = {};
importScripts("../../gen/worker/workermain.js");

View File

@ -1,6 +1,12 @@
"use strict"; "use strict";
var ENVIRONMENT_IS_NODE = typeof process === 'object' && typeof require === 'function'; import { WorkerResult, WorkerFileUpdate, WorkerBuildStep, WorkerMessage, WorkerError, Dependency } from "../workertypes";
const emglobal : any = this['window'] || this['global'] || this;
declare var WebAssembly;
declare function importScripts(path:string);
declare function postMessage(msg);
var ENVIRONMENT_IS_WEB = typeof window === 'object'; var ENVIRONMENT_IS_WEB = typeof window === 'object';
var ENVIRONMENT_IS_WORKER = typeof importScripts === 'function'; var ENVIRONMENT_IS_WORKER = typeof importScripts === 'function';
@ -8,7 +14,7 @@ var ENVIRONMENT_IS_WORKER = typeof importScripts === 'function';
// TODO: leaks memory even when disabled... // TODO: leaks memory even when disabled...
var _WASM_module_cache = {}; var _WASM_module_cache = {};
var CACHE_WASM_MODULES = true; var CACHE_WASM_MODULES = true;
function getWASMModule(module_id) { function getWASMModule(module_id:string) {
var module = _WASM_module_cache[module_id]; var module = _WASM_module_cache[module_id];
if (!module) { if (!module) {
starttime(); starttime();
@ -22,7 +28,7 @@ function getWASMModule(module_id) {
return module; return module;
} }
// function for use with instantiateWasm // function for use with instantiateWasm
function moduleInstFn(module_id) { function moduleInstFn(module_id:string) {
return function(imports,ri) { return function(imports,ri) {
var mod = getWASMModule(module_id); var mod = getWASMModule(module_id);
var inst = new WebAssembly.Instance(mod, imports); var inst = new WebAssembly.Instance(mod, imports);
@ -176,32 +182,46 @@ var PLATFORM_PARAMS = {
}, },
}; };
// shim out window and document objects for security
// https://github.com/mbostock/d3/issues/1053
var noop = function() { return new Function(); };
var window = noop();
window.CSSStyleDeclaration = noop();
window.CSSStyleDeclaration.setProperty = noop();
window.Element = noop();
window.Element.setAttribute = noop();
window.Element.setAttributeNS = noop();
window.navigator = noop();
var document = noop();
document.documentElement = noop();
document.documentElement.style = noop();
var _t1; var _t1;
function starttime() { _t1 = new Date(); } function starttime() { _t1 = new Date(); }
function endtime(msg) { var _t2 = new Date(); console.log(msg, _t2.getTime() - _t1.getTime(), "ms"); } function endtime(msg) { var _t2 = new Date(); console.log(msg, _t2.getTime() - _t1.getTime(), "ms"); }
/// working file store and build steps /// working file store and build steps
var buildsteps = []; type FileData = string | Uint8Array;
var buildstartseq = 0;
var workfs = {};
var workerseq = 0;
function compareData(a,b) { type FileEntry = {
path: string
encoding: string
data: FileData
ts: number
};
type BuildOptions = {
mainFilePath : string
};
// TODO
interface BuildStep extends WorkerBuildStep {
files? : string[]
args? : string[]
nextstep? : BuildStep
linkstep? : BuildStep
params?
result?
code?
generated?
prefix?
maxts?
dependencies?
};
var buildsteps : BuildStep[] = [];
var buildstartseq : number = 0;
var workfs : {[path:string]:FileEntry} = {};
var workerseq : number = 0;
function compareData(a:FileData, b:FileData) : boolean {
if (a.length != b.length) return false; if (a.length != b.length) return false;
if (typeof a === 'string' && typeof b === 'string') if (typeof a === 'string' && typeof b === 'string')
return a==b; return a==b;
@ -214,7 +234,7 @@ function compareData(a,b) {
} }
} }
function putWorkFile(path, data) { function putWorkFile(path:string, data:FileData) {
var encoding = (typeof data === 'string') ? 'utf8' : 'binary'; var encoding = (typeof data === 'string') ? 'utf8' : 'binary';
var entry = workfs[path]; var entry = workfs[path];
if (!entry || !compareData(entry.data, data) || entry.encoding != encoding) { if (!entry || !compareData(entry.data, data) || entry.encoding != encoding) {
@ -225,18 +245,18 @@ function putWorkFile(path, data) {
} }
// returns true if file changed during this build step // returns true if file changed during this build step
function wasChanged(entry) { function wasChanged(entry:FileEntry) : boolean {
return entry.ts > buildstartseq; return entry.ts > buildstartseq;
} }
function populateEntry(fs, path, entry) { function populateEntry(fs, path:string, entry:FileEntry) {
fs.writeFile(path, entry.data, {encoding:entry.encoding}); fs.writeFile(path, entry.data, {encoding:entry.encoding});
fs.utime(path, entry.ts, entry.ts); fs.utime(path, entry.ts, entry.ts);
console.log("<<<", path, entry.data.length); console.log("<<<", path, entry.data.length);
} }
// can call multiple times (from populateFiles) // can call multiple times (from populateFiles)
function gatherFiles(step, options) { function gatherFiles(step:BuildStep, options?:BuildOptions) {
var maxts = 0; var maxts = 0;
if (step.files) { if (step.files) {
for (var i=0; i<step.files.length; i++) { for (var i=0; i<step.files.length; i++) {
@ -246,7 +266,7 @@ function gatherFiles(step, options) {
} }
} }
else if (step.code) { else if (step.code) {
var path = step.path ? step.path : options.mainFilePath; var path = step.path ? step.path : options.mainFilePath; // TODO: what if options null
if (!path) throw "need path or mainFilePath"; if (!path) throw "need path or mainFilePath";
var code = step.code; var code = step.code;
var entry = putWorkFile(path, code); var entry = putWorkFile(path, code);
@ -267,7 +287,7 @@ function gatherFiles(step, options) {
return maxts; return maxts;
} }
function populateFiles(step, fs, options) { function populateFiles(step:BuildStep, fs, options?:BuildOptions) {
gatherFiles(step, options); gatherFiles(step, options);
if (!step.files) throw "call gatherFiles() first"; if (!step.files) throw "call gatherFiles() first";
for (var i=0; i<step.files.length; i++) { for (var i=0; i<step.files.length; i++) {
@ -276,7 +296,7 @@ function populateFiles(step, fs, options) {
} }
} }
function populateExtraFiles(step, fs) { function populateExtraFiles(step:BuildStep, fs) {
// TODO: cache extra files // TODO: cache extra files
var extrafiles = step.params.extrafiles; var extrafiles = step.params.extrafiles;
if (extrafiles) { if (extrafiles) {
@ -298,7 +318,7 @@ function populateExtraFiles(step, fs) {
} }
} }
function staleFiles(step, targets) { function staleFiles(step:BuildStep, targets:string[]) {
if (!step.maxts) throw "call populateFiles() first"; if (!step.maxts) throw "call populateFiles() first";
// see if any target files are more recent than inputs // see if any target files are more recent than inputs
for (var i=0; i<targets.length; i++) { for (var i=0; i<targets.length; i++) {
@ -310,7 +330,7 @@ function staleFiles(step, targets) {
return false; return false;
} }
function anyTargetChanged(step, targets) { function anyTargetChanged(step:BuildStep, targets:string[]) {
if (!step.maxts) throw "call populateFiles() first"; if (!step.maxts) throw "call populateFiles() first";
// see if any target files are more recent than inputs // see if any target files are more recent than inputs
for (var i=0; i<targets.length; i++) { for (var i=0; i<targets.length; i++) {
@ -322,7 +342,7 @@ function anyTargetChanged(step, targets) {
return false; return false;
} }
function execMain(step, mod, args) { function execMain(step:BuildStep, mod, args:string[]) {
starttime(); starttime();
mod.callMain(args); mod.callMain(args);
endtime(step.tool); endtime(step.tool);
@ -334,40 +354,43 @@ var fsMeta = {};
var fsBlob = {}; var fsBlob = {};
var wasmBlob = {}; var wasmBlob = {};
const PSRC = "../../src/";
const PWORKER = PSRC+"worker/";
// load filesystems for CC65 and others asynchronously // load filesystems for CC65 and others asynchronously
function loadFilesystem(name) { function loadFilesystem(name:string) {
var xhr = new XMLHttpRequest(); var xhr = new XMLHttpRequest();
xhr.responseType = 'blob'; xhr.responseType = 'blob';
xhr.open("GET", "fs/fs"+name+".data", false); // synchronous request xhr.open("GET", PWORKER+"fs/fs"+name+".data", false); // synchronous request
xhr.send(null); xhr.send(null);
fsBlob[name] = xhr.response; fsBlob[name] = xhr.response;
xhr = new XMLHttpRequest(); xhr = new XMLHttpRequest();
xhr.responseType = 'json'; xhr.responseType = 'json';
xhr.open("GET", "fs/fs"+name+".js.metadata", false); // synchronous request xhr.open("GET", PWORKER+"fs/fs"+name+".js.metadata", false); // synchronous request
xhr.send(null); xhr.send(null);
fsMeta[name] = xhr.response; fsMeta[name] = xhr.response;
console.log("Loaded "+name+" filesystem", fsMeta[name].files.length, 'files', fsBlob[name].size, 'bytes'); console.log("Loaded "+name+" filesystem", fsMeta[name].files.length, 'files', fsBlob[name].size, 'bytes');
} }
var loaded = {} var loaded = {}
function load(modulename, debug) { function load(modulename:string, debug?:boolean) {
if (!loaded[modulename]) { if (!loaded[modulename]) {
importScripts('asmjs/'+modulename+(debug?"."+debug+".js":".js")); importScripts(PWORKER+'asmjs/'+modulename+(debug?"."+debug+".js":".js"));
loaded[modulename] = 1; loaded[modulename] = 1;
} }
} }
function loadGen(modulename) { function loadGen(modulename:string) {
if (!loaded[modulename]) { if (!loaded[modulename]) {
importScripts('../../gen/'+modulename+".js"); importScripts('../../gen/'+modulename+".js");
loaded[modulename] = 1; loaded[modulename] = 1;
} }
} }
function loadWASM(modulename, debug) { function loadWASM(modulename:string, debug?:boolean) {
if (!loaded[modulename]) { if (!loaded[modulename]) {
importScripts("wasm/" + modulename+(debug?"."+debug+".js":".js")); importScripts(PWORKER+"wasm/" + modulename+(debug?"."+debug+".js":".js"));
var xhr = new XMLHttpRequest(); var xhr = new XMLHttpRequest();
xhr.responseType = 'arraybuffer'; xhr.responseType = 'arraybuffer';
xhr.open("GET", "wasm/"+modulename+".wasm", false); // synchronous request xhr.open("GET", PWORKER+"wasm/"+modulename+".wasm", false); // synchronous request
xhr.send(null); xhr.send(null);
if (xhr.response) { if (xhr.response) {
wasmBlob[modulename] = new Uint8Array(xhr.response); wasmBlob[modulename] = new Uint8Array(xhr.response);
@ -378,7 +401,7 @@ function loadWASM(modulename, debug) {
} }
} }
} }
function loadNative(modulename, debug) { function loadNative(modulename:string) {
// detect WASM // detect WASM
if (CACHE_WASM_MODULES && typeof WebAssembly === 'object') { if (CACHE_WASM_MODULES && typeof WebAssembly === 'object') {
loadWASM(modulename); loadWASM(modulename);
@ -388,7 +411,7 @@ function loadNative(modulename, debug) {
} }
// mount the filesystem at /share // mount the filesystem at /share
function setupFS(FS, name) { function setupFS(FS, name:string) {
var WORKERFS = FS.filesystems['WORKERFS'] var WORKERFS = FS.filesystems['WORKERFS']
FS.mkdir('/share'); FS.mkdir('/share');
FS.mount(WORKERFS, { FS.mount(WORKERFS, {
@ -414,7 +437,7 @@ function setupFS(FS, name) {
}; };
} }
var print_fn = function(s) { var print_fn = function(s:string) {
console.log(s); console.log(s);
//console.log(new Error().stack); //console.log(new Error().stack);
} }
@ -425,15 +448,15 @@ var print_fn = function(s) {
var re_msvc = /[/]*([^( ]+)\s*[(](\d+)[)]\s*:\s*(.+?):\s*(.*)/; var re_msvc = /[/]*([^( ]+)\s*[(](\d+)[)]\s*:\s*(.+?):\s*(.*)/;
var re_msvc2 = /\s*(at)\s+(\d+)\s*(:)\s*(.*)/; var re_msvc2 = /\s*(at)\s+(\d+)\s*(:)\s*(.*)/;
function msvcErrorMatcher(errors) { function msvcErrorMatcher(errors:WorkerError[]) {
return function(s) { return function(s:string) {
var matches = re_msvc.exec(s) || re_msvc2.exec(s); var matches = re_msvc.exec(s) || re_msvc2.exec(s);
if (matches) { if (matches) {
var errline = parseInt(matches[2]); var errline = parseInt(matches[2]);
errors.push({ errors.push({
line:errline, line:errline,
path:matches[1], path:matches[1],
type:matches[3], //type:matches[3],
msg:matches[4] msg:matches[4]
}); });
} else { } else {
@ -442,7 +465,7 @@ function msvcErrorMatcher(errors) {
} }
} }
function makeErrorMatcher(errors, regex, iline, imsg, path) { function makeErrorMatcher(errors:WorkerError[], regex, iline:number, imsg:number, path:string) {
return function(s) { return function(s) {
var matches = regex.exec(s); var matches = regex.exec(s);
if (matches) { if (matches) {
@ -457,7 +480,7 @@ function makeErrorMatcher(errors, regex, iline, imsg, path) {
} }
} }
function extractErrors(regex, strings, path) { function extractErrors(regex, strings:string[], path:string) {
var errors = []; var errors = [];
var matcher = makeErrorMatcher(errors, regex, 1, 2, path); var matcher = makeErrorMatcher(errors, regex, 1, 2, path);
for (var i=0; i<strings.length; i++) { for (var i=0; i<strings.length; i++) {
@ -470,7 +493,7 @@ function extractErrors(regex, strings, path) {
var re_crlf = /\r?\n/; var re_crlf = /\r?\n/;
function parseListing(code, lineMatch, iline, ioffset, iinsns) { function parseListing(code:string, lineMatch, iline:number, ioffset:number, iinsns:number) {
var lines = []; var lines = [];
for (var line of code.split(re_crlf)) { for (var line of code.split(re_crlf)) {
var linem = lineMatch.exec(line); var linem = lineMatch.exec(line);
@ -490,7 +513,7 @@ function parseListing(code, lineMatch, iline, ioffset, iinsns) {
return lines; return lines;
} }
function parseSourceLines(code, lineMatch, offsetMatch) { function parseSourceLines(code:string, lineMatch, offsetMatch) {
var lines = []; var lines = [];
var lastlinenum = 0; var lastlinenum = 0;
for (var line of code.split(re_crlf)) { for (var line of code.split(re_crlf)) {
@ -512,7 +535,7 @@ function parseSourceLines(code, lineMatch, offsetMatch) {
return lines; return lines;
} }
function parseDASMListing(code, unresolved, mainFilename) { function parseDASMListing(code:string, unresolved:{}, mainFilename:string) {
// 4 08ee a9 00 start lda #01workermain.js:23:5 // 4 08ee a9 00 start lda #01workermain.js:23:5
var lineMatch = /\s*(\d+)\s+(\S+)\s+([0-9a-f]+)\s+([?0-9a-f][?0-9a-f ]+)?\s+(.+)?/i; var lineMatch = /\s*(\d+)\s+(\S+)\s+([0-9a-f]+)\s+([?0-9a-f][?0-9a-f ]+)?\s+(.+)?/i;
var equMatch = /\bequ\b/i; var equMatch = /\bequ\b/i;
@ -594,11 +617,12 @@ function parseDASMListing(code, unresolved, mainFilename) {
return {lines:lines, macrolines:macrolines, errors:errors}; return {lines:lines, macrolines:macrolines, errors:errors};
} }
function assembleDASM(step) { function assembleDASM(step:BuildStep) {
load("dasm"); load("dasm");
var re_usl = /(\w+)\s+0000\s+[?][?][?][?]/; var re_usl = /(\w+)\s+0000\s+[?][?][?][?]/;
var unresolved = {}; var unresolved = {};
var errors = []; var errors = [];
var errorMatcher = msvcErrorMatcher(errors);
function match_fn(s) { function match_fn(s) {
var matches = re_usl.exec(s); var matches = re_usl.exec(s);
if (matches) { if (matches) {
@ -608,9 +632,11 @@ function assembleDASM(step) {
} }
} else if (s.startsWith("Warning:")) { } else if (s.startsWith("Warning:")) {
errors.push({line:0, msg:s.substr(9)}); errors.push({line:0, msg:s.substr(9)});
} else {
errorMatcher(s);
} }
} }
var Module = DASM({ var Module = emglobal.DASM({
noInitialRun:true, noInitialRun:true,
print:match_fn print:match_fn
}); });
@ -663,7 +689,7 @@ function assembleDASM(step) {
}; };
} }
function setupStdin(fs, code) { function setupStdin(fs, code:string) {
var i = 0; var i = 0;
fs.init( fs.init(
function() { return i<code.length ? code.charCodeAt(i++) : null; } function() { return i<code.length ? code.charCodeAt(i++) : null; }
@ -722,7 +748,7 @@ function parseCA65Listing(code, symbols, params, dbg) {
return lines; return lines;
} }
function assembleCA65(step) { function assembleCA65(step:BuildStep) {
loadNative("ca65"); loadNative("ca65");
var errors = []; var errors = [];
gatherFiles(step, {mainFilePath:"main.s"}); gatherFiles(step, {mainFilePath:"main.s"});
@ -730,7 +756,7 @@ function assembleCA65(step) {
var lstpath = step.prefix+".lst"; var lstpath = step.prefix+".lst";
if (staleFiles(step, [objpath, lstpath])) { if (staleFiles(step, [objpath, lstpath])) {
var objout, lstout; var objout, lstout;
var CA65 = ca65({ var CA65 = emglobal.ca65({
instantiateWasm: moduleInstFn('ca65'), instantiateWasm: moduleInstFn('ca65'),
noInitialRun:true, noInitialRun:true,
//logReadFiles:true, //logReadFiles:true,
@ -755,7 +781,7 @@ function assembleCA65(step) {
}; };
} }
function linkLD65(step) { function linkLD65(step:BuildStep) {
loadNative("ld65"); loadNative("ld65");
var params = step.params; var params = step.params;
var platform = step.platform; var platform = step.platform;
@ -764,7 +790,7 @@ function linkLD65(step) {
if (staleFiles(step, [binpath])) { if (staleFiles(step, [binpath])) {
var errors = []; var errors = [];
var errmsg = ''; var errmsg = '';
var LD65 = ld65({ var LD65 = emglobal.ld65({
instantiateWasm: moduleInstFn('ld65'), instantiateWasm: moduleInstFn('ld65'),
noInitialRun:true, noInitialRun:true,
//logReadFiles:true, //logReadFiles:true,
@ -833,7 +859,7 @@ function linkLD65(step) {
} }
} }
function compileCC65(step) { function compileCC65(step:BuildStep) {
load("cc65"); load("cc65");
var params = step.params; var params = step.params;
// stderr // stderr
@ -854,7 +880,7 @@ function compileCC65(step) {
gatherFiles(step, {mainFilePath:"main.c"}); gatherFiles(step, {mainFilePath:"main.c"});
var destpath = step.prefix + '.s'; var destpath = step.prefix + '.s';
if (staleFiles(step, [destpath])) { if (staleFiles(step, [destpath])) {
var CC65 = cc65({ var CC65 = emglobal.cc65({
noInitialRun:true, noInitialRun:true,
//logReadFiles:true, //logReadFiles:true,
print:print_fn, print:print_fn,
@ -911,7 +937,7 @@ function parseIHX(ihx, rom_start, rom_size) {
return output; return output;
} }
function assembleSDASZ80(step) { function assembleSDASZ80(step:BuildStep) {
loadNative("sdasz80"); loadNative("sdasz80");
var objout, lstout, symout; var objout, lstout, symout;
var errors = []; var errors = [];
@ -927,7 +953,7 @@ function assembleSDASZ80(step) {
var match_asm_re2 = / <\w> (.+)/; // TODO var match_asm_re2 = / <\w> (.+)/; // TODO
var errline = 0; var errline = 0;
var errpath = step.path; var errpath = step.path;
function match_asm_fn(s) { var match_asm_fn = (s:string) => {
var m = match_asm_re1.exec(s); var m = match_asm_re1.exec(s);
if (m) { if (m) {
errline = parseInt(m[1]); errline = parseInt(m[1]);
@ -943,7 +969,7 @@ function assembleSDASZ80(step) {
} }
} }
} }
var ASZ80 = sdasz80({ var ASZ80 = emglobal.sdasz80({
instantiateWasm: moduleInstFn('sdasz80'), instantiateWasm: moduleInstFn('sdasz80'),
noInitialRun:true, noInitialRun:true,
//logReadFiles:true, //logReadFiles:true,
@ -969,7 +995,7 @@ function assembleSDASZ80(step) {
//symout = FS.readFile("main.sym", {encoding:'utf8'}); //symout = FS.readFile("main.sym", {encoding:'utf8'});
} }
function linkSDLDZ80(step) function linkSDLDZ80(step:BuildStep)
{ {
loadNative("sdldz80"); loadNative("sdldz80");
var errors = []; var errors = [];
@ -978,7 +1004,7 @@ function linkSDLDZ80(step)
if (staleFiles(step, [binpath])) { if (staleFiles(step, [binpath])) {
//?ASlink-Warning-Undefined Global '__divsint' referenced by module 'main' //?ASlink-Warning-Undefined Global '__divsint' referenced by module 'main'
var match_aslink_re = /\?ASlink-(\w+)-(.+)/; var match_aslink_re = /\?ASlink-(\w+)-(.+)/;
function match_aslink_fn(s) { var match_aslink_fn = (s:string) => {
var matches = match_aslink_re.exec(s); var matches = match_aslink_re.exec(s);
if (matches) { if (matches) {
errors.push({ errors.push({
@ -988,7 +1014,7 @@ function linkSDLDZ80(step)
} }
} }
var params = step.params; var params = step.params;
var LDZ80 = sdldz80({ var LDZ80 = emglobal.sdldz80({
instantiateWasm: moduleInstFn('sdldz80'), instantiateWasm: moduleInstFn('sdldz80'),
noInitialRun:true, noInitialRun:true,
//logReadFiles:true, //logReadFiles:true,
@ -1055,7 +1081,7 @@ function linkSDLDZ80(step)
} }
var sdcc; var sdcc;
function compileSDCC(step) { function compileSDCC(step:BuildStep) {
gatherFiles(step, { gatherFiles(step, {
mainFilePath:"main.c" // not used mainFilePath:"main.c" // not used
@ -1076,7 +1102,7 @@ function compileSDCC(step) {
var FS = SDCC['FS']; var FS = SDCC['FS'];
populateFiles(step, FS); populateFiles(step, FS);
// load source file and preprocess // load source file and preprocess
var code = workfs[step.path].data; // TODO var code = workfs[step.path].data as string; // TODO
var preproc = preprocessMCPP(step); var preproc = preprocessMCPP(step);
if (preproc.errors) return preproc; if (preproc.errors) return preproc;
else code = preproc.code; else code = preproc.code;
@ -1115,7 +1141,7 @@ function compileSDCC(step) {
}; };
} }
function preprocessMCPP(step) { function preprocessMCPP(step:BuildStep) {
load("mcpp"); load("mcpp");
var platform = step.platform; var platform = step.platform;
var params = PLATFORM_PARAMS[platform]; var params = PLATFORM_PARAMS[platform];
@ -1123,7 +1149,7 @@ function preprocessMCPP(step) {
// <stdin>:2: error: Can't open include file "foo.h" // <stdin>:2: error: Can't open include file "foo.h"
var errors = []; var errors = [];
var match_fn = makeErrorMatcher(errors, /<stdin>:(\d+): (.+)/, 1, 2, step.path); var match_fn = makeErrorMatcher(errors, /<stdin>:(\d+): (.+)/, 1, 2, step.path);
var MCPP = mcpp({ var MCPP = emglobal.mcpp({
noInitialRun:true, noInitialRun:true,
noFSInit:true, noFSInit:true,
print:print_fn, print:print_fn,
@ -1166,21 +1192,21 @@ function preprocessMCPP(step) {
// TODO: must be a better way to do all this // TODO: must be a better way to do all this
function detectModuleName(code) { function detectModuleName(code:string) {
var m = /^\s*module\s+(\w+_top)\b/m.exec(code) var m = /^\s*module\s+(\w+_top)\b/m.exec(code)
|| /^\s*module\s+(top)\b/m.exec(code) || /^\s*module\s+(top)\b/m.exec(code)
|| /^\s*module\s+(\w+)\b/m.exec(code); || /^\s*module\s+(\w+)\b/m.exec(code);
return m ? m[1] : null; return m ? m[1] : null;
} }
function detectTopModuleName(code) { function detectTopModuleName(code:string) {
var topmod = detectModuleName(code) || "top"; var topmod = detectModuleName(code) || "top";
var m = /^\s*module\s+(\w+?_top)/m.exec(code); var m = /^\s*module\s+(\w+?_top)/m.exec(code);
if (m && m[1]) topmod = m[1]; if (m && m[1]) topmod = m[1];
return topmod; return topmod;
} }
function writeDependencies(depends, FS, errors, callback) { function writeDependencies(depends:Dependency[], FS, errors:WorkerError[], callback?) {
if (depends) { if (depends) {
for (var i=0; i<depends.length; i++) { for (var i=0; i<depends.length; i++) {
var d = depends[i]; var d = depends[i];
@ -1197,9 +1223,9 @@ var jsasm_module_top;
var jsasm_module_output; var jsasm_module_output;
var jsasm_module_key; var jsasm_module_key;
function compileJSASM(asmcode, platform, options, is_inline) { function compileJSASM(asmcode:string, platform, options, is_inline) {
loadGen("worker/assembler"); loadGen("worker/assembler");
var asm = new Assembler(); var asm = new (Assembler as any)();
var includes = []; var includes = [];
asm.loadJSON = function(filename) { asm.loadJSON = function(filename) {
// TODO: what if it comes from dependencies? // TODO: what if it comes from dependencies?
@ -1228,7 +1254,7 @@ function compileJSASM(asmcode, platform, options, is_inline) {
var main_filename = includes[includes.length-1]; var main_filename = includes[includes.length-1];
var code = '`include "' + main_filename + '"\n'; var code = '`include "' + main_filename + '"\n';
code += "/*\nmodule " + top_module + "\n*/\n"; code += "/*\nmodule " + top_module + "\n*/\n";
var voutput = compileVerilator({code:code, platform:platform, dependencies:options.dependencies, path:options.path}); // TODO var voutput = compileVerilator({code:code, platform:platform, dependencies:options.dependencies, path:options.path, tool:'verilator'}); // TODO
if (voutput.errors.length) if (voutput.errors.length)
return voutput.errors[0].msg; return voutput.errors[0].msg;
jsasm_module_output = voutput; jsasm_module_output = voutput;
@ -1248,14 +1274,14 @@ function compileJSASM(asmcode, platform, options, is_inline) {
return result; return result;
} }
function compileJSASMStep(step) { function compileJSASMStep(step:BuildStep) {
// TODO // TODO
var code = step.code; var code = step.code;
var platform = step.platform || 'verilog'; var platform = step.platform || 'verilog';
return compileJSASM(code, platform, step); // TODO return compileJSASM(code, platform, step, false); // TODO
} }
function compileInlineASM(code, platform, options, errors, asmlines) { function compileInlineASM(code:string, platform, options, errors, asmlines) {
code = code.replace(/__asm\b([\s\S]+?)\b__endasm\b/g, function(s,asmcode,index) { code = code.replace(/__asm\b([\s\S]+?)\b__endasm\b/g, function(s,asmcode,index) {
var firstline = code.substr(0,index).match(/\n/g).length; var firstline = code.substr(0,index).match(/\n/g).length;
var asmout = compileJSASM(asmcode, platform, options, true); var asmout = compileJSASM(asmcode, platform, options, true);
@ -1266,7 +1292,7 @@ function compileInlineASM(code, platform, options, errors, asmlines) {
} }
return ""; return "";
} else if (asmout.output) { } else if (asmout.output) {
var s = ""; let s = "";
var out = asmout.output; var out = asmout.output;
for (var i=0; i<out.length; i++) { for (var i=0; i<out.length; i++) {
if (i>0) s += ","; if (i>0) s += ",";
@ -1286,7 +1312,7 @@ function compileInlineASM(code, platform, options, errors, asmlines) {
} }
// TODO: make compliant with standard msg format // TODO: make compliant with standard msg format
function compileVerilator(step) { function compileVerilator(step:BuildStep) {
loadNative("verilator_bin"); loadNative("verilator_bin");
loadGen("worker/verilator2js"); loadGen("worker/verilator2js");
var platform = step.platform || 'verilog'; var platform = step.platform || 'verilog';
@ -1297,8 +1323,8 @@ function compileVerilator(step) {
return {errors:errors}; return {errors:errors};
} }
var code = step.code; var code = step.code;
var match_fn = makeErrorMatcher(errors, /%(.+?): (.+?:)?(\d+)?[:]?\s*(.+)/i, 3, 4); var match_fn = makeErrorMatcher(errors, /%(.+?): (.+?:)?(\d+)?[:]?\s*(.+)/i, 3, 4, step.path);
var verilator_mod = verilator_bin({ var verilator_mod = emglobal.verilator_bin({
instantiateWasm: moduleInstFn('verilator_bin'), instantiateWasm: moduleInstFn('verilator_bin'),
noInitialRun:true, noInitialRun:true,
print:print_fn, print:print_fn,
@ -1336,13 +1362,16 @@ function compileVerilator(step) {
putWorkFile("main.js", rtn.output.code); putWorkFile("main.js", rtn.output.code);
if (!anyTargetChanged(step, ["main.js"])) if (!anyTargetChanged(step, ["main.js"]))
return; return;
rtn.errors = errors; //rtn.intermediate = {listing:h_file + cpp_file}; // TODO
rtn.intermediate = {listing:h_file + cpp_file}; // TODO var listings = {};
rtn.listings = {};
// TODO: what if found in non-top-module? // TODO: what if found in non-top-module?
if (asmlines.length) if (asmlines.length)
rtn.listings[step.path] = {lines:asmlines}; listings[step.path] = {lines:asmlines};
return rtn; return {
output: rtn.output,
errors: errors,
listings: {},
};
} catch(e) { } catch(e) {
console.log(e); console.log(e);
return {errors:errors}; return {errors:errors};
@ -1350,13 +1379,13 @@ function compileVerilator(step) {
} }
// TODO: test // TODO: test
function compileYosys(step) { function compileYosys(step:BuildStep) {
loadNative("yosys"); loadNative("yosys");
var code = step.code; var code = step.code;
var errors = []; var errors = [];
var match_fn = makeErrorMatcher(errors, /ERROR: (.+?) in line (.+?[.]v):(\d+)[: ]+(.+)/i, 3, 4); var match_fn = makeErrorMatcher(errors, /ERROR: (.+?) in line (.+?[.]v):(\d+)[: ]+(.+)/i, 3, 4, step.path);
starttime(); starttime();
var yosys_mod = yosys({ var yosys_mod = emglobal.yosys({
instantiateWasm: moduleInstFn('yosys'), instantiateWasm: moduleInstFn('yosys'),
noInitialRun:true, noInitialRun:true,
print:print_fn, print:print_fn,
@ -1389,7 +1418,7 @@ function compileYosys(step) {
} }
} }
function assembleZMAC(step) { function assembleZMAC(step:BuildStep) {
loadNative("zmac"); loadNative("zmac");
var hexout, lstout, binout; var hexout, lstout, binout;
var errors = []; var errors = [];
@ -1406,7 +1435,7 @@ error1.asm(11): warning: 'foobar' treated as label (instruction typo?)
Add a colon or move to first column to stop this warning. Add a colon or move to first column to stop this warning.
1 errors (see listing if no diagnostics appeared here) 1 errors (see listing if no diagnostics appeared here)
*/ */
var ZMAC = zmac({ var ZMAC = emglobal.zmac({
instantiateWasm: moduleInstFn('zmac'), instantiateWasm: moduleInstFn('zmac'),
noInitialRun:true, noInitialRun:true,
//logReadFiles:true, //logReadFiles:true,
@ -1490,7 +1519,7 @@ var TOOL_PRELOADFS = {
'sccz80': 'sccz80', 'sccz80': 'sccz80',
} }
function applyDefaultErrorPath(errors, path) { function applyDefaultErrorPath(errors:WorkerError[], path:string) {
if (!path) return; if (!path) return;
for (var i=0; i<errors.length; i++) { for (var i=0; i<errors.length; i++) {
var err = errors[i]; var err = errors[i];

View File

@ -49,8 +49,16 @@ export interface Dependency {
data:FileData // TODO: or binary? data:FileData // TODO: or binary?
} }
export interface WorkerFileUpdate { path:string, data:FileData }; export interface WorkerFileUpdate {
export interface WorkerBuildStep { path:string, platform:string, tool:string, mainfile?:boolean }; path:string,
data:FileData
};
export interface WorkerBuildStep {
path?:string
platform:string
tool:string
mainfile?:boolean
};
export interface WorkerMessage { export interface WorkerMessage {
updates:WorkerFileUpdate[], updates:WorkerFileUpdate[],

View File

@ -5,13 +5,16 @@ var vm = require('vm');
var worker = {}; var worker = {};
global.window = global;
global.exports = {};
global.includeInThisContext = function(path) { global.includeInThisContext = function(path) {
var code = fs.readFileSync(path); var code = fs.readFileSync(path);
vm.runInThisContext(code, path); vm.runInThisContext(code, path);
}; };
global.importScripts = function(path) { global.importScripts = function(path) {
includeInThisContext('src/worker/'+path); includeInThisContext('gen/worker/'+path);
} }
function Blob(blob) { function Blob(blob) {
@ -58,7 +61,7 @@ global.FileReaderSync = function() {
global.onmessage = null; global.onmessage = null;
global.postMessage = null; global.postMessage = null;
includeInThisContext("src/worker/workermain.js"); includeInThisContext("gen/worker/workermain.js");
global.ab2str = function(buf) { global.ab2str = function(buf) {
return String.fromCharCode.apply(null, new Uint16Array(buf)); return String.fromCharCode.apply(null, new Uint16Array(buf));