porffor 0.2.0-fdf0fc5 → 0.14.0-4057a18e9

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.
Files changed (40) hide show
  1. package/README.md +9 -2
  2. package/byg/index.js +3 -24
  3. package/compiler/2c.js +2 -53
  4. package/compiler/assemble.js +26 -11
  5. package/compiler/builtins/annexb_string.js +10 -10
  6. package/compiler/builtins/annexb_string.ts +3 -3
  7. package/compiler/builtins/array.ts +2 -6
  8. package/compiler/builtins/base64.ts +1 -1
  9. package/compiler/builtins/boolean.ts +0 -2
  10. package/compiler/builtins/crypto.ts +1 -1
  11. package/compiler/builtins/date.ts +1 -4
  12. package/compiler/builtins/escape.ts +1 -1
  13. package/compiler/builtins/function.ts +0 -2
  14. package/compiler/builtins/int.ts +0 -2
  15. package/compiler/builtins/number.ts +3 -8
  16. package/compiler/builtins/object.ts +0 -2
  17. package/compiler/builtins/porffor.d.ts +9 -8
  18. package/compiler/builtins/set.ts +184 -2
  19. package/compiler/builtins/string.ts +1 -1
  20. package/compiler/builtins.js +4 -7
  21. package/compiler/codegen.js +21 -106
  22. package/compiler/decompile.js +2 -2
  23. package/compiler/embedding.js +2 -2
  24. package/compiler/encoding.js +0 -14
  25. package/compiler/expression.js +1 -1
  26. package/compiler/generated_builtins.js +303 -204
  27. package/compiler/index.js +0 -2
  28. package/compiler/opt.js +7 -7
  29. package/compiler/parse.js +1 -3
  30. package/compiler/precompile.js +17 -25
  31. package/compiler/prototype.js +5 -5
  32. package/compiler/wasmSpec.js +5 -0
  33. package/compiler/wrap.js +69 -56
  34. package/package.json +1 -1
  35. package/runner/compare.js +0 -1
  36. package/runner/debug.js +1 -6
  37. package/runner/profiler.js +15 -42
  38. package/runner/repl.js +3 -9
  39. package/runner/sizes.js +2 -2
  40. package/runner/version.js +10 -8
@@ -1,5 +1,187 @@
1
- // @porf --funsafe-no-unlikely-proto-checks
1
+ // dark wasm magic for dealing with memory, sorry.
2
+ export const __Porffor_allocate = (): number => {
3
+ Porffor.wasm`i32.const 1
4
+ memory.grow 0
5
+ drop
6
+ memory.size 0
7
+ i32.const 1
8
+ i32.sub
9
+ i32.const 65536
10
+ i32.mul
11
+ i32.from_u
12
+ return`;
13
+ };
2
14
 
