porffor 0.2.0-6aff0fa → 0.2.0-6bc63ef

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 (54) hide show
  1. package/CONTRIBUTING.md +256 -0
  2. package/LICENSE +20 -20
  3. package/README.md +115 -82
  4. package/asur/index.js +624 -340
  5. package/byg/index.js +216 -0
  6. package/compiler/2c.js +2 -53
  7. package/compiler/{sections.js → assemble.js} +60 -14
  8. package/compiler/builtins/annexb_string.js +72 -0
  9. package/compiler/builtins/annexb_string.ts +18 -0
  10. package/compiler/builtins/array.ts +145 -0
  11. package/compiler/builtins/base64.ts +7 -84
  12. package/compiler/builtins/boolean.ts +18 -0
  13. package/compiler/builtins/crypto.ts +120 -0
  14. package/compiler/builtins/date.ts +2067 -0
  15. package/compiler/builtins/escape.ts +141 -0
  16. package/compiler/builtins/function.ts +5 -0
  17. package/compiler/builtins/int.ts +145 -0
  18. package/compiler/builtins/number.ts +529 -0
  19. package/compiler/builtins/object.ts +4 -0
  20. package/compiler/builtins/porffor.d.ts +44 -7
  21. package/compiler/builtins/set.ts +187 -0
  22. package/compiler/builtins/string.ts +1080 -0
  23. package/compiler/builtins.js +400 -120
  24. package/compiler/{codeGen.js → codegen.js} +850 -402
  25. package/compiler/decompile.js +2 -3
  26. package/compiler/embedding.js +22 -22
  27. package/compiler/encoding.js +94 -10
  28. package/compiler/expression.js +1 -1
  29. package/compiler/generated_builtins.js +1613 -3
  30. package/compiler/index.js +16 -16
  31. package/compiler/log.js +2 -2
  32. package/compiler/opt.js +28 -27
  33. package/compiler/parse.js +36 -30
  34. package/compiler/precompile.js +37 -46
  35. package/compiler/prefs.js +7 -6
  36. package/compiler/prototype.js +20 -36
  37. package/compiler/types.js +38 -0
  38. package/compiler/wasmSpec.js +14 -1
  39. package/compiler/wrap.js +79 -69
  40. package/package.json +9 -5
  41. package/porf +2 -0
  42. package/rhemyn/compile.js +44 -26
  43. package/rhemyn/parse.js +322 -320
  44. package/rhemyn/test/parse.js +58 -58
  45. package/runner/compare.js +33 -34
  46. package/runner/debug.js +117 -0
  47. package/runner/index.js +69 -12
  48. package/runner/profiler.js +22 -30
  49. package/runner/repl.js +40 -13
  50. package/runner/sizes.js +37 -37
  51. package/runner/version.js +3 -3
  52. package/runner/info.js +0 -89
  53. package/runner/transform.js +0 -15
  54. package/util/enum.js +0 -20
