porffor 0.2.0-67434d5 → 0.2.0-6922552

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.
@@ -201,7 +201,7 @@ const generate = (scope, decl, global = false, name = undefined, valueUnused = f
201
201
  }
202
202
 
203
203
  let inst = Opcodes[asm[0].replace('.', '_')];
204
- if (!inst) throw new Error(`inline asm: inst ${asm[0]} not found`);
204
+ if (inst == null) throw new Error(`inline asm: inst ${asm[0]} not found`);
205
205
 
206
206
  if (!Array.isArray(inst)) inst = [ inst ];
207
207
  const immediates = asm.slice(1).map(x => {
@@ -219,8 +219,8 @@ const generate = (scope, decl, global = false, name = undefined, valueUnused = f
219
219
  __Porffor_bs: str => [
220
220
  ...makeString(scope, str, global, name, true),
221
221
 
222
- ...(name ? setType(scope, name, TYPES._bytestring) : [
223
- ...number(TYPES._bytestring, Valtype.i32),
222
+ ...(name ? setType(scope, name, TYPES.bytestring) : [
223
+ ...number(TYPES.bytestring, Valtype.i32),
224
224
  ...setLastType(scope)
225
225
  ])
226
226
  ],
@@ -460,7 +460,7 @@ const concatStrings = (scope, left, right, global, name, assign = false, bytestr
460
460
  const rightLength = localTmp(scope, 'concat_right_length', Valtype.i32);
461
461
  const leftLength = localTmp(scope, 'concat_left_length', Valtype.i32);
462
462
 
463
- if (assign) {
463
+ if (assign && Prefs.aotPointerOpt) {
464
464
  const pointer = scope.arrays?.get(name ?? '$undeclared');
465
465
 
466
466
  return [
@@ -723,7 +723,7 @@ const truthy = (scope, wasm, type, intIn = false, intOut = false) => {
723
723
 
724
724
  ...typeSwitch(scope, type, {
725
725
  // [TYPES.number]: def,
726
- [TYPES._array]: [
726
+ [TYPES.array]: [
727
727
  // arrays are always truthy
728
728
  ...number(1, intOut ? Valtype.i32 : valtypeBinary)
729
729
  ],
@@ -739,7 +739,7 @@ const truthy = (scope, wasm, type, intIn = false, intOut = false) => {
739
739
  [ Opcodes.i32_eqz ], */
740
740
  ...(intOut ? [] : [ Opcodes.i32_from_u ])
741
741
  ],
742
- [TYPES._bytestring]: [ // duplicate of string
742
+ [TYPES.bytestring]: [ // duplicate of string
743
743
  ...(!useTmp ? [] : [ [ Opcodes.local_get, tmp ] ]),
744
744
  ...(intIn ? [] : [ Opcodes.i32_to_u ]),
745
745
 
@@ -762,7 +762,7 @@ const falsy = (scope, wasm, type, intIn = false, intOut = false) => {
762
762
  ...(!useTmp ? [] : [ [ Opcodes.local_set, tmp ] ]),
763
763
 
764
764
  ...typeSwitch(scope, type, {
765
- [TYPES._array]: [
765
+ [TYPES.array]: [
766
766
  // arrays are always truthy
767
767
  ...number(0, intOut ? Valtype.i32 : valtypeBinary)
768
768
  ],
@@ -777,7 +777,7 @@ const falsy = (scope, wasm, type, intIn = false, intOut = false) => {
777
777
  [ Opcodes.i32_eqz ],
778
778
  ...(intOut ? [] : [ Opcodes.i32_from_u ])
779
779
  ],
780
- [TYPES._bytestring]: [ // duplicate of string
780
+ [TYPES.bytestring]: [ // duplicate of string
781
781
  ...(!useTmp ? [] : [ [ Opcodes.local_get, tmp ] ]),
782
782
  ...(intIn ? [] : [ Opcodes.i32_to_u ]),
783
783
 
@@ -922,7 +922,7 @@ const performOp = (scope, op, left, right, leftType, rightType, _global = false,
922
922
  }
923
923
  }
924
924
 
925
- if (knownLeft === TYPES._bytestring || knownRight === TYPES._bytestring) {
925
+ if (knownLeft === TYPES.bytestring || knownRight === TYPES.bytestring) {
926
926
  if (op === '+') {
927
927
  // todo: this should be dynamic too but for now only static
928
928
  // string concat (a + b)
@@ -1041,12 +1041,12 @@ const performOp = (scope, op, left, right, leftType, rightType, _global = false,
1041
1041
 
1042
1042
  // if left is bytestring
1043
1043
  ...leftType,
1044
- ...number(TYPES._bytestring, Valtype.i32),
1044
+ ...number(TYPES.bytestring, Valtype.i32),
1045
1045
  [ Opcodes.i32_eq ],
1046
1046
 
1047
1047
  // if right is bytestring
1048
1048
  ...rightType,
1049
- ...number(TYPES._bytestring, Valtype.i32),
1049
+ ...number(TYPES.bytestring, Valtype.i32),
1050
1050
  [ Opcodes.i32_eq ],
1051
1051
 
1052
1052
  // if both are true
@@ -1188,7 +1188,7 @@ const generateLogicExp = (scope, decl) => {
1188
1188
  // 5: pointer
1189
1189
 
1190
1190
  const isExistingProtoFunc = name => {
1191
- if (name.startsWith('__Array_prototype')) return !!prototypeFuncs[TYPES._array][name.slice(18)];
1191
+ if (name.startsWith('__Array_prototype')) return !!prototypeFuncs[TYPES.array][name.slice(18)];
1192
1192
  if (name.startsWith('__String_prototype_')) return !!prototypeFuncs[TYPES.string][name.slice(19)];
1193
1193
 
1194
1194
  return false;
@@ -1247,9 +1247,9 @@ const setLastType = scope => {
1247
1247
  const getNodeType = (scope, node) => {
1248
1248
  const inner = () => {
1249
1249
  if (node.type === 'Literal') {
1250
- if (node.regex) return TYPES._regexp;
1250
+ if (node.regex) return TYPES.regexp;
1251
1251
 
1252
- if (typeof node.value === 'string' && byteStringable(node.value)) return TYPES._bytestring;
1252
+ if (typeof node.value === 'string' && byteStringable(node.value)) return TYPES.bytestring;
1253
1253
 
1254
1254
  return TYPES[typeof node.value];
1255
1255
  }
@@ -1303,7 +1303,7 @@ const getNodeType = (scope, node) => {
1303
1303
  const spl = name.slice(2).split('_');
1304
1304
 
1305
1305
  const func = spl[spl.length - 1];
1306
- const protoFuncs = Object.keys(prototypeFuncs).filter(x => x != TYPES._bytestring && prototypeFuncs[x][func] != null);
1306
+ const protoFuncs = Object.keys(prototypeFuncs).filter(x => x != TYPES.bytestring && prototypeFuncs[x][func] != null);
1307
1307
  if (protoFuncs.length === 1) return protoFuncs[0].returnType ?? TYPES.number;
1308
1308
  }
1309
1309
 
@@ -1355,7 +1355,7 @@ const getNodeType = (scope, node) => {
1355
1355
  }
1356
1356
 
1357
1357
  if (node.type === 'ArrayExpression') {
1358
- return TYPES._array;
1358
+ return TYPES.array;
1359
1359
  }
1360
1360
 
1361
1361
  if (node.type === 'BinaryExpression') {
@@ -1367,7 +1367,7 @@ const getNodeType = (scope, node) => {
1367
1367
 
1368
1368
  // todo: this should be dynamic but for now only static
1369
1369
  if (knownLeft === TYPES.string || knownRight === TYPES.string) return TYPES.string;
1370
- if (knownLeft === TYPES._bytestring || knownRight === TYPES._bytestring) return TYPES._bytestring;
1370
+ if (knownLeft === TYPES.bytestring || knownRight === TYPES.bytestring) return TYPES.bytestring;
1371
1371
 
1372
1372
  return TYPES.number;
1373
1373
 
@@ -1393,7 +1393,7 @@ const getNodeType = (scope, node) => {
1393
1393
  if (node.operator === '!') return TYPES.boolean;
1394
1394
  if (node.operator === 'void') return TYPES.undefined;
1395
1395
  if (node.operator === 'delete') return TYPES.boolean;
1396
- if (node.operator === 'typeof') return Prefs.bytestring ? TYPES._bytestring : TYPES.string;
1396
+ if (node.operator === 'typeof') return Prefs.bytestring ? TYPES.bytestring : TYPES.string;
1397
1397
 
1398
1398
  return TYPES.number;
1399
1399
  }
@@ -1404,8 +1404,8 @@ const getNodeType = (scope, node) => {
1404
1404
 
1405
1405
  // ts hack
1406
1406
  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;
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;
1409
1409
 
1410
1410
  if (scope.locals['#last_type']) return getLastType(scope);
1411
1411
 
@@ -1827,20 +1827,20 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
1827
1827
  idx = funcIndex[name];
1828
1828
 
1829
1829
  // infer arguments types from builtins params
1830
- const func = funcs.find(x => x.name === name);
1831
- for (let i = 0; i < decl.arguments.length; i++) {
1832
- const arg = decl.arguments[i];
1833
- if (!arg.name) continue;
1834
-
1835
- const local = scope.locals[arg.name];
1836
- if (!local) continue;
1837
-
1838
- local.type = func.params[i];
1839
- if (local.type === Valtype.v128) {
1840
- // specify vec subtype inferred from last vec type in function name
1841
- local.vecType = name.split('_').reverse().find(x => x.includes('x'));
1842
- }
1843
- }
1830
+ // const func = funcs.find(x => x.name === name);
1831
+ // for (let i = 0; i < decl.arguments.length; i++) {
1832
+ // const arg = decl.arguments[i];
1833
+ // if (!arg.name) continue;
1834
+
1835
+ // const local = scope.locals[arg.name];
1836
+ // if (!local) continue;
1837
+
1838
+ // local.type = func.params[i];
1839
+ // if (local.type === Valtype.v128) {
1840
+ // // specify vec subtype inferred from last vec type in function name
1841
+ // local.vecType = name.split('_').reverse().find(x => x.includes('x'));
1842
+ // }
1843
+ // }
1844
1844
  }
1845
1845
 
1846
1846
  if (idx === undefined && internalConstrs[name]) return internalConstrs[name].generate(scope, decl, _global, _name);
@@ -1872,9 +1872,6 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
1872
1872
 
1873
1873
  // value
1874
1874
  i32_const: { imms: 1, args: [], returns: 1 },
1875
-
1876
- // a, b
1877
- i32_or: { imms: 0, args: [ true, true ], returns: 1 },
1878
1875
  };
1879
1876
 
1880
1877
  const opName = name.slice('__Porffor_wasm_'.length);
@@ -2095,7 +2092,7 @@ const brTable = (input, bc, returns) => {
2095
2092
  };
2096
2093
 
2097
2094
  const typeSwitch = (scope, type, bc, returns = valtypeBinary) => {
2098
- if (!Prefs.bytestring) delete bc[TYPES._bytestring];
2095
+ if (!Prefs.bytestring) delete bc[TYPES.bytestring];
2099
2096
 
2100
2097
  const known = knownType(scope, type);
2101
2098
  if (known != null) {
@@ -2198,7 +2195,7 @@ const extractTypeAnnotation = decl => {
2198
2195
  const typeName = type;
2199
2196
  type = typeAnnoToPorfType(type);
2200
2197
 
2201
- if (type === TYPES._bytestring && !Prefs.bytestring) type = TYPES.string;
2198
+ if (type === TYPES.bytestring && !Prefs.bytestring) type = TYPES.string;
2202
2199
 
2203
2200
  // if (decl.name) console.log(decl.name, { type, elementType });
2204
2201
 
@@ -2212,6 +2209,7 @@ const generateVar = (scope, decl) => {
2212
2209
 
2213
2210
  // global variable if in top scope (main) and var ..., or if wanted
2214
2211
  const global = topLevel || decl._bare; // decl.kind === 'var';
2212
+ const target = global ? globals : scope.locals;
2215
2213
 
2216
2214
  for (const x of decl.declarations) {
2217
2215
  const name = mapName(x.id.name);
@@ -2233,6 +2231,10 @@ const generateVar = (scope, decl) => {
2233
2231
  continue; // always ignore
2234
2232
  }
2235
2233
 
2234
+ // // generate init before allocating var
2235
+ // let generated;
2236
+ // if (x.init) generated = generate(scope, x.init, global, name);
2237
+
2236
2238
  const typed = typedInput && x.id.typeAnnotation;
2237
2239
  let idx = allocVar(scope, name, global, !(typed && extractTypeAnnotation(x.id).type != null));
2238
2240
 
@@ -2241,9 +2243,17 @@ const generateVar = (scope, decl) => {
2241
2243
  }
2242
2244
 
2243
2245
  if (x.init) {
2244
- out = out.concat(generate(scope, x.init, global, name));
2245
-
2246
- out.push([ global ? Opcodes.global_set : Opcodes.local_set, idx ]);
2246
+ const generated = generate(scope, x.init, global, name);
2247
+ if (scope.arrays?.get(name) != null) {
2248
+ // hack to set local as pointer before
2249
+ out.push(...number(scope.arrays.get(name)), [ global ? Opcodes.global_set : Opcodes.local_set, idx ]);
2250
+ if (generated.at(-1) == Opcodes.i32_from_u) generated.pop();
2251
+ generated.pop();
2252
+ out = out.concat(generated);
2253
+ } else {
2254
+ out = out.concat(generated);
2255
+ out.push([ global ? Opcodes.global_set : Opcodes.local_set, idx ]);
2256
+ }
2247
2257
  out.push(...setType(scope, name, getNodeType(scope, x.init)));
2248
2258
  }
2249
2259
 
@@ -2270,6 +2280,8 @@ const generateAssign = (scope, decl, _global, _name, valueUnused = false) => {
2270
2280
  return [];
2271
2281
  }
2272
2282
 
2283
+ const op = decl.operator.slice(0, -1) || '=';
2284
+
2273
2285
  // hack: .length setter
2274
2286
  if (decl.left.type === 'MemberExpression' && decl.left.property.name === 'length') {
2275
2287
  const name = decl.left.object.name;
@@ -2278,14 +2290,20 @@ const generateAssign = (scope, decl, _global, _name, valueUnused = false) => {
2278
2290
  const aotPointer = Prefs.aotPointerOpt && pointer != null;
2279
2291
 
2280
2292
  const newValueTmp = localTmp(scope, '__length_setter_tmp');
2293
+ const pointerTmp = op === '=' ? null : localTmp(scope, '__member_setter_ptr_tmp', Valtype.i32);
2281
2294
 
2282
2295
  return [
2283
2296
  ...(aotPointer ? number(0, Valtype.i32) : [
2284
2297
  ...generate(scope, decl.left.object),
2285
2298
  Opcodes.i32_to_u
2286
2299
  ]),
2300
+ ...(!pointerTmp ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
2287
2301
 
2288
- ...generate(scope, decl.right),
2302
+ ...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
2303
+ [ Opcodes.local_get, pointerTmp ],
2304
+ [ Opcodes.i32_load, Math.log2(ValtypeSize.i32) - 1, 0 ],
2305
+ Opcodes.i32_from_u
2306
+ ], generate(scope, decl.right), number(TYPES.number, Valtype.i32), getNodeType(scope, decl.right))),
2289
2307
  [ Opcodes.local_tee, newValueTmp ],
2290
2308
 
2291
2309
  Opcodes.i32_to_u,
@@ -2295,8 +2313,6 @@ const generateAssign = (scope, decl, _global, _name, valueUnused = false) => {
2295
2313
  ];
2296
2314
  }
2297
2315
 
2298
- const op = decl.operator.slice(0, -1) || '=';
2299
-
2300
2316
  // arr[i]
2301
2317
  if (decl.left.type === 'MemberExpression' && decl.left.computed) {
2302
2318
  const name = decl.left.object.name;
@@ -2309,7 +2325,7 @@ const generateAssign = (scope, decl, _global, _name, valueUnused = false) => {
2309
2325
 
2310
2326
  return [
2311
2327
  ...typeSwitch(scope, getNodeType(scope, decl.left.object), {
2312
- [TYPES._array]: [
2328
+ [TYPES.array]: [
2313
2329
  ...(aotPointer ? [] : [
2314
2330
  ...generate(scope, decl.left.object),
2315
2331
  Opcodes.i32_to_u
@@ -2511,7 +2527,7 @@ const generateUnary = (scope, decl) => {
2511
2527
  [TYPES.undefined]: makeString(scope, 'undefined', false, '#typeof_result'),
2512
2528
  [TYPES.function]: makeString(scope, 'function', false, '#typeof_result'),
2513
2529
 
2514
- [TYPES._bytestring]: makeString(scope, 'string', false, '#typeof_result'),
2530
+ [TYPES.bytestring]: makeString(scope, 'string', false, '#typeof_result'),
2515
2531
 
2516
2532
  // object and internal types
2517
2533
  default: makeString(scope, 'object', false, '#typeof_result'),
@@ -2747,7 +2763,7 @@ const generateForOf = (scope, decl) => {
2747
2763
  // set type for local
2748
2764
  // todo: optimize away counter and use end pointer
2749
2765
  out.push(...typeSwitch(scope, getNodeType(scope, decl.right), {
2750
- [TYPES._array]: [
2766
+ [TYPES.array]: [
2751
2767
  ...setType(scope, leftName, TYPES.number),
2752
2768
 
2753
2769
  [ Opcodes.loop, Blocktype.void ],
@@ -2830,8 +2846,8 @@ const generateForOf = (scope, decl) => {
2830
2846
  [ Opcodes.end ],
2831
2847
  [ Opcodes.end ]
2832
2848
  ],
2833
- [TYPES._bytestring]: [
2834
- ...setType(scope, leftName, TYPES._bytestring),
2849
+ [TYPES.bytestring]: [
2850
+ ...setType(scope, leftName, TYPES.bytestring),
2835
2851
 
2836
2852
  [ Opcodes.loop, Blocktype.void ],
2837
2853
 
@@ -3100,12 +3116,14 @@ const makeArray = (scope, decl, global = false, name = '$undeclared', initEmpty
3100
3116
  // todo: can we just have 1 undeclared array? probably not? but this is not really memory efficient
3101
3117
  const uniqueName = name === '$undeclared' ? name + Math.random().toString().slice(2) : name;
3102
3118
 
3103
- if (Prefs.scopedPageNames) scope.arrays.set(name, allocPage(scope, `${scope.name} | ${getAllocType(itemType)}: ${uniqueName}`, itemType) * pageSize);
3119
+ if (Prefs.scopedPageNames) scope.arrays.set(name, allocPage(scope, `${getAllocType(itemType)}: ${scope.name}/${uniqueName}`, itemType) * pageSize);
3104
3120
  else scope.arrays.set(name, allocPage(scope, `${getAllocType(itemType)}: ${uniqueName}`, itemType) * pageSize);
3105
3121
  }
3106
3122
 
3107
3123
  const pointer = scope.arrays.get(name);
3108
3124
 
3125
+ const local = global ? globals[name] : scope.locals[name];
3126
+
3109
3127
  const useRawElements = !!decl.rawElements;
3110
3128
  const elements = useRawElements ? decl.rawElements : decl.elements;
3111
3129
 
@@ -3138,11 +3156,22 @@ const makeArray = (scope, decl, global = false, name = '$undeclared', initEmpty
3138
3156
  return [ out, pointer ];
3139
3157
  }
3140
3158
 
3159
+ const pointerTmp = local != null ? localTmp(scope, '#makearray_pointer_tmp', Valtype.i32) : null;
3160
+ if (pointerTmp != null) {
3161
+ out.push(
3162
+ [ global ? Opcodes.global_get : Opcodes.local_get, local.idx ],
3163
+ Opcodes.i32_to_u,
3164
+ [ Opcodes.local_set, pointerTmp ]
3165
+ );
3166
+ }
3167
+
3168
+ const pointerWasm = pointerTmp != null ? [ [ Opcodes.local_get, pointerTmp ] ] : number(pointer, Valtype.i32);
3169
+
3141
3170
  // store length as 0th array
3142
3171
  out.push(
3143
- ...number(0, Valtype.i32),
3172
+ ...pointerWasm,
3144
3173
  ...number(length, Valtype.i32),
3145
- [ Opcodes.i32_store, Math.log2(ValtypeSize.i32) - 1, ...unsignedLEB128(pointer) ]
3174
+ [ Opcodes.i32_store, Math.log2(ValtypeSize.i32) - 1, 0 ]
3146
3175
  );
3147
3176
 
3148
3177
  const storeOp = StoreOps[itemType];
@@ -3151,14 +3180,14 @@ const makeArray = (scope, decl, global = false, name = '$undeclared', initEmpty
3151
3180
  if (elements[i] == null) continue;
3152
3181
 
3153
3182
  out.push(
3154
- ...number(0, Valtype.i32),
3183
+ ...pointerWasm,
3155
3184
  ...(useRawElements ? number(elements[i], Valtype[valtype]) : generate(scope, elements[i])),
3156
- [ storeOp, (Math.log2(ValtypeSize[itemType]) || 1) - 1, ...unsignedLEB128(pointer + ValtypeSize.i32 + i * ValtypeSize[itemType]) ]
3185
+ [ storeOp, (Math.log2(ValtypeSize[itemType]) || 1) - 1, ...unsignedLEB128(ValtypeSize.i32 + i * ValtypeSize[itemType]) ]
3157
3186
  );
3158
3187
  }
3159
3188
 
3160
3189
  // local value as pointer
3161
- out.push(...number(pointer));
3190
+ out.push(...pointerWasm, Opcodes.i32_from_u);
3162
3191
 
3163
3192
  return [ out, pointer ];
3164
3193
  };
@@ -3237,7 +3266,7 @@ export const generateMember = (scope, decl, _global, _name) => {
3237
3266
  }
3238
3267
 
3239
3268
  return typeSwitch(scope, getNodeType(scope, decl.object), {
3240
- [TYPES._array]: [
3269
+ [TYPES.array]: [
3241
3270
  // get index as valtype
3242
3271
  ...property,
3243
3272
 
@@ -3290,7 +3319,7 @@ export const generateMember = (scope, decl, _global, _name) => {
3290
3319
  ...number(TYPES.string, Valtype.i32),
3291
3320
  ...setLastType(scope)
3292
3321
  ],
3293
- [TYPES._bytestring]: [
3322
+ [TYPES.bytestring]: [
3294
3323
  // setup new/out array
3295
3324
  ...newOut,
3296
3325
  [ Opcodes.drop ],
@@ -3315,7 +3344,7 @@ export const generateMember = (scope, decl, _global, _name) => {
3315
3344
  // return new string (page)
3316
3345
  ...number(newPointer),
3317
3346
 
3318
- ...number(TYPES._bytestring, Valtype.i32),
3347
+ ...number(TYPES.bytestring, Valtype.i32),
3319
3348
  ...setLastType(scope)
3320
3349
  ],
3321
3350
 
@@ -3484,7 +3513,7 @@ const internalConstrs = {
3484
3513
  ...number(pointer)
3485
3514
  ];
3486
3515
  },
3487
- type: TYPES._array,
3516
+ type: TYPES.array,
3488
3517
  length: 1
3489
3518
  },
3490
3519
 
@@ -3496,7 +3525,7 @@ const internalConstrs = {
3496
3525
  elements: decl.arguments
3497
3526
  }, global, name);
3498
3527
  },
3499
- type: TYPES._array,
3528
+ type: TYPES.array,
3500
3529
  notConstr: true,
3501
3530
  length: 0
3502
3531
  },
@@ -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);