porffor 0.49.7 → 0.49.8

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.
@@ -1334,6 +1334,40 @@ const isExistingProtoFunc = name => {
1334
1334
  return false;
1335
1335
  };
1336
1336
 
1337
+ let globalInfer;
1338
+ const getInferred = (scope, name, global = false) => {
1339
+ if (global) {
1340
+ if (globalInfer.has(name)) return globalInfer.get(name);
1341
+ } else if (scope.inferTree) {
1342
+ for (let i = scope.inferTree.length - 1; i >= 0; i--) {
1343
+ const x = scope.inferTree[i];
1344
+ if (x._infer?.has(name)) return x._infer.get(name);
1345
+ }
1346
+ }
1347
+
1348
+ return null;
1349
+ };
1350
+
1351
+ const setInferred = (scope, name, type, global = false) => {
1352
+ scope.inferTree ??= [];
1353
+
1354
+ if (global) {
1355
+ // set inferred type in global if not already and not in a loop, else make it null
1356
+ globalInfer.set(name, globalInfer.has(name) || inferLoopPrev.length > 0 ? null : type);
1357
+ } else {
1358
+ // set inferred type in top
1359
+ const top = scope.inferTree.at(-1);
1360
+ top._infer ??= new Map();
1361
+ top._infer.set(name, type);
1362
+
1363
+ // invalidate inferred type above if mismatched
1364
+ for (let i = scope.inferTree.length - 2; i >= 0; i--) {
1365
+ const x = scope.inferTree[i];
1366
+ if (x._infer && x._infer.get(name) !== type) x._infer.set(name, null);
1367
+ }
1368
+ }
1369
+ };
1370
+
1337
1371
  const getType = (scope, name, failEarly = false) => {
1338
1372
  const fallback = failEarly ? number(TYPES.undefined, Valtype.i32) : [ [ null, () => {
1339
1373
  return getType(scope, name, true);
@@ -1341,71 +1375,73 @@ const getType = (scope, name, failEarly = false) => {
1341
1375
 
1342
1376
  if (Object.hasOwn(builtinVars, name)) return number(builtinVars[name].type ?? TYPES.number, Valtype.i32);
1343
1377
 
1378
+ let metadata, typeLocal, global = null;
1344
1379
  if (Object.hasOwn(scope.locals, name)) {
1345
- if (scope.locals[name]?.metadata?.type != null) return number(scope.locals[name].metadata.type, Valtype.i32);
1346
-
1347
- const typeLocal = scope.locals[name + '#type'];
1348
- if (typeLocal) return [ [ Opcodes.local_get, typeLocal.idx ] ];
1349
-
1350
- // todo: warn here?
1351
- return fallback;
1380
+ metadata = scope.locals[name].metadata;
1381
+ typeLocal = scope.locals[name + '#type'];
1382
+ global = false;
1383
+ } else if (Object.hasOwn(globals, name)) {
1384
+ metadata = globals[name].metadata;
1385
+ typeLocal = globals[name + '#type'];
1386
+ global = true;
1352
1387
  }
1353
1388
 
1354
- if (name === 'arguments' && scope.name !== '#main' && !scope.arrow) {
1389
+ if (global !== false && name === 'arguments' && scope.name !== '#main' && !scope.arrow) {
1355
1390
  return number(TYPES.array, Valtype.i32);
1356
1391
  }
1357
1392
 
1358
- if (Object.hasOwn(globals, name)) {
1359
- if (globals[name]?.metadata?.type != null) return number(globals[name].metadata.type, Valtype.i32);
1393
+ if (metadata?.type != null) {
1394
+ return number(metadata.type, Valtype.i32);
1395
+ }
1360
1396
 
1361
- const typeLocal = globals[name + '#type'];
1362
- if (typeLocal) return [ [ Opcodes.global_get, typeLocal.idx ] ];
1397
+ const inferred = getInferred(scope, name, global);
1398
+ if (metadata?.type === undefined && inferred != null) return number(inferred, Valtype.i32);
1363
1399
 
1364
- // todo: warn here?
1365
- return fallback;
1366
- }
1400
+ if (typeLocal) return [
1401
+ [ global ? Opcodes.global_get : Opcodes.local_get, typeLocal.idx ]
1402
+ ];
1367
1403
 
1368
- if (Object.hasOwn(builtinFuncs, name) || Object.hasOwn(importedFuncs, name) ||
1369
- Object.hasOwn(funcIndex, name) || Object.hasOwn(internalConstrs, name))
1370
- return number(TYPES.function, Valtype.i32);
1404
+ if (hasFuncWithName(name)) {
1405
+ return number(TYPES.function, Valtype.i32);
1406
+ }
1371
1407
 
1372
1408
  if (isExistingProtoFunc(name)) return number(TYPES.function, Valtype.i32);
1373
1409
 
1374
1410
  return fallback;
1375
1411
  };
1376
1412
 
1377
- const setType = (scope, name, type) => {
1413
+ const setType = (scope, name, type, noInfer = false) => {
1378
1414
  typeUsed(scope, knownType(scope, type));
1379
1415
 
1380
1416
  const out = typeof type === 'number' ? number(type, Valtype.i32) : type;
1381
1417
 
1418
+ let metadata, typeLocal, global = false;
1382
1419
  if (Object.hasOwn(scope.locals, name)) {
1383
- if (scope.locals[name]?.metadata?.type != null) return [];
1384
-
1385
- const typeLocal = scope.locals[name + '#type'];
1386
- if (typeLocal) return [
1387
- ...out,
1388
- [ Opcodes.local_set, typeLocal.idx ]
1389
- ];
1420
+ metadata = scope.locals[name].metadata;
1421
+ typeLocal = scope.locals[name + '#type'];
1422
+ } else if (Object.hasOwn(globals, name)) {
1423
+ metadata = globals[name].metadata;
1424
+ typeLocal = globals[name + '#type'];
1425
+ global = true;
1426
+ }
1390
1427
 
1391
- // todo: warn here?
1428
+ if (metadata?.type != null) {
1392
1429
  return [];
1393
1430
  }
1394
1431
 
1395
- if (Object.hasOwn(globals, name)) {
1396
- if (globals[name]?.metadata?.type != null) return [];
1397
-
1398
- const typeLocal = globals[name + '#type'];
1399
- if (typeLocal) return [
1400
- ...out,
1401
- [ Opcodes.global_set, typeLocal.idx ]
1402
- ];
1432
+ if (!noInfer) {
1433
+ const newInferred = knownType(scope, type);
1434
+ setInferred(scope, name, newInferred, global);
1403
1435
 
1404
- // todo: warn here?
1405
- return [];
1436
+ // todo/opt: skip setting if already matches previous
1406
1437
  }
1407
1438
 
1408
- // throw new Error('could not find var');
1439
+ if (typeLocal) return [
1440
+ ...out,
1441
+ [ global ? Opcodes.global_set : Opcodes.local_set, typeLocal.idx ]
1442
+ ];
1443
+
1444
+ // todo: warn or error here
1409
1445
  return [];
1410
1446
  };
1411
1447
 
@@ -1506,7 +1542,6 @@ const getNodeType = (scope, node) => {
1506
1542
  if (node.type === 'AssignmentExpression') {
1507
1543
  const op = node.operator.slice(0, -1) || '=';
1508
1544
  if (op === '=') return getNodeType(scope, node.right);
1509
- // if (op === '=') return getNodeType(scope, node.left);
1510
1545
 
1511
1546
  return getNodeType(scope, {
1512
1547
  type: ['||', '&&', '??'].includes(op) ? 'LogicalExpression' : 'BinaryExpression',
@@ -1615,6 +1650,10 @@ const getNodeType = (scope, node) => {
1615
1650
  return getNodeType(scope, node.expressions.at(-1));
1616
1651
  }
1617
1652
 
1653
+ if (node.type === 'ChainExpression') {
1654
+ return getNodeType(scope, node.expression);
1655
+ }
1656
+
1618
1657
  return getLastType(scope);
1619
1658
  })();
1620
1659
 
@@ -1763,6 +1802,14 @@ const ArrayUtil = {
1763
1802
  ]
1764
1803
  };
1765
1804
 
1805
+ const getLastInst = wasm => {
1806
+ for (let i = wasm.length - 1; i >= 0; i--) {
1807
+ if (wasm[i]?.[0] != null) return wasm[i];
1808
+ }
1809
+
1810
+ return null;
1811
+ };
1812
+
1766
1813
  const createNewTarget = (scope, decl, idx = 0, force = false) => {
1767
1814
  if (decl._new || force) {
1768
1815
  return [
@@ -1993,7 +2040,7 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
1993
2040
  });
1994
2041
  scope.inEval = false;
1995
2042
 
1996
- const lastInst = out[out.length - 1];
2043
+ const lastInst = getLastInst(out);
1997
2044
  if (lastInst && lastInst[0] === Opcodes.drop) {
1998
2045
  out.splice(out.length - 1, 1);
1999
2046
 
@@ -2671,10 +2718,7 @@ const knownType = (scope, type) => {
2671
2718
 
2672
2719
  // type idx = var idx + 1
2673
2720
  const name = Object.values(scope.locals).find(x => x.idx === idx)?.name;
2674
- if (name) {
2675
- const local = scope.locals[name];
2676
- if (local.metadata?.type != null) return v.metadata.type;
2677
- }
2721
+ if (scope.locals[name]?.metadata?.type != null) return scope.locals[name].metadata.type;
2678
2722
  }
2679
2723
 
2680
2724
  return null;
@@ -2775,8 +2819,6 @@ const typeUsed = (scope, x) => {
2775
2819
  if (x == null) return;
2776
2820
  usedTypes.add(x);
2777
2821
 
2778
- // console.log(scope.name, TYPE_NAMES[x]);
2779
-
2780
2822
  scope.usedTypes ??= new Set();
2781
2823
  scope.usedTypes.add(x);
2782
2824
  };
@@ -2932,6 +2974,11 @@ const allocVar = (scope, name, global = false, type = true) => {
2932
2974
  return idx;
2933
2975
  };
2934
2976
 
2977
+ const setVarMetadata = (scope, name, global = false, metadata = {}) => {
2978
+ const target = global ? globals : scope.locals;
2979
+ target[name].metadata = metadata;
2980
+ };
2981
+
2935
2982
  const addVarMetadata = (scope, name, global = false, metadata = {}) => {
2936
2983
  const target = global ? globals : scope.locals;
2937
2984
 
@@ -3111,13 +3158,12 @@ const generateVarDstr = (scope, kind, pattern, init, defaultValue, global) => {
3111
3158
  // let generated;
3112
3159
  // if (init) generated = generate(scope, init, global, name);
3113
3160
 
3114
- const typed = typedInput && pattern.typeAnnotation;
3115
- let idx = allocVar(scope, name, global, !(typed && extractTypeAnnotation(pattern).type != null));
3116
- addVarMetadata(scope, name, global, { kind });
3161
+ const typed = typedInput && pattern.typeAnnotation && extractTypeAnnotation(pattern);
3162
+ let idx = allocVar(scope, name, global, !(typed && typed.type != null));
3117
3163
 
3118
- if (typed) {
3119
- addVarMetadata(scope, name, global, extractTypeAnnotation(pattern));
3120
- }
3164
+ const metadata = { kind };
3165
+ setVarMetadata(scope, name, global, metadata);
3166
+ if (typed) Object.assign(metadata, typed);
3121
3167
 
3122
3168
  if (init) {
3123
3169
  const alreadyArray = scope.arrays?.get(name) != null;
@@ -3143,7 +3189,7 @@ const generateVarDstr = (scope, kind, pattern, init, defaultValue, global) => {
3143
3189
  [ Opcodes.if, Blocktype.void ],
3144
3190
  ...generate(scope, defaultValue, global, name),
3145
3191
  [ global ? Opcodes.global_set : Opcodes.local_set, idx ],
3146
- ...setType(scope, name, getNodeType(scope, defaultValue)),
3192
+ ...setType(scope, name, getNodeType(scope, defaultValue), true),
3147
3193
  [ Opcodes.end ],
3148
3194
  );
3149
3195
  }
@@ -3152,6 +3198,8 @@ const generateVarDstr = (scope, kind, pattern, init, defaultValue, global) => {
3152
3198
  scope.globalInits ??= {};
3153
3199
  scope.globalInits[name] = newOut;
3154
3200
  }
3201
+ } else {
3202
+ setInferred(scope, name, null, global);
3155
3203
  }
3156
3204
 
3157
3205
  return out;
@@ -3714,7 +3762,7 @@ const generateAssign = (scope, decl, _global, _name, valueUnused = false) => {
3714
3762
  // only allow = for this, or if in strict mode always throw
3715
3763
  if (!isIdentAssignable(scope, name, op)) return internalThrow(scope, 'ReferenceError', `${unhackName(name)} is not defined`, true);
3716
3764
 
3717
- if (type != 'Identifier') {
3765
+ if (type !== 'Identifier') {
3718
3766
  const tmpName = '#rhs' + uniqId();
3719
3767
  return [
3720
3768
  ...generateVarDstr(scope, 'const', tmpName, decl.right, undefined, true),
@@ -3755,6 +3803,8 @@ const generateAssign = (scope, decl, _global, _name, valueUnused = false) => {
3755
3803
  // instead, left @ (left = right)
3756
3804
  // eg, x &&= y ~= x && (x = y)
3757
3805
 
3806
+ setInferred(scope, name, knownType(scope, getNodeType(scope, decl)), isGlobal);
3807
+
3758
3808
  return [
3759
3809
  ...performOp(scope, op, [
3760
3810
  [ isGlobal ? Opcodes.global_get : Opcodes.local_get, local.idx ]
@@ -3765,7 +3815,7 @@ const generateAssign = (scope, decl, _global, _name, valueUnused = false) => {
3765
3815
  ], getType(scope, name), getNodeType(scope, decl.right), isGlobal, name, true),
3766
3816
  [ isGlobal ? Opcodes.global_get : Opcodes.local_get, local.idx ],
3767
3817
 
3768
- ...setType(scope, name, getLastType(scope))
3818
+ ...setType(scope, name, getLastType(scope), true)
3769
3819
  ];
3770
3820
  }
3771
3821
 
@@ -3776,6 +3826,8 @@ const generateAssign = (scope, decl, _global, _name, valueUnused = false) => {
3776
3826
  getNodeType(scope, decl)
3777
3827
  );
3778
3828
 
3829
+ setInferred(scope, name, knownType(scope, getNodeType(scope, decl)), isGlobal);
3830
+
3779
3831
  if (valueUnused) out.push(...number(UNDEFINED));
3780
3832
  return out;
3781
3833
  };
@@ -3999,6 +4051,33 @@ const generateUpdate = (scope, decl, _global, _name, valueUnused = false) => {
3999
4051
  ];
4000
4052
  };
4001
4053
 
4054
+ const inferBranchStart = (scope, decl) => {
4055
+ scope.inferTree ??= [];
4056
+ scope.inferTree.push(decl);
4057
+ };
4058
+
4059
+ const inferBranchEnd = scope => {
4060
+ scope.inferTree.pop();
4061
+ };
4062
+
4063
+ const inferBranchElse = (scope, decl) => {
4064
+ inferBranchEnd(scope);
4065
+ inferBranchStart(scope, decl);
4066
+ };
4067
+
4068
+ const inferLoopPrev = [];
4069
+ const inferLoopStart = (scope, decl) => {
4070
+ scope.inferTree ??= [];
4071
+
4072
+ // todo/opt: do not just wipe the infer tree for loops
4073
+ inferLoopPrev.push(scope.inferTree);
4074
+ scope.inferTree = [ decl ];
4075
+ };
4076
+
4077
+ const inferLoopEnd = scope => {
4078
+ scope.inferTree = inferLoopPrev.pop();
4079
+ };
4080
+
4002
4081
  const generateIf = (scope, decl) => {
4003
4082
  if (globalThis.precompile && decl.test?.tag?.name === '__Porffor_comptime_flag') {
4004
4083
  const flag = decl.test.quasi.quasis[0].value.raw;
@@ -4006,20 +4085,23 @@ const generateIf = (scope, decl) => {
4006
4085
  }
4007
4086
 
4008
4087
  const out = truthy(scope, generate(scope, decl.test), getNodeType(scope, decl.test), false, true);
4009
-
4010
4088
  out.push([ Opcodes.if, Blocktype.void ]);
4011
4089
  depth.push('if');
4090
+ inferBranchStart(scope, decl.consequent);
4012
4091
 
4013
4092
  const consOut = generate(scope, decl.consequent);
4014
4093
  disposeLeftover(consOut);
4015
4094
  out.push(...consOut);
4016
4095
 
4096
+ inferBranchEnd(scope);
4017
4097
  if (decl.alternate) {
4018
4098
  out.push([ Opcodes.else ]);
4099
+ inferBranchStart(scope, decl.alternate);
4019
4100
 
4020
4101
  const altOut = generate(scope, decl.alternate);
4021
4102
  disposeLeftover(altOut);
4022
4103
  out.push(...altOut);
4104
+ inferBranchEnd(scope);
4023
4105
  }
4024
4106
 
4025
4107
  out.push([ Opcodes.end ]);
@@ -4033,6 +4115,7 @@ const generateConditional = (scope, decl) => {
4033
4115
 
4034
4116
  out.push([ Opcodes.if, valtypeBinary ]);
4035
4117
  depth.push('if');
4118
+ inferBranchStart(scope, decl.consequent);
4036
4119
 
4037
4120
  out.push(
4038
4121
  ...generate(scope, decl.consequent),
@@ -4040,6 +4123,7 @@ const generateConditional = (scope, decl) => {
4040
4123
  );
4041
4124
 
4042
4125
  out.push([ Opcodes.else ]);
4126
+ inferBranchElse(scope, decl.alternate);
4043
4127
 
4044
4128
  out.push(
4045
4129
  ...generate(scope, decl.alternate),
@@ -4047,7 +4131,7 @@ const generateConditional = (scope, decl) => {
4047
4131
  );
4048
4132
 
4049
4133
  out.push([ Opcodes.end ]);
4050
- depth.pop();
4134
+ inferBranchEnd(scope);
4051
4135
 
4052
4136
  return out;
4053
4137
  };
@@ -4061,6 +4145,7 @@ const generateFor = (scope, decl) => {
4061
4145
  disposeLeftover(out);
4062
4146
  }
4063
4147
 
4148
+ inferLoopStart(scope, decl);
4064
4149
  out.push([ Opcodes.loop, Blocktype.void ]);
4065
4150
  depth.push('for');
4066
4151
 
@@ -4081,11 +4166,13 @@ const generateFor = (scope, decl) => {
4081
4166
  out.push([ Opcodes.end ], [ Opcodes.end ]);
4082
4167
  depth.pop(); depth.pop(); depth.pop();
4083
4168
 
4169
+ inferLoopEnd(scope);
4084
4170
  return out;
4085
4171
  };
4086
4172
 
4087
4173
  const generateWhile = (scope, decl) => {
4088
4174
  const out = [];
4175
+ inferLoopStart(scope, decl);
4089
4176
 
4090
4177
  out.push([ Opcodes.loop, Blocktype.void ]);
4091
4178
  depth.push('while');
@@ -4100,11 +4187,13 @@ const generateWhile = (scope, decl) => {
4100
4187
  out.push([ Opcodes.end ], [ Opcodes.end ]);
4101
4188
  depth.pop(); depth.pop();
4102
4189
 
4190
+ inferLoopEnd(scope);
4103
4191
  return out;
4104
4192
  };
4105
4193
 
4106
4194
  const generateDoWhile = (scope, decl) => {
4107
4195
  const out = [];
4196
+ inferLoopStart(scope, decl);
4108
4197
 
4109
4198
  out.push([ Opcodes.loop, Blocktype.void ]);
4110
4199
  depth.push('dowhile');
@@ -4130,6 +4219,7 @@ const generateDoWhile = (scope, decl) => {
4130
4219
  out.push([ Opcodes.end ], [ Opcodes.end ]);
4131
4220
  depth.pop(); depth.pop();
4132
4221
 
4222
+ inferLoopEnd(scope);
4133
4223
  return out;
4134
4224
  };
4135
4225
 
@@ -4174,6 +4264,7 @@ const generateForOf = (scope, decl) => {
4174
4264
  [ Opcodes.if, Blocktype.void ]
4175
4265
  );
4176
4266
 
4267
+ inferLoopStart(scope, decl);
4177
4268
  depth.push('if');
4178
4269
  depth.push('forof');
4179
4270
  depth.push('block');
@@ -4504,6 +4595,7 @@ const generateForOf = (scope, decl) => {
4504
4595
  depth.pop();
4505
4596
  depth.pop();
4506
4597
 
4598
+ inferLoopEnd(scope);
4507
4599
  return out;
4508
4600
  };
4509
4601
 
@@ -4537,6 +4629,7 @@ const generateForIn = (scope, decl) => {
4537
4629
  [ Opcodes.if, Blocktype.void ]
4538
4630
  );
4539
4631
 
4632
+ inferLoopStart(scope, decl);
4540
4633
  depth.push('if');
4541
4634
  depth.push('forin');
4542
4635
  depth.push('block');
@@ -4630,6 +4723,8 @@ const generateForIn = (scope, decl) => {
4630
4723
  depth.pop();
4631
4724
  depth.pop();
4632
4725
 
4726
+ inferLoopEnd(scope);
4727
+
4633
4728
  return typeSwitch(scope, getNodeType(scope, decl.right), {
4634
4729
  // fast path for objects
4635
4730
  [TYPES.object]: out,
@@ -5872,7 +5967,6 @@ const generateClass = (scope, decl) => {
5872
5967
  export const generateTemplate = (scope, decl) => {
5873
5968
  let current = null;
5874
5969
  const append = val => {
5875
- // console.log(val);
5876
5970
  if (!current) {
5877
5971
  current = val;
5878
5972
  return;
@@ -6065,6 +6159,8 @@ const generateFunc = (scope, decl, forceNoExpr = false) => {
6065
6159
  return [ func, out ];
6066
6160
  }
6067
6161
 
6162
+ if (name === '#main') globalInfer = new Map();
6163
+
6068
6164
  globalThis.progress?.(null, ' ' + name);
6069
6165
 
6070
6166
  const params = decl.params ?? [];
@@ -6083,6 +6179,7 @@ const generateFunc = (scope, decl, forceNoExpr = false) => {
6083
6179
  async: decl.async,
6084
6180
  subclass: decl._subclass, _onlyConstr: decl._onlyConstr, _onlyThisMethod: decl._onlyThisMethod,
6085
6181
  strict: scope.strict || decl.strict,
6182
+ inferTree: [ decl ],
6086
6183
 
6087
6184
  generate() {
6088
6185
  if (func.wasm) return func.wasm;
@@ -6163,7 +6260,7 @@ const generateFunc = (scope, decl, forceNoExpr = false) => {
6163
6260
  ...generate(func, def, false, name),
6164
6261
  [ Opcodes.local_set, func.locals[name].idx ],
6165
6262
 
6166
- ...setType(func, name, getNodeType(func, def)),
6263
+ ...setType(func, name, getNodeType(func, def), true),
6167
6264
  [ Opcodes.end ]
6168
6265
  );
6169
6266
 
@@ -6257,7 +6354,7 @@ const generateFunc = (scope, decl, forceNoExpr = false) => {
6257
6354
  let finalStatement = decl.body.body[decl.body.body.length - 1];
6258
6355
  if (finalStatement?.type === 'EmptyStatement') finalStatement = decl.body.body[decl.body.body.length - 2];
6259
6356
 
6260
- const lastInst = wasm[wasm.length - 1] ?? [ Opcodes.end ];
6357
+ const lastInst = getLastInst(wasm) ?? [ Opcodes.end ];
6261
6358
  if (lastInst[0] === Opcodes.drop || lastInst[0] === Opcodes.f64_const) {
6262
6359
  if (finalStatement.type.endsWith('Declaration')) {
6263
6360
  // final statement is decl, force undefined
@@ -6376,10 +6473,14 @@ const generateFunc = (scope, decl, forceNoExpr = false) => {
6376
6473
  const generateCode = (scope, decl) => {
6377
6474
  let out = [];
6378
6475
 
6476
+ scope.inferTree ??= [];
6477
+ scope.inferTree.push(decl);
6478
+
6379
6479
  for (const x of decl.body) {
6380
6480
  out = out.concat(generate(scope, x));
6381
6481
  }
6382
6482
 
6483
+ scope.inferTree.pop();
6383
6484
  return out;
6384
6485
  };
6385
6486
 
@@ -6497,6 +6598,13 @@ const internalConstrs = {
6497
6598
  type: TYPES.number,
6498
6599
  notConstr: true,
6499
6600
  length: 1
6601
+ },
6602
+
6603
+ __Porffor_compileType: {
6604
+ generate: (scope, decl) => makeString(scope, TYPE_NAMES[knownType(scope, getNodeType(scope, decl.arguments[0]))] ?? 'unknown'),
6605
+ type: TYPES.bytestring,
6606
+ notConstr: true,
6607
+ length: 1
6500
6608
  }
6501
6609
  };
6502
6610
 
@@ -3,7 +3,6 @@ import { signedLEB128, ieee754_binary64, read_ieee754_binary64, read_signedLEB12
3
3
  import { Opcodes, Valtype } from './wasmSpec.js';
4
4
  import { number } from './embedding.js';
5
5
 
6
-
7
6
  const f64ToI32Op = {
8
7
  [Opcodes.f64_eq]: Opcodes.i32_eq,
9
8
  [Opcodes.f64_ne]: Opcodes.i32_ne,
@@ -23,7 +22,6 @@ export default wasm => {
23
22
  let op = wasm[i];
24
23
  if (!op) continue;
25
24
 
26
- // op = [ ...op.filter(x => x != null && x <= 0xff) ];
27
25
  op = [ ...op ];
28
26
  wasm[i] = op;
29
27
 
@@ -479,6 +477,12 @@ export default wasm => {
479
477
  break;
480
478
  }
481
479
 
480
+ // case Opcodes.local_tee: {
481
+ // if (stack.length < 1) { empty(); break; }
482
+ // push(pop());
483
+ // break;
484
+ // }
485
+
482
486
  default: {
483
487
  empty();
484
488
  break;
package/compiler/index.js CHANGED
@@ -96,6 +96,8 @@ export default (code, module = undefined) => {
96
96
  if (logProgress) progressStart('generating wasm...');
97
97
  const t1 = performance.now();
98
98
  const { funcs, globals, tags, exceptions, pages, data } = codegen(program);
99
+ if (globalThis.compileCallback) globalThis.compileCallback({ funcs, globals, tags, exceptions, pages, data });
100
+
99
101
  if (logProgress) progressDone('generated wasm', t1);
100
102
 
101
103
  if (Prefs.funcs) logFuncs(funcs, globals, exceptions);
package/compiler/parse.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { log } from './log.js';
2
2
  import './prefs.js';
3
3
 
4
- const file = process.argv.slice(2).find(x => x[0] !== '-' && !['precompile', 'run', 'wasm', 'native', 'c', 'hotlines', 'debug', 'dissect'].includes(x));
4
+ const file = globalThis.file;
5
5
 
6
6
  // should we try to support types (while parsing)
7
7
  const types = Prefs.parseTypes || Prefs.t || file?.endsWith('.ts');
@@ -45,7 +45,7 @@ const compile = async (file, _funcs) => {
45
45
  first = source.slice(0, source.indexOf('\n'));
46
46
  }
47
47
 
48
- 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'];
48
+ 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', '--no-treeshake-wasm-imports'];
49
49
  if (first.startsWith('// @porf')) {
50
50
  args = first.slice('// @porf '.length).split(' ').concat(args);
51
51
  }
@@ -190,15 +190,15 @@ const precompile = async () => {
190
190
  try {
191
191
  await compile(join(dir, file), funcs);
192
192
  } catch (e) {
193
- console.log(`\r${' '.repeat(100)}\r${' '.repeat(12)}${file}`);
193
+ console.log(`\r${' '.repeat(80)}\r${' '.repeat(12)}${file}`);
194
194
  throw e;
195
195
  }
196
196
 
197
- process.stdout.write(`\r${' '.repeat(100)}\r\u001b[90m${`[${(performance.now() - t).toFixed(2)}ms]`.padEnd(12, ' ')}\u001b[0m\u001b[92m${file}\u001b[0m`);
197
+ process.stdout.write(`\r${' '.repeat(80)}\r\u001b[90m${`[${(performance.now() - t).toFixed(2)}ms]`.padEnd(12, ' ')}\u001b[0m\u001b[92m${file}\u001b[0m`);
198
198
  }
199
199
 
200
200
  const total = performance.now() - t;
201
- console.log(`\r${' '.repeat(100)}\r\u001b[90m${`[${total.toFixed(2)}ms]`.padEnd(12, ' ')}\u001b[0m\u001b[92mcompiled ${fileCount} files (${funcs.length} funcs)\u001b[0m \u001b[90m(${['parse', 'codegen', 'opt'].map(x => `${x}: ${((timing[x] / total) * 100).toFixed(0)}%`).join(', ')})\u001b[0m`);
201
+ console.log(`\r${' '.repeat(80)}\r\u001b[90m${`[${total.toFixed(2)}ms]`.padEnd(12, ' ')}\u001b[0m\u001b[92mcompiled ${fileCount} files (${funcs.length} funcs)\u001b[0m \u001b[90m(${['parse', 'codegen', 'opt'].map(x => `${x}: ${((timing[x] / total) * 100).toFixed(0)}%`).join(', ')})\u001b[0m`);
202
202
 
203
203
  const comptimeFlagChecks = {
204
204
  hasFunc: x => `hasFunc('${x}')`
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.49.7",
4
+ "version": "0.49.8",
5
5
  "author": "CanadaHonk",
6
6
  "license": "MIT",
7
7
  "scripts": {},
package/runner/debug.js CHANGED
@@ -1,5 +1,4 @@
1
1
  #!/usr/bin/env node
2
-
3
2
  import compile from '../compiler/wrap.js';
4
3
  import Byg from '../byg/index.js';
5
4
  import fs from 'node:fs';