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

Side by Side Diff: runtime/vm/parser.cc

Issue 10513008: Fix super call invocation (issue 2028). (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 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
« no previous file with comments | « runtime/vm/parser.h ('k') | tests/co19/co19-runtime.status » ('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) 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 #include "vm/parser.h" 5 #include "vm/parser.h"
6 6
7 #include "vm/bigint_operations.h" 7 #include "vm/bigint_operations.h"
8 #include "vm/class_finalizer.h" 8 #include "vm/class_finalizer.h"
9 #include "vm/compiler.h" 9 #include "vm/compiler.h"
10 #include "vm/compiler_stats.h" 10 #include "vm/compiler_stats.h"
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
47 static const char* kListLiteralFactoryName = "List.fromLiteral"; 47 static const char* kListLiteralFactoryName = "List.fromLiteral";
48 static const char* kMapLiteralFactoryClassName = "_MapLiteralFactory"; 48 static const char* kMapLiteralFactoryClassName = "_MapLiteralFactory";
49 static const char* kMapLiteralFactoryName = "Map.fromLiteral"; 49 static const char* kMapLiteralFactoryName = "Map.fromLiteral";
50 static const char* kImmutableMapName = "ImmutableMap"; 50 static const char* kImmutableMapName = "ImmutableMap";
51 static const char* kImmutableMapConstructorName = "ImmutableMap._create"; 51 static const char* kImmutableMapConstructorName = "ImmutableMap._create";
52 static const char* kStringClassName = "StringBase"; 52 static const char* kStringClassName = "StringBase";
53 static const char* kInterpolateName = "_interpolate"; 53 static const char* kInterpolateName = "_interpolate";
54 static const char* kThisName = "this"; 54 static const char* kThisName = "this";
55 static const char* kPhaseParameterName = ":phase"; 55 static const char* kPhaseParameterName = ":phase";
56 static const char* kGetIteratorName = "iterator"; 56 static const char* kGetIteratorName = "iterator";
57 static const char* kNoSuchMethodName = "noSuchMethod";
57 58
58 #if defined(DEBUG) 59 #if defined(DEBUG)
59 60
60 class TraceParser : public ValueObject { 61 class TraceParser : public ValueObject {
61 public: 62 public:
62 TraceParser(intptr_t token_index, const Script& script, const char* msg) { 63 TraceParser(intptr_t token_index, const Script& script, const char* msg) {
63 if (FLAG_trace_parser) { 64 if (FLAG_trace_parser) {
64 intptr_t line, column; 65 intptr_t line, column;
65 script.GetTokenLocation(token_index, &line, &column); 66 script.GetTokenLocation(token_index, &line, &column);
66 PrintIndent(); 67 PrintIndent();
(...skipping 1137 matching lines...) Expand 10 before | Expand all | Expand 10 after
1204 func = super_cls.LookupDynamicFunction(name); 1205 func = super_cls.LookupDynamicFunction(name);
1205 if (!func.IsNull()) { 1206 if (!func.IsNull()) {
1206 return func.raw(); 1207 return func.raw();
1207 } 1208 }
1208 super_cls = super_cls.SuperClass(); 1209 super_cls = super_cls.SuperClass();
1209 } 1210 }
1210 } 1211 }
1211 return func.raw(); 1212 return func.raw();
1212 } 1213 }
1213 1214
1214 1215 // Resolve and return the dynamic function of the given name in the superclass.
1216 // If it is not found, return noSuchMethod and set is_no_such_method to true.
1215 RawFunction* Parser::GetSuperFunction(intptr_t token_pos, 1217 RawFunction* Parser::GetSuperFunction(intptr_t token_pos,
1216 const String& name) { 1218 const String& name,
1219 bool* is_no_such_method) {
1217 const Class& super_class = Class::Handle(current_class().SuperClass()); 1220 const Class& super_class = Class::Handle(current_class().SuperClass());
1218 if (super_class.IsNull()) { 1221 if (super_class.IsNull()) {
1219 ErrorMsg(token_pos, "class '%s' does not have a superclass", 1222 ErrorMsg(token_pos, "class '%s' does not have a superclass",
1220 String::Handle(current_class().Name()).ToCString()); 1223 String::Handle(current_class().Name()).ToCString());
1221 } 1224 }
1222 1225
1223 const Function& super_func = 1226 Function& super_func =
1224 Function::Handle(ResolveDynamicFunction(super_class, name)); 1227 Function::Handle(ResolveDynamicFunction(super_class, name));
1225 if (super_func.IsNull()) { 1228 if (super_func.IsNull()) {
1226 ErrorMsg(token_pos, "function '%s' not found in super class", 1229 const String& no_such_method_name =
1227 name.ToCString()); 1230 String::ZoneHandle(String::NewSymbol(kNoSuchMethodName));
1231 super_func = ResolveDynamicFunction(super_class, no_such_method_name);
1232 ASSERT(!super_func.IsNull());
1233 *is_no_such_method = true;
1234 } else {
1235 *is_no_such_method = false;
1228 } 1236 }
1229 CheckFunctionIsCallable(token_pos, super_func); 1237 CheckFunctionIsCallable(token_pos, super_func);
1230 return super_func.raw(); 1238 return super_func.raw();
1231 } 1239 }
1232 1240
1233 1241
1242 // Lookup class in the corelib implementation which contains various VM
1243 // helper methods and classes.
1244 static RawClass* LookupImplClass(const String& class_name) {
1245 return Library::Handle(Library::CoreImplLibrary()).LookupClass(class_name);
1246 }
1247
1248
1249 // Lookup class in the corelib which also contains various VM
1250 // helper methods and classes. Allow look up of private classes.
1251 static RawClass* LookupCoreClass(const String& class_name) {
1252 const Library& core_lib = Library::Handle(Library::CoreLibrary());
1253 String& name = String::Handle(class_name.raw());
1254 if (class_name.CharAt(0) == Scanner::kPrivateIdentifierStart) {
1255 // Private identifiers are mangled on a per script basis.
1256 name = String::Concat(name, String::Handle(core_lib.private_key()));
1257 name = String::NewSymbol(name);
1258 }
1259 return core_lib.LookupClass(name);
1260 }
1261
1262
1263 ArgumentListNode* Parser::BuildNoSuchMethodArguments(
1264 const String& function_name,
1265 const ArgumentListNode& function_args) {
1266 ASSERT(function_args.length() >= 1); // The receiver is the first argument.
1267 const intptr_t args_pos = function_args.token_index();
1268 ArgumentListNode* arguments = new ArgumentListNode(args_pos);
1269 arguments->Add(function_args.NodeAt(0));
1270 // The second argument is the original function name.
1271 // TODO(regis): This will change once mirrors are supported.
1272 arguments->Add(new LiteralNode(args_pos, function_name));
1273 // The third argument is an array containing the original function arguments.
1274 ArrayNode* args_array = new ArrayNode(args_pos, TypeArguments::ZoneHandle());
1275 for (intptr_t i = 1; i < function_args.length(); i++) {
1276 args_array->AddElement(function_args.NodeAt(i));
1277 }
1278 arguments->Add(args_array);
1279 return arguments;
1280 }
1281
1282
1234 AstNode* Parser::ParseSuperCall(const String& function_name) { 1283 AstNode* Parser::ParseSuperCall(const String& function_name) {
1235 TRACE_PARSER("ParseSuperCall"); 1284 TRACE_PARSER("ParseSuperCall");
1236 ASSERT(CurrentToken() == Token::kLPAREN); 1285 ASSERT(CurrentToken() == Token::kLPAREN);
1237 const intptr_t supercall_pos = token_index_; 1286 const intptr_t supercall_pos = token_index_;
1238 1287
1288 bool is_no_such_method = false;
1239 const Function& super_function = Function::ZoneHandle( 1289 const Function& super_function = Function::ZoneHandle(
1240 GetSuperFunction(supercall_pos, function_name)); 1290 GetSuperFunction(supercall_pos, function_name, &is_no_such_method));
1241 1291
1242 ArgumentListNode* arguments = new ArgumentListNode(supercall_pos); 1292 ArgumentListNode* arguments = new ArgumentListNode(supercall_pos);
1243 // 'this' parameter is the first argument to super call. 1293 // 'this' parameter is the first argument to super call.
1244 AstNode* receiver = LoadReceiver(supercall_pos); 1294 AstNode* receiver = LoadReceiver(supercall_pos);
1245 arguments->Add(receiver); 1295 arguments->Add(receiver);
1246 ParseActualParameters(arguments, kAllowConst); 1296 ParseActualParameters(arguments, kAllowConst);
1297 if (is_no_such_method) {
1298 arguments = BuildNoSuchMethodArguments(function_name, *arguments);
1299 }
1247 return new StaticCallNode(supercall_pos, super_function, arguments); 1300 return new StaticCallNode(supercall_pos, super_function, arguments);
1248 } 1301 }
1249 1302
1250 1303
1251 // Simple test if a node is side effect free. 1304 // Simple test if a node is side effect free.
1252 static bool IsSimpleLocalOrLiteralNode(AstNode* node) { 1305 static bool IsSimpleLocalOrLiteralNode(AstNode* node) {
1253 if (node->IsLiteralNode()) { 1306 if (node->IsLiteralNode()) {
1254 return true; 1307 return true;
1255 } 1308 }
1256 if (node->IsLoadLocalNode() && !node->AsLoadLocalNode()->HasPseudo()) { 1309 if (node->IsLoadLocalNode() && !node->AsLoadLocalNode()->HasPseudo()) {
(...skipping 24 matching lines...) Expand all
1281 AstNode* save = 1334 AstNode* save =
1282 new StoreLocalNode(operator_pos, *temp, index_expr); 1335 new StoreLocalNode(operator_pos, *temp, index_expr);
1283 current_block_->statements->Add(save); 1336 current_block_->statements->Add(save);
1284 index_expr = new LoadLocalNode(operator_pos, *temp); 1337 index_expr = new LoadLocalNode(operator_pos, *temp);
1285 } 1338 }
1286 } 1339 }
1287 1340
1288 // Resolve the [] operator function in the superclass. 1341 // Resolve the [] operator function in the superclass.
1289 const String& index_operator_name = 1342 const String& index_operator_name =
1290 String::ZoneHandle(String::NewSymbol(Token::Str(Token::kINDEX))); 1343 String::ZoneHandle(String::NewSymbol(Token::Str(Token::kINDEX)));
1344 bool is_no_such_method = false;
1291 const Function& index_operator = Function::ZoneHandle( 1345 const Function& index_operator = Function::ZoneHandle(
1292 GetSuperFunction(operator_pos, index_operator_name)); 1346 GetSuperFunction(operator_pos,
1347 index_operator_name,
1348 &is_no_such_method));
1293 1349
1294 ArgumentListNode* index_op_arguments = new ArgumentListNode(operator_pos); 1350 ArgumentListNode* index_op_arguments = new ArgumentListNode(operator_pos);
1295 AstNode* receiver = LoadReceiver(operator_pos); 1351 AstNode* receiver = LoadReceiver(operator_pos);
1296 index_op_arguments->Add(receiver); 1352 index_op_arguments->Add(receiver);
1297 index_op_arguments->Add(index_expr); 1353 index_op_arguments->Add(index_expr);
1298 1354
1355 if (is_no_such_method) {
1356 index_op_arguments = BuildNoSuchMethodArguments(index_operator_name,
1357 *index_op_arguments);
1358 }
1299 super_op = new StaticCallNode( 1359 super_op = new StaticCallNode(
1300 operator_pos, index_operator, index_op_arguments); 1360 operator_pos, index_operator, index_op_arguments);
1301 1361
1302 if (Token::IsAssignmentOperator(CurrentToken())) { 1362 if (Token::IsAssignmentOperator(CurrentToken())) {
1303 Token::Kind assignment_op = CurrentToken(); 1363 Token::Kind assignment_op = CurrentToken();
1304 ConsumeToken(); 1364 ConsumeToken();
1305 AstNode* value = ParseExpr(kAllowConst); 1365 AstNode* value = ParseExpr(kAllowConst);
1306 1366
1307 value = ExpandAssignableOp(operator_pos, assignment_op, super_op, value); 1367 value = ExpandAssignableOp(operator_pos, assignment_op, super_op, value);
1308 1368
1309 // Resolve the []= operator function in the superclass. 1369 // Resolve the []= operator function in the superclass.
1310 const String& assign_index_operator_name = String::ZoneHandle( 1370 const String& assign_index_operator_name = String::ZoneHandle(
1311 String::NewSymbol(Token::Str(Token::kASSIGN_INDEX))); 1371 String::NewSymbol(Token::Str(Token::kASSIGN_INDEX)));
1372 bool is_no_such_method = false;
1312 const Function& assign_index_operator = Function::ZoneHandle( 1373 const Function& assign_index_operator = Function::ZoneHandle(
1313 GetSuperFunction(operator_pos, assign_index_operator_name)); 1374 GetSuperFunction(operator_pos,
1375 assign_index_operator_name,
1376 &is_no_such_method));
1314 1377
1315 ArgumentListNode* operator_args = new ArgumentListNode(operator_pos); 1378 ArgumentListNode* operator_args = new ArgumentListNode(operator_pos);
1316 operator_args->Add(LoadReceiver(operator_pos)); 1379 operator_args->Add(LoadReceiver(operator_pos));
1317 operator_args->Add(index_expr); 1380 operator_args->Add(index_expr);
1318 operator_args->Add(value); 1381 operator_args->Add(value);
1319 1382
1383 if (is_no_such_method) {
1384 operator_args = BuildNoSuchMethodArguments(assign_index_operator_name,
1385 *operator_args);
1386 }
1320 super_op = new StaticCallNode( 1387 super_op = new StaticCallNode(
1321 operator_pos, assign_index_operator, operator_args); 1388 operator_pos, assign_index_operator, operator_args);
1322 } 1389 }
1323 } else if (Token::CanBeOverloaded(CurrentToken())) { 1390 } else if (Token::CanBeOverloaded(CurrentToken())) {
1324 Token::Kind op = CurrentToken(); 1391 Token::Kind op = CurrentToken();
1325 ConsumeToken(); 1392 ConsumeToken();
1326 1393
1327 // Resolve the operator function in the superclass. 1394 // Resolve the operator function in the superclass.
1328 const String& operator_function_name = 1395 const String& operator_function_name =
1329 String::Handle(String::NewSymbol(Token::Str(op))); 1396 String::Handle(String::NewSymbol(Token::Str(op)));
1397 bool is_no_such_method = false;
1330 const Function& super_operator = Function::ZoneHandle( 1398 const Function& super_operator = Function::ZoneHandle(
1331 GetSuperFunction(operator_pos, operator_function_name)); 1399 GetSuperFunction(operator_pos,
1400 operator_function_name,
1401 &is_no_such_method));
1332 1402
1333 ASSERT(Token::Precedence(op) >= Token::Precedence(Token::kBIT_OR)); 1403 ASSERT(Token::Precedence(op) >= Token::Precedence(Token::kBIT_OR));
1334 AstNode* other_operand = ParseBinaryExpr(Token::Precedence(op) + 1); 1404 AstNode* other_operand = ParseBinaryExpr(Token::Precedence(op) + 1);
1335 1405
1336 ArgumentListNode* op_arguments = new ArgumentListNode(operator_pos); 1406 ArgumentListNode* op_arguments = new ArgumentListNode(operator_pos);
1337 AstNode* receiver = LoadReceiver(operator_pos); 1407 AstNode* receiver = LoadReceiver(operator_pos);
1338 op_arguments->Add(receiver); 1408 op_arguments->Add(receiver);
1339 op_arguments->Add(other_operand); 1409 op_arguments->Add(other_operand);
1340 1410
1341 CheckFunctionIsCallable(operator_pos, super_operator); 1411 CheckFunctionIsCallable(operator_pos, super_operator);
1412 if (is_no_such_method) {
1413 op_arguments = BuildNoSuchMethodArguments(operator_function_name,
1414 *op_arguments);
1415 }
1342 super_op = new StaticCallNode(operator_pos, super_operator, op_arguments); 1416 super_op = new StaticCallNode(operator_pos, super_operator, op_arguments);
1343 } 1417 }
1344 return super_op; 1418 return super_op;
1345 } 1419 }
1346 1420
1347 1421
1348 AstNode* Parser::CreateImplicitClosureNode(const Function& func, 1422 AstNode* Parser::CreateImplicitClosureNode(const Function& func,
1349 intptr_t token_pos, 1423 intptr_t token_pos,
1350 AstNode* receiver) { 1424 AstNode* receiver) {
1351 Function& implicit_closure_function = 1425 Function& implicit_closure_function =
(...skipping 3575 matching lines...) Expand 10 before | Expand all | Expand 10 after
4927 CloseBlock(); 5001 CloseBlock();
4928 return new ForNode(for_pos, 5002 return new ForNode(for_pos,
4929 label, 5003 label,
4930 NodeAsSequenceNode(init_pos, initializer, init_scope), 5004 NodeAsSequenceNode(init_pos, initializer, init_scope),
4931 condition, 5005 condition,
4932 NodeAsSequenceNode(incr_pos, increment, incr_scope), 5006 NodeAsSequenceNode(incr_pos, increment, incr_scope),
4933 body); 5007 body);
4934 } 5008 }
4935 5009
4936 5010
4937 // Lookup class in the corelib implementation which contains various VM
4938 // helper methods and classes.
4939 static RawClass* LookupImplClass(const String& class_name) {
4940 return Library::Handle(Library::CoreImplLibrary()).LookupClass(class_name);
4941 }
4942
4943
4944 // Lookup class in the corelib which also contains various VM
4945 // helper methods and classes. Allow look up of private classes.
4946 static RawClass* LookupCoreClass(const String& class_name) {
4947 const Library& core_lib = Library::Handle(Library::CoreLibrary());
4948 String& name = String::Handle(class_name.raw());
4949 if (class_name.CharAt(0) == Scanner::kPrivateIdentifierStart) {
4950 // Private identifiers are mangled on a per script basis.
4951 name = String::Concat(name, String::Handle(core_lib.private_key()));
4952 name = String::NewSymbol(name);
4953 }
4954 return core_lib.LookupClass(name);
4955 }
4956
4957
4958 // Calling VM-internal helpers, uses implementation core library. 5011 // Calling VM-internal helpers, uses implementation core library.
4959 AstNode* Parser::MakeStaticCall(const char* class_name, 5012 AstNode* Parser::MakeStaticCall(const char* class_name,
4960 const char* function_name, 5013 const char* function_name,
4961 ArgumentListNode* arguments) { 5014 ArgumentListNode* arguments) {
4962 const String& cls_name = 5015 const String& cls_name =
4963 String::Handle(String::NewSymbol(class_name)); 5016 String::Handle(String::NewSymbol(class_name));
4964 const Class& cls = Class::Handle(LookupImplClass(cls_name)); 5017 const Class& cls = Class::Handle(LookupImplClass(cls_name));
4965 ASSERT(!cls.IsNull()); 5018 ASSERT(!cls.IsNull());
4966 const String& func_name = 5019 const String& func_name =
4967 String::ZoneHandle(String::NewSymbol(function_name)); 5020 String::ZoneHandle(String::NewSymbol(function_name));
(...skipping 3566 matching lines...) Expand 10 before | Expand all | Expand 10 after
8534 void Parser::SkipQualIdent() { 8587 void Parser::SkipQualIdent() {
8535 ASSERT(IsIdentifier()); 8588 ASSERT(IsIdentifier());
8536 ConsumeToken(); 8589 ConsumeToken();
8537 if (CurrentToken() == Token::kPERIOD) { 8590 if (CurrentToken() == Token::kPERIOD) {
8538 ConsumeToken(); // Consume the kPERIOD token. 8591 ConsumeToken(); // Consume the kPERIOD token.
8539 ExpectIdentifier("identifier expected after '.'"); 8592 ExpectIdentifier("identifier expected after '.'");
8540 } 8593 }
8541 } 8594 }
8542 8595
8543 } // namespace dart 8596 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/parser.h ('k') | tests/co19/co19-runtime.status » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698