porffor 0.2.0-eeb45f8 → 0.2.0-fbab1de
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -3
- package/compiler/codeGen.js +20 -28
- package/package.json +1 -1
- package/r.js +9 -0
package/README.md
CHANGED
@@ -121,7 +121,7 @@ No particular order and no guarentees, just what could happen soon™
|
|
121
121
|
- *Basic* Wasm engine (interpreter) in JS
|
122
122
|
- More math operators (`**`, etc)
|
123
123
|
- `do { ... } while (...)`
|
124
|
-
-
|
124
|
+
- Typed export inputs (array)
|
125
125
|
- Exceptions
|
126
126
|
- Rewrite to use actual strings (optional?)
|
127
127
|
- `try { } finally { }`
|
@@ -130,7 +130,7 @@ No particular order and no guarentees, just what could happen soon™
|
|
130
130
|
- Rewrite local indexes per func for smallest local header and remove unused idxs
|
131
131
|
- Smarter inline selection (snapshots?)
|
132
132
|
- Remove const ifs (`if (true)`, etc)
|
133
|
-
-
|
133
|
+
- Memory alignment
|
134
134
|
- Runtime
|
135
135
|
- WASI target
|
136
136
|
- Run precompiled Wasm file if given
|
@@ -147,7 +147,7 @@ No particular order and no guarentees, just what could happen soon™
|
|
147
147
|
- Self hosted testing?
|
148
148
|
|
149
149
|
## Performance
|
150
|
-
*For the things it supports most of the time*, Porffor is blazingly fast compared to most interpreters, and common engines running without JIT. For those with JIT, it is
|
150
|
+
*For the things it supports most of the time*, Porffor is *blazingly fast* compared to most interpreters, and common engines running without JIT. For those with JIT, it is usually slower by default, but can catch up with compiler arguments and typed input.
|
151
151
|
|
152
152
|

