porffor 0.2.0-a6c01f5 → 0.2.0-ae8cbb8
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/CONTRIBUTING.md +256 -0
- package/README.md +17 -30
- package/asur/index.js +1 -1
- package/compiler/assemble.js +1 -1
- package/compiler/builtins/annexb_string.js +2 -2
- package/compiler/builtins/annexb_string.ts +5 -6
- package/compiler/builtins/array.ts +10 -10
- package/compiler/builtins/base64.ts +4 -79
- package/compiler/builtins/boolean.ts +6 -0
- package/compiler/builtins/crypto.ts +1 -1
- package/compiler/builtins/date.ts +799 -99
- package/compiler/builtins/escape.ts +2 -4
- package/compiler/builtins/int.ts +3 -3
- package/compiler/builtins/number.ts +9 -2
- package/compiler/builtins/porffor.d.ts +21 -4
- package/compiler/builtins/string.ts +37 -22
- package/compiler/builtins/tostring.ts +4 -4
- package/compiler/builtins.js +4 -25
- package/compiler/codegen.js +138 -88
- package/compiler/decompile.js +0 -1
- package/compiler/generated_builtins.js +426 -171
- package/compiler/parse.js +4 -2
- package/compiler/precompile.js +7 -2
- package/compiler/prefs.js +6 -5
- package/compiler/prototype.js +14 -14
- package/compiler/types.js +1 -1
- package/compiler/wrap.js +3 -3
- package/package.json +1 -1
- package/rhemyn/compile.js +42 -25
- package/rhemyn/parse.js +4 -5
- package/runner/index.js +22 -6
- package/runner/repl.js +2 -2
- package/runner/sizes.js +1 -1
- package/fib.js +0 -7
package/compiler/codegen.js
CHANGED
@@ -59,6 +59,10 @@ const todo = (scope, msg, expectsValue = undefined) => {
|
|
59
59
|
};
|
60
60
|
|
61
61
|
const isFuncType = type => type === 'FunctionDeclaration' || type === 'FunctionExpression' || type === 'ArrowFunctionExpression';
|
62
|
+
const hasFuncWithName = name => {
|
63
|
+
const func = funcs.find(x => x.name === name);
|
64
|
+
return !!(func || builtinFuncs[name] || importedFuncs[name] || internalConstrs[name])
|
65
|
+
};
|
62
66
|
const generate = (scope, decl, global = false, name = undefined, valueUnused = false) => {
|
63
67
|
switch (decl.type) {
|
64
68
|
case 'BinaryExpression':
|
@@ -201,7 +205,7 @@ const generate = (scope, decl, global = false, name = undefined, valueUnused = f
|
|
201
205
|
}
|
202
206
|
|
203
207
|
let inst = Opcodes[asm[0].replace('.', '_')];
|
204
|
-
if (
|
208
|
+
if (inst == null) throw new Error(`inline asm: inst ${asm[0]} not found`);
|
205
209
|
|
206
210
|
if (!Array.isArray(inst)) inst = [ inst ];
|
207
211
|
const immediates = asm.slice(1).map(x => {
|
@@ -219,8 +223,8 @@ const generate = (scope, decl, global = false, name = undefined, valueUnused = f
|
|
219
223
|
__Porffor_bs: str => [
|
220
224
|
...makeString(scope, str, global, name, true),
|
221
225
|
|
222
|
-
...(name ? setType(scope, name, TYPES.
|
223
|
-
...number(TYPES.
|
226
|
+
...(name ? setType(scope, name, TYPES.bytestring) : [
|
227
|
+
...number(TYPES.bytestring, Valtype.i32),
|
224
228
|
...setLastType(scope)
|
225
229
|
])
|
226
230
|
],
|
@@ -460,7 +464,7 @@ const concatStrings = (scope, left, right, global, name, assign = false, bytestr
|
|
460
464
|
const rightLength = localTmp(scope, 'concat_right_length', Valtype.i32);
|
461
465
|
const leftLength = localTmp(scope, 'concat_left_length', Valtype.i32);
|
462
466
|
|
463
|
-
if (assign) {
|
467
|
+
if (assign && Prefs.aotPointerOpt) {
|
464
468
|
const pointer = scope.arrays?.get(name ?? '$undeclared');
|
465
469
|
|
466
470
|
return [
|
@@ -723,7 +727,7 @@ const truthy = (scope, wasm, type, intIn = false, intOut = false) => {
|
|
723
727
|
|
724
728
|
...typeSwitch(scope, type, {
|
725
729
|
// [TYPES.number]: def,
|
726
|
-
[TYPES.
|
730
|
+
[TYPES.array]: [
|
727
731
|
// arrays are always truthy
|
728
732
|
...number(1, intOut ? Valtype.i32 : valtypeBinary)
|
729
733
|
],
|
@@ -739,7 +743,7 @@ const truthy = (scope, wasm, type, intIn = false, intOut = false) => {
|
|
739
743
|
[ Opcodes.i32_eqz ], */
|
740
744
|
...(intOut ? [] : [ Opcodes.i32_from_u ])
|
741
745
|
],
|
742
|
-
[TYPES.
|
746
|
+
[TYPES.bytestring]: [ // duplicate of string
|
743
747
|
...(!useTmp ? [] : [ [ Opcodes.local_get, tmp ] ]),
|
744
748
|
...(intIn ? [] : [ Opcodes.i32_to_u ]),
|
745
749
|
|
@@ -762,7 +766,7 @@ const falsy = (scope, wasm, type, intIn = false, intOut = false) => {
|
|
762
766
|
...(!useTmp ? [] : [ [ Opcodes.local_set, tmp ] ]),
|
763
767
|
|
764
768
|
...typeSwitch(scope, type, {
|
765
|
-
[TYPES.
|
769
|
+
[TYPES.array]: [
|
766
770
|
// arrays are always truthy
|
767
771
|
...number(0, intOut ? Valtype.i32 : valtypeBinary)
|
768
772
|
],
|
@@ -777,7 +781,7 @@ const falsy = (scope, wasm, type, intIn = false, intOut = false) => {
|
|
777
781
|
[ Opcodes.i32_eqz ],
|
778
782
|
...(intOut ? [] : [ Opcodes.i32_from_u ])
|
779
783
|
],
|
780
|
-
[TYPES.
|
784
|
+
[TYPES.bytestring]: [ // duplicate of string
|
781
785
|
...(!useTmp ? [] : [ [ Opcodes.local_get, tmp ] ]),
|
782
786
|
...(intIn ? [] : [ Opcodes.i32_to_u ]),
|
783
787
|
|
@@ -922,7 +926,7 @@ const performOp = (scope, op, left, right, leftType, rightType, _global = false,
|
|
922
926
|
}
|
923
927
|
}
|
924
928
|
|
925
|
-
if (knownLeft === TYPES.
|
929
|
+
if (knownLeft === TYPES.bytestring || knownRight === TYPES.bytestring) {
|
926
930
|
if (op === '+') {
|
927
931
|
// todo: this should be dynamic too but for now only static
|
928
932
|
// string concat (a + b)
|
@@ -1041,12 +1045,12 @@ const performOp = (scope, op, left, right, leftType, rightType, _global = false,
|
|
1041
1045
|
|
1042
1046
|
// if left is bytestring
|
1043
1047
|
...leftType,
|
1044
|
-
...number(TYPES.
|
1048
|
+
...number(TYPES.bytestring, Valtype.i32),
|
1045
1049
|
[ Opcodes.i32_eq ],
|
1046
1050
|
|
1047
1051
|
// if right is bytestring
|
1048
1052
|
...rightType,
|
1049
|
-
...number(TYPES.
|
1053
|
+
...number(TYPES.bytestring, Valtype.i32),
|
1050
1054
|
[ Opcodes.i32_eq ],
|
1051
1055
|
|
1052
1056
|
// if both are true
|
@@ -1177,7 +1181,6 @@ const generateLogicExp = (scope, decl) => {
|
|
1177
1181
|
// js type: 4 bits
|
1178
1182
|
// internal type: ? bits
|
1179
1183
|
// pointer: 32 bits
|
1180
|
-
|
1181
1184
|
// generic
|
1182
1185
|
// 1 23 4 5
|
1183
1186
|
// 0 11111111111 11TTTTIIII??????????PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP
|
@@ -1188,7 +1191,7 @@ const generateLogicExp = (scope, decl) => {
|
|
1188
1191
|
// 5: pointer
|
1189
1192
|
|
1190
1193
|
const isExistingProtoFunc = name => {
|
1191
|
-
if (name.startsWith('__Array_prototype')) return !!prototypeFuncs[TYPES.
|
1194
|
+
if (name.startsWith('__Array_prototype')) return !!prototypeFuncs[TYPES.array][name.slice(18)];
|
1192
1195
|
if (name.startsWith('__String_prototype_')) return !!prototypeFuncs[TYPES.string][name.slice(19)];
|
1193
1196
|
|
1194
1197
|
return false;
|
@@ -1247,9 +1250,9 @@ const setLastType = scope => {
|
|
1247
1250
|
const getNodeType = (scope, node) => {
|
1248
1251
|
const inner = () => {
|
1249
1252
|
if (node.type === 'Literal') {
|
1250
|
-
if (node.regex) return TYPES.
|
1253
|
+
if (node.regex) return TYPES.regexp;
|
1251
1254
|
|
1252
|
-
if (typeof node.value === 'string' && byteStringable(node.value)) return TYPES.
|
1255
|
+
if (typeof node.value === 'string' && byteStringable(node.value)) return TYPES.bytestring;
|
1253
1256
|
|
1254
1257
|
return TYPES[typeof node.value];
|
1255
1258
|
}
|
@@ -1303,7 +1306,7 @@ const getNodeType = (scope, node) => {
|
|
1303
1306
|
const spl = name.slice(2).split('_');
|
1304
1307
|
|
1305
1308
|
const func = spl[spl.length - 1];
|
1306
|
-
const protoFuncs = Object.keys(prototypeFuncs).filter(x => x != TYPES.
|
1309
|
+
const protoFuncs = Object.keys(prototypeFuncs).filter(x => x != TYPES.bytestring && prototypeFuncs[x][func] != null);
|
1307
1310
|
if (protoFuncs.length === 1) return protoFuncs[0].returnType ?? TYPES.number;
|
1308
1311
|
}
|
1309
1312
|
|
@@ -1355,7 +1358,7 @@ const getNodeType = (scope, node) => {
|
|
1355
1358
|
}
|
1356
1359
|
|
1357
1360
|
if (node.type === 'ArrayExpression') {
|
1358
|
-
return TYPES.
|
1361
|
+
return TYPES.array;
|
1359
1362
|
}
|
1360
1363
|
|
1361
1364
|
if (node.type === 'BinaryExpression') {
|
@@ -1367,7 +1370,7 @@ const getNodeType = (scope, node) => {
|
|
1367
1370
|
|
1368
1371
|
// todo: this should be dynamic but for now only static
|
1369
1372
|
if (knownLeft === TYPES.string || knownRight === TYPES.string) return TYPES.string;
|
1370
|
-
if (knownLeft === TYPES.
|
1373
|
+
if (knownLeft === TYPES.bytestring || knownRight === TYPES.bytestring) return TYPES.bytestring;
|
1371
1374
|
|
1372
1375
|
return TYPES.number;
|
1373
1376
|
|
@@ -1393,19 +1396,28 @@ const getNodeType = (scope, node) => {
|
|
1393
1396
|
if (node.operator === '!') return TYPES.boolean;
|
1394
1397
|
if (node.operator === 'void') return TYPES.undefined;
|
1395
1398
|
if (node.operator === 'delete') return TYPES.boolean;
|
1396
|
-
if (node.operator === 'typeof') return Prefs.bytestring ? TYPES.
|
1399
|
+
if (node.operator === 'typeof') return Prefs.bytestring ? TYPES.bytestring : TYPES.string;
|
1397
1400
|
|
1398
1401
|
return TYPES.number;
|
1399
1402
|
}
|
1400
1403
|
|
1401
1404
|
if (node.type === 'MemberExpression') {
|
1405
|
+
// hack: if something.name, string type
|
1406
|
+
if (node.property.name === 'name') {
|
1407
|
+
if (hasFuncWithName(node.object.name)) {
|
1408
|
+
return TYPES.bytestring;
|
1409
|
+
} else {
|
1410
|
+
return TYPES.undefined;
|
1411
|
+
}
|
1412
|
+
}
|
1413
|
+
|
1402
1414
|
// hack: if something.length, number type
|
1403
1415
|
if (node.property.name === 'length') return TYPES.number;
|
1404
1416
|
|
1405
1417
|
// ts hack
|
1406
1418
|
if (scope.locals[node.object.name]?.metadata?.type === TYPES.string) return TYPES.string;
|
1407
|
-
if (scope.locals[node.object.name]?.metadata?.type === TYPES.
|
1408
|
-
if (scope.locals[node.object.name]?.metadata?.type === TYPES.
|
1419
|
+
if (scope.locals[node.object.name]?.metadata?.type === TYPES.bytestring) return TYPES.bytestring;
|
1420
|
+
if (scope.locals[node.object.name]?.metadata?.type === TYPES.array) return TYPES.number;
|
1409
1421
|
|
1410
1422
|
if (scope.locals['#last_type']) return getLastType(scope);
|
1411
1423
|
|
@@ -1646,18 +1658,25 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
|
|
1646
1658
|
// megahack for /regex/.func()
|
1647
1659
|
const funcName = decl.callee.property.name;
|
1648
1660
|
if (decl.callee.object.regex && Object.hasOwn(Rhemyn, funcName)) {
|
1649
|
-
const
|
1661
|
+
const regex = decl.callee.object.regex.pattern;
|
1662
|
+
const rhemynName = `regex_${funcName}_${regex}`;
|
1650
1663
|
|
1651
|
-
funcIndex[
|
1652
|
-
|
1664
|
+
if (!funcIndex[rhemynName]) {
|
1665
|
+
const func = Rhemyn[funcName](regex, currentFuncIndex++, rhemynName);
|
1653
1666
|
|
1667
|
+
funcIndex[func.name] = func.index;
|
1668
|
+
funcs.push(func);
|
1669
|
+
}
|
1670
|
+
|
1671
|
+
const idx = funcIndex[rhemynName];
|
1654
1672
|
return [
|
1655
1673
|
// make string arg
|
1656
1674
|
...generate(scope, decl.arguments[0]),
|
1675
|
+
Opcodes.i32_to_u,
|
1676
|
+
...getNodeType(scope, decl.arguments[0]),
|
1657
1677
|
|
1658
1678
|
// call regex func
|
1659
|
-
Opcodes.
|
1660
|
-
[ Opcodes.call, func.index ],
|
1679
|
+
[ Opcodes.call, idx ],
|
1661
1680
|
Opcodes.i32_from_u,
|
1662
1681
|
|
1663
1682
|
...number(TYPES.boolean, Valtype.i32),
|
@@ -1820,20 +1839,20 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
|
|
1820
1839
|
idx = funcIndex[name];
|
1821
1840
|
|
1822
1841
|
// infer arguments types from builtins params
|
1823
|
-
const func = funcs.find(x => x.name === name);
|
1824
|
-
for (let i = 0; i < decl.arguments.length; i++) {
|
1825
|
-
|
1826
|
-
|
1827
|
-
|
1828
|
-
|
1829
|
-
|
1830
|
-
|
1831
|
-
|
1832
|
-
|
1833
|
-
|
1834
|
-
|
1835
|
-
|
1836
|
-
}
|
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
|
+
// }
|
1837
1856
|
}
|
1838
1857
|
|
1839
1858
|
if (idx === undefined && internalConstrs[name]) return internalConstrs[name].generate(scope, decl, _global, _name);
|
@@ -1865,9 +1884,6 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
|
|
1865
1884
|
|
1866
1885
|
// value
|
1867
1886
|
i32_const: { imms: 1, args: [], returns: 1 },
|
1868
|
-
|
1869
|
-
// a, b
|
1870
|
-
i32_or: { imms: 0, args: [ true, true ], returns: 1 },
|
1871
1887
|
};
|
1872
1888
|
|
1873
1889
|
const opName = name.slice('__Porffor_wasm_'.length);
|
@@ -2088,7 +2104,7 @@ const brTable = (input, bc, returns) => {
|
|
2088
2104
|
};
|
2089
2105
|
|
2090
2106
|
const typeSwitch = (scope, type, bc, returns = valtypeBinary) => {
|
2091
|
-
if (!Prefs.bytestring) delete bc[TYPES.
|
2107
|
+
if (!Prefs.bytestring) delete bc[TYPES.bytestring];
|
2092
2108
|
|
2093
2109
|
const known = knownType(scope, type);
|
2094
2110
|
if (known != null) {
|
@@ -2191,7 +2207,7 @@ const extractTypeAnnotation = decl => {
|
|
2191
2207
|
const typeName = type;
|
2192
2208
|
type = typeAnnoToPorfType(type);
|
2193
2209
|
|
2194
|
-
if (type === TYPES.
|
2210
|
+
if (type === TYPES.bytestring && !Prefs.bytestring) type = TYPES.string;
|
2195
2211
|
|
2196
2212
|
// if (decl.name) console.log(decl.name, { type, elementType });
|
2197
2213
|
|
@@ -2205,6 +2221,7 @@ const generateVar = (scope, decl) => {
|
|
2205
2221
|
|
2206
2222
|
// global variable if in top scope (main) and var ..., or if wanted
|
2207
2223
|
const global = topLevel || decl._bare; // decl.kind === 'var';
|
2224
|
+
const target = global ? globals : scope.locals;
|
2208
2225
|
|
2209
2226
|
for (const x of decl.declarations) {
|
2210
2227
|
const name = mapName(x.id.name);
|
@@ -2226,6 +2243,10 @@ const generateVar = (scope, decl) => {
|
|
2226
2243
|
continue; // always ignore
|
2227
2244
|
}
|
2228
2245
|
|
2246
|
+
// // generate init before allocating var
|
2247
|
+
// let generated;
|
2248
|
+
// if (x.init) generated = generate(scope, x.init, global, name);
|
2249
|
+
|
2229
2250
|
const typed = typedInput && x.id.typeAnnotation;
|
2230
2251
|
let idx = allocVar(scope, name, global, !(typed && extractTypeAnnotation(x.id).type != null));
|
2231
2252
|
|
@@ -2234,9 +2255,17 @@ const generateVar = (scope, decl) => {
|
|
2234
2255
|
}
|
2235
2256
|
|
2236
2257
|
if (x.init) {
|
2237
|
-
|
2238
|
-
|
2239
|
-
|
2258
|
+
const generated = generate(scope, x.init, global, name);
|
2259
|
+
if (scope.arrays?.get(name) != null) {
|
2260
|
+
// hack to set local as pointer before
|
2261
|
+
out.push(...number(scope.arrays.get(name)), [ global ? Opcodes.global_set : Opcodes.local_set, idx ]);
|
2262
|
+
if (generated.at(-1) == Opcodes.i32_from_u) generated.pop();
|
2263
|
+
generated.pop();
|
2264
|
+
out = out.concat(generated);
|
2265
|
+
} else {
|
2266
|
+
out = out.concat(generated);
|
2267
|
+
out.push([ global ? Opcodes.global_set : Opcodes.local_set, idx ]);
|
2268
|
+
}
|
2240
2269
|
out.push(...setType(scope, name, getNodeType(scope, x.init)));
|
2241
2270
|
}
|
2242
2271
|
|
@@ -2263,6 +2292,8 @@ const generateAssign = (scope, decl, _global, _name, valueUnused = false) => {
|
|
2263
2292
|
return [];
|
2264
2293
|
}
|
2265
2294
|
|
2295
|
+
const op = decl.operator.slice(0, -1) || '=';
|
2296
|
+
|
2266
2297
|
// hack: .length setter
|
2267
2298
|
if (decl.left.type === 'MemberExpression' && decl.left.property.name === 'length') {
|
2268
2299
|
const name = decl.left.object.name;
|
@@ -2271,14 +2302,20 @@ const generateAssign = (scope, decl, _global, _name, valueUnused = false) => {
|
|
2271
2302
|
const aotPointer = Prefs.aotPointerOpt && pointer != null;
|
2272
2303
|
|
2273
2304
|
const newValueTmp = localTmp(scope, '__length_setter_tmp');
|
2305
|
+
const pointerTmp = op === '=' ? null : localTmp(scope, '__member_setter_ptr_tmp', Valtype.i32);
|
2274
2306
|
|
2275
2307
|
return [
|
2276
2308
|
...(aotPointer ? number(0, Valtype.i32) : [
|
2277
2309
|
...generate(scope, decl.left.object),
|
2278
2310
|
Opcodes.i32_to_u
|
2279
2311
|
]),
|
2312
|
+
...(!pointerTmp ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
|
2280
2313
|
|
2281
|
-
...generate(scope, decl.right),
|
2314
|
+
...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
|
2315
|
+
[ Opcodes.local_get, pointerTmp ],
|
2316
|
+
[ Opcodes.i32_load, Math.log2(ValtypeSize.i32) - 1, 0 ],
|
2317
|
+
Opcodes.i32_from_u
|
2318
|
+
], generate(scope, decl.right), number(TYPES.number, Valtype.i32), getNodeType(scope, decl.right))),
|
2282
2319
|
[ Opcodes.local_tee, newValueTmp ],
|
2283
2320
|
|
2284
2321
|
Opcodes.i32_to_u,
|
@@ -2288,8 +2325,6 @@ const generateAssign = (scope, decl, _global, _name, valueUnused = false) => {
|
|
2288
2325
|
];
|
2289
2326
|
}
|
2290
2327
|
|
2291
|
-
const op = decl.operator.slice(0, -1) || '=';
|
2292
|
-
|
2293
2328
|
// arr[i]
|
2294
2329
|
if (decl.left.type === 'MemberExpression' && decl.left.computed) {
|
2295
2330
|
const name = decl.left.object.name;
|
@@ -2302,7 +2337,7 @@ const generateAssign = (scope, decl, _global, _name, valueUnused = false) => {
|
|
2302
2337
|
|
2303
2338
|
return [
|
2304
2339
|
...typeSwitch(scope, getNodeType(scope, decl.left.object), {
|
2305
|
-
[TYPES.
|
2340
|
+
[TYPES.array]: [
|
2306
2341
|
...(aotPointer ? [] : [
|
2307
2342
|
...generate(scope, decl.left.object),
|
2308
2343
|
Opcodes.i32_to_u
|
@@ -2504,7 +2539,7 @@ const generateUnary = (scope, decl) => {
|
|
2504
2539
|
[TYPES.undefined]: makeString(scope, 'undefined', false, '#typeof_result'),
|
2505
2540
|
[TYPES.function]: makeString(scope, 'function', false, '#typeof_result'),
|
2506
2541
|
|
2507
|
-
[TYPES.
|
2542
|
+
[TYPES.bytestring]: makeString(scope, 'string', false, '#typeof_result'),
|
2508
2543
|
|
2509
2544
|
// object and internal types
|
2510
2545
|
default: makeString(scope, 'object', false, '#typeof_result'),
|
@@ -2740,7 +2775,7 @@ const generateForOf = (scope, decl) => {
|
|
2740
2775
|
// set type for local
|
2741
2776
|
// todo: optimize away counter and use end pointer
|
2742
2777
|
out.push(...typeSwitch(scope, getNodeType(scope, decl.right), {
|
2743
|
-
[TYPES.
|
2778
|
+
[TYPES.array]: [
|
2744
2779
|
...setType(scope, leftName, TYPES.number),
|
2745
2780
|
|
2746
2781
|
[ Opcodes.loop, Blocktype.void ],
|
@@ -2823,8 +2858,8 @@ const generateForOf = (scope, decl) => {
|
|
2823
2858
|
[ Opcodes.end ],
|
2824
2859
|
[ Opcodes.end ]
|
2825
2860
|
],
|
2826
|
-
[TYPES.
|
2827
|
-
...setType(scope, leftName, TYPES.
|
2861
|
+
[TYPES.bytestring]: [
|
2862
|
+
...setType(scope, leftName, TYPES.bytestring),
|
2828
2863
|
|
2829
2864
|
[ Opcodes.loop, Blocktype.void ],
|
2830
2865
|
|
@@ -3093,12 +3128,14 @@ const makeArray = (scope, decl, global = false, name = '$undeclared', initEmpty
|
|
3093
3128
|
// todo: can we just have 1 undeclared array? probably not? but this is not really memory efficient
|
3094
3129
|
const uniqueName = name === '$undeclared' ? name + Math.random().toString().slice(2) : name;
|
3095
3130
|
|
3096
|
-
if (Prefs.scopedPageNames) scope.arrays.set(name, allocPage(scope, `${
|
3131
|
+
if (Prefs.scopedPageNames) scope.arrays.set(name, allocPage(scope, `${getAllocType(itemType)}: ${scope.name}/${uniqueName}`, itemType) * pageSize);
|
3097
3132
|
else scope.arrays.set(name, allocPage(scope, `${getAllocType(itemType)}: ${uniqueName}`, itemType) * pageSize);
|
3098
3133
|
}
|
3099
3134
|
|
3100
3135
|
const pointer = scope.arrays.get(name);
|
3101
3136
|
|
3137
|
+
const local = global ? globals[name] : scope.locals[name];
|
3138
|
+
|
3102
3139
|
const useRawElements = !!decl.rawElements;
|
3103
3140
|
const elements = useRawElements ? decl.rawElements : decl.elements;
|
3104
3141
|
|
@@ -3131,11 +3168,22 @@ const makeArray = (scope, decl, global = false, name = '$undeclared', initEmpty
|
|
3131
3168
|
return [ out, pointer ];
|
3132
3169
|
}
|
3133
3170
|
|
3171
|
+
const pointerTmp = local != null ? localTmp(scope, '#makearray_pointer_tmp', Valtype.i32) : null;
|
3172
|
+
if (pointerTmp != null) {
|
3173
|
+
out.push(
|
3174
|
+
[ global ? Opcodes.global_get : Opcodes.local_get, local.idx ],
|
3175
|
+
Opcodes.i32_to_u,
|
3176
|
+
[ Opcodes.local_set, pointerTmp ]
|
3177
|
+
);
|
3178
|
+
}
|
3179
|
+
|
3180
|
+
const pointerWasm = pointerTmp != null ? [ [ Opcodes.local_get, pointerTmp ] ] : number(pointer, Valtype.i32);
|
3181
|
+
|
3134
3182
|
// store length as 0th array
|
3135
3183
|
out.push(
|
3136
|
-
...
|
3184
|
+
...pointerWasm,
|
3137
3185
|
...number(length, Valtype.i32),
|
3138
|
-
[ Opcodes.i32_store, Math.log2(ValtypeSize.i32) - 1,
|
3186
|
+
[ Opcodes.i32_store, Math.log2(ValtypeSize.i32) - 1, 0 ]
|
3139
3187
|
);
|
3140
3188
|
|
3141
3189
|
const storeOp = StoreOps[itemType];
|
@@ -3144,14 +3192,14 @@ const makeArray = (scope, decl, global = false, name = '$undeclared', initEmpty
|
|
3144
3192
|
if (elements[i] == null) continue;
|
3145
3193
|
|
3146
3194
|
out.push(
|
3147
|
-
...
|
3195
|
+
...pointerWasm,
|
3148
3196
|
...(useRawElements ? number(elements[i], Valtype[valtype]) : generate(scope, elements[i])),
|
3149
|
-
[ storeOp, (Math.log2(ValtypeSize[itemType]) || 1) - 1, ...unsignedLEB128(
|
3197
|
+
[ storeOp, (Math.log2(ValtypeSize[itemType]) || 1) - 1, ...unsignedLEB128(ValtypeSize.i32 + i * ValtypeSize[itemType]) ]
|
3150
3198
|
);
|
3151
3199
|
}
|
3152
3200
|
|
3153
3201
|
// local value as pointer
|
3154
|
-
out.push(...
|
3202
|
+
out.push(...pointerWasm, Opcodes.i32_from_u);
|
3155
3203
|
|
3156
3204
|
return [ out, pointer ];
|
3157
3205
|
};
|
@@ -3193,6 +3241,15 @@ export const generateMember = (scope, decl, _global, _name) => {
|
|
3193
3241
|
|
3194
3242
|
const aotPointer = Prefs.aotPointerOpt && pointer != null;
|
3195
3243
|
|
3244
|
+
// hack: .name
|
3245
|
+
if (decl.property.name === 'name') {
|
3246
|
+
if (hasFuncWithName(name)) {
|
3247
|
+
return makeString(scope, name, _global, _name, true);
|
3248
|
+
} else {
|
3249
|
+
return generate(scope, DEFAULT_VALUE);
|
3250
|
+
}
|
3251
|
+
}
|
3252
|
+
|
3196
3253
|
// hack: .length
|
3197
3254
|
if (decl.property.name === 'length') {
|
3198
3255
|
const func = funcs.find(x => x.name === name);
|
@@ -3202,6 +3259,16 @@ export const generateMember = (scope, decl, _global, _name) => {
|
|
3202
3259
|
return number(typedParams ? func.params.length / 2 : func.params.length);
|
3203
3260
|
}
|
3204
3261
|
|
3262
|
+
if (builtinFuncs[name + '$constructor']) {
|
3263
|
+
const regularFunc = builtinFuncs[name];
|
3264
|
+
const regularParams = regularFunc.typedParams ? (regularFunc.params.length / 2) : regularFunc.params.length;
|
3265
|
+
|
3266
|
+
const constructorFunc = builtinFuncs[name + '$constructor'];
|
3267
|
+
const constructorParams = constructorFunc.typedParams ? (constructorFunc.params.length / 2) : constructorFunc.params.length;
|
3268
|
+
|
3269
|
+
return number(Math.max(regularParams, constructorParams));
|
3270
|
+
}
|
3271
|
+
|
3205
3272
|
if (builtinFuncs[name]) return number(builtinFuncs[name].typedParams ? (builtinFuncs[name].params.length / 2) : builtinFuncs[name].params.length);
|
3206
3273
|
if (importedFuncs[name]) return number(importedFuncs[name].params);
|
3207
3274
|
if (internalConstrs[name]) return number(internalConstrs[name].length ?? 0);
|
@@ -3230,7 +3297,7 @@ export const generateMember = (scope, decl, _global, _name) => {
|
|
3230
3297
|
}
|
3231
3298
|
|
3232
3299
|
return typeSwitch(scope, getNodeType(scope, decl.object), {
|
3233
|
-
[TYPES.
|
3300
|
+
[TYPES.array]: [
|
3234
3301
|
// get index as valtype
|
3235
3302
|
...property,
|
3236
3303
|
|
@@ -3283,7 +3350,7 @@ export const generateMember = (scope, decl, _global, _name) => {
|
|
3283
3350
|
...number(TYPES.string, Valtype.i32),
|
3284
3351
|
...setLastType(scope)
|
3285
3352
|
],
|
3286
|
-
[TYPES.
|
3353
|
+
[TYPES.bytestring]: [
|
3287
3354
|
// setup new/out array
|
3288
3355
|
...newOut,
|
3289
3356
|
[ Opcodes.drop ],
|
@@ -3308,7 +3375,7 @@ export const generateMember = (scope, decl, _global, _name) => {
|
|
3308
3375
|
// return new string (page)
|
3309
3376
|
...number(newPointer),
|
3310
3377
|
|
3311
|
-
...number(TYPES.
|
3378
|
+
...number(TYPES.bytestring, Valtype.i32),
|
3312
3379
|
...setLastType(scope)
|
3313
3380
|
],
|
3314
3381
|
|
@@ -3333,8 +3400,8 @@ const objectHack = node => {
|
|
3333
3400
|
|
3334
3401
|
if (!objectName) objectName = objectHack(node.object)?.name?.slice?.(2);
|
3335
3402
|
|
3336
|
-
// if .length, give up (hack within a hack!)
|
3337
|
-
if (node.property.name
|
3403
|
+
// if .name or .length, give up (hack within a hack!)
|
3404
|
+
if (['name', 'length'].includes(node.property.name)) {
|
3338
3405
|
node.object = objectHack(node.object);
|
3339
3406
|
return;
|
3340
3407
|
}
|
@@ -3477,7 +3544,7 @@ const internalConstrs = {
|
|
3477
3544
|
...number(pointer)
|
3478
3545
|
];
|
3479
3546
|
},
|
3480
|
-
type: TYPES.
|
3547
|
+
type: TYPES.array,
|
3481
3548
|
length: 1
|
3482
3549
|
},
|
3483
3550
|
|
@@ -3489,7 +3556,7 @@ const internalConstrs = {
|
|
3489
3556
|
elements: decl.arguments
|
3490
3557
|
}, global, name);
|
3491
3558
|
},
|
3492
|
-
type: TYPES.
|
3559
|
+
type: TYPES.array,
|
3493
3560
|
notConstr: true,
|
3494
3561
|
length: 0
|
3495
3562
|
},
|
@@ -3618,23 +3685,6 @@ const internalConstrs = {
|
|
3618
3685
|
}
|
3619
3686
|
};
|
3620
3687
|
|
3621
|
-
// const _ = Array.prototype.push;
|
3622
|
-
// Array.prototype.push = function (a) {
|
3623
|
-
// const check = arr => {
|
3624
|
-
// for (const x of arr) {
|
3625
|
-
// if (x === undefined) {
|
3626
|
-
// console.trace(arr);
|
3627
|
-
// process.exit();
|
3628
|
-
// }
|
3629
|
-
// if (Array.isArray(x)) check(x);
|
3630
|
-
// }
|
3631
|
-
// };
|
3632
|
-
// if (Array.isArray(a) && !new Error().stack.includes('node:')) check(a);
|
3633
|
-
// // if (Array.isArray(a)) check(a);
|
3634
|
-
|
3635
|
-
// return _.apply(this, arguments);
|
3636
|
-
// };
|
3637
|
-
|
3638
3688
|
export default program => {
|
3639
3689
|
globals = {};
|
3640
3690
|
globalInd = 0;
|
@@ -3649,7 +3699,7 @@ export default program => {
|
|
3649
3699
|
|
3650
3700
|
globalThis.valtype = 'f64';
|
3651
3701
|
|
3652
|
-
const valtypeOpt = process.argv.find(x => x.startsWith('
|
3702
|
+
const valtypeOpt = process.argv.find(x => x.startsWith('--valtype='));
|
3653
3703
|
if (valtypeOpt) valtype = valtypeOpt.split('=')[1];
|
3654
3704
|
|
3655
3705
|
globalThis.valtypeBinary = Valtype[valtype];
|
@@ -3657,7 +3707,7 @@ export default program => {
|
|
3657
3707
|
const valtypeInd = ['i32', 'i64', 'f64'].indexOf(valtype);
|
3658
3708
|
|
3659
3709
|
globalThis.pageSize = PageSize;
|
3660
|
-
const pageSizeOpt = process.argv.find(x => x.startsWith('
|
3710
|
+
const pageSizeOpt = process.argv.find(x => x.startsWith('--page-size='));
|
3661
3711
|
if (pageSizeOpt) pageSize = parseInt(pageSizeOpt.split('=')[1]) * 1024;
|
3662
3712
|
|
3663
3713
|
// set generic opcodes for current valtype
|