| 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 |