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.
@@ -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
- // todo: hook into terminal debugger
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
- out.push([ ...inst, ...immediates.flatMap(x => signedLEB128(x)) ]);
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
- return [
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
- // get index as valtype
2873
- ...generate(scope, property),
2874
- Opcodes.i32_to_u,
2883
+ return typeSwitch(scope, getNodeType(scope, decl.left.object), {
2884
+ [TYPES.array]: [
2885
+ ...generate(scope, object),
2886
+ Opcodes.i32_to_u,
2875
2887
 
2876
- // turn into byte offset by * valtypeSize + 1
2877
- ...number(ValtypeSize[valtype] + 1, Valtype.i32),
2878
- [ Opcodes.i32_mul ],
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
- ...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
2883
- [ Opcodes.local_get, pointerTmp ],
2884
- [ Opcodes.load, 0, ValtypeSize.i32 ]
2885
- ], generate(scope, decl.right), [
2886
- [ Opcodes.local_get, pointerTmp ],
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
- ...getNodeType(scope, decl),
2894
- [ Opcodes.i32_store8, 0, ValtypeSize.i32 + ValtypeSize[valtype] ],
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
- [TYPES.object]: [
2898
- ...generate(scope, object),
2899
- ...(op === '=' ? [] : [ [ Opcodes.local_tee, localTmp(scope, '#objset_object') ] ]),
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
- ...generate(scope, property),
2903
- ...getNodeType(scope, property),
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
- ...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
2910
- [ Opcodes.local_get, localTmp(scope, '#objset_object') ],
2911
- ...getNodeType(scope, object),
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
- [ Opcodes.local_get, localTmp(scope, '#objset_property') ],
2914
- [ Opcodes.local_get, localTmp(scope, '#objset_property_type', Valtype.i32) ],
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
- [ Opcodes.call, ...unsignedLEB128(includeBuiltin(scope, '__Map_prototype_get').index) ],
2917
- ...setLastType(scope)
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, '__Map_prototype_set').index) ],
2923
- [ Opcodes.drop ],
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
- ...setLastType(scope, getNodeType(scope, decl)),
2926
- ],
2943
+ [ Opcodes.call, ...unsignedLEB128(includeBuiltin(scope, '__Porffor_object_set').index) ],
2944
+ [ Opcodes.drop ],
2945
+ // ...setLastType(scope, getNodeType(scope, decl)),
2946
+ ],
2927
2947
 
