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 // Note: copied from package:kernel at revision 7346348. | 5 // Note: copied from package:kernel at revision 7346348. |
6 | 6 |
7 /// A library to help transform compounds and null-aware accessors into | 7 /// A library to help transform compounds and null-aware accessors into |
8 /// let expressions. | 8 /// let expressions. |
9 library kernel.frontend.accessors; | 9 library kernel.frontend.accessors; |
10 | 10 |
| 11 import 'package:front_end/src/fasta/builder/shadow_ast.dart'; |
| 12 import 'package:front_end/src/fasta/kernel/kernel_shadow_ast.dart'; |
11 import 'package:kernel/ast.dart'; | 13 import 'package:kernel/ast.dart'; |
12 | 14 |
13 import '../names.dart' show indexGetName, indexSetName; | 15 import '../names.dart' show indexGetName, indexSetName; |
14 | 16 |
15 /// An [Accessor] represents a subexpression for which we can't yet build a | 17 /// 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 | 18 /// kernel [Expression] because we don't yet know the context in which it is |
17 /// used. | 19 /// used. |
18 /// | 20 /// |
19 /// Once the context is known, an [Accessor] can be converted into an | 21 /// Once the context is known, an [Accessor] can be converted into an |
20 /// [Expression] by calling a "build" method. | 22 /// [Expression] by calling a "build" method. |
21 /// | 23 /// |
22 /// For example, when building a kernel representation for `a[x] = b`, after | 24 /// 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 | 25 /// 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 | 26 /// generate an invocation of `operator[]` or `operator[]=`, so we generate an |
25 /// [Accessor] object. Later, after `= b` is parsed, [buildAssignment] will be | 27 /// [Accessor] object. Later, after `= b` is parsed, [buildAssignment] will be |
26 /// called. | 28 /// called. |
27 abstract class Accessor { | 29 abstract class Accessor { |
28 /// Builds an [Expression] representing a read from the accessor. | 30 /// Builds an [Expression] representing a read from the accessor. |
29 Expression buildSimpleRead() { | 31 ShadowExpression buildSimpleRead() { |
30 return _finish(_makeSimpleRead()); | 32 return _finish(_makeSimpleRead() as ShadowExpression); |
31 } | 33 } |
32 | 34 |
33 /// Builds an [Expression] representing an assignment with the accessor on | 35 /// Builds an [Expression] representing an assignment with the accessor on |
34 /// the LHS and [value] on the RHS. | 36 /// the LHS and [value] on the RHS. |
35 /// | 37 /// |
36 /// The returned expression evaluates to the assigned value, unless | 38 /// The returned expression evaluates to the assigned value, unless |
37 /// [voidContext] is true, in which case it may evaluate to anything. | 39 /// [voidContext] is true, in which case it may evaluate to anything. |
38 Expression buildAssignment(Expression value, {bool voidContext: false}) { | 40 Expression buildAssignment(Expression value, {bool voidContext: false}) { |
39 return _finish(_makeSimpleWrite(value, voidContext)); | 41 return _finish(_makeSimpleWrite(value, voidContext) as ShadowExpression) |
| 42 as Expression; |
40 } | 43 } |
41 | 44 |
42 /// Returns an [Expression] representing a null-aware assignment (`??=`) with | 45 /// Returns an [Expression] representing a null-aware assignment (`??=`) with |
43 /// the accessor on the LHS and [value] on the RHS. | 46 /// the accessor on the LHS and [value] on the RHS. |
44 /// | 47 /// |
45 /// The returned expression evaluates to the assigned value, unless | 48 /// The returned expression evaluates to the assigned value, unless |
46 /// [voidContext] is true, in which case it may evaluate to anything. | 49 /// [voidContext] is true, in which case it may evaluate to anything. |
47 /// | 50 /// |
48 /// [type] is the static type of the RHS. | 51 /// [type] is the static type of the RHS. |
49 Expression buildNullAwareAssignment(Expression value, DartType type, | 52 Expression buildNullAwareAssignment(Expression value, DartType type, |
50 {bool voidContext: false}) { | 53 {bool voidContext: false}) { |
51 if (voidContext) { | 54 if (voidContext) { |
52 return _finish(new ConditionalExpression(buildIsNull(_makeRead()), | 55 return _finish(new ConditionalExpression( |
53 _makeWrite(value, false), new NullLiteral(), type)); | 56 buildIsNull(_makeRead()), |
| 57 _makeWrite(value, false), |
| 58 new NullLiteral(), |
| 59 type) as ShadowExpression) as Expression; |
54 } | 60 } |
55 var tmp = new VariableDeclaration.forValue(_makeRead()); | 61 var tmp = new VariableDeclaration.forValue(_makeRead()); |
56 return _finish(makeLet( | 62 return _finish(makeLet( |
57 tmp, | 63 tmp, |
58 new ConditionalExpression(buildIsNull(new VariableGet(tmp)), | 64 new ConditionalExpression( |
59 _makeWrite(value, false), new VariableGet(tmp), type))); | 65 buildIsNull(new VariableGet(tmp)), |
| 66 _makeWrite(value, false), |
| 67 new VariableGet(tmp), |
| 68 type)) as ShadowExpression) as Expression; |
60 } | 69 } |
61 | 70 |
62 /// Returns an [Expression] representing a compound assignment (e.g. `+=`) | 71 /// Returns an [Expression] representing a compound assignment (e.g. `+=`) |
63 /// with the accessor on the LHS and [value] on the RHS. | 72 /// with the accessor on the LHS and [value] on the RHS. |
64 Expression buildCompoundAssignment( | 73 Expression buildCompoundAssignment( |
65 Name binaryOperator, Expression value, int charOffset, | 74 Name binaryOperator, Expression value, int charOffset, |
66 {bool voidContext: false, Procedure interfaceTarget}) { | 75 {bool voidContext: false, Procedure interfaceTarget}) { |
67 return _finish(_makeWrite( | 76 return _finish(_makeWrite( |
68 makeBinary( | 77 makeBinary( |
69 _makeRead(), binaryOperator, interfaceTarget, value, charOffset), | 78 _makeRead(), binaryOperator, interfaceTarget, value, charOffset), |
70 voidContext)); | 79 voidContext) as ShadowExpression) as Expression; |
71 } | 80 } |
72 | 81 |
73 /// Returns an [Expression] representing a pre-increment or pre-decrement | 82 /// Returns an [Expression] representing a pre-increment or pre-decrement |
74 /// of the accessor. | 83 /// of the accessor. |
75 Expression buildPrefixIncrement(Name binaryOperator, int charOffset, | 84 Expression buildPrefixIncrement(Name binaryOperator, int charOffset, |
76 {bool voidContext: false, Procedure interfaceTarget}) { | 85 {bool voidContext: false, Procedure interfaceTarget}) { |
77 return buildCompoundAssignment( | 86 return buildCompoundAssignment( |
78 binaryOperator, new IntLiteral(1), charOffset, | 87 binaryOperator, new IntLiteral(1), charOffset, |
79 voidContext: voidContext, interfaceTarget: interfaceTarget); | 88 voidContext: voidContext, interfaceTarget: interfaceTarget); |
80 } | 89 } |
81 | 90 |
82 /// Returns an [Expression] representing a post-increment or post-decrement | 91 /// Returns an [Expression] representing a post-increment or post-decrement |
83 /// of the accessor. | 92 /// of the accessor. |
84 Expression buildPostfixIncrement(Name binaryOperator, int charOffset, | 93 Expression buildPostfixIncrement(Name binaryOperator, int charOffset, |
85 {bool voidContext: false, Procedure interfaceTarget}) { | 94 {bool voidContext: false, Procedure interfaceTarget}) { |
86 if (voidContext) { | 95 if (voidContext) { |
87 return buildPrefixIncrement(binaryOperator, charOffset, | 96 return buildPrefixIncrement(binaryOperator, charOffset, |
88 voidContext: true, interfaceTarget: interfaceTarget); | 97 voidContext: true, interfaceTarget: interfaceTarget); |
89 } | 98 } |
90 var value = new VariableDeclaration.forValue(_makeRead()); | 99 var value = new VariableDeclaration.forValue(_makeRead()); |
91 valueAccess() => new VariableGet(value); | 100 valueAccess() => new VariableGet(value); |
92 var dummy = new VariableDeclaration.forValue(_makeWrite( | 101 var dummy = new VariableDeclaration.forValue(_makeWrite( |
93 makeBinary(valueAccess(), binaryOperator, interfaceTarget, | 102 makeBinary(valueAccess(), binaryOperator, interfaceTarget, |
94 new IntLiteral(1), charOffset), | 103 new IntLiteral(1), charOffset), |
95 true)); | 104 true)); |
96 return _finish(makeLet(value, makeLet(dummy, valueAccess()))); | 105 return _finish( |
| 106 makeLet(value, makeLet(dummy, valueAccess())) as ShadowExpression) |
| 107 as Expression; |
97 } | 108 } |
98 | 109 |
99 Expression _makeSimpleRead() => _makeRead(); | 110 Expression _makeSimpleRead() => _makeRead(); |
100 | 111 |
101 Expression _makeSimpleWrite(Expression value, bool voidContext) { | 112 Expression _makeSimpleWrite(Expression value, bool voidContext) { |
102 return _makeWrite(value, voidContext); | 113 return _makeWrite(value, voidContext); |
103 } | 114 } |
104 | 115 |
105 Expression _makeRead(); | 116 Expression _makeRead(); |
106 | 117 |
107 Expression _makeWrite(Expression value, bool voidContext); | 118 Expression _makeWrite(Expression value, bool voidContext); |
108 | 119 |
109 Expression _finish(Expression body) => body; | 120 ShadowExpression _finish(ShadowExpression body) => body; |
110 | 121 |
111 /// Returns an [Expression] representing a compile-time error. | 122 /// Returns an [Expression] representing a compile-time error. |
112 /// | 123 /// |
113 /// At runtime, an exception will be thrown. | 124 /// At runtime, an exception will be thrown. |
114 makeInvalidRead() => new InvalidExpression(); | 125 makeInvalidRead() => new InvalidExpression(); |
115 | 126 |
116 /// Returns an [Expression] representing a compile-time error wrapping | 127 /// Returns an [Expression] representing a compile-time error wrapping |
117 /// [value]. | 128 /// [value]. |
118 /// | 129 /// |
119 /// At runtime, [value] will be evaluated before throwing an exception. | 130 /// At runtime, [value] will be evaluated before throwing an exception. |
120 makeInvalidWrite(Expression value) => wrapInvalid(value); | 131 makeInvalidWrite(Expression value) => wrapInvalid(value); |
121 } | 132 } |
122 | 133 |
123 class VariableAccessor extends Accessor { | 134 class VariableAccessor extends Accessor { |
124 VariableDeclaration variable; | 135 VariableDeclaration variable; |
125 int charOffset; | 136 int charOffset; |
126 DartType promotedType; | 137 DartType promotedType; |
127 | 138 |
128 VariableAccessor(this.variable, [this.promotedType]); | 139 VariableAccessor(this.variable, [this.promotedType]); |
129 | 140 |
130 VariableAccessor.internal(this.variable, this.charOffset, this.promotedType); | 141 VariableAccessor.internal(this.variable, this.charOffset, this.promotedType); |
131 | 142 |
132 _makeRead() => | 143 _makeRead() => |
133 new VariableGet(variable, promotedType)..fileOffset = charOffset; | 144 new KernelVariableGet(variable, promotedType)..fileOffset = charOffset; |
134 | 145 |
135 _makeWrite(Expression value, bool voidContext) { | 146 _makeWrite(Expression value, bool voidContext) { |
136 return variable.isFinal || variable.isConst | 147 return variable.isFinal || variable.isConst |
137 ? makeInvalidWrite(value) | 148 ? makeInvalidWrite(value) |
138 : new VariableSet(variable, value)..fileOffset = charOffset; | 149 : new VariableSet(variable, value)..fileOffset = charOffset; |
139 } | 150 } |
140 } | 151 } |
141 | 152 |
142 class PropertyAccessor extends Accessor { | 153 class PropertyAccessor extends Accessor { |
143 VariableDeclaration _receiverVariable; | 154 VariableDeclaration _receiverVariable; |
(...skipping 28 matching lines...) Expand all Loading... |
172 } | 183 } |
173 | 184 |
174 _makeRead() => | 185 _makeRead() => |
175 new PropertyGet(receiverAccess(), name, getter)..fileOffset = charOffset; | 186 new PropertyGet(receiverAccess(), name, getter)..fileOffset = charOffset; |
176 | 187 |
177 _makeWrite(Expression value, bool voidContext) { | 188 _makeWrite(Expression value, bool voidContext) { |
178 return new PropertySet(receiverAccess(), name, value, setter) | 189 return new PropertySet(receiverAccess(), name, value, setter) |
179 ..fileOffset = charOffset; | 190 ..fileOffset = charOffset; |
180 } | 191 } |
181 | 192 |
182 _finish(Expression body) => makeLet(_receiverVariable, body); | 193 _finish(ShadowExpression body) => |
| 194 makeLet(_receiverVariable, body as Expression) as ShadowExpression; |
183 } | 195 } |
184 | 196 |
185 /// Special case of [PropertyAccessor] to avoid creating an indirect access to | 197 /// Special case of [PropertyAccessor] to avoid creating an indirect access to |
186 /// 'this'. | 198 /// 'this'. |
187 class ThisPropertyAccessor extends Accessor { | 199 class ThisPropertyAccessor extends Accessor { |
188 Name name; | 200 Name name; |
189 Member getter, setter; | 201 Member getter, setter; |
190 final int charOffset; | 202 final int charOffset; |
191 | 203 |
192 ThisPropertyAccessor(this.name, this.getter, this.setter, this.charOffset); | 204 ThisPropertyAccessor(this.name, this.getter, this.setter, this.charOffset); |
(...skipping 18 matching lines...) Expand all Loading... |
211 : this.receiver = makeOrReuseVariable(receiver); | 223 : this.receiver = makeOrReuseVariable(receiver); |
212 | 224 |
213 receiverAccess() => new VariableGet(receiver); | 225 receiverAccess() => new VariableGet(receiver); |
214 | 226 |
215 _makeRead() => new PropertyGet(receiverAccess(), name, getter); | 227 _makeRead() => new PropertyGet(receiverAccess(), name, getter); |
216 | 228 |
217 _makeWrite(Expression value, bool voidContext) { | 229 _makeWrite(Expression value, bool voidContext) { |
218 return new PropertySet(receiverAccess(), name, value, setter); | 230 return new PropertySet(receiverAccess(), name, value, setter); |
219 } | 231 } |
220 | 232 |
221 _finish(Expression body) => makeLet( | 233 _finish(ShadowExpression body) => makeLet( |
222 receiver, | 234 receiver, |
223 new ConditionalExpression( | 235 new ConditionalExpression(buildIsNull(receiverAccess()), |
224 buildIsNull(receiverAccess()), new NullLiteral(), body, type)); | 236 new NullLiteral(), body as Expression, type)) as ShadowExpression; |
225 } | 237 } |
226 | 238 |
227 class SuperPropertyAccessor extends Accessor { | 239 class SuperPropertyAccessor extends Accessor { |
228 Name name; | 240 Name name; |
229 Member getter, setter; | 241 Member getter, setter; |
230 final int charOffset; | 242 final int charOffset; |
231 | 243 |
232 SuperPropertyAccessor(this.name, this.getter, this.setter, this.charOffset); | 244 SuperPropertyAccessor(this.name, this.getter, this.setter, this.charOffset); |
233 | 245 |
234 _makeRead() { | 246 _makeRead() { |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
320 var dummy = new VariableDeclaration.forValue(new MethodInvocation( | 332 var dummy = new VariableDeclaration.forValue(new MethodInvocation( |
321 receiverAccess(), | 333 receiverAccess(), |
322 indexSetName, | 334 indexSetName, |
323 new Arguments( | 335 new Arguments( |
324 <Expression>[indexAccess(), new VariableGet(valueVariable)]), | 336 <Expression>[indexAccess(), new VariableGet(valueVariable)]), |
325 setter)..fileOffset = charOffset); | 337 setter)..fileOffset = charOffset); |
326 return makeLet( | 338 return makeLet( |
327 valueVariable, makeLet(dummy, new VariableGet(valueVariable))); | 339 valueVariable, makeLet(dummy, new VariableGet(valueVariable))); |
328 } | 340 } |
329 | 341 |
330 Expression _finish(Expression body) { | 342 ShadowExpression _finish(ShadowExpression body) { |
331 return makeLet(receiverVariable, makeLet(indexVariable, body)); | 343 return makeLet(receiverVariable, makeLet(indexVariable, body as Expression)) |
| 344 as ShadowExpression; |
332 } | 345 } |
333 } | 346 } |
334 | 347 |
335 /// Special case of [IndexAccessor] to avoid creating an indirect access to | 348 /// Special case of [IndexAccessor] to avoid creating an indirect access to |
336 /// 'this'. | 349 /// 'this'. |
337 class ThisIndexAccessor extends Accessor { | 350 class ThisIndexAccessor extends Accessor { |
338 Expression index; | 351 Expression index; |
339 VariableDeclaration indexVariable; | 352 VariableDeclaration indexVariable; |
340 Procedure getter, setter; | 353 Procedure getter, setter; |
341 | 354 |
(...skipping 29 matching lines...) Expand all Loading... |
371 var dummy = new VariableDeclaration.forValue(new MethodInvocation( | 384 var dummy = new VariableDeclaration.forValue(new MethodInvocation( |
372 new ThisExpression(), | 385 new ThisExpression(), |
373 indexSetName, | 386 indexSetName, |
374 new Arguments( | 387 new Arguments( |
375 <Expression>[indexAccess(), new VariableGet(valueVariable)]), | 388 <Expression>[indexAccess(), new VariableGet(valueVariable)]), |
376 setter)); | 389 setter)); |
377 return makeLet( | 390 return makeLet( |
378 valueVariable, makeLet(dummy, new VariableGet(valueVariable))); | 391 valueVariable, makeLet(dummy, new VariableGet(valueVariable))); |
379 } | 392 } |
380 | 393 |
381 Expression _finish(Expression body) => makeLet(indexVariable, body); | 394 ShadowExpression _finish(ShadowExpression body) => |
| 395 makeLet(indexVariable, body as Expression) as ShadowExpression; |
382 } | 396 } |
383 | 397 |
384 class SuperIndexAccessor extends Accessor { | 398 class SuperIndexAccessor extends Accessor { |
385 Expression index; | 399 Expression index; |
386 VariableDeclaration indexVariable; | 400 VariableDeclaration indexVariable; |
387 Member getter, setter; | 401 Member getter, setter; |
388 | 402 |
389 SuperIndexAccessor(this.index, this.getter, this.setter); | 403 SuperIndexAccessor(this.index, this.getter, this.setter); |
390 | 404 |
391 indexAccess() { | 405 indexAccess() { |
(...skipping 25 matching lines...) Expand all Loading... |
417 var valueVariable = new VariableDeclaration.forValue(value); | 431 var valueVariable = new VariableDeclaration.forValue(value); |
418 var dummy = new VariableDeclaration.forValue(new SuperMethodInvocation( | 432 var dummy = new VariableDeclaration.forValue(new SuperMethodInvocation( |
419 indexSetName, | 433 indexSetName, |
420 new Arguments( | 434 new Arguments( |
421 <Expression>[indexAccess(), new VariableGet(valueVariable)]), | 435 <Expression>[indexAccess(), new VariableGet(valueVariable)]), |
422 setter)); | 436 setter)); |
423 return makeLet( | 437 return makeLet( |
424 valueVariable, makeLet(dummy, new VariableGet(valueVariable))); | 438 valueVariable, makeLet(dummy, new VariableGet(valueVariable))); |
425 } | 439 } |
426 | 440 |
427 Expression _finish(Expression body) { | 441 ShadowExpression _finish(ShadowExpression body) { |
428 return makeLet(indexVariable, body); | 442 return makeLet(indexVariable, body as Expression) as ShadowExpression; |
429 } | 443 } |
430 } | 444 } |
431 | 445 |
432 class StaticAccessor extends Accessor { | 446 class StaticAccessor extends Accessor { |
433 Member readTarget; | 447 Member readTarget; |
434 Member writeTarget; | 448 Member writeTarget; |
435 int charOffset; | 449 int charOffset; |
436 | 450 |
437 StaticAccessor(this.readTarget, this.writeTarget, this.charOffset); | 451 StaticAccessor(this.readTarget, this.writeTarget, this.charOffset); |
438 | 452 |
(...skipping 16 matching lines...) Expand all Loading... |
455 | 469 |
456 _makeSimpleRead() => expression; | 470 _makeSimpleRead() => expression; |
457 | 471 |
458 _makeRead() { | 472 _makeRead() { |
459 value ??= new VariableDeclaration.forValue(expression); | 473 value ??= new VariableDeclaration.forValue(expression); |
460 return new VariableGet(value); | 474 return new VariableGet(value); |
461 } | 475 } |
462 | 476 |
463 _makeWrite(Expression value, bool voidContext) => makeInvalidWrite(value); | 477 _makeWrite(Expression value, bool voidContext) => makeInvalidWrite(value); |
464 | 478 |
465 Expression _finish(Expression body) => makeLet(value, body); | 479 ShadowExpression _finish(ShadowExpression body) => |
| 480 makeLet(value, body as Expression) as ShadowExpression; |
466 } | 481 } |
467 | 482 |
468 Expression makeLet(VariableDeclaration variable, Expression body) { | 483 Expression makeLet(VariableDeclaration variable, Expression body) { |
469 if (variable == null) return body; | 484 if (variable == null) return body; |
470 return new Let(variable, body); | 485 return new Let(variable, body); |
471 } | 486 } |
472 | 487 |
473 Expression makeBinary(Expression left, Name operator, Procedure interfaceTarget, | 488 Expression makeBinary(Expression left, Name operator, Procedure interfaceTarget, |
474 Expression right, int charOffset) { | 489 Expression right, int charOffset) { |
475 return new MethodInvocation( | 490 return new MethodInvocation( |
(...skipping 10 matching lines...) Expand all Loading... |
486 | 501 |
487 VariableDeclaration makeOrReuseVariable(Expression value) { | 502 VariableDeclaration makeOrReuseVariable(Expression value) { |
488 // TODO: Devise a way to remember if a variable declaration was reused | 503 // TODO: Devise a way to remember if a variable declaration was reused |
489 // or is fresh (hence needs a let binding). | 504 // or is fresh (hence needs a let binding). |
490 return new VariableDeclaration.forValue(value); | 505 return new VariableDeclaration.forValue(value); |
491 } | 506 } |
492 | 507 |
493 Expression wrapInvalid(Expression e) { | 508 Expression wrapInvalid(Expression e) { |
494 return new Let(new VariableDeclaration.forValue(e), new InvalidExpression()); | 509 return new Let(new VariableDeclaration.forValue(e), new InvalidExpression()); |
495 } | 510 } |
OLD | NEW |