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

Side by Side Diff: runtime/vm/parser.cc

Issue 23640004: Require case expressions to be compile-time constants (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 3 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | tests/co19/co19-runtime.status » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/parser.h" 5 #include "vm/parser.h"
6 6
7 #include "lib/invocation_mirror.h" 7 #include "lib/invocation_mirror.h"
8 #include "vm/bigint_operations.h" 8 #include "vm/bigint_operations.h"
9 #include "vm/bootstrap.h" 9 #include "vm/bootstrap.h"
10 #include "vm/class_finalizer.h" 10 #include "vm/class_finalizer.h"
(...skipping 5885 matching lines...) Expand 10 before | Expand all | Expand 10 after
5896 SequenceNode* sequence = CloseBlock(); 5896 SequenceNode* sequence = CloseBlock();
5897 sequence->set_label(label); 5897 sequence->set_label(label);
5898 if_node = sequence; 5898 if_node = sequence;
5899 } 5899 }
5900 return if_node; 5900 return if_node;
5901 } 5901 }
5902 5902
5903 5903
5904 CaseNode* Parser::ParseCaseClause(LocalVariable* switch_expr_value, 5904 CaseNode* Parser::ParseCaseClause(LocalVariable* switch_expr_value,
5905 SourceLabel* case_label) { 5905 SourceLabel* case_label) {
5906 TRACE_PARSER("ParseCaseStatement"); 5906 TRACE_PARSER("ParseCaseClause");
5907 bool default_seen = false; 5907 bool default_seen = false;
5908 const intptr_t case_pos = TokenPos(); 5908 const intptr_t case_pos = TokenPos();
5909 // The case expressions node sequence does not own the enclosing scope. 5909 // The case expressions node sequence does not own the enclosing scope.
5910 SequenceNode* case_expressions = new SequenceNode(case_pos, NULL); 5910 SequenceNode* case_expressions = new SequenceNode(case_pos, NULL);
5911 while (CurrentToken() == Token::kCASE || CurrentToken() == Token::kDEFAULT) { 5911 while (CurrentToken() == Token::kCASE || CurrentToken() == Token::kDEFAULT) {
5912 if (CurrentToken() == Token::kCASE) { 5912 if (CurrentToken() == Token::kCASE) {
5913 if (default_seen) { 5913 if (default_seen) {
5914 ErrorMsg("default clause must be last case"); 5914 ErrorMsg("default clause must be last case");
5915 } 5915 }
5916 ConsumeToken(); // Keyword case. 5916 ConsumeToken(); // Keyword case.
5917 const intptr_t expr_pos = TokenPos(); 5917 const intptr_t expr_pos = TokenPos();
5918 AstNode* expr = ParseExpr(kAllowConst, kConsumeCascades); 5918 AstNode* expr = ParseExpr(kRequireConst, kConsumeCascades);
5919 AstNode* switch_expr_load = new LoadLocalNode(case_pos, 5919 AstNode* switch_expr_load = new LoadLocalNode(case_pos,
5920 switch_expr_value); 5920 switch_expr_value);
5921 AstNode* case_comparison = new ComparisonNode(expr_pos, 5921 AstNode* case_comparison = new ComparisonNode(expr_pos,
5922 Token::kEQ, 5922 Token::kEQ,
5923 expr, 5923 expr,
5924 switch_expr_load); 5924 switch_expr_load);
5925 case_expressions->Add(case_comparison); 5925 case_expressions->Add(case_comparison);
5926 } else { 5926 } else {
5927 if (default_seen) { 5927 if (default_seen) {
5928 ErrorMsg("only one default clause is allowed"); 5928 ErrorMsg("only one default clause is allowed");
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
5977 } 5977 }
5978 5978
5979 5979
5980 AstNode* Parser::ParseSwitchStatement(String* label_name) { 5980 AstNode* Parser::ParseSwitchStatement(String* label_name) {
5981 TRACE_PARSER("ParseSwitchStatement"); 5981 TRACE_PARSER("ParseSwitchStatement");
5982 ASSERT(CurrentToken() == Token::kSWITCH); 5982 ASSERT(CurrentToken() == Token::kSWITCH);
5983 const intptr_t switch_pos = TokenPos(); 5983 const intptr_t switch_pos = TokenPos();
5984 SourceLabel* label = 5984 SourceLabel* label =
5985 SourceLabel::New(switch_pos, label_name, SourceLabel::kSwitch); 5985 SourceLabel::New(switch_pos, label_name, SourceLabel::kSwitch);
5986 ConsumeToken(); 5986 ConsumeToken();
5987 const bool parens_are_mandatory = false; 5987 ExpectToken(Token::kLPAREN);
5988 bool paren_found = false;
5989 if (CurrentToken() == Token::kLPAREN) {
5990 paren_found = true;
5991 ConsumeToken();
5992 } else if (parens_are_mandatory) {
5993 ErrorMsg("'(' expected");
5994 }
5995 const intptr_t expr_pos = TokenPos(); 5988 const intptr_t expr_pos = TokenPos();
5996 AstNode* switch_expr = ParseExpr(kAllowConst, kConsumeCascades); 5989 AstNode* switch_expr = ParseExpr(kAllowConst, kConsumeCascades);
5997 if (paren_found) { 5990 ExpectToken(Token::kRPAREN);
5998 ExpectToken(Token::kRPAREN);
5999 }
6000 ExpectToken(Token::kLBRACE); 5991 ExpectToken(Token::kLBRACE);
6001 OpenBlock(); 5992 OpenBlock();
6002 current_block_->scope->AddLabel(label); 5993 current_block_->scope->AddLabel(label);
6003 5994
6004 // Store switch expression in temporary local variable. 5995 // Store switch expression in temporary local variable.
6005 LocalVariable* temp_variable = 5996 LocalVariable* temp_variable =
6006 new LocalVariable(expr_pos, 5997 new LocalVariable(expr_pos,
6007 Symbols::SwitchExpr(), 5998 Symbols::SwitchExpr(),
6008 Type::ZoneHandle(Type::DynamicType())); 5999 Type::ZoneHandle(Type::DynamicType()));
6009 current_block_->scope->AddVariable(temp_variable); 6000 current_block_->scope->AddVariable(temp_variable);
(...skipping 16 matching lines...) Expand all
6026 if (case_label == NULL) { 6017 if (case_label == NULL) {
6027 // Label does not exist yet. Add it to scope of switch statement. 6018 // Label does not exist yet. Add it to scope of switch statement.
6028 case_label = 6019 case_label =
6029 new SourceLabel(label_pos, *label_name, SourceLabel::kCase); 6020 new SourceLabel(label_pos, *label_name, SourceLabel::kCase);
6030 current_block_->scope->AddLabel(case_label); 6021 current_block_->scope->AddLabel(case_label);
6031 } else if (case_label->kind() == SourceLabel::kForward) { 6022 } else if (case_label->kind() == SourceLabel::kForward) {
6032 // We have seen a 'continue' with this label name. Resolve 6023 // We have seen a 'continue' with this label name. Resolve
6033 // the forward reference. 6024 // the forward reference.
6034 case_label->ResolveForwardReference(); 6025 case_label->ResolveForwardReference();
6035 } else { 6026 } else {
6036 ErrorMsg(label_pos, "name '%s' already exists in scope", 6027 ErrorMsg(label_pos, "label '%s' already exists in scope",
6037 label_name->ToCString()); 6028 label_name->ToCString());
6038 } 6029 }
6039 ASSERT(case_label->kind() == SourceLabel::kCase); 6030 ASSERT(case_label->kind() == SourceLabel::kCase);
6040 } 6031 }
6041 if (CurrentToken() == Token::kCASE || 6032 if (CurrentToken() == Token::kCASE ||
6042 CurrentToken() == Token::kDEFAULT) { 6033 CurrentToken() == Token::kDEFAULT) {
6043 if (default_seen) { 6034 if (default_seen) {
6044 ErrorMsg("no case clauses allowed after default clause"); 6035 ErrorMsg("no case clauses allowed after default clause");
6045 } 6036 }
6046 CaseNode* case_clause = ParseCaseClause(temp_variable, case_label); 6037 CaseNode* case_clause = ParseCaseClause(temp_variable, case_label);
6047 default_seen = case_clause->contains_default(); 6038 default_seen = case_clause->contains_default();
6048 current_block_->statements->Add(case_clause); 6039 current_block_->statements->Add(case_clause);
6049 } else if (CurrentToken() != Token::kRBRACE) { 6040 } else if (CurrentToken() != Token::kRBRACE) {
6050 ErrorMsg("'case' or '}' expected"); 6041 ErrorMsg("'case' or '}' expected");
6051 } else if (case_label != NULL) { 6042 } else if (case_label != NULL) {
6052 ErrorMsg("expecting at least one case clause after label"); 6043 ErrorMsg("expecting at least one case clause after label");
6053 } else { 6044 } else {
6054 break; 6045 break;
6055 } 6046 }
6056 } 6047 }
6057 6048
6049 // TODO(hausner): Check that all expressions in case clauses are
6050 // of the same class, or implement int or String (issue 7307).
6051
6058 // Check for unresolved label references. 6052 // Check for unresolved label references.
6059 SourceLabel* unresolved_label = 6053 SourceLabel* unresolved_label =
6060 current_block_->scope->CheckUnresolvedLabels(); 6054 current_block_->scope->CheckUnresolvedLabels();
6061 if (unresolved_label != NULL) { 6055 if (unresolved_label != NULL) {
6062 ErrorMsg("unresolved reference to label '%s'", 6056 ErrorMsg("unresolved reference to label '%s'",
6063 unresolved_label->name().ToCString()); 6057 unresolved_label->name().ToCString());
6064 } 6058 }
6065 6059
6066 SequenceNode* switch_body = CloseBlock(); 6060 SequenceNode* switch_body = CloseBlock();
6067 ExpectToken(Token::kRBRACE); 6061 ExpectToken(Token::kRBRACE);
(...skipping 4365 matching lines...) Expand 10 before | Expand all | Expand 10 after
10433 void Parser::SkipQualIdent() { 10427 void Parser::SkipQualIdent() {
10434 ASSERT(IsIdentifier()); 10428 ASSERT(IsIdentifier());
10435 ConsumeToken(); 10429 ConsumeToken();
10436 if (CurrentToken() == Token::kPERIOD) { 10430 if (CurrentToken() == Token::kPERIOD) {
10437 ConsumeToken(); // Consume the kPERIOD token. 10431 ConsumeToken(); // Consume the kPERIOD token.
10438 ExpectIdentifier("identifier expected after '.'"); 10432 ExpectIdentifier("identifier expected after '.'");
10439 } 10433 }
10440 } 10434 }
10441 10435
10442 } // namespace dart 10436 } // namespace dart
OLDNEW
« no previous file with comments | « no previous file | tests/co19/co19-runtime.status » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698