Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 6026 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 6037 if (label != NULL) { | 6037 if (label != NULL) { |
| 6038 current_block_->statements->Add(if_node); | 6038 current_block_->statements->Add(if_node); |
| 6039 SequenceNode* sequence = CloseBlock(); | 6039 SequenceNode* sequence = CloseBlock(); |
| 6040 sequence->set_label(label); | 6040 sequence->set_label(label); |
| 6041 if_node = sequence; | 6041 if_node = sequence; |
| 6042 } | 6042 } |
| 6043 return if_node; | 6043 return if_node; |
| 6044 } | 6044 } |
| 6045 | 6045 |
| 6046 | 6046 |
| 6047 void Parser::CheckCaseExpressions(const GrowableArray<LiteralNode*>& values) { | |
|
srdjan
2013/09/26 18:35:43
Add brief comment what checks are done.
hausner
2013/09/26 18:54:59
Done.
| |
| 6048 const intptr_t num_expressions = values.length(); | |
| 6049 if (num_expressions == 0) { | |
| 6050 return; | |
| 6051 } | |
| 6052 const Instance& first_value = values[0]->literal(); | |
| 6053 for (intptr_t i = 0; i < num_expressions; i++) { | |
| 6054 const Instance& val = values[i]->literal(); | |
| 6055 const intptr_t val_pos = values[i]->token_pos(); | |
| 6056 if (first_value.IsInteger()) { | |
| 6057 if (!val.IsInteger()) { | |
| 6058 ErrorMsg(val_pos, "expected case expression of type int"); | |
| 6059 } | |
| 6060 continue; | |
| 6061 } | |
| 6062 if (first_value.IsString()) { | |
| 6063 if (!val.IsString()) { | |
| 6064 ErrorMsg(val_pos, "expected case expression of type String"); | |
| 6065 } | |
| 6066 continue; | |
| 6067 } | |
| 6068 if (first_value.IsDouble()) { | |
| 6069 if (!val.IsDouble()) { | |
| 6070 ErrorMsg(val_pos, "expected case expression of type double"); | |
| 6071 } | |
| 6072 continue; | |
| 6073 } | |
| 6074 if (val.clazz() != first_value.clazz()) { | |
| 6075 ErrorMsg(val_pos, "all case expressions must be of same type"); | |
| 6076 } | |
| 6077 Class& cls = Class::Handle(val.clazz()); | |
| 6078 const Function& equal_op = Function::Handle( | |
| 6079 Resolver::ResolveDynamicAnyArgs(cls, Symbols::EqualOperator())); | |
| 6080 ASSERT(!equal_op.IsNull()); | |
| 6081 cls = equal_op.Owner(); | |
| 6082 if (!cls.IsObjectClass()) { | |
| 6083 ErrorMsg(val_pos, | |
| 6084 "type class of case expression must not implement operator =="); | |
| 6085 } | |
| 6086 } | |
| 6087 } | |
| 6088 | |
| 6089 | |
| 6047 CaseNode* Parser::ParseCaseClause(LocalVariable* switch_expr_value, | 6090 CaseNode* Parser::ParseCaseClause(LocalVariable* switch_expr_value, |
| 6091 GrowableArray<LiteralNode*>* case_expr_values, | |
| 6048 SourceLabel* case_label) { | 6092 SourceLabel* case_label) { |
| 6049 TRACE_PARSER("ParseCaseClause"); | 6093 TRACE_PARSER("ParseCaseClause"); |
| 6050 bool default_seen = false; | 6094 bool default_seen = false; |
| 6051 const intptr_t case_pos = TokenPos(); | 6095 const intptr_t case_pos = TokenPos(); |
| 6052 // The case expressions node sequence does not own the enclosing scope. | 6096 // The case expressions node sequence does not own the enclosing scope. |
| 6053 SequenceNode* case_expressions = new SequenceNode(case_pos, NULL); | 6097 SequenceNode* case_expressions = new SequenceNode(case_pos, NULL); |
| 6054 while (CurrentToken() == Token::kCASE || CurrentToken() == Token::kDEFAULT) { | 6098 while (CurrentToken() == Token::kCASE || CurrentToken() == Token::kDEFAULT) { |
| 6055 if (CurrentToken() == Token::kCASE) { | 6099 if (CurrentToken() == Token::kCASE) { |
| 6056 if (default_seen) { | 6100 if (default_seen) { |
| 6057 ErrorMsg("default clause must be last case"); | 6101 ErrorMsg("default clause must be last case"); |
| 6058 } | 6102 } |
| 6059 ConsumeToken(); // Keyword case. | 6103 ConsumeToken(); // Keyword case. |
| 6060 const intptr_t expr_pos = TokenPos(); | 6104 const intptr_t expr_pos = TokenPos(); |
| 6061 AstNode* expr = ParseExpr(kRequireConst, kConsumeCascades); | 6105 AstNode* expr = ParseExpr(kRequireConst, kConsumeCascades); |
| 6106 ASSERT(expr->IsLiteralNode()); | |
| 6107 case_expr_values->Add(expr->AsLiteralNode()); | |
| 6108 | |
| 6062 AstNode* switch_expr_load = new LoadLocalNode(case_pos, | 6109 AstNode* switch_expr_load = new LoadLocalNode(case_pos, |
| 6063 switch_expr_value); | 6110 switch_expr_value); |
| 6064 AstNode* case_comparison = new ComparisonNode(expr_pos, | 6111 AstNode* case_comparison = new ComparisonNode(expr_pos, |
| 6065 Token::kEQ, | 6112 Token::kEQ, |
| 6066 expr, | 6113 expr, |
| 6067 switch_expr_load); | 6114 switch_expr_load); |
| 6068 case_expressions->Add(case_comparison); | 6115 case_expressions->Add(case_comparison); |
| 6069 } else { | 6116 } else { |
| 6070 if (default_seen) { | 6117 if (default_seen) { |
| 6071 ErrorMsg("only one default clause is allowed"); | 6118 ErrorMsg("only one default clause is allowed"); |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 6140 new LocalVariable(expr_pos, | 6187 new LocalVariable(expr_pos, |
| 6141 Symbols::SwitchExpr(), | 6188 Symbols::SwitchExpr(), |
| 6142 Type::ZoneHandle(Type::DynamicType())); | 6189 Type::ZoneHandle(Type::DynamicType())); |
| 6143 current_block_->scope->AddVariable(temp_variable); | 6190 current_block_->scope->AddVariable(temp_variable); |
| 6144 AstNode* save_switch_expr = | 6191 AstNode* save_switch_expr = |
| 6145 new StoreLocalNode(expr_pos, temp_variable, switch_expr); | 6192 new StoreLocalNode(expr_pos, temp_variable, switch_expr); |
| 6146 current_block_->statements->Add(save_switch_expr); | 6193 current_block_->statements->Add(save_switch_expr); |
| 6147 | 6194 |
| 6148 // Parse case clauses | 6195 // Parse case clauses |
| 6149 bool default_seen = false; | 6196 bool default_seen = false; |
| 6197 GrowableArray<LiteralNode*> case_expr_values; | |
| 6150 while (true) { | 6198 while (true) { |
| 6151 // Check for statement label | 6199 // Check for statement label |
| 6152 SourceLabel* case_label = NULL; | 6200 SourceLabel* case_label = NULL; |
| 6153 if (IsIdentifier() && LookaheadToken(1) == Token::kCOLON) { | 6201 if (IsIdentifier() && LookaheadToken(1) == Token::kCOLON) { |
| 6154 // Case statements start with a label. | 6202 // Case statements start with a label. |
| 6155 String* label_name = CurrentLiteral(); | 6203 String* label_name = CurrentLiteral(); |
| 6156 const intptr_t label_pos = TokenPos(); | 6204 const intptr_t label_pos = TokenPos(); |
| 6157 ConsumeToken(); // Consume label identifier. | 6205 ConsumeToken(); // Consume label identifier. |
| 6158 ConsumeToken(); // Consume colon. | 6206 ConsumeToken(); // Consume colon. |
| 6159 case_label = current_block_->scope->LocalLookupLabel(*label_name); | 6207 case_label = current_block_->scope->LocalLookupLabel(*label_name); |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 6170 ErrorMsg(label_pos, "label '%s' already exists in scope", | 6218 ErrorMsg(label_pos, "label '%s' already exists in scope", |
| 6171 label_name->ToCString()); | 6219 label_name->ToCString()); |
| 6172 } | 6220 } |
| 6173 ASSERT(case_label->kind() == SourceLabel::kCase); | 6221 ASSERT(case_label->kind() == SourceLabel::kCase); |
| 6174 } | 6222 } |
| 6175 if (CurrentToken() == Token::kCASE || | 6223 if (CurrentToken() == Token::kCASE || |
| 6176 CurrentToken() == Token::kDEFAULT) { | 6224 CurrentToken() == Token::kDEFAULT) { |
| 6177 if (default_seen) { | 6225 if (default_seen) { |
| 6178 ErrorMsg("no case clauses allowed after default clause"); | 6226 ErrorMsg("no case clauses allowed after default clause"); |
| 6179 } | 6227 } |
| 6180 CaseNode* case_clause = ParseCaseClause(temp_variable, case_label); | 6228 CaseNode* case_clause = |
| 6229 ParseCaseClause(temp_variable, &case_expr_values, case_label); | |
| 6181 default_seen = case_clause->contains_default(); | 6230 default_seen = case_clause->contains_default(); |
| 6182 current_block_->statements->Add(case_clause); | 6231 current_block_->statements->Add(case_clause); |
| 6183 } else if (CurrentToken() != Token::kRBRACE) { | 6232 } else if (CurrentToken() != Token::kRBRACE) { |
| 6184 ErrorMsg("'case' or '}' expected"); | 6233 ErrorMsg("'case' or '}' expected"); |
| 6185 } else if (case_label != NULL) { | 6234 } else if (case_label != NULL) { |
| 6186 ErrorMsg("expecting at least one case clause after label"); | 6235 ErrorMsg("expecting at least one case clause after label"); |
| 6187 } else { | 6236 } else { |
| 6188 break; | 6237 break; |
| 6189 } | 6238 } |
| 6190 } | 6239 } |
| 6191 | 6240 |
| 6192 // TODO(hausner): Check that all expressions in case clauses are | 6241 // Check that all expressions in case clauses are of the same class, |
| 6193 // of the same class, or implement int or String (issue 7307). | 6242 // or implement int, double or String. |
| 6243 CheckCaseExpressions(case_expr_values); | |
| 6194 | 6244 |
| 6195 // Check for unresolved label references. | 6245 // Check for unresolved label references. |
| 6196 SourceLabel* unresolved_label = | 6246 SourceLabel* unresolved_label = |
| 6197 current_block_->scope->CheckUnresolvedLabels(); | 6247 current_block_->scope->CheckUnresolvedLabels(); |
| 6198 if (unresolved_label != NULL) { | 6248 if (unresolved_label != NULL) { |
| 6199 ErrorMsg("unresolved reference to label '%s'", | 6249 ErrorMsg("unresolved reference to label '%s'", |
| 6200 unresolved_label->name().ToCString()); | 6250 unresolved_label->name().ToCString()); |
| 6201 } | 6251 } |
| 6202 | 6252 |
| 6203 SequenceNode* switch_body = CloseBlock(); | 6253 SequenceNode* switch_body = CloseBlock(); |
| (...skipping 4342 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 10546 void Parser::SkipQualIdent() { | 10596 void Parser::SkipQualIdent() { |
| 10547 ASSERT(IsIdentifier()); | 10597 ASSERT(IsIdentifier()); |
| 10548 ConsumeToken(); | 10598 ConsumeToken(); |
| 10549 if (CurrentToken() == Token::kPERIOD) { | 10599 if (CurrentToken() == Token::kPERIOD) { |
| 10550 ConsumeToken(); // Consume the kPERIOD token. | 10600 ConsumeToken(); // Consume the kPERIOD token. |
| 10551 ExpectIdentifier("identifier expected after '.'"); | 10601 ExpectIdentifier("identifier expected after '.'"); |
| 10552 } | 10602 } |
| 10553 } | 10603 } |
| 10554 | 10604 |
| 10555 } // namespace dart | 10605 } // namespace dart |
| OLD | NEW |