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 bool isFunction() => false; | 19 bool isFunction() => false; |
20 /** Returns true if the constant is null, a bool, a number or a string. */ | 20 /** Returns true if the constant is null, a bool, a number or a string. */ |
21 bool isPrimitive() => false; | 21 bool isPrimitive() => false; |
22 /** Returns true if the constant is a list, a map or a constructed object. */ | 22 /** Returns true if the constant is a list, a map or a constructed object. */ |
23 bool isObject() => false; | 23 bool isObject() => false; |
24 bool isSentinel() => false; | 24 bool isSentinel() => false; |
25 | 25 |
26 bool isNaN() => false; | 26 bool isNaN() => false; |
| 27 bool isMinusZero() => false; |
27 | 28 |
28 abstract void _writeJsCode(CodeBuffer buffer, ConstantHandler handler); | 29 abstract void _writeJsCode(CodeBuffer buffer, ConstantHandler handler); |
29 /** | 30 /** |
30 * Unless the constant can be emitted multiple times (as for numbers and | 31 * Unless the constant can be emitted multiple times (as for numbers and |
31 * strings) adds its canonical name to the buffer. | 32 * strings) adds its canonical name to the buffer. |
32 */ | 33 */ |
33 abstract void _writeCanonicalizedJsCode(CodeBuffer buffer, | 34 abstract void _writeCanonicalizedJsCode(CodeBuffer buffer, |
34 ConstantHandler handler); | 35 ConstantHandler handler); |
35 abstract List<Constant> getDependencies(); | 36 abstract List<Constant> getDependencies(); |
36 } | 37 } |
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
186 return const DoubleConstant._internal(0.0); | 187 return const DoubleConstant._internal(0.0); |
187 } else if (value == 1.0) { | 188 } else if (value == 1.0) { |
188 return const DoubleConstant._internal(1.0); | 189 return const DoubleConstant._internal(1.0); |
189 } else { | 190 } else { |
190 return new DoubleConstant._internal(value); | 191 return new DoubleConstant._internal(value); |
191 } | 192 } |
192 } | 193 } |
193 const DoubleConstant._internal(this.value); | 194 const DoubleConstant._internal(this.value); |
194 bool isDouble() => true; | 195 bool isDouble() => true; |
195 bool isNaN() => value.isNaN(); | 196 bool isNaN() => value.isNaN(); |
| 197 // We need to check for the negative sign since -0.0 == 0.0. |
| 198 bool isMinusZero() => value == 0.0 && value.isNegative(); |
196 | 199 |
197 void _writeJsCode(CodeBuffer buffer, ConstantHandler handler) { | 200 void _writeJsCode(CodeBuffer buffer, ConstantHandler handler) { |
198 if (value.isNaN()) { | 201 if (value.isNaN()) { |
199 buffer.add("(0/0)"); | 202 buffer.add("(0/0)"); |
200 } else if (value == double.INFINITY) { | 203 } else if (value == double.INFINITY) { |
201 buffer.add("(1/0)"); | 204 buffer.add("(1/0)"); |
202 } else if (value == -double.INFINITY) { | 205 } else if (value == -double.INFINITY) { |
203 buffer.add("(-1/0)"); | 206 buffer.add("(-1/0)"); |
204 } else { | 207 } else { |
205 buffer.add("$value"); | 208 buffer.add("$value"); |
(...skipping 17 matching lines...) Expand all Loading... |
223 DartString toDartString() => new DartString.literal(value.toString()); | 226 DartString toDartString() => new DartString.literal(value.toString()); |
224 } | 227 } |
225 | 228 |
226 class BoolConstant extends PrimitiveConstant { | 229 class BoolConstant extends PrimitiveConstant { |
227 factory BoolConstant(value) { | 230 factory BoolConstant(value) { |
228 return value ? new TrueConstant() : new FalseConstant(); | 231 return value ? new TrueConstant() : new FalseConstant(); |
229 } | 232 } |
230 const BoolConstant._internal(); | 233 const BoolConstant._internal(); |
231 bool isBool() => true; | 234 bool isBool() => true; |
232 | 235 |
233 BoolConstant unaryFold(String op) { | |
234 if (op == "!") return new BoolConstant(!value); | |
235 return null; | |
236 } | |
237 | |
238 abstract BoolConstant negate(); | 236 abstract BoolConstant negate(); |
239 } | 237 } |
240 | 238 |
241 class TrueConstant extends BoolConstant { | 239 class TrueConstant extends BoolConstant { |
242 final bool value = true; | 240 final bool value = true; |
243 | 241 |
244 factory TrueConstant() => const TrueConstant._internal(); | 242 factory TrueConstant() => const TrueConstant._internal(); |
245 const TrueConstant._internal() : super._internal(); | 243 const TrueConstant._internal() : super._internal(); |
246 bool isTrue() => true; | 244 bool isTrue() => true; |
247 | 245 |
(...skipping 279 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
527 int hashCode() => _hashCode; | 525 int hashCode() => _hashCode; |
528 List<Constant> getDependencies() => fields; | 526 List<Constant> getDependencies() => fields; |
529 } | 527 } |
530 | 528 |
531 /** | 529 /** |
532 * The [ConstantHandler] keeps track of compile-time constants, | 530 * The [ConstantHandler] keeps track of compile-time constants, |
533 * initializations of global and static fields, and default values of | 531 * initializations of global and static fields, and default values of |
534 * optional parameters. | 532 * optional parameters. |
535 */ | 533 */ |
536 class ConstantHandler extends CompilerTask { | 534 class ConstantHandler extends CompilerTask { |
| 535 final ConstantSystem constantSystem; |
| 536 |
537 /** | 537 /** |
538 * Contains the initial value of fields. Must contain all static and global | 538 * Contains the initial value of fields. Must contain all static and global |
539 * initializations of const fields. May contain eagerly compiled values for | 539 * initializations of const fields. May contain eagerly compiled values for |
540 * statics and instance fields. | 540 * statics and instance fields. |
541 */ | 541 */ |
542 final Map<VariableElement, Constant> initialVariableValues; | 542 final Map<VariableElement, Constant> initialVariableValues; |
543 | 543 |
544 /** Map from compile-time constants to their JS name. */ | 544 /** Map from compile-time constants to their JS name. */ |
545 final Map<Constant, String> compiledConstants; | 545 final Map<Constant, String> compiledConstants; |
546 | 546 |
547 /** The set of variable elements that are in the process of being computed. */ | 547 /** The set of variable elements that are in the process of being computed. */ |
548 final Set<VariableElement> pendingVariables; | 548 final Set<VariableElement> pendingVariables; |
549 | 549 |
550 /** Caches the statics where the initial value cannot be eagerly compiled. */ | 550 /** Caches the statics where the initial value cannot be eagerly compiled. */ |
551 final Set<VariableElement> lazyStatics; | 551 final Set<VariableElement> lazyStatics; |
552 | 552 |
553 | 553 |
554 ConstantHandler(Compiler compiler) | 554 ConstantHandler(Compiler compiler, this.constantSystem) |
555 : initialVariableValues = new Map<VariableElement, Dynamic>(), | 555 : initialVariableValues = new Map<VariableElement, Dynamic>(), |
556 compiledConstants = new Map<Constant, String>(), | 556 compiledConstants = new Map<Constant, String>(), |
557 pendingVariables = new Set<VariableElement>(), | 557 pendingVariables = new Set<VariableElement>(), |
558 lazyStatics = new Set<VariableElement>(), | 558 lazyStatics = new Set<VariableElement>(), |
559 super(compiler); | 559 super(compiler); |
560 String get name => 'ConstantHandler'; | 560 String get name => 'ConstantHandler'; |
561 | 561 |
562 void registerCompileTimeConstant(Constant constant) { | 562 void registerCompileTimeConstant(Constant constant) { |
563 Function ifAbsentThunk = (() { | 563 Function ifAbsentThunk = (() { |
564 return constant.isFunction() | 564 return constant.isFunction() |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
663 pendingVariables.remove(element); | 663 pendingVariables.remove(element); |
664 return value; | 664 return value; |
665 }); | 665 }); |
666 } | 666 } |
667 | 667 |
668 Constant compileNodeWithDefinitions(Node node, | 668 Constant compileNodeWithDefinitions(Node node, |
669 TreeElements definitions, | 669 TreeElements definitions, |
670 [bool isConst]) { | 670 [bool isConst]) { |
671 return measure(() { | 671 return measure(() { |
672 assert(node !== null); | 672 assert(node !== null); |
673 CompileTimeConstantEvaluator evaluator = | 673 CompileTimeConstantEvaluator evaluator = new CompileTimeConstantEvaluator( |
674 new CompileTimeConstantEvaluator(definitions, compiler, isConst); | 674 constantSystem, definitions, compiler, isConst); |
675 return evaluator.evaluate(node); | 675 return evaluator.evaluate(node); |
676 }); | 676 }); |
677 } | 677 } |
678 | 678 |
679 /** Attempts to compile a constant expression. Returns null if not possible */ | 679 /** Attempts to compile a constant expression. Returns null if not possible */ |
680 Constant tryCompileNodeWithDefinitions(Node node, TreeElements definitions) { | 680 Constant tryCompileNodeWithDefinitions(Node node, TreeElements definitions) { |
681 return measure(() { | 681 return measure(() { |
682 assert(node !== null); | 682 assert(node !== null); |
683 try { | 683 try { |
684 TryCompileTimeConstantEvaluator evaluator = | 684 TryCompileTimeConstantEvaluator evaluator = |
685 new TryCompileTimeConstantEvaluator(definitions, compiler); | 685 new TryCompileTimeConstantEvaluator(constantSystem, |
| 686 definitions, |
| 687 compiler); |
686 return evaluator.evaluate(node); | 688 return evaluator.evaluate(node); |
687 } on CompileTimeConstantError catch (exn) { | 689 } on CompileTimeConstantError catch (exn) { |
688 return null; | 690 return null; |
689 } | 691 } |
690 }); | 692 }); |
691 } | 693 } |
692 | 694 |
693 /** | 695 /** |
694 * Returns a [List] of static non final fields that need to be initialized. | 696 * Returns a [List] of static non final fields that need to be initialized. |
695 * The list must be evaluated in order since the fields might depend on each | 697 * The list must be evaluated in order since the fields might depend on each |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
817 } | 819 } |
818 } | 820 } |
819 | 821 |
820 String getJsConstructor(ClassElement element) { | 822 String getJsConstructor(ClassElement element) { |
821 return compiler.namer.isolatePropertiesAccess(element); | 823 return compiler.namer.isolatePropertiesAccess(element); |
822 } | 824 } |
823 } | 825 } |
824 | 826 |
825 class CompileTimeConstantEvaluator extends AbstractVisitor { | 827 class CompileTimeConstantEvaluator extends AbstractVisitor { |
826 bool isEvaluatingConstant; | 828 bool isEvaluatingConstant; |
| 829 final ConstantSystem constantSystem; |
827 final TreeElements elements; | 830 final TreeElements elements; |
828 final Compiler compiler; | 831 final Compiler compiler; |
829 | 832 |
830 CompileTimeConstantEvaluator(this.elements, this.compiler, [bool isConst]) | 833 CompileTimeConstantEvaluator(this.constantSystem, |
| 834 this.elements, |
| 835 this.compiler, |
| 836 [bool isConst]) |
831 : this.isEvaluatingConstant = isConst; | 837 : this.isEvaluatingConstant = isConst; |
832 | 838 |
833 Constant evaluate(Node node) { | 839 Constant evaluate(Node node) { |
834 return node.accept(this); | 840 return node.accept(this); |
835 } | 841 } |
836 | 842 |
837 Constant evaluateConstant(Node node) { | 843 Constant evaluateConstant(Node node) { |
838 bool oldIsEvaluatingConstant = isEvaluatingConstant; | 844 bool oldIsEvaluatingConstant = isEvaluatingConstant; |
839 isEvaluatingConstant = true; | 845 isEvaluatingConstant = true; |
840 Constant result = node.accept(this); | 846 Constant result = node.accept(this); |
841 isEvaluatingConstant = oldIsEvaluatingConstant; | 847 isEvaluatingConstant = oldIsEvaluatingConstant; |
842 assert(result != null); | 848 assert(result != null); |
843 return result; | 849 return result; |
844 } | 850 } |
845 | 851 |
846 Constant visitNode(Node node) { | 852 Constant visitNode(Node node) { |
847 return signalNotCompileTimeConstant(node); | 853 return signalNotCompileTimeConstant(node); |
848 } | 854 } |
849 | 855 |
850 Constant visitLiteralBool(LiteralBool node) { | 856 Constant visitLiteralBool(LiteralBool node) { |
851 return new BoolConstant(node.value); | 857 return constantSystem.createBool(node.value); |
852 } | 858 } |
853 | 859 |
854 Constant visitLiteralDouble(LiteralDouble node) { | 860 Constant visitLiteralDouble(LiteralDouble node) { |
855 return new DoubleConstant(node.value); | 861 return constantSystem.createDouble(node.value); |
856 } | 862 } |
857 | 863 |
858 Constant visitLiteralInt(LiteralInt node) { | 864 Constant visitLiteralInt(LiteralInt node) { |
859 return new IntConstant(node.value); | 865 return constantSystem.createInt(node.value); |
860 } | 866 } |
861 | 867 |
862 Constant visitLiteralList(LiteralList node) { | 868 Constant visitLiteralList(LiteralList node) { |
863 if (!node.isConst()) { | 869 if (!node.isConst()) { |
864 return signalNotCompileTimeConstant(node); | 870 return signalNotCompileTimeConstant(node); |
865 } | 871 } |
866 List<Constant> arguments = <Constant>[]; | 872 List<Constant> arguments = <Constant>[]; |
867 for (Link<Node> link = node.elements.nodes; | 873 for (Link<Node> link = node.elements.nodes; |
868 !link.isEmpty(); | 874 !link.isEmpty(); |
869 link = link.tail) { | 875 link = link.tail) { |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
917 classElement.ensureResolved(compiler); | 923 classElement.ensureResolved(compiler); |
918 // TODO(floitsch): copy over the generic type. | 924 // TODO(floitsch): copy over the generic type. |
919 DartType type = new InterfaceType(classElement); | 925 DartType type = new InterfaceType(classElement); |
920 compiler.registerInstantiatedClass(classElement); | 926 compiler.registerInstantiatedClass(classElement); |
921 Constant constant = new MapConstant(type, keysList, values, protoValue); | 927 Constant constant = new MapConstant(type, keysList, values, protoValue); |
922 compiler.constantHandler.registerCompileTimeConstant(constant); | 928 compiler.constantHandler.registerCompileTimeConstant(constant); |
923 return constant; | 929 return constant; |
924 } | 930 } |
925 | 931 |
926 Constant visitLiteralNull(LiteralNull node) { | 932 Constant visitLiteralNull(LiteralNull node) { |
927 return new NullConstant(); | 933 return constantSystem.createNull(); |
928 } | 934 } |
929 | 935 |
930 Constant visitLiteralString(LiteralString node) { | 936 Constant visitLiteralString(LiteralString node) { |
931 return new StringConstant(node.dartString, node); | 937 return constantSystem.createString(node.dartString, node); |
932 } | 938 } |
933 | 939 |
934 Constant visitStringJuxtaposition(StringJuxtaposition node) { | 940 Constant visitStringJuxtaposition(StringJuxtaposition node) { |
935 StringConstant left = evaluate(node.first); | 941 StringConstant left = evaluate(node.first); |
936 StringConstant right = evaluate(node.second); | 942 StringConstant right = evaluate(node.second); |
937 if (left == null || right == null) return null; | 943 if (left == null || right == null) return null; |
938 return new StringConstant(new DartString.concat(left.value, right.value), | 944 return constantSystem.createString( |
939 node); | 945 new DartString.concat(left.value, right.value), node); |
940 } | 946 } |
941 | 947 |
942 Constant visitStringInterpolation(StringInterpolation node) { | 948 Constant visitStringInterpolation(StringInterpolation node) { |
943 StringConstant initialString = evaluate(node.string); | 949 StringConstant initialString = evaluate(node.string); |
944 if (initialString == null) return null; | 950 if (initialString == null) return null; |
945 DartString accumulator = initialString.value; | 951 DartString accumulator = initialString.value; |
946 for (StringInterpolationPart part in node.parts) { | 952 for (StringInterpolationPart part in node.parts) { |
947 Constant expression = evaluate(part.expression); | 953 Constant expression = evaluate(part.expression); |
948 DartString expressionString; | 954 DartString expressionString; |
949 if (expression.isNum() || expression.isBool()) { | 955 if (expression.isNum() || expression.isBool()) { |
950 PrimitiveConstant primitive = expression; | 956 PrimitiveConstant primitive = expression; |
951 expressionString = new DartString.literal(primitive.value.toString()); | 957 expressionString = new DartString.literal(primitive.value.toString()); |
952 } else if (expression.isString()) { | 958 } else if (expression.isString()) { |
953 PrimitiveConstant primitive = expression; | 959 PrimitiveConstant primitive = expression; |
954 expressionString = primitive.value; | 960 expressionString = primitive.value; |
955 } else { | 961 } else { |
956 return signalNotCompileTimeConstant(part.expression); | 962 return signalNotCompileTimeConstant(part.expression); |
957 } | 963 } |
958 accumulator = new DartString.concat(accumulator, expressionString); | 964 accumulator = new DartString.concat(accumulator, expressionString); |
959 StringConstant partString = evaluate(part.string); | 965 StringConstant partString = evaluate(part.string); |
960 if (partString == null) return null; | 966 if (partString == null) return null; |
961 accumulator = new DartString.concat(accumulator, partString.value); | 967 accumulator = new DartString.concat(accumulator, partString.value); |
962 }; | 968 }; |
963 return new StringConstant(accumulator, node); | 969 return constantSystem.createString(accumulator, node); |
964 } | 970 } |
965 | 971 |
966 // TODO(floitsch): provide better error-messages. | 972 // TODO(floitsch): provide better error-messages. |
967 Constant visitSend(Send send) { | 973 Constant visitSend(Send send) { |
968 Element element = elements[send]; | 974 Element element = elements[send]; |
969 if (Elements.isStaticOrTopLevelField(element)) { | 975 if (Elements.isStaticOrTopLevelField(element)) { |
970 Constant result; | 976 Constant result; |
971 if (element.modifiers !== null) { | 977 if (element.modifiers !== null) { |
972 if (element.modifiers.isConst()) { | 978 if (element.modifiers.isConst()) { |
973 result = compiler.compileConstant(element); | 979 result = compiler.compileConstant(element); |
(...skipping 12 matching lines...) Expand all Loading... |
986 compiler.constantHandler.registerCompileTimeConstant(constant); | 992 compiler.constantHandler.registerCompileTimeConstant(constant); |
987 return constant; | 993 return constant; |
988 } else if (send.isPrefix) { | 994 } else if (send.isPrefix) { |
989 assert(send.isOperator); | 995 assert(send.isOperator); |
990 Constant receiverConstant = evaluate(send.receiver); | 996 Constant receiverConstant = evaluate(send.receiver); |
991 if (receiverConstant == null) return null; | 997 if (receiverConstant == null) return null; |
992 Operator op = send.selector; | 998 Operator op = send.selector; |
993 Constant folded; | 999 Constant folded; |
994 switch (op.source.stringValue) { | 1000 switch (op.source.stringValue) { |
995 case "!": | 1001 case "!": |
996 folded = const NotOperation().fold(receiverConstant); | 1002 folded = constantSystem.not.fold(receiverConstant); |
997 break; | 1003 break; |
998 case "-": | 1004 case "-": |
999 folded = const NegateOperation().fold(receiverConstant); | 1005 folded = constantSystem.negate.fold(receiverConstant); |
1000 break; | 1006 break; |
1001 case "~": | 1007 case "~": |
1002 folded = const BitNotOperation().fold(receiverConstant); | 1008 folded = constantSystem.bitNot.fold(receiverConstant); |
1003 break; | 1009 break; |
1004 default: | 1010 default: |
1005 compiler.internalError("Unexpected operator.", node: op); | 1011 compiler.internalError("Unexpected operator.", node: op); |
1006 break; | 1012 break; |
1007 } | 1013 } |
1008 if (folded === null) return signalNotCompileTimeConstant(send); | 1014 if (folded === null) return signalNotCompileTimeConstant(send); |
1009 return folded; | 1015 return folded; |
1010 } else if (send.isOperator && !send.isPostfix) { | 1016 } else if (send.isOperator && !send.isPostfix) { |
1011 assert(send.argumentCount() == 1); | 1017 assert(send.argumentCount() == 1); |
1012 Constant left = evaluate(send.receiver); | 1018 Constant left = evaluate(send.receiver); |
1013 Constant right = evaluate(send.argumentsNode.nodes.head); | 1019 Constant right = evaluate(send.argumentsNode.nodes.head); |
1014 if (left == null || right == null) return null; | 1020 if (left == null || right == null) return null; |
1015 Operator op = send.selector.asOperator(); | 1021 Operator op = send.selector.asOperator(); |
1016 Constant folded = null; | 1022 Constant folded = null; |
1017 switch (op.source.stringValue) { | 1023 switch (op.source.stringValue) { |
1018 case "+": | 1024 case "+": |
1019 folded = const AddOperation().fold(left, right); | 1025 folded = constantSystem.add.fold(left, right); |
1020 break; | 1026 break; |
1021 case "-": | 1027 case "-": |
1022 folded = const SubtractOperation().fold(left, right); | 1028 folded = constantSystem.subtract.fold(left, right); |
1023 break; | 1029 break; |
1024 case "*": | 1030 case "*": |
1025 folded = const MultiplyOperation().fold(left, right); | 1031 folded = constantSystem.multiply.fold(left, right); |
1026 break; | 1032 break; |
1027 case "/": | 1033 case "/": |
1028 folded = const DivideOperation().fold(left, right); | 1034 folded = constantSystem.divide.fold(left, right); |
1029 break; | 1035 break; |
1030 case "%": | 1036 case "%": |
1031 folded = const ModuloOperation().fold(left, right); | 1037 folded = constantSystem.modulo.fold(left, right); |
1032 break; | 1038 break; |
1033 case "~/": | 1039 case "~/": |
1034 folded = const TruncatingDivideOperation().fold(left, right); | 1040 folded = constantSystem.truncatingDivide.fold(left, right); |
1035 break; | 1041 break; |
1036 case "|": | 1042 case "|": |
1037 folded = const BitOrOperation().fold(left, right); | 1043 folded = constantSystem.bitOr.fold(left, right); |
1038 break; | 1044 break; |
1039 case "&": | 1045 case "&": |
1040 folded = const BitAndOperation().fold(left, right); | 1046 folded = constantSystem.bitAnd.fold(left, right); |
1041 break; | 1047 break; |
1042 case "^": | 1048 case "^": |
1043 folded = const BitXorOperation().fold(left, right); | 1049 folded = constantSystem.bitXor.fold(left, right); |
1044 break; | 1050 break; |
1045 case "||": | 1051 case "||": |
1046 folded = const BooleanOr().fold(left, right); | 1052 folded = constantSystem.booleanOr.fold(left, right); |
1047 break; | 1053 break; |
1048 case "&&": | 1054 case "&&": |
1049 folded = const BooleanAnd().fold(left, right); | 1055 folded = constantSystem.booleanAnd.fold(left, right); |
1050 break; | 1056 break; |
1051 case "<<": | 1057 case "<<": |
1052 folded = const ShiftLeftOperation().fold(left, right); | 1058 folded = constantSystem.shiftLeft.fold(left, right); |
1053 break; | 1059 break; |
1054 case ">>": | 1060 case ">>": |
1055 folded = const ShiftRightOperation().fold(left, right); | 1061 folded = constantSystem.shiftRight.fold(left, right); |
1056 break; | 1062 break; |
1057 case "<": | 1063 case "<": |
1058 folded = const LessOperation().fold(left, right); | 1064 folded = constantSystem.less.fold(left, right); |
1059 break; | 1065 break; |
1060 case "<=": | 1066 case "<=": |
1061 folded = const LessEqualOperation().fold(left, right); | 1067 folded = constantSystem.lessEqual.fold(left, right); |
1062 break; | 1068 break; |
1063 case ">": | 1069 case ">": |
1064 folded = const GreaterOperation().fold(left, right); | 1070 folded = constantSystem.greater.fold(left, right); |
1065 break; | 1071 break; |
1066 case ">=": | 1072 case ">=": |
1067 folded = const GreaterEqualOperation().fold(left, right); | 1073 folded = constantSystem.greaterEqual.fold(left, right); |
1068 break; | 1074 break; |
1069 case "==": | 1075 case "==": |
1070 if (left.isPrimitive() && right.isPrimitive()) { | 1076 if (left.isPrimitive() && right.isPrimitive()) { |
1071 folded = const EqualsOperation().fold(left, right); | 1077 folded = constantSystem.equal.fold(left, right); |
1072 } | 1078 } |
1073 break; | 1079 break; |
1074 case "===": | 1080 case "===": |
1075 if (left.isPrimitive() && right.isPrimitive()) { | 1081 if (left.isPrimitive() && right.isPrimitive()) { |
1076 folded = const IdentityOperation().fold(left, right); | 1082 folded = constantSystem.identity.fold(left, right); |
1077 } | 1083 } |
1078 break; | 1084 break; |
1079 case "!=": | 1085 case "!=": |
1080 if (left.isPrimitive() && right.isPrimitive()) { | 1086 if (left.isPrimitive() && right.isPrimitive()) { |
1081 BoolConstant areEquals = const EqualsOperation().fold(left, right); | 1087 BoolConstant areEquals = constantSystem.equal.fold(left, right); |
1082 if (areEquals === null) { | 1088 if (areEquals === null) { |
1083 folded = null; | 1089 folded = null; |
1084 } else { | 1090 } else { |
1085 folded = areEquals.negate(); | 1091 folded = areEquals.negate(); |
1086 } | 1092 } |
1087 } | 1093 } |
1088 break; | 1094 break; |
1089 case "!==": | 1095 case "!==": |
1090 if (left.isPrimitive() && right.isPrimitive()) { | 1096 if (left.isPrimitive() && right.isPrimitive()) { |
1091 BoolConstant areIdentical = | 1097 BoolConstant areIdentical = |
1092 const IdentityOperation().fold(left, right); | 1098 constantSystem.identity.fold(left, right); |
1093 if (areIdentical === null) { | 1099 if (areIdentical === null) { |
1094 folded = null; | 1100 folded = null; |
1095 } else { | 1101 } else { |
1096 folded = areIdentical.negate(); | 1102 folded = areIdentical.negate(); |
1097 } | 1103 } |
1098 } | 1104 } |
1099 break; | 1105 break; |
1100 } | 1106 } |
1101 if (folded === null) return signalNotCompileTimeConstant(send); | 1107 if (folded === null) return signalNotCompileTimeConstant(send); |
1102 return folded; | 1108 return folded; |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1137 if (classElement.isInterface()) { | 1143 if (classElement.isInterface()) { |
1138 compiler.resolver.resolveMethodElement(constructor); | 1144 compiler.resolver.resolveMethodElement(constructor); |
1139 constructor = constructor.defaultImplementation; | 1145 constructor = constructor.defaultImplementation; |
1140 classElement = constructor.getEnclosingClass(); | 1146 classElement = constructor.getEnclosingClass(); |
1141 } | 1147 } |
1142 | 1148 |
1143 Selector selector = elements.getSelector(send); | 1149 Selector selector = elements.getSelector(send); |
1144 List<Constant> arguments = | 1150 List<Constant> arguments = |
1145 evaluateArgumentsToConstructor(selector, send.arguments, constructor); | 1151 evaluateArgumentsToConstructor(selector, send.arguments, constructor); |
1146 ConstructorEvaluator evaluator = | 1152 ConstructorEvaluator evaluator = |
1147 new ConstructorEvaluator(constructor, compiler); | 1153 new ConstructorEvaluator(constructor, constantSystem, compiler); |
1148 evaluator.evaluateConstructorFieldValues(arguments); | 1154 evaluator.evaluateConstructorFieldValues(arguments); |
1149 List<Constant> jsNewArguments = evaluator.buildJsNewArguments(classElement); | 1155 List<Constant> jsNewArguments = evaluator.buildJsNewArguments(classElement); |
1150 | 1156 |
1151 compiler.registerInstantiatedClass(classElement); | 1157 compiler.registerInstantiatedClass(classElement); |
1152 // TODO(floitsch): take generic types into account. | 1158 // TODO(floitsch): take generic types into account. |
1153 DartType type = classElement.computeType(compiler); | 1159 DartType type = classElement.computeType(compiler); |
1154 Constant constant = new ConstructedConstant(type, jsNewArguments); | 1160 Constant constant = new ConstructedConstant(type, jsNewArguments); |
1155 compiler.constantHandler.registerCompileTimeConstant(constant); | 1161 compiler.constantHandler.registerCompileTimeConstant(constant); |
1156 return constant; | 1162 return constant; |
1157 } | 1163 } |
(...skipping 16 matching lines...) Expand all Loading... |
1174 // Else we don't need to do anything. The final handler is only | 1180 // Else we don't need to do anything. The final handler is only |
1175 // optimistically trying to compile constants. So it is normal that we | 1181 // optimistically trying to compile constants. So it is normal that we |
1176 // sometimes see non-compile time constants. | 1182 // sometimes see non-compile time constants. |
1177 // Simply return [:null:] which is used to propagate a failing | 1183 // Simply return [:null:] which is used to propagate a failing |
1178 // compile-time compilation. | 1184 // compile-time compilation. |
1179 return null; | 1185 return null; |
1180 } | 1186 } |
1181 } | 1187 } |
1182 | 1188 |
1183 class TryCompileTimeConstantEvaluator extends CompileTimeConstantEvaluator { | 1189 class TryCompileTimeConstantEvaluator extends CompileTimeConstantEvaluator { |
1184 TryCompileTimeConstantEvaluator(TreeElements elements, Compiler compiler): | 1190 TryCompileTimeConstantEvaluator(ConstantSystem constantSystem, |
1185 super(elements, compiler, isConst: true); | 1191 TreeElements elements, |
| 1192 Compiler compiler) |
| 1193 : super(constantSystem, elements, compiler, isConst: true); |
1186 | 1194 |
1187 error(Node node) { | 1195 error(Node node) { |
1188 // Just fail without reporting it anywhere. | 1196 // Just fail without reporting it anywhere. |
1189 throw new CompileTimeConstantError( | 1197 throw new CompileTimeConstantError( |
1190 MessageKind.NOT_A_COMPILE_TIME_CONSTANT, const []); | 1198 MessageKind.NOT_A_COMPILE_TIME_CONSTANT, const []); |
1191 } | 1199 } |
1192 } | 1200 } |
1193 | 1201 |
1194 class ConstructorEvaluator extends CompileTimeConstantEvaluator { | 1202 class ConstructorEvaluator extends CompileTimeConstantEvaluator { |
1195 FunctionElement constructor; | 1203 FunctionElement constructor; |
1196 final Map<Element, Constant> definitions; | 1204 final Map<Element, Constant> definitions; |
1197 final Map<Element, Constant> fieldValues; | 1205 final Map<Element, Constant> fieldValues; |
1198 | 1206 |
1199 ConstructorEvaluator(FunctionElement constructor, Compiler compiler) | 1207 ConstructorEvaluator(FunctionElement constructor, |
| 1208 ConstantSystem constantSystem, |
| 1209 Compiler compiler) |
1200 : this.constructor = constructor, | 1210 : this.constructor = constructor, |
1201 this.definitions = new Map<Element, Constant>(), | 1211 this.definitions = new Map<Element, Constant>(), |
1202 this.fieldValues = new Map<Element, Constant>(), | 1212 this.fieldValues = new Map<Element, Constant>(), |
1203 super(compiler.resolver.resolveMethodElement(constructor), | 1213 super(constantSystem, |
| 1214 compiler.resolver.resolveMethodElement(constructor), |
1204 compiler, | 1215 compiler, |
1205 isConst: true); | 1216 isConst: true); |
1206 | 1217 |
1207 Constant visitSend(Send send) { | 1218 Constant visitSend(Send send) { |
1208 Element element = elements[send]; | 1219 Element element = elements[send]; |
1209 if (Elements.isLocal(element)) { | 1220 if (Elements.isLocal(element)) { |
1210 Constant constant = definitions[element]; | 1221 Constant constant = definitions[element]; |
1211 if (constant === null) { | 1222 if (constant === null) { |
1212 compiler.internalError("Local variable without value", node: send); | 1223 compiler.internalError("Local variable without value", node: send); |
1213 } | 1224 } |
(...skipping 20 matching lines...) Expand all Loading... |
1234 } | 1245 } |
1235 }); | 1246 }); |
1236 } | 1247 } |
1237 | 1248 |
1238 void evaluateSuperOrRedirectSend(Selector selector, | 1249 void evaluateSuperOrRedirectSend(Selector selector, |
1239 Link<Node> arguments, | 1250 Link<Node> arguments, |
1240 FunctionElement targetConstructor) { | 1251 FunctionElement targetConstructor) { |
1241 List<Constant> compiledArguments = | 1252 List<Constant> compiledArguments = |
1242 evaluateArgumentsToConstructor(selector, arguments, targetConstructor); | 1253 evaluateArgumentsToConstructor(selector, arguments, targetConstructor); |
1243 | 1254 |
1244 ConstructorEvaluator evaluator = | 1255 ConstructorEvaluator evaluator = new ConstructorEvaluator( |
1245 new ConstructorEvaluator(targetConstructor, compiler); | 1256 targetConstructor, constantSystem, compiler); |
1246 evaluator.evaluateConstructorFieldValues(compiledArguments); | 1257 evaluator.evaluateConstructorFieldValues(compiledArguments); |
1247 // Copy over the fieldValues from the super/redirect-constructor. | 1258 // Copy over the fieldValues from the super/redirect-constructor. |
1248 evaluator.fieldValues.forEach((key, value) => fieldValues[key] = value); | 1259 evaluator.fieldValues.forEach((key, value) => fieldValues[key] = value); |
1249 } | 1260 } |
1250 | 1261 |
1251 /** | 1262 /** |
1252 * Runs through the initializers of the given [constructor] and updates | 1263 * Runs through the initializers of the given [constructor] and updates |
1253 * the [fieldValues] map. | 1264 * the [fieldValues] map. |
1254 */ | 1265 */ |
1255 void evaluateConstructorInitializers() { | 1266 void evaluateConstructorInitializers() { |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1328 Constant fieldValue = fieldValues[field]; | 1339 Constant fieldValue = fieldValues[field]; |
1329 if (fieldValue === null) { | 1340 if (fieldValue === null) { |
1330 // Use the default value. | 1341 // Use the default value. |
1331 fieldValue = compiler.compileConstant(field); | 1342 fieldValue = compiler.compileConstant(field); |
1332 } | 1343 } |
1333 jsNewArguments.add(fieldValue); | 1344 jsNewArguments.add(fieldValue); |
1334 }); | 1345 }); |
1335 return jsNewArguments; | 1346 return jsNewArguments; |
1336 } | 1347 } |
1337 } | 1348 } |
OLD | NEW |