Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(269)

Side by Side Diff: lib/compiler/implementation/compile_time_constants.dart

Issue 10825386: Use JavaScript runtime semantics when constant folding. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Update status file. Created 8 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 24
25 bool isNaN() => false; 25 bool isNaN() => false;
26 bool isMinusZero() => false;
26 27
27 abstract void _writeJsCode(CodeBuffer buffer, ConstantHandler handler); 28 abstract void _writeJsCode(CodeBuffer buffer, ConstantHandler handler);
28 /** 29 /**
29 * Unless the constant can be emitted multiple times (as for numbers and 30 * Unless the constant can be emitted multiple times (as for numbers and
30 * strings) adds its canonical name to the buffer. 31 * strings) adds its canonical name to the buffer.
31 */ 32 */
32 abstract void _writeCanonicalizedJsCode(CodeBuffer buffer, 33 abstract void _writeCanonicalizedJsCode(CodeBuffer buffer,
33 ConstantHandler handler); 34 ConstantHandler handler);
34 abstract List<Constant> getDependencies(); 35 abstract List<Constant> getDependencies();
35 } 36 }
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after
164 return const DoubleConstant._internal(0.0); 165 return const DoubleConstant._internal(0.0);
165 } else if (value == 1.0) { 166 } else if (value == 1.0) {
166 return const DoubleConstant._internal(1.0); 167 return const DoubleConstant._internal(1.0);
167 } else { 168 } else {
168 return new DoubleConstant._internal(value); 169 return new DoubleConstant._internal(value);
169 } 170 }
170 } 171 }
171 const DoubleConstant._internal(this.value); 172 const DoubleConstant._internal(this.value);
172 bool isDouble() => true; 173 bool isDouble() => true;
173 bool isNaN() => value.isNaN(); 174 bool isNaN() => value.isNaN();
175 // We need to check for the negative sign since -0.0 == 0.0.
176 bool isMinusZero() => value == 0.0 && value.isNegative();
174 177
175 void _writeJsCode(CodeBuffer buffer, ConstantHandler handler) { 178 void _writeJsCode(CodeBuffer buffer, ConstantHandler handler) {
176 if (value.isNaN()) { 179 if (value.isNaN()) {
177 buffer.add("(0/0)"); 180 buffer.add("(0/0)");
178 } else if (value == double.INFINITY) { 181 } else if (value == double.INFINITY) {
179 buffer.add("(1/0)"); 182 buffer.add("(1/0)");
180 } else if (value == -double.INFINITY) { 183 } else if (value == -double.INFINITY) {
181 buffer.add("(-1/0)"); 184 buffer.add("(-1/0)");
182 } else { 185 } else {
183 buffer.add("$value"); 186 buffer.add("$value");
(...skipping 17 matching lines...) Expand all
201 DartString toDartString() => new DartString.literal(value.toString()); 204 DartString toDartString() => new DartString.literal(value.toString());
202 } 205 }
203 206
204 class BoolConstant extends PrimitiveConstant { 207 class BoolConstant extends PrimitiveConstant {
205 factory BoolConstant(value) { 208 factory BoolConstant(value) {
206 return value ? new TrueConstant() : new FalseConstant(); 209 return value ? new TrueConstant() : new FalseConstant();
207 } 210 }
208 const BoolConstant._internal(); 211 const BoolConstant._internal();
209 bool isBool() => true; 212 bool isBool() => true;
210 213
211 BoolConstant unaryFold(String op) {
212 if (op == "!") return new BoolConstant(!value);
213 return null;
214 }
215
216 abstract BoolConstant negate(); 214 abstract BoolConstant negate();
217 } 215 }
218 216
219 class TrueConstant extends BoolConstant { 217 class TrueConstant extends BoolConstant {
220 final bool value = true; 218 final bool value = true;
221 219
222 factory TrueConstant() => const TrueConstant._internal(); 220 factory TrueConstant() => const TrueConstant._internal();
223 const TrueConstant._internal() : super._internal(); 221 const TrueConstant._internal() : super._internal();
224 bool isTrue() => true; 222 bool isTrue() => true;
225 223
(...skipping 279 matching lines...) Expand 10 before | Expand all | Expand 10 after
505 int hashCode() => _hashCode; 503 int hashCode() => _hashCode;
506 List<Constant> getDependencies() => fields; 504 List<Constant> getDependencies() => fields;
507 } 505 }
508 506
509 /** 507 /**
510 * The [ConstantHandler] keeps track of compile-time constants, 508 * The [ConstantHandler] keeps track of compile-time constants,
511 * initializations of global and static fields, and default values of 509 * initializations of global and static fields, and default values of
512 * optional parameters. 510 * optional parameters.
513 */ 511 */
514 class ConstantHandler extends CompilerTask { 512 class ConstantHandler extends CompilerTask {
513 final ConstantSystem constantSystem;
515 // Contains the initial value of fields. Must contain all static and global 514 // Contains the initial value of fields. Must contain all static and global
516 // initializations of used fields. May contain caches for instance fields. 515 // initializations of used fields. May contain caches for instance fields.
517 final Map<VariableElement, Constant> initialVariableValues; 516 final Map<VariableElement, Constant> initialVariableValues;
518 517
519 // Map from compile-time constants to their JS name. 518 // Map from compile-time constants to their JS name.
520 final Map<Constant, String> compiledConstants; 519 final Map<Constant, String> compiledConstants;
521 520
522 // The set of variable elements that are in the process of being computed. 521 // The set of variable elements that are in the process of being computed.
523 final Set<VariableElement> pendingVariables; 522 final Set<VariableElement> pendingVariables;
524 523
525 ConstantHandler(Compiler compiler) 524 ConstantHandler(Compiler compiler, this.constantSystem)
526 : initialVariableValues = new Map<VariableElement, Dynamic>(), 525 : initialVariableValues = new Map<VariableElement, Dynamic>(),
527 compiledConstants = new Map<Constant, String>(), 526 compiledConstants = new Map<Constant, String>(),
528 pendingVariables = new Set<VariableElement>(), 527 pendingVariables = new Set<VariableElement>(),
529 super(compiler); 528 super(compiler);
530 String get name => 'ConstantHandler'; 529 String get name => 'ConstantHandler';
531 530
532 void registerCompileTimeConstant(Constant constant) { 531 void registerCompileTimeConstant(Constant constant) {
533 Function ifAbsentThunk = (() { 532 Function ifAbsentThunk = (() {
534 return constant.isFunction() 533 return constant.isFunction()
535 ? null : compiler.namer.getFreshGlobalName("CTC"); 534 ? null : compiler.namer.getFreshGlobalName("CTC");
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
591 } 590 }
592 initialVariableValues[element] = value; 591 initialVariableValues[element] = value;
593 pendingVariables.remove(element); 592 pendingVariables.remove(element);
594 return value; 593 return value;
595 }); 594 });
596 } 595 }
597 596
598 Constant compileNodeWithDefinitions(Node node, TreeElements definitions) { 597 Constant compileNodeWithDefinitions(Node node, TreeElements definitions) {
599 return measure(() { 598 return measure(() {
600 assert(node !== null); 599 assert(node !== null);
601 CompileTimeConstantEvaluator evaluator = 600 CompileTimeConstantEvaluator evaluator = new CompileTimeConstantEvaluator(
602 new CompileTimeConstantEvaluator(definitions, compiler); 601 constantSystem, definitions, compiler);
603 return evaluator.evaluate(node); 602 return evaluator.evaluate(node);
604 }); 603 });
605 } 604 }
606 605
607 /** Attempts to compile a constant expression. Returns null if not possible */ 606 /** Attempts to compile a constant expression. Returns null if not possible */
608 Constant tryCompileNodeWithDefinitions(Node node, TreeElements definitions) { 607 Constant tryCompileNodeWithDefinitions(Node node, TreeElements definitions) {
609 return measure(() { 608 return measure(() {
610 assert(node !== null); 609 assert(node !== null);
611 try { 610 try {
612 TryCompileTimeConstantEvaluator evaluator = 611 TryCompileTimeConstantEvaluator evaluator =
613 new TryCompileTimeConstantEvaluator(definitions, compiler); 612 new TryCompileTimeConstantEvaluator(constantSystem,
613 definitions,
614 compiler);
614 return evaluator.evaluate(node); 615 return evaluator.evaluate(node);
615 } on CompileTimeConstantError catch (exn) { 616 } on CompileTimeConstantError catch (exn) {
616 return null; 617 return null;
617 } 618 }
618 }); 619 });
619 } 620 }
620 621
621 /** 622 /**
622 * Returns a [List] of static non final fields that need to be initialized. 623 * Returns a [List] of static non final fields that need to be initialized.
623 * The list must be evaluated in order since the fields might depend on each 624 * 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
740 } 741 }
741 } 742 }
742 } 743 }
743 744
744 String getJsConstructor(ClassElement element) { 745 String getJsConstructor(ClassElement element) {
745 return compiler.namer.isolatePropertiesAccess(element); 746 return compiler.namer.isolatePropertiesAccess(element);
746 } 747 }
747 } 748 }
748 749
749 class CompileTimeConstantEvaluator extends AbstractVisitor { 750 class CompileTimeConstantEvaluator extends AbstractVisitor {
751 final ConstantSystem constantSystem;
750 final TreeElements elements; 752 final TreeElements elements;
751 final Compiler compiler; 753 final Compiler compiler;
752 754
753 CompileTimeConstantEvaluator(this.elements, this.compiler); 755 CompileTimeConstantEvaluator(this.constantSystem,
756 this.elements,
757 this.compiler);
754 758
755 Constant evaluate(Node node) { 759 Constant evaluate(Node node) {
756 return node.accept(this); 760 return node.accept(this);
757 } 761 }
758 762
759 visitNode(Node node) { 763 visitNode(Node node) {
760 error(node); 764 error(node);
761 } 765 }
762 766
763 Constant visitLiteralBool(LiteralBool node) { 767 Constant visitLiteralBool(LiteralBool node) {
764 return new BoolConstant(node.value); 768 return constantSystem.createBool(node.value);
765 } 769 }
766 770
767 Constant visitLiteralDouble(LiteralDouble node) { 771 Constant visitLiteralDouble(LiteralDouble node) {
768 return new DoubleConstant(node.value); 772 return constantSystem.createDouble(node.value);
769 } 773 }
770 774
771 Constant visitLiteralInt(LiteralInt node) { 775 Constant visitLiteralInt(LiteralInt node) {
772 return new IntConstant(node.value); 776 return constantSystem.createInt(node.value);
773 } 777 }
774 778
775 Constant visitLiteralList(LiteralList node) { 779 Constant visitLiteralList(LiteralList node) {
776 if (!node.isConst()) error(node); 780 if (!node.isConst()) error(node);
777 List<Constant> arguments = <Constant>[]; 781 List<Constant> arguments = <Constant>[];
778 for (Link<Node> link = node.elements.nodes; 782 for (Link<Node> link = node.elements.nodes;
779 !link.isEmpty(); 783 !link.isEmpty();
780 link = link.tail) { 784 link = link.tail) {
781 arguments.add(evaluate(link.head)); 785 arguments.add(evaluate(link.head));
782 } 786 }
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
825 classElement.ensureResolved(compiler); 829 classElement.ensureResolved(compiler);
826 // TODO(floitsch): copy over the generic type. 830 // TODO(floitsch): copy over the generic type.
827 DartType type = new InterfaceType(classElement); 831 DartType type = new InterfaceType(classElement);
828 compiler.registerInstantiatedClass(classElement); 832 compiler.registerInstantiatedClass(classElement);
829 Constant constant = new MapConstant(type, keysList, values, protoValue); 833 Constant constant = new MapConstant(type, keysList, values, protoValue);
830 compiler.constantHandler.registerCompileTimeConstant(constant); 834 compiler.constantHandler.registerCompileTimeConstant(constant);
831 return constant; 835 return constant;
832 } 836 }
833 837
834 Constant visitLiteralNull(LiteralNull node) { 838 Constant visitLiteralNull(LiteralNull node) {
835 return new NullConstant(); 839 return constantSystem.createNull();
836 } 840 }
837 841
838 Constant visitLiteralString(LiteralString node) { 842 Constant visitLiteralString(LiteralString node) {
839 return new StringConstant(node.dartString, node); 843 return constantSystem.createString(node.dartString, node);
840 } 844 }
841 845
842 Constant visitStringJuxtaposition(StringJuxtaposition node) { 846 Constant visitStringJuxtaposition(StringJuxtaposition node) {
843 StringConstant left = evaluate(node.first); 847 StringConstant left = evaluate(node.first);
844 StringConstant right = evaluate(node.second); 848 StringConstant right = evaluate(node.second);
845 return new StringConstant(new DartString.concat(left.value, right.value), 849 return constantSystem.createString(
846 node); 850 new DartString.concat(left.value, right.value), node);
847 } 851 }
848 852
849 Constant visitStringInterpolation(StringInterpolation node) { 853 Constant visitStringInterpolation(StringInterpolation node) {
850 StringConstant initialString = evaluate(node.string); 854 StringConstant initialString = evaluate(node.string);
851 DartString accumulator = initialString.value; 855 DartString accumulator = initialString.value;
852 for (StringInterpolationPart part in node.parts) { 856 for (StringInterpolationPart part in node.parts) {
853 Constant expression = evaluate(part.expression); 857 Constant expression = evaluate(part.expression);
854 DartString expressionString; 858 DartString expressionString;
855 if (expression.isNum() || expression.isBool()) { 859 if (expression.isNum() || expression.isBool()) {
856 PrimitiveConstant primitive = expression; 860 PrimitiveConstant primitive = expression;
857 expressionString = new DartString.literal(primitive.value.toString()); 861 expressionString = new DartString.literal(primitive.value.toString());
858 } else if (expression.isString()) { 862 } else if (expression.isString()) {
859 PrimitiveConstant primitive = expression; 863 PrimitiveConstant primitive = expression;
860 expressionString = primitive.value; 864 expressionString = primitive.value;
861 } else { 865 } else {
862 error(part.expression); 866 error(part.expression);
863 } 867 }
864 accumulator = new DartString.concat(accumulator, expressionString); 868 accumulator = new DartString.concat(accumulator, expressionString);
865 StringConstant partString = evaluate(part.string); 869 StringConstant partString = evaluate(part.string);
866 accumulator = new DartString.concat(accumulator, partString.value); 870 accumulator = new DartString.concat(accumulator, partString.value);
867 }; 871 };
868 return new StringConstant(accumulator, node); 872 return constantSystem.createString(accumulator, node);
869 } 873 }
870 874
871 // TODO(floitsch): provide better error-messages. 875 // TODO(floitsch): provide better error-messages.
872 Constant visitSend(Send send) { 876 Constant visitSend(Send send) {
873 Element element = elements[send]; 877 Element element = elements[send];
874 if (Elements.isStaticOrTopLevelField(element)) { 878 if (Elements.isStaticOrTopLevelField(element)) {
875 if (element.modifiers === null || 879 if (element.modifiers === null ||
876 // TODO(johnniwinther): This should eventually be [isConst]. 880 // TODO(johnniwinther): This should eventually be [isConst].
877 !element.modifiers.isFinalOrConst()) { 881 !element.modifiers.isFinalOrConst()) {
878 error(send); 882 error(send);
879 } 883 }
880 return compiler.compileVariable(element); 884 return compiler.compileVariable(element);
881 } else if (Elements.isStaticOrTopLevelFunction(element) 885 } else if (Elements.isStaticOrTopLevelFunction(element)
882 && send.isPropertyAccess) { 886 && send.isPropertyAccess) {
883 compiler.codegenWorld.staticFunctionsNeedingGetter.add(element); 887 compiler.codegenWorld.staticFunctionsNeedingGetter.add(element);
884 Constant constant = new FunctionConstant(element); 888 Constant constant = new FunctionConstant(element);
885 compiler.constantHandler.registerCompileTimeConstant(constant); 889 compiler.constantHandler.registerCompileTimeConstant(constant);
886 return constant; 890 return constant;
887 } else if (send.isPrefix) { 891 } else if (send.isPrefix) {
888 assert(send.isOperator); 892 assert(send.isOperator);
889 Constant receiverConstant = evaluate(send.receiver); 893 Constant receiverConstant = evaluate(send.receiver);
890 Operator op = send.selector; 894 Operator op = send.selector;
891 Constant folded; 895 Constant folded;
892 switch (op.source.stringValue) { 896 switch (op.source.stringValue) {
893 case "!": 897 case "!":
894 folded = const NotOperation().fold(receiverConstant); 898 folded = constantSystem.not.fold(receiverConstant);
895 break; 899 break;
896 case "-": 900 case "-":
897 folded = const NegateOperation().fold(receiverConstant); 901 folded = constantSystem.negate.fold(receiverConstant);
898 break; 902 break;
899 case "~": 903 case "~":
900 folded = const BitNotOperation().fold(receiverConstant); 904 folded = constantSystem.bitNot.fold(receiverConstant);
901 break; 905 break;
902 default: 906 default:
903 compiler.internalError("Unexpected operator.", node: op); 907 compiler.internalError("Unexpected operator.", node: op);
904 break; 908 break;
905 } 909 }
906 if (folded === null) error(send); 910 if (folded === null) error(send);
907 return folded; 911 return folded;
908 } else if (send.isOperator && !send.isPostfix) { 912 } else if (send.isOperator && !send.isPostfix) {
909 assert(send.argumentCount() == 1); 913 assert(send.argumentCount() == 1);
910 Constant left = evaluate(send.receiver); 914 Constant left = evaluate(send.receiver);
911 Constant right = evaluate(send.argumentsNode.nodes.head); 915 Constant right = evaluate(send.argumentsNode.nodes.head);
912 Operator op = send.selector.asOperator(); 916 Operator op = send.selector.asOperator();
913 Constant folded = null; 917 Constant folded = null;
914 switch (op.source.stringValue) { 918 switch (op.source.stringValue) {
915 case "+": 919 case "+":
916 folded = const AddOperation().fold(left, right); 920 folded = constantSystem.add.fold(left, right);
917 break; 921 break;
918 case "-": 922 case "-":
919 folded = const SubtractOperation().fold(left, right); 923 folded = constantSystem.subtract.fold(left, right);
920 break; 924 break;
921 case "*": 925 case "*":
922 folded = const MultiplyOperation().fold(left, right); 926 folded = constantSystem.multiply.fold(left, right);
923 break; 927 break;
924 case "/": 928 case "/":
925 folded = const DivideOperation().fold(left, right); 929 folded = constantSystem.divide.fold(left, right);
926 break; 930 break;
927 case "%": 931 case "%":
928 folded = const ModuloOperation().fold(left, right); 932 folded = constantSystem.modulo.fold(left, right);
929 break; 933 break;
930 case "~/": 934 case "~/":
931 folded = const TruncatingDivideOperation().fold(left, right); 935 folded = constantSystem.truncatingDivide.fold(left, right);
932 break; 936 break;
933 case "|": 937 case "|":
934 folded = const BitOrOperation().fold(left, right); 938 folded = constantSystem.bitOr.fold(left, right);
935 break; 939 break;
936 case "&": 940 case "&":
937 folded = const BitAndOperation().fold(left, right); 941 folded = constantSystem.bitAnd.fold(left, right);
938 break; 942 break;
939 case "^": 943 case "^":
940 folded = const BitXorOperation().fold(left, right); 944 folded = constantSystem.bitXor.fold(left, right);
941 break; 945 break;
942 case "||": 946 case "||":
943 folded = const BooleanOr().fold(left, right); 947 folded = constantSystem.booleanOr.fold(left, right);
944 break; 948 break;
945 case "&&": 949 case "&&":
946 folded = const BooleanAnd().fold(left, right); 950 folded = constantSystem.booleanAnd.fold(left, right);
947 break; 951 break;
948 case "<<": 952 case "<<":
949 folded = const ShiftLeftOperation().fold(left, right); 953 folded = constantSystem.shiftLeft.fold(left, right);
950 break; 954 break;
951 case ">>": 955 case ">>":
952 folded = const ShiftRightOperation().fold(left, right); 956 folded = constantSystem.shiftRight.fold(left, right);
953 break; 957 break;
954 case "<": 958 case "<":
955 folded = const LessOperation().fold(left, right); 959 folded = constantSystem.less.fold(left, right);
956 break; 960 break;
957 case "<=": 961 case "<=":
958 folded = const LessEqualOperation().fold(left, right); 962 folded = constantSystem.lessEqual.fold(left, right);
959 break; 963 break;
960 case ">": 964 case ">":
961 folded = const GreaterOperation().fold(left, right); 965 folded = constantSystem.greater.fold(left, right);
962 break; 966 break;
963 case ">=": 967 case ">=":
964 folded = const GreaterEqualOperation().fold(left, right); 968 folded = constantSystem.greaterEqual.fold(left, right);
965 break; 969 break;
966 case "==": 970 case "==":
967 if (left.isPrimitive() && right.isPrimitive()) { 971 if (left.isPrimitive() && right.isPrimitive()) {
968 folded = const EqualsOperation().fold(left, right); 972 folded = constantSystem.equal.fold(left, right);
969 } 973 }
970 break; 974 break;
971 case "===": 975 case "===":
972 if (left.isPrimitive() && right.isPrimitive()) { 976 if (left.isPrimitive() && right.isPrimitive()) {
973 folded = const IdentityOperation().fold(left, right); 977 folded = constantSystem.identity.fold(left, right);
974 } 978 }
975 break; 979 break;
976 case "!=": 980 case "!=":
977 if (left.isPrimitive() && right.isPrimitive()) { 981 if (left.isPrimitive() && right.isPrimitive()) {
978 BoolConstant areEquals = const EqualsOperation().fold(left, right); 982 BoolConstant areEquals = constantSystem.equal.fold(left, right);
979 if (areEquals === null) { 983 if (areEquals === null) {
980 folded = null; 984 folded = null;
981 } else { 985 } else {
982 folded = areEquals.negate(); 986 folded = areEquals.negate();
983 } 987 }
984 } 988 }
985 break; 989 break;
986 case "!==": 990 case "!==":
987 if (left.isPrimitive() && right.isPrimitive()) { 991 if (left.isPrimitive() && right.isPrimitive()) {
988 BoolConstant areIdentical = 992 BoolConstant areIdentical =
989 const IdentityOperation().fold(left, right); 993 constantSystem.identity.fold(left, right);
990 if (areIdentical === null) { 994 if (areIdentical === null) {
991 folded = null; 995 folded = null;
992 } else { 996 } else {
993 folded = areIdentical.negate(); 997 folded = areIdentical.negate();
994 } 998 }
995 } 999 }
996 break; 1000 break;
997 } 1001 }
998 if (folded === null) error(send); 1002 if (folded === null) error(send);
999 return folded; 1003 return folded;
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
1032 if (classElement.isInterface()) { 1036 if (classElement.isInterface()) {
1033 compiler.resolver.resolveMethodElement(constructor); 1037 compiler.resolver.resolveMethodElement(constructor);
1034 constructor = constructor.defaultImplementation; 1038 constructor = constructor.defaultImplementation;
1035 classElement = constructor.getEnclosingClass(); 1039 classElement = constructor.getEnclosingClass();
1036 } 1040 }
1037 1041
1038 Selector selector = elements.getSelector(send); 1042 Selector selector = elements.getSelector(send);
1039 List<Constant> arguments = 1043 List<Constant> arguments =
1040 evaluateArgumentsToConstructor(selector, send.arguments, constructor); 1044 evaluateArgumentsToConstructor(selector, send.arguments, constructor);
1041 ConstructorEvaluator evaluator = 1045 ConstructorEvaluator evaluator =
1042 new ConstructorEvaluator(constructor, compiler); 1046 new ConstructorEvaluator(constructor, constantSystem, compiler);
1043 evaluator.evaluateConstructorFieldValues(arguments); 1047 evaluator.evaluateConstructorFieldValues(arguments);
1044 List<Constant> jsNewArguments = evaluator.buildJsNewArguments(classElement); 1048 List<Constant> jsNewArguments = evaluator.buildJsNewArguments(classElement);
1045 1049
1046 compiler.registerInstantiatedClass(classElement); 1050 compiler.registerInstantiatedClass(classElement);
1047 // TODO(floitsch): take generic types into account. 1051 // TODO(floitsch): take generic types into account.
1048 DartType type = classElement.computeType(compiler); 1052 DartType type = classElement.computeType(compiler);
1049 Constant constant = new ConstructedConstant(type, jsNewArguments); 1053 Constant constant = new ConstructedConstant(type, jsNewArguments);
1050 compiler.constantHandler.registerCompileTimeConstant(constant); 1054 compiler.constantHandler.registerCompileTimeConstant(constant);
1051 return constant; 1055 return constant;
1052 } 1056 }
1053 1057
1054 Constant visitParenthesizedExpression(ParenthesizedExpression node) { 1058 Constant visitParenthesizedExpression(ParenthesizedExpression node) {
1055 return node.expression.accept(this); 1059 return node.expression.accept(this);
1056 } 1060 }
1057 1061
1058 error(Node node) { 1062 error(Node node) {
1059 // TODO(floitsch): get the list of constants that are currently compiled 1063 // TODO(floitsch): get the list of constants that are currently compiled
1060 // and present some kind of stack-trace. 1064 // and present some kind of stack-trace.
1061 MessageKind kind = MessageKind.NOT_A_COMPILE_TIME_CONSTANT; 1065 MessageKind kind = MessageKind.NOT_A_COMPILE_TIME_CONSTANT;
1062 compiler.reportError(node, new CompileTimeConstantError(kind, const [])); 1066 compiler.reportError(node, new CompileTimeConstantError(kind, const []));
1063 } 1067 }
1064 } 1068 }
1065 1069
1066 class TryCompileTimeConstantEvaluator extends CompileTimeConstantEvaluator { 1070 class TryCompileTimeConstantEvaluator extends CompileTimeConstantEvaluator {
1067 TryCompileTimeConstantEvaluator(TreeElements elements, Compiler compiler): 1071 TryCompileTimeConstantEvaluator(ConstantSystem constantSystem,
1068 super(elements, compiler); 1072 TreeElements elements,
1073 Compiler compiler):
1074 super(constantSystem, elements, compiler);
1069 1075
1070 error(Node node) { 1076 error(Node node) {
1071 // Just fail without reporting it anywhere. 1077 // Just fail without reporting it anywhere.
1072 throw new CompileTimeConstantError( 1078 throw new CompileTimeConstantError(
1073 MessageKind.NOT_A_COMPILE_TIME_CONSTANT, const []); 1079 MessageKind.NOT_A_COMPILE_TIME_CONSTANT, const []);
1074 } 1080 }
1075 } 1081 }
1076 1082
1077 class ConstructorEvaluator extends CompileTimeConstantEvaluator { 1083 class ConstructorEvaluator extends CompileTimeConstantEvaluator {
1078 FunctionElement constructor; 1084 FunctionElement constructor;
1079 final Map<Element, Constant> definitions; 1085 final Map<Element, Constant> definitions;
1080 final Map<Element, Constant> fieldValues; 1086 final Map<Element, Constant> fieldValues;
1081 1087
1082 ConstructorEvaluator(FunctionElement constructor, Compiler compiler) 1088 ConstructorEvaluator(FunctionElement constructor,
1089 ConstantSystem constantSystem,
1090 Compiler compiler)
1083 : this.constructor = constructor, 1091 : this.constructor = constructor,
1084 this.definitions = new Map<Element, Constant>(), 1092 this.definitions = new Map<Element, Constant>(),
1085 this.fieldValues = new Map<Element, Constant>(), 1093 this.fieldValues = new Map<Element, Constant>(),
1086 super(compiler.resolver.resolveMethodElement(constructor), 1094 super(constantSystem,
1095 compiler.resolver.resolveMethodElement(constructor),
1087 compiler); 1096 compiler);
1088 1097
1089 Constant visitSend(Send send) { 1098 Constant visitSend(Send send) {
1090 Element element = elements[send]; 1099 Element element = elements[send];
1091 if (Elements.isLocal(element)) { 1100 if (Elements.isLocal(element)) {
1092 Constant constant = definitions[element]; 1101 Constant constant = definitions[element];
1093 if (constant === null) { 1102 if (constant === null) {
1094 compiler.internalError("Local variable without value", node: send); 1103 compiler.internalError("Local variable without value", node: send);
1095 } 1104 }
1096 return constant; 1105 return constant;
(...skipping 19 matching lines...) Expand all
1116 } 1125 }
1117 }); 1126 });
1118 } 1127 }
1119 1128
1120 void evaluateSuperOrRedirectSend(Selector selector, 1129 void evaluateSuperOrRedirectSend(Selector selector,
1121 Link<Node> arguments, 1130 Link<Node> arguments,
1122 FunctionElement targetConstructor) { 1131 FunctionElement targetConstructor) {
1123 List<Constant> compiledArguments = 1132 List<Constant> compiledArguments =
1124 evaluateArgumentsToConstructor(selector, arguments, targetConstructor); 1133 evaluateArgumentsToConstructor(selector, arguments, targetConstructor);
1125 1134
1126 ConstructorEvaluator evaluator = 1135 ConstructorEvaluator evaluator = new ConstructorEvaluator(
1127 new ConstructorEvaluator(targetConstructor, compiler); 1136 targetConstructor, constantSystem, compiler);
1128 evaluator.evaluateConstructorFieldValues(compiledArguments); 1137 evaluator.evaluateConstructorFieldValues(compiledArguments);
1129 // Copy over the fieldValues from the super/redirect-constructor. 1138 // Copy over the fieldValues from the super/redirect-constructor.
1130 evaluator.fieldValues.forEach((key, value) => fieldValues[key] = value); 1139 evaluator.fieldValues.forEach((key, value) => fieldValues[key] = value);
1131 } 1140 }
1132 1141
1133 /** 1142 /**
1134 * Runs through the initializers of the given [constructor] and updates 1143 * Runs through the initializers of the given [constructor] and updates
1135 * the [fieldValues] map. 1144 * the [fieldValues] map.
1136 */ 1145 */
1137 void evaluateConstructorInitializers() { 1146 void evaluateConstructorInitializers() {
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
1210 Constant fieldValue = fieldValues[field]; 1219 Constant fieldValue = fieldValues[field];
1211 if (fieldValue === null) { 1220 if (fieldValue === null) {
1212 // Use the default value. 1221 // Use the default value.
1213 fieldValue = compiler.compileVariable(field); 1222 fieldValue = compiler.compileVariable(field);
1214 } 1223 }
1215 jsNewArguments.add(fieldValue); 1224 jsNewArguments.add(fieldValue);
1216 }); 1225 });
1217 return jsNewArguments; 1226 return jsNewArguments;
1218 } 1227 }
1219 } 1228 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698