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 | 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, |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
66 complexAssignment); | 66 complexAssignment); |
67 } | 67 } |
68 | 68 |
69 /// Returns an [Expression] representing a null-aware assignment (`??=`) with | 69 /// Returns an [Expression] representing a null-aware assignment (`??=`) with |
70 /// the accessor on the LHS and [value] on the RHS. | 70 /// the accessor on the LHS and [value] on the RHS. |
71 /// | 71 /// |
72 /// The returned expression evaluates to the assigned value, unless | 72 /// The returned expression evaluates to the assigned value, unless |
73 /// [voidContext] is true, in which case it may evaluate to anything. | 73 /// [voidContext] is true, in which case it may evaluate to anything. |
74 /// | 74 /// |
75 /// [type] is the static type of the RHS. | 75 /// [type] is the static type of the RHS. |
76 Expression buildNullAwareAssignment(Expression value, DartType type, | 76 Expression buildNullAwareAssignment( |
77 Expression value, DartType type, int offset, | |
77 {bool voidContext: false}) { | 78 {bool voidContext: false}) { |
78 var complexAssignment = startComplexAssignment(value); | 79 var complexAssignment = startComplexAssignment(value); |
79 if (voidContext) { | 80 if (voidContext) { |
80 var nullAwareCombiner = new KernelConditionalExpression( | 81 var nullAwareCombiner = new KernelConditionalExpression( |
81 buildIsNull(_makeRead(complexAssignment)), | 82 buildIsNull(_makeRead(complexAssignment), offset), |
82 _makeWrite(value, false, complexAssignment), | 83 _makeWrite(value, false, complexAssignment), |
83 new NullLiteral()); | 84 new NullLiteral()); |
84 complexAssignment?.nullAwareCombiner = nullAwareCombiner; | 85 complexAssignment?.nullAwareCombiner = nullAwareCombiner; |
85 return _finish(nullAwareCombiner, complexAssignment); | 86 return _finish(nullAwareCombiner, complexAssignment); |
86 } | 87 } |
87 var tmp = new VariableDeclaration.forValue(_makeRead(complexAssignment)); | 88 var tmp = new VariableDeclaration.forValue(_makeRead(complexAssignment)); |
88 var nullAwareCombiner = new KernelConditionalExpression( | 89 var nullAwareCombiner = new KernelConditionalExpression( |
89 buildIsNull(new VariableGet(tmp)), | 90 buildIsNull(new VariableGet(tmp), offset), |
90 _makeWrite(value, false, complexAssignment), | 91 _makeWrite(value, false, complexAssignment), |
91 new VariableGet(tmp)); | 92 new VariableGet(tmp)); |
92 complexAssignment?.nullAwareCombiner = nullAwareCombiner; | 93 complexAssignment?.nullAwareCombiner = nullAwareCombiner; |
93 return _finish(makeLet(tmp, nullAwareCombiner), complexAssignment); | 94 return _finish(makeLet(tmp, nullAwareCombiner), complexAssignment); |
94 } | 95 } |
95 | 96 |
96 /// Returns an [Expression] representing a compound assignment (e.g. `+=`) | 97 /// Returns an [Expression] representing a compound assignment (e.g. `+=`) |
97 /// with the accessor on the LHS and [value] on the RHS. | 98 /// with the accessor on the LHS and [value] on the RHS. |
98 Expression buildCompoundAssignment(Name binaryOperator, Expression value, | 99 Expression buildCompoundAssignment(Name binaryOperator, Expression value, |
99 {int offset: TreeNode.noOffset, | 100 {int offset: TreeNode.noOffset, |
(...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
341 KernelComplexAssignment complexAssignment) { | 342 KernelComplexAssignment complexAssignment) { |
342 var write = new KernelPropertySet(receiverAccess(), name, value, setter) | 343 var write = new KernelPropertySet(receiverAccess(), name, value, setter) |
343 ..fileOffset = offsetForToken(token); | 344 ..fileOffset = offsetForToken(token); |
344 complexAssignment?.write = write; | 345 complexAssignment?.write = write; |
345 return write; | 346 return write; |
346 } | 347 } |
347 | 348 |
348 Expression _finish( | 349 Expression _finish( |
349 Expression body, KernelComplexAssignment complexAssignment) { | 350 Expression body, KernelComplexAssignment complexAssignment) { |
350 var nullAwareGuard = new KernelConditionalExpression( | 351 var nullAwareGuard = new KernelConditionalExpression( |
351 buildIsNull(receiverAccess()), new NullLiteral(), body) | 352 buildIsNull(receiverAccess(), offsetForToken(token)), |
353 new NullLiteral(), | |
354 body) | |
352 ..fileOffset = offsetForToken(token); | 355 ..fileOffset = offsetForToken(token); |
353 body = makeLet(receiver, nullAwareGuard); | 356 body = makeLet(receiver, nullAwareGuard); |
354 if (complexAssignment != null) { | 357 if (complexAssignment != null) { |
355 KernelPropertyAssign kernelPropertyAssign = complexAssignment; | 358 KernelPropertyAssign kernelPropertyAssign = complexAssignment; |
356 kernelPropertyAssign.nullAwareGuard = nullAwareGuard; | 359 kernelPropertyAssign.nullAwareGuard = nullAwareGuard; |
357 kernelPropertyAssign.desugared = body; | 360 kernelPropertyAssign.desugared = body; |
358 return kernelPropertyAssign; | 361 return kernelPropertyAssign; |
359 } else { | 362 } else { |
360 return body; | 363 return body; |
361 } | 364 } |
(...skipping 311 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
673 | 676 |
674 Expression makeBinary( | 677 Expression makeBinary( |
675 Expression left, Name operator, Procedure interfaceTarget, Expression right, | 678 Expression left, Name operator, Procedure interfaceTarget, Expression right, |
676 {int offset: TreeNode.noOffset}) { | 679 {int offset: TreeNode.noOffset}) { |
677 return new KernelMethodInvocation( | 680 return new KernelMethodInvocation( |
678 left, operator, new KernelArguments(<Expression>[right]), | 681 left, operator, new KernelArguments(<Expression>[right]), |
679 interfaceTarget: interfaceTarget) | 682 interfaceTarget: interfaceTarget) |
680 ..fileOffset = offset; | 683 ..fileOffset = offset; |
681 } | 684 } |
682 | 685 |
683 Expression buildIsNull(Expression value, {int offset: TreeNode.noOffset}) { | 686 Expression buildIsNull(Expression value, int offset) { |
Paul Berry
2017/06/12 20:17:23
Note: I changed `offset` to a required argument he
| |
684 return makeBinary(value, equalsName, null, new NullLiteral(), offset: offset); | 687 return makeBinary(value, equalsName, null, new NullLiteral(), offset: offset); |
685 } | 688 } |
686 | 689 |
687 VariableDeclaration makeOrReuseVariable(Expression value) { | 690 VariableDeclaration makeOrReuseVariable(Expression value) { |
688 // TODO: Devise a way to remember if a variable declaration was reused | 691 // TODO: Devise a way to remember if a variable declaration was reused |
689 // or is fresh (hence needs a let binding). | 692 // or is fresh (hence needs a let binding). |
690 return new VariableDeclaration.forValue(value); | 693 return new VariableDeclaration.forValue(value); |
691 } | 694 } |
OLD | NEW |