|
153
153
|
|
package/compiler/codeGen.js
CHANGED
@@ -1175,7 +1175,7 @@ const getNodeType = (scope, node) => {
|
|
1175
1175
|
const spl = name.slice(2).split('_');
|
1176
1176
|
|
1177
1177
|
const func = spl[spl.length - 1];
|
1178
|
-
const protoFuncs = Object.
|
1178
|
+
const protoFuncs = Object.keys(prototypeFuncs).filter(x => x != TYPES._bytestring && prototypeFuncs[x][func] != null);
|
1179
1179
|
if (protoFuncs.length === 1) return protoFuncs[0].returnType ?? TYPES.number;
|
1180
1180
|
}
|
1181
1181
|
|
@@ -1260,6 +1260,10 @@ const getNodeType = (scope, node) => {
|
|
1260
1260
|
// hack: if something.length, number type
|
1261
1261
|
if (node.property.name === 'length') return TYPES.number;
|
1262
1262
|
|
1263
|
+
// ts hack
|
1264
|
+
if (scope.locals[node.object.name]?.metadata?.type === TYPES.string) return TYPES.string;
|
1265
|
+
if (scope.locals[node.object.name]?.metadata?.type === TYPES._array) return TYPES.number;
|
1266
|
+
|
1263
1267
|
if (scope.locals['#last_type']) return [ getLastType(scope) ];
|
1264
1268
|
|
1265
1269
|
// presume
|
@@ -1279,23 +1283,6 @@ const getNodeType = (scope, node) => {
|
|
1279
1283
|
return ret;
|
1280
1284
|
};
|
1281
1285
|
|
1282
|
-
const toString = (scope, wasm, type) => {
|
1283
|
-
const tmp = localTmp(scope, '#tostring_tmp');
|
1284
|
-
return [
|
1285
|
-
...wasm,
|
1286
|
-
[ Opcodes.local_set, tmp ],
|
1287
|
-
|
1288
|
-
...typeSwitch(scope, type, {
|
1289
|
-
[TYPES.string]: [
|
1290
|
-
[ Opcodes.local_get, tmp ]
|
1291
|
-
],
|
1292
|
-
[TYPES.undefined]: [
|
1293
|
-
// [ Opcodes.]
|
1294
|
-
]
|
1295
|
-
})
|
1296
|
-
]
|
1297
|
-
};
|
1298
|
-
|
1299
1286
|
const generateLiteral = (scope, decl, global, name) => {
|
1300
1287
|
if (decl.value === null) return number(NULL);
|
1301
1288
|
|
@@ -1486,8 +1473,8 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
|
|
1486
1473
|
// literal.func()
|
1487
1474
|
if (!name && decl.callee.type === 'MemberExpression') {
|
1488
1475
|
// megahack for /regex/.func()
|
1489
|
-
|
1490
|
-
|
1476
|
+
const funcName = decl.callee.property.name;
|
1477
|
+
if (decl.callee.object.regex && Object.hasOwn(Rhemyn, funcName)) {
|
1491
1478
|
const func = Rhemyn[funcName](decl.callee.object.regex.pattern, currentFuncIndex++);
|
1492
1479
|
|
1493
1480
|
funcIndex[func.name] = func.index;
|
@@ -1529,8 +1516,7 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
|
|
1529
1516
|
|
1530
1517
|
if (protoName) {
|
1531
1518
|
const protoCands = Object.keys(prototypeFuncs).reduce((acc, x) => {
|
1532
|
-
|
1533
|
-
if (f) acc[x] = f;
|
1519
|
+
if (Object.hasOwn(prototypeFuncs[x], protoName)) acc[x] = prototypeFuncs[x][protoName];
|
1534
1520
|
return acc;
|
1535
1521
|
}, {});
|
1536
1522
|
|
@@ -1928,6 +1914,8 @@ const extractTypeAnnotation = decl => {
|
|
1928
1914
|
const typeName = type;
|
1929
1915
|
type = typeAnnoToPorfType(type);
|
1930
1916
|
|
1917
|
+
if (type === TYPES._bytestring && !process.argv.includes('-bytestring')) type = TYPES.string;
|
1918
|
+
|
1931
1919
|
// if (decl.name) console.log(decl.name, { type, elementType });
|
1932
1920
|
|
1933
1921
|
return { type, typeName, elementType };
|
@@ -2327,8 +2315,10 @@ const generateFor = (scope, decl) => {
|
|
2327
2315
|
out.push([ Opcodes.loop, Blocktype.void ]);
|
2328
2316
|
depth.push('for');
|
2329
2317
|
|
2330
|
-
out.push(...generate(scope, decl.test));
|
2331
|
-
|
2318
|
+
if (decl.test) out.push(...generate(scope, decl.test), Opcodes.i32_to);
|
2319
|
+
else out.push(...number(1, Valtype.i32));
|
2320
|
+
|
2321
|
+
out.push([ Opcodes.if, Blocktype.void ]);
|
2332
2322
|
depth.push('if');
|
2333
2323
|
|
2334
2324
|
out.push([ Opcodes.block, Blocktype.void ]);
|
@@ -2336,8 +2326,7 @@ const generateFor = (scope, decl) => {
|
|
2336
2326
|
out.push(...generate(scope, decl.body));
|
2337
2327
|
out.push([ Opcodes.end ]);
|
2338
2328
|
|
2339
|
-
out.push(...generate(scope, decl.update));
|
2340
|
-
depth.pop();
|
2329
|
+
if (decl.update) out.push(...generate(scope, decl.update));
|
2341
2330
|
|
2342
2331
|
out.push([ Opcodes.br, 1 ]);
|
2343
2332
|
out.push([ Opcodes.end ], [ Opcodes.end ]);
|
@@ -2535,7 +2524,7 @@ const generateThrow = (scope, decl) => {
|
|
2535
2524
|
// hack: throw new X("...") -> throw "..."
|
2536
2525
|
if (!message && (decl.argument.type === 'NewExpression' || decl.argument.type === 'CallExpression')) {
|
2537
2526
|
constructor = decl.argument.callee.name;
|
2538
|
-
message = decl.argument.arguments[0]
|
2527
|
+
message = decl.argument.arguments[0]?.value ?? '';
|
2539
2528
|
}
|
2540
2529
|
|
2541
2530
|
if (tags.length === 0) tags.push({
|
@@ -2887,11 +2876,14 @@ const objectHack = node => {
|
|
2887
2876
|
// if object is not identifier or another member exp, give up
|
2888
2877
|
if (node.object.type !== 'Identifier' && node.object.type !== 'MemberExpression') return node;
|
2889
2878
|
|
2890
|
-
if (!objectName) objectName = objectHack(node.object)
|
2879
|
+
if (!objectName) objectName = objectHack(node.object)?.name?.slice?.(2);
|
2891
2880
|
|
2892
2881
|
// if .length, give up (hack within a hack!)
|
2893
2882
|
if (node.property.name === 'length') return node;
|
2894
2883
|
|
2884
|
+
// no object name, give up
|
2885
|
+
if (!objectName) return node;
|
2886
|
+
|
2895
2887
|
const name = '__' + objectName + '_' + node.property.name;
|
2896
2888
|
if (codeLog) log('codegen', `object hack! ${node.object.name}.${node.property.name} -> ${name}`);
|
2897
2889
|
|
package/package.json
CHANGED