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

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

Issue 34413007: Implement type checks for switch expression (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 1 month 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 | « runtime/vm/parser.h ('k') | tests/co19/co19-co19.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 6006 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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
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
OLDNEW
« no previous file with comments | « runtime/vm/parser.h ('k') | tests/co19/co19-co19.status » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698