porffor 0.20.10 → 0.21.0

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.
@@ -74,91 +74,94 @@ const generate = (scope, decl, global = false, name = undefined, valueUnused = f
74
74
  return cacheAst(decl, generateCode(scope, decl));
75
75
 
76
76
  case 'ReturnStatement':
77
- return cacheAst(decl, generateReturn(scope, decl))
77
+ return cacheAst(decl, generateReturn(scope, decl));
78
78
 
79
79
  case 'ExpressionStatement':
80
- return cacheAst(decl, generateExp(scope, decl))
80
+ return cacheAst(decl, generateExp(scope, decl));
81
81
 
82
82
  case 'SequenceExpression':
83
- return cacheAst(decl, generateSequence(scope, decl))
83
+ return cacheAst(decl, generateSequence(scope, decl));
84
84
 
85
85
  case 'ChainExpression':
86
- return cacheAst(decl, generateChain(scope, decl))
86
+ return cacheAst(decl, generateChain(scope, decl));
87
87
 
88
88
  case 'CallExpression':
89
- return cacheAst(decl, generateCall(scope, decl, global, name, valueUnused))
89
+ return cacheAst(decl, generateCall(scope, decl, global, name, valueUnused));
90
90
 
91
91
  case 'NewExpression':
92
- return cacheAst(decl, generateNew(scope, decl, global, name))
92
+ return cacheAst(decl, generateNew(scope, decl, global, name));
93
93
 
94
94
  case 'Literal':
95
- return cacheAst(decl, generateLiteral(scope, decl, global, name))
95
+ return cacheAst(decl, generateLiteral(scope, decl, global, name));
96
96
 
97
97
  case 'VariableDeclaration':
98
- return cacheAst(decl, generateVar(scope, decl))
98
+ return cacheAst(decl, generateVar(scope, decl));
99
99
 
100
100
  case 'AssignmentExpression':
101
- return cacheAst(decl, generateAssign(scope, decl))
101
+ return cacheAst(decl, generateAssign(scope, decl));
102
102
 
103
103
  case 'UnaryExpression':
104
- return cacheAst(decl, generateUnary(scope, decl))
104
+ return cacheAst(decl, generateUnary(scope, decl));
105
105
 
106
106
  case 'UpdateExpression':
107
- return cacheAst(decl, generateUpdate(scope, decl, global, name, valueUnused))
107
+ return cacheAst(decl, generateUpdate(scope, decl, global, name, valueUnused));
108
108
 
109
109
  case 'IfStatement':
110
- return cacheAst(decl, generateIf(scope, decl))
110
+ return cacheAst(decl, generateIf(scope, decl));
111
111
 
112
112
  case 'ForStatement':
113
- return cacheAst(decl, generateFor(scope, decl))
113
+ return cacheAst(decl, generateFor(scope, decl));
114
114
 
115
115
  case 'WhileStatement':
116
- return cacheAst(decl, generateWhile(scope, decl))
116
+ return cacheAst(decl, generateWhile(scope, decl));
117
117
 
118
118
  case 'DoWhileStatement':
119
- return cacheAst(decl, generateDoWhile(scope, decl))
119
+ return cacheAst(decl, generateDoWhile(scope, decl));
120
120
 
121
121
  case 'ForOfStatement':
122
- return cacheAst(decl, generateForOf(scope, decl))
122
+ return cacheAst(decl, generateForOf(scope, decl));
123
+
124
+ case 'ForInStatement':
125
+ return cacheAst(decl, generateForIn(scope, decl));
123
126
 
124
127
  case 'SwitchStatement':
125
- return cacheAst(decl, generateSwitch(scope, decl))
128
+ return cacheAst(decl, generateSwitch(scope, decl));
126
129
 
127
130
  case 'BreakStatement':
128
- return cacheAst(decl, generateBreak(scope, decl))
131
+ return cacheAst(decl, generateBreak(scope, decl));
129
132
 
130
133
  case 'ContinueStatement':
131
- return cacheAst(decl, generateContinue(scope, decl))
134
+ return cacheAst(decl, generateContinue(scope, decl));
132
135
 
133
136
  case 'LabeledStatement':
134
- return cacheAst(decl, generateLabel(scope, decl))
137
+ return cacheAst(decl, generateLabel(scope, decl));
135
138
 
136
139
  case 'EmptyStatement':
137
- return cacheAst(decl, generateEmpty(scope, decl))
140
+ return cacheAst(decl, generateEmpty(scope, decl));
138
141
 
139
142
  case 'MetaProperty':
140
- return cacheAst(decl, generateMeta(scope, decl))
143
+ return cacheAst(decl, generateMeta(scope, decl));
141
144
 
142
145
  case 'ConditionalExpression':
143
- return cacheAst(decl, generateConditional(scope, decl))
146
+ return cacheAst(decl, generateConditional(scope, decl));
144
147
 
145
148
  case 'ThrowStatement':
146
- return cacheAst(decl, generateThrow(scope, decl))
149
+ return cacheAst(decl, generateThrow(scope, decl));
147
150
 
148
151
  case 'TryStatement':
149
- return cacheAst(decl, generateTry(scope, decl))
152
+ return cacheAst(decl, generateTry(scope, decl));
150
153
 
151
154
  case 'DebuggerStatement':
152
- return cacheAst(decl, [[ Opcodes.call, importedFuncs.debugger ]])
155
+ return cacheAst(decl, [[ Opcodes.call, importedFuncs.debugger ]]);
153
156
 
154
157
  case 'ArrayExpression':
155
- return cacheAst(decl, generateArray(scope, decl, global, name))
158
+ return cacheAst(decl, generateArray(scope, decl, global, name));
156
159
 
157
160
  case 'ObjectExpression':
158
- return cacheAst(decl, generateObject(scope, decl, global, name))
161
+ return cacheAst(decl, generateObject(scope, decl, global, name));
159
162
 
160
163
  case 'MemberExpression':
161
- return cacheAst(decl, generateMember(scope, decl, global, name))
164
+ return cacheAst(decl, generateMember(scope, decl, global, name));
162
165
 
163
166
  case 'ExportNamedDeclaration':
164
167
  const funcsBefore = funcs.map(x => x.name);
@@ -173,7 +176,7 @@ const generate = (scope, decl, global = false, name = undefined, valueUnused = f
173
176
  }
174
177
  }
