summaryrefslogtreecommitdiffstats
path: root/node_modules/@webassemblyjs/wast-parser/lib/grammar.js
diff options
context:
space:
mode:
Diffstat (limited to 'node_modules/@webassemblyjs/wast-parser/lib/grammar.js')
-rw-r--r--node_modules/@webassemblyjs/wast-parser/lib/grammar.js1769
1 files changed, 1769 insertions, 0 deletions
diff --git a/node_modules/@webassemblyjs/wast-parser/lib/grammar.js b/node_modules/@webassemblyjs/wast-parser/lib/grammar.js
new file mode 100644
index 0000000..ddde33a
--- /dev/null
+++ b/node_modules/@webassemblyjs/wast-parser/lib/grammar.js
@@ -0,0 +1,1769 @@
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.parse = parse;
+
+var _helperCodeFrame = require("@webassemblyjs/helper-code-frame");
+
+var t = _interopRequireWildcard(require("@webassemblyjs/ast"));
+
+var _numberLiterals = require("./number-literals");
+
+var _stringLiterals = require("./string-literals");
+
+var _tokenizer = require("./tokenizer");
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
+
+function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
+
+function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
+
+function hasPlugin(name) {
+ if (name !== "wast") throw new Error("unknow plugin");
+ return true;
+}
+
+function isKeyword(token, id) {
+ return token.type === _tokenizer.tokens.keyword && token.value === id;
+}
+
+function tokenToString(token) {
+ if (token.type === "keyword") {
+ return "keyword (".concat(token.value, ")");
+ }
+
+ return token.type;
+}
+
+function identifierFromToken(token) {
+ var _token$loc = token.loc,
+ end = _token$loc.end,
+ start = _token$loc.start;
+ return t.withLoc(t.identifier(token.value), end, start);
+}
+
+function parse(tokensList, source) {
+ var current = 0;
+ var getUniqueName = t.getUniqueNameGenerator();
+ var state = {
+ registredExportedElements: []
+ }; // But this time we're going to use recursion instead of a `while` loop. So we
+ // define a `walk` function.
+
+ function walk() {
+ var token = tokensList[current];
+
+ function eatToken() {
+ token = tokensList[++current];
+ }
+
+ function getEndLoc() {
+ var currentToken = token;
+
+ if (typeof currentToken === "undefined") {
+ var lastToken = tokensList[tokensList.length - 1];
+ currentToken = lastToken;
+ }
+
+ return currentToken.loc.end;
+ }
+
+ function getStartLoc() {
+ return token.loc.start;
+ }
+
+ function eatTokenOfType(type) {
+ if (token.type !== type) {
+ throw new Error("\n" + (0, _helperCodeFrame.codeFrameFromSource)(source, token.loc) + "Assertion error: expected token of type " + type + ", given " + tokenToString(token));
+ }
+
+ eatToken();
+ }
+
+ function parseExportIndex(token) {
+ if (token.type === _tokenizer.tokens.identifier) {
+ var index = identifierFromToken(token);
+ eatToken();
+ return index;
+ } else if (token.type === _tokenizer.tokens.number) {
+ var _index = t.numberLiteralFromRaw(token.value);
+
+ eatToken();
+ return _index;
+ } else {
+ throw function () {
+ return new Error("\n" + (0, _helperCodeFrame.codeFrameFromSource)(source, token.loc) + "\n" + "unknown export index" + ", given " + tokenToString(token));
+ }();
+ }
+ }
+
+ function lookaheadAndCheck() {
+ var len = arguments.length;
+
+ for (var i = 0; i < len; i++) {
+ var tokenAhead = tokensList[current + i];
+ var expectedToken = i < 0 || arguments.length <= i ? undefined : arguments[i];
+
+ if (tokenAhead.type === "keyword") {
+ if (isKeyword(tokenAhead, expectedToken) === false) {
+ return false;
+ }
+ } else if (expectedToken !== tokenAhead.type) {
+ return false;
+ }
+ }
+
+ return true;
+ } // TODO(sven): there is probably a better way to do this
+ // can refactor it if it get out of hands
+
+
+ function maybeIgnoreComment() {
+ if (typeof token === "undefined") {
+ // Ignore
+ return;
+ }
+
+ while (token.type === _tokenizer.tokens.comment) {
+ eatToken();
+
+ if (typeof token === "undefined") {
+ // Hit the end
+ break;
+ }
+ }
+ }
+ /**
+ * Parses a memory instruction
+ *
+ * WAST:
+ *
+ * memory: ( memory <name>? <memory_sig> )
+ * ( memory <name>? ( export <string> ) <...> )
+ * ( memory <name>? ( import <string> <string> ) <memory_sig> )
+ * ( memory <name>? ( export <string> )* ( data <string>* )
+ * memory_sig: <nat> <nat>?
+ *
+ */
+
+
+ function parseMemory() {
+ var id = t.identifier(getUniqueName("memory"));
+ var limits = t.limit(0);
+
+ if (token.type === _tokenizer.tokens.string || token.type === _tokenizer.tokens.identifier) {
+ id = t.identifier(token.value);
+ eatToken();
+ } else {
+ id = t.withRaw(id, ""); // preserve anonymous
+ }
+ /**
+ * Maybe data
+ */
+
+
+ if (lookaheadAndCheck(_tokenizer.tokens.openParen, _tokenizer.keywords.data)) {
+ eatToken(); // (
+
+ eatToken(); // data
+ // TODO(sven): do something with the data collected here
+
+ var stringInitializer = token.value;
+ eatTokenOfType(_tokenizer.tokens.string); // Update limits accordingly
+
+ limits = t.limit(stringInitializer.length);
+ eatTokenOfType(_tokenizer.tokens.closeParen);
+ }
+ /**
+ * Maybe export
+ */
+
+
+ if (lookaheadAndCheck(_tokenizer.tokens.openParen, _tokenizer.keywords.export)) {
+ eatToken(); // (
+
+ eatToken(); // export
+
+ if (token.type !== _tokenizer.tokens.string) {
+ throw function () {
+ return new Error("\n" + (0, _helperCodeFrame.codeFrameFromSource)(source, token.loc) + "\n" + "Expected string in export" + ", given " + tokenToString(token));
+ }();
+ }
+
+ var _name = token.value;
+ eatToken();
+ state.registredExportedElements.push({
+ exportType: "Memory",
+ name: _name,
+ id: id
+ });
+ eatTokenOfType(_tokenizer.tokens.closeParen);
+ }
+ /**
+ * Memory signature
+ */
+
+
+ if (token.type === _tokenizer.tokens.number) {
+ limits = t.limit((0, _numberLiterals.parse32I)(token.value));
+ eatToken();
+
+ if (token.type === _tokenizer.tokens.number) {
+ limits.max = (0, _numberLiterals.parse32I)(token.value);
+ eatToken();
+ }
+ }
+
+ return t.memory(limits, id);
+ }
+ /**
+ * Parses a data section
+ * https://webassembly.github.io/spec/core/text/modules.html#data-segments
+ *
+ * WAST:
+ *
+ * data: ( data <index>? <offset> <string> )
+ */
+
+
+ function parseData() {
+ // optional memory index
+ var memidx = 0;
+
+ if (token.type === _tokenizer.tokens.number) {
+ memidx = token.value;
+ eatTokenOfType(_tokenizer.tokens.number); // .
+ }
+
+ eatTokenOfType(_tokenizer.tokens.openParen);
+ var offset;
+
+ if (token.type === _tokenizer.tokens.valtype) {
+ eatTokenOfType(_tokenizer.tokens.valtype); // i32
+
+ eatTokenOfType(_tokenizer.tokens.dot); // .
+
+ if (token.value !== "const") {
+ throw new Error("constant expression required");
+ }
+
+ eatTokenOfType(_tokenizer.tokens.name); // const
+
+ var numberLiteral = t.numberLiteralFromRaw(token.value, "i32");
+ offset = t.objectInstruction("const", "i32", [numberLiteral]);
+ eatToken();
+ eatTokenOfType(_tokenizer.tokens.closeParen);
+ } else {
+ eatTokenOfType(_tokenizer.tokens.name); // get_global
+
+ var _numberLiteral = t.numberLiteralFromRaw(token.value, "i32");
+
+ offset = t.instruction("get_global", [_numberLiteral]);
+ eatToken();
+ eatTokenOfType(_tokenizer.tokens.closeParen);
+ }
+
+ var byteArray = (0, _stringLiterals.parseString)(token.value);
+ eatToken(); // "string"
+
+ return t.data(t.memIndexLiteral(memidx), offset, t.byteArray(byteArray));
+ }
+ /**
+ * Parses a table instruction
+ *
+ * WAST:
+ *
+ * table: ( table <name>? <table_type> )
+ * ( table <name>? ( export <string> ) <...> )
+ * ( table <name>? ( import <string> <string> ) <table_type> )
+ * ( table <name>? ( export <string> )* <elem_type> ( elem <var>* ) )
+ *
+ * table_type: <nat> <nat>? <elem_type>
+ * elem_type: anyfunc
+ *
+ * elem: ( elem <var>? (offset <instr>* ) <var>* )
+ * ( elem <var>? <expr> <var>* )
+ */
+
+
+ function parseTable() {
+ var name = t.identifier(getUniqueName("table"));
+ var limit = t.limit(0);
+ var elemIndices = [];
+ var elemType = "anyfunc";
+
+ if (token.type === _tokenizer.tokens.string || token.type === _tokenizer.tokens.identifier) {
+ name = identifierFromToken(token);
+ eatToken();
+ } else {
+ name = t.withRaw(name, ""); // preserve anonymous
+ }
+
+ while (token.type !== _tokenizer.tokens.closeParen) {
+ /**
+ * Maybe export
+ */
+ if (lookaheadAndCheck(_tokenizer.tokens.openParen, _tokenizer.keywords.elem)) {
+ eatToken(); // (
+
+ eatToken(); // elem
+
+ while (token.type === _tokenizer.tokens.identifier) {
+ elemIndices.push(t.identifier(token.value));
+ eatToken();
+ }
+
+ eatTokenOfType(_tokenizer.tokens.closeParen);
+ } else if (lookaheadAndCheck(_tokenizer.tokens.openParen, _tokenizer.keywords.export)) {
+ eatToken(); // (
+
+ eatToken(); // export
+
+ if (token.type !== _tokenizer.tokens.string) {
+ throw function () {
+ return new Error("\n" + (0, _helperCodeFrame.codeFrameFromSource)(source, token.loc) + "\n" + "Expected string in export" + ", given " + tokenToString(token));
+ }();
+ }
+
+ var exportName = token.value;
+ eatToken();
+ state.registredExportedElements.push({
+ exportType: "Table",
+ name: exportName,
+ id: name
+ });
+ eatTokenOfType(_tokenizer.tokens.closeParen);
+ } else if (isKeyword(token, _tokenizer.keywords.anyfunc)) {
+ // It's the default value, we can ignore it
+ eatToken(); // anyfunc
+ } else if (token.type === _tokenizer.tokens.number) {
+ /**
+ * Table type
+ */
+ var min = parseInt(token.value);
+ eatToken();
+
+ if (token.type === _tokenizer.tokens.number) {
+ var max = parseInt(token.value);
+ eatToken();
+ limit = t.limit(min, max);
+ } else {
+ limit = t.limit(min);
+ }
+
+ eatToken();
+ } else {
+ throw function () {
+ return new Error("\n" + (0, _helperCodeFrame.codeFrameFromSource)(source, token.loc) + "\n" + "Unexpected token" + ", given " + tokenToString(token));
+ }();
+ }
+ }
+
+ if (elemIndices.length > 0) {
+ return t.table(elemType, limit, name, elemIndices);
+ } else {
+ return t.table(elemType, limit, name);
+ }
+ }
+ /**
+ * Parses an import statement
+ *
+ * WAST:
+ *
+ * import: ( import <string> <string> <imkind> )
+ * imkind: ( func <name>? <func_sig> )
+ * ( global <name>? <global_sig> )
+ * ( table <name>? <table_sig> )
+ * ( memory <name>? <memory_sig> )
+ *
+ * global_sig: <type> | ( mut <type> )
+ */
+
+
+ function parseImport() {
+ if (token.type !== _tokenizer.tokens.string) {
+ throw new Error("Expected a string, " + token.type + " given.");
+ }
+
+ var moduleName = token.value;
+ eatToken();
+
+ if (token.type !== _tokenizer.tokens.string) {
+ throw new Error("Expected a string, " + token.type + " given.");
+ }
+
+ var name = token.value;
+ eatToken();
+ eatTokenOfType(_tokenizer.tokens.openParen);
+ var descr;
+
+ if (isKeyword(token, _tokenizer.keywords.func)) {
+ eatToken(); // keyword
+
+ var fnParams = [];
+ var fnResult = [];
+ var typeRef;
+ var fnName = t.identifier(getUniqueName("func"));
+
+ if (token.type === _tokenizer.tokens.identifier) {
+ fnName = identifierFromToken(token);
+ eatToken();
+ }
+
+ while (token.type === _tokenizer.tokens.openParen) {
+ eatToken();
+
+ if (lookaheadAndCheck(_tokenizer.keywords.type) === true) {
+ eatToken();
+ typeRef = parseTypeReference();
+ } else if (lookaheadAndCheck(_tokenizer.keywords.param) === true) {
+ eatToken();
+ fnParams.push.apply(fnParams, _toConsumableArray(parseFuncParam()));
+ } else if (lookaheadAndCheck(_tokenizer.keywords.result) === true) {
+ eatToken();
+ fnResult.push.apply(fnResult, _toConsumableArray(parseFuncResult()));
+ } else {
+ throw function () {
+ return new Error("\n" + (0, _helperCodeFrame.codeFrameFromSource)(source, token.loc) + "\n" + "Unexpected token in import of type" + ", given " + tokenToString(token));
+ }();
+ }
+
+ eatTokenOfType(_tokenizer.tokens.closeParen);
+ }
+
+ if (typeof fnName === "undefined") {
+ throw new Error("Imported function must have a name");
+ }
+
+ descr = t.funcImportDescr(fnName, typeRef !== undefined ? typeRef : t.signature(fnParams, fnResult));
+ } else if (isKeyword(token, _tokenizer.keywords.global)) {
+ eatToken(); // keyword
+
+ if (token.type === _tokenizer.tokens.openParen) {
+ eatToken(); // (
+
+ eatTokenOfType(_tokenizer.tokens.keyword); // mut keyword
+
+ var valtype = token.value;
+ eatToken();
+ descr = t.globalType(valtype, "var");
+ eatTokenOfType(_tokenizer.tokens.closeParen);
+ } else {
+ var _valtype = token.value;
+ eatTokenOfType(_tokenizer.tokens.valtype);
+ descr = t.globalType(_valtype, "const");
+ }
+ } else if (isKeyword(token, _tokenizer.keywords.memory) === true) {
+ eatToken(); // Keyword
+
+ descr = parseMemory();
+ } else if (isKeyword(token, _tokenizer.keywords.table) === true) {
+ eatToken(); // Keyword
+
+ descr = parseTable();
+ } else {
+ throw new Error("Unsupported import type: " + tokenToString(token));
+ }
+
+ eatTokenOfType(_tokenizer.tokens.closeParen);
+ return t.moduleImport(moduleName, name, descr);
+ }
+ /**
+ * Parses a block instruction
+ *
+ * WAST:
+ *
+ * expr: ( block <name>? <block_sig> <instr>* )
+ * instr: block <name>? <block_sig> <instr>* end <name>?
+ * block_sig : ( result <type>* )*
+ *
+ */
+
+
+ function parseBlock() {
+ var label = t.identifier(getUniqueName("block"));
+ var blockResult = null;
+ var instr = [];
+
+ if (token.type === _tokenizer.tokens.identifier) {
+ label = identifierFromToken(token);
+ eatToken();
+ } else {
+ label = t.withRaw(label, ""); // preserve anonymous
+ }
+
+ while (token.type === _tokenizer.tokens.openParen) {
+ eatToken();
+
+ if (lookaheadAndCheck(_tokenizer.keywords.result) === true) {
+ eatToken();
+ blockResult = token.value;
+ eatToken();
+ } else if (lookaheadAndCheck(_tokenizer.tokens.name) === true || lookaheadAndCheck(_tokenizer.tokens.valtype) === true || token.type === "keyword" // is any keyword
+ ) {
+ // Instruction
+ instr.push(parseFuncInstr());
+ } else {
+ throw function () {
+ return new Error("\n" + (0, _helperCodeFrame.codeFrameFromSource)(source, token.loc) + "\n" + "Unexpected token in block body of type" + ", given " + tokenToString(token));
+ }();
+ }
+
+ maybeIgnoreComment();
+ eatTokenOfType(_tokenizer.tokens.closeParen);
+ }
+
+ return t.blockInstruction(label, instr, blockResult);
+ }
+ /**
+ * Parses a if instruction
+ *
+ * WAST:
+ *
+ * expr:
+ * ( if <name>? <block_sig> ( then <instr>* ) ( else <instr>* )? )
+ * ( if <name>? <block_sig> <expr>+ ( then <instr>* ) ( else <instr>* )? )
+ *
+ * instr:
+ * if <name>? <block_sig> <instr>* end <name>?
+ * if <name>? <block_sig> <instr>* else <name>? <instr>* end <name>?
+ *
+ * block_sig : ( result <type>* )*
+ *
+ */
+
+
+ function parseIf() {
+ var blockResult = null;
+ var label = t.identifier(getUniqueName("if"));
+ var testInstrs = [];
+ var consequent = [];
+ var alternate = [];
+
+ if (token.type === _tokenizer.tokens.identifier) {
+ label = identifierFromToken(token);
+ eatToken();
+ } else {
+ label = t.withRaw(label, ""); // preserve anonymous
+ }
+
+ while (token.type === _tokenizer.tokens.openParen) {
+ eatToken(); // (
+
+ /**
+ * Block signature
+ */
+
+ if (isKeyword(token, _tokenizer.keywords.result) === true) {
+ eatToken();
+ blockResult = token.value;
+ eatTokenOfType(_tokenizer.tokens.valtype);
+ eatTokenOfType(_tokenizer.tokens.closeParen);
+ continue;
+ }
+ /**
+ * Then
+ */
+
+
+ if (isKeyword(token, _tokenizer.keywords.then) === true) {
+ eatToken(); // then
+
+ while (token.type === _tokenizer.tokens.openParen) {
+ eatToken(); // Instruction
+
+ if (lookaheadAndCheck(_tokenizer.tokens.name) === true || lookaheadAndCheck(_tokenizer.tokens.valtype) === true || token.type === "keyword" // is any keyword
+ ) {
+ consequent.push(parseFuncInstr());
+ } else {
+ throw function () {
+ return new Error("\n" + (0, _helperCodeFrame.codeFrameFromSource)(source, token.loc) + "\n" + "Unexpected token in consequent body of type" + ", given " + tokenToString(token));
+ }();
+ }
+
+ eatTokenOfType(_tokenizer.tokens.closeParen);
+ }
+
+ eatTokenOfType(_tokenizer.tokens.closeParen);
+ continue;
+ }
+ /**
+ * Alternate
+ */
+
+
+ if (isKeyword(token, _tokenizer.keywords.else)) {
+ eatToken(); // else
+
+ while (token.type === _tokenizer.tokens.openParen) {
+ eatToken(); // Instruction
+
+ if (lookaheadAndCheck(_tokenizer.tokens.name) === true || lookaheadAndCheck(_tokenizer.tokens.valtype) === true || token.type === "keyword" // is any keyword
+ ) {
+ alternate.push(parseFuncInstr());
+ } else {
+ throw function () {
+ return new Error("\n" + (0, _helperCodeFrame.codeFrameFromSource)(source, token.loc) + "\n" + "Unexpected token in alternate body of type" + ", given " + tokenToString(token));
+ }();
+ }
+
+ eatTokenOfType(_tokenizer.tokens.closeParen);
+ }
+
+ eatTokenOfType(_tokenizer.tokens.closeParen);
+ continue;
+ }
+ /**
+ * Test instruction
+ */
+
+
+ if (lookaheadAndCheck(_tokenizer.tokens.name) === true || lookaheadAndCheck(_tokenizer.tokens.valtype) === true || token.type === "keyword" // is any keyword
+ ) {
+ testInstrs.push(parseFuncInstr());
+ eatTokenOfType(_tokenizer.tokens.closeParen);
+ continue;
+ }
+
+ throw function () {
+ return new Error("\n" + (0, _helperCodeFrame.codeFrameFromSource)(source, token.loc) + "\n" + "Unexpected token in if body" + ", given " + tokenToString(token));
+ }();
+ }
+
+ return t.ifInstruction(label, testInstrs, blockResult, consequent, alternate);
+ }
+ /**
+ * Parses a loop instruction
+ *
+ * WAT:
+ *
+ * blockinstr :: 'loop' I:label rt:resulttype (in:instr*) 'end' id?
+ *
+ * WAST:
+ *
+ * instr :: loop <name>? <block_sig> <instr>* end <name>?
+ * expr :: ( loop <name>? <block_sig> <instr>* )
+ * block_sig :: ( result <type>* )*
+ *
+ */
+
+
+ function parseLoop() {
+ var label = t.identifier(getUniqueName("loop"));
+ var blockResult;
+ var instr = [];
+
+ if (token.type === _tokenizer.tokens.identifier) {
+ label = identifierFromToken(token);
+ eatToken();
+ } else {
+ label = t.withRaw(label, ""); // preserve anonymous
+ }
+
+ while (token.type === _tokenizer.tokens.openParen) {
+ eatToken();
+
+ if (lookaheadAndCheck(_tokenizer.keywords.result) === true) {
+ eatToken();
+ blockResult = token.value;
+ eatToken();
+ } else if (lookaheadAndCheck(_tokenizer.tokens.name) === true || lookaheadAndCheck(_tokenizer.tokens.valtype) === true || token.type === "keyword" // is any keyword
+ ) {
+ // Instruction
+ instr.push(parseFuncInstr());
+ } else {
+ throw function () {
+ return new Error("\n" + (0, _helperCodeFrame.codeFrameFromSource)(source, token.loc) + "\n" + "Unexpected token in loop body" + ", given " + tokenToString(token));
+ }();
+ }
+
+ eatTokenOfType(_tokenizer.tokens.closeParen);
+ }
+
+ return t.loopInstruction(label, blockResult, instr);
+ }
+
+ function parseCallIndirect() {
+ var typeRef;
+ var params = [];
+ var results = [];
+ var instrs = [];
+
+ while (token.type !== _tokenizer.tokens.closeParen) {
+ if (lookaheadAndCheck(_tokenizer.tokens.openParen, _tokenizer.keywords.type)) {
+ eatToken(); // (
+
+ eatToken(); // type
+
+ typeRef = parseTypeReference();
+ } else if (lookaheadAndCheck(_tokenizer.tokens.openParen, _tokenizer.keywords.param)) {
+ eatToken(); // (
+
+ eatToken(); // param
+
+ /**
+ * Params can be empty:
+ * (params)`
+ */
+
+ if (token.type !== _tokenizer.tokens.closeParen) {
+ params.push.apply(params, _toConsumableArray(parseFuncParam()));
+ }
+ } else if (lookaheadAndCheck(_tokenizer.tokens.openParen, _tokenizer.keywords.result)) {
+ eatToken(); // (
+
+ eatToken(); // result
+
+ /**
+ * Results can be empty:
+ * (result)`
+ */
+
+ if (token.type !== _tokenizer.tokens.closeParen) {
+ results.push.apply(results, _toConsumableArray(parseFuncResult()));
+ }
+ } else {
+ eatTokenOfType(_tokenizer.tokens.openParen);
+ instrs.push(parseFuncInstr());
+ }
+
+ eatTokenOfType(_tokenizer.tokens.closeParen);
+ }
+
+ return t.callIndirectInstruction(typeRef !== undefined ? typeRef : t.signature(params, results), instrs);
+ }
+ /**
+ * Parses an export instruction
+ *
+ * WAT:
+ *
+ * export: ( export <string> <exkind> )
+ * exkind: ( func <var> )
+ * ( global <var> )
+ * ( table <var> )
+ * ( memory <var> )
+ * var: <nat> | <name>
+ *
+ */
+
+
+ function parseExport() {
+ if (token.type !== _tokenizer.tokens.string) {
+ throw new Error("Expected string after export, got: " + token.type);
+ }
+
+ var name = token.value;
+ eatToken();
+ var moduleExportDescr = parseModuleExportDescr();
+ return t.moduleExport(name, moduleExportDescr);
+ }
+
+ function parseModuleExportDescr() {
+ var startLoc = getStartLoc();
+ var type = "";
+ var index;
+ eatTokenOfType(_tokenizer.tokens.openParen);
+
+ while (token.type !== _tokenizer.tokens.closeParen) {
+ if (isKeyword(token, _tokenizer.keywords.func)) {
+ type = "Func";
+ eatToken();
+ index = parseExportIndex(token);
+ } else if (isKeyword(token, _tokenizer.keywords.table)) {
+ type = "Table";
+ eatToken();
+ index = parseExportIndex(token);
+ } else if (isKeyword(token, _tokenizer.keywords.global)) {
+ type = "Global";
+ eatToken();
+ index = parseExportIndex(token);
+ } else if (isKeyword(token, _tokenizer.keywords.memory)) {
+ type = "Memory";
+ eatToken();
+ index = parseExportIndex(token);
+ }
+
+ eatToken();
+ }
+
+ if (type === "") {
+ throw new Error("Unknown export type");
+ }
+
+ if (index === undefined) {
+ throw new Error("Exported function must have a name");
+ }
+
+ var node = t.moduleExportDescr(type, index);
+ var endLoc = getEndLoc();
+ eatTokenOfType(_tokenizer.tokens.closeParen);
+ return t.withLoc(node, endLoc, startLoc);
+ }
+
+ function parseModule() {
+ var name = null;
+ var isBinary = false;
+ var isQuote = false;
+ var moduleFields = [];
+
+ if (token.type === _tokenizer.tokens.identifier) {
+ name = token.value;
+ eatToken();
+ }
+
+ if (hasPlugin("wast") && token.type === _tokenizer.tokens.name && token.value === "binary") {
+ eatToken();
+ isBinary = true;
+ }
+
+ if (hasPlugin("wast") && token.type === _tokenizer.tokens.name && token.value === "quote") {
+ eatToken();
+ isQuote = true;
+ }
+
+ if (isBinary === true) {
+ var blob = [];
+
+ while (token.type === _tokenizer.tokens.string) {
+ blob.push(token.value);
+ eatToken();
+ maybeIgnoreComment();
+ }
+
+ eatTokenOfType(_tokenizer.tokens.closeParen);
+ return t.binaryModule(name, blob);
+ }
+
+ if (isQuote === true) {
+ var string = [];
+
+ while (token.type === _tokenizer.tokens.string) {
+ string.push(token.value);
+ eatToken();
+ }
+
+ eatTokenOfType(_tokenizer.tokens.closeParen);
+ return t.quoteModule(name, string);
+ }
+
+ while (token.type !== _tokenizer.tokens.closeParen) {
+ moduleFields.push(walk());
+
+ if (state.registredExportedElements.length > 0) {
+ state.registredExportedElements.forEach(function (decl) {
+ moduleFields.push(t.moduleExport(decl.name, t.moduleExportDescr(decl.exportType, decl.id)));
+ });
+ state.registredExportedElements = [];
+ }
+
+ token = tokensList[current];
+ }
+
+ eatTokenOfType(_tokenizer.tokens.closeParen);
+ return t.module(name, moduleFields);
+ }
+ /**
+ * Parses the arguments of an instruction
+ */
+
+
+ function parseFuncInstrArguments(signature) {
+ var args = [];
+ var namedArgs = {};
+ var signaturePtr = 0;
+
+ while (token.type === _tokenizer.tokens.name || isKeyword(token, _tokenizer.keywords.offset)) {
+ var key = token.value;
+ eatToken();
+ eatTokenOfType(_tokenizer.tokens.equal);
+ var value = void 0;
+
+ if (token.type === _tokenizer.tokens.number) {
+ value = t.numberLiteralFromRaw(token.value);
+ } else {
+ throw new Error("Unexpected type for argument: " + token.type);
+ }
+
+ namedArgs[key] = value;
+ eatToken();
+ } // $FlowIgnore
+
+
+ var signatureLength = signature.vector ? Infinity : signature.length;
+
+ while (token.type !== _tokenizer.tokens.closeParen && ( // $FlowIgnore
+ token.type === _tokenizer.tokens.openParen || signaturePtr < signatureLength)) {
+ if (token.type === _tokenizer.tokens.identifier) {
+ args.push(t.identifier(token.value));
+ eatToken();
+ } else if (token.type === _tokenizer.tokens.valtype) {
+ // Handle locals
+ args.push(t.valtypeLiteral(token.value));
+ eatToken();
+ } else if (token.type === _tokenizer.tokens.string) {
+ args.push(t.stringLiteral(token.value));
+ eatToken();
+ } else if (token.type === _tokenizer.tokens.number) {
+ args.push( // TODO(sven): refactor the type signature handling
+ // https://github.com/xtuc/webassemblyjs/pull/129 is a good start
+ t.numberLiteralFromRaw(token.value, // $FlowIgnore
+ signature[signaturePtr] || "f64")); // $FlowIgnore
+
+ if (!signature.vector) {
+ ++signaturePtr;
+ }
+
+ eatToken();
+ } else if (token.type === _tokenizer.tokens.openParen) {
+ /**
+ * Maybe some nested instructions
+ */
+ eatToken(); // Instruction
+
+ if (lookaheadAndCheck(_tokenizer.tokens.name) === true || lookaheadAndCheck(_tokenizer.tokens.valtype) === true || token.type === "keyword" // is any keyword
+ ) {
+ // $FlowIgnore
+ args.push(parseFuncInstr());
+ } else {
+ throw function () {
+ return new Error("\n" + (0, _helperCodeFrame.codeFrameFromSource)(source, token.loc) + "\n" + "Unexpected token in nested instruction" + ", given " + tokenToString(token));
+ }();
+ }
+
+ if (token.type === _tokenizer.tokens.closeParen) {
+ eatToken();
+ }
+ } else {
+ throw function () {
+ return new Error("\n" + (0, _helperCodeFrame.codeFrameFromSource)(source, token.loc) + "\n" + "Unexpected token in instruction argument" + ", given " + tokenToString(token));
+ }();
+ }
+ }
+
+ return {
+ args: args,
+ namedArgs: namedArgs
+ };
+ }
+ /**
+ * Parses an instruction
+ *
+ * WAT:
+ *
+ * instr :: plaininst
+ * blockinstr
+ *
+ * blockinstr :: 'block' I:label rt:resulttype (in:instr*) 'end' id?
+ * 'loop' I:label rt:resulttype (in:instr*) 'end' id?
+ * 'if' I:label rt:resulttype (in:instr*) 'else' id? (in2:intr*) 'end' id?
+ *
+ * plaininst :: 'unreachable'
+ * 'nop'
+ * 'br' l:labelidx
+ * 'br_if' l:labelidx
+ * 'br_table' l*:vec(labelidx) ln:labelidx
+ * 'return'
+ * 'call' x:funcidx
+ * 'call_indirect' x, I:typeuse
+ *
+ * WAST:
+ *
+ * instr:
+ * <expr>
+ * <op>
+ * block <name>? <block_sig> <instr>* end <name>?
+ * loop <name>? <block_sig> <instr>* end <name>?
+ * if <name>? <block_sig> <instr>* end <name>?
+ * if <name>? <block_sig> <instr>* else <name>? <instr>* end <name>?
+ *
+ * expr:
+ * ( <op> )
+ * ( <op> <expr>+ )
+ * ( block <name>? <block_sig> <instr>* )
+ * ( loop <name>? <block_sig> <instr>* )
+ * ( if <name>? <block_sig> ( then <instr>* ) ( else <instr>* )? )
+ * ( if <name>? <block_sig> <expr>+ ( then <instr>* ) ( else <instr>* )? )
+ *
+ * op:
+ * unreachable
+ * nop
+ * br <var>
+ * br_if <var>
+ * br_table <var>+
+ * return
+ * call <var>
+ * call_indirect <func_sig>
+ * drop
+ * select
+ * get_local <var>
+ * set_local <var>
+ * tee_local <var>
+ * get_global <var>
+ * set_global <var>
+ * <type>.load((8|16|32)_<sign>)? <offset>? <align>?
+ * <type>.store(8|16|32)? <offset>? <align>?
+ * current_memory
+ * grow_memory
+ * <type>.const <value>
+ * <type>.<unop>
+ * <type>.<binop>
+ * <type>.<testop>
+ * <type>.<relop>
+ * <type>.<cvtop>/<type>
+ *
+ * func_type: ( type <var> )? <param>* <result>*
+ */
+
+
+ function parseFuncInstr() {
+ var startLoc = getStartLoc();
+ maybeIgnoreComment();
+ /**
+ * A simple instruction
+ */
+
+ if (token.type === _tokenizer.tokens.name || token.type === _tokenizer.tokens.valtype) {
+ var _name2 = token.value;
+ var object;
+ eatToken();
+
+ if (token.type === _tokenizer.tokens.dot) {
+ object = _name2;
+ eatToken();
+
+ if (token.type !== _tokenizer.tokens.name) {
+ throw new TypeError("Unknown token: " + token.type + ", name expected");
+ }
+
+ _name2 = token.value;
+ eatToken();
+ }
+
+ if (token.type === _tokenizer.tokens.closeParen) {
+ var _endLoc = token.loc.end;
+
+ if (typeof object === "undefined") {
+ return t.withLoc(t.instruction(_name2), _endLoc, startLoc);
+ } else {
+ return t.withLoc(t.objectInstruction(_name2, object, []), _endLoc, startLoc);
+ }
+ }
+
+ var signature = t.signatureForOpcode(object || "", _name2);
+
+ var _parseFuncInstrArgume = parseFuncInstrArguments(signature),
+ _args = _parseFuncInstrArgume.args,
+ _namedArgs = _parseFuncInstrArgume.namedArgs;
+
+ var endLoc = token.loc.end;
+
+ if (typeof object === "undefined") {
+ return t.withLoc(t.instruction(_name2, _args, _namedArgs), endLoc, startLoc);
+ } else {
+ return t.withLoc(t.objectInstruction(_name2, object, _args, _namedArgs), endLoc, startLoc);
+ }
+ } else if (isKeyword(token, _tokenizer.keywords.loop)) {
+ /**
+ * Else a instruction with a keyword (loop or block)
+ */
+ eatToken(); // keyword
+
+ return parseLoop();
+ } else if (isKeyword(token, _tokenizer.keywords.block)) {
+ eatToken(); // keyword
+
+ return parseBlock();
+ } else if (isKeyword(token, _tokenizer.keywords.call_indirect)) {
+ eatToken(); // keyword
+
+ return parseCallIndirect();
+ } else if (isKeyword(token, _tokenizer.keywords.call)) {
+ eatToken(); // keyword
+
+ var index;
+
+ if (token.type === _tokenizer.tokens.identifier) {
+ index = identifierFromToken(token);
+ eatToken();
+ } else if (token.type === _tokenizer.tokens.number) {
+ index = t.indexLiteral(token.value);
+ eatToken();
+ }
+
+ var instrArgs = []; // Nested instruction
+
+ while (token.type === _tokenizer.tokens.openParen) {
+ eatToken();
+ instrArgs.push(parseFuncInstr());
+ eatTokenOfType(_tokenizer.tokens.closeParen);
+ }
+
+ if (typeof index === "undefined") {
+ throw new Error("Missing argument in call instruciton");
+ }
+
+ if (instrArgs.length > 0) {
+ return t.callInstruction(index, instrArgs);
+ } else {
+ return t.callInstruction(index);
+ }
+ } else if (isKeyword(token, _tokenizer.keywords.if)) {
+ eatToken(); // Keyword
+
+ return parseIf();
+ } else if (isKeyword(token, _tokenizer.keywords.module) && hasPlugin("wast")) {
+ eatToken(); // In WAST you can have a module as an instruction's argument
+ // we will cast it into a instruction to not break the flow
+ // $FlowIgnore
+
+ var module = parseModule();
+ return module;
+ } else {
+ throw function () {
+ return new Error("\n" + (0, _helperCodeFrame.codeFrameFromSource)(source, token.loc) + "\n" + "Unexpected instruction in function body" + ", given " + tokenToString(token));
+ }();
+ }
+ }
+ /*
+ * Parses a function
+ *
+ * WAT:
+ *
+ * functype :: ( 'func' t1:vec(param) t2:vec(result) )
+ * param :: ( 'param' id? t:valtype )
+ * result :: ( 'result' t:valtype )
+ *
+ * WAST:
+ *
+ * func :: ( func <name>? <func_sig> <local>* <instr>* )
+ * ( func <name>? ( export <string> ) <...> )
+ * ( func <name>? ( import <string> <string> ) <func_sig> )
+ * func_sig :: ( type <var> )? <param>* <result>*
+ * param :: ( param <type>* ) | ( param <name> <type> )
+ * result :: ( result <type>* )
+ * local :: ( local <type>* ) | ( local <name> <type> )
+ *
+ */
+
+
+ function parseFunc() {
+ var fnName = t.identifier(getUniqueName("func"));
+ var typeRef;
+ var fnBody = [];
+ var fnParams = [];
+ var fnResult = []; // name
+
+ if (token.type === _tokenizer.tokens.identifier) {
+ fnName = identifierFromToken(token);
+ eatToken();
+ } else {
+ fnName = t.withRaw(fnName, ""); // preserve anonymous
+ }
+
+ maybeIgnoreComment();
+
+ while (token.type === _tokenizer.tokens.openParen || token.type === _tokenizer.tokens.name || token.type === _tokenizer.tokens.valtype) {
+ // Instructions without parens
+ if (token.type === _tokenizer.tokens.name || token.type === _tokenizer.tokens.valtype) {
+ fnBody.push(parseFuncInstr());
+ continue;
+ }
+
+ eatToken();
+
+ if (lookaheadAndCheck(_tokenizer.keywords.param) === true) {
+ eatToken();
+ fnParams.push.apply(fnParams, _toConsumableArray(parseFuncParam()));
+ } else if (lookaheadAndCheck(_tokenizer.keywords.result) === true) {
+ eatToken();
+ fnResult.push.apply(fnResult, _toConsumableArray(parseFuncResult()));
+ } else if (lookaheadAndCheck(_tokenizer.keywords.export) === true) {
+ eatToken();
+ parseFuncExport(fnName);
+ } else if (lookaheadAndCheck(_tokenizer.keywords.type) === true) {
+ eatToken();
+ typeRef = parseTypeReference();
+ } else if (lookaheadAndCheck(_tokenizer.tokens.name) === true || lookaheadAndCheck(_tokenizer.tokens.valtype) === true || token.type === "keyword" // is any keyword
+ ) {
+ // Instruction
+ fnBody.push(parseFuncInstr());
+ } else {
+ throw function () {
+ return new Error("\n" + (0, _helperCodeFrame.codeFrameFromSource)(source, token.loc) + "\n" + "Unexpected token in func body" + ", given " + tokenToString(token));
+ }();
+ }
+
+ eatTokenOfType(_tokenizer.tokens.closeParen);
+ }
+
+ return t.func(fnName, typeRef !== undefined ? typeRef : t.signature(fnParams, fnResult), fnBody);
+ }
+ /**
+ * Parses shorthand export in func
+ *
+ * export :: ( export <string> )
+ */
+
+
+ function parseFuncExport(funcId) {
+ if (token.type !== _tokenizer.tokens.string) {
+ throw function () {
+ return new Error("\n" + (0, _helperCodeFrame.codeFrameFromSource)(source, token.loc) + "\n" + "Function export expected a string" + ", given " + tokenToString(token));
+ }();
+ }
+
+ var name = token.value;
+ eatToken();
+ /**
+ * Func export shorthand, we trait it as a syntaxic sugar.
+ * A export ModuleField will be added later.
+ *
+ * We give the anonymous function a generated name and export it.
+ */
+
+ var id = t.identifier(funcId.value);
+ state.registredExportedElements.push({
+ exportType: "Func",
+ name: name,
+ id: id
+ });
+ }
+ /**
+ * Parses a type instruction
+ *
+ * WAST:
+ *
+ * typedef: ( type <name>? ( func <param>* <result>* ) )
+ */
+
+
+ function parseType() {
+ var id;
+ var params = [];
+ var result = [];
+
+ if (token.type === _tokenizer.tokens.identifier) {
+ id = identifierFromToken(token);
+ eatToken();
+ }
+
+ if (lookaheadAndCheck(_tokenizer.tokens.openParen, _tokenizer.keywords.func)) {
+ eatToken(); // (
+
+ eatToken(); // func
+
+ if (token.type === _tokenizer.tokens.closeParen) {
+ eatToken(); // function with an empty signature, we can abort here
+
+ return t.typeInstruction(id, t.signature([], []));
+ }
+
+ if (lookaheadAndCheck(_tokenizer.tokens.openParen, _tokenizer.keywords.param)) {
+ eatToken(); // (
+
+ eatToken(); // param
+
+ params = parseFuncParam();
+ eatTokenOfType(_tokenizer.tokens.closeParen);
+ }
+
+ if (lookaheadAndCheck(_tokenizer.tokens.openParen, _tokenizer.keywords.result)) {
+ eatToken(); // (
+
+ eatToken(); // result
+
+ result = parseFuncResult();
+ eatTokenOfType(_tokenizer.tokens.closeParen);
+ }
+
+ eatTokenOfType(_tokenizer.tokens.closeParen);
+ }
+
+ return t.typeInstruction(id, t.signature(params, result));
+ }
+ /**
+ * Parses a function result
+ *
+ * WAST:
+ *
+ * result :: ( result <type>* )
+ */
+
+
+ function parseFuncResult() {
+ var results = [];
+
+ while (token.type !== _tokenizer.tokens.closeParen) {
+ if (token.type !== _tokenizer.tokens.valtype) {
+ throw function () {
+ return new Error("\n" + (0, _helperCodeFrame.codeFrameFromSource)(source, token.loc) + "\n" + "Unexpected token in func result" + ", given " + tokenToString(token));
+ }();
+ }
+
+ var valtype = token.value;
+ eatToken();
+ results.push(valtype);
+ }
+
+ return results;
+ }
+ /**
+ * Parses a type reference
+ *
+ */
+
+
+ function parseTypeReference() {
+ var ref;
+
+ if (token.type === _tokenizer.tokens.identifier) {
+ ref = identifierFromToken(token);
+ eatToken();
+ } else if (token.type === _tokenizer.tokens.number) {
+ ref = t.numberLiteralFromRaw(token.value);
+ eatToken();
+ }
+
+ return ref;
+ }
+ /**
+ * Parses a global instruction
+ *
+ * WAST:
+ *
+ * global: ( global <name>? <global_sig> <instr>* )
+ * ( global <name>? ( export <string> ) <...> )
+ * ( global <name>? ( import <string> <string> ) <global_sig> )
+ *
+ * global_sig: <type> | ( mut <type> )
+ *
+ */
+
+
+ function parseGlobal() {
+ var name = t.identifier(getUniqueName("global"));
+ var type; // Keep informations in case of a shorthand import
+
+ var importing = null;
+ maybeIgnoreComment();
+
+ if (token.type === _tokenizer.tokens.identifier) {
+ name = identifierFromToken(token);
+ eatToken();
+ } else {
+ name = t.withRaw(name, ""); // preserve anonymous
+ }
+ /**
+ * maybe export
+ */
+
+
+ if (lookaheadAndCheck(_tokenizer.tokens.openParen, _tokenizer.keywords.export)) {
+ eatToken(); // (
+
+ eatToken(); // export
+
+ var exportName = token.value;
+ eatTokenOfType(_tokenizer.tokens.string);
+ state.registredExportedElements.push({
+ exportType: "Global",
+ name: exportName,
+ id: name
+ });
+ eatTokenOfType(_tokenizer.tokens.closeParen);
+ }
+ /**
+ * maybe import
+ */
+
+
+ if (lookaheadAndCheck(_tokenizer.tokens.openParen, _tokenizer.keywords.import)) {
+ eatToken(); // (
+
+ eatToken(); // import
+
+ var moduleName = token.value;
+ eatTokenOfType(_tokenizer.tokens.string);
+ var _name3 = token.value;
+ eatTokenOfType(_tokenizer.tokens.string);
+ importing = {
+ module: moduleName,
+ name: _name3,
+ descr: undefined
+ };
+ eatTokenOfType(_tokenizer.tokens.closeParen);
+ }
+ /**
+ * global_sig
+ */
+
+
+ if (token.type === _tokenizer.tokens.valtype) {
+ type = t.globalType(token.value, "const");
+ eatToken();
+ } else if (token.type === _tokenizer.tokens.openParen) {
+ eatToken(); // (
+
+ if (isKeyword(token, _tokenizer.keywords.mut) === false) {
+ throw function () {
+ return new Error("\n" + (0, _helperCodeFrame.codeFrameFromSource)(source, token.loc) + "\n" + "Unsupported global type, expected mut" + ", given " + tokenToString(token));
+ }();
+ }
+
+ eatToken(); // mut
+
+ type = t.globalType(token.value, "var");
+ eatToken();
+ eatTokenOfType(_tokenizer.tokens.closeParen);
+ }
+
+ if (type === undefined) {
+ throw function () {
+ return new Error("\n" + (0, _helperCodeFrame.codeFrameFromSource)(source, token.loc) + "\n" + "Could not determine global type" + ", given " + tokenToString(token));
+ }();
+ }
+
+ maybeIgnoreComment();
+ var init = [];
+
+ if (importing != null) {
+ importing.descr = type;
+ init.push(t.moduleImport(importing.module, importing.name, importing.descr));
+ }
+ /**
+ * instr*
+ */
+
+
+ while (token.type === _tokenizer.tokens.openParen) {
+ eatToken();
+ init.push(parseFuncInstr());
+ eatTokenOfType(_tokenizer.tokens.closeParen);
+ }
+
+ return t.global(type, init, name);
+ }
+ /**
+ * Parses a function param
+ *
+ * WAST:
+ *
+ * param :: ( param <type>* ) | ( param <name> <type> )
+ */
+
+
+ function parseFuncParam() {
+ var params = [];
+ var id;
+ var valtype;
+
+ if (token.type === _tokenizer.tokens.identifier) {
+ id = token.value;
+ eatToken();
+ }
+
+ if (token.type === _tokenizer.tokens.valtype) {
+ valtype = token.value;
+ eatToken();
+ params.push({
+ id: id,
+ valtype: valtype
+ });
+ /**
+ * Shorthand notation for multiple anonymous parameters
+ * @see https://webassembly.github.io/spec/core/text/types.html#function-types
+ * @see https://github.com/xtuc/webassemblyjs/issues/6
+ */
+
+ if (id === undefined) {
+ while (token.type === _tokenizer.tokens.valtype) {
+ valtype = token.value;
+ eatToken();
+ params.push({
+ id: undefined,
+ valtype: valtype
+ });
+ }
+ }
+ } else {// ignore
+ }
+
+ return params;
+ }
+ /**
+ * Parses an element segments instruction
+ *
+ * WAST:
+ *
+ * elem: ( elem <var>? (offset <instr>* ) <var>* )
+ * ( elem <var>? <expr> <var>* )
+ *
+ * var: <nat> | <name>
+ */
+
+
+ function parseElem() {
+ var tableIndex = t.indexLiteral(0);
+ var offset = [];
+ var funcs = [];
+
+ if (token.type === _tokenizer.tokens.identifier) {
+ tableIndex = identifierFromToken(token);
+ eatToken();
+ }
+
+ if (token.type === _tokenizer.tokens.number) {
+ tableIndex = t.indexLiteral(token.value);
+ eatToken();
+ }
+
+ while (token.type !== _tokenizer.tokens.closeParen) {
+ if (lookaheadAndCheck(_tokenizer.tokens.openParen, _tokenizer.keywords.offset)) {
+ eatToken(); // (
+
+ eatToken(); // offset
+
+ while (token.type !== _tokenizer.tokens.closeParen) {
+ eatTokenOfType(_tokenizer.tokens.openParen);
+ offset.push(parseFuncInstr());
+ eatTokenOfType(_tokenizer.tokens.closeParen);
+ }
+
+ eatTokenOfType(_tokenizer.tokens.closeParen);
+ } else if (token.type === _tokenizer.tokens.identifier) {
+ funcs.push(t.identifier(token.value));
+ eatToken();
+ } else if (token.type === _tokenizer.tokens.number) {
+ funcs.push(t.indexLiteral(token.value));
+ eatToken();
+ } else if (token.type === _tokenizer.tokens.openParen) {
+ eatToken(); // (
+
+ offset.push(parseFuncInstr());
+ eatTokenOfType(_tokenizer.tokens.closeParen);
+ } else {
+ throw function () {
+ return new Error("\n" + (0, _helperCodeFrame.codeFrameFromSource)(source, token.loc) + "\n" + "Unsupported token in elem" + ", given " + tokenToString(token));
+ }();
+ }
+ }
+
+ return t.elem(tableIndex, offset, funcs);
+ }
+ /**
+ * Parses the start instruction in a module
+ *
+ * WAST:
+ *
+ * start: ( start <var> )
+ * var: <nat> | <name>
+ *
+ * WAT:
+ * start ::= ‘(’ ‘start’ x:funcidx ‘)’
+ */
+
+
+ function parseStart() {
+ if (token.type === _tokenizer.tokens.identifier) {
+ var index = identifierFromToken(token);
+ eatToken();
+ return t.start(index);
+ }
+
+ if (token.type === _tokenizer.tokens.number) {
+ var _index2 = t.indexLiteral(token.value);
+
+ eatToken();
+ return t.start(_index2);
+ }
+
+ throw new Error("Unknown start, token: " + tokenToString(token));
+ }
+
+ if (token.type === _tokenizer.tokens.openParen) {
+ eatToken();
+ var startLoc = getStartLoc();
+
+ if (isKeyword(token, _tokenizer.keywords.export)) {
+ eatToken();
+ var node = parseExport();
+
+ var _endLoc2 = getEndLoc();
+
+ return t.withLoc(node, _endLoc2, startLoc);
+ }
+
+ if (isKeyword(token, _tokenizer.keywords.loop)) {
+ eatToken();
+
+ var _node = parseLoop();
+
+ var _endLoc3 = getEndLoc();
+
+ return t.withLoc(_node, _endLoc3, startLoc);
+ }
+
+ if (isKeyword(token, _tokenizer.keywords.func)) {
+ eatToken();
+
+ var _node2 = parseFunc();
+
+ var _endLoc4 = getEndLoc();
+
+ maybeIgnoreComment();
+ eatTokenOfType(_tokenizer.tokens.closeParen);
+ return t.withLoc(_node2, _endLoc4, startLoc);
+ }
+
+ if (isKeyword(token, _tokenizer.keywords.module)) {
+ eatToken();
+
+ var _node3 = parseModule();
+
+ var _endLoc5 = getEndLoc();
+
+ return t.withLoc(_node3, _endLoc5, startLoc);
+ }
+
+ if (isKeyword(token, _tokenizer.keywords.import)) {
+ eatToken();
+
+ var _node4 = parseImport();
+
+ var _endLoc6 = getEndLoc();
+
+ eatTokenOfType(_tokenizer.tokens.closeParen);
+ return t.withLoc(_node4, _endLoc6, startLoc);
+ }
+
+ if (isKeyword(token, _tokenizer.keywords.block)) {
+ eatToken();
+
+ var _node5 = parseBlock();
+
+ var _endLoc7 = getEndLoc();
+
+ eatTokenOfType(_tokenizer.tokens.closeParen);
+ return t.withLoc(_node5, _endLoc7, startLoc);
+ }
+
+ if (isKeyword(token, _tokenizer.keywords.memory)) {
+ eatToken();
+
+ var _node6 = parseMemory();
+
+ var _endLoc8 = getEndLoc();
+
+ eatTokenOfType(_tokenizer.tokens.closeParen);
+ return t.withLoc(_node6, _endLoc8, startLoc);
+ }
+
+ if (isKeyword(token, _tokenizer.keywords.data)) {
+ eatToken();
+
+ var _node7 = parseData();
+
+ var _endLoc9 = getEndLoc();
+
+ eatTokenOfType(_tokenizer.tokens.closeParen);
+ return t.withLoc(_node7, _endLoc9, startLoc);
+ }
+
+ if (isKeyword(token, _tokenizer.keywords.table)) {
+ eatToken();
+
+ var _node8 = parseTable();
+
+ var _endLoc10 = getEndLoc();
+
+ eatTokenOfType(_tokenizer.tokens.closeParen);
+ return t.withLoc(_node8, _endLoc10, startLoc);
+ }
+
+ if (isKeyword(token, _tokenizer.keywords.global)) {
+ eatToken();
+
+ var _node9 = parseGlobal();
+
+ var _endLoc11 = getEndLoc();
+
+ eatTokenOfType(_tokenizer.tokens.closeParen);
+ return t.withLoc(_node9, _endLoc11, startLoc);
+ }
+
+ if (isKeyword(token, _tokenizer.keywords.type)) {
+ eatToken();
+
+ var _node10 = parseType();
+
+ var _endLoc12 = getEndLoc();
+
+ eatTokenOfType(_tokenizer.tokens.closeParen);
+ return t.withLoc(_node10, _endLoc12, startLoc);
+ }
+
+ if (isKeyword(token, _tokenizer.keywords.start)) {
+ eatToken();
+
+ var _node11 = parseStart();
+
+ var _endLoc13 = getEndLoc();
+
+ eatTokenOfType(_tokenizer.tokens.closeParen);
+ return t.withLoc(_node11, _endLoc13, startLoc);
+ }
+
+ if (isKeyword(token, _tokenizer.keywords.elem)) {
+ eatToken();
+
+ var _node12 = parseElem();
+
+ var _endLoc14 = getEndLoc();
+
+ eatTokenOfType(_tokenizer.tokens.closeParen);
+ return t.withLoc(_node12, _endLoc14, startLoc);
+ }
+
+ var instruction = parseFuncInstr();
+ var endLoc = getEndLoc();
+ maybeIgnoreComment();
+
+ if (_typeof(instruction) === "object") {
+ if (typeof token !== "undefined") {
+ eatTokenOfType(_tokenizer.tokens.closeParen);
+ }
+
+ return t.withLoc(instruction, endLoc, startLoc);
+ }
+ }
+
+ if (token.type === _tokenizer.tokens.comment) {
+ var _startLoc = getStartLoc();
+
+ var builder = token.opts.type === "leading" ? t.leadingComment : t.blockComment;
+
+ var _node13 = builder(token.value);
+
+ eatToken(); // comment
+
+ var _endLoc15 = getEndLoc();
+
+ return t.withLoc(_node13, _endLoc15, _startLoc);
+ }
+
+ throw function () {
+ return new Error("\n" + (0, _helperCodeFrame.codeFrameFromSource)(source, token.loc) + "\n" + "Unknown token" + ", given " + tokenToString(token));
+ }();
+ }
+
+ var body = [];
+
+ while (current < tokensList.length) {
+ body.push(walk());
+ }
+
+ return t.program(body);
+} \ No newline at end of file