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 6006 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6017 ASSERT(!equal_op.IsNull()); | 6017 ASSERT(!equal_op.IsNull()); |
6018 cls = equal_op.Owner(); | 6018 cls = equal_op.Owner(); |
6019 return !cls.IsObjectClass(); | 6019 return !cls.IsObjectClass(); |
6020 } | 6020 } |
6021 | 6021 |
6022 | 6022 |
6023 // Check that all case expressions are of the same type, either int, String, | 6023 // Check that all case expressions are of the same type, either int, String, |
6024 // or any other class that does not override the == operator. | 6024 // or any other class that does not override the == operator. |
6025 // The expressions are compile-time constants and are thus in the form | 6025 // The expressions are compile-time constants and are thus in the form |
6026 // of a LiteralNode. | 6026 // of a LiteralNode. |
6027 void Parser::CheckCaseExpressions(const GrowableArray<LiteralNode*>& values) { | 6027 RawClass* Parser::CheckCaseExpressions( |
| 6028 const GrowableArray<LiteralNode*>& values) { |
6028 const intptr_t num_expressions = values.length(); | 6029 const intptr_t num_expressions = values.length(); |
6029 if (num_expressions == 0) { | 6030 if (num_expressions == 0) { |
6030 return; | 6031 return Object::dynamic_class(); |
6031 } | 6032 } |
6032 const Instance& first_value = values[0]->literal(); | 6033 const Instance& first_value = values[0]->literal(); |
6033 for (intptr_t i = 0; i < num_expressions; i++) { | 6034 for (intptr_t i = 0; i < num_expressions; i++) { |
6034 const Instance& val = values[i]->literal(); | 6035 const Instance& val = values[i]->literal(); |
6035 const intptr_t val_pos = values[i]->token_pos(); | 6036 const intptr_t val_pos = values[i]->token_pos(); |
6036 if (first_value.IsInteger()) { | 6037 if (first_value.IsInteger()) { |
6037 if (!val.IsInteger()) { | 6038 if (!val.IsInteger()) { |
6038 ErrorMsg(val_pos, "expected case expression of type int"); | 6039 ErrorMsg(val_pos, "expected case expression of type int"); |
6039 } | 6040 } |
6040 continue; | 6041 continue; |
(...skipping 14 matching lines...) Expand all Loading... |
6055 // The value is of some type other than int, String or double. | 6056 // The value is of some type other than int, String or double. |
6056 // Check that the type class does not override the == operator. | 6057 // Check that the type class does not override the == operator. |
6057 // Check this only in the first loop iteration since all values | 6058 // Check this only in the first loop iteration since all values |
6058 // are of the same type, which we check above. | 6059 // are of the same type, which we check above. |
6059 if (ImplementsEqualOperator(val)) { | 6060 if (ImplementsEqualOperator(val)) { |
6060 ErrorMsg(val_pos, | 6061 ErrorMsg(val_pos, |
6061 "type class of case expression must not implement operator =="); | 6062 "type class of case expression must not implement operator =="); |
6062 } | 6063 } |
6063 } | 6064 } |
6064 } | 6065 } |
| 6066 if (first_value.IsInteger()) { |
| 6067 return Type::Handle(Type::IntType()).type_class(); |
| 6068 } else if (first_value.IsString()) { |
| 6069 return Type::Handle(Type::StringType()).type_class(); |
| 6070 } |
| 6071 return first_value.clazz(); |
6065 } | 6072 } |
6066 | 6073 |
6067 | 6074 |
6068 CaseNode* Parser::ParseCaseClause(LocalVariable* switch_expr_value, | 6075 CaseNode* Parser::ParseCaseClause(LocalVariable* switch_expr_value, |
6069 GrowableArray<LiteralNode*>* case_expr_values, | 6076 GrowableArray<LiteralNode*>* case_expr_values, |
6070 SourceLabel* case_label) { | 6077 SourceLabel* case_label) { |
6071 TRACE_PARSER("ParseCaseClause"); | 6078 TRACE_PARSER("ParseCaseClause"); |
6072 bool default_seen = false; | 6079 bool default_seen = false; |
6073 const intptr_t case_pos = TokenPos(); | 6080 const intptr_t case_pos = TokenPos(); |
6074 // The case expressions node sequence does not own the enclosing scope. | 6081 // The case expressions node sequence does not own the enclosing scope. |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6153 SourceLabel::New(switch_pos, label_name, SourceLabel::kSwitch); | 6160 SourceLabel::New(switch_pos, label_name, SourceLabel::kSwitch); |
6154 ConsumeToken(); | 6161 ConsumeToken(); |
6155 ExpectToken(Token::kLPAREN); | 6162 ExpectToken(Token::kLPAREN); |
6156 const intptr_t expr_pos = TokenPos(); | 6163 const intptr_t expr_pos = TokenPos(); |
6157 AstNode* switch_expr = ParseExpr(kAllowConst, kConsumeCascades); | 6164 AstNode* switch_expr = ParseExpr(kAllowConst, kConsumeCascades); |
6158 ExpectToken(Token::kRPAREN); | 6165 ExpectToken(Token::kRPAREN); |
6159 ExpectToken(Token::kLBRACE); | 6166 ExpectToken(Token::kLBRACE); |
6160 OpenBlock(); | 6167 OpenBlock(); |
6161 current_block_->scope->AddLabel(label); | 6168 current_block_->scope->AddLabel(label); |
6162 | 6169 |
6163 // Store switch expression in temporary local variable. | 6170 // Store switch expression in temporary local variable. The type of the |
| 6171 // variable is set to dynamic. It will later be patched to match the |
| 6172 // type of the case clause expressions. Therefore, we have to allocate |
| 6173 // a new type representing dynamic and can't reuse the canonical |
| 6174 // type object for dynamic. |
| 6175 const Type& temp_var_type = |
| 6176 Type::ZoneHandle(Type::New(Class::Handle(Object::dynamic_class()), |
| 6177 TypeArguments::Handle(), |
| 6178 expr_pos)); |
| 6179 temp_var_type.SetIsFinalized(); |
6164 LocalVariable* temp_variable = | 6180 LocalVariable* temp_variable = |
6165 new LocalVariable(expr_pos, | 6181 new LocalVariable(expr_pos, Symbols::SwitchExpr(), temp_var_type); |
6166 Symbols::SwitchExpr(), | |
6167 Type::ZoneHandle(Type::DynamicType())); | |
6168 current_block_->scope->AddVariable(temp_variable); | 6182 current_block_->scope->AddVariable(temp_variable); |
6169 AstNode* save_switch_expr = | 6183 AstNode* save_switch_expr = |
6170 new StoreLocalNode(expr_pos, temp_variable, switch_expr); | 6184 new StoreLocalNode(expr_pos, temp_variable, switch_expr); |
6171 current_block_->statements->Add(save_switch_expr); | 6185 current_block_->statements->Add(save_switch_expr); |
6172 | 6186 |
6173 // Parse case clauses | 6187 // Parse case clauses |
6174 bool default_seen = false; | 6188 bool default_seen = false; |
6175 GrowableArray<LiteralNode*> case_expr_values; | 6189 GrowableArray<LiteralNode*> case_expr_values; |
6176 while (true) { | 6190 while (true) { |
6177 // Check for statement label | 6191 // Check for statement label |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6210 } else if (CurrentToken() != Token::kRBRACE) { | 6224 } else if (CurrentToken() != Token::kRBRACE) { |
6211 ErrorMsg("'case' or '}' expected"); | 6225 ErrorMsg("'case' or '}' expected"); |
6212 } else if (case_label != NULL) { | 6226 } else if (case_label != NULL) { |
6213 ErrorMsg("expecting at least one case clause after label"); | 6227 ErrorMsg("expecting at least one case clause after label"); |
6214 } else { | 6228 } else { |
6215 break; | 6229 break; |
6216 } | 6230 } |
6217 } | 6231 } |
6218 | 6232 |
6219 // Check that all expressions in case clauses are of the same class, | 6233 // Check that all expressions in case clauses are of the same class, |
6220 // or implement int, double or String. | 6234 // or implement int, double or String. Patch the type of the temporary |
6221 CheckCaseExpressions(case_expr_values); | 6235 // variable holding the switch expression to match the type of the |
| 6236 // case clause constants. |
| 6237 temp_var_type.set_type_class( |
| 6238 Class::Handle(CheckCaseExpressions(case_expr_values))); |
6222 | 6239 |
6223 // Check for unresolved label references. | 6240 // Check for unresolved label references. |
6224 SourceLabel* unresolved_label = | 6241 SourceLabel* unresolved_label = |
6225 current_block_->scope->CheckUnresolvedLabels(); | 6242 current_block_->scope->CheckUnresolvedLabels(); |
6226 if (unresolved_label != NULL) { | 6243 if (unresolved_label != NULL) { |
6227 ErrorMsg("unresolved reference to label '%s'", | 6244 ErrorMsg("unresolved reference to label '%s'", |
6228 unresolved_label->name().ToCString()); | 6245 unresolved_label->name().ToCString()); |
6229 } | 6246 } |
6230 | 6247 |
6231 SequenceNode* switch_body = CloseBlock(); | 6248 SequenceNode* switch_body = CloseBlock(); |
(...skipping 4341 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10573 void Parser::SkipQualIdent() { | 10590 void Parser::SkipQualIdent() { |
10574 ASSERT(IsIdentifier()); | 10591 ASSERT(IsIdentifier()); |
10575 ConsumeToken(); | 10592 ConsumeToken(); |
10576 if (CurrentToken() == Token::kPERIOD) { | 10593 if (CurrentToken() == Token::kPERIOD) { |
10577 ConsumeToken(); // Consume the kPERIOD token. | 10594 ConsumeToken(); // Consume the kPERIOD token. |
10578 ExpectIdentifier("identifier expected after '.'"); | 10595 ExpectIdentifier("identifier expected after '.'"); |
10579 } | 10596 } |
10580 } | 10597 } |
10581 | 10598 |
10582 } // namespace dart | 10599 } // namespace dart |
OLD | NEW |