175
178
 
176
- return cacheAst(decl, [])
179
+ return cacheAst(decl, []);
177
180
 
178
181
  case 'TaggedTemplateExpression': {
179
182
  const funcs = {
@@ -228,7 +231,7 @@ const generate = (scope, decl, global = false, name = undefined, valueUnused = f
228
231
 
229
232
  const func = decl.tag.name;
230
233
  // hack for inline asm
231
- if (!funcs[func]) return cacheAst(decl, todo(scope, 'tagged template expressions not implemented', true))
234
+ if (!funcs[func]) return cacheAst(decl, todo(scope, 'tagged template expressions not implemented', true));
232
235
 
233
236
  const { quasis, expressions } = decl.quasi;
234
237
  let str = quasis[0].value.raw;
@@ -244,17 +247,17 @@ const generate = (scope, decl, global = false, name = undefined, valueUnused = f
244
247
  str += quasis[i + 1].value.raw;
245
248
  }
246
249
 
247
- return cacheAst(decl, funcs[func](str))
250
+ return cacheAst(decl, funcs[func](str));
248
251
  }
249
252
 
250
253
  default:
251
254
  // ignore typescript nodes
252
255
  if (decl.type.startsWith('TS') ||
253
256
  decl.type === 'ImportDeclaration' && decl.importKind === 'type') {
254
- return cacheAst(decl, [])
257
+ return cacheAst(decl, []);
255
258
  }
256
259
 
257
- return cacheAst(decl, todo(scope, `no generation for ${decl.type}!`))
260
+ return cacheAst(decl, todo(scope, `no generation for ${decl.type}!`));
258
261
  }
259
262
  };
260
263
 
@@ -3471,8 +3474,6 @@ const generateForOf = (scope, decl) => {
3471
3474
  generateVar(scope, { kind: 'var', _bare: true, declarations: [ { id: { name: leftName } } ] })
3472
3475
  }
