porffor 0.42.6 → 0.42.7

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.
@@ -279,7 +279,7 @@ export const __Math_cbrt = (y: number): number => {
279
279
  if (!Number.isFinite(y)) return y;
280
280
 
281
281
  // Babylonian method
282
- let x = Math.abs(y);
282
+ let x:number = Math.abs(y);
283
283
 
284
284
  let prev: number;
285
285
 
@@ -1780,9 +1780,9 @@ params:[124,127],typedParams:1,returns:[124,127],typedReturns:1,
1780
1780
  locals:[124,124],localNames:["y","y#type","x","prev"],
1781
1781
  }
1782
1782
  this.__Math_cbrt = {
1783
- wasm:(_,{builtin})=>[[32,0],[68,0],[97],[4,64],[68,0],[65,1],[15],[11],[32,0],[16,builtin('__Number_isFinite')],[68,0],[97],[4,64],[32,0],[65,1],[15],[11],[32,0],[16,builtin('__Math_abs')],[33,2],[65,1],[33,3],[3,64],[2,64],[32,2],[33,4],[68,2],[32,2],[162],[32,0],[32,2],[32,2],[162],[163],[160],[68,3],[163],[34,2],[65,1],[33,3],[26],[32,4],[32,2],[161],[16,builtin('__Math_abs')],[68,1e-15],[100],[13,1],[11],[11],[32,0],[68,0],[99],[4,124],[32,2],[154],[65,1],[33,5],[5],[32,2],[32,3],[33,5],[11],[32,5],[15]],
1783
+ wasm:(_,{builtin})=>[[32,0],[68,0],[97],[4,64],[68,0],[65,1],[15],[11],[32,0],[16,builtin('__Number_isFinite')],[68,0],[97],[4,64],[32,0],[65,1],[15],[11],[32,0],[16,builtin('__Math_abs')],[33,2],[3,64],[2,64],[32,2],[33,3],[68,2],[32,2],[162],[32,0],[32,2],[32,2],[162],[163],[160],[68,3],[163],[33,2],[32,3],[32,2],[161],[16,builtin('__Math_abs')],[68,1e-15],[100],[13,1],[11],[11],[32,0],[68,0],[99],[4,124],[32,2],[154],[65,1],[33,4],[5],[32,2],[65,1],[33,4],[11],[32,4],[15]],
1784
1784
  params:[124,127],typedParams:1,returns:[124,127],typedReturns:1,
1785
- locals:[124,127,124,127],localNames:["y","y#type","x","x#type","prev","#last_type"],
1785
+ locals:[124,124,127],localNames:["y","y#type","x","prev","#last_type"],
1786
1786
  }
