porffor 0.2.0-af678f0 → 0.2.0-b9abe0d

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.
Files changed (55) hide show
  1. package/.vscode/launch.json +18 -0
  2. package/LICENSE +20 -20
  3. package/README.md +120 -104
  4. package/asur/README.md +2 -0
  5. package/asur/index.js +1262 -0
  6. package/byg/index.js +237 -0
  7. package/compiler/2c.js +1 -1
  8. package/compiler/{sections.js → assemble.js} +63 -15
  9. package/compiler/builtins/annexb_string.js +72 -0
  10. package/compiler/builtins/annexb_string.ts +19 -0
  11. package/compiler/builtins/array.ts +145 -0
  12. package/compiler/builtins/base64.ts +151 -0
  13. package/compiler/builtins/crypto.ts +120 -0
  14. package/compiler/builtins/date.ts +9 -0
  15. package/compiler/builtins/escape.ts +141 -0
  16. package/compiler/builtins/int.ts +147 -0
  17. package/compiler/builtins/number.ts +527 -0
  18. package/compiler/builtins/porffor.d.ts +42 -0
  19. package/compiler/builtins/string.ts +1055 -0
  20. package/compiler/builtins/tostring.ts +45 -0
  21. package/compiler/builtins.js +466 -273
  22. package/compiler/{codeGen.js → codegen.js} +875 -335
  23. package/compiler/embedding.js +22 -22
  24. package/compiler/encoding.js +108 -10
  25. package/compiler/generated_builtins.js +722 -0
  26. package/compiler/index.js +25 -34
  27. package/compiler/log.js +6 -3
  28. package/compiler/opt.js +50 -36
  29. package/compiler/parse.js +35 -27
  30. package/compiler/precompile.js +123 -0
  31. package/compiler/prefs.js +26 -0
  32. package/compiler/prototype.js +13 -28
  33. package/compiler/types.js +37 -0
  34. package/compiler/wasmSpec.js +27 -8
  35. package/compiler/wrap.js +46 -44
  36. package/package.json +9 -5
  37. package/porf +2 -0
  38. package/rhemyn/compile.js +5 -3
  39. package/rhemyn/parse.js +323 -320
  40. package/rhemyn/test/parse.js +58 -58
  41. package/runner/compare.js +34 -34
  42. package/runner/debug.js +122 -0
  43. package/runner/index.js +35 -9
  44. package/runner/profiler.js +102 -0
  45. package/runner/repl.js +40 -7
  46. package/runner/sizes.js +37 -37
  47. package/test262_changes_from_1afe9b87d2_to_04-09.md +270 -0
  48. package/compiler/builtins/base64.js +0 -92
  49. package/filesize.cmd +0 -2
  50. package/runner/info.js +0 -89
  51. package/runner/profile.js +0 -46
  52. package/runner/results.json +0 -1
  53. package/runner/transform.js +0 -15
  54. package/tmp.c +0 -661
  55. package/util/enum.js +0 -20
