{ "version": 3, "sources": ["../../src/common/util.ts", "../../src/common/basic/compiler.ts", "../../src/worker/tools/misc.ts", "../../src/worker/tools/cc65.ts", "../../src/worker/tools/dasm.ts", "../../src/worker/tools/sdcc.ts", "../../src/worker/assembler.ts", "../../src/common/hdl/hdltypes.ts", "../../src/common/hdl/vxmlparser.ts", "../../src/worker/tools/verilog.ts", "../../src/worker/tools/m6809.ts", "../../src/worker/tools/m6502.ts", "../../src/worker/tools/z80.ts", "../../src/worker/tools/x86.ts", "../../src/worker/tools/arm.ts", "../../src/common/tokenizer.ts", "../../src/common/ecs/binpack.ts", "../../src/common/ecs/ecs.ts", "../../src/common/ecs/decoder.ts", "../../src/common/ecs/compiler.ts", "../../src/worker/tools/ecs.ts", "../../src/common/workertypes.ts", "../../src/worker/tools/remote.ts", "../../src/worker/workermain.ts"], "sourcesContent": ["\nexport function lpad(s:string, n:number):string {\n s += ''; // convert to string\n while (s.length 0) ? s.substr(0, pos) : s;\n}\n\nexport function hex(v:number, nd?:number) {\n if (!nd) nd = 2;\n if (nd == 8) {\n return hex((v>>16)&0xffff,4) + hex(v&0xffff,4);\n } else {\n return toradix(v,nd,16);\n }\n}\n\nexport function tobin(v:number, nd?:number) {\n if (!nd) nd = 8;\n return toradix(v,nd,2);\n}\n\nexport function toradix(v:number, nd:number, radix:number) {\n try {\n var s = v.toString(radix).toUpperCase();\n while (s.length < nd)\n s = \"0\" + s;\n return s;\n } catch (e) {\n return v+\"\";\n }\n}\n\nexport function arrayCompare(a:ArrayLike, b:ArrayLike):boolean {\n if (a == null && b == null) return true;\n if (a == null) return false;\n if (b == null) return false;\n if (a.length != b.length) return false;\n for (var i=0; i= 0) {\n while (i < s1.length && split1[i].indexOf(\"\\n\") < 0)\n i++;\n }\n if (w1 != w2) {\n w2 = '' + w2 + '';\n }\n result += w2;\n i++;\n j++;\n }\n while (j < split2.length) {\n result += split2[j++];\n }\n return result;\n}\n\nexport function lzgmini() {\n\n // Constants\n var LZG_HEADER_SIZE = 16;\n var LZG_METHOD_COPY = 0;\n var LZG_METHOD_LZG1 = 1;\n\n // LUT for decoding the copy length parameter\n var LZG_LENGTH_DECODE_LUT = [2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,\n 20,21,22,23,24,25,26,27,28,29,35,48,72,128];\n\n // Decoded data (produced by the decode() method)\n var outdata = null;\n\n // Calculate the checksum\n var calcChecksum = function(data) {\n var a = 1;\n var b = 0;\n var i = LZG_HEADER_SIZE;\n while (i < data.length)\n {\n a = (a + (data[i] & 0xff)) & 0xffff;\n b = (b + a) & 0xffff;\n i++;\n }\n return (b << 16) | a;\n }\n\n // Decode LZG coded data. The function returns the size of the decoded data.\n // Use any of the get* methods to retrieve the decoded data.\n this.decode = function(data:number[]):number[] {\n // Start by clearing the decompressed array in this object\n outdata = null;\n\n // Check magic ID\n if ((data.length < LZG_HEADER_SIZE) || (data[0] != 76) ||\n (data[1] != 90) || (data[2] != 71))\n {\n return null;\n }\n \n // what's the length?\n var uncomplen = data[6] | (data[5]<<8) | (data[4]<<16) | (data[3]<<24);\n\n // Calculate & check the checksum\n var checksum = ((data[11] & 0xff) << 24) |\n ((data[12] & 0xff) << 16) |\n ((data[13] & 0xff) << 8) |\n (data[14] & 0xff);\n if (calcChecksum(data) != checksum)\n {\n return null;\n }\n\n var dst = new Array();\n // Check which method to use\n var method = data[15] & 0xff;\n if (method == LZG_METHOD_LZG1)\n {\n // Get marker symbols\n var m1 = data[16] & 0xff;\n var m2 = data[17] & 0xff;\n var m3 = data[18] & 0xff;\n var m4 = data[19] & 0xff;\n\n // Main decompression loop\n var symbol, b, b2, b3, len, offset;\n var dstlen = 0;\n var k = LZG_HEADER_SIZE + 4;\n var datalen = data.length;\n while (k <= datalen)\n {\n symbol = data[k++] & 0xff;\n if ((symbol != m1) && (symbol != m2) && (symbol != m3) && (symbol != m4))\n {\n // Literal copy\n dst[dstlen++] = symbol;\n }\n else\n {\n b = data[k++] & 0xff;\n if (b != 0)\n {\n // Decode offset / length parameters\n if (symbol == m1)\n {\n // marker1 - \"Distant copy\"\n len = LZG_LENGTH_DECODE_LUT[b & 0x1f];\n b2 = data[k++] & 0xff;\n b3 = data[k++] & 0xff;\n offset = (((b & 0xe0) << 11) | (b2 << 8) | b3) + 2056;\n }\n else if (symbol == m2)\n {\n // marker2 - \"Medium copy\"\n len = LZG_LENGTH_DECODE_LUT[b & 0x1f];\n b2 = data[k++] & 0xff;\n offset = (((b & 0xe0) << 3) | b2) + 8;\n }\n else if (symbol == m3)\n {\n // marker3 - \"Short copy\"\n len = (b >> 6) + 3;\n offset = (b & 63) + 8;\n }\n else\n {\n // marker4 - \"Near copy (incl. RLE)\"\n len = LZG_LENGTH_DECODE_LUT[b & 0x1f];\n offset = (b >> 5) + 1;\n }\n\n // Copy the corresponding data from the history window\n for (i = 0; i < len; i++)\n {\n dst[dstlen] = dst[dstlen-offset];\n dstlen++;\n }\n }\n else\n {\n // Literal copy (single occurance of a marker symbol)\n dst[dstlen++] = symbol;\n }\n }\n }\n\n }\n else if (method == LZG_METHOD_COPY)\n {\n // Plain copy\n var dstlen = 0;\n var datalen = data.length;\n for (var i = LZG_HEADER_SIZE; i < datalen; i++)\n {\n dst[dstlen++] = data[i] & 0xff;\n }\n }\n else\n {\n // Unknown method\n return null;\n }\n // Store the decompressed data in the lzgmini object for later retrieval\n if (dst.length < uncomplen) return null; // data too short\n outdata = dst.slice(0, uncomplen);\n return outdata;\n }\n\n // Get the decoded byte array\n this.getByteArray = function():number[]\n {\n return outdata;\n }\n\n // Get the decoded string from a Latin 1 (or ASCII) encoded array\n this.getStringLatin1 = function():string {\n return byteArrayToString(outdata);\n }\n\n // Get the decoded string from an UTF-8 encoded array\n this.getStringUTF8 = function():string {\n return byteArrayToUTF8(outdata);\n }\n}\n\nexport function stringToByteArray(s:string) : Uint8Array {\n var a = new Uint8Array(s.length);\n for (var i=0; i= 192) && (c < 224)) {\n c = ((c & 31) << 6) | (data[i++] & 63);\n } else {\n c = ((c & 15) << 12) | ((data[i] & 63) << 6) | (data[i+1] & 63);\n i += 2;\n if (c == 0xfeff) continue; // ignore BOM\n }\n str += String.fromCharCode(c);\n }\n }\n return str;\n}\n\nexport function removeBOM(s:string) {\n if (s.charCodeAt(0) === 0xFEFF) {\n s = s.substr(1);\n }\n return s;\n}\n\nexport function isProbablyBinary(path:string, data?:number[] | Uint8Array) : boolean {\n var score = 0;\n // check extensions\n if (path) {\n path = path.toUpperCase();\n const BINEXTS = ['.CHR','.BIN','.DAT','.PAL','.NAM','.RLE','.LZ4','.NSF'];\n for (var ext of BINEXTS) {\n if (path.endsWith(ext)) score++;\n }\n }\n // decode as UTF-8\n for (var i = 0; i < (data?data.length:0);) {\n let c = data[i++];\n if ((c & 0x80) == 0) {\n // more likely binary if we see a NUL or obscure control character\n if (c < 9 || (c >= 14 && c < 26) || c == 0x7f) {\n score++;\n break;\n }\n } else {\n // look for invalid unicode sequences\n var nextra = 0;\n if ((c & 0xe0) == 0xc0) nextra = 1;\n else if ((c & 0xf0) == 0xe0) nextra = 2;\n else if ((c & 0xf8) == 0xf0) nextra = 3;\n else if (c < 0xa0) score++;\n else if (c == 0xff) score++;\n while (nextra--) {\n if (i >= data.length || (data[i++] & 0xc0) != 0x80) {\n score++;\n break;\n }\n }\n }\n }\n return score > 0;\n}\n\n// need to load liblzg.js first\nexport function compressLZG(em_module, inBuffer:number[], levelArg?:boolean) : Uint8Array {\n var level = levelArg || 9;\n var inLen = inBuffer.length;\n var inPtr = em_module._malloc(inLen + 1);\n for (var i = 0; i < inLen; i++) {\n em_module.setValue(inPtr + i, inBuffer[i], 'i8');\n }\n var maxEncSize = em_module._LZG_MaxEncodedSize(inLen);\n var outPtr = em_module._malloc(maxEncSize + 1);\n var compLen = em_module.ccall('compress_lzg', 'number', ['number', 'number', 'number', 'number', 'number'], [level, inPtr, inLen, maxEncSize, outPtr]);\n em_module._free(inPtr);\n var outBuffer = new Uint8Array(compLen);\n for (var i = 0; i < compLen; i++) {\n outBuffer[i] = em_module.getValue(outPtr + i, 'i8');\n }\n em_module._free(outPtr);\n return outBuffer;\n}\n\n// only does primitives, 1D arrays and no recursion\nexport function safe_extend(deep, dest, src) {\n // TODO: deep ignored\n for (var key in src) {\n var val = src[key];\n var type = typeof(val);\n if (val === null || type == 'undefined') {\n dest[key] = val;\n } else if (type == 'function') {\n // ignore function\n } else if (type == 'object') {\n if (val['slice']) { // array?\n dest[key] = val.slice();\n } else {\n // ignore object\n }\n } else {\n dest[key] = val;\n }\n }\n return dest;\n}\n\nexport function printFlags(val:number, names:string[], r2l:boolean) {\n var s = '';\n for (var i=0; i 0) s += \" \";\n s += (val & bit) ? names[i] : \"-\";\n }\n }\n return s;\n}\n\nexport function rgb2bgr(x) {\n return ((x&0xff)<<16) | ((x>>16)&0xff) | (x&0x00ff00);\n}\n\nexport function RGBA(r:number,g:number,b:number) {\n return (r&0xff) | ((g&0xff)<<8) | ((b&0xff)<<16) | 0xff000000;\n}\n\nexport function clamp(minv:number, maxv:number, v:number) {\n return (v < minv) ? minv : (v > maxv) ? maxv : v;\n}\n\nexport function safeident(s : string) : string {\n return s.replace(/\\W+/g, \"_\");\n}\n\nexport function rle_unpack(src : Uint8Array) : Uint8Array {\n var i = 0;\n var tag = src[i++];\n var dest = [];\n var data = tag;\n while (i < src.length) {\n var ch = src[i++];\n if (ch == tag) {\n var count = src[i++];\n for (var j=0; jvoid, datatype:'text'|'arraybuffer') {\n var oReq = new XMLHttpRequest();\n oReq.open(\"GET\", url, true);\n oReq.responseType = datatype;\n oReq.onload = function (oEvent) {\n if (oReq.status == 200) {\n var data = oReq.response;\n if (data instanceof ArrayBuffer) {\n data = new Uint8Array(data);\n }\n success(data);\n } else if (oReq.status == 404) {\n success(null);\n } else {\n throw Error(\"Error \" + oReq.status + \" loading \" + url);\n }\n }\n oReq.onerror = function (oEvent) {\n success(null);\n }\n oReq.ontimeout = function (oEvent) {\n throw Error(\"Timeout loading \" + url);\n }\n oReq.send(null);\n}\n\n// get platform ID without . emulator\nexport function getBasePlatform(platform : string) : string {\n return platform.split('.')[0];\n}\n\n// get platform ID without - specialization\nfunction getRootPlatform(platform : string) : string {\n return platform.split('-')[0];\n}\n\n// get platform ID without emulator or specialization\nexport function getRootBasePlatform(platform : string) : string {\n return getRootPlatform(getBasePlatform(platform));\n}\n\nexport function isArray(obj: any) : obj is ArrayLike {\n return obj != null && (Array.isArray(obj) || isTypedArray(obj));\n}\n\nexport function isTypedArray(obj: any) : obj is ArrayLike {\n return obj != null && obj['BYTES_PER_ELEMENT'];\n}\n\nexport function convertDataToUint8Array(data: string|Uint8Array) : Uint8Array {\n return (typeof data === 'string') ? stringToByteArray(data) : data;\n}\n\nexport function convertDataToString(data: string|Uint8Array) : string {\n return (data instanceof Uint8Array) ? byteArrayToUTF8(data) : data;\n}\n\nexport function byteToASCII(b: number) : string {\n if (b < 32)\n return String.fromCharCode(b + 0x2400);\n else\n return String.fromCharCode(b);\n}\n\nexport function loadScript(scriptfn:string) : Promise {\n return new Promise( (resolve, reject) => {\n var script = document.createElement('script');\n script.onload = resolve;\n script.onerror = reject;\n script.src = scriptfn;\n document.getElementsByTagName('head')[0].appendChild(script);\n });\n}\n\nexport function decodeQueryString(qs : string) : {} {\n if (qs.startsWith('?')) qs = qs.substr(1);\n var a = qs.split('&');\n if (!a || a.length == 0)\n return {};\n var b = {};\n for (var i = 0; i < a.length; ++i) {\n var p = a[i].split('=', 2);\n if (p.length == 1)\n b[p[0]] = \"\";\n else\n b[p[0]] = decodeURIComponent(p[1].replace(/\\+/g, \" \"));\n }\n return b;\n}\n\nexport function parseBool(s : string) : boolean {\n if (!s) return false;\n if (s == 'false' || s == '0') return false;\n if (s == 'true' || s == '1') return true;\n return s ? true : false;\n}\n\n///\n\nexport class XMLParseError extends Error {\n}\n\nexport interface XMLNode {\n type: string;\n text: string | null;\n children: XMLNode[];\n attrs: { [id: string]: string };\n obj: any;\n}\n\nexport type XMLVisitFunction = (node: XMLNode) => any;\n\nfunction escapeXML(s: string): string {\n if (s.indexOf('&') >= 0) {\n return s.replace(/'/g, \"'\")\n .replace(/"/g, '\"')\n .replace(/>/g, '>')\n .replace(/</g, '<')\n .replace(/&/g, '&');\n } else {\n return s;\n }\n}\n\nexport function parseXMLPoorly(s: string, openfn?: XMLVisitFunction, closefn?: XMLVisitFunction): XMLNode {\n const tag_re = /[<]([/]?)([?a-z_-]+)([^>]*)[>]+|(\\s*[^<]+)/gi;\n const attr_re = /\\s*(\\w+)=\"(.*?)\"\\s*/gi;\n var fm: RegExpMatchArray;\n var stack: XMLNode[] = [];\n var top: XMLNode;\n\n function closetop() {\n top = stack.pop();\n if (top == null || top.type != ident) throw new XMLParseError(\"mismatch close tag: \" + ident);\n if (closefn) {\n top.obj = closefn(top);\n }\n if (stack.length == 0) throw new XMLParseError(\"close tag without open: \" + ident);\n stack[stack.length - 1].children.push(top);\n }\n function parseattrs(as: string): { [id: string]: string } {\n var am;\n var attrs = {};\n if (as != null) {\n while (am = attr_re.exec(as)) {\n attrs[am[1]] = escapeXML(am[2]);\n }\n }\n return attrs;\n }\n while (fm = tag_re.exec(s)) {\n var [_m0, close, ident, attrs, content] = fm;\n //console.log(stack.length, close, ident, attrs, content);\n if (close) {\n closetop();\n } else if (ident) {\n var node = { type: ident, text: null, children: [], attrs: parseattrs(attrs), obj: null };\n stack.push(node);\n if (attrs) {\n parseattrs(attrs);\n }\n if (openfn) {\n node.obj = openfn(node);\n }\n if (attrs && attrs.endsWith('/')) closetop();\n } else if (content != null) {\n if (stack.length == 0) throw new XMLParseError(\"content without element\");\n var txt = escapeXML(content as string).trim();\n if (txt.length) stack[stack.length - 1].text = txt;\n }\n }\n if (stack.length != 1) throw new XMLParseError(\"tag not closed\");\n if (stack[0].type != '?xml') throw new XMLParseError(\"?xml needs to be first element\");\n return top;\n}\n\nexport function escapeHTML(s: string): string {\n return s.replace(/[&]/g, '&').replace(/[<]/g, '<').replace(/[>]/g, '>');\n}\n\n// lame factorization for displaying bitmaps\n// returns a > b such that a * b == x (or higher), a >= mina, b >= minb\nexport function findIntegerFactors(x: number, mina: number, minb: number, aspect: number) : {a: number, b: number} {\n let a = x;\n let b = 1;\n if (minb > 1 && minb < a) {\n a = Math.ceil(x / minb);\n b = minb;\n }\n while (a > b) {\n let a2 = a;\n let b2 = b;\n if ((a & 1) == 0) {\n b2 = b * 2;\n a2 = a / 2;\n }\n if ((a % 3) == 0) {\n b2 = b * 3;\n a2 = a / 3;\n }\n if ((a % 5) == 0) {\n b2 = b * 5;\n a2 = a / 5;\n }\n if (a2 < mina) break;\n if (a2 < b2 * aspect) break;\n a = a2;\n b = b2;\n }\n return {a, b};\n}\n\nexport class FileDataCache {\n maxSize : number = 8000000;\n size : number;\n cache : Map;\n constructor() {\n this.reset();\n }\n get(key : string) : string|Uint8Array {\n return this.cache.get(key);\n }\n put(key : string, value : string|Uint8Array) {\n this.cache.set(key, value);\n this.size += value.length;\n if (this.size > this.maxSize) {\n console.log('cache reset', this);\n this.reset();\n }\n }\n reset() {\n this.cache = new Map();\n this.size = 0;\n }\n}\n\nexport function coerceToArray(arrobj: any) : T[] {\n if (Array.isArray(arrobj)) return arrobj;\n else if (arrobj != null && typeof arrobj[Symbol.iterator] === 'function') return Array.from(arrobj);\n else if (typeof arrobj === 'object') return Array.from(Object.values(arrobj))\n else throw new Error(`Expected array or object, got \"${arrobj}\"`);\n}\n", "import { WorkerError, CodeListingMap, SourceLocation, SourceLine, SourceLocated, SourceLineLocated } from \"../workertypes\";\n\nexport interface BASICOptions {\n dialectName : string; // use this to select the dialect \n // SYNTAX AND PARSING\n asciiOnly : boolean; // reject non-ASCII chars?\n uppercaseOnly : boolean; // convert everything to uppercase?\n optionalLabels : boolean;\t\t\t// can omit line numbers and use labels?\n optionalWhitespace : boolean; // can \"crunch\" keywords? also, eat extra \":\" delims\n multipleStmtsPerLine : boolean; // multiple statements separated by \":\"\n varNaming : 'A'|'A1'|'A1$'|'AA'|'*'; // only allow A0-9 for numerics, single letter for arrays/strings\n squareBrackets : boolean; // \"[\" and \"]\" interchangable with \"(\" and \")\"?\n tickComments : boolean; // support 'comments?\n hexOctalConsts : boolean; // support &H and &O integer constants?\n optionalLet : boolean; // LET is optional\n chainAssignments : boolean; // support A = B = value (HP2000)\n validKeywords : string[]; // valid keywords (or null for accept all)\n validFunctions : string[]; // valid functions (or null for accept all)\n validOperators : string[]; // valid operators (or null for accept all)\n // VALUES AND OPERATORS\n defaultValues : boolean; // initialize unset variables to default value? (0 or \"\")\n stringConcat : boolean; // can concat strings with \"+\" operator?\n checkOverflow : boolean; // check for overflow of numerics?\n bitwiseLogic : boolean; // -1 = TRUE, 0 = FALSE, AND/OR/NOT done with bitwise ops\n maxStringLength : number; // maximum string length in chars\n maxDefArgs : number; // maximum # of arguments for user-defined functions\n // ARRAYS\n staticArrays : boolean; // can only DIM with constant value? (and never redim)\n sharedArrayNamespace : boolean; // arrays and variables have same namespace? (TODO)\n defaultArrayBase : number; // arrays start at this number (0 or 1)\n defaultArraySize : number; // arrays are allocated w/ this size (starting @ 0)\n maxDimensions : number; // max number of dimensions for arrays\n arraysContainChars : boolean; // HP BASIC array-slicing syntax\n // PRINTING\n printZoneLength : number; // print zone length\n numericPadding : boolean; // \" \" or \"-\" before and \" \" after numbers?\n // CONTROL FLOW\n compiledBlocks : boolean; // assume blocks are statically compiled, not interpreted\n testInitialFor : boolean; // can we skip a NEXT statement? (can't interleave tho)\n optionalNextVar : boolean; // can do NEXT without variable\n multipleNextVars : boolean; // NEXT J,I\n checkOnGotoIndex : boolean; // fatal error when ON..GOTO index out of bounds\n computedGoto : boolean; // non-const expr GOTO label (and GOTO..OF expression)\n restoreWithLabel : boolean; // RESTORE