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

Unified Diff: runtime/vm/parser.cc

Issue 8234022: Implement index operator super call (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: '' Created 9 years, 2 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « runtime/vm/parser.h ('k') | tests/language/src/SuperOperatorTest.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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");
« no previous file with comments | « runtime/vm/parser.h ('k') | tests/language/src/SuperOperatorTest.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698