@@ -0,0 +1,151 @@
1
+ // @porf -funsafe-no-unlikely-proto-checks -valtype=i32
2
+
3
+ // while (len >= 8) {
4
+ // Porffor.wasm`
5
+ // local tmp i64
6
+ // local.get ${i}
7
+ // i64.load 0 4
8
+ // local.set tmp
9
+
10
+ // local k i64
11
+ // i64.const 0
12
+ // local.set k
13
+
14
+ // loop 64
15
+ // local.get ${j}
16
+
17
+ // local.get ${keyStrPtr}
18
+
19
+ // local.get tmp
20
+
21
+ // ;; k * 6
22
+ // i64.const 58
23
+
24
+ // local.get k
25
+ // i64.const 6
26
+ // i64.mul
27
+
28
+ // i64.sub
29
+
30
+ // ;; tmp >> (58 - (k * 6))
31
+ // i64.shr_u
32
+
33
+ // ;; (tmp >> (58 - (k * 6))) & 0x3f
34
+ // i64.const 63
35
+ // i64.and
36
+
37
+ // i32.wrap_i64
38
+
39
+ // ;; keyStrPtr + ...
40
+ // i32.add
41
+
42
+ // ;; load character from keyStr
43
+ // i32.load8_u 0 4
44
+
45
+ // ;; store in output at j
46
+ // i32.store8 0 4
47
+
48
+ // local.get ${j}
49
+ // i32.const 1
50
+ // i32.add
51
+ // local.set ${j}
52
+
53
+ // local.get k
54
+ // i64.const 1
55
+ // i64.add
56
+ // local.tee k
57
+
58
+ // i64.const 8
59
+ // i64.lt_s
60
+ // br_if 0
61
+ // end
62
+
63
+ // `;
64
+
65
+ // // len -= 6;
66
+ // i += 6;
67
+ // }
68
+
69
+ // // while (k < 8) {
70
+ // // Porffor.wasm.i32.store8(j++, Porffor.wasm.i32.load8_u(keyStrPtr + Porffor.wasm.i32.wrap_i64(Porffor.wasm.i64.and(
71
+ // // Porffor.wasm.i64.shr_u(tmp, Porffor.wasm.i64.extend_i32_u(58 - k * 6)),
72
+ // // Porffor.wasm.i64.const(0x3f)
73
+ // // )), 0, 4), 0, 4);
74
+ // // k += 1;
75
+ // // }
76
+
77
+ // i += 6;
78
+ // len -= 6;
79
+ // }
80
+
81
+ export const btoa = (input: bytestring): bytestring => {
82
+ const keyStr: bytestring = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
83
+ const keyStrPtr: i32 = Porffor.wasm`local.get ${keyStr}`;
84
+
85
+ let len: i32 = input.length;
86
+ let output: bytestring = '';
87
+ output.length = 4 * (len / 3 + !!(len % 3));
88
+
89
+ let i: i32 = Porffor.wasm`local.get ${input}`,
90
+ j: i32 = Porffor.wasm`local.get ${output}`;
91
+
92
+ const endPtr = i + len;
93
+ while (i < endPtr) {
94
+ const chr1: i32 = Porffor.wasm.i32.load8_u(i++, 0, 4);
95
+ const chr2: i32 = i < endPtr ? Porffor.wasm.i32.load8_u(i++, 0, 4) : -1;
96
+ const chr3: i32 = i < endPtr ? Porffor.wasm.i32.load8_u(i++, 0, 4) : -1;
97
+
98
+ const enc1: i32 = chr1 >> 2;
99
+ const enc2: i32 = ((chr1 & 3) << 4) | (chr2 == -1 ? 0 : (chr2 >> 4));
100
+ let enc3: i32 = ((chr2 & 15) << 2) | (chr3 == -1 ? 0 : (chr3 >> 6));
101
+ let enc4: i32 = chr3 & 63;
102
+
103
+ if (chr2 == -1) {
104
+ enc3 = 64;
105
+ enc4 = 64;
106
+ } else if (chr3 == -1) {
107
+ enc4 = 64;
108
+ }
109
+
110
+ Porffor.wasm.i32.store8(j++, Porffor.wasm.i32.load8_u(keyStrPtr + enc1, 0, 4), 0, 4);
111
+ Porffor.wasm.i32.store8(j++, Porffor.wasm.i32.load8_u(keyStrPtr + enc2, 0, 4), 0, 4);
112
+ Porffor.wasm.i32.store8(j++, Porffor.wasm.i32.load8_u(keyStrPtr + enc3, 0, 4), 0, 4);
113
+ Porffor.wasm.i32.store8(j++, Porffor.wasm.i32.load8_u(keyStrPtr + enc4, 0, 4), 0, 4);
114
+ }
115
+
116
+ return output;
117
+ };
118
+
119
+ /* var atob = function (input) {
120
+ const keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
121
+
122
+ let output = "";
123
+ let chr1, chr2, chr3;
124
+ let enc1, enc2, enc3, enc4;
125
+ let i = 0;
126
+
127
+ while (i < input.length) {
128
+ enc1 = keyStr.indexOf(input.charAt(i++));
129
+ enc2 = keyStr.indexOf(input.charAt(i++));
130
+ enc3 = keyStr.indexOf(input.charAt(i++));
131
+ enc4 = keyStr.indexOf(input.charAt(i++));
132
+
133
+ chr1 = (enc1 << 2) | (enc2 >> 4);
134
+ chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
135
+ chr3 = ((enc3 & 3) << 6) | enc4;
136
+
137
+ // output += String.fromCharCode(chr1);
138
+ Porffor.bytestring.appendCharCode(output, chr1);
139
+
140
+ if (enc3 != 64) {
141
+ // output += String.fromCharCode(chr2);
142
+ Porffor.bytestring.appendCharCode(output, chr2);
143
+ }
144
+ if (enc4 != 64) {
145
+ // output += String.fromCharCode(chr3);
146
+ Porffor.bytestring.appendCharCode(output, chr3);
147
+ }
148
+ }
149
+
150
+ return output;
151
+ }; */
@@ -0,0 +1,120 @@
1
+ // @porf -funsafe-no-unlikely-proto-checks -valtype=i32
2
+
3
+ export const __crypto_randomUUID = (): bytestring => {
4
+ let bytes: bytestring = '................';
5
+
6
+ const bytesPtr: i32 = Porffor.wasm`local.get ${bytes}`;
7
+
8
+ let a: i32 = bytesPtr;
9
+ let aEndPtr: i32 = a + 16;
10
+ while (a < aEndPtr) {
11
+ Porffor.wasm.i32.store8(a++, Porffor.randomByte(), 0, 4);
12
+ }
13
+
14
+ // bytes[6] = (bytes[6] & 0b00001111) | 0b01000000
15
+ Porffor.wasm.i32.store8(
16
+ bytesPtr,
17
+ (Porffor.wasm.i32.load8_u(bytesPtr, 0, 10) & 0b00001111) | 0b01000000,
18
+ 0,
19
+ 10 // 4 + 6
20
+ );
21
+
22
+ // bytes[8] = (bytes[8] & 0b00111111) | 0b10000000
23
+ Porffor.wasm.i32.store8(
24
+ bytesPtr,
25
+ (Porffor.wasm.i32.load8_u(bytesPtr, 0, 12) & 0b00111111) | 0b10000000,
26
+ 0,
27
+ 12 // 4 + 8
28
+ );
29
+
30
+ let output: bytestring = '------------------------------------';
31
+
32
+ let i: i32 = Porffor.wasm`local.get ${output}`;
33
+ let j: i32 = bytesPtr;
34
+
35
+ // bytes[0..4]-bytes[4..6]-bytes[6..8]-bytes[8..10]-bytes[10..15]
36
+ // 00112233-4455-6677-8899-aabbccddeeff
37
+
38
+ // bytes[0..4]-
39
+ let endPtr: i32 = i + 8;
40
+ while (i < endPtr) {
41
+ const byte: i32 = Porffor.wasm.i32.load8_u(j++, 0, 4);
42
+
43
+ let lower: i32 = (byte & 0x0f) + 48;
44
+ if (lower > 57) lower += 39;
45
+
46
+ let upper: i32 = (byte >> 4) + 48;
47
+ if (upper > 57) upper += 39;
48
+
49
+ Porffor.wasm.i32.store8(i++, upper, 0, 4);
50
+ Porffor.wasm.i32.store8(i++, lower, 0, 4);
51
+ }
52
+ i++;
53
+
54
+ // bytes[4..6]-
55
+ endPtr = i + 4;
56
+ while (i < endPtr) {
57
+ const byte: i32 = Porffor.wasm.i32.load8_u(j++, 0, 4);
58
+
59
+ let lower: i32 = (byte & 0x0f) + 48;
60
+ if (lower > 57) lower += 39;
61
+
62
+ let upper: i32 = (byte >> 4) + 48;
63
+ if (upper > 57) upper += 39;
64
+
65
+ Porffor.wasm.i32.store8(i++, upper, 0, 4);
66
+ Porffor.wasm.i32.store8(i++, lower, 0, 4);
67
+ }
68
+ i++;
69
+
70
+ // bytes[6..8]-
71
+ endPtr = i + 4;
72
+ while (i < endPtr) {
73
+ const byte: i32 = Porffor.wasm.i32.load8_u(j++, 0, 4);
74
+
75
+ let lower: i32 = (byte & 0x0f) + 48;
76
+ if (lower > 57) lower += 39;
77
+
78
+ let upper: i32 = (byte >> 4) + 48;
79
+ if (upper > 57) upper += 39;
80
+
81
+ Porffor.wasm.i32.store8(i++, upper, 0, 4);
82
+ Porffor.wasm.i32.store8(i++, lower, 0, 4);
83
+ }
84
+ i++;
85
+
86
+ // bytes[8..10]-
87
+ endPtr = i + 4;
88
+ while (i < endPtr) {
89
+ const byte: i32 = Porffor.wasm.i32.load8_u(j++, 0, 4);
90
+
91
+ let lower: i32 = (byte & 0x0f) + 48;
92
+ if (lower > 57) lower += 39;
93
+
94
+ let upper: i32 = (byte >> 4) + 48;
95
+ if (upper > 57) upper += 39;
96
+
97
+ Porffor.wasm.i32.store8(i++, upper, 0, 4);
98
+ Porffor.wasm.i32.store8(i++, lower, 0, 4);
99
+ }
100
+ i++;
101
+
102
+ // bytes[10..15]
103
+ endPtr = i + 12;
104
+ while (i < endPtr) {
105
+ const byte: i32 = Porffor.wasm.i32.load8_u(j++, 0, 4);
106
+
107
+ let lower: i32 = (byte & 0x0f) + 48;
108
+ if (lower > 57) lower += 39;
109
+
110
+ let upper: i32 = (byte >> 4) + 48;
111
+ if (upper > 57) upper += 39;
112
+
113
+ Porffor.wasm.i32.store8(i++, upper, 0, 4);
114
+ Porffor.wasm.i32.store8(i++, lower, 0, 4);
115
+ }
116
+ i++;
117
+
118
+
119
+ return output;
120
+ };
@@ -0,0 +1,9 @@
1
+ // @porf -funsafe-no-unlikely-proto-checks
2
+
3
+ export const __Date_now = (): number => Math.trunc(performance.timeOrigin + performance.now());
4
+
5
+ export const Date = (): bytestring => {
6
+ // todo
7
+ };
8
+
9
+ export const Date$constructor = (): Date => __Date_now();
@@ -0,0 +1,141 @@
1
+ // @porf -funsafe-no-unlikely-proto-checks -valtype=i32
2
+
3
+ import type {} from './porffor';
4
+
5
+ export const escape = (input: string|bytestring): bytestring => {
6
+ // we have no byte array yet so use bytestring with 0x00 and 0x01 via escape characters
7
+ // 0 = should escape, 1 = should not escape
8
+ // aka if in set 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_@*+-./'
9
+ const lut: bytestring = '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x01\x00\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x00\x00\x00\x00\x00\x00\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x00\x00\x00\x00\x01\x00\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x00\x00\x00\x00\x00';
10
+
11
+ const len: i32 = input.length;
12
+ let outLength: i32 = len; // at minimum, output length = input length
13
+
14
+ let i: i32 = Porffor.wasm`local.get ${input}`;
15
+
16
+ if (Porffor.wasm`local.get ${input+1}` == Porffor.TYPES._bytestring) {
17
+ const endPtr: i32 = i + len;
18
+ while (i < endPtr) {
19
+ const chr: i32 = Porffor.wasm.i32.load8_u(i++, 0, 4);
20
+
21
+ if (chr < 128) {
22
+ if (Porffor.wasm.i32.load8_u(Porffor.wasm`local.get ${lut}` + chr, 0, 4)) {
23
+ continue;
24
+ }
25
+ }
26
+
27
+ outLength += 2;
28
+ }
29
+
30
+ if (outLength == len) return input;
31
+
32
+ let output: bytestring = '';
33
+ output.length = outLength;
34
+
35
+ i = Porffor.wasm`local.get ${input}`;
36
+ let j: i32 = Porffor.wasm`local.get ${output}`;
37
+ while (i < endPtr) {
38
+ const chr: i32 = Porffor.wasm.i32.load8_u(i++, 0, 4);
39
+
40
+ if (chr < 128) {
41
+ if (Porffor.wasm.i32.load8_u(Porffor.wasm`local.get ${lut}` + chr, 0, 4)) {
42
+ // append just character
43
+ Porffor.wasm.i32.store8(j++, chr, 0, 4);
44
+ continue;
45
+ }
46
+ }
47
+
48
+ // %
49
+ Porffor.wasm.i32.store8(j++, 37, 0, 4);
50
+
51
+ // 8 bit integer to hex (0x12)
52
+ let lower: i32 = (chr & 0x0f) + 48;
53
+ if (lower > 57) lower += 7;
54
+
55
+ let upper: i32 = (chr >> 4) + 48;
56
+ if (upper > 57) upper += 7;
57
+
58
+ Porffor.wasm.i32.store8(j++, upper, 0, 4);
59
+ Porffor.wasm.i32.store8(j++, lower, 0, 4);
60
+ }
61
+
62
+ return output;
63
+ }
64
+
65
+ const endPtr: i32 = i + len * 2;
66
+ while (i < endPtr) {
67
+ const chr: i32 = Porffor.wasm.i32.load16_u(i, 0, 4);
68
+ i += 2;
69
+
70
+ if (chr < 128) {
71
+ if (Porffor.wasm.i32.load8_u(Porffor.wasm`local.get ${lut}` + chr, 0, 4)) {
72
+ continue;
73
+ }
74
+ }
75
+
76
+ if (chr < 256) {
77
+ outLength += 2;
78
+ } else {
79
+ outLength += 5;
80
+ }
81
+ }
82
+
83
+ if (outLength == len) return input;
84
+
85
+ let output: bytestring = '';
86
+ output.length = outLength;
87
+
88
+ i = Porffor.wasm`local.get ${input}`;
89
+ let j: i32 = Porffor.wasm`local.get ${output}`;
90
+
91
+ while (i < endPtr) {
92
+ const chr: i32 = Porffor.wasm.i32.load16_u(i, 0, 4);
93
+ i += 2;
94
+
95
+ if (chr < 128) {
96
+ if (Porffor.wasm.i32.load8_u(Porffor.wasm`local.get ${lut}` + chr, 0, 4)) {
97
+ // append just character
98
+ Porffor.wasm.i32.store8(j++, chr, 0, 4);
99
+ continue;
100
+ }
101
+ }
102
+
103
+ if (chr < 256) {
104
+ // %
105
+ Porffor.wasm.i32.store8(j++, 37, 0, 4);
106
+
107
+ // 8 bit integer to hex (0x12)
108
+ let lower: i32 = (chr & 0x0f) + 48;
109
+ if (lower > 57) lower += 7;
110
+
111
+ let upper: i32 = (chr >> 4) + 48;
112
+ if (upper > 57) upper += 7;
113
+
114
+ Porffor.wasm.i32.store8(j++, upper, 0, 4);
115
+ Porffor.wasm.i32.store8(j++, lower, 0, 4);
116
+ } else {
117
+ // %u
118
+ Porffor.wasm.i32.store16(j, 29989, 0, 4);
119
+ j += 2;
120
+
121
+ // 16 bit integer to hex (0x1234)
122
+ let nibble: i32 = ((chr >> 12) & 0x0f) + 48;
123
+ if (nibble > 57) nibble += 7;
124
+ Porffor.wasm.i32.store8(j++, nibble, 0, 4);
125
+
126
+ nibble = ((chr >> 8) & 0x0f) + 48;
127
+ if (nibble > 57) nibble += 7;
128
+ Porffor.wasm.i32.store8(j++, nibble, 0, 4);
129
+
130
+ nibble = ((chr >> 4) & 0x0f) + 48;
131
+ if (nibble > 57) nibble += 7;
132
+ Porffor.wasm.i32.store8(j++, nibble, 0, 4);
133
+
134
+ nibble = (chr & 0x0f) + 48;
135
+ if (nibble > 57) nibble += 7;
136
+ Porffor.wasm.i32.store8(j++, nibble, 0, 4);
137
+ }
138
+ }
139
+
140
+ return output;
141
+ };
@@ -0,0 +1,147 @@
1
+ // @porf -funsafe-no-unlikely-proto-checks
2
+
3
+ // radix: number|any for rawType check
4
+ // export const parseInt = (input: string|bytestring, radix: number|any): f64 => {
5
+ export const parseInt = (input: string|bytestring, radix: number): f64 => {
6
+ // todo/perf: optimize this instead of doing a naive algo (https://kholdstare.github.io/technical/2020/05/26/faster-integer-parsing.html)
7
+ // todo/perf: use i32s here once that becomes not annoying
8
+
9
+ if (Porffor.rawType(radix) != Porffor.TYPES.number) {
10
+ // todo: string to number
11
+ radix = 10;
12
+ }
13
+
14
+ if (radix == 0) radix = 10;
15
+ if (radix < 2 || radix > 36) return NaN;
16
+
17
+ let nMax: f64 = 58;
18
+ if (radix < 10) nMax = 48 + radix;
19
+
20
+ // if (Porffor.rawType(input) == Porffor.TYPES._bytestring) input = ___bytestring_prototype_trimStart(input);
21
+ // else input = __String_prototype_trimStart(input);
22
+
23
+ let n: f64 = NaN;
24
+
25
+ const inputPtr: f64 = Porffor.wasm`local.get ${input}`;
26
+ const len: f64 = Porffor.wasm.i32.load(inputPtr, 0, 0);
27
+ let i: f64 = inputPtr;
28
+
29
+ let negative: boolean = false;
30
+
31
+ if (Porffor.rawType(input) == Porffor.TYPES._bytestring) {
32
+ const endPtr: f64 = i + len;
33
+
34
+ // check start of string
35
+ const startChr: f64 = Porffor.wasm.i32.load8_u(i, 0, 4);
36
+
37
+ // +, ignore
38
+ if (startChr == 43) i++;
39
+
40
+ // -, switch to negative
41
+ if (startChr == 45) {
42
+ negative = true;
43
+ i++;
44
+ }
45
+
46
+ // 0, potential start of hex
47
+ if (startChr == 48) {
48
+ const second: f64 = Porffor.wasm.i32.load8_u(i + 1, 0, 4);
49
+ // 0x or 0X
50
+ if (second == 120 || second == 88) {
51
+ // set radix to 16 and skip leading 2 chars
52
+ i += 2;
53
+ radix = 16;
54
+ }
55
+ }
56
+
57
+ while (i < endPtr) {
58
+ const chr: f64 = Porffor.wasm.i32.load8_u(i++, 0, 4);
59
+
60
+ if (chr >= 48 && chr < nMax) {
61
+ if (Number.isNaN(n)) n = 0;
62
+
63
+ n *= radix;
64
+ n += chr - 48;
65
+ } else if (radix > 10) {
66
+ if (chr >= 97 && chr < (87 + radix)) {
67
+ if (Number.isNaN(n)) n = 0;
68
+
69
+ n *= radix;
70
+ n += chr - 87;
71
+ } else if (chr >= 65 && chr < (55 + radix)) {
72
+ if (Number.isNaN(n)) n = 0;
73
+
74
+ n *= radix;
75
+ n += chr - 55;
76
+ } else {
77
+ if (negative) return -n;
78
+ return n;
79
+ }
80
+ } else {
81
+ if (negative) return -n;
82
+ return n;
83
+ }
84
+ }
85
+
86
+ if (negative) return -n;
87
+ return n;
88
+ }
89
+
90
+ const endPtr: f64 = i + len * 2;
91
+
92
+ // check start of string
93
+ const startChr: f64 = Porffor.wasm.i32.load16_u(i, 0, 4);
94
+
95
+ // +, ignore
96
+ if (startChr == 43) i += 2;
97
+
98
+ // -, switch to negative
99
+ if (startChr == 45) {
100
+ negative = true;
101
+ i += 2;
102
+ }
103
+
104
+ // 0, potential start of hex
105
+ if (startChr == 48) {
106
+ const second: f64 = Porffor.wasm.i32.load16_u(i + 2, 0, 4);
107
+ // 0x or 0X
108
+ if (second == 120 || second == 88) {
109
+ // set radix to 16 and skip leading 2 chars
110
+ i += 4;
111
+ radix = 16;
112
+ }
113
+ }
114
+
115
+ while (i < endPtr) {
116
+ const chr: f64 = Porffor.wasm.i32.load16_u(i, 0, 4);
117
+ i += 2;
118
+
119
+ if (chr >= 48 && chr < nMax) {
120
+ if (Number.isNaN(n)) n = 0;
121
+
122
+ n *= radix;
123
+ n += chr - 48;
124
+ } else if (radix > 10) {
125
+ if (chr >= 97 && chr < (87 + radix)) {
126
+ if (Number.isNaN(n)) n = 0;
127
+
128
+ n *= radix;
129
+ n += chr - 87;
130
+ } else if (chr >= 65 && chr < (55 + radix)) {
131
+ if (Number.isNaN(n)) n = 0;
132
+
133
+ n *= radix;
134
+ n += chr - 55;
135
+ } else {
136
+ if (negative) return -n;
137
+ return n;
138
+ }
139
+ } else {
140
+ if (negative) return -n;
141
+ return n;
142
+ }
143
+ }
144
+
145
+ if (negative) return -n;
146
+ return n;
147
+ };