OLD | NEW |
1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 /// A library to help transform compounds and null-aware accessors into | 5 /// A library to help transform compounds and null-aware accessors into |
6 /// let expressions. | 6 /// let expressions. |
7 library kernel.frontend.accessors; | 7 library kernel.frontend.accessors; |
8 | 8 |
9 import '../ast.dart'; | 9 import '../ast.dart'; |
10 | 10 |
| 11 final Name indexGetName = new Name("[]"); |
| 12 |
| 13 final Name indexSetName = new Name("[]="); |
| 14 |
| 15 /// An [Accessor] represents a subexpression for which we can't yet build a |
| 16 /// kernel [Expression] because we don't yet know the context in which it is |
| 17 /// used. |
| 18 /// |
| 19 /// Once the context is known, an [Accessor] can be converted into an |
| 20 /// [Expression] by calling a "build" method. |
| 21 /// |
| 22 /// For example, when building a kernel representation for `a[x] = b`, after |
| 23 /// parsing `a[x]` but before parsing `= b`, we don't yet know whether to |
| 24 /// generate an invocation of `operator[]` or `operator[]=`, so we generate an |
| 25 /// [Accessor] object. Later, after `= b` is parsed, [buildAssignment] will be |
| 26 /// called. |
11 abstract class Accessor { | 27 abstract class Accessor { |
| 28 final int offset; |
| 29 |
12 // [builtBinary] and [builtGetter] capture the inner nodes. Used by | 30 // [builtBinary] and [builtGetter] capture the inner nodes. Used by |
13 // dart2js+rasta for determining how subexpressions map to legacy dart2js Ast | 31 // dart2js+rasta for determining how subexpressions map to legacy dart2js Ast |
14 // nodes. This will be removed once dart2js type analysis (aka inference) is | 32 // nodes. This will be removed once dart2js type analysis (aka inference) is |
15 // reimplemented on kernel. | 33 // reimplemented on kernel. |
16 Expression builtBinary; | 34 Expression builtBinary; |
17 Expression builtGetter; | 35 Expression builtGetter; |
18 | 36 |
| 37 Accessor(this.offset); |
| 38 |
| 39 /// Builds an [Expression] representing a read from the accessor. |
19 Expression buildSimpleRead() { | 40 Expression buildSimpleRead() { |
20 return _finish(_makeSimpleRead()); | 41 return _finish(_makeSimpleRead()); |
21 } | 42 } |
22 | 43 |
23 /// Returns an assignment to the accessor. | 44 /// Builds an [Expression] representing an assignment with the accessor on |
| 45 /// the LHS and [value] on the RHS. |
24 /// | 46 /// |
25 /// The returned expression evaluates to the assigned value, unless | 47 /// The returned expression evaluates to the assigned value, unless |
26 /// [voidContext] is true, in which case it may evaluate to anything. | 48 /// [voidContext] is true, in which case it may evaluate to anything. |
27 Expression buildAssignment(Expression value, {bool voidContext: false}) { | 49 Expression buildAssignment(Expression value, {bool voidContext: false}) { |
28 return _finish(_makeSimpleWrite(value, voidContext)); | 50 return _finish(_makeSimpleWrite(value, voidContext)); |
29 } | 51 } |
30 | 52 |
| 53 /// Returns an [Expression] representing a null-aware assignment (`??=`) with |
| 54 /// the accessor on the LHS and [value] on the RHS. |
| 55 /// |
| 56 /// The returned expression evaluates to the assigned value, unless |
| 57 /// [voidContext] is true, in which case it may evaluate to anything. |
| 58 /// |
| 59 /// [type] is the static type of the RHS. |
31 Expression buildNullAwareAssignment(Expression value, DartType type, | 60 Expression buildNullAwareAssignment(Expression value, DartType type, |
32 {bool voidContext: false}) { | 61 {bool voidContext: false}) { |
33 if (voidContext) { | 62 if (voidContext) { |
34 return _finish(new ConditionalExpression(buildIsNull(_makeRead()), | 63 return _finish(new ConditionalExpression(buildIsNull(_makeRead()), |
35 _makeWrite(value, false), new NullLiteral(), type)); | 64 _makeWrite(value, false), new NullLiteral(), type)); |
36 } | 65 } |
37 var tmp = new VariableDeclaration.forValue(_makeRead()); | 66 var tmp = new VariableDeclaration.forValue(_makeRead()); |
38 return _finish(makeLet( | 67 return _finish(makeLet( |
39 tmp, | 68 tmp, |
40 new ConditionalExpression(buildIsNull(new VariableGet(tmp)), | 69 new ConditionalExpression(buildIsNull(new VariableGet(tmp)), |
41 _makeWrite(value, false), new VariableGet(tmp), type))); | 70 _makeWrite(value, false), new VariableGet(tmp), type))); |
42 } | 71 } |
43 | 72 |
| 73 /// Returns an [Expression] representing a compound assignment (e.g. `+=`) |
| 74 /// with the accessor on the LHS and [value] on the RHS. |
44 Expression buildCompoundAssignment(Name binaryOperator, Expression value, | 75 Expression buildCompoundAssignment(Name binaryOperator, Expression value, |
45 {int offset: TreeNode.noOffset, | 76 {int offset: TreeNode.noOffset, |
46 bool voidContext: false, | 77 bool voidContext: false, |
47 Procedure interfaceTarget}) { | 78 Procedure interfaceTarget}) { |
48 return _finish(_makeWrite( | 79 return _finish(_makeWrite( |
49 builtBinary = makeBinary( | 80 builtBinary = makeBinary( |
50 _makeRead(), binaryOperator, interfaceTarget, value, | 81 _makeRead(), binaryOperator, interfaceTarget, value, |
51 offset: offset), | 82 offset: offset), |
52 voidContext)); | 83 voidContext)); |
53 } | 84 } |
54 | 85 |
| 86 /// Returns an [Expression] representing a pre-increment or pre-decrement |
| 87 /// of the accessor. |
55 Expression buildPrefixIncrement(Name binaryOperator, | 88 Expression buildPrefixIncrement(Name binaryOperator, |
56 {int offset: TreeNode.noOffset, | 89 {int offset: TreeNode.noOffset, |
57 bool voidContext: false, | 90 bool voidContext: false, |
58 Procedure interfaceTarget}) { | 91 Procedure interfaceTarget}) { |
59 return buildCompoundAssignment(binaryOperator, new IntLiteral(1), | 92 return buildCompoundAssignment(binaryOperator, new IntLiteral(1), |
60 offset: offset, | 93 offset: offset, |
61 voidContext: voidContext, | 94 voidContext: voidContext, |
62 interfaceTarget: interfaceTarget); | 95 interfaceTarget: interfaceTarget); |
63 } | 96 } |
64 | 97 |
| 98 /// Returns an [Expression] representing a post-increment or post-decrement |
| 99 /// of the accessor. |
65 Expression buildPostfixIncrement(Name binaryOperator, | 100 Expression buildPostfixIncrement(Name binaryOperator, |
66 {int offset: TreeNode.noOffset, | 101 {int offset: TreeNode.noOffset, |
67 bool voidContext: false, | 102 bool voidContext: false, |
68 Procedure interfaceTarget}) { | 103 Procedure interfaceTarget}) { |
69 if (voidContext) { | 104 if (voidContext) { |
70 return buildPrefixIncrement(binaryOperator, | 105 return buildPrefixIncrement(binaryOperator, |
71 offset: offset, voidContext: true, interfaceTarget: interfaceTarget); | 106 offset: offset, voidContext: true, interfaceTarget: interfaceTarget); |
72 } | 107 } |
73 var value = new VariableDeclaration.forValue(_makeRead()); | 108 var value = new VariableDeclaration.forValue(_makeRead()); |
74 valueAccess() => new VariableGet(value); | 109 valueAccess() => new VariableGet(value); |
(...skipping 10 matching lines...) Expand all Loading... |
85 Expression _makeSimpleWrite(Expression value, bool voidContext) { | 120 Expression _makeSimpleWrite(Expression value, bool voidContext) { |
86 return _makeWrite(value, voidContext); | 121 return _makeWrite(value, voidContext); |
87 } | 122 } |
88 | 123 |
89 Expression _makeRead(); | 124 Expression _makeRead(); |
90 | 125 |
91 Expression _makeWrite(Expression value, bool voidContext); | 126 Expression _makeWrite(Expression value, bool voidContext); |
92 | 127 |
93 Expression _finish(Expression body) => body; | 128 Expression _finish(Expression body) => body; |
94 | 129 |
| 130 /// Returns an [Expression] representing a compile-time error. |
| 131 /// |
| 132 /// At runtime, an exception will be thrown. |
95 makeInvalidRead() => new InvalidExpression(); | 133 makeInvalidRead() => new InvalidExpression(); |
96 | 134 |
| 135 /// Returns an [Expression] representing a compile-time error wrapping |
| 136 /// [value]. |
| 137 /// |
| 138 /// At runtime, [value] will be evaluated before throwing an exception. |
97 makeInvalidWrite(Expression value) => wrapInvalid(value); | 139 makeInvalidWrite(Expression value) => wrapInvalid(value); |
98 } | 140 } |
99 | 141 |
100 class VariableAccessor extends Accessor { | 142 class VariableAccessor extends Accessor { |
101 VariableDeclaration variable; | 143 VariableDeclaration variable; |
102 DartType promotedType; | 144 DartType promotedType; |
103 | 145 |
104 VariableAccessor(this.variable, [this.promotedType]); | 146 VariableAccessor(this.variable, this.promotedType, int offset) |
| 147 : super(offset); |
105 | 148 |
106 _makeRead() => new VariableGet(variable, promotedType); | 149 _makeRead() => new VariableGet(variable, promotedType)..fileOffset = offset; |
107 | 150 |
108 _makeWrite(Expression value, bool voidContext) { | 151 _makeWrite(Expression value, bool voidContext) { |
109 return variable.isFinal || variable.isConst | 152 return variable.isFinal || variable.isConst |
110 ? makeInvalidWrite(value) | 153 ? makeInvalidWrite(value) |
111 : new VariableSet(variable, value); | 154 : new VariableSet(variable, value)..fileOffset = offset; |
112 } | 155 } |
113 } | 156 } |
114 | 157 |
115 class PropertyAccessor extends Accessor { | 158 class PropertyAccessor extends Accessor { |
116 VariableDeclaration _receiverVariable; | 159 VariableDeclaration _receiverVariable; |
117 Expression receiver; | 160 Expression receiver; |
118 Name name; | 161 Name name; |
119 Member getter, setter; | 162 Member getter, setter; |
120 | 163 |
121 static Accessor make( | 164 static Accessor make( |
122 Expression receiver, Name name, Member getter, Member setter) { | 165 Expression receiver, Name name, Member getter, Member setter, |
| 166 {int offset: TreeNode.noOffset}) { |
123 if (receiver is ThisExpression) { | 167 if (receiver is ThisExpression) { |
124 return new ThisPropertyAccessor(name, getter, setter); | 168 return new ThisPropertyAccessor(name, getter, setter, offset); |
125 } else { | 169 } else { |
126 return new PropertyAccessor._internal(receiver, name, getter, setter); | 170 return new PropertyAccessor.internal( |
| 171 receiver, name, getter, setter, offset); |
127 } | 172 } |
128 } | 173 } |
129 | 174 |
130 PropertyAccessor._internal( | 175 PropertyAccessor.internal( |
131 this.receiver, this.name, this.getter, this.setter); | 176 this.receiver, this.name, this.getter, this.setter, int offset) |
| 177 : super(offset); |
132 | 178 |
133 _makeSimpleRead() => new PropertyGet(receiver, name, getter); | 179 _makeSimpleRead() => |
| 180 new PropertyGet(receiver, name, getter)..fileOffset = offset; |
| 181 |
134 _makeSimpleWrite(Expression value, bool voidContext) { | 182 _makeSimpleWrite(Expression value, bool voidContext) { |
135 return new PropertySet(receiver, name, value, setter); | 183 return new PropertySet(receiver, name, value, setter)..fileOffset = offset; |
136 } | 184 } |
137 | 185 |
138 receiverAccess() { | 186 receiverAccess() { |
139 _receiverVariable ??= new VariableDeclaration.forValue(receiver); | 187 _receiverVariable ??= new VariableDeclaration.forValue(receiver); |
140 return new VariableGet(_receiverVariable); | 188 return new VariableGet(_receiverVariable)..fileOffset = offset; |
141 } | 189 } |
142 | 190 |
143 _makeRead() => builtGetter = new PropertyGet(receiverAccess(), name, getter); | 191 _makeRead() => builtGetter = new PropertyGet(receiverAccess(), name, getter) |
| 192 ..fileOffset = offset; |
144 | 193 |
145 _makeWrite(Expression value, bool voidContext) { | 194 _makeWrite(Expression value, bool voidContext) { |
146 return new PropertySet(receiverAccess(), name, value, setter); | 195 return new PropertySet(receiverAccess(), name, value, setter) |
| 196 ..fileOffset = offset; |
147 } | 197 } |
148 | 198 |
149 _finish(Expression body) => makeLet(_receiverVariable, body); | 199 _finish(Expression body) => makeLet(_receiverVariable, body); |
150 } | 200 } |
151 | 201 |
152 /// Special case of [PropertyAccessor] to avoid creating an indirect access to | 202 /// Special case of [PropertyAccessor] to avoid creating an indirect access to |
153 /// 'this'. | 203 /// 'this'. |
154 class ThisPropertyAccessor extends Accessor { | 204 class ThisPropertyAccessor extends Accessor { |
155 Name name; | 205 Name name; |
156 Member getter, setter; | 206 Member getter, setter; |
157 | 207 |
158 ThisPropertyAccessor(this.name, this.getter, this.setter); | 208 ThisPropertyAccessor(this.name, this.getter, this.setter, int offset) |
| 209 : super(offset); |
159 | 210 |
160 _makeRead() => | 211 _makeRead() => builtGetter = |
161 builtGetter = new PropertyGet(new ThisExpression(), name, getter); | 212 new PropertyGet(new ThisExpression(), name, getter)..fileOffset = offset; |
162 | 213 |
163 _makeWrite(Expression value, bool voidContext) { | 214 _makeWrite(Expression value, bool voidContext) { |
164 return new PropertySet(new ThisExpression(), name, value, setter); | 215 return new PropertySet(new ThisExpression(), name, value, setter) |
| 216 ..fileOffset = offset; |
165 } | 217 } |
166 } | 218 } |
167 | 219 |
168 class NullAwarePropertyAccessor extends Accessor { | 220 class NullAwarePropertyAccessor extends Accessor { |
169 VariableDeclaration receiver; | 221 VariableDeclaration receiver; |
170 Name name; | 222 Name name; |
171 Member getter, setter; | 223 Member getter, setter; |
172 DartType type; | 224 DartType type; |
173 | 225 |
174 NullAwarePropertyAccessor( | 226 NullAwarePropertyAccessor(Expression receiver, this.name, this.getter, |
175 Expression receiver, this.name, this.getter, this.setter, this.type) | 227 this.setter, this.type, int offset) |
176 : this.receiver = makeOrReuseVariable(receiver); | 228 : this.receiver = makeOrReuseVariable(receiver), |
| 229 super(offset); |
177 | 230 |
178 receiverAccess() => new VariableGet(receiver); | 231 receiverAccess() => new VariableGet(receiver); |
179 | 232 |
180 _makeRead() => builtGetter = new PropertyGet(receiverAccess(), name, getter); | 233 _makeRead() => builtGetter = new PropertyGet(receiverAccess(), name, getter); |
181 | 234 |
182 _makeWrite(Expression value, bool voidContext) { | 235 _makeWrite(Expression value, bool voidContext) { |
183 return new PropertySet(receiverAccess(), name, value, setter); | 236 return new PropertySet(receiverAccess(), name, value, setter); |
184 } | 237 } |
185 | 238 |
186 _finish(Expression body) => makeLet( | 239 _finish(Expression body) => makeLet( |
187 receiver, | 240 receiver, |
188 new ConditionalExpression( | 241 new ConditionalExpression( |
189 buildIsNull(receiverAccess()), new NullLiteral(), body, type)); | 242 buildIsNull(receiverAccess()), new NullLiteral(), body, type)); |
190 } | 243 } |
191 | 244 |
192 class SuperPropertyAccessor extends Accessor { | 245 class SuperPropertyAccessor extends Accessor { |
193 Name name; | 246 Name name; |
194 Member getter, setter; | 247 Member getter, setter; |
195 | 248 |
196 SuperPropertyAccessor(this.name, this.getter, this.setter); | 249 SuperPropertyAccessor(this.name, this.getter, this.setter, int offset) |
| 250 : super(offset); |
197 | 251 |
198 _makeRead() => builtGetter = new SuperPropertyGet(name, getter); | 252 _makeRead() { |
| 253 if (getter == null) return makeInvalidRead(); |
| 254 // TODO(ahe): Use [DirectPropertyGet] when possible. |
| 255 return builtGetter = new SuperPropertyGet(name, getter) |
| 256 ..fileOffset = offset; |
| 257 } |
199 | 258 |
200 _makeWrite(Expression value, bool voidContext) { | 259 _makeWrite(Expression value, bool voidContext) { |
201 return new SuperPropertySet(name, value, setter); | 260 if (setter == null) return makeInvalidWrite(value); |
| 261 // TODO(ahe): Use [DirectPropertySet] when possible. |
| 262 return new SuperPropertySet(name, value, setter)..fileOffset = offset; |
202 } | 263 } |
203 } | 264 } |
204 | 265 |
205 final Name _indexGet = new Name('[]'); | |
206 final Name _indexSet = new Name('[]='); | |
207 | |
208 class IndexAccessor extends Accessor { | 266 class IndexAccessor extends Accessor { |
209 Expression receiver; | 267 Expression receiver; |
210 Expression index; | 268 Expression index; |
211 VariableDeclaration receiverVariable; | 269 VariableDeclaration receiverVariable; |
212 VariableDeclaration indexVariable; | 270 VariableDeclaration indexVariable; |
213 Procedure getter, setter; | 271 Procedure getter, setter; |
214 | 272 |
215 static Accessor make(Expression receiver, Expression index, Procedure getter, | 273 static Accessor make( |
216 Procedure setter) { | 274 Expression receiver, Expression index, Procedure getter, Procedure setter, |
| 275 {int offset: TreeNode.noOffset}) { |
217 if (receiver is ThisExpression) { | 276 if (receiver is ThisExpression) { |
218 return new ThisIndexAccessor(index, getter, setter); | 277 return new ThisIndexAccessor(index, getter, setter, offset); |
219 } else { | 278 } else { |
220 return new IndexAccessor._internal(receiver, index, getter, setter); | 279 return new IndexAccessor.internal( |
| 280 receiver, index, getter, setter, offset); |
221 } | 281 } |
222 } | 282 } |
223 | 283 |
224 IndexAccessor._internal(this.receiver, this.index, this.getter, this.setter); | 284 IndexAccessor.internal( |
| 285 this.receiver, this.index, this.getter, this.setter, int offset) |
| 286 : super(offset); |
225 | 287 |
226 _makeSimpleRead() => new MethodInvocation( | 288 _makeSimpleRead() => new MethodInvocation( |
227 receiver, _indexGet, new Arguments(<Expression>[index]), getter); | 289 receiver, indexGetName, new Arguments(<Expression>[index]), getter) |
| 290 ..fileOffset = offset; |
228 | 291 |
229 _makeSimpleWrite(Expression value, bool voidContext) { | 292 _makeSimpleWrite(Expression value, bool voidContext) { |
230 if (!voidContext) return _makeWriteAndReturn(value); | 293 if (!voidContext) return _makeWriteAndReturn(value); |
231 return new MethodInvocation( | 294 return new MethodInvocation(receiver, indexSetName, |
232 receiver, _indexSet, new Arguments(<Expression>[index, value]), setter); | 295 new Arguments(<Expression>[index, value]), setter)..fileOffset = offset; |
233 } | 296 } |
234 | 297 |
235 receiverAccess() { | 298 receiverAccess() { |
236 // We cannot reuse the receiver if it is a variable since it might be | 299 // We cannot reuse the receiver if it is a variable since it might be |
237 // reassigned in the index expression. | 300 // reassigned in the index expression. |
238 receiverVariable ??= new VariableDeclaration.forValue(receiver); | 301 receiverVariable ??= new VariableDeclaration.forValue(receiver); |
239 return new VariableGet(receiverVariable); | 302 return new VariableGet(receiverVariable)..fileOffset = offset; |
240 } | 303 } |
241 | 304 |
242 indexAccess() { | 305 indexAccess() { |
243 indexVariable ??= new VariableDeclaration.forValue(index); | 306 indexVariable ??= new VariableDeclaration.forValue(index); |
244 return new VariableGet(indexVariable); | 307 return new VariableGet(indexVariable)..fileOffset = offset; |
245 } | 308 } |
246 | 309 |
247 _makeRead() { | 310 _makeRead() { |
248 return builtGetter = new MethodInvocation(receiverAccess(), _indexGet, | 311 return builtGetter = new MethodInvocation( |
249 new Arguments(<Expression>[indexAccess()]), getter); | 312 receiverAccess(), |
| 313 indexGetName, |
| 314 new Arguments(<Expression>[indexAccess()]), |
| 315 getter)..fileOffset = offset; |
250 } | 316 } |
251 | 317 |
252 _makeWrite(Expression value, bool voidContext) { | 318 _makeWrite(Expression value, bool voidContext) { |
253 if (!voidContext) return _makeWriteAndReturn(value); | 319 if (!voidContext) return _makeWriteAndReturn(value); |
254 return new MethodInvocation(receiverAccess(), _indexSet, | 320 return new MethodInvocation( |
255 new Arguments(<Expression>[indexAccess(), value]), setter); | 321 receiverAccess(), |
| 322 indexSetName, |
| 323 new Arguments(<Expression>[indexAccess(), value]), |
| 324 setter)..fileOffset = offset; |
256 } | 325 } |
257 | 326 |
258 _makeWriteAndReturn(Expression value) { | 327 _makeWriteAndReturn(Expression value) { |
259 // The call to []= does not return the value like direct-style assignments | 328 // The call to []= does not return the value like direct-style assignments |
260 // do. We need to bind the value in a let. | 329 // do. We need to bind the value in a let. |
261 var valueVariable = new VariableDeclaration.forValue(value); | 330 var valueVariable = new VariableDeclaration.forValue(value); |
262 var dummy = new VariableDeclaration.forValue(new MethodInvocation( | 331 var dummy = new VariableDeclaration.forValue(new MethodInvocation( |
263 receiverAccess(), | 332 receiverAccess(), |
264 _indexSet, | 333 indexSetName, |
265 new Arguments( | 334 new Arguments( |
266 <Expression>[indexAccess(), new VariableGet(valueVariable)]), | 335 <Expression>[indexAccess(), new VariableGet(valueVariable)]), |
267 setter)); | 336 setter)..fileOffset = offset); |
268 return makeLet( | 337 return makeLet( |
269 valueVariable, makeLet(dummy, new VariableGet(valueVariable))); | 338 valueVariable, makeLet(dummy, new VariableGet(valueVariable))); |
270 } | 339 } |
271 | 340 |
272 Expression _finish(Expression body) { | 341 Expression _finish(Expression body) { |
273 return makeLet(receiverVariable, makeLet(indexVariable, body)); | 342 return makeLet(receiverVariable, makeLet(indexVariable, body)); |
274 } | 343 } |
275 } | 344 } |
276 | 345 |
277 /// Special case of [IndexAccessor] to avoid creating an indirect access to | 346 /// Special case of [IndexAccessor] to avoid creating an indirect access to |
278 /// 'this'. | 347 /// 'this'. |
279 class ThisIndexAccessor extends Accessor { | 348 class ThisIndexAccessor extends Accessor { |
280 Expression index; | 349 Expression index; |
281 VariableDeclaration indexVariable; | 350 VariableDeclaration indexVariable; |
282 Procedure getter, setter; | 351 Procedure getter, setter; |
283 | 352 |
284 ThisIndexAccessor(this.index, this.getter, this.setter); | 353 ThisIndexAccessor(this.index, this.getter, this.setter, int offset) |
| 354 : super(offset); |
285 | 355 |
286 _makeSimpleRead() { | 356 _makeSimpleRead() { |
287 return new MethodInvocation(new ThisExpression(), _indexGet, | 357 return new MethodInvocation(new ThisExpression(), indexGetName, |
288 new Arguments(<Expression>[index]), getter); | 358 new Arguments(<Expression>[index]), getter); |
289 } | 359 } |
290 | 360 |
291 _makeSimpleWrite(Expression value, bool voidContext) { | 361 _makeSimpleWrite(Expression value, bool voidContext) { |
292 if (!voidContext) return _makeWriteAndReturn(value); | 362 if (!voidContext) return _makeWriteAndReturn(value); |
293 return new MethodInvocation(new ThisExpression(), _indexSet, | 363 return new MethodInvocation(new ThisExpression(), indexSetName, |
294 new Arguments(<Expression>[index, value]), setter); | 364 new Arguments(<Expression>[index, value]), setter); |
295 } | 365 } |
296 | 366 |
297 indexAccess() { | 367 indexAccess() { |
298 indexVariable ??= new VariableDeclaration.forValue(index); | 368 indexVariable ??= new VariableDeclaration.forValue(index); |
299 return new VariableGet(indexVariable); | 369 return new VariableGet(indexVariable); |
300 } | 370 } |
301 | 371 |
302 _makeRead() => builtGetter = new MethodInvocation(new ThisExpression(), | 372 _makeRead() => builtGetter = new MethodInvocation(new ThisExpression(), |
303 _indexGet, new Arguments(<Expression>[indexAccess()]), getter); | 373 indexGetName, new Arguments(<Expression>[indexAccess()]), getter); |
304 | 374 |
305 _makeWrite(Expression value, bool voidContext) { | 375 _makeWrite(Expression value, bool voidContext) { |
306 if (!voidContext) return _makeWriteAndReturn(value); | 376 if (!voidContext) return _makeWriteAndReturn(value); |
307 return new MethodInvocation(new ThisExpression(), _indexSet, | 377 return new MethodInvocation(new ThisExpression(), indexSetName, |
308 new Arguments(<Expression>[indexAccess(), value]), setter); | 378 new Arguments(<Expression>[indexAccess(), value]), setter); |
309 } | 379 } |
310 | 380 |
311 _makeWriteAndReturn(Expression value) { | 381 _makeWriteAndReturn(Expression value) { |
312 var valueVariable = new VariableDeclaration.forValue(value); | 382 var valueVariable = new VariableDeclaration.forValue(value); |
313 var dummy = new VariableDeclaration.forValue(new MethodInvocation( | 383 var dummy = new VariableDeclaration.forValue(new MethodInvocation( |
314 new ThisExpression(), | 384 new ThisExpression(), |
315 _indexSet, | 385 indexSetName, |
316 new Arguments( | 386 new Arguments( |
317 <Expression>[indexAccess(), new VariableGet(valueVariable)]), | 387 <Expression>[indexAccess(), new VariableGet(valueVariable)]), |
318 setter)); | 388 setter)); |
319 return makeLet( | 389 return makeLet( |
320 valueVariable, makeLet(dummy, new VariableGet(valueVariable))); | 390 valueVariable, makeLet(dummy, new VariableGet(valueVariable))); |
321 } | 391 } |
322 | 392 |
323 Expression _finish(Expression body) => makeLet(indexVariable, body); | 393 Expression _finish(Expression body) => makeLet(indexVariable, body); |
324 } | 394 } |
325 | 395 |
326 class SuperIndexAccessor extends Accessor { | 396 class SuperIndexAccessor extends Accessor { |
327 Expression index; | 397 Expression index; |
328 VariableDeclaration indexVariable; | 398 VariableDeclaration indexVariable; |
329 Member getter, setter; | 399 Member getter, setter; |
330 | 400 |
331 SuperIndexAccessor(this.index, this.getter, this.setter); | 401 SuperIndexAccessor(this.index, this.getter, this.setter, int offset) |
| 402 : super(offset); |
332 | 403 |
333 indexAccess() { | 404 indexAccess() { |
334 indexVariable ??= new VariableDeclaration.forValue(index); | 405 indexVariable ??= new VariableDeclaration.forValue(index); |
335 return new VariableGet(indexVariable); | 406 return new VariableGet(indexVariable); |
336 } | 407 } |
337 | 408 |
338 _makeSimpleRead() => new SuperMethodInvocation( | 409 _makeSimpleRead() => new SuperMethodInvocation( |
339 _indexGet, new Arguments(<Expression>[index]), getter); | 410 indexGetName, new Arguments(<Expression>[index]), getter); |
340 | 411 |
341 _makeSimpleWrite(Expression value, bool voidContext) { | 412 _makeSimpleWrite(Expression value, bool voidContext) { |
342 if (!voidContext) return _makeWriteAndReturn(value); | 413 if (!voidContext) return _makeWriteAndReturn(value); |
343 return new SuperMethodInvocation( | 414 return new SuperMethodInvocation( |
344 _indexSet, new Arguments(<Expression>[index, value]), setter); | 415 indexSetName, new Arguments(<Expression>[index, value]), setter); |
345 } | 416 } |
346 | 417 |
347 _makeRead() { | 418 _makeRead() { |
348 return builtGetter = new SuperMethodInvocation( | 419 return builtGetter = new SuperMethodInvocation( |
349 _indexGet, new Arguments(<Expression>[indexAccess()]), getter); | 420 indexGetName, new Arguments(<Expression>[indexAccess()]), getter); |
350 } | 421 } |
351 | 422 |
352 _makeWrite(Expression value, bool voidContext) { | 423 _makeWrite(Expression value, bool voidContext) { |
353 if (!voidContext) return _makeWriteAndReturn(value); | 424 if (!voidContext) return _makeWriteAndReturn(value); |
354 return new SuperMethodInvocation( | 425 return new SuperMethodInvocation(indexSetName, |
355 _indexSet, new Arguments(<Expression>[indexAccess(), value]), setter); | 426 new Arguments(<Expression>[indexAccess(), value]), setter); |
356 } | 427 } |
357 | 428 |
358 _makeWriteAndReturn(Expression value) { | 429 _makeWriteAndReturn(Expression value) { |
359 var valueVariable = new VariableDeclaration.forValue(value); | 430 var valueVariable = new VariableDeclaration.forValue(value); |
360 var dummy = new VariableDeclaration.forValue(new SuperMethodInvocation( | 431 var dummy = new VariableDeclaration.forValue(new SuperMethodInvocation( |
361 _indexSet, | 432 indexSetName, |
362 new Arguments( | 433 new Arguments( |
363 <Expression>[indexAccess(), new VariableGet(valueVariable)]), | 434 <Expression>[indexAccess(), new VariableGet(valueVariable)]), |
364 setter)); | 435 setter)); |
365 return makeLet( | 436 return makeLet( |
366 valueVariable, makeLet(dummy, new VariableGet(valueVariable))); | 437 valueVariable, makeLet(dummy, new VariableGet(valueVariable))); |
367 } | 438 } |
368 | 439 |
369 Expression _finish(Expression body) { | 440 Expression _finish(Expression body) { |
370 return makeLet(indexVariable, body); | 441 return makeLet(indexVariable, body); |
371 } | 442 } |
372 } | 443 } |
373 | 444 |
374 class StaticAccessor extends Accessor { | 445 class StaticAccessor extends Accessor { |
375 Member readTarget; | 446 Member readTarget; |
376 Member writeTarget; | 447 Member writeTarget; |
377 | 448 |
378 StaticAccessor(this.readTarget, this.writeTarget); | 449 StaticAccessor(this.readTarget, this.writeTarget, int offset) : super(offset); |
379 | 450 |
380 _makeRead() => builtGetter = | 451 _makeRead() => builtGetter = readTarget == null |
381 readTarget == null ? makeInvalidRead() : new StaticGet(readTarget); | 452 ? makeInvalidRead() |
| 453 : new StaticGet(readTarget)..fileOffset = offset; |
382 | 454 |
383 _makeWrite(Expression value, bool voidContext) { | 455 _makeWrite(Expression value, bool voidContext) { |
384 return writeTarget == null | 456 return writeTarget == null |
385 ? makeInvalidWrite(value) | 457 ? makeInvalidWrite(value) |
386 : new StaticSet(writeTarget, value); | 458 : new StaticSet(writeTarget, value)..fileOffset = offset; |
387 } | 459 } |
388 } | 460 } |
389 | 461 |
390 class ReadOnlyAccessor extends Accessor { | 462 class ReadOnlyAccessor extends Accessor { |
391 Expression expression; | 463 Expression expression; |
392 VariableDeclaration value; | 464 VariableDeclaration value; |
393 | 465 |
394 ReadOnlyAccessor(this.expression); | 466 ReadOnlyAccessor(this.expression, int offset) : super(offset); |
395 | 467 |
396 _makeSimpleRead() => expression; | 468 _makeSimpleRead() => expression; |
397 | 469 |
398 _makeRead() { | 470 _makeRead() { |
399 value ??= new VariableDeclaration.forValue(expression); | 471 value ??= new VariableDeclaration.forValue(expression); |
400 return new VariableGet(value); | 472 return new VariableGet(value); |
401 } | 473 } |
402 | 474 |
403 _makeWrite(Expression value, bool voidContext) => makeInvalidWrite(value); | 475 _makeWrite(Expression value, bool voidContext) => makeInvalidWrite(value); |
404 | 476 |
(...skipping 22 matching lines...) Expand all Loading... |
427 | 499 |
428 VariableDeclaration makeOrReuseVariable(Expression value) { | 500 VariableDeclaration makeOrReuseVariable(Expression value) { |
429 // TODO: Devise a way to remember if a variable declaration was reused | 501 // TODO: Devise a way to remember if a variable declaration was reused |
430 // or is fresh (hence needs a let binding). | 502 // or is fresh (hence needs a let binding). |
431 return new VariableDeclaration.forValue(value); | 503 return new VariableDeclaration.forValue(value); |
432 } | 504 } |
433 | 505 |
434 Expression wrapInvalid(Expression e) { | 506 Expression wrapInvalid(Expression e) { |
435 return new Let(new VariableDeclaration.forValue(e), new InvalidExpression()); | 507 return new Let(new VariableDeclaration.forValue(e), new InvalidExpression()); |
436 } | 508 } |
OLD | NEW |