1787
1787
  this.__Math_hypot = {
1788
1788
  wasm:(_,{builtin})=>[[32,0],[32,0],[162],[32,2],[32,2],[162],[160],[65,1],[16,builtin('__Math_sqrt')],[34,4],[15]],
@@ -1340,8 +1340,12 @@ const setType = (scope, name, type) => {
1340
1340
  };
1341
1341
 
1342
1342
  const getLastType = scope => {
1343
+ if (!scope.locals['#last_type']) return number(TYPES.number, Valtype.i32);
1344
+
1343
1345
  scope.gotLastType = true;
1344
- return [ [ Opcodes.local_get, localTmp(scope, '#last_type', Valtype.i32) ] ];
1346
+ return [
1347
+ [ Opcodes.local_get, localTmp(scope, '#last_type', Valtype.i32) ]
1348
+ ];
1345
1349
  };
1346
1350
 
1347
1351
  const setLastType = (scope, type = []) => {
@@ -1388,11 +1392,7 @@ const getNodeType = (scope, node) => {
1388
1392
 
1389
1393
  if (name == null) {
1390
1394
  // iife
1391
- if (scope.locals['#last_type']) return getLastType(scope);
1392
-
1393
- // presume
1394
- if (Prefs.warnAssumedType) console.warn(`Indirect call assumed to be number`);
1395
- return TYPES.number;
1395
+ return getLastType(scope);
1396
1396
  }
1397
1397
 
1398
1398
  const func = funcByName(name);
@@ -1426,38 +1426,7 @@ const getNodeType = (scope, node) => {
1426
1426
  return TYPES.number;
1427
1427
  }
1428
1428
 
1429
- if (scope.locals['#last_type']) return getLastType(scope);
1430
-
1431
- // presume
1432
- if (Prefs.warnAssumedType) console.warn(`Call to ${name} assumed to be number`);
1433
- return TYPES.number;
1434
-
1435
- // let protoFunc;
1436
- // // ident.func()
1437
- // if (name && name.startsWith('__')) {
1438
- // const spl = name.slice(2).split('_');
1439
-
1440
- // const baseName = spl.slice(0, -1).join('_');
1441
- // const baseType = getType(scope, baseName);
1442
-
1443
- // const func = spl[spl.length - 1];
1444
- // protoFunc = prototypeFuncs[baseType]?.[func];
1445
- // }
1446
-
1447
- // // literal.func()
1448
- // if (!name && node.callee.type === 'MemberExpression') {
1449
- // if (node.callee.object.regex) {
1450
- // const funcName = node.callee.property.name;
1451
- // return Rhemyn[funcName] ? TYPES.boolean : TYPES.undefined;
1452
- // }
1453
-
1454
- // const baseType = getNodeType(scope, node.callee.object);
1455
-
1456
- // const func = node.callee.property.name;
1457
- // protoFunc = prototypeFuncs[baseType]?.[func];
1458
- // }
1459
-
1460
- // if (protoFunc) return protoFunc.returnType;
1429
+ return getLastType(scope);
1461
1430
  }
1462
1431
 
1463
1432
  if (node.type === 'ExpressionStatement') {
@@ -1505,10 +1474,7 @@ const getNodeType = (scope, node) => {
1505
1474
  if (knownLeft === TYPES.bytestring || knownRight === TYPES.bytestring)
1506
1475
  guess = TYPES.bytestring;
1507
1476
 
1508
- if (scope.locals['#last_type']) return getLastType(scope);
1509
-
1510
- // presume
1511
- return TYPES.number;
1477
+ return getLastType(scope);
1512
1478
  }
1513
1479
 
1514
1480
  if (node.type === 'UnaryExpression') {
@@ -1542,11 +1508,7 @@ const getNodeType = (scope, node) => {
1542
1508
  }
1543
1509
  }
1544
1510
 
1545
- if (scope.locals['#last_type']) return getLastType(scope);
1546
-
1547
- // presume
1548
- if (Prefs.warnAssumedType) console.warn(`Member access to field .${name} assumed to be number`);
1549
- return TYPES.number;
1511
+ return getLastType(scope);
1550
1512
  }
1551
1513
 
1552
1514
  if (node.type === 'TemplateLiteral') {
@@ -1579,11 +1541,7 @@ const getNodeType = (scope, node) => {
1579
1541
  }
1580
1542
  }
1581
1543
 
1582
- if (scope.locals['#last_type']) return getLastType(scope);
1583
-
1584
- // presume
1585
- if (Prefs.warnAssumedType) console.warn(`AST node ${node.type} assumed to be number`);
1586
- return TYPES.number;
1544
+ return getLastType(scope);
1587
1545
  })();
1588
1546
 
1589
1547
  const out = typeof ret === 'number' ? number(ret, Valtype.i32) : ret;
@@ -2447,6 +2405,31 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
2447
2405
  paramOffset += 4;
2448
2406
  }
2449
2407
 
