porffor 0.2.0-15592d6 → 0.2.0-181627c

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.
@@ -2,6 +2,38 @@
2
2
 
3
3
  import type { i32, bytestring } from './porffor.d.ts';
4
4
 
5
+ // const appendKeyChar = (target: bytestring, ind: i32): bytestring => {
6
+ // const keyStr: bytestring = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
7
+ // return target + keyStr.charAt(ind);
8
+ // };
9
+
10
+ // const appendKeyChar = (target: bytestring, ind: i32): void => {
11
+ // const keyStr: bytestring = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
12
+
13
+ // Porffor.bytestring.appendCharAt(target, keyStr, ind);
14
+
15
+ // Porffor.wasm`local.get ${ind}
16
+ // i32.to_u
17
+ // i32.const 2
18
+ // i32.mul
19
+ // local.get ${keyStr}
20
+ // i32.to_u
21
+ // i32.add
22
+ // i32.load8_u 0 4
23
+
24
+ // local targetI32 i32
25
+ // local.get ${target}
26
+ // i32.to_u
27
+ // local.tee targetI32
28
+ // local.get targetI32
29
+ // i32.load 1 0
30
+ // i32.const 2
31
+ // i32.mul
32
+ // i32.add
33
+
34
+ // i32.store8 0 4`;
35
+ // };
36
+
5
37
  export const btoa = (input: bytestring): bytestring => {
6
38
  const keyStr: bytestring = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
7
39
 
@@ -20,37 +52,22 @@ export const btoa = (input: bytestring): bytestring => {
20
52
  let enc3: i32 = ((chr2 & 15) << 2) | (chr3 >> 6);
21
53
  let enc4: i32 = chr3 & 63;
22
54
 
23
- if (isNaN(chr2)) {
55
+ if (Number.isNaN(chr2)) {
24
56
  enc3 = 64;
25
57
  enc4 = 64;
26
- } else if (isNaN(chr3)) {
58
+ } else if (Number.isNaN(chr3)) {
27
59
  enc4 = 64;
28
60
  }
29
61
 
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`;
62
+ Porffor.bytestring.appendCharAt(output, keyStr, enc1);
63
+ Porffor.bytestring.appendCharAt(output, keyStr, enc2);
64
+ Porffor.bytestring.appendCharAt(output, keyStr, enc3);
65
+ Porffor.bytestring.appendCharAt(output, keyStr, enc4);
49
66
 
50
- output += keyStr.charAt(enc1);
51
- output += keyStr.charAt(enc2);
52
- output += keyStr.charAt(enc3);
53
- output += keyStr.charAt(enc4);
67
+ // output += keyStr.charAt(enc1);
68
+ // output += keyStr.charAt(enc2);
69
+ // output += keyStr.charAt(enc3);
70
+ // output += keyStr.charAt(enc4);
54
71
  }
55
72
 
56
73
  return output;
@@ -74,13 +91,16 @@ export const btoa = (input: bytestring): bytestring => {
74
91
  chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
75
92
  chr3 = ((enc3 & 3) << 6) | enc4;
76
93
 
77
- output += String.fromCharCode(chr1);
94
+ // output += String.fromCharCode(chr1);
95
+ Porffor.bytestring.appendCharCode(output, chr1);
78
96
 
79
97
  if (enc3 != 64) {
80
- output += String.fromCharCode(chr2);
98
+ // output += String.fromCharCode(chr2);
99
+ Porffor.bytestring.appendCharCode(output, chr2);
81
100
  }
82
101
  if (enc4 != 64) {
83
- output += String.fromCharCode(chr3);
102
+ // output += String.fromCharCode(chr3);
103
+ Porffor.bytestring.appendCharCode(output, chr3);
84
104
  }
85
105
  }
86
106
 
@@ -3,6 +3,11 @@ export type bytestring = string;
3
3
 
4
4
  type PorfforGlobal = {
5
5
  wasm: (...args: any[]) => void;
6
+
7
+ bytestring: {
8
+ appendCharAt: (target: bytestring, lookup: bytestring, ind: i32) => void;
9
+ appendCharCode: (target: bytestring, code: i32) => void;
10
+ }
6
11
  };
7
12
 
8
13
  declare global {
@@ -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) {
@@ -722,6 +723,82 @@ export const BuiltinFuncs = function() {
722
723
  ]
723
724
  };
724
725
 
726
+ this.__Porffor_bytestring_appendCharAt = {
727
+ params: [ valtypeBinary, valtypeBinary, valtypeBinary ],
728
+ locals: [ Valtype.i32 ],
729
+ localNames: ['target', 'lookup', 'index', 'length'],
730
+ returns: [],
731
+ wasm: [
732
+ // get ptr for target[target.length]
733
+ [ Opcodes.local_get, 0 ],
734
+ Opcodes.i32_to_u,
735
+ [ Opcodes.local_get, 0 ],
736
+ Opcodes.i32_to_u,
737
+ [ Opcodes.i32_load, 1, 0 ],
738
+ [ Opcodes.local_tee, 3 ],
739
+ [ Opcodes.i32_const, 2 ],
740
+ [ Opcodes.i32_mul ],
741
+ [ Opcodes.i32_add ],
742
+
743
+ // get lookup[index]
744
+ [ Opcodes.local_get, 2 ],
745
+ Opcodes.i32_to_u,
746
+ [ Opcodes.i32_const, 2 ],
747
+ [ Opcodes.i32_mul ],
748
+ [ Opcodes.local_get, 1 ],
749
+ Opcodes.i32_to_u,
750
+ [ Opcodes.i32_add ],
751
+ [ Opcodes.i32_load8_u, 0, ValtypeSize.i32 ],
752
+
753
+ // store target[target.length] = lookup[index]
754
+ [ Opcodes.i32_store8, 0, 4 ],
755
+
756
+ // store target.length = target.length + 1
757
+ [ Opcodes.local_get, 0 ],
758
+ Opcodes.i32_to_u,
759
+ [ Opcodes.local_get, 3 ],
760
+ [ Opcodes.i32_const, 1 ],
761
+ [ Opcodes.i32_add ],
762
+ [ Opcodes.i32_store, 0, 0 ],
763
+ ]
764
+ };
765
+
766
+ this.__Porffor_bytestring_appendCharCode = {
767
+ params: [ valtypeBinary, valtypeBinary ],
768
+ locals: [ Valtype.i32 ],
769
+ localnames: ['target', 'code', 'length'],
770
+ returns: [],
771
+ wasm: [
772
+ // get ptr for target[target.length]
773
+ [ Opcodes.local_get, 0 ],
774
+ Opcodes.i32_to_u,
775
+ [ Opcodes.local_get, 0 ],
776
+ Opcodes.i32_to_u,
777
+ [ Opcodes.i32_load, 1, 0 ],
778
+ [ Opcodes.local_tee, 3 ],
779
+ [ Opcodes.i32_const, 2 ],
780
+ [ Opcodes.i32_mul ],
781
+ [ Opcodes.i32_add ],
782
+
783
+ // get code
784
+ [ Opcodes.local_get, 1 ],
785
+ [ Opcodes.i32_to_u ],
786
+
787
+ // set target[target.length] = code
788
+ [ Opcodes.i32_store8, 0, 4 ],
789
+
790
+ // store target.length = target.length + 1
791
+ [ Opcodes.local_get, 0 ],
792
+ Opcodes.i32_to_u,
793
+ [ Opcodes.local_get, 3 ],
794
+ [ Opcodes.i32_const, 1 ],
795
+ [ Opcodes.i32_add ],
796
+ [ Opcodes.i32_store, 0, 0 ],
797
+ ]
798
+ };
799
+
800
+ // todo: indexOfCharAt
801
+
725
802
 
726
803
  this.__SIMD_i32x4_load = {
727
804
  params: [ Valtype.i32 ],
@@ -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;
@@ -168,8 +169,8 @@ const generate = (scope, decl, global = false, name = undefined, valueUnused = f
168
169
  if (asm[0] === '') continue; // blank
169
170
 
170
171
  if (asm[0] === 'local') {
171
- const [ name, idx, type ] = asm.slice(1);
172
- scope.locals[name] = { idx: parseInt(idx), type: Valtype[type] };
172
+ const [ name, type ] = asm.slice(1);
173
+ scope.locals[name] = { idx: scope.localInd++, type: Valtype[type] };
173
174
  continue;
174
175
  }
175
176
 
@@ -188,7 +189,7 @@ const generate = (scope, decl, global = false, name = undefined, valueUnused = f
188
189
  if (!inst) throw new Error(`inline asm: inst ${asm[0]} not found`);
189
190
 
190
191
  if (!Array.isArray(inst)) inst = [ inst ];
191
- const immediates = asm.slice(1).map(x => parseInt(x));
192
+ const immediates = asm.slice(1).map(x => parseInt(x) || scope.locals[x]?.idx);
192
193
 
193
194
  out.push([ ...inst, ...immediates ]);
194
195
  }
@@ -419,9 +420,6 @@ const concatStrings = (scope, left, right, global, name, assign) => {
419
420
  const rightLength = localTmp(scope, 'concat_right_length', Valtype.i32);
420
421
  const leftLength = localTmp(scope, 'concat_left_length', Valtype.i32);
421
422
 
422
- const aotWFA = process.argv.includes('-aot-well-formed-string-approximation');
423
- if (aotWFA) addVarMeta(name, { wellFormed: undefined });
424
-
425
423
  if (assign) {
426
424
  const pointer = arrays.get(name ?? '$undeclared');
427
425
 
@@ -1273,7 +1271,7 @@ const getNodeType = (scope, node) => {
1273
1271
  if (node.operator === '!') return TYPES.boolean;
1274
1272
  if (node.operator === 'void') return TYPES.undefined;
1275
1273
  if (node.operator === 'delete') return TYPES.boolean;
1276
- 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;
1277
1275
 
1278
1276
  return TYPES.number;
1279
1277
  }
@@ -1836,14 +1834,14 @@ const brTable = (input, bc, returns) => {
1836
1834
  };
1837
1835
 
1838
1836
  const typeSwitch = (scope, type, bc, returns = valtypeBinary) => {
1839
- if (!process.argv.includes('-bytestring')) delete bc[TYPES._bytestring];
1837
+ if (!Prefs.bytestring) delete bc[TYPES._bytestring];
1840
1838
 
1841
1839
  const known = knownType(scope, type);
1842
1840
  if (known != null) {
1843
1841
  return bc[known] ?? bc.default;
1844
1842
  }
1845
1843
 
1846
- if (process.argv.includes('-typeswitch-use-brtable'))
1844
+ if (Prefs.typeswitchUseBrtable)
1847
1845
  return brTable(type, bc, returns);
1848
1846
 
1849
1847
  const tmp = localTmp(scope, '#typeswitch_tmp', Valtype.i32);
@@ -1938,7 +1936,7 @@ const extractTypeAnnotation = decl => {
1938
1936
  const typeName = type;
1939
1937
  type = typeAnnoToPorfType(type);
1940
1938
 
1941
- if (type === TYPES._bytestring && !process.argv.includes('-bytestring')) type = TYPES.string;
1939
+ if (type === TYPES._bytestring && !Prefs.bytestring) type = TYPES.string;
1942
1940
 
1943
1941
  // if (decl.name) console.log(decl.name, { type, elementType });
1944
1942
 
@@ -2631,7 +2629,7 @@ const allocPage = (scope, reason, type) => {
2631
2629
  scope.pages ??= new Map();
2632
2630
  scope.pages.set(reason, { ind, type });
2633
2631
 
2634
- if (allocLog) log('alloc', `allocated new page of memory (${ind}) | ${reason} (type: ${type})`);
2632
+ if (Prefs.allocLog) log('alloc', `allocated new page of memory (${ind}) | ${reason} (type: ${type})`);
2635
2633
 
2636
2634
  return ind;
2637
2635
  };
@@ -2641,7 +2639,7 @@ const freePage = reason => {
2641
2639
  const { ind } = pages.get(reason);
2642
2640
  pages.delete(reason);
2643
2641
 
2644
- if (allocLog) log('alloc', `freed page of memory (${ind}) | ${reason}`);
2642
+ if (Prefs.allocLog) log('alloc', `freed page of memory (${ind}) | ${reason}`);
2645
2643
 
2646
2644
  return ind;
2647
2645
  };
@@ -2710,21 +2708,24 @@ const makeArray = (scope, decl, global = false, name = '$undeclared', initEmpty
2710
2708
  const length = elements.length;
2711
2709
 
2712
2710
  if (firstAssign && useRawElements) {
2713
- let bytes = compileBytes(length, 'i32');
2711
+ // if length is 0 memory/data will just be 0000... anyway
2712
+ if (length !== 0) {
2713
+ let bytes = compileBytes(length, 'i32');
2714
2714
 
2715
- if (!initEmpty) for (let i = 0; i < length; i++) {
2716
- if (elements[i] == null) continue;
2715
+ if (!initEmpty) for (let i = 0; i < length; i++) {
2716
+ if (elements[i] == null) continue;
2717
2717
 
2718
- bytes.push(...compileBytes(elements[i], itemType));
2719
- }
2718
+ bytes.push(...compileBytes(elements[i], itemType));
2719
+ }
2720
2720
 
2721
- const ind = data.push({
2722
- offset: pointer,
2723
- bytes
2724
- }) - 1;
2721
+ const ind = data.push({
2722
+ offset: pointer,
2723
+ bytes
2724
+ }) - 1;
2725
2725
 
2726
- scope.data ??= [];
2727
- scope.data.push(ind);
2726
+ scope.data ??= [];
2727
+ scope.data.push(ind);
2728
+ }
2728
2729
 
2729
2730
  // local value as pointer
2730
2731
  out.push(...number(pointer));
@@ -2758,7 +2759,7 @@ const makeArray = (scope, decl, global = false, name = '$undeclared', initEmpty
2758
2759
  };
2759
2760
 
2760
2761
  const byteStringable = str => {
2761
- if (!process.argv.includes('-bytestring')) return false;
2762
+ if (!Prefs.bytestring) return false;
2762
2763
 
2763
2764
  for (let i = 0; i < str.length; i++) {
2764
2765
  if (str.charCodeAt(i) > 0xFF) return false;
@@ -2769,7 +2770,7 @@ const byteStringable = str => {
2769
2770
 
2770
2771
  const makeString = (scope, str, global = false, name = '$undeclared', forceBytestring = undefined) => {
2771
2772
  const rawElements = new Array(str.length);
2772
- let byteStringable = process.argv.includes('-bytestring');
2773
+ let byteStringable = Prefs.bytestring;
2773
2774
  for (let i = 0; i < str.length; i++) {
2774
2775
  const c = str.charCodeAt(i);
2775
2776
  rawElements[i] = c;
@@ -2930,7 +2931,7 @@ const objectHack = node => {
2930
2931
  if (!objectName) return node;
2931
2932
 
2932
2933
  const name = '__' + objectName + '_' + node.property.name;
2933
- if (codeLog) log('codegen', `object hack! ${node.object.name}.${node.property.name} -> ${name}`);
2934
+ if (Prefs.codeLog) log('codegen', `object hack! ${node.object.name}.${node.property.name} -> ${name}`);
2934
2935
 
2935
2936
  return {
2936
2937
  type: 'Identifier',
@@ -3157,7 +3158,7 @@ export default program => {
3157
3158
  body: program.body
3158
3159
  };
3159
3160
 
3160
- if (process.argv.includes('-ast-log')) console.log(program.body.body);
3161
+ if (Prefs.astLog) console.log(program.body.body);
3161
3162
 
3162
3163
  generateFunc(scope, program);
3163
3164
 
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
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 ];
package/compiler/opt.js CHANGED
@@ -2,6 +2,7 @@ import { Opcodes, Valtype } from "./wasmSpec.js";
2
2
  import { number } from "./embedding.js";
3
3
  import { read_signedLEB128, read_ieee754_binary64 } from "./encoding.js";
4
4
  import { log } from "./log.js";
5
+ import Prefs from './prefs.js';
5
6
 
6
7
  const performWasmOp = (op, a, b) => {
7
8
  switch (op) {
@@ -15,17 +16,17 @@ export default (funcs, globals, pages, tags, exceptions) => {
15
16
  const optLevel = parseInt(process.argv.find(x => x.startsWith('-O'))?.[2] ?? 1);
16
17
  if (optLevel === 0) return;
17
18
 
18
- const tailCall = process.argv.includes('-tail-call');
19
+ const tailCall = Prefs.tailCall;
19
20
  if (tailCall) log.warning('opt', 'tail call proposal is not widely implemented! (you used -tail-call)');
20
21
 
21
- if (optLevel >= 2 && !process.argv.includes('-opt-no-inline')) {
22
+ if (optLevel >= 2 && !Prefs.optNoInline) {
22
23
  // inline pass (very WIP)
23
24
  // get candidates for inlining
24
25
  // todo: pick smart in future (if func is used <N times? or?)
25
26
  const callsSelf = f => f.wasm.some(x => x[0] === Opcodes.call && x[1] === f.index);
26
27
  const suitableReturns = wasm => wasm.reduce((acc, x) => acc + (x[0] === Opcodes.return), 0) <= 1;
27
28
  const candidates = funcs.filter(x => x.name !== 'main' && Object.keys(x.locals).length === x.params.length && (x.returns.length === 0 || suitableReturns(x.wasm)) && !callsSelf(x) && !x.throws).reverse();
28
- if (optLog) {
29
+ if (Prefs.optLog) {
29
30
  log('opt', `found inline candidates: ${candidates.map(x => x.name).join(', ')} (${candidates.length}/${funcs.length - 1})`);
30
31
 
31
32
  let reasons = {};
@@ -53,7 +54,7 @@ export default (funcs, globals, pages, tags, exceptions) => {
53
54
  for (let i = 0; i < tWasm.length; i++) {
54
55
  const inst = tWasm[i];
55
56
  if (inst[0] === Opcodes.call && inst[1] === c.index) {
56
- if (optLog) log('opt', `inlining call for ${c.name} (in ${t.name})`);
57
+ if (Prefs.optLog) log('opt', `inlining call for ${c.name} (in ${t.name})`);
57
58
  tWasm.splice(i, 1); // remove this call
58
59
 
59
60
  // add params as locals and set in reverse order
@@ -80,7 +81,7 @@ export default (funcs, globals, pages, tags, exceptions) => {
80
81
  // adjust local operands to go to correct param index
81
82
  for (const inst of iWasm) {
82
83
  if ((inst[0] === Opcodes.local_get || inst[0] === Opcodes.local_set) && inst[1] < c.params.length) {
83
- if (optLog) log('opt', `replacing local operand in inlined wasm (${inst[1]} -> ${paramIdx[inst[1]]})`);
84
+ if (Prefs.optLog) log('opt', `replacing local operand in inlined wasm (${inst[1]} -> ${paramIdx[inst[1]]})`);
84
85
  inst[1] = paramIdx[inst[1]];
85
86
  }
86
87
  }
@@ -97,7 +98,7 @@ export default (funcs, globals, pages, tags, exceptions) => {
97
98
  }
98
99
  }
99
100
 
100
- if (process.argv.includes('-opt-inline-only')) return;
101
+ if (Prefs.optInlineOnly) return;
101
102
 
102
103
  const tagUse = tags.reduce((acc, x) => { acc[x.idx] = 0; return acc; }, {});
103
104
  const exceptionUse = exceptions.reduce((acc, _, i) => { acc[i] = 0; return acc; }, {});
@@ -166,7 +167,7 @@ export default (funcs, globals, pages, tags, exceptions) => {
166
167
 
167
168
  wasm.splice(j - 1, 1); // remove end of this block
168
169
 
169
- if (optLog) log('opt', `removed unneeded block in for loop`);
170
+ if (Prefs.optLog) log('opt', `removed unneeded block in for loop`);
170
171
  }
171
172
  }
172
173
 
@@ -215,7 +216,7 @@ export default (funcs, globals, pages, tags, exceptions) => {
215
216
  i -= 4;
216
217
  inst = wasm[i];
217
218
 
218
- if (optLog) log('opt', `removed unneeded typeswitch check`);
219
+ if (Prefs.optLog) log('opt', `removed unneeded typeswitch check`);
219
220
  }
220
221
  }
221
222
 
@@ -238,7 +239,7 @@ export default (funcs, globals, pages, tags, exceptions) => {
238
239
  wasm.splice(j - 1, 2, [ Opcodes.drop ]); // remove typeswitch start
239
240
  wasm.splice(i - 1, 1); // remove this inst
240
241
 
241
- if (optLog) log('opt', 'removed unneeded entire typeswitch');
242
+ if (Prefs.optLog) log('opt', 'removed unneeded entire typeswitch');
242
243
 
243
244
  if (i > 0) i--;
244
245
  continue;
@@ -267,7 +268,7 @@ export default (funcs, globals, pages, tags, exceptions) => {
267
268
 
268
269
  getCount[inst[1]]--;
269
270
  i--;
270
- // if (optLog) log('opt', `consolidated set, get -> tee`);
271
+ // if (Prefs.optLog) log('opt', `consolidated set, get -> tee`);
271
272
  continue;
272
273
  }
273
274
 
@@ -335,7 +336,7 @@ export default (funcs, globals, pages, tags, exceptions) => {
335
336
 
336
337
  wasm.splice(i - 1, 2); // remove this inst and last
337
338
  i -= 2;
338
- // if (optLog) log('opt', `removed redundant i32 -> i64 -> i32 conversion ops`);
339
+ // if (Prefs.optLog) log('opt', `removed redundant i32 -> i64 -> i32 conversion ops`);
339
340
  continue;
340
341
  }
341
342
 
@@ -348,7 +349,7 @@ export default (funcs, globals, pages, tags, exceptions) => {
348
349
 
349
350
  wasm.splice(i - 1, 2); // remove this inst and last
350
351
  i -= 2;
351
- // if (optLog) log('opt', `removed redundant i32 -> f64 -> i32 conversion ops`);
352
+ // if (Prefs.optLog) log('opt', `removed redundant i32 -> f64 -> i32 conversion ops`);
352
353
  continue;
353
354
  }
354
355
 
@@ -363,7 +364,7 @@ export default (funcs, globals, pages, tags, exceptions) => {
363
364
 
364
365
  wasm.splice(i, 1); // remove this inst
365
366
  i--;
366
- if (optLog) log('opt', `converted const -> i32 convert into i32 const`);
367
+ if (Prefs.optLog) log('opt', `converted const -> i32 convert into i32 const`);
367
368
  continue;
368
369
  }
369
370
 
@@ -378,7 +379,7 @@ export default (funcs, globals, pages, tags, exceptions) => {
378
379
 
379
380
  wasm.splice(i, 1); // remove this inst
380
381
  i--;
381
- if (optLog) log('opt', `converted i32 const -> convert into const`);
382
+ if (Prefs.optLog) log('opt', `converted i32 const -> convert into const`);
382
383
  continue;
383
384
  }
384
385
 
@@ -393,7 +394,7 @@ export default (funcs, globals, pages, tags, exceptions) => {
393
394
 
394
395
  wasm.splice(i, 1); // remove this inst (return)
395
396
  i--;
396
- if (optLog) log('opt', `tail called return, call`);
397
+ if (Prefs.optLog) log('opt', `tail called return, call`);
397
398
  continue;
398
399
  }
399
400
 
@@ -406,7 +407,7 @@ export default (funcs, globals, pages, tags, exceptions) => {
406
407
 
407
408
  wasm.splice(i, 1); // remove this inst (return)
408
409
  i--;
409
- // if (optLog) log('opt', `removed redundant return at end`);
410
+ // if (Prefs.optLog) log('opt', `removed redundant return at end`);
410
411
  continue;
411
412
  }
412
413
 
@@ -436,7 +437,7 @@ export default (funcs, globals, pages, tags, exceptions) => {
436
437
  // <nothing>
437
438
 
438
439
  wasm.splice(i - 2, 3); // remove this, last, 2nd last insts
439
- if (optLog) log('opt', `removed redundant inline param local handling`);
440
+ if (Prefs.optLog) log('opt', `removed redundant inline param local handling`);
440
441
  i -= 3;
441
442
  continue;
442
443
  }
@@ -444,12 +445,12 @@ export default (funcs, globals, pages, tags, exceptions) => {
444
445
 
445
446
  if (optLevel < 2) continue;
446
447
 
447
- if (optLog) log('opt', `get counts: ${Object.keys(f.locals).map(x => `${x} (${f.locals[x].idx}): ${getCount[f.locals[x].idx]}`).join(', ')}`);
448
+ if (Prefs.optLog) log('opt', `get counts: ${Object.keys(f.locals).map(x => `${x} (${f.locals[x].idx}): ${getCount[f.locals[x].idx]}`).join(', ')}`);
448
449
 
449
450
  // remove unneeded var: remove pass
450
451
  // locals only got once. we don't need to worry about sets/else as these are only candidates and we will check for matching set + get insts in wasm
451
452
  let unneededCandidates = Object.keys(getCount).filter(x => getCount[x] === 0 || (getCount[x] === 1 && setCount[x] === 0)).map(x => parseInt(x));
452
- if (optLog) log('opt', `found unneeded locals candidates: ${unneededCandidates.join(', ')} (${unneededCandidates.length}/${Object.keys(getCount).length})`);
453
+ if (Prefs.optLog) log('opt', `found unneeded locals candidates: ${unneededCandidates.join(', ')} (${unneededCandidates.length}/${Object.keys(getCount).length})`);
453
454
 
454
455
  // note: disabled for now due to instability
455
456
  if (unneededCandidates.length > 0 && false) for (let i = 0; i < wasm.length; i++) {
@@ -467,7 +468,7 @@ export default (funcs, globals, pages, tags, exceptions) => {
467
468
  wasm.splice(i - 1, 2); // remove insts
468
469
  i -= 2;
469
470
  delete f.locals[Object.keys(f.locals)[inst[1]]]; // remove from locals
470
- if (optLog) log('opt', `removed redundant local (get set ${inst[1]})`);
471
+ if (Prefs.optLog) log('opt', `removed redundant local (get set ${inst[1]})`);
471
472
  }
472
473
 
473
474
  if (inst[0] === Opcodes.local_tee && unneededCandidates.includes(inst[1])) {
@@ -495,7 +496,7 @@ export default (funcs, globals, pages, tags, exceptions) => {
495
496
  unneededCandidates.splice(unneededCandidates.indexOf(inst[1]), 1);
496
497
  unneededCandidates = unneededCandidates.map(x => x > removedIdx ? (x - 1) : x);
497
498
 
498
- if (optLog) log('opt', `removed redundant local ${localName} (tee ${inst[1]})`);
499
+ if (Prefs.optLog) log('opt', `removed redundant local ${localName} (tee ${inst[1]})`);
499
500
  }
500
501
  }
501
502
 
@@ -531,7 +532,7 @@ export default (funcs, globals, pages, tags, exceptions) => {
531
532
  let b = lastInst[1];
532
533
 
533
534
  const val = performWasmOp(inst[0], a, b);
534
- if (optLog) log('opt', `inlined math op (${a} ${inst[0].toString(16)} ${b} -> ${val})`);
535
+ if (Prefs.optLog) log('opt', `inlined math op (${a} ${inst[0].toString(16)} ${b} -> ${val})`);
535
536
 
536
537
  wasm.splice(i - 2, 3, ...number(val)); // remove consts, math op and add new const
537
538
  i -= 2;
@@ -543,12 +544,12 @@ export default (funcs, globals, pages, tags, exceptions) => {
543
544
  for (const x in useCount) {
544
545
  if (useCount[x] === 0) {
545
546
  const name = Object.keys(f.locals)[localIdxs.indexOf(parseInt(x))];
546
- if (optLog) log('opt', `removed internal local ${x} (${name})`);
547
+ if (Prefs.optLog) log('opt', `removed internal local ${x} (${name})`);
547
548
  delete f.locals[name];
548
549
  }
549
550
  }
550
551
 
551
- if (optLog) log('opt', `final use counts: ${Object.keys(f.locals).map(x => `${x} (${f.locals[x].idx}): ${useCount[f.locals[x].idx]}`).join(', ')}`);
552
+ if (Prefs.optLog) log('opt', `final use counts: ${Object.keys(f.locals).map(x => `${x} (${f.locals[x].idx}): ${useCount[f.locals[x].idx]}`).join(', ')}`);
552
553
  }
553
554
  }
554
555
 
package/compiler/parse.js CHANGED
@@ -1,4 +1,6 @@
1
1
  import { log } from "./log.js";
2
+ import Prefs from './prefs.js';
3
+
2
4
  // import { parse } from 'acorn';
3
5
 
4
6
  // deno compat
@@ -8,8 +10,8 @@ if (typeof process === 'undefined' && typeof Deno !== 'undefined') {
8
10
  }
9
11
 
10
12
  // should we try to support types (while parsing)
11
- const types = process.argv.includes('-parse-types');
12
- globalThis.typedInput = types && process.argv.includes('-opt-types');
13
+ const types = Prefs.parseTypes;
14
+ globalThis.typedInput = types && Prefs.optTypes;
13
15
 
14
16
  // todo: review which to use by default
15
17
  // supported parsers: