porffor 0.0.0-1989c22 → 0.0.0-44bc2d8

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.
package/README.md CHANGED
@@ -76,6 +76,7 @@ these include some early (stage 1/0) and/or dead (last commit years ago) proposa
76
76
  - string member (char) access via `str[ind]` (eg `str[0]`)
77
77
  - string concat (`+`) (eg `'a' + 'b'`)
78
78
  - truthy/falsy (eg `!'' == true`)
79
+ - string comparison (eg `'a' == 'a'`, `'a' != 'b'`)
79
80
 
80
81
  ### built-ins
81
82
 
@@ -106,7 +107,6 @@ these include some early (stage 1/0) and/or dead (last commit years ago) proposa
106
107
  - arrays/strings inside arrays
107
108
  - strings
108
109
  - member setting
109
- - equality
110
110
  - more math operators (`**`, etc)
111
111
  - `do { ... } while (...)`
112
112
  - exceptions
@@ -101,6 +101,9 @@ const generate = (scope, decl, global = false, name = undefined) => {
101
101
  case 'WhileStatement':
102
102
  return generateWhile(scope, decl);
103
103
 
104
+ /* case 'ForOfStatement':
105
+ return generateForOf(scope, decl); */
106
+
104
107
  case 'BreakStatement':
105
108
  return generateBreak(scope, decl);
106
109
 
@@ -472,9 +475,6 @@ const compareStrings = (scope, left, right) => {
472
475
  const indexEnd = localTmp(scope, 'compare_index_end', Valtype.i32);
473
476
 
474
477
  return [
475
- // use block to "return" a value early
476
- [ Opcodes.block, Valtype.i32 ],
477
-
478
478
  // setup left
479
479
  ...left,
480
480
  Opcodes.i32_to_u,
@@ -486,11 +486,9 @@ const compareStrings = (scope, left, right) => {
486
486
  [ Opcodes.local_tee, rightPointer ],
487
487
 
488
488
  // fast path: check leftPointer == rightPointer
489
- [ Opcodes.i32_eq ],
490
- [ Opcodes.if, Blocktype.void ],
491
- ...number(1, Valtype.i32),
492
- [ Opcodes.br, 1 ],
493
- [ Opcodes.end ],
489
+ // use if (block) for everything after to "return" a value early
490
+ [ Opcodes.i32_ne ],
491
+ [ Opcodes.if, Valtype.i32 ],
494
492
 
495
493
  // get lengths
496
494
  [ Opcodes.local_get, leftPointer ],
@@ -553,6 +551,10 @@ const compareStrings = (scope, left, right) => {
553
551
 
554
552
  // no failed checks, so true!
555
553
  ...number(1, Valtype.i32),
554
+
555
+ // pointers match, so true
556
+ [ Opcodes.else ],
557
+ ...number(1, Valtype.i32),
556
558
  [ Opcodes.end ],
557
559
 
558
560
  // convert i32 result to valtype
@@ -1552,6 +1554,25 @@ const generateWhile = (scope, decl) => {
1552
1554
  return out;
1553
1555
  };
1554
1556
 
1557
+ const generateForOf = (scope, decl) => {
1558
+ const out = [];
1559
+
1560
+ out.push([ Opcodes.loop, Blocktype.void ]);
1561
+ depth.push('while');
1562
+
1563
+ out.push(...generate(scope, decl.test));
1564
+ out.push(Opcodes.i32_to, [ Opcodes.if, Blocktype.void ]);
1565
+ depth.push('if');
1566
+
1567
+ out.push(...generate(scope, decl.body));
1568
+
1569
+ out.push([ Opcodes.br, 1 ]);
1570
+ out.push([ Opcodes.end ], [ Opcodes.end ]);
1571
+ depth.pop(); depth.pop();
1572
+
1573
+ return out;
1574
+ };
1575
+
1555
1576
  const getNearestLoop = () => {
1556
1577
  for (let i = depth.length - 1; i >= 0; i--) {
1557
1578
  if (depth[i] === 'while' || depth[i] === 'for' || depth[i] === 'forof') return i;
package/compiler/opt.js CHANGED
@@ -20,7 +20,7 @@ export default (funcs, globals) => {
20
20
  if (optLevel === 0) return;
21
21
 
22
22
  const tailCall = process.argv.includes('-tail-call');
23
- if (tailCall) log('opt', 'tail call proposal is not widely implemented! (you used -tail-call)');
23
+ if (tailCall) log('opt', 'warning: tail call proposal is not widely implemented! (you used -tail-call)');
24
24
 
25
25
  if (optLevel >= 2 && !process.argv.includes('-opt-no-inline')) {
26
26
  // inline pass (very WIP)
@@ -36,7 +36,7 @@ export default (funcs, globals, tags, pages, flags) => {
36
36
  // tree shake imports
37
37
  for (const f of funcs) {
38
38
  for (const inst of f.wasm) {
39
- if (inst[0] === Opcodes.call && inst[1] < importedFuncs.length) {
39
+ if ((inst[0] === Opcodes.call || inst[0] === Opcodes.return_call) && inst[1] < importedFuncs.length) {
40
40
  const idx = inst[1];
41
41
  const func = importedFuncs[idx];
42
42
 
@@ -51,10 +51,11 @@ export default (funcs, globals, tags, pages, flags) => {
51
51
  // fix call indexes for non-imports
52
52
  const delta = importedFuncs.length - importFuncs.length;
53
53
  for (const f of funcs) {
54
+ f.originalIndex = f.index;
54
55
  f.index -= delta;
55
56
 
56
57
  for (const inst of f.wasm) {
57
- if (inst[0] === Opcodes.call && inst[1] >= importedFuncs.length) {
58
+ if ((inst[0] === Opcodes.call || inst[0] === Opcodes.return_call) && inst[1] >= importedFuncs.length) {
58
59
  inst[1] -= delta;
59
60
  }
60
61
  }
package/compiler/wrap.js CHANGED
@@ -90,6 +90,15 @@ export default async (source, flags = [ 'module' ], customImports = {}, print =
90
90
  return Array.from(new Uint16Array(memory.buffer, pointer + 4, length)).map(x => String.fromCharCode(x)).join('');
91
91
  }
92
92
 
93
+ case 'function': {
94
+ // wasm func index, including all imports
95
+ const func = funcs.find(x => (x.originalIndex ?? x.index) === ret);
96
+ if (!func) return ret;
97
+
98
+ // make fake empty func for repl/etc
99
+ return {[func.name]() {}}[func.name];
100
+ }
101
+
93
102
  default: return ret;
94
103
  }
95
104
  } catch (e) {
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.0.0-1989c22",
4
+ "version": "0.0.0-44bc2d8",
5
5
  "author": "CanadaHonk",
6
6
  "license": "MIT",
7
7
  "dependencies": {
package/runner/repl.js CHANGED
@@ -48,10 +48,12 @@ const memoryToString = mem => {
48
48
  return out;
49
49
  };
50
50
 
51
+ const alwaysPrev = process.argv.includes('-always-prev');
52
+
51
53
  let prev = '';
52
54
  const run = async (source, _context, _filename, callback, run = true) => {
53
55
  let toRun = prev + source.trim();
54
- // prev = toRun + ';\n';
56
+ if (alwaysPrev) prev = toRun + ';\n';
55
57
 
56
58
  const { exports, wasm, pages } = await compile(toRun, []);
57
59
  fs.writeFileSync('out.wasm', Buffer.from(wasm));
@@ -64,7 +66,7 @@ const run = async (source, _context, _filename, callback, run = true) => {
64
66
  const ret = run ? exports.main() : undefined;
65
67
  callback(null, ret);
66
68
 
67
- if (source.includes(' = ') || source.includes('let ') || source.includes('var ') || source.includes('const ') || source.includes('function ')) prev = toRun + ';\n';
69
+ if (!alwaysPrev && (source.includes(' = ') || source.includes('let ') || source.includes('var ') || source.includes('const ') || source.includes('function '))) prev = toRun + ';\n';
68
70
  // prev = toRun + ';\n';
69
71
  };
70
72