porffor 0.14.0-7bef6473d → 0.14.0-86ac87fa4
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/assemble.js +12 -1
- package/compiler/builtins/boolean.ts +1 -1
- package/compiler/builtins/symbol.ts +61 -0
- package/compiler/builtins.js +4 -2
- package/compiler/codegen.js +116 -20
- package/compiler/decompile.js +1 -1
- package/compiler/generated_builtins.js +45 -0
- package/compiler/index.js +3 -8
- package/compiler/precompile.js +1 -1
- package/compiler/prefs.js +6 -2
- package/compiler/wrap.js +26 -8
- package/package.json +1 -1
package/compiler/assemble.js
CHANGED
@@ -65,6 +65,7 @@ export default (funcs, globals, tags, pages, data, flags) => {
|
|
65
65
|
importFuncs = [...imports.values()];
|
66
66
|
|
67
67
|
// fix call indexes for non-imports
|
68
|
+
// also fix call_indirect types
|
68
69
|
const delta = importedFuncs.length - importFuncs.length;
|
69
70
|
for (const f of funcs) {
|
70
71
|
f.originalIndex = f.index;
|
@@ -74,6 +75,16 @@ export default (funcs, globals, tags, pages, data, flags) => {
|
|
74
75
|
if ((inst[0] === Opcodes.call || inst[0] === Opcodes.return_call) && inst[1] >= importedFuncs.length) {
|
75
76
|
inst[1] -= delta;
|
76
77
|
}
|
78
|
+
|
79
|
+
if (inst[0] === Opcodes.call_indirect) {
|
80
|
+
const params = [];
|
81
|
+
for (let i = 0; i < inst[1]; i++) {
|
82
|
+
params.push(valtypeBinary, Valtype.i32);
|
83
|
+
}
|
84
|
+
|
85
|
+
const returns = [ valtypeBinary, Valtype.i32 ];
|
86
|
+
inst[1] = getType(params, returns);
|
87
|
+
}
|
77
88
|
}
|
78
89
|
}
|
79
90
|
}
|
@@ -101,7 +112,7 @@ export default (funcs, globals, tags, pages, data, flags) => {
|
|
101
112
|
encodeVector([ [
|
102
113
|
0x00,
|
103
114
|
Opcodes.i32_const, 0, Opcodes.end,
|
104
|
-
encodeVector(funcs.map(x => x.index))
|
115
|
+
...encodeVector(funcs.map(x => x.index))
|
105
116
|
] ])
|
106
117
|
);
|
107
118
|
|
@@ -0,0 +1,61 @@
|
|
1
|
+
export const __Porffor_symbol_descStore = (op: boolean, value: any): any => {
|
2
|
+
const ptr: bytestring = '';
|
3
|
+
|
4
|
+
if (op) { // write
|
5
|
+
const size: number = Porffor.wasm.i32.load(ptr, 0, 0);
|
6
|
+
Porffor.wasm.i32.store(ptr, size + 1, 0, 0)
|
7
|
+
|
8
|
+
// reuse set internals to store description
|
9
|
+
__Porffor_set_write(ptr, size, value);
|
10
|
+
return size;
|
11
|
+
} else { // read
|
12
|
+
return __Porffor_set_read(ptr, value);
|
13
|
+
}
|
14
|
+
};
|
15
|
+
|
16
|
+
export const Symbol = (description: any): Symbol => {
|
17
|
+
// 1-based so always truthy as numeric value
|
18
|
+
return __Porffor_symbol_descStore(true, description) + 1;
|
19
|
+
};
|
20
|
+
|
21
|
+
// todo: this should be a getter somehow not a method
|
22
|
+
export const __Symbol_prototype_description = (_this: Symbol) => {
|
23
|
+
const description: bytestring = __Porffor_symbol_descStore(false,
|
24
|
+
Porffor.wasm`local.get ${_this}` - 1);
|
25
|
+
return description;
|
26
|
+
};
|
27
|
+
|
28
|
+
export const __Symbol_prototype_toString = (_this: Symbol) => {
|
29
|
+
let out: bytestring = '';
|
30
|
+
|
31
|
+
// Symbol(
|
32
|
+
Porffor.wasm.i32.store8(out, 83, 0, 4);
|
33
|
+
Porffor.wasm.i32.store8(out, 121, 0, 5);
|
34
|
+
Porffor.wasm.i32.store8(out, 109, 0, 6);
|
35
|
+
Porffor.wasm.i32.store8(out, 98, 0, 7);
|
36
|
+
Porffor.wasm.i32.store8(out, 111, 0, 8);
|
37
|
+
Porffor.wasm.i32.store8(out, 108, 0, 9);
|
38
|
+
Porffor.wasm.i32.store8(out, 40, 0, 10);
|
39
|
+
|
40
|
+
const description: bytestring = __Porffor_symbol_descStore(false,
|
41
|
+
Porffor.wasm`local.get ${_this}` - 1);
|
42
|
+
|
43
|
+
const descLen: i32 = description.length;
|
44
|
+
let outPtr: i32 = Porffor.wasm`local.get ${out}` + 7;
|
45
|
+
let descPtr: i32 = Porffor.wasm`local.get ${description}`;
|
46
|
+
const descPtrEnd: i32 = descPtr + descLen;
|
47
|
+
while (descPtr < descPtrEnd) {
|
48
|
+
Porffor.wasm.i32.store8(outPtr++, Porffor.wasm.i32.load8_u(descPtr++, 0, 4), 0, 4);
|
49
|
+
}
|
50
|
+
|
51
|
+
// )
|
52
|
+
Porffor.wasm.i32.store8(Porffor.wasm`local.get ${out}` + descLen, 41, 0, 11);
|
53
|
+
|
54
|
+
out.length = 8 + descLen;
|
55
|
+
|
56
|
+
return out;
|
57
|
+
};
|
58
|
+
|
59
|
+
export const __Symbol_prototype_valueOf = (_this: Symbol) => {
|
60
|
+
return _this;
|
61
|
+
};
|
package/compiler/builtins.js
CHANGED
@@ -198,7 +198,8 @@ export const BuiltinFuncs = function() {
|
|
198
198
|
returns: [ valtypeBinary ],
|
199
199
|
wasm: [
|
200
200
|
[ Opcodes.local_get, 0 ]
|
201
|
-
]
|
201
|
+
],
|
202
|
+
constr: true
|
202
203
|
};
|
203
204
|
|
204
205
|
// just return given (default 0) for (new) Object() as we somewhat supports object just not constructor
|
@@ -210,7 +211,8 @@ export const BuiltinFuncs = function() {
|
|
210
211
|
wasm: [
|
211
212
|
// [ Opcodes.local_get, 0 ]
|
212
213
|
...number(1)
|
213
|
-
]
|
214
|
+
],
|
215
|
+
constr: true
|
214
216
|
};
|
215
217
|
|
216
218
|
|
package/compiler/codegen.js
CHANGED
@@ -58,10 +58,11 @@ const generate = (scope, decl, global = false, name = undefined, valueUnused = f
|
|
58
58
|
|
59
59
|
case 'ArrowFunctionExpression':
|
60
60
|
case 'FunctionDeclaration':
|
61
|
+
case 'FunctionExpression':
|
61
62
|
const func = generateFunc(scope, decl);
|
62
63
|
|
63
64
|
if (decl.type.endsWith('Expression')) {
|
64
|
-
return number(func.index);
|
65
|
+
return number(func.index - importedFuncs.length);
|
65
66
|
}
|
66
67
|
|
67
68
|
return [];
|
@@ -139,6 +140,9 @@ const generate = (scope, decl, global = false, name = undefined, valueUnused = f
|
|
139
140
|
case 'ArrayExpression':
|
140
141
|
return generateArray(scope, decl, global, name);
|
141
142
|
|
143
|
+
case 'ObjectExpression':
|
144
|
+
return generateObject(scope, decl, global, name);
|
145
|
+
|
142
146
|
case 'MemberExpression':
|
143
147
|
return generateMember(scope, decl, global, name);
|
144
148
|
|
@@ -187,7 +191,7 @@ const generate = (scope, decl, global = false, name = undefined, valueUnused = f
|
|
187
191
|
if (!Array.isArray(inst)) inst = [ inst ];
|
188
192
|
const immediates = asm.slice(1).map(x => {
|
189
193
|
const int = parseInt(x);
|
190
|
-
if (Number.isNaN(int)) return scope.locals[x]?.idx;
|
194
|
+
if (Number.isNaN(int)) return scope.locals[x]?.idx ?? globals[x].idx;
|
191
195
|
return int;
|
192
196
|
});
|
193
197
|
|
@@ -313,10 +317,10 @@ const generateIdent = (scope, decl) => {
|
|
313
317
|
|
314
318
|
if (local?.idx === undefined) {
|
315
319
|
// no local var with name
|
316
|
-
if (Object.hasOwn(importedFuncs, name)) return number(importedFuncs[name]);
|
317
|
-
if (Object.hasOwn(funcIndex, name)) return number(funcIndex[name]);
|
318
|
-
|
319
320
|
if (Object.hasOwn(globals, name)) return [ [ Opcodes.global_get, globals[name].idx ] ];
|
321
|
+
|
322
|
+
if (Object.hasOwn(importedFuncs, name)) return number(importedFuncs[name] - importedFuncs.length);
|
323
|
+
if (Object.hasOwn(funcIndex, name)) return number(funcIndex[name] - importedFuncs.length);
|
320
324
|
}
|
321
325
|
|
322
326
|
if (local?.idx === undefined && rawName.startsWith('__')) {
|
@@ -350,9 +354,7 @@ const generateReturn = (scope, decl) => {
|
|
350
354
|
|
351
355
|
return [
|
352
356
|
...generate(scope, decl.argument),
|
353
|
-
...(scope.returnType != null ? [] :
|
354
|
-
...getNodeType(scope, decl.argument)
|
355
|
-
]),
|
357
|
+
...(scope.returnType != null ? [] : getNodeType(scope, decl.argument)),
|
356
358
|
[ Opcodes.return ]
|
357
359
|
];
|
358
360
|
};
|
@@ -1450,6 +1452,10 @@ const countLeftover = wasm => {
|
|
1450
1452
|
} else count--;
|
1451
1453
|
if (func) count += func.returns.length;
|
1452
1454
|
}
|
1455
|
+
} else if (inst[0] === Opcodes.call_indirect) {
|
1456
|
+
count--; // funcidx
|
1457
|
+
count -= inst[1] * 2; // params * 2 (typed)
|
1458
|
+
count += 2; // fixed return (value, type)
|
1453
1459
|
} else count--;
|
1454
1460
|
|
1455
1461
|
// console.log(count, decompile([ inst ]).slice(0, -1));
|
@@ -1831,7 +1837,45 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
|
|
1831
1837
|
}
|
1832
1838
|
|
1833
1839
|
if (idx === undefined) {
|
1834
|
-
if (scope.locals[name] !== undefined || globals[name] !== undefined || builtinVars[name] !== undefined)
|
1840
|
+
if (scope.locals[name] !== undefined || globals[name] !== undefined || builtinVars[name] !== undefined) {
|
1841
|
+
const [ local, global ] = lookupName(scope, name);
|
1842
|
+
if (!Prefs.indirectCalls || local == null) return internalThrow(scope, 'TypeError', `${unhackName(name)} is not a function`, true);
|
1843
|
+
|
1844
|
+
// todo: only works when:
|
1845
|
+
// 1. arg count matches arg count of function
|
1846
|
+
// 2. function uses typedParams and typedReturns
|
1847
|
+
|
1848
|
+
funcs.table = true;
|
1849
|
+
|
1850
|
+
let args = decl.arguments;
|
1851
|
+
let argWasm = [];
|
1852
|
+
|
1853
|
+
for (let i = 0; i < args.length; i++) {
|
1854
|
+
const arg = args[i];
|
1855
|
+
argWasm = argWasm.concat(generate(scope, arg));
|
1856
|
+
|
1857
|
+
if (valtypeBinary !== Valtype.i32 && (
|
1858
|
+
(builtinFuncs[name] && builtinFuncs[name].params[i * (typedParams ? 2 : 1)] === Valtype.i32) ||
|
1859
|
+
(importedFuncs[name] && name.startsWith('profile'))
|
1860
|
+
)) {
|
1861
|
+
argWasm.push(Opcodes.i32_to);
|
1862
|
+
}
|
1863
|
+
|
1864
|
+
argWasm = argWasm.concat(getNodeType(scope, arg));
|
1865
|
+
}
|
1866
|
+
|
1867
|
+
return typeSwitch(scope, getNodeType(scope, decl.callee), {
|
1868
|
+
[TYPES.function]: [
|
1869
|
+
...argWasm,
|
1870
|
+
[ global ? Opcodes.global_get : Opcodes.local_get, local.idx ],
|
1871
|
+
Opcodes.i32_to_u,
|
1872
|
+
[ Opcodes.call_indirect, args.length, 0 ],
|
1873
|
+
...setLastType(scope)
|
1874
|
+
],
|
1875
|
+
default: internalThrow(scope, 'TypeError', `${unhackName(name)} is not a function`, true)
|
1876
|
+
});
|
1877
|
+
}
|
1878
|
+
|
1835
1879
|
return internalThrow(scope, 'ReferenceError', `${unhackName(name)} is not defined`, true);
|
1836
1880
|
}
|
1837
1881
|
|
@@ -1860,11 +1904,16 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
|
|
1860
1904
|
const arg = args[i];
|
1861
1905
|
out = out.concat(generate(scope, arg));
|
1862
1906
|
|
1863
|
-
if (
|
1864
|
-
|
1907
|
+
if (i >= paramCount) {
|
1908
|
+
// over param count of func, drop arg
|
1909
|
+
out.push([ Opcodes.drop ]);
|
1910
|
+
continue;
|
1865
1911
|
}
|
1866
1912
|
|
1867
|
-
if (
|
1913
|
+
if (valtypeBinary !== Valtype.i32 && (
|
1914
|
+
(builtinFuncs[name] && builtinFuncs[name].params[i * (typedParams ? 2 : 1)] === Valtype.i32) ||
|
1915
|
+
(importedFuncs[name] && name.startsWith('profile'))
|
1916
|
+
)) {
|
1868
1917
|
out.push(Opcodes.i32_to);
|
1869
1918
|
}
|
1870
1919
|
|
@@ -1909,6 +1958,11 @@ const generateNew = (scope, decl, _global, _name) => {
|
|
1909
1958
|
}, _global, _name);
|
1910
1959
|
}
|
1911
1960
|
|
1961
|
+
if (
|
1962
|
+
(builtinFuncs[name] && !builtinFuncs[name].constr) ||
|
1963
|
+
(internalConstrs[name] && builtinFuncs[name].notConstr)
|
1964
|
+
) return internalThrow(scope, 'TypeError', `${name} is not a constructor`);
|
1965
|
+
|
1912
1966
|
if (!builtinFuncs[name]) return todo(scope, `new statement is not supported yet`); // return todo(scope, `new statement is not supported yet (new ${unhackName(name)})`);
|
1913
1967
|
|
1914
1968
|
return generateCall(scope, decl, _global, _name);
|
@@ -2174,6 +2228,22 @@ const generateVar = (scope, decl) => {
|
|
2174
2228
|
}
|
2175
2229
|
|
2176
2230
|
if (x.init) {
|
2231
|
+
// if (isFuncType(x.init.type)) {
|
2232
|
+
// // let a = function () { ... }
|
2233
|
+
// x.init.id = { name };
|
2234
|
+
|
2235
|
+
// const func = generateFunc(scope, x.init);
|
2236
|
+
|
2237
|
+
// out.push(
|
2238
|
+
// ...number(func.index - importedFuncs.length),
|
2239
|
+
// [ global ? Opcodes.global_set : Opcodes.local_set, idx ],
|
2240
|
+
|
2241
|
+
// ...setType(scope, name, TYPES.function)
|
2242
|
+
// );
|
2243
|
+
|
2244
|
+
// continue;
|
2245
|
+
// }
|
2246
|
+
|
2177
2247
|
const generated = generate(scope, x.init, global, name);
|
2178
2248
|
if (scope.arrays?.get(name) != null) {
|
2179
2249
|
// hack to set local as pointer before
|
@@ -2185,6 +2255,7 @@ const generateVar = (scope, decl) => {
|
|
2185
2255
|
out = out.concat(generated);
|
2186
2256
|
out.push([ global ? Opcodes.global_set : Opcodes.local_set, idx ]);
|
2187
2257
|
}
|
2258
|
+
|
2188
2259
|
out.push(...setType(scope, name, getNodeType(scope, x.init)));
|
2189
2260
|
}
|
2190
2261
|
|
@@ -2198,6 +2269,7 @@ const generateVar = (scope, decl) => {
|
|
2198
2269
|
// todo: optimize this func for valueUnused
|
2199
2270
|
const generateAssign = (scope, decl, _global, _name, valueUnused = false) => {
|
2200
2271
|
const { type, name } = decl.left;
|
2272
|
+
const [ local, isGlobal ] = lookupName(scope, name);
|
2201
2273
|
|
2202
2274
|
if (type === 'ObjectPattern') {
|
2203
2275
|
// hack: ignore object parts of `var a = {} = 2`
|
@@ -2207,8 +2279,18 @@ const generateAssign = (scope, decl, _global, _name, valueUnused = false) => {
|
|
2207
2279
|
if (isFuncType(decl.right.type)) {
|
2208
2280
|
// hack for a = function () { ... }
|
2209
2281
|
decl.right.id = { name };
|
2210
|
-
|
2211
|
-
|
2282
|
+
|
2283
|
+
const func = generateFunc(scope, decl.right);
|
2284
|
+
|
2285
|
+
return [
|
2286
|
+
...number(func.index - importedFuncs.length),
|
2287
|
+
...(local != null ? [
|
2288
|
+
[ isGlobal ? Opcodes.global_set : Opcodes.local_set, local.idx ],
|
2289
|
+
[ isGlobal ? Opcodes.global_get : Opcodes.local_get, local.idx ],
|
2290
|
+
|
2291
|
+
...setType(scope, name, TYPES.function)
|
2292
|
+
] : [])
|
2293
|
+
];
|
2212
2294
|
}
|
2213
2295
|
|
2214
2296
|
const op = decl.operator.slice(0, -1) || '=';
|
@@ -2307,8 +2389,6 @@ const generateAssign = (scope, decl, _global, _name, valueUnused = false) => {
|
|
2307
2389
|
|
2308
2390
|
if (!name) return todo(scope, 'destructuring is not supported yet', true);
|
2309
2391
|
|
2310
|
-
const [ local, isGlobal ] = lookupName(scope, name);
|
2311
|
-
|
2312
2392
|
if (local === undefined) {
|
2313
2393
|
// todo: this should be a sloppy mode only thing
|
2314
2394
|
|
@@ -2457,6 +2537,7 @@ const generateUnary = (scope, decl) => {
|
|
2457
2537
|
[TYPES.string]: makeString(scope, 'string', false, '#typeof_result'),
|
2458
2538
|
[TYPES.undefined]: makeString(scope, 'undefined', false, '#typeof_result'),
|
2459
2539
|
[TYPES.function]: makeString(scope, 'function', false, '#typeof_result'),
|
2540
|
+
[TYPES.symbol]: makeString(scope, 'symbol', false, '#typeof_result'),
|
2460
2541
|
|
2461
2542
|
[TYPES.bytestring]: makeString(scope, 'string', false, '#typeof_result'),
|
2462
2543
|
|
@@ -3147,7 +3228,18 @@ const generateArray = (scope, decl, global = false, name = '$undeclared', initEm
|
|
3147
3228
|
return makeArray(scope, decl, global, name, initEmpty, valtype)[0];
|
3148
3229
|
};
|
3149
3230
|
|
3150
|
-
|
3231
|
+
const generateObject = (scope, decl, global = false, name = '$undeclared') => {
|
3232
|
+
if (decl.properties.length > 0) return todo(scope, 'objects are not supported yet', true);
|
3233
|
+
|
3234
|
+
return [
|
3235
|
+
...number(1),
|
3236
|
+
|
3237
|
+
...number(TYPES.object, Valtype.i32),
|
3238
|
+
...setLastType(scope)
|
3239
|
+
];
|
3240
|
+
};
|
3241
|
+
|
3242
|
+
const generateMember = (scope, decl, _global, _name) => {
|
3151
3243
|
const name = decl.object.name;
|
3152
3244
|
const pointer = scope.arrays?.get(name);
|
3153
3245
|
|
@@ -3368,7 +3460,7 @@ const generateFunc = (scope, decl) => {
|
|
3368
3460
|
|
3369
3461
|
if (typedInput && decl.returnType) {
|
3370
3462
|
const { type } = extractTypeAnnotation(decl.returnType);
|
3371
|
-
if (type != null) {
|
3463
|
+
if (type != null && !Prefs.indirectCalls) {
|
3372
3464
|
innerScope.returnType = type;
|
3373
3465
|
innerScope.returns = [ valtypeBinary ];
|
3374
3466
|
}
|
@@ -3586,8 +3678,10 @@ const internalConstrs = {
|
|
3586
3678
|
}),
|
3587
3679
|
|
3588
3680
|
// print space
|
3589
|
-
...
|
3590
|
-
|
3681
|
+
...(i !== decl.arguments.length - 1 ? [
|
3682
|
+
...number(32),
|
3683
|
+
[ Opcodes.call, importedFuncs.printChar ]
|
3684
|
+
] : [])
|
3591
3685
|
);
|
3592
3686
|
}
|
3593
3687
|
|
@@ -3597,6 +3691,8 @@ const internalConstrs = {
|
|
3597
3691
|
[ Opcodes.call, importedFuncs.printChar ]
|
3598
3692
|
);
|
3599
3693
|
|
3694
|
+
out.push(...number(UNDEFINED));
|
3695
|
+
|
3600
3696
|
return out;
|
3601
3697
|
},
|
3602
3698
|
type: TYPES.undefined,
|
package/compiler/decompile.js
CHANGED
@@ -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`)
|
@@ -1622,4 +1622,49 @@ export const BuiltinFuncs = function() {
|
|
1622
1622
|
locals: [],
|
1623
1623
|
localNames: ["_this","_this#type"],
|
1624
1624
|
};
|
1625
|
+
this.__Porffor_symbol_descStore = {
|
1626
|
+
wasm: (scope, {allocPage,builtin,}) => [...number(allocPage(scope, 'bytestring: __Porffor_symbol_descStore/ptr', 'i8') * pageSize, 124),[33,4],[32,0],[252,3],[4,64],[32,4],[252,2],[40,0,0],[183],[33,5],[32,4],[252,2],[32,5],[68,0,0,0,0,0,0,240,63],[160],[252,2],[54,0,0],[32,4],[65,18],[32,5],[65,0],[32,2],[32,3],[16, builtin('__Porffor_set_write')],[26],[32,5],[65,0],[15],[5],[32,4],[65,18],[32,2],[32,3],[16, builtin('__Porffor_set_read')],[34,6],[15],[11],[68,0,0,0,0,0,0,0,0],[65,3],[15]],
|
1627
|
+
params: [124,127,124,127],
|
1628
|
+
typedParams: true,
|
1629
|
+
returns: [124,127],
|
1630
|
+
typedReturns: true,
|
1631
|
+
locals: [124,124,127],
|
1632
|
+
localNames: ["op","op#type","value","value#type","ptr","size","#last_type"],
|
1633
|
+
};
|
1634
|
+
this.Symbol = {
|
1635
|
+
wasm: (scope, {builtin,}) => [[68,0,0,0,0,0,0,240,63],[65,1],[32,0],[32,1],[16, builtin('__Porffor_symbol_descStore')],[33,2],[68,0,0,0,0,0,0,240,63],[160],[15]],
|
1636
|
+
params: [124,127],
|
1637
|
+
typedParams: true,
|
1638
|
+
returns: [124],
|
1639
|
+
returnType: 6,
|
1640
|
+
locals: [127],
|
1641
|
+
localNames: ["description","description#type","#last_type"],
|
1642
|
+
};
|
1643
|
+
this.__Symbol_prototype_description = {
|
1644
|
+
wasm: (scope, {builtin,}) => [[68,0,0,0,0,0,0,0,0],[65,1],[32,0],[68,0,0,0,0,0,0,240,63],[161],[65,0],[16, builtin('__Porffor_symbol_descStore')],[33,3],[34,2],[65,18],[15]],
|
1645
|
+
params: [124,127],
|
1646
|
+
typedParams: true,
|
1647
|
+
returns: [124,127],
|
1648
|
+
typedReturns: true,
|
1649
|
+
locals: [124,127],
|
1650
|
+
localNames: ["_this","_this#type","description","#last_type"],
|
1651
|
+
};
|
1652
|
+
this.__Symbol_prototype_toString = {
|
1653
|
+
wasm: (scope, {allocPage,builtin,}) => [...number(allocPage(scope, 'bytestring: __Symbol_prototype_toString/out', 'i8') * pageSize, 124),[34,2],[252,2],[65,211,0],[58,0,4],[32,2],[252,2],[65,249,0],[58,0,5],[32,2],[252,2],[65,237,0],[58,0,6],[32,2],[252,2],[65,226,0],[58,0,7],[32,2],[252,2],[65,239,0],[58,0,8],[32,2],[252,2],[65,236,0],[58,0,9],[32,2],[252,2],[65,40],[58,0,10],[68,0,0,0,0,0,0,0,0],[65,1],[32,0],[68,0,0,0,0,0,0,240,63],[161],[65,0],[16, builtin('__Porffor_symbol_descStore')],[33,4],[34,3],[252,3],[40,1,0],[184],[33,5],[32,2],[68,0,0,0,0,0,0,28,64],[160],[33,6],[32,3],[34,7],[32,5],[160],[33,8],[3,64],[32,7],[32,8],[99],[4,64],[32,6],[32,6],[68,0,0,0,0,0,0,240,63],[160],[33,6],[252,2],[32,7],[32,7],[68,0,0,0,0,0,0,240,63],[160],[33,7],[252,2],[45,0,4],[58,0,4],[12,1],[11],[11],[32,2],[32,5],[160],[252,2],[65,41],[58,0,11],[32,2],[252,3],[68,0,0,0,0,0,0,32,64],[32,5],[160],[34,9],[252,3],[54,1,0],[32,2],[65,18],[15]],
|
1654
|
+
params: [124,127],
|
1655
|
+
typedParams: true,
|
1656
|
+
returns: [124,127],
|
1657
|
+
typedReturns: true,
|
1658
|
+
locals: [124,124,127,124,124,124,124,124],
|
1659
|
+
localNames: ["_this","_this#type","out","description","#last_type","descLen","outPtr","descPtr","descPtrEnd","__length_setter_tmp"],
|
1660
|
+
};
|
1661
|
+
this.__Symbol_prototype_valueOf = {
|
1662
|
+
wasm: (scope, {}) => [[32,0],[65,6],[15]],
|
1663
|
+
params: [124,127],
|
1664
|
+
typedParams: true,
|
1665
|
+
returns: [124,127],
|
1666
|
+
typedReturns: true,
|
1667
|
+
locals: [],
|
1668
|
+
localNames: ["_this","_this#type"],
|
1669
|
+
};
|
1625
1670
|
};
|
package/compiler/index.js
CHANGED
@@ -12,14 +12,7 @@ globalThis.decompile = decompile;
|
|
12
12
|
const logFuncs = (funcs, globals, exceptions) => {
|
13
13
|
console.log('\n' + underline(bold('funcs')));
|
14
14
|
|
15
|
-
const startIndex = funcs.sort((a, b) => a.index - b.index)[0].index;
|
16
15
|
for (const f of funcs) {
|
17
|
-
console.log(`${underline(f.name)} (${f.index - startIndex})`);
|
18
|
-
|
19
|
-
console.log(`params: ${f.params.map((_, i) => Object.keys(f.locals)[Object.values(f.locals).indexOf(Object.values(f.locals).find(x => x.idx === i))]).join(', ')}`);
|
20
|
-
console.log(`returns: ${f.returns.length > 0 ? true : false}`);
|
21
|
-
console.log(`locals: ${Object.keys(f.locals).sort((a, b) => f.locals[a].idx - f.locals[b].idx).map(x => `${x} (${f.locals[x].idx})`).join(', ')}`);
|
22
|
-
console.log();
|
23
16
|
console.log(decompile(f.wasm, f.name, f.index, f.locals, f.params, f.returns, funcs, globals, exceptions));
|
24
17
|
}
|
25
18
|
|
@@ -44,12 +37,14 @@ export default (code, flags) => {
|
|
44
37
|
opt(funcs, globals, pages, tags, exceptions);
|
45
38
|
if (Prefs.profileCompiler) console.log(`3. optimized in ${(performance.now() - t2).toFixed(2)}ms`);
|
46
39
|
|
47
|
-
if (Prefs.optFuncs) logFuncs(funcs, globals, exceptions);
|
40
|
+
// if (Prefs.optFuncs) logFuncs(funcs, globals, exceptions);
|
48
41
|
|
49
42
|
const t3 = performance.now();
|
50
43
|
const wasm = assemble(funcs, globals, tags, pages, data, flags);
|
51
44
|
if (Prefs.profileCompiler) console.log(`4. assembled in ${(performance.now() - t3).toFixed(2)}ms`);
|
52
45
|
|
46
|
+
if (Prefs.optFuncs) logFuncs(funcs, globals, exceptions);
|
47
|
+
|
53
48
|
if (Prefs.allocLog) {
|
54
49
|
const wasmPages = Math.ceil((pages.size * pageSize) / 65536);
|
55
50
|
const bytes = wasmPages * 65536;
|
package/compiler/precompile.js
CHANGED
@@ -18,7 +18,7 @@ const compile = async (file, [ _funcs, _globals ]) => {
|
|
18
18
|
first = source.slice(0, source.indexOf('\n'));
|
19
19
|
}
|
20
20
|
|
21
|
-
let args = ['--bytestring', '--todo-time=compile', '--no-aot-pointer-opt', '--no-treeshake-wasm-imports', '--no-rm-unused-types', '--scoped-page-names', '--funsafe-no-unlikely-proto-checks', '--parse-types', '--opt-types'];
|
21
|
+
let args = ['--bytestring', '--todo-time=compile', '--no-aot-pointer-opt', '--no-indirect-calls', '--no-treeshake-wasm-imports', '--no-rm-unused-types', '--scoped-page-names', '--funsafe-no-unlikely-proto-checks', '--parse-types', '--opt-types'];
|
22
22
|
if (first.startsWith('// @porf')) {
|
23
23
|
args = args.concat(first.slice('// @porf '.length).split(' '));
|
24
24
|
}
|
package/compiler/prefs.js
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
const onByDefault = [ 'bytestring', 'aotPointerOpt', 'treeshakeWasmImports', 'alwaysMemory' ];
|
1
|
+
const onByDefault = [ 'bytestring', 'aotPointerOpt', 'treeshakeWasmImports', 'alwaysMemory', 'indirectCalls' ];
|
2
2
|
|
3
3
|
let cache = {};
|
4
4
|
const obj = new Proxy({}, {
|
@@ -6,7 +6,7 @@ const obj = new Proxy({}, {
|
|
6
6
|
// intentionally misses with undefined values cached
|
7
7
|
if (cache[p]) return cache[p];
|
8
8
|
|
9
|
-
|
9
|
+
const ret = (() => {
|
10
10
|
// fooBar -> foo-bar
|
11
11
|
const name = p[0] === '_' ? p : p.replace(/[A-Z]/g, c => `-${c.toLowerCase()}`);
|
12
12
|
const prefix = name.length === 1 ? '-' : '--';
|
@@ -19,6 +19,10 @@ const obj = new Proxy({}, {
|
|
19
19
|
if (onByDefault.includes(p)) return true;
|
20
20
|
return undefined;
|
21
21
|
})();
|
22
|
+
|
23
|
+
// do not cache in web demo as args are changed live
|
24
|
+
if (!globalThis.document) cache[p] = ret;
|
25
|
+
return ret;
|
22
26
|
}
|
23
27
|
});
|
24
28
|
|
package/compiler/wrap.js
CHANGED
@@ -1,22 +1,27 @@
|
|
1
|
+
import { encodeVector, encodeLocal } from './encoding.js';
|
2
|
+
import { importedFuncs } from './builtins.js';
|
1
3
|
import compile from './index.js';
|
2
4
|
import decompile from './decompile.js';
|
3
|
-
import { encodeVector, encodeLocal } from './encoding.js';
|
4
5
|
import { TYPES } from './types.js';
|
5
6
|
import { log } from './log.js';
|
6
7
|
import Prefs from './prefs.js';
|
7
8
|
|
8
9
|
const bold = x => `\u001b[1m${x}\u001b[0m`;
|
9
10
|
|
10
|
-
const porfToJSValue = (memory, funcs, value, type) => {
|
11
|
+
const porfToJSValue = ({ memory, funcs, pages }, value, type) => {
|
11
12
|
switch (type) {
|
12
13
|
case TYPES.boolean: return Boolean(value);
|
13
14
|
case TYPES.undefined: return undefined;
|
14
15
|
case TYPES.object: return value === 0 ? null : {};
|
15
16
|
|
16
17
|
case TYPES.function: {
|
17
|
-
|
18
|
-
|
19
|
-
|
18
|
+
let func;
|
19
|
+
if (value < 0) {
|
20
|
+
func = importedFuncs[value + importedFuncs.length];
|
21
|
+
} else {
|
22
|
+
func = funcs.find(x => ((x.originalIndex ?? x.index) - importedFuncs.length) === value);
|
23
|
+
}
|
24
|
+
|
20
25
|
if (!func) return function () {};
|
21
26
|
|
22
27
|
// make fake empty func for repl/etc
|
@@ -61,12 +66,24 @@ const porfToJSValue = (memory, funcs, value, type) => {
|
|
61
66
|
// console.log(' memory:', Array.from(new Uint8Array(memory.buffer, offset, 9)).map(x => x.toString(16).padStart(2, '0')).join(' '));
|
62
67
|
// console.log(' read:', { value: v, type: t }, '\n');
|
63
68
|
|
64
|
-
out.add(porfToJSValue(memory, funcs, v, t));
|
69
|
+
out.add(porfToJSValue({ memory, funcs, pages }, v, t));
|
65
70
|
}
|
66
71
|
|
67
72
|
return out;
|
68
73
|
}
|
69
74
|
|
75
|
+
case TYPES.symbol: {
|
76
|
+
const descStore = pages.get('bytestring: __Porffor_symbol_descStore/ptr').ind * pageSize;
|
77
|
+
const offset = descStore + 4 + ((value - 1) * 9);
|
78
|
+
|
79
|
+
const v = (new Float64Array(memory.buffer.slice(offset, offset + 8), 0, 1))[0];
|
80
|
+
const t = (new Uint8Array(memory.buffer, offset + 8, 1))[0];
|
81
|
+
|
82
|
+
const desc = porfToJSValue({ memory, funcs, pages }, v, t);
|
83
|
+
|
84
|
+
return Symbol(desc);
|
85
|
+
}
|
86
|
+
|
70
87
|
default: return value;
|
71
88
|
}
|
72
89
|
};
|
@@ -213,10 +230,11 @@ export default async (source, flags = [ 'module' ], customImports = {}, print =
|
|
213
230
|
exports[func.name] = function() {
|
214
231
|
try {
|
215
232
|
const ret = exp.apply(this, arguments);
|
216
|
-
|
217
233
|
if (ret == null) return undefined;
|
218
234
|
|
219
|
-
|
235
|
+
if (Prefs.rawValue) return { value: ret[0], type: ret[1] };
|
236
|
+
|
237
|
+
return porfToJSValue({ memory, funcs, pages }, ret[0], ret[1]);
|
220
238
|
} catch (e) {
|
221
239
|
if (e.is && e.is(exceptTag)) {
|
222
240
|
const exceptId = e.getArg(exceptTag, 0);
|
package/package.json
CHANGED