porffor 0.2.0-aea77ff → 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 (53) hide show
  1. package/.vscode/launch.json +18 -0
  2. package/LICENSE +20 -20
  3. package/README.md +124 -83
  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 +317 -72
  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 +479 -262
  22. package/compiler/{codeGen.js → codegen.js} +1049 -394
  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 +36 -34
  27. package/compiler/log.js +6 -3
  28. package/compiler/opt.js +51 -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 +177 -37
  33. package/compiler/types.js +37 -0
  34. package/compiler/wasmSpec.js +29 -7
  35. package/compiler/wrap.js +52 -39
  36. package/package.json +9 -5
  37. package/porf +4 -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 +49 -10
  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/runner/info.js +0 -89
  50. package/runner/profile.js +0 -46
  51. package/runner/results.json +0 -1
  52. package/runner/transform.js +0 -15
  53. package/util/enum.js +0 -20
@@ -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
+ };
@@ -0,0 +1,527 @@
1
+ // // @porf -funsafe-no-unlikely-proto-checks
2
+
3
+ // radix: number|any for rawType check
4
+ export const __Number_prototype_toString = (_this: number, radix: number|any) => {
5
+ let out: bytestring = '';
6
+ let outPtr: i32 = Porffor.wasm`local.get ${out}`;
7
+
8
+ if (!Number.isFinite(_this)) {
9
+ if (Number.isNaN(_this)) out = 'NaN';
10
+ else if (_this == Infinity) out = 'Infinity';
11
+ else out = '-Infinity';
12
+
13
+ return out;
14
+ }
15
+
16
+ if (Porffor.rawType(radix) != Porffor.TYPES.number) {
17
+ // todo: string to number
18
+ radix = 10;
19
+ }
20
+
21
+ radix |= 0;
22
+ if (radix < 2 || radix > 36) {
23
+ // todo: throw RangeError: toString() radix argument must be between 2 and 36
24
+ return out;
25
+ }
26
+
27
+ if (_this == 0) {
28
+ out = '0';
29
+ return out;
30
+ }
31
+
32
+ // if negative value
33
+ if (_this < 0) {
34
+ _this = -_this; // turn value positive for later use
35
+ Porffor.wasm.i32.store8(outPtr++, 45, 0, 4); // prepend -
36
+ }
37
+
38
+ let i: f64 = Math.trunc(_this);
39
+
40
+ let digits: bytestring = ''; // byte "array"
41
+
42
+ let l: i32 = 0;
43
+ if (radix == 10) {
44
+ if (i >= 1e21) {
45
+ // large exponential
46
+ let trailing: boolean = true;
47
+ let e: i32 = -1;
48
+ while (i > 0) {
49
+ const digit: f64 = i % radix;
50
+ i = Math.trunc(i / radix);
51
+
52
+ e++;
53
+ if (trailing) {
54
+ if (digit == 0) { // skip trailing 0s
55
+ continue;
56
+ }
57
+ trailing = false;
58
+ }
59
+
60
+ Porffor.wasm.i32.store8(Porffor.wasm`local.get ${digits}` + l, digit, 0, 4);
61
+ l++;
62
+ }
63
+
64
+ let digitsPtr: i32 = Porffor.wasm`local.get ${digits}` + l;
65
+ let endPtr: i32 = outPtr + l;
66
+ let dotPlace: i32 = outPtr + 1;
67
+ while (outPtr < endPtr) {
68
+ if (outPtr == dotPlace) {
69
+ Porffor.wasm.i32.store8(outPtr++, 46, 0, 4); // .
70
+ endPtr++;
71
+ }
72
+
73
+ let digit: i32 = Porffor.wasm.i32.load8_u(--digitsPtr, 0, 4);
74
+
75
+ if (digit < 10) digit += 48; // 0-9
76
+ else digit += 87; // a-z
77
+
78
+ Porffor.wasm.i32.store8(outPtr++, digit, 0, 4);
79
+ }
80
+
81
+ Porffor.wasm.i32.store8(outPtr++, 101, 0, 4); // e
82
+ Porffor.wasm.i32.store8(outPtr++, 43, 0, 4); // +
83
+
84
+ l = 0;
85
+ for (; e > 0; l++) {
86
+ Porffor.wasm.i32.store8(Porffor.wasm`local.get ${digits}` + l, e % radix, 0, 4);
87
+ e = Math.trunc(e / radix);
88
+ }
89
+
90
+ digitsPtr = Porffor.wasm`local.get ${digits}` + l;
91
+
92
+ endPtr = outPtr + l;
93
+ while (outPtr < endPtr) {
94
+ let digit: i32 = Porffor.wasm.i32.load8_u(--digitsPtr, 0, 4);
95
+
96
+ if (digit < 10) digit += 48; // 0-9
97
+ else digit += 87; // a-z
98
+
99
+ Porffor.wasm.i32.store8(outPtr++, digit, 0, 4);
100
+ }
101
+
102
+ out.length = outPtr - Porffor.wasm`local.get ${out}`;
103
+
104
+ return out;
105
+ }
106
+
107
+ if (_this < 1e-6) {
108
+ // small exponential
109
+ let decimal: f64 = _this;
110
+
111
+ let e: i32 = 1;
112
+ while (true) {
113
+ decimal *= radix;
114
+
115
+ const intPart: i32 = Math.trunc(decimal);
116
+ if (intPart > 0) {
117
+ if (decimal - intPart < 1e-10) break;
118
+ } else e++;
119
+ }
120
+
121
+ while (decimal > 0) {
122
+ const digit: f64 = decimal % radix;
123
+ decimal = Math.trunc(decimal / radix);
124
+
125
+ Porffor.wasm.i32.store8(Porffor.wasm`local.get ${digits}` + l, digit, 0, 4);
126
+ l++;
127
+ }
128
+
129
+ let digitsPtr: i32 = Porffor.wasm`local.get ${digits}` + l;
130
+ let endPtr: i32 = outPtr + l;
131
+ let dotPlace: i32 = outPtr + 1;
132
+ while (outPtr < endPtr) {
133
+ let digit: i32 = Porffor.wasm.i32.load8_u(--digitsPtr, 0, 4);
134
+
135
+ if (outPtr == dotPlace) {
136
+ Porffor.wasm.i32.store8(outPtr++, 46, 0, 4); // .
137
+ endPtr++;
138
+ }
139
+
140
+ if (digit < 10) digit += 48; // 0-9
141
+ else digit += 87; // a-z
142
+
143
+ Porffor.wasm.i32.store8(outPtr++, digit, 0, 4);
144
+ }
145
+
146
+ Porffor.wasm.i32.store8(outPtr++, 101, 0, 4); // e
147
+ Porffor.wasm.i32.store8(outPtr++, 45, 0, 4); // -
148
+
149
+ l = 0;
150
+ for (; e > 0; l++) {
151
+ Porffor.wasm.i32.store8(Porffor.wasm`local.get ${digits}` + l, e % radix, 0, 4);
152
+ e = Math.trunc(e / radix);
153
+ }
154
+
155
+ digitsPtr = Porffor.wasm`local.get ${digits}` + l;
156
+
157
+ endPtr = outPtr + l;
158
+ while (outPtr < endPtr) {
159
+ let digit: i32 = Porffor.wasm.i32.load8_u(--digitsPtr, 0, 4);
160
+
161
+ if (digit < 10) digit += 48; // 0-9
162
+ else digit += 87; // a-z
163
+
164
+ Porffor.wasm.i32.store8(outPtr++, digit, 0, 4);
165
+ }
166
+
167
+ out.length = outPtr - Porffor.wasm`local.get ${out}`;
168
+
169
+ return out;
170
+ }
171
+ }
172
+
173
+ if (i == 0) {
174
+ Porffor.wasm.i32.store8(Porffor.wasm`local.get ${digits}`, 0, 0, 4);
175
+ l = 1;
176
+ } else {
177
+ for (; i > 0; l++) {
178
+ Porffor.wasm.i32.store8(Porffor.wasm`local.get ${digits}` + l, i % radix, 0, 4);
179
+ i = Math.trunc(i / radix);
180
+ }
181
+ }
182
+
183
+ let digitsPtr: i32 = Porffor.wasm`local.get ${digits}` + l;
184
+ let endPtr: i32 = outPtr + l;
185
+ while (outPtr < endPtr) {
186
+ let digit: i32 = Porffor.wasm.i32.load8_u(--digitsPtr, 0, 4);
187
+
188
+ if (digit < 10) digit += 48; // 0-9
189
+ else digit += 87; // a-z
190
+
191
+ Porffor.wasm.i32.store8(outPtr++, digit, 0, 4);
192
+ }
193
+
194
+ let decimal: f64 = _this - Math.trunc(_this);
195
+ if (decimal > 0) {
196
+ Porffor.wasm.i32.store8(outPtr++, 46, 0, 4); // .
197
+
198
+ decimal += 1;
199
+
200
+ // todo: doesn't handle non-10 radix properly
201
+ let decimalDigits: i32 = 16 - l;
202
+ for (let j: i32 = 0; j < decimalDigits; j++) {
203
+ decimal *= radix;
204
+ }
205
+
206
+ decimal = Math.round(decimal);
207
+
208
+ l = 0;
209
+ let trailing: boolean = true;
210
+ while (decimal > 1) {
211
+ const digit: f64 = decimal % radix;
212
+ decimal = Math.trunc(decimal / radix);
213
+
214
+ if (trailing) {
215
+ if (digit == 0) { // skip trailing 0s
216
+ continue;
217
+ }
218
+ trailing = false;
219
+ }
220
+
221
+ Porffor.wasm.i32.store8(Porffor.wasm`local.get ${digits}` + l, digit, 0, 4);
222
+ l++;
223
+ }
224
+
225
+ digitsPtr = Porffor.wasm`local.get ${digits}` + l;
226
+
227
+ endPtr = outPtr + l;
228
+ while (outPtr < endPtr) {
229
+ let digit: i32 = Porffor.wasm.i32.load8_u(--digitsPtr, 0, 4);
230
+
231
+ if (digit < 10) digit += 48; // 0-9
232
+ else digit += 87; // a-z
233
+
234
+ Porffor.wasm.i32.store8(outPtr++, digit, 0, 4);
235
+ }
236
+ }
237
+
238
+ out.length = outPtr - Porffor.wasm`local.get ${out}`;
239
+
240
+ return out;
241
+ };
242
+
243
+ export const __Number_prototype_toFixed = (_this: number, fractionDigits: number) => {
244
+ let out: bytestring = '';
245
+ let outPtr: i32 = Porffor.wasm`local.get ${out}`;
246
+
247
+ if (!Number.isFinite(_this)) {
248
+ if (Number.isNaN(_this)) out = 'NaN';
249
+ else if (_this == Infinity) out = 'Infinity';
250
+ else out = '-Infinity';
251
+
252
+ return out;
253
+ }
254
+
255
+ fractionDigits |= 0;
256
+ if (fractionDigits < 0 || fractionDigits > 100) {
257
+ // todo: throw RangeError: toFixed() digits argument must be between 0 and 100
258
+ return out;
259
+ }
260
+
261
+ // if negative value
262
+ if (_this < 0) {
263
+ _this = -_this; // turn value positive for later use
264
+ Porffor.wasm.i32.store8(outPtr++, 45, 0, 4); // prepend -
265
+ }
266
+
267
+ let i: f64 = Math.trunc(_this);
268
+
269
+ let digits: bytestring = ''; // byte "array"
270
+
271
+ let l: i32 = 0;
272
+
273
+ if (i == 0) {
274
+ Porffor.wasm.i32.store8(Porffor.wasm`local.get ${digits}`, 0, 0, 4);
275
+ l = 1;
276
+ } else {
277
+ for (; i > 0; l++) {
278
+ Porffor.wasm.i32.store8(Porffor.wasm`local.get ${digits}` + l, i % 10, 0, 4);
279
+ i = Math.trunc(i / 10);
280
+ }
281
+ }
282
+
283
+ let digitsPtr: i32 = Porffor.wasm`local.get ${digits}` + l;
284
+ let endPtr: i32 = outPtr + l;
285
+ while (outPtr < endPtr) {
286
+ let digit: i32 = Porffor.wasm.i32.load8_u(--digitsPtr, 0, 4);
287
+
288
+ if (digit < 10) digit += 48; // 0-9
289
+ else digit += 87; // a-z
290
+
291
+ Porffor.wasm.i32.store8(outPtr++, digit, 0, 4);
292
+ }
293
+
294
+ let decimal: f64 = _this - Math.trunc(_this);
295
+ if (fractionDigits > 0) {
296
+ Porffor.wasm.i32.store8(outPtr++, 46, 0, 4); // .
297
+
298
+ decimal += 1;
299
+
300
+ for (let j: i32 = 0; j < fractionDigits; j++) {
301
+ decimal *= 10;
302
+ }
303
+
304
+ decimal = Math.round(decimal);
305
+
306
+ l = 0;
307
+ while (decimal > 1) {
308
+ const digit: f64 = decimal % 10;
309
+ decimal = Math.trunc(decimal / 10);
310
+
311
+ Porffor.wasm.i32.store8(Porffor.wasm`local.get ${digits}` + l, digit, 0, 4);
312
+ l++;
313
+ }
314
+
315
+ digitsPtr = Porffor.wasm`local.get ${digits}` + l;
316
+
317
+ endPtr = outPtr + l;
318
+ while (outPtr < endPtr) {
319
+ let digit: i32 = Porffor.wasm.i32.load8_u(--digitsPtr, 0, 4);
320
+
321
+ if (digit < 10) digit += 48; // 0-9
322
+ else digit += 87; // a-z
323
+
324
+ Porffor.wasm.i32.store8(outPtr++, digit, 0, 4);
325
+ }
326
+ }
327
+
328
+ out.length = outPtr - Porffor.wasm`local.get ${out}`;
329
+
330
+ return out;
331
+ };
332
+
333
+ // fractionDigits: number|any for rawType check
334
+ export const __Number_prototype_toExponential = (_this: number, fractionDigits: number|any) => {
335
+ let out: bytestring = '';
336
+ let outPtr: i32 = Porffor.wasm`local.get ${out}`;
337
+
338
+ if (!Number.isFinite(_this)) {
339
+ if (Number.isNaN(_this)) out = 'NaN';
340
+ else if (_this == Infinity) out = 'Infinity';
341
+ else out = '-Infinity';
342
+
343
+ return out;
344
+ }
345
+
346
+ if (Porffor.rawType(fractionDigits) != Porffor.TYPES.number) {
347
+ // todo: string to number
348
+ fractionDigits = undefined;
349
+ } else {
350
+ fractionDigits |= 0;
351
+ if (fractionDigits < 0 || fractionDigits > 100) {
352
+ // todo: throw RangeError: toExponential() digits argument must be between 0 and 100
353
+ return out;
354
+ }
355
+ }
356
+
357
+ // if negative value
358
+ if (_this < 0) {
359
+ _this = -_this; // turn value positive for later use
360
+ Porffor.wasm.i32.store8(outPtr++, 45, 0, 4); // prepend -
361
+ }
362
+
363
+ let i: f64 = _this;
364
+
365
+ let digits: bytestring = ''; // byte "array"
366
+
367
+ let l: i32 = 0;
368
+ let e: i32 = 0;
369
+ let digitsPtr: i32;
370
+ let endPtr: i32;
371
+ if (_this == 0) {
372
+ Porffor.wasm.i32.store8(outPtr++, 48, 0, 4); // 0
373
+
374
+ if (fractionDigits > 0) {
375
+ Porffor.wasm.i32.store8(outPtr++, 46, 0, 4); // .
376
+ for (let j: i32 = 0; j < fractionDigits; j++) {
377
+ Porffor.wasm.i32.store8(outPtr++, 48, 0, 4); // 0
378
+ }
379
+ }
380
+
381
+ Porffor.wasm.i32.store8(outPtr++, 101, 0, 4); // e
382
+ Porffor.wasm.i32.store8(outPtr++, 43, 0, 4); // +
383
+ } else if (_this < 1) {
384
+ // small exponential
385
+ if (Porffor.rawType(fractionDigits) != Porffor.TYPES.number) {
386
+ e = 1;
387
+ while (true) {
388
+ i *= 10;
389
+
390
+ const intPart: i32 = Math.trunc(i);
391
+ if (intPart > 0) {
392
+ if (i - intPart < 1e-10) break;
393
+ } else e++;
394
+ }
395
+ } else {
396
+ e = 1;
397
+ let j: i32 = 0;
398
+ while (j <= fractionDigits) {
399
+ i *= 10;
400
+
401
+ const intPart: i32 = Math.trunc(i);
402
+ if (intPart == 0) e++;
403
+ else j++;
404
+ }
405
+ }
406
+
407
+ while (i > 0) {
408
+ const digit: f64 = i % 10;
409
+ i = Math.trunc(i / 10);
410
+
411
+ Porffor.wasm.i32.store8(Porffor.wasm`local.get ${digits}` + l, digit, 0, 4);
412
+ l++;
413
+ }
414
+
415
+ digitsPtr = Porffor.wasm`local.get ${digits}` + l;
416
+ endPtr = outPtr + l;
417
+ let dotPlace: i32 = outPtr + 1;
418
+ while (outPtr < endPtr) {
419
+ let digit: i32 = Porffor.wasm.i32.load8_u(--digitsPtr, 0, 4);
420
+
421
+ if (outPtr == dotPlace) {
422
+ Porffor.wasm.i32.store8(outPtr++, 46, 0, 4); // .
423
+ endPtr++;
424
+ }
425
+
426
+ if (digit < 10) digit += 48; // 0-9
427
+ else digit += 87; // a-z
428
+
429
+ Porffor.wasm.i32.store8(outPtr++, digit, 0, 4);
430
+ }
431
+
432
+ Porffor.wasm.i32.store8(outPtr++, 101, 0, 4); // e
433
+ Porffor.wasm.i32.store8(outPtr++, 45, 0, 4); // -
434
+ } else {
435
+ // large exponential
436
+ e = -1;
437
+ while (i >= 1) {
438
+ i /= 10;
439
+ e++;
440
+ }
441
+
442
+ if (Porffor.rawType(fractionDigits) != Porffor.TYPES.number) {
443
+ while (true) {
444
+ i *= 10;
445
+
446
+ const intPart: i32 = Math.trunc(i);
447
+ if (intPart > 0) {
448
+ if (i - intPart < 1e-10) break;
449
+ } else e++;
450
+ }
451
+ } else {
452
+ // i = _this;
453
+ // if (e >= fractionDigits) {
454
+ // for (let j: i32 = 0; j < e - fractionDigits; j++) {
455
+ // i /= 10;
456
+ // }
457
+ // } else {
458
+ // for (let j: i32 = 0; j < fractionDigits - e; j++) {
459
+ // i *= 10;
460
+ // }
461
+ // }
462
+
463
+ // eg: 1.2345 -> 123.45, if fractionDigits = 2
464
+ for (let j: i32 = 0; j <= fractionDigits; j++) {
465
+ i *= 10;
466
+ }
467
+ }
468
+
469
+ // eg: 123.45 -> 123
470
+ i = Math.round(i);
471
+
472
+ while (i > 0) {
473
+ const digit: f64 = i % 10;
474
+ i = Math.trunc(i / 10);
475
+
476
+ Porffor.wasm.i32.store8(Porffor.wasm`local.get ${digits}` + l, digit, 0, 4);
477
+ l++;
478
+ }
479
+
480
+ digitsPtr = Porffor.wasm`local.get ${digits}` + l;
481
+ endPtr = outPtr + l;
482
+ let dotPlace: i32 = outPtr + 1;
483
+ while (outPtr < endPtr) {
484
+ if (outPtr == dotPlace) {
485
+ Porffor.wasm.i32.store8(outPtr++, 46, 0, 4); // .
486
+ endPtr++;
487
+ }
488
+
489
+ let digit: i32 = Porffor.wasm.i32.load8_u(--digitsPtr, 0, 4);
490
+
491
+ if (digit < 10) digit += 48; // 0-9
492
+ else digit += 87; // a-z
493
+
494
+ Porffor.wasm.i32.store8(outPtr++, digit, 0, 4);
495
+ }
496
+
497
+ Porffor.wasm.i32.store8(outPtr++, 101, 0, 4); // e
498
+ Porffor.wasm.i32.store8(outPtr++, 43, 0, 4); // +
499
+ }
500
+
501
+ if (e == 0) {
502
+ Porffor.wasm.i32.store8(Porffor.wasm`local.get ${digits}`, 0, 0, 4);
503
+ l = 1;
504
+ } else {
505
+ l = 0;
506
+ for (; e > 0; l++) {
507
+ Porffor.wasm.i32.store8(Porffor.wasm`local.get ${digits}` + l, e % 10, 0, 4);
508
+ e = Math.trunc(e / 10);
509
+ }
510
+ }
511
+
512
+ digitsPtr = Porffor.wasm`local.get ${digits}` + l;
513
+
514
+ endPtr = outPtr + l;
515
+ while (outPtr < endPtr) {
516
+ let digit: i32 = Porffor.wasm.i32.load8_u(--digitsPtr, 0, 4);
517
+
518
+ if (digit < 10) digit += 48; // 0-9
519
+ else digit += 87; // a-z
520
+
521
+ Porffor.wasm.i32.store8(outPtr++, digit, 0, 4);
522
+ }
523
+
524
+ out.length = outPtr - Porffor.wasm`local.get ${out}`;
525
+
526
+ return out;
527
+ };
@@ -0,0 +1,42 @@
1
+ export type i32 = number;
2
+ export type i64 = number;
3
+ export type f64 = number;
4
+ export type bytestring = string;
5
+
6
+ type PorfforGlobal = {
7
+ wasm: {
8
+ (...args: any[]): any;
9
+ i32: {
10
+ or(a: i32, b: i32): i32;
11
+
12
+ load(pointer: i32, align: i32, offset: i32): i32;
13
+ store(pointer: i32, value: i32, align: i32, offset: i32): i32;
14
+ load8_u(pointer: i32, align: i32, offset: i32): i32;
15
+ store8(pointer: i32, value: i32, align: i32, offset: i32): i32;
16
+ load16_u(pointer: i32, align: i32, offset: i32): i32;
17
+ store16(pointer: i32, value: i32, align: i32, offset: i32): i32;
18
+ }
19
+ }
20
+
21
+ // randomInt(): i32;
22
+ randomByte(): i32;
23
+
24
+ type(x: any): bytestring;
25
+ rawType(x: any): i32;
26
+ TYPES: Record<string, i32>;
27
+
28
+ fastOr(...args: any): boolean;
29
+ fastAnd(...args: any): boolean;
30
+
31
+ s(...args: any): string;
32
+ bs(...args: any): bytestring;
33
+ };
34
+
35
+ declare global {
36
+ const Porffor: PorfforGlobal;
37
+
38
+ type i32 = number;
39
+ type i64 = number;
40
+ type f64 = number;
41
+ type bytestring = string;
42
+ }