| 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'; |
| 11 import '../constants/values.dart'; | 11 import '../constants/values.dart'; |
| 12 import '../common_elements.dart'; | 12 import '../common_elements.dart'; |
| 13 import '../elements/elements.dart'; | 13 import '../elements/elements.dart'; |
| 14 import '../elements/entities.dart'; | 14 import '../elements/entities.dart'; |
| 15 import '../elements/types.dart'; | 15 import '../elements/types.dart'; |
| 16 import '../js_backend/backend.dart' show JavaScriptBackend; | 16 import '../js_backend/backend.dart' show JavaScriptBackend; |
| 17 import '../native/native.dart' as native; | 17 import '../native/native.dart' as native; |
| 18 import '../resolution/operators.dart'; |
| 18 import '../universe/call_structure.dart'; | 19 import '../universe/call_structure.dart'; |
| 19 import '../universe/selector.dart'; | 20 import '../universe/selector.dart'; |
| 20 import 'kernel_debug.dart'; | 21 import 'kernel_debug.dart'; |
| 21 | 22 |
| 22 /// Interface that translates between Kernel IR nodes and entities. | 23 /// Interface that translates between Kernel IR nodes and entities. |
| 23 abstract class KernelElementAdapter { | 24 abstract class KernelElementAdapter { |
| 24 /// Access to the commonly used elements and types. | 25 /// Access to the commonly used elements and types. |
| 25 CommonElements get commonElements; | 26 CommonElements get commonElements; |
| 26 | 27 |
| 27 /// [ElementEnvironment] for library, class and member lookup. | 28 /// [ElementEnvironment] for library, class and member lookup. |
| (...skipping 430 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 458 sb.write(value); | 459 sb.write(value); |
| 459 } | 460 } |
| 460 return sb.toString(); | 461 return sb.toString(); |
| 461 } | 462 } |
| 462 } | 463 } |
| 463 | 464 |
| 464 /// Visitor that converts a kernel constant expression into a | 465 /// Visitor that converts a kernel constant expression into a |
| 465 /// [ConstantExpression]. | 466 /// [ConstantExpression]. |
| 466 class Constantifier extends ir.ExpressionVisitor<ConstantExpression> { | 467 class Constantifier extends ir.ExpressionVisitor<ConstantExpression> { |
| 467 final bool requireConstant; | 468 final bool requireConstant; |
| 468 final KernelElementAdapter elementAdapter; | 469 final KernelElementAdapterMixin elementAdapter; |
| 469 | 470 |
| 470 Constantifier(this.elementAdapter, {this.requireConstant: true}); | 471 Constantifier(this.elementAdapter, {this.requireConstant: true}); |
| 471 | 472 |
| 473 CommonElements get _commonElements => elementAdapter.commonElements; |
| 474 |
| 472 ConstantExpression visit(ir.Expression node) { | 475 ConstantExpression visit(ir.Expression node) { |
| 473 ConstantExpression constant = node.accept(this); | 476 ConstantExpression constant = node.accept(this); |
| 474 if (constant == null && requireConstant) { | 477 if (constant == null && requireConstant) { |
| 475 throw new UnsupportedError( | 478 throw new UnsupportedError( |
| 476 "No constant computed for $node (${node.runtimeType})"); | 479 "No constant computed for $node (${node.runtimeType})"); |
| 477 } | 480 } |
| 478 return constant; | 481 return constant; |
| 479 } | 482 } |
| 480 | 483 |
| 481 ConstantExpression defaultExpression(ir.Expression node) { | 484 ConstantExpression defaultExpression(ir.Expression node) { |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 534 assert(function.namedParameters.contains(node.variable)); | 537 assert(function.namedParameters.contains(node.variable)); |
| 535 return new NamedArgumentReference(node.variable.name); | 538 return new NamedArgumentReference(node.variable.name); |
| 536 } | 539 } |
| 537 } | 540 } |
| 538 throw new UnimplementedError( | 541 throw new UnimplementedError( |
| 539 'Unimplemented constant expression $node (${node.runtimeType})'); | 542 'Unimplemented constant expression $node (${node.runtimeType})'); |
| 540 } | 543 } |
| 541 | 544 |
| 542 @override | 545 @override |
| 543 ConstantExpression visitStaticGet(ir.StaticGet node) { | 546 ConstantExpression visitStaticGet(ir.StaticGet node) { |
| 544 return new FieldConstantExpression(elementAdapter.getField(node.target)); | 547 if (node.target is ir.Field) { |
| 548 return new FieldConstantExpression(elementAdapter.getField(node.target)); |
| 549 } else if (node.target is ir.Procedure) { |
| 550 FunctionEntity function = elementAdapter.getMethod(node.target); |
| 551 DartType type = elementAdapter.getFunctionType(node.target.function); |
| 552 return new FunctionConstantExpression(function, type); |
| 553 } |
| 554 throw new UnimplementedError( |
| 555 'Unexpected constant expression $node (${node.runtimeType})'); |
| 545 } | 556 } |
| 546 | 557 |
| 547 @override | 558 @override |
| 559 ConstantExpression visitNullLiteral(ir.NullLiteral node) { |
| 560 return new NullConstantExpression(); |
| 561 } |
| 562 |
| 563 @override |
| 564 ConstantExpression visitBoolLiteral(ir.BoolLiteral node) { |
| 565 return new BoolConstantExpression(node.value); |
| 566 } |
| 567 |
| 568 @override |
| 569 ConstantExpression visitIntLiteral(ir.IntLiteral node) { |
| 570 return new IntConstantExpression(node.value); |
| 571 } |
| 572 |
| 573 @override |
| 574 ConstantExpression visitDoubleLiteral(ir.DoubleLiteral node) { |
| 575 return new DoubleConstantExpression(node.value); |
| 576 } |
| 577 |
| 578 @override |
| 548 ConstantExpression visitStringLiteral(ir.StringLiteral node) { | 579 ConstantExpression visitStringLiteral(ir.StringLiteral node) { |
| 549 return new StringConstantExpression(node.value); | 580 return new StringConstantExpression(node.value); |
| 550 } | 581 } |
| 551 | 582 |
| 552 @override | 583 @override |
| 584 ConstantExpression visitSymbolLiteral(ir.SymbolLiteral node) { |
| 585 return new SymbolConstantExpression(node.value); |
| 586 } |
| 587 |
| 588 @override |
| 553 ConstantExpression visitStringConcatenation(ir.StringConcatenation node) { | 589 ConstantExpression visitStringConcatenation(ir.StringConcatenation node) { |
| 554 return new ConcatenateConstantExpression(_computeList(node.expressions)); | 590 return new ConcatenateConstantExpression(_computeList(node.expressions)); |
| 555 } | 591 } |
| 556 | 592 |
| 593 @override |
| 594 ConstantExpression visitMapLiteral(ir.MapLiteral node) { |
| 595 if (!node.isConst) { |
| 596 throw new UnimplementedError( |
| 597 'Unexpected constant expression $node (${node.runtimeType})'); |
| 598 } |
| 599 DartType keyType = elementAdapter.getDartType(node.keyType); |
| 600 DartType valueType = elementAdapter.getDartType(node.valueType); |
| 601 List<ConstantExpression> keys = <ConstantExpression>[]; |
| 602 List<ConstantExpression> values = <ConstantExpression>[]; |
| 603 for (ir.MapEntry entry in node.entries) { |
| 604 keys.add(visit(entry.key)); |
| 605 values.add(visit(entry.value)); |
| 606 } |
| 607 return new MapConstantExpression( |
| 608 _commonElements.mapType(keyType, valueType), keys, values); |
| 609 } |
| 610 |
| 611 @override |
| 612 ConstantExpression visitListLiteral(ir.ListLiteral node) { |
| 613 if (!node.isConst) { |
| 614 throw new UnimplementedError( |
| 615 'Unexpected constant expression $node (${node.runtimeType})'); |
| 616 } |
| 617 DartType elementType = elementAdapter.getDartType(node.typeArgument); |
| 618 List<ConstantExpression> values = <ConstantExpression>[]; |
| 619 for (ir.Expression value in node.expressions) { |
| 620 values.add(visit(value)); |
| 621 } |
| 622 return new ListConstantExpression( |
| 623 _commonElements.listType(elementType), values); |
| 624 } |
| 625 |
| 626 @override |
| 627 ConstantExpression visitConditionalExpression(ir.ConditionalExpression node) { |
| 628 ConstantExpression condition = visit(node.condition); |
| 629 ConstantExpression trueExp = visit(node.then); |
| 630 ConstantExpression falseExp = visit(node.otherwise); |
| 631 return new ConditionalConstantExpression(condition, trueExp, falseExp); |
| 632 } |
| 633 |
| 634 @override |
| 635 ConstantExpression visitPropertyGet(ir.PropertyGet node) { |
| 636 if (node.name.name != 'length') { |
| 637 throw new UnimplementedError( |
| 638 'Unexpected constant expression $node (${node.runtimeType})'); |
| 639 } |
| 640 ConstantExpression receiver = visit(node.receiver); |
| 641 return new StringLengthConstantExpression(receiver); |
| 642 } |
| 643 |
| 644 @override |
| 645 ConstantExpression visitMethodInvocation(ir.MethodInvocation node) { |
| 646 // Method invocations are generally not constant expressions but unary |
| 647 // and binary expressions are encoded as method invocations in kernel. |
| 648 if (node.arguments.named.isNotEmpty) { |
| 649 throw new UnimplementedError( |
| 650 'Unexpected constant expression $node (${node.runtimeType})'); |
| 651 } |
| 652 if (node.arguments.positional.length == 0) { |
| 653 UnaryOperator operator; |
| 654 if (node.name.name == UnaryOperator.NEGATE.selectorName) { |
| 655 operator = UnaryOperator.NEGATE; |
| 656 } else { |
| 657 operator = UnaryOperator.parse(node.name.name); |
| 658 } |
| 659 if (operator != null) { |
| 660 ConstantExpression expression = visit(node.receiver); |
| 661 return new UnaryConstantExpression(operator, expression); |
| 662 } |
| 663 } |
| 664 if (node.arguments.positional.length == 1) { |
| 665 BinaryOperator operator = BinaryOperator.parse(node.name.name); |
| 666 if (operator != null) { |
| 667 ConstantExpression left = visit(node.receiver); |
| 668 ConstantExpression right = visit(node.arguments.positional.single); |
| 669 return new BinaryConstantExpression(left, operator, right); |
| 670 } |
| 671 } |
| 672 throw new UnimplementedError( |
| 673 'Unexpected constant expression $node (${node.runtimeType})'); |
| 674 } |
| 675 |
| 676 @override |
| 677 ConstantExpression visitStaticInvocation(ir.StaticInvocation node) { |
| 678 MemberEntity member = elementAdapter.getMember(node.target); |
| 679 if (member == _commonElements.identicalFunction) { |
| 680 if (node.arguments.positional.length == 2 && |
| 681 node.arguments.named.isEmpty) { |
| 682 ConstantExpression left = visit(node.arguments.positional[0]); |
| 683 ConstantExpression right = visit(node.arguments.positional[1]); |
| 684 return new IdenticalConstantExpression(left, right); |
| 685 } |
| 686 } else if (member.name == 'fromEnvironment' && |
| 687 node.arguments.positional.length == 1) { |
| 688 ConstantExpression name = visit(node.arguments.positional.single); |
| 689 ConstantExpression defaultValue; |
| 690 if (node.arguments.named.length == 1) { |
| 691 if (node.arguments.named.single.name != 'defaultValue') { |
| 692 throw new UnimplementedError( |
| 693 'Unexpected constant expression $node (${node.runtimeType})'); |
| 694 } |
| 695 defaultValue = visit(node.arguments.named.single.value); |
| 696 } |
| 697 if (member.enclosingClass == _commonElements.boolClass) { |
| 698 return new BoolFromEnvironmentConstantExpression(name, defaultValue); |
| 699 } else if (member.enclosingClass == _commonElements.intClass) { |
| 700 return new IntFromEnvironmentConstantExpression(name, defaultValue); |
| 701 } else if (member.enclosingClass == _commonElements.stringClass) { |
| 702 return new StringFromEnvironmentConstantExpression(name, defaultValue); |
| 703 } |
| 704 } |
| 705 throw new UnimplementedError( |
| 706 'Unexpected constant expression $node (${node.runtimeType})'); |
| 707 } |
| 708 |
| 709 @override |
| 710 ConstantExpression visitLogicalExpression(ir.LogicalExpression node) { |
| 711 BinaryOperator operator = BinaryOperator.parse(node.operator); |
| 712 if (operator != null) { |
| 713 ConstantExpression left = visit(node.left); |
| 714 ConstantExpression right = visit(node.right); |
| 715 return new BinaryConstantExpression(left, operator, right); |
| 716 } |
| 717 throw new UnimplementedError( |
| 718 'Unexpected constant expression $node (${node.runtimeType})'); |
| 719 } |
| 720 |
| 557 /// Compute the [ConstantConstructor] corresponding to the const constructor | 721 /// Compute the [ConstantConstructor] corresponding to the const constructor |
| 558 /// [node]. | 722 /// [node]. |
| 559 ConstantConstructor computeConstantConstructor(ir.Constructor node) { | 723 ConstantConstructor computeConstantConstructor(ir.Constructor node) { |
| 560 assert(node.isConst); | 724 assert(node.isConst); |
| 561 ir.Class cls = node.enclosingClass; | 725 ir.Class cls = node.enclosingClass; |
| 562 InterfaceType type = elementAdapter.elementEnvironment | 726 InterfaceType type = elementAdapter.elementEnvironment |
| 563 .getThisType(elementAdapter.getClass(cls)); | 727 .getThisType(elementAdapter.getClass(cls)); |
| 564 | 728 |
| 565 Map<dynamic, ConstantExpression> defaultValues = | 729 Map<dynamic, ConstantExpression> defaultValues = |
| 566 <dynamic, ConstantExpression>{}; | 730 <dynamic, ConstantExpression>{}; |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 615 } | 779 } |
| 616 if (isRedirecting) { | 780 if (isRedirecting) { |
| 617 return new RedirectingGenerativeConstantConstructor( | 781 return new RedirectingGenerativeConstantConstructor( |
| 618 defaultValues, superConstructorInvocation); | 782 defaultValues, superConstructorInvocation); |
| 619 } else { | 783 } else { |
| 620 return new GenerativeConstantConstructor( | 784 return new GenerativeConstantConstructor( |
| 621 type, defaultValues, fieldMap, superConstructorInvocation); | 785 type, defaultValues, fieldMap, superConstructorInvocation); |
| 622 } | 786 } |
| 623 } | 787 } |
| 624 } | 788 } |
| OLD | NEW |