porffor 0.14.0-dcfc43df0 → 0.14.0-eca486960
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/builtins/set.ts +5 -6
- package/compiler/builtins/symbol.ts +1 -1
- package/compiler/codegen.js +154 -86
- package/compiler/generated_builtins.js +14 -14
- package/compiler/precompile.js +1 -1
- package/compiler/prefs.js +1 -1
- package/compiler/wrap.js +48 -33
- package/package.json +1 -1
package/compiler/builtins/set.ts
CHANGED
@@ -56,14 +56,13 @@ i32.store8 0 12`;
|
|
56
56
|
};
|
57
57
|
|
58
58
|
|
59
|
-
|
60
|
-
export const __Set_prototype_size = (_this: Set) => {
|
59
|
+
export const __Set_prototype_size$get = (_this: Set) => {
|
61
60
|
return Porffor.wasm.i32.load(_this, 0, 0);
|
62
61
|
};
|
63
62
|
|
64
63
|
export const __Set_prototype_values = (_this: Set) => {
|
65
64
|
// todo: this should return an iterator not array
|
66
|
-
const size: number =
|
65
|
+
const size: number = Porffor.wasm.i32.load(_this, 0, 0);
|
67
66
|
|
68
67
|
const out: any[] = __Porffor_allocate();
|
69
68
|
for (let i: number = 0; i < size; i++) {
|
@@ -79,7 +78,7 @@ export const __Set_prototype_keys = (_this: Set) => {
|
|
79
78
|
};
|
80
79
|
|
81
80
|
export const __Set_prototype_has = (_this: Set, value: any) => {
|
82
|
-
const size: number =
|
81
|
+
const size: number = Porffor.wasm.i32.load(_this, 0, 0);
|
83
82
|
|
84
83
|
for (let i: number = 0; i < size; i++) {
|
85
84
|
if (__Porffor_set_read(_this, i) === value) return true;
|
@@ -89,7 +88,7 @@ export const __Set_prototype_has = (_this: Set, value: any) => {
|
|
89
88
|
};
|
90
89
|
|
91
90
|
export const __Set_prototype_add = (_this: Set, value: any) => {
|
92
|
-
const size: number =
|
91
|
+
const size: number = Porffor.wasm.i32.load(_this, 0, 0);
|
93
92
|
|
94
93
|
// check if already in set
|
95
94
|
for (let i: number = 0; i < size; i++) {
|
@@ -107,7 +106,7 @@ export const __Set_prototype_add = (_this: Set, value: any) => {
|
|
107
106
|
};
|
108
107
|
|
109
108
|
export const __Set_prototype_delete = (_this: Set, value: any) => {
|
110
|
-
const size: number =
|
109
|
+
const size: number = Porffor.wasm.i32.load(_this, 0, 0);
|
111
110
|
|
112
111
|
// check if already in set
|
113
112
|
for (let i: number = 0; i < size; i++) {
|
@@ -19,7 +19,7 @@ export const Symbol = (description: any): Symbol => {
|
|
19
19
|
};
|
20
20
|
|
21
21
|
// todo: this should be a getter somehow not a method
|
22
|
-
export const __Symbol_prototype_description = (_this: Symbol) => {
|
22
|
+
export const __Symbol_prototype_description$get = (_this: Symbol) => {
|
23
23
|
const description: bytestring = __Porffor_symbol_descStore(false,
|
24
24
|
Porffor.wasm`local.get ${_this}` - 1);
|
25
25
|
return description;
|
package/compiler/codegen.js
CHANGED
@@ -140,6 +140,9 @@ const generate = (scope, decl, global = false, name = undefined, valueUnused = f
|
|
140
140
|
case 'ArrayExpression':
|
141
141
|
return generateArray(scope, decl, global, name);
|
142
142
|
|
143
|
+
case 'ObjectExpression':
|
144
|
+
return generateObject(scope, decl, global, name);
|
145
|
+
|
143
146
|
case 'MemberExpression':
|
144
147
|
return generateMember(scope, decl, global, name);
|
145
148
|
|
@@ -200,19 +203,11 @@ const generate = (scope, decl, global = false, name = undefined, valueUnused = f
|
|
200
203
|
|
201
204
|
__Porffor_bs: str => [
|
202
205
|
...makeString(scope, str, global, name, true),
|
203
|
-
|
204
|
-
...(name ? setType(scope, name, TYPES.bytestring) : [
|
205
|
-
...number(TYPES.bytestring, Valtype.i32),
|
206
|
-
...setLastType(scope)
|
207
|
-
])
|
206
|
+
...(name ? setType(scope, name, TYPES.bytestring) : setLastType(scope, TYPES.bytestring))
|
208
207
|
],
|
209
208
|
__Porffor_s: str => [
|
210
209
|
...makeString(scope, str, global, name, false),
|
211
|
-
|
212
|
-
...(name ? setType(scope, name, TYPES.string) : [
|
213
|
-
...number(TYPES.string, Valtype.i32),
|
214
|
-
...setLastType(scope)
|
215
|
-
])
|
210
|
+
...(name ? setType(scope, name, TYPES.string) : setLastType(scope, TYPES.string))
|
216
211
|
],
|
217
212
|
};
|
218
213
|
|
@@ -400,13 +395,11 @@ const performLogicOp = (scope, op, left, right, leftType, rightType) => {
|
|
400
395
|
[ Opcodes.if, Valtype.i32 ],
|
401
396
|
...right,
|
402
397
|
// note type
|
403
|
-
...rightType,
|
404
|
-
...setLastType(scope),
|
398
|
+
...setLastType(scope, rightType),
|
405
399
|
[ Opcodes.else ],
|
406
400
|
[ Opcodes.local_get, localTmp(scope, 'logictmpi', Valtype.i32) ],
|
407
401
|
// note type
|
408
|
-
...leftType,
|
409
|
-
...setLastType(scope),
|
402
|
+
...setLastType(scope, leftType),
|
410
403
|
[ Opcodes.end ],
|
411
404
|
Opcodes.i32_from
|
412
405
|
];
|
@@ -419,13 +412,11 @@ const performLogicOp = (scope, op, left, right, leftType, rightType) => {
|
|
419
412
|
[ Opcodes.if, valtypeBinary ],
|
420
413
|
...right,
|
421
414
|
// note type
|
422
|
-
...rightType,
|
423
|
-
...setLastType(scope),
|
415
|
+
...setLastType(scope, rightType),
|
424
416
|
[ Opcodes.else ],
|
425
417
|
[ Opcodes.local_get, localTmp(scope, 'logictmp') ],
|
426
418
|
// note type
|
427
|
-
...leftType,
|
428
|
-
...setLastType(scope),
|
419
|
+
...setLastType(scope, leftType),
|
429
420
|
[ Opcodes.end ]
|
430
421
|
];
|
431
422
|
};
|
@@ -1194,9 +1185,10 @@ const getLastType = scope => {
|
|
1194
1185
|
return [ [ Opcodes.local_get, localTmp(scope, '#last_type', Valtype.i32) ] ];
|
1195
1186
|
};
|
1196
1187
|
|
1197
|
-
const setLastType = scope =>
|
1198
|
-
|
1199
|
-
|
1188
|
+
const setLastType = (scope, type = []) => [
|
1189
|
+
...(typeof type === 'number' ? number(type, Valtype.i32) : type),
|
1190
|
+
[ Opcodes.local_set, localTmp(scope, '#last_type', Valtype.i32) ]
|
1191
|
+
];
|
1200
1192
|
|
1201
1193
|
const getNodeType = (scope, node) => {
|
1202
1194
|
const ret = (() => {
|
@@ -1352,22 +1344,27 @@ const getNodeType = (scope, node) => {
|
|
1352
1344
|
}
|
1353
1345
|
|
1354
1346
|
if (node.type === 'MemberExpression') {
|
1355
|
-
|
1356
|
-
|
1357
|
-
|
1358
|
-
|
1359
|
-
|
1360
|
-
return TYPES.undefined;
|
1361
|
-
}
|
1347
|
+
const name = node.property.name;
|
1348
|
+
|
1349
|
+
if (name === 'length') {
|
1350
|
+
if (hasFuncWithName(node.object.name)) return TYPES.number;
|
1351
|
+
if (Prefs.fastLength) return TYPES.number;
|
1362
1352
|
}
|
1363
1353
|
|
1364
|
-
// hack: if something.length, number type
|
1365
|
-
if (node.property.name === 'length') return TYPES.number;
|
1366
1354
|
|
1367
|
-
|
1368
|
-
if (
|
1369
|
-
|
1370
|
-
|
1355
|
+
const objectKnownType = knownType(scope, getNodeType(scope, node.object));
|
1356
|
+
if (objectKnownType != null) {
|
1357
|
+
if (name === 'length') {
|
1358
|
+
if ([ TYPES.string, TYPES.bytestring, TYPES.array ].includes(objectKnownType)) return TYPES.number;
|
1359
|
+
else return TYPES.undefined;
|
1360
|
+
}
|
1361
|
+
|
1362
|
+
if (node.computed) {
|
1363
|
+
if (objectKnownType === TYPES.string) return TYPES.string;
|
1364
|
+
if (objectKnownType === TYPES.bytestring) return TYPES.bytestring;
|
1365
|
+
if (objectKnownType === TYPES.array) return TYPES.number;
|
1366
|
+
}
|
1367
|
+
}
|
1371
1368
|
|
1372
1369
|
if (scope.locals['#last_type']) return getLastType(scope);
|
1373
1370
|
|
@@ -1561,16 +1558,10 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
|
|
1561
1558
|
out.splice(out.length - 1, 1);
|
1562
1559
|
|
1563
1560
|
const finalStatement = parsed.body[parsed.body.length - 1];
|
1564
|
-
out.push(
|
1565
|
-
...getNodeType(scope, finalStatement),
|
1566
|
-
...setLastType(scope)
|
1567
|
-
);
|
1561
|
+
out.push(...setLastType(scope, getNodeType(scope, finalStatement)));
|
1568
1562
|
} else if (countLeftover(out) === 0) {
|
1569
1563
|
out.push(...number(UNDEFINED));
|
1570
|
-
out.push(
|
1571
|
-
...number(TYPES.undefined, Valtype.i32),
|
1572
|
-
...setLastType(scope)
|
1573
|
-
);
|
1564
|
+
out.push(...setLastType(scope, TYPES.undefined));
|
1574
1565
|
}
|
1575
1566
|
|
1576
1567
|
// if (lastInst && lastInst[0] === Opcodes.drop) {
|
@@ -1622,8 +1613,7 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
|
|
1622
1613
|
[ Opcodes.call, idx ],
|
1623
1614
|
Opcodes.i32_from_u,
|
1624
1615
|
|
1625
|
-
...
|
1626
|
-
...setLastType(scope)
|
1616
|
+
...setLastType(scope, TYPES.boolean)
|
1627
1617
|
];
|
1628
1618
|
}
|
1629
1619
|
|
@@ -1695,9 +1685,7 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
|
|
1695
1685
|
if (protoFunc.noArgRetLength && decl.arguments.length === 0) {
|
1696
1686
|
protoBC[x] = [
|
1697
1687
|
...RTArrayUtil.getLength(getPointer),
|
1698
|
-
|
1699
|
-
...number(TYPES.number, Valtype.i32),
|
1700
|
-
...setLastType(scope)
|
1688
|
+
...setLastType(scope, TYPES.number)
|
1701
1689
|
];
|
1702
1690
|
continue;
|
1703
1691
|
}
|
@@ -1730,9 +1718,7 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
|
|
1730
1718
|
protoBC[x] = [
|
1731
1719
|
[ Opcodes.block, unusedValue && optUnused ? Blocktype.void : valtypeBinary ],
|
1732
1720
|
...protoOut,
|
1733
|
-
|
1734
|
-
...number(protoFunc.returnType ?? TYPES.number, Valtype.i32),
|
1735
|
-
...setLastType(scope),
|
1721
|
+
...setLastType(scope, protoFunc.returnType ?? TYPES.number),
|
1736
1722
|
[ Opcodes.end ]
|
1737
1723
|
];
|
1738
1724
|
}
|
@@ -1901,6 +1887,7 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
|
|
1901
1887
|
const arg = args[i];
|
1902
1888
|
out = out.concat(generate(scope, arg));
|
1903
1889
|
|
1890
|
+
// todo: this should be used instead of the too many args thing above (by removing that)
|
1904
1891
|
if (i >= paramCount) {
|
1905
1892
|
// over param count of func, drop arg
|
1906
1893
|
out.push([ Opcodes.drop ]);
|
@@ -1985,8 +1972,11 @@ const knownType = (scope, type) => {
|
|
1985
1972
|
const idx = type[0][1];
|
1986
1973
|
|
1987
1974
|
// type idx = var idx + 1
|
1988
|
-
const
|
1989
|
-
if (
|
1975
|
+
const name = Object.values(scope.locals).find(x => x.idx === idx)?.name;
|
1976
|
+
if (name) {
|
1977
|
+
const local = scope.locals[name];
|
1978
|
+
if (local.metadata?.type != null) return v.metadata.type;
|
1979
|
+
}
|
1990
1980
|
}
|
1991
1981
|
|
1992
1982
|
return null;
|
@@ -2117,6 +2107,17 @@ const typeSwitch = (scope, type, bc, returns = valtypeBinary) => {
|
|
2117
2107
|
return out;
|
2118
2108
|
};
|
2119
2109
|
|
2110
|
+
const typeIsOneOf = (type, types, valtype = Valtype.i32) => {
|
2111
|
+
const out = [];
|
2112
|
+
|
2113
|
+
for (let i = 0; i < types.length; i++) {
|
2114
|
+
out.push(...type, ...number(types[i], valtype), valtype === Valtype.f64 ? [ Opcodes.f64_eq ] : [ Opcodes.i32_eq ]);
|
2115
|
+
if (i !== 0) out.push([ Opcodes.i32_or ]);
|
2116
|
+
}
|
2117
|
+
|
2118
|
+
return out;
|
2119
|
+
};
|
2120
|
+
|
2120
2121
|
const allocVar = (scope, name, global = false, type = true) => {
|
2121
2122
|
const target = global ? globals : scope.locals;
|
2122
2123
|
|
@@ -2133,7 +2134,7 @@ const allocVar = (scope, name, global = false, type = true) => {
|
|
2133
2134
|
|
2134
2135
|
if (type) {
|
2135
2136
|
let typeIdx = global ? globalInd++ : scope.localInd++;
|
2136
|
-
target[name + '#type'] = { idx: typeIdx, type: Valtype.i32 };
|
2137
|
+
target[name + '#type'] = { idx: typeIdx, type: Valtype.i32, name };
|
2137
2138
|
}
|
2138
2139
|
|
2139
2140
|
return idx;
|
@@ -2611,21 +2612,16 @@ const generateConditional = (scope, decl) => {
|
|
2611
2612
|
out.push([ Opcodes.if, valtypeBinary ]);
|
2612
2613
|
depth.push('if');
|
2613
2614
|
|
2614
|
-
out.push(...generate(scope, decl.consequent));
|
2615
|
-
|
2616
|
-
// note type
|
2617
2615
|
out.push(
|
2618
|
-
...
|
2619
|
-
...setLastType(scope)
|
2616
|
+
...generate(scope, decl.consequent),
|
2617
|
+
...setLastType(scope, getNodeType(scope, decl.consequent))
|
2620
2618
|
);
|
2621
2619
|
|
2622
2620
|
out.push([ Opcodes.else ]);
|
2623
|
-
out.push(...generate(scope, decl.alternate));
|
2624
2621
|
|
2625
|
-
// note type
|
2626
2622
|
out.push(
|
2627
|
-
...
|
2628
|
-
...setLastType(scope)
|
2623
|
+
...generate(scope, decl.alternate),
|
2624
|
+
...setLastType(scope, getNodeType(scope, decl.alternate))
|
2629
2625
|
);
|
2630
2626
|
|
2631
2627
|
out.push([ Opcodes.end ]);
|
@@ -3225,7 +3221,21 @@ const generateArray = (scope, decl, global = false, name = '$undeclared', initEm
|
|
3225
3221
|
return makeArray(scope, decl, global, name, initEmpty, valtype)[0];
|
3226
3222
|
};
|
3227
3223
|
|
3228
|
-
|
3224
|
+
const generateObject = (scope, decl, global = false, name = '$undeclared') => {
|
3225
|
+
if (decl.properties.length > 0) return todo(scope, 'objects are not supported yet', true);
|
3226
|
+
|
3227
|
+
return [
|
3228
|
+
...number(1),
|
3229
|
+
...setLastType(scope, TYPES.object)
|
3230
|
+
];
|
3231
|
+
};
|
3232
|
+
|
3233
|
+
const withType = (scope, wasm, type) => [
|
3234
|
+
...wasm,
|
3235
|
+
...setLastType(scope, type)
|
3236
|
+
];
|
3237
|
+
|
3238
|
+
const generateMember = (scope, decl, _global, _name) => {
|
3229
3239
|
const name = decl.object.name;
|
3230
3240
|
const pointer = scope.arrays?.get(name);
|
3231
3241
|
|
@@ -3239,9 +3249,9 @@ export const generateMember = (scope, decl, _global, _name) => {
|
|
3239
3249
|
// eg: __String_prototype_toLowerCase -> toLowerCase
|
3240
3250
|
if (nameProp.startsWith('__')) nameProp = nameProp.split('_').pop();
|
3241
3251
|
|
3242
|
-
return makeString(scope, nameProp, _global, _name, true);
|
3252
|
+
return withType(scope, makeString(scope, nameProp, _global, _name, true), TYPES.bytestring);
|
3243
3253
|
} else {
|
3244
|
-
return
|
3254
|
+
return withType(scope, number(0), TYPES.undefined);
|
3245
3255
|
}
|
3246
3256
|
}
|
3247
3257
|
|
@@ -3251,7 +3261,7 @@ export const generateMember = (scope, decl, _global, _name) => {
|
|
3251
3261
|
if (func) {
|
3252
3262
|
const userFunc = funcIndex[name] && !importedFuncs[name] && !builtinFuncs[name] && !internalConstrs[name];
|
3253
3263
|
const typedParams = userFunc || builtinFuncs[name]?.typedParams;
|
3254
|
-
return number(typedParams ? func.params.length / 2 : func.params.length);
|
3264
|
+
return withType(scope, number(typedParams ? func.params.length / 2 : func.params.length), TYPES.number);
|
3255
3265
|
}
|
3256
3266
|
|
3257
3267
|
if (builtinFuncs[name + '$constructor']) {
|
@@ -3261,24 +3271,88 @@ export const generateMember = (scope, decl, _global, _name) => {
|
|
3261
3271
|
const constructorFunc = builtinFuncs[name + '$constructor'];
|
3262
3272
|
const constructorParams = constructorFunc.typedParams ? (constructorFunc.params.length / 2) : constructorFunc.params.length;
|
3263
3273
|
|
3264
|
-
return number(Math.max(regularParams, constructorParams));
|
3274
|
+
return withType(scope, number(Math.max(regularParams, constructorParams)), TYPES.number);
|
3275
|
+
}
|
3276
|
+
|
3277
|
+
if (builtinFuncs[name]) return withType(scope, number(builtinFuncs[name].typedParams ? (builtinFuncs[name].params.length / 2) : builtinFuncs[name].params.length), TYPES.number);
|
3278
|
+
if (importedFuncs[name]) return withType(scope, number(importedFuncs[name].params), TYPES.number);
|
3279
|
+
if (internalConstrs[name]) return withType(scope, number(internalConstrs[name].length ?? 0), TYPES.number);
|
3280
|
+
|
3281
|
+
if (Prefs.fastLength) {
|
3282
|
+
// presume valid length object
|
3283
|
+
return [
|
3284
|
+
...(aotPointer ? number(0, Valtype.i32) : [
|
3285
|
+
...generate(scope, decl.object),
|
3286
|
+
Opcodes.i32_to_u
|
3287
|
+
]),
|
3288
|
+
|
3289
|
+
[ Opcodes.i32_load, Math.log2(ValtypeSize.i32) - 1, ...unsignedLEB128(aotPointer ? pointer : 0) ],
|
3290
|
+
Opcodes.i32_from_u
|
3291
|
+
];
|
3265
3292
|
}
|
3266
3293
|
|
3267
|
-
|
3268
|
-
|
3269
|
-
if (
|
3294
|
+
const type = getNodeType(scope, decl.object);
|
3295
|
+
const known = knownType(scope, type);
|
3296
|
+
if (known != null) {
|
3297
|
+
if ([ TYPES.string, TYPES.bytestring, TYPES.array ].includes(known)) return [
|
3298
|
+
...(aotPointer ? number(0, Valtype.i32) : [
|
3299
|
+
...generate(scope, decl.object),
|
3300
|
+
Opcodes.i32_to_u
|
3301
|
+
]),
|
3302
|
+
|
3303
|
+
[ Opcodes.i32_load, Math.log2(ValtypeSize.i32) - 1, ...unsignedLEB128(aotPointer ? pointer : 0) ],
|
3304
|
+
Opcodes.i32_from_u
|
3305
|
+
];
|
3306
|
+
|
3307
|
+
return number(0);
|
3308
|
+
}
|
3270
3309
|
|
3271
3310
|
return [
|
3272
|
-
...(
|
3273
|
-
|
3274
|
-
|
3275
|
-
|
3311
|
+
...typeIsOneOf(getNodeType(scope, decl.object), [ TYPES.string, TYPES.bytestring, TYPES.array ]),
|
3312
|
+
[ Opcodes.if, valtypeBinary ],
|
3313
|
+
...(aotPointer ? number(0, Valtype.i32) : [
|
3314
|
+
...generate(scope, decl.object),
|
3315
|
+
Opcodes.i32_to_u
|
3316
|
+
]),
|
3276
3317
|
|
3277
|
-
|
3278
|
-
|
3318
|
+
[ Opcodes.i32_load, Math.log2(ValtypeSize.i32) - 1, ...unsignedLEB128(aotPointer ? pointer : 0) ],
|
3319
|
+
Opcodes.i32_from_u,
|
3320
|
+
|
3321
|
+
...setLastType(scope, TYPES.number),
|
3322
|
+
[ Opcodes.else ],
|
3323
|
+
...number(0),
|
3324
|
+
...setLastType(scope, TYPES.undefined),
|
3325
|
+
[ Opcodes.end ]
|
3279
3326
|
];
|
3280
3327
|
}
|
3281
3328
|
|
3329
|
+
// todo: generate this array procedurally during builtinFuncs creation
|
3330
|
+
if (['size', 'description'].includes(decl.property.name)) {
|
3331
|
+
const bc = {};
|
3332
|
+
const cands = Object.keys(builtinFuncs).filter(x => x.startsWith('__') && x.endsWith('_prototype_' + decl.property.name + '$get'));
|
3333
|
+
|
3334
|
+
if (cands.length > 0) {
|
3335
|
+
for (const x of cands) {
|
3336
|
+
const type = TYPES[x.split('_prototype_')[0].slice(2).toLowerCase()];
|
3337
|
+
if (type == null) continue;
|
3338
|
+
|
3339
|
+
bc[type] = generateCall(scope, {
|
3340
|
+
callee: {
|
3341
|
+
type: 'Identifier',
|
3342
|
+
name: x
|
3343
|
+
},
|
3344
|
+
arguments: [ decl.object ],
|
3345
|
+
_protoInternalCall: true
|
3346
|
+
});
|
3347
|
+
}
|
3348
|
+
}
|
3349
|
+
|
3350
|
+
return typeSwitch(scope, getNodeType(scope, decl.object), {
|
3351
|
+
...bc,
|
3352
|
+
default: withType(scope, number(0), TYPES.undefined)
|
3353
|
+
}, valtypeBinary);
|
3354
|
+
}
|
3355
|
+
|
3282
3356
|
const object = generate(scope, decl.object);
|
3283
3357
|
const property = generate(scope, decl.property);
|
3284
3358
|
|
@@ -3309,9 +3383,7 @@ export const generateMember = (scope, decl, _global, _name) => {
|
|
3309
3383
|
|
3310
3384
|
// read from memory
|
3311
3385
|
[ Opcodes.load, Math.log2(ValtypeSize[valtype]) - 1, ...unsignedLEB128((aotPointer ? pointer : 0) + ValtypeSize.i32) ],
|
3312
|
-
|
3313
|
-
...number(TYPES.number, Valtype.i32),
|
3314
|
-
...setLastType(scope)
|
3386
|
+
...setLastType(scope, TYPES.number)
|
3315
3387
|
],
|
3316
3388
|
|
3317
3389
|
[TYPES.string]: [
|
@@ -3341,9 +3413,7 @@ export const generateMember = (scope, decl, _global, _name) => {
|
|
3341
3413
|
|
3342
3414
|
// return new string (page)
|
3343
3415
|
...number(newPointer),
|
3344
|
-
|
3345
|
-
...number(TYPES.string, Valtype.i32),
|
3346
|
-
...setLastType(scope)
|
3416
|
+
...setLastType(scope, TYPES.string)
|
3347
3417
|
],
|
3348
3418
|
[TYPES.bytestring]: [
|
3349
3419
|
// setup new/out array
|
@@ -3369,9 +3439,7 @@ export const generateMember = (scope, decl, _global, _name) => {
|
|
3369
3439
|
|
3370
3440
|
// return new string (page)
|
3371
3441
|
...number(newPointer),
|
3372
|
-
|
3373
|
-
...number(TYPES.bytestring, Valtype.i32),
|
3374
|
-
...setLastType(scope)
|
3442
|
+
...setLastType(scope, TYPES.bytestring)
|
3375
3443
|
],
|
3376
3444
|
|
3377
3445
|
default: internalThrow(scope, 'TypeError', 'Member expression is not supported for non-string non-array yet', true)
|
@@ -3396,7 +3464,7 @@ const objectHack = node => {
|
|
3396
3464
|
if (!objectName) objectName = objectHack(node.object)?.name?.slice?.(2);
|
3397
3465
|
|
3398
3466
|
// if .name or .length, give up (hack within a hack!)
|
3399
|
-
if (['name', 'length'].includes(node.property.name)) {
|
3467
|
+
if (['name', 'length', 'size', 'description'].includes(node.property.name)) {
|
3400
3468
|
node.object = objectHack(node.object);
|
3401
3469
|
return;
|
3402
3470
|
}
|
@@ -1225,7 +1225,7 @@ export const BuiltinFuncs = function() {
|
|
1225
1225
|
locals: [127],
|
1226
1226
|
localNames: ["_this","_this#type","index","index#type","value","value#type","offset"],
|
1227
1227
|
};
|
1228
|
-
this.__Set_prototype_size = {
|
1228
|
+
this.__Set_prototype_size$get = {
|
1229
1229
|
wasm: (scope, {}) => [[32,0],[252,2],[40,0,0],[183],[65,0],[15]],
|
1230
1230
|
params: [124,127],
|
1231
1231
|
typedParams: true,
|
@@ -1235,13 +1235,13 @@ export const BuiltinFuncs = function() {
|
|
1235
1235
|
localNames: ["_this","_this#type"],
|
1236
1236
|
};
|
1237
1237
|
this.__Set_prototype_values = {
|
1238
|
-
wasm: (scope, {builtin,}) => [[32,0],[
|
1238
|
+
wasm: (scope, {builtin,}) => [[32,0],[252,2],[40,0,0],[183],[33,2],[16, builtin('__Porffor_allocate')],[33,3],[68,0,0,0,0,0,0,0,0],[33,4],[3,64],[32,4],[32,2],[99],[4,64],[32,0],[65,20],[32,4],[65,0],[16, builtin('__Porffor_set_read')],[33,7],[33,5],[32,7],[33,6],[32,3],[252,3],[34,9],[40,1,0],[34,8],[65,8],[108],[32,9],[106],[32,5],[57,2,4],[32,9],[32,8],[65,1],[106],[54,1,0],[65,0],[33,7],[32,4],[68,0,0,0,0,0,0,240,63],[160],[33,4],[12,1],[11],[11],[32,3],[65,16],[15]],
|
1239
1239
|
params: [124,127],
|
1240
1240
|
typedParams: true,
|
1241
1241
|
returns: [124,127],
|
1242
1242
|
typedReturns: true,
|
1243
|
-
locals: [124,
|
1244
|
-
localNames: ["_this","_this#type","size","
|
1243
|
+
locals: [124,124,124,124,127,127,127,127],
|
1244
|
+
localNames: ["_this","_this#type","size","out","i","val","val#type","#last_type","__proto_length_cache","__proto_pointer_cache"],
|
1245
1245
|
};
|
1246
1246
|
this.__Set_prototype_keys = {
|
1247
1247
|
wasm: (scope, {builtin,}) => [[32,0],[65,20],[16, builtin('__Set_prototype_values')],[34,2],[15]],
|
@@ -1253,31 +1253,31 @@ export const BuiltinFuncs = function() {
|
|
1253
1253
|
localNames: ["_this","_this#type","#last_type"],
|
1254
1254
|
};
|
1255
1255
|
this.__Set_prototype_has = {
|
1256
|
-
wasm: (scope, {builtin,}) => [[32,0],[
|
1256
|
+
wasm: (scope, {builtin,}) => [[32,0],[252,2],[40,0,0],[183],[33,4],[68,0,0,0,0,0,0,0,0],[33,5],[3,64],[32,5],[32,4],[99],[4,64],[2,64],[2,127,"string_only"],[32,0],[65,20],[32,5],[65,0],[16, builtin('__Porffor_set_read')],[33,6],[34,7,"string_only"],[32,2],[34,8,"string_only"],[32,6,"string_only|start"],[65,2],[70],[32,3],[65,2],[70],[113],[4,64],[32,7],[252,3],[34,9],[32,8],[252,3],[34,11],[71],[4,127],[32,9],[40,2,0],[34,10],[32,11],[40,2,0],[71],[4,64],[65,0],[12,1],[11],[65,0],[33,12],[32,10],[65,2],[108],[33,13],[3,64],[32,12],[32,9],[106],[47,0,4],[32,12],[32,11],[106],[47,0,4],[71],[4,64],[65,0],[12,2],[11],[32,12],[65,2],[106],[34,12],[32,13],[71],[13,0],[11],[65,1],[5],[65,1],[11],[12,1],[11],[32,6],[65,18],[70],[32,3],[65,18],[70],[113],[4,64],[32,7],[252,3],[34,9],[32,8],[252,3],[34,11],[71],[4,127],[32,9],[40,2,0],[34,10],[32,11],[40,2,0],[71],[4,64],[65,0],[12,1],[11],[65,0],[33,12],[32,10],[33,13],[3,64],[32,12],[32,9],[106],[45,0,4],[32,12],[32,11],[106],[45,0,4],[71],[4,64],[65,0],[12,2],[11],[32,12],[65,1],[106],[34,12],[32,13],[71],[13,0],[11],[65,1],[5],[65,1],[11],[12,1],[11,"string_only|end"],[97],[11,"string_only"],[32,6],[32,3],[70],[113],[4,64],[68,0,0,0,0,0,0,240,63],[65,1],[15],[11],[11],[32,5],[68,0,0,0,0,0,0,240,63],[160],[33,5],[12,1],[11],[11],[68,0,0,0,0,0,0,0,0],[65,1],[15]],
|
1257
1257
|
params: [124,127,124,127],
|
1258
1258
|
typedParams: true,
|
1259
1259
|
returns: [124,127],
|
1260
1260
|
typedReturns: true,
|
1261
|
-
locals: [124,127,124],
|
1262
|
-
localNames: ["_this","_this#type","value","value#type","size","#last_type","
|
1261
|
+
locals: [124,124,127,124,124,127,127,127,127,127],
|
1262
|
+
localNames: ["_this","_this#type","value","value#type","size","i","#last_type","__tmpop_left","__tmpop_right","compare_left_pointer","compare_left_length","compare_right_pointer","compare_index","compare_index_end"],
|
1263
1263
|
};
|
1264
1264
|
this.__Set_prototype_add = {
|
1265
|
-
wasm: (scope, {builtin,}) => [[32,0],[
|
1265
|
+
wasm: (scope, {builtin,}) => [[32,0],[252,2],[40,0,0],[183],[33,4],[68,0,0,0,0,0,0,0,0],[33,5],[3,64],[32,5],[32,4],[99],[4,64],[2,64],[2,127,"string_only"],[32,0],[65,20],[32,5],[65,0],[16, builtin('__Porffor_set_read')],[33,6],[34,7,"string_only"],[32,2],[34,8,"string_only"],[32,6,"string_only|start"],[65,2],[70],[32,3],[65,2],[70],[113],[4,64],[32,7],[252,3],[34,9],[32,8],[252,3],[34,11],[71],[4,127],[32,9],[40,2,0],[34,10],[32,11],[40,2,0],[71],[4,64],[65,0],[12,1],[11],[65,0],[33,12],[32,10],[65,2],[108],[33,13],[3,64],[32,12],[32,9],[106],[47,0,4],[32,12],[32,11],[106],[47,0,4],[71],[4,64],[65,0],[12,2],[11],[32,12],[65,2],[106],[34,12],[32,13],[71],[13,0],[11],[65,1],[5],[65,1],[11],[12,1],[11],[32,6],[65,18],[70],[32,3],[65,18],[70],[113],[4,64],[32,7],[252,3],[34,9],[32,8],[252,3],[34,11],[71],[4,127],[32,9],[40,2,0],[34,10],[32,11],[40,2,0],[71],[4,64],[65,0],[12,1],[11],[65,0],[33,12],[32,10],[33,13],[3,64],[32,12],[32,9],[106],[45,0,4],[32,12],[32,11],[106],[45,0,4],[71],[4,64],[65,0],[12,2],[11],[32,12],[65,1],[106],[34,12],[32,13],[71],[13,0],[11],[65,1],[5],[65,1],[11],[12,1],[11,"string_only|end"],[97],[11,"string_only"],[32,6],[32,3],[70],[113],[4,64],[32,0],[65,20],[15],[11],[11],[32,5],[68,0,0,0,0,0,0,240,63],[160],[33,5],[12,1],[11],[11],[32,0],[252,2],[32,4],[68,0,0,0,0,0,0,240,63],[160],[252,2],[54,0,0],[32,0],[65,20],[32,4],[65,0],[32,2],[32,3],[16, builtin('__Porffor_set_write')],[26],[32,0],[65,20],[15]],
|
1266
1266
|
params: [124,127,124,127],
|
1267
1267
|
typedParams: true,
|
1268
1268
|
returns: [124,127],
|
1269
1269
|
typedReturns: true,
|
1270
|
-
locals: [124,127,124],
|
1271
|
-
localNames: ["_this","_this#type","value","value#type","size","#last_type","
|
1270
|
+
locals: [124,124,127,124,124,127,127,127,127,127],
|
1271
|
+
localNames: ["_this","_this#type","value","value#type","size","i","#last_type","__tmpop_left","__tmpop_right","compare_left_pointer","compare_left_length","compare_right_pointer","compare_index","compare_index_end"],
|
1272
1272
|
};
|
1273
1273
|
this.__Set_prototype_delete = {
|
1274
|
-
wasm: (scope, {builtin,}) => [[32,0],[
|
1274
|
+
wasm: (scope, {builtin,}) => [[32,0],[252,2],[40,0,0],[183],[33,4],[68,0,0,0,0,0,0,0,0],[33,5],[3,64],[32,5],[32,4],[99],[4,64],[2,64],[2,127,"string_only"],[32,0],[65,20],[32,5],[65,0],[16, builtin('__Porffor_set_read')],[33,6],[34,7,"string_only"],[32,2],[34,8,"string_only"],[32,6,"string_only|start"],[65,2],[70],[32,3],[65,2],[70],[113],[4,64],[32,7],[252,3],[34,9],[32,8],[252,3],[34,11],[71],[4,127],[32,9],[40,2,0],[34,10],[32,11],[40,2,0],[71],[4,64],[65,0],[12,1],[11],[65,0],[33,12],[32,10],[65,2],[108],[33,13],[3,64],[32,12],[32,9],[106],[47,0,4],[32,12],[32,11],[106],[47,0,4],[71],[4,64],[65,0],[12,2],[11],[32,12],[65,2],[106],[34,12],[32,13],[71],[13,0],[11],[65,1],[5],[65,1],[11],[12,1],[11],[32,6],[65,18],[70],[32,3],[65,18],[70],[113],[4,64],[32,7],[252,3],[34,9],[32,8],[252,3],[34,11],[71],[4,127],[32,9],[40,2,0],[34,10],[32,11],[40,2,0],[71],[4,64],[65,0],[12,1],[11],[65,0],[33,12],[32,10],[33,13],[3,64],[32,12],[32,9],[106],[45,0,4],[32,12],[32,11],[106],[45,0,4],[71],[4,64],[65,0],[12,2],[11],[32,12],[65,1],[106],[34,12],[32,13],[71],[13,0],[11],[65,1],[5],[65,1],[11],[12,1],[11,"string_only|end"],[97],[11,"string_only"],[32,6],[32,3],[70],[113],[4,64],[32,0],[252,2],[32,4],[68,0,0,0,0,0,0,240,63],[161],[252,2],[54,0,0],[32,5],[252,3],[65,9],[108],[32,0],[252,3],[106],[65,4],[106],[34,14],[32,14],[65,9],[106],[32,4],[32,5],[161],[252,3],[65,1],[107],[65,9],[108],[252,10,0,0],[68,0,0,0,0,0,0,240,63],[65,1],[15],[11],[11],[32,5],[68,0,0,0,0,0,0,240,63],[160],[33,5],[12,1],[11],[11],[68,0,0,0,0,0,0,0,0],[65,1],[15]],
|
1275
1275
|
params: [124,127,124,127],
|
1276
1276
|
typedParams: true,
|
1277
1277
|
returns: [124,127],
|
1278
1278
|
typedReturns: true,
|
1279
|
-
locals: [124,127,124,127],
|
1280
|
-
localNames: ["_this","_this#type","value","value#type","size","#last_type","
|
1279
|
+
locals: [124,124,127,124,124,127,127,127,127,127,127],
|
1280
|
+
localNames: ["_this","_this#type","value","value#type","size","i","#last_type","__tmpop_left","__tmpop_right","compare_left_pointer","compare_left_length","compare_right_pointer","compare_index","compare_index_end","offset"],
|
1281
1281
|
};
|
1282
1282
|
this.__Set_prototype_clear = {
|
1283
1283
|
wasm: (scope, {}) => [[32,0],[252,2],[65,0],[54,0,0],[68,0,0,0,0,0,0,0,0],[65,3],[15]],
|
@@ -1640,7 +1640,7 @@ export const BuiltinFuncs = function() {
|
|
1640
1640
|
locals: [127],
|
1641
1641
|
localNames: ["description","description#type","#last_type"],
|
1642
1642
|
};
|
1643
|
-
this.__Symbol_prototype_description = {
|
1643
|
+
this.__Symbol_prototype_description$get = {
|
1644
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
1645
|
params: [124,127],
|
1646
1646
|
typedParams: true,
|
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-
|
21
|
+
let args = ['--bytestring', '--todo-time=compile', '--no-indirect-calls', '--no-treeshake-wasm-imports', '--no-rm-unused-types', '--scoped-page-names', '--funsafe-no-unlikely-proto-checks', '--fast-length', '--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
package/compiler/wrap.js
CHANGED
@@ -103,40 +103,12 @@ export default async (source, flags = [ 'module' ], customImports = {}, print =
|
|
103
103
|
times.push(performance.now() - t1);
|
104
104
|
if (Prefs.profileCompiler) console.log(bold(`compiled in ${times[0].toFixed(2)}ms`));
|
105
105
|
|
106
|
-
const
|
107
|
-
|
108
|
-
let instance;
|
109
|
-
try {
|
110
|
-
let wasmEngine = WebAssembly;
|
111
|
-
if (Prefs.asur) {
|
112
|
-
log.warning('wrap', 'using our !experimental! asur wasm engine instead of host to run');
|
113
|
-
wasmEngine = await import('../asur/index.js');
|
114
|
-
}
|
115
|
-
|
116
|
-
0, { instance } = await wasmEngine.instantiate(wasm, {
|
117
|
-
'': {
|
118
|
-
p: valtype === 'i64' ? i => print(Number(i).toString()) : i => print(i.toString()),
|
119
|
-
c: valtype === 'i64' ? i => print(String.fromCharCode(Number(i))) : i => print(String.fromCharCode(i)),
|
120
|
-
t: () => performance.now(),
|
121
|
-
u: () => performance.timeOrigin,
|
122
|
-
y: () => {},
|
123
|
-
z: () => {},
|
124
|
-
...customImports
|
125
|
-
}
|
126
|
-
});
|
127
|
-
} catch (e) {
|
128
|
-
// only backtrace for runner, not test262/etc
|
129
|
-
if (!process.argv[1].includes('/runner')) throw e;
|
130
|
-
|
131
|
-
const funcInd = parseInt(e.message.match(/function #([0-9]+) /)?.[1]);
|
132
|
-
const blobOffset = parseInt(e.message.split('@')?.[1]);
|
133
|
-
|
134
|
-
if (!funcInd) throw e;
|
106
|
+
const backtrace = (funcInd, blobOffset) => {
|
107
|
+
if (funcInd == null || blobOffset == null) return false;
|
135
108
|
|
136
109
|
// convert blob offset -> function wasm offset.
|
137
110
|
// this is not good code and is somewhat duplicated
|
138
111
|
// I just want it to work for debugging, I don't care about perf/yes
|
139
|
-
|
140
112
|
const func = funcs.find(x => x.index === funcInd);
|
141
113
|
const locals = Object.values(func.locals).sort((a, b) => a.idx - b.idx).slice(func.params.length).sort((a, b) => a.idx - b.idx);
|
142
114
|
|
@@ -154,7 +126,7 @@ export default async (source, flags = [ 'module' ], customImports = {}, print =
|
|
154
126
|
|
155
127
|
if (typeCount !== 0) localDecl.push(encodeLocal(typeCount, lastType));
|
156
128
|
|
157
|
-
const toFind = encodeVector(localDecl).concat(func.wasm.flat().filter(x => x != null && x <= 0xff).slice(0,
|
129
|
+
const toFind = encodeVector(localDecl).concat(func.wasm.flat().filter(x => x != null && x <= 0xff).slice(0, 60));
|
158
130
|
|
159
131
|
let i = 0;
|
160
132
|
for (; i < wasm.length; i++) {
|
@@ -169,7 +141,7 @@ export default async (source, flags = [ 'module' ], customImports = {}, print =
|
|
169
141
|
if (!mismatch) break;
|
170
142
|
}
|
171
143
|
|
172
|
-
if (i === wasm.length)
|
144
|
+
if (i === wasm.length) return false;
|
173
145
|
|
174
146
|
const offset = (blobOffset - i) + encodeVector(localDecl).length;
|
175
147
|
|
@@ -180,7 +152,7 @@ export default async (source, flags = [ 'module' ], customImports = {}, print =
|
|
180
152
|
if (cumLen === offset) break;
|
181
153
|
}
|
182
154
|
|
183
|
-
if (cumLen !== offset)
|
155
|
+
if (cumLen !== offset) return false;
|
184
156
|
|
185
157
|
i -= 1;
|
186
158
|
|
@@ -205,6 +177,38 @@ export default async (source, flags = [ 'module' ], customImports = {}, print =
|
|
205
177
|
console.log(decomp.join('\n'));
|
206
178
|
console.log('\x1B[90m...\x1B[0m\n');
|
207
179
|
|
180
|
+
return true;
|
181
|
+
};
|
182
|
+
|
183
|
+
const t2 = performance.now();
|
184
|
+
|
185
|
+
let instance;
|
186
|
+
try {
|
187
|
+
let wasmEngine = WebAssembly;
|
188
|
+
if (Prefs.asur) {
|
189
|
+
log.warning('wrap', 'using our !experimental! asur wasm engine instead of host to run');
|
190
|
+
wasmEngine = await import('../asur/index.js');
|
191
|
+
}
|
192
|
+
|
193
|
+
0, { instance } = await wasmEngine.instantiate(wasm, {
|
194
|
+
'': {
|
195
|
+
p: valtype === 'i64' ? i => print(Number(i).toString()) : i => print(i.toString()),
|
196
|
+
c: valtype === 'i64' ? i => print(String.fromCharCode(Number(i))) : i => print(String.fromCharCode(i)),
|
197
|
+
t: () => performance.now(),
|
198
|
+
u: () => performance.timeOrigin,
|
199
|
+
y: () => {},
|
200
|
+
z: () => {},
|
201
|
+
...customImports
|
202
|
+
}
|
203
|
+
});
|
204
|
+
} catch (e) {
|
205
|
+
// only backtrace for runner, not test262/etc
|
206
|
+
if (!process.argv[1].includes('/runner')) throw e;
|
207
|
+
|
208
|
+
const funcInd = parseInt(e.message.match(/function #([0-9]+) /)?.[1]);
|
209
|
+
const blobOffset = parseInt(e.message.split('@')?.[1]);
|
210
|
+
|
211
|
+
backtrace(funcInd, blobOffset);
|
208
212
|
throw e;
|
209
213
|
}
|
210
214
|
|
@@ -249,6 +253,17 @@ export default async (source, flags = [ 'module' ], customImports = {}, print =
|
|
249
253
|
throw new constructor(exception.message);
|
250
254
|
}
|
251
255
|
|
256
|
+
if (e instanceof WebAssembly.RuntimeError) {
|
257
|
+
// only backtrace for runner, not test262/etc
|
258
|
+
if (!process.argv[1].includes('/runner')) throw e;
|
259
|
+
|
260
|
+
const match = e.stack.match(/wasm-function\[([0-9]+)\]:([0-9a-z]+)/) ?? [];
|
261
|
+
const funcInd = parseInt(match[1]);
|
262
|
+
const blobOffset = parseInt(match[2]);
|
263
|
+
|
264
|
+
backtrace(funcInd, blobOffset);
|
265
|
+
}
|
266
|
+
|
252
267
|
throw e;
|
253
268
|
}
|
254
269
|
};
|
package/package.json
CHANGED