porffor 0.39.1 → 0.39.2

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.
@@ -335,7 +335,7 @@ const internalThrow = (scope, constructor, message, expectsValue = Prefs.alwaysV
335
335
  ];
336
336
 
337
337
  const generateIdent = (scope, decl) => {
338
- const lookup = rawName => {
338
+ const lookup = (rawName, failEarly = false) => {
339
339
  const name = mapName(rawName);
340
340
  let local = scope.locals[rawName];
341
341
 
@@ -376,11 +376,18 @@ const generateIdent = (scope, decl) => {
376
376
  let parent = rawName.slice(2).split('_').slice(0, -1).join('_');
377
377
  if (parent.includes('_')) parent = '__' + parent;
378
378
 
379
- const parentLookup = lookup(parent);
379
+ const parentLookup = lookup(parent, true);
380
380
  if (!parentLookup[1]) return number(UNDEFINED);
381
381
  }
382
382
 
383
- if (local?.idx === undefined) return internalThrow(scope, 'ReferenceError', `${unhackName(name)} is not defined`, true);
383
+ if (local?.idx === undefined) {
384
+ if (failEarly) return internalThrow(scope, 'ReferenceError', `${unhackName(name)} is not defined`, true);
385
+
386
+ return [ [ null, () => {
387
+ // try generating again at the end
388
+ return lookup(rawName, true);
389
+ }, 1 ] ];
390
+ }
384
391
 
385
392
  return [
386
393
  [ Opcodes.local_get, local.idx ],
@@ -889,12 +896,17 @@ const generateBinaryExp = (scope, decl, _global, _name) => {
889
896
  // try hacky version for built-ins first
890
897
  const rightName = decl.right.name;
891
898
  if (rightName) {
892
- const checkType = TYPES[rightName.toLowerCase()];
899
+ let checkType = TYPES[rightName.toLowerCase()];
893
900
  if (checkType != null && rightName === TYPE_NAMES[checkType] && !rightName.endsWith('Error')) {
894
901
  const out = generate(scope, decl.left);
895
902
  disposeLeftover(out);
896
903
 
897
- if ([TYPES.number, TYPES.boolean, TYPES.string].includes(checkType)) {
904
+ // switch primitive types to primitive object types
905
+ if (checkType === TYPES.number) checkType = TYPES.numberobject;
906
+ if (checkType === TYPES.boolean) checkType = TYPES.booleanobject;
907
+
908
+ // currently unsupported types
909
+ if ([TYPES.string].includes(checkType)) {
898
910
  out.push(...number(0));
899
911
  } else {
900
912
  out.push(
@@ -1032,7 +1044,7 @@ const asmFuncToAsm = (scope, func) => {
1032
1044
  return [ [ null, () => {
1033
1045
  if (types.some(x => usedTypes.has(x))) return wasm();
1034
1046
  return [];
1035
- } ] ];
1047
+ }, 0 ] ];
1036
1048
  }
1037
1049
  }
1038
1050
  });
@@ -1160,7 +1172,11 @@ const isExistingProtoFunc = name => {
1160
1172
  return false;
1161
1173
  };
1162
1174
 
1163
- const getType = (scope, _name) => {
1175
+ const getType = (scope, _name, failEarly = false) => {
1176
+ const fallback = failEarly ? number(TYPES.undefined, Valtype.i32) : [ [ null, () => {
1177
+ return getType(scope, _name, true);
1178
+ }, 1 ] ];
1179
+
1164
1180
  const name = mapName(_name);
1165
1181
 
1166
1182
  if (Object.hasOwn(builtinVars, name)) return number(builtinVars[name].type ?? TYPES.number, Valtype.i32);
@@ -1172,7 +1188,7 @@ const getType = (scope, _name) => {
1172
1188
  if (typeLocal) return [ [ Opcodes.local_get, typeLocal.idx ] ];
1173
1189
 
1174
1190
  // todo: warn here?
1175
- return number(TYPES.undefined, Valtype.i32);
1191
+ return fallback;
1176
1192
  }
1177
1193
 
1178
1194
  if (name === 'arguments' && scope.name !== 'main' && !scope.arrow) {
@@ -1186,7 +1202,7 @@ const getType = (scope, _name) => {
1186
1202
  if (typeLocal) return [ [ Opcodes.global_get, typeLocal.idx ] ];
1187
1203
 
1188
1204
  // todo: warn here?
1189
- return number(TYPES.undefined, Valtype.i32);
1205
+ return fallback;
1190
1206
  }
1191
1207
 
1192
1208
  if (Object.hasOwn(builtinFuncs, name) || Object.hasOwn(importedFuncs, name) ||
@@ -1195,7 +1211,7 @@ const getType = (scope, _name) => {
1195
1211
 
1196
1212
  if (isExistingProtoFunc(name)) return number(TYPES.function, Valtype.i32);
1197
1213
 
1198
- return number(TYPES.undefined, Valtype.i32);
1214
+ return fallback;
1199
1215
  };
1200
1216
 
1201
1217
  const setType = (scope, _name, type) => {
@@ -1507,7 +1523,10 @@ const countLeftover = wasm => {
1507
1523
 
1508
1524
  for (let i = 0; i < wasm.length; i++) {
1509
1525
  const inst = wasm[i];
1510
- if (inst[0] == null) continue;
1526
+ if (depth === 0 && inst[0] == null) {
1527
+ if (typeof inst[1] === 'function' && typeof inst[2] === 'number') count += inst[2];
1528
+ continue;
1529
+ }
1511
1530
 
1512
1531
  if (depth === 0 && (inst[0] === Opcodes.if || inst[0] === Opcodes.block || inst[0] === Opcodes.loop)) {
1513
1532
  if (inst[0] === Opcodes.if) count--;
@@ -1538,7 +1557,7 @@ const countLeftover = wasm => {
1538
1557
  count += 2; // fixed return (value, type)
1539
1558
  } else count--;
1540
1559
 
1541
- // console.log(count, decompile([ inst ]).slice(0, -1));
1560
+ // console.log(count, depth, decompile([ inst ]).slice(0, -1));
1542
1561
  }
1543
1562
 
1544
1563
  return count;
@@ -2861,7 +2880,7 @@ const typeSwitch = (scope, type, bc, returns = valtypeBinary, fallthrough = fals
2861
2880
  out = [];
2862
2881
  if (types.some(x => usedTypes.has(x))) add();
2863
2882
  return out;
2864
- }]);
2883
+ }, 0 ]);
2865
2884
  }
2866
2885
  }
2867
2886
  }
@@ -4542,16 +4561,7 @@ const generateForIn = (scope, decl) => {
4542
4561
  };
4543
4562
 
4544
4563
  const generateSwitch = (scope, decl) => {
4545
- const tmp = localTmp(scope, '#switch_disc');
4546
- const out = [
4547
- ...generate(scope, decl.discriminant),
4548
- [ Opcodes.local_set, tmp ],
4549
-
4550
- [ Opcodes.block, Blocktype.void ]
4551
- ];
4552
-
4553
- depth.push('switch');
4554
-
4564
+ // special fast path just for `switch (Porffor.rawType(...))`
4555
4565
  if (decl.discriminant.type === 'CallExpression' && decl.discriminant.callee.type === 'Identifier' && decl.discriminant.callee.name === '__Porffor_rawType') {
4556
4566
  const cases = []
4557
4567
  let canTypeCheck = true;
@@ -4574,28 +4584,42 @@ const generateSwitch = (scope, decl) => {
4574
4584
  }
4575
4585
 
4576
4586
  if (canTypeCheck) {
4577
- const out = typeSwitch(scope,
4578
- getNodeType(scope, decl.discriminant.arguments[0]),
4579
- () => {
4580
- const bc = [];
4581
- let types = [];
4582
- for (const [ type, consequent ] of cases) {
4583
- types.push(type);
4584
-
4585
- if (consequent.length !== 0) {
4586
- bc.push([ types, () => generate(scope, { type: 'BlockStatement', body: consequent }) ]);
4587
- types = [];
4588
- }
4587
+ depth.push('switch');
4588
+
4589
+ const out = typeSwitch(scope, getNodeType(scope, decl.discriminant.arguments[0]), () => {
4590
+ const bc = [];
4591
+ let types = [];
4592
+ for (const [ type, consequent ] of cases) {
4593
+ types.push(type);
4594
+
4595
+ if (consequent.length !== 0) {
4596
+ bc.push([ types, () => generate(scope, { type: 'BlockStatement', body: consequent }) ]);
4597
+ types = [];
4589
4598
  }
4599
+ }
4590
4600
 
4591
- return bc;
4592
- }, Blocktype.void, true);
4601
+ return bc;
4602
+ }, Blocktype.void, true);
4593
4603
 
4594
4604
  depth.pop();
4595
4605
  return out;
4596
4606
  }
4597
4607
  }
4598
4608
 
4609
+ const tmpName = '#switch' + uniqId();
4610
+ const tmp = localTmp(scope, tmpName);
4611
+ localTmp(scope, tmpName + '#type', Valtype.i32);
4612
+
4613
+ const out = [
4614
+ ...generate(scope, decl.discriminant),
4615
+ [ Opcodes.local_set, tmp ],
4616
+ ...setType(scope, tmpName, getNodeType(scope, decl.discriminant)),
4617
+
4618
+ [ Opcodes.block, Blocktype.void ]
4619
+ ];
4620
+
4621
+ depth.push('switch');
4622
+
4599
4623
  const cases = decl.cases.slice();
4600
4624
  const defaultCase = cases.findIndex(x => x.test == null);
4601
4625
  if (defaultCase != -1) {
@@ -4613,9 +4637,16 @@ const generateSwitch = (scope, decl) => {
4613
4637
  if (x.test) {
4614
4638
  // todo: this should use same value zero
4615
4639
  out.push(
4616
- [ Opcodes.local_get, tmp ],
4617
- ...generate(scope, x.test),
4618
- [ Opcodes.eq ],
4640
+ ...generate(scope, {
4641
+ type: 'BinaryExpression',
4642
+ operator: '===',
4643
+ left: {
4644
+ type: 'Identifier',
4645
+ name: tmpName
4646
+ },
4647
+ right: x.test
4648
+ }),
4649
+ Opcodes.i32_to_u,
4619
4650
  [ Opcodes.br_if, i ]
4620
4651
  );
4621
4652
  } else {
@@ -25,7 +25,7 @@ const compile = async (file, _funcs) => {
25
25
  first = source.slice(0, source.indexOf('\n'));
26
26
  }
27
27
 
28
- let args = ['--module', '--todo-time=compile', '--truthy=no_nan_negative', '--no-rm-unused-types', '--scoped-page-names', '--funsafe-no-unlikely-proto-checks', '--fast-length', '--parse-types', '--opt-types', '--no-passive-data', '--active-data', '--exception-mode=lut'];
28
+ let args = ['--module', '--todo-time=compile', '--truthy=no_nan_negative', '--no-rm-unused-types', '--scoped-page-names', '--funsafe-no-unlikely-proto-checks', '--zero-checks=charCodeAt', '--fast-length', '--parse-types', '--opt-types', '--no-passive-data', '--active-data', '--exception-mode=lut'];
29
29
  if (first.startsWith('// @porf')) {
30
30
  args = first.slice('// @porf '.length).split(' ').concat(args);
31
31
  }
@@ -10,7 +10,7 @@ export const PrototypeFuncs = function() {
10
10
  const noUnlikelyChecks = Prefs.funsafeNoUnlikelyProtoChecks;
11
11
 
12
12
  let zeroChecks;
13
- if (Prefs.zeroChecks) zeroChecks = Prefs.zeroChecks.split('=')[1].split(',').reduce((acc, x) => { acc[x.toLowerCase()] = true; return acc; }, {});
13
+ if (Prefs.zeroChecks) zeroChecks = Prefs.zeroChecks.split(',').reduce((acc, x) => { acc[x.toLowerCase()] = true; return acc; }, {});
14
14
  else zeroChecks = {};
15
15
 
16
16
  this[TYPES.array] = {
package/compiler/types.js CHANGED
@@ -85,6 +85,8 @@ registerInternalType('SyntaxError');
85
85
  registerInternalType('RangeError');
86
86
  registerInternalType('EvalError');
87
87
  registerInternalType('URIError');
88
+ registerInternalType('Test262Error');
89
+ registerInternalType('__Porffor_TodoError');
88
90
 
89
91
  if (Prefs.largestTypes) {
90
92
  const typeKeys = Object.keys(TYPES);
package/compiler/wrap.js CHANGED
@@ -312,9 +312,11 @@ ${flags & 0b0001 ? ` get func idx: ${get}
312
312
  case TYPES.syntaxerror:
313
313
  case TYPES.rangeerror:
314
314
  case TYPES.evalerror:
315
- case TYPES.urierror: {
315
+ case TYPES.urierror:
316
+ case TYPES.test262error:
317
+ case TYPES.__porffor_todoerror: {
316
318
  const obj = porfToJSValue({ memory, funcs, pages }, value, TYPES.object);
317
- const constr = globalThis[TYPE_NAMES[type]];
319
+ const constr = globalThis[TYPE_NAMES[type]] ?? Error;
318
320
  const err = new constr(obj.message);
319
321
  err.name = obj.name;
320
322
  err.stack = `${TYPE_NAMES[type]}: ${obj.message}`;
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.39.1+bd1e18648",
4
+ "version": "0.39.2+c58905509",
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.39.1+bd1e18648';
3
+ globalThis.version = '0.39.2+c58905509';
4
4
 
5
5
  // deno compat
6
6
  if (typeof process === 'undefined' && typeof Deno !== 'undefined') {