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

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

Issue 2926763003: Add type inference for complex assignments whose LHS is an index expression. (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,
12 KernelConditionalExpression,
11 KernelMethodInvocation, 13 KernelMethodInvocation,
12 KernelPropertyGet, 14 KernelPropertyGet,
13 KernelPropertySet, 15 KernelPropertySet,
16 KernelVariableDeclaration,
14 KernelVariableGet, 17 KernelVariableGet,
15 KernelVariableSet; 18 KernelVariableSet;
16 19
17 import 'package:front_end/src/fasta/kernel/utils.dart' show offsetForToken; 20 import 'package:front_end/src/fasta/kernel/utils.dart' show offsetForToken;
18 21
19 import 'package:front_end/src/scanner/token.dart' show Token; 22 import 'package:front_end/src/scanner/token.dart' show Token;
20 23
21 import 'package:front_end/src/fasta/kernel/fasta_accessors.dart' 24 import 'package:front_end/src/fasta/kernel/fasta_accessors.dart'
22 show BuilderHelper; 25 show BuilderHelper;
23 26
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
62 /// Returns an [Expression] representing a null-aware assignment (`??=`) with 65 /// Returns an [Expression] representing a null-aware assignment (`??=`) with
63 /// the accessor on the LHS and [value] on the RHS. 66 /// the accessor on the LHS and [value] on the RHS.
64 /// 67 ///
65 /// The returned expression evaluates to the assigned value, unless 68 /// The returned expression evaluates to the assigned value, unless
66 /// [voidContext] is true, in which case it may evaluate to anything. 69 /// [voidContext] is true, in which case it may evaluate to anything.
67 /// 70 ///
68 /// [type] is the static type of the RHS. 71 /// [type] is the static type of the RHS.
69 Expression buildNullAwareAssignment(Expression value, DartType type, 72 Expression buildNullAwareAssignment(Expression value, DartType type,
70 {bool voidContext: false}) { 73 {bool voidContext: false}) {
71 if (voidContext) { 74 if (voidContext) {
72 return _finish(new ConditionalExpression(buildIsNull(_makeRead()), 75 return _finish(new KernelConditionalExpression(
73 _makeWrite(value, false), new NullLiteral(), type)); 76 buildIsNull(_makeRead()), _makeWrite(value, false), new NullLiteral(),
77 isNullAwareCombiner: true));
74 } 78 }
75 var tmp = new VariableDeclaration.forValue(_makeRead()); 79 var tmp = new VariableDeclaration.forValue(_makeRead());
76 return _finish(makeLet( 80 return _finish(makeLet(
77 tmp, 81 tmp,
78 new ConditionalExpression(buildIsNull(new VariableGet(tmp)), 82 new KernelConditionalExpression(buildIsNull(new VariableGet(tmp)),
79 _makeWrite(value, false), new VariableGet(tmp), type))); 83 _makeWrite(value, false), new VariableGet(tmp),
84 isNullAwareCombiner: true)));
80 } 85 }
81 86
82 /// Returns an [Expression] representing a compound assignment (e.g. `+=`) 87 /// Returns an [Expression] representing a compound assignment (e.g. `+=`)
83 /// with the accessor on the LHS and [value] on the RHS. 88 /// with the accessor on the LHS and [value] on the RHS.
84 Expression buildCompoundAssignment(Name binaryOperator, Expression value, 89 Expression buildCompoundAssignment(Name binaryOperator, Expression value,
85 {int offset: TreeNode.noOffset, 90 {int offset: TreeNode.noOffset,
86 bool voidContext: false, 91 bool voidContext: false,
87 Procedure interfaceTarget}) { 92 Procedure interfaceTarget}) {
88 return _finish(_makeWrite( 93 return _finish(_makeWrite(
89 makeBinary(_makeRead(), binaryOperator, interfaceTarget, value, 94 makeBinary(_makeRead(), binaryOperator, interfaceTarget, value,
90 offset: offset), 95 offset: offset, isCombiner: true),
91 voidContext)); 96 voidContext));
92 } 97 }
93 98
94 /// Returns an [Expression] representing a pre-increment or pre-decrement 99 /// Returns an [Expression] representing a pre-increment or pre-decrement
95 /// of the accessor. 100 /// of the accessor.
96 Expression buildPrefixIncrement(Name binaryOperator, 101 Expression buildPrefixIncrement(Name binaryOperator,
97 {int offset: TreeNode.noOffset, 102 {int offset: TreeNode.noOffset,
98 bool voidContext: false, 103 bool voidContext: false,
99 Procedure interfaceTarget}) { 104 Procedure interfaceTarget}) {
100 return buildCompoundAssignment(binaryOperator, new IntLiteral(1), 105 return buildCompoundAssignment(binaryOperator, new IntLiteral(1),
101 offset: offset, 106 offset: offset,
102 voidContext: voidContext, 107 voidContext: voidContext,
103 interfaceTarget: interfaceTarget); 108 interfaceTarget: interfaceTarget);
104 } 109 }
105 110
106 /// Returns an [Expression] representing a post-increment or post-decrement 111 /// Returns an [Expression] representing a post-increment or post-decrement
107 /// of the accessor. 112 /// of the accessor.
108 Expression buildPostfixIncrement(Name binaryOperator, 113 Expression buildPostfixIncrement(Name binaryOperator,
109 {int offset: TreeNode.noOffset, 114 {int offset: TreeNode.noOffset,
110 bool voidContext: false, 115 bool voidContext: false,
111 Procedure interfaceTarget}) { 116 Procedure interfaceTarget}) {
112 if (voidContext) { 117 if (voidContext) {
113 return buildPrefixIncrement(binaryOperator, 118 return buildPrefixIncrement(binaryOperator,
114 offset: offset, voidContext: true, interfaceTarget: interfaceTarget); 119 offset: offset, voidContext: true, interfaceTarget: interfaceTarget);
115 } 120 }
116 var value = new VariableDeclaration.forValue(_makeRead()); 121 var value = new VariableDeclaration.forValue(_makeRead());
117 valueAccess() => new VariableGet(value); 122 valueAccess() => new VariableGet(value);
118 var dummy = new VariableDeclaration.forValue(_makeWrite( 123 var dummy = new KernelVariableDeclaration.forValue(
119 makeBinary( 124 _makeWrite(
120 valueAccess(), binaryOperator, interfaceTarget, new IntLiteral(1), 125 makeBinary(valueAccess(), binaryOperator, interfaceTarget,
121 offset: offset), 126 new IntLiteral(1),
122 true)); 127 offset: offset, isCombiner: true),
128 true),
129 helper.functionNestingLevel,
130 isDiscarding: true);
123 return _finish(makeLet(value, makeLet(dummy, valueAccess()))); 131 return _finish(makeLet(value, makeLet(dummy, valueAccess())));
124 } 132 }
125 133
126 Expression _makeSimpleRead() => _makeRead(); 134 Expression _makeSimpleRead() => _makeRead();
127 135
128 Expression _makeSimpleWrite(Expression value, bool voidContext) { 136 Expression _makeSimpleWrite(Expression value, bool voidContext) {
129 return _makeWrite(value, voidContext); 137 return _makeWrite(value, voidContext);
130 } 138 }
131 139
132 Expression _makeRead(); 140 Expression _makeRead();
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after
260 268
261 Expression _makeRead() => 269 Expression _makeRead() =>
262 new KernelPropertyGet(receiverAccess(), name, getter); 270 new KernelPropertyGet(receiverAccess(), name, getter);
263 271
264 Expression _makeWrite(Expression value, bool voidContext) { 272 Expression _makeWrite(Expression value, bool voidContext) {
265 return new KernelPropertySet(receiverAccess(), name, value, setter); 273 return new KernelPropertySet(receiverAccess(), name, value, setter);
266 } 274 }
267 275
268 Expression _finish(Expression body) => makeLet( 276 Expression _finish(Expression body) => makeLet(
269 receiver, 277 receiver,
270 new ConditionalExpression( 278 new KernelConditionalExpression(
271 buildIsNull(receiverAccess()), new NullLiteral(), body, type)); 279 buildIsNull(receiverAccess()), new NullLiteral(), body));
272 } 280 }
273 281
274 class SuperPropertyAccessor extends Accessor { 282 class SuperPropertyAccessor extends Accessor {
275 Name name; 283 Name name;
276 Member getter, setter; 284 Member getter, setter;
277 285
278 SuperPropertyAccessor( 286 SuperPropertyAccessor(
279 BuilderHelper helper, this.name, this.getter, this.setter, Token token) 287 BuilderHelper helper, this.name, this.getter, this.setter, Token token)
280 : super(helper, token); 288 : super(helper, token);
281 289
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
356 interfaceTarget: setter) 364 interfaceTarget: setter)
357 ..fileOffset = offsetForToken(token); 365 ..fileOffset = offsetForToken(token);
358 } 366 }
359 367
360 // TODO(dmitryas): remove this method after the "[]=" operator of the Context 368 // TODO(dmitryas): remove this method after the "[]=" operator of the Context
361 // class is made to return a value. 369 // class is made to return a value.
362 _makeWriteAndReturn(Expression value) { 370 _makeWriteAndReturn(Expression value) {
363 // The call to []= does not return the value like direct-style assignments 371 // The call to []= does not return the value like direct-style assignments
364 // do. We need to bind the value in a let. 372 // do. We need to bind the value in a let.
365 var valueVariable = new VariableDeclaration.forValue(value); 373 var valueVariable = new VariableDeclaration.forValue(value);
366 var dummy = new VariableDeclaration.forValue(new KernelMethodInvocation( 374 var dummy = new KernelVariableDeclaration.forValue(
367 receiverAccess(), 375 new KernelMethodInvocation(
368 indexSetName, 376 receiverAccess(),
369 new KernelArguments( 377 indexSetName,
370 <Expression>[indexAccess(), new VariableGet(valueVariable)]), 378 new KernelArguments(
371 interfaceTarget: setter) 379 <Expression>[indexAccess(), new VariableGet(valueVariable)]),
372 ..fileOffset = offsetForToken(token)); 380 interfaceTarget: setter)
381 ..fileOffset = offsetForToken(token),
382 helper.functionNestingLevel,
383 isDiscarding: true);
373 return makeLet( 384 return makeLet(
374 valueVariable, makeLet(dummy, new VariableGet(valueVariable))); 385 valueVariable, makeLet(dummy, new VariableGet(valueVariable)));
375 } 386 }
376 387
377 Expression _finish(Expression body) { 388 Expression _finish(Expression body) {
378 return makeLet(receiverVariable, makeLet(indexVariable, body)); 389 if (receiverVariable == null) {
390 assert(indexVariable == null);
391 return body;
392 } else {
393 return new KernelComplexAssign(
394 receiverVariable, makeLet(indexVariable, body));
395 }
379 } 396 }
380 } 397 }
381 398
382 /// Special case of [IndexAccessor] to avoid creating an indirect access to 399 /// Special case of [IndexAccessor] to avoid creating an indirect access to
383 /// 'this'. 400 /// 'this'.
384 class ThisIndexAccessor extends Accessor { 401 class ThisIndexAccessor extends Accessor {
385 Expression index; 402 Expression index;
386 VariableDeclaration indexVariable; 403 VariableDeclaration indexVariable;
387 Procedure getter, setter; 404 Procedure getter, setter;
388 405
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after
524 Expression _finish(Expression body) => makeLet(value, body); 541 Expression _finish(Expression body) => makeLet(value, body);
525 } 542 }
526 543
527 Expression makeLet(VariableDeclaration variable, Expression body) { 544 Expression makeLet(VariableDeclaration variable, Expression body) {
528 if (variable == null) return body; 545 if (variable == null) return body;
529 return new Let(variable, body); 546 return new Let(variable, body);
530 } 547 }
531 548
532 Expression makeBinary( 549 Expression makeBinary(
533 Expression left, Name operator, Procedure interfaceTarget, Expression right, 550 Expression left, Name operator, Procedure interfaceTarget, Expression right,
534 {int offset: TreeNode.noOffset}) { 551 {int offset: TreeNode.noOffset, bool isCombiner: false}) {
535 return new KernelMethodInvocation( 552 return new KernelMethodInvocation(
536 left, operator, new KernelArguments(<Expression>[right]), 553 left, operator, new KernelArguments(<Expression>[right]),
537 interfaceTarget: interfaceTarget) 554 interfaceTarget: interfaceTarget, isCombiner: isCombiner)
538 ..fileOffset = offset; 555 ..fileOffset = offset;
539 } 556 }
540 557
541 Expression buildIsNull(Expression value, {int offset: TreeNode.noOffset}) { 558 Expression buildIsNull(Expression value, {int offset: TreeNode.noOffset}) {
542 return makeBinary(value, equalsName, null, new NullLiteral(), offset: offset); 559 return makeBinary(value, equalsName, null, new NullLiteral(), offset: offset);
543 } 560 }
544 561
545 VariableDeclaration makeOrReuseVariable(Expression value) { 562 VariableDeclaration makeOrReuseVariable(Expression value) {
546 // TODO: Devise a way to remember if a variable declaration was reused 563 // TODO: Devise a way to remember if a variable declaration was reused
547 // or is fresh (hence needs a let binding). 564 // or is fresh (hence needs a let binding).
548 return new VariableDeclaration.forValue(value); 565 return new VariableDeclaration.forValue(value);
549 } 566 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698