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 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 `porffor-for-vscode` which tweaks JS syntax highlighting to be nicer with porffor features (eg highlighting wasm inside of inline asm).
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 keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
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);
@@ -1,2 +1,10 @@
1
1
  export type i32 = number;
2
- export type bytestring = string;
2
+ export type bytestring = string;
3
+
4
+ type PorfforGlobal = {
5
+ wasm: (...args: any[]) => void;
6
+ };
7
+
8
+ declare global {
9
+ const Porffor: PorfforGlobal;
10
+ }
@@ -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: process.argv.includes('-bytestring') ? '_bytestring' : 'string',
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) {
@@ -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
- __Porffor_asm: str => {
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 str = decl.quasi.quasis[0].value.raw;
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
- if (decl.type.startsWith('TS')) {
223
- // ignore typescript nodes
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 finalise = out => startOut.concat(out, endOut);
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
- // if (leftType === TYPES.string || rightType === TYPES.string) {
838
- // if (op === '+') {
839
- // // string concat (a + b)
840
- // return finalise(concatStrings(scope, left, right, _global, _name, assign));
841
- // }
842
-
843
- // // not an equality op, NaN
844
- // if (!eqOp) return finalise(number(NaN));
845
-
846
- // // else leave bool ops
847
- // // todo: convert string to number if string and number/bool
848
- // // todo: string (>|>=|<|<=) string
849
-
850
- // // string comparison
851
- // if (op === '===' || op === '==') {
852
- // return finalise(compareStrings(scope, left, right));
853
- // }
854
-
855
- // if (op === '!==' || op === '!=') {
856
- // return finalise([
857
- // ...compareStrings(scope, left, right),
858
- // [ Opcodes.i32_eqz ]
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 finalise([
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 finalise([
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 process.argv.includes('-bytestring') ? TYPES._bytestring : TYPES.string;
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 typedReturn = userFunc || builtinFuncs[name]?.typedReturn;
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 (!typedReturn) {
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 (!process.argv.includes('-bytestring')) delete bc[TYPES._bytestring];
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 (process.argv.includes('-typeswitch-use-brtable'))
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
- let typeIdx = global ? globalInd++ : scope.localInd++;
1874
- target[name + '#type'] = { idx: typeIdx, type: Valtype.i32 };
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 && !process.argv.includes('-bytestring')) type = TYPES.string;
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
- if (allocLog) log('alloc', `allocated new page of memory (${ind}) | ${reason} (type: ${type})`);
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 (!process.argv.includes('-bytestring')) return false;
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 = process.argv.includes('-bytestring');
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 (process.argv.includes('-ast-log')) console.log(program.body.body);
3158
+ if (Prefs.astLog) console.log(program.body.body);
3127
3159
 
3128
3160
  generateFunc(scope, program);
3129
3161
 
@@ -0,0 +1,3 @@
1
+
2
+ export const BuiltinFuncs = function() {
3
+ };
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 (process.argv.includes('-funcs')) logFuncs(funcs, globals, exceptions);
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 (process.argv.includes('-opt-funcs')) logFuncs(funcs, globals, exceptions);
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 = getArg('target') ?? getArg('t') ?? 'wasm';
69
- const outFile = getArg('o');
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 = getArg('compiler') ?? 'clang';
92
- const cO = getArg('cO') ?? 'Ofast';
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 ];