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 class Constant implements Hashable { | 5 class Constant implements Hashable { |
6 const Constant(); | 6 const Constant(); |
7 | 7 |
8 bool isNull() => false; | 8 bool isNull() => false; |
9 bool isBool() => false; | 9 bool isBool() => false; |
10 bool isTrue() => false; | 10 bool isTrue() => false; |
11 bool isFalse() => false; | 11 bool isFalse() => false; |
12 bool isInt() => false; | 12 bool isInt() => false; |
13 bool isDouble() => false; | 13 bool isDouble() => false; |
14 bool isNum() => false; | 14 bool isNum() => false; |
15 bool isString() => false; | 15 bool isString() => false; |
16 bool isList() => false; | 16 bool isList() => false; |
17 bool isMap() => false; | 17 bool isMap() => false; |
18 bool isConstructedObject() => false; | 18 bool isConstructedObject() => false; |
19 /** Returns true if the constant is null, a bool, a number or a string. */ | 19 /** Returns true if the constant is null, a bool, a number or a string. */ |
20 bool isPrimitive() => false; | 20 bool isPrimitive() => false; |
21 /** Returns true if the constant is a list, a map or a constructed object. */ | 21 /** Returns true if the constant is a list, a map or a constructed object. */ |
22 bool isObject() => false; | 22 bool isObject() => false; |
23 | 23 |
24 bool isNaN() => false; | 24 bool isNaN() => false; |
25 bool isMinusZero() => false; | |
25 | 26 |
26 abstract void _writeJsCode(CodeBuffer buffer, ConstantHandler handler); | 27 abstract void _writeJsCode(CodeBuffer buffer, ConstantHandler handler); |
27 /** | 28 /** |
28 * Unless the constant can be emitted multiple times (as for numbers and | 29 * Unless the constant can be emitted multiple times (as for numbers and |
29 * strings) adds its canonical name to the buffer. | 30 * strings) adds its canonical name to the buffer. |
30 */ | 31 */ |
31 abstract void _writeCanonicalizedJsCode(CodeBuffer buffer, | 32 abstract void _writeCanonicalizedJsCode(CodeBuffer buffer, |
32 ConstantHandler handler); | 33 ConstantHandler handler); |
33 abstract List<Constant> getDependencies(); | 34 abstract List<Constant> getDependencies(); |
34 } | 35 } |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
133 return const DoubleConstant._internal(0.0); | 134 return const DoubleConstant._internal(0.0); |
134 } else if (value == 1.0) { | 135 } else if (value == 1.0) { |
135 return const DoubleConstant._internal(1.0); | 136 return const DoubleConstant._internal(1.0); |
136 } else { | 137 } else { |
137 return new DoubleConstant._internal(value); | 138 return new DoubleConstant._internal(value); |
138 } | 139 } |
139 } | 140 } |
140 const DoubleConstant._internal(this.value); | 141 const DoubleConstant._internal(this.value); |
141 bool isDouble() => true; | 142 bool isDouble() => true; |
142 bool isNaN() => value.isNaN(); | 143 bool isNaN() => value.isNaN(); |
144 bool isMinusZero() => value == 0.0 && value.isNegative(); | |
ngeoffray
2012/08/17 08:32:59
Please add a comment why -0.0 doesn't work.
floitsch
2012/09/03 14:34:52
Done.
| |
143 | 145 |
144 void _writeJsCode(CodeBuffer buffer, ConstantHandler handler) { | 146 void _writeJsCode(CodeBuffer buffer, ConstantHandler handler) { |
145 if (value.isNaN()) { | 147 if (value.isNaN()) { |
146 buffer.add("(0/0)"); | 148 buffer.add("(0/0)"); |
147 } else if (value == double.INFINITY) { | 149 } else if (value == double.INFINITY) { |
148 buffer.add("(1/0)"); | 150 buffer.add("(1/0)"); |
149 } else if (value == -double.INFINITY) { | 151 } else if (value == -double.INFINITY) { |
150 buffer.add("(-1/0)"); | 152 buffer.add("(-1/0)"); |
151 } else { | 153 } else { |
152 buffer.add("$value"); | 154 buffer.add("$value"); |
(...skipping 17 matching lines...) Expand all Loading... | |
170 DartString toDartString() => new DartString.literal(value.toString()); | 172 DartString toDartString() => new DartString.literal(value.toString()); |
171 } | 173 } |
172 | 174 |
173 class BoolConstant extends PrimitiveConstant { | 175 class BoolConstant extends PrimitiveConstant { |
174 factory BoolConstant(value) { | 176 factory BoolConstant(value) { |
175 return value ? new TrueConstant() : new FalseConstant(); | 177 return value ? new TrueConstant() : new FalseConstant(); |
176 } | 178 } |
177 const BoolConstant._internal(); | 179 const BoolConstant._internal(); |
178 bool isBool() => true; | 180 bool isBool() => true; |
179 | 181 |
180 BoolConstant unaryFold(String op) { | |
181 if (op == "!") return new BoolConstant(!value); | |
182 return null; | |
183 } | |
184 | |
185 abstract BoolConstant negate(); | 182 abstract BoolConstant negate(); |
186 } | 183 } |
187 | 184 |
188 class TrueConstant extends BoolConstant { | 185 class TrueConstant extends BoolConstant { |
189 final bool value = true; | 186 final bool value = true; |
190 | 187 |
191 factory TrueConstant() => const TrueConstant._internal(); | 188 factory TrueConstant() => const TrueConstant._internal(); |
192 const TrueConstant._internal() : super._internal(); | 189 const TrueConstant._internal() : super._internal(); |
193 bool isTrue() => true; | 190 bool isTrue() => true; |
194 | 191 |
(...skipping 279 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
474 int hashCode() => _hashCode; | 471 int hashCode() => _hashCode; |
475 List<Constant> getDependencies() => fields; | 472 List<Constant> getDependencies() => fields; |
476 } | 473 } |
477 | 474 |
478 /** | 475 /** |
479 * The [ConstantHandler] keeps track of compile-time constants, | 476 * The [ConstantHandler] keeps track of compile-time constants, |
480 * initializations of global and static fields, and default values of | 477 * initializations of global and static fields, and default values of |
481 * optional parameters. | 478 * optional parameters. |
482 */ | 479 */ |
483 class ConstantHandler extends CompilerTask { | 480 class ConstantHandler extends CompilerTask { |
481 final FoldingOperations foldingOperations; | |
484 // Contains the initial value of fields. Must contain all static and global | 482 // Contains the initial value of fields. Must contain all static and global |
485 // initializations of used fields. May contain caches for instance fields. | 483 // initializations of used fields. May contain caches for instance fields. |
486 final Map<VariableElement, Constant> initialVariableValues; | 484 final Map<VariableElement, Constant> initialVariableValues; |
487 | 485 |
488 // Map from compile-time constants to their JS name. | 486 // Map from compile-time constants to their JS name. |
489 final Map<Constant, String> compiledConstants; | 487 final Map<Constant, String> compiledConstants; |
490 | 488 |
491 // The set of variable elements that are in the process of being computed. | 489 // The set of variable elements that are in the process of being computed. |
492 final Set<VariableElement> pendingVariables; | 490 final Set<VariableElement> pendingVariables; |
493 | 491 |
494 ConstantHandler(Compiler compiler) | 492 ConstantHandler(Compiler compiler, this.foldingOperations) |
495 : initialVariableValues = new Map<VariableElement, Dynamic>(), | 493 : initialVariableValues = new Map<VariableElement, Dynamic>(), |
496 compiledConstants = new Map<Constant, String>(), | 494 compiledConstants = new Map<Constant, String>(), |
497 pendingVariables = new Set<VariableElement>(), | 495 pendingVariables = new Set<VariableElement>(), |
498 super(compiler); | 496 super(compiler); |
499 String get name() => 'ConstantHandler'; | 497 String get name() => 'ConstantHandler'; |
500 | 498 |
501 void registerCompileTimeConstant(Constant constant) { | 499 void registerCompileTimeConstant(Constant constant) { |
502 Function ifAbsentThunk = (() => compiler.namer.getFreshGlobalName("CTC")); | 500 Function ifAbsentThunk = (() => compiler.namer.getFreshGlobalName("CTC")); |
503 compiledConstants.putIfAbsent(constant, ifAbsentThunk); | 501 compiledConstants.putIfAbsent(constant, ifAbsentThunk); |
504 } | 502 } |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
557 } | 555 } |
558 initialVariableValues[element] = value; | 556 initialVariableValues[element] = value; |
559 pendingVariables.remove(element); | 557 pendingVariables.remove(element); |
560 return value; | 558 return value; |
561 }); | 559 }); |
562 } | 560 } |
563 | 561 |
564 Constant compileNodeWithDefinitions(Node node, TreeElements definitions) { | 562 Constant compileNodeWithDefinitions(Node node, TreeElements definitions) { |
565 return measure(() { | 563 return measure(() { |
566 assert(node !== null); | 564 assert(node !== null); |
567 CompileTimeConstantEvaluator evaluator = | 565 CompileTimeConstantEvaluator evaluator = new CompileTimeConstantEvaluator( |
568 new CompileTimeConstantEvaluator(definitions, compiler); | 566 foldingOperations, definitions, compiler); |
569 return evaluator.evaluate(node); | 567 return evaluator.evaluate(node); |
570 }); | 568 }); |
571 } | 569 } |
572 | 570 |
573 /** Attempts to compile a constant expression. Returns null if not possible */ | 571 /** Attempts to compile a constant expression. Returns null if not possible */ |
574 Constant tryCompileNodeWithDefinitions(Node node, TreeElements definitions) { | 572 Constant tryCompileNodeWithDefinitions(Node node, TreeElements definitions) { |
575 return measure(() { | 573 return measure(() { |
576 assert(node !== null); | 574 assert(node !== null); |
577 try { | 575 try { |
578 TryCompileTimeConstantEvaluator evaluator = | 576 TryCompileTimeConstantEvaluator evaluator = |
579 new TryCompileTimeConstantEvaluator(definitions, compiler); | 577 new TryCompileTimeConstantEvaluator(foldingOperations, |
578 definitions, | |
579 compiler); | |
580 return evaluator.evaluate(node); | 580 return evaluator.evaluate(node); |
581 } catch (CompileTimeConstantError exn) { | 581 } catch (CompileTimeConstantError exn) { |
582 return null; | 582 return null; |
583 } | 583 } |
584 }); | 584 }); |
585 } | 585 } |
586 | 586 |
587 /** | 587 /** |
588 * Returns a [List] of static non final fields that need to be initialized. | 588 * Returns a [List] of static non final fields that need to be initialized. |
589 * The list must be evaluated in order since the fields might depend on each | 589 * The list must be evaluated in order since the fields might depend on each |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
706 } | 706 } |
707 } | 707 } |
708 } | 708 } |
709 | 709 |
710 String getJsConstructor(ClassElement element) { | 710 String getJsConstructor(ClassElement element) { |
711 return compiler.namer.isolatePropertiesAccess(element); | 711 return compiler.namer.isolatePropertiesAccess(element); |
712 } | 712 } |
713 } | 713 } |
714 | 714 |
715 class CompileTimeConstantEvaluator extends AbstractVisitor { | 715 class CompileTimeConstantEvaluator extends AbstractVisitor { |
716 final FoldingOperations foldingOperations; | |
716 final TreeElements elements; | 717 final TreeElements elements; |
717 final Compiler compiler; | 718 final Compiler compiler; |
718 | 719 |
719 CompileTimeConstantEvaluator(this.elements, this.compiler); | 720 CompileTimeConstantEvaluator(this.foldingOperations, |
721 this.elements, | |
722 this.compiler); | |
720 | 723 |
721 Constant evaluate(Node node) { | 724 Constant evaluate(Node node) { |
722 return node.accept(this); | 725 return node.accept(this); |
723 } | 726 } |
724 | 727 |
725 visitNode(Node node) { | 728 visitNode(Node node) { |
726 error(node); | 729 error(node); |
727 } | 730 } |
728 | 731 |
729 Constant visitLiteralBool(LiteralBool node) { | 732 Constant visitLiteralBool(LiteralBool node) { |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
843 error(send); | 846 error(send); |
844 } | 847 } |
845 return compiler.compileVariable(element); | 848 return compiler.compileVariable(element); |
846 } else if (send.isPrefix) { | 849 } else if (send.isPrefix) { |
847 assert(send.isOperator); | 850 assert(send.isOperator); |
848 Constant receiverConstant = evaluate(send.receiver); | 851 Constant receiverConstant = evaluate(send.receiver); |
849 Operator op = send.selector; | 852 Operator op = send.selector; |
850 Constant folded; | 853 Constant folded; |
851 switch (op.source.stringValue) { | 854 switch (op.source.stringValue) { |
852 case "!": | 855 case "!": |
853 folded = const NotOperation().fold(receiverConstant); | 856 folded = foldingOperations.not.fold(receiverConstant); |
854 break; | 857 break; |
855 case "-": | 858 case "-": |
856 folded = const NegateOperation().fold(receiverConstant); | 859 folded = foldingOperations.negate.fold(receiverConstant); |
857 break; | 860 break; |
858 case "~": | 861 case "~": |
859 folded = const BitNotOperation().fold(receiverConstant); | 862 folded = foldingOperations.bitNot.fold(receiverConstant); |
860 break; | 863 break; |
861 default: | 864 default: |
862 compiler.internalError("Unexpected operator.", node: op); | 865 compiler.internalError("Unexpected operator.", node: op); |
863 break; | 866 break; |
864 } | 867 } |
865 if (folded === null) error(send); | 868 if (folded === null) error(send); |
866 return folded; | 869 return folded; |
867 } else if (send.isOperator && !send.isPostfix) { | 870 } else if (send.isOperator && !send.isPostfix) { |
868 assert(send.argumentCount() == 1); | 871 assert(send.argumentCount() == 1); |
869 Constant left = evaluate(send.receiver); | 872 Constant left = evaluate(send.receiver); |
870 Constant right = evaluate(send.argumentsNode.nodes.head); | 873 Constant right = evaluate(send.argumentsNode.nodes.head); |
871 Operator op = send.selector.asOperator(); | 874 Operator op = send.selector.asOperator(); |
872 Constant folded = null; | 875 Constant folded = null; |
873 switch (op.source.stringValue) { | 876 switch (op.source.stringValue) { |
874 case "+": | 877 case "+": |
875 folded = const AddOperation().fold(left, right); | 878 folded = foldingOperations.add.fold(left, right); |
876 break; | 879 break; |
877 case "-": | 880 case "-": |
878 folded = const SubtractOperation().fold(left, right); | 881 folded = foldingOperations.subtract.fold(left, right); |
879 break; | 882 break; |
880 case "*": | 883 case "*": |
881 folded = const MultiplyOperation().fold(left, right); | 884 folded = foldingOperations.multiply.fold(left, right); |
882 break; | 885 break; |
883 case "/": | 886 case "/": |
884 folded = const DivideOperation().fold(left, right); | 887 folded = foldingOperations.divide.fold(left, right); |
885 break; | 888 break; |
886 case "%": | 889 case "%": |
887 folded = const ModuloOperation().fold(left, right); | 890 folded = foldingOperations.modulo.fold(left, right); |
888 break; | 891 break; |
889 case "~/": | 892 case "~/": |
890 folded = const TruncatingDivideOperation().fold(left, right); | 893 folded = foldingOperations.truncatingDivide.fold(left, right); |
891 break; | 894 break; |
892 case "|": | 895 case "|": |
893 folded = const BitOrOperation().fold(left, right); | 896 folded = foldingOperations.bitOr.fold(left, right); |
894 break; | 897 break; |
895 case "&": | 898 case "&": |
896 folded = const BitAndOperation().fold(left, right); | 899 folded = foldingOperations.bitAnd.fold(left, right); |
897 break; | 900 break; |
898 case "^": | 901 case "^": |
899 folded = const BitXorOperation().fold(left, right); | 902 folded = foldingOperations.bitXor.fold(left, right); |
900 break; | 903 break; |
901 case "||": | 904 case "||": |
902 folded = const BooleanOr().fold(left, right); | 905 folded = foldingOperations.booleanOr.fold(left, right); |
903 break; | 906 break; |
904 case "&&": | 907 case "&&": |
905 folded = const BooleanAnd().fold(left, right); | 908 folded = foldingOperations.booleanAnd.fold(left, right); |
906 break; | 909 break; |
907 case "<<": | 910 case "<<": |
908 folded = const ShiftLeftOperation().fold(left, right); | 911 folded = foldingOperations.shiftLeft.fold(left, right); |
909 break; | 912 break; |
910 case ">>": | 913 case ">>": |
911 folded = const ShiftRightOperation().fold(left, right); | 914 folded = foldingOperations.shiftRight.fold(left, right); |
912 break; | 915 break; |
913 case "<": | 916 case "<": |
914 folded = const LessOperation().fold(left, right); | 917 folded = foldingOperations.less.fold(left, right); |
915 break; | 918 break; |
916 case "<=": | 919 case "<=": |
917 folded = const LessEqualOperation().fold(left, right); | 920 folded = foldingOperations.lessEqual.fold(left, right); |
918 break; | 921 break; |
919 case ">": | 922 case ">": |
920 folded = const GreaterOperation().fold(left, right); | 923 folded = foldingOperations.greater.fold(left, right); |
921 break; | 924 break; |
922 case ">=": | 925 case ">=": |
923 folded = const GreaterEqualOperation().fold(left, right); | 926 folded = foldingOperations.greaterEqual.fold(left, right); |
924 break; | 927 break; |
925 case "==": | 928 case "==": |
926 if (left.isPrimitive() && right.isPrimitive()) { | 929 if (left.isPrimitive() && right.isPrimitive()) { |
927 folded = const EqualsOperation().fold(left, right); | 930 folded = foldingOperations.equal.fold(left, right); |
928 } | 931 } |
929 break; | 932 break; |
930 case "===": | 933 case "===": |
931 if (left.isPrimitive() && right.isPrimitive()) { | 934 if (left.isPrimitive() && right.isPrimitive()) { |
932 folded = const IdentityOperation().fold(left, right); | 935 folded = foldingOperations.identity.fold(left, right); |
933 } | 936 } |
934 break; | 937 break; |
935 case "!=": | 938 case "!=": |
936 if (left.isPrimitive() && right.isPrimitive()) { | 939 if (left.isPrimitive() && right.isPrimitive()) { |
937 BoolConstant areEquals = const EqualsOperation().fold(left, right); | 940 BoolConstant areEquals = foldingOperations.equal.fold(left, right); |
938 if (areEquals === null) { | 941 if (areEquals === null) { |
939 folded = null; | 942 folded = null; |
940 } else { | 943 } else { |
941 folded = areEquals.negate(); | 944 folded = areEquals.negate(); |
942 } | 945 } |
943 } | 946 } |
944 break; | 947 break; |
945 case "!==": | 948 case "!==": |
946 if (left.isPrimitive() && right.isPrimitive()) { | 949 if (left.isPrimitive() && right.isPrimitive()) { |
947 BoolConstant areIdentical = | 950 BoolConstant areIdentical = |
948 const IdentityOperation().fold(left, right); | 951 foldingOperations.identity.fold(left, right); |
949 if (areIdentical === null) { | 952 if (areIdentical === null) { |
950 folded = null; | 953 folded = null; |
951 } else { | 954 } else { |
952 folded = areIdentical.negate(); | 955 folded = areIdentical.negate(); |
953 } | 956 } |
954 } | 957 } |
955 break; | 958 break; |
956 } | 959 } |
957 if (folded === null) error(send); | 960 if (folded === null) error(send); |
958 return folded; | 961 return folded; |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
991 if (classElement.isInterface()) { | 994 if (classElement.isInterface()) { |
992 compiler.resolver.resolveMethodElement(constructor); | 995 compiler.resolver.resolveMethodElement(constructor); |
993 constructor = constructor.defaultImplementation; | 996 constructor = constructor.defaultImplementation; |
994 classElement = constructor.getEnclosingClass(); | 997 classElement = constructor.getEnclosingClass(); |
995 } | 998 } |
996 | 999 |
997 Selector selector = elements.getSelector(send); | 1000 Selector selector = elements.getSelector(send); |
998 List<Constant> arguments = | 1001 List<Constant> arguments = |
999 evaluateArgumentsToConstructor(selector, send.arguments, constructor); | 1002 evaluateArgumentsToConstructor(selector, send.arguments, constructor); |
1000 ConstructorEvaluator evaluator = | 1003 ConstructorEvaluator evaluator = |
1001 new ConstructorEvaluator(constructor, compiler); | 1004 new ConstructorEvaluator(constructor, foldingOperations, compiler); |
1002 evaluator.evaluateConstructorFieldValues(arguments); | 1005 evaluator.evaluateConstructorFieldValues(arguments); |
1003 List<Constant> jsNewArguments = evaluator.buildJsNewArguments(classElement); | 1006 List<Constant> jsNewArguments = evaluator.buildJsNewArguments(classElement); |
1004 | 1007 |
1005 compiler.registerInstantiatedClass(classElement); | 1008 compiler.registerInstantiatedClass(classElement); |
1006 // TODO(floitsch): take generic types into account. | 1009 // TODO(floitsch): take generic types into account. |
1007 Type type = classElement.computeType(compiler); | 1010 Type type = classElement.computeType(compiler); |
1008 Constant constant = new ConstructedConstant(type, jsNewArguments); | 1011 Constant constant = new ConstructedConstant(type, jsNewArguments); |
1009 compiler.constantHandler.registerCompileTimeConstant(constant); | 1012 compiler.constantHandler.registerCompileTimeConstant(constant); |
1010 return constant; | 1013 return constant; |
1011 } | 1014 } |
1012 | 1015 |
1013 Constant visitParenthesizedExpression(ParenthesizedExpression node) { | 1016 Constant visitParenthesizedExpression(ParenthesizedExpression node) { |
1014 return node.expression.accept(this); | 1017 return node.expression.accept(this); |
1015 } | 1018 } |
1016 | 1019 |
1017 error(Node node) { | 1020 error(Node node) { |
1018 // TODO(floitsch): get the list of constants that are currently compiled | 1021 // TODO(floitsch): get the list of constants that are currently compiled |
1019 // and present some kind of stack-trace. | 1022 // and present some kind of stack-trace. |
1020 MessageKind kind = MessageKind.NOT_A_COMPILE_TIME_CONSTANT; | 1023 MessageKind kind = MessageKind.NOT_A_COMPILE_TIME_CONSTANT; |
1021 compiler.reportError(node, new CompileTimeConstantError(kind, const [])); | 1024 compiler.reportError(node, new CompileTimeConstantError(kind, const [])); |
1022 } | 1025 } |
1023 } | 1026 } |
1024 | 1027 |
1025 class TryCompileTimeConstantEvaluator extends CompileTimeConstantEvaluator { | 1028 class TryCompileTimeConstantEvaluator extends CompileTimeConstantEvaluator { |
1026 TryCompileTimeConstantEvaluator(TreeElements elements, Compiler compiler): | 1029 TryCompileTimeConstantEvaluator(FoldingOperations foldingOperations, |
1027 super(elements, compiler); | 1030 TreeElements elements, |
1031 Compiler compiler): | |
1032 super(foldingOperations, elements, compiler); | |
1028 | 1033 |
1029 error(Node node) { | 1034 error(Node node) { |
1030 // Just fail without reporting it anywhere. | 1035 // Just fail without reporting it anywhere. |
1031 throw new CompileTimeConstantError( | 1036 throw new CompileTimeConstantError( |
1032 MessageKind.NOT_A_COMPILE_TIME_CONSTANT, const []); | 1037 MessageKind.NOT_A_COMPILE_TIME_CONSTANT, const []); |
1033 } | 1038 } |
1034 } | 1039 } |
1035 | 1040 |
1036 class ConstructorEvaluator extends CompileTimeConstantEvaluator { | 1041 class ConstructorEvaluator extends CompileTimeConstantEvaluator { |
1037 FunctionElement constructor; | 1042 FunctionElement constructor; |
1038 final Map<Element, Constant> definitions; | 1043 final Map<Element, Constant> definitions; |
1039 final Map<Element, Constant> fieldValues; | 1044 final Map<Element, Constant> fieldValues; |
1040 | 1045 |
1041 ConstructorEvaluator(FunctionElement constructor, Compiler compiler) | 1046 ConstructorEvaluator(FunctionElement constructor, |
1047 FoldingOperations foldingOperations, | |
1048 Compiler compiler) | |
1042 : this.constructor = constructor, | 1049 : this.constructor = constructor, |
1043 this.definitions = new Map<Element, Constant>(), | 1050 this.definitions = new Map<Element, Constant>(), |
1044 this.fieldValues = new Map<Element, Constant>(), | 1051 this.fieldValues = new Map<Element, Constant>(), |
1045 super(compiler.resolver.resolveMethodElement(constructor), | 1052 super(foldingOperations, |
1053 compiler.resolver.resolveMethodElement(constructor), | |
1046 compiler); | 1054 compiler); |
1047 | 1055 |
1048 Constant visitSend(Send send) { | 1056 Constant visitSend(Send send) { |
1049 Element element = elements[send]; | 1057 Element element = elements[send]; |
1050 if (Elements.isLocal(element)) { | 1058 if (Elements.isLocal(element)) { |
1051 Constant constant = definitions[element]; | 1059 Constant constant = definitions[element]; |
1052 if (constant === null) { | 1060 if (constant === null) { |
1053 compiler.internalError("Local variable without value", node: send); | 1061 compiler.internalError("Local variable without value", node: send); |
1054 } | 1062 } |
1055 return constant; | 1063 return constant; |
(...skipping 19 matching lines...) Expand all Loading... | |
1075 } | 1083 } |
1076 }); | 1084 }); |
1077 } | 1085 } |
1078 | 1086 |
1079 void evaluateSuperOrRedirectSend(Selector selector, | 1087 void evaluateSuperOrRedirectSend(Selector selector, |
1080 Link<Node> arguments, | 1088 Link<Node> arguments, |
1081 FunctionElement targetConstructor) { | 1089 FunctionElement targetConstructor) { |
1082 List<Constant> compiledArguments = | 1090 List<Constant> compiledArguments = |
1083 evaluateArgumentsToConstructor(selector, arguments, targetConstructor); | 1091 evaluateArgumentsToConstructor(selector, arguments, targetConstructor); |
1084 | 1092 |
1085 ConstructorEvaluator evaluator = | 1093 ConstructorEvaluator evaluator = new ConstructorEvaluator( |
1086 new ConstructorEvaluator(targetConstructor, compiler); | 1094 targetConstructor, foldingOperations, compiler); |
1087 evaluator.evaluateConstructorFieldValues(compiledArguments); | 1095 evaluator.evaluateConstructorFieldValues(compiledArguments); |
1088 // Copy over the fieldValues from the super/redirect-constructor. | 1096 // Copy over the fieldValues from the super/redirect-constructor. |
1089 evaluator.fieldValues.forEach((key, value) => fieldValues[key] = value); | 1097 evaluator.fieldValues.forEach((key, value) => fieldValues[key] = value); |
1090 } | 1098 } |
1091 | 1099 |
1092 /** | 1100 /** |
1093 * Runs through the initializers of the given [constructor] and updates | 1101 * Runs through the initializers of the given [constructor] and updates |
1094 * the [fieldValues] map. | 1102 * the [fieldValues] map. |
1095 */ | 1103 */ |
1096 void evaluateConstructorInitializers() { | 1104 void evaluateConstructorInitializers() { |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1169 Constant fieldValue = fieldValues[field]; | 1177 Constant fieldValue = fieldValues[field]; |
1170 if (fieldValue === null) { | 1178 if (fieldValue === null) { |
1171 // Use the default value. | 1179 // Use the default value. |
1172 fieldValue = compiler.compileVariable(field); | 1180 fieldValue = compiler.compileVariable(field); |
1173 } | 1181 } |
1174 jsNewArguments.add(fieldValue); | 1182 jsNewArguments.add(fieldValue); |
1175 }); | 1183 }); |
1176 return jsNewArguments; | 1184 return jsNewArguments; |
1177 } | 1185 } |
1178 } | 1186 } |
OLD | NEW |