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

Side by Side Diff: gen.dart

Issue 8343037: Throw FallThroughError when we fall through a case in a switch statement. Fixes (Closed) Base URL: http://dart.googlecode.com/svn/experimental/frog/
Patch Set: '' Created 9 years, 1 month 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
« no previous file with comments | « frogsh ('k') | lib/corelib.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 /** 5 /**
6 * Top level generator object for writing code and keeping track of 6 * Top level generator object for writing code and keeping track of
7 * dependencies. 7 * dependencies.
8 * 8 *
9 * Should have two compilation models, but only one implemented so far. 9 * Should have two compilation models, but only one implemented so far.
10 * 10 *
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after
156 // no preludes for top type 156 // no preludes for top type
157 } else if (type.constructors.length == 0) { 157 } else if (type.constructors.length == 0) {
158 if (!type.isNativeType) { 158 if (!type.isNativeType) {
159 // TODO(jimhug): More guards to guarantee staticness 159 // TODO(jimhug): More guards to guarantee staticness
160 writer.writeln('function ${type.jsname}() {}'); 160 writer.writeln('function ${type.jsname}() {}');
161 } 161 }
162 } else { 162 } else {
163 Member standardConstructor = type.constructors['']; 163 Member standardConstructor = type.constructors[''];
164 if (standardConstructor == null || 164 if (standardConstructor == null ||
165 standardConstructor.generator == null) { 165 standardConstructor.generator == null) {
166 if (!type.isNativeType) { 166 if (!type.isNativeType) {
167 writer.writeln('function ${type.jsname}() {}'); 167 writer.writeln('function ${type.jsname}() {}');
168 } 168 }
169 } else { 169 } else {
170 standardConstructor.generator.writeDefinition(writer, null); 170 standardConstructor.generator.writeDefinition(writer, null);
171 } 171 }
172 172
173 for (var c in type.constructors.getValues()) { 173 for (var c in type.constructors.getValues()) {
174 if (c.generator != null && c != standardConstructor) { 174 if (c.generator != null && c != standardConstructor) {
175 c.generator.writeDefinition(writer, null); 175 c.generator.writeDefinition(writer, null);
176 } 176 }
(...skipping 681 matching lines...) Expand 10 before | Expand all | Expand 10 after
858 * Escapes a string so it can be inserted into JS code as a double-quoted 858 * Escapes a string so it can be inserted into JS code as a double-quoted
859 * JS string. 859 * JS string.
860 */ 860 */
861 static String _escapeString(String text) { 861 static String _escapeString(String text) {
862 // TODO(jimhug): Use a regex for performance here. 862 // TODO(jimhug): Use a regex for performance here.
863 return text.replaceAll('\\', '\\\\').replaceAll('"', '\\"').replaceAll( 863 return text.replaceAll('\\', '\\\\').replaceAll('"', '\\"').replaceAll(
864 '\n', '\\n').replaceAll('\r', '\\r'); 864 '\n', '\\n').replaceAll('\r', '\\r');
865 } 865 }
866 866
867 /** Visits [body] without creating a new block for a [BlockStatement]. */ 867 /** Visits [body] without creating a new block for a [BlockStatement]. */
868 void visitStatementsInBlock(Statement body) { 868 bool visitStatementsInBlock(Statement body) {
869 if (body is BlockStatement) { 869 if (body is BlockStatement) {
870 for (var stmt in body.body) { 870 for (var stmt in body.body) {
871 stmt.visit(this); 871 stmt.visit(this);
872 } 872 }
873 } else { 873 } else {
874 if (body != null) body.visit(this); 874 if (body != null) body.visit(this);
875 } 875 }
876 return false;
876 } 877 }
877 878
878 _pushBlock([bool reentrant = false]) { 879 _pushBlock([bool reentrant = false]) {
879 _scope = new BlockScope(this, _scope, reentrant); 880 _scope = new BlockScope(this, _scope, reentrant);
880 } 881 }
881 882
882 _popBlock() { 883 _popBlock() {
883 _scope = _scope.parent; 884 _scope = _scope.parent;
884 } 885 }
885 886
(...skipping 29 matching lines...) Expand all
915 var value = visitPostfixExpression(node, /*isVoid:*/true); 916 var value = visitPostfixExpression(node, /*isVoid:*/true);
916 value.checkFirstClass(node.span); 917 value.checkFirstClass(node.span);
917 return value; 918 return value;
918 } 919 }
919 // TODO(jimhug): Some level of warnings for non-void things here? 920 // TODO(jimhug): Some level of warnings for non-void things here?
920 return visitValue(node); 921 return visitValue(node);
921 } 922 }
922 923
923 // ******************* Statements ******************* 924 // ******************* Statements *******************
924 925
925 void visitDietStatement(DietStatement node) { 926 bool visitDietStatement(DietStatement node) {
926 var parser = new Parser(node.span.file, /*diet:*/false, node.span.start); 927 var parser = new Parser(node.span.file, /*diet:*/false, node.span.start);
927 visitStatementsInBlock(parser.block()); 928 visitStatementsInBlock(parser.block());
929 return false;
928 } 930 }
929 931
930 void visitVariableDefinition(VariableDefinition node) { 932 bool visitVariableDefinition(VariableDefinition node) {
931 var isFinal = false; 933 var isFinal = false;
932 // TODO(jimhug): Clean this up and share modifier parsing somewhere. 934 // TODO(jimhug): Clean this up and share modifier parsing somewhere.
933 if (node.modifiers != null && node.modifiers[0].kind == TokenKind.FINAL) { 935 if (node.modifiers != null && node.modifiers[0].kind == TokenKind.FINAL) {
934 isFinal = true; 936 isFinal = true;
935 } 937 }
936 writer.write('var '); 938 writer.write('var ');
937 var type = method.resolveType(node.type); 939 var type = method.resolveType(node.type);
938 for (int i=0; i < node.names.length; i++) { 940 for (int i=0; i < node.names.length; i++) {
939 var thisType = type; 941 var thisType = type;
940 if (i > 0) { 942 if (i > 0) {
(...skipping 12 matching lines...) Expand all
953 955
954 var val = _scope.create(name, thisType, node.names[i]); 956 var val = _scope.create(name, thisType, node.names[i]);
955 957
956 if (value == null) { 958 if (value == null) {
957 writer.write('${val.code}'); 959 writer.write('${val.code}');
958 } else { 960 } else {
959 writer.write('${val.code} = ${value.code}'); 961 writer.write('${val.code} = ${value.code}');
960 } 962 }
961 } 963 }
962 writer.writeln(';'); 964 writer.writeln(';');
965 return false;
966
963 } 967 }
964 968
965 void visitFunctionDefinition(FunctionDefinition node) { 969 bool visitFunctionDefinition(FunctionDefinition node) {
966 var name = world.toJsIdentifier(node.name.name); 970 var name = world.toJsIdentifier(node.name.name);
967 971
968 var meth = _makeLambdaMethod(name, node); 972 var meth = _makeLambdaMethod(name, node);
969 973
970 // TODO(jimhug): Pass js name into writeDefinition? 974 // TODO(jimhug): Pass js name into writeDefinition?
971 var funcValue = _scope.create(name, meth.functionType, method.definition); 975 var funcValue = _scope.create(name, meth.functionType, method.definition);
972 meth.generator.writeDefinition(writer, null); 976 meth.generator.writeDefinition(writer, null);
977 return false;
973 } 978 }
974 979
975 void visitReturnStatement(ReturnStatement node) { 980 /**
981 * Returns true indicating that normal control-flow is interrupted by
982 * this statement. (This could be a return, break, throw, or continue.)
983 */
984 bool visitReturnStatement(ReturnStatement node) {
976 if (node.value == null) { 985 if (node.value == null) {
977 writer.writeln('return;'); 986 writer.writeln('return;');
978 } else { 987 } else {
979 if (method.isConstructor) { 988 if (method.isConstructor) {
980 world.error('return of value not allowed from constructor', node.span); 989 world.error('return of value not allowed from constructor', node.span);
981 } 990 }
982 writer.writeln('return ${visitValue(node.value).code};'); 991 writer.writeln('return ${visitValue(node.value).code};');
983 } 992 }
993 return true;
984 } 994 }
985 995
986 void visitThrowStatement(ThrowStatement node) { 996 bool visitThrowStatement(ThrowStatement node) {
987 // Dart allows throwing anything, just like JS 997 // Dart allows throwing anything, just like JS
988 if (node.value != null) { 998 if (node.value != null) {
989 var value = visitValue(node.value); 999 var value = visitValue(node.value);
990 // Ensure that we generate a toString() method for things that we throw 1000 // Ensure that we generate a toString() method for things that we throw
991 value.invoke(parent, 'toString', node, Arguments.EMPTY); 1001 value.invoke(parent, 'toString', node, Arguments.EMPTY);
992 writer.writeln('\$throw(${value.code});'); 1002 writer.writeln('\$throw(${value.code});');
993 } else { 1003 } else {
994 var rethrow = _scope.getRethrow(); 1004 var rethrow = _scope.getRethrow();
995 if (rethrow == null) { 1005 if (rethrow == null) {
996 world.error('rethrow outside of catch', node.span); 1006 world.error('rethrow outside of catch', node.span);
997 } else { 1007 } else {
998 // Use a normal throw instead of $throw so we don't capture a new stack 1008 // Use a normal throw instead of $throw so we don't capture a new stack
999 writer.writeln('throw ${rethrow.code};'); 1009 writer.writeln('throw ${rethrow.code};');
1000 } 1010 }
1001 } 1011 }
1012 return true;
1002 } 1013 }
1003 1014
1004 void visitAssertStatement(AssertStatement node) { 1015 bool visitAssertStatement(AssertStatement node) {
1005 // be sure to walk test for static checking even is asserts disabled 1016 // be sure to walk test for static checking even is asserts disabled
1006 var test = visitValue(node.test); // TODO(jimhug): check bool or callable. 1017 var test = visitValue(node.test); // TODO(jimhug): check bool or callable.
1007 if (options.enableAsserts) { 1018 if (options.enableAsserts) {
1008 var err = world.corelib.types['AssertError']; 1019 var err = world.corelib.types['AssertError'];
1009 err.markUsed(); 1020 err.markUsed();
1010 parent.genMethod(err.getConstructor('')); 1021 parent.genMethod(err.getConstructor(''));
1011 parent.genMethod(err.members['toString']); 1022 parent.genMethod(err.members['toString']);
1012 var span = node.test.span; 1023 var span = node.test.span;
1013 1024
1014 var line = span.file.getLine(span.start); 1025 var line = span.file.getLine(span.start);
1015 var column = span.file.getColumn(line, span.start); 1026 var column = span.file.getColumn(line, span.start);
1016 writer.writeln('\$assert(${test.code}, "${_escapeString(span.text)}",' + 1027 writer.writeln('\$assert(${test.code}, "${_escapeString(span.text)}",' +
1017 ' "${span.file.filename}", ${line + 1}, ${column + 1});'); 1028 ' "${span.file.filename}", ${line + 1}, ${column + 1});');
1018 } 1029 }
1030 return false;
1019 } 1031 }
1020 1032
1021 void visitBreakStatement(BreakStatement node) { 1033 bool visitBreakStatement(BreakStatement node) {
1022 // TODO(jimhug): Lots of flow error checking here and below. 1034 // TODO(jimhug): Lots of flow error checking here and below.
1023 if (node.label == null) { 1035 if (node.label == null) {
1024 writer.writeln('break;'); 1036 writer.writeln('break;');
1025 } else { 1037 } else {
1026 writer.writeln('break ${node.label.name};'); 1038 writer.writeln('break ${node.label.name};');
1027 } 1039 }
1040 return true;
1028 } 1041 }
1029 1042
1030 void visitContinueStatement(ContinueStatement node) { 1043 bool visitContinueStatement(ContinueStatement node) {
1031 if (node.label == null) { 1044 if (node.label == null) {
1032 writer.writeln('continue;'); 1045 writer.writeln('continue;');
1033 } else { 1046 } else {
1034 writer.writeln('continue ${node.label.name};'); 1047 writer.writeln('continue ${node.label.name};');
1035 } 1048 }
1049 return true;
1036 } 1050 }
1037 1051
1038 void visitIfStatement(IfStatement node) { 1052 bool visitIfStatement(IfStatement node) {
1039 var test = visitBool(node.test); 1053 var test = visitBool(node.test);
1040 writer.write('if (${test.code}) '); 1054 writer.write('if (${test.code}) ');
1041 node.trueBranch.visit(this); 1055 var exit1 = node.trueBranch.visit(this);
1042 if (node.falseBranch != null) { 1056 if (node.falseBranch != null) {
1043 writer.write('else '); 1057 writer.write('else ');
1044 node.falseBranch.visit(this); 1058 if (node.falseBranch.visit(this) && exit1) {
1059 return true;
1060 }
1045 } 1061 }
1062 return false;
1046 } 1063 }
1047 1064
1048 void visitWhileStatement(WhileStatement node) { 1065 bool visitWhileStatement(WhileStatement node) {
1049 var test = visitBool(node.test); 1066 var test = visitBool(node.test);
1050 writer.write('while (${test.code}) '); 1067 writer.write('while (${test.code}) ');
1051 _pushBlock(/*reentrant:*/true); 1068 _pushBlock(/*reentrant:*/true);
1052 node.body.visit(this); 1069 node.body.visit(this);
1053 _popBlock(); 1070 _popBlock();
1071 return false;
1054 } 1072 }
1055 1073
1056 void visitDoStatement(DoStatement node) { 1074 bool visitDoStatement(DoStatement node) {
1057 writer.write('do '); 1075 writer.write('do ');
1058 _pushBlock(/*reentrant:*/true); 1076 _pushBlock(/*reentrant:*/true);
1059 node.body.visit(this); 1077 node.body.visit(this);
1060 _popBlock(); 1078 _popBlock();
1061 var test = visitBool(node.test); 1079 var test = visitBool(node.test);
1062 writer.writeln('while (${test.code})'); 1080 writer.writeln('while (${test.code})');
1081 return false;
1063 } 1082 }
1064 1083
1065 void visitForStatement(ForStatement node) { 1084 bool visitForStatement(ForStatement node) {
1066 _pushBlock(); 1085 _pushBlock();
1067 writer.write('for ('); 1086 writer.write('for (');
1068 if (node.init != null) node.init.visit(this); 1087 if (node.init != null) node.init.visit(this);
1069 else writer.write(';'); 1088 else writer.write(';');
1070 if (node.test != null) { 1089 if (node.test != null) {
1071 var test = visitBool(node.test); 1090 var test = visitBool(node.test);
1072 writer.write(' ${test.code}; '); 1091 writer.write(' ${test.code}; ');
1073 } else { 1092 } else {
1074 writer.write('; '); 1093 writer.write('; ');
1075 } 1094 }
1076 1095
1077 bool needsComma = false; 1096 bool needsComma = false;
1078 for (var s in node.step) { 1097 for (var s in node.step) {
1079 if (needsComma) writer.write(', '); 1098 if (needsComma) writer.write(', ');
1080 var sv = visitVoid(s); 1099 var sv = visitVoid(s);
1081 writer.write(sv.code); 1100 writer.write(sv.code);
1082 needsComma = true; 1101 needsComma = true;
1083 } 1102 }
1084 writer.write(') '); 1103 writer.write(') ');
1085 _pushBlock(/*reentrant:*/true); 1104 _pushBlock(/*reentrant:*/true);
1086 node.body.visit(this); 1105 node.body.visit(this);
1087 _popBlock(); 1106 _popBlock();
1088 _popBlock(); 1107 _popBlock();
1108 return false;
1089 } 1109 }
1090 1110
1091 void visitForInStatement(ForInStatement node) { 1111 bool visitForInStatement(ForInStatement node) {
1092 // TODO(jimhug): visitValue and other cleanups here. 1112 // TODO(jimhug): visitValue and other cleanups here.
1093 var itemType = method.resolveType(node.item.type); 1113 var itemType = method.resolveType(node.item.type);
1094 var itemName = node.item.name.name; 1114 var itemName = node.item.name.name;
1095 var list = node.list.visit(this); 1115 var list = node.list.visit(this);
1096 _pushBlock(/*reentrant:*/true); 1116 _pushBlock(/*reentrant:*/true);
1097 // TODO(jimhug): Check that itemType matches list members... 1117 // TODO(jimhug): Check that itemType matches list members...
1098 var item = _scope.create(itemName, itemType, node.item.name); 1118 var item = _scope.create(itemName, itemType, node.item.name);
1099 Value listVar = list; 1119 Value listVar = list;
1100 if (list.needsTemp) { 1120 if (list.needsTemp) {
1101 listVar = _scope.create('\$list', list.type, null); 1121 listVar = _scope.create('\$list', list.type, null);
(...skipping 23 matching lines...) Expand all
1125 var next = tmpi.invoke(parent, 'next', node.list, Arguments.EMPTY); 1145 var next = tmpi.invoke(parent, 'next', node.list, Arguments.EMPTY);
1126 1146
1127 writer.enterBlock( 1147 writer.enterBlock(
1128 'for (var ${tmpi.code} = ${iterator.code}; ${hasNext.code}; ) {'); 1148 'for (var ${tmpi.code} = ${iterator.code}; ${hasNext.code}; ) {');
1129 writer.writeln('var ${item.code} = ${next.code};'); 1149 writer.writeln('var ${item.code} = ${next.code};');
1130 } 1150 }
1131 1151
1132 visitStatementsInBlock(node.body); 1152 visitStatementsInBlock(node.body);
1133 writer.exitBlock('}'); 1153 writer.exitBlock('}');
1134 _popBlock(); 1154 _popBlock();
1155 return false;
1135 } 1156 }
1136 1157
1137 void visitTryStatement(TryStatement node) { 1158 bool visitTryStatement(TryStatement node) {
1138 writer.enterBlock('try {'); 1159 writer.enterBlock('try {');
1139 _pushBlock(); 1160 _pushBlock();
1140 visitStatementsInBlock(node.body); 1161 visitStatementsInBlock(node.body);
1141 _popBlock(); 1162 _popBlock();
1142 1163
1143 if (node.catches.length == 1) { 1164 if (node.catches.length == 1) {
1144 // Handle a single catch. We can generate simple code here compared to the 1165 // Handle a single catch. We can generate simple code here compared to the
1145 // multiple catch, such as no extra temp or if-else-if chain. 1166 // multiple catch, such as no extra temp or if-else-if chain.
1146 var catch_ = node.catches[0]; 1167 var catch_ = node.catches[0];
1147 _pushBlock(); 1168 _pushBlock();
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
1222 1243
1223 if (node.finallyBlock != null) { 1244 if (node.finallyBlock != null) {
1224 writer.nextBlock('} finally {'); 1245 writer.nextBlock('} finally {');
1225 _pushBlock(); 1246 _pushBlock();
1226 visitStatementsInBlock(node.finallyBlock); 1247 visitStatementsInBlock(node.finallyBlock);
1227 _popBlock(); 1248 _popBlock();
1228 } 1249 }
1229 1250
1230 // Close the try-catch-finally 1251 // Close the try-catch-finally
1231 writer.exitBlock('}'); 1252 writer.exitBlock('}');
1253 // TODO(efortuna): This could be more precise by combining all the different
1254 // paths here. -i.e. if there is a finally block with a return at the end
1255 // then this can return true, similarly if all blocks have a return at the
1256 // end then the same holds.
1257 return false;
1232 } 1258 }
1233 1259
1234 void visitSwitchStatement(SwitchStatement node) { 1260 bool visitSwitchStatement(SwitchStatement node) {
1235 // TODO(jimhug): Lots of negative tests to check for. 1261 // TODO(jimhug): Lots of negative tests to check for.
1236 var test = visitValue(node.test); 1262 var test = visitValue(node.test);
1237 writer.enterBlock('switch (${test.code}) {'); 1263 writer.enterBlock('switch (${test.code}) {');
1238 for (var case_ in node.cases) { 1264 for (var case_ in node.cases) {
1239 if (case_.label != null) { 1265 if (case_.label != null) {
1240 world.error('unimplemented: labeled case statement', case_.span); 1266 world.error('unimplemented: labeled case statement', case_.span);
1241 } 1267 }
1242 _pushBlock(); 1268 _pushBlock();
1243 for (int i=0; i < case_.cases.length; i++) { 1269 for (int i=0; i < case_.cases.length; i++) {
1244 var expr = case_.cases[i]; 1270 var expr = case_.cases[i];
1245 if (expr == null) { 1271 if (expr == null) {
1246 // Default can only be the last case. 1272 // Default can only be the last case.
1247 if (i < case_.cases.length - 1) { 1273 if (i < case_.cases.length - 1) {
1248 world.error('default clause must be the last case', case_.span); 1274 world.error('default clause must be the last case', case_.span);
1249 } 1275 }
1250 writer.writeln('default:'); 1276 writer.writeln('default:');
1251 } else { 1277 } else {
1252 var value = visitValue(expr); 1278 var value = visitValue(expr);
1253 writer.writeln('case ${value.code}:'); 1279 writer.writeln('case ${value.code}:');
1254 } 1280 }
1255 } 1281 }
1256 writer.enterBlock(''); 1282 writer.enterBlock('');
1257 for (var stmt in case_.statements) { 1283 bool caseExits = _visitAllStatements(case_.statements, false);
1258 stmt.visit(this); 1284
1259 } 1285 if (case_ != node.cases[node.cases.length - 1] && !caseExits) {
1260 if (case_ != node.cases[node.cases.length - 1]) {
1261 var span = case_.statements[case_.statements.length - 1].span; 1286 var span = case_.statements[case_.statements.length - 1].span;
1287 //TODO(efortuna): This error message isn't 100% correct because
1288 // constructors are not being built correctly. Check back for correct
1289 // output when constructors are fixed.
1290 writer.writeln('\$throw(new FallThroughError("${span.file.filename}",' +
1291 ' ${span.file.getLine(span.start)}))');
1262 } 1292 }
1263 writer.exitBlock(''); 1293 writer.exitBlock('');
1264 _popBlock(); 1294 _popBlock();
1265 } 1295 }
1266 writer.exitBlock('}'); 1296 writer.exitBlock('}');
1297 // TODO(efortuna): When we are passing more information back about
1298 // control flow by returning something other than bool, return true for the
1299 // cases where every branch of the switch statement ends with a return
1300 // statement.
1301 return false;
1302 }
1303
1304 bool _visitAllStatements(statementList, exits) {
1305 for (int i = 0; i < statementList.length; i++) {
1306 var stmt = statementList[i];
1307 exits = stmt.visit(this);
1308 //TODO(efortuna): fix this so you only get one error if you have "return;
1309 //a; b; c;"
1310 if (stmt != statementList[statementList.length - 1] && exits) {
1311 world.warning('unreachable code', statementList[i + 1].span);
1312 }
1313 }
1314 return exits;
1267 } 1315 }
1268 1316
1269 void visitBlockStatement(BlockStatement node) { 1317 bool visitBlockStatement(BlockStatement node) {
1270 _pushBlock(); 1318 _pushBlock();
1271 writer.enterBlock('{'); 1319 writer.enterBlock('{');
1272 for (var stmt in node.body) { 1320 var exits = _visitAllStatements(node.body, false);
1273 stmt.visit(this);
1274 }
1275 writer.exitBlock('}'); 1321 writer.exitBlock('}');
1276 _popBlock(); 1322 _popBlock();
1323 return exits;
1277 } 1324 }
1278 1325
1279 void visitLabeledStatement(LabeledStatement node) { 1326 bool visitLabeledStatement(LabeledStatement node) {
1280 writer.writeln('${node.name.name}:'); 1327 writer.writeln('${node.name.name}:');
1281 node.body.visit(this); 1328 node.body.visit(this);
1329 return false;
1282 } 1330 }
1283 1331
1284 void visitExpressionStatement(ExpressionStatement node) { 1332 bool visitExpressionStatement(ExpressionStatement node) {
1285 if (node.body is VarExpression || node.body is ThisExpression) { 1333 if (node.body is VarExpression || node.body is ThisExpression) {
1286 // TODO(jmesserly): this is a "warning" but not a "type warning", 1334 // TODO(jmesserly): this is a "warning" but not a "type warning",
1287 // Is that okay? We have a similar issue around unreachable code warnings. 1335 // Is that okay? We have a similar issue around unreachable code warnings.
1288 world.warning('variable used as statement', node.span); 1336 world.warning('variable used as statement', node.span);
1289 } 1337 }
1290 var value = visitVoid(node.body); 1338 var value = visitVoid(node.body);
1291 writer.writeln('${value.code};'); 1339 writer.writeln('${value.code};');
1340 return false;
1292 } 1341 }
1293 1342
1294 void visitEmptyStatement(EmptyStatement node) { 1343 bool visitEmptyStatement(EmptyStatement node) {
1295 writer.writeln(';'); 1344 writer.writeln(';');
1345 return false;
1296 } 1346 }
1297 1347
1298 _checkNonStatic(Node node) { 1348 _checkNonStatic(Node node) {
1299 if (method.isStatic) { 1349 if (method.isStatic) {
1300 world.warning('not allowed in static method', node.span); 1350 world.warning('not allowed in static method', node.span);
1301 } 1351 }
1302 } 1352 }
1303 1353
1304 _makeSuperValue(Node node) { 1354 _makeSuperValue(Node node) {
1305 var parentType = method.declaringType.parent; 1355 var parentType = method.declaringType.parent;
(...skipping 470 matching lines...) Expand 10 before | Expand all | Expand 10 after
1776 } 1826 }
1777 for (var arg in node.arguments) { 1827 for (var arg in node.arguments) {
1778 if (!visitValue(arg.value).isConst) { 1828 if (!visitValue(arg.value).isConst) {
1779 world.error('const constructor expects const arguments', arg.span); 1829 world.error('const constructor expects const arguments', arg.span);
1780 } 1830 }
1781 } 1831 }
1782 } 1832 }
1783 return m.invoke(parent, node, null, _makeArgs(node.arguments)); 1833 return m.invoke(parent, node, null, _makeArgs(node.arguments));
1784 } 1834 }
1785 1835
1786 void visitListExpression(ListExpression node) { 1836 visitListExpression(ListExpression node) {
1787 // TODO(jimhug): Use node.type or other type inference here. 1837 // TODO(jimhug): Use node.type or other type inference here.
1788 var argsCode = []; 1838 var argsCode = [];
1789 var argValues = []; 1839 var argValues = [];
1790 for (var item in node.values) { 1840 for (var item in node.values) {
1791 var arg = visitValue(item); 1841 var arg = visitValue(item);
1792 argValues.add(arg); 1842 argValues.add(arg);
1793 if (node.isConst) { 1843 if (node.isConst) {
1794 if (!arg.isConst) { 1844 if (!arg.isConst) {
1795 world.error('const list can only contain const values', item.span); 1845 world.error('const list can only contain const values', item.span);
1796 argsCode.add(arg.code); 1846 argsCode.add(arg.code);
1797 } else { 1847 } else {
1798 argsCode.add(arg.canonicalCode); 1848 argsCode.add(arg.canonicalCode);
1799 } 1849 }
1800 } else { 1850 } else {
1801 argsCode.add(arg.code); 1851 argsCode.add(arg.code);
1802 } 1852 }
1803 } 1853 }
1804 1854
1805 var code = '[${Strings.join(argsCode, ", ")}]'; 1855 var code = '[${Strings.join(argsCode, ", ")}]';
1806 if (node.isConst) { 1856 if (node.isConst) {
1807 final value = new EvaluatedValue(world.listType, 1857 final value = new EvaluatedValue(world.listType,
1808 'const $code', code, node.span); 1858 'const $code', code, node.span);
1809 return parent.globalForConst(value, argValues); 1859 return parent.globalForConst(value, argValues);
1810 } 1860 }
1811 return new Value(world.listType, code); 1861 return new Value(world.listType, code);
1812 } 1862 }
1813 1863
1814 void visitMapExpression(MapExpression node) { 1864 visitMapExpression(MapExpression node) {
1815 // Ensure that Map factory is intialized - pseudo-call needed members. 1865 // Ensure that Map factory is intialized - pseudo-call needed members.
1816 var mapImplType = parent.useMapFactory(); 1866 var mapImplType = parent.useMapFactory();
1817 1867
1818 var argValues = []; 1868 var argValues = [];
1819 var argsCode = []; 1869 var argsCode = [];
1820 for (int i=0; i < node.items.length; i += 2) { 1870 for (int i=0; i < node.items.length; i += 2) {
1821 // TODO(jimhug): Use node.type or other type inference here. 1871 // TODO(jimhug): Use node.type or other type inference here.
1822 // TODO(jimhug): Would be nice to allow arbitrary keys here. 1872 // TODO(jimhug): Would be nice to allow arbitrary keys here.
1823 var key = visitTypedValue(node.items[i], world.stringType); 1873 var key = visitTypedValue(node.items[i], world.stringType);
1824 final valueItem = node.items[i+1]; 1874 final valueItem = node.items[i+1];
(...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after
2089 result.add(new Value(world.varType, '\$$i', false, /*needsTemp:*/false)); 2139 result.add(new Value(world.varType, '\$$i', false, /*needsTemp:*/false));
2090 } 2140 }
2091 for (int i = bareCount; i < length; i++) { 2141 for (int i = bareCount; i < length; i++) {
2092 var name = getName(i); 2142 var name = getName(i);
2093 if (name == null) name = '\$$i'; 2143 if (name == null) name = '\$$i';
2094 result.add(new Value(world.varType, name, false, /*needsTemp:*/false)); 2144 result.add(new Value(world.varType, name, false, /*needsTemp:*/false));
2095 } 2145 }
2096 return new Arguments(nodes, result); 2146 return new Arguments(nodes, result);
2097 } 2147 }
2098 } 2148 }
OLDNEW
« no previous file with comments | « frogsh ('k') | lib/corelib.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698