3
- export const Set = (iterable: any): Set => {
15
+ export const __Porffor_set_read = (_this: Set, index: number): any => {
16
+ Porffor.wasm`
17
+ local offset i32
18
+ local.get ${index}
19
+ i32.to_u
20
+ i32.const 9
21
+ i32.mul
22
+ local.get ${_this}
23
+ i32.to_u
24
+ i32.add
25
+ local.set offset
4
26
 
27
+ local.get offset
28
+ f64.load 0 4
29
+
30
+ local.get offset
31
+ i32.load8_u 0 12
32
+ return`;
33
+ };
34
+
35
+ export const __Porffor_set_write = (_this: Set, index: number, value: any): boolean => {
36
+ Porffor.wasm`
37
+ local offset i32
38
+ local.get ${index}
39
+ i32.to_u
40
+ i32.const 9
41
+ i32.mul
42
+ local.get ${_this}
43
+ i32.to_u
44
+ i32.add
45
+ local.set offset
46
+
47
+ local.get offset
48
+ local.get ${value}
49
+ f64.store 0 4
50
+
51
+ local.get offset
52
+ local.get ${value+1}
53
+ i32.store8 0 12`;
54
+
55
+ return true;
56
+ };
57
+
58
+
59
+ // todo: this should be a getter somehow not a method
60
+ export const __Set_prototype_size = (_this: Set) => {
61
+ return Porffor.wasm.i32.load(_this, 0, 0);
62
+ };
63
+
64
+ export const __Set_prototype_values = (_this: Set) => {
65
+ // todo: this should return an iterator not array
66
+ const size: number = __Set_prototype_size(_this);
67
+
68
+ const out: any[] = __Porffor_allocate();
69
+ for (let i: number = 0; i < size; i++) {
70
+ const val: any = __Porffor_set_read(_this, i);
71
+ out.push(val);
72
+ }
73
+
74
+ return out;
75
+ };
76
+
77
+ export const __Set_prototype_keys = (_this: Set) => {
78
+ return __Set_prototype_values(_this);
79
+ };
80
+
81
+ export const __Set_prototype_has = (_this: Set, value: any) => {
82
+ const size: number = __Set_prototype_size(_this);
83
+
84
+ for (let i: number = 0; i < size; i++) {
85
+ if (__Porffor_set_read(_this, i) === value) return true;
86
+ }
87
+
88
+ return false;
89
+ };
90
+
91
+ export const __Set_prototype_add = (_this: Set, value: any) => {
92
+ const size: number = __Set_prototype_size(_this);
93
+
94
+ // check if already in set
95
+ for (let i: number = 0; i < size; i++) {
96
+ if (__Porffor_set_read(_this, i) === value) return _this;
97
+ }
98
+
99
+ // not, add it
100
+ // increment size by 1
101
+ Porffor.wasm.i32.store(_this, size + 1, 0, 0);
102
+
103
+ // write new value at end
104
+ __Porffor_set_write(_this, size, value);
105
+
106
+ return _this;
107
+ };
108
+
109
+ export const __Set_prototype_delete = (_this: Set, value: any) => {
110
+ const size: number = __Set_prototype_size(_this);
111
+
112
+ // check if already in set
113
+ for (let i: number = 0; i < size; i++) {
114
+ if (__Porffor_set_read(_this, i) === value) {
115
+ // found, delete
116
+ // decrement size by 1
117
+ Porffor.wasm.i32.store(_this, size - 1, 0, 0);
118
+
119
+ // offset all elements after by -1 ind
120
+ Porffor.wasm`
121
+ local offset i32
122
+ local.get ${i}
123
+ i32.to_u
124
+ i32.const 9
125
+ i32.mul
126
+ local.get ${_this}
127
+ i32.to_u
128
+ i32.add
129
+ i32.const 4
130
+ i32.add
131
+ local.set offset
132
+
133
+ ;; dst = offset (this element)
134
+ local.get offset
135
+
136
+ ;; src = offset + 9 (this element + 1 element)
137
+ local.get offset
138
+ i32.const 9
139
+ i32.add
140
+
141
+ ;; size = (size - i - 1) * 9
142
+ local.get ${size}
143
+ local.get ${i}
144
+ f64.sub
145
+ i32.to_u
146
+ i32.const 1
147
+ i32.sub
148
+ i32.const 9
149
+ i32.mul
150
+
151
+ memory.copy 0 0`;
152
+
153
+ return true;
154
+ }
155
+ }
156
+
157
+ // not, return false
158
+ return false;
159
+ };
160
+
161
+ export const __Set_prototype_clear = (_this: Set) => {
162
+ // just set size to 0
163
+ // do not need to delete any as will not be accessed anymore,
164
+ // and will be overwritten with new add
165
+ Porffor.wasm.i32.store(_this, 0, 0, 0);
166
+ };
167
+
168
+ export const Set = () => {
169
+ throw new TypeError("Constructor Set requires 'new'");
170
+ };
171
+
172
+ export const Set$constructor = (iterable: any): Set => {
173
+ const out: Set = __Porffor_allocate();
174
+
175
+ const type: number = Porffor.rawType(iterable);
176
+ if (Porffor.fastOr(
177
+ type == Porffor.TYPES.array,
178
+ type == Porffor.TYPES.string, type == Porffor.TYPES.bytestring,
179
+ type == Porffor.TYPES.set
180
+ )) {
181
+ for (const x of iterable) {
182
+ __Set_prototype_add(out, x);
183
+ }
184
+ }
185
+
186
+ return out;
5
187
  };
@@ -1,4 +1,4 @@
1
- // @porf --funsafe-no-unlikely-proto-checks --valtype=i32
1
+ // @porf --valtype=i32
2
2
 
3
3
  export const __String_fromCharCode = (code: i32) => {
4
4
  // todo: support >1 arg
@@ -1,8 +1,8 @@
1
- import { Blocktype, Opcodes, Valtype, ValtypeSize } from "./wasmSpec.js";
2
- import { number, i32x4 } from "./embedding.js";
3
- import Prefs from './prefs.js';
4
1
  import * as GeneratedBuiltins from './generated_builtins.js';
2
+ import { Blocktype, Opcodes, Valtype, ValtypeSize } from './wasmSpec.js';
3
+ import { number } from './embedding.js';
5
4
  import { TYPES } from './types.js';
5
+ import Prefs from './prefs.js';
6
6
 
7
7
  export const importedFuncs = [
8
8
  {
@@ -48,8 +48,6 @@ for (let i = 0; i < importedFuncs.length; i++) {
48
48
  importedFuncs[f.name] = i;
49
49
  }
50
50
 
51
- const char = c => number(c.charCodeAt(0));
52
-
53
51
  const printStaticStr = str => {
54
52
  const out = [];
55
53
 
@@ -140,7 +138,7 @@ export const BuiltinVars = function() {
140
138
  this.Math = number(1);
141
139
 
142
140
  // wintercg(tm)
143
- this.__navigator_userAgent = (scope, { makeString }) => makeString(scope, `Porffor/0.2.0`, false, '__navigator_userAgent');
141
+ this.__navigator_userAgent = (scope, { makeString }) => makeString(scope, `Porffor/0.14.0`, false, '__navigator_userAgent');
144
142
  this.__navigator_userAgent.type = Prefs.bytestring ? TYPES.bytestring : TYPES.string;
145
143
 
146
144
  for (const x in TYPES) {
@@ -569,7 +567,6 @@ export const BuiltinFuncs = function() {
569
567
 
570
568
  // this is an implementation of xorshift128+ (in wasm bytecode)
571
569
  // fun fact: v8, SM, JSC also use this (you will need this fun fact to maintain your sanity reading this code)
572
- // const prngSeed0 = Math.floor(Math.random() * Number.MAX_SAFE_INTEGER), prngSeed1 = Math.floor(Math.random() * Number.MAX_SAFE_INTEGER);
573
570
  const prngSeed0 = (Math.random() * (2 ** 30)) | 0, prngSeed1 = (Math.random() * (2 ** 30)) | 0;
574
571
 
575
572
  const prng = ({
@@ -1,14 +1,14 @@
1
- import { Blocktype, Opcodes, Valtype, PageSize, ValtypeSize } from "./wasmSpec.js";
2
- import { ieee754_binary64, signedLEB128, unsignedLEB128, encodeVector } from "./encoding.js";
3
- import { operatorOpcode } from "./expression.js";
4
- import { BuiltinFuncs, BuiltinVars, importedFuncs, NULL, UNDEFINED } from "./builtins.js";
5
- import { PrototypeFuncs } from "./prototype.js";
6
- import { number, i32x4, enforceOneByte, enforceTwoBytes, enforceFourBytes, enforceEightBytes } from "./embedding.js";
7
- import { log } from "./log.js";
8
- import parse from "./parse.js";
9
- import * as Rhemyn from "../rhemyn/compile.js";
10
- import Prefs from './prefs.js';
1
+ import { Blocktype, Opcodes, Valtype, PageSize, ValtypeSize } from './wasmSpec.js';
2
+ import { ieee754_binary64, signedLEB128, unsignedLEB128, encodeVector } from './encoding.js';
3
+ import { operatorOpcode } from './expression.js';
4
+ import { BuiltinFuncs, BuiltinVars, importedFuncs, NULL, UNDEFINED } from './builtins.js';
5
+ import { PrototypeFuncs } from './prototype.js';
6
+ import { number } from './embedding.js';
11
7
  import { TYPES, TYPE_NAMES } from './types.js';
8
+ import * as Rhemyn from '../rhemyn/compile.js';
9
+ import parse from './parse.js';
10
+ import { log } from './log.js';
11
+ import Prefs from './prefs.js';
12
12
 
13
13
  let globals = {};
14
14
  let globalInd = 0;
@@ -19,24 +19,6 @@ let funcIndex = {};
19
19
  let currentFuncIndex = importedFuncs.length;
20
20
  let builtinFuncs = {}, builtinVars = {}, prototypeFuncs = {};
21
21
 
22
- const debug = str => {
23
- const code = [];
24
-
25
- const logChar = n => {
26
- code.push(...number(n));
27
-
28
- code.push([ Opcodes.call, 0 ]);
29
- };
30
-
31
- for (let i = 0; i < str.length; i++) {
32
- logChar(str.charCodeAt(i));
33
- }
34
-
35
- logChar(10); // new line
36
-
37
- return code;
38
- };
39
-
40
22
  class TodoError extends Error {
41
23
  constructor(message) {
42
24
  super(message);
@@ -171,11 +153,6 @@ const generate = (scope, decl, global = false, name = undefined, valueUnused = f
171
153
  newFunc.export = true;
172
154
  }
173
155
 
174
- // if (funcsBefore === funcs.length) throw new Error('no new func added in export');
175
-
176
- // const newFunc = funcs[funcs.length - 1];
177
- // newFunc.export = true;
178
-
179
156
  return [];
180
157
 
181
158
  case 'TaggedTemplateExpression': {
@@ -858,31 +835,6 @@ const performOp = (scope, op, left, right, leftType, rightType, _global = false,
858
835
 
859
836
  // if strict (in)equal check types match
860
837
  if (strictOp) {
861
- // startOut.push(
862
- // ...leftType,
863
- // ...rightType,
864
- // [ Opcodes.i32_eq ]
865
- // );
866
-
867
- // endOut.push(
868
- // [ Opcodes.i32_and ]
869
- // );
870
-
871
- // startOut.push(
872
- // [ Opcodes.block, Valtype.i32 ],
873
- // ...leftType,
874
- // ...rightType,
875
- // [ Opcodes.i32_ne ],
876
- // [ Opcodes.if, Blocktype.void ],
877
- // ...number(op === '===' ? 0 : 1, Valtype.i32),
878
- // [ Opcodes.br, 1 ],
879
- // [ Opcodes.end ]
880
- // );
881
-
882
- // endOut.push(
883
- // [ Opcodes.end ]
884
- // );
885
-
886
838
  endOut.push(
887
839
  ...leftType,
888
840
  ...rightType,
@@ -1089,7 +1041,7 @@ const generateBinaryExp = (scope, decl, _global, _name) => {
1089
1041
 
1090
1042
  const asmFuncToAsm = (func, { name = '#unknown_asm_func', params = [], locals = [], returns = [], localInd = 0 }) => {
1091
1043
  return func({ name, params, locals, returns, localInd }, {
1092
- TYPES, TYPE_NAMES, typeSwitch, makeArray, makeString, allocPage,
1044
+ TYPES, TYPE_NAMES, typeSwitch, makeArray, makeString, allocPage, internalThrow,
1093
1045
  builtin: name => {
1094
1046
  let idx = funcIndex[name] ?? importedFuncs[name];
1095
1047
  if (idx === undefined && builtinFuncs[name]) {
@@ -1248,7 +1200,7 @@ const setLastType = scope => {
1248
1200
  };
1249
1201
 
1250
1202
  const getNodeType = (scope, node) => {
1251
- const inner = () => {
1203
+ const ret = (() => {
1252
1204
  if (node.type === 'Literal') {
1253
1205
  if (node.regex) return TYPES.regexp;
1254
1206
 
@@ -1291,7 +1243,6 @@ const getNodeType = (scope, node) => {
1291
1243
  const func = funcs.find(x => x.name === name);
1292
1244
 
1293
1245
  if (func) {
1294
- // console.log(scope, func, func.returnType);
1295
1246
  if (func.returnType) return func.returnType;
1296
1247
  }
1297
1248
 
@@ -1435,10 +1386,8 @@ const getNodeType = (scope, node) => {
1435
1386
  // presume
1436
1387
  // todo: warn here?
1437
1388
  return TYPES.number;
1438
- };
1389
+ })();
1439
1390
 
1440
- const ret = inner();
1441
- // console.trace(node, ret);
1442
1391
  if (typeof ret === 'number') return number(ret, Valtype.i32);
1443
1392
  return ret;
1444
1393
  };
@@ -1577,15 +1526,6 @@ const RTArrayUtil = {
1577
1526
  };
1578
1527
 
1579
1528
  const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
1580
- /* const callee = decl.callee;
1581
- const args = decl.arguments;
1582
-
1583
- return [
1584
- ...generate(args),
1585
- ...generate(callee),
1586
- Opcodes.call_indirect,
1587
- ]; */
1588
-
1589
1529
  let name = mapName(decl.callee.name);
1590
1530
  if (isFuncType(decl.callee.type)) { // iife
1591
1531
  const func = generateFunc(scope, decl.callee);
@@ -1759,8 +1699,6 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
1759
1699
  continue;
1760
1700
  }
1761
1701
 
1762
- // const protoLocal = protoFunc.local ? localTmp(scope, `__${TYPE_NAMES[x]}_${protoName}_tmp`, protoFunc.local) : -1;
1763
- // const protoLocal2 = protoFunc.local2 ? localTmp(scope, `__${TYPE_NAMES[x]}_${protoName}_tmp2`, protoFunc.local2) : -1;
1764
1702
  const protoLocal = protoFunc.local ? localTmp(scope, `__${protoName}_tmp`, protoFunc.local) : -1;
1765
1703
  const protoLocal2 = protoFunc.local2 ? localTmp(scope, `__${protoName}_tmp2`, protoFunc.local2) : -1;
1766
1704
 
@@ -1837,22 +1775,6 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
1837
1775
 
1838
1776
  includeBuiltin(scope, name);
1839
1777
  idx = funcIndex[name];
1840
-
1841
- // infer arguments types from builtins params
1842
- // const func = funcs.find(x => x.name === name);
1843
- // for (let i = 0; i < decl.arguments.length; i++) {
1844
- // const arg = decl.arguments[i];
1845
- // if (!arg.name) continue;
1846
-
1847
- // const local = scope.locals[arg.name];
1848
- // if (!local) continue;
1849
-
1850
- // local.type = func.params[i];
1851
- // if (local.type === Valtype.v128) {
1852
- // // specify vec subtype inferred from last vec type in function name
1853
- // local.vecType = name.split('_').reverse().find(x => x.includes('x'));
1854
- // }
1855
- // }
1856
1778
  }
1857
1779
 
1858
1780
  if (idx === undefined && internalConstrs[name]) return internalConstrs[name].generate(scope, decl, _global, _name);
@@ -2178,7 +2100,6 @@ const addVarMetadata = (scope, name, global = false, metadata = {}) => {
2178
2100
  const typeAnnoToPorfType = x => {
2179
2101
  if (!x) return null;
2180
2102
  if (TYPES[x.toLowerCase()] != null) return TYPES[x.toLowerCase()];
2181
- if (TYPES['_' + x.toLowerCase()] != null) return TYPES['_' + x.toLowerCase()];
2182
2103
 
2183
2104
  switch (x) {
2184
2105
  case 'i32':
@@ -2219,9 +2140,8 @@ const generateVar = (scope, decl) => {
2219
2140
 
2220
2141
  const topLevel = scope.name === 'main';
2221
2142
 
2222
- // global variable if in top scope (main) and var ..., or if wanted
2223
- const global = topLevel || decl._bare; // decl.kind === 'var';
2224
- const target = global ? globals : scope.locals;
2143
+ // global variable if in top scope (main) or if internally wanted
2144
+ const global = topLevel || decl._bare;
2225
2145
 
2226
2146
  for (const x of decl.declarations) {
2227
2147
  const name = mapName(x.id.name);
@@ -2235,7 +2155,6 @@ const generateVar = (scope, decl) => {
2235
2155
  continue;
2236
2156
  }
2237
2157
 
2238
- // console.log(name);
2239
2158
  if (topLevel && builtinVars[name]) {
2240
2159
  // cannot redeclare
2241
2160
  if (decl.kind !== 'var') return internalThrow(scope, 'SyntaxError', `Identifier '${unhackName(name)}' has already been declared`);
@@ -3036,13 +2955,6 @@ const generateEmpty = (scope, decl) => {
3036
2955
  return [];
3037
2956
  };
3038
2957
 
3039
- const generateAssignPat = (scope, decl) => {
3040
- // TODO
3041
- // if identifier declared, use that
3042
- // else, use default (right)
3043
- return todo(scope, 'assignment pattern (optional arg)');
3044
- };
3045
-
3046
2958
  let pages = new Map();
3047
2959
  const allocPage = (scope, reason, type) => {
3048
2960
  if (pages.has(reason)) return pages.get(reason).ind;
@@ -3455,8 +3367,11 @@ const generateFunc = (scope, decl) => {
3455
3367
  };
3456
3368
 
3457
3369
  if (typedInput && decl.returnType) {
3458
- innerScope.returnType = extractTypeAnnotation(decl.returnType).type;
3459
- innerScope.returns = [ valtypeBinary ];
3370
+ const { type } = extractTypeAnnotation(decl.returnType);
3371
+ if (type != null) {
3372
+ innerScope.returnType = type;
3373
+ innerScope.returns = [ valtypeBinary ];
3374
+ }
3460
3375
  }
3461
3376
 
3462
3377
  for (let i = 0; i < params.length; i++) {
@@ -3498,7 +3413,7 @@ const generateFunc = (scope, decl) => {
3498
3413
  if (name !== 'main' && wasm[wasm.length - 1]?.[0] !== Opcodes.return && countLeftover(wasm) === 0) {
3499
3414
  wasm.push(
3500
3415
  ...number(0),
3501
- ...number(TYPES.undefined, Valtype.i32),
3416
+ ...(innerScope.returnType != null ? [] : number(TYPES.undefined, Valtype.i32)),
3502
3417
  [ Opcodes.return ]
3503
3418
  );
3504
3419
  }
@@ -1,5 +1,5 @@
1
- import { Blocktype, Opcodes, Valtype } from "./wasmSpec.js";
2
- import { read_ieee754_binary64, read_signedLEB128, read_unsignedLEB128 } from "./encoding.js";
1
+ import { Blocktype, Opcodes, Valtype } from './wasmSpec.js';
2
+ import { read_ieee754_binary64, read_signedLEB128, read_unsignedLEB128 } from './encoding.js';
3
3
 
4
4
  const inv = (obj, keyMap = x => x) => Object.keys(obj).reduce((acc, x) => { acc[keyMap(obj[x])] = x; return acc; }, {});
5
5
  const invOpcodes = inv(Opcodes);
@@ -1,5 +1,5 @@
1
- import { Opcodes, Valtype } from "./wasmSpec.js";
2
- import { signedLEB128, ieee754_binary64 } from "./encoding.js";
1
+ import { Opcodes, Valtype } from './wasmSpec.js';
2
+ import { signedLEB128, ieee754_binary64 } from './encoding.js';
3
3
 
4
4
  export const number = (n, valtype = valtypeBinary) => {
5
5
  switch (valtype) {
@@ -7,21 +7,7 @@ export const codifyString = str => {
7
7
  return out;
8
8
  };
9
9
 
10
- // export const encodeString = str => [
11
- // str.length,
12
- // ...codifyString(str)
13
- // ];
14
10
  export const encodeString = str => unsignedLEB128(str.length).concat(codifyString(str));
15
-
16
- // export const encodeVector = data => [
17
- // ...unsignedLEB128(data.length),
18
- // ...data.flat()
19
- // ];
20
- // export const encodeVector = data => {
21
- // const out = data.flat();
22
- // out.unshift.apply(out, unsignedLEB128(data.length));
23
- // return out;
24
- // };
25
11
  export const encodeVector = data => unsignedLEB128(data.length).concat(data.flat());
26
12
 
27
13
  export const encodeLocal = (count, type) => [
@@ -1,4 +1,4 @@
1
- import { Opcodes } from "./wasmSpec.js";
1
+ import { Opcodes } from './wasmSpec.js';
2
2
 
3
3
  export const operatorOpcode = {
4
4
  i32: {