porffor 0.55.36 → 0.56.0

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.
@@ -809,12 +809,23 @@ const compareStrings = (scope, left, right, leftType, rightType, noConv = false)
809
809
  };
810
810
 
811
811
  const truthy = (scope, wasm, type, intIn = false, intOut = false, forceTruthyMode = undefined) => {
812
+ const truthyMode = forceTruthyMode ?? Prefs.truthy ?? 'full';
812
813
  if (isIntToFloatOp(wasm[wasm.length - 1])) return [
813
814
  ...wasm,
814
- ...(!intIn && intOut ? [ Opcodes.i32_to_u ] : [])
815
+ ...(truthyMode === 'full' ? [
816
+ [ Opcodes.f64_const, 0 ],
817
+ [ Opcodes.f64_ne ],
818
+ ...(!intOut ? [ Opcodes.i32_from_u ] : [])
819
+ ] : [
820
+ ...(!intIn && intOut ? [ Opcodes.i32_to_u ] : [])
821
+ ])
815
822
  ];
816
823
  if (isIntOp(wasm[wasm.length - 1])) return [
817
824
  ...wasm,
825
+ ...(truthyMode === 'full' ? [
826
+ [ Opcodes.i32_eqz ],
827
+ [ Opcodes.i32_eqz ]
828
+ ] : []),
818
829
  ...(intOut ? [] : [ Opcodes.i32_from ]),
819
830
  ];
820
831
 
@@ -822,8 +833,6 @@ const truthy = (scope, wasm, type, intIn = false, intOut = false, forceTruthyMod
822
833
 
823
834
  const useTmp = knownType(scope, type) == null;
824
835
  const tmp = useTmp && localTmp(scope, `#logicinner_tmp${intIn ? '_int' : ''}`, intIn ? Valtype.i32 : valtypeBinary);
825
-
826
- const truthyMode = forceTruthyMode ?? Prefs.truthy ?? 'full';
827
836
  const def = (() => {
828
837
  if (truthyMode === 'full') return [
829
838
  // if value != 0 or NaN
@@ -1059,21 +1068,9 @@ const performOp = (scope, op, left, right, leftType, rightType) => {
1059
1068
 
1060
1069
  let ops = operatorOpcode[valtype][op];
1061
1070
 
1062
- // some complex ops are implemented as builtin funcs
1063
- const builtinName = `${valtype}_${op}`;
1064
- if (!ops && builtinFuncs[builtinName]) {
1065
- includeBuiltin(scope, builtinName);
1066
- const idx = funcIndex[builtinName];
1067
-
1068
- return finalize([
1069
- ...left,
1070
- ...right,
1071
- [ Opcodes.call, idx ]
1072
- ]);
1073
- }
1074
-
1071
+ // some complex ops are implemented in funcs
1072
+ if (typeof ops === 'function') return finalize(asmFuncToAsm(scope, ops, { left, right }));
1075
1073
  if (!ops) return todo(scope, `operator ${op} not implemented yet`, true);
1076
-
1077
1074
  if (!Array.isArray(ops)) ops = [ ops ];
1078
1075
  ops = [ ops ];
1079
1076
 
@@ -1244,7 +1241,7 @@ const generateBinaryExp = (scope, decl) => {
1244
1241
  return out;
1245
1242
  };
1246
1243
 
1247
- const asmFuncToAsm = (scope, func) => {
1244
+ const asmFuncToAsm = (scope, func, extra) => {
1248
1245
  return func(scope, {
1249
1246
  Valtype, Opcodes, TYPES, TYPE_NAMES, usedTypes, typeSwitch, makeString, internalThrow,
1250
1247
  getNodeType, generate, generateIdent,
@@ -1325,7 +1322,7 @@ const asmFuncToAsm = (scope, func) => {
1325
1322
  return wasm;
1326
1323
  },
1327
1324
  allocPage: (scope, name) => allocPage({ scope, pages }, name)
1328
- });
1325
+ }, extra);
1329
1326
  };
1330
1327
 
1331
1328
  const asmFunc = (name, { wasm, params = [], typedParams = false, locals: localTypes = [], globals: globalTypes = [], globalInits = [], returns = [], returnType, localNames = [], globalNames = [], table = false, constr = false, hasRestArgument = false, usesTag = false, usesImports = false, usedTypes = [] } = {}) => {
@@ -1,4 +1,14 @@
1
- import { Opcodes } from './wasmSpec.js';
1
+ import { Opcodes, Valtype } from './wasmSpec.js';
2
+ import { TYPES } from './types.js';
3
+
4
+ const f64ifyBitwise = op => (_1, _2, { left, right }) => [
5
+ ...left,
6
+ Opcodes.i32_trunc_sat_f64_s,
7
+ ...right,
8
+ Opcodes.i32_trunc_sat_f64_s,
9
+ [ op ],
10
+ [ Opcodes.f64_convert_i32_s ]
11
+ ];
2
12
 
3
13
  export const operatorOpcode = {
4
14
  i32: {
@@ -23,7 +33,17 @@ export const operatorOpcode = {
23
33
  '>': Opcodes.i32_gt_s,
24
34
  '>=': Opcodes.i32_ge_s,
25
35
  '<': Opcodes.i32_lt_s,
26
- '<=': Opcodes.i32_le_s
36
+ '<=': Opcodes.i32_le_s,
37
+
38
+ '**': (_, { builtin }, { left, right }) => [
39
+ ...left,
40
+ [ Opcodes.f64_convert_i32_s ],
41
+ [ Opcodes.i32_const, TYPES.number ],
42
+ ...right,
43
+ [ Opcodes.f64_convert_i32_s ],
44
+ [ Opcodes.i32_const, TYPES.number ],
45
+ [ Opcodes.call, builtin('__Math_pow') ]
46
+ ]
27
47
  },
28
48
 
29
49
  i64: {
@@ -65,6 +85,38 @@ export const operatorOpcode = {
65
85
  '>': Opcodes.f64_gt,
66
86
  '>=': Opcodes.f64_ge,
67
87
  '<': Opcodes.f64_lt,
68
- '<=': Opcodes.f64_le
88
+ '<=': Opcodes.f64_le,
89
+
90
+ '**': (_, { builtin }, { left, right }) => [
91
+ ...left,
92
+ [ Opcodes.i32_const, TYPES.number ],
93
+ ...right,
94
+ [ Opcodes.i32_const, TYPES.number ],
95
+ [ Opcodes.call, builtin('__Math_pow') ]
96
+ ],
97
+
98
+ '%': (_, { builtin, loc }, { left, right }) => [
99
+ // a - truncf(a / b) * b
100
+ ...left,
101
+ [ Opcodes.local_tee, loc('#math_a', Valtype.f64) ],
102
+ ...right,
103
+ [ Opcodes.local_tee, loc('#math_b', Valtype.f64) ],
104
+
105
+ [ Opcodes.local_get, loc('#math_a', Valtype.f64) ],
106
+ [ Opcodes.local_get, loc('#math_b', Valtype.f64) ],
107
+ [ Opcodes.f64_div ],
108
+ [ Opcodes.f64_trunc ],
109
+
110
+ [ Opcodes.f64_mul ],
111
+ [ Opcodes.f64_sub ]
112
+ ],
113
+
114
+ // add bitwise ops by converting operands to i32 first
115
+ '&': f64ifyBitwise(Opcodes.i32_and),
116
+ '|': f64ifyBitwise(Opcodes.i32_or),
117
+ '^': f64ifyBitwise(Opcodes.i32_xor),
118
+ '<<': f64ifyBitwise(Opcodes.i32_shl),
119
+ '>>': f64ifyBitwise(Opcodes.i32_shr_s),
120
+ '>>>': f64ifyBitwise(Opcodes.i32_shr_u)
69
121
  }
70
122
  };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "porffor",
3
3
  "description": "An ahead-of-time JavaScript compiler",
4
- "version": "0.55.36",
4
+ "version": "0.56.0",
5
5
  "author": "Oliver Medhurst <honk@goose.icu>",
6
6
  "license": "MIT",
7
7
  "scripts": {},
package/r.cjs CHANGED
@@ -1,8 +1,107 @@
1
- function* foo() {
2
- yield* [1, 2, 3];
1
+ var assert = mustBeTrue => {
2
+ if (mustBeTrue === true) {
3
+ return;
4
+ }
5
+
6
+ throw new Test262Error('assert failed');
7
+ };
8
+
9
+ function isConfigurable(obj, name) {
10
+ if (Object.hasOwn(obj, name)) return Object.getOwnPropertyDescriptor(obj, name).configurable;
11
+ return true;
12
+ }
13
+
14
+ function isEnumerable(obj, name) {
15
+ return Object.hasOwn(obj, name) && Object.getOwnPropertyDescriptor(obj, name).enumerable;
16
+ }
17
+
18
+ function isSameValue(a, b) {
19
+ if (a === 0 && b === 0) return 1 / a === 1 / b;
20
+ if (a !== a && b !== b) return true;
21
+
22
+ return a === b;
23
+ }
24
+
25
+ function isWritable(obj, name, verifyProp, value) {
26
+ if (Object.hasOwn(obj, name) && Object.getOwnPropertyDescriptor(obj, name).writable != null) return Object.getOwnPropertyDescriptor(obj, name).writable;
27
+ if (!Object.hasOwn(obj, name) && Object.isExtensible(obj)) return true;
28
+
29
+ var unlikelyValue = Array.isArray(obj) && name === "length" ?
30
+ Math.pow(2, 32) - 1 :
31
+ "unlikelyValue";
32
+ var newValue = value || unlikelyValue;
33
+ var hadValue = Object.hasOwn(obj, name);
34
+ var oldValue = obj[name];
35
+ var writeSucceeded;
36
+
37
+ try {
38
+ obj[name] = newValue;
39
+ } catch {}
40
+
41
+ writeSucceeded = isSameValue(obj[verifyProp || name], newValue);
42
+
43
+ if (writeSucceeded) {
44
+ if (hadValue) {
45
+ obj[name] = oldValue;
46
+ } else {
47
+ delete obj[name];
48
+ }
49
+ }
50
+
51
+ return writeSucceeded;
3
52
  }
4
53
 
5
- console.log(foo().next());
54
+ function verifyProperty(obj, name, desc, options) {
55
+ var originalDesc = Object.getOwnPropertyDescriptor(obj, name);
56
+
57
+ if (desc === undefined) {
58
+ if (originalDesc !== undefined) {
59
+ throw new Test262Error('verifyProperty: expected undefined descriptor');
60
+ }
61
+
62
+ return true;
63
+ }
64
+
65
+ if (!Object.hasOwn(obj, name)) throw new Test262Error('verifyProperty: obj should have own property');
66
+
67
+ if (Object.hasOwn(desc, 'value')) {
68
+ const v = desc.value;
69
+ if (!isSameValue(originalDesc.value, v)) throw new Test262Error('verifyProperty: descriptor value mismatch');
70
+ // if (!isSameValue(obj[name], v)) throw new Test262Error('verifyProperty: object value mismatch');
71
+ }
72
+
73
+ if (Object.hasOwn(desc, 'enumerable')) {
74
+ if (desc.enumerable !== originalDesc.enumerable ||
75
+ desc.enumerable !== isEnumerable(obj, name)) {
76
+ throw new Test262Error('enumerable fail');
77
+ }
78
+ }
79
+
80
+ if (Object.hasOwn(desc, 'writable')) {
81
+ if (desc.writable !== originalDesc.writable ||
82
+ desc.writable !== isWritable(obj, name)) {
83
+ throw new Test262Error('writable fail');
84
+ }
85
+ }
86
+
87
+ if (Object.hasOwn(desc, 'configurable')) {
88
+ if (desc.configurable !== originalDesc.configurable ||
89
+ desc.configurable !== isConfigurable(obj, name)) {
90
+ throw new Test262Error('configurable fail');
91
+ }
92
+ }
93
+
94
+ if (options && options.restore) {
95
+ Object.defineProperty(obj, name, originalDesc);
96
+ }
97
+
98
+ return true;
99
+ }
100
+
101
+ const desc = { enumerable: true, configurable: true, writable: true };
102
+ const obj = Object.defineProperty({}, 'wow', desc);
103
+ assert(verifyProperty(obj, 'wow', desc));
104
+
6
105
 
7
106
  // var EQUAL = 1;
8
107
  // var NOT_EQUAL = -1;
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.55.36';
3
+ globalThis.version = '0.56.0';
4
4
 
5
5
  // deno compat
6
6
  if (typeof process === 'undefined' && typeof Deno !== 'undefined') {