| Index: runtime/vm/parser.cc
|
| ===================================================================
|
| --- runtime/vm/parser.cc (revision 358)
|
| +++ runtime/vm/parser.cc (working copy)
|
| @@ -1002,56 +1002,110 @@
|
| }
|
|
|
|
|
| +RawFunction* Parser::GetSuperFunction(intptr_t token_pos,
|
| + const String& name) {
|
| + 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);
|
| @@ -6663,7 +6717,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");
|
|
|