Index: runtime/vm/parser.cc |
=================================================================== |
--- runtime/vm/parser.cc (revision 14228) |
+++ runtime/vm/parser.cc (working copy) |
@@ -1386,6 +1386,38 @@ |
} |
+AstNode* Parser::BuildUnarySuperOperator(Token::Kind op, PrimaryNode* super) { |
+ ASSERT(super->IsSuper()); |
+ AstNode* super_op = NULL; |
+ const intptr_t super_pos = super->token_pos(); |
+ if ((op == Token::kNEGATE) || |
+ (op == Token::kBIT_NOT)) { |
+ // Resolve the operator function in the superclass. |
+ const String& operator_function_name = |
+ String::ZoneHandle(Symbols::New(Token::Str(op))); |
+ const bool kResolveGetter = false; |
+ bool is_no_such_method = false; |
+ const Function& super_operator = Function::ZoneHandle( |
+ GetSuperFunction(super_pos, |
+ operator_function_name, |
+ kResolveGetter, |
+ &is_no_such_method)); |
+ ArgumentListNode* op_arguments = new ArgumentListNode(super_pos); |
+ AstNode* receiver = LoadReceiver(super_pos); |
+ op_arguments->Add(receiver); |
+ CheckFunctionIsCallable(super_pos, super_operator); |
+ if (is_no_such_method) { |
+ op_arguments = BuildNoSuchMethodArguments(operator_function_name, |
+ *op_arguments); |
+ } |
+ super_op = new StaticCallNode(super_pos, super_operator, op_arguments); |
+ } else { |
+ ErrorMsg(super_pos, "illegal super operator call"); |
+ } |
+ return super_op; |
+} |
+ |
+ |
AstNode* Parser::ParseSuperOperator() { |
TRACE_PARSER("ParseSuperOperator"); |
AstNode* super_op = NULL; |
@@ -6657,6 +6689,10 @@ |
TRACE_PARSER("ParseBinaryExpr"); |
ASSERT(min_preced >= 4); |
AstNode* left_operand = ParseUnaryExpr(); |
+ if (left_operand->IsPrimaryNode() && |
+ (left_operand->AsPrimaryNode()->IsSuper())) { |
+ ErrorMsg(left_operand->token_pos(), "illegal use of 'super'"); |
+ } |
if (IsLiteral("as")) { // Not a reserved word. |
token_kind_ = Token::kAS; |
} |
@@ -6720,12 +6756,12 @@ |
bool Parser::IsAssignableExpr(AstNode* expr) { |
- return expr->IsPrimaryNode() |
- || (expr->IsLoadLocalNode() && !expr->AsLoadLocalNode()->HasPseudo()) |
+ return (expr->IsLoadLocalNode() && !expr->AsLoadLocalNode()->HasPseudo()) |
|| expr->IsLoadStaticFieldNode() |
|| expr->IsStaticGetterNode() |
|| expr->IsInstanceGetterNode() |
- || expr->IsLoadIndexedNode(); |
+ || expr->IsLoadIndexedNode() |
+ || (expr->IsPrimaryNode() && !expr->AsPrimaryNode()->IsSuper()); |
} |
@@ -7082,6 +7118,8 @@ |
ErrorMsg(op_pos, "unexpected operator '+'"); |
} |
// Expression is the literal itself. |
+ } else if (expr->IsPrimaryNode() && (expr->AsPrimaryNode()->IsSuper())) { |
+ expr = BuildUnarySuperOperator(unary_op, expr->AsPrimaryNode()); |
} else { |
expr = UnaryOpNode::UnaryOpOrLiteral(op_pos, unary_op, expr); |
} |
@@ -7349,6 +7387,9 @@ |
} |
PrimaryNode* primary = node->AsPrimaryNode(); |
if (primary->primary().IsString()) { |
+ if (primary->IsSuper()) { |
+ return primary; |
+ } |
// In a static method, evaluation of an unresolved identifier causes a |
// NoSuchMethodError to be thrown. |
// In an instance method, we convert this into a getter call |
@@ -7400,6 +7441,9 @@ |
if (left->AsPrimaryNode()->primary().IsFunction()) { |
left = LoadClosure(left->AsPrimaryNode()); |
} else { |
+ // Super field access handled in ParseSuperFieldAccess(), |
+ // super calls handled in ParseSuperCall(). |
+ ASSERT(!left->AsPrimaryNode()->IsSuper()); |
left = LoadFieldIfUnresolved(left); |
} |
} |
@@ -7437,6 +7481,9 @@ |
} |
} |
} else if (CurrentToken() == Token::kLBRACK) { |
+ // Super index operator handled in ParseSuperOperator(). |
+ ASSERT(!left->IsPrimaryNode() || !left->AsPrimaryNode()->IsSuper()); |
+ |
const intptr_t bracket_pos = TokenPos(); |
ConsumeToken(); |
left = LoadFieldIfUnresolved(left); |
@@ -7482,6 +7529,9 @@ |
} |
} else if (primary->primary().IsString()) { |
// Primary is an unresolved name. |
+ if (primary->IsSuper()) { |
+ ErrorMsg(primary->token_pos(), "illegal use of super"); |
+ } |
String& name = String::CheckedZoneHandle(primary->primary().raw()); |
if (current_function().is_static()) { |
selector = ThrowNoSuchMethodError(primary->token_pos(), name); |
@@ -7516,6 +7566,10 @@ |
ErrorMsg(left->token_pos(), |
"illegal use of class name '%s'", |
cls_name.ToCString()); |
+ } else if (primary->IsSuper()) { |
+ // Return "super" to handle unary super operator calls, |
+ // or to report illegal use of "super" otherwise. |
+ left = primary; |
} else { |
UNREACHABLE(); // Internal parser error. |
} |
@@ -9472,7 +9526,8 @@ |
(CurrentToken() == Token::kNE)) { |
primary = ParseSuperOperator(); |
} else { |
- ErrorMsg("illegal super call"); |
+ primary = new PrimaryNode(TokenPos(), |
+ String::ZoneHandle(Symbols::Super())); |
} |
} else if (CurrentToken() == Token::kCONDITIONAL) { |
primary = ParseArgumentDefinitionTest(); |