watr 1.3.0 → 1.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/package.json +1 -1
  2. package/watr.js +167 -122
  3. package/watr.min.js +1 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "watr",
3
- "version": "1.3.0",
3
+ "version": "1.3.2",
4
4
  "description": "Ligth & fast WAT compiler",
5
5
  "main": "watr.js",
6
6
  "type": "module",
package/watr.js CHANGED
@@ -143,11 +143,45 @@ ALIGN = {
143
143
 
144
144
  OP.map((op,i)=>OP[op]=i); // init op names
145
145
 
146
+ const OPAREN = 40, CPAREN = 41, SPACE = 32, DQUOTE = 34, SEMIC = 59;
147
+
148
+ var parse = (str) => {
149
+ let i = 0, level = [], buf = '';
150
+
151
+ const commit = () => buf && (
152
+ level.push(buf),
153
+ buf = ''
154
+ );
155
+
156
+ const parseLevel = () => {
157
+ for (let c, root; i < str.length;) {
158
+ c = str.charCodeAt(i);
159
+ if (c === DQUOTE) commit(), buf = str.slice(i++, i = str.indexOf('"', i) + 1), commit();
160
+ else if (c === OPAREN) {
161
+ if (str.charCodeAt(i + 1) === SEMIC) i = str.indexOf(';)', i) + 2; // (; ... ;)
162
+ else commit(), i++, (root = level).push(level = []), parseLevel(), level = root;
163
+ }
164
+ else if (c === SEMIC) i = str.indexOf('\n', i) + 1; // ; ...
165
+ else if (c <= SPACE) commit(), i++;
166
+ else if (c === CPAREN) return commit(), i++
167
+ else buf += str[i++];
168
+ }
169
+
170
+ commit();
171
+ };
172
+
173
+ parseLevel();
174
+
175
+ return level.length > 1 ? level : level[0]
176
+ };
177
+
146
178
  // some inlinable instructions
147
- const INLINE = {loop: 1, block: 1, if: 1, end: -1, return: -1};
179
+ const INLINE = { loop: 1, block: 1, if: 1, end: -1, return: -1 };
148
180
 
149
181
  // convert wat tree to wasm binary
150
182
  var compile = (nodes) => {
183
+ if (typeof nodes === 'string') nodes = parse(nodes);
184
+
151
185
  // IR. Alias is stored directly to section array by key, eg. section.func.$name = idx
152
186
  let sections = {
153
187
  type: [], import: [], func: [], table: [], memory: [], global: [], export: [], start: [], elem: [], code: [], data: []
@@ -163,11 +197,11 @@ var compile = (nodes) => {
163
197
  // (global $a (import "a" "b") (mut i32)) → (import "a" "b" (global $a (mut i32)))
164
198
  // (memory (import "a" "b") min max shared) → (import "a" "b" (memory min max shared))
165
199
  nodes = nodes.map(node => {
166
- if (node[2]?.[0]==='import') {
200
+ if (node[2]?.[0] === 'import') {
167
201
  let [kind, name, imp, ...args] = node;
168
202
  return [...imp, [kind, name, ...args]]
169
203
  }
170
- else if (node[1]?.[0]==='import') {
204
+ else if (node[1]?.[0] === 'import') {
171
205
  let [kind, imp, ...args] = node;
172
206
  return [...imp, [kind, ...args]]
173
207
  }
@@ -192,11 +226,11 @@ var compile = (nodes) => {
192
226
 
193
227
  // 3. build binary
194
228
  for (let name in sections) {
195
- let items=sections[name];
229
+ let items = sections[name];
196
230
  if (items.importc) items = items.slice(items.importc); // discard imported functions/globals
197
231
  if (!items.length) continue
198
232
  let sectionCode = SECTION[name], bytes = [];
199
- if (sectionCode!==8) bytes.push(items.length); // skip start section count
233
+ if (sectionCode !== 8) bytes.push(items.length); // skip start section count
200
234
  for (let item of items) bytes.push(...item);
201
235
  binary.push(sectionCode, ...uleb(bytes.length), ...bytes);
202
236
  }
@@ -209,10 +243,10 @@ const build = {
209
243
  // signature part is identical to function
210
244
  // FIXME: handle non-function types
211
245
  type([, typeName, decl], ctx) {
212
- if (typeName[0]!=='$') decl=typeName, typeName=null;
213
- let params = [], result = [], [kind,...sig] = decl, idx, bytes;
246
+ if (typeName[0] !== '$') decl = typeName, typeName = null;
247
+ let params = [], result = [], [kind, ...sig] = decl, idx, bytes;
214
248
 
215
- if (kind==='func') {
249
+ if (kind === 'func') {
216
250
  // collect params
217
251
  while (sig[0]?.[0] === 'param') {
218
252
  let [, ...types] = sig.shift();
@@ -227,7 +261,7 @@ const build = {
227
261
  bytes = [TYPE.func, ...uleb(params.length), ...params, ...uleb(result.length), ...result];
228
262
 
229
263
  idx = ctx.type.findIndex((prevType) => prevType.every((byte, i) => byte === bytes[i]));
230
- if (idx < 0) idx = ctx.type.push(bytes)-1;
264
+ if (idx < 0) idx = ctx.type.push(bytes) - 1;
231
265
  }
232
266
 
233
267
  if (typeName) ctx.type[typeName] = idx;
@@ -236,9 +270,9 @@ const build = {
236
270
  },
237
271
 
238
272
  // (func $name? ...params result ...body)
239
- func([,...body], ctx) {
240
- let locals=[], // list of local variables
241
- callstack=[];
273
+ func([, ...body], ctx) {
274
+ let locals = [], // list of local variables
275
+ callstack = [];
242
276
 
243
277
  // fn name
244
278
  if (body[0]?.[0] === '$') ctx.func[body.shift()] = ctx.func.length;
@@ -247,7 +281,7 @@ const build = {
247
281
  if (body[0]?.[0] === 'export') build.export([...body.shift(), ['func', ctx.func.length]], ctx);
248
282
 
249
283
  // register type
250
- let [typeIdx, params, result] = build.type([,['func',...body]], ctx);
284
+ let [typeIdx, params, result] = build.type([, ['func', ...body]], ctx);
251
285
  // FIXME: try merging with build.type: it should be able to consume body
252
286
  while (body[0]?.[0] === 'param' || body[0]?.[0] === 'result') body.shift();
253
287
  ctx.func.push([typeIdx]);
@@ -255,139 +289,139 @@ const build = {
255
289
  // collect locals
256
290
  while (body[0]?.[0] === 'local') {
257
291
  let [, ...types] = body.shift(), name;
258
- if (types[0][0]==='$')
259
- params[name=types.shift()] ? err('Ambiguous name '+name) :
260
- locals[name] = params.length + locals.length;
292
+ if (types[0][0] === '$')
293
+ params[name = types.shift()] ? err('Ambiguous name ' + name) :
294
+ locals[name] = params.length + locals.length;
261
295
  locals.push(...types.map(t => TYPE[t]));
262
296
  }
263
297
 
264
298
  // squash local types
265
- let locTypes = locals.reduce((a, type) => (type==a[a.length-1] ? a[a.length-2]++ : a.push(1,type), a), []);
299
+ let locTypes = locals.reduce((a, type) => (type == a[a.length - 1] ? a[a.length - 2]++ : a.push(1, type), a), []);
266
300
 
267
301
  // map code instruction into bytes: [args, opCode, immediates]
268
302
  const instr = (group) => {
269
303
  let [op, ...nodes] = group;
270
- let opCode = OP[op], argc=0, before=[], after=[], id;
304
+ let opCode = OP[op], argc = 0, before = [], after = [], id;
271
305
 
272
306
  // NOTE: we could reorganize ops by groups and detect signature as `op in STORE`
273
307
  // but numeric comparison is faster than generic hash lookup
274
308
  // FIXME: we often use OP.end or alike: what if we had list of global constants?
275
309
 
276
310
  // binary/unary
277
- if (opCode>=69) {
278
- argc = opCode>=167 ||
279
- (opCode<=159 && opCode>=153) ||
280
- (opCode<=145 && opCode>=139) ||
281
- (opCode<=123 && opCode>=121) ||
282
- (opCode<=105 && opCode>=103) ||
283
- opCode==80 || opCode==69 ? 1 : 2;
311
+ if (opCode >= 69) {
312
+ argc = opCode >= 167 ||
313
+ (opCode <= 159 && opCode >= 153) ||
314
+ (opCode <= 145 && opCode >= 139) ||
315
+ (opCode <= 123 && opCode >= 121) ||
316
+ (opCode <= 105 && opCode >= 103) ||
317
+ opCode == 80 || opCode == 69 ? 1 : 2;
284
318
  }
285
319
  // instruction
286
320
  else {
287
321
  // (i32.store align=n offset=m at value)
288
- if (opCode>=40&&opCode<=62) {
322
+ if (opCode >= 40 && opCode <= 62) {
289
323
  // FIXME: figure out point in Math.log2 aligns
290
- let o = {align: ALIGN[op], offset: 0}, p;
291
- while (nodes[0]?.[0] in o) p = nodes.shift(), o[p[0]] = +p[1];
324
+ let o = { align: ALIGN[op], offset: 0 }, p;
325
+ while (nodes[0]?.includes('=')) p = nodes.shift().split('='), o[p[0]] = Number(p[1]);
292
326
  after = [Math.log2(o.align), ...uleb(o.offset)];
293
327
  argc = opCode >= 54 ? 2 : 1;
294
328
  }
295
329
 
296
330
  // (i32.const 123)
297
- else if (opCode>=65&&opCode<=68) {
298
- after = (opCode==65?leb:opCode==66?bigleb:opCode==67?f32:f64)(nodes.shift());
331
+ else if (opCode >= 65 && opCode <= 68) {
332
+ after = (opCode == 65 ? leb : opCode == 66 ? bigleb : opCode == 67 ? f32 : f64)(nodes.shift());
299
333
  }
300
334
 
301
335
  // (local.get $id), (local.tee $id x)
302
- else if (opCode>=32&&opCode<=34) {
303
- after = uleb(nodes[0]?.[0]==='$' ? params[id=nodes.shift()] || locals[id] : nodes.shift());
304
- if (opCode>32) argc = 1;
336
+ else if (opCode >= 32 && opCode <= 34) {
337
+ after = uleb(nodes[0]?.[0] === '$' ? params[id = nodes.shift()] || locals[id] : nodes.shift());
338
+ if (opCode > 32) argc = 1;
305
339
  }
306
340
 
307
341
  // (global.get id), (global.set id)
308
- else if (opCode==35||opCode==36) {
309
- after = uleb(nodes[0]?.[0]==='$' ? ctx.global[nodes.shift()] : nodes.shift());
310
- if (opCode>35) argc = 1;
342
+ else if (opCode == 35 || opCode == 36) {
343
+ after = uleb(nodes[0]?.[0] === '$' ? ctx.global[nodes.shift()] : nodes.shift());
344
+ if (opCode > 35) argc = 1;
311
345
  }
312
346
 
313
347
  // (call id ...nodes)
314
- else if (opCode==16) {
348
+ else if (opCode == 16) {
315
349
  let fnName = nodes.shift();
316
- after = uleb(id = fnName[0]==='$' ? ctx.func[fnName] ?? err('Unknown function `' + fnName + '`') : fnName);
350
+ after = uleb(id = fnName[0] === '$' ? ctx.func[fnName] ?? err('Unknown function `' + fnName + '`') : fnName);
317
351
  // FIXME: how to get signature of imported function
318
- [,argc] = ctx.type[ctx.func[id][0]];
352
+ [, argc] = ctx.type[ctx.func[id][0]];
319
353
  }
320
354
 
321
355
  // (call_indirect (type $typeName) (idx) ...nodes)
322
- else if (opCode==17) {
356
+ else if (opCode == 17) {
323
357
  let typeId = nodes.shift()[1];
324
- [,argc] = ctx.type[typeId = typeId[0]==='$'?ctx.type[typeId]:typeId];
358
+ [, argc] = ctx.type[typeId = typeId[0] === '$' ? ctx.type[typeId] : typeId];
325
359
  argc++;
326
360
  after = uleb(typeId), after.push(0); // extra afterediate indicates table idx (reserved)
327
361
  }
328
362
 
329
363
  // FIXME (memory.grow $idx?)
330
- else if (opCode==63||opCode==64) {
364
+ else if (opCode == 63 || opCode == 64) {
331
365
  after = [0];
332
366
  argc = 1;
333
367
  }
334
368
 
335
369
  // (if (result i32)? (local.get 0) (then a b) (else a b)?)
336
- else if (opCode==4) {
370
+ else if (opCode == 4) {
337
371
  callstack.push(opCode);
338
- let [,type] = nodes[0][0]==='result' ? nodes.shift() : [,'void'];
339
- after=[TYPE[type]];
372
+ let [, type] = nodes[0][0] === 'result' ? nodes.shift() : [, 'void'];
373
+ after = [TYPE[type]];
340
374
 
341
375
  argc = 0, before.push(...instr(nodes.shift()));
342
376
  let body;
343
- if (nodes[0]?.[0]==='then') [,...body] = nodes.shift(); else body = nodes;
377
+ if (nodes[0]?.[0] === 'then') [, ...body] = nodes.shift(); else body = nodes;
344
378
  after.push(...consume(body));
345
379
 
346
380
  callstack.pop(), callstack.push(OP.else);
347
- if (nodes[0]?.[0]==='else') {
348
- [,...body] = nodes.shift();
349
- if (body.length) after.push(OP.else,...consume(body));
381
+ if (nodes[0]?.[0] === 'else') {
382
+ [, ...body] = nodes.shift();
383
+ if (body.length) after.push(OP.else, ...consume(body));
350
384
  }
351
385
  callstack.pop();
352
386
  after.push(OP.end);
353
387
  }
354
388
 
355
389
  // (drop arg?), (return arg?)
356
- else if (opCode==0x1a || opCode==0x0f) { argc = nodes.length?1:0; }
390
+ else if (opCode == 0x1a || opCode == 0x0f) { argc = nodes.length ? 1 : 0; }
357
391
 
358
392
  // (select a b cond)
359
- else if (opCode==0x1b) { argc = 3; }
393
+ else if (opCode == 0x1b) { argc = 3; }
360
394
 
361
395
  // (block ...), (loop ...)
362
- else if (opCode==2||opCode==3) {
396
+ else if (opCode == 2 || opCode == 3) {
363
397
  callstack.push(opCode);
364
- if (nodes[0]?.[0]==='$') (callstack[nodes.shift()] = callstack.length);
365
- let [,type] = nodes[0]?.[0]==='result' ? nodes.shift() : [,'void'];
366
- after=[TYPE[type], ...consume(nodes)];
398
+ if (nodes[0]?.[0] === '$') (callstack[nodes.shift()] = callstack.length);
399
+ let [, type] = nodes[0]?.[0] === 'result' ? nodes.shift() : [, 'void'];
400
+ after = [TYPE[type], ...consume(nodes)];
367
401
 
368
402
  if (!group.inline) callstack.pop(), after.push(OP.end); // inline loop/block expects end to be separately provided
369
403
  }
370
404
 
371
405
  // (end)
372
- else if (opCode==0x0b) callstack.pop();
406
+ else if (opCode == 0x0b) callstack.pop();
373
407
 
374
408
  // (br $label result?)
375
409
  // (br_if $label cond result?)
376
- else if (opCode==0x0c||opCode==0x0d) {
410
+ else if (opCode == 0x0c || opCode == 0x0d) {
377
411
  // br index indicates how many callstack items to pop
378
- after = uleb(nodes[0]?.[0]==='$' ? callstack.length-callstack[nodes.shift()] : nodes.shift());
379
- argc = (opCode==0x0d ? 1 + (nodes.length > 1) : !!nodes.length);
412
+ after = uleb(nodes[0]?.[0] === '$' ? callstack.length - callstack[nodes.shift()] : nodes.shift());
413
+ argc = (opCode == 0x0d ? 1 + (nodes.length > 1) : !!nodes.length);
380
414
  }
381
415
 
382
416
  // (br_table 1 2 3 4 0 selector result?)
383
- else if (opCode==0x0e) {
417
+ else if (opCode == 0x0e) {
384
418
  after = [];
385
- while (!Array.isArray(nodes[0])) id=nodes.shift(), after.push(...uleb(id[0][0]==='$'?callstack.length-callstack[id]:id));
386
- after.unshift(...uleb(after.length-1));
387
- argc = 1 + (nodes.length>1);
419
+ while (!Array.isArray(nodes[0])) id = nodes.shift(), after.push(...uleb(id[0][0] === '$' ? callstack.length - callstack[id] : id));
420
+ after.unshift(...uleb(after.length - 1));
421
+ argc = 1 + (nodes.length > 1);
388
422
  }
389
423
 
390
- else if (opCode==null) err(`Unknown instruction \`${op}\``);
424
+ else if (opCode == null) err(`Unknown instruction \`${op}\``);
391
425
  }
392
426
 
393
427
  // consume arguments
@@ -406,9 +440,9 @@ const build = {
406
440
 
407
441
  if (typeof node === 'string') {
408
442
  // permit some inline instructions: loop $label ... end, br $label, arg return
409
- if (c=INLINE[node]) {
443
+ if (c = INLINE[node]) {
410
444
  node = [node], node.inline = true;
411
- if (c>0) nodes[0]?.[0]==='$' && node.push(nodes.shift());
445
+ if (c > 0) nodes[0]?.[0] === '$' && node.push(nodes.shift());
412
446
  }
413
447
  else err(`Inline instruction \`${node}\` is not supported`);
414
448
  }
@@ -421,7 +455,7 @@ const build = {
421
455
  // evaluates after all definitions
422
456
  return () => {
423
457
  let code = consume(body);
424
- ctx.code.push([...uleb(code.length+2+locTypes.length), ...uleb(locTypes.length>>1), ...locTypes, ...code, OP.end]);
458
+ ctx.code.push([...uleb(code.length + 2 + locTypes.length), ...uleb(locTypes.length >> 1), ...locTypes, ...code, OP.end]);
425
459
  }
426
460
  },
427
461
 
@@ -429,7 +463,7 @@ const build = {
429
463
  // (memory $name min max shared)
430
464
  // (memory (export "mem") 5)
431
465
  memory([, ...parts], ctx) {
432
- if (parts[0][0]==='$') ctx.memory[parts.shift()] = ctx.memory.length;
466
+ if (parts[0][0] === '$') ctx.memory[parts.shift()] = ctx.memory.length;
433
467
  if (parts[0][0] === 'export') build.export([...parts.shift(), ['memory', ctx.memory.length]], ctx);
434
468
  ctx.memory.push(range(parts));
435
469
  },
@@ -438,7 +472,7 @@ const build = {
438
472
  // (global $id i32 (i32.const 42))
439
473
  // (global $id (mut i32) (i32.const 42))
440
474
  global([, ...args], ctx) {
441
- let name = args[0][0]==='$' && args.shift();
475
+ let name = args[0][0] === '$' && args.shift();
442
476
  if (name) ctx.global[name] = ctx.global.length;
443
477
  let [type, init] = args, mut = type[0] === 'mut' ? 1 : 0;
444
478
  ctx.global.push([TYPE[mut ? type[1] : type], mut, ...iinit(init)]);
@@ -447,7 +481,7 @@ const build = {
447
481
  // (table 1 2? funcref)
448
482
  // (table $name 1 2? funcref)
449
483
  table([, ...args], ctx) {
450
- let name = args[0][0]==='$' && args.shift();
484
+ let name = args[0][0] === '$' && args.shift();
451
485
  if (name) ctx.table[name] = ctx.table.length;
452
486
  let lims = range(args);
453
487
  ctx.table.push([TYPE[args.pop()], ...lims]);
@@ -456,12 +490,12 @@ const build = {
456
490
  // (elem (i32.const 0) $f1 $f2), (elem (global.get 0) $f1 $f2)
457
491
  elem([, offset, ...elems], ctx) {
458
492
  const tableIdx = 0; // FIXME: table index can be defined
459
- ctx.elem.push([tableIdx, ...iinit(offset, ctx), ...uleb(elems.length), ...elems.flatMap(el => uleb(el[0]==='$' ? ctx.func[el] : el))]);
493
+ ctx.elem.push([tableIdx, ...iinit(offset, ctx), ...uleb(elems.length), ...elems.flatMap(el => uleb(el[0] === '$' ? ctx.func[el] : el))]);
460
494
  },
461
495
 
462
496
  // (export "name" (kind $name|idx))
463
497
  export([, name, [kind, idx]], ctx) {
464
- if (idx[0]==='$') idx = ctx[kind][idx];
498
+ if (idx[0] === '$') idx = ctx[kind][idx];
465
499
  ctx.export.push([...str(name), KIND[kind], ...uleb(idx)]);
466
500
  },
467
501
 
@@ -471,26 +505,26 @@ const build = {
471
505
  // (import "js" "v" (global $name (mut f64)))
472
506
  import([, mod, field, ref], ctx) {
473
507
  let details, [kind, ...parts] = ref,
474
- name = parts[0]?.[0]==='$' && parts.shift();
508
+ name = parts[0]?.[0] === '$' && parts.shift();
475
509
 
476
- if (kind==='func') {
510
+ if (kind === 'func') {
477
511
  // we track imported funcs in func section to share namespace, and skip them on final build
478
512
  if (name) ctx.func[name] = ctx.func.length;
479
513
  let [typeIdx] = build.type([, ['func', ...parts]], ctx);
480
514
  ctx.func.push(details = uleb(typeIdx));
481
- ctx.func.importc = (ctx.func.importc||0)+1;
515
+ ctx.func.importc = (ctx.func.importc || 0) + 1;
482
516
  }
483
- else if (kind==='memory') {
517
+ else if (kind === 'memory') {
484
518
  if (name) ctx.memory[name] = ctx.memory.length;
485
519
  details = range(parts);
486
520
  }
487
- else if (kind==='global') {
521
+ else if (kind === 'global') {
488
522
  // imported globals share namespace with internal globals - we skip them in final build
489
523
  if (name) ctx.global[name] = ctx.global.length;
490
524
  let [type] = parts, mut = type[0] === 'mut' ? 1 : 0;
491
525
  details = [TYPE[mut ? type[1] : type], mut];
492
526
  ctx.global.push(details);
493
- ctx.global.importc = (ctx.global.importc||0)+1;
527
+ ctx.global.importc = (ctx.global.importc || 0) + 1;
494
528
  }
495
529
  else throw Error('Unimplemented ' + kind)
496
530
 
@@ -500,76 +534,87 @@ const build = {
500
534
  // (data (i32.const 0) "\aa" "\bb"?)
501
535
  data([, offset, ...inits], ctx) {
502
536
  // FIXME: first is mem index
503
- ctx.data.push([0, ...iinit(offset,ctx), ...str(inits.map(i=>i[0]==='"'?i.slice(1,-1):i).join(''))]);
537
+ ctx.data.push([0, ...iinit(offset, ctx), ...str(inits.map(i => i[0] === '"' ? i.slice(1, -1) : i).join(''))]);
504
538
  },
505
539
 
506
540
  // (start $main)
507
- start([, name],ctx) {
508
- if (!ctx.start.length) ctx.start.push([name[0]==='$' ? ctx.func[name] : name]);
541
+ start([, name], ctx) {
542
+ if (!ctx.start.length) ctx.start.push([name[0] === '$' ? ctx.func[name] : name]);
509
543
  }
510
544
  };
511
545
 
512
546
  // (i32.const 0) - instantiation time initializer
513
- const iinit = ([op, literal], ctx) => op[0]==='f' ?
514
- [OP[op], ...(op[1]==='3'?f32:f64)(literal), OP.end] :
515
- [OP[op], ...(op[1]==='3'?leb:bigleb)(literal[0] === '$' ? ctx.global[literal] : literal), OP.end];
547
+ const iinit = ([op, literal], ctx) => op[0] === 'f' ?
548
+ [OP[op], ...(op[1] === '3' ? f32 : f64)(literal), OP.end] :
549
+ [OP[op], ...(op[1] === '3' ? leb : bigleb)(literal[0] === '$' ? ctx.global[literal] : literal), OP.end];
516
550
 
517
- const escape = {n:10, r:13, t:9, v:1};
551
+ const escape = { n: 10, r: 13, t: 9, v: 1 };
518
552
 
519
553
  // build string binary
520
554
  const str = str => {
521
- str = str[0]==='"' ? str.slice(1,-1) : str;
522
- let res = [], i = 0, c, BSLASH=92;
555
+ str = str[0] === '"' ? str.slice(1, -1) : str;
556
+ let res = [], i = 0, c, BSLASH = 92;
523
557
  // spec https://webassembly.github.io/spec/core/text/values.html#strings
524
- for (;i < str.length;) {
525
- c=str.charCodeAt(i++);
526
- res.push(c===BSLASH ? escape[str[i++]] || parseInt(str.slice(i-1,++i), 16) : c);
558
+ for (; i < str.length;) {
559
+ c = str.charCodeAt(i++);
560
+ res.push(c === BSLASH ? escape[str[i++]] || parseInt(str.slice(i - 1, ++i), 16) : c);
527
561
  }
528
562
 
529
563
  res.unshift(...uleb(res.length));
530
564
  return res
531
565
  };
532
566
 
567
+
533
568
  // build range/limits sequence (non-consuming)
534
- const range = ([min, max, shared]) => isNaN(parseInt(max)) ? [0, ...uleb(min)] : [shared==='shared'?3:1, ...uleb(min), ...uleb(max)];
569
+ const range = ([min, max, shared]) => isNaN(parseInt(max)) ? [0, ...uleb(min)] : [shared === 'shared' ? 3 : 1, ...uleb(min), ...uleb(max)];
535
570
 
536
571
  const err = text => { throw Error(text) };
537
572
 
538
- const OPAREN=40, CPAREN=41, SPACE=32, DQUOTE=34, SEMIC=59;
573
+ let indent = '', newline = '\n', pad = '', comments = false;
539
574
 
540
- var parse = (str) => {
541
- let i = 0, level = [], buf='';
575
+ function print(tree, options = {}) {
576
+ if (typeof tree === 'string') tree = parse(tree);
542
577
 
543
- const commit = () => buf && (
544
- level.push(buf[0]!=='"' && ~buf.indexOf('=') ? buf.split('=') : buf),
545
- buf = ''
546
- );
578
+ ({ indent, newline, pad, comments } = options);
579
+ newline ||= '';
580
+ pad ||= '';
581
+ indent ||= '';
547
582
 
548
- const parseLevel = () => {
549
- for (let c, root; i < str.length; ) {
550
- c = str.charCodeAt(i);
551
- if (c === DQUOTE) commit(), buf = str.slice(i++, i=str.indexOf('"', i)+1), commit();
552
- else if (c === OPAREN) {
553
- if (str.charCodeAt(i+1) === SEMIC) i=str.indexOf(';)', i)+2; // (; ... ;)
554
- else commit(), i++, (root=level).push(level=[]), parseLevel(), level=root;
555
- }
556
- else if (c === SEMIC) i=str.indexOf('\n', i)+1; // ; ...
557
- else if (c <= SPACE) commit(), i++;
558
- else if (c === CPAREN) return commit(), i++
559
- else buf+=str[i++];
560
- }
583
+ let out = typeof tree[0] === 'string' ? printNode(tree) : tree.map(node => printNode(node)).join(newline);
561
584
 
562
- commit();
563
- };
564
-
565
- parseLevel();
585
+ return out
586
+ }
566
587
 
567
- return level.length>1 ? level : level[0]
568
- };
588
+ const flats = ['param', 'local', 'global', 'result', 'export'];
589
+
590
+ function printNode(node, level = 0) {
591
+ if (!Array.isArray(node)) return node + ''
592
+
593
+ let content = node[0];
594
+
595
+ for (let i = 1; i < node.length; i++) {
596
+ // new node doesn't need space separator, eg. [x,[y]] -> `x(y)`
597
+ if (Array.isArray(node[i])) {
598
+ // inline nodes like (param x)(param y)
599
+ // (func (export "xxx")..., but not (func (export "a")(param "b")...
600
+ if (
601
+ flats.includes(node[i][0]) &&
602
+ (!Array.isArray(node[i - 1]) || node[i][0] === node[i - 1][0])
603
+ ) {
604
+ if (!Array.isArray(node[i - 1])) content += ` `;
605
+ } else {
606
+ content += newline;
607
+ if (node[i]) content += indent.repeat(level + 1);
608
+ }
569
609
 
570
- var watr = src => (
571
- src = typeof src === 'string' ? parse(src) : src,
572
- compile(src)
573
- );
610
+ content += printNode(node[i], level + 1);
611
+ }
612
+ else {
613
+ content += ` `;
614
+ content += node[i];
615
+ }
616
+ }
617
+ return `(${content})`
618
+ }
574
619
 
575
- export { compile, watr as default, parse };
620
+ export { compile, compile as default, parse, print };
package/watr.min.js CHANGED
@@ -1 +1 @@
1
- const e=(t,i=[])=>{"string"==typeof t&&(t=parseInt(t.replaceAll("_","")));let l=127&t;return 0==(t>>>=7)?(i.push(l),i):(i.push(128|l),e(t,i))};function t(e,t=[]){for("string"==typeof e&&(e=parseInt(e.replaceAll("_","")));;){const i=Number(127&e);if(0==(e>>=7)&&0==(64&i)||-1===e&&0!=(64&i)){t.push(i);break}t.push(128|i)}return t}function i(e,t=[]){for("string"==typeof e&&(e="-"===(e=e.replaceAll("_",""))[0]?-BigInt(e.slice(1)):BigInt(e),n.setBigInt64(0,e),e=n.getBigInt64(0));;){const i=Number(0x7Fn&e);if(0n===(e>>=7n)&&0==(64&i)||-1n===e&&0!=(64&i)){t.push(i);break}t.push(128|i)}return t}const l=e=>"nan"===e||"+nan"===e||"-nan"===e?NaN:"inf"===e||"+inf"===e?1/0:"-inf"===e?-1/0:parseFloat(e.replaceAll("_","")),n=new DataView(new BigInt64Array(1).buffer);function s(e,t,i){return~(i=e.indexOf("nan:"))?(t=parseInt(e.slice(i+4)),t|=2139095040,"-"===e[0]&&(t|=2147483648),n.setInt32(0,t)):(t="string"==typeof e?l(e):e,n.setFloat32(0,t)),[n.getUint8(3),n.getUint8(2),n.getUint8(1),n.getUint8(0)]}const r=0x8000000000000000n,o=0x7ff0000000000000n;function f(e,t,i){return~(i=e.indexOf("nan:"))?(t=BigInt(e.slice(i+4)),t|=o,"-"===e[0]&&(t|=r),n.setBigInt64(0,t)):(t="string"==typeof e?l(e):e,n.setFloat64(0,t)),[n.getUint8(7),n.getUint8(6),n.getUint8(5),n.getUint8(4),n.getUint8(3),n.getUint8(2),n.getUint8(1),n.getUint8(0)]}const u=["unreachable","nop","block","loop","if","else",,,,,,"end","br","br_if","br_table","return","call","call_indirect",,,,,,,,,"drop","select",,,,,"local.get","local.set","local.tee","global.get","global.set",,,,"i32.load","i64.load","f32.load","f64.load","i32.load8_s","i32.load8_u","i32.load16_s","i32.load16_u","i64.load8_s","i64.load8_u","i64.load16_s","i64.load16_u","i64.load32_s","i64.load32_u","i32.store","i64.store","f32.store","f64.store","i32.store8","i32.store16","i64.store8","i64.store16","i64.store32","memory.size","memory.grow","i32.const","i64.const","f32.const","f64.const","i32.eqz","i32.eq","i32.ne","i32.lt_s","i32.lt_u","i32.gt_s","i32.gt_u","i32.le_s","i32.le_u","i32.ge_s","i32.ge_u","i64.eqz","i64.eq","i64.ne","i64.lt_s","i64.lt_u","i64.gt_s","i64.gt_u","i64.le_s","i64.le_u","i64.ge_s","i64.ge_u","f32.eq","f32.ne","f32.lt","f32.gt","f32.le","f32.ge","f64.eq","f64.ne","f64.lt","f64.gt","f64.le","f64.ge","i32.clz","i32.ctz","i32.popcnt","i32.add","i32.sub","i32.mul","i32.div_s","i32.div_u","i32.rem_s","i32.rem_u","i32.and","i32.or","i32.xor","i32.shl","i32.shr_s","i32.shr_u","i32.rotl","i32.rotr","i64.clz","i64.ctz","i64.popcnt","i64.add","i64.sub","i64.mul","i64.div_s","i64.div_u","i64.rem_s","i64.rem_u","i64.and","i64.or","i64.xor","i64.shl","i64.shr_s","i64.shr_u","i64.rotl","i64.rotr","f32.abs","f32.neg","f32.ceil","f32.floor","f32.trunc","f32.nearest","f32.sqrt","f32.add","f32.sub","f32.mul","f32.div","f32.min","f32.max","f32.copysign","f64.abs","f64.neg","f64.ceil","f64.floor","f64.trunc","f64.nearest","f64.sqrt","f64.add","f64.sub","f64.mul","f64.div","f64.min","f64.max","f64.copysign","i32.wrap_i64","i32.trunc_f32_s","i32.trunc_f32_u","i32.trunc_f64_s","i32.trunc_f64_u","i64.extend_i32_s","i64.extend_i32_u","i64.trunc_f32_s","i64.trunc_f32_u","i64.trunc_f64_s","i64.trunc_f64_u","f32.convert_i32_s","f32.convert_i32_u","f32.convert_i64_s","f32.convert_i64_u","f32.demote_f64","f64.convert_i32_s","f64.convert_i32_u","f64.convert_i64_s","f64.convert_i64_u","f64.promote_f32","i32.reinterpret_f32","i64.reinterpret_f64","f32.reinterpret_i32","f64.reinterpret_i64"],a={type:1,import:2,func:3,table:4,memory:5,global:6,export:7,start:8,elem:9,code:10,data:11},p={i32:127,i64:126,f32:125,f64:124,void:64,func:96,funcref:112},h={func:0,table:1,memory:2,global:3},c={"i32.load":4,"i64.load":8,"f32.load":4,"f64.load":8,"i32.load8_s":1,"i32.load8_u":1,"i32.load16_s":2,"i32.load16_u":2,"i64.load8_s":1,"i64.load8_u":1,"i64.load16_s":2,"i64.load16_u":2,"i64.load32_s":4,"i64.load32_u":4,"i32.store":4,"i64.store":8,"f32.store":4,"f64.store":8,"i32.store8":1,"i32.store16":2,"i64.store8":1,"i64.store16":2,"i64.store32":4};u.map(((e,t)=>u[e]=t));const g={loop:1,block:1,if:1,end:-1,return:-1};var _=t=>{let i={type:[],import:[],func:[],table:[],memory:[],global:[],export:[],start:[],elem:[],code:[],data:[]},l=[0,97,115,109,1,0,0,0];"string"==typeof t[0]&&"module"!==t[0]&&(t=[t]),t=t.map((e=>{if("import"===e[2]?.[0]){let[t,i,l,...n]=e;return[...l,[t,i,...n]]}if("import"===e[1]?.[0]){let[t,i,...l]=e;return[...i,[t,...l]]}return e}));let n=["type","import","table","memory","global","func","export","start","elem","data"],s=[];for(let e of n){let l=[];for(let n of t)n[0]===e?s.push(d[e](n,i)):l.push(n);t=l}for(let e of s)e&&e.call&&e();for(let t in i){let n=i[t];if(n.importc&&(n=n.slice(n.importc)),!n.length)continue;let s=a[t],r=[];8!==s&&r.push(n.length);for(let e of n)r.push(...e);l.push(s,...e(r.length),...r)}return new Uint8Array(l)};const d={type([,t,i],l){"$"!==t[0]&&(i=t,t=null);let n,s,r=[],o=[],[f,...u]=i;if("func"===f){for(;"param"===u[0]?.[0];){let[,...e]=u.shift();"$"===e[0]?.[0]&&(r[e.shift()]=r.length),r.push(...e.map((e=>p[e])))}"result"===u[0]?.[0]&&(o=u.shift().slice(1).map((e=>p[e]))),s=[p.func,...e(r.length),...r,...e(o.length),...o],n=l.type.findIndex((e=>e.every(((e,t)=>e===s[t])))),n<0&&(n=l.type.push(s)-1)}return t&&(l.type[t]=n),[n,r,o]},func([,...l],n){let r=[],o=[];"$"===l[0]?.[0]&&(n.func[l.shift()]=n.func.length),"export"===l[0]?.[0]&&d.export([...l.shift(),["func",n.func.length]],n);let[a,h,_]=d.type([,["func",...l]],n);for(;"param"===l[0]?.[0]||"result"===l[0]?.[0];)l.shift();for(n.func.push([a]);"local"===l[0]?.[0];){let e,[,...t]=l.shift();"$"===t[0][0]&&(h[e=t.shift()]?$("Ambiguous name "+e):r[e]=h.length+r.length),r.push(...t.map((e=>p[e])))}let m=r.reduce(((e,t)=>(t==e[e.length-1]?e[e.length-2]++:e.push(1,t),e)),[]);const b=l=>{let a,[g,..._]=l,d=u[g],m=0,x=[],v=[];if(d>=69)m=d>=167||d<=159&&d>=153||d<=145&&d>=139||d<=123&&d>=121||d<=105&&d>=103||80==d||69==d?1:2;else if(d>=40&&d<=62){let t,i={align:c[g],offset:0};for(;_[0]?.[0]in i;)t=_.shift(),i[t[0]]=+t[1];v=[Math.log2(i.align),...e(i.offset)],m=d>=54?2:1}else if(d>=65&&d<=68)v=(65==d?t:66==d?i:67==d?s:f)(_.shift());else if(d>=32&&d<=34)v=e("$"===_[0]?.[0]?h[a=_.shift()]||r[a]:_.shift()),d>32&&(m=1);else if(35==d||36==d)v=e("$"===_[0]?.[0]?n.global[_.shift()]:_.shift()),d>35&&(m=1);else if(16==d){let t=_.shift();v=e(a="$"===t[0]?n.func[t]??$("Unknown function `"+t+"`"):t),[,m]=n.type[n.func[a][0]]}else if(17==d){let t=_.shift()[1];[,m]=n.type[t="$"===t[0]?n.type[t]:t],m++,v=e(t),v.push(0)}else if(63==d||64==d)v=[0],m=1;else if(4==d){o.push(d);let e,[,t]="result"===_[0][0]?_.shift():[,"void"];v=[p[t]],m=0,x.push(...b(_.shift())),"then"===_[0]?.[0]?[,...e]=_.shift():e=_,v.push(...y(e)),o.pop(),o.push(u.else),"else"===_[0]?.[0]&&([,...e]=_.shift(),e.length&&v.push(u.else,...y(e))),o.pop(),v.push(u.end)}else if(26==d||15==d)m=_.length?1:0;else if(27==d)m=3;else if(2==d||3==d){o.push(d),"$"===_[0]?.[0]&&(o[_.shift()]=o.length);let[,e]="result"===_[0]?.[0]?_.shift():[,"void"];v=[p[e],...y(_)],l.inline||(o.pop(),v.push(u.end))}else if(11==d)o.pop();else if(12==d||13==d)v=e("$"===_[0]?.[0]?o.length-o[_.shift()]:_.shift()),m=13==d?1+(_.length>1):!!_.length;else if(14==d){for(v=[];!Array.isArray(_[0]);)a=_.shift(),v.push(...e("$"===a[0][0]?o.length-o[a]:a));v.unshift(...e(v.length-1)),m=1+(_.length>1)}else null==d&&$(`Unknown instruction \`${g}\``);for(_.length<m&&$(`Stack arguments are not supported at \`${g}\``);m--;)x.push(...b(_.shift()));return _.length&&$(`Too many arguments for \`${g}\`.`),[...x,d,...v]},y=e=>{let t=[];for(;e.length;){let i,l=e.shift();"string"==typeof l&&((i=g[l])?(l=[l],l.inline=!0,i>0&&"$"===e[0]?.[0]&&l.push(e.shift())):$(`Inline instruction \`${l}\` is not supported`)),l&&t.push(...b(l))}return t};return()=>{let t=y(l);n.code.push([...e(t.length+2+m.length),...e(m.length>>1),...m,...t,u.end])}},memory([,...e],t){"$"===e[0][0]&&(t.memory[e.shift()]=t.memory.length),"export"===e[0][0]&&d.export([...e.shift(),["memory",t.memory.length]],t),t.memory.push(x(e))},global([,...e],t){let i="$"===e[0][0]&&e.shift();i&&(t.global[i]=t.global.length);let[l,n]=e,s="mut"===l[0]?1:0;t.global.push([p[s?l[1]:l],s,...m(n)])},table([,...e],t){let i="$"===e[0][0]&&e.shift();i&&(t.table[i]=t.table.length);let l=x(e);t.table.push([p[e.pop()],...l])},elem([,t,...i],l){l.elem.push([0,...m(t,l),...e(i.length),...i.flatMap((t=>e("$"===t[0]?l.func[t]:t)))])},export([,t,[i,l]],n){"$"===l[0]&&(l=n[i][l]),n.export.push([...y(t),h[i],...e(l)])},import([,t,i,l],n){let s,[r,...o]=l,f="$"===o[0]?.[0]&&o.shift();if("func"===r){f&&(n.func[f]=n.func.length);let[t]=d.type([,["func",...o]],n);n.func.push(s=e(t)),n.func.importc=(n.func.importc||0)+1}else if("memory"===r)f&&(n.memory[f]=n.memory.length),s=x(o);else{if("global"!==r)throw Error("Unimplemented "+r);{f&&(n.global[f]=n.global.length);let[e]=o,t="mut"===e[0]?1:0;s=[p[t?e[1]:e],t],n.global.push(s),n.global.importc=(n.global.importc||0)+1}}n.import.push([...y(t),...y(i),h[r],...s])},data([,e,...t],i){i.data.push([0,...m(e,i),...y(t.map((e=>'"'===e[0]?e.slice(1,-1):e)).join(""))])},start([,e],t){t.start.length||t.start.push(["$"===e[0]?t.func[e]:e])}},m=([e,l],n)=>"f"===e[0]?[u[e],...("3"===e[1]?s:f)(l),u.end]:[u[e],...("3"===e[1]?t:i)("$"===l[0]?n.global[l]:l),u.end],b={n:10,r:13,t:9,v:1},y=t=>{t='"'===t[0]?t.slice(1,-1):t;let i,l=[],n=0;for(;n<t.length;)i=t.charCodeAt(n++),l.push(92===i?b[t[n++]]||parseInt(t.slice(n-1,++n),16):i);return l.unshift(...e(l.length)),l},x=([t,i,l])=>isNaN(parseInt(i))?[0,...e(t)]:["shared"===l?3:1,...e(t),...e(i)],$=e=>{throw Error(e)};var v=e=>{let t=0,i=[],l="";const n=()=>l&&(i.push('"'!==l[0]&&~l.indexOf("=")?l.split("="):l),l=""),s=()=>{for(let r,o;t<e.length;)if(r=e.charCodeAt(t),34===r)n(),l=e.slice(t++,t=e.indexOf('"',t)+1),n();else if(40===r)59===e.charCodeAt(t+1)?t=e.indexOf(";)",t)+2:(n(),t++,(o=i).push(i=[]),s(),i=o);else if(59===r)t=e.indexOf("\n",t)+1;else if(r<=32)n(),t++;else{if(41===r)return n(),t++;l+=e[t++]}n()};return s(),i.length>1?i:i[0]},U=e=>(e="string"==typeof e?v(e):e,_(e));export{_ as compile,U as default,v as parse};
1
+ const e=(t,i=[])=>{"string"==typeof t&&(t=parseInt(t.replaceAll("_","")));let l=127&t;return 0==(t>>>=7)?(i.push(l),i):(i.push(128|l),e(t,i))};function t(e,t=[]){for("string"==typeof e&&(e=parseInt(e.replaceAll("_","")));;){const i=Number(127&e);if(0==(e>>=7)&&0==(64&i)||-1===e&&0!=(64&i)){t.push(i);break}t.push(128|i)}return t}function i(e,t=[]){for("string"==typeof e&&(e="-"===(e=e.replaceAll("_",""))[0]?-BigInt(e.slice(1)):BigInt(e),n.setBigInt64(0,e),e=n.getBigInt64(0));;){const i=Number(0x7Fn&e);if(0n===(e>>=7n)&&0==(64&i)||-1n===e&&0!=(64&i)){t.push(i);break}t.push(128|i)}return t}const l=e=>"nan"===e||"+nan"===e||"-nan"===e?NaN:"inf"===e||"+inf"===e?1/0:"-inf"===e?-1/0:parseFloat(e.replaceAll("_","")),n=new DataView(new BigInt64Array(1).buffer);function r(e,t,i){return~(i=e.indexOf("nan:"))?(t=parseInt(e.slice(i+4)),t|=2139095040,"-"===e[0]&&(t|=2147483648),n.setInt32(0,t)):(t="string"==typeof e?l(e):e,n.setFloat32(0,t)),[n.getUint8(3),n.getUint8(2),n.getUint8(1),n.getUint8(0)]}const s=0x8000000000000000n,o=0x7ff0000000000000n;function f(e,t,i){return~(i=e.indexOf("nan:"))?(t=BigInt(e.slice(i+4)),t|=o,"-"===e[0]&&(t|=s),n.setBigInt64(0,t)):(t="string"==typeof e?l(e):e,n.setFloat64(0,t)),[n.getUint8(7),n.getUint8(6),n.getUint8(5),n.getUint8(4),n.getUint8(3),n.getUint8(2),n.getUint8(1),n.getUint8(0)]}const u=["unreachable","nop","block","loop","if","else",,,,,,"end","br","br_if","br_table","return","call","call_indirect",,,,,,,,,"drop","select",,,,,"local.get","local.set","local.tee","global.get","global.set",,,,"i32.load","i64.load","f32.load","f64.load","i32.load8_s","i32.load8_u","i32.load16_s","i32.load16_u","i64.load8_s","i64.load8_u","i64.load16_s","i64.load16_u","i64.load32_s","i64.load32_u","i32.store","i64.store","f32.store","f64.store","i32.store8","i32.store16","i64.store8","i64.store16","i64.store32","memory.size","memory.grow","i32.const","i64.const","f32.const","f64.const","i32.eqz","i32.eq","i32.ne","i32.lt_s","i32.lt_u","i32.gt_s","i32.gt_u","i32.le_s","i32.le_u","i32.ge_s","i32.ge_u","i64.eqz","i64.eq","i64.ne","i64.lt_s","i64.lt_u","i64.gt_s","i64.gt_u","i64.le_s","i64.le_u","i64.ge_s","i64.ge_u","f32.eq","f32.ne","f32.lt","f32.gt","f32.le","f32.ge","f64.eq","f64.ne","f64.lt","f64.gt","f64.le","f64.ge","i32.clz","i32.ctz","i32.popcnt","i32.add","i32.sub","i32.mul","i32.div_s","i32.div_u","i32.rem_s","i32.rem_u","i32.and","i32.or","i32.xor","i32.shl","i32.shr_s","i32.shr_u","i32.rotl","i32.rotr","i64.clz","i64.ctz","i64.popcnt","i64.add","i64.sub","i64.mul","i64.div_s","i64.div_u","i64.rem_s","i64.rem_u","i64.and","i64.or","i64.xor","i64.shl","i64.shr_s","i64.shr_u","i64.rotl","i64.rotr","f32.abs","f32.neg","f32.ceil","f32.floor","f32.trunc","f32.nearest","f32.sqrt","f32.add","f32.sub","f32.mul","f32.div","f32.min","f32.max","f32.copysign","f64.abs","f64.neg","f64.ceil","f64.floor","f64.trunc","f64.nearest","f64.sqrt","f64.add","f64.sub","f64.mul","f64.div","f64.min","f64.max","f64.copysign","i32.wrap_i64","i32.trunc_f32_s","i32.trunc_f32_u","i32.trunc_f64_s","i32.trunc_f64_u","i64.extend_i32_s","i64.extend_i32_u","i64.trunc_f32_s","i64.trunc_f32_u","i64.trunc_f64_s","i64.trunc_f64_u","f32.convert_i32_s","f32.convert_i32_u","f32.convert_i64_s","f32.convert_i64_u","f32.demote_f64","f64.convert_i32_s","f64.convert_i32_u","f64.convert_i64_s","f64.convert_i64_u","f64.promote_f32","i32.reinterpret_f32","i64.reinterpret_f64","f32.reinterpret_i32","f64.reinterpret_i64"],a={type:1,import:2,func:3,table:4,memory:5,global:6,export:7,start:8,elem:9,code:10,data:11},p={i32:127,i64:126,f32:125,f64:124,void:64,func:96,funcref:112},h={func:0,table:1,memory:2,global:3},c={"i32.load":4,"i64.load":8,"f32.load":4,"f64.load":8,"i32.load8_s":1,"i32.load8_u":1,"i32.load16_s":2,"i32.load16_u":2,"i64.load8_s":1,"i64.load8_u":1,"i64.load16_s":2,"i64.load16_u":2,"i64.load32_s":4,"i64.load32_u":4,"i32.store":4,"i64.store":8,"f32.store":4,"f64.store":8,"i32.store8":1,"i32.store16":2,"i64.store8":1,"i64.store16":2,"i64.store32":4};u.map(((e,t)=>u[e]=t));var g=e=>{let t=0,i=[],l="";const n=()=>l&&(i.push(l),l=""),r=()=>{for(let s,o;t<e.length;)if(s=e.charCodeAt(t),34===s)n(),l=e.slice(t++,t=e.indexOf('"',t)+1),n();else if(40===s)59===e.charCodeAt(t+1)?t=e.indexOf(";)",t)+2:(n(),t++,(o=i).push(i=[]),r(),i=o);else if(59===s)t=e.indexOf("\n",t)+1;else if(s<=32)n(),t++;else{if(41===s)return n(),t++;l+=e[t++]}n()};return r(),i.length>1?i:i[0]};const _={loop:1,block:1,if:1,end:-1,return:-1};var d=t=>{"string"==typeof t&&(t=g(t));let i={type:[],import:[],func:[],table:[],memory:[],global:[],export:[],start:[],elem:[],code:[],data:[]},l=[0,97,115,109,1,0,0,0];"string"==typeof t[0]&&"module"!==t[0]&&(t=[t]),t=t.map((e=>{if("import"===e[2]?.[0]){let[t,i,l,...n]=e;return[...l,[t,i,...n]]}if("import"===e[1]?.[0]){let[t,i,...l]=e;return[...i,[t,...l]]}return e}));let n=["type","import","table","memory","global","func","export","start","elem","data"],r=[];for(let e of n){let l=[];for(let n of t)n[0]===e?r.push(m[e](n,i)):l.push(n);t=l}for(let e of r)e&&e.call&&e();for(let t in i){let n=i[t];if(n.importc&&(n=n.slice(n.importc)),!n.length)continue;let r=a[t],s=[];8!==r&&s.push(n.length);for(let e of n)s.push(...e);l.push(r,...e(s.length),...s)}return new Uint8Array(l)};const m={type([,t,i],l){"$"!==t[0]&&(i=t,t=null);let n,r,s=[],o=[],[f,...u]=i;if("func"===f){for(;"param"===u[0]?.[0];){let[,...e]=u.shift();"$"===e[0]?.[0]&&(s[e.shift()]=s.length),s.push(...e.map((e=>p[e])))}"result"===u[0]?.[0]&&(o=u.shift().slice(1).map((e=>p[e]))),r=[p.func,...e(s.length),...s,...e(o.length),...o],n=l.type.findIndex((e=>e.every(((e,t)=>e===r[t])))),n<0&&(n=l.type.push(r)-1)}return t&&(l.type[t]=n),[n,s,o]},func([,...l],n){let s=[],o=[];"$"===l[0]?.[0]&&(n.func[l.shift()]=n.func.length),"export"===l[0]?.[0]&&m.export([...l.shift(),["func",n.func.length]],n);let[a,h,g]=m.type([,["func",...l]],n);for(;"param"===l[0]?.[0]||"result"===l[0]?.[0];)l.shift();for(n.func.push([a]);"local"===l[0]?.[0];){let e,[,...t]=l.shift();"$"===t[0][0]&&(h[e=t.shift()]?v("Ambiguous name "+e):s[e]=h.length+s.length),s.push(...t.map((e=>p[e])))}let d=s.reduce(((e,t)=>(t==e[e.length-1]?e[e.length-2]++:e.push(1,t),e)),[]);const y=l=>{let a,[g,..._]=l,d=u[g],m=0,x=[],$=[];if(d>=69)m=d>=167||d<=159&&d>=153||d<=145&&d>=139||d<=123&&d>=121||d<=105&&d>=103||80==d||69==d?1:2;else if(d>=40&&d<=62){let t,i={align:c[g],offset:0};for(;_[0]?.includes("=");)t=_.shift().split("="),i[t[0]]=Number(t[1]);$=[Math.log2(i.align),...e(i.offset)],m=d>=54?2:1}else if(d>=65&&d<=68)$=(65==d?t:66==d?i:67==d?r:f)(_.shift());else if(d>=32&&d<=34)$=e("$"===_[0]?.[0]?h[a=_.shift()]||s[a]:_.shift()),d>32&&(m=1);else if(35==d||36==d)$=e("$"===_[0]?.[0]?n.global[_.shift()]:_.shift()),d>35&&(m=1);else if(16==d){let t=_.shift();$=e(a="$"===t[0]?n.func[t]??v("Unknown function `"+t+"`"):t),[,m]=n.type[n.func[a][0]]}else if(17==d){let t=_.shift()[1];[,m]=n.type[t="$"===t[0]?n.type[t]:t],m++,$=e(t),$.push(0)}else if(63==d||64==d)$=[0],m=1;else if(4==d){o.push(d);let e,[,t]="result"===_[0][0]?_.shift():[,"void"];$=[p[t]],m=0,x.push(...y(_.shift())),"then"===_[0]?.[0]?[,...e]=_.shift():e=_,$.push(...b(e)),o.pop(),o.push(u.else),"else"===_[0]?.[0]&&([,...e]=_.shift(),e.length&&$.push(u.else,...b(e))),o.pop(),$.push(u.end)}else if(26==d||15==d)m=_.length?1:0;else if(27==d)m=3;else if(2==d||3==d){o.push(d),"$"===_[0]?.[0]&&(o[_.shift()]=o.length);let[,e]="result"===_[0]?.[0]?_.shift():[,"void"];$=[p[e],...b(_)],l.inline||(o.pop(),$.push(u.end))}else if(11==d)o.pop();else if(12==d||13==d)$=e("$"===_[0]?.[0]?o.length-o[_.shift()]:_.shift()),m=13==d?1+(_.length>1):!!_.length;else if(14==d){for($=[];!Array.isArray(_[0]);)a=_.shift(),$.push(...e("$"===a[0][0]?o.length-o[a]:a));$.unshift(...e($.length-1)),m=1+(_.length>1)}else null==d&&v(`Unknown instruction \`${g}\``);for(_.length<m&&v(`Stack arguments are not supported at \`${g}\``);m--;)x.push(...y(_.shift()));return _.length&&v(`Too many arguments for \`${g}\`.`),[...x,d,...$]},b=e=>{let t=[];for(;e.length;){let i,l=e.shift();"string"==typeof l&&((i=_[l])?(l=[l],l.inline=!0,i>0&&"$"===e[0]?.[0]&&l.push(e.shift())):v(`Inline instruction \`${l}\` is not supported`)),l&&t.push(...y(l))}return t};return()=>{let t=b(l);n.code.push([...e(t.length+2+d.length),...e(d.length>>1),...d,...t,u.end])}},memory([,...e],t){"$"===e[0][0]&&(t.memory[e.shift()]=t.memory.length),"export"===e[0][0]&&m.export([...e.shift(),["memory",t.memory.length]],t),t.memory.push($(e))},global([,...e],t){let i="$"===e[0][0]&&e.shift();i&&(t.global[i]=t.global.length);let[l,n]=e,r="mut"===l[0]?1:0;t.global.push([p[r?l[1]:l],r,...y(n)])},table([,...e],t){let i="$"===e[0][0]&&e.shift();i&&(t.table[i]=t.table.length);let l=$(e);t.table.push([p[e.pop()],...l])},elem([,t,...i],l){l.elem.push([0,...y(t,l),...e(i.length),...i.flatMap((t=>e("$"===t[0]?l.func[t]:t)))])},export([,t,[i,l]],n){"$"===l[0]&&(l=n[i][l]),n.export.push([...x(t),h[i],...e(l)])},import([,t,i,l],n){let r,[s,...o]=l,f="$"===o[0]?.[0]&&o.shift();if("func"===s){f&&(n.func[f]=n.func.length);let[t]=m.type([,["func",...o]],n);n.func.push(r=e(t)),n.func.importc=(n.func.importc||0)+1}else if("memory"===s)f&&(n.memory[f]=n.memory.length),r=$(o);else{if("global"!==s)throw Error("Unimplemented "+s);{f&&(n.global[f]=n.global.length);let[e]=o,t="mut"===e[0]?1:0;r=[p[t?e[1]:e],t],n.global.push(r),n.global.importc=(n.global.importc||0)+1}}n.import.push([...x(t),...x(i),h[s],...r])},data([,e,...t],i){i.data.push([0,...y(e,i),...x(t.map((e=>'"'===e[0]?e.slice(1,-1):e)).join(""))])},start([,e],t){t.start.length||t.start.push(["$"===e[0]?t.func[e]:e])}},y=([e,l],n)=>"f"===e[0]?[u[e],...("3"===e[1]?r:f)(l),u.end]:[u[e],...("3"===e[1]?t:i)("$"===l[0]?n.global[l]:l),u.end],b={n:10,r:13,t:9,v:1},x=t=>{t='"'===t[0]?t.slice(1,-1):t;let i,l=[],n=0;for(;n<t.length;)i=t.charCodeAt(n++),l.push(92===i?b[t[n++]]||parseInt(t.slice(n-1,++n),16):i);return l.unshift(...e(l.length)),l},$=([t,i,l])=>isNaN(parseInt(i))?[0,...e(t)]:["shared"===l?3:1,...e(t),...e(i)],v=e=>{throw Error(e)};let A="",U="\n",I="",w=!1;function q(e,t={}){return"string"==typeof e&&(e=g(e)),({indent:A,newline:U,pad:I,comments:w}=t),U||="",I||="",A||="","string"==typeof e[0]?z(e):e.map((e=>z(e))).join(U)}const k=["param","local","global","result","export"];function z(e,t=0){if(!Array.isArray(e))return e+"";let i=e[0];for(let l=1;l<e.length;l++)Array.isArray(e[l])?(!k.includes(e[l][0])||Array.isArray(e[l-1])&&e[l][0]!==e[l-1][0]?(i+=U,e[l]&&(i+=A.repeat(t+1))):Array.isArray(e[l-1])||(i+=" "),i+=z(e[l],t+1)):(i+=" ",i+=e[l]);return`(${i})`}export{d as compile,d as default,g as parse,q as print};