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.
- package/CONTRIBUTING.md +12 -7
- package/README.md +18 -15
- package/asur/index.js +1 -1
- package/byg/index.js +3 -24
- package/compiler/2c.js +69 -55
- package/compiler/assemble.js +51 -11
- package/compiler/builtins/annexb_string.js +10 -10
- package/compiler/builtins/annexb_string.ts +4 -3
- package/compiler/builtins/array.ts +85 -9
- package/compiler/builtins/base64.ts +2 -1
- package/compiler/builtins/boolean.ts +2 -2
- package/compiler/builtins/console.ts +4 -0
- package/compiler/builtins/crypto.ts +2 -1
- package/compiler/builtins/date.ts +2 -3
- package/compiler/builtins/error.js +22 -0
- package/compiler/builtins/escape.ts +2 -3
- package/compiler/builtins/function.ts +1 -1
- package/compiler/builtins/int.ts +1 -1
- package/compiler/builtins/math.ts +410 -0
- package/compiler/builtins/number.ts +4 -7
- package/compiler/builtins/object.ts +1 -1
- package/compiler/builtins/porffor.d.ts +9 -8
- package/compiler/builtins/set.ts +197 -3
- package/compiler/builtins/string.ts +2 -1
- package/compiler/builtins/symbol.ts +62 -0
- package/compiler/builtins.js +30 -15
- package/compiler/codegen.js +641 -365
- package/compiler/decompile.js +7 -3
- package/compiler/embedding.js +2 -2
- package/compiler/encoding.js +0 -14
- package/compiler/expression.js +1 -1
- package/compiler/generated_builtins.js +781 -187
- package/compiler/index.js +5 -11
- package/compiler/opt.js +7 -7
- package/compiler/parse.js +2 -4
- package/compiler/precompile.js +18 -25
- package/compiler/prefs.js +6 -2
- package/compiler/prototype.js +185 -162
- package/compiler/wasmSpec.js +5 -0
- package/compiler/wrap.js +150 -90
- package/package.json +1 -1
- package/runner/compare.js +0 -1
- package/runner/debug.js +1 -6
- package/runner/index.js +5 -4
- package/runner/profiler.js +15 -42
- package/runner/repl.js +20 -10
- package/runner/sizes.js +2 -2
- 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:
|
11
|
-
store(pointer:
|
12
|
-
load8_u(pointer:
|
13
|
-
store8(pointer:
|
14
|
-
load16_u(pointer:
|
15
|
-
store16(pointer:
|
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:
|
21
|
-
store(pointer:
|
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;
|
package/compiler/builtins/set.ts
CHANGED
@@ -1,5 +1,199 @@
|
|
1
|
-
|
1
|
+
import type {} from './porffor.d.ts';
|
2
2
|
|
3
|
-
|
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
|
+
};
|
@@ -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
|
+
};
|
package/compiler/builtins.js
CHANGED
@@ -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.
|
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
|
341
|
+
// print current array element
|
330
342
|
[ Opcodes.local_get, 2 ],
|
331
|
-
[ Opcodes.load,
|
332
|
-
|
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 = ({
|