porffor 0.2.0-fdf0fc5 → 0.14.0-1a571ec24
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 +9 -2
- package/byg/index.js +3 -24
- package/compiler/2c.js +2 -53
- package/compiler/assemble.js +37 -11
- package/compiler/builtins/annexb_string.js +10 -10
- package/compiler/builtins/annexb_string.ts +3 -3
- package/compiler/builtins/array.ts +2 -6
- package/compiler/builtins/base64.ts +1 -1
- package/compiler/builtins/boolean.ts +1 -3
- package/compiler/builtins/crypto.ts +1 -1
- package/compiler/builtins/date.ts +1 -4
- package/compiler/builtins/escape.ts +1 -1
- package/compiler/builtins/function.ts +0 -2
- package/compiler/builtins/int.ts +0 -2
- package/compiler/builtins/number.ts +3 -8
- package/compiler/builtins/object.ts +0 -2
- package/compiler/builtins/porffor.d.ts +9 -8
- package/compiler/builtins/set.ts +184 -2
- package/compiler/builtins/string.ts +1 -1
- package/compiler/builtins/symbol.ts +61 -0
- package/compiler/builtins.js +8 -9
- package/compiler/codegen.js +121 -124
- package/compiler/decompile.js +3 -3
- package/compiler/embedding.js +2 -2
- package/compiler/encoding.js +0 -14
- package/compiler/expression.js +1 -1
- package/compiler/generated_builtins.js +348 -204
- package/compiler/index.js +3 -10
- package/compiler/opt.js +7 -7
- package/compiler/parse.js +1 -3
- package/compiler/precompile.js +17 -25
- package/compiler/prefs.js +1 -1
- package/compiler/prototype.js +5 -5
- package/compiler/wasmSpec.js +5 -0
- package/compiler/wrap.js +88 -57
- package/package.json +1 -1
- package/runner/compare.js +0 -1
- package/runner/debug.js +1 -6
- package/runner/profiler.js +15 -42
- package/runner/repl.js +3 -9
- package/runner/sizes.js +2 -2
- package/runner/version.js +10 -8
package/compiler/codegen.js
CHANGED
@@ -1,14 +1,14 @@
|
|
1
|
-
import { Blocktype, Opcodes, Valtype, PageSize, ValtypeSize } from
|
2
|
-
import { ieee754_binary64, signedLEB128, unsignedLEB128, encodeVector } from
|
3
|
-
import { operatorOpcode } from
|
4
|
-
import { BuiltinFuncs, BuiltinVars, importedFuncs, NULL, UNDEFINED } from
|
5
|
-
import { PrototypeFuncs } from
|
6
|
-
import { number
|
7
|
-
import { log } from "./log.js";
|
8
|
-
import parse from "./parse.js";
|
9
|
-
import * as Rhemyn from "../rhemyn/compile.js";
|
10
|
-
import Prefs from './prefs.js';
|
1
|
+
import { Blocktype, Opcodes, Valtype, PageSize, ValtypeSize } from './wasmSpec.js';
|
2
|
+
import { ieee754_binary64, signedLEB128, unsignedLEB128, encodeVector } from './encoding.js';
|
3
|
+
import { operatorOpcode } from './expression.js';
|
4
|
+
import { BuiltinFuncs, BuiltinVars, importedFuncs, NULL, UNDEFINED } from './builtins.js';
|
5
|
+
import { PrototypeFuncs } from './prototype.js';
|
6
|
+
import { number } from './embedding.js';
|
11
7
|
import { TYPES, TYPE_NAMES } from './types.js';
|
8
|
+
import * as Rhemyn from '../rhemyn/compile.js';
|
9
|
+
import parse from './parse.js';
|
10
|
+
import { log } from './log.js';
|
11
|
+
import Prefs from './prefs.js';
|
12
12
|
|
13
13
|
let globals = {};
|
14
14
|
let globalInd = 0;
|
@@ -19,24 +19,6 @@ let funcIndex = {};
|
|
19
19
|
let currentFuncIndex = importedFuncs.length;
|
20
20
|
let builtinFuncs = {}, builtinVars = {}, prototypeFuncs = {};
|
21
21
|
|
22
|
-
const debug = str => {
|
23
|
-
const code = [];
|
24
|
-
|
25
|
-
const logChar = n => {
|
26
|
-
code.push(...number(n));
|
27
|
-
|
28
|
-
code.push([ Opcodes.call, 0 ]);
|
29
|
-
};
|
30
|
-
|
31
|
-
for (let i = 0; i < str.length; i++) {
|
32
|
-
logChar(str.charCodeAt(i));
|
33
|
-
}
|
34
|
-
|
35
|
-
logChar(10); // new line
|
36
|
-
|
37
|
-
return code;
|
38
|
-
};
|
39
|
-
|
40
22
|
class TodoError extends Error {
|
41
23
|
constructor(message) {
|
42
24
|
super(message);
|
@@ -76,10 +58,11 @@ const generate = (scope, decl, global = false, name = undefined, valueUnused = f
|
|
76
58
|
|
77
59
|
case 'ArrowFunctionExpression':
|
78
60
|
case 'FunctionDeclaration':
|
61
|
+
case 'FunctionExpression':
|
79
62
|
const func = generateFunc(scope, decl);
|
80
63
|
|
81
64
|
if (decl.type.endsWith('Expression')) {
|
82
|
-
return number(func.index);
|
65
|
+
return number(func.index - importedFuncs.length);
|
83
66
|
}
|
84
67
|
|
85
68
|
return [];
|
@@ -171,11 +154,6 @@ const generate = (scope, decl, global = false, name = undefined, valueUnused = f
|
|
171
154
|
newFunc.export = true;
|
172
155
|
}
|
173
156
|
|
174
|
-
// if (funcsBefore === funcs.length) throw new Error('no new func added in export');
|
175
|
-
|
176
|
-
// const newFunc = funcs[funcs.length - 1];
|
177
|
-
// newFunc.export = true;
|
178
|
-
|
179
157
|
return [];
|
180
158
|
|
181
159
|
case 'TaggedTemplateExpression': {
|
@@ -210,7 +188,7 @@ const generate = (scope, decl, global = false, name = undefined, valueUnused = f
|
|
210
188
|
if (!Array.isArray(inst)) inst = [ inst ];
|
211
189
|
const immediates = asm.slice(1).map(x => {
|
212
190
|
const int = parseInt(x);
|
213
|
-
if (Number.isNaN(int)) return scope.locals[x]?.idx;
|
191
|
+
if (Number.isNaN(int)) return scope.locals[x]?.idx ?? globals[x].idx;
|
214
192
|
return int;
|
215
193
|
});
|
216
194
|
|
@@ -336,10 +314,10 @@ const generateIdent = (scope, decl) => {
|
|
336
314
|
|
337
315
|
if (local?.idx === undefined) {
|
338
316
|
// no local var with name
|
339
|
-
if (Object.hasOwn(importedFuncs, name)) return number(importedFuncs[name]);
|
340
|
-
if (Object.hasOwn(funcIndex, name)) return number(funcIndex[name]);
|
341
|
-
|
342
317
|
if (Object.hasOwn(globals, name)) return [ [ Opcodes.global_get, globals[name].idx ] ];
|
318
|
+
|
319
|
+
if (Object.hasOwn(importedFuncs, name)) return number(importedFuncs[name] - importedFuncs.length);
|
320
|
+
if (Object.hasOwn(funcIndex, name)) return number(funcIndex[name] - importedFuncs.length);
|
343
321
|
}
|
344
322
|
|
345
323
|
if (local?.idx === undefined && rawName.startsWith('__')) {
|
@@ -373,9 +351,7 @@ const generateReturn = (scope, decl) => {
|
|
373
351
|
|
374
352
|
return [
|
375
353
|
...generate(scope, decl.argument),
|
376
|
-
...(scope.returnType != null ? [] :
|
377
|
-
...getNodeType(scope, decl.argument)
|
378
|
-
]),
|
354
|
+
...(scope.returnType != null ? [] : getNodeType(scope, decl.argument)),
|
379
355
|
[ Opcodes.return ]
|
380
356
|
];
|
381
357
|
};
|
@@ -858,31 +834,6 @@ const performOp = (scope, op, left, right, leftType, rightType, _global = false,
|
|
858
834
|
|
859
835
|
// if strict (in)equal check types match
|
860
836
|
if (strictOp) {
|
861
|
-
// startOut.push(
|
862
|
-
// ...leftType,
|
863
|
-
// ...rightType,
|
864
|
-
// [ Opcodes.i32_eq ]
|
865
|
-
// );
|
866
|
-
|
867
|
-
// endOut.push(
|
868
|
-
// [ Opcodes.i32_and ]
|
869
|
-
// );
|
870
|
-
|
871
|
-
// startOut.push(
|
872
|
-
// [ Opcodes.block, Valtype.i32 ],
|
873
|
-
// ...leftType,
|
874
|
-
// ...rightType,
|
875
|
-
// [ Opcodes.i32_ne ],
|
876
|
-
// [ Opcodes.if, Blocktype.void ],
|
877
|
-
// ...number(op === '===' ? 0 : 1, Valtype.i32),
|
878
|
-
// [ Opcodes.br, 1 ],
|
879
|
-
// [ Opcodes.end ]
|
880
|
-
// );
|
881
|
-
|
882
|
-
// endOut.push(
|
883
|
-
// [ Opcodes.end ]
|
884
|
-
// );
|
885
|
-
|
886
837
|
endOut.push(
|
887
838
|
...leftType,
|
888
839
|
...rightType,
|
@@ -1089,7 +1040,7 @@ const generateBinaryExp = (scope, decl, _global, _name) => {
|
|
1089
1040
|
|
1090
1041
|
const asmFuncToAsm = (func, { name = '#unknown_asm_func', params = [], locals = [], returns = [], localInd = 0 }) => {
|
1091
1042
|
return func({ name, params, locals, returns, localInd }, {
|
1092
|
-
TYPES, TYPE_NAMES, typeSwitch, makeArray, makeString, allocPage,
|
1043
|
+
TYPES, TYPE_NAMES, typeSwitch, makeArray, makeString, allocPage, internalThrow,
|
1093
1044
|
builtin: name => {
|
1094
1045
|
let idx = funcIndex[name] ?? importedFuncs[name];
|
1095
1046
|
if (idx === undefined && builtinFuncs[name]) {
|
@@ -1248,7 +1199,7 @@ const setLastType = scope => {
|
|
1248
1199
|
};
|
1249
1200
|
|
1250
1201
|
const getNodeType = (scope, node) => {
|
1251
|
-
const
|
1202
|
+
const ret = (() => {
|
1252
1203
|
if (node.type === 'Literal') {
|
1253
1204
|
if (node.regex) return TYPES.regexp;
|
1254
1205
|
|
@@ -1291,7 +1242,6 @@ const getNodeType = (scope, node) => {
|
|
1291
1242
|
const func = funcs.find(x => x.name === name);
|
1292
1243
|
|
1293
1244
|
if (func) {
|
1294
|
-
// console.log(scope, func, func.returnType);
|
1295
1245
|
if (func.returnType) return func.returnType;
|
1296
1246
|
}
|
1297
1247
|
|
@@ -1435,10 +1385,8 @@ const getNodeType = (scope, node) => {
|
|
1435
1385
|
// presume
|
1436
1386
|
// todo: warn here?
|
1437
1387
|
return TYPES.number;
|
1438
|
-
};
|
1388
|
+
})();
|
1439
1389
|
|
1440
|
-
const ret = inner();
|
1441
|
-
// console.trace(node, ret);
|
1442
1390
|
if (typeof ret === 'number') return number(ret, Valtype.i32);
|
1443
1391
|
return ret;
|
1444
1392
|
};
|
@@ -1501,6 +1449,10 @@ const countLeftover = wasm => {
|
|
1501
1449
|
} else count--;
|
1502
1450
|
if (func) count += func.returns.length;
|
1503
1451
|
}
|
1452
|
+
} else if (inst[0] === Opcodes.call_indirect) {
|
1453
|
+
count--; // funcidx
|
1454
|
+
count -= inst[1] * 2; // params * 2 (typed)
|
1455
|
+
count += 2; // fixed return (value, type)
|
1504
1456
|
} else count--;
|
1505
1457
|
|
1506
1458
|
// console.log(count, decompile([ inst ]).slice(0, -1));
|
@@ -1577,15 +1529,6 @@ const RTArrayUtil = {
|
|
1577
1529
|
};
|
1578
1530
|
|
1579
1531
|
const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
|
1580
|
-
/* const callee = decl.callee;
|
1581
|
-
const args = decl.arguments;
|
1582
|
-
|
1583
|
-
return [
|
1584
|
-
...generate(args),
|
1585
|
-
...generate(callee),
|
1586
|
-
Opcodes.call_indirect,
|
1587
|
-
]; */
|
1588
|
-
|
1589
1532
|
let name = mapName(decl.callee.name);
|
1590
1533
|
if (isFuncType(decl.callee.type)) { // iife
|
1591
1534
|
const func = generateFunc(scope, decl.callee);
|
@@ -1759,8 +1702,6 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
|
|
1759
1702
|
continue;
|
1760
1703
|
}
|
1761
1704
|
|
1762
|
-
// const protoLocal = protoFunc.local ? localTmp(scope, `__${TYPE_NAMES[x]}_${protoName}_tmp`, protoFunc.local) : -1;
|
1763
|
-
// const protoLocal2 = protoFunc.local2 ? localTmp(scope, `__${TYPE_NAMES[x]}_${protoName}_tmp2`, protoFunc.local2) : -1;
|
1764
1705
|
const protoLocal = protoFunc.local ? localTmp(scope, `__${protoName}_tmp`, protoFunc.local) : -1;
|
1765
1706
|
const protoLocal2 = protoFunc.local2 ? localTmp(scope, `__${protoName}_tmp2`, protoFunc.local2) : -1;
|
1766
1707
|
|
@@ -1837,22 +1778,6 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
|
|
1837
1778
|
|
1838
1779
|
includeBuiltin(scope, name);
|
1839
1780
|
idx = funcIndex[name];
|
1840
|
-
|
1841
|
-
// infer arguments types from builtins params
|
1842
|
-
// const func = funcs.find(x => x.name === name);
|
1843
|
-
// for (let i = 0; i < decl.arguments.length; i++) {
|
1844
|
-
// const arg = decl.arguments[i];
|
1845
|
-
// if (!arg.name) continue;
|
1846
|
-
|
1847
|
-
// const local = scope.locals[arg.name];
|
1848
|
-
// if (!local) continue;
|
1849
|
-
|
1850
|
-
// local.type = func.params[i];
|
1851
|
-
// if (local.type === Valtype.v128) {
|
1852
|
-
// // specify vec subtype inferred from last vec type in function name
|
1853
|
-
// local.vecType = name.split('_').reverse().find(x => x.includes('x'));
|
1854
|
-
// }
|
1855
|
-
// }
|
1856
1781
|
}
|
1857
1782
|
|
1858
1783
|
if (idx === undefined && internalConstrs[name]) return internalConstrs[name].generate(scope, decl, _global, _name);
|
@@ -1909,7 +1834,45 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
|
|
1909
1834
|
}
|
1910
1835
|
|
1911
1836
|
if (idx === undefined) {
|
1912
|
-
if (scope.locals[name] !== undefined || globals[name] !== undefined || builtinVars[name] !== undefined)
|
1837
|
+
if (scope.locals[name] !== undefined || globals[name] !== undefined || builtinVars[name] !== undefined) {
|
1838
|
+
const [ local, global ] = lookupName(scope, name);
|
1839
|
+
if (!Prefs.indirectCalls || local == null) return internalThrow(scope, 'TypeError', `${unhackName(name)} is not a function`, true);
|
1840
|
+
|
1841
|
+
// todo: only works when:
|
1842
|
+
// 1. arg count matches arg count of function
|
1843
|
+
// 2. function uses typedParams and typedReturns
|
1844
|
+
|
1845
|
+
funcs.table = true;
|
1846
|
+
|
1847
|
+
let args = decl.arguments;
|
1848
|
+
let argWasm = [];
|
1849
|
+
|
1850
|
+
for (let i = 0; i < args.length; i++) {
|
1851
|
+
const arg = args[i];
|
1852
|
+
argWasm = argWasm.concat(generate(scope, arg));
|
1853
|
+
|
1854
|
+
if (valtypeBinary !== Valtype.i32 && (
|
1855
|
+
(builtinFuncs[name] && builtinFuncs[name].params[i * (typedParams ? 2 : 1)] === Valtype.i32) ||
|
1856
|
+
(importedFuncs[name] && name.startsWith('profile'))
|
1857
|
+
)) {
|
1858
|
+
argWasm.push(Opcodes.i32_to);
|
1859
|
+
}
|
1860
|
+
|
1861
|
+
argWasm = argWasm.concat(getNodeType(scope, arg));
|
1862
|
+
}
|
1863
|
+
|
1864
|
+
return typeSwitch(scope, getNodeType(scope, decl.callee), {
|
1865
|
+
[TYPES.function]: [
|
1866
|
+
...argWasm,
|
1867
|
+
[ global ? Opcodes.global_get : Opcodes.local_get, local.idx ],
|
1868
|
+
Opcodes.i32_to_u,
|
1869
|
+
[ Opcodes.call_indirect, args.length, 0 ],
|
1870
|
+
...setLastType(scope)
|
1871
|
+
],
|
1872
|
+
default: internalThrow(scope, 'TypeError', `${unhackName(name)} is not a function`, true)
|
1873
|
+
});
|
1874
|
+
}
|
1875
|
+
|
1913
1876
|
return internalThrow(scope, 'ReferenceError', `${unhackName(name)} is not defined`, true);
|
1914
1877
|
}
|
1915
1878
|
|
@@ -1938,11 +1901,16 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
|
|
1938
1901
|
const arg = args[i];
|
1939
1902
|
out = out.concat(generate(scope, arg));
|
1940
1903
|
|
1941
|
-
if (
|
1942
|
-
|
1904
|
+
if (i >= paramCount) {
|
1905
|
+
// over param count of func, drop arg
|
1906
|
+
out.push([ Opcodes.drop ]);
|
1907
|
+
continue;
|
1943
1908
|
}
|
1944
1909
|
|
1945
|
-
if (
|
1910
|
+
if (valtypeBinary !== Valtype.i32 && (
|
1911
|
+
(builtinFuncs[name] && builtinFuncs[name].params[i * (typedParams ? 2 : 1)] === Valtype.i32) ||
|
1912
|
+
(importedFuncs[name] && name.startsWith('profile'))
|
1913
|
+
)) {
|
1946
1914
|
out.push(Opcodes.i32_to);
|
1947
1915
|
}
|
1948
1916
|
|
@@ -1987,6 +1955,11 @@ const generateNew = (scope, decl, _global, _name) => {
|
|
1987
1955
|
}, _global, _name);
|
1988
1956
|
}
|
1989
1957
|
|
1958
|
+
if (
|
1959
|
+
(builtinFuncs[name] && !builtinFuncs[name].constr) ||
|
1960
|
+
(internalConstrs[name] && builtinFuncs[name].notConstr)
|
1961
|
+
) return internalThrow(scope, 'TypeError', `${name} is not a constructor`);
|
1962
|
+
|
1990
1963
|
if (!builtinFuncs[name]) return todo(scope, `new statement is not supported yet`); // return todo(scope, `new statement is not supported yet (new ${unhackName(name)})`);
|
1991
1964
|
|
1992
1965
|
return generateCall(scope, decl, _global, _name);
|
@@ -2178,7 +2151,6 @@ const addVarMetadata = (scope, name, global = false, metadata = {}) => {
|
|
2178
2151
|
const typeAnnoToPorfType = x => {
|
2179
2152
|
if (!x) return null;
|
2180
2153
|
if (TYPES[x.toLowerCase()] != null) return TYPES[x.toLowerCase()];
|
2181
|
-
if (TYPES['_' + x.toLowerCase()] != null) return TYPES['_' + x.toLowerCase()];
|
2182
2154
|
|
2183
2155
|
switch (x) {
|
2184
2156
|
case 'i32':
|
@@ -2219,9 +2191,8 @@ const generateVar = (scope, decl) => {
|
|
2219
2191
|
|
2220
2192
|
const topLevel = scope.name === 'main';
|
2221
2193
|
|
2222
|
-
// global variable if in top scope (main)
|
2223
|
-
const global = topLevel || decl._bare;
|
2224
|
-
const target = global ? globals : scope.locals;
|
2194
|
+
// global variable if in top scope (main) or if internally wanted
|
2195
|
+
const global = topLevel || decl._bare;
|
2225
2196
|
|
2226
2197
|
for (const x of decl.declarations) {
|
2227
2198
|
const name = mapName(x.id.name);
|
@@ -2235,7 +2206,6 @@ const generateVar = (scope, decl) => {
|
|
2235
2206
|
continue;
|
2236
2207
|
}
|
2237
2208
|
|
2238
|
-
// console.log(name);
|
2239
2209
|
if (topLevel && builtinVars[name]) {
|
2240
2210
|
// cannot redeclare
|
2241
2211
|
if (decl.kind !== 'var') return internalThrow(scope, 'SyntaxError', `Identifier '${unhackName(name)}' has already been declared`);
|
@@ -2255,6 +2225,22 @@ const generateVar = (scope, decl) => {
|
|
2255
2225
|
}
|
2256
2226
|
|
2257
2227
|
if (x.init) {
|
2228
|
+
// if (isFuncType(x.init.type)) {
|
2229
|
+
// // let a = function () { ... }
|
2230
|
+
// x.init.id = { name };
|
2231
|
+
|
2232
|
+
// const func = generateFunc(scope, x.init);
|
2233
|
+
|
2234
|
+
// out.push(
|
2235
|
+
// ...number(func.index - importedFuncs.length),
|
2236
|
+
// [ global ? Opcodes.global_set : Opcodes.local_set, idx ],
|
2237
|
+
|
2238
|
+
// ...setType(scope, name, TYPES.function)
|
2239
|
+
// );
|
2240
|
+
|
2241
|
+
// continue;
|
2242
|
+
// }
|
2243
|
+
|
2258
2244
|
const generated = generate(scope, x.init, global, name);
|
2259
2245
|
if (scope.arrays?.get(name) != null) {
|
2260
2246
|
// hack to set local as pointer before
|
@@ -2266,6 +2252,7 @@ const generateVar = (scope, decl) => {
|
|
2266
2252
|
out = out.concat(generated);
|
2267
2253
|
out.push([ global ? Opcodes.global_set : Opcodes.local_set, idx ]);
|
2268
2254
|
}
|
2255
|
+
|
2269
2256
|
out.push(...setType(scope, name, getNodeType(scope, x.init)));
|
2270
2257
|
}
|
2271
2258
|
|
@@ -2279,6 +2266,7 @@ const generateVar = (scope, decl) => {
|
|
2279
2266
|
// todo: optimize this func for valueUnused
|
2280
2267
|
const generateAssign = (scope, decl, _global, _name, valueUnused = false) => {
|
2281
2268
|
const { type, name } = decl.left;
|
2269
|
+
const [ local, isGlobal ] = lookupName(scope, name);
|
2282
2270
|
|
2283
2271
|
if (type === 'ObjectPattern') {
|
2284
2272
|
// hack: ignore object parts of `var a = {} = 2`
|
@@ -2288,8 +2276,18 @@ const generateAssign = (scope, decl, _global, _name, valueUnused = false) => {
|
|
2288
2276
|
if (isFuncType(decl.right.type)) {
|
2289
2277
|
// hack for a = function () { ... }
|
2290
2278
|
decl.right.id = { name };
|
2291
|
-
|
2292
|
-
|
2279
|
+
|
2280
|
+
const func = generateFunc(scope, decl.right);
|
2281
|
+
|
2282
|
+
return [
|
2283
|
+
...number(func.index - importedFuncs.length),
|
2284
|
+
...(local != null ? [
|
2285
|
+
[ isGlobal ? Opcodes.global_set : Opcodes.local_set, local.idx ],
|
2286
|
+
[ isGlobal ? Opcodes.global_get : Opcodes.local_get, local.idx ],
|
2287
|
+
|
2288
|
+
...setType(scope, name, TYPES.function)
|
2289
|
+
] : [])
|
2290
|
+
];
|
2293
2291
|
}
|
2294
2292
|
|
2295
2293
|
const op = decl.operator.slice(0, -1) || '=';
|
@@ -2388,8 +2386,6 @@ const generateAssign = (scope, decl, _global, _name, valueUnused = false) => {
|
|
2388
2386
|
|
2389
2387
|
if (!name) return todo(scope, 'destructuring is not supported yet', true);
|
2390
2388
|
|
2391
|
-
const [ local, isGlobal ] = lookupName(scope, name);
|
2392
|
-
|
2393
2389
|
if (local === undefined) {
|
2394
2390
|
// todo: this should be a sloppy mode only thing
|
2395
2391
|
|
@@ -2538,6 +2534,7 @@ const generateUnary = (scope, decl) => {
|
|
2538
2534
|
[TYPES.string]: makeString(scope, 'string', false, '#typeof_result'),
|
2539
2535
|
[TYPES.undefined]: makeString(scope, 'undefined', false, '#typeof_result'),
|
2540
2536
|
[TYPES.function]: makeString(scope, 'function', false, '#typeof_result'),
|
2537
|
+
[TYPES.symbol]: makeString(scope, 'symbol', false, '#typeof_result'),
|
2541
2538
|
|
2542
2539
|
[TYPES.bytestring]: makeString(scope, 'string', false, '#typeof_result'),
|
2543
2540
|
|
@@ -3036,13 +3033,6 @@ const generateEmpty = (scope, decl) => {
|
|
3036
3033
|
return [];
|
3037
3034
|
};
|
3038
3035
|
|
3039
|
-
const generateAssignPat = (scope, decl) => {
|
3040
|
-
// TODO
|
3041
|
-
// if identifier declared, use that
|
3042
|
-
// else, use default (right)
|
3043
|
-
return todo(scope, 'assignment pattern (optional arg)');
|
3044
|
-
};
|
3045
|
-
|
3046
3036
|
let pages = new Map();
|
3047
3037
|
const allocPage = (scope, reason, type) => {
|
3048
3038
|
if (pages.has(reason)) return pages.get(reason).ind;
|
@@ -3455,8 +3445,11 @@ const generateFunc = (scope, decl) => {
|
|
3455
3445
|
};
|
3456
3446
|
|
3457
3447
|
if (typedInput && decl.returnType) {
|
3458
|
-
|
3459
|
-
|
3448
|
+
const { type } = extractTypeAnnotation(decl.returnType);
|
3449
|
+
if (type != null && !Prefs.indirectCalls) {
|
3450
|
+
innerScope.returnType = type;
|
3451
|
+
innerScope.returns = [ valtypeBinary ];
|
3452
|
+
}
|
3460
3453
|
}
|
3461
3454
|
|
3462
3455
|
for (let i = 0; i < params.length; i++) {
|
@@ -3498,7 +3491,7 @@ const generateFunc = (scope, decl) => {
|
|
3498
3491
|
if (name !== 'main' && wasm[wasm.length - 1]?.[0] !== Opcodes.return && countLeftover(wasm) === 0) {
|
3499
3492
|
wasm.push(
|
3500
3493
|
...number(0),
|
3501
|
-
...number(TYPES.undefined, Valtype.i32),
|
3494
|
+
...(innerScope.returnType != null ? [] : number(TYPES.undefined, Valtype.i32)),
|
3502
3495
|
[ Opcodes.return ]
|
3503
3496
|
);
|
3504
3497
|
}
|
@@ -3671,8 +3664,10 @@ const internalConstrs = {
|
|
3671
3664
|
}),
|
3672
3665
|
|
3673
3666
|
// print space
|
3674
|
-
...
|
3675
|
-
|
3667
|
+
...(i !== decl.arguments.length - 1 ? [
|
3668
|
+
...number(32),
|
3669
|
+
[ Opcodes.call, importedFuncs.printChar ]
|
3670
|
+
] : [])
|
3676
3671
|
);
|
3677
3672
|
}
|
3678
3673
|
|
@@ -3682,6 +3677,8 @@ const internalConstrs = {
|
|
3682
3677
|
[ Opcodes.call, importedFuncs.printChar ]
|
3683
3678
|
);
|
3684
3679
|
|
3680
|
+
out.push(...number(UNDEFINED));
|
3681
|
+
|
3685
3682
|
return out;
|
3686
3683
|
},
|
3687
3684
|
type: TYPES.undefined,
|
package/compiler/decompile.js
CHANGED
@@ -1,5 +1,5 @@
|
|
1
|
-
import { Blocktype, Opcodes, Valtype } from
|
2
|
-
import { read_ieee754_binary64, read_signedLEB128, read_unsignedLEB128 } from
|
1
|
+
import { Blocktype, Opcodes, Valtype } from './wasmSpec.js';
|
2
|
+
import { read_ieee754_binary64, read_signedLEB128, read_unsignedLEB128 } from './encoding.js';
|
3
3
|
|
4
4
|
const inv = (obj, keyMap = x => x) => Object.keys(obj).reduce((acc, x) => { acc[keyMap(obj[x])] = x; return acc; }, {});
|
5
5
|
const invOpcodes = inv(Opcodes);
|
@@ -119,7 +119,7 @@ export const highlightAsm = asm => asm
|
|
119
119
|
.replace(/(local|global|memory)\.[^\s]*/g, _ => `\x1B[31m${_}\x1B[0m`)
|
120
120
|
.replace(/(i(8|16|32|64)x[0-9]+|v128)(\.[^\s]*)?/g, _ => `\x1B[34m${_}\x1B[0m`)
|
121
121
|
.replace(/(i32|i64|f32|f64|drop)(\.[^\s]*)?/g, _ => `\x1B[36m${_}\x1B[0m`)
|
122
|
-
.replace(/(return_call|call|br_if|br|return|rethrow|throw)/g, _ => `\x1B[35m${_}\x1B[0m`)
|
122
|
+
.replace(/(return_call|call_indirect|call|br_if|br|return|rethrow|throw)/g, _ => `\x1B[35m${_}\x1B[0m`)
|
123
123
|
.replace(/(block|loop|if|end|else|try|catch_all|catch|delegate)/g, _ => `\x1B[95m${_}\x1B[0m`)
|
124
124
|
.replace(/unreachable/g, _ => `\x1B[91m${_}\x1B[0m`)
|
125
125
|
.replace(/ \-?[0-9\.]+/g, _ => ` \x1B[33m${_.slice(1)}\x1B[0m`)
|
package/compiler/embedding.js
CHANGED
@@ -1,5 +1,5 @@
|
|
1
|
-
import { Opcodes, Valtype } from
|
2
|
-
import { signedLEB128, ieee754_binary64 } from
|
1
|
+
import { Opcodes, Valtype } from './wasmSpec.js';
|
2
|
+
import { signedLEB128, ieee754_binary64 } from './encoding.js';
|
3
3
|
|
4
4
|
export const number = (n, valtype = valtypeBinary) => {
|
5
5
|
switch (valtype) {
|
package/compiler/encoding.js
CHANGED
@@ -7,21 +7,7 @@ export const codifyString = str => {
|
|
7
7
|
return out;
|
8
8
|
};
|
9
9
|
|
10
|
-
// export const encodeString = str => [
|
11
|
-
// str.length,
|
12
|
-
// ...codifyString(str)
|
13
|
-
// ];
|
14
10
|
export const encodeString = str => unsignedLEB128(str.length).concat(codifyString(str));
|
15
|
-
|
16
|
-
// export const encodeVector = data => [
|
17
|
-
// ...unsignedLEB128(data.length),
|
18
|
-
// ...data.flat()
|
19
|
-
// ];
|
20
|
-
// export const encodeVector = data => {
|
21
|
-
// const out = data.flat();
|
22
|
-
// out.unshift.apply(out, unsignedLEB128(data.length));
|
23
|
-
// return out;
|
24
|
-
// };
|
25
11
|
export const encodeVector = data => unsignedLEB128(data.length).concat(data.flat());
|
26
12
|
|
27
13
|
export const encodeLocal = (count, type) => [
|
package/compiler/expression.js
CHANGED