3473
3476
 
3474
- // if (!leftName) console.log(decl.left?.declarations?.[0]?.id ?? decl.left);
3475
-
3476
3477
  const [ local, isGlobal ] = lookupName(scope, leftName);
3477
3478
  if (!local) return todo(scope, 'for of failed to get left local (probably destructure)');
3478
3479
 
@@ -3784,6 +3785,120 @@ const generateForOf = (scope, decl) => {
3784
3785
  return out;
3785
3786
  };
3786
3787
 
3788
+ const generateForIn = (scope, decl) => {
3789
+ const out = [];
3790
+
3791
+ // todo: for in inside for in might fuck up?
3792
+ const pointer = localTmp(scope, '#forin_base_pointer', Valtype.i32);
3793
+ const length = localTmp(scope, '#forin_length', Valtype.i32);
3794
+ const counter = localTmp(scope, '#forin_counter', Valtype.i32);
3795
+
3796
+ out.push(
3797
+ // set pointer as right
3798
+ ...generate(scope, decl.right),
3799
+ Opcodes.i32_to_u,
3800
+ [ Opcodes.local_set, pointer ],
3801
+
3802
+ // set counter as 0 (could be already used)
3803
+ ...number(0, Valtype.i32),
3804
+ [ Opcodes.local_set, counter ],
3805
+
3806
+ // get length
3807
+ [ Opcodes.local_get, pointer ],
3808
+ [ Opcodes.i32_load, Math.log2(ValtypeSize.i32) - 1, 0 ],
3809
+ [ Opcodes.local_tee, length ],
3810
+
3811
+ [ Opcodes.if, Blocktype.void ]
3812
+ );
3813
+
3814
+ depth.push('if');
3815
+ depth.push('forin');
3816
+ depth.push('block');
3817
+ depth.push('block');
3818
+
3819
+ // setup local for left
3820
+ generate(scope, decl.left);
3821
+
3822
+ let leftName = decl.left.declarations?.[0]?.id?.name;
3823
+ if (!leftName && decl.left.name) {
3824
+ // todo: should be sloppy mode only
3825
+ leftName = decl.left.name;
3826
+
3827
+ generateVar(scope, { kind: 'var', _bare: true, declarations: [ { id: { name: leftName } } ] })
3828
+ }
3829
+
3830
+ const [ local, isGlobal ] = lookupName(scope, leftName);
3831
+ if (!local) return todo(scope, 'for of failed to get left local (probably destructure)');
3832
+
3833
+ // set type for local
3834
+ // todo: optimize away counter and use end pointer
3835
+ out.push(...typeSwitch(scope, getNodeType(scope, decl.right), {
3836
+ [TYPES.object]: [
3837
+ [ Opcodes.loop, Blocktype.void ],
3838
+
3839
+ [ Opcodes.local_get, pointer ],
3840
+ [ Opcodes.i32_load, 0, 4 ],
3841
+ [ Opcodes.local_tee, localTmp(scope, '#forin_tmp', Valtype.i32) ],
3842
+
3843
+ ...setType(scope, leftName, [
3844
+ [ Opcodes.i32_const, 31 ],
3845
+ [ Opcodes.i32_shr_u ],
3846
+ [ Opcodes.if, Valtype.i32 ],
3847
+ // unset MSB in tmp
3848
+ [ Opcodes.local_get, localTmp(scope, '#forin_tmp', Valtype.i32) ],
3849
+ ...number(0x7fffffff, Valtype.i32),
3850
+ [ Opcodes.i32_and ],
3851
+ [ Opcodes.local_set, localTmp(scope, '#forin_tmp', Valtype.i32) ],
3852
+
3853
+ [ Opcodes.i32_const, ...unsignedLEB128(TYPES.string) ],
3854
+ [ Opcodes.else ],
3855
+ [ Opcodes.i32_const, ...unsignedLEB128(TYPES.bytestring) ],
3856
+ [ Opcodes.end ]
3857
+ ]),
3858
+
3859
+ [ Opcodes.local_get, localTmp(scope, '#forin_tmp', Valtype.i32) ],
3860
+ Opcodes.i32_from_u,
3861
+ [ isGlobal ? Opcodes.global_set : Opcodes.local_set, local.idx ],
3862
+
3863
+ [ Opcodes.block, Blocktype.void ],
3864
+ [ Opcodes.block, Blocktype.void ],
3865
+ ...generate(scope, decl.body),
3866
+ [ Opcodes.end ],
3867
+
3868
+ // increment iter pointer by 14
3869
+ [ Opcodes.local_get, pointer ],
3870
+ ...number(14, Valtype.i32),
3871
+ [ Opcodes.i32_add ],
3872
+ [ Opcodes.local_set, pointer ],
3873
+
3874
+ // increment counter by 1
3875
+ [ Opcodes.local_get, counter ],
3876
+ ...number(1, Valtype.i32),
3877
+ [ Opcodes.i32_add ],
3878
+ [ Opcodes.local_tee, counter ],
3879
+
3880
+ // loop if counter != length
3881
+ [ Opcodes.local_get, length ],
3882
+ [ Opcodes.i32_ne ],
3883
+ [ Opcodes.br_if, 1 ],
3884
+
3885
+ [ Opcodes.end ],
3886
+ [ Opcodes.end ]
3887
+ ],
3888
+
3889
+ // todo: use Object.keys as fallback
3890
+ default: internalThrow(scope, 'TypeError', `Tried for..in on unsupported type`)
3891
+ }, Blocktype.void));
3892
+
3893
+ out.push([ Opcodes.end ]); // end if
3894
+
3895
+ depth.pop();
3896
+ depth.pop();
3897
+ depth.pop();
3898
+
3899
+ return out;
3900
+ };
3901
+
3787
3902
  const generateSwitch = (scope, decl) => {
3788
3903
  const tmp = localTmp(scope, '#switch_disc');
3789
3904
  const out = [
@@ -3840,7 +3955,7 @@ const generateSwitch = (scope, decl) => {
3840
3955
  // find the nearest loop in depth map by type
3841
3956
  const getNearestLoop = () => {
3842
3957
  for (let i = depth.length - 1; i >= 0; i--) {
3843
- if (['while', 'dowhile', 'for', 'forof', 'switch'].includes(depth[i])) return i;
3958
+ if (['while', 'dowhile', 'for', 'forof', 'forin', 'switch'].includes(depth[i])) return i;
3844
3959
  }
3845
3960
 
3846
3961
  return -1;
@@ -3859,6 +3974,7 @@ const generateBreak = (scope, decl) => {
3859
3974
  while: 2, // loop > if (wanted branch) (we are here)
3860
3975
  dowhile: 2, // loop > block (wanted branch) > block (we are here)
3861
3976
  forof: 2, // loop > block (wanted branch) > block (we are here)
3977
+ forin: 2, // loop > block (wanted branch) > block (we are here)
3862
3978
  if: 1, // break inside if, branch 0 to skip the rest of the if
3863
3979
  switch: 1
3864
3980
  })[type];
@@ -3880,7 +3996,8 @@ const generateContinue = (scope, decl) => {
3880
3996
  for: 3, // loop (wanted branch) > if > block (we are here)
3881
3997
  while: 1, // loop (wanted branch) > if (we are here)
3882
3998
  dowhile: 3, // loop > block > block (wanted branch) (we are here)
3883
- forof: 3 // loop > block > block (wanted branch) (we are here)
3999
+ forof: 3, // loop > block > block (wanted branch) (we are here)
4000
+ forin: 3 // loop > block > block (wanted branch) (we are here)
3884
4001
  })[type];
3885
4002
 
3886
4003
  return [
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.20.10+137dc7300",
4
+ "version": "0.21.0+0c514ac58",
5
5
  "author": "CanadaHonk",
6
6
  "license": "MIT",
7
7
  "scripts": {},
package/runner/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import fs from 'node:fs';
3
- globalThis.version = '0.20.10+137dc7300';
3
+ globalThis.version = '0.21.0+0c514ac58';
4
4
 
5
5
  // deno compat
6
6
  if (typeof process === 'undefined' && typeof Deno !== 'undefined') {