porffor 0.2.0-fdf0fc5 → 0.14.0-0ad2c8a7c

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 (48) hide show
  1. package/CONTRIBUTING.md +12 -7
  2. package/README.md +18 -15
  3. package/asur/index.js +1 -1
  4. package/byg/index.js +3 -24
  5. package/compiler/2c.js +69 -55
  6. package/compiler/assemble.js +51 -11
  7. package/compiler/builtins/annexb_string.js +10 -10
  8. package/compiler/builtins/annexb_string.ts +4 -3
  9. package/compiler/builtins/array.ts +85 -9
  10. package/compiler/builtins/base64.ts +2 -1
  11. package/compiler/builtins/boolean.ts +2 -2
  12. package/compiler/builtins/console.ts +4 -0
  13. package/compiler/builtins/crypto.ts +2 -1
  14. package/compiler/builtins/date.ts +2 -3
  15. package/compiler/builtins/error.js +22 -0
  16. package/compiler/builtins/escape.ts +2 -3
  17. package/compiler/builtins/function.ts +1 -1
  18. package/compiler/builtins/int.ts +1 -1
  19. package/compiler/builtins/math.ts +410 -0
  20. package/compiler/builtins/number.ts +4 -7
  21. package/compiler/builtins/object.ts +1 -1
  22. package/compiler/builtins/porffor.d.ts +9 -8
  23. package/compiler/builtins/set.ts +197 -3
  24. package/compiler/builtins/string.ts +2 -1
  25. package/compiler/builtins/symbol.ts +62 -0
  26. package/compiler/builtins.js +30 -15
  27. package/compiler/codegen.js +641 -365
  28. package/compiler/decompile.js +7 -3
  29. package/compiler/embedding.js +2 -2
  30. package/compiler/encoding.js +0 -14
  31. package/compiler/expression.js +1 -1
  32. package/compiler/generated_builtins.js +781 -187
  33. package/compiler/index.js +5 -11
  34. package/compiler/opt.js +7 -7
  35. package/compiler/parse.js +2 -4
  36. package/compiler/precompile.js +18 -25
  37. package/compiler/prefs.js +6 -2
  38. package/compiler/prototype.js +185 -162
  39. package/compiler/wasmSpec.js +5 -0
  40. package/compiler/wrap.js +150 -90
  41. package/package.json +1 -1
  42. package/runner/compare.js +0 -1
  43. package/runner/debug.js +1 -6
  44. package/runner/index.js +5 -4
  45. package/runner/profiler.js +15 -42
  46. package/runner/repl.js +20 -10
  47. package/runner/sizes.js +2 -2
  48. package/runner/version.js +10 -8
