porffor 0.0.0-44bc2d8 → 0.0.0-61de729
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/compiler/codeGen.js +49 -30
- package/compiler/index.js +10 -1
- package/compiler/prototype.js +2 -4
- package/package.json +1 -1
- package/runner/index.js +6 -0
- package/runner/repl.js +3 -10
- package/runner/version.js +10 -0
package/compiler/codeGen.js
CHANGED
@@ -35,7 +35,14 @@ const debug = str => {
|
|
35
35
|
};
|
36
36
|
|
37
37
|
const todo = msg => {
|
38
|
-
|
38
|
+
class TodoError extends Error {
|
39
|
+
constructor(message) {
|
40
|
+
super(message);
|
41
|
+
this.name = 'TodoError';
|
42
|
+
}
|
43
|
+
}
|
44
|
+
|
45
|
+
throw new TodoError(`todo: ${msg}`);
|
39
46
|
|
40
47
|
const code = [];
|
41
48
|
|
@@ -298,10 +305,10 @@ const localTmp = (scope, name, type = valtypeBinary) => {
|
|
298
305
|
return idx;
|
299
306
|
};
|
300
307
|
|
301
|
-
const performLogicOp = (scope, op, left, right) => {
|
308
|
+
const performLogicOp = (scope, op, left, right, leftType, rightType) => {
|
302
309
|
const checks = {
|
303
|
-
'||':
|
304
|
-
'&&':
|
310
|
+
'||': falsy,
|
311
|
+
'&&': truthy,
|
305
312
|
// todo: ??
|
306
313
|
};
|
307
314
|
|
@@ -313,7 +320,8 @@ const performLogicOp = (scope, op, left, right) => {
|
|
313
320
|
return [
|
314
321
|
...left,
|
315
322
|
[ Opcodes.local_tee, localTmp(scope, 'logictmp') ],
|
316
|
-
...checks[op],
|
323
|
+
...checks[op](scope, [], leftType),
|
324
|
+
Opcodes.i32_to,
|
317
325
|
[ Opcodes.if, valtypeBinary ],
|
318
326
|
...right,
|
319
327
|
[ Opcodes.else ],
|
@@ -563,75 +571,77 @@ const compareStrings = (scope, left, right) => {
|
|
563
571
|
];
|
564
572
|
};
|
565
573
|
|
566
|
-
const
|
574
|
+
const truthy = (scope, wasm, type) => {
|
567
575
|
// arrays are always truthy
|
568
576
|
if (type === TYPES._array) return [
|
569
577
|
...wasm,
|
570
|
-
[ Opcodes.drop ],
|
571
|
-
number(
|
578
|
+
...(wasm.length === 0 ? [] : [ [ Opcodes.drop ] ]),
|
579
|
+
number(1)
|
572
580
|
];
|
573
581
|
|
574
582
|
if (type === TYPES.string) {
|
575
|
-
// if "" (length = 0)
|
583
|
+
// if not "" (length = 0)
|
576
584
|
return [
|
577
585
|
// pointer
|
578
586
|
...wasm,
|
587
|
+
Opcodes.i32_to_u,
|
579
588
|
|
580
589
|
// get length
|
581
590
|
[ Opcodes.i32_load, Math.log2(ValtypeSize.i32) - 1, 0 ],
|
582
591
|
|
583
|
-
// if length
|
584
|
-
[ Opcodes.i32_eqz ],
|
592
|
+
// if length != 0
|
593
|
+
/* [ Opcodes.i32_eqz ],
|
594
|
+
[ Opcodes.i32_eqz ], */
|
585
595
|
Opcodes.i32_from_u
|
586
596
|
]
|
587
597
|
}
|
588
598
|
|
589
|
-
// if
|
599
|
+
// if != 0
|
590
600
|
return [
|
591
601
|
...wasm,
|
592
602
|
|
593
|
-
|
594
|
-
Opcodes.
|
603
|
+
/* Opcodes.eqz,
|
604
|
+
[ Opcodes.i32_eqz ],
|
605
|
+
Opcodes.i32_from */
|
595
606
|
];
|
596
607
|
};
|
597
608
|
|
598
|
-
const
|
609
|
+
const falsy = (scope, wasm, type) => {
|
599
610
|
// arrays are always truthy
|
600
611
|
if (type === TYPES._array) return [
|
601
612
|
...wasm,
|
602
|
-
[ Opcodes.drop ],
|
603
|
-
number(
|
613
|
+
...(wasm.length === 0 ? [] : [ [ Opcodes.drop ] ]),
|
614
|
+
number(0)
|
604
615
|
];
|
605
616
|
|
606
617
|
if (type === TYPES.string) {
|
607
|
-
// if
|
618
|
+
// if "" (length = 0)
|
608
619
|
return [
|
609
620
|
// pointer
|
610
621
|
...wasm,
|
622
|
+
Opcodes.i32_to_u,
|
611
623
|
|
612
624
|
// get length
|
613
625
|
[ Opcodes.i32_load, Math.log2(ValtypeSize.i32) - 1, 0 ],
|
614
626
|
|
615
|
-
// if length
|
616
|
-
|
617
|
-
[ Opcodes.i32_eqz ], */
|
627
|
+
// if length == 0
|
628
|
+
[ Opcodes.i32_eqz ],
|
618
629
|
Opcodes.i32_from_u
|
619
630
|
]
|
620
631
|
}
|
621
632
|
|
622
|
-
// if
|
633
|
+
// if = 0
|
623
634
|
return [
|
624
635
|
...wasm,
|
625
636
|
|
626
|
-
|
627
|
-
|
628
|
-
Opcodes.i32_from */
|
637
|
+
...Opcodes.eqz,
|
638
|
+
Opcodes.i32_from_u
|
629
639
|
];
|
630
640
|
};
|
631
641
|
|
632
642
|
const performOp = (scope, op, left, right, leftType, rightType, _global = false, _name = '$undeclared', assign = false) => {
|
633
643
|
if (op === '||' || op === '&&' || op === '??') {
|
634
|
-
return performLogicOp(scope, op, left, right);
|
644
|
+
return performLogicOp(scope, op, left, right, leftType, rightType);
|
635
645
|
}
|
636
646
|
|
637
647
|
if (codeLog && (!leftType || !rightType)) log('codegen', 'untracked type in op', op, _name, '\n' + new Error().stack.split('\n').slice(1).join('\n'));
|
@@ -772,7 +782,7 @@ const includeBuiltin = (scope, builtin) => {
|
|
772
782
|
};
|
773
783
|
|
774
784
|
const generateLogicExp = (scope, decl) => {
|
775
|
-
return performLogicOp(scope, decl.operator, generate(scope, decl.left), generate(scope, decl.right));
|
785
|
+
return performLogicOp(scope, decl.operator, generate(scope, decl.left), generate(scope, decl.right), getNodeType(scope, decl.left), getNodeType(scope, decl.right));
|
776
786
|
};
|
777
787
|
|
778
788
|
const TYPES = {
|
@@ -1189,7 +1199,7 @@ const generateNew = (scope, decl, _global, _name) => {
|
|
1189
1199
|
// hack: basically treat this as a normal call for builtins for now
|
1190
1200
|
const name = mapName(decl.callee.name);
|
1191
1201
|
if (internalConstrs[name]) return internalConstrs[name].generate(scope, decl, _global, _name);
|
1192
|
-
if (!builtinFuncs[name]) return todo(`new statement is not supported yet (new ${unhackName(name)})`);
|
1202
|
+
if (!builtinFuncs[name]) return todo(`new statement is not supported yet`); // return todo(`new statement is not supported yet (new ${unhackName(name)})`);
|
1193
1203
|
|
1194
1204
|
return generateCall(scope, decl, _global, _name);
|
1195
1205
|
};
|
@@ -1377,7 +1387,7 @@ const generateUnary = (scope, decl) => {
|
|
1377
1387
|
|
1378
1388
|
case '!':
|
1379
1389
|
// !=
|
1380
|
-
return falsy(scope, generate(scope, decl.argument));
|
1390
|
+
return falsy(scope, generate(scope, decl.argument), getNodeType(scope, decl.argument));
|
1381
1391
|
|
1382
1392
|
case '~':
|
1383
1393
|
return [
|
@@ -1665,7 +1675,16 @@ const allocPage = reason => {
|
|
1665
1675
|
let ind = pages.size;
|
1666
1676
|
pages.set(reason, ind);
|
1667
1677
|
|
1668
|
-
if (
|
1678
|
+
if (allocLog) log('alloc', `allocated new page of memory (${ind}) | ${reason}`);
|
1679
|
+
|
1680
|
+
return ind;
|
1681
|
+
};
|
1682
|
+
|
1683
|
+
const freePage = reason => {
|
1684
|
+
let ind = pages.get(reason);
|
1685
|
+
pages.delete(reason);
|
1686
|
+
|
1687
|
+
if (allocLog) log('alloc', `freed page of memory (${ind}) | ${reason}`);
|
1669
1688
|
|
1670
1689
|
return ind;
|
1671
1690
|
};
|
package/compiler/index.js
CHANGED
@@ -14,7 +14,8 @@ const bold = x => `\u001b[1m${x}\u001b[0m`;
|
|
14
14
|
const areaColors = {
|
15
15
|
codegen: [ 20, 80, 250 ],
|
16
16
|
opt: [ 250, 20, 80 ],
|
17
|
-
sections: [ 20, 250, 80 ]
|
17
|
+
sections: [ 20, 250, 80 ],
|
18
|
+
alloc: [ 250, 250, 20 ]
|
18
19
|
};
|
19
20
|
|
20
21
|
globalThis.log = (area, ...args) => console.log(`\u001b[90m[\u001b[0m${rgb(...areaColors[area], area)}\u001b[90m]\u001b[0m`, ...args);
|
@@ -38,6 +39,7 @@ const logFuncs = (funcs, globals, exceptions) => {
|
|
38
39
|
export default (code, flags) => {
|
39
40
|
globalThis.optLog = process.argv.includes('-opt-log');
|
40
41
|
globalThis.codeLog = process.argv.includes('-code-log');
|
42
|
+
globalThis.allocLog = process.argv.includes('-alloc-log');
|
41
43
|
|
42
44
|
for (const x in BuiltinPreludes) {
|
43
45
|
if (code.indexOf(x + '(') !== -1) code = BuiltinPreludes[x] + code;
|
@@ -63,5 +65,12 @@ export default (code, flags) => {
|
|
63
65
|
const sections = produceSections(funcs, globals, tags, pages, flags);
|
64
66
|
if (flags.includes('info')) console.log(`4. produced sections in ${(performance.now() - t3).toFixed(2)}ms`);
|
65
67
|
|
68
|
+
if (allocLog) {
|
69
|
+
const wasmPages = Math.ceil((pages.size * pageSize) / 65536);
|
70
|
+
const bytes = wasmPages * 65536;
|
71
|
+
log('alloc', `\x1B[1mallocated ${bytes / 1024}KiB\x1B[0m for ${pages.size} things using ${wasmPages} Wasm page${wasmPages === 1 ? '' : 's'}`);
|
72
|
+
// console.log([...pages.keys()].map(x => `\x1B[36m - ${x}\x1B[0m`).join('\n'));
|
73
|
+
}
|
74
|
+
|
66
75
|
return { wasm: sections, funcs, globals, tags, exceptions, pages };
|
67
76
|
};
|
package/compiler/prototype.js
CHANGED
@@ -25,7 +25,6 @@ export const PrototypeFuncs = function() {
|
|
25
25
|
|
26
26
|
this[TYPES._array] = {
|
27
27
|
// lX = local accessor of X ({ get, set }), iX = local index of X, wX = wasm ops of X
|
28
|
-
// todo: out of bounds (>) properly
|
29
28
|
at: (pointer, length, wIndex, iTmp) => [
|
30
29
|
...wIndex,
|
31
30
|
Opcodes.i32_to,
|
@@ -147,7 +146,6 @@ export const PrototypeFuncs = function() {
|
|
147
146
|
this[TYPES._array].push.noArgRetLength = true;
|
148
147
|
|
149
148
|
this[TYPES.string] = {
|
150
|
-
// todo: out of bounds properly
|
151
149
|
at: (pointer, length, wIndex, iTmp, arrayShell) => {
|
152
150
|
const [ newOut, newPointer ] = arrayShell(1, 'i16');
|
153
151
|
|
@@ -157,9 +155,9 @@ export const PrototypeFuncs = function() {
|
|
157
155
|
[ Opcodes.drop ],
|
158
156
|
|
159
157
|
...number(0, Valtype.i32), // base 0 for store later
|
160
|
-
Opcodes.i32_to_u,
|
161
158
|
|
162
159
|
...wIndex,
|
160
|
+
Opcodes.i32_to_u,
|
163
161
|
[ Opcodes.local_tee, iTmp ],
|
164
162
|
|
165
163
|
// if index < 0: access index + array length
|
@@ -265,7 +263,7 @@ export const PrototypeFuncs = function() {
|
|
265
263
|
},
|
266
264
|
};
|
267
265
|
|
268
|
-
this[TYPES.string].at.local =
|
266
|
+
this[TYPES.string].at.local = Valtype.i32;
|
269
267
|
this[TYPES.string].at.returnType = TYPES.string;
|
270
268
|
this[TYPES.string].charAt.returnType = TYPES.string;
|
271
269
|
this[TYPES.string].charCodeAt.local = Valtype.i32;
|
package/package.json
CHANGED
package/runner/index.js
CHANGED
@@ -5,6 +5,12 @@ import fs from 'node:fs';
|
|
5
5
|
|
6
6
|
const file = process.argv.slice(2).find(x => x[0] !== '-');
|
7
7
|
if (!file) {
|
8
|
+
if (process.argv.includes('-v')) {
|
9
|
+
// just print version
|
10
|
+
console.log((await import('./version.js')).default);
|
11
|
+
process.exit(0);
|
12
|
+
}
|
13
|
+
|
8
14
|
// run repl if no file given
|
9
15
|
await import('./repl.js');
|
10
16
|
|
package/runner/repl.js
CHANGED
@@ -1,14 +1,7 @@
|
|
1
1
|
import compile from '../compiler/wrap.js';
|
2
|
+
import rev from './version.js';
|
2
3
|
|
3
4
|
import repl from 'node:repl';
|
4
|
-
import fs from 'node:fs';
|
5
|
-
|
6
|
-
let rev = 'unknown';
|
7
|
-
try {
|
8
|
-
rev = fs.readFileSync(new URL('../.git/refs/heads/main', import.meta.url), 'utf8').trim().slice(0, 7);
|
9
|
-
} catch {
|
10
|
-
rev = JSON.parse(fs.readFileSync(new URL('../package.json', import.meta.url), 'utf8')).version.split('-')[1];
|
11
|
-
}
|
12
5
|
|
13
6
|
// process.argv.push('-O0'); // disable opts
|
14
7
|
|
@@ -48,7 +41,7 @@ const memoryToString = mem => {
|
|
48
41
|
return out;
|
49
42
|
};
|
50
43
|
|
51
|
-
const alwaysPrev = process.argv.includes('-
|
44
|
+
const alwaysPrev = process.argv.includes('-prev');
|
52
45
|
|
53
46
|
let prev = '';
|
54
47
|
const run = async (source, _context, _filename, callback, run = true) => {
|
@@ -56,7 +49,7 @@ const run = async (source, _context, _filename, callback, run = true) => {
|
|
56
49
|
if (alwaysPrev) prev = toRun + ';\n';
|
57
50
|
|
58
51
|
const { exports, wasm, pages } = await compile(toRun, []);
|
59
|
-
fs.writeFileSync('out.wasm', Buffer.from(wasm));
|
52
|
+
// fs.writeFileSync('out.wasm', Buffer.from(wasm));
|
60
53
|
|
61
54
|
if (run && exports.$) {
|
62
55
|
lastMemory = exports.$;
|
@@ -0,0 +1,10 @@
|
|
1
|
+
import fs from 'node:fs';
|
2
|
+
|
3
|
+
let rev = 'unknown';
|
4
|
+
try {
|
5
|
+
rev = fs.readFileSync(new URL('../.git/refs/heads/main', import.meta.url), 'utf8').trim().slice(0, 7);
|
6
|
+
} catch {
|
7
|
+
rev = JSON.parse(fs.readFileSync(new URL('../package.json', import.meta.url), 'utf8')).version.split('-')[1].slice(0, 7);
|
8
|
+
}
|
9
|
+
|
10
|
+
export default rev;
|