porffor 0.20.7 → 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 +79 -13
- package/compiler/builtins/set.ts +0 -11
- package/compiler/builtins/z_ecma262.ts +6 -5
- package/compiler/builtins.js +16 -16
- package/compiler/codegen.js +290 -269
- package/compiler/generated_builtins.js +696 -678
- package/compiler/precompile.js +13 -1
- package/compiler/types.js +22 -1
- 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,
|
@@ -100,8 +167,7 @@ export const __Object_prototype_hasOwnProperty = (_this: any, prop: any) => {
|
|
100
167
|
|
101
168
|
const t: i32 = Porffor.rawType(_this);
|
102
169
|
if (t == Porffor.TYPES.object) {
|
103
|
-
|
104
|
-
return __Set_prototype_has(keys, p);
|
170
|
+
return __Porffor_object_lookup(_this, prop) != -1;
|
105
171
|
}
|
106
172
|
|
107
173
|
const keys: any[] = __Object_keys(_this);
|
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
|
@@ -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
|
};
|
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: [],
|