| OLD | NEW |
| 1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2017, 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 import 'package:kernel/ast.dart' as ir; | 5 import 'package:kernel/ast.dart' as ir; |
| 6 | 6 |
| 7 import '../common.dart'; | 7 import '../common.dart'; |
| 8 import '../common/names.dart'; | 8 import '../common/names.dart'; |
| 9 import '../constants/constructors.dart'; | 9 import '../constants/constructors.dart'; |
| 10 import '../constants/expressions.dart'; | 10 import '../constants/expressions.dart'; |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 140 ir.StaticInvocation node); | 140 ir.StaticInvocation node); |
| 141 | 141 |
| 142 /// Compute the kind of foreign helper function called by [node], if any. | 142 /// Compute the kind of foreign helper function called by [node], if any. |
| 143 ForeignKind getForeignKind(ir.StaticInvocation node); | 143 ForeignKind getForeignKind(ir.StaticInvocation node); |
| 144 | 144 |
| 145 /// Computes the [InterfaceType] referenced by a call to the | 145 /// Computes the [InterfaceType] referenced by a call to the |
| 146 /// [JS_INTERCEPTOR_CONSTANT] function, if any. | 146 /// [JS_INTERCEPTOR_CONSTANT] function, if any. |
| 147 InterfaceType getInterfaceTypeForJsInterceptorCall(ir.StaticInvocation node); | 147 InterfaceType getInterfaceTypeForJsInterceptorCall(ir.StaticInvocation node); |
| 148 | 148 |
| 149 /// Computes the [ConstantValue] for the constant [expression]. | 149 /// Computes the [ConstantValue] for the constant [expression]. |
| 150 ConstantValue getConstantValue(ir.Expression expression); | 150 ConstantValue getConstantValue(ir.Expression expression, |
| 151 {bool requireConstant: true}); |
| 151 | 152 |
| 152 /// Returns the `noSuchMethod` [FunctionEntity] call from a | 153 /// Returns the `noSuchMethod` [FunctionEntity] call from a |
| 153 /// `super.noSuchMethod` invocation within [cls]. | 154 /// `super.noSuchMethod` invocation within [cls]. |
| 154 FunctionEntity getSuperNoSuchMethod(ClassEntity cls); | 155 FunctionEntity getSuperNoSuchMethod(ClassEntity cls); |
| 155 | 156 |
| 156 /// Returns a [Spannable] for a message pointing to the IR [node] in the | 157 /// Returns a [Spannable] for a message pointing to the IR [node] in the |
| 157 /// context of [member]. | 158 /// context of [member]. |
| 158 Spannable getSpannable(MemberEntity member, ir.Node node); | 159 Spannable getSpannable(MemberEntity member, ir.Node node); |
| 159 } | 160 } |
| 160 | 161 |
| 161 /// Kinds of foreign functions. | 162 /// Kinds of foreign functions. |
| 162 enum ForeignKind { | 163 enum ForeignKind { |
| 163 JS, | 164 JS, |
| 164 JS_BUILTIN, | 165 JS_BUILTIN, |
| 165 JS_EMBEDDED_GLOBAL, | 166 JS_EMBEDDED_GLOBAL, |
| 166 JS_INTERCEPTOR_CONSTANT, | 167 JS_INTERCEPTOR_CONSTANT, |
| 167 NONE, | 168 NONE, |
| 168 } | 169 } |
| 169 | 170 |
| 170 abstract class KernelToElementMapMixin implements KernelToElementMap { | 171 abstract class KernelToElementMapMixin implements KernelToElementMap { |
| 171 DiagnosticReporter get reporter; | 172 DiagnosticReporter get reporter; |
| 172 native.BehaviorBuilder get nativeBehaviorBuilder; | 173 native.BehaviorBuilder get nativeBehaviorBuilder; |
| 173 ConstantValue computeConstantValue(ConstantExpression constant); | 174 ConstantValue computeConstantValue(ConstantExpression constant, |
| 175 {bool requireConstant: true}); |
| 174 | 176 |
| 175 @override | 177 @override |
| 176 Name getName(ir.Name name) { | 178 Name getName(ir.Name name) { |
| 177 return new Name( | 179 return new Name( |
| 178 name.name, name.isPrivate ? getLibrary(name.library) : null); | 180 name.name, name.isPrivate ? getLibrary(name.library) : null); |
| 179 } | 181 } |
| 180 | 182 |
| 181 @override | 183 @override |
| 182 CallStructure getCallStructure(ir.Arguments arguments) { | 184 CallStructure getCallStructure(ir.Arguments arguments) { |
| 183 int argumentCount = arguments.positional.length + arguments.named.length; | 185 int argumentCount = arguments.positional.length + arguments.named.length; |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 233 irName.name, irName.isPrivate ? getLibrary(irName.library) : null); | 235 irName.name, irName.isPrivate ? getLibrary(irName.library) : null); |
| 234 return new Selector.getter(name); | 236 return new Selector.getter(name); |
| 235 } | 237 } |
| 236 | 238 |
| 237 Selector getSetterSelector(ir.Name irName) { | 239 Selector getSetterSelector(ir.Name irName) { |
| 238 Name name = new Name( | 240 Name name = new Name( |
| 239 irName.name, irName.isPrivate ? getLibrary(irName.library) : null); | 241 irName.name, irName.isPrivate ? getLibrary(irName.library) : null); |
| 240 return new Selector.setter(name); | 242 return new Selector.setter(name); |
| 241 } | 243 } |
| 242 | 244 |
| 243 ConstantValue getConstantValue(ir.Expression node) { | 245 ConstantValue getConstantValue(ir.Expression node, |
| 244 ConstantExpression constant = new Constantifier(this).visit(node); | 246 {bool requireConstant: true}) { |
| 247 ConstantExpression constant = |
| 248 new Constantifier(this, requireConstant: requireConstant).visit(node); |
| 245 if (constant == null) { | 249 if (constant == null) { |
| 246 throw new UnsupportedError( | 250 if (requireConstant) { |
| 247 'No constant for ${DebugPrinter.prettyPrint(node)}'); | 251 throw new UnsupportedError( |
| 252 'No constant for ${DebugPrinter.prettyPrint(node)}'); |
| 253 } |
| 254 return null; |
| 248 } | 255 } |
| 249 return computeConstantValue(constant); | 256 return computeConstantValue(constant, requireConstant: requireConstant); |
| 250 } | 257 } |
| 251 | 258 |
| 252 /// Converts [annotations] into a list of [ConstantValue]s. | 259 /// Converts [annotations] into a list of [ConstantValue]s. |
| 253 List<ConstantValue> getMetadata(List<ir.Expression> annotations) { | 260 List<ConstantValue> getMetadata(List<ir.Expression> annotations) { |
| 254 if (annotations.isEmpty) return const <ConstantValue>[]; | 261 if (annotations.isEmpty) return const <ConstantValue>[]; |
| 255 List<ConstantValue> metadata = <ConstantValue>[]; | 262 List<ConstantValue> metadata = <ConstantValue>[]; |
| 256 annotations.forEach((ir.Expression node) { | 263 annotations.forEach((ir.Expression node) { |
| 257 metadata.add(getConstantValue(node)); | 264 metadata.add(getConstantValue(node)); |
| 258 }); | 265 }); |
| 259 return metadata; | 266 return metadata; |
| (...skipping 283 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 543 ConstantExpression visit(ir.Expression node) { | 550 ConstantExpression visit(ir.Expression node) { |
| 544 ConstantExpression constant = node.accept(this); | 551 ConstantExpression constant = node.accept(this); |
| 545 if (constant == null && requireConstant) { | 552 if (constant == null && requireConstant) { |
| 546 throw new UnsupportedError( | 553 throw new UnsupportedError( |
| 547 "No constant computed for $node (${node.runtimeType})"); | 554 "No constant computed for $node (${node.runtimeType})"); |
| 548 } | 555 } |
| 549 return constant; | 556 return constant; |
| 550 } | 557 } |
| 551 | 558 |
| 552 ConstantExpression defaultExpression(ir.Expression node) { | 559 ConstantExpression defaultExpression(ir.Expression node) { |
| 553 throw new UnimplementedError( | 560 if (requireConstant) { |
| 554 'Unimplemented constant expression $node (${node.runtimeType})'); | 561 throw new UnimplementedError( |
| 562 'Unimplemented constant expression $node (${node.runtimeType})'); |
| 563 } |
| 564 return null; |
| 555 } | 565 } |
| 556 | 566 |
| 557 List<ConstantExpression> _computeList(List<ir.Expression> expressions) { | 567 List<ConstantExpression> _computeList(List<ir.Expression> expressions) { |
| 558 List<ConstantExpression> list = <ConstantExpression>[]; | 568 List<ConstantExpression> list = <ConstantExpression>[]; |
| 559 for (ir.Expression expression in expressions) { | 569 for (ir.Expression expression in expressions) { |
| 560 ConstantExpression constant = visit(expression); | 570 ConstantExpression constant = visit(expression); |
| 561 if (constant == null) return null; | 571 if (constant == null) return null; |
| 562 list.add(constant); | 572 list.add(constant); |
| 563 } | 573 } |
| 564 return list; | 574 return list; |
| 565 } | 575 } |
| 566 | 576 |
| 567 List<ConstantExpression> _computeArguments(ir.Arguments node) { | 577 List<ConstantExpression> _computeArguments(ir.Arguments node) { |
| 568 List<ConstantExpression> arguments = <ConstantExpression>[]; | 578 List<ConstantExpression> arguments = <ConstantExpression>[]; |
| 569 for (ir.Expression argument in node.positional) { | 579 for (ir.Expression argument in node.positional) { |
| 570 ConstantExpression constant = visit(argument); | 580 ConstantExpression constant = visit(argument); |
| 571 if (constant == null) return null; | 581 if (constant == null) return null; |
| 572 arguments.add(constant); | 582 arguments.add(constant); |
| 573 } | 583 } |
| 574 for (ir.NamedExpression argument in node.named) { | 584 for (ir.NamedExpression argument in node.named) { |
| 575 ConstantExpression constant = visit(argument.value); | 585 ConstantExpression constant = visit(argument.value); |
| 576 if (constant == null) return null; | 586 if (constant == null) return null; |
| 577 arguments.add(constant); | 587 arguments.add(constant); |
| 578 } | 588 } |
| 579 return arguments; | 589 return arguments; |
| 580 } | 590 } |
| 581 | 591 |
| 582 ConstructedConstantExpression _computeConstructorInvocation( | 592 ConstructedConstantExpression _computeConstructorInvocation( |
| 583 ir.Constructor target, ir.Arguments arguments) { | 593 ir.Constructor target, ir.Arguments arguments) { |
| 594 List<ConstantExpression> expressions = _computeArguments(arguments); |
| 595 if (expressions == null) return null; |
| 584 return new ConstructedConstantExpression( | 596 return new ConstructedConstantExpression( |
| 585 elementAdapter.createInterfaceType( | 597 elementAdapter.createInterfaceType( |
| 586 target.enclosingClass, arguments.types), | 598 target.enclosingClass, arguments.types), |
| 587 elementAdapter.getConstructor(target), | 599 elementAdapter.getConstructor(target), |
| 588 elementAdapter.getCallStructure(arguments), | 600 elementAdapter.getCallStructure(arguments), |
| 589 _computeArguments(arguments)); | 601 expressions); |
| 590 } | 602 } |
| 591 | 603 |
| 592 @override | 604 @override |
| 593 ConstantExpression visitConstructorInvocation(ir.ConstructorInvocation node) { | 605 ConstantExpression visitConstructorInvocation(ir.ConstructorInvocation node) { |
| 594 return _computeConstructorInvocation(node.target, node.arguments); | 606 return _computeConstructorInvocation(node.target, node.arguments); |
| 595 } | 607 } |
| 596 | 608 |
| 597 @override | 609 @override |
| 598 ConstantExpression visitVariableGet(ir.VariableGet node) { | 610 ConstantExpression visitVariableGet(ir.VariableGet node) { |
| 599 if (node.variable.parent is ir.FunctionNode) { | 611 if (node.variable.parent is ir.FunctionNode) { |
| 600 ir.FunctionNode function = node.variable.parent; | 612 ir.FunctionNode function = node.variable.parent; |
| 601 int index = function.positionalParameters.indexOf(node.variable); | 613 int index = function.positionalParameters.indexOf(node.variable); |
| 602 if (index != -1) { | 614 if (index != -1) { |
| 603 return new PositionalArgumentReference(index); | 615 return new PositionalArgumentReference(index); |
| 604 } else { | 616 } else { |
| 605 assert(function.namedParameters.contains(node.variable)); | 617 assert(function.namedParameters.contains(node.variable)); |
| 606 return new NamedArgumentReference(node.variable.name); | 618 return new NamedArgumentReference(node.variable.name); |
| 607 } | 619 } |
| 620 } else if (node.variable.isConst) { |
| 621 return visit(node.variable.initializer); |
| 608 } | 622 } |
| 609 throw new UnimplementedError( | 623 return defaultExpression(node); |
| 610 'Unimplemented constant expression $node (${node.runtimeType})'); | |
| 611 } | 624 } |
| 612 | 625 |
| 613 @override | 626 @override |
| 614 ConstantExpression visitStaticGet(ir.StaticGet node) { | 627 ConstantExpression visitStaticGet(ir.StaticGet node) { |
| 615 if (node.target is ir.Field) { | 628 ir.Member target = node.target; |
| 629 if (target is ir.Field && target.isConst) { |
| 616 return new FieldConstantExpression(elementAdapter.getField(node.target)); | 630 return new FieldConstantExpression(elementAdapter.getField(node.target)); |
| 617 } else if (node.target is ir.Procedure) { | 631 } else if (node.target is ir.Procedure) { |
| 618 FunctionEntity function = elementAdapter.getMethod(node.target); | 632 FunctionEntity function = elementAdapter.getMethod(node.target); |
| 619 DartType type = elementAdapter.getFunctionType(node.target.function); | 633 DartType type = elementAdapter.getFunctionType(node.target.function); |
| 620 return new FunctionConstantExpression(function, type); | 634 return new FunctionConstantExpression(function, type); |
| 621 } | 635 } |
| 622 throw new UnimplementedError( | 636 return defaultExpression(node); |
| 623 'Unexpected constant expression $node (${node.runtimeType})'); | |
| 624 } | 637 } |
| 625 | 638 |
| 626 @override | 639 @override |
| 627 ConstantExpression visitNullLiteral(ir.NullLiteral node) { | 640 ConstantExpression visitNullLiteral(ir.NullLiteral node) { |
| 628 return new NullConstantExpression(); | 641 return new NullConstantExpression(); |
| 629 } | 642 } |
| 630 | 643 |
| 631 @override | 644 @override |
| 632 ConstantExpression visitBoolLiteral(ir.BoolLiteral node) { | 645 ConstantExpression visitBoolLiteral(ir.BoolLiteral node) { |
| 633 return new BoolConstantExpression(node.value); | 646 return new BoolConstantExpression(node.value); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 648 return new StringConstantExpression(node.value); | 661 return new StringConstantExpression(node.value); |
| 649 } | 662 } |
| 650 | 663 |
| 651 @override | 664 @override |
| 652 ConstantExpression visitSymbolLiteral(ir.SymbolLiteral node) { | 665 ConstantExpression visitSymbolLiteral(ir.SymbolLiteral node) { |
| 653 return new SymbolConstantExpression(node.value); | 666 return new SymbolConstantExpression(node.value); |
| 654 } | 667 } |
| 655 | 668 |
| 656 @override | 669 @override |
| 657 ConstantExpression visitStringConcatenation(ir.StringConcatenation node) { | 670 ConstantExpression visitStringConcatenation(ir.StringConcatenation node) { |
| 658 return new ConcatenateConstantExpression(_computeList(node.expressions)); | 671 List<ConstantExpression> expressions = _computeList(node.expressions); |
| 672 if (expressions == null) return null; |
| 673 return new ConcatenateConstantExpression(expressions); |
| 659 } | 674 } |
| 660 | 675 |
| 661 @override | 676 @override |
| 662 ConstantExpression visitMapLiteral(ir.MapLiteral node) { | 677 ConstantExpression visitMapLiteral(ir.MapLiteral node) { |
| 663 if (!node.isConst) { | 678 if (!node.isConst) { |
| 664 throw new UnimplementedError( | 679 return defaultExpression(node); |
| 665 'Unexpected constant expression $node (${node.runtimeType})'); | |
| 666 } | 680 } |
| 667 DartType keyType = elementAdapter.getDartType(node.keyType); | 681 DartType keyType = elementAdapter.getDartType(node.keyType); |
| 668 DartType valueType = elementAdapter.getDartType(node.valueType); | 682 DartType valueType = elementAdapter.getDartType(node.valueType); |
| 669 List<ConstantExpression> keys = <ConstantExpression>[]; | 683 List<ConstantExpression> keys = <ConstantExpression>[]; |
| 670 List<ConstantExpression> values = <ConstantExpression>[]; | 684 List<ConstantExpression> values = <ConstantExpression>[]; |
| 671 for (ir.MapEntry entry in node.entries) { | 685 for (ir.MapEntry entry in node.entries) { |
| 672 keys.add(visit(entry.key)); | 686 ConstantExpression key = visit(entry.key); |
| 673 values.add(visit(entry.value)); | 687 if (key == null) return null; |
| 688 keys.add(key); |
| 689 ConstantExpression value = visit(entry.value); |
| 690 if (value == null) return null; |
| 691 values.add(value); |
| 674 } | 692 } |
| 675 return new MapConstantExpression( | 693 return new MapConstantExpression( |
| 676 _commonElements.mapType(keyType, valueType), keys, values); | 694 _commonElements.mapType(keyType, valueType), keys, values); |
| 677 } | 695 } |
| 678 | 696 |
| 679 @override | 697 @override |
| 680 ConstantExpression visitListLiteral(ir.ListLiteral node) { | 698 ConstantExpression visitListLiteral(ir.ListLiteral node) { |
| 681 if (!node.isConst) { | 699 if (!node.isConst) { |
| 682 throw new UnimplementedError( | 700 return defaultExpression(node); |
| 683 'Unexpected constant expression $node (${node.runtimeType})'); | |
| 684 } | 701 } |
| 685 DartType elementType = elementAdapter.getDartType(node.typeArgument); | 702 DartType elementType = elementAdapter.getDartType(node.typeArgument); |
| 686 List<ConstantExpression> values = <ConstantExpression>[]; | 703 List<ConstantExpression> values = <ConstantExpression>[]; |
| 687 for (ir.Expression value in node.expressions) { | 704 for (ir.Expression expression in node.expressions) { |
| 688 values.add(visit(value)); | 705 ConstantExpression value = visit(expression); |
| 706 if (value == null) return null; |
| 707 values.add(value); |
| 689 } | 708 } |
| 690 return new ListConstantExpression( | 709 return new ListConstantExpression( |
| 691 _commonElements.listType(elementType), values); | 710 _commonElements.listType(elementType), values); |
| 692 } | 711 } |
| 693 | 712 |
| 694 @override | 713 @override |
| 714 ConstantExpression visitTypeLiteral(ir.TypeLiteral node) { |
| 715 DartType type = elementAdapter.getDartType(node.type); |
| 716 String name; |
| 717 if (type.isDynamic) { |
| 718 name = 'dynamic'; |
| 719 } else if (type is InterfaceType) { |
| 720 name = type.element.name; |
| 721 } else if (type.isFunctionType || type.isTypedef) { |
| 722 // TODO(johnniwinther): Compute a name for the type literal? It is only |
| 723 // used in error messages in the old SSA builder. |
| 724 name = '?'; |
| 725 } else { |
| 726 return defaultExpression(node); |
| 727 } |
| 728 return new TypeConstantExpression(type, name); |
| 729 } |
| 730 |
| 731 @override |
| 732 ConstantExpression visitNot(ir.Not node) { |
| 733 ConstantExpression expression = visit(node.operand); |
| 734 if (expression == null) return null; |
| 735 return new UnaryConstantExpression(UnaryOperator.NOT, expression); |
| 736 } |
| 737 |
| 738 @override |
| 695 ConstantExpression visitConditionalExpression(ir.ConditionalExpression node) { | 739 ConstantExpression visitConditionalExpression(ir.ConditionalExpression node) { |
| 696 ConstantExpression condition = visit(node.condition); | 740 ConstantExpression condition = visit(node.condition); |
| 741 if (condition == null) return null; |
| 697 ConstantExpression trueExp = visit(node.then); | 742 ConstantExpression trueExp = visit(node.then); |
| 743 if (trueExp == null) return null; |
| 698 ConstantExpression falseExp = visit(node.otherwise); | 744 ConstantExpression falseExp = visit(node.otherwise); |
| 745 if (falseExp == null) return null; |
| 699 return new ConditionalConstantExpression(condition, trueExp, falseExp); | 746 return new ConditionalConstantExpression(condition, trueExp, falseExp); |
| 700 } | 747 } |
| 701 | 748 |
| 702 @override | 749 @override |
| 703 ConstantExpression visitPropertyGet(ir.PropertyGet node) { | 750 ConstantExpression visitPropertyGet(ir.PropertyGet node) { |
| 704 if (node.name.name != 'length') { | 751 if (node.name.name != 'length') { |
| 705 throw new UnimplementedError( | 752 throw new UnimplementedError( |
| 706 'Unexpected constant expression $node (${node.runtimeType})'); | 753 'Unexpected constant expression $node (${node.runtimeType})'); |
| 707 } | 754 } |
| 708 ConstantExpression receiver = visit(node.receiver); | 755 ConstantExpression receiver = visit(node.receiver); |
| 756 if (receiver == null) return null; |
| 709 return new StringLengthConstantExpression(receiver); | 757 return new StringLengthConstantExpression(receiver); |
| 710 } | 758 } |
| 711 | 759 |
| 712 @override | 760 @override |
| 713 ConstantExpression visitMethodInvocation(ir.MethodInvocation node) { | 761 ConstantExpression visitMethodInvocation(ir.MethodInvocation node) { |
| 714 // Method invocations are generally not constant expressions but unary | 762 // Method invocations are generally not constant expressions but unary |
| 715 // and binary expressions are encoded as method invocations in kernel. | 763 // and binary expressions are encoded as method invocations in kernel. |
| 716 if (node.arguments.named.isNotEmpty) { | 764 if (node.arguments.named.isNotEmpty) { |
| 717 throw new UnimplementedError( | 765 return defaultExpression(node); |
| 718 'Unexpected constant expression $node (${node.runtimeType})'); | |
| 719 } | 766 } |
| 720 if (node.arguments.positional.length == 0) { | 767 if (node.arguments.positional.length == 0) { |
| 721 UnaryOperator operator; | 768 UnaryOperator operator; |
| 722 if (node.name.name == UnaryOperator.NEGATE.selectorName) { | 769 if (node.name.name == UnaryOperator.NEGATE.selectorName) { |
| 723 operator = UnaryOperator.NEGATE; | 770 operator = UnaryOperator.NEGATE; |
| 724 } else { | 771 } else { |
| 725 operator = UnaryOperator.parse(node.name.name); | 772 operator = UnaryOperator.parse(node.name.name); |
| 726 } | 773 } |
| 727 if (operator != null) { | 774 if (operator != null) { |
| 728 ConstantExpression expression = visit(node.receiver); | 775 ConstantExpression expression = visit(node.receiver); |
| 776 if (expression == null) return null; |
| 729 return new UnaryConstantExpression(operator, expression); | 777 return new UnaryConstantExpression(operator, expression); |
| 730 } | 778 } |
| 731 } | 779 } |
| 732 if (node.arguments.positional.length == 1) { | 780 if (node.arguments.positional.length == 1) { |
| 733 BinaryOperator operator = BinaryOperator.parse(node.name.name); | 781 BinaryOperator operator = BinaryOperator.parse(node.name.name); |
| 734 if (operator != null) { | 782 if (operator != null) { |
| 735 ConstantExpression left = visit(node.receiver); | 783 ConstantExpression left = visit(node.receiver); |
| 784 if (left == null) return null; |
| 736 ConstantExpression right = visit(node.arguments.positional.single); | 785 ConstantExpression right = visit(node.arguments.positional.single); |
| 786 if (right == null) return null; |
| 737 return new BinaryConstantExpression(left, operator, right); | 787 return new BinaryConstantExpression(left, operator, right); |
| 738 } | 788 } |
| 739 } | 789 } |
| 740 throw new UnimplementedError( | 790 return defaultExpression(node); |
| 741 'Unexpected constant expression $node (${node.runtimeType})'); | |
| 742 } | 791 } |
| 743 | 792 |
| 744 @override | 793 @override |
| 745 ConstantExpression visitStaticInvocation(ir.StaticInvocation node) { | 794 ConstantExpression visitStaticInvocation(ir.StaticInvocation node) { |
| 746 MemberEntity member = elementAdapter.getMember(node.target); | 795 MemberEntity member = elementAdapter.getMember(node.target); |
| 747 if (member == _commonElements.identicalFunction) { | 796 if (member == _commonElements.identicalFunction) { |
| 748 if (node.arguments.positional.length == 2 && | 797 if (node.arguments.positional.length == 2 && |
| 749 node.arguments.named.isEmpty) { | 798 node.arguments.named.isEmpty) { |
| 750 ConstantExpression left = visit(node.arguments.positional[0]); | 799 ConstantExpression left = visit(node.arguments.positional[0]); |
| 800 if (left == null) return null; |
| 751 ConstantExpression right = visit(node.arguments.positional[1]); | 801 ConstantExpression right = visit(node.arguments.positional[1]); |
| 802 if (right == null) return null; |
| 752 return new IdenticalConstantExpression(left, right); | 803 return new IdenticalConstantExpression(left, right); |
| 753 } | 804 } |
| 754 } else if (member.name == 'fromEnvironment' && | 805 } else if (member.name == 'fromEnvironment' && |
| 755 node.arguments.positional.length == 1) { | 806 node.arguments.positional.length == 1) { |
| 756 ConstantExpression name = visit(node.arguments.positional.single); | 807 ConstantExpression name = visit(node.arguments.positional.single); |
| 808 if (name == null) return null; |
| 757 ConstantExpression defaultValue; | 809 ConstantExpression defaultValue; |
| 758 if (node.arguments.named.length == 1) { | 810 if (node.arguments.named.length == 1) { |
| 759 if (node.arguments.named.single.name != 'defaultValue') { | 811 if (node.arguments.named.single.name != 'defaultValue') { |
| 760 throw new UnimplementedError( | 812 return defaultExpression(node); |
| 761 'Unexpected constant expression $node (${node.runtimeType})'); | |
| 762 } | 813 } |
| 763 defaultValue = visit(node.arguments.named.single.value); | 814 defaultValue = visit(node.arguments.named.single.value); |
| 815 if (defaultValue == null) return null; |
| 764 } | 816 } |
| 765 if (member.enclosingClass == _commonElements.boolClass) { | 817 if (member.enclosingClass == _commonElements.boolClass) { |
| 766 return new BoolFromEnvironmentConstantExpression(name, defaultValue); | 818 return new BoolFromEnvironmentConstantExpression(name, defaultValue); |
| 767 } else if (member.enclosingClass == _commonElements.intClass) { | 819 } else if (member.enclosingClass == _commonElements.intClass) { |
| 768 return new IntFromEnvironmentConstantExpression(name, defaultValue); | 820 return new IntFromEnvironmentConstantExpression(name, defaultValue); |
| 769 } else if (member.enclosingClass == _commonElements.stringClass) { | 821 } else if (member.enclosingClass == _commonElements.stringClass) { |
| 770 return new StringFromEnvironmentConstantExpression(name, defaultValue); | 822 return new StringFromEnvironmentConstantExpression(name, defaultValue); |
| 771 } | 823 } |
| 772 } | 824 } |
| 773 throw new UnimplementedError( | 825 return defaultExpression(node); |
| 774 'Unexpected constant expression $node (${node.runtimeType})'); | |
| 775 } | 826 } |
| 776 | 827 |
| 777 @override | 828 @override |
| 778 ConstantExpression visitLogicalExpression(ir.LogicalExpression node) { | 829 ConstantExpression visitLogicalExpression(ir.LogicalExpression node) { |
| 779 BinaryOperator operator = BinaryOperator.parse(node.operator); | 830 BinaryOperator operator = BinaryOperator.parse(node.operator); |
| 780 if (operator != null) { | 831 if (operator != null) { |
| 781 ConstantExpression left = visit(node.left); | 832 ConstantExpression left = visit(node.left); |
| 833 if (left == null) return null; |
| 782 ConstantExpression right = visit(node.right); | 834 ConstantExpression right = visit(node.right); |
| 835 if (right == null) return null; |
| 783 return new BinaryConstantExpression(left, operator, right); | 836 return new BinaryConstantExpression(left, operator, right); |
| 784 } | 837 } |
| 785 throw new UnimplementedError( | 838 return defaultExpression(node); |
| 786 'Unexpected constant expression $node (${node.runtimeType})'); | |
| 787 } | 839 } |
| 788 | 840 |
| 789 @override | 841 @override |
| 790 ConstantExpression visitLet(ir.Let node) { | 842 ConstantExpression visitLet(ir.Let node) { |
| 791 ir.Expression body = node.body; | 843 ir.Expression body = node.body; |
| 792 if (body is ir.ConditionalExpression) { | 844 if (body is ir.ConditionalExpression) { |
| 793 ir.Expression condition = body.condition; | 845 ir.Expression condition = body.condition; |
| 794 if (condition is ir.MethodInvocation) { | 846 if (condition is ir.MethodInvocation) { |
| 795 ir.Expression receiver = condition.receiver; | 847 ir.Expression receiver = condition.receiver; |
| 796 ir.Expression otherwise = body.otherwise; | 848 ir.Expression otherwise = body.otherwise; |
| 797 if (condition.name.name == BinaryOperator.EQ.name && | 849 if (condition.name.name == BinaryOperator.EQ.name && |
| 798 receiver is ir.VariableGet && | 850 receiver is ir.VariableGet && |
| 799 condition.arguments.positional.single is ir.NullLiteral && | 851 condition.arguments.positional.single is ir.NullLiteral && |
| 800 otherwise is ir.VariableGet) { | 852 otherwise is ir.VariableGet) { |
| 801 if (receiver.variable == node.variable && | 853 if (receiver.variable == node.variable && |
| 802 otherwise.variable == node.variable) { | 854 otherwise.variable == node.variable) { |
| 803 // We have <left> ?? <right> encoded as: | 855 // We have <left> ?? <right> encoded as: |
| 804 // let #1 = <left> in #1 == null ? <right> : #1 | 856 // let #1 = <left> in #1 == null ? <right> : #1 |
| 805 ConstantExpression left = visit(node.variable.initializer); | 857 ConstantExpression left = visit(node.variable.initializer); |
| 858 if (left == null) return null; |
| 806 ConstantExpression right = visit(body.then); | 859 ConstantExpression right = visit(body.then); |
| 860 if (right == null) return null; |
| 807 // TODO(johnniwinther): Remove [IF_NULL] binary constant expression | 861 // TODO(johnniwinther): Remove [IF_NULL] binary constant expression |
| 808 // when the resolver is removed; then we no longer need the | 862 // when the resolver is removed; then we no longer need the |
| 809 // expressions to be structurally equivalence for equivalence | 863 // expressions to be structurally equivalence for equivalence |
| 810 // testing. | 864 // testing. |
| 811 return new BinaryConstantExpression( | 865 return new BinaryConstantExpression( |
| 812 left, BinaryOperator.IF_NULL, right); | 866 left, BinaryOperator.IF_NULL, right); |
| 813 } | 867 } |
| 814 } | 868 } |
| 815 } | 869 } |
| 816 } | 870 } |
| 817 throw new UnimplementedError( | 871 return defaultExpression(node); |
| 818 'Unexpected constant expression $node (${node.runtimeType})'); | |
| 819 } | 872 } |
| 820 | 873 |
| 821 /// Compute the [ConstantConstructor] corresponding to the const constructor | 874 /// Compute the [ConstantConstructor] corresponding to the const constructor |
| 822 /// [node]. | 875 /// [node]. |
| 823 ConstantConstructor computeConstantConstructor(ir.Constructor node) { | 876 ConstantConstructor computeConstantConstructor(ir.Constructor node) { |
| 824 assert(node.isConst); | 877 assert(node.isConst); |
| 825 ir.Class cls = node.enclosingClass; | 878 ir.Class cls = node.enclosingClass; |
| 826 InterfaceType type = elementAdapter.elementEnvironment | 879 InterfaceType type = elementAdapter.elementEnvironment |
| 827 .getThisType(elementAdapter.getClass(cls)); | 880 .getThisType(elementAdapter.getClass(cls)); |
| 828 | 881 |
| 829 Map<dynamic, ConstantExpression> defaultValues = | 882 Map<dynamic, ConstantExpression> defaultValues = |
| 830 <dynamic, ConstantExpression>{}; | 883 <dynamic, ConstantExpression>{}; |
| 831 int parameterIndex = 0; | 884 int parameterIndex = 0; |
| 832 node.function.positionalParameters | 885 for (ir.VariableDeclaration parameter |
| 833 .forEach((ir.VariableDeclaration parameter) { | 886 in node.function.positionalParameters) { |
| 834 if (parameterIndex >= node.function.requiredParameterCount) { | 887 if (parameterIndex >= node.function.requiredParameterCount) { |
| 888 ConstantExpression defaultValue; |
| 835 if (parameter.initializer != null) { | 889 if (parameter.initializer != null) { |
| 836 defaultValues[parameterIndex] = parameter.initializer.accept(this); | 890 defaultValue = parameter.initializer.accept(this); |
| 837 } else { | 891 } else { |
| 838 defaultValues[parameterIndex] = new NullConstantExpression(); | 892 defaultValue = new NullConstantExpression(); |
| 839 } | 893 } |
| 894 if (defaultValue == null) return null; |
| 895 defaultValues[parameterIndex] = defaultValue; |
| 840 } | 896 } |
| 841 parameterIndex++; | 897 parameterIndex++; |
| 842 }); | 898 } |
| 843 node.function.namedParameters.forEach((ir.VariableDeclaration parameter) { | 899 for (ir.VariableDeclaration parameter in node.function.namedParameters) { |
| 844 defaultValues[parameter.name] = parameter.initializer.accept(this); | 900 ConstantExpression defaultValue = parameter.initializer.accept(this); |
| 845 }); | 901 if (defaultValue == null) return null; |
| 902 defaultValues[parameter.name] = defaultValue; |
| 903 } |
| 846 | 904 |
| 847 bool isRedirecting = node.initializers.length == 1 && | 905 bool isRedirecting = node.initializers.length == 1 && |
| 848 node.initializers.single is ir.RedirectingInitializer; | 906 node.initializers.single is ir.RedirectingInitializer; |
| 849 | 907 |
| 850 Map<FieldEntity, ConstantExpression> fieldMap = | 908 Map<FieldEntity, ConstantExpression> fieldMap = |
| 851 <FieldEntity, ConstantExpression>{}; | 909 <FieldEntity, ConstantExpression>{}; |
| 852 | 910 |
| 853 void registerField(ir.Field field, ConstantExpression constant) { | 911 void registerField(ir.Field field, ConstantExpression constant) { |
| 854 fieldMap[elementAdapter.getField(field)] = constant; | 912 fieldMap[elementAdapter.getField(field)] = constant; |
| 855 } | 913 } |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 950 /// Call to notify that [member] is no longer being inlined. | 1008 /// Call to notify that [member] is no longer being inlined. |
| 951 void leaveInlinedMember(MemberEntity member); | 1009 void leaveInlinedMember(MemberEntity member); |
| 952 | 1010 |
| 953 /// Returns the [Local] for [node]. | 1011 /// Returns the [Local] for [node]. |
| 954 Local getLocal(ir.VariableDeclaration node); | 1012 Local getLocal(ir.VariableDeclaration node); |
| 955 | 1013 |
| 956 /// Returns the [JumpTarget] for the branch in [node]. | 1014 /// Returns the [JumpTarget] for the branch in [node]. |
| 957 // TODO(johnniwinther): Split this by kind of [node]? | 1015 // TODO(johnniwinther): Split this by kind of [node]? |
| 958 JumpTarget getJumpTarget(ir.TreeNode node, {bool isContinueTarget: false}); | 1016 JumpTarget getJumpTarget(ir.TreeNode node, {bool isContinueTarget: false}); |
| 959 } | 1017 } |
| OLD | NEW |