OLD | NEW |
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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 library tree_ir_nodes; | 5 library tree_ir_nodes; |
6 | 6 |
7 import '../constants/expressions.dart'; | 7 import '../constants/expressions.dart'; |
8 import '../constants/values.dart' as values; | 8 import '../constants/values.dart' as values; |
9 import '../dart_types.dart' show DartType, InterfaceType, TypeVariableType; | 9 import '../dart_types.dart' show DartType, InterfaceType, TypeVariableType; |
10 import '../elements/elements.dart'; | 10 import '../elements/elements.dart'; |
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
194 * A call to a method, operator, getter, setter or index getter/setter. | 194 * A call to a method, operator, getter, setter or index getter/setter. |
195 * | 195 * |
196 * If [receiver] is `null`, an error is thrown before the arguments are | 196 * If [receiver] is `null`, an error is thrown before the arguments are |
197 * evaluated. This corresponds to the JS evaluation order. | 197 * evaluated. This corresponds to the JS evaluation order. |
198 */ | 198 */ |
199 class InvokeMethod extends Expression implements Invoke { | 199 class InvokeMethod extends Expression implements Invoke { |
200 Expression receiver; | 200 Expression receiver; |
201 final Selector selector; | 201 final Selector selector; |
202 final TypeMask mask; | 202 final TypeMask mask; |
203 final List<Expression> arguments; | 203 final List<Expression> arguments; |
| 204 final SourceInformation sourceInformation; |
204 | 205 |
205 /// If true, it is known that the receiver cannot be `null`. | 206 /// If true, it is known that the receiver cannot be `null`. |
206 bool receiverIsNotNull = false; | 207 bool receiverIsNotNull = false; |
207 | 208 |
208 InvokeMethod(this.receiver, this.selector, this.mask, this.arguments) { | 209 InvokeMethod(this.receiver, |
| 210 this.selector, |
| 211 this.mask, |
| 212 this.arguments, |
| 213 this.sourceInformation) { |
209 assert(receiver != null); | 214 assert(receiver != null); |
210 } | 215 } |
211 | 216 |
212 accept(ExpressionVisitor visitor) => visitor.visitInvokeMethod(this); | 217 accept(ExpressionVisitor visitor) => visitor.visitInvokeMethod(this); |
213 accept1(ExpressionVisitor1 visitor, arg) { | 218 accept1(ExpressionVisitor1 visitor, arg) { |
214 return visitor.visitInvokeMethod(this, arg); | 219 return visitor.visitInvokeMethod(this, arg); |
215 } | 220 } |
216 } | 221 } |
217 | 222 |
218 /// Invoke [target] on [receiver], bypassing ordinary dispatch semantics. | 223 /// Invoke [target] on [receiver], bypassing ordinary dispatch semantics. |
219 /// | 224 /// |
220 /// Since the [receiver] is not used for method lookup, it may be `null` | 225 /// Since the [receiver] is not used for method lookup, it may be `null` |
221 /// without an error being thrown. | 226 /// without an error being thrown. |
222 class InvokeMethodDirectly extends Expression implements Invoke { | 227 class InvokeMethodDirectly extends Expression implements Invoke { |
223 Expression receiver; | 228 Expression receiver; |
224 final Element target; | 229 final Element target; |
225 final Selector selector; | 230 final Selector selector; |
226 final List<Expression> arguments; | 231 final List<Expression> arguments; |
| 232 final SourceInformation sourceInformation; |
227 | 233 |
228 InvokeMethodDirectly(this.receiver, this.target, this.selector, | 234 InvokeMethodDirectly(this.receiver, this.target, this.selector, |
229 this.arguments); | 235 this.arguments, this.sourceInformation); |
230 | 236 |
231 accept(ExpressionVisitor visitor) => visitor.visitInvokeMethodDirectly(this); | 237 accept(ExpressionVisitor visitor) => visitor.visitInvokeMethodDirectly(this); |
232 accept1(ExpressionVisitor1 visitor, arg) { | 238 accept1(ExpressionVisitor1 visitor, arg) { |
233 return visitor.visitInvokeMethodDirectly(this, arg); | 239 return visitor.visitInvokeMethodDirectly(this, arg); |
234 } | 240 } |
235 } | 241 } |
236 | 242 |
237 /** | 243 /** |
238 * Call to a factory or generative constructor. | 244 * Call to a factory or generative constructor. |
239 */ | 245 */ |
240 class InvokeConstructor extends Expression implements Invoke { | 246 class InvokeConstructor extends Expression implements Invoke { |
241 final DartType type; | 247 final DartType type; |
242 final FunctionElement target; | 248 final FunctionElement target; |
243 final List<Expression> arguments; | 249 final List<Expression> arguments; |
244 final Selector selector; | 250 final Selector selector; |
| 251 final SourceInformation sourceInformation; |
245 /// TODO(karlklose): get rid of this field. Instead use the constant's | 252 /// TODO(karlklose): get rid of this field. Instead use the constant's |
246 /// expression to find the constructor to be called in dart2dart. | 253 /// expression to find the constructor to be called in dart2dart. |
247 final values.ConstantValue constant; | 254 final values.ConstantValue constant; |
248 | 255 |
249 InvokeConstructor(this.type, this.target, this.selector, this.arguments, | 256 InvokeConstructor(this.type, this.target, this.selector, this.arguments, |
250 [this.constant]); | 257 this.sourceInformation, [this.constant]); |
251 | 258 |
252 ClassElement get targetClass => target.enclosingElement; | 259 ClassElement get targetClass => target.enclosingElement; |
253 | 260 |
254 accept(ExpressionVisitor visitor) { | 261 accept(ExpressionVisitor visitor) { |
255 return visitor.visitInvokeConstructor(this); | 262 return visitor.visitInvokeConstructor(this); |
256 } | 263 } |
257 | 264 |
258 accept1(ExpressionVisitor1 visitor, arg) { | 265 accept1(ExpressionVisitor1 visitor, arg) { |
259 return visitor.visitInvokeConstructor(this, arg); | 266 return visitor.visitInvokeConstructor(this, arg); |
260 } | 267 } |
261 } | 268 } |
262 | 269 |
263 /** | 270 /** |
264 * A constant. | 271 * A constant. |
265 */ | 272 */ |
266 class Constant extends Expression { | 273 class Constant extends Expression { |
267 final values.ConstantValue value; | 274 final values.ConstantValue value; |
| 275 final SourceInformation sourceInformation; |
268 | 276 |
269 Constant(this.value); | 277 Constant(this.value, {this.sourceInformation}); |
270 | 278 |
271 Constant.bool(values.BoolConstantValue constantValue) | 279 Constant.bool(values.BoolConstantValue constantValue) |
272 : value = constantValue; | 280 : value = constantValue, |
| 281 sourceInformation = null; |
273 | 282 |
274 accept(ExpressionVisitor visitor) => visitor.visitConstant(this); | 283 accept(ExpressionVisitor visitor) => visitor.visitConstant(this); |
275 accept1(ExpressionVisitor1 visitor, arg) => visitor.visitConstant(this, arg); | 284 accept1(ExpressionVisitor1 visitor, arg) => visitor.visitConstant(this, arg); |
| 285 |
| 286 String toString() => 'Constant(value=${value.toStructuredString()})'; |
276 } | 287 } |
277 | 288 |
278 class This extends Expression { | 289 class This extends Expression { |
279 accept(ExpressionVisitor visitor) => visitor.visitThis(this); | 290 accept(ExpressionVisitor visitor) => visitor.visitThis(this); |
280 accept1(ExpressionVisitor1 visitor, arg) => visitor.visitThis(this, arg); | 291 accept1(ExpressionVisitor1 visitor, arg) => visitor.visitThis(this, arg); |
281 } | 292 } |
282 | 293 |
283 class LiteralList extends Expression { | 294 class LiteralList extends Expression { |
284 final InterfaceType type; | 295 final InterfaceType type; |
285 final List<Expression> values; | 296 final List<Expression> values; |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
357 Expression condition; | 368 Expression condition; |
358 Expression thenExpression; | 369 Expression thenExpression; |
359 Expression elseExpression; | 370 Expression elseExpression; |
360 | 371 |
361 Conditional(this.condition, this.thenExpression, this.elseExpression); | 372 Conditional(this.condition, this.thenExpression, this.elseExpression); |
362 | 373 |
363 accept(ExpressionVisitor visitor) => visitor.visitConditional(this); | 374 accept(ExpressionVisitor visitor) => visitor.visitConditional(this); |
364 accept1(ExpressionVisitor1 visitor, arg) { | 375 accept1(ExpressionVisitor1 visitor, arg) { |
365 return visitor.visitConditional(this, arg); | 376 return visitor.visitConditional(this, arg); |
366 } | 377 } |
| 378 |
| 379 String toString() => 'Conditional(condition=$condition,thenExpression=' |
| 380 '$thenExpression,elseExpression=$elseExpression)'; |
367 } | 381 } |
368 | 382 |
369 /// An && or || expression. The operator is internally represented as a boolean | 383 /// An && or || expression. The operator is internally represented as a boolean |
370 /// [isAnd] to simplify rewriting of logical operators. | 384 /// [isAnd] to simplify rewriting of logical operators. |
371 class LogicalOperator extends Expression { | 385 class LogicalOperator extends Expression { |
372 Expression left; | 386 Expression left; |
373 bool isAnd; | 387 bool isAnd; |
374 Expression right; | 388 Expression right; |
375 | 389 |
376 LogicalOperator(this.left, this.right, this.isAnd); | 390 LogicalOperator(this.left, this.right, this.isAnd); |
377 LogicalOperator.and(this.left, this.right) : isAnd = true; | 391 LogicalOperator.and(this.left, this.right) : isAnd = true; |
378 LogicalOperator.or(this.left, this.right) : isAnd = false; | 392 LogicalOperator.or(this.left, this.right) : isAnd = false; |
379 | 393 |
380 String get operator => isAnd ? '&&' : '||'; | 394 String get operator => isAnd ? '&&' : '||'; |
381 | 395 |
382 accept(ExpressionVisitor visitor) => visitor.visitLogicalOperator(this); | 396 accept(ExpressionVisitor visitor) => visitor.visitLogicalOperator(this); |
383 accept1(ExpressionVisitor1 visitor, arg) { | 397 accept1(ExpressionVisitor1 visitor, arg) { |
384 return visitor.visitLogicalOperator(this, arg); | 398 return visitor.visitLogicalOperator(this, arg); |
385 } | 399 } |
| 400 |
| 401 String toString() => 'LogicalOperator(left=$left,right=$right,isAnd=$isAnd)'; |
386 } | 402 } |
387 | 403 |
388 /// Logical negation. | 404 /// Logical negation. |
389 // TODO(asgerf): Replace this class with the IsFalsy builtin operator? | 405 // TODO(asgerf): Replace this class with the IsFalsy builtin operator? |
390 // Right now the tree builder compiles IsFalsy to Not. | 406 // Right now the tree builder compiles IsFalsy to Not. |
391 class Not extends Expression { | 407 class Not extends Expression { |
392 Expression operand; | 408 Expression operand; |
393 | 409 |
394 Not(this.operand); | 410 Not(this.operand); |
395 | 411 |
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
534 * | 550 * |
535 * In contrast to the CPS-based IR, the return value is an arbitrary | 551 * In contrast to the CPS-based IR, the return value is an arbitrary |
536 * expression. | 552 * expression. |
537 */ | 553 */ |
538 class Return extends Statement { | 554 class Return extends Statement { |
539 /// Should not be null. Use [Constant] with [NullConstantValue] for void | 555 /// Should not be null. Use [Constant] with [NullConstantValue] for void |
540 /// returns. | 556 /// returns. |
541 /// Even in constructors this holds true. Take special care when translating | 557 /// Even in constructors this holds true. Take special care when translating |
542 /// back to dart, where `return null;` in a constructor is an error. | 558 /// back to dart, where `return null;` in a constructor is an error. |
543 Expression value; | 559 Expression value; |
| 560 SourceInformation sourceInformation; |
544 | 561 |
545 Statement get next => null; | 562 Statement get next => null; |
546 void set next(Statement s) => throw 'UNREACHABLE'; | 563 void set next(Statement s) => throw 'UNREACHABLE'; |
547 | 564 |
548 Return(this.value); | 565 Return(this.value, {this.sourceInformation}); |
549 | 566 |
550 accept(StatementVisitor visitor) => visitor.visitReturn(this); | 567 accept(StatementVisitor visitor) => visitor.visitReturn(this); |
551 accept1(StatementVisitor1 visitor, arg) => visitor.visitReturn(this, arg); | 568 accept1(StatementVisitor1 visitor, arg) => visitor.visitReturn(this, arg); |
552 } | 569 } |
553 | 570 |
554 /// A throw statement. | 571 /// A throw statement. |
555 /// | 572 /// |
556 /// In the Tree IR, throw is a statement (like JavaScript and unlike Dart). | 573 /// In the Tree IR, throw is a statement (like JavaScript and unlike Dart). |
557 /// It does not have a successor statement. | 574 /// It does not have a successor statement. |
558 class Throw extends Statement { | 575 class Throw extends Statement { |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
657 | 674 |
658 class CreateBox extends Expression { | 675 class CreateBox extends Expression { |
659 accept(ExpressionVisitor visitor) => visitor.visitCreateBox(this); | 676 accept(ExpressionVisitor visitor) => visitor.visitCreateBox(this); |
660 accept1(ExpressionVisitor1 visitor, arg) => visitor.visitCreateBox(this, arg); | 677 accept1(ExpressionVisitor1 visitor, arg) => visitor.visitCreateBox(this, arg); |
661 } | 678 } |
662 | 679 |
663 class CreateInstance extends Expression { | 680 class CreateInstance extends Expression { |
664 ClassElement classElement; | 681 ClassElement classElement; |
665 List<Expression> arguments; | 682 List<Expression> arguments; |
666 List<Expression> typeInformation; | 683 List<Expression> typeInformation; |
| 684 SourceInformation sourceInformation; |
667 | 685 |
668 CreateInstance(this.classElement, this.arguments, this.typeInformation); | 686 CreateInstance(this.classElement, this.arguments, |
| 687 this.typeInformation, this.sourceInformation); |
669 | 688 |
670 accept(ExpressionVisitor visitor) => visitor.visitCreateInstance(this); | 689 accept(ExpressionVisitor visitor) => visitor.visitCreateInstance(this); |
671 accept1(ExpressionVisitor1 visitor, arg) { | 690 accept1(ExpressionVisitor1 visitor, arg) { |
672 return visitor.visitCreateInstance(this, arg); | 691 return visitor.visitCreateInstance(this, arg); |
673 } | 692 } |
674 } | 693 } |
675 | 694 |
676 class GetField extends Expression { | 695 class GetField extends Expression { |
677 Expression object; | 696 Expression object; |
678 Element field; | 697 Element field; |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
742 Expression value; | 761 Expression value; |
743 | 762 |
744 SetIndex(this.object, this.index, this.value); | 763 SetIndex(this.object, this.index, this.value); |
745 | 764 |
746 accept(ExpressionVisitor v) => v.visitSetIndex(this); | 765 accept(ExpressionVisitor v) => v.visitSetIndex(this); |
747 accept1(ExpressionVisitor1 v, arg) => v.visitSetIndex(this, arg); | 766 accept1(ExpressionVisitor1 v, arg) => v.visitSetIndex(this, arg); |
748 } | 767 } |
749 | 768 |
750 class ReifyRuntimeType extends Expression { | 769 class ReifyRuntimeType extends Expression { |
751 Expression value; | 770 Expression value; |
| 771 SourceInformation sourceInformation; |
752 | 772 |
753 ReifyRuntimeType(this.value); | 773 ReifyRuntimeType(this.value, this.sourceInformation); |
754 | 774 |
755 accept(ExpressionVisitor visitor) { | 775 accept(ExpressionVisitor visitor) { |
756 return visitor.visitReifyRuntimeType(this); | 776 return visitor.visitReifyRuntimeType(this); |
757 } | 777 } |
758 | 778 |
759 accept1(ExpressionVisitor1 visitor, arg) { | 779 accept1(ExpressionVisitor1 visitor, arg) { |
760 return visitor.visitReifyRuntimeType(this, arg); | 780 return visitor.visitReifyRuntimeType(this, arg); |
761 } | 781 } |
762 } | 782 } |
763 | 783 |
764 class ReadTypeVariable extends Expression { | 784 class ReadTypeVariable extends Expression { |
765 final TypeVariableType variable; | 785 final TypeVariableType variable; |
766 Expression target; | 786 Expression target; |
| 787 final SourceInformation sourceInformation; |
767 | 788 |
768 ReadTypeVariable(this.variable, this.target); | 789 ReadTypeVariable(this.variable, this.target, this.sourceInformation); |
769 | 790 |
770 accept(ExpressionVisitor visitor) { | 791 accept(ExpressionVisitor visitor) { |
771 return visitor.visitReadTypeVariable(this); | 792 return visitor.visitReadTypeVariable(this); |
772 } | 793 } |
773 | 794 |
774 accept1(ExpressionVisitor1 visitor, arg) { | 795 accept1(ExpressionVisitor1 visitor, arg) { |
775 return visitor.visitReadTypeVariable(this, arg); | 796 return visitor.visitReadTypeVariable(this, arg); |
776 } | 797 } |
777 } | 798 } |
778 | 799 |
(...skipping 652 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1431 | 1452 |
1432 /// Number of uses of the current fallthrough target. | 1453 /// Number of uses of the current fallthrough target. |
1433 int get useCount => _stack.last.useCount; | 1454 int get useCount => _stack.last.useCount; |
1434 | 1455 |
1435 /// Indicate that a statement will fall through to the current fallthrough | 1456 /// Indicate that a statement will fall through to the current fallthrough |
1436 /// target. | 1457 /// target. |
1437 void use() { | 1458 void use() { |
1438 ++_stack.last.useCount; | 1459 ++_stack.last.useCount; |
1439 } | 1460 } |
1440 } | 1461 } |
OLD | NEW |