porffor 0.0.0-1989c22 → 0.0.0-44bc2d8
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/README.md +1 -1
- package/compiler/codeGen.js +29 -8
- package/compiler/opt.js +1 -1
- package/compiler/sections.js +3 -2
- package/compiler/wrap.js +9 -0
- package/package.json +1 -1
- package/runner/repl.js +4 -2
package/README.md
CHANGED
@@ -76,6 +76,7 @@ these include some early (stage 1/0) and/or dead (last commit years ago) proposa
|
|
76
76
|
- string member (char) access via `str[ind]` (eg `str[0]`)
|
77
77
|
- string concat (`+`) (eg `'a' + 'b'`)
|
78
78
|
- truthy/falsy (eg `!'' == true`)
|
79
|
+
- string comparison (eg `'a' == 'a'`, `'a' != 'b'`)
|
79
80
|
|
80
81
|
### built-ins
|
81
82
|
|
@@ -106,7 +107,6 @@ these include some early (stage 1/0) and/or dead (last commit years ago) proposa
|
|
106
107
|
- arrays/strings inside arrays
|
107
108
|
- strings
|
108
109
|
- member setting
|
109
|
-
- equality
|
110
110
|
- more math operators (`**`, etc)
|
111
111
|
- `do { ... } while (...)`
|
112
112
|
- exceptions
|
package/compiler/codeGen.js
CHANGED
@@ -101,6 +101,9 @@ const generate = (scope, decl, global = false, name = undefined) => {
|
|
101
101
|
case 'WhileStatement':
|
102
102
|
return generateWhile(scope, decl);
|
103
103
|
|
104
|
+
/* case 'ForOfStatement':
|
105
|
+
return generateForOf(scope, decl); */
|
106
|
+
|
104
107
|
case 'BreakStatement':
|
105
108
|
return generateBreak(scope, decl);
|
106
109
|
|
@@ -472,9 +475,6 @@ const compareStrings = (scope, left, right) => {
|
|
472
475
|
const indexEnd = localTmp(scope, 'compare_index_end', Valtype.i32);
|
473
476
|
|
474
477
|
return [
|
475
|
-
// use block to "return" a value early
|
476
|
-
[ Opcodes.block, Valtype.i32 ],
|
477
|
-
|
478
478
|
// setup left
|
479
479
|
...left,
|
480
480
|
Opcodes.i32_to_u,
|
@@ -486,11 +486,9 @@ const compareStrings = (scope, left, right) => {
|
|
486
486
|
[ Opcodes.local_tee, rightPointer ],
|
487
487
|
|
488
488
|
// fast path: check leftPointer == rightPointer
|
489
|
-
|
490
|
-
[ Opcodes.
|
491
|
-
|
492
|
-
[ Opcodes.br, 1 ],
|
493
|
-
[ Opcodes.end ],
|
489
|
+
// use if (block) for everything after to "return" a value early
|
490
|
+
[ Opcodes.i32_ne ],
|
491
|
+
[ Opcodes.if, Valtype.i32 ],
|
494
492
|
|
495
493
|
// get lengths
|
496
494
|
[ Opcodes.local_get, leftPointer ],
|
@@ -553,6 +551,10 @@ const compareStrings = (scope, left, right) => {
|
|
553
551
|
|
554
552
|
// no failed checks, so true!
|
555
553
|
...number(1, Valtype.i32),
|
554
|
+
|
555
|
+
// pointers match, so true
|
556
|
+
[ Opcodes.else ],
|
557
|
+
...number(1, Valtype.i32),
|
556
558
|
[ Opcodes.end ],
|
557
559
|
|
558
560
|
// convert i32 result to valtype
|
@@ -1552,6 +1554,25 @@ const generateWhile = (scope, decl) => {
|
|
1552
1554
|
return out;
|
1553
1555
|
};
|
1554
1556
|
|
1557
|
+
const generateForOf = (scope, decl) => {
|
1558
|
+
const out = [];
|
1559
|
+
|
1560
|
+
out.push([ Opcodes.loop, Blocktype.void ]);
|
1561
|
+
depth.push('while');
|
1562
|
+
|
1563
|
+
out.push(...generate(scope, decl.test));
|
1564
|
+
out.push(Opcodes.i32_to, [ Opcodes.if, Blocktype.void ]);
|
1565
|
+
depth.push('if');
|
1566
|
+
|
1567
|
+
out.push(...generate(scope, decl.body));
|
1568
|
+
|
1569
|
+
out.push([ Opcodes.br, 1 ]);
|
1570
|
+
out.push([ Opcodes.end ], [ Opcodes.end ]);
|
1571
|
+
depth.pop(); depth.pop();
|
1572
|
+
|
1573
|
+
return out;
|
1574
|
+
};
|
1575
|
+
|
1555
1576
|
const getNearestLoop = () => {
|
1556
1577
|
for (let i = depth.length - 1; i >= 0; i--) {
|
1557
1578
|
if (depth[i] === 'while' || depth[i] === 'for' || depth[i] === 'forof') return i;
|
package/compiler/opt.js
CHANGED
@@ -20,7 +20,7 @@ export default (funcs, globals) => {
|
|
20
20
|
if (optLevel === 0) return;
|
21
21
|
|
22
22
|
const tailCall = process.argv.includes('-tail-call');
|
23
|
-
if (tailCall) log('opt', 'tail call proposal is not widely implemented! (you used -tail-call)');
|
23
|
+
if (tailCall) log('opt', 'warning: tail call proposal is not widely implemented! (you used -tail-call)');
|
24
24
|
|
25
25
|
if (optLevel >= 2 && !process.argv.includes('-opt-no-inline')) {
|
26
26
|
// inline pass (very WIP)
|
package/compiler/sections.js
CHANGED
@@ -36,7 +36,7 @@ export default (funcs, globals, tags, pages, flags) => {
|
|
36
36
|
// tree shake imports
|
37
37
|
for (const f of funcs) {
|
38
38
|
for (const inst of f.wasm) {
|
39
|
-
if (inst[0] === Opcodes.call && inst[1] < importedFuncs.length) {
|
39
|
+
if ((inst[0] === Opcodes.call || inst[0] === Opcodes.return_call) && inst[1] < importedFuncs.length) {
|
40
40
|
const idx = inst[1];
|
41
41
|
const func = importedFuncs[idx];
|
42
42
|
|
@@ -51,10 +51,11 @@ export default (funcs, globals, tags, pages, flags) => {
|
|
51
51
|
// fix call indexes for non-imports
|
52
52
|
const delta = importedFuncs.length - importFuncs.length;
|
53
53
|
for (const f of funcs) {
|
54
|
+
f.originalIndex = f.index;
|
54
55
|
f.index -= delta;
|
55
56
|
|
56
57
|
for (const inst of f.wasm) {
|
57
|
-
if (inst[0] === Opcodes.call && inst[1] >= importedFuncs.length) {
|
58
|
+
if ((inst[0] === Opcodes.call || inst[0] === Opcodes.return_call) && inst[1] >= importedFuncs.length) {
|
58
59
|
inst[1] -= delta;
|
59
60
|
}
|
60
61
|
}
|
package/compiler/wrap.js
CHANGED
@@ -90,6 +90,15 @@ export default async (source, flags = [ 'module' ], customImports = {}, print =
|
|
90
90
|
return Array.from(new Uint16Array(memory.buffer, pointer + 4, length)).map(x => String.fromCharCode(x)).join('');
|
91
91
|
}
|
92
92
|
|
93
|
+
case 'function': {
|
94
|
+
// wasm func index, including all imports
|
95
|
+
const func = funcs.find(x => (x.originalIndex ?? x.index) === ret);
|
96
|
+
if (!func) return ret;
|
97
|
+
|
98
|
+
// make fake empty func for repl/etc
|
99
|
+
return {[func.name]() {}}[func.name];
|
100
|
+
}
|
101
|
+
|
93
102
|
default: return ret;
|
94
103
|
}
|
95
104
|
} catch (e) {
|
package/package.json
CHANGED
package/runner/repl.js
CHANGED
@@ -48,10 +48,12 @@ const memoryToString = mem => {
|
|
48
48
|
return out;
|
49
49
|
};
|
50
50
|
|
51
|
+
const alwaysPrev = process.argv.includes('-always-prev');
|
52
|
+
|
51
53
|
let prev = '';
|
52
54
|
const run = async (source, _context, _filename, callback, run = true) => {
|
53
55
|
let toRun = prev + source.trim();
|
54
|
-
|
56
|
+
if (alwaysPrev) prev = toRun + ';\n';
|
55
57
|
|
56
58
|
const { exports, wasm, pages } = await compile(toRun, []);
|
57
59
|
fs.writeFileSync('out.wasm', Buffer.from(wasm));
|
@@ -64,7 +66,7 @@ const run = async (source, _context, _filename, callback, run = true) => {
|
|
64
66
|
const ret = run ? exports.main() : undefined;
|
65
67
|
callback(null, ret);
|
66
68
|
|
67
|
-
if (source.includes(' = ') || source.includes('let ') || source.includes('var ') || source.includes('const ') || source.includes('function ')) prev = toRun + ';\n';
|
69
|
+
if (!alwaysPrev && (source.includes(' = ') || source.includes('let ') || source.includes('var ') || source.includes('const ') || source.includes('function '))) prev = toRun + ';\n';
|
68
70
|
// prev = toRun + ';\n';
|
69
71
|
};
|
70
72
|
|