2408
+ if (args.at(-1)?.type === 'SpreadElement') {
2409
+ // hack: support spread element if last by doing essentially:
2410
+ // const foo = (a, b, c, d) => ...
2411
+ // foo(a, b, ...c) -> _ = c; foo(a, b, _[0], _[1])
2412
+ const arg = args.at(-1).argument;
2413
+ out.push(
2414
+ ...generate(scope, arg),
2415
+ [ Opcodes.local_set, localTmp(scope, '#spread') ],
2416
+ ...getNodeType(scope, arg),
2417
+ [ Opcodes.local_set, localTmp(scope, '#spread#type', Valtype.i32) ]
2418
+ );
2419
+
2420
+ args.pop();
2421
+ const leftover = paramCount - args.length;
2422
+ for (let i = 0; i < leftover; i++) {
2423
+ args.push({
2424
+ type: 'MemberExpression',
2425
+ object: { type: 'Identifier', name: '#spread' },
2426
+ property: { type: 'Literal', value: i },
2427
+ computed: true,
2428
+ optional: false
2429
+ });
2430
+ }
2431
+ }
2432
+
2450
2433
  if (func && args.length < paramCount) {
2451
2434
  // too little args, push undefineds
2452
2435
  args = args.concat(new Array(paramCount - (func.hasRestArgument ? 1 : 0) - args.length).fill(DEFAULT_VALUE()));
@@ -3689,7 +3672,10 @@ const ifIdentifierErrors = (scope, decl) => {
3689
3672
  const generateUnary = (scope, decl) => {
3690
3673
  switch (decl.operator) {
3691
3674
  case '+':
3692
- // todo/opt: skip ToNumber if already known number type
3675
+ // opt: skip ToNumber if already known as number type
3676
+ generate(scope, decl.argument); // hack: fix last type not being defined for getNodeType before generation
3677
+ const known = knownType(scope, getNodeType(scope, decl.argument));
3678
+ if (known === TYPES.number) return generate(scope, decl.argument);
3693
3679
 
3694
3680
  // 13.5.4 Unary + Operator, 13.5.4.1 Runtime Semantics: Evaluation
3695
3681
  // https://tc39.es/ecma262/#sec-unary-plus-operator-runtime-semantics-evaluation
@@ -3707,7 +3693,7 @@ const generateUnary = (scope, decl) => {
3707
3693
  });
3708
3694
 
3709
3695
  case '-':
3710
- // * -1
3696
+ // +x * -1
3711
3697
 
3712
3698
  if (decl.prefix && decl.argument.type === 'Literal' && typeof decl.argument.value === 'number') {
3713
3699
  // if -n, just return that as a const
@@ -3715,7 +3701,12 @@ const generateUnary = (scope, decl) => {
3715
3701
  }
3716
3702
 
3717
3703
  return [
3718
- ...generate(scope, decl.argument),
3704
+ ...generate(scope, {
3705
+ type: 'UnaryExpression',
3706
+ operator: '+',
3707
+ prefix: true,
3708
+ argument: decl.argument
3709
+ }),
3719
3710
  ...(valtype === 'f64' ? [ [ Opcodes.f64_neg ] ] : [ ...number(-1), [ Opcodes.mul ] ])
3720
3711
  ];
3721
3712
 
@@ -3731,7 +3722,12 @@ const generateUnary = (scope, decl) => {
3731
3722
 
3732
3723
  case '~':
3733
3724
  return [
3734
- ...generate(scope, decl.argument),
3725
+ ...generate(scope, {
3726
+ type: 'UnaryExpression',
3727
+ operator: '+',
3728
+ prefix: true,
3729
+ argument: decl.argument
3730
+ }),
3735
3731
  Opcodes.i32_to,
3736
3732
  [ Opcodes.i32_const, ...signedLEB128(-1) ],
3737
3733
  [ Opcodes.i32_xor ],
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.42.6+d8f9d3f11",
4
+ "version": "0.42.7+5472762e8",
5
5
  "author": "CanadaHonk",
6
6
  "license": "MIT",
7
7
  "scripts": {},
package/r.js ADDED
@@ -0,0 +1,4 @@
1
+ const foo = (a, b, c, d) => console.log(a, b, c, d);
2
+
3
+ const arr = [ 7, 8, 9 ];
4
+ foo(1, ...arr);
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.42.6+d8f9d3f11';
3
+ globalThis.version = '0.42.7+5472762e8';
4
4
 
5
5
  // deno compat
6
6
  if (typeof process === 'undefined' && typeof Deno !== 'undefined') {
package/runner/repl.js CHANGED
@@ -1,5 +1,6 @@
1
1
  import { TYPE_NAMES } from '../compiler/types.js';
2
2
  import compile from '../compiler/wrap.js';
3
+ import parse from '../compiler/parse.js';
3
4
 
4
5
  import util from 'node:util';
5
6
 
@@ -83,7 +84,13 @@ const run = (source, _context, _filename, callback, run = true) => {
83
84
  // hack: print "secret" before latest code ran to only enable printing for new code
84
85
 
85
86
  source = source.trim();
86
- if (source.startsWith('{') && source.endsWith('}')) source = '(' + source + ')';
87
+ if (source.startsWith('{') && source.endsWith('}')) {
88
+ const wrapped = '(' + source + ')';
89
+ try {
90
+ parse(wrapped);
91
+ source = wrapped;
92
+ } catch {}
93
+ }
87
94
 
88
95
  let toRun = (prev ? (prev + `;\nprint(-0x1337);\n`) : '') + source;
89
96