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

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
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 847 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);
1054 var exit1;
1040 writer.write('if (${test.code}) '); 1055 writer.write('if (${test.code}) ');
1041 node.trueBranch.visit(this); 1056 exit1 = node.trueBranch.visit(this);
jimhug 2011/10/28 20:02:44 I'd move the var decl to this line as I really lik
1042 if (node.falseBranch != null) { 1057 if (node.falseBranch != null) {
1043 writer.write('else '); 1058 writer.write('else ');
1044 node.falseBranch.visit(this); 1059 if (node.falseBranch.visit(this) && exit1) {
1060 return true;
1061 }
1045 } 1062 }
1063 return false;
1046 } 1064 }
1047 1065
1048 void visitWhileStatement(WhileStatement node) { 1066 bool visitWhileStatement(WhileStatement node) {
1049 var test = visitBool(node.test); 1067 var test = visitBool(node.test);
1050 writer.write('while (${test.code}) '); 1068 writer.write('while (${test.code}) ');
1051 _pushBlock(/*reentrant:*/true); 1069 _pushBlock(/*reentrant:*/true);
1052 node.body.visit(this); 1070 node.body.visit(this);
1053 _popBlock(); 1071 _popBlock();
1072 return false;
1054 } 1073 }
1055 1074
1056 void visitDoStatement(DoStatement node) { 1075 bool visitDoStatement(DoStatement node) {
1057 writer.write('do '); 1076 writer.write('do ');
1058 _pushBlock(/*reentrant:*/true); 1077 _pushBlock(/*reentrant:*/true);
1059 node.body.visit(this); 1078 node.body.visit(this);
1060 _popBlock(); 1079 _popBlock();
1061 var test = visitBool(node.test); 1080 var test = visitBool(node.test);
1062 writer.writeln('while (${test.code})'); 1081 writer.writeln('while (${test.code})');
1082 return false;
1063 } 1083 }
1064 1084
1065 void visitForStatement(ForStatement node) { 1085 bool visitForStatement(ForStatement node) {
1066 _pushBlock(); 1086 _pushBlock();
1067 writer.write('for ('); 1087 writer.write('for (');
1068 if (node.init != null) node.init.visit(this); 1088 if (node.init != null) node.init.visit(this);
1069 else writer.write(';'); 1089 else writer.write(';');
1070 if (node.test != null) { 1090 if (node.test != null) {
1071 var test = visitBool(node.test); 1091 var test = visitBool(node.test);
1072 writer.write(' ${test.code}; '); 1092 writer.write(' ${test.code}; ');
1073 } else { 1093 } else {
1074 writer.write('; '); 1094 writer.write('; ');
1075 } 1095 }
1076 1096
1077 bool needsComma = false; 1097 bool needsComma = false;
1078 for (var s in node.step) { 1098 for (var s in node.step) {
1079 if (needsComma) writer.write(', '); 1099 if (needsComma) writer.write(', ');
1080 var sv = visitVoid(s); 1100 var sv = visitVoid(s);
1081 writer.write(sv.code); 1101 writer.write(sv.code);
1082 needsComma = true; 1102 needsComma = true;
1083 } 1103 }
1084 writer.write(') '); 1104 writer.write(') ');
1085 _pushBlock(/*reentrant:*/true); 1105 _pushBlock(/*reentrant:*/true);
1086 node.body.visit(this); 1106 node.body.visit(this);
1087 _popBlock(); 1107 _popBlock();
1088 _popBlock(); 1108 _popBlock();
1109 return false;
1089 } 1110 }
1090 1111
1091 void visitForInStatement(ForInStatement node) { 1112 bool visitForInStatement(ForInStatement node) {
1092 // TODO(jimhug): visitValue and other cleanups here. 1113 // TODO(jimhug): visitValue and other cleanups here.
1093 var itemType = method.resolveType(node.item.type); 1114 var itemType = method.resolveType(node.item.type);
1094 var itemName = node.item.name.name; 1115 var itemName = node.item.name.name;
1095 var list = node.list.visit(this); 1116 var list = node.list.visit(this);
1096 _pushBlock(/*reentrant:*/true); 1117 _pushBlock(/*reentrant:*/true);
1097 // TODO(jimhug): Check that itemType matches list members... 1118 // TODO(jimhug): Check that itemType matches list members...
1098 var item = _scope.create(itemName, itemType, node.item.name); 1119 var item = _scope.create(itemName, itemType, node.item.name);
1099 Value listVar = list; 1120 Value listVar = list;
1100 if (list.needsTemp) { 1121 if (list.needsTemp) {
1101 listVar = _scope.create('\$list', list.type, null); 1122 listVar = _scope.create('\$list', list.type, null);
(...skipping 23 matching lines...) Expand all
1125 var next = tmpi.invoke(parent, 'next', node.list, Arguments.EMPTY); 1146 var next = tmpi.invoke(parent, 'next', node.list, Arguments.EMPTY);
1126 1147
1127 writer.enterBlock( 1148 writer.enterBlock(
1128 'for (var ${tmpi.code} = ${iterator.code}; ${hasNext.code}; ) {'); 1149 'for (var ${tmpi.code} = ${iterator.code}; ${hasNext.code}; ) {');
1129 writer.writeln('var ${item.code} = ${next.code};'); 1150 writer.writeln('var ${item.code} = ${next.code};');
1130 } 1151 }
1131 1152
1132 visitStatementsInBlock(node.body); 1153 visitStatementsInBlock(node.body);
1133 writer.exitBlock('}'); 1154 writer.exitBlock('}');
1134 _popBlock(); 1155 _popBlock();
1156 return false;
1135 } 1157 }
1136 1158
1137 void visitTryStatement(TryStatement node) { 1159 bool visitTryStatement(TryStatement node) {
1138 writer.enterBlock('try {'); 1160 writer.enterBlock('try {');
1139 _pushBlock(); 1161 _pushBlock();
1140 visitStatementsInBlock(node.body); 1162 visitStatementsInBlock(node.body);
1141 _popBlock(); 1163 _popBlock();
1142 1164
1143 if (node.catches.length == 1) { 1165 if (node.catches.length == 1) {
1144 // Handle a single catch. We can generate simple code here compared to the 1166 // 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. 1167 // multiple catch, such as no extra temp or if-else-if chain.
1146 var catch_ = node.catches[0]; 1168 var catch_ = node.catches[0];
1147 _pushBlock(); 1169 _pushBlock();
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
1221 } 1243 }
1222 1244
1223 if (node.finallyBlock != null) { 1245 if (node.finallyBlock != null) {
1224 writer.nextBlock('} finally {'); 1246 writer.nextBlock('} finally {');
1225 _pushBlock(); 1247 _pushBlock();
1226 visitStatementsInBlock(node.finallyBlock); 1248 visitStatementsInBlock(node.finallyBlock);
1227 _popBlock(); 1249 _popBlock();
1228 } 1250 }
1229 1251
1230 // Close the try-catch-finally 1252 // Close the try-catch-finally
1231 writer.exitBlock('}'); 1253 writer.exitBlock('}');
jimhug 2011/10/28 20:02:44 Add a TODO: This could be more precise by combinin
1254 return false;
1232 } 1255 }
1233 1256
1234 void visitSwitchStatement(SwitchStatement node) { 1257 bool visitSwitchStatement(SwitchStatement node) {
1235 // TODO(jimhug): Lots of negative tests to check for. 1258 // TODO(jimhug): Lots of negative tests to check for.
1236 var test = visitValue(node.test); 1259 var test = visitValue(node.test);
1237 writer.enterBlock('switch (${test.code}) {'); 1260 writer.enterBlock('switch (${test.code}) {');
1238 for (var case_ in node.cases) { 1261 for (var case_ in node.cases) {
1239 if (case_.label != null) { 1262 if (case_.label != null) {
1240 world.error('unimplemented: labeled case statement', case_.span); 1263 world.error('unimplemented: labeled case statement', case_.span);
1241 } 1264 }
1242 _pushBlock(); 1265 _pushBlock();
1243 for (int i=0; i < case_.cases.length; i++) { 1266 for (int i=0; i < case_.cases.length; i++) {
1244 var expr = case_.cases[i]; 1267 var expr = case_.cases[i];
1245 if (expr == null) { 1268 if (expr == null) {
1246 // Default can only be the last case. 1269 // Default can only be the last case.
1247 if (i < case_.cases.length - 1) { 1270 if (i < case_.cases.length - 1) {
1248 world.error('default clause must be the last case', case_.span); 1271 world.error('default clause must be the last case', case_.span);
1249 } 1272 }
1250 writer.writeln('default:'); 1273 writer.writeln('default:');
1251 } else { 1274 } else {
1252 var value = visitValue(expr); 1275 var value = visitValue(expr);
1253 writer.writeln('case ${value.code}:'); 1276 writer.writeln('case ${value.code}:');
1254 } 1277 }
1255 } 1278 }
1256 writer.enterBlock(''); 1279 writer.enterBlock('');
1257 for (var stmt in case_.statements) { 1280 bool caseExits = false;
1258 stmt.visit(this); 1281 for (int i = 0; i < case_.statements.length; i++) {
1282 var stmt = case_.statements[i];
1283 caseExits = stmt.visit(this);
1284 if (stmt != case_.statements[case_.statements.length - 1] && caseExits) {
1285 world.warning('unreachable code', case_.statements[i + 1].span);
jimhug 2011/10/28 20:02:44 Don't worry about it in this checkin - but for a f
1286 }
1259 } 1287 }
1260 if (case_ != node.cases[node.cases.length - 1]) { 1288 if (case_ != node.cases[node.cases.length - 1] && !caseExits) {
1261 var span = case_.statements[case_.statements.length - 1].span; 1289 var span = case_.statements[case_.statements.length - 1].span;
1290 //TODO(efortuna): This error message isn't 100% correct because
1291 // constructors are not being built correctly. Check back for correct
1292 // output when constructors are fixed.
1293 writer.writeln('\$throw(new FallThroughError("${span.file.filename}",' +
1294 ' ${span.file.getLine(span.start)}))');
1262 } 1295 }
1263 writer.exitBlock(''); 1296 writer.exitBlock('');
1264 _popBlock(); 1297 _popBlock();
1265 } 1298 }
1266 writer.exitBlock('}'); 1299 writer.exitBlock('}');
1300 // TODO(efortuna): When we are passing more information back about
1301 // control flow by returning something other than bool, return true for the
1302 // cases where every branch of the switch statement ends with a return
1303 // statement.
jimhug 2011/10/28 20:02:44 Nice TODO.
1304 return false;
1267 } 1305 }
1268 1306
1269 void visitBlockStatement(BlockStatement node) { 1307 bool visitBlockStatement(BlockStatement node) {
1270 _pushBlock(); 1308 _pushBlock();
1271 writer.enterBlock('{'); 1309 writer.enterBlock('{');
1272 for (var stmt in node.body) { 1310 var exits = false;
1273 stmt.visit(this); 1311 for (int i = 0; i < node.body.length; i++) {
1312 var stmt = node.body[i];
1313 exits = stmt.visit(this);
1314 if (exits && stmt != node.body[node.body.length - 1]) {
jimhug 2011/10/28 20:02:44 TODO: Again, not for this checkin - but the same s
1315 world.warning('unreachable code', node.body[i + 1].span);
1316 }
1274 } 1317 }
1275 writer.exitBlock('}'); 1318 writer.exitBlock('}');
1276 _popBlock(); 1319 _popBlock();
1320 return exits;
1277 } 1321 }
1278 1322
1279 void visitLabeledStatement(LabeledStatement node) { 1323 bool visitLabeledStatement(LabeledStatement node) {
1280 writer.writeln('${node.name.name}:'); 1324 writer.writeln('${node.name.name}:');
1281 node.body.visit(this); 1325 node.body.visit(this);
1326 return false;
1282 } 1327 }
1283 1328
1284 void visitExpressionStatement(ExpressionStatement node) { 1329 bool visitExpressionStatement(ExpressionStatement node) {
1285 if (node.body is VarExpression || node.body is ThisExpression) { 1330 if (node.body is VarExpression || node.body is ThisExpression) {
1286 // TODO(jmesserly): this is a "warning" but not a "type warning", 1331 // TODO(jmesserly): this is a "warning" but not a "type warning",
1287 // Is that okay? We have a similar issue around unreachable code warnings. 1332 // Is that okay? We have a similar issue around unreachable code warnings.
1288 world.warning('variable used as statement', node.span); 1333 world.warning('variable used as statement', node.span);
1289 } 1334 }
1290 var value = visitVoid(node.body); 1335 var value = visitVoid(node.body);
1291 writer.writeln('${value.code};'); 1336 writer.writeln('${value.code};');
1337 return false;
1292 } 1338 }
1293 1339
1294 void visitEmptyStatement(EmptyStatement node) { 1340 bool visitEmptyStatement(EmptyStatement node) {
1295 writer.writeln(';'); 1341 writer.writeln(';');
1342 return false;
1296 } 1343 }
1297 1344
1298 _checkNonStatic(Node node) { 1345 _checkNonStatic(Node node) {
1299 if (method.isStatic) { 1346 if (method.isStatic) {
1300 world.warning('not allowed in static method', node.span); 1347 world.warning('not allowed in static method', node.span);
1301 } 1348 }
1302 } 1349 }
1303 1350
1304 _makeSuperValue(Node node) { 1351 _makeSuperValue(Node node) {
1305 var parentType = method.declaringType.parent; 1352 var parentType = method.declaringType.parent;
(...skipping 470 matching lines...) Expand 10 before | Expand all | Expand 10 after
1776 } 1823 }
1777 for (var arg in node.arguments) { 1824 for (var arg in node.arguments) {
1778 if (!visitValue(arg.value).isConst) { 1825 if (!visitValue(arg.value).isConst) {
1779 world.error('const constructor expects const arguments', arg.span); 1826 world.error('const constructor expects const arguments', arg.span);
1780 } 1827 }
1781 } 1828 }
1782 } 1829 }
1783 return m.invoke(parent, node, null, _makeArgs(node.arguments)); 1830 return m.invoke(parent, node, null, _makeArgs(node.arguments));
1784 } 1831 }
1785 1832
1786 void visitListExpression(ListExpression node) { 1833 visitListExpression(ListExpression node) {
1787 // TODO(jimhug): Use node.type or other type inference here. 1834 // TODO(jimhug): Use node.type or other type inference here.
1788 var argsCode = []; 1835 var argsCode = [];
1789 var argValues = []; 1836 var argValues = [];
1790 for (var item in node.values) { 1837 for (var item in node.values) {
1791 var arg = visitValue(item); 1838 var arg = visitValue(item);
1792 argValues.add(arg); 1839 argValues.add(arg);
1793 if (node.isConst) { 1840 if (node.isConst) {
1794 if (!arg.isConst) { 1841 if (!arg.isConst) {
1795 world.error('const list can only contain const values', item.span); 1842 world.error('const list can only contain const values', item.span);
1796 argsCode.add(arg.code); 1843 argsCode.add(arg.code);
1797 } else { 1844 } else {
1798 argsCode.add(arg.canonicalCode); 1845 argsCode.add(arg.canonicalCode);
1799 } 1846 }
1800 } else { 1847 } else {
1801 argsCode.add(arg.code); 1848 argsCode.add(arg.code);
1802 } 1849 }
1803 } 1850 }
1804 1851
1805 var code = '[${Strings.join(argsCode, ", ")}]'; 1852 var code = '[${Strings.join(argsCode, ", ")}]';
1806 if (node.isConst) { 1853 if (node.isConst) {
1807 final value = new EvaluatedValue(world.listType, 1854 final value = new EvaluatedValue(world.listType,
1808 'const $code', code, node.span); 1855 'const $code', code, node.span);
1809 return parent.globalForConst(value, argValues); 1856 return parent.globalForConst(value, argValues);
1810 } 1857 }
1811 return new Value(world.listType, code); 1858 return new Value(world.listType, code);
1812 } 1859 }
1813 1860
1814 void visitMapExpression(MapExpression node) { 1861 visitMapExpression(MapExpression node) {
1815 // Ensure that Map factory is intialized - pseudo-call needed members. 1862 // Ensure that Map factory is intialized - pseudo-call needed members.
1816 var mapImplType = parent.useMapFactory(); 1863 var mapImplType = parent.useMapFactory();
1817 1864
1818 var argValues = []; 1865 var argValues = [];
1819 var argsCode = []; 1866 var argsCode = [];
1820 for (int i=0; i < node.items.length; i += 2) { 1867 for (int i=0; i < node.items.length; i += 2) {
1821 // TODO(jimhug): Use node.type or other type inference here. 1868 // TODO(jimhug): Use node.type or other type inference here.
1822 // TODO(jimhug): Would be nice to allow arbitrary keys here. 1869 // TODO(jimhug): Would be nice to allow arbitrary keys here.
1823 var key = visitTypedValue(node.items[i], world.stringType); 1870 var key = visitTypedValue(node.items[i], world.stringType);
1824 final valueItem = node.items[i+1]; 1871 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)); 2136 result.add(new Value(world.varType, '\$$i', false, /*needsTemp:*/false));
2090 } 2137 }
2091 for (int i = bareCount; i < length; i++) { 2138 for (int i = bareCount; i < length; i++) {
2092 var name = getName(i); 2139 var name = getName(i);
2093 if (name == null) name = '\$$i'; 2140 if (name == null) name = '\$$i';
2094 result.add(new Value(world.varType, name, false, /*needsTemp:*/false)); 2141 result.add(new Value(world.varType, name, false, /*needsTemp:*/false));
2095 } 2142 }
2096 return new Arguments(nodes, result); 2143 return new Arguments(nodes, result);
2097 } 2144 }
2098 } 2145 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698