porffor 0.2.0-e04e26f → 0.2.0-e62542f
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 +254 -0
- package/README.md +63 -44
- 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/crypto.ts +1 -1
- package/compiler/builtins/date.ts +1292 -349
- package/compiler/builtins/escape.ts +2 -2
- package/compiler/builtins/int.ts +3 -3
- package/compiler/builtins/number.ts +1 -1
- package/compiler/builtins/porffor.d.ts +21 -4
- package/compiler/builtins/string.ts +22 -22
- package/compiler/builtins/tostring.ts +4 -4
- package/compiler/builtins.js +6 -30
- package/compiler/codegen.js +138 -68
- package/compiler/decompile.js +0 -1
- package/compiler/generated_builtins.js +499 -154
- 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 +45 -4
- package/runner/repl.js +2 -2
- package/runner/sizes.js +1 -1
package/compiler/codegen.js
CHANGED
@@ -201,7 +201,7 @@ const generate = (scope, decl, global = false, name = undefined, valueUnused = f
|
|
201
201
|
}
|
202
202
|
|
203
203
|
let inst = Opcodes[asm[0].replace('.', '_')];
|
204
|
-
if (
|
204
|
+
if (inst == null) throw new Error(`inline asm: inst ${asm[0]} not found`);
|
205
205
|
|
206
206
|
if (!Array.isArray(inst)) inst = [ inst ];
|
207
207
|
const immediates = asm.slice(1).map(x => {
|
@@ -219,8 +219,8 @@ const generate = (scope, decl, global = false, name = undefined, valueUnused = f
|
|
219
219
|
__Porffor_bs: str => [
|
220
220
|
...makeString(scope, str, global, name, true),
|
221
221
|
|
222
|
-
...(name ? setType(scope, name, TYPES.
|
223
|
-
...number(TYPES.
|
222
|
+
...(name ? setType(scope, name, TYPES.bytestring) : [
|
223
|
+
...number(TYPES.bytestring, Valtype.i32),
|
224
224
|
...setLastType(scope)
|
225
225
|
])
|
226
226
|
],
|
@@ -460,7 +460,7 @@ const concatStrings = (scope, left, right, global, name, assign = false, bytestr
|
|
460
460
|
const rightLength = localTmp(scope, 'concat_right_length', Valtype.i32);
|
461
461
|
const leftLength = localTmp(scope, 'concat_left_length', Valtype.i32);
|
462
462
|
|
463
|
-
if (assign) {
|
463
|
+
if (assign && Prefs.aotPointerOpt) {
|
464
464
|
const pointer = scope.arrays?.get(name ?? '$undeclared');
|
465
465
|
|
466
466
|
return [
|
@@ -723,7 +723,7 @@ const truthy = (scope, wasm, type, intIn = false, intOut = false) => {
|
|
723
723
|
|
724
724
|
...typeSwitch(scope, type, {
|
725
725
|
// [TYPES.number]: def,
|
726
|
-
[TYPES.
|
726
|
+
[TYPES.array]: [
|
727
727
|
// arrays are always truthy
|
728
728
|
...number(1, intOut ? Valtype.i32 : valtypeBinary)
|
729
729
|
],
|
@@ -739,7 +739,7 @@ const truthy = (scope, wasm, type, intIn = false, intOut = false) => {
|
|
739
739
|
[ Opcodes.i32_eqz ], */
|
740
740
|
...(intOut ? [] : [ Opcodes.i32_from_u ])
|
741
741
|
],
|
742
|
-
[TYPES.
|
742
|
+
[TYPES.bytestring]: [ // duplicate of string
|
743
743
|
...(!useTmp ? [] : [ [ Opcodes.local_get, tmp ] ]),
|
744
744
|
...(intIn ? [] : [ Opcodes.i32_to_u ]),
|
745
745
|
|
@@ -762,7 +762,7 @@ const falsy = (scope, wasm, type, intIn = false, intOut = false) => {
|
|
762
762
|
...(!useTmp ? [] : [ [ Opcodes.local_set, tmp ] ]),
|
763
763
|
|
764
764
|
...typeSwitch(scope, type, {
|
765
|
-
[TYPES.
|
765
|
+
[TYPES.array]: [
|
766
766
|
// arrays are always truthy
|
767
767
|
...number(0, intOut ? Valtype.i32 : valtypeBinary)
|
768
768
|
],
|
@@ -777,7 +777,7 @@ const falsy = (scope, wasm, type, intIn = false, intOut = false) => {
|
|
777
777
|
[ Opcodes.i32_eqz ],
|
778
778
|
...(intOut ? [] : [ Opcodes.i32_from_u ])
|
779
779
|
],
|
780
|
-
[TYPES.
|
780
|
+
[TYPES.bytestring]: [ // duplicate of string
|
781
781
|
...(!useTmp ? [] : [ [ Opcodes.local_get, tmp ] ]),
|
782
782
|
...(intIn ? [] : [ Opcodes.i32_to_u ]),
|
783
783
|
|
@@ -922,7 +922,7 @@ const performOp = (scope, op, left, right, leftType, rightType, _global = false,
|
|
922
922
|
}
|
923
923
|
}
|
924
924
|
|
925
|
-
if (knownLeft === TYPES.
|
925
|
+
if (knownLeft === TYPES.bytestring || knownRight === TYPES.bytestring) {
|
926
926
|
if (op === '+') {
|
927
927
|
// todo: this should be dynamic too but for now only static
|
928
928
|
// string concat (a + b)
|
@@ -1041,12 +1041,12 @@ const performOp = (scope, op, left, right, leftType, rightType, _global = false,
|
|
1041
1041
|
|
1042
1042
|
// if left is bytestring
|
1043
1043
|
...leftType,
|
1044
|
-
...number(TYPES.
|
1044
|
+
...number(TYPES.bytestring, Valtype.i32),
|
1045
1045
|
[ Opcodes.i32_eq ],
|
1046
1046
|
|
1047
1047
|
// if right is bytestring
|
1048
1048
|
...rightType,
|
1049
|
-
...number(TYPES.
|
1049
|
+
...number(TYPES.bytestring, Valtype.i32),
|
1050
1050
|
[ Opcodes.i32_eq ],
|
1051
1051
|
|
1052
1052
|
// if both are true
|
@@ -1188,7 +1188,7 @@ const generateLogicExp = (scope, decl) => {
|
|
1188
1188
|
// 5: pointer
|
1189
1189
|
|
1190
1190
|
const isExistingProtoFunc = name => {
|
1191
|
-
if (name.startsWith('__Array_prototype')) return !!prototypeFuncs[TYPES.
|
1191
|
+
if (name.startsWith('__Array_prototype')) return !!prototypeFuncs[TYPES.array][name.slice(18)];
|
1192
1192
|
if (name.startsWith('__String_prototype_')) return !!prototypeFuncs[TYPES.string][name.slice(19)];
|
1193
1193
|
|
1194
1194
|
return false;
|
@@ -1247,9 +1247,9 @@ const setLastType = scope => {
|
|
1247
1247
|
const getNodeType = (scope, node) => {
|
1248
1248
|
const inner = () => {
|
1249
1249
|
if (node.type === 'Literal') {
|
1250
|
-
if (node.regex) return TYPES.
|
1250
|
+
if (node.regex) return TYPES.regexp;
|
1251
1251
|
|
1252
|
-
if (typeof node.value === 'string' && byteStringable(node.value)) return TYPES.
|
1252
|
+
if (typeof node.value === 'string' && byteStringable(node.value)) return TYPES.bytestring;
|
1253
1253
|
|
1254
1254
|
return TYPES[typeof node.value];
|
1255
1255
|
}
|
@@ -1303,7 +1303,7 @@ const getNodeType = (scope, node) => {
|
|
1303
1303
|
const spl = name.slice(2).split('_');
|
1304
1304
|
|
1305
1305
|
const func = spl[spl.length - 1];
|
1306
|
-
const protoFuncs = Object.keys(prototypeFuncs).filter(x => x != TYPES.
|
1306
|
+
const protoFuncs = Object.keys(prototypeFuncs).filter(x => x != TYPES.bytestring && prototypeFuncs[x][func] != null);
|
1307
1307
|
if (protoFuncs.length === 1) return protoFuncs[0].returnType ?? TYPES.number;
|
1308
1308
|
}
|
1309
1309
|
|
@@ -1355,7 +1355,7 @@ const getNodeType = (scope, node) => {
|
|
1355
1355
|
}
|
1356
1356
|
|
1357
1357
|
if (node.type === 'ArrayExpression') {
|
1358
|
-
return TYPES.
|
1358
|
+
return TYPES.array;
|
1359
1359
|
}
|
1360
1360
|
|
1361
1361
|
if (node.type === 'BinaryExpression') {
|
@@ -1367,7 +1367,7 @@ const getNodeType = (scope, node) => {
|
|
1367
1367
|
|
1368
1368
|
// todo: this should be dynamic but for now only static
|
1369
1369
|
if (knownLeft === TYPES.string || knownRight === TYPES.string) return TYPES.string;
|
1370
|
-
if (knownLeft === TYPES.
|
1370
|
+
if (knownLeft === TYPES.bytestring || knownRight === TYPES.bytestring) return TYPES.bytestring;
|
1371
1371
|
|
1372
1372
|
return TYPES.number;
|
1373
1373
|
|
@@ -1393,7 +1393,7 @@ const getNodeType = (scope, node) => {
|
|
1393
1393
|
if (node.operator === '!') return TYPES.boolean;
|
1394
1394
|
if (node.operator === 'void') return TYPES.undefined;
|
1395
1395
|
if (node.operator === 'delete') return TYPES.boolean;
|
1396
|
-
if (node.operator === 'typeof') return Prefs.bytestring ? TYPES.
|
1396
|
+
if (node.operator === 'typeof') return Prefs.bytestring ? TYPES.bytestring : TYPES.string;
|
1397
1397
|
|
1398
1398
|
return TYPES.number;
|
1399
1399
|
}
|
@@ -1404,8 +1404,8 @@ const getNodeType = (scope, node) => {
|
|
1404
1404
|
|
1405
1405
|
// ts hack
|
1406
1406
|
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.
|
1407
|
+
if (scope.locals[node.object.name]?.metadata?.type === TYPES.bytestring) return TYPES.bytestring;
|
1408
|
+
if (scope.locals[node.object.name]?.metadata?.type === TYPES.array) return TYPES.number;
|
1409
1409
|
|
1410
1410
|
if (scope.locals['#last_type']) return getLastType(scope);
|
1411
1411
|
|
@@ -1646,18 +1646,25 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
|
|
1646
1646
|
// megahack for /regex/.func()
|
1647
1647
|
const funcName = decl.callee.property.name;
|
1648
1648
|
if (decl.callee.object.regex && Object.hasOwn(Rhemyn, funcName)) {
|
1649
|
-
const
|
1649
|
+
const regex = decl.callee.object.regex.pattern;
|
1650
|
+
const rhemynName = `regex_${funcName}_${regex}`;
|
1650
1651
|
|
1651
|
-
funcIndex[
|
1652
|
-
|
1652
|
+
if (!funcIndex[rhemynName]) {
|
1653
|
+
const func = Rhemyn[funcName](regex, currentFuncIndex++, rhemynName);
|
1653
1654
|
|
1655
|
+
funcIndex[func.name] = func.index;
|
1656
|
+
funcs.push(func);
|
1657
|
+
}
|
1658
|
+
|
1659
|
+
const idx = funcIndex[rhemynName];
|
1654
1660
|
return [
|
1655
1661
|
// make string arg
|
1656
1662
|
...generate(scope, decl.arguments[0]),
|
1663
|
+
Opcodes.i32_to_u,
|
1664
|
+
...getNodeType(scope, decl.arguments[0]),
|
1657
1665
|
|
1658
1666
|
// call regex func
|
1659
|
-
Opcodes.
|
1660
|
-
[ Opcodes.call, func.index ],
|
1667
|
+
[ Opcodes.call, idx ],
|
1661
1668
|
Opcodes.i32_from_u,
|
1662
1669
|
|
1663
1670
|
...number(TYPES.boolean, Valtype.i32),
|
@@ -1697,6 +1704,7 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
|
|
1697
1704
|
|
1698
1705
|
protoBC[type] = generateCall(scope, {
|
1699
1706
|
callee: {
|
1707
|
+
type: 'Identifier',
|
1700
1708
|
name: x
|
1701
1709
|
},
|
1702
1710
|
arguments: [ target, ...decl.arguments ],
|
@@ -1819,20 +1827,20 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
|
|
1819
1827
|
idx = funcIndex[name];
|
1820
1828
|
|
1821
1829
|
// infer arguments types from builtins params
|
1822
|
-
const func = funcs.find(x => x.name === name);
|
1823
|
-
for (let i = 0; i < decl.arguments.length; i++) {
|
1824
|
-
|
1825
|
-
|
1826
|
-
|
1827
|
-
|
1828
|
-
|
1829
|
-
|
1830
|
-
|
1831
|
-
|
1832
|
-
|
1833
|
-
|
1834
|
-
|
1835
|
-
}
|
1830
|
+
// const func = funcs.find(x => x.name === name);
|
1831
|
+
// for (let i = 0; i < decl.arguments.length; i++) {
|
1832
|
+
// const arg = decl.arguments[i];
|
1833
|
+
// if (!arg.name) continue;
|
1834
|
+
|
1835
|
+
// const local = scope.locals[arg.name];
|
1836
|
+
// if (!local) continue;
|
1837
|
+
|
1838
|
+
// local.type = func.params[i];
|
1839
|
+
// if (local.type === Valtype.v128) {
|
1840
|
+
// // specify vec subtype inferred from last vec type in function name
|
1841
|
+
// local.vecType = name.split('_').reverse().find(x => x.includes('x'));
|
1842
|
+
// }
|
1843
|
+
// }
|
1836
1844
|
}
|
1837
1845
|
|
1838
1846
|
if (idx === undefined && internalConstrs[name]) return internalConstrs[name].generate(scope, decl, _global, _name);
|
@@ -1864,9 +1872,6 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
|
|
1864
1872
|
|
1865
1873
|
// value
|
1866
1874
|
i32_const: { imms: 1, args: [], returns: 1 },
|
1867
|
-
|
1868
|
-
// a, b
|
1869
|
-
i32_or: { imms: 0, args: [ true, true ], returns: 1 },
|
1870
1875
|
};
|
1871
1876
|
|
1872
1877
|
const opName = name.slice('__Porffor_wasm_'.length);
|
@@ -2087,7 +2092,7 @@ const brTable = (input, bc, returns) => {
|
|
2087
2092
|
};
|
2088
2093
|
|
2089
2094
|
const typeSwitch = (scope, type, bc, returns = valtypeBinary) => {
|
2090
|
-
if (!Prefs.bytestring) delete bc[TYPES.
|
2095
|
+
if (!Prefs.bytestring) delete bc[TYPES.bytestring];
|
2091
2096
|
|
2092
2097
|
const known = knownType(scope, type);
|
2093
2098
|
if (known != null) {
|
@@ -2190,7 +2195,7 @@ const extractTypeAnnotation = decl => {
|
|
2190
2195
|
const typeName = type;
|
2191
2196
|
type = typeAnnoToPorfType(type);
|
2192
2197
|
|
2193
|
-
if (type === TYPES.
|
2198
|
+
if (type === TYPES.bytestring && !Prefs.bytestring) type = TYPES.string;
|
2194
2199
|
|
2195
2200
|
// if (decl.name) console.log(decl.name, { type, elementType });
|
2196
2201
|
|
@@ -2204,6 +2209,7 @@ const generateVar = (scope, decl) => {
|
|
2204
2209
|
|
2205
2210
|
// global variable if in top scope (main) and var ..., or if wanted
|
2206
2211
|
const global = topLevel || decl._bare; // decl.kind === 'var';
|
2212
|
+
const target = global ? globals : scope.locals;
|
2207
2213
|
|
2208
2214
|
for (const x of decl.declarations) {
|
2209
2215
|
const name = mapName(x.id.name);
|
@@ -2225,6 +2231,10 @@ const generateVar = (scope, decl) => {
|
|
2225
2231
|
continue; // always ignore
|
2226
2232
|
}
|
2227
2233
|
|
2234
|
+
// // generate init before allocating var
|
2235
|
+
// let generated;
|
2236
|
+
// if (x.init) generated = generate(scope, x.init, global, name);
|
2237
|
+
|
2228
2238
|
const typed = typedInput && x.id.typeAnnotation;
|
2229
2239
|
let idx = allocVar(scope, name, global, !(typed && extractTypeAnnotation(x.id).type != null));
|
2230
2240
|
|
@@ -2233,9 +2243,17 @@ const generateVar = (scope, decl) => {
|
|
2233
2243
|
}
|
2234
2244
|
|
2235
2245
|
if (x.init) {
|
2236
|
-
|
2237
|
-
|
2238
|
-
|
2246
|
+
const generated = generate(scope, x.init, global, name);
|
2247
|
+
if (scope.arrays?.get(name) != null) {
|
2248
|
+
// hack to set local as pointer before
|
2249
|
+
out.push(...number(scope.arrays.get(name)), [ global ? Opcodes.global_set : Opcodes.local_set, idx ]);
|
2250
|
+
if (generated.at(-1) == Opcodes.i32_from_u) generated.pop();
|
2251
|
+
generated.pop();
|
2252
|
+
out = out.concat(generated);
|
2253
|
+
} else {
|
2254
|
+
out = out.concat(generated);
|
2255
|
+
out.push([ global ? Opcodes.global_set : Opcodes.local_set, idx ]);
|
2256
|
+
}
|
2239
2257
|
out.push(...setType(scope, name, getNodeType(scope, x.init)));
|
2240
2258
|
}
|
2241
2259
|
|
@@ -2262,6 +2280,8 @@ const generateAssign = (scope, decl, _global, _name, valueUnused = false) => {
|
|
2262
2280
|
return [];
|
2263
2281
|
}
|
2264
2282
|
|
2283
|
+
const op = decl.operator.slice(0, -1) || '=';
|
2284
|
+
|
2265
2285
|
// hack: .length setter
|
2266
2286
|
if (decl.left.type === 'MemberExpression' && decl.left.property.name === 'length') {
|
2267
2287
|
const name = decl.left.object.name;
|
@@ -2270,14 +2290,20 @@ const generateAssign = (scope, decl, _global, _name, valueUnused = false) => {
|
|
2270
2290
|
const aotPointer = Prefs.aotPointerOpt && pointer != null;
|
2271
2291
|
|
2272
2292
|
const newValueTmp = localTmp(scope, '__length_setter_tmp');
|
2293
|
+
const pointerTmp = op === '=' ? null : localTmp(scope, '__member_setter_ptr_tmp', Valtype.i32);
|
2273
2294
|
|
2274
2295
|
return [
|
2275
2296
|
...(aotPointer ? number(0, Valtype.i32) : [
|
2276
2297
|
...generate(scope, decl.left.object),
|
2277
2298
|
Opcodes.i32_to_u
|
2278
2299
|
]),
|
2300
|
+
...(!pointerTmp ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
|
2279
2301
|
|
2280
|
-
...generate(scope, decl.right),
|
2302
|
+
...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
|
2303
|
+
[ Opcodes.local_get, pointerTmp ],
|
2304
|
+
[ Opcodes.i32_load, Math.log2(ValtypeSize.i32) - 1, 0 ],
|
2305
|
+
Opcodes.i32_from_u
|
2306
|
+
], generate(scope, decl.right), number(TYPES.number, Valtype.i32), getNodeType(scope, decl.right))),
|
2281
2307
|
[ Opcodes.local_tee, newValueTmp ],
|
2282
2308
|
|
2283
2309
|
Opcodes.i32_to_u,
|
@@ -2287,8 +2313,6 @@ const generateAssign = (scope, decl, _global, _name, valueUnused = false) => {
|
|
2287
2313
|
];
|
2288
2314
|
}
|
2289
2315
|
|
2290
|
-
const op = decl.operator.slice(0, -1) || '=';
|
2291
|
-
|
2292
2316
|
// arr[i]
|
2293
2317
|
if (decl.left.type === 'MemberExpression' && decl.left.computed) {
|
2294
2318
|
const name = decl.left.object.name;
|
@@ -2301,7 +2325,7 @@ const generateAssign = (scope, decl, _global, _name, valueUnused = false) => {
|
|
2301
2325
|
|
2302
2326
|
return [
|
2303
2327
|
...typeSwitch(scope, getNodeType(scope, decl.left.object), {
|
2304
|
-
[TYPES.
|
2328
|
+
[TYPES.array]: [
|
2305
2329
|
...(aotPointer ? [] : [
|
2306
2330
|
...generate(scope, decl.left.object),
|
2307
2331
|
Opcodes.i32_to_u
|
@@ -2503,7 +2527,7 @@ const generateUnary = (scope, decl) => {
|
|
2503
2527
|
[TYPES.undefined]: makeString(scope, 'undefined', false, '#typeof_result'),
|
2504
2528
|
[TYPES.function]: makeString(scope, 'function', false, '#typeof_result'),
|
2505
2529
|
|
2506
|
-
[TYPES.
|
2530
|
+
[TYPES.bytestring]: makeString(scope, 'string', false, '#typeof_result'),
|
2507
2531
|
|
2508
2532
|
// object and internal types
|
2509
2533
|
default: makeString(scope, 'object', false, '#typeof_result'),
|
@@ -2739,7 +2763,7 @@ const generateForOf = (scope, decl) => {
|
|
2739
2763
|
// set type for local
|
2740
2764
|
// todo: optimize away counter and use end pointer
|
2741
2765
|
out.push(...typeSwitch(scope, getNodeType(scope, decl.right), {
|
2742
|
-
[TYPES.
|
2766
|
+
[TYPES.array]: [
|
2743
2767
|
...setType(scope, leftName, TYPES.number),
|
2744
2768
|
|
2745
2769
|
[ Opcodes.loop, Blocktype.void ],
|
@@ -2822,8 +2846,8 @@ const generateForOf = (scope, decl) => {
|
|
2822
2846
|
[ Opcodes.end ],
|
2823
2847
|
[ Opcodes.end ]
|
2824
2848
|
],
|
2825
|
-
[TYPES.
|
2826
|
-
...setType(scope, leftName, TYPES.
|
2849
|
+
[TYPES.bytestring]: [
|
2850
|
+
...setType(scope, leftName, TYPES.bytestring),
|
2827
2851
|
|
2828
2852
|
[ Opcodes.loop, Blocktype.void ],
|
2829
2853
|
|
@@ -3092,12 +3116,14 @@ const makeArray = (scope, decl, global = false, name = '$undeclared', initEmpty
|
|
3092
3116
|
// todo: can we just have 1 undeclared array? probably not? but this is not really memory efficient
|
3093
3117
|
const uniqueName = name === '$undeclared' ? name + Math.random().toString().slice(2) : name;
|
3094
3118
|
|
3095
|
-
if (Prefs.scopedPageNames) scope.arrays.set(name, allocPage(scope, `${
|
3119
|
+
if (Prefs.scopedPageNames) scope.arrays.set(name, allocPage(scope, `${getAllocType(itemType)}: ${scope.name}/${uniqueName}`, itemType) * pageSize);
|
3096
3120
|
else scope.arrays.set(name, allocPage(scope, `${getAllocType(itemType)}: ${uniqueName}`, itemType) * pageSize);
|
3097
3121
|
}
|
3098
3122
|
|
3099
3123
|
const pointer = scope.arrays.get(name);
|
3100
3124
|
|
3125
|
+
const local = global ? globals[name] : scope.locals[name];
|
3126
|
+
|
3101
3127
|
const useRawElements = !!decl.rawElements;
|
3102
3128
|
const elements = useRawElements ? decl.rawElements : decl.elements;
|
3103
3129
|
|
@@ -3130,11 +3156,22 @@ const makeArray = (scope, decl, global = false, name = '$undeclared', initEmpty
|
|
3130
3156
|
return [ out, pointer ];
|
3131
3157
|
}
|
3132
3158
|
|
3159
|
+
const pointerTmp = local != null ? localTmp(scope, '#makearray_pointer_tmp', Valtype.i32) : null;
|
3160
|
+
if (pointerTmp != null) {
|
3161
|
+
out.push(
|
3162
|
+
[ global ? Opcodes.global_get : Opcodes.local_get, local.idx ],
|
3163
|
+
Opcodes.i32_to_u,
|
3164
|
+
[ Opcodes.local_set, pointerTmp ]
|
3165
|
+
);
|
3166
|
+
}
|
3167
|
+
|
3168
|
+
const pointerWasm = pointerTmp != null ? [ [ Opcodes.local_get, pointerTmp ] ] : number(pointer, Valtype.i32);
|
3169
|
+
|
3133
3170
|
// store length as 0th array
|
3134
3171
|
out.push(
|
3135
|
-
...
|
3172
|
+
...pointerWasm,
|
3136
3173
|
...number(length, Valtype.i32),
|
3137
|
-
[ Opcodes.i32_store, Math.log2(ValtypeSize.i32) - 1,
|
3174
|
+
[ Opcodes.i32_store, Math.log2(ValtypeSize.i32) - 1, 0 ]
|
3138
3175
|
);
|
3139
3176
|
|
3140
3177
|
const storeOp = StoreOps[itemType];
|
@@ -3143,14 +3180,14 @@ const makeArray = (scope, decl, global = false, name = '$undeclared', initEmpty
|
|
3143
3180
|
if (elements[i] == null) continue;
|
3144
3181
|
|
3145
3182
|
out.push(
|
3146
|
-
...
|
3183
|
+
...pointerWasm,
|
3147
3184
|
...(useRawElements ? number(elements[i], Valtype[valtype]) : generate(scope, elements[i])),
|
3148
|
-
[ storeOp, (Math.log2(ValtypeSize[itemType]) || 1) - 1, ...unsignedLEB128(
|
3185
|
+
[ storeOp, (Math.log2(ValtypeSize[itemType]) || 1) - 1, ...unsignedLEB128(ValtypeSize.i32 + i * ValtypeSize[itemType]) ]
|
3149
3186
|
);
|
3150
3187
|
}
|
3151
3188
|
|
3152
3189
|
// local value as pointer
|
3153
|
-
out.push(...
|
3190
|
+
out.push(...pointerWasm, Opcodes.i32_from_u);
|
3154
3191
|
|
3155
3192
|
return [ out, pointer ];
|
3156
3193
|
};
|
@@ -3229,7 +3266,7 @@ export const generateMember = (scope, decl, _global, _name) => {
|
|
3229
3266
|
}
|
3230
3267
|
|
3231
3268
|
return typeSwitch(scope, getNodeType(scope, decl.object), {
|
3232
|
-
[TYPES.
|
3269
|
+
[TYPES.array]: [
|
3233
3270
|
// get index as valtype
|
3234
3271
|
...property,
|
3235
3272
|
|
@@ -3282,7 +3319,7 @@ export const generateMember = (scope, decl, _global, _name) => {
|
|
3282
3319
|
...number(TYPES.string, Valtype.i32),
|
3283
3320
|
...setLastType(scope)
|
3284
3321
|
],
|
3285
|
-
[TYPES.
|
3322
|
+
[TYPES.bytestring]: [
|
3286
3323
|
// setup new/out array
|
3287
3324
|
...newOut,
|
3288
3325
|
[ Opcodes.drop ],
|
@@ -3307,7 +3344,7 @@ export const generateMember = (scope, decl, _global, _name) => {
|
|
3307
3344
|
// return new string (page)
|
3308
3345
|
...number(newPointer),
|
3309
3346
|
|
3310
|
-
...number(TYPES.
|
3347
|
+
...number(TYPES.bytestring, Valtype.i32),
|
3311
3348
|
...setLastType(scope)
|
3312
3349
|
],
|
3313
3350
|
|
@@ -3476,7 +3513,7 @@ const internalConstrs = {
|
|
3476
3513
|
...number(pointer)
|
3477
3514
|
];
|
3478
3515
|
},
|
3479
|
-
type: TYPES.
|
3516
|
+
type: TYPES.array,
|
3480
3517
|
length: 1
|
3481
3518
|
},
|
3482
3519
|
|
@@ -3488,7 +3525,7 @@ const internalConstrs = {
|
|
3488
3525
|
elements: decl.arguments
|
3489
3526
|
}, global, name);
|
3490
3527
|
},
|
3491
|
-
type: TYPES.
|
3528
|
+
type: TYPES.array,
|
3492
3529
|
notConstr: true,
|
3493
3530
|
length: 0
|
3494
3531
|
},
|
@@ -3581,6 +3618,39 @@ const internalConstrs = {
|
|
3581
3618
|
type: TYPES.number,
|
3582
3619
|
notConstr: true,
|
3583
3620
|
length: 2
|
3621
|
+
},
|
3622
|
+
|
3623
|
+
__console_log: {
|
3624
|
+
generate: (scope, decl) => {
|
3625
|
+
const out = [];
|
3626
|
+
|
3627
|
+
for (let i = 0; i < decl.arguments.length; i++) {
|
3628
|
+
out.push(
|
3629
|
+
...generateCall(scope, {
|
3630
|
+
callee: {
|
3631
|
+
type: 'Identifier',
|
3632
|
+
name: '__Porffor_print'
|
3633
|
+
},
|
3634
|
+
arguments: [ decl.arguments[i] ]
|
3635
|
+
}),
|
3636
|
+
|
3637
|
+
// print space
|
3638
|
+
...number(32),
|
3639
|
+
[ Opcodes.call, importedFuncs.printChar ]
|
3640
|
+
);
|
3641
|
+
}
|
3642
|
+
|
3643
|
+
// print newline
|
3644
|
+
out.push(
|
3645
|
+
...number(10),
|
3646
|
+
[ Opcodes.call, importedFuncs.printChar ]
|
3647
|
+
);
|
3648
|
+
|
3649
|
+
return out;
|
3650
|
+
},
|
3651
|
+
type: TYPES.undefined,
|
3652
|
+
notConstr: true,
|
3653
|
+
length: 0
|
3584
3654
|
}
|
3585
3655
|
};
|
3586
3656
|
|
@@ -3615,7 +3685,7 @@ export default program => {
|
|
3615
3685
|
|
3616
3686
|
globalThis.valtype = 'f64';
|
3617
3687
|
|
3618
|
-
const valtypeOpt = process.argv.find(x => x.startsWith('
|
3688
|
+
const valtypeOpt = process.argv.find(x => x.startsWith('--valtype='));
|
3619
3689
|
if (valtypeOpt) valtype = valtypeOpt.split('=')[1];
|
3620
3690
|
|
3621
3691
|
globalThis.valtypeBinary = Valtype[valtype];
|
@@ -3623,7 +3693,7 @@ export default program => {
|
|
3623
3693
|
const valtypeInd = ['i32', 'i64', 'f64'].indexOf(valtype);
|
3624
3694
|
|
3625
3695
|
globalThis.pageSize = PageSize;
|
3626
|
-
const pageSizeOpt = process.argv.find(x => x.startsWith('
|
3696
|
+
const pageSizeOpt = process.argv.find(x => x.startsWith('--page-size='));
|
3627
3697
|
if (pageSizeOpt) pageSize = parseInt(pageSizeOpt.split('=')[1]) * 1024;
|
3628
3698
|
|
3629
3699
|
// set generic opcodes for current valtype
|