porffor 0.2.0-fdf0fc5 → 0.14.0-0ad2c8a7c

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 (48) hide show
  1. package/CONTRIBUTING.md +12 -7
  2. package/README.md +18 -15
  3. package/asur/index.js +1 -1
  4. package/byg/index.js +3 -24
  5. package/compiler/2c.js +69 -55
  6. package/compiler/assemble.js +51 -11
  7. package/compiler/builtins/annexb_string.js +10 -10
  8. package/compiler/builtins/annexb_string.ts +4 -3
  9. package/compiler/builtins/array.ts +85 -9
  10. package/compiler/builtins/base64.ts +2 -1
  11. package/compiler/builtins/boolean.ts +2 -2
  12. package/compiler/builtins/console.ts +4 -0
  13. package/compiler/builtins/crypto.ts +2 -1
  14. package/compiler/builtins/date.ts +2 -3
  15. package/compiler/builtins/error.js +22 -0
  16. package/compiler/builtins/escape.ts +2 -3
  17. package/compiler/builtins/function.ts +1 -1
  18. package/compiler/builtins/int.ts +1 -1
  19. package/compiler/builtins/math.ts +410 -0
  20. package/compiler/builtins/number.ts +4 -7
  21. package/compiler/builtins/object.ts +1 -1
  22. package/compiler/builtins/porffor.d.ts +9 -8
  23. package/compiler/builtins/set.ts +197 -3
  24. package/compiler/builtins/string.ts +2 -1
  25. package/compiler/builtins/symbol.ts +62 -0
  26. package/compiler/builtins.js +30 -15
  27. package/compiler/codegen.js +641 -365
  28. package/compiler/decompile.js +7 -3
  29. package/compiler/embedding.js +2 -2
  30. package/compiler/encoding.js +0 -14
  31. package/compiler/expression.js +1 -1
  32. package/compiler/generated_builtins.js +781 -187
  33. package/compiler/index.js +5 -11
  34. package/compiler/opt.js +7 -7
  35. package/compiler/parse.js +2 -4
  36. package/compiler/precompile.js +18 -25
  37. package/compiler/prefs.js +6 -2
  38. package/compiler/prototype.js +185 -162
  39. package/compiler/wasmSpec.js +5 -0
  40. package/compiler/wrap.js +150 -90
  41. package/package.json +1 -1
  42. package/runner/compare.js +0 -1
  43. package/runner/debug.js +1 -6
  44. package/runner/index.js +5 -4
  45. package/runner/profiler.js +15 -42
  46. package/runner/repl.js +20 -10
  47. package/runner/sizes.js +2 -2
  48. package/runner/version.js +10 -8
package/compiler/wrap.js CHANGED
@@ -1,12 +1,106 @@
1
+ import { encodeVector, encodeLocal } from './encoding.js';
2
+ import { importedFuncs } from './builtins.js';
1
3
  import compile from './index.js';
2
4
  import decompile from './decompile.js';
3
- import { encodeVector, encodeLocal } from './encoding.js';
4
- import Prefs from './prefs.js';
5
- import { log } from './log.js';
6
5
  import { TYPES } from './types.js';
6
+ import { log } from './log.js';
7
+ import Prefs from './prefs.js';
7
8
 
8
9
  const bold = x => `\u001b[1m${x}\u001b[0m`;
9
10
 
