porffor 0.57.28 → 0.57.30

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.
@@ -470,11 +470,18 @@ const lookup = (scope, name, failEarly = false) => {
470
470
  ...Opcodes.eqz,
471
471
  [ Opcodes.if, Blocktype.void ],
472
472
  ...generateObject(scope, {
473
- properties: names.map((x, i) => ({
474
- key: { type: 'Literal', value: i },
475
- value: { type: 'Identifier', name: x },
476
- kind: 'init'
477
- }))
473
+ properties: [
474
+ {
475
+ key: { type: 'Literal', value: 'length' },
476
+ value: { type: 'Literal', value: len },
477
+ kind: 'init'
478
+ },
479
+ ...names.map((x, i) => ({
480
+ key: { type: 'Literal', value: i },
481
+ value: { type: 'Identifier', name: x },
482
+ kind: 'init'
483
+ }))
484
+ ]
478
485
  }, '#arguments', false),
479
486
  [ Opcodes.local_set, localTmp(scope, '#arguments') ],
480
487
  [ Opcodes.end ],
@@ -700,11 +707,14 @@ const generateReturn = (scope, decl) => {
700
707
  ];
701
708
  }
702
709
 
703
- return [
704
- ...generate(scope, arg),
705
- ...(scope.returnType != null ? [] : getNodeType(scope, arg)),
706
- [ Opcodes.return ]
707
- ];
710
+ const out = generate(scope, arg);
711
+ if (scope.returns[0] === Valtype.f64 && valtypeBinary === Valtype.i32 && out[out.length - 1][0] !== Opcodes.f64_const && out[out.length - 1] !== Opcodes.i32_to_u)
712
+ out.push([ Opcodes.f64_convert_i32_s ]);
713
+
714
+ if (scope.returnType == null) out.push(...getNodeType(scope, arg));
715
+
716
+ out.push([ Opcodes.return ]);
717
+ return out;
708
718
  };
709
719
 
710
720
  const localTmp = (scope, name, type = valtypeBinary) => {
@@ -2536,7 +2546,8 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
2536
2546
  [ Opcodes.local_get, calleeLocal ],
2537
2547
  Opcodes.i32_to_u,
2538
2548
  [ Opcodes.call_indirect, args.length + 2, 0 ],
2539
- ...setLastType(scope)
2549
+ ...setLastType(scope),
2550
+ ...(globalThis.precompile && valtypeBinary === Valtype.i32 ? [ Opcodes.i32_trunc_sat_f64_s ] : [])
2540
2551
  ],
2541
2552
 
2542
2553
  default: decl.optional ? withType(scope, [ number(UNDEFINED) ], TYPES.undefined)
@@ -2570,13 +2581,15 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
2570
2581
  }
2571
2582
 
2572
2583
  if (func && func.constr) {
2573
- out.push(...(decl._newTargetWasm ?? createNewTarget(scope, decl, idx - importedFuncs.length)));
2574
- out.push(...(decl._thisWasm ?? createThisArg(scope, decl)));
2584
+ out.push(
2585
+ ...forceDuoValtype(scope, decl._newTargetWasm ?? createNewTarget(scope, decl, idx - importedFuncs.length), func.params[0]),
2586
+ ...forceDuoValtype(scope, decl._thisWasm ?? createThisArg(scope, decl), func.params[2])
2587
+ );
2575
2588
  paramOffset += 4;
2576
2589
  }
2577
2590
 
2578
2591
  if (func && func.method) {
2579
- out.push(...(decl._thisWasm ?? createThisArg(scope, decl)));
2592
+ out.push(...forceDuoValtype(scope, decl._thisWasm ?? createThisArg(scope, decl), func.params[0]));
2580
2593
  paramOffset += 2;
2581
2594
  }
2582
2595
 
package/compiler/opt.js CHANGED
@@ -163,6 +163,19 @@ export default (funcs, globals, pages, tags, exceptions) => {
163
163
  continue;
164
164
  }
165
165
 
