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

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

Issue 9453020: Fix handling of unresolved names (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 10 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
« no previous file with comments | « runtime/vm/parser.h ('k') | tests/language/language.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 "vm/bigint_operations.h" 7 #include "vm/bigint_operations.h"
8 #include "vm/class_finalizer.h" 8 #include "vm/class_finalizer.h"
9 #include "vm/compiler.h" 9 #include "vm/compiler.h"
10 #include "vm/compiler_stats.h" 10 #include "vm/compiler_stats.h"
(...skipping 6025 matching lines...) Expand 10 before | Expand all | Expand 10 after
6036 field_name); 6036 field_name);
6037 } 6037 }
6038 } else { 6038 } else {
6039 return GenerateStaticFieldLookup(field, token_index_); 6039 return GenerateStaticFieldLookup(field, token_index_);
6040 } 6040 }
6041 } 6041 }
6042 return access; 6042 return access;
6043 } 6043 }
6044 6044
6045 6045
6046 AstNode* Parser::LoadFieldIfUnresolved(AstNode* node) {
6047 if (!node->IsPrimaryNode()) {
6048 return node;
6049 }
6050 PrimaryNode* primary = node->AsPrimaryNode();
6051 if (primary->primary().IsString()) {
6052 // In a static method, an unresolved identifier is an error.
6053 // In an instance method, we convert this into a getter call
6054 // for a field (which may be defined in a subclass.)
6055 String& name = String::CheckedZoneHandle(primary->primary().raw());
6056 if (current_function().is_static() ||
6057 current_function().IsInFactoryScope()) {
6058 ErrorMsg(primary->token_index(),
6059 "identifier '%s' is not declared in this scope",
6060 name.ToCString());
6061 } else {
6062 AstNode* receiver = LoadReceiver(primary->token_index());
6063 return CallGetter(node->token_index(), receiver, name);
6064 }
6065 }
6066 return primary;
6067 }
6068
6069
6070 AstNode* Parser::LoadClosure(PrimaryNode* primary) {
6071 ASSERT(primary->primary().IsFunction());
6072 AstNode* closure = NULL;
6073 const Function& func =
6074 Function::CheckedZoneHandle(primary->primary().raw());
6075 const String& funcname = String::ZoneHandle(func.name());
6076 if (func.is_static()) {
6077 // Static function access.
6078 closure = CreateImplicitClosureNode(func, primary->token_index(), NULL);
6079 } else {
6080 // Instance function access.
6081 if (current_function().is_static() ||
6082 current_function().IsInFactoryScope()) {
6083 ErrorMsg(primary->token_index(),
6084 "cannot access instance method '%s' from static method",
6085 funcname.ToCString());
6086 }
6087 AstNode* receiver = LoadReceiver(primary->token_index());
6088 closure = CallGetter(primary->token_index(), receiver, funcname);
6089 }
6090 return closure;
6091 }
6092
6093
6046 AstNode* Parser::ParsePostfixExpr() { 6094 AstNode* Parser::ParsePostfixExpr() {
6047 TRACE_PARSER("ParsePostfixExpr"); 6095 TRACE_PARSER("ParsePostfixExpr");
6048 const intptr_t postfix_expr_pos = token_index_; 6096 const intptr_t postfix_expr_pos = token_index_;
6049 AstNode* postfix_expr = ParsePrimary(); 6097 AstNode* postfix_expr = ParsePrimary();
6050 while (true) { 6098 while (true) {
6051 AstNode* selector = NULL; 6099 AstNode* selector = NULL;
6052 AstNode* left = postfix_expr; 6100 AstNode* left = postfix_expr;
6101 if (left->IsPrimaryNode() &&
6102 left->AsPrimaryNode()->primary().IsTypeParameter()) {
6103 TypeParameter& type_param =
6104 TypeParameter::CheckedHandle(left->AsPrimaryNode()->primary().raw());
6105 ASSERT(!type_param.IsNull());
6106 String& type_param_name = String::Handle(type_param.Name());
6107 ErrorMsg(left->token_index(),
6108 "illegal use of type parameter %s",
6109 type_param_name.ToCString());
6110 }
6053 if (CurrentToken() == Token::kPERIOD) { 6111 if (CurrentToken() == Token::kPERIOD) {
6054 ConsumeToken(); 6112 ConsumeToken();
6113 if (left->IsPrimaryNode()) {
6114 if (left->AsPrimaryNode()->primary().IsFunction()) {
6115 left = LoadClosure(left->AsPrimaryNode());
6116 } else {
6117 left = LoadFieldIfUnresolved(left);
6118 }
6119 }
6055 const intptr_t ident_pos = token_index_; 6120 const intptr_t ident_pos = token_index_;
6056 String* ident = ExpectIdentifier("identifier expected"); 6121 String* ident = ExpectIdentifier("identifier expected");
6057 if (CurrentToken() == Token::kLPAREN) { 6122 if (CurrentToken() == Token::kLPAREN) {
6058 // Identifier followed by a opening paren: method call. 6123 // Identifier followed by a opening paren: method call.
6059 if (left->IsPrimaryNode() 6124 if (left->IsPrimaryNode()
6060 && left->AsPrimaryNode()->primary().IsClass()) { 6125 && left->AsPrimaryNode()->primary().IsClass()) {
6061 // Static method call prefixed with class name. 6126 // Static method call prefixed with class name.
6062 Class& cls = Class::CheckedHandle( 6127 Class& cls = Class::CheckedHandle(
6063 left->AsPrimaryNode()->primary().raw()); 6128 left->AsPrimaryNode()->primary().raw());
6064 selector = ParseStaticCall(cls, *ident, ident_pos); 6129 selector = ParseStaticCall(cls, *ident, ident_pos);
(...skipping 15 matching lines...) Expand all
6080 // Instance field access. 6145 // Instance field access.
6081 selector = ParseInstanceFieldAccess(left, *ident); 6146 selector = ParseInstanceFieldAccess(left, *ident);
6082 } else { 6147 } else {
6083 // Static field access. 6148 // Static field access.
6084 selector = ParseStaticFieldAccess(cls, *ident, ident_pos); 6149 selector = ParseStaticFieldAccess(cls, *ident, ident_pos);
6085 } 6150 }
6086 } 6151 }
6087 } else if (CurrentToken() == Token::kLBRACK) { 6152 } else if (CurrentToken() == Token::kLBRACK) {
6088 const intptr_t bracket_pos = token_index_; 6153 const intptr_t bracket_pos = token_index_;
6089 ConsumeToken(); 6154 ConsumeToken();
6155 left = LoadFieldIfUnresolved(left);
6090 const bool saved_mode = SetAllowFunctionLiterals(true); 6156 const bool saved_mode = SetAllowFunctionLiterals(true);
6091 AstNode* index = ParseExpr(kAllowConst); 6157 AstNode* index = ParseExpr(kAllowConst);
6092 SetAllowFunctionLiterals(saved_mode); 6158 SetAllowFunctionLiterals(saved_mode);
6093 ExpectToken(Token::kRBRACK); 6159 ExpectToken(Token::kRBRACK);
6094 AstNode* array = left; 6160 AstNode* array = left;
6095 if (left->IsPrimaryNode()) { 6161 if (left->IsPrimaryNode()) {
6096 PrimaryNode* primary = left->AsPrimaryNode(); 6162 PrimaryNode* primary = left->AsPrimaryNode();
6097 if (primary->primary().IsFunction()) { 6163 if (primary->primary().IsFunction()) {
6098 ErrorMsg(bracket_pos, "cannot apply index operator to function"); 6164 array = LoadClosure(primary);
6099 } else if (primary->primary().IsClass()) { 6165 } else if (primary->primary().IsClass()) {
6100 ErrorMsg(bracket_pos, "cannot apply index operator to class"); 6166 ErrorMsg(bracket_pos, "cannot apply index operator to class");
6101 } else if (primary->primary().IsString()) {
6102 // Primary is an unresolved name.
6103 String& name = String::CheckedZoneHandle(primary->primary().raw());
6104 if (current_function().is_static()) {
6105 ErrorMsg(primary->token_index(),
6106 "identifier '%s' is not declared in this scope",
6107 name.ToCString());
6108 } else {
6109 // Treat as call to unresolved (instance) method.
6110 AstNode* receiver = LoadReceiver(primary->token_index());
6111 selector = ParseInstanceCall(receiver, name);
6112 }
6113 } else { 6167 } else {
6114 // Internal parser error. 6168 UNREACHABLE(); // Internal parser error.
6115 UNREACHABLE();
6116 } 6169 }
6117 } 6170 }
6118 selector = new LoadIndexedNode(bracket_pos, array, index); 6171 selector = new LoadIndexedNode(bracket_pos, array, index);
6119 } else if (CurrentToken() == Token::kLPAREN) { 6172 } else if (CurrentToken() == Token::kLPAREN) {
6120 if (left->IsPrimaryNode()) { 6173 if (left->IsPrimaryNode()) {
6121 PrimaryNode* primary = left->AsPrimaryNode(); 6174 PrimaryNode* primary = left->AsPrimaryNode();
6122 const intptr_t primary_pos = primary->token_index(); 6175 const intptr_t primary_pos = primary->token_index();
6123 if (primary->primary().IsFunction()) { 6176 if (primary->primary().IsFunction()) {
6124 Function& func = Function::CheckedHandle(primary->primary().raw()); 6177 Function& func = Function::CheckedHandle(primary->primary().raw());
6125 String& func_name = String::ZoneHandle(func.name()); 6178 String& func_name = String::ZoneHandle(func.name());
(...skipping 20 matching lines...) Expand all
6146 name.ToCString()); 6199 name.ToCString());
6147 } else { 6200 } else {
6148 // Treat as call to unresolved (instance) method. 6201 // Treat as call to unresolved (instance) method.
6149 AstNode* receiver = LoadReceiver(primary->token_index()); 6202 AstNode* receiver = LoadReceiver(primary->token_index());
6150 selector = ParseInstanceCall(receiver, name); 6203 selector = ParseInstanceCall(receiver, name);
6151 } 6204 }
6152 } else if (primary->primary().IsClass()) { 6205 } else if (primary->primary().IsClass()) {
6153 ErrorMsg(left->token_index(), 6206 ErrorMsg(left->token_index(),
6154 "must use 'new' or 'const' to construct new instance"); 6207 "must use 'new' or 'const' to construct new instance");
6155 } else { 6208 } else {
6156 // Internal parser error. 6209 UNREACHABLE(); // Internal parser error.
6157 UNREACHABLE();
6158 } 6210 }
6159 } else { 6211 } else {
6160 // Left is not a primary node; this must be a closure call. 6212 // Left is not a primary node; this must be a closure call.
6161 AstNode* closure = left; 6213 AstNode* closure = left;
6162 selector = ParseClosureCall(closure); 6214 selector = ParseClosureCall(closure);
6163 } 6215 }
6164 } else { 6216 } else {
6165 // No (more) selector to parse. 6217 // No (more) selector to parse.
6218 left = LoadFieldIfUnresolved(left);
6166 if (left->IsPrimaryNode()) { 6219 if (left->IsPrimaryNode()) {
6167 if (left->AsPrimaryNode()->primary().IsString()) { 6220 PrimaryNode* primary = left->AsPrimaryNode();
6168 PrimaryNode* primary = left->AsPrimaryNode(); 6221 if (primary->primary().IsFunction()) {
6169 const String& ident =
6170 String::CheckedZoneHandle(primary->primary().raw());
6171 // An unresolved identifier that is not followed by a selector token
6172 // . or [ or (.
6173 // If we are in a static method, this is an error.
6174 // If we are compiling an instance method, convert this into
6175 // a runtime lookup for a field (which may be defined in a
6176 // subclass.)
6177 if (current_function().is_static()) {
6178 ErrorMsg(primary->token_index(),
6179 "identifier '%s' is not declared in this scope",
6180 ident.ToCString());
6181 } else {
6182 // Treat as call to unresolved (instance) field.
6183 AstNode* receiver = LoadReceiver(primary->token_index());
6184 postfix_expr = ParseInstanceFieldAccess(receiver, ident);
6185 }
6186 } else if (left->AsPrimaryNode()->primary().IsFunction()) {
6187 // Treat as implicit closure. 6222 // Treat as implicit closure.
6188 PrimaryNode* primary = left->AsPrimaryNode(); 6223 left = LoadClosure(primary);
6189 const Function& func = 6224 } else if (left->AsPrimaryNode()->primary().IsClass()) {
6190 Function::CheckedZoneHandle(primary->primary().raw()); 6225 Class& cls = Class::CheckedHandle(
6191 const String& funcname = String::ZoneHandle(func.name()); 6226 left->AsPrimaryNode()->primary().raw());
6192 if (func.is_static()) { 6227 String& cls_name = String::Handle(cls.Name());
6193 // Static function access. 6228 ErrorMsg(left->token_index(),
6194 postfix_expr = CreateImplicitClosureNode(func, 6229 "illegal use of class name '%s'",
6195 primary->token_index(), 6230 cls_name.ToCString());
6196 NULL); 6231 } else {
6197 } else { 6232 UNREACHABLE(); // Internal parser error.
6198 // Instance function access.
6199 if (current_function().is_static() ||
6200 current_function().IsInFactoryScope()) {
6201 ErrorMsg(primary->token_index(),
6202 "illegal use of method '%s'",
6203 funcname.ToCString());
6204 }
6205 AstNode* receiver = LoadReceiver(primary->token_index());
6206 postfix_expr = ParseInstanceFieldAccess(receiver, funcname);
6207 }
6208 } 6233 }
6209 } 6234 }
6235 postfix_expr = left;
6210 // Done parsing selectors. 6236 // Done parsing selectors.
6211 break; 6237 break;
6212 } 6238 }
6213 ASSERT(selector != NULL); 6239 ASSERT(selector != NULL);
6214 postfix_expr = selector; 6240 postfix_expr = selector;
6215 } 6241 }
6216 if (IsIncrementOperator(CurrentToken())) { 6242 if (IsIncrementOperator(CurrentToken())) {
6217 TRACE_PARSER("IncrementOperator"); 6243 TRACE_PARSER("IncrementOperator");
6218 Token::Kind incr_op = CurrentToken(); 6244 Token::Kind incr_op = CurrentToken();
6219 if (!IsAssignableExpr(postfix_expr)) { 6245 if (!IsAssignableExpr(postfix_expr)) {
(...skipping 1269 matching lines...) Expand 10 before | Expand all | Expand 10 after
7489 OpenBlock(); 7515 OpenBlock();
7490 primary = ParseFunctionStatement(true); 7516 primary = ParseFunctionStatement(true);
7491 CloseBlock(); 7517 CloseBlock();
7492 } else if (IsIdentifier()) { 7518 } else if (IsIdentifier()) {
7493 QualIdent qual_ident; 7519 QualIdent qual_ident;
7494 ParseQualIdent(&qual_ident); 7520 ParseQualIdent(&qual_ident);
7495 if (qual_ident.lib_prefix == NULL) { 7521 if (qual_ident.lib_prefix == NULL) {
7496 if (!ResolveIdentInLocalScope(qual_ident.ident_pos, 7522 if (!ResolveIdentInLocalScope(qual_ident.ident_pos,
7497 *qual_ident.ident, 7523 *qual_ident.ident,
7498 &primary)) { 7524 &primary)) {
7499 // This is a non-local unqualified identifier so resolve the identifier 7525 // Check whether the identifier is a type parameter.
7500 // locally in the main app library and all libraries imported by it. 7526 const Class& scope_class = Class::Handle(TypeParametersScopeClass());
7501 primary = ResolveIdentInLibraryScope(library_, 7527 if (!scope_class.IsNull()) {
7502 qual_ident, 7528 TypeParameter& type_param = TypeParameter::ZoneHandle();
7503 kResolveIncludingImports); 7529 type_param = scope_class.LookupTypeParameter(
7530 *(qual_ident.ident), token_index_);
regis 2012/02/23 19:11:44 Strange indentation. But why not just one statemen
hausner 2012/02/23 19:43:18 Found it more readable with two statements due to
7531 if (!type_param.IsNull()) {
7532 primary = new PrimaryNode(qual_ident.ident_pos, type_param);
7533 }
7534 }
7535 if (primary == NULL) {
7536 // This is a non-local unqualified identifier so resolve the
7537 // identifier locally in the main app library and all libraries
7538 // imported by it.
7539 primary = ResolveIdentInLibraryScope(library_,
7540 qual_ident,
7541 kResolveIncludingImports);
7542 }
7504 } 7543 }
7505 } else { 7544 } else {
7506 // This is a qualified identifier with a library prefix so resolve 7545 // This is a qualified identifier with a library prefix so resolve
7507 // the identifier locally in that library (we do not include the 7546 // the identifier locally in that library (we do not include the
7508 // libraries imported by that library). 7547 // libraries imported by that library).
7509 primary = ResolveIdentInLibraryPrefixScope(*(qual_ident.lib_prefix), 7548 primary = ResolveIdentInLibraryPrefixScope(*(qual_ident.lib_prefix),
7510 qual_ident); 7549 qual_ident);
7511 } 7550 }
7512 ASSERT(primary != NULL); 7551 ASSERT(primary != NULL);
7513 } else if (CurrentToken() == Token::kTHIS) { 7552 } else if (CurrentToken() == Token::kTHIS) {
(...skipping 364 matching lines...) Expand 10 before | Expand all | Expand 10 after
7878 void Parser::SkipQualIdent() { 7917 void Parser::SkipQualIdent() {
7879 ASSERT(IsIdentifier()); 7918 ASSERT(IsIdentifier());
7880 ConsumeToken(); 7919 ConsumeToken();
7881 if (CurrentToken() == Token::kPERIOD) { 7920 if (CurrentToken() == Token::kPERIOD) {
7882 ConsumeToken(); // Consume the kPERIOD token. 7921 ConsumeToken(); // Consume the kPERIOD token.
7883 ExpectIdentifier("identifier expected after '.'"); 7922 ExpectIdentifier("identifier expected after '.'");
7884 } 7923 }
7885 } 7924 }
7886 7925
7887 } // namespace dart 7926 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/parser.h ('k') | tests/language/language.status » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698