11
+ const porfToJSValue = ({ memory, funcs, pages }, value, type) => {
12
+ switch (type) {
13
+ case TYPES.boolean: return Boolean(value);
14
+ case TYPES.undefined: return undefined;
15
+ case TYPES.object: return value === 0 ? null : {};
16
+
17
+ case TYPES.function: {
18
+ let func;
19
+ if (value < 0) {
20
+ func = importedFuncs[value + importedFuncs.length];
21
+ } else {
22
+ func = funcs.find(x => ((x.originalIndex ?? x.index) - importedFuncs.length) === value);
23
+ }
24
+
25
+ if (!func) return function () {};
26
+
27
+ // make fake empty func for repl/etc
28
+ return {[func.name]() {}}[func.name];
29
+ }
30
+
31
+ case TYPES.string: {
32
+ const length = (new Int32Array(memory.buffer, value, 1))[0];
33
+ return Array.from(new Uint16Array(memory.buffer, value + 4, length)).map(x => String.fromCharCode(x)).join('');
34
+ }
35
+
36
+ case TYPES.bytestring: {
37
+ const length = (new Int32Array(memory.buffer, value, 1))[0];
38
+ return Array.from(new Uint8Array(memory.buffer, value + 4, length)).map(x => String.fromCharCode(x)).join('');
39
+ }
40
+
41
+ case TYPES.array: {
42
+ const length = (new Int32Array(memory.buffer, value, 1))[0];
43
+
44
+ const out = [];
45
+ for (let i = 0; i < length; i++) {
46
+ const offset = value + 4 + (i * 9);
47
+
48
+ // have to slice because of memory alignment (?)
49
+ const v = (new Float64Array(memory.buffer.slice(offset, offset + 8), 0, 1))[0];
50
+ const t = (new Uint8Array(memory.buffer, offset + 8, 1))[0];
51
+
52
+ // console.log(`reading value at index ${i}...`)
53
+ // console.log(' memory:', Array.from(new Uint8Array(memory.buffer, offset, 9)).map(x => x.toString(16).padStart(2, '0')).join(' '));
54
+ // console.log(' read:', { value: v, type: t }, '\n');
55
+
56
+ out.push(porfToJSValue({ memory, funcs, pages }, v, t));
57
+ }
58
+
59
+ return out;
60
+ }
61
+
62
+ case TYPES.date: {
63
+ const t = (new Float64Array(memory.buffer, value, 1))[0];
64
+ return new Date(t);
65
+ }
66
+
67
+ case TYPES.set: {
68
+ const size = (new Int32Array(memory.buffer, value, 1))[0];
69
+
70
+ const out = new Set();
71
+ for (let i = 0; i < size; i++) {
72
+ const offset = value + 4 + (i * 9);
73
+
74
+ // have to slice because of memory alignment (?)
75
+ const v = (new Float64Array(memory.buffer.slice(offset, offset + 8), 0, 1))[0];
76
+ const t = (new Uint8Array(memory.buffer, offset + 8, 1))[0];
77
+
78
+ // console.log(`reading value at index ${i}...`)
79
+ // console.log(' memory:', Array.from(new Uint8Array(memory.buffer, offset, 9)).map(x => x.toString(16).padStart(2, '0')).join(' '));
80
+ // console.log(' read:', { value: v, type: t }, '\n');
81
+
82
+ out.add(porfToJSValue({ memory, funcs, pages }, v, t));
83
+ }
84
+
85
+ return out;
86
+ }
87
+
88
+ case TYPES.symbol: {
89
+ const descStore = pages.get('bytestring: __Porffor_symbol_descStore/ptr').ind * pageSize;
90
+ const offset = descStore + 4 + ((value - 1) * 9);
91
+
92
+ const v = (new Float64Array(memory.buffer.slice(offset, offset + 8), 0, 1))[0];
93
+ const t = (new Uint8Array(memory.buffer, offset + 8, 1))[0];
94
+
95
+ const desc = porfToJSValue({ memory, funcs, pages }, v, t);
96
+
97
+ return Symbol(desc);
98
+ }
99
+
100
+ default: return value;
101
+ }
102
+ };
103
+
10
104
  export default async (source, flags = [ 'module' ], customImports = {}, print = str => process.stdout.write(str)) => {
11
105
  const times = [];
12
106
 
@@ -22,40 +116,12 @@ export default async (source, flags = [ 'module' ], customImports = {}, print =
22
116
  times.push(performance.now() - t1);
23
117
  if (Prefs.profileCompiler) console.log(bold(`compiled in ${times[0].toFixed(2)}ms`));
24
118
 
25
- const t2 = performance.now();
26
-
27
- let instance;
28
- try {
29
- let wasmEngine = WebAssembly;
30
- if (Prefs.asur) {
31
- log.warning('wrap', 'using our !experimental! asur wasm engine instead of host to run');
32
- wasmEngine = await import('../asur/index.js');
33
- }
34
-
35
- 0, { instance } = await wasmEngine.instantiate(wasm, {
36
- '': {
37
- p: valtype === 'i64' ? i => print(Number(i).toString()) : i => print(i.toString()),
38
- c: valtype === 'i64' ? i => print(String.fromCharCode(Number(i))) : i => print(String.fromCharCode(i)),
39
- t: () => performance.now(),
40
- u: () => performance.timeOrigin,
41
- y: () => {},
42
- z: () => {},
43
- ...customImports
44
- }
45
- });
46
- } catch (e) {
47
- // only backtrace for runner, not test262/etc
48
- if (!process.argv[1].includes('/runner')) throw e;
49
-
50
- const funcInd = parseInt(e.message.match(/function #([0-9]+) /)?.[1]);
51
- const blobOffset = parseInt(e.message.split('@')?.[1]);
52
-
53
- if (!funcInd) throw e;
119
+ const backtrace = (funcInd, blobOffset) => {
120
+ if (funcInd == null || blobOffset == null) return false;
54
121
 
55
122
  // convert blob offset -> function wasm offset.
56
123
  // this is not good code and is somewhat duplicated
57
124
  // I just want it to work for debugging, I don't care about perf/yes
58
-
59
125
  const func = funcs.find(x => x.index === funcInd);
60
126
  const locals = Object.values(func.locals).sort((a, b) => a.idx - b.idx).slice(func.params.length).sort((a, b) => a.idx - b.idx);
61
127
 
@@ -73,7 +139,7 @@ export default async (source, flags = [ 'module' ], customImports = {}, print =
73
139
 
74
140
  if (typeCount !== 0) localDecl.push(encodeLocal(typeCount, lastType));
75
141
 
76
- const toFind = encodeVector(localDecl).concat(func.wasm.flat().filter(x => x != null && x <= 0xff).slice(0, 40));
142
+ const toFind = encodeVector(localDecl).concat(func.wasm.flat().filter(x => x != null && x <= 0xff).slice(0, 60));
77
143
 
78
144
  let i = 0;
79
145
  for (; i < wasm.length; i++) {
@@ -88,7 +154,7 @@ export default async (source, flags = [ 'module' ], customImports = {}, print =
88
154
  if (!mismatch) break;
89
155
  }
90
156
 
91
- if (i === wasm.length) throw e;
157
+ if (i === wasm.length) return false;
92
158
 
93
159
  const offset = (blobOffset - i) + encodeVector(localDecl).length;
94
160
 
@@ -99,7 +165,7 @@ export default async (source, flags = [ 'module' ], customImports = {}, print =
99
165
  if (cumLen === offset) break;
100
166
  }
101
167
 
102
- if (cumLen !== offset) throw e;
168
+ if (cumLen !== offset) return false;
103
169
 
104
170
  i -= 1;
105
171
 
@@ -124,6 +190,38 @@ export default async (source, flags = [ 'module' ], customImports = {}, print =
124
190
  console.log(decomp.join('\n'));
125
191
  console.log('\x1B[90m...\x1B[0m\n');
126
192
 
193
+ return true;
194
+ };
195
+
196
+ const t2 = performance.now();
197
+
198
+ let instance;
199
+ try {
200
+ let wasmEngine = WebAssembly;
201
+ if (Prefs.asur) {
202
+ log.warning('wrap', 'using our !experimental! asur wasm engine instead of host to run');
203
+ wasmEngine = await import('../asur/index.js');
204
+ }
205
+
206
+ 0, { instance } = await wasmEngine.instantiate(wasm, {
207
+ '': {
208
+ p: valtype === 'i64' ? i => print(Number(i).toString()) : i => print(i.toString()),
209
+ c: valtype === 'i64' ? i => print(String.fromCharCode(Number(i))) : i => print(String.fromCharCode(i)),
210
+ t: () => performance.now(),
211
+ u: () => performance.timeOrigin,
212
+ y: () => {},
213
+ z: () => {},
214
+ ...customImports
215
+ }
216
+ });
217
+ } catch (e) {
218
+ // only backtrace for runner, not test262/etc
219
+ if (!process.argv[1].includes('/runner')) throw e;
220
+
221
+ const funcInd = parseInt(e.message.match(/function #([0-9]+) /)?.[1]);
222
+ const blobOffset = parseInt(e.message.split('@')?.[1]);
223
+
224
+ backtrace(funcInd, blobOffset);
127
225
  throw e;
128
226
  }
129
227
 
@@ -131,6 +229,7 @@ export default async (source, flags = [ 'module' ], customImports = {}, print =
131
229
  if (Prefs.profileCompiler) console.log(`instantiated in ${times[1].toFixed(2)}ms`);
132
230
 
133
231
  const exports = {};
232
+ const rawValues = process.argv.includes('-i');
134
233
 
135
234
  const exceptTag = instance.exports['0'], memory = instance.exports['$'];
136
235
  for (const x in instance.exports) {
@@ -148,62 +247,12 @@ export default async (source, flags = [ 'module' ], customImports = {}, print =
148
247
 
149
248
  exports[func.name] = function() {
150
249
  try {
151
- const _ret = exp.apply(this, arguments);
152
-
153
- if (_ret == null) return undefined;
154
-
155
- const [ ret, type ] = _ret;
156
-
157
- // if (ret >= typeBase && ret <= typeBase + 8) return ret > (typeBase + 7) ? 'object' : TYPES[ret];
158
-
159
- switch (type) {
160
- case TYPES.boolean: return Boolean(ret);
161
- case TYPES.undefined: return undefined;
162
- case TYPES.object: return ret === 0 ? null : {};
163
-
164
- case TYPES.string: {
165
- const pointer = ret;
166
- const length = (new Int32Array(memory.buffer, pointer, 1))[0];
250
+ const ret = exp.apply(this, arguments);
251
+ if (ret == null) return undefined;
167
252
 
168
- return Array.from(new Uint16Array(memory.buffer, pointer + 4, length)).map(x => String.fromCharCode(x)).join('');
169
- }
253
+ if (rawValues) return { value: ret[0], type: ret[1], js: porfToJSValue({ memory, funcs, pages }, ret[0], ret[1]) };
170
254
 
171
- case TYPES.function: {
172
- // wasm func index, including all imports
173
- const func = funcs.find(x => (x.originalIndex ?? x.index) === ret);
174
- // if (!func) return ret;
175
- if (!func) return function () {};
176
-
177
- // make fake empty func for repl/etc
178
- return {[func.name]() {}}[func.name];
179
- }
180
-
181
- case TYPES.array: {
182
- const pointer = ret;
183
- const length = (new Int32Array(memory.buffer, pointer, 1))[0];
184
-
185
- // have to slice because of memory alignment
186
- const buf = memory.buffer.slice(pointer + 4, pointer + 4 + 8 * length);
187
-
188
- return Array.from(new Float64Array(buf));
189
- }
190
-
191
- case TYPES.bytestring: {
192
- const pointer = ret;
193
- const length = (new Int32Array(memory.buffer, pointer, 1))[0];
194
-
195
- return Array.from(new Uint8Array(memory.buffer, pointer + 4, length)).map(x => String.fromCharCode(x)).join('');
196
- }
197
-
198
- case TYPES.date: {
199
- const pointer = ret;
200
- const value = (new Float64Array(memory.buffer, pointer, 1))[0];
201
-
202
- return new Date(value);
203
- }
204
-
205
- default: return ret;
206
- }
255
+ return porfToJSValue({ memory, funcs, pages }, ret[0], ret[1]);
207
256
  } catch (e) {
208
257
  if (e.is && e.is(exceptTag)) {
209
258
  const exceptId = e.getArg(exceptTag, 0);
@@ -218,6 +267,17 @@ export default async (source, flags = [ 'module' ], customImports = {}, print =
218
267
  throw new constructor(exception.message);
219
268
  }
220
269
 
270
+ if (e instanceof WebAssembly.RuntimeError) {
271
+ // only backtrace for runner, not test262/etc
272
+ if (!process.argv[1].includes('/runner')) throw e;
273
+
274
+ const match = e.stack.match(/wasm-function\[([0-9]+)\]:([0-9a-z]+)/) ?? [];
275
+ const funcInd = parseInt(match[1]);
276
+ const blobOffset = parseInt(match[2]);
277
+
278
+ backtrace(funcInd, blobOffset);
279
+ }
280
+
221
281
  throw e;
222
282
  }
223
283
  };
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-fdf0fc5",
4
+ "version": "0.14.0-0ad2c8a7c",
5
5
  "author": "CanadaHonk",
6
6
  "license": "MIT",
7
7
  "scripts": {
package/runner/compare.js CHANGED
@@ -1,5 +1,4 @@
1
1
  import { execSync } from 'node:child_process';
2
- import { pathToFileURL } from 'node:url';
3
2
  import fs from 'node:fs';
4
3
 
5
4
  const [ commitsAgo, file ] = process.argv.slice(2);
package/runner/debug.js CHANGED
@@ -1,9 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  import compile from '../compiler/wrap.js';
4
- import fs from 'node:fs';
5
-
6
4
  import Byg from '../byg/index.js';
5
+ import fs from 'node:fs';
7
6
 
8
7
  const file = process.argv.slice(2).find(x => x[0] !== '-');
9
8
  let source = fs.readFileSync(file, 'utf8');
@@ -19,7 +18,6 @@ source = source.replace(/^\s*(function|const)\s*([a-zA-Z0-9]+)(\s*=\s*)?\([^)]*\
19
18
 
20
19
  const lines = source.split('\n');
21
20
  for (let i = 0; i < lines.length; i++) {
22
- // lines[line] = lines[line].replace(/^[^\n}]*;$/, _ => `profile(${line});${_}`);
23
21
  if (lines[i].trim().replace('}', '') !== '') lines[i] = `profile1(Porffor.wasm.i32.const(${i}));` + lines[i];
24
22
  }
25
23
  source = lines.join('\n');
@@ -35,8 +33,6 @@ const byg = Byg({
35
33
  }
36
34
  });
37
35
 
38
- // console.log(source);
39
-
40
36
  let stepIn = false, stepOut = false;
41
37
  const callStack = [];
42
38
 
@@ -72,7 +68,6 @@ try {
72
68
  [
73
69
  {
74
70
  x: termWidth - 1 - 40 - 6,
75
- // y: () => termHeight - 20 - 1 - 4,
76
71
  y: () => 4,
77
72
  width: 40,
78
73
  height: 20,
package/runner/index.js CHANGED
@@ -25,7 +25,7 @@ if (process.argv.includes('--help')) {
25
25
  console.log(`Usage: \x1B[1mporf [command] path/to/script.js [...prefs] [...args]\x1B[0m`);
26
26
 
27
27
  // commands
28
- console.log(`\n\u001b[4mCommands\x1B[0m`);
28
+ console.log(`\n\x1B[1mCommands:\x1B[0m`);
29
29
  for (const [ cmd, [ color, desc ] ] of Object.entries({
30
30
  run: [ 34, 'Run a JS file' ],
31
31
  wasm: [ 34, 'Compile a JS file to a Wasm binary\n' ],
@@ -60,8 +60,10 @@ if (process.argv.includes('--help')) {
60
60
 
61
61
  let file = process.argv.slice(2).find(x => x[0] !== '-');
62
62
  if (['run', 'wasm', 'native', 'c', 'profile', 'debug', 'debug-wasm'].includes(file)) {
63
+ // remove this arg
64
+ process.argv.splice(process.argv.indexOf(file), 1);
65
+
63
66
  if (file === 'profile') {
64
- process.argv.splice(process.argv.indexOf(file), 1);
65
67
  await import('./profiler.js');
66
68
  await new Promise(() => {}); // do nothing for the rest of this file
67
69
  }
@@ -75,12 +77,11 @@ if (['run', 'wasm', 'native', 'c', 'profile', 'debug', 'debug-wasm'].includes(fi
75
77
  }
76
78
 
77
79
  if (file === 'debug') {
78
- process.argv.splice(process.argv.indexOf(file), 1);
79
80
  await import('./debug.js');
80
81
  await new Promise(() => {}); // do nothing for the rest of this file
81
82
  }
82
83
 
83
- file = process.argv.slice(process.argv.indexOf(file) + 1).find(x => x[0] !== '-');
84
+ file = process.argv.slice(2).find(x => x[0] !== '-');
84
85
 
85
86
  const nonOptOutFile = process.argv.slice(process.argv.indexOf(file) + 1).find(x => x[0] !== '-');
86
87
  if (nonOptOutFile) {
@@ -3,22 +3,12 @@
3
3
  import compile from '../compiler/wrap.js';
4
4
  import fs from 'node:fs';
5
5
 
6
- import Prefs from '../compiler/prefs.js';
7
-
8
- // const fast = Prefs.profiler === 'fast';
9
- const fast = !Prefs.experimentalProfiler;
10
-
11
6
  const file = process.argv.slice(2).find(x => x[0] !== '-');
12
7
  let source = fs.readFileSync(file, 'utf8');
13
8
 
14
9
  let profileId = 0;
15
- // source = fast ? source.replace(/^[^\n}]*;$/mg, _ => `profile(${profileId++});${_}profile(${profileId++});`) : source.replace(/^[^\n}]*;$/mg, _ => `profile(${profileId++});profile(${profileId++});${_}profile(${profileId++});`);
16
- // source = fast ? source.replace(/^[^\n}]*;$/mg, _ => `profile(Porffor.wasm.i32.const(${profileId++}));${_}profile(Porffor.wasm.i32.const(${profileId++}));`) : source.replace(/^[^\n}]*;$/mg, _ => `profile(${profileId++});profile(${profileId++});${_}profile(${profileId++});`);
17
- source = fast ? source.replace(/^[^\n}]*;$/mg, _ => `profile1(Porffor.wasm.i32.const(${profileId}));${_}profile2(Porffor.wasm.i32.const(${profileId++}));`) : source.replace(/^[^\n}]*;$/mg, _ => `profile(${profileId++});profile(${profileId++});${_}profile(${profileId++});`);
10
+ source = source.replace(/^[^\n}]*;$/mg, _ => `profile1(Porffor.wasm.i32.const(${profileId}));${_}profile2(Porffor.wasm.i32.const(${profileId++}));`)
18
11
 
19
- // console.log(source);
20
-
21
- // let tmp = new Array(profileId).fill(0);
22
12
  let tmp = new Array(profileId).fill(0);
23
13
  let times = new Array(profileId).fill(0);
24
14
  let samples = 0;
@@ -31,31 +21,19 @@ let last = 0;
31
21
 
32
22
  try {
33
23
  const { exports } = await compile(source, process.argv.includes('--module') ? [ 'module' ] : [], {
34
- y: fast ? n => {
24
+ y: n => {
35
25
  tmp[n] = performance.now();
36
- } : n => { /* todo */ },
37
- z: fast ? n => {
38
- times[n] += performance.now() - tmp[n];
39
- } : n => { /* todo */ }
40
- // z: fast ? n => {
41
- // if (n % 2) {
42
- // tmp[n] += performance.now() - tmp[n - 1];
43
- // } else {
44
- // tmp[n] = performance.now();
45
- // }
46
- // } : n => {
47
- // if (n % 3 === 2) {
48
- // tmp[n] += (performance.now() - tmp[n - 1]) - (tmp[n - 1] - tmp[n - 2]);
49
- // samples++;
50
-
51
- // if (performance.now() > last) {
52
- // process.stdout.write(`\r${spinner[spin++ % 4]} running: collected ${samples} samples...`);
53
- // last = performance.now() + 100;
54
- // }
55
- // } else {
56
- // tmp[n] = performance.now();
57
- // }
58
- // }
26
+ },
27
+ z: n => {
28
+ const t = performance.now();
29
+ times[n] += t - tmp[n];
30
+
31
+ samples++;
32
+ if (t > last) {
33
+ process.stdout.write(`\r${spinner[spin++ % 4]} running: collected ${samples} samples...`);
34
+ last = t + 100;
35
+ }
36
+ }
59
37
  });
60
38
 
61
39
  const start = performance.now();
@@ -64,14 +42,11 @@ try {
64
42
 
65
43
  const total = performance.now() - start;
66
44
 
67
- console.log(`\n${fast ? '' : `samples: ${samples}\n`}total: ${total}ms\n\n` + source.split('\n').map(x => {
45
+ console.log(`\ntotal: ${total}ms\nsamples: ${samples}\n\n\n` + source.split('\n').map(x => {
68
46
  let time = 0;
69
47
  if (x.startsWith('profile')) {
70
- // const id = parseInt(x.slice(8, x.indexOf(')')));
71
- // const id = parseInt(x.slice(31, x.indexOf(')') + 1));
72
48
  const id = parseInt(x.slice(32, x.indexOf(')')));
73
- // time = fast ? tmp[id + 1] : tmp[id + 2];
74
- time = fast ? times[id] : tmp[id + 2];
49
+ time = times[id]
75
50
  }
76
51
 
77
52
  let color = [ 0, 0, 0 ];
@@ -85,8 +60,6 @@ try {
85
60
 
86
61
  const ansiColor = `2;${color[0]};${color[1]};${color[2]}m`;
87
62
 
88
- // const line = x.replace(/profile\([0-9]+\);/g, '');
89
- // const line = x.replace(/profile\(Porffor.wasm.i32.const\([0-9]+\)\);/g, '');
90
63
  const line = x.replace(/profile[0-9]\(Porffor.wasm.i32.const\([0-9]+\)\);/g, '');
91
64
 
92
65
  if (percents) return `\x1b[48;${ansiColor}\x1b[97m${time ? ((time * 100).toFixed(0).padStart(4, ' ') + '%') : ' '}\x1b[0m\x1b[38;${ansiColor}▌\x1b[0m ${line}`;
package/runner/repl.js CHANGED
@@ -1,8 +1,10 @@
1
+ import { TYPE_NAMES } from '../compiler/types.js';
1
2
  import compile from '../compiler/wrap.js';
2
- import rev from './version.js';
3
+ import version from './version.js';
3
4
 
4
- // import repl from 'node:repl';
5
- // import repl from '../../node-repl-polyfill/index.js';
5
+ import util from 'node:util';
6
+
7
+ process.argv.push('--no-opt-unused');
6
8
 
7
9
  let repl;
8
10
  try {
@@ -17,8 +19,6 @@ try {
17
19
  repl = (await import('node-repl-polyfill')).default;
18
20
  }
19
21
 
20
- // process.argv.push('-O0'); // disable opts
21
-
22
22
  globalThis.valtype = 'f64';
23
23
 
24
24
  const valtypeOpt = process.argv.find(x => x.startsWith('--valtype='));
@@ -32,7 +32,7 @@ if (host.startsWith('Node')) host = '\x1B[92m' + host;
32
32
  if (host.startsWith('Deno')) host = '\x1B[97m' + host;
33
33
  if (host.startsWith('Bun')) host = '\x1B[93m' + host;
34
34
 
35
- console.log(`Welcome to \x1B[1m\x1B[35mPorffor\x1B[0m \x1B[90m(${rev.slice(0, 7)})\x1B[0m running on \x1B[1m${host.replace('/', ' \x1B[0m\x1B[90m(')})\x1B[0m`);
35
+ console.log(`Welcome to \x1B[1m\x1B[35mPorffor\x1B[0m \x1B[90m(${version})\x1B[0m running on \x1B[1m${host.replace('/', ' \x1B[0m\x1B[90m(')})\x1B[0m`);
36
36
  console.log(`\x1B[90musing opt ${process.argv.find(x => x.startsWith('-O')) ?? '-O1'}, parser ${parser}, valtype ${valtype}\x1B[0m`);
37
37
  console.log();
38
38
 
@@ -81,21 +81,31 @@ const run = async (source, _context, _filename, callback, run = true) => {
81
81
  let toRun = (prev ? (prev + `;\nprint(-0x1337);\n`) : '') + source.trim();
82
82
 
83
83
  let shouldPrint = !prev;
84
- const { exports, wasm, pages } = await compile(toRun, [], {}, str => {
84
+ const { exports, pages } = await compile(toRun, [], {}, str => {
85
85
  if (shouldPrint) process.stdout.write(str);
86
86
  if (str === '-4919') shouldPrint = true;
87
87
  });
88
- // fs.writeFileSync('out.wasm', Buffer.from(wasm));
89
88
 
90
89
  if (run && exports.$) {
91
90
  lastMemory = exports.$;
92
91
  lastPages = [...pages.keys()];
93
92
  }
94
93
 
95
- const ret = run ? exports.main() : undefined;
96
- callback(null, ret);
94
+ let ret = run ? exports.main() : undefined;
95
+ let value, type;
96
+ if (ret?.type != null) {
97
+ value = ret.value;
98
+ type = ret.type;
99
+ ret = ret.js;
100
+ }
101
+
102
+ console.log(util.inspect(ret, false, 2, true), (value != null ? `\x1B[34m\x1B[3m(value: ${value}, type: ${TYPE_NAMES[type]})\x1B[0m` : ''));
103
+
104
+ // callback(null, ret);
97
105
 
98
106
  prev = prev + ';\n' + source.trim();
107
+
108
+ callback();
99
109
  };
100
110
 
101
111
  const replServer = repl.start({ prompt: '> ', eval: run });
package/runner/sizes.js CHANGED
@@ -1,5 +1,5 @@
1
- import fs from 'node:fs';
2
1
  import compile from '../compiler/index.js';
2
+ import fs from 'node:fs';
3
3
 
4
4
  // deno compat
5
5
  const textEncoder = new TextEncoder();
@@ -18,7 +18,7 @@ const perform = async (file, args) => {
18
18
  console.log(label, ' '.repeat(40 - label.length), `${size}b`);
19
19
  };
20
20
 
21
- const argsValtypes = [ '--valtype=i32', '--valtype=i64', '--valtype=f64' ];
21
+ const argsValtypes = [ '--valtype=i32', '--valtype=f64' ];
22
22
  const argsOptlevels = [ '-O0', '-O1', '-O2', '-O3' ];
23
23
 
24
24
  for (const file of [ 'bench/prime_basic.js', 'bench/fib_iter.js', 'test/math_1.js', 'test/math_3.js', 'test/while_1.js', 'test/for_2.js', 'test/unary_3.js', 'test/updateexp_1.js', 'test/eq_3.js', 'test/empty.js' ]) {
package/runner/version.js CHANGED
@@ -1,10 +1,12 @@
1
- import fs from 'node:fs';
1
+ import { readFileSync } from 'node:fs';
2
2
 
3
- let rev = 'unknown';
4
- try {
5
- rev = JSON.parse(fs.readFileSync(new URL('../package.json', import.meta.url), 'utf8')).version.split('-')[1].slice(0, 7);
6
- } catch {
7
- rev = fs.readFileSync(new URL('../.git/refs/heads/main', import.meta.url), 'utf8').trim().slice(0, 7);
8
- }
3
+ export let version = 'unknown';
4
+ export let rev = 'unknown';
9
5
 
10
- export default rev;
6
+ const packageJson = JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf8'));
7
+ version = packageJson.version.split('-')[0];
8
+ rev = packageJson.version.split('-')[1];
9
+
10
+ if (!rev) rev = readFileSync(new URL('../.git/refs/heads/main', import.meta.url), 'utf8').trim().slice(0, 9);
11
+
12
+ export default `${version}-${rev}`;