porffor 0.20.6 → 0.20.8
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/compiler/builtins/_internal_object.ts +131 -0
- package/compiler/builtins/console.ts +1 -1
- package/compiler/builtins/error.js +2 -2
- package/compiler/builtins/object.ts +107 -13
- package/compiler/builtins/set.ts +1 -15
- package/compiler/builtins/weakref.ts +1 -1
- package/compiler/builtins/z_ecma262.ts +6 -5
- package/compiler/builtins/z_map.ts +2 -4
- package/compiler/builtins/z_weakmap.ts +3 -5
- package/compiler/builtins/z_weakset.ts +2 -5
- package/compiler/builtins.js +16 -16
- package/compiler/codegen.js +305 -285
- package/compiler/generated_builtins.js +725 -694
- package/compiler/precompile.js +13 -1
- package/compiler/types.js +32 -17
- package/compiler/wrap.js +23 -9
- package/package.json +1 -1
- package/runner/index.js +1 -1
@@ -0,0 +1,131 @@
|
|
1
|
+
// @porf --valtype=i32
|
2
|
+
import type {} from './porffor.d.ts';
|
3
|
+
|
4
|
+
// memory layout:
|
5
|
+
// size (i32, 4)
|
6
|
+
// per entry (14):
|
7
|
+
// key - value, type MSB encoded (u32, 4)
|
8
|
+
// value - value (f64, 8)
|
9
|
+
// value - type + obj flag (u16, 2)
|
10
|
+
// flags:
|
11
|
+
// accessor - 0b0001
|
12
|
+
// configurable - 0b0010
|
13
|
+
// enumerable - 0b0100
|
14
|
+
// writable - 0b1000
|
15
|
+
|
16
|
+
export const __Porffor_object_lookup = (_this: object, target: any): i32 => {
|
17
|
+
const targetType: i32 = Porffor.wasm`local.get ${target+1}`;
|
18
|
+
|
19
|
+
let ptr: i32 = Porffor.wasm`local.get ${_this}` + 4;
|
20
|
+
|
21
|
+
const size: i32 = Porffor.wasm.i32.load(_this, 0, 0);
|
22
|
+
const endPtr: i32 = ptr + size * 14;
|
23
|
+
|
24
|
+
if (targetType == Porffor.TYPES.bytestring) {
|
25
|
+
const targetStr: bytestring = target;
|
26
|
+
for (; ptr < endPtr; ptr += 14) {
|
27
|
+
const keyRaw: i32 = Porffor.wasm.i32.load(ptr, 0, 0);
|
28
|
+
if (keyRaw == 0) break; // ran out of keys
|
29
|
+
if (keyRaw >>> 31) continue; // MSB set, regular string type
|
30
|
+
|
31
|
+
const keyStr: bytestring = keyRaw;
|
32
|
+
if (keyStr == targetStr) return ptr;
|
33
|
+
}
|
34
|
+
} else {
|
35
|
+
const targetStr: string = target;
|
36
|
+
for (; ptr < endPtr; ptr += 14) {
|
37
|
+
const keyRaw: i32 = Porffor.wasm.i32.load(ptr, 0, 0);
|
38
|
+
if (keyRaw == 0) break; // ran out of keys
|
39
|
+
if (keyRaw >>> 31) { // MSB set, regular string type
|
40
|
+
const keyStr: string = keyRaw & 0x7FFFFFFF; // unset MSB
|
41
|
+
if (keyStr == targetStr) return ptr;
|
42
|
+
}
|
43
|
+
}
|
44
|
+
}
|
45
|
+
|
46
|
+
return -1;
|
47
|
+
};
|
48
|
+
|
49
|
+
export const __Porffor_object_get = (_this: object, key: any): any => {
|
50
|
+
const entryPtr: i32 = __Porffor_object_lookup(_this, key);
|
51
|
+
if (entryPtr == -1) {
|
52
|
+
Porffor.wasm`
|
53
|
+
f64.const 0
|
54
|
+
i32.const 128
|
55
|
+
return`;
|
56
|
+
}
|
57
|
+
|
58
|
+
const tail: i32 = Porffor.wasm.i32.load16_u(entryPtr, 0, 12);
|
59
|
+
|
60
|
+
if (tail & 0b0001) {
|
61
|
+
// accessor descriptor
|
62
|
+
// todo
|
63
|
+
|
64
|
+
Porffor.wasm`
|
65
|
+
f64.const 0
|
66
|
+
i32.const 128
|
67
|
+
return`;
|
68
|
+
}
|
69
|
+
|
70
|
+
// data descriptor
|
71
|
+
Porffor.wasm`
|
72
|
+
local.get ${entryPtr}
|
73
|
+
f64.load 0 4
|
74
|
+
local.get ${tail}
|
75
|
+
i32.const 8
|
76
|
+
i32.shr_u
|
77
|
+
return`;
|
78
|
+
};
|
79
|
+
|
80
|
+
export const __Porffor_object_set = (_this: object, key: any, value: any): any => {
|
81
|
+
let entryPtr: i32 = __Porffor_object_lookup(_this, key);
|
82
|
+
let flags: i32;
|
83
|
+
if (entryPtr == -1) {
|
84
|
+
// add new entry
|
85
|
+
// bump size +1
|
86
|
+
const size: i32 = Porffor.wasm.i32.load(_this, 0, 0);
|
87
|
+
Porffor.wasm.i32.store(_this, size + 1, 0, 0);
|
88
|
+
|
89
|
+
// entryPtr = current end of object
|
90
|
+
entryPtr = Porffor.wasm`local.get ${_this}` + 4 + size * 14;
|
91
|
+
|
92
|
+
// encode key type, set MSB if regular string
|
93
|
+
let keyEnc: i32 = Porffor.wasm`local.get ${key}`;
|
94
|
+
if (Porffor.wasm`local.get ${key+1}` == Porffor.TYPES.string) keyEnc |= 0x80000000;
|
95
|
+
|
96
|
+
// write key value and type (MSB)
|
97
|
+
Porffor.wasm.i32.store(entryPtr, keyEnc, 0, 0);
|
98
|
+
|
99
|
+
// flags = writable, enumerable, configurable, not accessor
|
100
|
+
flags = 0b1110;
|
101
|
+
} else {
|
102
|
+
// existing entry, modify it
|
103
|
+
const tail: i32 = Porffor.wasm.i32.load16_u(entryPtr, 0, 12);
|
104
|
+
|
105
|
+
if (tail & 0b0001) {
|
106
|
+
// accessor descriptor
|
107
|
+
// todo
|
108
|
+
|
109
|
+
return value;
|
110
|
+
}
|
111
|
+
|
112
|
+
// data descriptor
|
113
|
+
if (!(tail & 0b1000)) {
|
114
|
+
// not writable, return now
|
115
|
+
return value;
|
116
|
+
}
|
117
|
+
|
118
|
+
// flags = same flags as before
|
119
|
+
flags = tail & 0xff;
|
120
|
+
}
|
121
|
+
|
122
|
+
// write new value value (lol)
|
123
|
+
Porffor.wasm.f64.store(entryPtr, value, 0, 4);
|
124
|
+
|
125
|
+
// write new tail (value type + flags)
|
126
|
+
Porffor.wasm.i32.store16(entryPtr,
|
127
|
+
flags + (Porffor.wasm`local.get ${value+1}` << 8),
|
128
|
+
0, 12);
|
129
|
+
|
130
|
+
return value;
|
131
|
+
};
|
@@ -1,5 +1,19 @@
|
|
1
1
|
import type {} from './porffor.d.ts';
|
2
2
|
|
3
|
+
export const Object = function (value: any): object {
|
4
|
+
new.target; // trick compiler into allowing as constructor
|
5
|
+
|
6
|
+
if (value == null) {
|
7
|
+
// if nullish, return new empty object
|
8
|
+
const obj: object = Porffor.allocate();
|
9
|
+
return obj;
|
10
|
+
}
|
11
|
+
|
12
|
+
// todo: turn primitive args into objects
|
13
|
+
// return input
|
14
|
+
return value;
|
15
|
+
};
|
16
|
+
|
3
17
|
export const __Object_keys = (obj: any): any[] => {
|
4
18
|
if (obj == null) throw new TypeError('Argument is nullish, expected object');
|
5
19
|
|
@@ -7,13 +21,46 @@ export const __Object_keys = (obj: any): any[] => {
|
|
7
21
|
|
8
22
|
const t: i32 = Porffor.rawType(obj);
|
9
23
|
if (t == Porffor.TYPES.object) {
|
10
|
-
const
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
24
|
+
const size: i32 = Porffor.wasm.i32.load(obj, 0, 0);
|
25
|
+
let len: i32 = size;
|
26
|
+
|
27
|
+
let ptr: i32 = Porffor.wasm`local.get ${obj}` + 4;
|
28
|
+
const endPtr: i32 = ptr + size * 14;
|
29
|
+
|
30
|
+
let i: i32 = 0;
|
31
|
+
for (; ptr < endPtr; ptr += 14) {
|
32
|
+
// todo: check enumerable flag
|
33
|
+
|
34
|
+
let key: any;
|
35
|
+
Porffor.wasm`local raw i32
|
36
|
+
local.get ${ptr}
|
37
|
+
i32.to_u
|
38
|
+
i32.load 0 0
|
39
|
+
local.set raw
|
40
|
+
|
41
|
+
local.get raw
|
42
|
+
i32.const 31
|
43
|
+
i32.shr_u
|
44
|
+
if 127
|
45
|
+
i32.const 67
|
46
|
+
local.set ${key+1}
|
47
|
+
|
48
|
+
local.get raw
|
49
|
+
i32.const 2147483647
|
50
|
+
i32.and
|
51
|
+
else
|
52
|
+
i32.const 195
|
53
|
+
local.set ${key+1}
|
54
|
+
|
55
|
+
local.get raw
|
56
|
+
end
|
57
|
+
i32.from_u
|
58
|
+
local.set ${key}`;
|
59
|
+
|
60
|
+
out[i++] = key;
|
16
61
|
}
|
62
|
+
|
63
|
+
out.length = len;
|
17
64
|
} else if (Porffor.fastOr(
|
18
65
|
t == Porffor.TYPES.array,
|
19
66
|
t == Porffor.TYPES.bytestring,
|
@@ -37,13 +84,33 @@ export const __Object_values = (obj: any): any[] => {
|
|
37
84
|
|
38
85
|
const t: i32 = Porffor.rawType(obj);
|
39
86
|
if (t == Porffor.TYPES.object) {
|
40
|
-
const size: i32 = Porffor.wasm.i32.load(
|
41
|
-
|
87
|
+
const size: i32 = Porffor.wasm.i32.load(obj, 0, 0);
|
88
|
+
let len: i32 = size;
|
42
89
|
|
43
|
-
|
44
|
-
|
45
|
-
|
90
|
+
let ptr: i32 = Porffor.wasm`local.get ${obj}` + 4;
|
91
|
+
const endPtr: i32 = ptr + size * 14;
|
92
|
+
|
93
|
+
let i: i32 = 0;
|
94
|
+
for (; ptr < endPtr; ptr += 14) {
|
95
|
+
// todo: check enumerable flag
|
96
|
+
|
97
|
+
let val: any;
|
98
|
+
Porffor.wasm`local ptr32 i32
|
99
|
+
local.get ${ptr}
|
100
|
+
i32.to_u
|
101
|
+
local.tee ptr32
|
102
|
+
|
103
|
+
f64.load 0 4
|
104
|
+
local.set ${val}
|
105
|
+
|
106
|
+
local.get ptr32
|
107
|
+
i32.load8_u 0 13
|
108
|
+
local.set ${val+1}`;
|
109
|
+
|
110
|
+
out[i++] = val;
|
46
111
|
}
|
112
|
+
|
113
|
+
out.length = len;
|
47
114
|
} else if (Porffor.fastOr(
|
48
115
|
t == Porffor.TYPES.array,
|
49
116
|
t == Porffor.TYPES.bytestring,
|
@@ -83,14 +150,24 @@ export const __Object_entries = (obj: any): any[] => {
|
|
83
150
|
return out;
|
84
151
|
};
|
85
152
|
|
153
|
+
export const __Object_fromEntries = (iterable: any): object => {
|
154
|
+
const out: object = {};
|
155
|
+
|
156
|
+
for (const x of iterable) {
|
157
|
+
if (Porffor.rawType(x) < 0x06) throw new TypeError('Iterator contains non-object');
|
158
|
+
out[ecma262.ToPropertyKey(x[0])] = x[1];
|
159
|
+
}
|
160
|
+
|
161
|
+
return out;
|
162
|
+
};
|
163
|
+
|
86
164
|
|
87
165
|
export const __Object_prototype_hasOwnProperty = (_this: any, prop: any) => {
|
88
166
|
const p: any = ecma262.ToPropertyKey(prop);
|
89
167
|
|
90
168
|
const t: i32 = Porffor.rawType(_this);
|
91
169
|
if (t == Porffor.TYPES.object) {
|
92
|
-
|
93
|
-
return __Set_prototype_has(keys, p);
|
170
|
+
return __Porffor_object_lookup(_this, prop) != -1;
|
94
171
|
}
|
95
172
|
|
96
173
|
const keys: any[] = __Object_keys(_this);
|
@@ -103,6 +180,23 @@ export const __Object_hasOwn = (obj: any, prop: any) => {
|
|
103
180
|
};
|
104
181
|
|
105
182
|
|
183
|
+
export const __Object_assign = (target: any, ...sources: any[]) => {
|
184
|
+
if (target == null) throw new TypeError('Argument is nullish, expected object');
|
185
|
+
|
186
|
+
for (const x of sources) {
|
187
|
+
const keys: any[] = __Object_keys(x);
|
188
|
+
const vals: any[] = __Object_values(x);
|
189
|
+
|
190
|
+
const len: i32 = keys.length;
|
191
|
+
for (let i: i32 = 0; i < len; i++) {
|
192
|
+
target[keys[i]] = vals[i];
|
193
|
+
}
|
194
|
+
}
|
195
|
+
|
196
|
+
return target;
|
197
|
+
};
|
198
|
+
|
199
|
+
|
106
200
|
export const __Object_prototype_toString = (_this: object) => {
|
107
201
|
let out: bytestring = '[object Object]';
|
108
202
|
return out;
|
package/compiler/builtins/set.ts
CHANGED
@@ -1,17 +1,6 @@
|
|
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`
|
6
|
-
i32.const 1
|
7
|
-
memory.grow 0
|
8
|
-
i32.const 65536
|
9
|
-
i32.mul
|
10
|
-
i32.from_u
|
11
|
-
i32.const 1
|
12
|
-
return`;
|
13
|
-
};
|
14
|
-
|
15
4
|
export const __Porffor_set_read = (_this: Set, index: number): any => {
|
16
5
|
Porffor.wasm`
|
17
6
|
local offset i32
|
@@ -184,10 +173,7 @@ export const Set = function (iterable: any): Set {
|
|
184
173
|
|
185
174
|
const out: Set = __Porffor_allocate();
|
186
175
|
|
187
|
-
if (
|
188
|
-
Porffor.rawType(iterable) != Porffor.TYPES.undefined,
|
189
|
-
iterable !== null
|
190
|
-
)) for (const x of iterable) {
|
176
|
+
if (iterable != null) for (const x of iterable) {
|
191
177
|
__Set_prototype_add(out, x);
|
192
178
|
}
|
193
179
|
|
@@ -3,7 +3,7 @@ import type {} from './porffor.d.ts';
|
|
3
3
|
export const WeakRef = function (target: any): WeakRef {
|
4
4
|
if (!new.target) throw new TypeError("Constructor WeakRef requires 'new'");
|
5
5
|
|
6
|
-
if (Porffor.rawType(target) <
|
6
|
+
if (Porffor.rawType(target) < 0x05) throw new TypeError('Target for WeakRef needs to be an object or symbol');
|
7
7
|
|
8
8
|
const out: WeakRef = Porffor.allocateBytes(9);
|
9
9
|
|
@@ -26,7 +26,6 @@ export const __ecma262_ToIntegerOrInfinity = (argument: unknown): number => {
|
|
26
26
|
// 7.1.17 ToString (argument)
|
27
27
|
// https://tc39.es/ecma262/#sec-tostring
|
28
28
|
export const __ecma262_ToString = (argument: unknown): bytestring => {
|
29
|
-
let out: bytestring = Porffor.allocate();
|
30
29
|
const type: i32 = Porffor.rawType(argument);
|
31
30
|
|
32
31
|
// 1. If argument is a String, return argument.
|
@@ -37,6 +36,8 @@ export const __ecma262_ToString = (argument: unknown): bytestring => {
|
|
37
36
|
// 2. If argument is a Symbol, throw a TypeError exception.
|
38
37
|
if (type == Porffor.TYPES.symbol) throw new TypeError('Cannot convert a Symbol value to a string');
|
39
38
|
|
39
|
+
let out: bytestring = Porffor.allocate();
|
40
|
+
|
40
41
|
// 3. If argument is undefined, return "undefined".
|
41
42
|
if (Porffor.fastOr(
|
42
43
|
type == Porffor.TYPES.undefined,
|
@@ -68,14 +69,14 @@ export const __ecma262_ToString = (argument: unknown): bytestring => {
|
|
68
69
|
// https://tc39.es/ecma262/#sec-topropertykey
|
69
70
|
export const __ecma262_ToPropertyKey = (argument: any): any => {
|
70
71
|
// 1. Let key be ? ToPrimitive(argument, string).
|
71
|
-
|
72
|
+
// argument = key
|
72
73
|
|
73
74
|
// 2. If key is a Symbol, then
|
74
|
-
if (Porffor.rawType(
|
75
|
+
if (Porffor.rawType(argument) == Porffor.TYPES.symbol) {
|
75
76
|
// a. Return key.
|
76
|
-
return
|
77
|
+
return argument;
|
77
78
|
}
|
78
79
|
|
79
80
|
// 3. Return ! ToString(key).
|
80
|
-
return __ecma262_ToString(
|
81
|
+
return __ecma262_ToString(argument);
|
81
82
|
};
|
@@ -97,10 +97,8 @@ export const Map = function (iterable: any): Map {
|
|
97
97
|
const vals: any[] = Porffor.allocate();
|
98
98
|
Porffor.wasm.i32.store(out, vals, 0, 4);
|
99
99
|
|
100
|
-
if (
|
101
|
-
Porffor.rawType(
|
102
|
-
iterable !== null
|
103
|
-
)) for (const x of iterable) {
|
100
|
+
if (iterable != null) for (const x of iterable) {
|
101
|
+
if (Porffor.rawType(x) < 0x06) throw new TypeError('Iterator contains non-object');
|
104
102
|
__Map_prototype_set(out, x[0], x[1]);
|
105
103
|
}
|
106
104
|
|
@@ -3,7 +3,7 @@ import type {} from './porffor.d.ts';
|
|
3
3
|
export const __WeakMap_prototype_has = (_this: WeakMap, key: any) => __Map_prototype_has(_this, key);
|
4
4
|
|
5
5
|
export const __WeakMap_prototype_set = (_this: WeakMap, key: any, value: any) => {
|
6
|
-
if (Porffor.rawType(key) <
|
6
|
+
if (Porffor.rawType(key) < 0x05) throw new TypeError('Value in WeakSet needs to be an object or symbol');
|
7
7
|
|
8
8
|
__Map_prototype_set(_this, key, value);
|
9
9
|
return _this;
|
@@ -22,10 +22,8 @@ export const WeakMap = function (iterable: any): WeakMap {
|
|
22
22
|
const vals: any[] = Porffor.allocate();
|
23
23
|
Porffor.wasm.i32.store(out, vals, 0, 4);
|
24
24
|
|
25
|
-
if (
|
26
|
-
Porffor.rawType(
|
27
|
-
iterable !== null
|
28
|
-
)) for (const x of iterable) {
|
25
|
+
if (iterable != null) for (const x of iterable) {
|
26
|
+
if (Porffor.rawType(x) < 0x06) throw new TypeError('Iterator contains non-object');
|
29
27
|
__WeakMap_prototype_set(out, x[0], x[1]);
|
30
28
|
}
|
31
29
|
|
@@ -3,7 +3,7 @@ import type {} from './porffor.d.ts';
|
|
3
3
|
export const __WeakSet_prototype_has = (_this: WeakSet, value: any) => __Set_prototype_has(_this, value);
|
4
4
|
|
5
5
|
export const __WeakSet_prototype_add = (_this: WeakSet, value: any) => {
|
6
|
-
if (Porffor.rawType(value) <
|
6
|
+
if (Porffor.rawType(value) < 0x05) throw new TypeError('Value in WeakSet needs to be an object or symbol');
|
7
7
|
|
8
8
|
__Set_prototype_add(_this, value);
|
9
9
|
return _this;
|
@@ -16,10 +16,7 @@ export const WeakSet = function (iterable: any): WeakSet {
|
|
16
16
|
|
17
17
|
const out: WeakSet = __Porffor_allocate();
|
18
18
|
|
19
|
-
if (
|
20
|
-
Porffor.rawType(iterable) != Porffor.TYPES.undefined,
|
21
|
-
iterable !== null
|
22
|
-
)) for (const x of iterable) {
|
19
|
+
if (iterable != null) for (const x of iterable) {
|
23
20
|
__WeakSet_prototype_add(out, x);
|
24
21
|
}
|
25
22
|
|
package/compiler/builtins.js
CHANGED
@@ -248,19 +248,6 @@ export const BuiltinFuncs = function() {
|
|
248
248
|
constr: true
|
249
249
|
};
|
250
250
|
|
251
|
-
// just return given (default 0) for (new) Object() as we somewhat supports object just not constructor
|
252
|
-
this.Object = {
|
253
|
-
params: [ valtypeBinary ],
|
254
|
-
locals: [],
|
255
|
-
returns: [ valtypeBinary ],
|
256
|
-
returnType: TYPES.object,
|
257
|
-
wasm: [
|
258
|
-
// [ Opcodes.local_get, 0 ]
|
259
|
-
...number(1)
|
260
|
-
],
|
261
|
-
constr: true
|
262
|
-
};
|
263
|
-
|
264
251
|
this.isNaN = {
|
265
252
|
floatOnly: true,
|
266
253
|
params: [ valtypeBinary ],
|
@@ -427,7 +414,7 @@ export const BuiltinFuncs = function() {
|
|
427
414
|
returnType: TYPES.number,
|
428
415
|
wasm: [
|
429
416
|
[ Opcodes.local_get, 0 ],
|
430
|
-
Opcodes.
|
417
|
+
Opcodes.i32_to_u,
|
431
418
|
[ Opcodes.i32_clz ],
|
432
419
|
Opcodes.i32_from
|
433
420
|
]
|
@@ -455,9 +442,9 @@ export const BuiltinFuncs = function() {
|
|
455
442
|
returnType: TYPES.number,
|
456
443
|
wasm: [
|
457
444
|
[ Opcodes.local_get, 0 ],
|
458
|
-
Opcodes.
|
445
|
+
Opcodes.i32_to,
|
459
446
|
[ Opcodes.local_get, 1 ],
|
460
|
-
Opcodes.
|
447
|
+
Opcodes.i32_to,
|
461
448
|
[ Opcodes.i32_mul ],
|
462
449
|
Opcodes.i32_from
|
463
450
|
]
|
@@ -980,6 +967,19 @@ export const BuiltinFuncs = function() {
|
|
980
967
|
]
|
981
968
|
};
|
982
969
|
|
970
|
+
this.__Porffor_allocate = {
|
971
|
+
params: [],
|
972
|
+
locals: [],
|
973
|
+
returns: [ Valtype.i32 ],
|
974
|
+
returnType: TYPES.number,
|
975
|
+
wasm: [
|
976
|
+
...number(1, Valtype.i32),
|
977
|
+
[ Opcodes.memory_grow, 0 ],
|
978
|
+
...number(65536, Valtype.i32),
|
979
|
+
[ Opcodes.i32_mul ]
|
980
|
+
]
|
981
|
+
};
|
982
|
+
|
983
983
|
this.__Porffor_allocateBytes = {
|
984
984
|
params: [ Valtype.i32 ],
|
985
985
|
locals: [],
|