Chromium Code Reviews| Index: runtime/vm/parser.cc |
| =================================================================== |
| --- runtime/vm/parser.cc (revision 335) |
| +++ runtime/vm/parser.cc (working copy) |
| @@ -1002,56 +1002,110 @@ |
| } |
| +RawFunction* Parser::GetSuperFunction(intptr_t token_pos, |
| + const String& name) { |
|
regis
2011/10/11 23:43:10
indentation
hausner
2011/10/11 23:50:24
Done.
|
| + const Class& super_class = Class::Handle(current_class().SuperClass()); |
| + if (super_class.IsNull()) { |
| + ErrorMsg(token_pos, "class '%s' does not have a superclass", |
| + String::Handle(current_class().Name()).ToCString()); |
| + } |
| + |
| + const Function& super_func = |
| + Function::Handle(ResolveDynamicFunction(super_class, name)); |
| + if (super_func.IsNull()) { |
| + ErrorMsg(token_pos, "function '%s' not found in super class", |
| + name.ToCString()); |
| + } |
| + CheckFunctionIsCallable(token_pos, super_func); |
| + return super_func.raw(); |
| +} |
| + |
| + |
| AstNode* Parser::ParseSuperCall(const String& function_name) { |
| TRACE_PARSER("ParseSuperCall"); |
| ASSERT(CurrentToken() == Token::kLPAREN); |
| const intptr_t supercall_pos = token_index_; |
| - const Class& super_class = Class::Handle(current_class().SuperClass()); |
| - if (super_class.IsNull()) { |
| - ErrorMsg("class '%s' does not have a superclass", |
| - String::Handle(current_class().Name()).ToCString()); |
| - } |
| + |
| + const Function& super_function = Function::ZoneHandle( |
| + GetSuperFunction(supercall_pos, function_name)); |
| + |
| // 'this' parameter is the first argument to super call. |
| - AstNode* implicit_argument = LoadReceiver(supercall_pos); |
| + AstNode* receiver = LoadReceiver(supercall_pos); |
| ArgumentListNode* arguments = |
| - ParseActualParameters(implicit_argument, kAllowConst); |
| - // Resolve the function. |
| - const Function& super_function = Function::ZoneHandle( |
| - ResolveDynamicFunction(super_class, function_name)); |
| - if (super_function.IsNull()) { |
| - ErrorMsg(supercall_pos, |
| - "function '%s' not found in super class", |
| - function_name.ToCString()); |
| - } |
| - CheckFunctionIsCallable(supercall_pos, super_function); |
| + ParseActualParameters(receiver, kAllowConst); |
| return new StaticCallNode(supercall_pos, super_function, arguments); |
| } |
| AstNode* Parser::ParseSuperOperator() { |
| + TRACE_PARSER("ParseSuperOperator"); |
| AstNode* super_op = NULL; |
| const intptr_t operator_pos = token_index_; |
| - const Class& super_class = Class::Handle(current_class().SuperClass()); |
| - if (super_class.IsNull()) { |
| - ErrorMsg(operator_pos, "class '%s' does not have a superclass", |
| - String::Handle(current_class().Name()).ToCString()); |
| - } |
| if (CurrentToken() == Token::kLBRACK) { |
| - Unimplemented("Not yet implemented: super[expr]"); |
| + ConsumeToken(); |
| + AstNode* index_expr = ParseExpr(kAllowConst); |
| + ExpectToken(Token::kRBRACK); |
| + |
| + if (Token::IsAssignmentOperator(CurrentToken()) && |
| + (CurrentToken() != Token::kASSIGN)) { |
| + // Compound assignment. Ensure side effects in index expression |
| + // only execute once. If the index is not a local variable or an |
| + // literal, evaluate and save in a temporary local. |
| + if (!index_expr->IsLoadLocalNode() && !index_expr->IsLiteralNode()) { |
| + LocalVariable* temp = |
| + CreateTempConstVariable(operator_pos, index_expr->id(), "lix"); |
| + AstNode* save = |
| + new StoreLocalNode(operator_pos, *temp, index_expr); |
| + current_block_->statements->Add(save); |
| + index_expr = new LoadLocalNode(operator_pos, *temp); |
| + } |
| + } |
| + |
| + // Resolve the [] operator function in the superclass. |
| + const String& index_operator_name = |
| + String::ZoneHandle(String::NewSymbol(Token::Str(Token::kINDEX))); |
| + const Function& index_operator = Function::ZoneHandle( |
| + GetSuperFunction(operator_pos, index_operator_name)); |
| + |
| + ArgumentListNode* index_op_arguments = new ArgumentListNode(operator_pos); |
| + AstNode* receiver = LoadReceiver(operator_pos); |
| + index_op_arguments->Add(receiver); |
| + index_op_arguments->Add(index_expr); |
| + |
| + super_op = new StaticCallNode( |
| + operator_pos, index_operator, index_op_arguments); |
| + |
| + if (Token::IsAssignmentOperator(CurrentToken())) { |
| + Token::Kind assignment_op = CurrentToken(); |
| + ConsumeToken(); |
| + AstNode* value = ParseExpr(kAllowConst); |
| + |
| + value = ExpandAssignableOp(operator_pos, assignment_op, super_op, value); |
| + |
| + // Resolve the []= operator function in the superclass. |
| + const String& assign_index_operator_name = String::ZoneHandle( |
| + String::NewSymbol(Token::Str(Token::kASSIGN_INDEX))); |
| + const Function& assign_index_operator = Function::ZoneHandle( |
| + GetSuperFunction(operator_pos, assign_index_operator_name)); |
| + |
| + ArgumentListNode* operator_args = new ArgumentListNode(operator_pos); |
| + operator_args->Add(LoadReceiver(operator_pos)); |
| + operator_args->Add(index_expr); |
| + operator_args->Add(value); |
| + |
| + super_op = new StaticCallNode( |
| + operator_pos, assign_index_operator, operator_args); |
| + } |
| } else if (Token::CanBeOverloaded(CurrentToken())) { |
| Token::Kind op = CurrentToken(); |
| ConsumeToken(); |
| // Resolve the operator function in the superclass. |
| const String& operator_function_name = |
| - String::ZoneHandle(String::NewSymbol(Token::Str(op))); |
| + String::Handle(String::NewSymbol(Token::Str(op))); |
| const Function& super_operator = Function::ZoneHandle( |
| - ResolveDynamicFunction(super_class, operator_function_name)); |
| - if (super_operator.IsNull()) { |
| - ErrorMsg(operator_pos, "operator '%s' not found in super class", |
| - Token::Str(op)); |
| - } |
| + GetSuperFunction(operator_pos, operator_function_name)); |
| ASSERT(Token::Precedence(op) >= Token::Precedence(Token::kBIT_OR)); |
| AstNode* other_operand = ParseBinaryExpr(Token::Precedence(op) + 1); |
| @@ -6665,7 +6719,8 @@ |
| } else { |
| primary = ParseSuperFieldAccess(ident); |
| } |
| - } else if (Token::CanBeOverloaded(CurrentToken())) { |
| + } else if ((CurrentToken() == Token::kLBRACK) || |
| + Token::CanBeOverloaded(CurrentToken())) { |
| primary = ParseSuperOperator(); |
| } else { |
| ErrorMsg("Illegal super call"); |