2928
- ...wrapBC({
2929
- [TYPES.uint8array]: [
2930
- [ Opcodes.i32_add ],
2931
- ...(op === '=' ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
2948
+ ...wrapBC({
2949
+ [TYPES.uint8array]: [
2950
+ [ Opcodes.i32_add ],
2951
+ ...(op === '=' ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
2932
2952
 
2933
- ...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
2934
- [ Opcodes.local_get, pointerTmp ],
2935
- [ Opcodes.i32_load8_u, 0, 4 ],
2936
- Opcodes.i32_from_u
2937
- ], generate(scope, decl.right), number(TYPES.number, Valtype.i32), getNodeType(scope, decl.right), false, name, true)),
2938
- [ Opcodes.local_tee, newValueTmp ],
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
- Opcodes.i32_to_u,
2941
- [ Opcodes.i32_store8, 0, 4 ]
2942
- ],
2943
- [TYPES.uint8clampedarray]: [
2944
- [ Opcodes.i32_add ],
2945
- ...(op === '=' ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
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
- ...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
2966
- [ Opcodes.local_get, pointerTmp ],
2967
- [ Opcodes.i32_load8_s, 0, 4 ],
2968
- Opcodes.i32_from
2969
- ], generate(scope, decl.right), number(TYPES.number, Valtype.i32), getNodeType(scope, decl.right), false, name, true)),
2970
- [ Opcodes.local_tee, newValueTmp ],
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
- Opcodes.i32_to,
2973
- [ Opcodes.i32_store8, 0, 4 ]
2974
- ],
2975
- [TYPES.uint16array]: [
2976
- ...number(2, Valtype.i32),
2977
- [ Opcodes.i32_mul ],
2978
- [ Opcodes.i32_add ],
2979
- ...(op === '=' ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
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
- ...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
2982
- [ Opcodes.local_get, pointerTmp ],
2983
- [ Opcodes.i32_load16_u, 0, 4 ],
2984
- Opcodes.i32_from_u
2985
- ], generate(scope, decl.right), number(TYPES.number, Valtype.i32), getNodeType(scope, decl.right), false, name, true)),
2986
- [ Opcodes.local_tee, newValueTmp ],
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
- Opcodes.i32_to_u,
2989
- [ Opcodes.i32_store16, 0, 4 ]
2990
- ],
2991
- [TYPES.int16array]: [
2992
- ...number(2, Valtype.i32),
2993
- [ Opcodes.i32_mul ],
2994
- [ Opcodes.i32_add ],
2995
- ...(op === '=' ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
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
- ...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
2998
- [ Opcodes.local_get, pointerTmp ],
2999
- [ Opcodes.i32_load16_s, 0, 4 ],
3000
- Opcodes.i32_from
3001
- ], generate(scope, decl.right), number(TYPES.number, Valtype.i32), getNodeType(scope, decl.right), false, name, true)),
3002
- [ Opcodes.local_tee, newValueTmp ],
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
- Opcodes.i32_to,
3005
- [ Opcodes.i32_store16, 0, 4 ]
3006
- ],
3007
- [TYPES.uint32array]: [
3008
- ...number(4, Valtype.i32),
3009
- [ Opcodes.i32_mul ],
3010
- [ Opcodes.i32_add ],
3011
- ...(op === '=' ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
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
- ...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
3014
- [ Opcodes.local_get, pointerTmp ],
3015
- [ Opcodes.i32_load, 0, 4 ],
3016
- Opcodes.i32_from_u
3017
- ], generate(scope, decl.right), number(TYPES.number, Valtype.i32), getNodeType(scope, decl.right), false, name, true)),
3018
- [ Opcodes.local_tee, newValueTmp ],
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
- Opcodes.i32_to_u,
3021
- [ Opcodes.i32_store, 0, 4 ]
3022
- ],
3023
- [TYPES.int32array]: [
3024
- ...number(4, Valtype.i32),
3025
- [ Opcodes.i32_mul ],
3026
- [ Opcodes.i32_add ],
3027
- ...(op === '=' ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
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
- ...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
3030
- [ Opcodes.local_get, pointerTmp ],
3031
- [ Opcodes.i32_load, 0, 4 ],
3032
- Opcodes.i32_from
3033
- ], generate(scope, decl.right), number(TYPES.number, Valtype.i32), getNodeType(scope, decl.right), false, name, true)),
3034
- [ Opcodes.local_tee, newValueTmp ],
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
- Opcodes.i32_to,
3037
- [ Opcodes.i32_store, 0, 4 ]
3038
- ],
3039
- [TYPES.float32array]: [
3040
- ...number(4, Valtype.i32),
3041
- [ Opcodes.i32_mul ],
3042
- [ Opcodes.i32_add ],
3043
- ...(op === '=' ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
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
- ...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
3046
- [ Opcodes.local_get, pointerTmp ],
3047
- [ Opcodes.f32_load, 0, 4 ],
3048
- [ Opcodes.f64_promote_f32 ]
3049
- ], generate(scope, decl.right), number(TYPES.number, Valtype.i32), getNodeType(scope, decl.right), false, name, true)),
3050
- [ Opcodes.local_tee, newValueTmp ],
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
- [ Opcodes.f32_demote_f64 ],
3053
- [ Opcodes.f32_store, 0, 4 ]
3054
- ],
3055
- [TYPES.float64array]: [
3056
- ...number(8, Valtype.i32),
3057
- [ Opcodes.i32_mul ],
3058
- [ Opcodes.i32_add ],
3059
- ...(op === '=' ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
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
- ...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
3062
- [ Opcodes.local_get, pointerTmp ],
3063
- [ Opcodes.f64_load, 0, 4 ]
3064
- ], generate(scope, decl.right), number(TYPES.number, Valtype.i32), getNodeType(scope, decl.right), false, name, true)),
3065
- [ Opcodes.local_tee, newValueTmp ],
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
- [ Opcodes.f64_store, 0, 4 ]
3068
- ],
3069
- }, {
3070
- prelude: [
3071
- ...generate(scope, object),
3072
- Opcodes.i32_to_u,
3073
- [ Opcodes.i32_load, 0, 4 ],
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
- ...generate(scope, property),
3076
- Opcodes.i32_to_u,
3077
- ],
3078
- postlude: setLastType(scope, TYPES.number)
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
- default: internalThrow(scope, 'TypeError', `Cannot assign member with non-array`)
3082
- }, Blocktype.void),
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
- [ Opcodes.local_get, newValueTmp ]
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);
@@ -4333,55 +4353,55 @@ const generateArray = (scope, decl, global = false, name = '$undeclared', initEm
4333
4353
  return makeArray(scope, decl, global, name, initEmpty, valtype, false, true)[0];
4334
4354
  };
