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 6003 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6014 ASSERT(!equal_op.IsNull()); | 6014 ASSERT(!equal_op.IsNull()); |
6015 cls = equal_op.Owner(); | 6015 cls = equal_op.Owner(); |
6016 return !cls.IsObjectClass(); | 6016 return !cls.IsObjectClass(); |
6017 } | 6017 } |
6018 | 6018 |
6019 | 6019 |
6020 // Check that all case expressions are of the same type, either int, String, | 6020 // Check that all case expressions are of the same type, either int, String, |
6021 // or any other class that does not override the == operator. | 6021 // or any other class that does not override the == operator. |
6022 // The expressions are compile-time constants and are thus in the form | 6022 // The expressions are compile-time constants and are thus in the form |
6023 // of a LiteralNode. | 6023 // of a LiteralNode. |
6024 void Parser::CheckCaseExpressions(const GrowableArray<LiteralNode*>& values) { | 6024 RawType* Parser::CheckCaseExpressions( |
| 6025 const GrowableArray<LiteralNode*>& values) { |
6025 const intptr_t num_expressions = values.length(); | 6026 const intptr_t num_expressions = values.length(); |
6026 if (num_expressions == 0) { | 6027 if (num_expressions == 0) { |
6027 return; | 6028 return Type::DynamicType(); |
6028 } | 6029 } |
6029 const Instance& first_value = values[0]->literal(); | 6030 const Instance& first_value = values[0]->literal(); |
6030 for (intptr_t i = 0; i < num_expressions; i++) { | 6031 for (intptr_t i = 0; i < num_expressions; i++) { |
6031 const Instance& val = values[i]->literal(); | 6032 const Instance& val = values[i]->literal(); |
6032 const intptr_t val_pos = values[i]->token_pos(); | 6033 const intptr_t val_pos = values[i]->token_pos(); |
6033 if (first_value.IsInteger()) { | 6034 if (first_value.IsInteger()) { |
6034 if (!val.IsInteger()) { | 6035 if (!val.IsInteger()) { |
6035 ErrorMsg(val_pos, "expected case expression of type int"); | 6036 ErrorMsg(val_pos, "expected case expression of type int"); |
6036 } | 6037 } |
6037 continue; | 6038 continue; |
(...skipping 14 matching lines...) Expand all Loading... |
6052 // The value is of some type other than int, String or double. | 6053 // The value is of some type other than int, String or double. |
6053 // Check that the type class does not override the == operator. | 6054 // Check that the type class does not override the == operator. |
6054 // Check this only in the first loop iteration since all values | 6055 // Check this only in the first loop iteration since all values |
6055 // are of the same type, which we check above. | 6056 // are of the same type, which we check above. |
6056 if (ImplementsEqualOperator(val)) { | 6057 if (ImplementsEqualOperator(val)) { |
6057 ErrorMsg(val_pos, | 6058 ErrorMsg(val_pos, |
6058 "type class of case expression must not implement operator =="); | 6059 "type class of case expression must not implement operator =="); |
6059 } | 6060 } |
6060 } | 6061 } |
6061 } | 6062 } |
| 6063 if (first_value.IsInteger()) { |
| 6064 return Type::IntType(); |
| 6065 } else if (first_value.IsString()) { |
| 6066 return Type::StringType(); |
| 6067 } |
| 6068 return Type::NewNonParameterizedType(Class::Handle(first_value.clazz())); |
6062 } | 6069 } |
6063 | 6070 |
6064 | 6071 |
6065 CaseNode* Parser::ParseCaseClause(LocalVariable* switch_expr_value, | 6072 CaseNode* Parser::ParseCaseClause(LocalVariable* switch_expr_value, |
6066 GrowableArray<LiteralNode*>* case_expr_values, | 6073 GrowableArray<LiteralNode*>* case_expr_values, |
6067 SourceLabel* case_label) { | 6074 SourceLabel* case_label) { |
6068 TRACE_PARSER("ParseCaseClause"); | 6075 TRACE_PARSER("ParseCaseClause"); |
6069 bool default_seen = false; | 6076 bool default_seen = false; |
6070 const intptr_t case_pos = TokenPos(); | 6077 const intptr_t case_pos = TokenPos(); |
6071 // The case expressions node sequence does not own the enclosing scope. | 6078 // The case expressions node sequence does not own the enclosing scope. |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6151 ConsumeToken(); | 6158 ConsumeToken(); |
6152 ExpectToken(Token::kLPAREN); | 6159 ExpectToken(Token::kLPAREN); |
6153 const intptr_t expr_pos = TokenPos(); | 6160 const intptr_t expr_pos = TokenPos(); |
6154 AstNode* switch_expr = ParseExpr(kAllowConst, kConsumeCascades); | 6161 AstNode* switch_expr = ParseExpr(kAllowConst, kConsumeCascades); |
6155 ExpectToken(Token::kRPAREN); | 6162 ExpectToken(Token::kRPAREN); |
6156 ExpectToken(Token::kLBRACE); | 6163 ExpectToken(Token::kLBRACE); |
6157 OpenBlock(); | 6164 OpenBlock(); |
6158 current_block_->scope->AddLabel(label); | 6165 current_block_->scope->AddLabel(label); |
6159 | 6166 |
6160 // Store switch expression in temporary local variable. | 6167 // Store switch expression in temporary local variable. |
| 6168 Type& temp_var_type = Type::ZoneHandle(Type::DynamicType()); |
6161 LocalVariable* temp_variable = | 6169 LocalVariable* temp_variable = |
6162 new LocalVariable(expr_pos, | 6170 new LocalVariable(expr_pos, Symbols::SwitchExpr(), temp_var_type); |
6163 Symbols::SwitchExpr(), | |
6164 Type::ZoneHandle(Type::DynamicType())); | |
6165 current_block_->scope->AddVariable(temp_variable); | 6171 current_block_->scope->AddVariable(temp_variable); |
6166 AstNode* save_switch_expr = | 6172 AstNode* save_switch_expr = |
6167 new StoreLocalNode(expr_pos, temp_variable, switch_expr); | 6173 new StoreLocalNode(expr_pos, temp_variable, switch_expr); |
6168 current_block_->statements->Add(save_switch_expr); | 6174 current_block_->statements->Add(save_switch_expr); |
6169 | 6175 |
6170 // Parse case clauses | 6176 // Parse case clauses |
6171 bool default_seen = false; | 6177 bool default_seen = false; |
6172 GrowableArray<LiteralNode*> case_expr_values; | 6178 GrowableArray<LiteralNode*> case_expr_values; |
6173 while (true) { | 6179 while (true) { |
6174 // Check for statement label | 6180 // Check for statement label |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6207 } else if (CurrentToken() != Token::kRBRACE) { | 6213 } else if (CurrentToken() != Token::kRBRACE) { |
6208 ErrorMsg("'case' or '}' expected"); | 6214 ErrorMsg("'case' or '}' expected"); |
6209 } else if (case_label != NULL) { | 6215 } else if (case_label != NULL) { |
6210 ErrorMsg("expecting at least one case clause after label"); | 6216 ErrorMsg("expecting at least one case clause after label"); |
6211 } else { | 6217 } else { |
6212 break; | 6218 break; |
6213 } | 6219 } |
6214 } | 6220 } |
6215 | 6221 |
6216 // Check that all expressions in case clauses are of the same class, | 6222 // Check that all expressions in case clauses are of the same class, |
6217 // or implement int, double or String. | 6223 // or implement int, double or String. Patch the type of the temporary |
6218 CheckCaseExpressions(case_expr_values); | 6224 // variable holding the switch expression to match the type of the |
| 6225 // case clause constants. |
| 6226 temp_var_type = CheckCaseExpressions(case_expr_values); |
| 6227 temp_variable->set_type(temp_var_type); |
6219 | 6228 |
6220 // Check for unresolved label references. | 6229 // Check for unresolved label references. |
6221 SourceLabel* unresolved_label = | 6230 SourceLabel* unresolved_label = |
6222 current_block_->scope->CheckUnresolvedLabels(); | 6231 current_block_->scope->CheckUnresolvedLabels(); |
6223 if (unresolved_label != NULL) { | 6232 if (unresolved_label != NULL) { |
6224 ErrorMsg("unresolved reference to label '%s'", | 6233 ErrorMsg("unresolved reference to label '%s'", |
6225 unresolved_label->name().ToCString()); | 6234 unresolved_label->name().ToCString()); |
6226 } | 6235 } |
6227 | 6236 |
6228 SequenceNode* switch_body = CloseBlock(); | 6237 SequenceNode* switch_body = CloseBlock(); |
(...skipping 4339 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10568 void Parser::SkipQualIdent() { | 10577 void Parser::SkipQualIdent() { |
10569 ASSERT(IsIdentifier()); | 10578 ASSERT(IsIdentifier()); |
10570 ConsumeToken(); | 10579 ConsumeToken(); |
10571 if (CurrentToken() == Token::kPERIOD) { | 10580 if (CurrentToken() == Token::kPERIOD) { |
10572 ConsumeToken(); // Consume the kPERIOD token. | 10581 ConsumeToken(); // Consume the kPERIOD token. |
10573 ExpectIdentifier("identifier expected after '.'"); | 10582 ExpectIdentifier("identifier expected after '.'"); |
10574 } | 10583 } |
10575 } | 10584 } |
10576 | 10585 |
10577 } // namespace dart | 10586 } // namespace dart |
OLD | NEW |