porffor 0.2.0-c7b7423 → 0.2.0-dcc06c8

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.
@@ -2,6 +2,7 @@ import { Opcodes, Blocktype, Valtype, ValtypeSize, PageSize } from "./wasmSpec.j
2
2
  import { number } from "./embedding.js";
3
3
  import { unsignedLEB128 } from "./encoding.js";
4
4
  import { UNDEFINED } from "./builtins.js";
5
+ import Prefs from './prefs.js';
5
6
 
6
7
  // todo: do not duplicate this
7
8
  const TYPES = {
@@ -16,15 +17,17 @@ const TYPES = {
16
17
 
17
18
  // these are not "typeof" types but tracked internally
18
19
  _array: 0x10,
19
- _regexp: 0x11
20
+ _regexp: 0x11,
21
+ _bytestring: 0x12
20
22
  };
21
23
 
22
24
  // todo: turn these into built-ins once arrays and these become less hacky
23
25
 
24
26
  export const PrototypeFuncs = function() {
25
- const noUnlikelyChecks = process.argv.includes('-funsafe-no-unlikely-proto-checks');
26
- let zeroChecks = process.argv.find(x => x.startsWith('-funsafe-zero-proto-checks='));
27
- if (zeroChecks) zeroChecks = zeroChecks.split('=')[1].split(',').reduce((acc, x) => { acc[x.toLowerCase()] = true; return acc; }, {});
27
+ const noUnlikelyChecks = Prefs.funsafeNoUnlikelyProtoChecks;
28
+
29
+ let zeroChecks;
30
+ if (Prefs.zeroChecks) zeroChecks = Prefs.zeroChecks.split('=')[1].split(',').reduce((acc, x) => { acc[x.toLowerCase()] = true; return acc; }, {});
28
31
  else zeroChecks = {};
29
32
 
30
33
  this[TYPES._array] = {
@@ -71,7 +74,7 @@ export const PrototypeFuncs = function() {
71
74
  ],
72
75
 
73
76
  // todo: only for 1 argument
74
- push: (pointer, length, wNewMember) => [
77
+ push: (pointer, length, wNewMember, _1, _2, _3, unusedValue) => [
75
78
  // get memory offset of array at last index (length)
76
79
  ...length.getCachedI32(),
77
80
  ...number(ValtypeSize[valtype], Valtype.i32),
@@ -92,22 +95,28 @@ export const PrototypeFuncs = function() {
92
95
  ...number(1, Valtype.i32),
93
96
  [ Opcodes.i32_add ],
94
97
 
95
- ...length.setCachedI32(),
96
- ...length.getCachedI32(),
98
+ ...(unusedValue() ? [] : [
99
+ ...length.setCachedI32(),
100
+ ...length.getCachedI32(),
101
+ ])
97
102
  ]),
98
103
 
99
- ...length.getCachedI32(),
100
- Opcodes.i32_from_u
104
+ ...(unusedValue() ? [] : [
105
+ ...length.getCachedI32(),
106
+ Opcodes.i32_from_u
107
+ ])
101
108
 
102
109
  // ...length.get()
103
110
  ],
104
111
 
105
- pop: (pointer, length) => [
112
+ pop: (pointer, length, _1, _2, _3, _4, unusedValue) => [
106
113
  // if length == 0, noop
107
114
  ...length.getCachedI32(),
108
115
  [ Opcodes.i32_eqz ],
109
116
  [ Opcodes.if, Blocktype.void ],
110
- ...number(UNDEFINED),
117
+ ...(unusedValue() ? [] : [
118
+ ...number(UNDEFINED),
119
+ ]),
111
120
  [ Opcodes.br, 1 ],
112
121
  [ Opcodes.end ],
113
122
 
@@ -119,19 +128,23 @@ export const PrototypeFuncs = function() {
119
128
  ...number(1, Valtype.i32),
120
129
  [ Opcodes.i32_sub ],
121
130
 
122
- ...length.setCachedI32(),
123
- ...length.getCachedI32(),
131
+ ...(unusedValue() ? [] : [
132
+ ...length.setCachedI32(),
133
+ ...length.getCachedI32(),
134
+ ])
124
135
  ]),
125
136
 
126
137
  // load last element
127
- ...length.getCachedI32(),
128
- ...number(ValtypeSize[valtype], Valtype.i32),
129
- [ Opcodes.i32_mul ],
138
+ ...(unusedValue() ? [] : [
139
+ ...length.getCachedI32(),
140
+ ...number(ValtypeSize[valtype], Valtype.i32),
141
+ [ Opcodes.i32_mul ],
130
142
 
131
- ...pointer,
132
- [ Opcodes.i32_add ],
143
+ ...pointer,
144
+ [ Opcodes.i32_add ],
133
145
 
134
- [ Opcodes.load, Math.log2(ValtypeSize[valtype]) - 1, ...unsignedLEB128(ValtypeSize.i32) ]
146
+ [ Opcodes.load, Math.log2(ValtypeSize[valtype]) - 1, ...unsignedLEB128(ValtypeSize.i32) ]
147
+ ])
135
148
  ],
136
149
 
137
150
  shift: (pointer, length) => [
@@ -331,8 +344,8 @@ export const PrototypeFuncs = function() {
331
344
  ...number(0, Valtype.i32), // base 0 for store later
332
345
 
333
346
  ...wIndex,
334
-
335
347
  Opcodes.i32_to,
348
+
336
349
  ...number(ValtypeSize.i16, Valtype.i32),
337
350
  [ Opcodes.i32_mul ],
338
351
 
@@ -472,8 +485,151 @@ export const PrototypeFuncs = function() {
472
485
  this[TYPES.string].at.returnType = TYPES.string;
473
486
  this[TYPES.string].charAt.returnType = TYPES.string;
474
487
  this[TYPES.string].charCodeAt.local = Valtype.i32;
488
+ this[TYPES.string].charCodeAt.noPointerCache = zeroChecks.charcodeat;
475
489
 
476
490
  this[TYPES.string].isWellFormed.local = Valtype.i32;
477
491
  this[TYPES.string].isWellFormed.local2 = Valtype.i32;
478
492
  this[TYPES.string].isWellFormed.returnType = TYPES.boolean;
493
+
494
+ if (Prefs.bytestring) {
495
+ this[TYPES._bytestring] = {
496
+ at: (pointer, length, wIndex, iTmp, _, arrayShell) => {
497
+ const [ newOut, newPointer ] = arrayShell(1, 'i8');
498
+
499
+ return [
500
+ // setup new/out array
501
+ ...newOut,
502
+ [ Opcodes.drop ],
503
+
504
+ ...number(0, Valtype.i32), // base 0 for store later
505
+
506
+ ...wIndex,
507
+ Opcodes.i32_to_u,
508
+ [ Opcodes.local_tee, iTmp ],
509
+
510
+ // if index < 0: access index + array length
511
+ ...number(0, Valtype.i32),
512
+ [ Opcodes.i32_lt_s ],
513
+ [ Opcodes.if, Blocktype.void ],
514
+ [ Opcodes.local_get, iTmp ],
515
+ ...length.getCachedI32(),
516
+ [ Opcodes.i32_add ],
517
+ [ Opcodes.local_set, iTmp ],
518
+ [ Opcodes.end ],
519
+
520
+ // if still < 0 or >= length: return undefined
521
+ [ Opcodes.local_get, iTmp ],
522
+ ...number(0, Valtype.i32),
523
+ [ Opcodes.i32_lt_s ],
524
+
525
+ [ Opcodes.local_get, iTmp ],
526
+ ...length.getCachedI32(),
527
+ [ Opcodes.i32_ge_s ],
528
+ [ Opcodes.i32_or ],
529
+
530
+ [ Opcodes.if, Blocktype.void ],
531
+ ...number(UNDEFINED),
532
+ [ Opcodes.br, 1 ],
533
+ [ Opcodes.end ],
534
+
535
+ [ Opcodes.local_get, iTmp ],
536
+
537
+ ...pointer,
538
+ [ Opcodes.i32_add ],
539
+
540
+ // load current string ind {arg}
541
+ [ Opcodes.i32_load8_u, 0, ...unsignedLEB128(ValtypeSize.i32) ],
542
+
543
+ // store to new string ind 0
544
+ [ Opcodes.i32_store8, 0, ...unsignedLEB128(newPointer + ValtypeSize.i32) ],
545
+
546
+ // return new string (pointer)
547
+ ...number(newPointer)
548
+ ];
549
+ },
550
+
551
+ // todo: out of bounds properly
552
+ charAt: (pointer, length, wIndex, _1, _2, arrayShell) => {
553
+ const [ newOut, newPointer ] = arrayShell(1, 'i8');
554
+
555
+ return [
556
+ // setup new/out array
557
+ ...newOut,
558
+ [ Opcodes.drop ],
559
+
560
+ ...number(0, Valtype.i32), // base 0 for store later
561
+
562
+ ...wIndex,
563
+ Opcodes.i32_to,
564
+
565
+ ...pointer,
566
+ [ Opcodes.i32_add ],
567
+
568
+ // load current string ind {arg}
569
+ [ Opcodes.i32_load8_u, 0, ...unsignedLEB128(ValtypeSize.i32) ],
570
+
571
+ // store to new string ind 0
572
+ [ Opcodes.i32_store8, 0, ...unsignedLEB128(newPointer + ValtypeSize.i32) ],
573
+
574
+ // return new string (page)
575
+ ...number(newPointer)
576
+ ];
577
+ },
578
+
579
+ charCodeAt: (pointer, length, wIndex, iTmp) => {
580
+ return [
581
+ ...wIndex,
582
+ Opcodes.i32_to,
583
+
584
+ ...(zeroChecks.charcodeat ? [] : [
585
+ [ Opcodes.local_set, iTmp ],
586
+
587
+ // index < 0
588
+ ...(noUnlikelyChecks ? [] : [
589
+ [ Opcodes.local_get, iTmp ],
590
+ ...number(0, Valtype.i32),
591
+ [ Opcodes.i32_lt_s ],
592
+ ]),
593
+
594
+ // index >= length
595
+ [ Opcodes.local_get, iTmp ],
596
+ ...length.getCachedI32(),
597
+ [ Opcodes.i32_ge_s ],
598
+
599
+ ...(noUnlikelyChecks ? [] : [ [ Opcodes.i32_or ] ]),
600
+ [ Opcodes.if, Blocktype.void ],
601
+ ...number(NaN),
602
+ [ Opcodes.br, 1 ],
603
+ [ Opcodes.end ],
604
+
605
+ [ Opcodes.local_get, iTmp ],
606
+ ]),
607
+
608
+ ...pointer,
609
+ [ Opcodes.i32_add ],
610
+
611
+ // load current string ind {arg}
612
+ [ Opcodes.i32_load8_u, 0, ...unsignedLEB128(ValtypeSize.i32) ],
613
+ Opcodes.i32_from_u
614
+ ];
615
+ },
616
+
617
+ isWellFormed: () => {
618
+ return [
619
+ // we know it must be true as it is a bytestring lol
620
+ ...number(1)
621
+ ]
622
+ }
623
+ };
624
+
625
+ this[TYPES._bytestring].at.local = Valtype.i32;
626
+ this[TYPES._bytestring].at.returnType = TYPES._bytestring;
627
+ this[TYPES._bytestring].charAt.returnType = TYPES._bytestring;
628
+ this[TYPES._bytestring].charCodeAt.local = Valtype.i32;
629
+ this[TYPES._bytestring].charCodeAt.noPointerCache = zeroChecks.charcodeat;
630
+
631
+ this[TYPES._bytestring].isWellFormed.local = Valtype.i32;
632
+ this[TYPES._bytestring].isWellFormed.local2 = Valtype.i32;
633
+ this[TYPES._bytestring].isWellFormed.returnType = TYPES.boolean;
634
+ }
479
635
  };
@@ -3,6 +3,7 @@ import { encodeVector, encodeString, encodeLocal, unsignedLEB128, signedLEB128 }
3
3
  import { number } from './embedding.js';
4
4
  import { importedFuncs } from './builtins.js';
5
5
  import { log } from "./log.js";
6
+ import Prefs from './prefs.js';
6
7
 
7
8
  const createSection = (type, data) => [
8
9
  type,
@@ -26,12 +27,12 @@ export default (funcs, globals, tags, pages, data, flags) => {
26
27
 
27
28
  const optLevel = parseInt(process.argv.find(x => x.startsWith('-O'))?.[2] ?? 1);
28
29
 
29
- const compileHints = process.argv.includes('-compile-hints');
30
+ const compileHints = Prefs.compileHints;
30
31
  if (compileHints) log.warning('sections', 'compile hints is V8 only w/ experimental arg! (you used -compile-hints)');
31
32
 
32
33
  const getType = (params, returns) => {
33
34
  const hash = `${params.join(',')}_${returns.join(',')}`;
34
- if (optLog) log('sections', `getType(${JSON.stringify(params)}, ${JSON.stringify(returns)}) -> ${hash} | cache: ${typeCache[hash]}`);
35
+ if (Prefs.optLog) log('sections', `getType(${JSON.stringify(params)}, ${JSON.stringify(returns)}) -> ${hash} | cache: ${typeCache[hash]}`);
35
36
  if (optLevel >= 1 && typeCache[hash] !== undefined) return typeCache[hash];
36
37
 
37
38
  const type = [ FuncType, ...encodeVector(params), ...encodeVector(returns) ];
@@ -79,7 +80,7 @@ export default (funcs, globals, tags, pages, data, flags) => {
79
80
  }
80
81
  globalThis.importFuncs = importFuncs;
81
82
 
82
- if (optLog) log('sections', `treeshake: using ${importFuncs.length}/${importedFuncs.length} imports`);
83
+ if (Prefs.optLog) log('sections', `treeshake: using ${importFuncs.length}/${importedFuncs.length} imports`);
83
84
 
84
85
  const importSection = importFuncs.length === 0 ? [] : createSection(
85
86
  Section.import,
@@ -95,7 +96,7 @@ export default (funcs, globals, tags, pages, data, flags) => {
95
96
  // https://github.com/WebAssembly/design/issues/1473#issuecomment-1431274746
96
97
  const chSection = !compileHints ? [] : customSection(
97
98
  'compilationHints',
98
- // for now just do everything as optimise eager
99
+ // for now just do everything as optimize eager
99
100
  encodeVector(funcs.map(_ => chHint(0x02, 0x02, 0x02)))
100
101
  );
101
102
 
@@ -106,7 +107,7 @@ export default (funcs, globals, tags, pages, data, flags) => {
106
107
 
107
108
  const exports = funcs.filter(x => x.export).map((x, i) => [ ...encodeString(x.name === 'main' ? 'm' : x.name), ExportDesc.func, x.index ]);
108
109
 
109
- if (process.argv.includes('-always-memory') && pages.size === 0) pages.set('-always-memory', 0);
110
+ if (Prefs.alwaysMemory && pages.size === 0) pages.set('-always-memory', 0);
110
111
  if (optLevel === 0) pages.set('O0 precaution', 0);
111
112
 
112
113
  const usesMemory = pages.size > 0;
@@ -150,7 +151,7 @@ export default (funcs, globals, tags, pages, data, flags) => {
150
151
 
151
152
  if (typeCount !== 0) localDecl.push(encodeLocal(typeCount, lastType));
152
153
 
153
- return encodeVector([ ...encodeVector(localDecl), ...x.wasm.flat().filter(x => x <= 0xff), Opcodes.end ]);
154
+ return encodeVector([ ...encodeVector(localDecl), ...x.wasm.flat().filter(x => x != null && x <= 0xff), Opcodes.end ]);
154
155
  }))
155
156
  );
156
157
 
@@ -169,7 +170,7 @@ export default (funcs, globals, tags, pages, data, flags) => {
169
170
  unsignedLEB128(data.length)
170
171
  );
171
172
 
172
- if (process.argv.includes('-sections')) console.log({
173
+ if (Prefs.sections) console.log({
173
174
  typeSection: typeSection.map(x => x.toString(16)),
174
175
  importSection: importSection.map(x => x.toString(16)),
175
176
  funcSection: funcSection.map(x => x.toString(16)),
@@ -32,8 +32,6 @@ export const Opcodes = {
32
32
  throw: 0x08,
33
33
  rethrow: 0x09,
34
34
 
35
- return: 0x0F,
36
-
37
35
  call: 0x10,
38
36
  call_indirect: 0x11,
39
37
  return_call: 0x12,
@@ -42,7 +40,10 @@ export const Opcodes = {
42
40
  end: 0x0b,
43
41
  br: 0x0c,
44
42
  br_if: 0x0d,
43
+ br_table: 0x0e,
44
+ return: 0x0f,
45
45
  call: 0x10,
46
+
46
47
  drop: 0x1a,
47
48
 
48
49
  local_get: 0x20,
@@ -56,9 +57,12 @@ export const Opcodes = {
56
57
  i64_load: 0x29,
57
58
  f64_load: 0x2b,
58
59
 
60
+ i32_load8_s: 0x2c,
61
+ i32_load8_u: 0x2d,
59
62
  i32_load16_s: 0x2e,
60
63
  i32_load16_u: 0x2f,
61
64
 
65
+ i32_store8: 0x3a,
62
66
  i32_store16: 0x3b,
63
67
 
64
68
  i32_store: 0x36,
package/compiler/wrap.js CHANGED
@@ -1,5 +1,6 @@
1
1
  import compile from './index.js';
2
2
  import decompile from './decompile.js';
3
+ import { encodeVector, encodeLocal } from './encoding.js';
3
4
  // import fs from 'node:fs';
4
5
 
5
6
  const bold = x => `\u001b[1m${x}\u001b[0m`;
@@ -18,7 +19,8 @@ const TYPES = {
18
19
 
19
20
  // internal
20
21
  [internalTypeBase]: '_array',
21
- [internalTypeBase + 1]: '_regexp'
22
+ [internalTypeBase + 1]: '_regexp',
23
+ [internalTypeBase + 2]: '_bytestring'
22
24
  };
23
25
 
24
26
  export default async (source, flags = [ 'module' ], customImports = {}, print = str => process.stdout.write(str)) => {
@@ -35,14 +37,98 @@ export default async (source, flags = [ 'module' ], customImports = {}, print =
35
37
  if (flags.includes('info')) console.log(bold(`compiled in ${times[0].toFixed(2)}ms`));
36
38
 
37
39
  const t2 = performance.now();
38
- const { instance } = await WebAssembly.instantiate(wasm, {
39
- '': {
40
- p: valtype === 'i64' ? i => print(Number(i).toString()) : i => print(i.toString()),
41
- c: valtype === 'i64' ? i => print(String.fromCharCode(Number(i))) : i => print(String.fromCharCode(i)),
42
- t: _ => performance.now(),
43
- ...customImports
40
+
41
+ let instance;
42
+ try {
43
+ 0, { instance } = await WebAssembly.instantiate(wasm, {
44
+ '': {
45
+ p: valtype === 'i64' ? i => print(Number(i).toString()) : i => print(i.toString()),
46
+ c: valtype === 'i64' ? i => print(String.fromCharCode(Number(i))) : i => print(String.fromCharCode(i)),
47
+ t: _ => performance.now(),
48
+ ...customImports
49
+ }
50
+ });
51
+ } catch (e) {
52
+ // only backtrace for runner, not test262/etc
53
+ if (!process.argv[1].includes('/runner')) throw e;
54
+
55
+ const funcInd = parseInt(e.message.match(/function #([0-9]+) /)[1]);
56
+ const blobOffset = parseInt(e.message.split('@')[1]);
57
+
58
+ // convert blob offset -> function wasm offset.
59
+ // this is not good code and is somewhat duplicated
60
+ // I just want it to work for debugging, I don't care about perf/yes
61
+
62
+ const func = funcs.find(x => x.index === funcInd);
63
+ const locals = Object.values(func.locals).sort((a, b) => a.idx - b.idx).slice(func.params.length).sort((a, b) => a.idx - b.idx);
64
+
65
+ let localDecl = [], typeCount = 0, lastType;
66
+ for (let i = 0; i < locals.length; i++) {
67
+ const local = locals[i];
68
+ if (i !== 0 && local.type !== lastType) {
69
+ localDecl.push(encodeLocal(typeCount, lastType));
70
+ typeCount = 0;
71
+ }
72
+
73
+ typeCount++;
74
+ lastType = local.type;
75
+ }
76
+
77
+ if (typeCount !== 0) localDecl.push(encodeLocal(typeCount, lastType));
78
+
79
+ const toFind = encodeVector(localDecl).concat(func.wasm.flat().filter(x => x != null && x <= 0xff).slice(0, 40));
80
+
81
+ let i = 0;
82
+ for (; i < wasm.length; i++) {
83
+ let mismatch = false;
84
+ for (let j = 0; j < toFind.length; j++) {
85
+ if (wasm[i + j] !== toFind[j]) {
86
+ mismatch = true;
87
+ break;
88
+ }
89
+ }
90
+
91
+ if (!mismatch) break;
92
+ }
93
+
94
+ if (i === wasm.length) throw e;
95
+
96
+ const offset = (blobOffset - i) + encodeVector(localDecl).length;
97
+
98
+ let cumLen = 0;
99
+ i = 0;
100
+ for (; i < func.wasm.length; i++) {
101
+ cumLen += func.wasm[i].filter(x => x != null && x <= 0xff).length;
102
+ if (cumLen === offset) break;
103
+ }
104
+
105
+ if (cumLen !== offset) throw e;
106
+
107
+ i -= 1;
108
+
109
+ console.log(`\x1B[35m\x1B[1mporffor backtrace\u001b[0m`);
110
+
111
+ console.log('\x1B[4m' + func.name + '\x1B[0m');
112
+
113
+ const surrounding = 6;
114
+
115
+ const decomp = decompile(func.wasm.slice(i - surrounding, i + surrounding + 1), '', 0, func.locals, func.params, func.returns, funcs, globals, exceptions).slice(0, -1).split('\n');
116
+
117
+ const noAnsi = s => s.replace(/\u001b\[[0-9]+m/g, '');
118
+ let longest = 0;
119
+ for (let j = 0; j < decomp.length; j++) {
120
+ longest = Math.max(longest, noAnsi(decomp[j]).length);
44
121
  }
45
- });
122
+
123
+ const middle = Math.floor(decomp.length / 2);
124
+ decomp[middle] = `\x1B[47m\x1B[30m${noAnsi(decomp[middle])}${'\u00a0'.repeat(longest - noAnsi(decomp[middle]).length)}\x1B[0m`;
125
+
126
+ console.log('\x1B[90m...\x1B[0m');
127
+ console.log(decomp.join('\n'));
128
+ console.log('\x1B[90m...\x1B[0m\n');
129
+
130
+ throw e;
131
+ }
46
132
 
47
133
  times.push(performance.now() - t2);
48
134
  if (flags.includes('info')) console.log(`instantiated in ${times[1].toFixed(2)}ms`);
@@ -95,10 +181,18 @@ export default async (source, flags = [ 'module' ], customImports = {}, print =
95
181
  return Array.from(new Uint16Array(memory.buffer, pointer + 4, length)).map(x => String.fromCharCode(x)).join('');
96
182
  }
97
183
 
184
+ case '_bytestring': {
185
+ const pointer = ret;
186
+ const length = new Int32Array(memory.buffer, pointer, 1);
187
+
188
+ return Array.from(new Uint8Array(memory.buffer, pointer + 4, length)).map(x => String.fromCharCode(x)).join('');
189
+ }
190
+
98
191
  case 'function': {
99
192
  // wasm func index, including all imports
100
193
  const func = funcs.find(x => (x.originalIndex ?? x.index) === ret);
101
- if (!func) return ret;
194
+ // if (!func) return ret;
195
+ if (!func) return function () {};
102
196
 
103
197
  // make fake empty func for repl/etc
104
198
  return {[func.name]() {}}[func.name];
package/demo.js ADDED
@@ -0,0 +1,3 @@
1
+ // foo();
2
+
3
+ console.log('Hello, World!');
package/demo.ts ADDED
@@ -0,0 +1 @@
1
+ console.log("hello world");
package/filesize.cmd ADDED
@@ -0,0 +1,2 @@
1
+ @echo off
2
+ echo %~z1
package/hello ADDED
Binary file
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "porffor",
3
3
  "description": "a basic experimental wip aot optimizing js -> wasm engine/compiler/runtime in js",
4
- "version": "0.2.0-c7b7423",
4
+ "version": "0.2.0-dcc06c8",
5
5
  "author": "CanadaHonk",
6
6
  "license": "MIT",
7
7
  "dependencies": {
package/porf ADDED
@@ -0,0 +1,2 @@
1
+ #!/bin/sh
2
+ node runner/index.js "$@"
package/rhemyn/compile.js CHANGED
@@ -2,6 +2,7 @@ import { Blocktype, Opcodes, Valtype, PageSize, ValtypeSize } from '../compiler/
2
2
  import { number } from '../compiler/embedding.js';
3
3
  import { signedLEB128, unsignedLEB128 } from '../compiler/encoding.js';
4
4
  import parse from './parse.js';
5
+ import Prefs from '../compiler/prefs.js';
5
6
 
6
7
  // local indexes
7
8
  const BasePointer = 0; // base string pointer
@@ -80,7 +81,7 @@ const generate = (node, negated = false, get = true, func = 'test') => {
80
81
  })[func], Valtype.i32)
81
82
  ];
82
83
 
83
- if (globalThis.regexLog) {
84
+ if (Prefs.regexLog) {
84
85
  const underline = x => `\u001b[4m\u001b[1m${x}\u001b[0m`;
85
86
  console.log(`\n${underline('ast')}`);
86
87
  console.log(node);
package/runner/index.js CHANGED
@@ -3,6 +3,8 @@
3
3
  import compile from '../compiler/wrap.js';
4
4
  import fs from 'node:fs';
5
5
 
6
+ const start = performance.now();
7
+
6
8
  if (process.argv.includes('-compile-hints')) {
7
9
  const v8 = await import('node:v8');
8
10
  v8.setFlagsFromString(`--experimental-wasm-compilation-hints`);
@@ -15,9 +17,22 @@ if (process.argv.includes('-compile-hints')) {
15
17
  // --experimental-wasm-return-call (on by default)
16
18
  }
17
19
 
18
- const file = process.argv.slice(2).find(x => x[0] !== '-');
20
+ let file = process.argv.slice(2).find(x => x[0] !== '-');
21
+ if (['run', 'wasm', 'native', 'c'].includes(file)) {
22
+ if (['wasm', 'native', 'c'].includes(file)) {
23
+ process.argv.push(`-target=${file}`);
24
+ }
25
+
26
+ file = process.argv.slice(process.argv.indexOf(file) + 1).find(x => x[0] !== '-');
27
+
28
+ const nonOptOutFile = process.argv.slice(process.argv.indexOf(file) + 1).find(x => x[0] !== '-');
29
+ if (nonOptOutFile) {
30
+ process.argv.push(`-o=${nonOptOutFile}`);
31
+ }
32
+ }
33
+
19
34
  if (!file) {
20
- if (process.argv.includes('-v')) {
35
+ if (process.argv.includes('-v') || process.argv.includes('--version')) {
21
36
  // just print version
22
37
  console.log((await import('./version.js')).default);
23
38
  process.exit(0);
@@ -52,4 +67,6 @@ try {
52
67
  } catch (e) {
53
68
  if (cache) process.stdout.write(cache);
54
69
  console.error(process.argv.includes('-i') ? e : `${e.constructor.name}: ${e.message}`);
55
- }
70
+ }
71
+
72
+ if (process.argv.includes('-t')) console.log(performance.now() - start);
package/runner/repl.js CHANGED
@@ -45,9 +45,9 @@ let prev = '';
45
45
  const run = async (source, _context, _filename, callback, run = true) => {
46
46
  // hack: print "secret" before latest code ran to only enable printing for new code
47
47
 
48
- let toRun = prev + `;\nprint(-0x1337);\n` + source.trim();
48
+ let toRun = (prev ? (prev + `;\nprint(-0x1337);\n`) : '') + source.trim();
49
49
 
50
- let shouldPrint = false;
50
+ let shouldPrint = !prev;
51
51
  const { exports, wasm, pages } = await compile(toRun, [], {}, str => {
52
52
  if (shouldPrint) process.stdout.write(str);
53
53
  if (str === '-4919') shouldPrint = true;