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

Unified Diff: runtime/vm/parser.cc

Issue 10796109: Implement cascade operator in VM (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 5 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') | runtime/vm/scanner.cc » ('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 9834)
+++ runtime/vm/parser.cc (working copy)
@@ -775,7 +775,7 @@
// the static const field initializer is a constant expression and
// leave the evaluation to the getter function.
const intptr_t expr_pos = TokenPos();
- AstNode* expr = ParseExpr(kAllowConst);
+ AstNode* expr = ParseExpr(kAllowConst, kConsumeCascades);
if (field.is_const()) {
// This getter will only be called once at compile time.
if (expr->EvalConstExpr() == NULL) {
@@ -1336,7 +1336,7 @@
if (CurrentToken() == Token::kLBRACK) {
ConsumeToken();
- AstNode* index_expr = ParseExpr(kAllowConst);
+ AstNode* index_expr = ParseExpr(kAllowConst, kConsumeCascades);
ExpectToken(Token::kRBRACK);
if (Token::IsAssignmentOperator(CurrentToken()) &&
@@ -1378,7 +1378,7 @@
if (Token::IsAssignmentOperator(CurrentToken())) {
Token::Kind assignment_op = CurrentToken();
ConsumeToken();
- AstNode* value = ParseExpr(kAllowConst);
+ AstNode* value = ParseExpr(kAllowConst, kConsumeCascades);
value = ExpandAssignableOp(operator_pos, assignment_op, super_op, value);
@@ -1506,7 +1506,7 @@
Token::Kind assignment_op = CurrentToken();
ConsumeToken();
- AstNode* value = ParseExpr(kAllowConst);
+ AstNode* value = ParseExpr(kAllowConst, kConsumeCascades);
value = ExpandAssignableOp(field_pos, assignment_op, super_field, value);
ArgumentListNode* setter_arguments = new ArgumentListNode(field_pos);
@@ -2178,7 +2178,7 @@
} else if (CurrentToken() == Token::kARROW) {
ConsumeToken();
const intptr_t expr_pos = TokenPos();
- AstNode* expr = ParseExpr(kAllowConst);
+ AstNode* expr = ParseExpr(kAllowConst, kConsumeCascades);
ASSERT(expr != NULL);
current_block_->statements->Add(new ReturnNode(expr_pos, expr));
} else if (IsLiteral("native")) {
@@ -4098,7 +4098,7 @@
// Variable initialization.
const intptr_t assign_pos = TokenPos();
ConsumeToken();
- AstNode* expr = ParseExpr(kAllowConst);
+ AstNode* expr = ParseExpr(kAllowConst, kConsumeCascades);
initialization = new StoreLocalNode(assign_pos, *variable, expr);
} else if (is_final) {
ErrorMsg(ident_pos, "missing initialization of 'final' variable");
@@ -4672,7 +4672,7 @@
}
ConsumeToken();
ExpectToken(Token::kLPAREN);
- AstNode* cond_expr = ParseExpr(kAllowConst);
+ AstNode* cond_expr = ParseExpr(kAllowConst, kConsumeCascades);
ExpectToken(Token::kRPAREN);
const bool parsing_loop_body = false;
SequenceNode* true_branch = ParseNestedStatement(parsing_loop_body, NULL);
@@ -4706,7 +4706,7 @@
}
ConsumeToken(); // Keyword case.
const intptr_t expr_pos = TokenPos();
- AstNode* expr = ParseExpr(kAllowConst);
+ AstNode* expr = ParseExpr(kAllowConst, kConsumeCascades);
AstNode* switch_expr_load = new LoadLocalNode(case_pos,
*switch_expr_value);
AstNode* case_comparison = new ComparisonNode(expr_pos,
@@ -4782,7 +4782,7 @@
ErrorMsg("'(' expected");
}
const intptr_t expr_pos = TokenPos();
- AstNode* switch_expr = ParseExpr(kAllowConst);
+ AstNode* switch_expr = ParseExpr(kAllowConst, kConsumeCascades);
if (paren_found) {
ExpectToken(Token::kRPAREN);
}
@@ -4865,7 +4865,7 @@
SourceLabel::New(while_pos, label_name, SourceLabel::kWhile);
ConsumeToken();
ExpectToken(Token::kLPAREN);
- AstNode* cond_expr = ParseExpr(kAllowConst);
+ AstNode* cond_expr = ParseExpr(kAllowConst, kConsumeCascades);
ExpectToken(Token::kRPAREN);
const bool parsing_loop_body = true;
SequenceNode* while_body = ParseNestedStatement(parsing_loop_body, label);
@@ -4883,7 +4883,7 @@
SequenceNode* dowhile_body = ParseNestedStatement(parsing_loop_body, label);
ExpectToken(Token::kWHILE);
ExpectToken(Token::kLPAREN);
- AstNode* cond_expr = ParseExpr(kAllowConst);
+ AstNode* cond_expr = ParseExpr(kAllowConst, kConsumeCascades);
ExpectToken(Token::kRPAREN);
ExpectSemicolon();
return new DoWhileNode(do_pos, label, cond_expr, dowhile_body);
@@ -4914,7 +4914,7 @@
}
ExpectToken(Token::kIN);
const intptr_t collection_pos = TokenPos();
- AstNode* collection_expr = ParseExpr(kAllowConst);
+ AstNode* collection_expr = ParseExpr(kAllowConst, kConsumeCascades);
ExpectToken(Token::kRPAREN);
OpenBlock(); // Implicit block around while loop.
@@ -5024,13 +5024,13 @@
if (IsVariableDeclaration()) {
initializer = ParseVariableDeclarationList();
} else {
- initializer = ParseExpr(kAllowConst);
+ initializer = ParseExpr(kAllowConst, kConsumeCascades);
}
}
ExpectSemicolon();
AstNode* condition = NULL;
if (CurrentToken() != Token::kSEMICOLON) {
- condition = ParseExpr(kAllowConst);
+ condition = ParseExpr(kAllowConst, kConsumeCascades);
}
ExpectSemicolon();
AstNode* increment = NULL;
@@ -5128,7 +5128,7 @@
ExpectToken(Token::kRPAREN);
return NULL;
}
- AstNode* condition = ParseExpr(kAllowConst);
+ AstNode* condition = ParseExpr(kAllowConst, kConsumeCascades);
const intptr_t condition_end = TokenPos();
ExpectToken(Token::kRPAREN);
condition = InsertClosureCallNodes(condition);
@@ -5602,7 +5602,7 @@
(current_block_->scope->function_level() == 0)) {
ErrorMsg(return_pos, "return of a value not allowed in constructors");
}
- AstNode* expr = ParseExpr(kAllowConst);
+ AstNode* expr = ParseExpr(kAllowConst, kConsumeCascades);
statement = new ReturnNode(statement_pos, expr);
} else {
statement = new ReturnNode(statement_pos);
@@ -5649,7 +5649,7 @@
ConsumeToken();
AstNode* expr = NULL;
if (CurrentToken() != Token::kSEMICOLON) {
- expr = ParseExpr(kAllowConst);
+ expr = ParseExpr(kAllowConst, kConsumeCascades);
ExpectSemicolon();
statement = new ThrowNode(statement_pos, expr, NULL);
} else { // No exception object seen so must be a rethrow.
@@ -5673,7 +5673,7 @@
new LoadLocalNode(statement_pos, *trace_var));
}
} else {
- statement = ParseExpr(kAllowConst);
+ statement = ParseExpr(kAllowConst, kConsumeCascades);
ExpectSemicolon();
}
return statement;
@@ -6044,14 +6044,14 @@
AstNode* Parser::ParseExprList() {
TRACE_PARSER("ParseExprList");
- AstNode* expressions = ParseExpr(kAllowConst);
+ AstNode* expressions = ParseExpr(kAllowConst, kConsumeCascades);
if (CurrentToken() == Token::kCOMMA) {
// Collect comma-separated expressions in a non scope owning sequence node.
SequenceNode* list = new SequenceNode(TokenPos(), NULL);
list->Add(expressions);
while (CurrentToken() == Token::kCOMMA) {
ConsumeToken();
- AstNode* expr = ParseExpr(kAllowConst);
+ AstNode* expr = ParseExpr(kAllowConst, kConsumeCascades);
list->Add(expr);
}
expressions = list;
@@ -6244,11 +6244,42 @@
}
-AstNode* Parser::ParseExpr(bool require_compiletime_const) {
+AstNode* Parser::ParseCascades(AstNode* expr) {
+ intptr_t cascade_pos = TokenPos();
+ LocalVariable* cascade_receiver_var =
+ CreateTempConstVariable(cascade_pos, expr->id(), "casc");
+ StoreLocalNode* save_cascade =
+ new StoreLocalNode(cascade_pos, *cascade_receiver_var, expr);
+ current_block_->statements->Add(save_cascade);
+ while (CurrentToken() == Token::kCASCADE) {
+ cascade_pos = TokenPos();
+ LoadLocalNode* load_cascade_receiver =
+ new LoadLocalNode(cascade_pos, *cascade_receiver_var);
+ if (Token::IsIdentifier(LookaheadToken(1))) {
+ // Replace .. with . for ParseSelectors().
+ token_kind_ = Token::kPERIOD;
+ } else if (LookaheadToken(1) == Token::kLBRACK) {
+ ConsumeToken();
+ } else {
+ ErrorMsg("identifier or [ expected after ..");
+ }
+ expr = ParseSelectors(load_cascade_receiver, true);
+ current_block_->statements->Add(expr);
+ }
+ // Result of the cascade is the receiver.
+ return new LoadLocalNode(cascade_pos, *cascade_receiver_var);
+}
+
+
+AstNode* Parser::ParseExpr(bool require_compiletime_const,
+ bool consume_cascades) {
TRACE_PARSER("ParseExpr");
const intptr_t expr_pos = TokenPos();
AstNode* expr = ParseConditionalExpr();
if (!Token::IsAssignmentOperator(CurrentToken())) {
+ if ((CurrentToken() == Token::kCASCADE) && consume_cascades) {
+ return ParseCascades(expr);
+ }
if (require_compiletime_const) {
expr = FoldConstExpr(expr_pos, expr);
}
@@ -6262,7 +6293,7 @@
if (require_compiletime_const && (assignment_op != Token::kASSIGN)) {
ErrorMsg(right_expr_pos, "expression must be a compile time constant");
}
- AstNode* right_expr = ParseExpr(require_compiletime_const);
+ AstNode* right_expr = ParseExpr(require_compiletime_const, kConsumeCascades);
AstNode* left_expr = expr;
if (assignment_op != Token::kASSIGN) {
// Compound assignment: store inputs with side effects into temp. locals.
@@ -6282,7 +6313,7 @@
LiteralNode* Parser::ParseConstExpr() {
TRACE_PARSER("ParseConstExpr");
- AstNode* expr = ParseExpr(kRequireConst);
+ AstNode* expr = ParseExpr(kRequireConst, kNoCascades);
ASSERT(expr->IsLiteralNode());
return expr->AsLiteralNode();
}
@@ -6295,9 +6326,9 @@
if (CurrentToken() == Token::kCONDITIONAL) {
EnsureExpressionTemp();
ConsumeToken();
- AstNode* expr1 = ParseExpr(kAllowConst);
+ AstNode* expr1 = ParseExpr(kAllowConst, kNoCascades);
ExpectToken(Token::kCOLON);
- AstNode* expr2 = ParseExpr(kAllowConst);
+ AstNode* expr2 = ParseExpr(kAllowConst, kNoCascades);
expr = new ConditionalExprNode(expr_pos, expr, expr1, expr2);
}
return expr;
@@ -6385,7 +6416,7 @@
} else if (named_argument_seen) {
ErrorMsg("named argument expected");
}
- arguments->Add(ParseExpr(require_const));
+ arguments->Add(ParseExpr(require_const, kConsumeCascades));
} while (CurrentToken() == Token::kCOMMA);
} else {
ConsumeToken();
@@ -6487,14 +6518,15 @@
AstNode* Parser::ParseInstanceFieldAccess(AstNode* receiver,
- const String& field_name) {
+ const String& field_name,
+ bool consume_cascades) {
TRACE_PARSER("ParseInstanceFieldAccess");
AstNode* access = NULL;
const intptr_t call_pos = TokenPos();
if (Token::IsAssignmentOperator(CurrentToken())) {
Token::Kind assignment_op = CurrentToken();
ConsumeToken();
- AstNode* value = ParseExpr(kAllowConst);
+ AstNode* value = ParseExpr(kAllowConst, consume_cascades);
AstNode* load_access =
new InstanceGetterNode(call_pos, receiver, field_name);
AstNode* left_load_access = load_access;
@@ -6534,7 +6566,8 @@
AstNode* Parser::ParseStaticFieldAccess(const Class& cls,
const String& field_name,
- intptr_t ident_pos) {
+ intptr_t ident_pos,
+ bool consume_cascades) {
TRACE_PARSER("ParseStaticFieldAccess");
AstNode* access = NULL;
const intptr_t call_pos = TokenPos();
@@ -6561,7 +6594,7 @@
}
}
ConsumeToken();
- AstNode* value = ParseExpr(kAllowConst);
+ AstNode* value = ParseExpr(kAllowConst, consume_cascades);
AstNode* load_access = NULL;
if (field.IsNull()) {
// No field found, we must have at least a setter function defined.
@@ -6674,13 +6707,10 @@
}
-AstNode* Parser::ParsePostfixExpr() {
- TRACE_PARSER("ParsePostfixExpr");
- const intptr_t postfix_expr_pos = TokenPos();
- AstNode* postfix_expr = ParsePrimary();
+AstNode* Parser::ParseSelectors(AstNode* primary, bool is_cascade) {
+ AstNode* left = primary;
while (true) {
AstNode* selector = NULL;
- AstNode* left = postfix_expr;
if (CurrentToken() == Token::kPERIOD) {
ConsumeToken();
if (left->IsPrimaryNode()) {
@@ -6716,10 +6746,11 @@
}
if (cls.IsNull()) {
// Instance field access.
- selector = ParseInstanceFieldAccess(left, *ident);
+ selector = ParseInstanceFieldAccess(left, *ident, !is_cascade);
} else {
// Static field access.
- selector = ParseStaticFieldAccess(cls, *ident, ident_pos);
+ selector =
+ ParseStaticFieldAccess(cls, *ident, ident_pos, !is_cascade);
}
}
} else if (CurrentToken() == Token::kLBRACK) {
@@ -6727,7 +6758,7 @@
ConsumeToken();
left = LoadFieldIfUnresolved(left);
const bool saved_mode = SetAllowFunctionLiterals(true);
- AstNode* index = ParseExpr(kAllowConst);
+ AstNode* index = ParseExpr(kAllowConst, kConsumeCascades);
SetAllowFunctionLiterals(saved_mode);
ExpectToken(Token::kRBRACK);
AstNode* array = left;
@@ -6787,7 +6818,7 @@
selector = ParseClosureCall(closure);
}
} else {
- // No (more) selector to parse.
+ // No (more) selectors to parse.
left = LoadFieldIfUnresolved(left);
if (left->IsPrimaryNode()) {
PrimaryNode* primary = left->AsPrimaryNode();
@@ -6805,13 +6836,20 @@
UNREACHABLE(); // Internal parser error.
}
}
- postfix_expr = left;
// Done parsing selectors.
- break;
+ return left;
}
ASSERT(selector != NULL);
- postfix_expr = selector;
+ left = selector;
}
+}
+
+
+AstNode* Parser::ParsePostfixExpr() {
+ TRACE_PARSER("ParsePostfixExpr");
+ const intptr_t postfix_expr_pos = TokenPos();
+ AstNode* postfix_expr = ParsePrimary();
+ postfix_expr = ParseSelectors(postfix_expr, false);
if (IsIncrementOperator(CurrentToken())) {
TRACE_PARSER("IncrementOperator");
Token::Kind incr_op = CurrentToken();
@@ -7524,7 +7562,7 @@
Symbols::New("list literal element"));
while (CurrentToken() != Token::kRBRACK) {
const intptr_t element_pos = TokenPos();
- AstNode* element = ParseExpr(is_const);
+ AstNode* element = ParseExpr(is_const, kConsumeCascades);
if (FLAG_enable_type_checks &&
!is_const &&
!element_type.IsDynamicType()) {
@@ -7719,7 +7757,7 @@
ExpectToken(Token::kCOLON);
const bool saved_mode = SetAllowFunctionLiterals(true);
const intptr_t value_pos = TokenPos();
- AstNode* value = ParseExpr(is_const);
+ AstNode* value = ParseExpr(is_const, kConsumeCascades);
SetAllowFunctionLiterals(saved_mode);
if (FLAG_enable_type_checks &&
!is_const &&
@@ -8178,7 +8216,7 @@
} else {
ASSERT(CurrentToken() == Token::kINTERPOL_START);
ConsumeToken();
- expr = ParseExpr(kAllowConst);
+ expr = ParseExpr(kAllowConst, kConsumeCascades);
ExpectToken(Token::kINTERPOL_END);
}
// Check if this interpolated string is still considered a compile time
@@ -8336,7 +8374,7 @@
} else if (CurrentToken() == Token::kLPAREN) {
ConsumeToken();
const bool saved_mode = SetAllowFunctionLiterals(true);
- primary = ParseExpr(kAllowConst);
+ primary = ParseExpr(kAllowConst, kConsumeCascades);
SetAllowFunctionLiterals(saved_mode);
ExpectToken(Token::kRPAREN);
} else if (CurrentToken() == Token::kDOUBLE) {
« no previous file with comments | « runtime/vm/parser.h ('k') | runtime/vm/scanner.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698