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

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, 2 months 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
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 6003 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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
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
OLDNEW
« no previous file with comments | « runtime/vm/parser.h ('k') | runtime/vm/scopes.h » ('j') | runtime/vm/scopes.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698