porffor 0.16.0-ab08df866 โ 0.16.0-c86dc1d57
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.
- package/CONTRIBUTING.md +2 -3
- package/compiler/2c.js +65 -53
- package/compiler/builtins/console.ts +2 -4
- package/compiler/builtins/porffor.d.ts +0 -11
- package/compiler/builtins/set.ts +2 -3
- package/compiler/builtins/symbol.ts +6 -6
- package/compiler/builtins.js +3 -23
- package/compiler/codegen.js +17 -9
- package/compiler/generated_builtins.js +1 -1
- package/compiler/opt.js +2 -2
- package/compiler/parse.js +1 -1
- package/package.json +1 -1
package/CONTRIBUTING.md
CHANGED
@@ -206,7 +206,6 @@ Store the character code into the `out` pointer variable, and increment it.
|
|
206
206
|
- You cannot use other functions in the file not exported, or variables not inside the current function.
|
207
207
|
- `if (...)` uses a fast truthy implementation which is not spec-compliant as most conditions should be strictly checked. To use spec-compliant behavior, use `if (Boolean(...))`.
|
208
208
|
- For object (string/array/etc) literals, you must use a variable eg `const out: bytestring = 'foobar'; console.log(out);` instead of `console.log('foobar')` due to precompile's allocator constraints.
|
209
|
-
- Generally prefer/use non-strict equality ops (`==`/`!=`).
|
210
209
|
|
211
210
|
<br>
|
212
211
|
|
@@ -233,7 +232,7 @@ builtins/tostring_number: impl radix
|
|
233
232
|
|
234
233
|
## Test262
|
235
234
|
|
236
|
-
|
235
|
+
Make sure you have Test262 cloned already **inside of `test262/`** (`git clone https://github.com/tc39/test262.git test262/test262`) and run `npm install` inside `test262/` too.
|
237
236
|
|
238
237
|
Run `node test262` to run all the tests and get an output of total overall test results.
|
239
238
|
|
@@ -247,7 +246,7 @@ The main thing you want to pay attention to is the emoji summary (lol):
|
|
247
246
|
To break this down:
|
248
247
|
๐งช total ๐ค pass โ fail ๐ runtime error ๐ todo (error) โฐ timeout ๐๏ธ wasm compile error ๐ฅ compile error
|
249
248
|
|
250
|
-
The diff compared to the last commit (with test262 data) is shown in brackets. Basically, you
|
249
|
+
The diff compared to the last commit (with test262 data) is shown in brackets. Basically, you can passes ๐ค up, and errors ๐๐๐๐ฅ down. It is fine if some errors change balance/etc, as long as they are not new failures.
|
251
250
|
|
252
251
|
It will also log new passes/fails. Be careful as sometimes the overall passes can increase, but other files have also regressed into failures which you might miss. Also keep in mind some tests may have been false positives before, but we can investigate the diff together :)
|
253
252
|
|
package/compiler/2c.js
CHANGED
@@ -29,8 +29,8 @@ typedef double f64;
|
|
29
29
|
f64 NAN = 0e+0/0e+0;
|
30
30
|
|
31
31
|
struct ReturnValue {
|
32
|
-
f64 value;
|
33
|
-
i32 type;
|
32
|
+
${CValtype.f64} value;
|
33
|
+
${CValtype.i32} type;
|
34
34
|
};\n\n`;
|
35
35
|
|
36
36
|
// todo: is memcpy/etc safe with host endianness?
|
@@ -41,60 +41,60 @@ const CMemFuncs = {
|
|
41
41
|
[Opcodes.i32_store]: {
|
42
42
|
c: `memcpy(_memory + offset + pointer, &value, sizeof(value));`,
|
43
43
|
args: ['pointer', 'value'],
|
44
|
-
argTypes: [
|
44
|
+
argTypes: [CValtype.i32, CValtype.i32],
|
45
45
|
returns: false
|
46
46
|
},
|
47
47
|
[Opcodes.i32_store16]: {
|
48
48
|
c: `memcpy(_memory + offset + pointer, &value, sizeof(value));`,
|
49
49
|
args: ['pointer', 'value'],
|
50
|
-
argTypes: [
|
50
|
+
argTypes: [CValtype.i32, CValtype.i16],
|
51
51
|
returns: false
|
52
52
|
},
|
53
53
|
[Opcodes.i32_store8]: {
|
54
54
|
c: `memcpy(_memory + offset + pointer, &value, sizeof(value));`,
|
55
55
|
args: ['pointer', 'value'],
|
56
|
-
argTypes: [
|
56
|
+
argTypes: [CValtype.i32, CValtype.i8],
|
57
57
|
returns: false
|
58
58
|
},
|
59
59
|
|
60
60
|
[Opcodes.i32_load]: {
|
61
|
-
c:
|
61
|
+
c: `${CValtype.i32} out;
|
62
62
|
memcpy(&out, _memory + offset + pointer, sizeof(out));
|
63
63
|
return out;`,
|
64
64
|
args: ['pointer'],
|
65
|
-
argTypes: [
|
66
|
-
returns:
|
65
|
+
argTypes: [CValtype.i32],
|
66
|
+
returns: CValtype.i32
|
67
67
|
},
|
68
68
|
[Opcodes.i32_load16_u]: {
|
69
|
-
c:
|
69
|
+
c: `${CValtype.i16} out;
|
70
70
|
memcpy(&out, _memory + offset + pointer, sizeof(out));
|
71
71
|
return out;`,
|
72
72
|
args: ['pointer'],
|
73
|
-
argTypes: [
|
74
|
-
returns:
|
73
|
+
argTypes: [CValtype.i32],
|
74
|
+
returns: CValtype.i32
|
75
75
|
},
|
76
76
|
[Opcodes.i32_load8_u]: {
|
77
|
-
c:
|
77
|
+
c: `${CValtype.i8} out;
|
78
78
|
memcpy(&out, _memory + offset + pointer, sizeof(out));
|
79
79
|
return out;`,
|
80
80
|
args: ['pointer'],
|
81
|
-
argTypes: [
|
82
|
-
returns:
|
81
|
+
argTypes: [CValtype.i32],
|
82
|
+
returns: CValtype.i32
|
83
83
|
},
|
84
84
|
|
85
85
|
[Opcodes.f64_store]: {
|
86
86
|
c: `memcpy(_memory + offset + pointer, &value, sizeof(value));`,
|
87
87
|
args: ['pointer', 'value'],
|
88
|
-
argTypes: [
|
88
|
+
argTypes: [CValtype.i32, CValtype.f64],
|
89
89
|
returns: false
|
90
90
|
},
|
91
91
|
[Opcodes.f64_load]: {
|
92
|
-
c:
|
92
|
+
c: `${CValtype.f64} out;
|
93
93
|
memcpy(&out, _memory + offset + pointer, sizeof(out));
|
94
94
|
return out;`,
|
95
95
|
args: ['pointer'],
|
96
|
-
argTypes: [
|
97
|
-
returns:
|
96
|
+
argTypes: [CValtype.i32],
|
97
|
+
returns: CValtype.f64
|
98
98
|
},
|
99
99
|
};
|
100
100
|
|
@@ -108,7 +108,7 @@ for (const x in CValtype) {
|
|
108
108
|
|
109
109
|
const removeBrackets = str => {
|
110
110
|
// return str;
|
111
|
-
// if (str.startsWith(
|
111
|
+
// if (str.startsWith(`(${CValtype.i32})(${CValtype.u32})`)) return `(${CValtype.i32})(${CValtype.u32})(` + removeBrackets(str.slice(22, -1)) + ')';
|
112
112
|
|
113
113
|
for (const x in CValtype) {
|
114
114
|
const p = `(${x})`;
|
@@ -156,7 +156,7 @@ export default ({ funcs, globals, tags, data, exceptions, pages }) => {
|
|
156
156
|
}
|
157
157
|
|
158
158
|
if (data.length > 0) {
|
159
|
-
prependMain.set('_data', data.map(x => `memcpy(_memory + ${x.offset}, (unsigned char[]){${x.bytes.join(',')}}, ${x.bytes.length});`).join('\n
|
159
|
+
prependMain.set('_data', data.map(x => `memcpy(_memory + ${x.offset}, (unsigned char[]){${x.bytes.join(',')}}, ${x.bytes.length});`).join('\n'));
|
160
160
|
}
|
161
161
|
|
162
162
|
if (importFuncs.find(x => x.name === '__Porffor_readArgv')) {
|
@@ -168,10 +168,10 @@ export default ({ funcs, globals, tags, data, exceptions, pages }) => {
|
|
168
168
|
|
169
169
|
let depth = 1;
|
170
170
|
let brDepth = 0;
|
171
|
-
const line = (str, semi = true) => out += `${' '.repeat(
|
171
|
+
const line = (str, semi = true) => out += `${' '.repeat(depth * 2 + brDepth * 2)}${str}${semi ? ';' : ''}\n`;
|
172
172
|
const lines = lines => {
|
173
173
|
for (const x of lines) {
|
174
|
-
out += `${' '.repeat(
|
174
|
+
out += `${' '.repeat(depth * 2)}${x}\n`;
|
175
175
|
}
|
176
176
|
};
|
177
177
|
|
@@ -219,10 +219,10 @@ export default ({ funcs, globals, tags, data, exceptions, pages }) => {
|
|
219
219
|
|
220
220
|
const shouldInline = false; // f.internal;
|
221
221
|
if (f.name === 'main') out += `int main(${prependMain.has('argv') ? 'int argc, char* argv[]' : ''}) {\n`;
|
222
|
-
else out += `${f.internal ? (returns ?
|
222
|
+
else out += `${f.internal ? (returns ? CValtype.f64 : 'void') : 'struct ReturnValue'} ${shouldInline ? 'inline ' : ''}${sanitize(f.name)}(${f.params.map((x, i) => `${CValtype[x]} ${invLocals[i]}`).join(', ')}) {\n`;
|
223
223
|
|
224
224
|
if (f.name === 'main') {
|
225
|
-
out +=
|
225
|
+
out += [...prependMain.values()].join('\n');
|
226
226
|
if (prependMain.size > 0) out += '\n\n';
|
227
227
|
}
|
228
228
|
|
@@ -283,12 +283,12 @@ export default ({ funcs, globals, tags, data, exceptions, pages }) => {
|
|
283
283
|
switch (i[1]) {
|
284
284
|
// i32_trunc_sat_f64_s
|
285
285
|
case 0x02:
|
286
|
-
vals.push(`(i32)(${vals.pop()})`);
|
286
|
+
vals.push(`(${CValtype.i32})(${vals.pop()})`);
|
287
287
|
break;
|
288
288
|
|
289
289
|
// i32_trunc_sat_f64_u
|
290
290
|
case 0x03:
|
291
|
-
vals.push(`(u32)(${vals.pop()})`);
|
291
|
+
vals.push(`(${CValtype.u32})(${vals.pop()})`);
|
292
292
|
break;
|
293
293
|
}
|
294
294
|
|
@@ -337,7 +337,7 @@ export default ({ funcs, globals, tags, data, exceptions, pages }) => {
|
|
337
337
|
|
338
338
|
case Opcodes.f64_trunc:
|
339
339
|
// vals.push(`trunc(${vals.pop()})`);
|
340
|
-
vals.push(`(i32)(${removeBrackets(vals.pop())})`); // this is ~10x faster with clang??
|
340
|
+
vals.push(`(${CValtype.i32})(${removeBrackets(vals.pop())})`); // this is ~10x faster with clang??
|
341
341
|
break;
|
342
342
|
|
343
343
|
case Opcodes.f64_convert_i32_u:
|
@@ -345,7 +345,7 @@ export default ({ funcs, globals, tags, data, exceptions, pages }) => {
|
|
345
345
|
case Opcodes.f64_convert_i64_u:
|
346
346
|
case Opcodes.f64_convert_i64_s:
|
347
347
|
// int to f64
|
348
|
-
vals.push(`(f64)(${removeBrackets(vals.pop())})`);
|
348
|
+
vals.push(`(${CValtype.f64})(${removeBrackets(vals.pop())})`);
|
349
349
|
break;
|
350
350
|
|
351
351
|
case Opcodes.i32_eqz:
|
@@ -353,7 +353,7 @@ export default ({ funcs, globals, tags, data, exceptions, pages }) => {
|
|
353
353
|
vals.push(`!(${removeBrackets(vals.pop())})`);
|
354
354
|
} else {
|
355
355
|
let cond = '(' + removeBrackets(vals.pop());
|
356
|
-
if (cond.startsWith(`(i32)`)) cond = `${cond.slice(
|
356
|
+
if (cond.startsWith(`(${CValtype.i32})`)) cond = `${cond.slice(`(${CValtype.i32})`.length)}) == 0e+0`;
|
357
357
|
else cond += ') == 0';
|
358
358
|
vals.push(cond);
|
359
359
|
}
|
@@ -368,7 +368,7 @@ export default ({ funcs, globals, tags, data, exceptions, pages }) => {
|
|
368
368
|
case Opcodes.if: {
|
369
369
|
let cond = removeBrackets(vals.pop());
|
370
370
|
if (!lastCond) {
|
371
|
-
if (cond.startsWith(`(i32)`)) cond =
|
371
|
+
if (cond.startsWith(`(${CValtype.i32})`)) cond = `(${cond.slice(`(${CValtype.i32})`.length)}) != 0e+0`;
|
372
372
|
else cond = `(${cond}) != 0`;
|
373
373
|
}
|
374
374
|
|
@@ -434,16 +434,28 @@ export default ({ funcs, globals, tags, data, exceptions, pages }) => {
|
|
434
434
|
const importFunc = importFuncs[i[1]];
|
435
435
|
switch (importFunc.name) {
|
436
436
|
case 'print':
|
437
|
+
// line(`printf("%f\\n", ${vals.pop()})`);
|
437
438
|
line(`printf("${valtype === 'f64' ? '%g' : '%i'}\\n", ${vals.pop()})`);
|
438
439
|
includes.set('stdio.h', true);
|
439
440
|
break;
|
440
441
|
case 'printChar':
|
441
|
-
line(`
|
442
|
+
line(`printf("%c", (int)(${vals.pop()}))`);
|
442
443
|
includes.set('stdio.h', true);
|
443
444
|
break;
|
444
445
|
|
445
446
|
case 'time':
|
446
447
|
line(`double _time_out`);
|
448
|
+
/* platformSpecific(
|
449
|
+
`FILETIME _time_filetime;
|
450
|
+
GetSystemTimeAsFileTime(&_time_filetime);
|
451
|
+
|
452
|
+
ULARGE_INTEGER _time_ularge;
|
453
|
+
_time_ularge.LowPart = _time_filetime.dwLowDateTime;
|
454
|
+
_time_ularge.HighPart = _time_filetime.dwHighDateTime;
|
455
|
+
_time_out = (_time_ularge.QuadPart - 116444736000000000i64) / 10000.;`,
|
456
|
+
`struct timespec _time;
|
457
|
+
clock_gettime(CLOCK_MONOTONIC, &_time);
|
458
|
+
_time_out = _time.tv_nsec / 1000000.;`); */
|
447
459
|
platformSpecific(
|
448
460
|
`LARGE_INTEGER _time_freq, _time_t;
|
449
461
|
QueryPerformanceFrequency(&_time_freq);
|
@@ -458,11 +470,14 @@ _time_out = _time.tv_nsec / 1000000. + _time.tv_sec * 1000.;`);
|
|
458
470
|
winIncludes.set('windows.h', true);
|
459
471
|
break;
|
460
472
|
|
461
|
-
case '__Porffor_readArgv':
|
473
|
+
case '__Porffor_readArgv':
|
474
|
+
includes.set('stdlib.h', true);
|
475
|
+
|
462
476
|
prepend.set('__Porffor_readArgv',
|
463
|
-
`
|
477
|
+
`void __Porffor_readArgv(u32 index, u32 outPtr) {
|
464
478
|
if (index >= _argc) {
|
465
|
-
|
479
|
+
printf("expected %d arguments\\n", index);
|
480
|
+
exit(1);
|
466
481
|
}
|
467
482
|
|
468
483
|
char* arg = _argv[index];
|
@@ -475,24 +490,23 @@ _time_out = _time.tv_nsec / 1000000. + _time.tv_sec * 1000.;`);
|
|
475
490
|
}
|
476
491
|
|
477
492
|
memcpy(_memory + outPtr, &read, sizeof(read));
|
478
|
-
return read;
|
479
493
|
}`);
|
480
494
|
|
481
|
-
|
482
|
-
|
483
|
-
vals.push(`(f64)__Porffor_readArgv((u32)(${index}), (u32)(${outPtr}))`);
|
495
|
+
line(`__Porffor_readArgv((u32)(${vals.at(-2)}), (u32)(${vals.pop()}))`);
|
496
|
+
vals.pop();
|
484
497
|
break;
|
485
|
-
}
|
486
498
|
|
487
|
-
case '__Porffor_readFile':
|
499
|
+
case '__Porffor_readFile':
|
488
500
|
includes.set('stdio.h', true);
|
501
|
+
includes.set('stdlib.h', true);
|
489
502
|
|
490
503
|
prepend.set('__Porffor_readFile',
|
491
|
-
`
|
504
|
+
`void __Porffor_readFile(u32 pathPtr, u32 outPtr) {
|
492
505
|
char* path = _memory + pathPtr + 4;
|
493
506
|
FILE* fp = fopen(path, "r");
|
494
507
|
if (fp == NULL) {
|
495
|
-
|
508
|
+
printf("failed to open file: %s\\n", path);
|
509
|
+
exit(1);
|
496
510
|
}
|
497
511
|
|
498
512
|
u32 read = 0;
|
@@ -505,13 +519,10 @@ _time_out = _time.tv_nsec / 1000000. + _time.tv_sec * 1000.;`);
|
|
505
519
|
fclose(fp);
|
506
520
|
|
507
521
|
memcpy(_memory + outPtr, &read, sizeof(read));
|
508
|
-
return read;
|
509
522
|
}`);
|
510
|
-
|
511
|
-
|
512
|
-
vals.push(`(f64)__Porffor_readFile((u32)(${pathPtr}), (u32)(${outPtr}))`);
|
523
|
+
line(`__Porffor_readFile((u32)(${vals.at(-2)}), (u32)(${vals.pop()}))`);
|
524
|
+
vals.pop();
|
513
525
|
break;
|
514
|
-
}
|
515
526
|
|
516
527
|
default:
|
517
528
|
log.warning('2c', `unimplemented import: ${importFunc.name}`);
|
@@ -528,10 +539,9 @@ _time_out = _time.tv_nsec / 1000000. + _time.tv_sec * 1000.;`);
|
|
528
539
|
if (func.internal) {
|
529
540
|
vals.push(`${sanitize(func.name)}(${args.join(', ')})`);
|
530
541
|
} else {
|
531
|
-
const
|
532
|
-
|
533
|
-
vals.push(`_
|
534
|
-
vals.push(`_${id}.type`);
|
542
|
+
line(`const struct ReturnValue _${retTmpId++} = ${sanitize(func.name)}(${args.join(', ')})`);
|
543
|
+
vals.push(`_.value`);
|
544
|
+
vals.push(`_.type`);
|
535
545
|
}
|
536
546
|
} else line(`${sanitize(func.name)}(${args.join(', ')})`);
|
537
547
|
|
@@ -561,7 +571,7 @@ _time_out = _time.tv_nsec / 1000000. + _time.tv_sec * 1000.;`);
|
|
561
571
|
|
562
572
|
let cond = removeBrackets(vals.pop());
|
563
573
|
if (!lastCond) {
|
564
|
-
if (cond.startsWith(`(i32)`)) cond =
|
574
|
+
if (cond.startsWith(`(${CValtype.i32})`)) cond = `(${cond.slice(`(${CValtype.i32})`.length)}) != 0e+0`;
|
565
575
|
else cond = `(${cond}) != 0`;
|
566
576
|
}
|
567
577
|
|
@@ -591,7 +601,8 @@ _time_out = _time.tv_nsec / 1000000. + _time.tv_sec * 1000.;`);
|
|
591
601
|
const name = invOpcodes[i[0]];
|
592
602
|
const func = CMemFuncs[i[0]];
|
593
603
|
if (!prepend.has(name)) {
|
594
|
-
prepend.set(name, `${func.returns || 'void'} ${name}(i32 align, i32 offset, ${func.args.map((x, i) => `${func.argTypes[i]} ${x}`).join(', ')}) {\n ${func.c.replaceAll('\n', '\n ')}\n}\n`);
|
604
|
+
prepend.set(name, `${func.returns || 'void'} ${name}(${CValtype.i32} align, ${CValtype.i32} offset, ${func.args.map((x, i) => `${func.argTypes[i]} ${x}`).join(', ')}) {\n ${func.c.replaceAll('\n', '\n ')}\n}\n`);
|
605
|
+
// generate func c and prepend
|
595
606
|
}
|
596
607
|
|
597
608
|
const immediates = [ i[1], read_unsignedLEB128(i.slice(2)) ];
|
@@ -626,6 +637,7 @@ _time_out = _time.tv_nsec / 1000000. + _time.tv_sec * 1000.;`);
|
|
626
637
|
depth = 0;
|
627
638
|
|
628
639
|
const makeIncludes = includes => [...includes.keys()].map(x => `#include <${x}>\n`).join('');
|
640
|
+
|
629
641
|
out = platformSpecific(makeIncludes(winIncludes), makeIncludes(unixIncludes), false) + '\n' + makeIncludes(includes) + '\n' + alwaysPreface + [...prepend.values()].join('\n') + '\n\n' + out;
|
630
642
|
|
631
643
|
return out.trim();
|
@@ -22,14 +22,6 @@ type PorfforGlobal = {
|
|
22
22
|
}
|
23
23
|
}
|
24
24
|
|
25
|
-
allocate(): any;
|
26
|
-
set: {
|
27
|
-
read(_this: any, index: number): i32;
|
28
|
-
write(_this: any, index: number, value: any): boolean;
|
29
|
-
}
|
30
|
-
|
31
|
-
print(x: any): i32;
|
32
|
-
|
33
25
|
randomByte(): i32;
|
34
26
|
|
35
27
|
type(x: any): bytestring;
|
@@ -56,9 +48,6 @@ type PorfforGlobal = {
|
|
56
48
|
|
57
49
|
s(...args: any): string;
|
58
50
|
bs(...args: any): bytestring;
|
59
|
-
|
60
|
-
readArgv(index: i32, out: bytestring): i32;
|
61
|
-
readFile(path: bytestring, out: bytestring): i32;
|
62
51
|
};
|
63
52
|
|
64
53
|
declare global {
|
package/compiler/builtins/set.ts
CHANGED
@@ -189,10 +189,9 @@ export const Set$constructor = (iterable: any): Set => {
|
|
189
189
|
|
190
190
|
export const __Set_prototype_union = (_this: Set, other: any) => {
|
191
191
|
if (Porffor.rawType(other) != Porffor.TYPES.set) {
|
192
|
-
throw new TypeError("Set.
|
192
|
+
throw new TypeError("Set.union requires 'Set'");
|
193
193
|
}
|
194
|
-
|
195
|
-
const out: Set = Set$constructor(_this);
|
194
|
+
const out: Set = new Set(_this);
|
196
195
|
for (const x of other) {
|
197
196
|
out.add(x);
|
198
197
|
}
|
@@ -8,10 +8,10 @@ export const __Porffor_symbol_descStore = (op: boolean, value: any): any => {
|
|
8
8
|
Porffor.wasm.i32.store(ptr, size + 1, 0, 0)
|
9
9
|
|
10
10
|
// reuse set internals to store description
|
11
|
-
|
11
|
+
__Porffor_set_write(ptr, size, value);
|
12
12
|
return size;
|
13
13
|
} else { // read
|
14
|
-
return
|
14
|
+
return __Porffor_set_read(ptr, value);
|
15
15
|
}
|
16
16
|
};
|
17
17
|
|
@@ -21,8 +21,8 @@ export const Symbol = (description: any): Symbol => {
|
|
21
21
|
};
|
22
22
|
|
23
23
|
export const __Symbol_prototype_description$get = (_this: Symbol) => {
|
24
|
-
const description: bytestring =
|
25
|
-
|
24
|
+
const description: bytestring = __Porffor_symbol_descStore(false,
|
25
|
+
Porffor.wasm`local.get ${_this}` - 1);
|
26
26
|
return description;
|
27
27
|
};
|
28
28
|
|
@@ -38,8 +38,8 @@ export const __Symbol_prototype_toString = (_this: Symbol) => {
|
|
38
38
|
Porffor.wasm.i32.store8(out, 108, 0, 9);
|
39
39
|
Porffor.wasm.i32.store8(out, 40, 0, 10);
|
40
40
|
|
41
|
-
const description: bytestring =
|
42
|
-
|
41
|
+
const description: bytestring = __Porffor_symbol_descStore(false,
|
42
|
+
Porffor.wasm`local.get ${_this}` - 1);
|
43
43
|
|
44
44
|
const descLen: i32 = description.length;
|
45
45
|
let outPtr: i32 = Porffor.wasm`local.get ${out}` + 7;
|
package/compiler/builtins.js
CHANGED
@@ -45,13 +45,13 @@ export const importedFuncs = [
|
|
45
45
|
name: '__Porffor_readArgv',
|
46
46
|
import: 'w',
|
47
47
|
params: 2,
|
48
|
-
returns:
|
48
|
+
returns: 0
|
49
49
|
},
|
50
50
|
{
|
51
51
|
name: '__Porffor_readFile',
|
52
52
|
import: 'q',
|
53
53
|
params: 2,
|
54
|
-
returns:
|
54
|
+
returns: 0
|
55
55
|
}
|
56
56
|
];
|
57
57
|
|
@@ -167,7 +167,6 @@ export const BuiltinFuncs = function() {
|
|
167
167
|
params: [ valtypeBinary, valtypeBinary ],
|
168
168
|
locals: [],
|
169
169
|
returns: [ valtypeBinary ],
|
170
|
-
returnType: TYPES.number,
|
171
170
|
wasm: [ // x - truncf(x / y) * y
|
172
171
|
[ Opcodes.local_get, 0 ], // x
|
173
172
|
|
@@ -190,7 +189,6 @@ export const BuiltinFuncs = function() {
|
|
190
189
|
params: [ valtypeBinary, valtypeBinary ],
|
191
190
|
locals: [],
|
192
191
|
returns: [ valtypeBinary ],
|
193
|
-
returnType: TYPES.number,
|
194
192
|
wasm: [
|
195
193
|
[ Opcodes.local_get, 0 ],
|
196
194
|
Opcodes.i32_to,
|
@@ -210,7 +208,6 @@ export const BuiltinFuncs = function() {
|
|
210
208
|
params: [ valtypeBinary ],
|
211
209
|
locals: [],
|
212
210
|
returns: [ valtypeBinary ],
|
213
|
-
returnType: TYPES.number,
|
214
211
|
wasm: [
|
215
212
|
[ Opcodes.local_get, 0 ]
|
216
213
|
],
|
@@ -472,7 +469,6 @@ export const BuiltinFuncs = function() {
|
|
472
469
|
params: [ valtypeBinary ],
|
473
470
|
locals: [],
|
474
471
|
returns: [ valtypeBinary ],
|
475
|
-
returnType: TYPES.number,
|
476
472
|
wasm: [
|
477
473
|
[ Opcodes.local_get, 0 ],
|
478
474
|
[ Opcodes.f64_sqrt ]
|
@@ -484,7 +480,6 @@ export const BuiltinFuncs = function() {
|
|
484
480
|
params: [ valtypeBinary ],
|
485
481
|
locals: [],
|
486
482
|
returns: [ valtypeBinary ],
|
487
|
-
returnType: TYPES.number,
|
488
483
|
wasm: [
|
489
484
|
[ Opcodes.local_get, 0 ],
|
490
485
|
[ Opcodes.f64_abs ]
|
@@ -496,7 +491,6 @@ export const BuiltinFuncs = function() {
|
|
496
491
|
params: [ valtypeBinary ],
|
497
492
|
locals: [],
|
498
493
|
returns: [ valtypeBinary ],
|
499
|
-
returnType: TYPES.number,
|
500
494
|
wasm: [
|
501
495
|
...number(1),
|
502
496
|
[ Opcodes.local_get, 0 ],
|
@@ -509,7 +503,6 @@ export const BuiltinFuncs = function() {
|
|
509
503
|
params: [ valtypeBinary ],
|
510
504
|
locals: [],
|
511
505
|
returns: [ valtypeBinary ],
|
512
|
-
returnType: TYPES.number,
|
513
506
|
wasm: [
|
514
507
|
[ Opcodes.local_get, 0 ],
|
515
508
|
[ Opcodes.f64_floor ]
|
@@ -521,7 +514,6 @@ export const BuiltinFuncs = function() {
|
|
521
514
|
params: [ valtypeBinary ],
|
522
515
|
locals: [],
|
523
516
|
returns: [ valtypeBinary ],
|
524
|
-
returnType: TYPES.number,
|
525
517
|
wasm: [
|
526
518
|
[ Opcodes.local_get, 0 ],
|
527
519
|
[ Opcodes.f64_ceil ]
|
@@ -533,7 +525,6 @@ export const BuiltinFuncs = function() {
|
|
533
525
|
params: [ valtypeBinary ],
|
534
526
|
locals: [],
|
535
527
|
returns: [ valtypeBinary ],
|
536
|
-
returnType: TYPES.number,
|
537
528
|
wasm: [
|
538
529
|
[ Opcodes.local_get, 0 ],
|
539
530
|
[ Opcodes.f64_nearest ]
|
@@ -545,7 +536,6 @@ export const BuiltinFuncs = function() {
|
|
545
536
|
params: [ valtypeBinary ],
|
546
537
|
locals: [],
|
547
538
|
returns: [ valtypeBinary ],
|
548
|
-
returnType: TYPES.number,
|
549
539
|
wasm: [
|
550
540
|
[ Opcodes.local_get, 0 ],
|
551
541
|
[ Opcodes.f64_trunc ]
|
@@ -557,7 +547,6 @@ export const BuiltinFuncs = function() {
|
|
557
547
|
params: [ valtypeBinary ],
|
558
548
|
locals: [],
|
559
549
|
returns: [ valtypeBinary ],
|
560
|
-
returnType: TYPES.number,
|
561
550
|
wasm: [
|
562
551
|
[ Opcodes.local_get, 0 ],
|
563
552
|
Opcodes.i32_trunc_sat_f64_u,
|
@@ -571,7 +560,6 @@ export const BuiltinFuncs = function() {
|
|
571
560
|
params: [ valtypeBinary ],
|
572
561
|
locals: [],
|
573
562
|
returns: [ valtypeBinary ],
|
574
|
-
returnType: TYPES.number,
|
575
563
|
wasm: [
|
576
564
|
[ Opcodes.local_get, 0 ],
|
577
565
|
[ Opcodes.f32_demote_f64 ],
|
@@ -585,7 +573,6 @@ export const BuiltinFuncs = function() {
|
|
585
573
|
params: [ valtypeBinary, valtypeBinary ],
|
586
574
|
locals: [],
|
587
575
|
returns: [ valtypeBinary ],
|
588
|
-
returnType: TYPES.number,
|
589
576
|
wasm: [
|
590
577
|
[ Opcodes.local_get, 0 ],
|
591
578
|
Opcodes.i32_trunc_sat_f64_s,
|
@@ -900,7 +887,6 @@ export const BuiltinFuncs = function() {
|
|
900
887
|
globalNames: [ 'state0', 'state1' ],
|
901
888
|
globalInits: [ prngSeed0, prngSeed1 ],
|
902
889
|
returns: [ Valtype.f64 ],
|
903
|
-
returnType: TYPES.number,
|
904
890
|
wasm: [
|
905
891
|
...prng.wasm,
|
906
892
|
|
@@ -952,7 +938,6 @@ export const BuiltinFuncs = function() {
|
|
952
938
|
globalNames: [ 'state0', 'state1' ],
|
953
939
|
globalInits: [ prngSeed0, prngSeed1 ],
|
954
940
|
returns: [ Valtype.i32 ],
|
955
|
-
returnType: TYPES.number,
|
956
941
|
wasm: [
|
957
942
|
...prng.wasm,
|
958
943
|
|
@@ -974,7 +959,6 @@ export const BuiltinFuncs = function() {
|
|
974
959
|
params: [ valtypeBinary ],
|
975
960
|
locals: [],
|
976
961
|
returns: [ valtypeBinary ],
|
977
|
-
returnType: TYPES.number,
|
978
962
|
wasm: [
|
979
963
|
[ Opcodes.local_get, 0 ],
|
980
964
|
...number(Math.PI / 180),
|
@@ -987,7 +971,6 @@ export const BuiltinFuncs = function() {
|
|
987
971
|
params: [ valtypeBinary ],
|
988
972
|
locals: [],
|
989
973
|
returns: [ valtypeBinary ],
|
990
|
-
returnType: TYPES.number,
|
991
974
|
wasm: [
|
992
975
|
[ Opcodes.local_get, 0 ],
|
993
976
|
...number(180 / Math.PI),
|
@@ -1001,7 +984,6 @@ export const BuiltinFuncs = function() {
|
|
1001
984
|
locals: [],
|
1002
985
|
localNames: [ 'x', 'lower', 'upper' ],
|
1003
986
|
returns: [ valtypeBinary ],
|
1004
|
-
returnType: TYPES.number,
|
1005
987
|
wasm: [
|
1006
988
|
[ Opcodes.local_get, 0 ],
|
1007
989
|
[ Opcodes.local_get, 1 ],
|
@@ -1017,9 +999,9 @@ export const BuiltinFuncs = function() {
|
|
1017
999
|
locals: [],
|
1018
1000
|
localNames: [ 'x', 'inLow', 'inHigh', 'outLow', 'outHigh' ],
|
1019
1001
|
returns: [ valtypeBinary ],
|
1020
|
-
returnType: TYPES.number,
|
1021
1002
|
wasm: [
|
1022
1003
|
// (x โ inLow) * (outHigh โ outLow) / (inHigh - inLow) + outLow
|
1004
|
+
|
1023
1005
|
[ Opcodes.local_get, 0 ],
|
1024
1006
|
[ Opcodes.local_get, 1 ],
|
1025
1007
|
[ Opcodes.f64_sub ],
|
@@ -1061,7 +1043,6 @@ export const BuiltinFuncs = function() {
|
|
1061
1043
|
params: [],
|
1062
1044
|
locals: [],
|
1063
1045
|
returns: [ valtypeBinary ],
|
1064
|
-
returnType: TYPES.number,
|
1065
1046
|
wasm: [
|
1066
1047
|
[ Opcodes.call, importedFuncs.time ]
|
1067
1048
|
]
|
@@ -1089,7 +1070,6 @@ export const BuiltinFuncs = function() {
|
|
1089
1070
|
typedParams: true,
|
1090
1071
|
locals: [],
|
1091
1072
|
returns: [ valtypeBinary ],
|
1092
|
-
returnType: TYPES.number,
|
1093
1073
|
wasm: [
|
1094
1074
|
[ Opcodes.local_get, 1 ],
|
1095
1075
|
Opcodes.i32_from_u
|
package/compiler/codegen.js
CHANGED
@@ -1078,7 +1078,7 @@ const asmFunc = (name, { wasm, params, locals: localTypes, globals: globalTypes
|
|
1078
1078
|
locals,
|
1079
1079
|
localInd: allLocals.length,
|
1080
1080
|
returns,
|
1081
|
-
returnType,
|
1081
|
+
returnType: returnType ?? TYPES.number,
|
1082
1082
|
internal: true,
|
1083
1083
|
index: currentFuncIndex++,
|
1084
1084
|
table
|
@@ -1254,7 +1254,7 @@ const getNodeType = (scope, node) => {
|
|
1254
1254
|
const func = funcs.find(x => x.name === name);
|
1255
1255
|
|
1256
1256
|
if (func) {
|
1257
|
-
if (func.returnType
|
1257
|
+
if (func.returnType) return func.returnType;
|
1258
1258
|
}
|
1259
1259
|
|
1260
1260
|
if (builtinFuncs[name] && !builtinFuncs[name].typedReturns) return builtinFuncs[name].returnType ?? TYPES.number;
|
@@ -1270,7 +1270,15 @@ const getNodeType = (scope, node) => {
|
|
1270
1270
|
const func = spl[spl.length - 1];
|
1271
1271
|
const protoFuncs = Object.keys(prototypeFuncs).filter(x => x != TYPES.bytestring && prototypeFuncs[x][func] != null);
|
1272
1272
|
if (protoFuncs.length === 1) {
|
1273
|
-
if (protoFuncs[0].returnType
|
1273
|
+
if (protoFuncs[0].returnType) return protoFuncs[0].returnType;
|
1274
|
+
}
|
1275
|
+
|
1276
|
+
if (protoFuncs.length > 0) {
|
1277
|
+
if (scope.locals['#last_type']) return getLastType(scope);
|
1278
|
+
|
1279
|
+
// presume
|
1280
|
+
// todo: warn here?
|
1281
|
+
return TYPES.number;
|
1274
1282
|
}
|
1275
1283
|
}
|
1276
1284
|
|
@@ -1970,7 +1978,7 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
|
|
1970
1978
|
const func = funcs[idx - importedFuncs.length]; // idx === scope.index ? scope : funcs.find(x => x.index === idx);
|
1971
1979
|
const userFunc = func && !func.internal;
|
1972
1980
|
const typedParams = userFunc || builtinFuncs[name]?.typedParams;
|
1973
|
-
const typedReturns = (
|
1981
|
+
const typedReturns = (func && func.returnType == null) || builtinFuncs[name]?.typedReturns;
|
1974
1982
|
const paramCount = func && (typedParams ? func.params.length / 2 : func.params.length);
|
1975
1983
|
|
1976
1984
|
let args = decl.arguments;
|
@@ -2563,7 +2571,7 @@ const generateUnary = (scope, decl) => {
|
|
2563
2571
|
// * -1
|
2564
2572
|
|
2565
2573
|
if (decl.prefix && decl.argument.type === 'Literal' && typeof decl.argument.value === 'number') {
|
2566
|
-
// if
|
2574
|
+
// if -<N>, just return that
|
2567
2575
|
return number(-1 * decl.argument.value);
|
2568
2576
|
}
|
2569
2577
|
|
@@ -2574,15 +2582,15 @@ const generateUnary = (scope, decl) => {
|
|
2574
2582
|
|
2575
2583
|
case '!':
|
2576
2584
|
const arg = decl.argument;
|
2577
|
-
if (arg.type ===
|
2578
|
-
//
|
2585
|
+
if (arg.type === "UnaryExpression" && arg.operator === "!") {
|
2586
|
+
// !!x -> is x truthy
|
2579
2587
|
return truthy(scope, generate(scope, arg.argument), getNodeType(scope, arg.argument), false, false);
|
2580
2588
|
}
|
2581
|
-
|
2582
2589
|
// !=
|
2583
|
-
return falsy(scope, generate(scope,
|
2590
|
+
return falsy(scope, generate(scope, decl.argument), getNodeType(scope, decl.argument), false, false);
|
2584
2591
|
|
2585
2592
|
case '~':
|
2593
|
+
// todo: does not handle Infinity properly (should convert to 0) (but opt const converting saves us sometimes)
|
2586
2594
|
return [
|
2587
2595
|
...generate(scope, decl.argument),
|
2588
2596
|
Opcodes.i32_to,
|
@@ -1748,7 +1748,7 @@ export const BuiltinFuncs = function() {
|
|
1748
1748
|
localNames: ["iterable","iterable#type","out","type","forof_base_pointer","forof_length","forof_counter","x","x#type","#last_type","#typeswitch_tmp"],
|
1749
1749
|
};
|
1750
1750
|
this.__Set_prototype_union = {
|
1751
|
-
wasm: (scope, {builtin,internalThrow,}) => [[32,2],[32,3],[16, builtin('__Porffor_rawType')],[68,0,0,0,0,0,0,52,64],[98],[4,64],...internalThrow(scope, 'TypeError', `Set.
|
1751
|
+
wasm: (scope, {builtin,internalThrow,}) => [[32,2],[32,3],[16, builtin('__Porffor_rawType')],[68,0,0,0,0,0,0,52,64],[98],[4,64],...internalThrow(scope, 'TypeError', `Set.union requires 'Set'`),[11],[32,0],[65,20],[16, builtin('Set$constructor')],[33,4],[32,2],[252,3],[33,5],[65,0],[33,7],[32,5],[40,1,0],[33,6],[32,3],[33,11],[2,64],[32,11],[65,2],[70],[4,64,"TYPESWITCH|String"],[65,2],[33,9],[3,64],[65,0],[32,5],[47,0,4],[59,0,3],[68,0,0,0,0,0,0,240,191],[33,8],[2,64],[32,4],[65,20],[32,8],[32,9],[16, builtin('__Set_prototype_add')],[26],[26],[32,5],[65,2],[106],[33,5],[32,7],[65,1],[106],[34,7],[32,6],[71],[13,1],[11],[11],[12,1],[11],[32,11],[65,16],[70],[4,64,"TYPESWITCH|Array"],[3,64],[32,5],[43,0,4],[32,5],[45,0,12],[33,9],[33,8],[2,64],[32,4],[65,20],[32,8],[32,9],[16, builtin('__Set_prototype_add')],[26],[26],[32,5],[65,9],[106],[33,5],[32,7],[65,1],[106],[34,7],[32,6],[71],[13,1],[11],[11],[12,1],[11],[32,11],[65,18],[70],[4,64,"TYPESWITCH|ByteString"],[65,18],[33,9],[3,64],[65,0],[32,5],[32,7],[106],[45,0,4],[58,0,3],[68,0,0,0,0,0,0,240,191],[33,8],[2,64],[32,4],[65,20],[32,8],[32,9],[16, builtin('__Set_prototype_add')],[26],[26],[32,7],[65,1],[106],[34,7],[32,6],[71],[13,1],[11],[11],[12,1],[11],[32,11],[65,20],[70],[4,64,"TYPESWITCH|Set"],[3,64],[32,5],[43,0,4],[32,5],[45,0,12],[33,9],[33,8],[2,64],[32,4],[65,20],[32,8],[32,9],[16, builtin('__Set_prototype_add')],[26],[26],[32,5],[65,9],[106],[33,5],[32,7],[65,1],[106],[34,7],[32,6],[71],[13,1],[11],[11],[12,1],[11],...internalThrow(scope, 'TypeError', `Tried for..of on non-iterable type`),[11,"TYPESWITCH_end"],[32,4],[65,20],[15]],
|
1752
1752
|
params: [124,127,124,127],
|
1753
1753
|
typedParams: true,
|
1754
1754
|
returns: [124,127],
|
package/compiler/opt.js
CHANGED
@@ -108,7 +108,7 @@ export default (funcs, globals, pages, tags, exceptions) => {
|
|
108
108
|
for (const f of funcs) {
|
109
109
|
const wasm = f.wasm;
|
110
110
|
|
111
|
-
const lastType = f.locals['#last_type']
|
111
|
+
const lastType = f.locals['#last_type'];
|
112
112
|
|
113
113
|
let runs = (+Prefs.optWasmRuns) || 2; // todo: how many by default?
|
114
114
|
while (runs > 0) {
|
@@ -248,7 +248,7 @@ export default (funcs, globals, pages, tags, exceptions) => {
|
|
248
248
|
}
|
249
249
|
|
250
250
|
// remove setting last type if it is never gotten
|
251
|
-
if (!f.gotLastType && inst[0] === Opcodes.local_set && inst[1] === lastType) {
|
251
|
+
if (!f.gotLastType && inst[0] === Opcodes.local_set && inst[1] === lastType?.idx) {
|
252
252
|
// replace this inst with drop
|
253
253
|
wasm.splice(i, 1, [ Opcodes.drop ]); // remove this and last inst
|
254
254
|
if (i > 0) i--;
|
package/compiler/parse.js
CHANGED
@@ -10,7 +10,7 @@ if (typeof process === 'undefined' && typeof Deno !== 'undefined') {
|
|
10
10
|
const file = process.argv.slice(2).find(x => x[0] !== '-' && !['run', 'wasm', 'native', 'c', 'profile', 'debug', 'debug-wasm'].includes(x));
|
11
11
|
|
12
12
|
// should we try to support types (while parsing)
|
13
|
-
const types = Prefs.parseTypes ||
|
13
|
+
const types = Prefs.parseTypes || file?.endsWith('.ts');
|
14
14
|
globalThis.typedInput = types && Prefs.optTypes;
|
15
15
|
|
16
16
|
// todo: review which to use by default
|
package/package.json
CHANGED