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

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

Issue 11342027: Handle super call to unary operators (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 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 | « runtime/vm/parser.h ('k') | runtime/vm/symbols.h » ('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 1368 matching lines...) Expand 10 before | Expand all | Expand 10 after
1379 if (node->IsLiteralNode()) { 1379 if (node->IsLiteralNode()) {
1380 return true; 1380 return true;
1381 } 1381 }
1382 if (node->IsLoadLocalNode() && !node->AsLoadLocalNode()->HasPseudo()) { 1382 if (node->IsLoadLocalNode() && !node->AsLoadLocalNode()->HasPseudo()) {
1383 return true; 1383 return true;
1384 } 1384 }
1385 return false; 1385 return false;
1386 } 1386 }
1387 1387
1388 1388
1389 AstNode* Parser::BuildUnarySuperOperator(Token::Kind op, PrimaryNode* super) {
1390 ASSERT(super->IsSuper());
1391 AstNode* super_op = NULL;
1392 const intptr_t super_pos = super->token_pos();
1393 if ((op == Token::kNEGATE) ||
1394 (op == Token::kBIT_NOT)) {
1395 // Resolve the operator function in the superclass.
1396 const String& operator_function_name =
1397 String::ZoneHandle(Symbols::New(Token::Str(op)));
1398 const bool kResolveGetter = false;
1399 bool is_no_such_method = false;
1400 const Function& super_operator = Function::ZoneHandle(
1401 GetSuperFunction(super_pos,
1402 operator_function_name,
1403 kResolveGetter,
1404 &is_no_such_method));
1405 ArgumentListNode* op_arguments = new ArgumentListNode(super_pos);
1406 AstNode* receiver = LoadReceiver(super_pos);
1407 op_arguments->Add(receiver);
1408 CheckFunctionIsCallable(super_pos, super_operator);
1409 if (is_no_such_method) {
1410 op_arguments = BuildNoSuchMethodArguments(operator_function_name,
1411 *op_arguments);
1412 }
1413 super_op = new StaticCallNode(super_pos, super_operator, op_arguments);
1414 } else {
1415 ErrorMsg(super_pos, "illegal super operator call");
1416 }
1417 return super_op;
1418 }
1419
1420
1389 AstNode* Parser::ParseSuperOperator() { 1421 AstNode* Parser::ParseSuperOperator() {
1390 TRACE_PARSER("ParseSuperOperator"); 1422 TRACE_PARSER("ParseSuperOperator");
1391 AstNode* super_op = NULL; 1423 AstNode* super_op = NULL;
1392 const intptr_t operator_pos = TokenPos(); 1424 const intptr_t operator_pos = TokenPos();
1393 1425
1394 if (CurrentToken() == Token::kLBRACK) { 1426 if (CurrentToken() == Token::kLBRACK) {
1395 ConsumeToken(); 1427 ConsumeToken();
1396 AstNode* index_expr = ParseExpr(kAllowConst, kConsumeCascades); 1428 AstNode* index_expr = ParseExpr(kAllowConst, kConsumeCascades);
1397 ExpectToken(Token::kRBRACK); 1429 ExpectToken(Token::kRBRACK);
1398 AstNode* receiver = LoadReceiver(operator_pos); 1430 AstNode* receiver = LoadReceiver(operator_pos);
(...skipping 5251 matching lines...) Expand 10 before | Expand all | Expand 10 after
6650 const String& cls_name = String::Handle(Symbols::NoSuchMethodError()); 6682 const String& cls_name = String::Handle(Symbols::NoSuchMethodError());
6651 const String& func_name = String::Handle(Symbols::ThrowNew()); 6683 const String& func_name = String::Handle(Symbols::ThrowNew());
6652 return MakeStaticCall(cls_name, func_name, arguments); 6684 return MakeStaticCall(cls_name, func_name, arguments);
6653 } 6685 }
6654 6686
6655 6687
6656 AstNode* Parser::ParseBinaryExpr(int min_preced) { 6688 AstNode* Parser::ParseBinaryExpr(int min_preced) {
6657 TRACE_PARSER("ParseBinaryExpr"); 6689 TRACE_PARSER("ParseBinaryExpr");
6658 ASSERT(min_preced >= 4); 6690 ASSERT(min_preced >= 4);
6659 AstNode* left_operand = ParseUnaryExpr(); 6691 AstNode* left_operand = ParseUnaryExpr();
6692 if (left_operand->IsPrimaryNode() &&
6693 (left_operand->AsPrimaryNode()->IsSuper())) {
6694 ErrorMsg(left_operand->token_pos(), "illegal use of 'super'");
6695 }
6660 if (IsLiteral("as")) { // Not a reserved word. 6696 if (IsLiteral("as")) { // Not a reserved word.
6661 token_kind_ = Token::kAS; 6697 token_kind_ = Token::kAS;
6662 } 6698 }
6663 int current_preced = Token::Precedence(CurrentToken()); 6699 int current_preced = Token::Precedence(CurrentToken());
6664 while (current_preced >= min_preced) { 6700 while (current_preced >= min_preced) {
6665 while (Token::Precedence(CurrentToken()) == current_preced) { 6701 while (Token::Precedence(CurrentToken()) == current_preced) {
6666 Token::Kind op_kind = CurrentToken(); 6702 Token::Kind op_kind = CurrentToken();
6667 if (op_kind == Token::kTIGHTADD) { 6703 if (op_kind == Token::kTIGHTADD) {
6668 op_kind = Token::kADD; 6704 op_kind = Token::kADD;
6669 } 6705 }
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
6713 op_pos, op_kind, left_operand, right_operand); 6749 op_pos, op_kind, left_operand, right_operand);
6714 } 6750 }
6715 } 6751 }
6716 current_preced--; 6752 current_preced--;
6717 } 6753 }
6718 return left_operand; 6754 return left_operand;
6719 } 6755 }
6720 6756
6721 6757
6722 bool Parser::IsAssignableExpr(AstNode* expr) { 6758 bool Parser::IsAssignableExpr(AstNode* expr) {
6723 return expr->IsPrimaryNode() 6759 return (expr->IsLoadLocalNode() && !expr->AsLoadLocalNode()->HasPseudo())
6724 || (expr->IsLoadLocalNode() && !expr->AsLoadLocalNode()->HasPseudo())
6725 || expr->IsLoadStaticFieldNode() 6760 || expr->IsLoadStaticFieldNode()
6726 || expr->IsStaticGetterNode() 6761 || expr->IsStaticGetterNode()
6727 || expr->IsInstanceGetterNode() 6762 || expr->IsInstanceGetterNode()
6728 || expr->IsLoadIndexedNode(); 6763 || expr->IsLoadIndexedNode()
6764 || (expr->IsPrimaryNode() && !expr->AsPrimaryNode()->IsSuper());
6729 } 6765 }
6730 6766
6731 6767
6732 AstNode* Parser::ParseExprList() { 6768 AstNode* Parser::ParseExprList() {
6733 TRACE_PARSER("ParseExprList"); 6769 TRACE_PARSER("ParseExprList");
6734 AstNode* expressions = ParseExpr(kAllowConst, kConsumeCascades); 6770 AstNode* expressions = ParseExpr(kAllowConst, kConsumeCascades);
6735 if (CurrentToken() == Token::kCOMMA) { 6771 if (CurrentToken() == Token::kCOMMA) {
6736 // Collect comma-separated expressions in a non scope owning sequence node. 6772 // Collect comma-separated expressions in a non scope owning sequence node.
6737 SequenceNode* list = new SequenceNode(TokenPos(), NULL); 6773 SequenceNode* list = new SequenceNode(TokenPos(), NULL);
6738 list->Add(expressions); 6774 list->Add(expressions);
(...skipping 336 matching lines...) Expand 10 before | Expand all | Expand 10 after
7075 unary_op = Token::kNEGATE; 7111 unary_op = Token::kNEGATE;
7076 } 7112 }
7077 ConsumeToken(); 7113 ConsumeToken();
7078 expr = ParseUnaryExpr(); 7114 expr = ParseUnaryExpr();
7079 if (unary_op == Token::kTIGHTADD) { 7115 if (unary_op == Token::kTIGHTADD) {
7080 // kTIGHADD is added only in front of a number literal. 7116 // kTIGHADD is added only in front of a number literal.
7081 if (!expr->IsLiteralNode()) { 7117 if (!expr->IsLiteralNode()) {
7082 ErrorMsg(op_pos, "unexpected operator '+'"); 7118 ErrorMsg(op_pos, "unexpected operator '+'");
7083 } 7119 }
7084 // Expression is the literal itself. 7120 // Expression is the literal itself.
7121 } else if (expr->IsPrimaryNode() && (expr->AsPrimaryNode()->IsSuper())) {
7122 expr = BuildUnarySuperOperator(unary_op, expr->AsPrimaryNode());
7085 } else { 7123 } else {
7086 expr = UnaryOpNode::UnaryOpOrLiteral(op_pos, unary_op, expr); 7124 expr = UnaryOpNode::UnaryOpOrLiteral(op_pos, unary_op, expr);
7087 } 7125 }
7088 } else if (IsIncrementOperator(CurrentToken())) { 7126 } else if (IsIncrementOperator(CurrentToken())) {
7089 Token::Kind incr_op = CurrentToken(); 7127 Token::Kind incr_op = CurrentToken();
7090 ConsumeToken(); 7128 ConsumeToken();
7091 expr = ParseUnaryExpr(); 7129 expr = ParseUnaryExpr();
7092 if (!IsAssignableExpr(expr)) { 7130 if (!IsAssignableExpr(expr)) {
7093 ErrorMsg("expression is not assignable"); 7131 ErrorMsg("expression is not assignable");
7094 } 7132 }
(...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after
7342 return access; 7380 return access;
7343 } 7381 }
7344 7382
7345 7383
7346 AstNode* Parser::LoadFieldIfUnresolved(AstNode* node) { 7384 AstNode* Parser::LoadFieldIfUnresolved(AstNode* node) {
7347 if (!node->IsPrimaryNode()) { 7385 if (!node->IsPrimaryNode()) {
7348 return node; 7386 return node;
7349 } 7387 }
7350 PrimaryNode* primary = node->AsPrimaryNode(); 7388 PrimaryNode* primary = node->AsPrimaryNode();
7351 if (primary->primary().IsString()) { 7389 if (primary->primary().IsString()) {
7390 if (primary->IsSuper()) {
7391 return primary;
7392 }
7352 // In a static method, evaluation of an unresolved identifier causes a 7393 // In a static method, evaluation of an unresolved identifier causes a
7353 // NoSuchMethodError to be thrown. 7394 // NoSuchMethodError to be thrown.
7354 // In an instance method, we convert this into a getter call 7395 // In an instance method, we convert this into a getter call
7355 // for a field (which may be defined in a subclass.) 7396 // for a field (which may be defined in a subclass.)
7356 String& name = String::CheckedZoneHandle(primary->primary().raw()); 7397 String& name = String::CheckedZoneHandle(primary->primary().raw());
7357 if (current_function().is_static() || 7398 if (current_function().is_static() ||
7358 current_function().IsInFactoryScope()) { 7399 current_function().IsInFactoryScope()) {
7359 return ThrowNoSuchMethodError(primary->token_pos(), name); 7400 return ThrowNoSuchMethodError(primary->token_pos(), name);
7360 } else { 7401 } else {
7361 AstNode* receiver = LoadReceiver(primary->token_pos()); 7402 AstNode* receiver = LoadReceiver(primary->token_pos());
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
7393 AstNode* Parser::ParseSelectors(AstNode* primary, bool is_cascade) { 7434 AstNode* Parser::ParseSelectors(AstNode* primary, bool is_cascade) {
7394 AstNode* left = primary; 7435 AstNode* left = primary;
7395 while (true) { 7436 while (true) {
7396 AstNode* selector = NULL; 7437 AstNode* selector = NULL;
7397 if (CurrentToken() == Token::kPERIOD) { 7438 if (CurrentToken() == Token::kPERIOD) {
7398 ConsumeToken(); 7439 ConsumeToken();
7399 if (left->IsPrimaryNode()) { 7440 if (left->IsPrimaryNode()) {
7400 if (left->AsPrimaryNode()->primary().IsFunction()) { 7441 if (left->AsPrimaryNode()->primary().IsFunction()) {
7401 left = LoadClosure(left->AsPrimaryNode()); 7442 left = LoadClosure(left->AsPrimaryNode());
7402 } else { 7443 } else {
7444 // Super field access handled in ParseSuperFieldAccess(),
7445 // super calls handled in ParseSuperCall().
7446 ASSERT(!left->AsPrimaryNode()->IsSuper());
7403 left = LoadFieldIfUnresolved(left); 7447 left = LoadFieldIfUnresolved(left);
7404 } 7448 }
7405 } 7449 }
7406 const intptr_t ident_pos = TokenPos(); 7450 const intptr_t ident_pos = TokenPos();
7407 String* ident = ExpectIdentifier("identifier expected"); 7451 String* ident = ExpectIdentifier("identifier expected");
7408 if (CurrentToken() == Token::kLPAREN) { 7452 if (CurrentToken() == Token::kLPAREN) {
7409 // Identifier followed by a opening paren: method call. 7453 // Identifier followed by a opening paren: method call.
7410 if (left->IsPrimaryNode() 7454 if (left->IsPrimaryNode()
7411 && left->AsPrimaryNode()->primary().IsClass()) { 7455 && left->AsPrimaryNode()->primary().IsClass()) {
7412 // Static method call prefixed with class name. 7456 // Static method call prefixed with class name.
(...skipping 17 matching lines...) Expand all
7430 if (cls.IsNull()) { 7474 if (cls.IsNull()) {
7431 // Instance field access. 7475 // Instance field access.
7432 selector = CallGetter(ident_pos, left, *ident); 7476 selector = CallGetter(ident_pos, left, *ident);
7433 } else { 7477 } else {
7434 // Static field access. 7478 // Static field access.
7435 selector = 7479 selector =
7436 ParseStaticFieldAccess(cls, *ident, ident_pos, !is_cascade); 7480 ParseStaticFieldAccess(cls, *ident, ident_pos, !is_cascade);
7437 } 7481 }
7438 } 7482 }
7439 } else if (CurrentToken() == Token::kLBRACK) { 7483 } else if (CurrentToken() == Token::kLBRACK) {
7484 // Super index operator handled in ParseSuperOperator().
7485 ASSERT(!left->IsPrimaryNode() || !left->AsPrimaryNode()->IsSuper());
7486
7440 const intptr_t bracket_pos = TokenPos(); 7487 const intptr_t bracket_pos = TokenPos();
7441 ConsumeToken(); 7488 ConsumeToken();
7442 left = LoadFieldIfUnresolved(left); 7489 left = LoadFieldIfUnresolved(left);
7443 const bool saved_mode = SetAllowFunctionLiterals(true); 7490 const bool saved_mode = SetAllowFunctionLiterals(true);
7444 AstNode* index = ParseExpr(kAllowConst, kConsumeCascades); 7491 AstNode* index = ParseExpr(kAllowConst, kConsumeCascades);
7445 SetAllowFunctionLiterals(saved_mode); 7492 SetAllowFunctionLiterals(saved_mode);
7446 ExpectToken(Token::kRBRACK); 7493 ExpectToken(Token::kRBRACK);
7447 AstNode* array = left; 7494 AstNode* array = left;
7448 if (left->IsPrimaryNode()) { 7495 if (left->IsPrimaryNode()) {
7449 PrimaryNode* primary = left->AsPrimaryNode(); 7496 PrimaryNode* primary = left->AsPrimaryNode();
(...skipping 25 matching lines...) Expand all
7475 if (current_function().is_static()) { 7522 if (current_function().is_static()) {
7476 ErrorMsg(primary_pos, 7523 ErrorMsg(primary_pos,
7477 "cannot access instance method '%s' " 7524 "cannot access instance method '%s' "
7478 "from static function", 7525 "from static function",
7479 func_name.ToCString()); 7526 func_name.ToCString());
7480 } 7527 }
7481 selector = ParseInstanceCall(LoadReceiver(primary_pos), func_name); 7528 selector = ParseInstanceCall(LoadReceiver(primary_pos), func_name);
7482 } 7529 }
7483 } else if (primary->primary().IsString()) { 7530 } else if (primary->primary().IsString()) {
7484 // Primary is an unresolved name. 7531 // Primary is an unresolved name.
7532 if (primary->IsSuper()) {
7533 ErrorMsg(primary->token_pos(), "illegal use of super");
7534 }
7485 String& name = String::CheckedZoneHandle(primary->primary().raw()); 7535 String& name = String::CheckedZoneHandle(primary->primary().raw());
7486 if (current_function().is_static()) { 7536 if (current_function().is_static()) {
7487 selector = ThrowNoSuchMethodError(primary->token_pos(), name); 7537 selector = ThrowNoSuchMethodError(primary->token_pos(), name);
7488 } else { 7538 } else {
7489 // Treat as call to unresolved (instance) method. 7539 // Treat as call to unresolved (instance) method.
7490 AstNode* receiver = LoadReceiver(primary->token_pos()); 7540 AstNode* receiver = LoadReceiver(primary->token_pos());
7491 selector = ParseInstanceCall(receiver, name); 7541 selector = ParseInstanceCall(receiver, name);
7492 } 7542 }
7493 } else if (primary->primary().IsClass()) { 7543 } else if (primary->primary().IsClass()) {
7494 ErrorMsg(left->token_pos(), 7544 ErrorMsg(left->token_pos(),
(...skipping 14 matching lines...) Expand all
7509 if (primary->primary().IsFunction()) { 7559 if (primary->primary().IsFunction()) {
7510 // Treat as implicit closure. 7560 // Treat as implicit closure.
7511 left = LoadClosure(primary); 7561 left = LoadClosure(primary);
7512 } else if (left->AsPrimaryNode()->primary().IsClass()) { 7562 } else if (left->AsPrimaryNode()->primary().IsClass()) {
7513 Class& cls = Class::CheckedHandle( 7563 Class& cls = Class::CheckedHandle(
7514 left->AsPrimaryNode()->primary().raw()); 7564 left->AsPrimaryNode()->primary().raw());
7515 String& cls_name = String::Handle(cls.Name()); 7565 String& cls_name = String::Handle(cls.Name());
7516 ErrorMsg(left->token_pos(), 7566 ErrorMsg(left->token_pos(),
7517 "illegal use of class name '%s'", 7567 "illegal use of class name '%s'",
7518 cls_name.ToCString()); 7568 cls_name.ToCString());
7569 } else if (primary->IsSuper()) {
7570 // Return "super" to handle unary super operator calls,
7571 // or to report illegal use of "super" otherwise.
7572 left = primary;
7519 } else { 7573 } else {
7520 UNREACHABLE(); // Internal parser error. 7574 UNREACHABLE(); // Internal parser error.
7521 } 7575 }
7522 } 7576 }
7523 // Done parsing selectors. 7577 // Done parsing selectors.
7524 return left; 7578 return left;
7525 } 7579 }
7526 ASSERT(selector != NULL); 7580 ASSERT(selector != NULL);
7527 left = selector; 7581 left = selector;
7528 } 7582 }
(...skipping 1936 matching lines...) Expand 10 before | Expand all | Expand 10 after
9465 if (CurrentToken() == Token::kLPAREN) { 9519 if (CurrentToken() == Token::kLPAREN) {
9466 primary = ParseSuperCall(ident); 9520 primary = ParseSuperCall(ident);
9467 } else { 9521 } else {
9468 primary = ParseSuperFieldAccess(ident); 9522 primary = ParseSuperFieldAccess(ident);
9469 } 9523 }
9470 } else if ((CurrentToken() == Token::kLBRACK) || 9524 } else if ((CurrentToken() == Token::kLBRACK) ||
9471 Token::CanBeOverloaded(CurrentToken()) || 9525 Token::CanBeOverloaded(CurrentToken()) ||
9472 (CurrentToken() == Token::kNE)) { 9526 (CurrentToken() == Token::kNE)) {
9473 primary = ParseSuperOperator(); 9527 primary = ParseSuperOperator();
9474 } else { 9528 } else {
9475 ErrorMsg("illegal super call"); 9529 primary = new PrimaryNode(TokenPos(),
9530 String::ZoneHandle(Symbols::Super()));
9476 } 9531 }
9477 } else if (CurrentToken() == Token::kCONDITIONAL) { 9532 } else if (CurrentToken() == Token::kCONDITIONAL) {
9478 primary = ParseArgumentDefinitionTest(); 9533 primary = ParseArgumentDefinitionTest();
9479 } else { 9534 } else {
9480 UnexpectedToken(); 9535 UnexpectedToken();
9481 } 9536 }
9482 return primary; 9537 return primary;
9483 } 9538 }
9484 9539
9485 9540
(...skipping 302 matching lines...) Expand 10 before | Expand all | Expand 10 after
9788 void Parser::SkipQualIdent() { 9843 void Parser::SkipQualIdent() {
9789 ASSERT(IsIdentifier()); 9844 ASSERT(IsIdentifier());
9790 ConsumeToken(); 9845 ConsumeToken();
9791 if (CurrentToken() == Token::kPERIOD) { 9846 if (CurrentToken() == Token::kPERIOD) {
9792 ConsumeToken(); // Consume the kPERIOD token. 9847 ConsumeToken(); // Consume the kPERIOD token.
9793 ExpectIdentifier("identifier expected after '.'"); 9848 ExpectIdentifier("identifier expected after '.'");
9794 } 9849 }
9795 } 9850 }
9796 9851
9797 } // namespace dart 9852 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/parser.h ('k') | runtime/vm/symbols.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698