@@ -1,59 +1,59 @@
1
- import util from 'node:util';
2
-
3
- import parse from '../parse.js';
4
-
5
- const tests = {
6
- 'a': {},
7
- 'a(b)': {},
8
- 'a(b(c))': {},
9
- 'ab': {},
10
- '[ab]': {},
11
- '[a-z]': {},
12
- 'a*': {},
13
- 'a+': {},
14
- 'a?': {},
15
- 'a(b)+': {},
16
- '[^a]': {},
17
- '[a^]': {},
18
- '[^ab]': {},
19
- '.': {},
20
-
21
- // not range
22
- '[-]': {},
23
- '[0-]': {},
24
- '[-0]': {},
25
- '[\\s-\\S]': {},
26
- '[\\s-.]': {},
27
-
28
- '[\\S]': {},
29
-
30
- '\\c': {},
31
- '\\c0': {},
32
- '\\cJ': {},
33
-
34
- '\\x': {},
35
- '\\x0': {},
36
- '\\x0g': {},
37
- '\\x0a': {},
38
-
39
- '\\u': {},
40
- '\\u0': {},
41
- '\\u000': {},
42
- '\\u000g': {},
43
- '\\u000a': {},
44
-
45
- /*
46
- // email regexes
47
- '^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$': {},
48
-
49
- // input type=email from HTML spec
50
- // https://html.spec.whatwg.org/multipage/input.html#email-state-(type=email)
51
- // simpler form
52
- '^[a-zA-Z0-9.!#$%&’*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\\.[a-zA-Z0-9-]+)*$': {},
53
- // full/complex form
54
- '^[a-zA-Z0-9.!#$%&\'*+\\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$': {}*/
55
- };
56
-
57
- for (const str in tests) {
58
- console.log(str, util.inspect(parse(str), false, null, true));
1
+ import util from 'node:util';
2
+
3
+ import parse from '../parse.js';
4
+
5
+ const tests = {
6
+ 'a': {},
7
+ 'a(b)': {},
8
+ 'a(b(c))': {},
9
+ 'ab': {},
10
+ '[ab]': {},
11
+ '[a-z]': {},
12
+ 'a*': {},
13
+ 'a+': {},
14
+ 'a?': {},
15
+ 'a(b)+': {},
16
+ '[^a]': {},
17
+ '[a^]': {},
18
+ '[^ab]': {},
19
+ '.': {},
20
+
21
+ // not range
22
+ '[-]': {},
23
+ '[0-]': {},
24
+ '[-0]': {},
25
+ '[\\s-\\S]': {},
26
+ '[\\s-.]': {},
27
+
28
+ '[\\S]': {},
29
+
30
+ '\\c': {},
31
+ '\\c0': {},
32
+ '\\cJ': {},
33
+
34
+ '\\x': {},
35
+ '\\x0': {},
36
+ '\\x0g': {},
37
+ '\\x0a': {},
38
+
39
+ '\\u': {},
40
+ '\\u0': {},
41
+ '\\u000': {},
42
+ '\\u000g': {},
43
+ '\\u000a': {},
44
+
45
+ /*
46
+ // email regexes
47
+ '^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$': {},
48
+
49
+ // input type=email from HTML spec
50
+ // https://html.spec.whatwg.org/multipage/input.html#email-state-(type=email)
51
+ // simpler form
52
+ '^[a-zA-Z0-9.!#$%&’*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\\.[a-zA-Z0-9-]+)*$': {},
53
+ // full/complex form
54
+ '^[a-zA-Z0-9.!#$%&\'*+\\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$': {}*/
55
+ };
56
+
57
+ for (const str in tests) {
58
+ console.log(str, util.inspect(parse(str), false, null, true));
59
59
  }
package/runner/compare.js CHANGED
@@ -1,35 +1,34 @@
1
- import { execSync } from 'node:child_process';
2
- import { pathToFileURL } from 'node:url';
3
- import fs from 'node:fs';
4
-
5
- const [ commitsAgo, file ] = process.argv.slice(2);
6
- const source = fs.readFileSync(file, 'utf8');
7
-
8
- const compileNow = (await import('../compiler/index.js')).default;
9
- const wasmNow = compileNow(source).byteLength;
10
-
11
- execSync(`git checkout HEAD~${commitsAgo}`);
12
-
13
- let failed = false;
14
-
15
- fs.writeFileSync('tmp.js', source);
16
- try {
17
- execSync(`node runner/index.js tmp.js`);
18
- } catch {
19
- failed = true;
20
- } finally {
21
- fs.rmSync('tmp.js');
22
- execSync(`git checkout main`);
23
- }
24
-
25
- console.log();
26
-
27
- if (failed) {
28
- console.log(`!! failed to compile then`);
29
- process.exit();
30
- }
31
-
32
- const wasmThen = Buffer.byteLength(fs.readFileSync('out.wasm'));
33
-
34
- console.log(`now: ${wasmNow} bytes`);
1
+ import { execSync } from 'node:child_process';
2
+ import fs from 'node:fs';
3
+
4
+ const [ commitsAgo, file ] = process.argv.slice(2);
5
+ const source = fs.readFileSync(file, 'utf8');
6
+
7
+ const compileNow = (await import('../compiler/index.js')).default;
8
+ const wasmNow = compileNow(source).byteLength;
9
+
10
+ execSync(`git checkout HEAD~${commitsAgo}`);
11
+
12
+ let failed = false;
13
+
14
+ fs.writeFileSync('tmp.js', source);
15
+ try {
16
+ execSync(`node runner/index.js tmp.js`);
17
+ } catch {
18
+ failed = true;
19
+ } finally {
20
+ fs.rmSync('tmp.js');
21
+ execSync(`git checkout main`);
22
+ }
23
+
24
+ console.log();
25
+
26
+ if (failed) {
27
+ console.log(`!! failed to compile then`);
28
+ process.exit();
29
+ }
30
+
31
+ const wasmThen = Buffer.byteLength(fs.readFileSync('out.wasm'));
32
+
33
+ console.log(`now: ${wasmNow} bytes`);
35
34
  console.log(`${commitsAgo} commit${commitsAgo > 1 ? 's' : ''} ago: ${wasmThen} bytes`);
@@ -0,0 +1,117 @@
1
+ #!/usr/bin/env node
2
+
3
+ import compile from '../compiler/wrap.js';
4
+ import Byg from '../byg/index.js';
5
+ import fs from 'node:fs';
6
+
7
+ const file = process.argv.slice(2).find(x => x[0] !== '-');
8
+ let source = fs.readFileSync(file, 'utf8');
9
+
10
+ const originalLines = source.split('\n');
11
+
12
+ let funcs = {}, funcId = 0;
13
+ source = source.replace(/^\s*(function|const)\s*([a-zA-Z0-9]+)(\s*=\s*)?\([^)]*\)\s*(=>)?\s*\{$/gm, (x, _, n) => {
14
+ const id = funcId++;
15
+ funcs[funcId] = n;
16
+ return `${x}profile2(Porffor.wasm.i32.const(${id}))`;
17
+ });
18
+
19
+ const lines = source.split('\n');
20
+ for (let i = 0; i < lines.length; i++) {
21
+ if (lines[i].trim().replace('}', '') !== '') lines[i] = `profile1(Porffor.wasm.i32.const(${i}));` + lines[i];
22
+ }
23
+ source = lines.join('\n');
24
+
25
+ const breakpoints = new Array(lines.length);
26
+
27
+ let paused = true;
28
+ const byg = Byg({
29
+ lines: originalLines,
30
+ pause: () => { paused = true; },
31
+ breakpoint: (line, breakpoint) => {
32
+ breakpoints[line] = breakpoint;
33
+ }
34
+ });
35
+
36
+ let stepIn = false, stepOut = false;
37
+ const callStack = [];
38
+
39
+ let _paused;
40
+ let callStarts = [];
41
+ let lastLine;
42
+
43
+ let output = '';
44
+
45
+ try {
46
+ const { exports } = await compile(source, process.argv.includes('--module') ? [ 'module' ] : [], {
47
+ y: n => {
48
+ if (callStarts[callStarts.length - 1] === n - 1) {
49
+ // end of call
50
+
51
+ callStarts.pop();
52
+ callStack.pop();
53
+
54
+ paused = _paused;
55
+ }
56
+
57
+ lastLine = n;
58
+
59
+ if (breakpoints[n]) paused = true;
60
+
61
+ if (paused) {
62
+ stepIn = false; stepOut = false;
63
+
64
+ switch (byg(
65
+ paused,
66
+ n,
67
+ `\x1b[1mporffor debugger\x1b[22m: ${file}@${n + 1} ${callStack.join('->')}`,
68
+ [
69
+ {
70
+ x: termWidth - 1 - 40 - 6,
71
+ y: () => 4,
72
+ width: 40,
73
+ height: 20,
74
+ title: 'console',
75
+ content: output.split('\n')
76
+ }
77
+ ]
78
+ )) {
79
+ case 'resume': {
80
+ paused = false;
81
+ break;
82
+ }
83
+
84
+ case 'stepOver': {
85
+ break;
86
+ }
87
+
88
+ case 'stepIn': {
89
+ stepIn = true;
90
+ // paused = false;
91
+ break;
92
+ }
93
+
94
+ case 'stepOut': {
95
+ stepOut = true;
96
+ paused = false;
97
+ break;
98
+ }
99
+ }
100
+ }
101
+ },
102
+ z: n => {
103
+ // start of call
104
+ callStack.push(funcs[n]);
105
+
106
+ callStarts.push(lastLine);
107
+
108
+ _paused = paused;
109
+ if (!stepIn) paused = false;
110
+ else paused = true;
111
+ }
112
+ }, s => output += s);
113
+
114
+ exports.main();
115
+ } catch (e) {
116
+ console.error(e);
117
+ }
package/runner/index.js CHANGED
@@ -5,7 +5,7 @@ import fs from 'node:fs';
5
5
 
6
6
  const start = performance.now();
7
7
 
8
- if (process.argv.includes('-compile-hints')) {
8
+ if (process.argv.includes('--compile-hints')) {
9
9
  const v8 = await import('node:v8');
10
10
  v8.setFlagsFromString(`--experimental-wasm-compilation-hints`);
11
11
 
@@ -17,16 +17,67 @@ if (process.argv.includes('-compile-hints')) {
17
17
  // --experimental-wasm-return-call (on by default)
18
18
  }
19
19
 
20
+ if (process.argv.includes('--help')) {
21
+ // description + version
22
+ console.log(`\x1B[1m\x1B[35mPorffor\x1B[0m is a JavaScript engine/runtime/compiler. \x1B[90m(${(await import('./version.js')).default})\x1B[0m`);
23
+
24
+ // basic usage
25
+ console.log(`Usage: \x1B[1mporf [command] path/to/script.js [...prefs] [...args]\x1B[0m`);
26
+
27
+ // commands
28
+ console.log(`\n\u001b[4mCommands\x1B[0m`);
29
+ for (const [ cmd, [ color, desc ] ] of Object.entries({
30
+ run: [ 34, 'Run a JS file' ],
31
+ wasm: [ 34, 'Compile a JS file to a Wasm binary\n' ],
32
+ c: [ 31, 'Compile a JS file to C source code' ],
33
+ native: [ 31, 'Compile a JS file to a native binary\n' ],
34
+ profile: [ 33, 'Profile a JS file' ],
35
+ debug: [ 33, 'Debug a JS file' ],
36
+ 'debug-wasm': [ 33, 'Debug the compiled Wasm of a JS file' ]
37
+ })) {
38
+ console.log(` \x1B[1m\x1B[${color}m${cmd}\x1B[0m${' '.repeat(20 - cmd.length - (desc.startsWith('🧪') ? 3 : 0))}${desc}`);
39
+ }
40
+
41
+ // console.log();
42
+
43
+ // // options
44
+ // console.log(`\n\u001b[4mCommands\x1B[0m`);
45
+ // for (const [ cmd, [ color, desc ] ] of Object.entries({
46
+ // run: [ 34, 'Run a JS file' ],
47
+ // wasm: [ 34, 'Compile a JS file to a Wasm binary\n' ],
48
+ // c: [ 31, 'Compile a JS file to C source code' ],
49
+ // native: [ 31, 'Compile a JS file to a native binary\n' ],
50
+ // profile: [ 33, 'Profile a JS file' ],
51
+ // debug: [ 33, 'Debug a JS file' ],
52
+ // 'debug-wasm': [ 33, 'Debug the compiled Wasm of a JS file' ]
53
+ // })) {
54
+ // console.log(` \x1B[1m\x1B[${color}m${cmd}\x1B[0m${' '.repeat(20 - cmd.length - (desc.startsWith('🧪') ? 3 : 0))}${desc}`);
55
+ // }
56
+
57
+ console.log();
58
+ process.exit(0);
59
+ }
60
+
20
61
  let file = process.argv.slice(2).find(x => x[0] !== '-');
21
- if (['run', 'wasm', 'native', 'c', 'profile'].includes(file)) {
62
+ if (['run', 'wasm', 'native', 'c', 'profile', 'debug', 'debug-wasm'].includes(file)) {
22
63
  if (file === 'profile') {
23
64
  process.argv.splice(process.argv.indexOf(file), 1);
24
65
  await import('./profiler.js');
25
- await new Promise(() => {});
66
+ await new Promise(() => {}); // do nothing for the rest of this file
26
67
  }
27
68
 
28
69
  if (['wasm', 'native', 'c'].includes(file)) {
29
- process.argv.push(`-target=${file}`);
70
+ process.argv.push(`--target=${file}`);
71
+ }
72
+
73
+ if (file === 'debug-wasm') {
74
+ process.argv.push('--asur', '--wasm-debug');
75
+ }
76
+
77
+ if (file === 'debug') {
78
+ process.argv.splice(process.argv.indexOf(file), 1);
79
+ await import('./debug.js');
80
+ await new Promise(() => {}); // do nothing for the rest of this file
30
81
  }
31
82
 
32
83
  file = process.argv.slice(process.argv.indexOf(file) + 1).find(x => x[0] !== '-');
@@ -46,9 +97,7 @@ if (!file) {
46
97
 
47
98
  // run repl if no file given
48
99
  await import('./repl.js');
49
-
50
- // do nothing for the rest of this file
51
- await new Promise(() => {});
100
+ await new Promise(() => {}); // do nothing for the rest of this file
52
101
  }
53
102
 
54
103
  const source = fs.readFileSync(file, 'utf8');
@@ -66,13 +115,21 @@ const print = str => {
66
115
  };
67
116
 
68
117
  try {
69
- const { exports } = await compile(source, process.argv.includes('--module') ? [ 'module' ] : [], {}, print);
118
+ if (process.argv.includes('-b')) {
119
+ const { wasm, exports } = await compile(source, process.argv.includes('--module') ? [ 'module' ] : [], {}, print);
70
120
 
71
- if (!process.argv.includes('-no-run')) exports.main();
72
- if (cache) process.stdout.write(cache);
121
+ if (!process.argv.includes('--no-run')) exports.main();
122
+
123
+ console.log(`\n\nwasm size: ${wasm.byteLength} bytes`);
124
+ } else {
125
+ const { exports } = await compile(source, process.argv.includes('--module') ? [ 'module' ] : [], {}, print);
126
+
127
+ if (!process.argv.includes('-no-run')) exports.main();
128
+ }
129
+ // if (cache) process.stdout.write(cache);
73
130
  } catch (e) {
74
- if (cache) process.stdout.write(cache);
131
+ // if (cache) process.stdout.write(cache);
75
132
  console.error(process.argv.includes('-i') ? e : `${e.constructor.name}: ${e.message}`);
76
133
  }
77
134
 
78
- if (process.argv.includes('-t')) console.log(`\n\ntotal time: ${(performance.now() - start).toFixed(2)}ms`);
135
+ if (process.argv.includes('-t')) console.log(`${process.argv.includes('-b') ? '' : '\n\n'}total time: ${(performance.now() - start).toFixed(2)}ms`);
@@ -3,19 +3,14 @@
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
-
10
6
  const file = process.argv.slice(2).find(x => x[0] !== '-');
11
7
  let source = fs.readFileSync(file, 'utf8');
12
8
 
13
9
  let profileId = 0;
14
- source = fast ? source.replace(/^[^\n}]*;$/mg, _ => `profile(${profileId++});${_}profile(${profileId++});`) : source.replace(/^[^\n}]*;$/mg, _ => `profile(${profileId++});profile(${profileId++});${_}profile(${profileId++});`);
15
-
16
- // console.log(source);
10
+ source = source.replace(/^[^\n}]*;$/mg, _ => `profile1(Porffor.wasm.i32.const(${profileId}));${_}profile2(Porffor.wasm.i32.const(${profileId++}));`)
17
11
 
18
12
  let tmp = new Array(profileId).fill(0);
13
+ let times = new Array(profileId).fill(0);
19
14
  let samples = 0;
20
15
 
21
16
  const percents = process.argv.includes('-%');
@@ -26,23 +21,17 @@ let last = 0;
26
21
 
27
22
  try {
28
23
  const { exports } = await compile(source, process.argv.includes('--module') ? [ 'module' ] : [], {
29
- z: fast ? n => {
30
- if (n % 2) {
31
- tmp[n] += performance.now() - tmp[n - 1];
32
- } else {
33
- tmp[n] = performance.now();
34
- }
35
- } : n => {
36
- if (n % 3 === 2) {
37
- tmp[n] += (performance.now() - tmp[n - 1]) - (tmp[n - 1] - tmp[n - 2]);
38
- samples++;
39
-
40
- if (performance.now() > last) {
41
- process.stdout.write(`\r${spinner[spin++ % 4]} running: collected ${samples} samples...`);
42
- last = performance.now() + 100;
43
- }
44
- } else {
45
- tmp[n] = performance.now();
24
+ y: n => {
25
+ tmp[n] = performance.now();
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;
46
35
  }
47
36
  }
48
37
  });
@@ -53,30 +42,33 @@ try {
53
42
 
54
43
  const total = performance.now() - start;
55
44
 
56
- console.log(`\nsamples: ${fast ? 'not measured' : samples}\ntotal: ${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 => {
57
46
  let time = 0;
58
47
  if (x.startsWith('profile')) {
59
- const id = parseInt(x.slice(8, x.indexOf(')')));
60
- time = fast ? tmp[id + 1] : tmp[id + 2];
48
+ const id = parseInt(x.slice(32, x.indexOf(')')));
49
+ time = times[id]
61
50
  }
62
51
 
63
52
  let color = [ 0, 0, 0 ];
64
53
  if (time) {
65
- const relativeTime = Math.sqrt(time / total);
54
+ let relativeTime = time / total;
66
55
  if (percents) time = relativeTime;
67
56
 
57
+ relativeTime = Math.sqrt(relativeTime);
68
58
  color = [ (relativeTime * 250) | 0, (Math.sin(relativeTime * Math.PI) * 50) | 0, 0 ];
69
59
  }
70
60
 
71
61
  const ansiColor = `2;${color[0]};${color[1]};${color[2]}m`;
72
62
 
73
- if (percents) return `\x1b[48;${ansiColor}\x1b[97m${time ? ((time * 100).toFixed(0).padStart(4, ' ') + '%') : ' '}\x1b[0m\x1b[38;${ansiColor}▌\x1b[0m ${x.replace(/profile\([0-9]+\);/g, '')}`;
63
+ const line = x.replace(/profile[0-9]\(Porffor.wasm.i32.const\([0-9]+\)\);/g, '');
64
+
65
+ if (percents) return `\x1b[48;${ansiColor}\x1b[97m${time ? ((time * 100).toFixed(0).padStart(4, ' ') + '%') : ' '}\x1b[0m\x1b[38;${ansiColor}▌\x1b[0m ${line}`;
74
66
 
75
67
  let digits = 2;
76
68
  if (time >= 100) digits = 1;
77
69
  if (time >= 1000) digits = 0;
78
70
 
79
- return `\x1b[48;${ansiColor}\x1b[97m${time ? time.toFixed(digits).padStart(6, ' ') : ' '}\x1b[0m\x1b[38;${ansiColor}▌\x1b[0m ${x.replace(/profile\([0-9]+\);/g, '')}`;
71
+ return `\x1b[48;${ansiColor}\x1b[97m${time ? time.toFixed(digits).padStart(6, ' ') : ' '}\x1b[0m\x1b[38;${ansiColor}▌\x1b[0m ${line}`;
80
72
  }).join('\n'));
81
73
  } catch (e) {
82
74
  console.error(e);
package/runner/repl.js CHANGED
@@ -1,17 +1,34 @@
1
1
  import compile from '../compiler/wrap.js';
2
2
  import rev from './version.js';
3
3
 
4
- import repl from 'node:repl';
5
-
6
- // process.argv.push('-O0'); // disable opts
4
+ let repl;
5
+ try {
6
+ // try importing node:repl
7
+ repl = await import('node:repl');
8
+
9
+ // check it is not just a mock with REPLServer prototype
10
+ if (repl.REPLServer.prototype.defineCommand == null)
11
+ throw 'mock node:repl detected';
12
+ } catch {
13
+ // it failed, import the polyfill
14
+ repl = (await import('node-repl-polyfill')).default;
15
+ }
7
16
 
8
17
  globalThis.valtype = 'f64';
9
18
 
10
- const valtypeOpt = process.argv.find(x => x.startsWith('-valtype='));
19
+ const valtypeOpt = process.argv.find(x => x.startsWith('--valtype='));
11
20
  if (valtypeOpt) valtype = valtypeOpt.split('=')[1];
12
21
 
13
- console.log(`welcome to porffor rev ${rev.slice(0, 7)}`);
14
- console.log(`info: using opt ${process.argv.find(x => x.startsWith('-O')) ?? '-O1'} and valtype ${valtype}`);
22
+ let host = globalThis?.navigator?.userAgent;
23
+ if (typeof process !== 'undefined' && process.argv0 === 'node') host = 'Node/' + process.versions.node;
24
+ host ??= 'Unknown';
25
+
26
+ if (host.startsWith('Node')) host = '\x1B[92m' + host;
27
+ if (host.startsWith('Deno')) host = '\x1B[97m' + host;
28
+ if (host.startsWith('Bun')) host = '\x1B[93m' + host;
29
+
30
+ 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`);
31
+ console.log(`\x1B[90musing opt ${process.argv.find(x => x.startsWith('-O')) ?? '-O1'}, parser ${parser}, valtype ${valtype}\x1B[0m`);
15
32
  console.log();
16
33
 
17
34
  let lastMemory, lastPages;
@@ -21,16 +38,27 @@ const memoryToString = mem => {
21
38
  const pages = lastPages.length;
22
39
  const wasmPages = mem.buffer.byteLength / PageSize;
23
40
 
24
- out += `\x1B[1mallocated ${mem.buffer.byteLength / 1024}KB\x1B[0m for ${pages} thing${pages === 1 ? '' : 's'} using ${wasmPages} Wasm page${wasmPages === 1 ? '' : 's'}\n`;
41
+ out += `\x1B[1mallocated ${mem.buffer.byteLength / 1024}KB\x1B[0m for ${pages} thing${pages === 1 ? '' : 's'} using ${wasmPages} Wasm page${wasmPages === 1 ? '' : 's'}\n\n`;
25
42
 
26
43
  const buf = new Uint8Array(mem.buffer);
27
44
 
45
+ let longestType = 0, longestName = 0;
46
+ for (const x of lastPages) {
47
+ const [ type, name ] = x.split(': ');
48
+ if (type.length > longestType) longestType = type.length;
49
+ if (name.length > longestName) longestName = name.length;
50
+ }
51
+
52
+ out += `\x1B[0m\x1B[1m name${' '.repeat(longestName - 4)} \x1B[0m\x1B[90m│\x1B[0m\x1B[1m type${' '.repeat(longestType - 4)} \x1B[0m\x1B[90m│\x1B[0m\x1B[1m memory\x1B[0m\n`; // ─
28
53
  for (let i = 0; i < pages; i++) {
29
- out += `\x1B[36m${lastPages[i]}\x1B[2m | \x1B[0m`;
54
+ const [ type, name ] = lastPages[i].split(': ');
55
+ // out += `\x1B[36m${lastPages[i].replace(':', '\x1B[90m:\x1B[34m')}\x1B[90m${' '.repeat(longestName - lastPages[i].length)} | \x1B[0m`;
56
+ out += ` \x1B[34m${name}${' '.repeat(longestName - name.length)} \x1B[90m│\x1B[0m \x1B[36m${type}${' '.repeat(longestType - type.length)} \x1B[90m│\x1B[0m `;
30
57
 
31
- for (let j = 0; j < 50; j++) {
58
+ for (let j = 0; j < 40; j++) {
32
59
  const val = buf[i * pageSize + j];
33
- if (val === 0) out += '\x1B[2m';
60
+ // if (val === 0) out += '\x1B[2m';
61
+ if (val === 0) out += '\x1B[90m';
34
62
  out += val.toString(16).padStart(2, '0');
35
63
  if (val === 0) out += '\x1B[0m';
36
64
  out += ' ';
@@ -48,11 +76,10 @@ const run = async (source, _context, _filename, callback, run = true) => {
48
76
  let toRun = (prev ? (prev + `;\nprint(-0x1337);\n`) : '') + source.trim();
49
77
 
50
78
  let shouldPrint = !prev;
51
- const { exports, wasm, pages } = await compile(toRun, [], {}, str => {
79
+ const { exports, pages } = await compile(toRun, [], {}, str => {
52
80
  if (shouldPrint) process.stdout.write(str);
53
81
  if (str === '-4919') shouldPrint = true;
54
82
  });
55
- // fs.writeFileSync('out.wasm', Buffer.from(wasm));
56
83
 
57
84
  if (run && exports.$) {
58
85
  lastMemory = exports.$;
@@ -83,7 +110,7 @@ replServer.defineCommand('asm', {
83
110
  this.clearBufferedCommand();
84
111
 
85
112
  try {
86
- process.argv.push('-opt-funcs');
113
+ process.argv.push('--opt-funcs');
87
114
  await run('', null, null, () => {}, false);
88
115
  process.argv.pop();
89
116
  } catch { }