porffor 0.2.0-a6c01f5 → 0.2.0-ae8cbb8

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.
@@ -59,6 +59,10 @@ const todo = (scope, msg, expectsValue = undefined) => {
59
59
  };
60
60
 
61
61
  const isFuncType = type => type === 'FunctionDeclaration' || type === 'FunctionExpression' || type === 'ArrowFunctionExpression';
62
+ const hasFuncWithName = name => {
63
+ const func = funcs.find(x => x.name === name);
64
+ return !!(func || builtinFuncs[name] || importedFuncs[name] || internalConstrs[name])
65
+ };
62
66
  const generate = (scope, decl, global = false, name = undefined, valueUnused = false) => {
63
67
  switch (decl.type) {
64
68
  case 'BinaryExpression':
@@ -201,7 +205,7 @@ const generate = (scope, decl, global = false, name = undefined, valueUnused = f
201
205
  }
202
206
 
203
207
  let inst = Opcodes[asm[0].replace('.', '_')];
204
- if (!inst) throw new Error(`inline asm: inst ${asm[0]} not found`);
208
+ if (inst == null) throw new Error(`inline asm: inst ${asm[0]} not found`);
205
209
 
206
210
  if (!Array.isArray(inst)) inst = [ inst ];
207
211
  const immediates = asm.slice(1).map(x => {
@@ -219,8 +223,8 @@ const generate = (scope, decl, global = false, name = undefined, valueUnused = f
219
223
  __Porffor_bs: str => [
220
224
  ...makeString(scope, str, global, name, true),
221
225
 
222
- ...(name ? setType(scope, name, TYPES._bytestring) : [
223
- ...number(TYPES._bytestring, Valtype.i32),
226
+ ...(name ? setType(scope, name, TYPES.bytestring) : [
227
+ ...number(TYPES.bytestring, Valtype.i32),
224
228
  ...setLastType(scope)
225
229
  ])
226
230
  ],
@@ -460,7 +464,7 @@ const concatStrings = (scope, left, right, global, name, assign = false, bytestr
460
464
  const rightLength = localTmp(scope, 'concat_right_length', Valtype.i32);
461
465
  const leftLength = localTmp(scope, 'concat_left_length', Valtype.i32);
462
466
 
463
- if (assign) {
467
+ if (assign && Prefs.aotPointerOpt) {
464
468
  const pointer = scope.arrays?.get(name ?? '$undeclared');
465
469
 
466
470
  return [
@@ -723,7 +727,7 @@ const truthy = (scope, wasm, type, intIn = false, intOut = false) => {
723
727
 
724
728
  ...typeSwitch(scope, type, {
725
729
  // [TYPES.number]: def,
726
- [TYPES._array]: [
730
+ [TYPES.array]: [
727
731
  // arrays are always truthy
728
732
  ...number(1, intOut ? Valtype.i32 : valtypeBinary)
729
733
  ],
@@ -739,7 +743,7 @@ const truthy = (scope, wasm, type, intIn = false, intOut = false) => {
739
743
  [ Opcodes.i32_eqz ], */
740
744
  ...(intOut ? [] : [ Opcodes.i32_from_u ])
741
745
  ],
742
- [TYPES._bytestring]: [ // duplicate of string
746
+ [TYPES.bytestring]: [ // duplicate of string
743
747
  ...(!useTmp ? [] : [ [ Opcodes.local_get, tmp ] ]),
744
748
  ...(intIn ? [] : [ Opcodes.i32_to_u ]),
745
749
 
@@ -762,7 +766,7 @@ const falsy = (scope, wasm, type, intIn = false, intOut = false) => {
762
766
  ...(!useTmp ? [] : [ [ Opcodes.local_set, tmp ] ]),
763
767
 
764
768
  ...typeSwitch(scope, type, {
765
- [TYPES._array]: [
769
+ [TYPES.array]: [
766
770
  // arrays are always truthy
767
771
  ...number(0, intOut ? Valtype.i32 : valtypeBinary)
768
772
  ],
@@ -777,7 +781,7 @@ const falsy = (scope, wasm, type, intIn = false, intOut = false) => {
777
781
  [ Opcodes.i32_eqz ],
778
782
  ...(intOut ? [] : [ Opcodes.i32_from_u ])
779
783
  ],
780
- [TYPES._bytestring]: [ // duplicate of string
784
+ [TYPES.bytestring]: [ // duplicate of string
781
785
  ...(!useTmp ? [] : [ [ Opcodes.local_get, tmp ] ]),
782
786
  ...(intIn ? [] : [ Opcodes.i32_to_u ]),
783
787
 
@@ -922,7 +926,7 @@ const performOp = (scope, op, left, right, leftType, rightType, _global = false,
922
926
  }
923
927
  }
924
928
 
925
- if (knownLeft === TYPES._bytestring || knownRight === TYPES._bytestring) {
929
+ if (knownLeft === TYPES.bytestring || knownRight === TYPES.bytestring) {
926
930
  if (op === '+') {
927
931
  // todo: this should be dynamic too but for now only static
928
932
  // string concat (a + b)
@@ -1041,12 +1045,12 @@ const performOp = (scope, op, left, right, leftType, rightType, _global = false,
1041
1045
 
1042
1046
  // if left is bytestring
1043
1047
  ...leftType,
1044
- ...number(TYPES._bytestring, Valtype.i32),
1048
+ ...number(TYPES.bytestring, Valtype.i32),
1045
1049
  [ Opcodes.i32_eq ],
1046
1050
 
1047
1051
  // if right is bytestring
1048
1052
  ...rightType,
1049
- ...number(TYPES._bytestring, Valtype.i32),
1053
+ ...number(TYPES.bytestring, Valtype.i32),
1050
1054
  [ Opcodes.i32_eq ],
1051
1055
 
1052
1056
  // if both are true
@@ -1177,7 +1181,6 @@ const generateLogicExp = (scope, decl) => {
1177
1181
  // js type: 4 bits
1178
1182
  // internal type: ? bits
1179
1183
  // pointer: 32 bits
1180
-
1181
1184
  // generic
1182
1185
  // 1 23 4 5
1183
1186
  // 0 11111111111 11TTTTIIII??????????PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP
@@ -1188,7 +1191,7 @@ const generateLogicExp = (scope, decl) => {
1188
1191
  // 5: pointer
1189
1192
 
1190
1193
  const isExistingProtoFunc = name => {
1191
- if (name.startsWith('__Array_prototype')) return !!prototypeFuncs[TYPES._array][name.slice(18)];
1194
+ if (name.startsWith('__Array_prototype')) return !!prototypeFuncs[TYPES.array][name.slice(18)];
1192
1195
  if (name.startsWith('__String_prototype_')) return !!prototypeFuncs[TYPES.string][name.slice(19)];
1193
1196
 
1194
1197
  return false;
@@ -1247,9 +1250,9 @@ const setLastType = scope => {
1247
1250
  const getNodeType = (scope, node) => {
1248
1251
  const inner = () => {
1249
1252
  if (node.type === 'Literal') {
1250
- if (node.regex) return TYPES._regexp;
1253
+ if (node.regex) return TYPES.regexp;
1251
1254
 
1252
- if (typeof node.value === 'string' && byteStringable(node.value)) return TYPES._bytestring;
1255
+ if (typeof node.value === 'string' && byteStringable(node.value)) return TYPES.bytestring;
1253
1256
 
1254
1257
  return TYPES[typeof node.value];
1255
1258
  }
@@ -1303,7 +1306,7 @@ const getNodeType = (scope, node) => {
1303
1306
  const spl = name.slice(2).split('_');
1304
1307
 
1305
1308
  const func = spl[spl.length - 1];
1306
- const protoFuncs = Object.keys(prototypeFuncs).filter(x => x != TYPES._bytestring && prototypeFuncs[x][func] != null);
1309
+ const protoFuncs = Object.keys(prototypeFuncs).filter(x => x != TYPES.bytestring && prototypeFuncs[x][func] != null);
1307
1310
  if (protoFuncs.length === 1) return protoFuncs[0].returnType ?? TYPES.number;
1308
1311
  }
1309
1312
 
@@ -1355,7 +1358,7 @@ const getNodeType = (scope, node) => {
1355
1358
  }
1356
1359
 
1357
1360
  if (node.type === 'ArrayExpression') {
1358
- return TYPES._array;
1361
+ return TYPES.array;
1359
1362
  }
1360
1363
 
1361
1364
  if (node.type === 'BinaryExpression') {
@@ -1367,7 +1370,7 @@ const getNodeType = (scope, node) => {
1367
1370
 
1368
1371
  // todo: this should be dynamic but for now only static
1369
1372
  if (knownLeft === TYPES.string || knownRight === TYPES.string) return TYPES.string;
1370
- if (knownLeft === TYPES._bytestring || knownRight === TYPES._bytestring) return TYPES._bytestring;
1373
+ if (knownLeft === TYPES.bytestring || knownRight === TYPES.bytestring) return TYPES.bytestring;
1371
1374
 
1372
1375
  return TYPES.number;
1373
1376
 
@@ -1393,19 +1396,28 @@ const getNodeType = (scope, node) => {
1393
1396
  if (node.operator === '!') return TYPES.boolean;
1394
1397
  if (node.operator === 'void') return TYPES.undefined;
1395
1398
  if (node.operator === 'delete') return TYPES.boolean;
1396
- if (node.operator === 'typeof') return Prefs.bytestring ? TYPES._bytestring : TYPES.string;
1399
+ if (node.operator === 'typeof') return Prefs.bytestring ? TYPES.bytestring : TYPES.string;
1397
1400
 
1398
1401
  return TYPES.number;
1399
1402
  }
1400
1403
 
1401
1404
  if (node.type === 'MemberExpression') {
1405
+ // hack: if something.name, string type
1406
+ if (node.property.name === 'name') {
1407
+ if (hasFuncWithName(node.object.name)) {
1408
+ return TYPES.bytestring;
1409
+ } else {
1410
+ return TYPES.undefined;
1411
+ }
1412
+ }
1413
+
1402
1414
  // hack: if something.length, number type
1403
1415
  if (node.property.name === 'length') return TYPES.number;
1404
1416
 
1405
1417
  // ts hack
1406
1418
  if (scope.locals[node.object.name]?.metadata?.type === TYPES.string) return TYPES.string;
1407
- if (scope.locals[node.object.name]?.metadata?.type === TYPES._bytestring) return TYPES._bytestring;
1408
- if (scope.locals[node.object.name]?.metadata?.type === TYPES._array) return TYPES.number;
1419
+ if (scope.locals[node.object.name]?.metadata?.type === TYPES.bytestring) return TYPES.bytestring;
1420
+ if (scope.locals[node.object.name]?.metadata?.type === TYPES.array) return TYPES.number;
1409
1421
 
1410
1422
  if (scope.locals['#last_type']) return getLastType(scope);
1411
1423
 
@@ -1646,18 +1658,25 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
1646
1658
  // megahack for /regex/.func()
1647
1659
  const funcName = decl.callee.property.name;
1648
1660
  if (decl.callee.object.regex && Object.hasOwn(Rhemyn, funcName)) {
1649
- const func = Rhemyn[funcName](decl.callee.object.regex.pattern, currentFuncIndex++);
1661
+ const regex = decl.callee.object.regex.pattern;
1662
+ const rhemynName = `regex_${funcName}_${regex}`;
1650
1663
 
1651
- funcIndex[func.name] = func.index;
1652
- funcs.push(func);
1664
+ if (!funcIndex[rhemynName]) {
1665
+ const func = Rhemyn[funcName](regex, currentFuncIndex++, rhemynName);
1653
1666
 
1667
+ funcIndex[func.name] = func.index;
1668
+ funcs.push(func);
1669
+ }
1670
+
1671
+ const idx = funcIndex[rhemynName];
1654
1672
  return [
1655
1673
  // make string arg
1656
1674
  ...generate(scope, decl.arguments[0]),
1675
+ Opcodes.i32_to_u,
1676
+ ...getNodeType(scope, decl.arguments[0]),
1657
1677
 
1658
1678
  // call regex func
1659
- Opcodes.i32_to_u,
1660
- [ Opcodes.call, func.index ],
1679
+ [ Opcodes.call, idx ],
1661
1680
  Opcodes.i32_from_u,
1662
1681
 
1663
1682
  ...number(TYPES.boolean, Valtype.i32),
@@ -1820,20 +1839,20 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
1820
1839
  idx = funcIndex[name];
1821
1840
 
1822
1841
  // infer arguments types from builtins params
1823
- const func = funcs.find(x => x.name === name);
1824
- for (let i = 0; i < decl.arguments.length; i++) {
1825
- const arg = decl.arguments[i];
1826
- if (!arg.name) continue;
1827
-
1828
- const local = scope.locals[arg.name];
1829
- if (!local) continue;
1830
-
1831
- local.type = func.params[i];
1832
- if (local.type === Valtype.v128) {
1833
- // specify vec subtype inferred from last vec type in function name
1834
- local.vecType = name.split('_').reverse().find(x => x.includes('x'));
1835
- }
1836
- }
1842
+ // const func = funcs.find(x => x.name === name);
1843
+ // for (let i = 0; i < decl.arguments.length; i++) {
1844
+ // const arg = decl.arguments[i];
1845
+ // if (!arg.name) continue;
1846
+
1847
+ // const local = scope.locals[arg.name];
1848
+ // if (!local) continue;
1849
+
1850
+ // local.type = func.params[i];
1851
+ // if (local.type === Valtype.v128) {
1852
+ // // specify vec subtype inferred from last vec type in function name
1853
+ // local.vecType = name.split('_').reverse().find(x => x.includes('x'));
1854
+ // }
1855
+ // }
1837
1856
  }
1838
1857
 
1839
1858
  if (idx === undefined && internalConstrs[name]) return internalConstrs[name].generate(scope, decl, _global, _name);
@@ -1865,9 +1884,6 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
1865
1884
 
1866
1885
  // value
1867
1886
  i32_const: { imms: 1, args: [], returns: 1 },
1868
-
1869
- // a, b
1870
- i32_or: { imms: 0, args: [ true, true ], returns: 1 },
1871
1887
  };
1872
1888
 
1873
1889
  const opName = name.slice('__Porffor_wasm_'.length);
@@ -2088,7 +2104,7 @@ const brTable = (input, bc, returns) => {
2088
2104
  };
2089
2105
 
2090
2106
  const typeSwitch = (scope, type, bc, returns = valtypeBinary) => {
2091
- if (!Prefs.bytestring) delete bc[TYPES._bytestring];
2107
+ if (!Prefs.bytestring) delete bc[TYPES.bytestring];
2092
2108
 
2093
2109
  const known = knownType(scope, type);
2094
2110
  if (known != null) {
@@ -2191,7 +2207,7 @@ const extractTypeAnnotation = decl => {
2191
2207
  const typeName = type;
2192
2208
  type = typeAnnoToPorfType(type);
2193
2209
 
2194
- if (type === TYPES._bytestring && !Prefs.bytestring) type = TYPES.string;
2210
+ if (type === TYPES.bytestring && !Prefs.bytestring) type = TYPES.string;
2195
2211
 
2196
2212
  // if (decl.name) console.log(decl.name, { type, elementType });
2197
2213
 
@@ -2205,6 +2221,7 @@ const generateVar = (scope, decl) => {
2205
2221
 
2206
2222
  // global variable if in top scope (main) and var ..., or if wanted
2207
2223
  const global = topLevel || decl._bare; // decl.kind === 'var';
2224
+ const target = global ? globals : scope.locals;
2208
2225
 
2209
2226
  for (const x of decl.declarations) {
2210
2227
  const name = mapName(x.id.name);
@@ -2226,6 +2243,10 @@ const generateVar = (scope, decl) => {
2226
2243
  continue; // always ignore
2227
2244
  }
2228
2245
 
2246
+ // // generate init before allocating var
2247
+ // let generated;
2248
+ // if (x.init) generated = generate(scope, x.init, global, name);
2249
+
2229
2250
  const typed = typedInput && x.id.typeAnnotation;
2230
2251
  let idx = allocVar(scope, name, global, !(typed && extractTypeAnnotation(x.id).type != null));
2231
2252
 
@@ -2234,9 +2255,17 @@ const generateVar = (scope, decl) => {
2234
2255
  }
2235
2256
 
2236
2257
  if (x.init) {
2237
- out = out.concat(generate(scope, x.init, global, name));
2238
-
2239
- out.push([ global ? Opcodes.global_set : Opcodes.local_set, idx ]);
2258
+ const generated = generate(scope, x.init, global, name);
2259
+ if (scope.arrays?.get(name) != null) {
2260
+ // hack to set local as pointer before
2261
+ out.push(...number(scope.arrays.get(name)), [ global ? Opcodes.global_set : Opcodes.local_set, idx ]);
2262
+ if (generated.at(-1) == Opcodes.i32_from_u) generated.pop();
2263
+ generated.pop();
2264
+ out = out.concat(generated);
2265
+ } else {
2266
+ out = out.concat(generated);
2267
+ out.push([ global ? Opcodes.global_set : Opcodes.local_set, idx ]);
2268
+ }
2240
2269
  out.push(...setType(scope, name, getNodeType(scope, x.init)));
2241
2270
  }
2242
2271
 
@@ -2263,6 +2292,8 @@ const generateAssign = (scope, decl, _global, _name, valueUnused = false) => {
2263
2292
  return [];
2264
2293
  }
2265
2294
 
2295
+ const op = decl.operator.slice(0, -1) || '=';
2296
+
2266
2297
  // hack: .length setter
2267
2298
  if (decl.left.type === 'MemberExpression' && decl.left.property.name === 'length') {
2268
2299
  const name = decl.left.object.name;
@@ -2271,14 +2302,20 @@ const generateAssign = (scope, decl, _global, _name, valueUnused = false) => {
2271
2302
  const aotPointer = Prefs.aotPointerOpt && pointer != null;
2272
2303
 
2273
2304
  const newValueTmp = localTmp(scope, '__length_setter_tmp');
2305
+ const pointerTmp = op === '=' ? null : localTmp(scope, '__member_setter_ptr_tmp', Valtype.i32);
2274
2306
 
2275
2307
  return [
2276
2308
  ...(aotPointer ? number(0, Valtype.i32) : [
2277
2309
  ...generate(scope, decl.left.object),
2278
2310
  Opcodes.i32_to_u
2279
2311
  ]),
2312
+ ...(!pointerTmp ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
2280
2313
 
2281
- ...generate(scope, decl.right),
2314
+ ...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
2315
+ [ Opcodes.local_get, pointerTmp ],
2316
+ [ Opcodes.i32_load, Math.log2(ValtypeSize.i32) - 1, 0 ],
2317
+ Opcodes.i32_from_u
2318
+ ], generate(scope, decl.right), number(TYPES.number, Valtype.i32), getNodeType(scope, decl.right))),
2282
2319
  [ Opcodes.local_tee, newValueTmp ],
2283
2320
 
2284
2321
  Opcodes.i32_to_u,
@@ -2288,8 +2325,6 @@ const generateAssign = (scope, decl, _global, _name, valueUnused = false) => {
2288
2325
  ];
2289
2326
  }
2290
2327
 
2291
- const op = decl.operator.slice(0, -1) || '=';
2292
-
2293
2328
  // arr[i]
2294
2329
  if (decl.left.type === 'MemberExpression' && decl.left.computed) {
2295
2330
  const name = decl.left.object.name;
@@ -2302,7 +2337,7 @@ const generateAssign = (scope, decl, _global, _name, valueUnused = false) => {
2302
2337
 
2303
2338
  return [
2304
2339
  ...typeSwitch(scope, getNodeType(scope, decl.left.object), {
2305
- [TYPES._array]: [
2340
+ [TYPES.array]: [
2306
2341
  ...(aotPointer ? [] : [
2307
2342
  ...generate(scope, decl.left.object),
2308
2343
  Opcodes.i32_to_u
@@ -2504,7 +2539,7 @@ const generateUnary = (scope, decl) => {
2504
2539
  [TYPES.undefined]: makeString(scope, 'undefined', false, '#typeof_result'),
2505
2540
  [TYPES.function]: makeString(scope, 'function', false, '#typeof_result'),
2506
2541
 
2507
- [TYPES._bytestring]: makeString(scope, 'string', false, '#typeof_result'),
2542
+ [TYPES.bytestring]: makeString(scope, 'string', false, '#typeof_result'),
2508
2543
 
2509
2544
  // object and internal types
2510
2545
  default: makeString(scope, 'object', false, '#typeof_result'),
@@ -2740,7 +2775,7 @@ const generateForOf = (scope, decl) => {
2740
2775
  // set type for local
2741
2776
  // todo: optimize away counter and use end pointer
2742
2777
  out.push(...typeSwitch(scope, getNodeType(scope, decl.right), {
2743
- [TYPES._array]: [
2778
+ [TYPES.array]: [
2744
2779
  ...setType(scope, leftName, TYPES.number),
2745
2780
 
2746
2781
  [ Opcodes.loop, Blocktype.void ],
@@ -2823,8 +2858,8 @@ const generateForOf = (scope, decl) => {
2823
2858
  [ Opcodes.end ],
2824
2859
  [ Opcodes.end ]
2825
2860
  ],
2826
- [TYPES._bytestring]: [
2827
- ...setType(scope, leftName, TYPES._bytestring),
2861
+ [TYPES.bytestring]: [
2862
+ ...setType(scope, leftName, TYPES.bytestring),
2828
2863
 
2829
2864
  [ Opcodes.loop, Blocktype.void ],
2830
2865
 
@@ -3093,12 +3128,14 @@ const makeArray = (scope, decl, global = false, name = '$undeclared', initEmpty
3093
3128
  // todo: can we just have 1 undeclared array? probably not? but this is not really memory efficient
3094
3129
  const uniqueName = name === '$undeclared' ? name + Math.random().toString().slice(2) : name;
3095
3130
 
3096
- if (Prefs.scopedPageNames) scope.arrays.set(name, allocPage(scope, `${scope.name} | ${getAllocType(itemType)}: ${uniqueName}`, itemType) * pageSize);
3131
+ if (Prefs.scopedPageNames) scope.arrays.set(name, allocPage(scope, `${getAllocType(itemType)}: ${scope.name}/${uniqueName}`, itemType) * pageSize);
3097
3132
  else scope.arrays.set(name, allocPage(scope, `${getAllocType(itemType)}: ${uniqueName}`, itemType) * pageSize);
3098
3133
  }
3099
3134
 
3100
3135
  const pointer = scope.arrays.get(name);
3101
3136
 
3137
+ const local = global ? globals[name] : scope.locals[name];
3138
+
3102
3139
  const useRawElements = !!decl.rawElements;
3103
3140
  const elements = useRawElements ? decl.rawElements : decl.elements;
3104
3141
 
@@ -3131,11 +3168,22 @@ const makeArray = (scope, decl, global = false, name = '$undeclared', initEmpty
3131
3168
  return [ out, pointer ];
3132
3169
  }
3133
3170
 
3171
+ const pointerTmp = local != null ? localTmp(scope, '#makearray_pointer_tmp', Valtype.i32) : null;
3172
+ if (pointerTmp != null) {
3173
+ out.push(
3174
+ [ global ? Opcodes.global_get : Opcodes.local_get, local.idx ],
3175
+ Opcodes.i32_to_u,
3176
+ [ Opcodes.local_set, pointerTmp ]
3177
+ );
3178
+ }
3179
+
3180
+ const pointerWasm = pointerTmp != null ? [ [ Opcodes.local_get, pointerTmp ] ] : number(pointer, Valtype.i32);
3181
+
3134
3182
  // store length as 0th array
3135
3183
  out.push(
3136
- ...number(0, Valtype.i32),
3184
+ ...pointerWasm,
3137
3185
  ...number(length, Valtype.i32),
3138
- [ Opcodes.i32_store, Math.log2(ValtypeSize.i32) - 1, ...unsignedLEB128(pointer) ]
3186
+ [ Opcodes.i32_store, Math.log2(ValtypeSize.i32) - 1, 0 ]
3139
3187
  );
3140
3188
 
3141
3189
  const storeOp = StoreOps[itemType];
@@ -3144,14 +3192,14 @@ const makeArray = (scope, decl, global = false, name = '$undeclared', initEmpty
3144
3192
  if (elements[i] == null) continue;
3145
3193
 
3146
3194
  out.push(
3147
- ...number(0, Valtype.i32),
3195
+ ...pointerWasm,
3148
3196
  ...(useRawElements ? number(elements[i], Valtype[valtype]) : generate(scope, elements[i])),
3149
- [ storeOp, (Math.log2(ValtypeSize[itemType]) || 1) - 1, ...unsignedLEB128(pointer + ValtypeSize.i32 + i * ValtypeSize[itemType]) ]
3197
+ [ storeOp, (Math.log2(ValtypeSize[itemType]) || 1) - 1, ...unsignedLEB128(ValtypeSize.i32 + i * ValtypeSize[itemType]) ]
3150
3198
  );
3151
3199
  }
3152
3200
 
3153
3201
  // local value as pointer
3154
- out.push(...number(pointer));
3202
+ out.push(...pointerWasm, Opcodes.i32_from_u);
3155
3203
 
3156
3204
  return [ out, pointer ];
3157
3205
  };
@@ -3193,6 +3241,15 @@ export const generateMember = (scope, decl, _global, _name) => {
3193
3241
 
3194
3242
  const aotPointer = Prefs.aotPointerOpt && pointer != null;
3195
3243
 
3244
+ // hack: .name
3245
+ if (decl.property.name === 'name') {
3246
+ if (hasFuncWithName(name)) {
3247
+ return makeString(scope, name, _global, _name, true);
3248
+ } else {
3249
+ return generate(scope, DEFAULT_VALUE);
3250
+ }
3251
+ }
3252
+
3196
3253
  // hack: .length
3197
3254
  if (decl.property.name === 'length') {
3198
3255
  const func = funcs.find(x => x.name === name);
@@ -3202,6 +3259,16 @@ export const generateMember = (scope, decl, _global, _name) => {
3202
3259
  return number(typedParams ? func.params.length / 2 : func.params.length);
3203
3260
  }
3204
3261
 
3262
+ if (builtinFuncs[name + '$constructor']) {
3263
+ const regularFunc = builtinFuncs[name];
3264
+ const regularParams = regularFunc.typedParams ? (regularFunc.params.length / 2) : regularFunc.params.length;
3265
+
3266
+ const constructorFunc = builtinFuncs[name + '$constructor'];
3267
+ const constructorParams = constructorFunc.typedParams ? (constructorFunc.params.length / 2) : constructorFunc.params.length;
3268
+
3269
+ return number(Math.max(regularParams, constructorParams));
3270
+ }
3271
+
3205
3272
  if (builtinFuncs[name]) return number(builtinFuncs[name].typedParams ? (builtinFuncs[name].params.length / 2) : builtinFuncs[name].params.length);
3206
3273
  if (importedFuncs[name]) return number(importedFuncs[name].params);
3207
3274
  if (internalConstrs[name]) return number(internalConstrs[name].length ?? 0);
@@ -3230,7 +3297,7 @@ export const generateMember = (scope, decl, _global, _name) => {
3230
3297
  }
3231
3298
 
3232
3299
  return typeSwitch(scope, getNodeType(scope, decl.object), {
3233
- [TYPES._array]: [
3300
+ [TYPES.array]: [
3234
3301
  // get index as valtype
3235
3302
  ...property,
3236
3303
 
@@ -3283,7 +3350,7 @@ export const generateMember = (scope, decl, _global, _name) => {
3283
3350
  ...number(TYPES.string, Valtype.i32),
3284
3351
  ...setLastType(scope)
3285
3352
  ],
3286
- [TYPES._bytestring]: [
3353
+ [TYPES.bytestring]: [
3287
3354
  // setup new/out array
3288
3355
  ...newOut,
3289
3356
  [ Opcodes.drop ],
@@ -3308,7 +3375,7 @@ export const generateMember = (scope, decl, _global, _name) => {
3308
3375
  // return new string (page)
3309
3376
  ...number(newPointer),
3310
3377
 
3311
- ...number(TYPES._bytestring, Valtype.i32),
3378
+ ...number(TYPES.bytestring, Valtype.i32),
3312
3379
  ...setLastType(scope)
3313
3380
  ],
3314
3381
 
@@ -3333,8 +3400,8 @@ const objectHack = node => {
3333
3400
 
3334
3401
  if (!objectName) objectName = objectHack(node.object)?.name?.slice?.(2);
3335
3402
 
3336
- // if .length, give up (hack within a hack!)
3337
- if (node.property.name === 'length') {
3403
+ // if .name or .length, give up (hack within a hack!)
3404
+ if (['name', 'length'].includes(node.property.name)) {
3338
3405
  node.object = objectHack(node.object);
3339
3406
  return;
3340
3407
  }
@@ -3477,7 +3544,7 @@ const internalConstrs = {
3477
3544
  ...number(pointer)
3478
3545
  ];
3479
3546
  },
3480
- type: TYPES._array,
3547
+ type: TYPES.array,
3481
3548
  length: 1
3482
3549
  },
3483
3550
 
@@ -3489,7 +3556,7 @@ const internalConstrs = {
3489
3556
  elements: decl.arguments
3490
3557
  }, global, name);
3491
3558
  },
3492
- type: TYPES._array,
3559
+ type: TYPES.array,
3493
3560
  notConstr: true,
3494
3561
  length: 0
3495
3562
  },
@@ -3618,23 +3685,6 @@ const internalConstrs = {
3618
3685
  }
3619
3686
  };
3620
3687
 
3621
- // const _ = Array.prototype.push;
3622
- // Array.prototype.push = function (a) {
3623
- // const check = arr => {
3624
- // for (const x of arr) {
3625
- // if (x === undefined) {
3626
- // console.trace(arr);
3627
- // process.exit();
3628
- // }
3629
- // if (Array.isArray(x)) check(x);
3630
- // }
3631
- // };
3632
- // if (Array.isArray(a) && !new Error().stack.includes('node:')) check(a);
3633
- // // if (Array.isArray(a)) check(a);
3634
-
3635
- // return _.apply(this, arguments);
3636
- // };
3637
-
3638
3688
  export default program => {
3639
3689
  globals = {};
3640
3690
  globalInd = 0;
@@ -3649,7 +3699,7 @@ export default program => {
3649
3699
 
3650
3700
  globalThis.valtype = 'f64';
3651
3701
 
3652
- const valtypeOpt = process.argv.find(x => x.startsWith('-valtype='));
3702
+ const valtypeOpt = process.argv.find(x => x.startsWith('--valtype='));
3653
3703
  if (valtypeOpt) valtype = valtypeOpt.split('=')[1];
3654
3704
 
3655
3705
  globalThis.valtypeBinary = Valtype[valtype];
@@ -3657,7 +3707,7 @@ export default program => {
3657
3707
  const valtypeInd = ['i32', 'i64', 'f64'].indexOf(valtype);
3658
3708
 
3659
3709
  globalThis.pageSize = PageSize;
3660
- const pageSizeOpt = process.argv.find(x => x.startsWith('-page-size='));
3710
+ const pageSizeOpt = process.argv.find(x => x.startsWith('--page-size='));
3661
3711
  if (pageSizeOpt) pageSize = parseInt(pageSizeOpt.split('=')[1]) * 1024;
3662
3712
 
3663
3713
  // set generic opcodes for current valtype
@@ -110,7 +110,6 @@ export default (wasm, name = '', ind = 0, locals = {}, params = [], returns = []
110
110
 
111
111
  out += '\n';
112
112
  lastInst = inst;
113
- i++;
114
113
  }
115
114
 
116
115
  return highlightAsm(out);