166
+ if (lastInst[0] === Opcodes.i32_trunc_sat_f64_s[0] && (inst[0] === Opcodes.f64_convert_i32_u || inst[0] === Opcodes.f64_convert_i32_s)) {
167
+ // remove unneeded f64 -> i32 -> f64
168
+ // i32.trunc_sat_f64_s || i32.trunc_sat_f64_u
169
+ // f64.convert_i32_s || f64.convert_i32_u
170
+ // -->
171
+ // <nothing>
172
+
173
+ wasm.splice(i - 1, 2); // remove this inst and last
174
+ i -= 2;
175
+ // if (Prefs.optLog) log('opt', `removed redundant f64 -> i32 -> f64 conversion ops`);
176
+ continue;
177
+ }
178
+
166
179
  if (lastInst[0] === Opcodes.const && inst[0] === Opcodes.i32_to[0] && (inst[1] === Opcodes.i32_to[1] || inst[1] === Opcodes.i32_to_u[1])) {
167
180
  // change const and immediate i32 convert to i32 const
168
181
  // f64.const 0
@@ -269,7 +269,7 @@ ${funcs.map(x => {
269
269
  return `[null,()=>{const r=()=>{valtype=Prefs.valtype??'f64';valtypeBinary=Valtype[valtype];Opcodes.const=valtypeBinary===Valtype.i32?Opcodes.i32_const:Opcodes.f64_const;Opcodes.eq=valtypeBinary===Valtype.i32?Opcodes.i32_eq:Opcodes.f64_eq;Opcodes.eqz=valtypeBinary===Valtype.i32?[[Opcodes.i32_eqz]]:[number(0),[Opcodes.f64_eq]];Opcodes.mul=valtypeBinary===Valtype.i32?Opcodes.i32_mul:Opcodes.f64_mul;Opcodes.add=valtypeBinary===Valtype.i32?Opcodes.i32_add:Opcodes.f64_add;Opcodes.sub=valtypeBinary===Valtype.i32?Opcodes.i32_sub:Opcodes.f64_sub;Opcodes.i32_to=valtypeBinary===Valtype.i32?[]:Opcodes.i32_trunc_sat_f64_s;Opcodes.i32_to_u=valtypeBinary===Valtype.i32?[]:Opcodes.i32_trunc_sat_f64_u;Opcodes.i32_from=valtypeBinary===Valtype.i32?[]:[Opcodes.f64_convert_i32_s];Opcodes.i32_from_u=valtypeBinary===Valtype.i32?[]:[Opcodes.f64_convert_i32_u];Opcodes.load=valtypeBinary===Valtype.i32?Opcodes.i32_load:Opcodes.f64_load;Opcodes.store=valtypeBinary===Valtype.i32?Opcodes.i32_store:Opcodes.f64_store};const a=Prefs;Prefs=${prefs};r();const b=generate(_,${comptimeFlagChecks[id](extra)}?${passAst}:${failAst});if(b.at(-1)[0]>=0x41&&b.at(-1)[0]<=0x44)b.pop();Prefs=a;r();return b;}]`;
270
270
  });
271
271
 
272
- return `(_,{${str.includes('usedTypes.') ? 'usedTypes,' : ''}${str.includes('hasFunc(') ? 'hasFunc,' : ''}${str.includes('Valtype[') ? 'Valtype,' : ''}${str.includes('i32ify') ? 'i32ify,' : ''}${str.includes('Opcodes.') ? 'Opcodes,' : ''}${str.includes('...t(') ? 't,' : ''}${`${str.includes('allocPage(') ? 'allocPage,' : ''}${str.includes('makeString(') ? 'makeString,' : ''}${str.includes('glbl(') ? 'glbl,' : ''}${str.includes('loc(') ? 'loc,' : ''}${str.includes('builtin(') ? 'builtin,' : ''}${str.includes('funcRef(') ? 'funcRef,' : ''}${str.includes('internalThrow(') ? 'internalThrow,' : ''}${str.includes('generateIdent(') ? 'generateIdent,' : ''}${str.includes('generate(') ? 'generate,' : ''}`.slice(0, -1)}})=>`.replace('_,{}', '') + str;
272
+ return `(_,{${str.includes('usedTypes.') ? 'usedTypes,' : ''}${str.includes('hasFunc(') ? 'hasFunc,' : ''}${str.includes('Valtype[') ? 'Valtype,' : ''}${str.includes('i32ify') ? 'i32ify,' : ''}${str.includes('Opcodes.') ? 'Opcodes,' : ''}${str.includes('...t(') ? 't,' : ''}${`${str.includes('allocPage(') ? 'allocPage,' : ''}${str.includes('makeString(') ? 'makeString,' : ''}${str.includes('glbl(') ? 'glbl,' : ''}${str.includes('loc(') ? 'loc,' : ''}${str.includes('builtin(') ? 'builtin,' : ''}${str.includes('funcRef(') ? 'funcRef,' : ''}${str.includes('internalThrow(') ? 'internalThrow,' : ''}${str.includes('generateIdent(') ? 'generateIdent,' : ''}${str.includes('generate(') ? 'generate,' : ''}`.slice(0, -1)}})=>`.replace('_,{}', '') + `eval(${JSON.stringify(str)})`;
273
273
  };
274
274
 
275
275
  const locals = Object.entries(x.locals).sort((a,b) => a[1].idx - b[1].idx)
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.57.28",
4
+ "version": "0.57.30",
5
5
  "author": "Oliver Medhurst <honk@goose.icu>",
6
6
  "license": "MIT",
7
7
  "scripts": {},
package/regex_notes.md ADDED
@@ -0,0 +1,74 @@
1
+ **ES3 (1999)**
2
+ * Basic regex syntax (Perl-inspired)
3
+ * `RegExp` object
4
+ * `test()`, `exec()` methods for `RegExp`
5
+ * `match()`, `replace()`, `search()`, `split()` methods for `String`
6
+ * **Flags:**
7
+ * `g` (global)
8
+ * `i` (ignore case)
9
+ * `m` (multiline) - `^` and `$` match start/end of lines, not just start/end of string.
10
+ * **Special Characters/Constructs:**
11
+ * `.` (wildcard - matches any character except newline)
12
+ * `\d`, `\D` (digit, non-digit)
13
+ * `\w`, `\W` (word character, non-word character)
14
+ * `\s`, `\S` (whitespace, non-whitespace)
15
+ * `\t`, `\r`, `\n`, `\v`, `\f` (tab, carriage return, line feed, vertical tab, form feed)
16
+ * `[...]`, `[^...]` (character classes)
17
+ * `^`, `$` (start/end of string/line - see `m` flag)
18
+ * `\b`, `\B` (word boundary, non-word boundary)
19
+ * `(...)` (capturing group)
20
+ * `(?:...)` (non-capturing group)
21
+ * `\1`, `\2`, ... (backreferences to capturing groups)
22
+ * `|` (alternation/OR)
23
+ * `*`, `+`, `?` (quantifiers: zero or more, one or more, zero or one)
24
+ * `{n}`, `{n,}`, `{n,m}` (quantifiers: exactly n, at least n, between n and m)
25
+ * `*?`, `+?`, `??`, `{n}?`, `{n,}?`, `{n,m}?` (lazy quantifiers)
26
+ * `(?=...)` (positive lookahead)
27
+ * `(?!...)` (negative lookahead)
28
+
29
+ **ES5 (2009)**
30
+ * Regex literals `(/abc/)` now create a new object each time they are evaluated.
31
+ * Unescaped forward slashes allowed within character classes (e.g., `/[/]/`).
32
+
33
+ **ES6/ES2015**
34
+ * **New Flags:**
35
+ * `u` (unicode): Enables stricter parsing, improved handling of Unicode surrogate pairs, and allows `\u{...}` for Unicode code points.
36
+ * `y` (sticky): The match must start at the `lastIndex` property of the `RegExp`.
37
+ * `RegExp.prototype.flags` getter: Returns a string containing the flags of the regex.
38
+ * Support for subclassing `RegExp`.
39
+ * Ability to copy a regex while changing its flags: `new RegExp(/ab+c/, 'i')`.
40
+
41
+ **ES2018 (ES9)**
42
+ * **New Flag:**
43
+ * `s` (dotAll/singleline): Causes `.` to match newline characters as well.
44
+ * **Lookbehind Assertions:**
45
+ * `(?<=...)` (positive lookbehind)
46
+ * `(?<!...)` (negative lookbehind)
47
+ * **Named Capture Groups:**
48
+ * `(?<name>...)` (defines a named capture group)
49
+ * `\k<name>` (backreference to a named capture group)
50
+ * Named groups are accessible via the `groups` property of the match object.
51
+ * **Unicode Property Escapes:** (Requires `u` or `v` flag)
52
+ * `\p{PropertyName}` (e.g., `\p{Script=Greek}`, `\p{Number}`, `\p{Alphabetic}`)
53
+ * `\P{PropertyName}` (negated version)
54
+
55
+ **ES2020 (ES11)**
56
+ * `String.prototype.matchAll()`: Returns an iterator of all results matching a global regular expression against a string. (Requires the `g` flag).
57
+
58
+ **ES2021 (ES12)**
59
+ * `String.prototype.replaceAll()`: Replaces all occurrences of a substring (can be a regex). If a regex is used, it must have the `g` flag.
60
+
61
+ **ES2022 (ES13)**
62
+ * **New Flag:**
63
+ * `d` (hasIndices): Provides start and end indices for matched substrings (and capturing groups) via the `indices` property on the match object.
64
+
65
+ **ES2024 (ES15)**
66
+ * **New Flag:**
67
+ * `v` (unicodeSets): An upgrade to the `u` flag (cannot be used with `u`).
68
+ * Adds set notation for strings of characters to `\p{...}` and `\q{...}` (matching literal strings) within character classes.
69
+ * Nested character classes.
70
+ * Set operations within character classes:
71
+ * Subtraction: `[A--B]` (characters in A but not in B)
72
+ * Intersection: `[A&&B]` (characters in both A and B)
73
+ * Improved case-insensitive matching for Unicode properties within negated sets `[^...]`.
74
+ * `\p{RGI_Emoji}` for matching complete emojis.
package/runtime/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import fs from 'node:fs';
3
- globalThis.version = '0.57.28';
3
+ globalThis.version = '0.57.30';
4
4
 
5
5
  // deno compat
6
6
  if (typeof process === 'undefined' && typeof Deno !== 'undefined') {
package/foo.js DELETED
@@ -1,8 +0,0 @@
1
- const a = {
2
- b: {
3
- c: () => {}
4
- },
5
- c: () => {}
6
- };
7
-
8
- a.c();