UNPKG

killawat

Version:

KillaWAT is a WebAssembly Text Macro Assembler

129 lines (115 loc) 4.17 kB
const { RED, logError, globalSymbolTable, globalSymbolMap, binaryen, WasmModule } = require('./shared'); class Global { constructor(tokenArray) { this.meta = tokenArray.pop(); this.index = globalSymbolTable.length; this.id = `$global_${this.index}`; this.globalType = binaryen.i32; this.mutable = false; this.initValue = WasmModule.i32.const(0); this.externalModuleName = null; this.externalBaseName = null; this.exportName = null; this.exportRef = null; for (let i = 0; i < tokenArray.length; i++) { let token = tokenArray[i]; if (token.type === 'lp') { this.subExpression(tokenArray.slice(i + 1, i + token.endTokenOffset)); i += token.endTokenOffset; } else if (token.type === 'name') { this.id = token.text; } else if (token.type === 'valtype') { this.globalType = token.value; } } if (this.externalModuleName != null && this.externalBaseName != null) { WasmModule.addGlobalImport(this.id.slice(1), this.externalModuleName, this.externalBaseName, this.globalType); } else if (this.exportName != null) { this.exportRef = WasmModule.addGlobalExport(this.id.slice(1), this.exportName); } else { this.expression = WasmModule.addGlobal(this.id.slice(1), this.globalType, this.mutable, this.initValue); } globalSymbolTable.push(this); globalSymbolMap.set(this.id, this); } subExpression(tokenArray) { //console.log('global subexpression:') //console.log(tokenArray) if (tokenArray.length < 2) { logError(`global subexpression not followed by a valid keyword`, tokenArray[0]); //console.log(tokenArray); return; } let token = tokenArray[0]; let nextToken = tokenArray[1]; if (token.text === 'mut') { if (nextToken.type !== 'valtype') { logError(`mut must be followed by a type such as i32, f32, i64 or f64`, nextToken); return; } this.mutable = nextToken.value; } else if (token.text === 'i32.const') { // int_literal, hex_literal, bin_literal if (nextToken.type === 'int_literal') { this.initValue = WasmModule.i32.const(nextToken.value); } else { logError(`i32.const must be followed by an integer literal`, nextToken); return; } } else if (token.text === 'f32.const' || token.text === 'f64.const') { // float_literal if (nextToken.type != 'float_literal') { this.initValue = WasmModule.f32.const(nextToken.value); } else { logError(`i32.const must be followed by an integer literal`, nextToken); return; } } else if (token.text === 'i64.const') { if (nextToken.type != 'int_literal' && nextToken.type != 'hex_literal' && nextToken.type != 'bin_literal') { this.initValue = WasmModule.i64.const(nextToken.value, nextToken.hival); } else { logError(`i32.const must be followed by an integer literal`, nextToken); return; } } else if (token.text === 'import') { if (tokenArray.length < 3 || nextToken.type !== 'string_literal' || tokenArray[2].type !== 'string_literal') { logError(`import requires an external name and a base name`, token); console.log(RED, `required 3 tokens but got ${tokenArray.length} param1.type: ${nextToken.type} param1.text: ${nextToken.text} `); /// param2.type: ${tokenArray[2].type} return; } this.externalModuleName = tokenArray[2].text;; this.externalBaseName = nextToken.text; } else if (token.text === 'export') { if (nextToken.type !== 'string_literal') { logError(`export requires an export name`, token); return; } this.exportName = nextToken.value; } else { logError(`improper subexpression on global definition`, token); return; } } } module.exports.Global = Global;