grammar.js 51 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", {
  3. value: true
  4. });
  5. exports.parse = parse;
  6. var _helperCodeFrame = require("@webassemblyjs/helper-code-frame");
  7. var t = _interopRequireWildcard(require("@webassemblyjs/ast"));
  8. var _numberLiterals = require("./number-literals");
  9. var _stringLiterals = require("./string-literals");
  10. var _tokenizer = require("./tokenizer");
  11. 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; } }
  12. 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); }
  13. 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); } }
  14. function hasPlugin(name) {
  15. if (name !== "wast") throw new Error("unknow plugin");
  16. return true;
  17. }
  18. function isKeyword(token, id) {
  19. return token.type === _tokenizer.tokens.keyword && token.value === id;
  20. }
  21. function tokenToString(token) {
  22. if (token.type === "keyword") {
  23. return "keyword (".concat(token.value, ")");
  24. }
  25. return token.type;
  26. }
  27. function identifierFromToken(token) {
  28. var _token$loc = token.loc,
  29. end = _token$loc.end,
  30. start = _token$loc.start;
  31. return t.withLoc(t.identifier(token.value), end, start);
  32. }
  33. function parse(tokensList, source) {
  34. var current = 0;
  35. var getUniqueName = t.getUniqueNameGenerator();
  36. var state = {
  37. registredExportedElements: []
  38. }; // But this time we're going to use recursion instead of a `while` loop. So we
  39. // define a `walk` function.
  40. function walk() {
  41. var token = tokensList[current];
  42. function eatToken() {
  43. token = tokensList[++current];
  44. }
  45. function getEndLoc() {
  46. var currentToken = token;
  47. if (typeof currentToken === "undefined") {
  48. var lastToken = tokensList[tokensList.length - 1];
  49. currentToken = lastToken;
  50. }
  51. return currentToken.loc.end;
  52. }
  53. function getStartLoc() {
  54. return token.loc.start;
  55. }
  56. function eatTokenOfType(type) {
  57. if (token.type !== type) {
  58. throw new Error("\n" + (0, _helperCodeFrame.codeFrameFromSource)(source, token.loc) + "Assertion error: expected token of type " + type + ", given " + tokenToString(token));
  59. }
  60. eatToken();
  61. }
  62. function parseExportIndex(token) {
  63. if (token.type === _tokenizer.tokens.identifier) {
  64. var index = identifierFromToken(token);
  65. eatToken();
  66. return index;
  67. } else if (token.type === _tokenizer.tokens.number) {
  68. var _index = t.numberLiteralFromRaw(token.value);
  69. eatToken();
  70. return _index;
  71. } else {
  72. throw function () {
  73. return new Error("\n" + (0, _helperCodeFrame.codeFrameFromSource)(source, token.loc) + "\n" + "unknown export index" + ", given " + tokenToString(token));
  74. }();
  75. }
  76. }
  77. function lookaheadAndCheck() {
  78. var len = arguments.length;
  79. for (var i = 0; i < len; i++) {
  80. var tokenAhead = tokensList[current + i];
  81. var expectedToken = i < 0 || arguments.length <= i ? undefined : arguments[i];
  82. if (tokenAhead.type === "keyword") {
  83. if (isKeyword(tokenAhead, expectedToken) === false) {
  84. return false;
  85. }
  86. } else if (expectedToken !== tokenAhead.type) {
  87. return false;
  88. }
  89. }
  90. return true;
  91. } // TODO(sven): there is probably a better way to do this
  92. // can refactor it if it get out of hands
  93. function maybeIgnoreComment() {
  94. if (typeof token === "undefined") {
  95. // Ignore
  96. return;
  97. }
  98. while (token.type === _tokenizer.tokens.comment) {
  99. eatToken();
  100. if (typeof token === "undefined") {
  101. // Hit the end
  102. break;
  103. }
  104. }
  105. }
  106. /**
  107. * Parses a memory instruction
  108. *
  109. * WAST:
  110. *
  111. * memory: ( memory <name>? <memory_sig> )
  112. * ( memory <name>? ( export <string> ) <...> )
  113. * ( memory <name>? ( import <string> <string> ) <memory_sig> )
  114. * ( memory <name>? ( export <string> )* ( data <string>* )
  115. * memory_sig: <nat> <nat>?
  116. *
  117. */
  118. function parseMemory() {
  119. var id = t.identifier(getUniqueName("memory"));
  120. var limits = t.limit(0);
  121. if (token.type === _tokenizer.tokens.string || token.type === _tokenizer.tokens.identifier) {
  122. id = t.identifier(token.value);
  123. eatToken();
  124. } else {
  125. id = t.withRaw(id, ""); // preserve anonymous
  126. }
  127. /**
  128. * Maybe data
  129. */
  130. if (lookaheadAndCheck(_tokenizer.tokens.openParen, _tokenizer.keywords.data)) {
  131. eatToken(); // (
  132. eatToken(); // data
  133. // TODO(sven): do something with the data collected here
  134. var stringInitializer = token.value;
  135. eatTokenOfType(_tokenizer.tokens.string); // Update limits accordingly
  136. limits = t.limit(stringInitializer.length);
  137. eatTokenOfType(_tokenizer.tokens.closeParen);
  138. }
  139. /**
  140. * Maybe export
  141. */
  142. if (lookaheadAndCheck(_tokenizer.tokens.openParen, _tokenizer.keywords.export)) {
  143. eatToken(); // (
  144. eatToken(); // export
  145. if (token.type !== _tokenizer.tokens.string) {
  146. throw function () {
  147. return new Error("\n" + (0, _helperCodeFrame.codeFrameFromSource)(source, token.loc) + "\n" + "Expected string in export" + ", given " + tokenToString(token));
  148. }();
  149. }
  150. var _name = token.value;
  151. eatToken();
  152. state.registredExportedElements.push({
  153. exportType: "Memory",
  154. name: _name,
  155. id: id
  156. });
  157. eatTokenOfType(_tokenizer.tokens.closeParen);
  158. }
  159. /**
  160. * Memory signature
  161. */
  162. if (token.type === _tokenizer.tokens.number) {
  163. limits = t.limit((0, _numberLiterals.parse32I)(token.value));
  164. eatToken();
  165. if (token.type === _tokenizer.tokens.number) {
  166. limits.max = (0, _numberLiterals.parse32I)(token.value);
  167. eatToken();
  168. }
  169. }
  170. return t.memory(limits, id);
  171. }
  172. /**
  173. * Parses a data section
  174. * https://webassembly.github.io/spec/core/text/modules.html#data-segments
  175. *
  176. * WAST:
  177. *
  178. * data: ( data <index>? <offset> <string> )
  179. */
  180. function parseData() {
  181. // optional memory index
  182. var memidx = 0;
  183. if (token.type === _tokenizer.tokens.number) {
  184. memidx = token.value;
  185. eatTokenOfType(_tokenizer.tokens.number); // .
  186. }
  187. eatTokenOfType(_tokenizer.tokens.openParen);
  188. var offset;
  189. if (token.type === _tokenizer.tokens.valtype) {
  190. eatTokenOfType(_tokenizer.tokens.valtype); // i32
  191. eatTokenOfType(_tokenizer.tokens.dot); // .
  192. if (token.value !== "const") {
  193. throw new Error("constant expression required");
  194. }
  195. eatTokenOfType(_tokenizer.tokens.name); // const
  196. var numberLiteral = t.numberLiteralFromRaw(token.value, "i32");
  197. offset = t.objectInstruction("const", "i32", [numberLiteral]);
  198. eatToken();
  199. eatTokenOfType(_tokenizer.tokens.closeParen);
  200. } else {
  201. eatTokenOfType(_tokenizer.tokens.name); // get_global
  202. var _numberLiteral = t.numberLiteralFromRaw(token.value, "i32");
  203. offset = t.instruction("get_global", [_numberLiteral]);
  204. eatToken();
  205. eatTokenOfType(_tokenizer.tokens.closeParen);
  206. }
  207. var byteArray = (0, _stringLiterals.parseString)(token.value);
  208. eatToken(); // "string"
  209. return t.data(t.memIndexLiteral(memidx), offset, t.byteArray(byteArray));
  210. }
  211. /**
  212. * Parses a table instruction
  213. *
  214. * WAST:
  215. *
  216. * table: ( table <name>? <table_type> )
  217. * ( table <name>? ( export <string> ) <...> )
  218. * ( table <name>? ( import <string> <string> ) <table_type> )
  219. * ( table <name>? ( export <string> )* <elem_type> ( elem <var>* ) )
  220. *
  221. * table_type: <nat> <nat>? <elem_type>
  222. * elem_type: anyfunc
  223. *
  224. * elem: ( elem <var>? (offset <instr>* ) <var>* )
  225. * ( elem <var>? <expr> <var>* )
  226. */
  227. function parseTable() {
  228. var name = t.identifier(getUniqueName("table"));
  229. var limit = t.limit(0);
  230. var elemIndices = [];
  231. var elemType = "anyfunc";
  232. if (token.type === _tokenizer.tokens.string || token.type === _tokenizer.tokens.identifier) {
  233. name = identifierFromToken(token);
  234. eatToken();
  235. } else {
  236. name = t.withRaw(name, ""); // preserve anonymous
  237. }
  238. while (token.type !== _tokenizer.tokens.closeParen) {
  239. /**
  240. * Maybe export
  241. */
  242. if (lookaheadAndCheck(_tokenizer.tokens.openParen, _tokenizer.keywords.elem)) {
  243. eatToken(); // (
  244. eatToken(); // elem
  245. while (token.type === _tokenizer.tokens.identifier) {
  246. elemIndices.push(t.identifier(token.value));
  247. eatToken();
  248. }
  249. eatTokenOfType(_tokenizer.tokens.closeParen);
  250. } else if (lookaheadAndCheck(_tokenizer.tokens.openParen, _tokenizer.keywords.export)) {
  251. eatToken(); // (
  252. eatToken(); // export
  253. if (token.type !== _tokenizer.tokens.string) {
  254. throw function () {
  255. return new Error("\n" + (0, _helperCodeFrame.codeFrameFromSource)(source, token.loc) + "\n" + "Expected string in export" + ", given " + tokenToString(token));
  256. }();
  257. }
  258. var exportName = token.value;
  259. eatToken();
  260. state.registredExportedElements.push({
  261. exportType: "Table",
  262. name: exportName,
  263. id: name
  264. });
  265. eatTokenOfType(_tokenizer.tokens.closeParen);
  266. } else if (isKeyword(token, _tokenizer.keywords.anyfunc)) {
  267. // It's the default value, we can ignore it
  268. eatToken(); // anyfunc
  269. } else if (token.type === _tokenizer.tokens.number) {
  270. /**
  271. * Table type
  272. */
  273. var min = parseInt(token.value);
  274. eatToken();
  275. if (token.type === _tokenizer.tokens.number) {
  276. var max = parseInt(token.value);
  277. eatToken();
  278. limit = t.limit(min, max);
  279. } else {
  280. limit = t.limit(min);
  281. }
  282. eatToken();
  283. } else {
  284. throw function () {
  285. return new Error("\n" + (0, _helperCodeFrame.codeFrameFromSource)(source, token.loc) + "\n" + "Unexpected token" + ", given " + tokenToString(token));
  286. }();
  287. }
  288. }
  289. if (elemIndices.length > 0) {
  290. return t.table(elemType, limit, name, elemIndices);
  291. } else {
  292. return t.table(elemType, limit, name);
  293. }
  294. }
  295. /**
  296. * Parses an import statement
  297. *
  298. * WAST:
  299. *
  300. * import: ( import <string> <string> <imkind> )
  301. * imkind: ( func <name>? <func_sig> )
  302. * ( global <name>? <global_sig> )
  303. * ( table <name>? <table_sig> )
  304. * ( memory <name>? <memory_sig> )
  305. *
  306. * global_sig: <type> | ( mut <type> )
  307. */
  308. function parseImport() {
  309. if (token.type !== _tokenizer.tokens.string) {
  310. throw new Error("Expected a string, " + token.type + " given.");
  311. }
  312. var moduleName = token.value;
  313. eatToken();
  314. if (token.type !== _tokenizer.tokens.string) {
  315. throw new Error("Expected a string, " + token.type + " given.");
  316. }
  317. var name = token.value;
  318. eatToken();
  319. eatTokenOfType(_tokenizer.tokens.openParen);
  320. var descr;
  321. if (isKeyword(token, _tokenizer.keywords.func)) {
  322. eatToken(); // keyword
  323. var fnParams = [];
  324. var fnResult = [];
  325. var fnName = t.identifier(getUniqueName("func"));
  326. if (token.type === _tokenizer.tokens.identifier) {
  327. fnName = identifierFromToken(token);
  328. eatToken();
  329. }
  330. while (token.type === _tokenizer.tokens.openParen) {
  331. eatToken();
  332. if (lookaheadAndCheck(_tokenizer.keywords.param) === true) {
  333. eatToken();
  334. fnParams.push.apply(fnParams, _toConsumableArray(parseFuncParam()));
  335. } else if (lookaheadAndCheck(_tokenizer.keywords.result) === true) {
  336. eatToken();
  337. fnResult.push.apply(fnResult, _toConsumableArray(parseFuncResult()));
  338. } else {
  339. throw function () {
  340. return new Error("\n" + (0, _helperCodeFrame.codeFrameFromSource)(source, token.loc) + "\n" + "Unexpected token in import of type" + ", given " + tokenToString(token));
  341. }();
  342. }
  343. eatTokenOfType(_tokenizer.tokens.closeParen);
  344. }
  345. if (typeof fnName === "undefined") {
  346. throw new Error("Imported function must have a name");
  347. }
  348. descr = t.funcImportDescr(fnName, t.signature(fnParams, fnResult));
  349. } else if (isKeyword(token, _tokenizer.keywords.global)) {
  350. eatToken(); // keyword
  351. if (token.type === _tokenizer.tokens.openParen) {
  352. eatToken(); // (
  353. eatTokenOfType(_tokenizer.tokens.keyword); // mut keyword
  354. var valtype = token.value;
  355. eatToken();
  356. descr = t.globalType(valtype, "var");
  357. eatTokenOfType(_tokenizer.tokens.closeParen);
  358. } else {
  359. var _valtype = token.value;
  360. eatTokenOfType(_tokenizer.tokens.valtype);
  361. descr = t.globalType(_valtype, "const");
  362. }
  363. } else if (isKeyword(token, _tokenizer.keywords.memory) === true) {
  364. eatToken(); // Keyword
  365. descr = parseMemory();
  366. } else if (isKeyword(token, _tokenizer.keywords.table) === true) {
  367. eatToken(); // Keyword
  368. descr = parseTable();
  369. } else {
  370. throw new Error("Unsupported import type: " + tokenToString(token));
  371. }
  372. eatTokenOfType(_tokenizer.tokens.closeParen);
  373. return t.moduleImport(moduleName, name, descr);
  374. }
  375. /**
  376. * Parses a block instruction
  377. *
  378. * WAST:
  379. *
  380. * expr: ( block <name>? <block_sig> <instr>* )
  381. * instr: block <name>? <block_sig> <instr>* end <name>?
  382. * block_sig : ( result <type>* )*
  383. *
  384. */
  385. function parseBlock() {
  386. var label = t.identifier(getUniqueName("block"));
  387. var blockResult = null;
  388. var instr = [];
  389. if (token.type === _tokenizer.tokens.identifier) {
  390. label = identifierFromToken(token);
  391. eatToken();
  392. } else {
  393. label = t.withRaw(label, ""); // preserve anonymous
  394. }
  395. while (token.type === _tokenizer.tokens.openParen) {
  396. eatToken();
  397. if (lookaheadAndCheck(_tokenizer.keywords.result) === true) {
  398. eatToken();
  399. blockResult = token.value;
  400. eatToken();
  401. } else if (lookaheadAndCheck(_tokenizer.tokens.name) === true || lookaheadAndCheck(_tokenizer.tokens.valtype) === true || token.type === "keyword" // is any keyword
  402. ) {
  403. // Instruction
  404. instr.push(parseFuncInstr());
  405. } else {
  406. throw function () {
  407. return new Error("\n" + (0, _helperCodeFrame.codeFrameFromSource)(source, token.loc) + "\n" + "Unexpected token in block body of type" + ", given " + tokenToString(token));
  408. }();
  409. }
  410. maybeIgnoreComment();
  411. eatTokenOfType(_tokenizer.tokens.closeParen);
  412. }
  413. return t.blockInstruction(label, instr, blockResult);
  414. }
  415. /**
  416. * Parses a if instruction
  417. *
  418. * WAST:
  419. *
  420. * expr:
  421. * ( if <name>? <block_sig> ( then <instr>* ) ( else <instr>* )? )
  422. * ( if <name>? <block_sig> <expr>+ ( then <instr>* ) ( else <instr>* )? )
  423. *
  424. * instr:
  425. * if <name>? <block_sig> <instr>* end <name>?
  426. * if <name>? <block_sig> <instr>* else <name>? <instr>* end <name>?
  427. *
  428. * block_sig : ( result <type>* )*
  429. *
  430. */
  431. function parseIf() {
  432. var blockResult = null;
  433. var label = t.identifier(getUniqueName("if"));
  434. var testInstrs = [];
  435. var consequent = [];
  436. var alternate = [];
  437. if (token.type === _tokenizer.tokens.identifier) {
  438. label = identifierFromToken(token);
  439. eatToken();
  440. } else {
  441. label = t.withRaw(label, ""); // preserve anonymous
  442. }
  443. while (token.type === _tokenizer.tokens.openParen) {
  444. eatToken(); // (
  445. /**
  446. * Block signature
  447. */
  448. if (isKeyword(token, _tokenizer.keywords.result) === true) {
  449. eatToken();
  450. blockResult = token.value;
  451. eatTokenOfType(_tokenizer.tokens.valtype);
  452. eatTokenOfType(_tokenizer.tokens.closeParen);
  453. continue;
  454. }
  455. /**
  456. * Then
  457. */
  458. if (isKeyword(token, _tokenizer.keywords.then) === true) {
  459. eatToken(); // then
  460. while (token.type === _tokenizer.tokens.openParen) {
  461. eatToken(); // Instruction
  462. if (lookaheadAndCheck(_tokenizer.tokens.name) === true || lookaheadAndCheck(_tokenizer.tokens.valtype) === true || token.type === "keyword" // is any keyword
  463. ) {
  464. consequent.push(parseFuncInstr());
  465. } else {
  466. throw function () {
  467. return new Error("\n" + (0, _helperCodeFrame.codeFrameFromSource)(source, token.loc) + "\n" + "Unexpected token in consequent body of type" + ", given " + tokenToString(token));
  468. }();
  469. }
  470. eatTokenOfType(_tokenizer.tokens.closeParen);
  471. }
  472. eatTokenOfType(_tokenizer.tokens.closeParen);
  473. continue;
  474. }
  475. /**
  476. * Alternate
  477. */
  478. if (isKeyword(token, _tokenizer.keywords.else)) {
  479. eatToken(); // else
  480. while (token.type === _tokenizer.tokens.openParen) {
  481. eatToken(); // Instruction
  482. if (lookaheadAndCheck(_tokenizer.tokens.name) === true || lookaheadAndCheck(_tokenizer.tokens.valtype) === true || token.type === "keyword" // is any keyword
  483. ) {
  484. alternate.push(parseFuncInstr());
  485. } else {
  486. throw function () {
  487. return new Error("\n" + (0, _helperCodeFrame.codeFrameFromSource)(source, token.loc) + "\n" + "Unexpected token in alternate body of type" + ", given " + tokenToString(token));
  488. }();
  489. }
  490. eatTokenOfType(_tokenizer.tokens.closeParen);
  491. }
  492. eatTokenOfType(_tokenizer.tokens.closeParen);
  493. continue;
  494. }
  495. /**
  496. * Test instruction
  497. */
  498. if (lookaheadAndCheck(_tokenizer.tokens.name) === true || lookaheadAndCheck(_tokenizer.tokens.valtype) === true || token.type === "keyword" // is any keyword
  499. ) {
  500. testInstrs.push(parseFuncInstr());
  501. eatTokenOfType(_tokenizer.tokens.closeParen);
  502. continue;
  503. }
  504. throw function () {
  505. return new Error("\n" + (0, _helperCodeFrame.codeFrameFromSource)(source, token.loc) + "\n" + "Unexpected token in if body" + ", given " + tokenToString(token));
  506. }();
  507. }
  508. return t.ifInstruction(label, testInstrs, blockResult, consequent, alternate);
  509. }
  510. /**
  511. * Parses a loop instruction
  512. *
  513. * WAT:
  514. *
  515. * blockinstr :: 'loop' I:label rt:resulttype (in:instr*) 'end' id?
  516. *
  517. * WAST:
  518. *
  519. * instr :: loop <name>? <block_sig> <instr>* end <name>?
  520. * expr :: ( loop <name>? <block_sig> <instr>* )
  521. * block_sig :: ( result <type>* )*
  522. *
  523. */
  524. function parseLoop() {
  525. var label = t.identifier(getUniqueName("loop"));
  526. var blockResult;
  527. var instr = [];
  528. if (token.type === _tokenizer.tokens.identifier) {
  529. label = identifierFromToken(token);
  530. eatToken();
  531. } else {
  532. label = t.withRaw(label, ""); // preserve anonymous
  533. }
  534. while (token.type === _tokenizer.tokens.openParen) {
  535. eatToken();
  536. if (lookaheadAndCheck(_tokenizer.keywords.result) === true) {
  537. eatToken();
  538. blockResult = token.value;
  539. eatToken();
  540. } else if (lookaheadAndCheck(_tokenizer.tokens.name) === true || lookaheadAndCheck(_tokenizer.tokens.valtype) === true || token.type === "keyword" // is any keyword
  541. ) {
  542. // Instruction
  543. instr.push(parseFuncInstr());
  544. } else {
  545. throw function () {
  546. return new Error("\n" + (0, _helperCodeFrame.codeFrameFromSource)(source, token.loc) + "\n" + "Unexpected token in loop body" + ", given " + tokenToString(token));
  547. }();
  548. }
  549. eatTokenOfType(_tokenizer.tokens.closeParen);
  550. }
  551. return t.loopInstruction(label, blockResult, instr);
  552. }
  553. function parseCallIndirect() {
  554. var typeRef;
  555. var params = [];
  556. var results = [];
  557. var instrs = [];
  558. while (token.type !== _tokenizer.tokens.closeParen) {
  559. if (lookaheadAndCheck(_tokenizer.tokens.openParen, _tokenizer.keywords.type)) {
  560. eatToken(); // (
  561. eatToken(); // type
  562. typeRef = parseTypeReference();
  563. } else if (lookaheadAndCheck(_tokenizer.tokens.openParen, _tokenizer.keywords.param)) {
  564. eatToken(); // (
  565. eatToken(); // param
  566. /**
  567. * Params can be empty:
  568. * (params)`
  569. */
  570. if (token.type !== _tokenizer.tokens.closeParen) {
  571. params.push.apply(params, _toConsumableArray(parseFuncParam()));
  572. }
  573. } else if (lookaheadAndCheck(_tokenizer.tokens.openParen, _tokenizer.keywords.result)) {
  574. eatToken(); // (
  575. eatToken(); // result
  576. /**
  577. * Results can be empty:
  578. * (result)`
  579. */
  580. if (token.type !== _tokenizer.tokens.closeParen) {
  581. results.push.apply(results, _toConsumableArray(parseFuncResult()));
  582. }
  583. } else {
  584. eatTokenOfType(_tokenizer.tokens.openParen);
  585. instrs.push(parseFuncInstr());
  586. }
  587. eatTokenOfType(_tokenizer.tokens.closeParen);
  588. }
  589. return t.callIndirectInstruction(typeRef !== undefined ? typeRef : t.signature(params, results), instrs);
  590. }
  591. /**
  592. * Parses an export instruction
  593. *
  594. * WAT:
  595. *
  596. * export: ( export <string> <exkind> )
  597. * exkind: ( func <var> )
  598. * ( global <var> )
  599. * ( table <var> )
  600. * ( memory <var> )
  601. * var: <nat> | <name>
  602. *
  603. */
  604. function parseExport() {
  605. if (token.type !== _tokenizer.tokens.string) {
  606. throw new Error("Expected string after export, got: " + token.type);
  607. }
  608. var name = token.value;
  609. eatToken();
  610. var moduleExportDescr = parseModuleExportDescr();
  611. return t.moduleExport(name, moduleExportDescr);
  612. }
  613. function parseModuleExportDescr() {
  614. var startLoc = getStartLoc();
  615. var type = "";
  616. var index;
  617. eatTokenOfType(_tokenizer.tokens.openParen);
  618. while (token.type !== _tokenizer.tokens.closeParen) {
  619. if (isKeyword(token, _tokenizer.keywords.func)) {
  620. type = "Func";
  621. eatToken();
  622. index = parseExportIndex(token);
  623. } else if (isKeyword(token, _tokenizer.keywords.table)) {
  624. type = "Table";
  625. eatToken();
  626. index = parseExportIndex(token);
  627. } else if (isKeyword(token, _tokenizer.keywords.global)) {
  628. type = "Global";
  629. eatToken();
  630. index = parseExportIndex(token);
  631. } else if (isKeyword(token, _tokenizer.keywords.memory)) {
  632. type = "Memory";
  633. eatToken();
  634. index = parseExportIndex(token);
  635. }
  636. eatToken();
  637. }
  638. if (type === "") {
  639. throw new Error("Unknown export type");
  640. }
  641. if (index === undefined) {
  642. throw new Error("Exported function must have a name");
  643. }
  644. var node = t.moduleExportDescr(type, index);
  645. var endLoc = getEndLoc();
  646. eatTokenOfType(_tokenizer.tokens.closeParen);
  647. return t.withLoc(node, endLoc, startLoc);
  648. }
  649. function parseModule() {
  650. var name = null;
  651. var isBinary = false;
  652. var isQuote = false;
  653. var moduleFields = [];
  654. if (token.type === _tokenizer.tokens.identifier) {
  655. name = token.value;
  656. eatToken();
  657. }
  658. if (hasPlugin("wast") && token.type === _tokenizer.tokens.name && token.value === "binary") {
  659. eatToken();
  660. isBinary = true;
  661. }
  662. if (hasPlugin("wast") && token.type === _tokenizer.tokens.name && token.value === "quote") {
  663. eatToken();
  664. isQuote = true;
  665. }
  666. if (isBinary === true) {
  667. var blob = [];
  668. while (token.type === _tokenizer.tokens.string) {
  669. blob.push(token.value);
  670. eatToken();
  671. maybeIgnoreComment();
  672. }
  673. eatTokenOfType(_tokenizer.tokens.closeParen);
  674. return t.binaryModule(name, blob);
  675. }
  676. if (isQuote === true) {
  677. var string = [];
  678. while (token.type === _tokenizer.tokens.string) {
  679. string.push(token.value);
  680. eatToken();
  681. }
  682. eatTokenOfType(_tokenizer.tokens.closeParen);
  683. return t.quoteModule(name, string);
  684. }
  685. while (token.type !== _tokenizer.tokens.closeParen) {
  686. moduleFields.push(walk());
  687. if (state.registredExportedElements.length > 0) {
  688. state.registredExportedElements.forEach(function (decl) {
  689. moduleFields.push(t.moduleExport(decl.name, t.moduleExportDescr(decl.exportType, decl.id)));
  690. });
  691. state.registredExportedElements = [];
  692. }
  693. token = tokensList[current];
  694. }
  695. eatTokenOfType(_tokenizer.tokens.closeParen);
  696. return t.module(name, moduleFields);
  697. }
  698. /**
  699. * Parses the arguments of an instruction
  700. */
  701. function parseFuncInstrArguments(signature) {
  702. var args = [];
  703. var namedArgs = {};
  704. var signaturePtr = 0;
  705. while (token.type === _tokenizer.tokens.name || isKeyword(token, _tokenizer.keywords.offset)) {
  706. var key = token.value;
  707. eatToken();
  708. eatTokenOfType(_tokenizer.tokens.equal);
  709. var value = void 0;
  710. if (token.type === _tokenizer.tokens.number) {
  711. value = t.numberLiteralFromRaw(token.value);
  712. } else {
  713. throw new Error("Unexpected type for argument: " + token.type);
  714. }
  715. namedArgs[key] = value;
  716. eatToken();
  717. } // $FlowIgnore
  718. var signatureLength = signature.vector ? Infinity : signature.length;
  719. while (token.type !== _tokenizer.tokens.closeParen && ( // $FlowIgnore
  720. token.type === _tokenizer.tokens.openParen || signaturePtr < signatureLength)) {
  721. if (token.type === _tokenizer.tokens.identifier) {
  722. args.push(t.identifier(token.value));
  723. eatToken();
  724. } else if (token.type === _tokenizer.tokens.valtype) {
  725. // Handle locals
  726. args.push(t.valtypeLiteral(token.value));
  727. eatToken();
  728. } else if (token.type === _tokenizer.tokens.string) {
  729. args.push(t.stringLiteral(token.value));
  730. eatToken();
  731. } else if (token.type === _tokenizer.tokens.number) {
  732. args.push( // TODO(sven): refactor the type signature handling
  733. // https://github.com/xtuc/webassemblyjs/pull/129 is a good start
  734. t.numberLiteralFromRaw(token.value, // $FlowIgnore
  735. signature[signaturePtr] || "f64")); // $FlowIgnore
  736. if (!signature.vector) {
  737. ++signaturePtr;
  738. }
  739. eatToken();
  740. } else if (token.type === _tokenizer.tokens.openParen) {
  741. /**
  742. * Maybe some nested instructions
  743. */
  744. eatToken(); // Instruction
  745. if (lookaheadAndCheck(_tokenizer.tokens.name) === true || lookaheadAndCheck(_tokenizer.tokens.valtype) === true || token.type === "keyword" // is any keyword
  746. ) {
  747. // $FlowIgnore
  748. args.push(parseFuncInstr());
  749. } else {
  750. throw function () {
  751. return new Error("\n" + (0, _helperCodeFrame.codeFrameFromSource)(source, token.loc) + "\n" + "Unexpected token in nested instruction" + ", given " + tokenToString(token));
  752. }();
  753. }
  754. if (token.type === _tokenizer.tokens.closeParen) {
  755. eatToken();
  756. }
  757. } else {
  758. throw function () {
  759. return new Error("\n" + (0, _helperCodeFrame.codeFrameFromSource)(source, token.loc) + "\n" + "Unexpected token in instruction argument" + ", given " + tokenToString(token));
  760. }();
  761. }
  762. }
  763. return {
  764. args: args,
  765. namedArgs: namedArgs
  766. };
  767. }
  768. /**
  769. * Parses an instruction
  770. *
  771. * WAT:
  772. *
  773. * instr :: plaininst
  774. * blockinstr
  775. *
  776. * blockinstr :: 'block' I:label rt:resulttype (in:instr*) 'end' id?
  777. * 'loop' I:label rt:resulttype (in:instr*) 'end' id?
  778. * 'if' I:label rt:resulttype (in:instr*) 'else' id? (in2:intr*) 'end' id?
  779. *
  780. * plaininst :: 'unreachable'
  781. * 'nop'
  782. * 'br' l:labelidx
  783. * 'br_if' l:labelidx
  784. * 'br_table' l*:vec(labelidx) ln:labelidx
  785. * 'return'
  786. * 'call' x:funcidx
  787. * 'call_indirect' x, I:typeuse
  788. *
  789. * WAST:
  790. *
  791. * instr:
  792. * <expr>
  793. * <op>
  794. * block <name>? <block_sig> <instr>* end <name>?
  795. * loop <name>? <block_sig> <instr>* end <name>?
  796. * if <name>? <block_sig> <instr>* end <name>?
  797. * if <name>? <block_sig> <instr>* else <name>? <instr>* end <name>?
  798. *
  799. * expr:
  800. * ( <op> )
  801. * ( <op> <expr>+ )
  802. * ( block <name>? <block_sig> <instr>* )
  803. * ( loop <name>? <block_sig> <instr>* )
  804. * ( if <name>? <block_sig> ( then <instr>* ) ( else <instr>* )? )
  805. * ( if <name>? <block_sig> <expr>+ ( then <instr>* ) ( else <instr>* )? )
  806. *
  807. * op:
  808. * unreachable
  809. * nop
  810. * br <var>
  811. * br_if <var>
  812. * br_table <var>+
  813. * return
  814. * call <var>
  815. * call_indirect <func_sig>
  816. * drop
  817. * select
  818. * get_local <var>
  819. * set_local <var>
  820. * tee_local <var>
  821. * get_global <var>
  822. * set_global <var>
  823. * <type>.load((8|16|32)_<sign>)? <offset>? <align>?
  824. * <type>.store(8|16|32)? <offset>? <align>?
  825. * current_memory
  826. * grow_memory
  827. * <type>.const <value>
  828. * <type>.<unop>
  829. * <type>.<binop>
  830. * <type>.<testop>
  831. * <type>.<relop>
  832. * <type>.<cvtop>/<type>
  833. *
  834. * func_type: ( type <var> )? <param>* <result>*
  835. */
  836. function parseFuncInstr() {
  837. var startLoc = getStartLoc();
  838. maybeIgnoreComment();
  839. /**
  840. * A simple instruction
  841. */
  842. if (token.type === _tokenizer.tokens.name || token.type === _tokenizer.tokens.valtype) {
  843. var _name2 = token.value;
  844. var object;
  845. eatToken();
  846. if (token.type === _tokenizer.tokens.dot) {
  847. object = _name2;
  848. eatToken();
  849. if (token.type !== _tokenizer.tokens.name) {
  850. throw new TypeError("Unknown token: " + token.type + ", name expected");
  851. }
  852. _name2 = token.value;
  853. eatToken();
  854. }
  855. if (token.type === _tokenizer.tokens.closeParen) {
  856. var _endLoc = token.loc.end;
  857. if (typeof object === "undefined") {
  858. return t.withLoc(t.instruction(_name2), _endLoc, startLoc);
  859. } else {
  860. return t.withLoc(t.objectInstruction(_name2, object, []), _endLoc, startLoc);
  861. }
  862. }
  863. var signature = t.signatureForOpcode(object || "", _name2);
  864. var _parseFuncInstrArgume = parseFuncInstrArguments(signature),
  865. _args = _parseFuncInstrArgume.args,
  866. _namedArgs = _parseFuncInstrArgume.namedArgs;
  867. var endLoc = token.loc.end;
  868. if (typeof object === "undefined") {
  869. return t.withLoc(t.instruction(_name2, _args, _namedArgs), endLoc, startLoc);
  870. } else {
  871. return t.withLoc(t.objectInstruction(_name2, object, _args, _namedArgs), endLoc, startLoc);
  872. }
  873. } else if (isKeyword(token, _tokenizer.keywords.loop)) {
  874. /**
  875. * Else a instruction with a keyword (loop or block)
  876. */
  877. eatToken(); // keyword
  878. return parseLoop();
  879. } else if (isKeyword(token, _tokenizer.keywords.block)) {
  880. eatToken(); // keyword
  881. return parseBlock();
  882. } else if (isKeyword(token, _tokenizer.keywords.call_indirect)) {
  883. eatToken(); // keyword
  884. return parseCallIndirect();
  885. } else if (isKeyword(token, _tokenizer.keywords.call)) {
  886. eatToken(); // keyword
  887. var index;
  888. if (token.type === _tokenizer.tokens.identifier) {
  889. index = identifierFromToken(token);
  890. eatToken();
  891. } else if (token.type === _tokenizer.tokens.number) {
  892. index = t.indexLiteral(token.value);
  893. eatToken();
  894. }
  895. var instrArgs = []; // Nested instruction
  896. while (token.type === _tokenizer.tokens.openParen) {
  897. eatToken();
  898. instrArgs.push(parseFuncInstr());
  899. eatTokenOfType(_tokenizer.tokens.closeParen);
  900. }
  901. if (typeof index === "undefined") {
  902. throw new Error("Missing argument in call instruciton");
  903. }
  904. if (instrArgs.length > 0) {
  905. return t.callInstruction(index, instrArgs);
  906. } else {
  907. return t.callInstruction(index);
  908. }
  909. } else if (isKeyword(token, _tokenizer.keywords.if)) {
  910. eatToken(); // Keyword
  911. return parseIf();
  912. } else if (isKeyword(token, _tokenizer.keywords.module) && hasPlugin("wast")) {
  913. eatToken(); // In WAST you can have a module as an instruction's argument
  914. // we will cast it into a instruction to not break the flow
  915. // $FlowIgnore
  916. var module = parseModule();
  917. return module;
  918. } else {
  919. throw function () {
  920. return new Error("\n" + (0, _helperCodeFrame.codeFrameFromSource)(source, token.loc) + "\n" + "Unexpected instruction in function body" + ", given " + tokenToString(token));
  921. }();
  922. }
  923. }
  924. /*
  925. * Parses a function
  926. *
  927. * WAT:
  928. *
  929. * functype :: ( 'func' t1:vec(param) t2:vec(result) )
  930. * param :: ( 'param' id? t:valtype )
  931. * result :: ( 'result' t:valtype )
  932. *
  933. * WAST:
  934. *
  935. * func :: ( func <name>? <func_sig> <local>* <instr>* )
  936. * ( func <name>? ( export <string> ) <...> )
  937. * ( func <name>? ( import <string> <string> ) <func_sig> )
  938. * func_sig :: ( type <var> )? <param>* <result>*
  939. * param :: ( param <type>* ) | ( param <name> <type> )
  940. * result :: ( result <type>* )
  941. * local :: ( local <type>* ) | ( local <name> <type> )
  942. *
  943. */
  944. function parseFunc() {
  945. var fnName = t.identifier(getUniqueName("func"));
  946. var typeRef;
  947. var fnBody = [];
  948. var fnParams = [];
  949. var fnResult = []; // name
  950. if (token.type === _tokenizer.tokens.identifier) {
  951. fnName = identifierFromToken(token);
  952. eatToken();
  953. } else {
  954. fnName = t.withRaw(fnName, ""); // preserve anonymous
  955. }
  956. maybeIgnoreComment();
  957. while (token.type === _tokenizer.tokens.openParen || token.type === _tokenizer.tokens.name || token.type === _tokenizer.tokens.valtype) {
  958. // Instructions without parens
  959. if (token.type === _tokenizer.tokens.name || token.type === _tokenizer.tokens.valtype) {
  960. fnBody.push(parseFuncInstr());
  961. continue;
  962. }
  963. eatToken();
  964. if (lookaheadAndCheck(_tokenizer.keywords.param) === true) {
  965. eatToken();
  966. fnParams.push.apply(fnParams, _toConsumableArray(parseFuncParam()));
  967. } else if (lookaheadAndCheck(_tokenizer.keywords.result) === true) {
  968. eatToken();
  969. fnResult.push.apply(fnResult, _toConsumableArray(parseFuncResult()));
  970. } else if (lookaheadAndCheck(_tokenizer.keywords.export) === true) {
  971. eatToken();
  972. parseFuncExport(fnName);
  973. } else if (lookaheadAndCheck(_tokenizer.keywords.type) === true) {
  974. eatToken();
  975. typeRef = parseTypeReference();
  976. } else if (lookaheadAndCheck(_tokenizer.tokens.name) === true || lookaheadAndCheck(_tokenizer.tokens.valtype) === true || token.type === "keyword" // is any keyword
  977. ) {
  978. // Instruction
  979. fnBody.push(parseFuncInstr());
  980. } else {
  981. throw function () {
  982. return new Error("\n" + (0, _helperCodeFrame.codeFrameFromSource)(source, token.loc) + "\n" + "Unexpected token in func body" + ", given " + tokenToString(token));
  983. }();
  984. }
  985. eatTokenOfType(_tokenizer.tokens.closeParen);
  986. }
  987. return t.func(fnName, typeRef !== undefined ? typeRef : t.signature(fnParams, fnResult), fnBody);
  988. }
  989. /**
  990. * Parses shorthand export in func
  991. *
  992. * export :: ( export <string> )
  993. */
  994. function parseFuncExport(funcId) {
  995. if (token.type !== _tokenizer.tokens.string) {
  996. throw function () {
  997. return new Error("\n" + (0, _helperCodeFrame.codeFrameFromSource)(source, token.loc) + "\n" + "Function export expected a string" + ", given " + tokenToString(token));
  998. }();
  999. }
  1000. var name = token.value;
  1001. eatToken();
  1002. /**
  1003. * Func export shorthand, we trait it as a syntaxic sugar.
  1004. * A export ModuleField will be added later.
  1005. *
  1006. * We give the anonymous function a generated name and export it.
  1007. */
  1008. var id = t.identifier(funcId.value);
  1009. state.registredExportedElements.push({
  1010. exportType: "Func",
  1011. name: name,
  1012. id: id
  1013. });
  1014. }
  1015. /**
  1016. * Parses a type instruction
  1017. *
  1018. * WAST:
  1019. *
  1020. * typedef: ( type <name>? ( func <param>* <result>* ) )
  1021. */
  1022. function parseType() {
  1023. var id;
  1024. var params = [];
  1025. var result = [];
  1026. if (token.type === _tokenizer.tokens.identifier) {
  1027. id = identifierFromToken(token);
  1028. eatToken();
  1029. }
  1030. if (lookaheadAndCheck(_tokenizer.tokens.openParen, _tokenizer.keywords.func)) {
  1031. eatToken(); // (
  1032. eatToken(); // func
  1033. if (token.type === _tokenizer.tokens.closeParen) {
  1034. eatToken(); // function with an empty signature, we can abort here
  1035. return t.typeInstruction(id, t.signature([], []));
  1036. }
  1037. if (lookaheadAndCheck(_tokenizer.tokens.openParen, _tokenizer.keywords.param)) {
  1038. eatToken(); // (
  1039. eatToken(); // param
  1040. params = parseFuncParam();
  1041. eatTokenOfType(_tokenizer.tokens.closeParen);
  1042. }
  1043. if (lookaheadAndCheck(_tokenizer.tokens.openParen, _tokenizer.keywords.result)) {
  1044. eatToken(); // (
  1045. eatToken(); // result
  1046. result = parseFuncResult();
  1047. eatTokenOfType(_tokenizer.tokens.closeParen);
  1048. }
  1049. eatTokenOfType(_tokenizer.tokens.closeParen);
  1050. }
  1051. return t.typeInstruction(id, t.signature(params, result));
  1052. }
  1053. /**
  1054. * Parses a function result
  1055. *
  1056. * WAST:
  1057. *
  1058. * result :: ( result <type>* )
  1059. */
  1060. function parseFuncResult() {
  1061. var results = [];
  1062. while (token.type !== _tokenizer.tokens.closeParen) {
  1063. if (token.type !== _tokenizer.tokens.valtype) {
  1064. throw function () {
  1065. return new Error("\n" + (0, _helperCodeFrame.codeFrameFromSource)(source, token.loc) + "\n" + "Unexpected token in func result" + ", given " + tokenToString(token));
  1066. }();
  1067. }
  1068. var valtype = token.value;
  1069. eatToken();
  1070. results.push(valtype);
  1071. }
  1072. return results;
  1073. }
  1074. /**
  1075. * Parses a type reference
  1076. *
  1077. */
  1078. function parseTypeReference() {
  1079. var ref;
  1080. if (token.type === _tokenizer.tokens.identifier) {
  1081. ref = identifierFromToken(token);
  1082. eatToken();
  1083. } else if (token.type === _tokenizer.tokens.number) {
  1084. ref = t.numberLiteralFromRaw(token.value);
  1085. eatToken();
  1086. }
  1087. return ref;
  1088. }
  1089. /**
  1090. * Parses a global instruction
  1091. *
  1092. * WAST:
  1093. *
  1094. * global: ( global <name>? <global_sig> <instr>* )
  1095. * ( global <name>? ( export <string> ) <...> )
  1096. * ( global <name>? ( import <string> <string> ) <global_sig> )
  1097. *
  1098. * global_sig: <type> | ( mut <type> )
  1099. *
  1100. */
  1101. function parseGlobal() {
  1102. var name = t.identifier(getUniqueName("global"));
  1103. var type; // Keep informations in case of a shorthand import
  1104. var importing = null;
  1105. maybeIgnoreComment();
  1106. if (token.type === _tokenizer.tokens.identifier) {
  1107. name = identifierFromToken(token);
  1108. eatToken();
  1109. } else {
  1110. name = t.withRaw(name, ""); // preserve anonymous
  1111. }
  1112. /**
  1113. * maybe export
  1114. */
  1115. if (lookaheadAndCheck(_tokenizer.tokens.openParen, _tokenizer.keywords.export)) {
  1116. eatToken(); // (
  1117. eatToken(); // export
  1118. var exportName = token.value;
  1119. eatTokenOfType(_tokenizer.tokens.string);
  1120. state.registredExportedElements.push({
  1121. exportType: "Global",
  1122. name: exportName,
  1123. id: name
  1124. });
  1125. eatTokenOfType(_tokenizer.tokens.closeParen);
  1126. }
  1127. /**
  1128. * maybe import
  1129. */
  1130. if (lookaheadAndCheck(_tokenizer.tokens.openParen, _tokenizer.keywords.import)) {
  1131. eatToken(); // (
  1132. eatToken(); // import
  1133. var moduleName = token.value;
  1134. eatTokenOfType(_tokenizer.tokens.string);
  1135. var _name3 = token.value;
  1136. eatTokenOfType(_tokenizer.tokens.string);
  1137. importing = {
  1138. module: moduleName,
  1139. name: _name3,
  1140. descr: undefined
  1141. };
  1142. eatTokenOfType(_tokenizer.tokens.closeParen);
  1143. }
  1144. /**
  1145. * global_sig
  1146. */
  1147. if (token.type === _tokenizer.tokens.valtype) {
  1148. type = t.globalType(token.value, "const");
  1149. eatToken();
  1150. } else if (token.type === _tokenizer.tokens.openParen) {
  1151. eatToken(); // (
  1152. if (isKeyword(token, _tokenizer.keywords.mut) === false) {
  1153. throw function () {
  1154. return new Error("\n" + (0, _helperCodeFrame.codeFrameFromSource)(source, token.loc) + "\n" + "Unsupported global type, expected mut" + ", given " + tokenToString(token));
  1155. }();
  1156. }
  1157. eatToken(); // mut
  1158. type = t.globalType(token.value, "var");
  1159. eatToken();
  1160. eatTokenOfType(_tokenizer.tokens.closeParen);
  1161. }
  1162. if (type === undefined) {
  1163. throw function () {
  1164. return new Error("\n" + (0, _helperCodeFrame.codeFrameFromSource)(source, token.loc) + "\n" + "Could not determine global type" + ", given " + tokenToString(token));
  1165. }();
  1166. }
  1167. maybeIgnoreComment();
  1168. var init = [];
  1169. if (importing != null) {
  1170. importing.descr = type;
  1171. init.push(t.moduleImport(importing.module, importing.name, importing.descr));
  1172. }
  1173. /**
  1174. * instr*
  1175. */
  1176. while (token.type === _tokenizer.tokens.openParen) {
  1177. eatToken();
  1178. init.push(parseFuncInstr());
  1179. eatTokenOfType(_tokenizer.tokens.closeParen);
  1180. }
  1181. return t.global(type, init, name);
  1182. }
  1183. /**
  1184. * Parses a function param
  1185. *
  1186. * WAST:
  1187. *
  1188. * param :: ( param <type>* ) | ( param <name> <type> )
  1189. */
  1190. function parseFuncParam() {
  1191. var params = [];
  1192. var id;
  1193. var valtype;
  1194. if (token.type === _tokenizer.tokens.identifier) {
  1195. id = token.value;
  1196. eatToken();
  1197. }
  1198. if (token.type === _tokenizer.tokens.valtype) {
  1199. valtype = token.value;
  1200. eatToken();
  1201. params.push({
  1202. id: id,
  1203. valtype: valtype
  1204. });
  1205. /**
  1206. * Shorthand notation for multiple anonymous parameters
  1207. * @see https://webassembly.github.io/spec/core/text/types.html#function-types
  1208. * @see https://github.com/xtuc/webassemblyjs/issues/6
  1209. */
  1210. if (id === undefined) {
  1211. while (token.type === _tokenizer.tokens.valtype) {
  1212. valtype = token.value;
  1213. eatToken();
  1214. params.push({
  1215. id: undefined,
  1216. valtype: valtype
  1217. });
  1218. }
  1219. }
  1220. } else {// ignore
  1221. }
  1222. return params;
  1223. }
  1224. /**
  1225. * Parses an element segments instruction
  1226. *
  1227. * WAST:
  1228. *
  1229. * elem: ( elem <var>? (offset <instr>* ) <var>* )
  1230. * ( elem <var>? <expr> <var>* )
  1231. *
  1232. * var: <nat> | <name>
  1233. */
  1234. function parseElem() {
  1235. var tableIndex = t.indexLiteral(0);
  1236. var offset = [];
  1237. var funcs = [];
  1238. if (token.type === _tokenizer.tokens.identifier) {
  1239. tableIndex = identifierFromToken(token);
  1240. eatToken();
  1241. }
  1242. if (token.type === _tokenizer.tokens.number) {
  1243. tableIndex = t.indexLiteral(token.value);
  1244. eatToken();
  1245. }
  1246. while (token.type !== _tokenizer.tokens.closeParen) {
  1247. if (lookaheadAndCheck(_tokenizer.tokens.openParen, _tokenizer.keywords.offset)) {
  1248. eatToken(); // (
  1249. eatToken(); // offset
  1250. while (token.type !== _tokenizer.tokens.closeParen) {
  1251. eatTokenOfType(_tokenizer.tokens.openParen);
  1252. offset.push(parseFuncInstr());
  1253. eatTokenOfType(_tokenizer.tokens.closeParen);
  1254. }
  1255. eatTokenOfType(_tokenizer.tokens.closeParen);
  1256. } else if (token.type === _tokenizer.tokens.identifier) {
  1257. funcs.push(t.identifier(token.value));
  1258. eatToken();
  1259. } else if (token.type === _tokenizer.tokens.number) {
  1260. funcs.push(t.indexLiteral(token.value));
  1261. eatToken();
  1262. } else if (token.type === _tokenizer.tokens.openParen) {
  1263. eatToken(); // (
  1264. offset.push(parseFuncInstr());
  1265. eatTokenOfType(_tokenizer.tokens.closeParen);
  1266. } else {
  1267. throw function () {
  1268. return new Error("\n" + (0, _helperCodeFrame.codeFrameFromSource)(source, token.loc) + "\n" + "Unsupported token in elem" + ", given " + tokenToString(token));
  1269. }();
  1270. }
  1271. }
  1272. return t.elem(tableIndex, offset, funcs);
  1273. }
  1274. /**
  1275. * Parses the start instruction in a module
  1276. *
  1277. * WAST:
  1278. *
  1279. * start: ( start <var> )
  1280. * var: <nat> | <name>
  1281. *
  1282. * WAT:
  1283. * start ::= ‘(’ ‘start’ x:funcidx ‘)’
  1284. */
  1285. function parseStart() {
  1286. if (token.type === _tokenizer.tokens.identifier) {
  1287. var index = identifierFromToken(token);
  1288. eatToken();
  1289. return t.start(index);
  1290. }
  1291. if (token.type === _tokenizer.tokens.number) {
  1292. var _index2 = t.indexLiteral(token.value);
  1293. eatToken();
  1294. return t.start(_index2);
  1295. }
  1296. throw new Error("Unknown start, token: " + tokenToString(token));
  1297. }
  1298. if (token.type === _tokenizer.tokens.openParen) {
  1299. eatToken();
  1300. var startLoc = getStartLoc();
  1301. if (isKeyword(token, _tokenizer.keywords.export)) {
  1302. eatToken();
  1303. var node = parseExport();
  1304. var _endLoc2 = getEndLoc();
  1305. return t.withLoc(node, _endLoc2, startLoc);
  1306. }
  1307. if (isKeyword(token, _tokenizer.keywords.loop)) {
  1308. eatToken();
  1309. var _node = parseLoop();
  1310. var _endLoc3 = getEndLoc();
  1311. return t.withLoc(_node, _endLoc3, startLoc);
  1312. }
  1313. if (isKeyword(token, _tokenizer.keywords.func)) {
  1314. eatToken();
  1315. var _node2 = parseFunc();
  1316. var _endLoc4 = getEndLoc();
  1317. maybeIgnoreComment();
  1318. eatTokenOfType(_tokenizer.tokens.closeParen);
  1319. return t.withLoc(_node2, _endLoc4, startLoc);
  1320. }
  1321. if (isKeyword(token, _tokenizer.keywords.module)) {
  1322. eatToken();
  1323. var _node3 = parseModule();
  1324. var _endLoc5 = getEndLoc();
  1325. return t.withLoc(_node3, _endLoc5, startLoc);
  1326. }
  1327. if (isKeyword(token, _tokenizer.keywords.import)) {
  1328. eatToken();
  1329. var _node4 = parseImport();
  1330. var _endLoc6 = getEndLoc();
  1331. eatTokenOfType(_tokenizer.tokens.closeParen);
  1332. return t.withLoc(_node4, _endLoc6, startLoc);
  1333. }
  1334. if (isKeyword(token, _tokenizer.keywords.block)) {
  1335. eatToken();
  1336. var _node5 = parseBlock();
  1337. var _endLoc7 = getEndLoc();
  1338. eatTokenOfType(_tokenizer.tokens.closeParen);
  1339. return t.withLoc(_node5, _endLoc7, startLoc);
  1340. }
  1341. if (isKeyword(token, _tokenizer.keywords.memory)) {
  1342. eatToken();
  1343. var _node6 = parseMemory();
  1344. var _endLoc8 = getEndLoc();
  1345. eatTokenOfType(_tokenizer.tokens.closeParen);
  1346. return t.withLoc(_node6, _endLoc8, startLoc);
  1347. }
  1348. if (isKeyword(token, _tokenizer.keywords.data)) {
  1349. eatToken();
  1350. var _node7 = parseData();
  1351. var _endLoc9 = getEndLoc();
  1352. eatTokenOfType(_tokenizer.tokens.closeParen);
  1353. return t.withLoc(_node7, _endLoc9, startLoc);
  1354. }
  1355. if (isKeyword(token, _tokenizer.keywords.table)) {
  1356. eatToken();
  1357. var _node8 = parseTable();
  1358. var _endLoc10 = getEndLoc();
  1359. eatTokenOfType(_tokenizer.tokens.closeParen);
  1360. return t.withLoc(_node8, _endLoc10, startLoc);
  1361. }
  1362. if (isKeyword(token, _tokenizer.keywords.global)) {
  1363. eatToken();
  1364. var _node9 = parseGlobal();
  1365. var _endLoc11 = getEndLoc();
  1366. eatTokenOfType(_tokenizer.tokens.closeParen);
  1367. return t.withLoc(_node9, _endLoc11, startLoc);
  1368. }
  1369. if (isKeyword(token, _tokenizer.keywords.type)) {
  1370. eatToken();
  1371. var _node10 = parseType();
  1372. var _endLoc12 = getEndLoc();
  1373. eatTokenOfType(_tokenizer.tokens.closeParen);
  1374. return t.withLoc(_node10, _endLoc12, startLoc);
  1375. }
  1376. if (isKeyword(token, _tokenizer.keywords.start)) {
  1377. eatToken();
  1378. var _node11 = parseStart();
  1379. var _endLoc13 = getEndLoc();
  1380. eatTokenOfType(_tokenizer.tokens.closeParen);
  1381. return t.withLoc(_node11, _endLoc13, startLoc);
  1382. }
  1383. if (isKeyword(token, _tokenizer.keywords.elem)) {
  1384. eatToken();
  1385. var _node12 = parseElem();
  1386. var _endLoc14 = getEndLoc();
  1387. eatTokenOfType(_tokenizer.tokens.closeParen);
  1388. return t.withLoc(_node12, _endLoc14, startLoc);
  1389. }
  1390. var instruction = parseFuncInstr();
  1391. var endLoc = getEndLoc();
  1392. maybeIgnoreComment();
  1393. if (_typeof(instruction) === "object") {
  1394. if (typeof token !== "undefined") {
  1395. eatTokenOfType(_tokenizer.tokens.closeParen);
  1396. }
  1397. return t.withLoc(instruction, endLoc, startLoc);
  1398. }
  1399. }
  1400. if (token.type === _tokenizer.tokens.comment) {
  1401. var _startLoc = getStartLoc();
  1402. var builder = token.opts.type === "leading" ? t.leadingComment : t.blockComment;
  1403. var _node13 = builder(token.value);
  1404. eatToken(); // comment
  1405. var _endLoc15 = getEndLoc();
  1406. return t.withLoc(_node13, _endLoc15, _startLoc);
  1407. }
  1408. throw function () {
  1409. return new Error("\n" + (0, _helperCodeFrame.codeFrameFromSource)(source, token.loc) + "\n" + "Unknown token" + ", given " + tokenToString(token));
  1410. }();
  1411. }
  1412. var body = [];
  1413. while (current < tokensList.length) {
  1414. body.push(walk());
  1415. }
  1416. return t.program(body);
  1417. }