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
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
|
|
@@ -1332,7 +1347,7 @@ const isExistingProtoFunc = name => {
|
|
1332
1347
|
const getType = (scope, _name) => {
|
1333
1348
|
const name = mapName(_name);
|
1334
1349
|
|
1335
|
-
|
1350
|
+
if (Object.hasOwn(builtinVars, name)) return number(builtinVars[name].type ?? TYPES.number, Valtype.i32);
|
1336
1351
|
|
1337
1352
|
if (typedInput && scope.locals[name]?.metadata?.type != null) return number(scope.locals[name].metadata.type, Valtype.i32);
|
1338
1353
|
if (Object.hasOwn(scope.locals, name)) return [ [ Opcodes.local_get, scope.locals[name + '#type'].idx ] ];
|
@@ -1340,13 +1355,13 @@ const getType = (scope, _name) => {
|
|
1340
1355
|
if (typedInput && globals[name]?.metadata?.type != null) return number(globals[name].metadata.type, Valtype.i32);
|
1341
1356
|
if (Object.hasOwn(globals, name)) return [ [ Opcodes.global_get, globals[name + '#type'].idx ] ];
|
1342
1357
|
|
1343
|
-
|
1344
|
-
|
1345
|
-
|
1358
|
+
if (Object.hasOwn(builtinFuncs, name) || Object.hasOwn(importedFuncs, name) ||
|
1359
|
+
Object.hasOwn(funcIndex, name) || Object.hasOwn(internalConstrs, name))
|
1360
|
+
return number(TYPES.function, Valtype.i32);
|
1346
1361
|
|
1347
|
-
if (isExistingProtoFunc(name))
|
1362
|
+
if (isExistingProtoFunc(name)) return number(TYPES.function, Valtype.i32);
|
1348
1363
|
|
1349
|
-
return number(
|
1364
|
+
return number(TYPES.undefined, Valtype.i32);
|
1350
1365
|
};
|
1351
1366
|
|
1352
1367
|
const setType = (scope, _name, type) => {
|
@@ -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),
|
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);
|
@@ -3430,16 +3450,22 @@ const generateForOf = (scope, decl) => {
|
|
3430
3450
|
// get length
|
3431
3451
|
[ Opcodes.local_get, pointer ],
|
3432
3452
|
[ Opcodes.i32_load, Math.log2(ValtypeSize.i32) - 1, 0 ],
|
3433
|
-
[ Opcodes.
|
3453
|
+
[ Opcodes.local_tee, length ],
|
3454
|
+
|
3455
|
+
[ Opcodes.if, Blocktype.void ]
|
3434
3456
|
);
|
3435
3457
|
|
3458
|
+
depth.push('if');
|
3436
3459
|
depth.push('forof');
|
3460
|
+
depth.push('block');
|
3461
|
+
depth.push('block');
|
3437
3462
|
|
3438
3463
|
// setup local for left
|
3439
3464
|
generate(scope, decl.left);
|
3440
3465
|
|
3441
3466
|
let leftName = decl.left.declarations?.[0]?.id?.name;
|
3442
3467
|
if (!leftName && decl.left.name) {
|
3468
|
+
// todo: should be sloppy mode only
|
3443
3469
|
leftName = decl.left.name;
|
3444
3470
|
|
3445
3471
|
generateVar(scope, { kind: 'var', _bare: true, declarations: [ { id: { name: leftName } } ] })
|
@@ -3450,9 +3476,6 @@ const generateForOf = (scope, decl) => {
|
|
3450
3476
|
const [ local, isGlobal ] = lookupName(scope, leftName);
|
3451
3477
|
if (!local) return todo(scope, 'for of failed to get left local (probably destructure)');
|
3452
3478
|
|
3453
|
-
depth.push('block');
|
3454
|
-
depth.push('block');
|
3455
|
-
|
3456
3479
|
// // todo: we should only do this for strings but we don't know at compile-time :(
|
3457
3480
|
// hack: this is naughty and will break things!
|
3458
3481
|
let newOut = number(0, Valtype.i32), newPointer = number(0, Valtype.i32);
|
@@ -3595,12 +3618,6 @@ const generateForOf = (scope, decl) => {
|
|
3595
3618
|
...generate(scope, decl.body),
|
3596
3619
|
[ Opcodes.end ],
|
3597
3620
|
|
3598
|
-
// increment iter pointer
|
3599
|
-
// [ Opcodes.local_get, pointer ],
|
3600
|
-
// ...number(1, Valtype.i32),
|
3601
|
-
// [ Opcodes.i32_add ],
|
3602
|
-
// [ Opcodes.local_set, pointer ],
|
3603
|
-
|
3604
3621
|
// increment counter by 1
|
3605
3622
|
[ Opcodes.local_get, counter ],
|
3606
3623
|
...number(1, Valtype.i32),
|
@@ -3758,6 +3775,8 @@ const generateForOf = (scope, decl) => {
|
|
3758
3775
|
default: internalThrow(scope, 'TypeError', `Tried for..of on non-iterable type`)
|
3759
3776
|
}, Blocktype.void));
|
3760
3777
|
|
3778
|
+
out.push([ Opcodes.end ]); // end if
|
3779
|
+
|
3761
3780
|
depth.pop();
|
3762
3781
|
depth.pop();
|
3763
3782
|
depth.pop();
|
@@ -4334,55 +4353,55 @@ const generateArray = (scope, decl, global = false, name = '$undeclared', initEm
|
|
4334
4353
|
return makeArray(scope, decl, global, name, initEmpty, valtype, false, true)[0];
|
4335
4354
|
};
|
4336
4355
|
|
4337
|
-
const toPropertyKey = scope
|
4338
|
-
[ Opcodes.call, ...unsignedLEB128(includeBuiltin(scope, '__ecma262_ToPropertyKey').index) ]
|
4356
|
+
const toPropertyKey = (scope, i32Conv = false) => [
|
4357
|
+
[ Opcodes.call, ...unsignedLEB128(includeBuiltin(scope, '__ecma262_ToPropertyKey').index) ],
|
4358
|
+
...(i32Conv ? [
|
4359
|
+
[ Opcodes.local_set, localTmp(scope, '#swap', Valtype.i32) ],
|
4360
|
+
Opcodes.i32_to_u,
|
4361
|
+
[ Opcodes.local_get, localTmp(scope, '#swap', Valtype.i32) ]
|
4362
|
+
] : [])
|
4339
4363
|
];
|
4340
4364
|
|
4341
4365
|
const generateObject = (scope, decl, global = false, name = '$undeclared') => {
|
4342
|
-
includeBuiltin(scope, 'Map');
|
4343
|
-
|
4344
|
-
// todo: optimize const objects
|
4345
|
-
const tmp = localTmp(scope, `#objectexpr${randId()}`);
|
4346
4366
|
const out = [
|
4347
|
-
...
|
4348
|
-
callee: {
|
4349
|
-
type: 'Identifier',
|
4350
|
-
name: 'Map'
|
4351
|
-
},
|
4352
|
-
arguments: [],
|
4353
|
-
_new: true
|
4354
|
-
}),
|
4355
|
-
[ Opcodes.local_tee, tmp ]
|
4367
|
+
[ Opcodes.call, ...unsignedLEB128(includeBuiltin(scope, '__Porffor_allocate').index) ]
|
4356
4368
|
];
|
4357
4369
|
|
4358
|
-
|
4359
|
-
const
|
4360
|
-
|
4370
|
+
if (decl.properties.length > 0) {
|
4371
|
+
const tmp = localTmp(scope, `#objectexpr${randId()}`, Valtype.i32);
|
4372
|
+
out.push([ Opcodes.local_tee, tmp ]);
|
4361
4373
|
|
4362
|
-
|
4363
|
-
|
4364
|
-
|
4365
|
-
value: key.name
|
4366
|
-
};
|
4374
|
+
for (const x of decl.properties) {
|
4375
|
+
const { method, shorthand, computed, kind, key, value } = x;
|
4376
|
+
if (kind !== 'init') return todo(scope, 'complex objects are not supported yet', true);
|
4367
4377
|
|
4368
|
-
|
4369
|
-
|
4370
|
-
|
4378
|
+
let k = key;
|
4379
|
+
if (!computed && key.type !== 'Literal') k = {
|
4380
|
+
type: 'Literal',
|
4381
|
+
value: key.name
|
4382
|
+
};
|
4371
4383
|
|
4372
|
-
|
4373
|
-
|
4374
|
-
|
4384
|
+
out.push(
|
4385
|
+
[ Opcodes.local_get, tmp ],
|
4386
|
+
...number(TYPES.object, Valtype.i32),
|
4375
4387
|
|
4376
|
-
|
4377
|
-
|
4388
|
+
...generate(scope, k),
|
4389
|
+
...getNodeType(scope, k),
|
4390
|
+
...toPropertyKey(scope, true),
|
4378
4391
|
|
4379
|
-
|
4392
|
+
...generate(scope, value),
|
4393
|
+
...getNodeType(scope, value),
|
4380
4394
|
|
4381
|
-
|
4382
|
-
|
4383
|
-
|
4395
|
+
[ Opcodes.call, ...unsignedLEB128(includeBuiltin(scope, '__Porffor_object_set').index) ],
|
4396
|
+
|
4397
|
+
[ Opcodes.drop ],
|
4398
|
+
[ Opcodes.drop ]
|
4399
|
+
);
|
4400
|
+
}
|
4384
4401
|
}
|
4385
4402
|
|
4403
|
+
out.push(Opcodes.i32_from_u);
|
4404
|
+
|
4386
4405
|
return out;
|
4387
4406
|
};
|
4388
4407
|
|
@@ -4603,13 +4622,14 @@ const generateMember = (scope, decl, _global, _name) => {
|
|
4603
4622
|
|
4604
4623
|
[TYPES.object]: [
|
4605
4624
|
...objectWasm,
|
4625
|
+
Opcodes.i32_to_u,
|
4606
4626
|
...getNodeType(scope, object),
|
4607
4627
|
|
4608
4628
|
...propertyWasm,
|
4609
4629
|
...getNodeType(scope, property),
|
4610
|
-
...toPropertyKey(scope),
|
4630
|
+
...toPropertyKey(scope, true),
|
4611
4631
|
|
4612
|
-
[ Opcodes.call, ...unsignedLEB128(includeBuiltin(scope, '
|
4632
|
+
[ Opcodes.call, ...unsignedLEB128(includeBuiltin(scope, '__Porffor_object_get').index) ],
|
4613
4633
|
...setLastType(scope)
|
4614
4634
|
],
|
4615
4635
|
|