porffor 0.2.0-cb647c8 → 0.2.0-dcc06c8
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 +1 -1
- package/compiler/builtins/base64.ts +23 -3
- package/compiler/builtins/porffor.d.ts +9 -1
- package/compiler/builtins.js +2 -1
- package/compiler/codeGen.js +91 -59
- package/compiler/generated_builtins.js +3 -0
- package/compiler/index.js +9 -15
- package/compiler/opt.js +39 -26
- package/compiler/parse.js +4 -2
- package/compiler/precompile.js +79 -0
- package/compiler/prefs.js +22 -0
- package/compiler/prototype.js +9 -8
- package/compiler/sections.js +7 -6
- package/demo.js +2 -2
- package/hello +0 -0
- package/package.json +1 -1
- package/rhemyn/compile.js +2 -1
- package/tmp.c +20 -1116
package/README.md
CHANGED
@@ -272,7 +272,7 @@ Basically none right now (other than giving people headaches). Potential ideas:
|
|
272
272
|
- More in future probably?
|
273
273
|
|
274
274
|
## VSCode extension
|
275
|
-
There is a vscode extension in `
|
275
|
+
There is a vscode extension in `vscode-ext` which tweaks JS syntax highlighting to be nicer with porffor features (eg highlighting wasm inside of inline asm).
|
276
276
|
|
277
277
|
## Isn't this the same as AssemblyScript/other Wasm langs?
|
278
278
|
No. they are not alike at all internally and have very different goals/ideals:
|
@@ -2,12 +2,12 @@
|
|
2
2
|
|
3
3
|
import type { i32, bytestring } from './porffor.d.ts';
|
4
4
|
|
5
|
-
const
|
5
|
+
export const btoa = (input: bytestring): bytestring => {
|
6
|
+
const keyStr: bytestring = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
|
6
7
|
|
7
|
-
const btoa = (input: bytestring): bytestring => {
|
8
8
|
// todo: throw invalid character for unicode
|
9
9
|
|
10
|
-
let output: bytestring =
|
10
|
+
let output: bytestring = '';
|
11
11
|
let i: i32 = 0;
|
12
12
|
|
13
13
|
while (i < input.length) {
|
@@ -27,6 +27,26 @@ const btoa = (input: bytestring): bytestring => {
|
|
27
27
|
enc4 = 64;
|
28
28
|
}
|
29
29
|
|
30
|
+
// const endPtr: i32 = output.length * 2;
|
31
|
+
|
32
|
+
// smile :)
|
33
|
+
// Porffor.wasm`local.get ${enc1}
|
34
|
+
// i32.to_u
|
35
|
+
// i32.const 2
|
36
|
+
// i32.mul
|
37
|
+
// local.get ${keyStr}
|
38
|
+
// i32.to_u
|
39
|
+
// i32.add
|
40
|
+
// i32.load16_u 0 4
|
41
|
+
|
42
|
+
// local.get ${output}
|
43
|
+
// i32.to_u
|
44
|
+
// local.get ${endPtr}
|
45
|
+
// i32.to_u
|
46
|
+
// i32.add
|
47
|
+
|
48
|
+
// i32.store16 0 4`;
|
49
|
+
|
30
50
|
output += keyStr.charAt(enc1);
|
31
51
|
output += keyStr.charAt(enc2);
|
32
52
|
output += keyStr.charAt(enc3);
|
package/compiler/builtins.js
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
import { Blocktype, Opcodes, Valtype, ValtypeSize } from "./wasmSpec.js";
|
2
2
|
import { number, i32x4 } from "./embedding.js";
|
3
|
+
import Prefs from './prefs.js';
|
3
4
|
|
4
5
|
export const importedFuncs = [
|
5
6
|
{
|
@@ -685,7 +686,7 @@ export const BuiltinFuncs = function() {
|
|
685
686
|
typedParams: true,
|
686
687
|
locals: [ Valtype.i32, Valtype.i32 ],
|
687
688
|
returns: [ valtypeBinary ],
|
688
|
-
returnType:
|
689
|
+
returnType: Prefs.bytestring ? '_bytestring' : 'string',
|
689
690
|
wasm: (scope, { TYPE_NAMES, typeSwitch, makeString }) => {
|
690
691
|
const bc = {};
|
691
692
|
for (const x in TYPE_NAMES) {
|
package/compiler/codeGen.js
CHANGED
@@ -7,6 +7,7 @@ import { number, i32x4, enforceOneByte, enforceTwoBytes, enforceFourBytes, enfor
|
|
7
7
|
import { log } from "./log.js";
|
8
8
|
import parse from "./parse.js";
|
9
9
|
import * as Rhemyn from "../rhemyn/compile.js";
|
10
|
+
import Prefs from './prefs.js';
|
10
11
|
|
11
12
|
let globals = {};
|
12
13
|
let globalInd = 0;
|
@@ -160,7 +161,7 @@ const generate = (scope, decl, global = false, name = undefined, valueUnused = f
|
|
160
161
|
|
161
162
|
case 'TaggedTemplateExpression': {
|
162
163
|
const funcs = {
|
163
|
-
|
164
|
+
__Porffor_wasm: str => {
|
164
165
|
let out = [];
|
165
166
|
|
166
167
|
for (const line of str.split('\n')) {
|
@@ -179,7 +180,7 @@ const generate = (scope, decl, global = false, name = undefined, valueUnused = f
|
|
179
180
|
}
|
180
181
|
|
181
182
|
if (asm[0] === 'memory') {
|
182
|
-
allocPage('asm instrinsic');
|
183
|
+
allocPage(scope, 'asm instrinsic');
|
183
184
|
// todo: add to store/load offset insts
|
184
185
|
continue;
|
185
186
|
}
|
@@ -214,13 +215,23 @@ const generate = (scope, decl, global = false, name = undefined, valueUnused = f
|
|
214
215
|
// hack for inline asm
|
215
216
|
if (!funcs[name]) return todo('tagged template expressions not implemented');
|
216
217
|
|
217
|
-
const
|
218
|
+
const { quasis, expressions } = decl.quasi;
|
219
|
+
let str = quasis[0].value.raw;
|
220
|
+
|
221
|
+
for (let i = 0; i < expressions.length; i++) {
|
222
|
+
const e = expressions[i];
|
223
|
+
str += lookupName(scope, e.name)[0];
|
224
|
+
|
225
|
+
str += quasis[i + 1].value.raw;
|
226
|
+
}
|
227
|
+
|
218
228
|
return funcs[name](str);
|
219
229
|
}
|
220
230
|
|
221
231
|
default:
|
222
|
-
|
223
|
-
|
232
|
+
// ignore typescript nodes
|
233
|
+
if (decl.type.startsWith('TS') ||
|
234
|
+
decl.type === 'ImportDeclaration' && decl.importKind === 'type') {
|
224
235
|
return [];
|
225
236
|
}
|
226
237
|
|
@@ -409,9 +420,6 @@ const concatStrings = (scope, left, right, global, name, assign) => {
|
|
409
420
|
const rightLength = localTmp(scope, 'concat_right_length', Valtype.i32);
|
410
421
|
const leftLength = localTmp(scope, 'concat_left_length', Valtype.i32);
|
411
422
|
|
412
|
-
const aotWFA = process.argv.includes('-aot-well-formed-string-approximation');
|
413
|
-
if (aotWFA) addVarMeta(name, { wellFormed: undefined });
|
414
|
-
|
415
423
|
if (assign) {
|
416
424
|
const pointer = arrays.get(name ?? '$undeclared');
|
417
425
|
|
@@ -785,11 +793,14 @@ const performOp = (scope, op, left, right, leftType, rightType, _global = false,
|
|
785
793
|
return performLogicOp(scope, op, left, right, leftType, rightType);
|
786
794
|
}
|
787
795
|
|
796
|
+
const knownLeft = knownType(scope, leftType);
|
797
|
+
const knownRight = knownType(scope, rightType);
|
798
|
+
|
788
799
|
const eqOp = ['==', '===', '!=', '!==', '>', '>=', '<', '<='].includes(op);
|
789
800
|
const strictOp = op === '===' || op === '!==';
|
790
801
|
|
791
802
|
const startOut = [], endOut = [];
|
792
|
-
const
|
803
|
+
const finalize = out => startOut.concat(out, endOut);
|
793
804
|
|
794
805
|
// if strict (in)equal check types match
|
795
806
|
if (strictOp) {
|
@@ -834,31 +845,32 @@ const performOp = (scope, op, left, right, leftType, rightType, _global = false,
|
|
834
845
|
// todo: if equality op and an operand is undefined, return false
|
835
846
|
// todo: niche null hell with 0
|
836
847
|
|
837
|
-
//
|
838
|
-
|
839
|
-
|
840
|
-
|
841
|
-
|
842
|
-
|
843
|
-
|
844
|
-
|
845
|
-
|
846
|
-
|
847
|
-
|
848
|
-
|
849
|
-
|
850
|
-
|
851
|
-
|
852
|
-
|
853
|
-
|
854
|
-
|
855
|
-
|
856
|
-
|
857
|
-
|
858
|
-
|
859
|
-
|
860
|
-
|
861
|
-
|
848
|
+
// todo: this should be dynamic but for now only static
|
849
|
+
if (knownLeft === TYPES.string || knownRight === TYPES.string) {
|
850
|
+
if (op === '+') {
|
851
|
+
// string concat (a + b)
|
852
|
+
return concatStrings(scope, left, right, _global, _name, assign);
|
853
|
+
}
|
854
|
+
|
855
|
+
// not an equality op, NaN
|
856
|
+
if (!eqOp) return number(NaN);
|
857
|
+
|
858
|
+
// else leave bool ops
|
859
|
+
// todo: convert string to number if string and number/bool
|
860
|
+
// todo: string (>|>=|<|<=) string
|
861
|
+
|
862
|
+
// string comparison
|
863
|
+
if (op === '===' || op === '==') {
|
864
|
+
return compareStrings(scope, left, right);
|
865
|
+
}
|
866
|
+
|
867
|
+
if (op === '!==' || op === '!=') {
|
868
|
+
return [
|
869
|
+
...compareStrings(scope, left, right),
|
870
|
+
[ Opcodes.i32_eqz ]
|
871
|
+
];
|
872
|
+
}
|
873
|
+
}
|
862
874
|
|
863
875
|
let ops = operatorOpcode[valtype][op];
|
864
876
|
|
@@ -868,7 +880,7 @@ const performOp = (scope, op, left, right, leftType, rightType, _global = false,
|
|
868
880
|
includeBuiltin(scope, builtinName);
|
869
881
|
const idx = funcIndex[builtinName];
|
870
882
|
|
871
|
-
return
|
883
|
+
return finalize([
|
872
884
|
...left,
|
873
885
|
...right,
|
874
886
|
[ Opcodes.call, idx ]
|
@@ -883,9 +895,6 @@ const performOp = (scope, op, left, right, leftType, rightType, _global = false,
|
|
883
895
|
let tmpLeft, tmpRight;
|
884
896
|
// if equal op, check if strings for compareStrings
|
885
897
|
if (op === '===' || op === '==' || op === '!==' || op === '!=') (() => {
|
886
|
-
const knownLeft = knownType(scope, leftType);
|
887
|
-
const knownRight = knownType(scope, rightType);
|
888
|
-
|
889
898
|
// todo: intelligent partial skip later
|
890
899
|
// if neither known are string, stop this madness
|
891
900
|
if ((knownLeft != null && knownLeft !== TYPES.string) && (knownRight != null && knownRight !== TYPES.string)) {
|
@@ -943,7 +952,7 @@ const performOp = (scope, op, left, right, leftType, rightType, _global = false,
|
|
943
952
|
// }
|
944
953
|
})();
|
945
954
|
|
946
|
-
return
|
955
|
+
return finalize([
|
947
956
|
...left,
|
948
957
|
...(tmpLeft != null ? stringOnly([ [ Opcodes.local_tee, tmpLeft ] ]) : []),
|
949
958
|
...right,
|
@@ -1086,7 +1095,10 @@ const TYPE_NAMES = {
|
|
1086
1095
|
const getType = (scope, _name) => {
|
1087
1096
|
const name = mapName(_name);
|
1088
1097
|
|
1098
|
+
if (typedInput && scope.locals[name]?.metadata?.type != null) return number(scope.locals[name].metadata.type, Valtype.i32);
|
1089
1099
|
if (scope.locals[name]) return [ [ Opcodes.local_get, scope.locals[name + '#type'].idx ] ];
|
1100
|
+
|
1101
|
+
if (typedInput && globals[name]?.metadata?.type != null) return number(globals[name].metadata.type, Valtype.i32);
|
1090
1102
|
if (globals[name]) return [ [ Opcodes.global_get, globals[name + '#type'].idx ] ];
|
1091
1103
|
|
1092
1104
|
let type = TYPES.undefined;
|
@@ -1227,6 +1239,14 @@ const getNodeType = (scope, node) => {
|
|
1227
1239
|
|
1228
1240
|
if (node.type === 'BinaryExpression') {
|
1229
1241
|
if (['==', '===', '!=', '!==', '>', '>=', '<', '<='].includes(node.operator)) return TYPES.boolean;
|
1242
|
+
if (node.operator !== '+') return TYPES.number;
|
1243
|
+
|
1244
|
+
const knownLeft = knownType(scope, getNodeType(scope, node.left));
|
1245
|
+
const knownRight = knownType(scope, getNodeType(scope, node.right));
|
1246
|
+
|
1247
|
+
// todo: this should be dynamic but for now only static
|
1248
|
+
if (knownLeft === TYPES.string || knownRight === TYPES.string) return TYPES.string;
|
1249
|
+
|
1230
1250
|
return TYPES.number;
|
1231
1251
|
|
1232
1252
|
// todo: string concat types
|
@@ -1251,7 +1271,7 @@ const getNodeType = (scope, node) => {
|
|
1251
1271
|
if (node.operator === '!') return TYPES.boolean;
|
1252
1272
|
if (node.operator === 'void') return TYPES.undefined;
|
1253
1273
|
if (node.operator === 'delete') return TYPES.boolean;
|
1254
|
-
if (node.operator === 'typeof') return
|
1274
|
+
if (node.operator === 'typeof') return Prefs.bytestring ? TYPES._bytestring : TYPES.string;
|
1255
1275
|
|
1256
1276
|
return TYPES.number;
|
1257
1277
|
}
|
@@ -1654,7 +1674,7 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
|
|
1654
1674
|
|
1655
1675
|
const userFunc = (funcIndex[name] && !importedFuncs[name] && !builtinFuncs[name] && !internalConstrs[name]) || idx === -1;
|
1656
1676
|
const typedParams = userFunc || builtinFuncs[name]?.typedParams;
|
1657
|
-
const
|
1677
|
+
const typedReturns = userFunc || builtinFuncs[name]?.typedReturns;
|
1658
1678
|
const paramCount = func && (typedParams ? func.params.length / 2 : func.params.length);
|
1659
1679
|
|
1660
1680
|
let args = decl.arguments;
|
@@ -1678,7 +1698,7 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
|
|
1678
1698
|
|
1679
1699
|
out.push([ Opcodes.call, idx ]);
|
1680
1700
|
|
1681
|
-
if (!
|
1701
|
+
if (!typedReturns) {
|
1682
1702
|
// let type;
|
1683
1703
|
// if (builtinFuncs[name]) type = TYPES[builtinFuncs[name].returnType ?? 'number'];
|
1684
1704
|
// if (internalConstrs[name]) type = internalConstrs[name].type;
|
@@ -1814,14 +1834,14 @@ const brTable = (input, bc, returns) => {
|
|
1814
1834
|
};
|
1815
1835
|
|
1816
1836
|
const typeSwitch = (scope, type, bc, returns = valtypeBinary) => {
|
1817
|
-
if (!
|
1837
|
+
if (!Prefs.bytestring) delete bc[TYPES._bytestring];
|
1818
1838
|
|
1819
1839
|
const known = knownType(scope, type);
|
1820
1840
|
if (known != null) {
|
1821
1841
|
return bc[known] ?? bc.default;
|
1822
1842
|
}
|
1823
1843
|
|
1824
|
-
if (
|
1844
|
+
if (Prefs.typeswitchUseBrtable)
|
1825
1845
|
return brTable(type, bc, returns);
|
1826
1846
|
|
1827
1847
|
const tmp = localTmp(scope, '#typeswitch_tmp', Valtype.i32);
|
@@ -1856,7 +1876,7 @@ const typeSwitch = (scope, type, bc, returns = valtypeBinary) => {
|
|
1856
1876
|
return out;
|
1857
1877
|
};
|
1858
1878
|
|
1859
|
-
const allocVar = (scope, name, global = false) => {
|
1879
|
+
const allocVar = (scope, name, global = false, type = true) => {
|
1860
1880
|
const target = global ? globals : scope.locals;
|
1861
1881
|
|
1862
1882
|
// already declared
|
@@ -1870,8 +1890,10 @@ const allocVar = (scope, name, global = false) => {
|
|
1870
1890
|
let idx = global ? globalInd++ : scope.localInd++;
|
1871
1891
|
target[name] = { idx, type: valtypeBinary };
|
1872
1892
|
|
1873
|
-
|
1874
|
-
|
1893
|
+
if (type) {
|
1894
|
+
let typeIdx = global ? globalInd++ : scope.localInd++;
|
1895
|
+
target[name + '#type'] = { idx: typeIdx, type: Valtype.i32 };
|
1896
|
+
}
|
1875
1897
|
|
1876
1898
|
return idx;
|
1877
1899
|
};
|
@@ -1914,7 +1936,7 @@ const extractTypeAnnotation = decl => {
|
|
1914
1936
|
const typeName = type;
|
1915
1937
|
type = typeAnnoToPorfType(type);
|
1916
1938
|
|
1917
|
-
if (type === TYPES._bytestring && !
|
1939
|
+
if (type === TYPES._bytestring && !Prefs.bytestring) type = TYPES.string;
|
1918
1940
|
|
1919
1941
|
// if (decl.name) console.log(decl.name, { type, elementType });
|
1920
1942
|
|
@@ -1949,7 +1971,7 @@ const generateVar = (scope, decl) => {
|
|
1949
1971
|
continue; // always ignore
|
1950
1972
|
}
|
1951
1973
|
|
1952
|
-
let idx = allocVar(scope, name, global);
|
1974
|
+
let idx = allocVar(scope, name, global, !x.id.typeAnnotation);
|
1953
1975
|
|
1954
1976
|
if (typedInput && x.id.typeAnnotation) {
|
1955
1977
|
addVarMetadata(scope, name, global, extractTypeAnnotation(x.id));
|
@@ -2546,6 +2568,9 @@ const generateThrow = (scope, decl) => {
|
|
2546
2568
|
let exceptId = exceptions.push({ constructor, message }) - 1;
|
2547
2569
|
let tagIdx = tags[0].idx;
|
2548
2570
|
|
2571
|
+
scope.exceptions ??= [];
|
2572
|
+
scope.exceptions.push(exceptId);
|
2573
|
+
|
2549
2574
|
// todo: write a description of how this works lol
|
2550
2575
|
|
2551
2576
|
return [
|
@@ -2590,7 +2615,7 @@ const generateAssignPat = (scope, decl) => {
|
|
2590
2615
|
};
|
2591
2616
|
|
2592
2617
|
let pages = new Map();
|
2593
|
-
const allocPage = (reason, type) => {
|
2618
|
+
const allocPage = (scope, reason, type) => {
|
2594
2619
|
if (pages.has(reason)) return pages.get(reason).ind;
|
2595
2620
|
|
2596
2621
|
if (reason.startsWith('array:')) pages.hasArray = true;
|
@@ -2601,16 +2626,20 @@ const allocPage = (reason, type) => {
|
|
2601
2626
|
const ind = pages.size;
|
2602
2627
|
pages.set(reason, { ind, type });
|
2603
2628
|
|
2604
|
-
|
2629
|
+
scope.pages ??= new Map();
|
2630
|
+
scope.pages.set(reason, { ind, type });
|
2631
|
+
|
2632
|
+
if (Prefs.allocLog) log('alloc', `allocated new page of memory (${ind}) | ${reason} (type: ${type})`);
|
2605
2633
|
|
2606
2634
|
return ind;
|
2607
2635
|
};
|
2608
2636
|
|
2637
|
+
// todo: add scope.pages
|
2609
2638
|
const freePage = reason => {
|
2610
2639
|
const { ind } = pages.get(reason);
|
2611
2640
|
pages.delete(reason);
|
2612
2641
|
|
2613
|
-
if (allocLog) log('alloc', `freed page of memory (${ind}) | ${reason}`);
|
2642
|
+
if (Prefs.allocLog) log('alloc', `freed page of memory (${ind}) | ${reason}`);
|
2614
2643
|
|
2615
2644
|
return ind;
|
2616
2645
|
};
|
@@ -2667,7 +2696,7 @@ const makeArray = (scope, decl, global = false, name = '$undeclared', initEmpty
|
|
2667
2696
|
|
2668
2697
|
// todo: can we just have 1 undeclared array? probably not? but this is not really memory efficient
|
2669
2698
|
const uniqueName = name === '$undeclared' ? name + Math.random().toString().slice(2) : name;
|
2670
|
-
arrays.set(name, allocPage(`${getAllocType(itemType)}: ${uniqueName}`, itemType) * pageSize);
|
2699
|
+
arrays.set(name, allocPage(scope, `${getAllocType(itemType)}: ${uniqueName}`, itemType) * pageSize);
|
2671
2700
|
}
|
2672
2701
|
|
2673
2702
|
const pointer = arrays.get(name);
|
@@ -2687,10 +2716,13 @@ const makeArray = (scope, decl, global = false, name = '$undeclared', initEmpty
|
|
2687
2716
|
bytes.push(...compileBytes(elements[i], itemType));
|
2688
2717
|
}
|
2689
2718
|
|
2690
|
-
data.push({
|
2719
|
+
const ind = data.push({
|
2691
2720
|
offset: pointer,
|
2692
2721
|
bytes
|
2693
|
-
});
|
2722
|
+
}) - 1;
|
2723
|
+
|
2724
|
+
scope.data ??= [];
|
2725
|
+
scope.data.push(ind);
|
2694
2726
|
|
2695
2727
|
// local value as pointer
|
2696
2728
|
out.push(...number(pointer));
|
@@ -2724,7 +2756,7 @@ const makeArray = (scope, decl, global = false, name = '$undeclared', initEmpty
|
|
2724
2756
|
};
|
2725
2757
|
|
2726
2758
|
const byteStringable = str => {
|
2727
|
-
if (!
|
2759
|
+
if (!Prefs.bytestring) return false;
|
2728
2760
|
|
2729
2761
|
for (let i = 0; i < str.length; i++) {
|
2730
2762
|
if (str.charCodeAt(i) > 0xFF) return false;
|
@@ -2735,7 +2767,7 @@ const byteStringable = str => {
|
|
2735
2767
|
|
2736
2768
|
const makeString = (scope, str, global = false, name = '$undeclared', forceBytestring = undefined) => {
|
2737
2769
|
const rawElements = new Array(str.length);
|
2738
|
-
let byteStringable =
|
2770
|
+
let byteStringable = Prefs.bytestring;
|
2739
2771
|
for (let i = 0; i < str.length; i++) {
|
2740
2772
|
const c = str.charCodeAt(i);
|
2741
2773
|
rawElements[i] = c;
|
@@ -2896,7 +2928,7 @@ const objectHack = node => {
|
|
2896
2928
|
if (!objectName) return node;
|
2897
2929
|
|
2898
2930
|
const name = '__' + objectName + '_' + node.property.name;
|
2899
|
-
if (codeLog) log('codegen', `object hack! ${node.object.name}.${node.property.name} -> ${name}`);
|
2931
|
+
if (Prefs.codeLog) log('codegen', `object hack! ${node.object.name}.${node.property.name} -> ${name}`);
|
2900
2932
|
|
2901
2933
|
return {
|
2902
2934
|
type: 'Identifier',
|
@@ -3123,7 +3155,7 @@ export default program => {
|
|
3123
3155
|
body: program.body
|
3124
3156
|
};
|
3125
3157
|
|
3126
|
-
if (
|
3158
|
+
if (Prefs.astLog) console.log(program.body.body);
|
3127
3159
|
|
3128
3160
|
generateFunc(scope, program);
|
3129
3161
|
|
package/compiler/index.js
CHANGED
@@ -5,6 +5,7 @@ import opt from './opt.js';
|
|
5
5
|
import produceSections from './sections.js';
|
6
6
|
import decompile from './decompile.js';
|
7
7
|
import toc from './2c.js';
|
8
|
+
import Prefs from './prefs.js';
|
8
9
|
|
9
10
|
globalThis.decompile = decompile;
|
10
11
|
|
@@ -25,17 +26,10 @@ const logFuncs = (funcs, globals, exceptions) => {
|
|
25
26
|
console.log();
|
26
27
|
};
|
27
28
|
|
28
|
-
const getArg = name => process.argv.find(x => x.startsWith(`-${name}=`))?.slice(name.length + 2);
|
29
|
-
|
30
29
|
const writeFileSync = (typeof process?.version !== 'undefined' ? (await import('node:fs')).writeFileSync : undefined);
|
31
30
|
const execSync = (typeof process?.version !== 'undefined' ? (await import('node:child_process')).execSync : undefined);
|
32
31
|
|
33
32
|
export default (code, flags) => {
|
34
|
-
globalThis.optLog = process.argv.includes('-opt-log');
|
35
|
-
globalThis.codeLog = process.argv.includes('-code-log');
|
36
|
-
globalThis.allocLog = process.argv.includes('-alloc-log');
|
37
|
-
globalThis.regexLog = process.argv.includes('-regex-log');
|
38
|
-
|
39
33
|
const t0 = performance.now();
|
40
34
|
const program = parse(code, flags);
|
41
35
|
if (flags.includes('info')) console.log(`1. parsed in ${(performance.now() - t0).toFixed(2)}ms`);
|
@@ -44,19 +38,19 @@ export default (code, flags) => {
|
|
44
38
|
const { funcs, globals, tags, exceptions, pages, data } = codeGen(program);
|
45
39
|
if (flags.includes('info')) console.log(`2. generated code in ${(performance.now() - t1).toFixed(2)}ms`);
|
46
40
|
|
47
|
-
if (
|
41
|
+
if (Prefs.funcs) logFuncs(funcs, globals, exceptions);
|
48
42
|
|
49
43
|
const t2 = performance.now();
|
50
|
-
opt(funcs, globals, pages, tags);
|
44
|
+
opt(funcs, globals, pages, tags, exceptions);
|
51
45
|
if (flags.includes('info')) console.log(`3. optimized code in ${(performance.now() - t2).toFixed(2)}ms`);
|
52
46
|
|
53
|
-
if (
|
47
|
+
if (Prefs.optFuncs) logFuncs(funcs, globals, exceptions);
|
54
48
|
|
55
49
|
const t3 = performance.now();
|
56
50
|
const sections = produceSections(funcs, globals, tags, pages, data, flags);
|
57
51
|
if (flags.includes('info')) console.log(`4. produced sections in ${(performance.now() - t3).toFixed(2)}ms`);
|
58
52
|
|
59
|
-
if (allocLog) {
|
53
|
+
if (Prefs.allocLog) {
|
60
54
|
const wasmPages = Math.ceil((pages.size * pageSize) / 65536);
|
61
55
|
const bytes = wasmPages * 65536;
|
62
56
|
log('alloc', `\x1B[1mallocated ${bytes / 1024}KiB\x1B[0m for ${pages.size} things using ${wasmPages} Wasm page${wasmPages === 1 ? '' : 's'}`);
|
@@ -65,8 +59,8 @@ export default (code, flags) => {
|
|
65
59
|
|
66
60
|
const out = { wasm: sections, funcs, globals, tags, exceptions, pages, data };
|
67
61
|
|
68
|
-
const target =
|
69
|
-
const outFile =
|
62
|
+
const target = Prefs.target ?? 'wasm';
|
63
|
+
const outFile = Prefs.o;
|
70
64
|
|
71
65
|
if (target === 'wasm' && outFile) {
|
72
66
|
writeFileSync(outFile, Buffer.from(sections));
|
@@ -88,8 +82,8 @@ export default (code, flags) => {
|
|
88
82
|
}
|
89
83
|
|
90
84
|
if (target === 'native') {
|
91
|
-
let compiler =
|
92
|
-
const cO =
|
85
|
+
let compiler = Prefs.compiler ?? 'clang';
|
86
|
+
const cO = Prefs._cO ?? 'Ofast';
|
93
87
|
|
94
88
|
if (compiler === 'zig') compiler = [ 'zig', 'cc' ];
|
95
89
|
else compiler = [ compiler ];
|