Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(13)

Side by Side Diff: pkg/front_end/lib/src/fasta/kernel/frontend_accessors.dart

Issue 2927013004: Rework type inference of assignments to index expressions. (Closed)
Patch Set: Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 7
8 import 'package:front_end/src/fasta/kernel/kernel_shadow_ast.dart' 8 import 'package:front_end/src/fasta/kernel/kernel_shadow_ast.dart'
9 show 9 show
10 KernelArguments, 10 KernelArguments,
11 KernelComplexAssign, 11 KernelComplexAssignment,
12 KernelConditionalExpression, 12 KernelConditionalExpression,
13 KernelMethodInvocation, 13 KernelMethodInvocation,
14 KernelPropertyGet, 14 KernelPropertyGet,
15 KernelPropertySet, 15 KernelPropertySet,
16 KernelVariableDeclaration, 16 KernelVariableDeclaration,
17 KernelVariableGet, 17 KernelVariableGet,
18 KernelVariableSet; 18 KernelVariableSet;
19 19
20 import 'package:front_end/src/fasta/kernel/utils.dart' show offsetForToken; 20 import 'package:front_end/src/fasta/kernel/utils.dart' show offsetForToken;
21 21
(...skipping 21 matching lines...) Expand all
43 /// [Accessor] object. Later, after `= b` is parsed, [buildAssignment] will be 43 /// [Accessor] object. Later, after `= b` is parsed, [buildAssignment] will be
44 /// called. 44 /// called.
45 abstract class Accessor { 45 abstract class Accessor {
46 final BuilderHelper helper; 46 final BuilderHelper helper;
47 final Token token; 47 final Token token;
48 48
49 Accessor(this.helper, this.token); 49 Accessor(this.helper, this.token);
50 50
51 /// Builds an [Expression] representing a read from the accessor. 51 /// Builds an [Expression] representing a read from the accessor.
52 Expression buildSimpleRead() { 52 Expression buildSimpleRead() {
53 return _finish(_makeSimpleRead()); 53 return _finish(_makeSimpleRead(), null);
54 } 54 }
55 55
56 /// Builds an [Expression] representing an assignment with the accessor on 56 /// Builds an [Expression] representing an assignment with the accessor on
57 /// the LHS and [value] on the RHS. 57 /// the LHS and [value] on the RHS.
58 /// 58 ///
59 /// The returned expression evaluates to the assigned value, unless 59 /// The returned expression evaluates to the assigned value, unless
60 /// [voidContext] is true, in which case it may evaluate to anything. 60 /// [voidContext] is true, in which case it may evaluate to anything.
61 Expression buildAssignment(Expression value, {bool voidContext: false}) { 61 Expression buildAssignment(Expression value, {bool voidContext: false}) {
62 return _finish(_makeSimpleWrite(value, voidContext)); 62 var complexAssignment = startComplexAssignment(value);
63 return _finish(_makeSimpleWrite(value, voidContext, complexAssignment),
64 complexAssignment);
63 } 65 }
64 66
65 /// Returns an [Expression] representing a null-aware assignment (`??=`) with 67 /// Returns an [Expression] representing a null-aware assignment (`??=`) with
66 /// the accessor on the LHS and [value] on the RHS. 68 /// the accessor on the LHS and [value] on the RHS.
67 /// 69 ///
68 /// The returned expression evaluates to the assigned value, unless 70 /// The returned expression evaluates to the assigned value, unless
69 /// [voidContext] is true, in which case it may evaluate to anything. 71 /// [voidContext] is true, in which case it may evaluate to anything.
70 /// 72 ///
71 /// [type] is the static type of the RHS. 73 /// [type] is the static type of the RHS.
72 Expression buildNullAwareAssignment(Expression value, DartType type, 74 Expression buildNullAwareAssignment(Expression value, DartType type,
73 {bool voidContext: false}) { 75 {bool voidContext: false}) {
76 var complexAssignment = startComplexAssignment(value);
74 if (voidContext) { 77 if (voidContext) {
75 return _finish(new KernelConditionalExpression( 78 var nullAwareCombiner = new KernelConditionalExpression(
76 buildIsNull(_makeRead()), _makeWrite(value, false), new NullLiteral(), 79 buildIsNull(_makeRead(complexAssignment)),
77 isNullAwareCombiner: true)); 80 _makeWrite(value, false, complexAssignment),
81 new NullLiteral());
82 complexAssignment?.nullAwareCombiner = nullAwareCombiner;
83 return _finish(nullAwareCombiner, complexAssignment);
78 } 84 }
79 var tmp = new VariableDeclaration.forValue(_makeRead()); 85 var tmp = new VariableDeclaration.forValue(_makeRead(complexAssignment));
80 return _finish(makeLet( 86 var nullAwareCombiner = new KernelConditionalExpression(
81 tmp, 87 buildIsNull(new VariableGet(tmp)),
82 new KernelConditionalExpression(buildIsNull(new VariableGet(tmp)), 88 _makeWrite(value, false, complexAssignment),
83 _makeWrite(value, false), new VariableGet(tmp), 89 new VariableGet(tmp));
84 isNullAwareCombiner: true))); 90 complexAssignment?.nullAwareCombiner = nullAwareCombiner;
91 return _finish(makeLet(tmp, nullAwareCombiner), complexAssignment);
85 } 92 }
86 93
87 /// Returns an [Expression] representing a compound assignment (e.g. `+=`) 94 /// Returns an [Expression] representing a compound assignment (e.g. `+=`)
88 /// with the accessor on the LHS and [value] on the RHS. 95 /// with the accessor on the LHS and [value] on the RHS.
89 Expression buildCompoundAssignment(Name binaryOperator, Expression value, 96 Expression buildCompoundAssignment(Name binaryOperator, Expression value,
90 {int offset: TreeNode.noOffset, 97 {int offset: TreeNode.noOffset,
91 bool voidContext: false, 98 bool voidContext: false,
92 Procedure interfaceTarget}) { 99 Procedure interfaceTarget}) {
93 return _finish(_makeWrite( 100 var complexAssignment = startComplexAssignment(value);
94 makeBinary(_makeRead(), binaryOperator, interfaceTarget, value, 101 var combiner = makeBinary(
95 offset: offset, isCombiner: true), 102 _makeRead(complexAssignment), binaryOperator, interfaceTarget, value,
96 voidContext)); 103 offset: offset);
104 complexAssignment?.combiner = combiner;
105 return _finish(_makeWrite(combiner, voidContext, complexAssignment),
106 complexAssignment);
97 } 107 }
98 108
99 /// Returns an [Expression] representing a pre-increment or pre-decrement 109 /// Returns an [Expression] representing a pre-increment or pre-decrement
100 /// of the accessor. 110 /// of the accessor.
101 Expression buildPrefixIncrement(Name binaryOperator, 111 Expression buildPrefixIncrement(Name binaryOperator,
102 {int offset: TreeNode.noOffset, 112 {int offset: TreeNode.noOffset,
103 bool voidContext: false, 113 bool voidContext: false,
104 Procedure interfaceTarget}) { 114 Procedure interfaceTarget}) {
105 return buildCompoundAssignment(binaryOperator, new IntLiteral(1), 115 return buildCompoundAssignment(binaryOperator, new IntLiteral(1),
106 offset: offset, 116 offset: offset,
107 voidContext: voidContext, 117 voidContext: voidContext,
108 interfaceTarget: interfaceTarget); 118 interfaceTarget: interfaceTarget);
109 } 119 }
110 120
111 /// Returns an [Expression] representing a post-increment or post-decrement 121 /// Returns an [Expression] representing a post-increment or post-decrement
112 /// of the accessor. 122 /// of the accessor.
113 Expression buildPostfixIncrement(Name binaryOperator, 123 Expression buildPostfixIncrement(Name binaryOperator,
114 {int offset: TreeNode.noOffset, 124 {int offset: TreeNode.noOffset,
115 bool voidContext: false, 125 bool voidContext: false,
116 Procedure interfaceTarget}) { 126 Procedure interfaceTarget}) {
117 if (voidContext) { 127 if (voidContext) {
118 return buildPrefixIncrement(binaryOperator, 128 return buildPrefixIncrement(binaryOperator,
119 offset: offset, voidContext: true, interfaceTarget: interfaceTarget); 129 offset: offset, voidContext: true, interfaceTarget: interfaceTarget);
120 } 130 }
121 var value = new VariableDeclaration.forValue(_makeRead()); 131 var rhs = new IntLiteral(1);
132 var complexAssignment = startComplexAssignment(rhs);
133 var value = new VariableDeclaration.forValue(_makeRead(complexAssignment));
122 valueAccess() => new VariableGet(value); 134 valueAccess() => new VariableGet(value);
135 var combiner = makeBinary(
136 valueAccess(), binaryOperator, interfaceTarget, rhs,
137 offset: offset);
138 complexAssignment?.combiner = combiner;
139 complexAssignment?.isPostIncDec = true;
123 var dummy = new KernelVariableDeclaration.forValue( 140 var dummy = new KernelVariableDeclaration.forValue(
124 _makeWrite( 141 _makeWrite(combiner, true, complexAssignment),
125 makeBinary(valueAccess(), binaryOperator, interfaceTarget, 142 helper.functionNestingLevel);
126 new IntLiteral(1), 143 return _finish(
127 offset: offset, isCombiner: true), 144 makeLet(value, makeLet(dummy, valueAccess())), complexAssignment);
128 true),
129 helper.functionNestingLevel,
130 isDiscarding: true);
131 return _finish(makeLet(value, makeLet(dummy, valueAccess())));
132 } 145 }
133 146
134 Expression _makeSimpleRead() => _makeRead(); 147 Expression _makeSimpleRead() => _makeRead(null);
135 148
136 Expression _makeSimpleWrite(Expression value, bool voidContext) { 149 Expression _makeSimpleWrite(Expression value, bool voidContext,
137 return _makeWrite(value, voidContext); 150 KernelComplexAssignment complexAssignment) {
151 return _makeWrite(value, voidContext, complexAssignment);
138 } 152 }
139 153
140 Expression _makeRead(); 154 Expression _makeRead(KernelComplexAssignment complexAssignment);
141 155
142 Expression _makeWrite(Expression value, bool voidContext); 156 Expression _makeWrite(Expression value, bool voidContext,
157 KernelComplexAssignment complexAssignment);
143 158
144 Expression _finish(Expression body) => body; 159 Expression _finish(
160 Expression body, KernelComplexAssignment complexAssignment) =>
161 body;
145 162
146 /// Returns an [Expression] representing a compile-time error. 163 /// Returns an [Expression] representing a compile-time error.
147 /// 164 ///
148 /// At runtime, an exception will be thrown. 165 /// At runtime, an exception will be thrown.
149 makeInvalidRead() { 166 makeInvalidRead() {
150 return internalError( 167 return internalError(
151 "Unhandled compile-time error.", null, offsetForToken(token)); 168 "Unhandled compile-time error.", null, offsetForToken(token));
152 } 169 }
153 170
154 /// Returns an [Expression] representing a compile-time error wrapping 171 /// Returns an [Expression] representing a compile-time error wrapping
155 /// [value]. 172 /// [value].
156 /// 173 ///
157 /// At runtime, [value] will be evaluated before throwing an exception. 174 /// At runtime, [value] will be evaluated before throwing an exception.
158 makeInvalidWrite(Expression value) { 175 makeInvalidWrite(Expression value) {
159 return internalError( 176 return internalError(
160 "Unhandled compile-time error.", null, offsetForToken(token)); 177 "Unhandled compile-time error.", null, offsetForToken(token));
161 } 178 }
179
180 /// Creates a data structure for tracking the desugaring of a complex
181 /// assignment expression whose right hand side is [rhs], if necessary, or
182 /// returns `null` if not necessary.
183 KernelComplexAssignment startComplexAssignment(Expression rhs) => null;
162 } 184 }
163 185
164 abstract class VariableAccessor extends Accessor { 186 abstract class VariableAccessor extends Accessor {
165 VariableDeclaration variable; 187 VariableDeclaration variable;
166 DartType promotedType; 188 DartType promotedType;
167 189
168 VariableAccessor( 190 VariableAccessor(
169 BuilderHelper helper, this.variable, this.promotedType, Token token) 191 BuilderHelper helper, this.variable, this.promotedType, Token token)
170 : super(helper, token); 192 : super(helper, token);
171 193
172 Expression _makeRead() { 194 Expression _makeRead(KernelComplexAssignment complexAssignment) {
173 var fact = helper.typePromoter 195 var fact = helper.typePromoter
174 .getFactForAccess(variable, helper.functionNestingLevel); 196 .getFactForAccess(variable, helper.functionNestingLevel);
175 var scope = helper.typePromoter.currentScope; 197 var scope = helper.typePromoter.currentScope;
176 return new KernelVariableGet(variable, fact, scope) 198 return new KernelVariableGet(variable, fact, scope)
177 ..fileOffset = offsetForToken(token); 199 ..fileOffset = offsetForToken(token);
178 } 200 }
179 201
180 Expression _makeWrite(Expression value, bool voidContext) { 202 Expression _makeWrite(Expression value, bool voidContext,
203 KernelComplexAssignment complexAssignment) {
181 helper.typePromoter.mutateVariable(variable, helper.functionNestingLevel); 204 helper.typePromoter.mutateVariable(variable, helper.functionNestingLevel);
182 return variable.isFinal || variable.isConst 205 return variable.isFinal || variable.isConst
183 ? makeInvalidWrite(value) 206 ? makeInvalidWrite(value)
184 : new KernelVariableSet(variable, value) 207 : new KernelVariableSet(variable, value)
185 ..fileOffset = offsetForToken(token); 208 ..fileOffset = offsetForToken(token);
186 } 209 }
187 } 210 }
188 211
189 class PropertyAccessor extends Accessor { 212 class PropertyAccessor extends Accessor {
190 VariableDeclaration _receiverVariable; 213 VariableDeclaration _receiverVariable;
(...skipping 12 matching lines...) Expand all
203 } 226 }
204 } 227 }
205 228
206 PropertyAccessor.internal(BuilderHelper helper, this.receiver, this.name, 229 PropertyAccessor.internal(BuilderHelper helper, this.receiver, this.name,
207 this.getter, this.setter, Token token) 230 this.getter, this.setter, Token token)
208 : super(helper, token); 231 : super(helper, token);
209 232
210 Expression _makeSimpleRead() => new KernelPropertyGet(receiver, name, getter) 233 Expression _makeSimpleRead() => new KernelPropertyGet(receiver, name, getter)
211 ..fileOffset = offsetForToken(token); 234 ..fileOffset = offsetForToken(token);
212 235
213 Expression _makeSimpleWrite(Expression value, bool voidContext) { 236 Expression _makeSimpleWrite(Expression value, bool voidContext,
237 KernelComplexAssignment complexAssignment) {
214 return new KernelPropertySet(receiver, name, value, setter) 238 return new KernelPropertySet(receiver, name, value, setter)
215 ..fileOffset = offsetForToken(token); 239 ..fileOffset = offsetForToken(token);
216 } 240 }
217 241
218 receiverAccess() { 242 receiverAccess() {
219 _receiverVariable ??= new VariableDeclaration.forValue(receiver); 243 _receiverVariable ??= new VariableDeclaration.forValue(receiver);
220 return new VariableGet(_receiverVariable) 244 return new VariableGet(_receiverVariable)
221 ..fileOffset = offsetForToken(token); 245 ..fileOffset = offsetForToken(token);
222 } 246 }
223 247
224 Expression _makeRead() => 248 Expression _makeRead(KernelComplexAssignment complexAssignment) =>
225 new KernelPropertyGet(receiverAccess(), name, getter) 249 new KernelPropertyGet(receiverAccess(), name, getter)
226 ..fileOffset = offsetForToken(token); 250 ..fileOffset = offsetForToken(token);
227 251
228 Expression _makeWrite(Expression value, bool voidContext) { 252 Expression _makeWrite(Expression value, bool voidContext,
253 KernelComplexAssignment complexAssignment) {
229 return new KernelPropertySet(receiverAccess(), name, value, setter) 254 return new KernelPropertySet(receiverAccess(), name, value, setter)
230 ..fileOffset = offsetForToken(token); 255 ..fileOffset = offsetForToken(token);
231 } 256 }
232 257
233 Expression _finish(Expression body) => makeLet(_receiverVariable, body); 258 Expression _finish(
259 Expression body, KernelComplexAssignment complexAssignment) =>
260 makeLet(_receiverVariable, body);
234 } 261 }
235 262
236 /// Special case of [PropertyAccessor] to avoid creating an indirect access to 263 /// Special case of [PropertyAccessor] to avoid creating an indirect access to
237 /// 'this'. 264 /// 'this'.
238 class ThisPropertyAccessor extends Accessor { 265 class ThisPropertyAccessor extends Accessor {
239 Name name; 266 Name name;
240 Member getter, setter; 267 Member getter, setter;
241 268
242 ThisPropertyAccessor( 269 ThisPropertyAccessor(
243 BuilderHelper helper, this.name, this.getter, this.setter, Token token) 270 BuilderHelper helper, this.name, this.getter, this.setter, Token token)
244 : super(helper, token); 271 : super(helper, token);
245 272
246 Expression _makeRead() => 273 Expression _makeRead(KernelComplexAssignment complexAssignment) =>
247 new KernelPropertyGet(new ThisExpression(), name, getter) 274 new KernelPropertyGet(new ThisExpression(), name, getter)
248 ..fileOffset = offsetForToken(token); 275 ..fileOffset = offsetForToken(token);
249 276
250 Expression _makeWrite(Expression value, bool voidContext) { 277 Expression _makeWrite(Expression value, bool voidContext,
278 KernelComplexAssignment complexAssignment) {
251 return new KernelPropertySet(new ThisExpression(), name, value, setter) 279 return new KernelPropertySet(new ThisExpression(), name, value, setter)
252 ..fileOffset = offsetForToken(token); 280 ..fileOffset = offsetForToken(token);
253 } 281 }
254 } 282 }
255 283
256 class NullAwarePropertyAccessor extends Accessor { 284 class NullAwarePropertyAccessor extends Accessor {
257 VariableDeclaration receiver; 285 VariableDeclaration receiver;
258 Name name; 286 Name name;
259 Member getter, setter; 287 Member getter, setter;
260 DartType type; 288 DartType type;
261 289
262 NullAwarePropertyAccessor(BuilderHelper helper, Expression receiver, 290 NullAwarePropertyAccessor(BuilderHelper helper, Expression receiver,
263 this.name, this.getter, this.setter, this.type, Token token) 291 this.name, this.getter, this.setter, this.type, Token token)
264 : this.receiver = makeOrReuseVariable(receiver), 292 : this.receiver = makeOrReuseVariable(receiver),
265 super(helper, token); 293 super(helper, token);
266 294
267 receiverAccess() => new VariableGet(receiver); 295 receiverAccess() => new VariableGet(receiver);
268 296
269 Expression _makeRead() => 297 Expression _makeRead(KernelComplexAssignment complexAssignment) =>
270 new KernelPropertyGet(receiverAccess(), name, getter); 298 new KernelPropertyGet(receiverAccess(), name, getter);
271 299
272 Expression _makeWrite(Expression value, bool voidContext) { 300 Expression _makeWrite(Expression value, bool voidContext,
301 KernelComplexAssignment complexAssignment) {
273 return new KernelPropertySet(receiverAccess(), name, value, setter); 302 return new KernelPropertySet(receiverAccess(), name, value, setter);
274 } 303 }
275 304
276 Expression _finish(Expression body) => makeLet( 305 Expression _finish(
277 receiver, 306 Expression body, KernelComplexAssignment complexAssignment) =>
278 new KernelConditionalExpression( 307 makeLet(
279 buildIsNull(receiverAccess()), new NullLiteral(), body)); 308 receiver,
309 new KernelConditionalExpression(
310 buildIsNull(receiverAccess()), new NullLiteral(), body));
280 } 311 }
281 312
282 class SuperPropertyAccessor extends Accessor { 313 class SuperPropertyAccessor extends Accessor {
283 Name name; 314 Name name;
284 Member getter, setter; 315 Member getter, setter;
285 316
286 SuperPropertyAccessor( 317 SuperPropertyAccessor(
287 BuilderHelper helper, this.name, this.getter, this.setter, Token token) 318 BuilderHelper helper, this.name, this.getter, this.setter, Token token)
288 : super(helper, token); 319 : super(helper, token);
289 320
290 Expression _makeRead() { 321 Expression _makeRead(KernelComplexAssignment complexAssignment) {
291 if (getter == null) return makeInvalidRead(); 322 if (getter == null) return makeInvalidRead();
292 // TODO(ahe): Use [DirectPropertyGet] when possible. 323 // TODO(ahe): Use [DirectPropertyGet] when possible.
293 return new SuperPropertyGet(name, getter) 324 return new SuperPropertyGet(name, getter)
294 ..fileOffset = offsetForToken(token); 325 ..fileOffset = offsetForToken(token);
295 } 326 }
296 327
297 Expression _makeWrite(Expression value, bool voidContext) { 328 Expression _makeWrite(Expression value, bool voidContext,
329 KernelComplexAssignment complexAssignment) {
298 if (setter == null) return makeInvalidWrite(value); 330 if (setter == null) return makeInvalidWrite(value);
299 // TODO(ahe): Use [DirectPropertySet] when possible. 331 // TODO(ahe): Use [DirectPropertySet] when possible.
300 return new SuperPropertySet(name, value, setter) 332 return new SuperPropertySet(name, value, setter)
301 ..fileOffset = offsetForToken(token); 333 ..fileOffset = offsetForToken(token);
302 } 334 }
303 } 335 }
304 336
305 class IndexAccessor extends Accessor { 337 class IndexAccessor extends Accessor {
306 Expression receiver; 338 Expression receiver;
307 Expression index; 339 Expression index;
308 VariableDeclaration receiverVariable; 340 VariableDeclaration receiverVariable;
309 VariableDeclaration indexVariable; 341 VariableDeclaration indexVariable;
310 Procedure getter, setter; 342 Procedure getter, setter;
311 343
312 static Accessor make(BuilderHelper helper, Expression receiver, 344 static Accessor make(BuilderHelper helper, Expression receiver,
313 Expression index, Procedure getter, Procedure setter, 345 Expression index, Procedure getter, Procedure setter,
314 {Token token}) { 346 {Token token}) {
315 if (receiver is ThisExpression) { 347 if (receiver is ThisExpression) {
316 return new ThisIndexAccessor(helper, index, getter, setter, token); 348 return new ThisIndexAccessor(helper, index, getter, setter, token);
317 } else { 349 } else {
318 return new IndexAccessor.internal( 350 return new IndexAccessor.internal(
319 helper, receiver, index, getter, setter, token); 351 helper, receiver, index, getter, setter, token);
320 } 352 }
321 } 353 }
322 354
323 IndexAccessor.internal(BuilderHelper helper, this.receiver, this.index, 355 IndexAccessor.internal(BuilderHelper helper, this.receiver, this.index,
324 this.getter, this.setter, Token token) 356 this.getter, this.setter, Token token)
325 : super(helper, token); 357 : super(helper, token);
326 358
327 Expression _makeSimpleRead() => new KernelMethodInvocation( 359 Expression _makeSimpleRead() {
328 receiver, indexGetName, new KernelArguments(<Expression>[index]), 360 var read = new KernelMethodInvocation(
329 interfaceTarget: getter) 361 receiver, indexGetName, new KernelArguments(<Expression>[index]),
330 ..fileOffset = offsetForToken(token); 362 interfaceTarget: getter)
363 ..fileOffset = offsetForToken(token);
364 return read;
365 }
331 366
332 Expression _makeSimpleWrite(Expression value, bool voidContext) { 367 Expression _makeSimpleWrite(Expression value, bool voidContext,
333 if (!voidContext) return _makeWriteAndReturn(value); 368 KernelComplexAssignment complexAssignment) {
334 return new KernelMethodInvocation( 369 if (!voidContext) return _makeWriteAndReturn(value, complexAssignment);
370 var write = new KernelMethodInvocation(
335 receiver, indexSetName, new KernelArguments(<Expression>[index, value]), 371 receiver, indexSetName, new KernelArguments(<Expression>[index, value]),
336 interfaceTarget: setter) 372 interfaceTarget: setter)
337 ..fileOffset = offsetForToken(token); 373 ..fileOffset = offsetForToken(token);
374 complexAssignment?.write = write;
375 return write;
338 } 376 }
339 377
340 receiverAccess() { 378 receiverAccess() {
341 // We cannot reuse the receiver if it is a variable since it might be 379 // We cannot reuse the receiver if it is a variable since it might be
342 // reassigned in the index expression. 380 // reassigned in the index expression.
343 receiverVariable ??= new VariableDeclaration.forValue(receiver); 381 receiverVariable ??= new VariableDeclaration.forValue(receiver);
344 return new VariableGet(receiverVariable) 382 return new VariableGet(receiverVariable)
345 ..fileOffset = offsetForToken(token); 383 ..fileOffset = offsetForToken(token);
346 } 384 }
347 385
348 indexAccess() { 386 indexAccess() {
349 indexVariable ??= new VariableDeclaration.forValue(index); 387 indexVariable ??= new VariableDeclaration.forValue(index);
350 return new VariableGet(indexVariable)..fileOffset = offsetForToken(token); 388 return new VariableGet(indexVariable)..fileOffset = offsetForToken(token);
351 } 389 }
352 390
353 Expression _makeRead() { 391 Expression _makeRead(KernelComplexAssignment complexAssignment) {
354 return new KernelMethodInvocation(receiverAccess(), indexGetName, 392 var read = new KernelMethodInvocation(receiverAccess(), indexGetName,
355 new KernelArguments(<Expression>[indexAccess()]), 393 new KernelArguments(<Expression>[indexAccess()]),
356 interfaceTarget: getter) 394 interfaceTarget: getter)
357 ..fileOffset = offsetForToken(token); 395 ..fileOffset = offsetForToken(token);
396 complexAssignment?.read = read;
397 return read;
358 } 398 }
359 399
360 Expression _makeWrite(Expression value, bool voidContext) { 400 Expression _makeWrite(Expression value, bool voidContext,
361 if (!voidContext) return _makeWriteAndReturn(value); 401 KernelComplexAssignment complexAssignment) {
362 return new KernelMethodInvocation(receiverAccess(), indexSetName, 402 if (!voidContext) return _makeWriteAndReturn(value, complexAssignment);
403 var write = new KernelMethodInvocation(receiverAccess(), indexSetName,
363 new KernelArguments(<Expression>[indexAccess(), value]), 404 new KernelArguments(<Expression>[indexAccess(), value]),
364 interfaceTarget: setter) 405 interfaceTarget: setter)
365 ..fileOffset = offsetForToken(token); 406 ..fileOffset = offsetForToken(token);
407 complexAssignment?.write = write;
408 return write;
366 } 409 }
367 410
368 // TODO(dmitryas): remove this method after the "[]=" operator of the Context 411 // TODO(dmitryas): remove this method after the "[]=" operator of the Context
369 // class is made to return a value. 412 // class is made to return a value.
370 _makeWriteAndReturn(Expression value) { 413 _makeWriteAndReturn(
414 Expression value, KernelComplexAssignment complexAssignment) {
371 // The call to []= does not return the value like direct-style assignments 415 // The call to []= does not return the value like direct-style assignments
372 // do. We need to bind the value in a let. 416 // do. We need to bind the value in a let.
373 var valueVariable = new VariableDeclaration.forValue(value); 417 var valueVariable = new VariableDeclaration.forValue(value);
418 var write = new KernelMethodInvocation(
419 receiverAccess(),
420 indexSetName,
421 new KernelArguments(
422 <Expression>[indexAccess(), new VariableGet(valueVariable)]),
423 interfaceTarget: setter)
424 ..fileOffset = offsetForToken(token);
425 complexAssignment?.write = write;
374 var dummy = new KernelVariableDeclaration.forValue( 426 var dummy = new KernelVariableDeclaration.forValue(
375 new KernelMethodInvocation( 427 write, helper.functionNestingLevel);
376 receiverAccess(),
377 indexSetName,
378 new KernelArguments(
379 <Expression>[indexAccess(), new VariableGet(valueVariable)]),
380 interfaceTarget: setter)
381 ..fileOffset = offsetForToken(token),
382 helper.functionNestingLevel,
383 isDiscarding: true);
384 return makeLet( 428 return makeLet(
385 valueVariable, makeLet(dummy, new VariableGet(valueVariable))); 429 valueVariable, makeLet(dummy, new VariableGet(valueVariable)));
386 } 430 }
387 431
388 Expression _finish(Expression body) { 432 Expression _finish(
389 if (receiverVariable == null) { 433 Expression body, KernelComplexAssignment complexAssignment) {
390 assert(indexVariable == null); 434 Expression desugared =
391 return body; 435 makeLet(receiverVariable, makeLet(indexVariable, body));
436 if (complexAssignment != null) {
437 complexAssignment.desugared = desugared;
438 return complexAssignment;
392 } else { 439 } else {
393 return new KernelComplexAssign( 440 return desugared;
394 receiverVariable, makeLet(indexVariable, body));
395 } 441 }
396 } 442 }
397 } 443 }
398 444
399 /// Special case of [IndexAccessor] to avoid creating an indirect access to 445 /// Special case of [IndexAccessor] to avoid creating an indirect access to
400 /// 'this'. 446 /// 'this'.
401 class ThisIndexAccessor extends Accessor { 447 class ThisIndexAccessor extends Accessor {
402 Expression index; 448 Expression index;
403 VariableDeclaration indexVariable; 449 VariableDeclaration indexVariable;
404 Procedure getter, setter; 450 Procedure getter, setter;
405 451
406 ThisIndexAccessor( 452 ThisIndexAccessor(
407 BuilderHelper helper, this.index, this.getter, this.setter, Token token) 453 BuilderHelper helper, this.index, this.getter, this.setter, Token token)
408 : super(helper, token); 454 : super(helper, token);
409 455
410 Expression _makeSimpleRead() { 456 Expression _makeSimpleRead() {
411 return new KernelMethodInvocation(new ThisExpression(), indexGetName, 457 return new KernelMethodInvocation(new ThisExpression(), indexGetName,
412 new KernelArguments(<Expression>[index]), 458 new KernelArguments(<Expression>[index]),
413 interfaceTarget: getter); 459 interfaceTarget: getter);
414 } 460 }
415 461
416 Expression _makeSimpleWrite(Expression value, bool voidContext) { 462 Expression _makeSimpleWrite(Expression value, bool voidContext,
463 KernelComplexAssignment complexAssignment) {
417 if (!voidContext) return _makeWriteAndReturn(value); 464 if (!voidContext) return _makeWriteAndReturn(value);
418 return new KernelMethodInvocation(new ThisExpression(), indexSetName, 465 return new KernelMethodInvocation(new ThisExpression(), indexSetName,
419 new KernelArguments(<Expression>[index, value]), 466 new KernelArguments(<Expression>[index, value]),
420 interfaceTarget: setter); 467 interfaceTarget: setter);
421 } 468 }
422 469
423 indexAccess() { 470 indexAccess() {
424 indexVariable ??= new VariableDeclaration.forValue(index); 471 indexVariable ??= new VariableDeclaration.forValue(index);
425 return new VariableGet(indexVariable); 472 return new VariableGet(indexVariable);
426 } 473 }
427 474
428 Expression _makeRead() => new KernelMethodInvocation(new ThisExpression(), 475 Expression _makeRead(KernelComplexAssignment complexAssignment) =>
429 indexGetName, new KernelArguments(<Expression>[indexAccess()]), 476 new KernelMethodInvocation(new ThisExpression(), indexGetName,
430 interfaceTarget: getter); 477 new KernelArguments(<Expression>[indexAccess()]),
478 interfaceTarget: getter);
431 479
432 Expression _makeWrite(Expression value, bool voidContext) { 480 Expression _makeWrite(Expression value, bool voidContext,
481 KernelComplexAssignment complexAssignment) {
433 if (!voidContext) return _makeWriteAndReturn(value); 482 if (!voidContext) return _makeWriteAndReturn(value);
434 return new KernelMethodInvocation(new ThisExpression(), indexSetName, 483 return new KernelMethodInvocation(new ThisExpression(), indexSetName,
435 new KernelArguments(<Expression>[indexAccess(), value]), 484 new KernelArguments(<Expression>[indexAccess(), value]),
436 interfaceTarget: setter); 485 interfaceTarget: setter);
437 } 486 }
438 487
439 _makeWriteAndReturn(Expression value) { 488 _makeWriteAndReturn(Expression value) {
440 var valueVariable = new VariableDeclaration.forValue(value); 489 var valueVariable = new VariableDeclaration.forValue(value);
441 var dummy = new VariableDeclaration.forValue(new KernelMethodInvocation( 490 var dummy = new VariableDeclaration.forValue(new KernelMethodInvocation(
442 new ThisExpression(), 491 new ThisExpression(),
443 indexSetName, 492 indexSetName,
444 new KernelArguments( 493 new KernelArguments(
445 <Expression>[indexAccess(), new VariableGet(valueVariable)]), 494 <Expression>[indexAccess(), new VariableGet(valueVariable)]),
446 interfaceTarget: setter)); 495 interfaceTarget: setter));
447 return makeLet( 496 return makeLet(
448 valueVariable, makeLet(dummy, new VariableGet(valueVariable))); 497 valueVariable, makeLet(dummy, new VariableGet(valueVariable)));
449 } 498 }
450 499
451 Expression _finish(Expression body) => makeLet(indexVariable, body); 500 Expression _finish(
501 Expression body, KernelComplexAssignment complexAssignment) =>
502 makeLet(indexVariable, body);
452 } 503 }
453 504
454 class SuperIndexAccessor extends Accessor { 505 class SuperIndexAccessor extends Accessor {
455 Expression index; 506 Expression index;
456 VariableDeclaration indexVariable; 507 VariableDeclaration indexVariable;
457 Member getter, setter; 508 Member getter, setter;
458 509
459 SuperIndexAccessor( 510 SuperIndexAccessor(
460 BuilderHelper helper, this.index, this.getter, this.setter, Token token) 511 BuilderHelper helper, this.index, this.getter, this.setter, Token token)
461 : super(helper, token); 512 : super(helper, token);
462 513
463 indexAccess() { 514 indexAccess() {
464 indexVariable ??= new VariableDeclaration.forValue(index); 515 indexVariable ??= new VariableDeclaration.forValue(index);
465 return new VariableGet(indexVariable); 516 return new VariableGet(indexVariable);
466 } 517 }
467 518
468 Expression _makeSimpleRead() => new SuperMethodInvocation( 519 Expression _makeSimpleRead() => new SuperMethodInvocation(
469 indexGetName, new KernelArguments(<Expression>[index]), getter); 520 indexGetName, new KernelArguments(<Expression>[index]), getter);
470 521
471 Expression _makeSimpleWrite(Expression value, bool voidContext) { 522 Expression _makeSimpleWrite(Expression value, bool voidContext,
523 KernelComplexAssignment complexAssignment) {
472 if (!voidContext) return _makeWriteAndReturn(value); 524 if (!voidContext) return _makeWriteAndReturn(value);
473 return new SuperMethodInvocation( 525 return new SuperMethodInvocation(
474 indexSetName, new KernelArguments(<Expression>[index, value]), setter); 526 indexSetName, new KernelArguments(<Expression>[index, value]), setter);
475 } 527 }
476 528
477 Expression _makeRead() { 529 Expression _makeRead(KernelComplexAssignment complexAssignment) {
478 return new SuperMethodInvocation( 530 return new SuperMethodInvocation(
479 indexGetName, new KernelArguments(<Expression>[indexAccess()]), getter); 531 indexGetName, new KernelArguments(<Expression>[indexAccess()]), getter);
480 } 532 }
481 533
482 Expression _makeWrite(Expression value, bool voidContext) { 534 Expression _makeWrite(Expression value, bool voidContext,
535 KernelComplexAssignment complexAssignment) {
483 if (!voidContext) return _makeWriteAndReturn(value); 536 if (!voidContext) return _makeWriteAndReturn(value);
484 return new SuperMethodInvocation(indexSetName, 537 return new SuperMethodInvocation(indexSetName,
485 new KernelArguments(<Expression>[indexAccess(), value]), setter); 538 new KernelArguments(<Expression>[indexAccess(), value]), setter);
486 } 539 }
487 540
488 _makeWriteAndReturn(Expression value) { 541 _makeWriteAndReturn(Expression value) {
489 var valueVariable = new VariableDeclaration.forValue(value); 542 var valueVariable = new VariableDeclaration.forValue(value);
490 var dummy = new VariableDeclaration.forValue(new SuperMethodInvocation( 543 var dummy = new VariableDeclaration.forValue(new SuperMethodInvocation(
491 indexSetName, 544 indexSetName,
492 new KernelArguments( 545 new KernelArguments(
493 <Expression>[indexAccess(), new VariableGet(valueVariable)]), 546 <Expression>[indexAccess(), new VariableGet(valueVariable)]),
494 setter)); 547 setter));
495 return makeLet( 548 return makeLet(
496 valueVariable, makeLet(dummy, new VariableGet(valueVariable))); 549 valueVariable, makeLet(dummy, new VariableGet(valueVariable)));
497 } 550 }
498 551
499 Expression _finish(Expression body) { 552 Expression _finish(
553 Expression body, KernelComplexAssignment complexAssignment) {
500 return makeLet(indexVariable, body); 554 return makeLet(indexVariable, body);
501 } 555 }
502 } 556 }
503 557
504 class StaticAccessor extends Accessor { 558 class StaticAccessor extends Accessor {
505 Member readTarget; 559 Member readTarget;
506 Member writeTarget; 560 Member writeTarget;
507 561
508 StaticAccessor( 562 StaticAccessor(
509 BuilderHelper helper, this.readTarget, this.writeTarget, Token token) 563 BuilderHelper helper, this.readTarget, this.writeTarget, Token token)
510 : super(helper, token); 564 : super(helper, token);
511 565
512 Expression _makeRead() => readTarget == null 566 Expression _makeRead(KernelComplexAssignment complexAssignment) =>
513 ? makeInvalidRead() 567 readTarget == null
514 : helper.makeStaticGet(readTarget, token); 568 ? makeInvalidRead()
569 : helper.makeStaticGet(readTarget, token);
515 570
516 Expression _makeWrite(Expression value, bool voidContext) { 571 Expression _makeWrite(Expression value, bool voidContext,
572 KernelComplexAssignment complexAssignment) {
517 return writeTarget == null 573 return writeTarget == null
518 ? makeInvalidWrite(value) 574 ? makeInvalidWrite(value)
519 : new StaticSet(writeTarget, value) 575 : new StaticSet(writeTarget, value)
520 ..fileOffset = offsetForToken(token); 576 ..fileOffset = offsetForToken(token);
521 } 577 }
522 } 578 }
523 579
524 class ReadOnlyAccessor extends Accessor { 580 class ReadOnlyAccessor extends Accessor {
525 Expression expression; 581 Expression expression;
526 VariableDeclaration value; 582 VariableDeclaration value;
527 583
528 ReadOnlyAccessor(BuilderHelper helper, this.expression, Token token) 584 ReadOnlyAccessor(BuilderHelper helper, this.expression, Token token)
529 : super(helper, token); 585 : super(helper, token);
530 586
531 Expression _makeSimpleRead() => expression; 587 Expression _makeSimpleRead() => expression;
532 588
533 Expression _makeRead() { 589 Expression _makeRead(KernelComplexAssignment complexAssignment) {
534 value ??= new VariableDeclaration.forValue(expression); 590 value ??= new VariableDeclaration.forValue(expression);
535 return new VariableGet(value); 591 return new VariableGet(value);
536 } 592 }
537 593
538 Expression _makeWrite(Expression value, bool voidContext) => 594 Expression _makeWrite(Expression value, bool voidContext,
595 KernelComplexAssignment complexAssignment) =>
539 makeInvalidWrite(value); 596 makeInvalidWrite(value);
540 597
541 Expression _finish(Expression body) => makeLet(value, body); 598 Expression _finish(
599 Expression body, KernelComplexAssignment complexAssignment) =>
600 makeLet(value, body);
542 } 601 }
543 602
544 Expression makeLet(VariableDeclaration variable, Expression body) { 603 Expression makeLet(VariableDeclaration variable, Expression body) {
545 if (variable == null) return body; 604 if (variable == null) return body;
546 return new Let(variable, body); 605 return new Let(variable, body);
547 } 606 }
548 607
549 Expression makeBinary( 608 Expression makeBinary(
550 Expression left, Name operator, Procedure interfaceTarget, Expression right, 609 Expression left, Name operator, Procedure interfaceTarget, Expression right,
551 {int offset: TreeNode.noOffset, bool isCombiner: false}) { 610 {int offset: TreeNode.noOffset}) {
552 return new KernelMethodInvocation( 611 return new KernelMethodInvocation(
553 left, operator, new KernelArguments(<Expression>[right]), 612 left, operator, new KernelArguments(<Expression>[right]),
554 interfaceTarget: interfaceTarget, isCombiner: isCombiner) 613 interfaceTarget: interfaceTarget)
555 ..fileOffset = offset; 614 ..fileOffset = offset;
556 } 615 }
557 616
558 Expression buildIsNull(Expression value, {int offset: TreeNode.noOffset}) { 617 Expression buildIsNull(Expression value, {int offset: TreeNode.noOffset}) {
559 return makeBinary(value, equalsName, null, new NullLiteral(), offset: offset); 618 return makeBinary(value, equalsName, null, new NullLiteral(), offset: offset);
560 } 619 }
561 620
562 VariableDeclaration makeOrReuseVariable(Expression value) { 621 VariableDeclaration makeOrReuseVariable(Expression value) {
563 // TODO: Devise a way to remember if a variable declaration was reused 622 // TODO: Devise a way to remember if a variable declaration was reused
564 // or is fresh (hence needs a let binding). 623 // or is fresh (hence needs a let binding).
565 return new VariableDeclaration.forValue(value); 624 return new VariableDeclaration.forValue(value);
566 } 625 }
OLDNEW
« no previous file with comments | « pkg/front_end/lib/src/fasta/kernel/fasta_accessors.dart ('k') | pkg/front_end/lib/src/fasta/kernel/kernel_shadow_ast.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698