import { Segment, CodeListingMap, WorkerResult, WorkerError } from "../../common/workertypes"; import * as basic_compiler from '../../common/basic/compiler'; import { getRootBasePlatform, parseXMLPoorly } from "../../common/util"; import { EmscriptenModule, emglobal, execMain, load, loadNative, moduleInstFn, print_fn, setupFS } from "../wasmutils"; import { BuildStep, BuildStepResult, getWorkFileAsString, gatherFiles, staleFiles, populateFiles, putWorkFile, anyTargetChanged, populateExtraFiles } from "../builder"; import { msvcErrorMatcher, parseListing, makeErrorMatcher } from "../listingutils"; import { setupRequireFunction } from "../workermain"; export function translateShowdown(step: BuildStep): BuildStepResult { setupRequireFunction(); load("showdown.min"); var showdown = emglobal['showdown']; var converter = new showdown.Converter({ tables: 'true', smoothLivePreview: 'true', requireSpaceBeforeHeadingText: 'true', emoji: 'true', }); var code = getWorkFileAsString(step.path); var html = converter.makeHtml(code); delete emglobal['require']; return { output: html }; } export function compileInform6(step: BuildStep): BuildStepResult { loadNative("inform"); var errors = []; gatherFiles(step, { mainFilePath: "main.inf" }); var objpath = step.prefix + ".z5"; if (staleFiles(step, [objpath])) { var errorMatcher = msvcErrorMatcher(errors); var lstout = ""; var match_fn = (s: string) => { if (s.indexOf("Error:") >= 0) { errorMatcher(s); } else { lstout += s; lstout += "\n"; } } // TODO: step.path must end in '.inf' or error var args = ['-afjnops', '-v5', '-Cu', '-E1', '-k', '+/share/lib', step.path]; var inform: EmscriptenModule = emglobal.inform({ instantiateWasm: moduleInstFn('inform'), noInitialRun: true, //logReadFiles:true, print: match_fn, printErr: match_fn, }); var FS = inform.FS; setupFS(FS, 'inform'); populateFiles(step, FS); //fixParamsWithDefines(step.path, step.params); execMain(step, inform, args); if (errors.length) return { errors: errors }; var objout = FS.readFile(objpath, { encoding: 'binary' }); putWorkFile(objpath, objout); if (!anyTargetChanged(step, [objpath])) return; // parse debug XML var symbolmap = {}; var segments: Segment[] = []; var entitymap = { // number -> string 'object': {}, 'property': {}, 'attribute': {}, 'constant': {}, 'global-variable': {}, 'routine': {}, }; var dbgout = FS.readFile("gameinfo.dbg", { encoding: 'utf8' }); var xmlroot = parseXMLPoorly(dbgout); //console.log(xmlroot); var segtype = "ram"; xmlroot.children.forEach((node) => { switch (node.type) { case 'global-variable': case 'routine': var ident = node.children.find((c, v) => c.type == 'identifier').text; var address = parseInt(node.children.find((c, v) => c.type == 'address').text); symbolmap[ident] = address; entitymap[node.type][address] = ident; break; case 'object': case 'property': case 'attribute': var ident = node.children.find((c, v) => c.type == 'identifier').text; var value = parseInt(node.children.find((c, v) => c.type == 'value').text); //entitymap[node.type][ident] = value; entitymap[node.type][value] = ident; //symbolmap[ident] = address | 0x1000000; break; case 'story-file-section': var name = node.children.find((c, v) => c.type == 'type').text; var address = parseInt(node.children.find((c, v) => c.type == 'address').text); var endAddress = parseInt(node.children.find((c, v) => c.type == 'end-address').text); if (name == "grammar table") segtype = "rom"; segments.push({ name: name, start: address, size: endAddress - address, type: segtype }); } }); // parse listing var listings: CodeListingMap = {}; // 35 +00015 <*> call_vs long_19 location long_424 -> sp var lines = parseListing(lstout, /\s*(\d+)\s+[+]([0-9a-f]+)\s+([<*>]*)\s*(\w+)\s+(.+)/i, -1, 2, 4); var lstpath = step.prefix + '.lst'; listings[lstpath] = { lines: [], asmlines: lines, text: lstout }; return { output: objout, //.slice(0), listings: listings, errors: errors, symbolmap: symbolmap, segments: segments, debuginfo: entitymap, }; } } export function compileBASIC(step: BuildStep): WorkerResult { var jsonpath = step.path + ".json"; gatherFiles(step); if (staleFiles(step, [jsonpath])) { var parser = new basic_compiler.BASICParser(); var code = getWorkFileAsString(step.path); try { var ast = parser.parseFile(code, step.path); } catch (e) { console.log(e); if (parser.errors.length == 0) throw e; } if (parser.errors.length) { return { errors: parser.errors }; } // put AST into JSON (sans source locations) to see if it has changed var json = JSON.stringify(ast, (key, value) => { return (key == '$loc' ? undefined : value) }); putWorkFile(jsonpath, json); if (anyTargetChanged(step, [jsonpath])) return { output: ast, listings: parser.getListings(), }; } } export function compileWiz(step: BuildStep): WorkerResult { loadNative("wiz"); var params = step.params; gatherFiles(step, { mainFilePath: "main.wiz" }); var destpath = step.prefix + (params.wiz_rom_ext || ".bin"); var errors: WorkerError[] = []; if (staleFiles(step, [destpath])) { var wiz: EmscriptenModule = emglobal.wiz({ instantiateWasm: moduleInstFn('wiz'), noInitialRun: true, print: print_fn, //test.wiz:2: error: expected statement, but got identifier `test` printErr: makeErrorMatcher(errors, /(.+?):(\d+):\s*(.+)/, 2, 3, step.path, 1), }); var FS = wiz.FS; setupFS(FS, 'wiz'); populateFiles(step, FS); populateExtraFiles(step, FS, params.extra_compile_files); const FWDIR = '/share/common'; var args = [ '-o', destpath, '-I', FWDIR + '/' + (params.wiz_inc_dir || getRootBasePlatform(step.platform)), '-s', 'wla', '--color=none', step.path]; args.push('--system', params.wiz_sys_type || params.arch); execMain(step, wiz, args); if (errors.length) return { errors: errors }; var binout = FS.readFile(destpath, { encoding: 'binary' }); putWorkFile(destpath, binout); var dbgout = FS.readFile(step.prefix + '.sym', { encoding: 'utf8' }); var symbolmap = {}; for (var s of dbgout.split("\n")) { var toks = s.split(/ /); // 00:4008 header.basic_start if (toks && toks.length >= 2) { var tokrange = toks[0].split(':'); var start = parseInt(tokrange[1], 16); var sym = toks[1]; symbolmap[sym] = start; } } return { output: binout, //.slice(0), errors: errors, symbolmap: symbolmap, }; } }