@@ -7,18 +7,18 @@ type PorfforGlobal = {
7
7
  wasm: {
8
8
  (...args: any[]): any;
9
9
  i32: {
10
- load(pointer: i32, align: i32, offset: i32): i32;
11
- store(pointer: i32, value: i32, align: i32, offset: i32): i32;
12
- load8_u(pointer: i32, align: i32, offset: i32): i32;
13
- store8(pointer: i32, value: i32, align: i32, offset: i32): i32;
14
- load16_u(pointer: i32, align: i32, offset: i32): i32;
15
- store16(pointer: i32, value: i32, align: i32, offset: i32): i32;
10
+ load(pointer: any, align: i32, offset: i32): i32;
11
+ store(pointer: any, value: i32, align: i32, offset: i32): i32;
12
+ load8_u(pointer: any, align: i32, offset: i32): i32;
13
+ store8(pointer: any, value: i32, align: i32, offset: i32): i32;
14
+ load16_u(pointer: any, align: i32, offset: i32): i32;
15
+ store16(pointer: any, value: i32, align: i32, offset: i32): i32;
16
16
  const(value: i32): i32;
17
17
  }
18
18
 
19
19
  f64: {
20
- load(pointer: i32, align: i32, offset: i32): i32;
21
- store(pointer: i32, value: f64, align: i32, offset: i32): f64;
20
+ load(pointer: any, align: i32, offset: i32): i32;
21
+ store(pointer: any, value: f64, align: i32, offset: i32): f64;
22
22
  }
23
23
  }
24
24
 
@@ -40,6 +40,7 @@ type PorfforGlobal = {
40
40
  regexp: i32;
41
41
  bytestring: i32;
42
42
  date: i32;
43
+ set: i32;
43
44
  }
44
45
 
45
46
  fastOr(...args: any): boolean;
@@ -1,5 +1,199 @@
1
- // @porf --funsafe-no-unlikely-proto-checks
1
+ import type {} from './porffor.d.ts';
2
2
 
3
- export const Set = (iterable: any): Set => {
3
+ // dark wasm magic for dealing with memory, sorry.
4
+ export const __Porffor_allocate = (): number => {
5
+ Porffor.wasm`i32.const 1
6
+ memory.grow 0
7
+ drop
8
+ memory.size 0
9
+ i32.const 1
10
+ i32.sub
11
+ i32.const 65536
12
+ i32.mul
13
+ i32.from_u
14
+ return`;
15
+ };
4
16
 
5
- };
17
+ export const __Porffor_set_read = (_this: Set, index: number): any => {
18
+ Porffor.wasm`
19
+ local offset i32
20
+ local.get ${index}
21
+ i32.to_u
22
+ i32.const 9
23
+ i32.mul
24
+ local.get ${_this}
25
+ i32.to_u
26
+ i32.add
27
+ local.set offset
28
+
29
+ local.get offset
30
+ f64.load 0 4
31
+
32
+ local.get offset
33
+ i32.load8_u 0 12
34
+ return`;
35
+ };
36
+
37
+ export const __Porffor_set_write = (_this: Set, index: number, value: any): boolean => {
38
+ Porffor.wasm`
39
+ local offset i32
40
+ local.get ${index}
41
+ i32.to_u
42
+ i32.const 9
43
+ i32.mul
44
+ local.get ${_this}
45
+ i32.to_u
46
+ i32.add
47
+ local.set offset
48
+
49
+ local.get offset
50
+ local.get ${value}
51
+ f64.store 0 4
52
+
53
+ local.get offset
54
+ local.get ${value+1}
55
+ i32.store8 0 12`;
56
+
57
+ return true;
58
+ };
59
+
60
+
61
+ export const __Set_prototype_size$get = (_this: Set) => {
62
+ return Porffor.wasm.i32.load(_this, 0, 0);
63
+ };
64
+
65
+ export const __Set_prototype_values = (_this: Set) => {
66
+ // todo: this should return an iterator not array
67
+ const size: number = Porffor.wasm.i32.load(_this, 0, 0);
68
+
69
+ const out: any[] = __Porffor_allocate();
70
+ for (let i: number = 0; i < size; i++) {
71
+ const val: any = __Porffor_set_read(_this, i);
72
+ out.push(val);
73
+ }
74
+
75
+ return out;
76
+ };
77
+
78
+ export const __Set_prototype_keys = (_this: Set) => {
79
+ return __Set_prototype_values(_this);
80
+ };
81
+
82
+ export const __Set_prototype_has = (_this: Set, value: any) => {
83
+ const size: number = Porffor.wasm.i32.load(_this, 0, 0);
84
+
85
+ for (let i: number = 0; i < size; i++) {
86
+ if (__Porffor_set_read(_this, i) === value) return true;
87
+ }
88
+
89
+ return false;
90
+ };
91
+
92
+ export const __Set_prototype_add = (_this: Set, value: any) => {
93
+ const size: number = Porffor.wasm.i32.load(_this, 0, 0);
94
+
95
+ // check if already in set
96
+ for (let i: number = 0; i < size; i++) {
97
+ if (__Porffor_set_read(_this, i) === value) return _this;
98
+ }
99
+
100
+ // not, add it
101
+ // increment size by 1
102
+ Porffor.wasm.i32.store(_this, size + 1, 0, 0);
103
+
104
+ // write new value at end
105
+ __Porffor_set_write(_this, size, value);
106
+
107
+ return _this;
108
+ };
109
+
110
+ export const __Set_prototype_delete = (_this: Set, value: any) => {
111
+ const size: number = Porffor.wasm.i32.load(_this, 0, 0);
112
+
113
+ // check if already in set
114
+ for (let i: number = 0; i < size; i++) {
115
+ if (__Porffor_set_read(_this, i) === value) {
116
+ // found, delete
117
+ // decrement size by 1
118
+ Porffor.wasm.i32.store(_this, size - 1, 0, 0);
119
+
120
+ // offset all elements after by -1 ind
121
+ Porffor.wasm`
122
+ local offset i32
123
+ local.get ${i}
124
+ i32.to_u
125
+ i32.const 9
126
+ i32.mul
127
+ local.get ${_this}
128
+ i32.to_u
129
+ i32.add
130
+ i32.const 4
131
+ i32.add
132
+ local.set offset
133
+
134
+ ;; dst = offset (this element)
135
+ local.get offset
136
+
137
+ ;; src = offset + 9 (this element + 1 element)
138
+ local.get offset
139
+ i32.const 9
140
+ i32.add
141
+
142
+ ;; size = (size - i - 1) * 9
143
+ local.get ${size}
144
+ local.get ${i}
145
+ f64.sub
146
+ i32.to_u
147
+ i32.const 1
148
+ i32.sub
149
+ i32.const 9
150
+ i32.mul
151
+
152
+ memory.copy 0 0`;
153
+
154
+ return true;
155
+ }
156
+ }
157
+
158
+ // not, return false
159
+ return false;
160
+ };
161
+
162
+ export const __Set_prototype_clear = (_this: Set) => {
163
+ // just set size to 0
164
+ // do not need to delete any as will not be accessed anymore,
165
+ // and will be overwritten with new add
166
+ Porffor.wasm.i32.store(_this, 0, 0, 0);
167
+ };
168
+
169
+ export const Set = () => {
170
+ throw new TypeError("Constructor Set requires 'new'");
171
+ };
172
+
173
+ export const Set$constructor = (iterable: any): Set => {
174
+ const out: Set = __Porffor_allocate();
175
+
176
+ const type: number = Porffor.rawType(iterable);
177
+ if (Porffor.fastOr(
178
+ type == Porffor.TYPES.array,
179
+ type == Porffor.TYPES.string, type == Porffor.TYPES.bytestring,
180
+ type == Porffor.TYPES.set
181
+ )) {
182
+ for (const x of iterable) {
183
+ __Set_prototype_add(out, x);
184
+ }
185
+ }
186
+
187
+ return out;
188
+ };
189
+
190
+ export const __Set_prototype_union = (_this: Set, other: any) => {
191
+ if (Porffor.rawType(other) != Porffor.TYPES.set) {
192
+ throw new TypeError("Set.union requires 'Set'");
193
+ }
194
+ const out: Set = new Set(_this);
195
+ for (const x of other) {
196
+ out.add(x);
197
+ }
198
+ return out;
199
+ };
@@ -1,4 +1,5 @@
1
- // @porf --funsafe-no-unlikely-proto-checks --valtype=i32
1
+ // @porf --valtype=i32
2
+ import type {} from './porffor.d.ts';
2
3
 
3
4
  export const __String_fromCharCode = (code: i32) => {
4
5
  // todo: support >1 arg
@@ -0,0 +1,62 @@
1
+ import type {} from './porffor.d.ts';
2
+
3
+ export const __Porffor_symbol_descStore = (op: boolean, value: any): any => {
4
+ const ptr: bytestring = '';
5
+
6
+ if (op) { // write
7
+ const size: number = Porffor.wasm.i32.load(ptr, 0, 0);
8
+ Porffor.wasm.i32.store(ptr, size + 1, 0, 0)
9
+
10
+ // reuse set internals to store description
11
+ __Porffor_set_write(ptr, size, value);
12
+ return size;
13
+ } else { // read
14
+ return __Porffor_set_read(ptr, value);
15
+ }
16
+ };
17
+
18
+ export const Symbol = (description: any): Symbol => {
19
+ // 1-based so always truthy as numeric value
20
+ return __Porffor_symbol_descStore(true, description) + 1;
21
+ };
22
+
23
+ export const __Symbol_prototype_description$get = (_this: Symbol) => {
24
+ const description: bytestring = __Porffor_symbol_descStore(false,
25
+ Porffor.wasm`local.get ${_this}` - 1);
26
+ return description;
27
+ };
28
+
29
+ export const __Symbol_prototype_toString = (_this: Symbol) => {
30
+ let out: bytestring = '';
31
+
32
+ // Symbol(
33
+ Porffor.wasm.i32.store8(out, 83, 0, 4);
34
+ Porffor.wasm.i32.store8(out, 121, 0, 5);
35
+ Porffor.wasm.i32.store8(out, 109, 0, 6);
36
+ Porffor.wasm.i32.store8(out, 98, 0, 7);
37
+ Porffor.wasm.i32.store8(out, 111, 0, 8);
38
+ Porffor.wasm.i32.store8(out, 108, 0, 9);
39
+ Porffor.wasm.i32.store8(out, 40, 0, 10);
40
+
41
+ const description: bytestring = __Porffor_symbol_descStore(false,
42
+ Porffor.wasm`local.get ${_this}` - 1);
43
+
44
+ const descLen: i32 = description.length;
45
+ let outPtr: i32 = Porffor.wasm`local.get ${out}` + 7;
46
+ let descPtr: i32 = Porffor.wasm`local.get ${description}`;
47
+ const descPtrEnd: i32 = descPtr + descLen;
48
+ while (descPtr < descPtrEnd) {
49
+ Porffor.wasm.i32.store8(outPtr++, Porffor.wasm.i32.load8_u(descPtr++, 0, 4), 0, 4);
50
+ }
51
+
52
+ // )
53
+ Porffor.wasm.i32.store8(Porffor.wasm`local.get ${out}` + descLen, 41, 0, 11);
54
+
55
+ out.length = 8 + descLen;
56
+
57
+ return out;
58
+ };
59
+
60
+ export const __Symbol_prototype_valueOf = (_this: Symbol) => {
61
+ return _this;
62
+ };
@@ -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
  {
@@ -40,6 +40,18 @@ export const importedFuncs = [
40
40
  import: 'z',
41
41
  params: 1,
42
42
  returns: 0
43
+ },
44
+ {
45
+ name: '__Porffor_readArgv',
46
+ import: 'w',
47
+ params: 2,
48
+ returns: 0
49
+ },
50
+ {
51
+ name: '__Porffor_readFile',
52
+ import: 'q',
53
+ params: 2,
54
+ returns: 0
43
55
  }
44
56
  ];
45
57
 
@@ -48,8 +60,6 @@ for (let i = 0; i < importedFuncs.length; i++) {
48
60
  importedFuncs[f.name] = i;
49
61
  }
50
62
 
51
- const char = c => number(c.charCodeAt(0));
52
-
53
63
  const printStaticStr = str => {
54
64
  const out = [];
55
65
 
@@ -140,7 +150,7 @@ export const BuiltinVars = function() {
140
150
  this.Math = number(1);
141
151
 
142
152
  // wintercg(tm)
143
- this.__navigator_userAgent = (scope, { makeString }) => makeString(scope, `Porffor/0.2.0`, false, '__navigator_userAgent');
153
+ this.__navigator_userAgent = (scope, { makeString }) => makeString(scope, `Porffor/0.14.0`, false, '__navigator_userAgent');
144
154
  this.__navigator_userAgent.type = Prefs.bytestring ? TYPES.bytestring : TYPES.string;
145
155
 
146
156
  for (const x in TYPES) {
@@ -200,7 +210,8 @@ export const BuiltinFuncs = function() {
200
210
  returns: [ valtypeBinary ],
201
211
  wasm: [
202
212
  [ Opcodes.local_get, 0 ]
203
- ]
213
+ ],
214
+ constr: true
204
215
  };
205
216
 
206
217
  // just return given (default 0) for (new) Object() as we somewhat supports object just not constructor
@@ -212,7 +223,8 @@ export const BuiltinFuncs = function() {
212
223
  wasm: [
213
224
  // [ Opcodes.local_get, 0 ]
214
225
  ...number(1)
215
- ]
226
+ ],
227
+ constr: true
216
228
  };
217
229
 
218
230
 
@@ -221,7 +233,7 @@ export const BuiltinFuncs = function() {
221
233
  typedParams: true,
222
234
  locals: [ Valtype.i32, Valtype.i32 ],
223
235
  returns: [],
224
- wasm: (scope, { typeSwitch }) => [
236
+ wasm: (scope, { typeSwitch, builtin }) => [
225
237
  ...typeSwitch(scope, [ [ Opcodes.local_get, 1 ] ], {
226
238
  [TYPES.number]: [
227
239
  [ Opcodes.local_get, 0 ],
@@ -317,7 +329,7 @@ export const BuiltinFuncs = function() {
317
329
 
318
330
  // make end pointer
319
331
  [ Opcodes.i32_load, Math.log2(ValtypeSize.i32) - 1, 0 ],
320
- ...number(ValtypeSize[valtype], Valtype.i32),
332
+ ...number(ValtypeSize[valtype] + 1, Valtype.i32),
321
333
  [ Opcodes.i32_mul ],
322
334
 
323
335
  [ Opcodes.local_get, 2 ],
@@ -326,14 +338,18 @@ export const BuiltinFuncs = function() {
326
338
 
327
339
  [ Opcodes.loop, Blocktype.void ],
328
340
 
329
- // print current char
341
+ // print current array element
330
342
  [ Opcodes.local_get, 2 ],
331
- [ Opcodes.load, Math.log2(ValtypeSize.i16) - 1, ValtypeSize.i32 ],
332
- [ Opcodes.call, importedFuncs.print ],
343
+ [ Opcodes.load, 0, ValtypeSize.i32 ],
344
+
345
+ [ Opcodes.local_get, 2 ],
346
+ [ Opcodes.i32_load8_u, 0, ValtypeSize.i32 + ValtypeSize[valtype] ],
347
+
348
+ [ Opcodes.call, builtin('__Porffor_print') ],
333
349
 
334
350
  // increment pointer by sizeof valtype
335
351
  [ Opcodes.local_get, 2 ],
336
- ...number(ValtypeSize[valtype], Valtype.i32),
352
+ ...number(ValtypeSize[valtype] + 1, Valtype.i32),
337
353
  [ Opcodes.i32_add ],
338
354
  [ Opcodes.local_tee, 2 ],
339
355
 
@@ -569,7 +585,6 @@ export const BuiltinFuncs = function() {
569
585
 
570
586
  // this is an implementation of xorshift128+ (in wasm bytecode)
571
587
  // 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
588
  const prngSeed0 = (Math.random() * (2 ** 30)) | 0, prngSeed1 = (Math.random() * (2 ** 30)) | 0;
574
589
 
575
590
  const prng = ({