porffor 0.20.7 → 0.20.9
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 +222 -0
- package/compiler/builtins/console.ts +1 -1
- package/compiler/builtins/error.js +2 -2
- package/compiler/builtins/object.ts +117 -14
- package/compiler/builtins/set.ts +0 -11
- package/compiler/builtins/weakref.ts +1 -1
- package/compiler/builtins/z_ecma262.ts +7 -7
- package/compiler/builtins/z_map.ts +1 -1
- package/compiler/builtins/z_weakmap.ts +2 -2
- package/compiler/builtins/z_weakset.ts +1 -1
- package/compiler/builtins.js +16 -16
- package/compiler/codegen.js +293 -271
- package/compiler/generated_builtins.js +730 -683
- package/compiler/precompile.js +16 -3
- package/compiler/types.js +22 -1
- package/compiler/wrap.js +30 -10
- package/package.json +1 -1
- package/runner/index.js +1 -1
package/compiler/codegen.js
CHANGED
@@ -41,16 +41,23 @@ const isFuncType = type =>
|
|
41
41
|
const hasFuncWithName = name =>
|
42
42
|
Object.hasOwn(funcIndex, name) != null || Object.hasOwn(builtinFuncs, name) != null || Object.hasOwn(importedFuncs, name) != null || Object.hasOwn(internalConstrs, name) != null;
|
43
43
|
|
44
|
+
const astCache = new WeakMap();
|
45
|
+
const cacheAst = (decl, wasm) => {
|
46
|
+
astCache.set(decl, wasm);
|
47
|
+
return wasm;
|
48
|
+
};
|
44
49
|
const generate = (scope, decl, global = false, name = undefined, valueUnused = false) => {
|
50
|
+
if (astCache.has(decl)) return astCache.get(decl);
|
51
|
+
|
45
52
|
switch (decl.type) {
|
46
53
|
case 'BinaryExpression':
|
47
|
-
return generateBinaryExp(scope, decl, global, name);
|
54
|
+
return cacheAst(decl, generateBinaryExp(scope, decl, global, name));
|
48
55
|
|
49
56
|
case 'LogicalExpression':
|
50
|
-
return generateLogicExp(scope, decl);
|
57
|
+
return cacheAst(decl, generateLogicExp(scope, decl));
|
51
58
|
|
52
59
|
case 'Identifier':
|
53
|
-
return generateIdent(scope, decl);
|
60
|
+
return cacheAst(decl, generateIdent(scope, decl));
|
54
61
|
|
55
62
|
case 'ArrowFunctionExpression':
|
56
63
|
case 'FunctionDeclaration':
|
@@ -58,101 +65,100 @@ const generate = (scope, decl, global = false, name = undefined, valueUnused = f
|
|
58
65
|
const func = generateFunc(scope, decl);
|
59
66
|
|
60
67
|
if (decl.type.endsWith('Expression')) {
|
61
|
-
return number(func.index - importedFuncs.length);
|
68
|
+
return cacheAst(decl, number(func.index - importedFuncs.length));
|
62
69
|
}
|
63
70
|
|
64
|
-
return [];
|
71
|
+
return cacheAst(decl, []);
|
65
72
|
|
66
73
|
case 'BlockStatement':
|
67
|
-
return generateCode(scope, decl);
|
74
|
+
return cacheAst(decl, generateCode(scope, decl));
|
68
75
|
|
69
76
|
case 'ReturnStatement':
|
70
|
-
return generateReturn(scope, decl)
|
77
|
+
return cacheAst(decl, generateReturn(scope, decl))
|
71
78
|
|
72
79
|
case 'ExpressionStatement':
|
73
|
-
return generateExp(scope, decl)
|
80
|
+
return cacheAst(decl, generateExp(scope, decl))
|
74
81
|
|
75
82
|
case 'SequenceExpression':
|
76
|
-
return generateSequence(scope, decl)
|
83
|
+
return cacheAst(decl, generateSequence(scope, decl))
|
77
84
|
|
78
85
|
case 'ChainExpression':
|
79
|
-
return generateChain(scope, decl)
|
86
|
+
return cacheAst(decl, generateChain(scope, decl))
|
80
87
|
|
81
88
|
case 'CallExpression':
|
82
|
-
return generateCall(scope, decl, global, name, valueUnused)
|
89
|
+
return cacheAst(decl, generateCall(scope, decl, global, name, valueUnused))
|
83
90
|
|
84
91
|
case 'NewExpression':
|
85
|
-
return generateNew(scope, decl, global, name)
|
92
|
+
return cacheAst(decl, generateNew(scope, decl, global, name))
|
86
93
|
|
87
94
|
case 'Literal':
|
88
|
-
return generateLiteral(scope, decl, global, name)
|
95
|
+
return cacheAst(decl, generateLiteral(scope, decl, global, name))
|
89
96
|
|
90
97
|
case 'VariableDeclaration':
|
91
|
-
return generateVar(scope, decl)
|
98
|
+
return cacheAst(decl, generateVar(scope, decl))
|
92
99
|
|
93
100
|
case 'AssignmentExpression':
|
94
|
-
return generateAssign(scope, decl)
|
101
|
+
return cacheAst(decl, generateAssign(scope, decl))
|
95
102
|
|
96
103
|
case 'UnaryExpression':
|
97
|
-
return generateUnary(scope, decl)
|
104
|
+
return cacheAst(decl, generateUnary(scope, decl))
|
98
105
|
|
99
106
|
case 'UpdateExpression':
|
100
|
-
return generateUpdate(scope, decl, global, name, valueUnused)
|
107
|
+
return cacheAst(decl, generateUpdate(scope, decl, global, name, valueUnused))
|
101
108
|
|
102
109
|
case 'IfStatement':
|
103
|
-
return generateIf(scope, decl)
|
110
|
+
return cacheAst(decl, generateIf(scope, decl))
|
104
111
|
|
105
112
|
case 'ForStatement':
|
106
|
-
return generateFor(scope, decl)
|
113
|
+
return cacheAst(decl, generateFor(scope, decl))
|
107
114
|
|
108
115
|
case 'WhileStatement':
|
109
|
-
return generateWhile(scope, decl)
|
116
|
+
return cacheAst(decl, generateWhile(scope, decl))
|
110
117
|
|
111
118
|
case 'DoWhileStatement':
|
112
|
-
return generateDoWhile(scope, decl)
|
119
|
+
return cacheAst(decl, generateDoWhile(scope, decl))
|
113
120
|
|
114
121
|
case 'ForOfStatement':
|
115
|
-
return generateForOf(scope, decl)
|
122
|
+
return cacheAst(decl, generateForOf(scope, decl))
|
116
123
|
|
117
124
|
case 'SwitchStatement':
|
118
|
-
return generateSwitch(scope, decl)
|
125
|
+
return cacheAst(decl, generateSwitch(scope, decl))
|
119
126
|
|
120
127
|
case 'BreakStatement':
|
121
|
-
return generateBreak(scope, decl)
|
128
|
+
return cacheAst(decl, generateBreak(scope, decl))
|
122
129
|
|
123
130
|
case 'ContinueStatement':
|
124
|
-
return generateContinue(scope, decl)
|
131
|
+
return cacheAst(decl, generateContinue(scope, decl))
|
125
132
|
|
126
133
|
case 'LabeledStatement':
|
127
|
-
return generateLabel(scope, decl)
|
134
|
+
return cacheAst(decl, generateLabel(scope, decl))
|
128
135
|
|
129
136
|
case 'EmptyStatement':
|
130
|
-
return generateEmpty(scope, decl)
|
137
|
+
return cacheAst(decl, generateEmpty(scope, decl))
|
131
138
|
|
132
139
|
case 'MetaProperty':
|
133
|
-
return generateMeta(scope, decl)
|
140
|
+
return cacheAst(decl, generateMeta(scope, decl))
|
134
141
|
|
135
142
|
case 'ConditionalExpression':
|
136
|
-
return generateConditional(scope, decl)
|
143
|
+
return cacheAst(decl, generateConditional(scope, decl))
|
137
144
|
|
138
145
|
case 'ThrowStatement':
|
139
|
-
return generateThrow(scope, decl)
|
146
|
+
return cacheAst(decl, generateThrow(scope, decl))
|
140
147
|
|
141
148
|
case 'TryStatement':
|
142
|
-
return generateTry(scope, decl)
|
149
|
+
return cacheAst(decl, generateTry(scope, decl))
|
143
150
|
|
144
151
|
case 'DebuggerStatement':
|
145
|
-
|
146
|
-
return [[ Opcodes.call, importedFuncs.debugger ]];
|
152
|
+
return cacheAst(decl, [[ Opcodes.call, importedFuncs.debugger ]])
|
147
153
|
|
148
154
|
case 'ArrayExpression':
|
149
|
-
return generateArray(scope, decl, global, name)
|
155
|
+
return cacheAst(decl, generateArray(scope, decl, global, name))
|
150
156
|
|
151
157
|
case 'ObjectExpression':
|
152
|
-
return generateObject(scope, decl, global, name)
|
158
|
+
return cacheAst(decl, generateObject(scope, decl, global, name))
|
153
159
|
|
154
160
|
case 'MemberExpression':
|
155
|
-
return generateMember(scope, decl, global, name)
|
161
|
+
return cacheAst(decl, generateMember(scope, decl, global, name))
|
156
162
|
|
157
163
|
case 'ExportNamedDeclaration':
|
158
164
|
const funcsBefore = funcs.map(x => x.name);
|
@@ -167,7 +173,7 @@ const generate = (scope, decl, global = false, name = undefined, valueUnused = f
|
|
167
173
|
}
|
168
174
|
}
|
169
175
|
|
170
|
-
return []
|
176
|
+
return cacheAst(decl, [])
|
171
177
|
|
172
178
|
case 'TaggedTemplateExpression': {
|
173
179
|
const funcs = {
|
@@ -191,8 +197,8 @@ const generate = (scope, decl, global = false, name = undefined, valueUnused = f
|
|
191
197
|
|
192
198
|
let inst = Opcodes[asm[0].replace('.', '_')];
|
193
199
|
if (inst == null) throw new Error(`inline asm: inst ${asm[0]} not found`);
|
194
|
-
|
195
200
|
if (!Array.isArray(inst)) inst = [ inst ];
|
201
|
+
|
196
202
|
const immediates = asm.slice(1).map(x => {
|
197
203
|
const int = parseInt(x);
|
198
204
|
if (Number.isNaN(int)) {
|
@@ -206,7 +212,11 @@ const generate = (scope, decl, global = false, name = undefined, valueUnused = f
|
|
206
212
|
return int;
|
207
213
|
});
|
208
214
|
|
209
|
-
|
215
|
+
const encodeFunc = ({
|
216
|
+
[Opcodes.f64_const]: ieee754_binary64,
|
217
|
+
[Opcodes.if]: unsignedLEB128
|
218
|
+
})[inst[0]] ?? signedLEB128;
|
219
|
+
out.push([ ...inst, ...immediates.flatMap(x => encodeFunc(x)) ]);
|
210
220
|
}
|
211
221
|
|
212
222
|
return out;
|
@@ -218,7 +228,7 @@ const generate = (scope, decl, global = false, name = undefined, valueUnused = f
|
|
218
228
|
|
219
229
|
const func = decl.tag.name;
|
220
230
|
// hack for inline asm
|
221
|
-
if (!funcs[func]) return todo(scope, 'tagged template expressions not implemented', true)
|
231
|
+
if (!funcs[func]) return cacheAst(decl, todo(scope, 'tagged template expressions not implemented', true))
|
222
232
|
|
223
233
|
const { quasis, expressions } = decl.quasi;
|
224
234
|
let str = quasis[0].value.raw;
|
@@ -234,17 +244,17 @@ const generate = (scope, decl, global = false, name = undefined, valueUnused = f
|
|
234
244
|
str += quasis[i + 1].value.raw;
|
235
245
|
}
|
236
246
|
|
237
|
-
return funcs[func](str)
|
247
|
+
return cacheAst(decl, funcs[func](str))
|
238
248
|
}
|
239
249
|
|
240
250
|
default:
|
241
251
|
// ignore typescript nodes
|
242
252
|
if (decl.type.startsWith('TS') ||
|
243
253
|
decl.type === 'ImportDeclaration' && decl.importKind === 'type') {
|
244
|
-
return []
|
254
|
+
return cacheAst(decl, [])
|
245
255
|
}
|
246
256
|
|
247
|
-
return todo(scope, `no generation for ${decl.type}!`)
|
257
|
+
return cacheAst(decl, todo(scope, `no generation for ${decl.type}!`))
|
248
258
|
}
|
249
259
|
};
|
250
260
|
|
@@ -1196,7 +1206,12 @@ const asmFuncToAsm = (scope, func) => {
|
|
1196
1206
|
});
|
1197
1207
|
};
|
1198
1208
|
|
1199
|
-
const asmFunc = (name, { wasm, params, locals: localTypes, globals: globalTypes = [], globalInits = [], returns, returnType, localNames = [], globalNames = [], data: _data = [], table = false, constr = false, hasRestArgument = false }) => {
|
1209
|
+
const asmFunc = (name, { wasm, params = [], locals: localTypes = [], globals: globalTypes = [], globalInits = [], returns = [], returnType, localNames = [], globalNames = [], data: _data = [], table = false, constr = false, hasRestArgument = false } = {}) => {
|
1210
|
+
if (wasm == null) { // called with no builtin
|
1211
|
+
log.warning('codegen', `${name} has no built-in!`);
|
1212
|
+
wasm = [];
|
1213
|
+
}
|
1214
|
+
|
1200
1215
|
const existing = funcs.find(x => x.name === name);
|
1201
1216
|
if (existing) return existing;
|
1202
1217
|
|
@@ -2863,226 +2878,231 @@ const generateAssign = (scope, decl, _global, _name, valueUnused = false) => {
|
|
2863
2878
|
value: decl.left.property.name
|
2864
2879
|
};
|
2865
2880
|
|
2866
|
-
|
2867
|
-
...typeSwitch(scope, getNodeType(scope, decl.left.object), {
|
2868
|
-
[TYPES.array]: [
|
2869
|
-
...generate(scope, object),
|
2870
|
-
Opcodes.i32_to_u,
|
2881
|
+
// todo: review last type usage here
|
2871
2882
|
|
2872
|
-
|
2873
|
-
|
2874
|
-
|
2883
|
+
return typeSwitch(scope, getNodeType(scope, decl.left.object), {
|
2884
|
+
[TYPES.array]: [
|
2885
|
+
...generate(scope, object),
|
2886
|
+
Opcodes.i32_to_u,
|
2875
2887
|
|
2876
|
-
|
2877
|
-
|
2878
|
-
|
2879
|
-
[ Opcodes.i32_add ],
|
2880
|
-
[ Opcodes.local_tee, pointerTmp ],
|
2888
|
+
// get index as valtype
|
2889
|
+
...generate(scope, property),
|
2890
|
+
Opcodes.i32_to_u,
|
2881
2891
|
|
2882
|
-
|
2883
|
-
|
2884
|
-
|
2885
|
-
|
2886
|
-
|
2887
|
-
[ Opcodes.i32_load8_u, 0, ValtypeSize.i32 + ValtypeSize[valtype] ]
|
2888
|
-
], getNodeType(scope, decl.right), false, name, true)),
|
2889
|
-
[ Opcodes.local_tee, newValueTmp ],
|
2890
|
-
[ Opcodes.store, 0, ValtypeSize.i32 ],
|
2892
|
+
// turn into byte offset by * valtypeSize + 1
|
2893
|
+
...number(ValtypeSize[valtype] + 1, Valtype.i32),
|
2894
|
+
[ Opcodes.i32_mul ],
|
2895
|
+
[ Opcodes.i32_add ],
|
2896
|
+
[ Opcodes.local_tee, pointerTmp ],
|
2891
2897
|
|
2898
|
+
...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
|
2892
2899
|
[ Opcodes.local_get, pointerTmp ],
|
2893
|
-
|
2894
|
-
|
2895
|
-
|
2900
|
+
[ Opcodes.load, 0, ValtypeSize.i32 ]
|
2901
|
+
], generate(scope, decl.right), [
|
2902
|
+
[ Opcodes.local_get, pointerTmp ],
|
2903
|
+
[ Opcodes.i32_load8_u, 0, ValtypeSize.i32 + ValtypeSize[valtype] ]
|
2904
|
+
], getNodeType(scope, decl.right), false, name, true)),
|
2905
|
+
[ Opcodes.local_tee, newValueTmp ],
|
2906
|
+
[ Opcodes.store, 0, ValtypeSize.i32 ],
|
2896
2907
|
|
2897
|
-
[
|
2898
|
-
|
2899
|
-
|
2900
|
-
...getNodeType(scope, object),
|
2908
|
+
[ Opcodes.local_get, pointerTmp ],
|
2909
|
+
...getNodeType(scope, decl),
|
2910
|
+
[ Opcodes.i32_store8, 0, ValtypeSize.i32 + ValtypeSize[valtype] ],
|
2901
2911
|
|
2902
|
-
|
2903
|
-
|
2904
|
-
...toPropertyKey(scope),
|
2905
|
-
...(op === '=' ? [] : [ [ Opcodes.local_set, localTmp(scope, '#objset_property_type', Valtype.i32) ] ]),
|
2906
|
-
...(op === '=' ? [] : [ [ Opcodes.local_tee, localTmp(scope, '#objset_property') ] ]),
|
2907
|
-
...(op === '=' ? [] : [ [ Opcodes.local_get, localTmp(scope, '#objset_property_type', Valtype.i32) ] ]),
|
2912
|
+
[ Opcodes.local_get, newValueTmp ]
|
2913
|
+
],
|
2908
2914
|
|
2909
|
-
|
2910
|
-
|
2911
|
-
|
2915
|
+
[TYPES.object]: [
|
2916
|
+
...generate(scope, object),
|
2917
|
+
Opcodes.i32_to_u,
|
2918
|
+
...(op === '=' ? [] : [ [ Opcodes.local_tee, localTmp(scope, '#objset_object', Valtype.i32) ] ]),
|
2919
|
+
...getNodeType(scope, object),
|
2920
|
+
|
2921
|
+
...generate(scope, property, false, '#member_prop'),
|
2922
|
+
...getNodeType(scope, property),
|
2923
|
+
...toPropertyKey(scope, op === '='),
|
2924
|
+
...(op === '=' ? [] : [ [ Opcodes.local_set, localTmp(scope, '#objset_property_type', Valtype.i32) ] ]),
|
2925
|
+
...(op === '=' ? [] : [
|
2926
|
+
Opcodes.i32_to_u,
|
2927
|
+
[ Opcodes.local_tee, localTmp(scope, '#objset_property', Valtype.i32) ]
|
2928
|
+
]),
|
2929
|
+
...(op === '=' ? [] : [ [ Opcodes.local_get, localTmp(scope, '#objset_property_type', Valtype.i32) ] ]),
|
2912
2930
|
|
2913
|
-
|
2914
|
-
|
2931
|
+
...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
|
2932
|
+
[ Opcodes.local_get, localTmp(scope, '#objset_object', Valtype.i32) ],
|
2933
|
+
...getNodeType(scope, object),
|
2915
2934
|
|
2916
|
-
|
2917
|
-
|
2918
|
-
], generate(scope, decl.right), getLastType(scope), getNodeType(scope, decl.right), false, name, true)),
|
2919
|
-
[ Opcodes.local_tee, newValueTmp ],
|
2920
|
-
...getNodeType(scope, decl),
|
2935
|
+
[ Opcodes.local_get, localTmp(scope, '#objset_property', Valtype.i32) ],
|
2936
|
+
[ Opcodes.local_get, localTmp(scope, '#objset_property_type', Valtype.i32) ],
|
2921
2937
|
|
2922
|
-
[ Opcodes.call, ...unsignedLEB128(includeBuiltin(scope, '
|
2923
|
-
|
2938
|
+
[ Opcodes.call, ...unsignedLEB128(includeBuiltin(scope, '__Porffor_object_get').index) ],
|
2939
|
+
...setLastType(scope)
|
2940
|
+
], generate(scope, decl.right), getLastType(scope), getNodeType(scope, decl.right), false, name, true)),
|
2941
|
+
...getNodeType(scope, decl),
|
2924
2942
|
|
2925
|
-
|
2926
|
-
],
|
2943
|
+
[ Opcodes.call, ...unsignedLEB128(includeBuiltin(scope, '__Porffor_object_set').index) ],
|
2944
|
+
[ Opcodes.drop ],
|
2945
|
+
// ...setLastType(scope, getNodeType(scope, decl)),
|
2946
|
+
],
|
2927
2947
|
|
2928
|
-
|
2929
|
-
|
2930
|
-
|
2931
|
-
|
2948
|
+
...wrapBC({
|
2949
|
+
[TYPES.uint8array]: [
|
2950
|
+
[ Opcodes.i32_add ],
|
2951
|
+
...(op === '=' ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
|
2932
2952
|
|
2933
|
-
|
2934
|
-
|
2935
|
-
|
2936
|
-
|
2937
|
-
|
2938
|
-
|
2953
|
+
...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
|
2954
|
+
[ Opcodes.local_get, pointerTmp ],
|
2955
|
+
[ Opcodes.i32_load8_u, 0, 4 ],
|
2956
|
+
Opcodes.i32_from_u
|
2957
|
+
], generate(scope, decl.right), number(TYPES.number, Valtype.i32), getNodeType(scope, decl.right), false, name, true)),
|
2958
|
+
[ Opcodes.local_tee, newValueTmp ],
|
2939
2959
|
|
2940
|
-
|
2941
|
-
|
2942
|
-
|
2943
|
-
|
2944
|
-
|
2945
|
-
|
2946
|
-
|
2947
|
-
...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
|
2948
|
-
[ Opcodes.local_get, pointerTmp ],
|
2949
|
-
[ Opcodes.i32_load8_u, 0, 4 ],
|
2950
|
-
Opcodes.i32_from_u
|
2951
|
-
], generate(scope, decl.right), number(TYPES.number, Valtype.i32), getNodeType(scope, decl.right), false, name, true)),
|
2952
|
-
[ Opcodes.local_tee, newValueTmp ],
|
2953
|
-
|
2954
|
-
...number(0),
|
2955
|
-
[ Opcodes.f64_max ],
|
2956
|
-
...number(255),
|
2957
|
-
[ Opcodes.f64_min ],
|
2958
|
-
Opcodes.i32_to_u,
|
2959
|
-
[ Opcodes.i32_store8, 0, 4 ]
|
2960
|
-
],
|
2961
|
-
[TYPES.int8array]: [
|
2962
|
-
[ Opcodes.i32_add ],
|
2963
|
-
...(op === '=' ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
|
2960
|
+
Opcodes.i32_to_u,
|
2961
|
+
[ Opcodes.i32_store8, 0, 4 ]
|
2962
|
+
],
|
2963
|
+
[TYPES.uint8clampedarray]: [
|
2964
|
+
[ Opcodes.i32_add ],
|
2965
|
+
...(op === '=' ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
|
2964
2966
|
|
2965
|
-
|
2966
|
-
|
2967
|
-
|
2968
|
-
|
2969
|
-
|
2970
|
-
|
2967
|
+
...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
|
2968
|
+
[ Opcodes.local_get, pointerTmp ],
|
2969
|
+
[ Opcodes.i32_load8_u, 0, 4 ],
|
2970
|
+
Opcodes.i32_from_u
|
2971
|
+
], generate(scope, decl.right), number(TYPES.number, Valtype.i32), getNodeType(scope, decl.right), false, name, true)),
|
2972
|
+
[ Opcodes.local_tee, newValueTmp ],
|
2971
2973
|
|
2972
|
-
|
2973
|
-
|
2974
|
-
|
2975
|
-
[
|
2976
|
-
|
2977
|
-
|
2978
|
-
|
2979
|
-
|
2974
|
+
...number(0),
|
2975
|
+
[ Opcodes.f64_max ],
|
2976
|
+
...number(255),
|
2977
|
+
[ Opcodes.f64_min ],
|
2978
|
+
Opcodes.i32_to_u,
|
2979
|
+
[ Opcodes.i32_store8, 0, 4 ]
|
2980
|
+
],
|
2981
|
+
[TYPES.int8array]: [
|
2982
|
+
[ Opcodes.i32_add ],
|
2983
|
+
...(op === '=' ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
|
2980
2984
|
|
2981
|
-
|
2982
|
-
|
2983
|
-
|
2984
|
-
|
2985
|
-
|
2986
|
-
|
2985
|
+
...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
|
2986
|
+
[ Opcodes.local_get, pointerTmp ],
|
2987
|
+
[ Opcodes.i32_load8_s, 0, 4 ],
|
2988
|
+
Opcodes.i32_from
|
2989
|
+
], generate(scope, decl.right), number(TYPES.number, Valtype.i32), getNodeType(scope, decl.right), false, name, true)),
|
2990
|
+
[ Opcodes.local_tee, newValueTmp ],
|
2987
2991
|
|
2988
|
-
|
2989
|
-
|
2990
|
-
|
2991
|
-
|
2992
|
-
|
2993
|
-
|
2994
|
-
|
2995
|
-
|
2992
|
+
Opcodes.i32_to,
|
2993
|
+
[ Opcodes.i32_store8, 0, 4 ]
|
2994
|
+
],
|
2995
|
+
[TYPES.uint16array]: [
|
2996
|
+
...number(2, Valtype.i32),
|
2997
|
+
[ Opcodes.i32_mul ],
|
2998
|
+
[ Opcodes.i32_add ],
|
2999
|
+
...(op === '=' ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
|
2996
3000
|
|
2997
|
-
|
2998
|
-
|
2999
|
-
|
3000
|
-
|
3001
|
-
|
3002
|
-
|
3001
|
+
...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
|
3002
|
+
[ Opcodes.local_get, pointerTmp ],
|
3003
|
+
[ Opcodes.i32_load16_u, 0, 4 ],
|
3004
|
+
Opcodes.i32_from_u
|
3005
|
+
], generate(scope, decl.right), number(TYPES.number, Valtype.i32), getNodeType(scope, decl.right), false, name, true)),
|
3006
|
+
[ Opcodes.local_tee, newValueTmp ],
|
3003
3007
|
|
3004
|
-
|
3005
|
-
|
3006
|
-
|
3007
|
-
|
3008
|
-
|
3009
|
-
|
3010
|
-
|
3011
|
-
|
3008
|
+
Opcodes.i32_to_u,
|
3009
|
+
[ Opcodes.i32_store16, 0, 4 ]
|
3010
|
+
],
|
3011
|
+
[TYPES.int16array]: [
|
3012
|
+
...number(2, Valtype.i32),
|
3013
|
+
[ Opcodes.i32_mul ],
|
3014
|
+
[ Opcodes.i32_add ],
|
3015
|
+
...(op === '=' ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
|
3012
3016
|
|
3013
|
-
|
3014
|
-
|
3015
|
-
|
3016
|
-
|
3017
|
-
|
3018
|
-
|
3017
|
+
...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
|
3018
|
+
[ Opcodes.local_get, pointerTmp ],
|
3019
|
+
[ Opcodes.i32_load16_s, 0, 4 ],
|
3020
|
+
Opcodes.i32_from
|
3021
|
+
], generate(scope, decl.right), number(TYPES.number, Valtype.i32), getNodeType(scope, decl.right), false, name, true)),
|
3022
|
+
[ Opcodes.local_tee, newValueTmp ],
|
3019
3023
|
|
3020
|
-
|
3021
|
-
|
3022
|
-
|
3023
|
-
|
3024
|
-
|
3025
|
-
|
3026
|
-
|
3027
|
-
|
3024
|
+
Opcodes.i32_to,
|
3025
|
+
[ Opcodes.i32_store16, 0, 4 ]
|
3026
|
+
],
|
3027
|
+
[TYPES.uint32array]: [
|
3028
|
+
...number(4, Valtype.i32),
|
3029
|
+
[ Opcodes.i32_mul ],
|
3030
|
+
[ Opcodes.i32_add ],
|
3031
|
+
...(op === '=' ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
|
3028
3032
|
|
3029
|
-
|
3030
|
-
|
3031
|
-
|
3032
|
-
|
3033
|
-
|
3034
|
-
|
3033
|
+
...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
|
3034
|
+
[ Opcodes.local_get, pointerTmp ],
|
3035
|
+
[ Opcodes.i32_load, 0, 4 ],
|
3036
|
+
Opcodes.i32_from_u
|
3037
|
+
], generate(scope, decl.right), number(TYPES.number, Valtype.i32), getNodeType(scope, decl.right), false, name, true)),
|
3038
|
+
[ Opcodes.local_tee, newValueTmp ],
|
3035
3039
|
|
3036
|
-
|
3037
|
-
|
3038
|
-
|
3039
|
-
|
3040
|
-
|
3041
|
-
|
3042
|
-
|
3043
|
-
|
3040
|
+
Opcodes.i32_to_u,
|
3041
|
+
[ Opcodes.i32_store, 0, 4 ]
|
3042
|
+
],
|
3043
|
+
[TYPES.int32array]: [
|
3044
|
+
...number(4, Valtype.i32),
|
3045
|
+
[ Opcodes.i32_mul ],
|
3046
|
+
[ Opcodes.i32_add ],
|
3047
|
+
...(op === '=' ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
|
3044
3048
|
|
3045
|
-
|
3046
|
-
|
3047
|
-
|
3048
|
-
|
3049
|
-
|
3050
|
-
|
3049
|
+
...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
|
3050
|
+
[ Opcodes.local_get, pointerTmp ],
|
3051
|
+
[ Opcodes.i32_load, 0, 4 ],
|
3052
|
+
Opcodes.i32_from
|
3053
|
+
], generate(scope, decl.right), number(TYPES.number, Valtype.i32), getNodeType(scope, decl.right), false, name, true)),
|
3054
|
+
[ Opcodes.local_tee, newValueTmp ],
|
3051
3055
|
|
3052
|
-
|
3053
|
-
|
3054
|
-
|
3055
|
-
|
3056
|
-
|
3057
|
-
|
3058
|
-
|
3059
|
-
|
3056
|
+
Opcodes.i32_to,
|
3057
|
+
[ Opcodes.i32_store, 0, 4 ]
|
3058
|
+
],
|
3059
|
+
[TYPES.float32array]: [
|
3060
|
+
...number(4, Valtype.i32),
|
3061
|
+
[ Opcodes.i32_mul ],
|
3062
|
+
[ Opcodes.i32_add ],
|
3063
|
+
...(op === '=' ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
|
3060
3064
|
|
3061
|
-
|
3062
|
-
|
3063
|
-
|
3064
|
-
|
3065
|
-
|
3065
|
+
...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
|
3066
|
+
[ Opcodes.local_get, pointerTmp ],
|
3067
|
+
[ Opcodes.f32_load, 0, 4 ],
|
3068
|
+
[ Opcodes.f64_promote_f32 ]
|
3069
|
+
], generate(scope, decl.right), number(TYPES.number, Valtype.i32), getNodeType(scope, decl.right), false, name, true)),
|
3070
|
+
[ Opcodes.local_tee, newValueTmp ],
|
3066
3071
|
|
3067
|
-
|
3068
|
-
]
|
3069
|
-
|
3070
|
-
|
3071
|
-
|
3072
|
-
|
3073
|
-
|
3072
|
+
[ Opcodes.f32_demote_f64 ],
|
3073
|
+
[ Opcodes.f32_store, 0, 4 ]
|
3074
|
+
],
|
3075
|
+
[TYPES.float64array]: [
|
3076
|
+
...number(8, Valtype.i32),
|
3077
|
+
[ Opcodes.i32_mul ],
|
3078
|
+
[ Opcodes.i32_add ],
|
3079
|
+
...(op === '=' ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
|
3074
3080
|
|
3075
|
-
|
3076
|
-
Opcodes.
|
3077
|
-
|
3078
|
-
|
3079
|
-
|
3081
|
+
...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
|
3082
|
+
[ Opcodes.local_get, pointerTmp ],
|
3083
|
+
[ Opcodes.f64_load, 0, 4 ]
|
3084
|
+
], generate(scope, decl.right), number(TYPES.number, Valtype.i32), getNodeType(scope, decl.right), false, name, true)),
|
3085
|
+
[ Opcodes.local_tee, newValueTmp ],
|
3080
3086
|
|
3081
|
-
|
3082
|
-
|
3087
|
+
[ Opcodes.f64_store, 0, 4 ]
|
3088
|
+
],
|
3089
|
+
}, {
|
3090
|
+
prelude: [
|
3091
|
+
...generate(scope, object),
|
3092
|
+
Opcodes.i32_to_u,
|
3093
|
+
[ Opcodes.i32_load, 0, 4 ],
|
3083
3094
|
|
3084
|
-
|
3085
|
-
|
3095
|
+
...generate(scope, property),
|
3096
|
+
Opcodes.i32_to_u,
|
3097
|
+
],
|
3098
|
+
postlude: [
|
3099
|
+
// setLastType(scope, TYPES.number)
|
3100
|
+
[ Opcodes.local_get, newValueTmp ]
|
3101
|
+
]
|
3102
|
+
}),
|
3103
|
+
|
3104
|
+
default: internalThrow(scope, 'TypeError', `Cannot assign member with non-array`)
|
3105
|
+
}, valtypeBinary);
|
3086
3106
|
}
|
3087
3107
|
|
3088
3108
|
if (!name) return todo(scope, 'destructuring is not supported yet', true);
|
@@ -4192,6 +4212,7 @@ const makeArray = (scope, decl, global = false, name = '$undeclared', initEmpty
|
|
4192
4212
|
const local = global ? globals[name] : scope.locals[name];
|
4193
4213
|
if (
|
4194
4214
|
Prefs.data && firstAssign && useRawElements &&
|
4215
|
+
name !== '#member_prop' &&
|
4195
4216
|
(!globalThis.precompile || !global)
|
4196
4217
|
) {
|
4197
4218
|
makeData(scope, elements, rawPtr, itemType, initEmpty);
|
@@ -4333,55 +4354,55 @@ const generateArray = (scope, decl, global = false, name = '$undeclared', initEm
|
|
4333
4354
|
return makeArray(scope, decl, global, name, initEmpty, valtype, false, true)[0];
|
4334
4355
|
};
|
4335
4356
|
|
4336
|
-
const toPropertyKey = scope
|
4337
|
-
[ Opcodes.call, ...unsignedLEB128(includeBuiltin(scope, '__ecma262_ToPropertyKey').index) ]
|
4357
|
+
const toPropertyKey = (scope, i32Conv = false) => [
|
4358
|
+
[ Opcodes.call, ...unsignedLEB128(includeBuiltin(scope, '__ecma262_ToPropertyKey').index) ],
|
4359
|
+
...(i32Conv ? [
|
4360
|
+
[ Opcodes.local_set, localTmp(scope, '#swap', Valtype.i32) ],
|
4361
|
+
Opcodes.i32_to_u,
|
4362
|
+
[ Opcodes.local_get, localTmp(scope, '#swap', Valtype.i32) ]
|
4363
|
+
] : [])
|
4338
4364
|
];
|
4339
4365
|
|
4340
4366
|
const generateObject = (scope, decl, global = false, name = '$undeclared') => {
|
4341
|
-
includeBuiltin(scope, 'Map');
|
4342
|
-
|
4343
|
-
// todo: optimize const objects
|
4344
|
-
const tmp = localTmp(scope, `#objectexpr${randId()}`);
|
4345
4367
|
const out = [
|
4346
|
-
...
|
4347
|
-
callee: {
|
4348
|
-
type: 'Identifier',
|
4349
|
-
name: 'Map'
|
4350
|
-
},
|
4351
|
-
arguments: [],
|
4352
|
-
_new: true
|
4353
|
-
}),
|
4354
|
-
[ Opcodes.local_tee, tmp ]
|
4368
|
+
[ Opcodes.call, ...unsignedLEB128(includeBuiltin(scope, '__Porffor_allocate').index) ]
|
4355
4369
|
];
|
4356
4370
|
|
4357
|
-
|
4358
|
-
const
|
4359
|
-
|
4371
|
+
if (decl.properties.length > 0) {
|
4372
|
+
const tmp = localTmp(scope, `#objectexpr${randId()}`, Valtype.i32);
|
4373
|
+
out.push([ Opcodes.local_tee, tmp ]);
|
4360
4374
|
|
4361
|
-
|
4362
|
-
|
4363
|
-
|
4364
|
-
value: key.name
|
4365
|
-
};
|
4375
|
+
for (const x of decl.properties) {
|
4376
|
+
const { method, shorthand, computed, kind, key, value } = x;
|
4377
|
+
if (kind !== 'init') return todo(scope, 'complex objects are not supported yet', true);
|
4366
4378
|
|
4367
|
-
|
4368
|
-
|
4369
|
-
|
4379
|
+
let k = key;
|
4380
|
+
if (!computed && key.type !== 'Literal') k = {
|
4381
|
+
type: 'Literal',
|
4382
|
+
value: key.name
|
4383
|
+
};
|
4370
4384
|
|
4371
|
-
|
4372
|
-
|
4373
|
-
|
4385
|
+
out.push(
|
4386
|
+
[ Opcodes.local_get, tmp ],
|
4387
|
+
...number(TYPES.object, Valtype.i32),
|
4374
4388
|
|
4375
|
-
|
4376
|
-
|
4389
|
+
...generate(scope, k),
|
4390
|
+
...getNodeType(scope, k),
|
4391
|
+
...toPropertyKey(scope, true),
|
4377
4392
|
|
4378
|
-
|
4393
|
+
...generate(scope, value),
|
4394
|
+
...getNodeType(scope, value),
|
4379
4395
|
|
4380
|
-
|
4381
|
-
|
4382
|
-
|
4396
|
+
[ Opcodes.call, ...unsignedLEB128(includeBuiltin(scope, '__Porffor_object_set').index) ],
|
4397
|
+
|
4398
|
+
[ Opcodes.drop ],
|
4399
|
+
[ Opcodes.drop ]
|
4400
|
+
);
|
4401
|
+
}
|
4383
4402
|
}
|
4384
4403
|
|
4404
|
+
out.push(Opcodes.i32_from_u);
|
4405
|
+
|
4385
4406
|
return out;
|
4386
4407
|
};
|
4387
4408
|
|
@@ -4602,13 +4623,14 @@ const generateMember = (scope, decl, _global, _name) => {
|
|
4602
4623
|
|
4603
4624
|
[TYPES.object]: [
|
4604
4625
|
...objectWasm,
|
4626
|
+
Opcodes.i32_to_u,
|
4605
4627
|
...getNodeType(scope, object),
|
4606
4628
|
|
4607
4629
|
...propertyWasm,
|
4608
4630
|
...getNodeType(scope, property),
|
4609
|
-
...toPropertyKey(scope),
|
4631
|
+
...toPropertyKey(scope, true),
|
4610
4632
|
|
4611
|
-
[ Opcodes.call, ...unsignedLEB128(includeBuiltin(scope, '
|
4633
|
+
[ Opcodes.call, ...unsignedLEB128(includeBuiltin(scope, '__Porffor_object_get').index) ],
|
4612
4634
|
...setLastType(scope)
|
4613
4635
|
],
|
4614
4636
|
|
@@ -4706,7 +4728,7 @@ const generateMember = (scope, decl, _global, _name) => {
|
|
4706
4728
|
[ Opcodes.br, 1 ],
|
4707
4729
|
[ Opcodes.end ],
|
4708
4730
|
|
4709
|
-
...generate(scope, property),
|
4731
|
+
...generate(scope, property, false, '#member_prop'),
|
4710
4732
|
[ Opcodes.local_set, localTmp(scope, '#member_prop') ]
|
4711
4733
|
);
|
4712
4734
|
|
@@ -4718,7 +4740,7 @@ const generateMember = (scope, decl, _global, _name) => {
|
|
4718
4740
|
...generate(scope, object),
|
4719
4741
|
[ Opcodes.local_set, localTmp(scope, '#member_obj') ],
|
4720
4742
|
|
4721
|
-
...generate(scope, property),
|
4743
|
+
...generate(scope, property, false, '#member_prop'),
|
4722
4744
|
[ Opcodes.local_set, localTmp(scope, '#member_prop') ]
|
4723
4745
|
);
|
4724
4746
|
}
|