OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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 /** | 5 /** |
6 * The [ConstantHandler] keeps track of compile-time constants, | 6 * The [ConstantHandler] keeps track of compile-time constants, |
7 * initializations of global and static fields, and default values of | 7 * initializations of global and static fields, and default values of |
8 * optional parameters. | 8 * optional parameters. |
9 */ | 9 */ |
10 class ConstantHandler extends CompilerTask { | 10 class ConstantHandler extends CompilerTask { |
(...skipping 512 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
523 return folded; | 523 return folded; |
524 } | 524 } |
525 return signalNotCompileTimeConstant(send); | 525 return signalNotCompileTimeConstant(send); |
526 } | 526 } |
527 | 527 |
528 Constant visitSendSet(SendSet node) { | 528 Constant visitSendSet(SendSet node) { |
529 return signalNotCompileTimeConstant(node); | 529 return signalNotCompileTimeConstant(node); |
530 } | 530 } |
531 | 531 |
532 /** Returns the list of constants that are passed to the static function. */ | 532 /** Returns the list of constants that are passed to the static function. */ |
533 List<Constant> evaluateArgumentsToConstructor(Selector selector, | 533 List<Constant> evaluateArgumentsToConstructor(Node node, |
| 534 Selector selector, |
534 Link<Node> arguments, | 535 Link<Node> arguments, |
535 FunctionElement target) { | 536 FunctionElement target) { |
536 List<Constant> compiledArguments = <Constant>[]; | 537 List<Constant> compiledArguments = <Constant>[]; |
537 | 538 |
538 Function compileArgument = evaluateConstant; | 539 Function compileArgument = evaluateConstant; |
539 Function compileConstant = compiler.compileConstant; | 540 Function compileConstant = compiler.compileConstant; |
540 bool succeeded = selector.addArgumentsToList(arguments, | 541 bool succeeded = selector.addArgumentsToList(arguments, |
541 compiledArguments, | 542 compiledArguments, |
542 target, | 543 target, |
543 compileArgument, | 544 compileArgument, |
544 compileConstant, | 545 compileConstant, |
545 compiler); | 546 compiler); |
546 assert(succeeded); | 547 if (!succeeded) { |
| 548 MessageKind kind = MessageKind.INVALID_ARGUMENTS; |
| 549 compiler.reportError(node, |
| 550 new CompileTimeConstantError(kind, [target.name.slowToString()])); |
| 551 } |
547 return compiledArguments; | 552 return compiledArguments; |
548 } | 553 } |
549 | 554 |
550 Constant visitNewExpression(NewExpression node) { | 555 Constant visitNewExpression(NewExpression node) { |
551 if (!node.isConst()) { | 556 if (!node.isConst()) { |
552 return signalNotCompileTimeConstant(node); | 557 return signalNotCompileTimeConstant(node); |
553 } | 558 } |
554 | 559 |
555 Send send = node.send; | 560 Send send = node.send; |
556 FunctionElement constructor = elements[send]; | 561 FunctionElement constructor = elements[send]; |
557 ClassElement classElement = constructor.getEnclosingClass(); | 562 ClassElement classElement = constructor.getEnclosingClass(); |
558 if (classElement.isInterface()) { | 563 if (classElement.isInterface()) { |
559 compiler.resolver.resolveMethodElement(constructor); | 564 compiler.resolver.resolveMethodElement(constructor); |
560 constructor = constructor.defaultImplementation; | 565 constructor = constructor.defaultImplementation; |
561 classElement = constructor.getEnclosingClass(); | 566 classElement = constructor.getEnclosingClass(); |
562 } | 567 } |
563 | 568 |
564 Selector selector = elements.getSelector(send); | 569 Selector selector = elements.getSelector(send); |
565 List<Constant> arguments = | 570 List<Constant> arguments = evaluateArgumentsToConstructor( |
566 evaluateArgumentsToConstructor(selector, send.arguments, constructor); | 571 node, selector, send.arguments, constructor); |
567 ConstructorEvaluator evaluator = | 572 ConstructorEvaluator evaluator = |
568 new ConstructorEvaluator(constructor, constantSystem, compiler); | 573 new ConstructorEvaluator(constructor, constantSystem, compiler); |
569 evaluator.evaluateConstructorFieldValues(arguments); | 574 evaluator.evaluateConstructorFieldValues(arguments); |
570 List<Constant> jsNewArguments = evaluator.buildJsNewArguments(classElement); | 575 List<Constant> jsNewArguments = evaluator.buildJsNewArguments(classElement); |
571 | 576 |
572 compiler.enqueuer.codegen.registerInstantiatedClass(classElement); | 577 compiler.enqueuer.codegen.registerInstantiatedClass(classElement); |
573 // TODO(floitsch): take generic types into account. | 578 // TODO(floitsch): take generic types into account. |
574 DartType type = classElement.computeType(compiler); | 579 DartType type = classElement.computeType(compiler); |
575 Constant constant = new ConstructedConstant(type, jsNewArguments); | 580 Constant constant = new ConstructedConstant(type, jsNewArguments); |
576 compiler.constantHandler.registerCompileTimeConstant(constant); | 581 compiler.constantHandler.registerCompileTimeConstant(constant); |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
675 Node node = parameter.parseNode(compiler); | 680 Node node = parameter.parseNode(compiler); |
676 potentiallyCheckType(node, parameter, argument); | 681 potentiallyCheckType(node, parameter, argument); |
677 definitions[parameter] = argument; | 682 definitions[parameter] = argument; |
678 if (parameter.kind == ElementKind.FIELD_PARAMETER) { | 683 if (parameter.kind == ElementKind.FIELD_PARAMETER) { |
679 FieldParameterElement fieldParameterElement = parameter; | 684 FieldParameterElement fieldParameterElement = parameter; |
680 updateFieldValue(node, fieldParameterElement.fieldElement, argument); | 685 updateFieldValue(node, fieldParameterElement.fieldElement, argument); |
681 } | 686 } |
682 }); | 687 }); |
683 } | 688 } |
684 | 689 |
685 void evaluateSuperOrRedirectSend(Selector selector, | 690 void evaluateSuperOrRedirectSend(Node currentNode, |
| 691 Selector selector, |
686 Link<Node> arguments, | 692 Link<Node> arguments, |
687 FunctionElement targetConstructor) { | 693 FunctionElement targetConstructor) { |
688 List<Constant> compiledArguments = | 694 List<Constant> compiledArguments = evaluateArgumentsToConstructor( |
689 evaluateArgumentsToConstructor(selector, arguments, targetConstructor); | 695 currentNode, selector, arguments, targetConstructor); |
690 | 696 |
691 ConstructorEvaluator evaluator = new ConstructorEvaluator( | 697 ConstructorEvaluator evaluator = new ConstructorEvaluator( |
692 targetConstructor, constantSystem, compiler); | 698 targetConstructor, constantSystem, compiler); |
693 evaluator.evaluateConstructorFieldValues(compiledArguments); | 699 evaluator.evaluateConstructorFieldValues(compiledArguments); |
694 // Copy over the fieldValues from the super/redirect-constructor. | 700 // Copy over the fieldValues from the super/redirect-constructor. |
695 // No need to go through [updateFieldValue] because the | 701 // No need to go through [updateFieldValue] because the |
696 // assignments have already been checked in checked mode. | 702 // assignments have already been checked in checked mode. |
697 evaluator.fieldValues.forEach((key, value) => fieldValues[key] = value); | 703 evaluator.fieldValues.forEach((key, value) => fieldValues[key] = value); |
698 } | 704 } |
699 | 705 |
(...skipping 11 matching lines...) Expand all Loading... |
711 for (Link<Node> link = initializerList.nodes; | 717 for (Link<Node> link = initializerList.nodes; |
712 !link.isEmpty(); | 718 !link.isEmpty(); |
713 link = link.tail) { | 719 link = link.tail) { |
714 assert(link.head is Send); | 720 assert(link.head is Send); |
715 if (link.head is !SendSet) { | 721 if (link.head is !SendSet) { |
716 // A super initializer or constructor redirection. | 722 // A super initializer or constructor redirection. |
717 Send call = link.head; | 723 Send call = link.head; |
718 FunctionElement targetConstructor = elements[call]; | 724 FunctionElement targetConstructor = elements[call]; |
719 Selector selector = elements.getSelector(call); | 725 Selector selector = elements.getSelector(call); |
720 Link<Node> arguments = call.arguments; | 726 Link<Node> arguments = call.arguments; |
721 evaluateSuperOrRedirectSend(selector, arguments, targetConstructor); | 727 evaluateSuperOrRedirectSend( |
| 728 call, selector, arguments, targetConstructor); |
722 foundSuperOrRedirect = true; | 729 foundSuperOrRedirect = true; |
723 } else { | 730 } else { |
724 // A field initializer. | 731 // A field initializer. |
725 SendSet init = link.head; | 732 SendSet init = link.head; |
726 Link<Node> initArguments = init.arguments; | 733 Link<Node> initArguments = init.arguments; |
727 assert(!initArguments.isEmpty() && initArguments.tail.isEmpty()); | 734 assert(!initArguments.isEmpty() && initArguments.tail.isEmpty()); |
728 Constant fieldValue = evaluate(initArguments.head); | 735 Constant fieldValue = evaluate(initArguments.head); |
729 updateFieldValue(init, elements[init], fieldValue); | 736 updateFieldValue(init, elements[init], fieldValue); |
730 } | 737 } |
731 } | 738 } |
(...skipping 10 matching lines...) Expand all Loading... |
742 FunctionElement targetConstructor = | 749 FunctionElement targetConstructor = |
743 superClass.lookupConstructor(superClass.name); | 750 superClass.lookupConstructor(superClass.name); |
744 if (targetConstructor === null) { | 751 if (targetConstructor === null) { |
745 compiler.internalError("no default constructor available", | 752 compiler.internalError("no default constructor available", |
746 node: functionNode); | 753 node: functionNode); |
747 } | 754 } |
748 | 755 |
749 Selector selector = new Selector.call(superClass.name, | 756 Selector selector = new Selector.call(superClass.name, |
750 enclosingClass.getLibrary(), | 757 enclosingClass.getLibrary(), |
751 0); | 758 0); |
752 evaluateSuperOrRedirectSend(selector, | 759 evaluateSuperOrRedirectSend(functionNode, |
| 760 selector, |
753 const EmptyLink<Node>(), | 761 const EmptyLink<Node>(), |
754 targetConstructor); | 762 targetConstructor); |
755 } | 763 } |
756 } | 764 } |
757 } | 765 } |
758 | 766 |
759 /** | 767 /** |
760 * Simulates the execution of the [constructor] with the given | 768 * Simulates the execution of the [constructor] with the given |
761 * [arguments] to obtain the field values that need to be passed to the | 769 * [arguments] to obtain the field values that need to be passed to the |
762 * native JavaScript constructor. | 770 * native JavaScript constructor. |
(...skipping 14 matching lines...) Expand all Loading... |
777 Constant fieldValue = fieldValues[field]; | 785 Constant fieldValue = fieldValues[field]; |
778 if (fieldValue === null) { | 786 if (fieldValue === null) { |
779 // Use the default value. | 787 // Use the default value. |
780 fieldValue = compiler.compileConstant(field); | 788 fieldValue = compiler.compileConstant(field); |
781 } | 789 } |
782 jsNewArguments.add(fieldValue); | 790 jsNewArguments.add(fieldValue); |
783 }); | 791 }); |
784 return jsNewArguments; | 792 return jsNewArguments; |
785 } | 793 } |
786 } | 794 } |
OLD | NEW |