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

Side by Side Diff: sdk/lib/_internal/compiler/implementation/ir/ir_builder.dart

Issue 348053002: dart2dart: Support for all constants in new backend. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: SVN rebase + merge Created 6 years, 6 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) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, 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 library dart2js.ir_builder; 5 library dart2js.ir_builder;
6 6
7 import 'ir_nodes.dart' as ir; 7 import 'ir_nodes.dart' as ir;
8 import '../elements/elements.dart'; 8 import '../elements/elements.dart';
9 import '../dart2jslib.dart'; 9 import '../dart2jslib.dart';
10 import '../dart_types.dart'; 10 import '../dart_types.dart';
11 import '../source_file.dart'; 11 import '../source_file.dart';
12 import '../tree/tree.dart' as ast; 12 import '../tree/tree.dart' as ast;
13 import '../scanner/scannerlib.dart' show Token, isUserDefinableOperator; 13 import '../scanner/scannerlib.dart' show Token, isUserDefinableOperator;
14 import '../dart_backend/dart_backend.dart' show DartBackend; 14 import '../dart_backend/dart_backend.dart' show DartBackend;
15 import '../universe/universe.dart' show SelectorKind; 15 import '../universe/universe.dart' show SelectorKind;
16 import '../util/util.dart' show Link; 16 import '../util/util.dart' show Link;
17 import '../helpers/helpers.dart';
17 18
18 /** 19 /**
19 * This task iterates through all resolved elements and builds [ir.Node]s. The 20 * This task iterates through all resolved elements and builds [ir.Node]s. The
20 * nodes are stored in the [nodes] map and accessible through [hasIr] and 21 * nodes are stored in the [nodes] map and accessible through [hasIr] and
21 * [getIr]. 22 * [getIr].
22 * 23 *
23 * The functionality of the IrNodes is added gradually, therefore elements might 24 * The functionality of the IrNodes is added gradually, therefore elements might
24 * have an IR or not, depending on the language features that are used. For 25 * have an IR or not, depending on the language features that are used. For
25 * elements that do have an IR, the tree [ast.Node]s and the [Token]s are not 26 * elements that do have an IR, the tree [ast.Node]s and the [Token]s are not
26 * used in the rest of the compilation. This is ensured by setting the element's 27 * used in the rest of the compilation. This is ensured by setting the element's
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
103 if (signature.optionalParameterCount > 0) return false; 104 if (signature.optionalParameterCount > 0) return false;
104 105
105 // TODO(kmillikin): support getters and setters and static class members. 106 // TODO(kmillikin): support getters and setters and static class members.
106 // With the current Dart Tree emitter they just require recognizing them 107 // With the current Dart Tree emitter they just require recognizing them
107 // and generating the correct syntax. 108 // and generating the correct syntax.
108 if (element.isGetter || element.isSetter) return false; 109 if (element.isGetter || element.isSetter) return false;
109 110
110 // TODO(lry): support native functions (also in [visitReturn]). 111 // TODO(lry): support native functions (also in [visitReturn]).
111 if (function.isNative) return false; 112 if (function.isNative) return false;
112 113
114 // TODO(asgerf): support syntax for redirecting factory constructors
115 if (function is ConstructorElement && function.isRedirectingFactory) {
116 return false;
117 }
118
113 return true; 119 return true;
114 } 120 }
115 121
116 bool get inCheckedMode { 122 bool get inCheckedMode {
117 bool result = false; 123 bool result = false;
118 assert((result = true)); 124 assert((result = true));
119 return result; 125 return result;
120 } 126 }
121 127
122 SourceFile elementSourceFile(Element element) { 128 SourceFile elementSourceFile(Element element) {
(...skipping 486 matching lines...) Expand 10 before | Expand all | Expand 10 after
609 entryArguments))); 615 entryArguments)));
610 current = resultContext; 616 current = resultContext;
611 } else { 617 } else {
612 add(resultContext); 618 add(resultContext);
613 } 619 }
614 return null; 620 return null;
615 } 621 }
616 622
617 ir.Primitive visitVariableDefinitions(ast.VariableDefinitions node) { 623 ir.Primitive visitVariableDefinitions(ast.VariableDefinitions node) {
618 assert(isOpen); 624 assert(isOpen);
625 if (node.modifiers.isConst) {
626 return giveup(node, 'Local const'); // TODO(asgerf): const vars
627 }
619 for (ast.Node definition in node.definitions.nodes) { 628 for (ast.Node definition in node.definitions.nodes) {
620 Element element = elements[definition]; 629 Element element = elements[definition];
621 // Definitions are either SendSets if there is an initializer, or 630 // Definitions are either SendSets if there is an initializer, or
622 // Identifiers if there is no initializer. 631 // Identifiers if there is no initializer.
623 if (definition is ast.SendSet) { 632 if (definition is ast.SendSet) {
624 assert(!definition.arguments.isEmpty); 633 assert(!definition.arguments.isEmpty);
625 assert(definition.arguments.tail.isEmpty); 634 assert(definition.arguments.tail.isEmpty);
626 ir.Primitive initialValue = visit(definition.arguments.head); 635 ir.Primitive initialValue = visit(definition.arguments.head);
627 // In case a primitive was introduced for the initializer expression, 636 // In case a primitive was introduced for the initializer expression,
628 // use this variable element to help derive a good name for it. 637 // use this variable element to help derive a good name for it.
(...skipping 16 matching lines...) Expand all
645 return null; 654 return null;
646 } 655 }
647 656
648 // Build(Return(e), C) = C'[InvokeContinuation(return, x)] 657 // Build(Return(e), C) = C'[InvokeContinuation(return, x)]
649 // where (C', x) = Build(e, C) 658 // where (C', x) = Build(e, C)
650 // 659 //
651 // Return without a subexpression is translated as if it were return null. 660 // Return without a subexpression is translated as if it were return null.
652 ir.Primitive visitReturn(ast.Return node) { 661 ir.Primitive visitReturn(ast.Return node) {
653 assert(isOpen); 662 assert(isOpen);
654 // TODO(lry): support native returns. 663 // TODO(lry): support native returns.
655 if (node.beginToken.value == 'native') return giveup(); 664 if (node.beginToken.value == 'native') return giveup(node, 'Native return');
656 ir.Primitive value; 665 ir.Primitive value;
657 if (node.expression == null) { 666 if (node.expression == null) {
658 value = new ir.Constant(constantSystem.createNull()); 667 value = new ir.Constant(constantSystem.createNull());
659 add(new ir.LetPrim(value)); 668 add(new ir.LetPrim(value));
660 } else { 669 } else {
661 value = visit(node.expression); 670 value = visit(node.expression);
662 } 671 }
663 add(new ir.InvokeContinuation(returnContinuation, [value])); 672 add(new ir.InvokeContinuation(returnContinuation, [value]));
664 current = null; 673 current = null;
665 return null; 674 return null;
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
762 } 771 }
763 772
764 Constant getConstantForNode(ast.Node node) { 773 Constant getConstantForNode(ast.Node node) {
765 Constant constant = 774 Constant constant =
766 compiler.backend.constants.getConstantForNode(node, elements); 775 compiler.backend.constants.getConstantForNode(node, elements);
767 assert(invariant(node, constant != null, 776 assert(invariant(node, constant != null,
768 message: 'No constant computed for $node')); 777 message: 'No constant computed for $node'));
769 return constant; 778 return constant;
770 } 779 }
771 780
772 bool isSupportedConst(Constant constant) {
773 return const SupportedConstantVisitor().visit(constant);
774 }
775
776 ir.Primitive visitLiteralList(ast.LiteralList node) { 781 ir.Primitive visitLiteralList(ast.LiteralList node) {
777 assert(isOpen); 782 assert(isOpen);
778 ir.Primitive result; 783 List<ir.Primitive> values = node.elements.nodes.mapToList(visit);
779 if (node.isConst) { 784 Constant constant = node.isConst ? getConstantForNode(node) : null;
780 // TODO(sigurdm): Remove when all constants are supported. 785 GenericType type = elements.getType(node);
781 Constant constant = getConstantForNode(node); 786 ir.Primitive result = new ir.LiteralList(type, values, constant);
782 if (!isSupportedConst(constant)) return giveup();
783 result = new ir.Constant(constant);
784 } else {
785 List<ir.Primitive> values = new List<ir.Primitive>();
786 node.elements.nodes.forEach((ast.Node node) {
787 values.add(visit(node));
788 });
789 result = new ir.LiteralList(values);
790 }
791 add(new ir.LetPrim(result)); 787 add(new ir.LetPrim(result));
792 return result; 788 return result;
793 } 789 }
794 790
795 ir.Primitive visitLiteralMap(ast.LiteralMap node) { 791 ir.Primitive visitLiteralMap(ast.LiteralMap node) {
796 assert(isOpen); 792 assert(isOpen);
797 ir.Primitive result; 793 List<ir.Primitive> keys = new List<ir.Primitive>();
798 if (node.isConst) { 794 List<ir.Primitive> values = new List<ir.Primitive>();
799 // TODO(sigurdm): Remove when all constants are supported. 795 node.entries.nodes.forEach((ast.LiteralMapEntry node) {
800 Constant constant = getConstantForNode(node); 796 keys.add(visit(node.key));
801 if (!isSupportedConst(constant)) return giveup(); 797 values.add(visit(node.value));
802 result = new ir.Constant(constant); 798 });
803 } else { 799 GenericType type = elements.getType(node);
804 List<ir.Primitive> keys = new List<ir.Primitive>(); 800 Constant constant = node.isConst ? getConstantForNode(node) : null;
805 List<ir.Primitive> values = new List<ir.Primitive>(); 801 ir.Primitive result = new ir.LiteralMap(type, keys, values, constant);
806 node.entries.nodes.forEach((ast.LiteralMapEntry node) {
807 keys.add(visit(node.key));
808 values.add(visit(node.value));
809 });
810 result = new ir.LiteralMap(keys, values);
811 }
812 add(new ir.LetPrim(result)); 802 add(new ir.LetPrim(result));
813 return result; 803 return result;
814 } 804 }
815 805
816 ir.Primitive visitLiteralSymbol(ast.LiteralSymbol node) { 806 ir.Primitive visitLiteralSymbol(ast.LiteralSymbol node) {
817 assert(isOpen); 807 assert(isOpen);
818 ir.Constant constant = new ir.Constant(getConstantForNode(node)); 808 ir.Constant constant = new ir.Constant(getConstantForNode(node));
819 add(new ir.LetPrim(constant)); 809 add(new ir.LetPrim(constant));
820 return constant; 810 return constant;
821 } 811 }
(...skipping 26 matching lines...) Expand all
848 838
849 ir.Primitive lookupLocal(Element element) { 839 ir.Primitive lookupLocal(Element element) {
850 int index = variableIndex[element]; 840 int index = variableIndex[element];
851 ir.Primitive value = assignedVars[index]; 841 ir.Primitive value = assignedVars[index];
852 return value == null ? freeVars[index] : value; 842 return value == null ? freeVars[index] : value;
853 } 843 }
854 844
855 // ==== Sends ==== 845 // ==== Sends ====
856 ir.Primitive visitAssert(ast.Send node) { 846 ir.Primitive visitAssert(ast.Send node) {
857 assert(isOpen); 847 assert(isOpen);
858 return giveup(); 848 return giveup(node, 'Assert');
859 } 849 }
860 850
861 ir.Primitive visitNamedArgument(ast.NamedArgument node) { 851 ir.Primitive visitNamedArgument(ast.NamedArgument node) {
862 assert(isOpen); 852 assert(isOpen);
863 return visit(node.expression); 853 return visit(node.expression);
864 } 854 }
865 855
866 ir.Primitive visitClosureSend(ast.Send node) { 856 ir.Primitive visitClosureSend(ast.Send node) {
867 assert(isOpen); 857 assert(isOpen);
868 Selector closureSelector = elements.getSelector(node); 858 Selector closureSelector = elements.getSelector(node);
(...skipping 19 matching lines...) Expand all
888 ir.Continuation k = new ir.Continuation([v]); 878 ir.Continuation k = new ir.Continuation([v]);
889 ir.Expression invoke = 879 ir.Expression invoke =
890 new ir.InvokeMethod(closureTarget, namedCallSelector, k, arguments); 880 new ir.InvokeMethod(closureTarget, namedCallSelector, k, arguments);
891 add(new ir.LetCont(k, invoke)); 881 add(new ir.LetCont(k, invoke));
892 return v; 882 return v;
893 } 883 }
894 884
895 ir.Primitive visitDynamicSend(ast.Send node) { 885 ir.Primitive visitDynamicSend(ast.Send node) {
896 assert(isOpen); 886 assert(isOpen);
897 if (node.receiver == null || node.receiver.isSuper()) { 887 if (node.receiver == null || node.receiver.isSuper()) {
898 return giveup(); 888 return giveup(node, 'DynamicSend without receiver, or super receiver');
899 } 889 }
900 Selector selector = elements.getSelector(node); 890 Selector selector = elements.getSelector(node);
901 ir.Primitive receiver = visit(node.receiver); 891 ir.Primitive receiver = visit(node.receiver);
902 List<ir.Primitive> arguments = new List<ir.Primitive>(); 892 List<ir.Primitive> arguments = new List<ir.Primitive>();
903 for (ast.Node n in node.arguments) { 893 for (ast.Node n in node.arguments) {
904 arguments.add(visit(n)); 894 arguments.add(visit(n));
905 } 895 }
906 ir.Parameter v = new ir.Parameter(null); 896 ir.Parameter v = new ir.Parameter(null);
907 ir.Continuation k = new ir.Continuation([v]); 897 ir.Continuation k = new ir.Continuation([v]);
908 ir.Expression invoke = 898 ir.Expression invoke =
909 new ir.InvokeMethod(receiver, selector, k, arguments); 899 new ir.InvokeMethod(receiver, selector, k, arguments);
910 add(new ir.LetCont(k, invoke)); 900 add(new ir.LetCont(k, invoke));
911 return v; 901 return v;
912 } 902 }
913 903
914 ir.Primitive visitGetterSend(ast.Send node) { 904 ir.Primitive visitGetterSend(ast.Send node) {
915 assert(isOpen); 905 assert(isOpen);
916 Element element = elements[node]; 906 Element element = elements[node];
917 if (Elements.isLocal(element)) { 907 if (Elements.isLocal(element)) {
918 return lookupLocal(element); 908 return lookupLocal(element);
919 } else if (element == null || Elements.isInstanceField(element)) { 909 } else if (element == null || Elements.isInstanceField(element)) {
920 // TODO: Support implicit this. 910 // TODO: Support implicit this.
921 if (node.receiver == null) return giveup(); 911 if (node.receiver == null) return giveup(node);
922 912
923 ir.Primitive receiver = visit(node.receiver); 913 ir.Primitive receiver = visit(node.receiver);
924 ir.Parameter v = new ir.Parameter(null); 914 ir.Parameter v = new ir.Parameter(null);
925 ir.Continuation k = new ir.Continuation([v]); 915 ir.Continuation k = new ir.Continuation([v]);
926 Selector selector = elements.getSelector(node); 916 Selector selector = elements.getSelector(node);
927 assert(selector.kind == SelectorKind.GETTER); 917 assert(selector.kind == SelectorKind.GETTER);
928 ir.InvokeMethod invoke = new ir.InvokeMethod(receiver, selector, k, []); 918 ir.InvokeMethod invoke = new ir.InvokeMethod(receiver, selector, k, []);
929 add(new ir.LetCont(k, invoke)); 919 add(new ir.LetCont(k, invoke));
930 return v; 920 return v;
931 } else if (element.isField) { 921 } else if (element.isField) {
932 ir.Parameter v = new ir.Parameter(null); 922 ir.Parameter v = new ir.Parameter(null);
933 ir.Continuation k = new ir.Continuation([v]); 923 ir.Continuation k = new ir.Continuation([v]);
934 Selector selector = elements.getSelector(node); 924 Selector selector = elements.getSelector(node);
935 assert(selector.kind == SelectorKind.GETTER); 925 assert(selector.kind == SelectorKind.GETTER);
936 ir.InvokeStatic invoke = new ir.InvokeStatic(element, selector, k, []); 926 ir.InvokeStatic invoke = new ir.InvokeStatic(element, selector, k, []);
937 add(new ir.LetCont(k, invoke)); 927 add(new ir.LetCont(k, invoke));
938 return v; 928 return v;
929 } else if (Elements.isStaticOrTopLevelFunction(element)) {
930 ir.Primitive prim = new ir.Constant(new FunctionConstant(element));
931 add(new ir.LetPrim(prim));
932 return prim;
939 } else { 933 } else {
940 return giveup(); // TODO: figure out what's missing here 934 return giveup(node); // TODO(asgerf): figure out what's missing here
941 } 935 }
942 } 936 }
943 937
944 ir.Primitive buildNegation(ir.Primitive condition) { 938 ir.Primitive buildNegation(ir.Primitive condition) {
945 // ! e is translated as e ? false : true 939 // ! e is translated as e ? false : true
946 940
947 // Add a continuation parameter for the result of the expression. 941 // Add a continuation parameter for the result of the expression.
948 ir.Parameter resultParameter = new ir.Parameter(null); 942 ir.Parameter resultParameter = new ir.Parameter(null);
949 943
950 ir.Continuation joinContinuation = new ir.Continuation([resultParameter]); 944 ir.Continuation joinContinuation = new ir.Continuation([resultParameter]);
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after
1075 assert(node.receiver != null); 1069 assert(node.receiver != null);
1076 assert(node.arguments.isEmpty); 1070 assert(node.arguments.isEmpty);
1077 return buildNegation(visit(node.receiver)); 1071 return buildNegation(visit(node.receiver));
1078 } 1072 }
1079 if (op.source == "!=") { 1073 if (op.source == "!=") {
1080 assert(node.receiver != null); 1074 assert(node.receiver != null);
1081 assert(!node.arguments.isEmpty); 1075 assert(!node.arguments.isEmpty);
1082 assert(node.arguments.tail.isEmpty); 1076 assert(node.arguments.tail.isEmpty);
1083 return buildNegation(visitDynamicSend(node)); 1077 return buildNegation(visitDynamicSend(node));
1084 } 1078 }
1085 return giveup(); 1079 return giveup(node);
1086 } 1080 }
1087 1081
1088 // Build(StaticSend(f, arguments), C) = C[C'[InvokeStatic(f, xs)]] 1082 // Build(StaticSend(f, arguments), C) = C[C'[InvokeStatic(f, xs)]]
1089 // where (C', xs) = arguments.fold(Build, C) 1083 // where (C', xs) = arguments.fold(Build, C)
1090 ir.Primitive visitStaticSend(ast.Send node) { 1084 ir.Primitive visitStaticSend(ast.Send node) {
1091 assert(isOpen); 1085 assert(isOpen);
1092 Element element = elements[node]; 1086 Element element = elements[node];
1093 // TODO(lry): support constructors / factory calls. 1087 // TODO(lry): support constructors / factory calls.
1094 if (element.isConstructor) return giveup(); 1088 if (element.isConstructor) return giveup(node, 'StaticSend: constructor');
1095 // TODO(lry): support foreign functions. 1089 // TODO(lry): support foreign functions.
1096 if (element.isForeign(compiler)) return giveup(); 1090 if (element.isForeign(compiler)) return giveup(node, 'StaticSend: foreign');
1097 // TODO(lry): for elements that could not be resolved emit code to throw a 1091 // TODO(lry): for elements that could not be resolved emit code to throw a
1098 // [NoSuchMethodError]. 1092 // [NoSuchMethodError].
1099 if (element.isErroneous) return giveup(); 1093 if (element.isErroneous) return giveup(node, 'StaticSend: erroneous');
1100 // TODO(lry): generate IR for object identicality. 1094 // TODO(lry): generate IR for object identicality.
1101 if (element == compiler.identicalFunction) giveup(); 1095 if (element == compiler.identicalFunction) {
1096 return giveup(node, 'StaticSend: identical');
1097 }
1102 1098
1103 Selector selector = elements.getSelector(node); 1099 Selector selector = elements.getSelector(node);
1104 1100
1105 // TODO(lry): support default arguments, need support for locals. 1101 // TODO(lry): support default arguments, need support for locals.
1106 List<ir.Definition> arguments = node.arguments.mapToList(visit, 1102 List<ir.Definition> arguments = node.arguments.mapToList(visit,
1107 growable:false); 1103 growable:false);
1108 ir.Parameter v = new ir.Parameter(null); 1104 ir.Parameter v = new ir.Parameter(null);
1109 ir.Continuation k = new ir.Continuation([v]); 1105 ir.Continuation k = new ir.Continuation([v]);
1110 ir.Expression invoke = 1106 ir.Expression invoke =
1111 new ir.InvokeStatic(element, selector, k, arguments); 1107 new ir.InvokeStatic(element, selector, k, arguments);
1112 add(new ir.LetCont(k, invoke)); 1108 add(new ir.LetCont(k, invoke));
1113 return v; 1109 return v;
1114 } 1110 }
1115 1111
1116 ir.Primitive visitSuperSend(ast.Send node) { 1112 ir.Primitive visitSuperSend(ast.Send node) {
1117 assert(isOpen); 1113 assert(isOpen);
1118 return giveup(); 1114 return giveup(node, 'SuperSend');
1119 } 1115 }
1120 1116
1121 ir.Primitive visitTypeReferenceSend(ast.Send node) { 1117 ir.Primitive visitTypeReferenceSend(ast.Send node) {
1122 assert(isOpen); 1118 assert(isOpen);
1123 return giveup(); 1119 if (node.argumentsNode != null) {
1120 // May happen in strange, invalid code.
1121 // TODO(asgerf): Generate code that throws a runtime error.
1122 return giveup(node, 'TypeReferenceSend: has argument');
1123 }
1124 Element element = elements[node];
1125 if (element is TypeDeclarationElement) {
1126 DartType typeType = compiler.backend.typeImplementation.rawType;
1127 ir.Primitive prim =
1128 new ir.Constant(new TypeConstant(element.rawType, typeType));
1129 add(new ir.LetPrim(prim));
1130 return prim;
1131 } else if (element.isTypeVariable) {
1132 // TODO(asgerf): Introduce IR to reify type variables
1133 return giveup(node, 'TypeReferenceSend: type variable');
1134 } else {
1135 // TODO(asgerf): Any other cases?
1136 return giveup(node);
1137 }
1124 } 1138 }
1125 1139
1126 ir.Primitive visitSendSet(ast.SendSet node) { 1140 ir.Primitive visitSendSet(ast.SendSet node) {
1127 assert(isOpen); 1141 assert(isOpen);
1128 Element element = elements[node]; 1142 Element element = elements[node];
1129 ast.Operator op = node.assignmentOperator; 1143 ast.Operator op = node.assignmentOperator;
1130 ir.Primitive result; 1144 ir.Primitive result;
1131 ir.Primitive getter; 1145 ir.Primitive getter;
1132 if (op.source == '=') { 1146 if (op.source == '=') {
1133 if (Elements.isLocal(element)) { 1147 if (Elements.isLocal(element)) {
(...skipping 12 matching lines...) Expand all
1146 Selector selector = elements.getSelector(node); 1160 Selector selector = elements.getSelector(node);
1147 ir.Definition arg = visit(node.arguments.head); 1161 ir.Definition arg = visit(node.arguments.head);
1148 ir.InvokeStatic invoke = 1162 ir.InvokeStatic invoke =
1149 new ir.InvokeStatic(element, selector, k, [arg]); 1163 new ir.InvokeStatic(element, selector, k, [arg]);
1150 add(new ir.LetCont(k, invoke)); 1164 add(new ir.LetCont(k, invoke));
1151 return arg; 1165 return arg;
1152 } else if (node.receiver == null) { 1166 } else if (node.receiver == null) {
1153 // Nodes that fall in this case: 1167 // Nodes that fall in this case:
1154 // - Unresolved top-level 1168 // - Unresolved top-level
1155 // - Assignment to final variable (will not be resolved) 1169 // - Assignment to final variable (will not be resolved)
1156 return giveup(); 1170 return giveup(node, 'SendSet: non-local, non-static, but no receiver');
1157 } else { 1171 } else {
1158 // Setter or index-setter invocation 1172 // Setter or index-setter invocation
1159 assert(node.receiver != null); 1173 assert(node.receiver != null);
1160 if (node.receiver.isSuper()) return giveup(); 1174 if (node.receiver.isSuper()) return giveup(node, 'Super SendSet');
1161 1175
1162 ir.Primitive receiver = visit(node.receiver); 1176 ir.Primitive receiver = visit(node.receiver);
1163 ir.Parameter v = new ir.Parameter(null); 1177 ir.Parameter v = new ir.Parameter(null);
1164 ir.Continuation k = new ir.Continuation([v]); 1178 ir.Continuation k = new ir.Continuation([v]);
1165 Selector selector = elements.getSelector(node); 1179 Selector selector = elements.getSelector(node);
1166 assert(selector.kind == SelectorKind.SETTER || 1180 assert(selector.kind == SelectorKind.SETTER ||
1167 selector.kind == SelectorKind.INDEX); 1181 selector.kind == SelectorKind.INDEX);
1168 List<ir.Definition> args = node.arguments.mapToList(visit, 1182 List<ir.Definition> args = node.arguments.mapToList(visit,
1169 growable:false); 1183 growable:false);
1170 ir.InvokeMethod invoke = 1184 ir.InvokeMethod invoke =
1171 new ir.InvokeMethod(receiver, selector, k, args); 1185 new ir.InvokeMethod(receiver, selector, k, args);
1172 add(new ir.LetCont(k, invoke)); 1186 add(new ir.LetCont(k, invoke));
1173 return args.last; 1187 return args.last;
1174 } 1188 }
1175 } else if (ast.Operator.COMPLEX_OPERATORS.contains(op.source)) { 1189 } else if (ast.Operator.COMPLEX_OPERATORS.contains(op.source)) {
1176 Element selectorElement = elements[node.selector]; 1190 Element selectorElement = elements[node.selector];
1177 if (selectorElement != null && !selectorElement.isAssignable) { 1191 if (selectorElement != null && !selectorElement.isAssignable) {
1178 return giveup(); 1192 return giveup(node, 'Unresolved or non-assignable compound assignment');
1179 } 1193 }
1180 if (!Elements.isLocal(selectorElement)) return giveup(); 1194 if (!Elements.isLocal(selectorElement)) {
1195 return giveup(node, 'Non-local compound assignment');
1196 }
1181 1197
1182 Selector selector = elements.getOperatorSelectorInComplexSendSet(node); 1198 Selector selector = elements.getOperatorSelectorInComplexSendSet(node);
1183 getter = lookupLocal(selectorElement); 1199 getter = lookupLocal(selectorElement);
1184 1200
1185 ir.Primitive arg; 1201 ir.Primitive arg;
1186 if (ast.Operator.INCREMENT_OPERATORS.contains(op.source)) { 1202 if (ast.Operator.INCREMENT_OPERATORS.contains(op.source)) {
1187 assert(node.arguments.isEmpty); 1203 assert(node.arguments.isEmpty);
1188 arg = new ir.Constant(constantSystem.createInt(1)); 1204 arg = new ir.Constant(constantSystem.createInt(1));
1189 add(new ir.LetPrim(arg)); 1205 add(new ir.LetPrim(arg));
1190 } else { 1206 } else {
(...skipping 19 matching lines...) Expand all
1210 } else { 1226 } else {
1211 compiler.internalError(node, "Unknown assignment operator ${op.source}"); 1227 compiler.internalError(node, "Unknown assignment operator ${op.source}");
1212 return null; 1228 return null;
1213 } 1229 }
1214 } 1230 }
1215 1231
1216 ir.Primitive visitNewExpression(ast.NewExpression node) { 1232 ir.Primitive visitNewExpression(ast.NewExpression node) {
1217 assert(isOpen); 1233 assert(isOpen);
1218 FunctionElement element = elements[node.send]; 1234 FunctionElement element = elements[node.send];
1219 if (Elements.isUnresolved(element)) { 1235 if (Elements.isUnresolved(element)) {
1220 return giveup(); 1236 return giveup(node, 'NewExpression: unresolved constructor');
1221 } 1237 }
1222 Selector selector = elements.getSelector(node.send); 1238 Selector selector = elements.getSelector(node.send);
1223 ast.Node selectorNode = node.send.selector; 1239 ast.Node selectorNode = node.send.selector;
1224 GenericType type = elements.getType(node); 1240 GenericType type = elements.getType(node);
1225 List<ir.Definition> args = node.send.arguments.mapToList(visit, 1241 List<ir.Primitive> args =
1226 growable:false); 1242 node.send.arguments.mapToList(visit, growable:false);
1227 if (node.isConst) { 1243 if (node.isConst) {
1228 List<ir.Primitive> arguments = new List<ir.Primitive>(); 1244 ir.Primitive result = new ir.InvokeConstConstructor(type, element,
1229 node.send.arguments.forEach((ast.Node node) { 1245 selector, args, getConstantForNode(node));
1230 arguments.add(visit(node));
1231 });
1232 ir.Primitive result = new ir.InvokeConstConstructor(type, element, selecto r,
1233 arguments);
1234 add(new ir.LetPrim(result)); 1246 add(new ir.LetPrim(result));
1235 return result; 1247 return result;
1236 } 1248 }
1237 ir.Parameter v = new ir.Parameter(null); 1249 ir.Parameter v = new ir.Parameter(null);
1238 ir.Continuation k = new ir.Continuation([v]); 1250 ir.Continuation k = new ir.Continuation([v]);
1239 ir.InvokeConstructor invoke = new ir.InvokeConstructor( 1251 ir.InvokeConstructor invoke =
1240 type, 1252 new ir.InvokeConstructor(type, element,selector, k, args);
1241 element,
1242 selector,
1243 k,
1244 args);
1245 add(new ir.LetCont(k, invoke)); 1253 add(new ir.LetCont(k, invoke));
1246 return v; 1254 return v;
1247 } 1255 }
1248 1256
1249 ir.Primitive visitStringJuxtaposition(ast.StringJuxtaposition node) { 1257 ir.Primitive visitStringJuxtaposition(ast.StringJuxtaposition node) {
1250 ir.Primitive first = visit(node.first); 1258 ir.Primitive first = visit(node.first);
1251 ir.Primitive second = visit(node.second); 1259 ir.Primitive second = visit(node.second);
1252 ir.Parameter v = new ir.Parameter(null); 1260 ir.Parameter v = new ir.Parameter(null);
1253 ir.Continuation k = new ir.Continuation([v]); 1261 ir.Continuation k = new ir.Continuation([v]);
1254 ir.ConcatenateStrings concat = 1262 ir.ConcatenateStrings concat =
(...skipping 13 matching lines...) Expand all
1268 } 1276 }
1269 ir.Parameter v = new ir.Parameter(null); 1277 ir.Parameter v = new ir.Parameter(null);
1270 ir.Continuation k = new ir.Continuation([v]); 1278 ir.Continuation k = new ir.Continuation([v]);
1271 ir.ConcatenateStrings concat = new ir.ConcatenateStrings(k, arguments); 1279 ir.ConcatenateStrings concat = new ir.ConcatenateStrings(k, arguments);
1272 add(new ir.LetCont(k, concat)); 1280 add(new ir.LetCont(k, concat));
1273 return v; 1281 return v;
1274 } 1282 }
1275 1283
1276 static final String ABORT_IRNODE_BUILDER = "IrNode builder aborted"; 1284 static final String ABORT_IRNODE_BUILDER = "IrNode builder aborted";
1277 1285
1278 ir.Primitive giveup() => throw ABORT_IRNODE_BUILDER; 1286 ir.Primitive giveup(ast.Node node, [String reason]) {
1287 throw ABORT_IRNODE_BUILDER;
1288 }
1279 1289
1280 ir.FunctionDefinition nullIfGiveup(ir.FunctionDefinition action()) { 1290 ir.FunctionDefinition nullIfGiveup(ir.FunctionDefinition action()) {
1281 try { 1291 try {
1282 return action(); 1292 return action();
1283 } catch(e) { 1293 } catch(e) {
1284 if (e == ABORT_IRNODE_BUILDER) return null; 1294 if (e == ABORT_IRNODE_BUILDER) return null;
1285 rethrow; 1295 rethrow;
1286 } 1296 }
1287 } 1297 }
1288 1298
1289 void internalError(String reason, {ast.Node node}) { 1299 void internalError(String reason, {ast.Node node}) {
1290 giveup(); 1300 giveup(node);
1291 } 1301 }
1292 } 1302 }
1293 1303
1294 // While we don't support all constants we need to filter out the unsupported
1295 // ones:
1296 class SupportedConstantVisitor extends ConstantVisitor<bool> {
1297 const SupportedConstantVisitor();
1298
1299 bool visit(Constant constant) => constant.accept(this);
1300 bool visitFunction(FunctionConstant constant) => false;
1301 bool visitNull(NullConstant constant) => true;
1302 bool visitInt(IntConstant constant) => true;
1303 bool visitDouble(DoubleConstant constant) => true;
1304 bool visitTrue(TrueConstant constant) => true;
1305 bool visitFalse(FalseConstant constant) => true;
1306 bool visitString(StringConstant constant) => true;
1307 bool visitList(ListConstant constant) {
1308 return constant.entries.every(visit);
1309 }
1310 bool visitMap(MapConstant constant) {
1311 return visit(constant.keys) && constant.values.every(visit);
1312 }
1313 bool visitConstructed(ConstructedConstant constant) => false;
1314 bool visitType(TypeConstant constant) => false;
1315 bool visitInterceptor(InterceptorConstant constant) => false;
1316 bool visitDummy(DummyConstant constant) => false;
1317 bool visitDeferred(DeferredConstant constant) => false;
1318 }
1319
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698