porffor 0.16.0-ec15a329e → 0.16.0-f9dde1759

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 CHANGED
@@ -26,7 +26,7 @@ You can also swap out `node` in the alias to use another runtime like Deno (`den
26
26
 
27
27
  ### Precompile
28
28
 
29
- **If you update any file inside `compiler/builtins` you will need to do this for it to update inside Porffor otherwise your changes will have no effect.** Run `node compiler/precompile.js` to precompile. It may error during this, if so, you might have an error in your code or there could be a compiler error with Porffor (feel free to ask for help as soon as you encounter any errors with it).
29
+ **If you update any file inside `compiler/builtins` you will need to do this for it to update inside Porffor otherwise your changes will have no effect.** Run `./porf precompile` to precompile. It may error during this, if so, you might have an error in your code or there could be a compiler error with Porffor (feel free to ask for help as soon as you encounter any errors with it).
30
30
 
31
31
  <br>
32
32
 
@@ -21,7 +21,7 @@ const chHint = (topTier, baselineTier, strategy) => {
21
21
  return (strategy | (baselineTier << 2) | (topTier << 4));
22
22
  };
23
23
 
24
- export default (funcs, globals, tags, pages, data, flags) => {
24
+ export default (funcs, globals, tags, pages, data, flags, noTreeshake = false) => {
25
25
  const types = [], typeCache = {};
26
26
 
27
27
  const optLevel = parseInt(process.argv.find(x => x.startsWith('-O'))?.[2] ?? 1);
@@ -44,7 +44,7 @@ export default (funcs, globals, tags, pages, data, flags) => {
44
44
 
45
45
  let importFuncs = [];
46
46
 
47
- if (optLevel < 1 || !Prefs.treeshakeWasmImports) {
47
+ if (optLevel < 1 || !Prefs.treeshakeWasmImports || noTreeshake) {
48
48
  importFuncs = importedFuncs;
49
49
  } else {
50
50
  let imports = new Map();
@@ -94,7 +94,7 @@ export default (funcs, globals, tags, pages, data, flags) => {
94
94
 
95
95
  const importSection = importFuncs.length === 0 ? [] : createSection(
96
96
  Section.import,
97
- encodeVector(importFuncs.map(x => [ 0, ...encodeString(x.import), ExportDesc.func, getType(new Array(x.params).fill(x.name.startsWith('profile') ? Valtype.i32 : valtypeBinary), new Array(x.returns).fill(valtypeBinary)) ]))
97
+ encodeVector(importFuncs.map(x => [ 0, ...encodeString(x.import), ExportDesc.func, getType(typeof x.params === 'object' ? x.params : new Array(x.params).fill(valtypeBinary), new Array(x.returns).fill(valtypeBinary)) ]))
98
98
  );
99
99
 
100
100
  const funcSection = createSection(
@@ -116,7 +116,7 @@ export default (funcs, globals, tags, pages, data, flags) => {
116
116
  ] ])
117
117
  );
118
118
 
119
- if (pages.has('func argc lut')) {
119
+ if (pages.has('func argc lut') && !data.addedFuncArgcLut) {
120
120
  // generate func argc lut data
121
121
  const bytes = [];
122
122
  for (let i = 0; i < funcs.length; i++) {
@@ -128,6 +128,7 @@ export default (funcs, globals, tags, pages, data, flags) => {
128
128
  offset: pages.get('func argc lut').ind * pageSize,
129
129
  bytes
130
130
  });
131
+ data.addedFuncArgcLut = true;
131
132
  }
132
133
 
133
134
  // const t0 = performance.now();
@@ -32,13 +32,13 @@ export const importedFuncs = [
32
32
  {
33
33
  name: 'profile1',
34
34
  import: 'y',
35
- params: 1,
35
+ params: [ Valtype.i32 ],
36
36
  returns: 0
37
37
  },
38
38
  {
39
39
  name: 'profile2',
40
40
  import: 'z',
41
- params: 1,
41
+ params: [ Valtype.i32 ],
42
42
  returns: 0
43
43
  },
44
44
  {
@@ -167,6 +167,7 @@ export const BuiltinFuncs = function() {
167
167
  params: [ valtypeBinary, valtypeBinary ],
168
168
  locals: [],
169
169
  returns: [ valtypeBinary ],
170
+ returnType: TYPES.number,
170
171
  wasm: [ // x - truncf(x / y) * y
171
172
  [ Opcodes.local_get, 0 ], // x
172
173
 
@@ -189,6 +190,7 @@ export const BuiltinFuncs = function() {
189
190
  params: [ valtypeBinary, valtypeBinary ],
190
191
  locals: [],
191
192
  returns: [ valtypeBinary ],
193
+ returnType: TYPES.number,
192
194
  wasm: [
193
195
  [ Opcodes.local_get, 0 ],
194
196
  Opcodes.i32_to,
@@ -208,6 +210,7 @@ export const BuiltinFuncs = function() {
208
210
  params: [ valtypeBinary ],
209
211
  locals: [],
210
212
  returns: [ valtypeBinary ],
213
+ returnType: TYPES.number,
211
214
  wasm: [
212
215
  [ Opcodes.local_get, 0 ]
213
216
  ],
@@ -469,6 +472,7 @@ export const BuiltinFuncs = function() {
469
472
  params: [ valtypeBinary ],
470
473
  locals: [],
471
474
  returns: [ valtypeBinary ],
475
+ returnType: TYPES.number,
472
476
  wasm: [
473
477
  [ Opcodes.local_get, 0 ],
474
478
  [ Opcodes.f64_sqrt ]
@@ -480,6 +484,7 @@ export const BuiltinFuncs = function() {
480
484
  params: [ valtypeBinary ],
481
485
  locals: [],
482
486
  returns: [ valtypeBinary ],
487
+ returnType: TYPES.number,
483
488
  wasm: [
484
489
  [ Opcodes.local_get, 0 ],
485
490
  [ Opcodes.f64_abs ]
@@ -491,6 +496,7 @@ export const BuiltinFuncs = function() {
491
496
  params: [ valtypeBinary ],
492
497
  locals: [],
493
498
  returns: [ valtypeBinary ],
499
+ returnType: TYPES.number,
494
500
  wasm: [
495
501
  ...number(1),
496
502
  [ Opcodes.local_get, 0 ],
@@ -503,6 +509,7 @@ export const BuiltinFuncs = function() {
503
509
  params: [ valtypeBinary ],
504
510
  locals: [],
505
511
  returns: [ valtypeBinary ],
512
+ returnType: TYPES.number,
506
513
  wasm: [
507
514
  [ Opcodes.local_get, 0 ],
508
515
  [ Opcodes.f64_floor ]
@@ -514,6 +521,7 @@ export const BuiltinFuncs = function() {
514
521
  params: [ valtypeBinary ],
515
522
  locals: [],
516
523
  returns: [ valtypeBinary ],
524
+ returnType: TYPES.number,
517
525
  wasm: [
518
526
  [ Opcodes.local_get, 0 ],
519
527
  [ Opcodes.f64_ceil ]
@@ -525,6 +533,7 @@ export const BuiltinFuncs = function() {
525
533
  params: [ valtypeBinary ],
526
534
  locals: [],
527
535
  returns: [ valtypeBinary ],
536
+ returnType: TYPES.number,
528
537
  wasm: [
529
538
  [ Opcodes.local_get, 0 ],
530
539
  [ Opcodes.f64_nearest ]
@@ -536,6 +545,7 @@ export const BuiltinFuncs = function() {
536
545
  params: [ valtypeBinary ],
537
546
  locals: [],
538
547
  returns: [ valtypeBinary ],
548
+ returnType: TYPES.number,
539
549
  wasm: [
540
550
  [ Opcodes.local_get, 0 ],
541
551
  [ Opcodes.f64_trunc ]
@@ -547,6 +557,7 @@ export const BuiltinFuncs = function() {
547
557
  params: [ valtypeBinary ],
548
558
  locals: [],
549
559
  returns: [ valtypeBinary ],
560
+ returnType: TYPES.number,
550
561
  wasm: [
551
562
  [ Opcodes.local_get, 0 ],
552
563
  Opcodes.i32_trunc_sat_f64_u,
@@ -560,6 +571,7 @@ export const BuiltinFuncs = function() {
560
571
  params: [ valtypeBinary ],
561
572
  locals: [],
562
573
  returns: [ valtypeBinary ],
574
+ returnType: TYPES.number,
563
575
  wasm: [
564
576
  [ Opcodes.local_get, 0 ],
565
577
  [ Opcodes.f32_demote_f64 ],
@@ -573,6 +585,7 @@ export const BuiltinFuncs = function() {
573
585
  params: [ valtypeBinary, valtypeBinary ],
574
586
  locals: [],
575
587
  returns: [ valtypeBinary ],
588
+ returnType: TYPES.number,
576
589
  wasm: [
577
590
  [ Opcodes.local_get, 0 ],
578
591
  Opcodes.i32_trunc_sat_f64_s,
@@ -887,6 +900,7 @@ export const BuiltinFuncs = function() {
887
900
  globalNames: [ 'state0', 'state1' ],
888
901
  globalInits: [ prngSeed0, prngSeed1 ],
889
902
  returns: [ Valtype.f64 ],
903
+ returnType: TYPES.number,
890
904
  wasm: [
891
905
  ...prng.wasm,
892
906
 
@@ -938,6 +952,7 @@ export const BuiltinFuncs = function() {
938
952
  globalNames: [ 'state0', 'state1' ],
939
953
  globalInits: [ prngSeed0, prngSeed1 ],
940
954
  returns: [ Valtype.i32 ],
955
+ returnType: TYPES.number,
941
956
  wasm: [
942
957
  ...prng.wasm,
943
958
 
@@ -959,6 +974,7 @@ export const BuiltinFuncs = function() {
959
974
  params: [ valtypeBinary ],
960
975
  locals: [],
961
976
  returns: [ valtypeBinary ],
977
+ returnType: TYPES.number,
962
978
  wasm: [
963
979
  [ Opcodes.local_get, 0 ],
964
980
  ...number(Math.PI / 180),
@@ -971,6 +987,7 @@ export const BuiltinFuncs = function() {
971
987
  params: [ valtypeBinary ],
972
988
  locals: [],
973
989
  returns: [ valtypeBinary ],
990
+ returnType: TYPES.number,
974
991
  wasm: [
975
992
  [ Opcodes.local_get, 0 ],
976
993
  ...number(180 / Math.PI),
@@ -984,6 +1001,7 @@ export const BuiltinFuncs = function() {
984
1001
  locals: [],
985
1002
  localNames: [ 'x', 'lower', 'upper' ],
986
1003
  returns: [ valtypeBinary ],
1004
+ returnType: TYPES.number,
987
1005
  wasm: [
988
1006
  [ Opcodes.local_get, 0 ],
989
1007
  [ Opcodes.local_get, 1 ],
@@ -999,9 +1017,9 @@ export const BuiltinFuncs = function() {
999
1017
  locals: [],
1000
1018
  localNames: [ 'x', 'inLow', 'inHigh', 'outLow', 'outHigh' ],
1001
1019
  returns: [ valtypeBinary ],
1020
+ returnType: TYPES.number,
1002
1021
  wasm: [
1003
1022
  // (x − inLow) * (outHigh − outLow) / (inHigh - inLow) + outLow
1004
-
1005
1023
  [ Opcodes.local_get, 0 ],
1006
1024
  [ Opcodes.local_get, 1 ],
1007
1025
  [ Opcodes.f64_sub ],
@@ -1043,6 +1061,7 @@ export const BuiltinFuncs = function() {
1043
1061
  params: [],
1044
1062
  locals: [],
1045
1063
  returns: [ valtypeBinary ],
1064
+ returnType: TYPES.number,
1046
1065
  wasm: [
1047
1066
  [ Opcodes.call, importedFuncs.time ]
1048
1067
  ]
@@ -1070,6 +1089,7 @@ export const BuiltinFuncs = function() {
1070
1089
  typedParams: true,
1071
1090
  locals: [],
1072
1091
  returns: [ valtypeBinary ],
1092
+ returnType: TYPES.number,
1073
1093
  wasm: [
1074
1094
  [ Opcodes.local_get, 1 ],
1075
1095
  Opcodes.i32_from_u
@@ -1078,7 +1078,7 @@ const asmFunc = (name, { wasm, params, locals: localTypes, globals: globalTypes
1078
1078
  locals,
1079
1079
  localInd: allLocals.length,
1080
1080
  returns,
1081
- returnType: returnType ?? TYPES.number,
1081
+ returnType,
1082
1082
  internal: true,
1083
1083
  index: currentFuncIndex++,
1084
1084
  table
@@ -1254,7 +1254,7 @@ const getNodeType = (scope, node) => {
1254
1254
  const func = funcs.find(x => x.name === name);
1255
1255
 
1256
1256
  if (func) {
1257
- if (func.returnType) return func.returnType;
1257
+ if (func.returnType != null) return func.returnType;
1258
1258
  }
1259
1259
 
1260
1260
  if (builtinFuncs[name] && !builtinFuncs[name].typedReturns) return builtinFuncs[name].returnType ?? TYPES.number;
@@ -1270,15 +1270,7 @@ const getNodeType = (scope, node) => {
1270
1270
  const func = spl[spl.length - 1];
1271
1271
  const protoFuncs = Object.keys(prototypeFuncs).filter(x => x != TYPES.bytestring && prototypeFuncs[x][func] != null);
1272
1272
  if (protoFuncs.length === 1) {
1273
- if (protoFuncs[0].returnType) return protoFuncs[0].returnType;
1274
- }
1275
-
1276
- if (protoFuncs.length > 0) {
1277
- if (scope.locals['#last_type']) return getLastType(scope);
1278
-
1279
- // presume
1280
- // todo: warn here?
1281
- return TYPES.number;
1273
+ if (protoFuncs[0].returnType != null) return protoFuncs[0].returnType;
1282
1274
  }
1283
1275
  }
1284
1276
 
@@ -1815,7 +1807,7 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
1815
1807
  f64_store: { imms: 2, args: [ true, false ], returns: 0 },
1816
1808
 
1817
1809
  // value
1818
- i32_const: { imms: 1, args: [], returns: 1 },
1810
+ i32_const: { imms: 1, args: [], returns: 0 },
1819
1811
  };
1820
1812
 
1821
1813
  const opName = name.slice('__Porffor_wasm_'.length);
@@ -1978,7 +1970,7 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
1978
1970
  const func = funcs[idx - importedFuncs.length]; // idx === scope.index ? scope : funcs.find(x => x.index === idx);
1979
1971
  const userFunc = func && !func.internal;
1980
1972
  const typedParams = userFunc || builtinFuncs[name]?.typedParams;
1981
- const typedReturns = (func && func.returnType == null) || builtinFuncs[name]?.typedReturns;
1973
+ const typedReturns = (userFunc && func.returnType == null) || builtinFuncs[name]?.typedReturns;
1982
1974
  const paramCount = func && (typedParams ? func.params.length / 2 : func.params.length);
1983
1975
 
1984
1976
  let args = decl.arguments;
@@ -2007,8 +1999,8 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
2007
1999
  }
2008
2000
 
2009
2001
  if (valtypeBinary !== Valtype.i32 && (
2010
- (builtinFuncs[name] && builtinFuncs[name].params[i * (typedParams ? 2 : 1)] === Valtype.i32) ||
2011
- (importedFuncs[name] && name.startsWith('profile'))
2002
+ (builtinFuncs[name] && builtinFuncs[name].params[i * (typedParams ? 2 : 1)] === Valtype.i32)
2003
+ // (importedFuncs[name] && name.startsWith('profile'))
2012
2004
  )) {
2013
2005
  out.push(Opcodes.i32_to);
2014
2006
  }
@@ -2123,7 +2115,6 @@ const brTable = (input, bc, returns) => {
2123
2115
  }
2124
2116
 
2125
2117
  for (let i = 0; i < count; i++) {
2126
- // if (i === 0) out.push([ Opcodes.block, returns, 'br table start' ]);
2127
2118
  if (i === 0) out.push([ Opcodes.block, returns ]);
2128
2119
  else out.push([ Opcodes.block, Blocktype.void ]);
2129
2120
  }
@@ -2157,10 +2148,8 @@ const brTable = (input, bc, returns) => {
2157
2148
  [ Opcodes.br_table, ...encodeVector(table), 0 ]
2158
2149
  );
2159
2150
 
2160
- // if you can guess why we sort the wrong way and then reverse
2161
- // (instead of just sorting the correct way)
2162
- // dm me and if you are correct and the first person
2163
- // I will somehow shout you out or something
2151
+ // sort the wrong way and then reverse
2152
+ // so strings ('default') are at the start before any numbers
2164
2153
  const orderedBc = keys.sort((a, b) => b - a).reverse();
2165
2154
 
2166
2155
  br = count - 1;
@@ -2186,10 +2175,10 @@ const typeSwitch = (scope, type, bc, returns = valtypeBinary) => {
2186
2175
  return bc[known] ?? bc.default;
2187
2176
  }
2188
2177
 
2189
- if (Prefs.typeswitchUseBrtable)
2178
+ if (Prefs.typeswitchBrtable)
2190
2179
  return brTable(type, bc, returns);
2191
2180
 
2192
- const tmp = localTmp(scope, '#typeswitch_tmp', Valtype.i32);
2181
+ const tmp = localTmp(scope, '#typeswitch_tmp' + (Prefs.typeswitchUniqueTmp ? randId() : ''), Valtype.i32);
2193
2182
  const out = [
2194
2183
  ...type,
2195
2184
  [ Opcodes.local_set, tmp ],
@@ -2571,7 +2560,7 @@ const generateUnary = (scope, decl) => {
2571
2560
  // * -1
2572
2561
 
2573
2562
  if (decl.prefix && decl.argument.type === 'Literal' && typeof decl.argument.value === 'number') {
2574
- // if -<N>, just return that
2563
+ // if -n, just return that as a const
2575
2564
  return number(-1 * decl.argument.value);
2576
2565
  }
2577
2566
 
@@ -2583,14 +2572,14 @@ const generateUnary = (scope, decl) => {
2583
2572
  case '!':
2584
2573
  const arg = decl.argument;
2585
2574
  if (arg.type === 'UnaryExpression' && arg.operator === '!') {
2586
- // !!x -> is x truthy
2575
+ // opt: !!x -> is x truthy
2587
2576
  return truthy(scope, generate(scope, arg.argument), getNodeType(scope, arg.argument), false, false);
2588
2577
  }
2578
+
2589
2579
  // !=
2590
- return falsy(scope, generate(scope, decl.argument), getNodeType(scope, decl.argument), false, false);
2580
+ return falsy(scope, generate(scope, arg), getNodeType(scope, arg), false, false);
2591
2581
 
2592
2582
  case '~':
2593
- // todo: does not handle Infinity properly (should convert to 0) (but opt const converting saves us sometimes)
2594
2583
  return [
2595
2584
  ...generate(scope, decl.argument),
2596
2585
  Opcodes.i32_to,
@@ -3278,7 +3267,7 @@ const makeArray = (scope, decl, global = false, name = '$undeclared', initEmpty
3278
3267
  firstAssign = true;
3279
3268
 
3280
3269
  // todo: can we just have 1 undeclared array? probably not? but this is not really memory efficient
3281
- const uniqueName = name === '$undeclared' ? name + Math.random().toString().slice(2) : name;
3270
+ const uniqueName = name === '$undeclared' ? name + randId() : name;
3282
3271
 
3283
3272
  let page;
3284
3273
  if (Prefs.scopedPageNames) page = allocPage(scope, `${getAllocType(itemType)}: ${scope.name}/${uniqueName}`, itemType);
@@ -3510,7 +3499,7 @@ const generateMember = (scope, decl, _global, _name) => {
3510
3499
  }
3511
3500
 
3512
3501
  if (builtinFuncs[name]) return withType(scope, number(builtinFuncs[name].typedParams ? (builtinFuncs[name].params.length / 2) : builtinFuncs[name].params.length), TYPES.number);
3513
- if (importedFuncs[name]) return withType(scope, number(importedFuncs[name].params), TYPES.number);
3502
+ if (importedFuncs[name]) return withType(scope, number(importedFuncs[name].params.length ?? importedFuncs[name].params), TYPES.number);
3514
3503
  if (internalConstrs[name]) return withType(scope, number(internalConstrs[name].length ?? 0), TYPES.number);
3515
3504
 
3516
3505
  if (Prefs.fastLength) {
@@ -3666,7 +3655,7 @@ const generateMember = (scope, decl, _global, _name) => {
3666
3655
  });
3667
3656
  };
3668
3657
 
3669
- const randId = () => Math.random().toString(16).slice(0, -4);
3658
+ const randId = () => Math.random().toString(16).slice(1, -2).padEnd(12, '0');
3670
3659
 
3671
3660
  const objectHack = node => {
3672
3661
  if (!node) return node;
@@ -3718,7 +3707,7 @@ const generateFunc = (scope, decl) => {
3718
3707
  if (decl.async) return todo(scope, 'async functions are not supported');
3719
3708
  if (decl.generator) return todo(scope, 'generator functions are not supported');
3720
3709
 
3721
- const name = decl.id ? decl.id.name : `anonymous_${randId()}`;
3710
+ const name = decl.id ? decl.id.name : `anonymous${randId()}`;
3722
3711
  const params = decl.params ?? [];
3723
3712
 
3724
3713
  // TODO: share scope/locals between !!!
@@ -3979,19 +3968,8 @@ export default program => {
3979
3968
  data = [];
3980
3969
  currentFuncIndex = importedFuncs.length;
3981
3970
 
3982
- globalThis.valtype = 'f64';
3983
-
3984
- const valtypeOpt = process.argv.find(x => x.startsWith('--valtype='));
3985
- if (valtypeOpt) valtype = valtypeOpt.split('=')[1];
3986
-
3987
- globalThis.valtypeBinary = Valtype[valtype];
3988
-
3989
3971
  const valtypeInd = ['i32', 'i64', 'f64'].indexOf(valtype);
3990
3972
 
3991
- globalThis.pageSize = PageSize;
3992
- const pageSizeOpt = process.argv.find(x => x.startsWith('--page-size='));
3993
- if (pageSizeOpt) pageSize = parseInt(pageSizeOpt.split('=')[1]) * 1024;
3994
-
3995
3973
  // set generic opcodes for current valtype
3996
3974
  Opcodes.const = [ Opcodes.i32_const, Opcodes.i64_const, Opcodes.f64_const ][valtypeInd];
3997
3975
  Opcodes.eq = [ Opcodes.i32_eq, Opcodes.i64_eq, Opcodes.f64_eq ][valtypeInd];