4335
4355
 
4336
- const toPropertyKey = scope => Prefs.fastObject ? [] : [
4337
- [ 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
+ ] : [])
4338
4363
  ];
4339
4364
 
4340
4365
  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
4366
  const out = [
4346
- ...generateCall(scope, {
4347
- callee: {
4348
- type: 'Identifier',
4349
- name: 'Map'
4350
- },
4351
- arguments: [],
4352
- _new: true
4353
- }),
4354
- [ Opcodes.local_tee, tmp ]
4367
+ [ Opcodes.call, ...unsignedLEB128(includeBuiltin(scope, '__Porffor_allocate').index) ]
4355
4368
  ];
4356
4369
 
4357
- for (const x of decl.properties) {
4358
- const { method, shorthand, computed, kind, key, value } = x;
4359
- if (kind !== 'init') return todo(scope, 'complex objects are not supported yet', true);
4370
+ if (decl.properties.length > 0) {
4371
+ const tmp = localTmp(scope, `#objectexpr${randId()}`, Valtype.i32);
4372
+ out.push([ Opcodes.local_tee, tmp ]);
4360
4373
 
4361
- let k = key;
4362
- if (!computed && key.type !== 'Literal') k = {
4363
- type: 'Literal',
4364
- value: key.name
4365
- };
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);
4366
4377
 
4367
- out.push(
4368
- [ Opcodes.local_get, tmp ],
4369
- ...number(TYPES.map, Valtype.i32),
4378
+ let k = key;
4379
+ if (!computed && key.type !== 'Literal') k = {
4380
+ type: 'Literal',
4381
+ value: key.name
4382
+ };
4370
4383
 
4371
- ...generate(scope, k),
4372
- ...getNodeType(scope, k),
4373
- ...toPropertyKey(scope),
4384
+ out.push(
4385
+ [ Opcodes.local_get, tmp ],
4386
+ ...number(TYPES.object, Valtype.i32),
4374
4387
 
4375
- ...generate(scope, value),
4376
- ...getNodeType(scope, value),
4388
+ ...generate(scope, k),
4389
+ ...getNodeType(scope, k),
4390
+ ...toPropertyKey(scope, true),
4377
4391
 
4378
- [ Opcodes.call, ...unsignedLEB128(includeBuiltin(scope, '__Map_prototype_set').index) ],
4392
+ ...generate(scope, value),
4393
+ ...getNodeType(scope, value),
4379
4394
 
4380
- [ Opcodes.drop ],
4381
- [ Opcodes.drop ]
4382
- );
4395
+ [ Opcodes.call, ...unsignedLEB128(includeBuiltin(scope, '__Porffor_object_set').index) ],
4396
+
4397
+ [ Opcodes.drop ],
4398
+ [ Opcodes.drop ]
4399
+ );
4400
+ }
4383
4401
  }
4384
4402
 
4403
+ out.push(Opcodes.i32_from_u);
4404
+
4385
4405
  return out;
4386
4406
  };
4387
4407
 
@@ -4602,13 +4622,14 @@ const generateMember = (scope, decl, _global, _name) => {
4602
4622
 
4603
4623
  [TYPES.object]: [
4604
4624
  ...objectWasm,
4625
+ Opcodes.i32_to_u,
4605
4626
  ...getNodeType(scope, object),
4606
4627
 
4607
4628
  ...propertyWasm,
4608
4629
  ...getNodeType(scope, property),
4609
- ...toPropertyKey(scope),
4630
+ ...toPropertyKey(scope, true),
4610
4631
 
4611
- [ Opcodes.call, ...unsignedLEB128(includeBuiltin(scope, '__Map_prototype_get').index) ],
4632
+ [ Opcodes.call, ...unsignedLEB128(includeBuiltin(scope, '__Porffor_object_get').index) ],
4612
4633
  ...setLastType(scope)
4613
4634
  ],
4614
4635