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

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

Issue 23480064: Update unresolved name handling with library prefixes (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 3 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 | « no previous file | tests/co19/co19-runtime.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 8858 matching lines...) Expand 10 before | Expand all | Expand 10 after
8869 if (obj.IsClass()) { 8869 if (obj.IsClass()) {
8870 return Class::Cast(obj).raw(); 8870 return Class::Cast(obj).raw();
8871 } 8871 }
8872 return Class::null(); 8872 return Class::null();
8873 } 8873 }
8874 8874
8875 8875
8876 // Resolve an identifier by checking the global scope of the current 8876 // Resolve an identifier by checking the global scope of the current
8877 // library. If not found in the current library, then look in the scopes 8877 // library. If not found in the current library, then look in the scopes
8878 // of all libraries that are imported without a library prefix. 8878 // of all libraries that are imported without a library prefix.
8879 // Issue an error if the identifier is not found in the global scope
8880 // of the current library, but is defined in more than one imported
8881 // library, i.e. if the identifier cannot be resolved unambiguously.
8882 AstNode* Parser::ResolveIdentInCurrentLibraryScope(intptr_t ident_pos, 8879 AstNode* Parser::ResolveIdentInCurrentLibraryScope(intptr_t ident_pos,
8883 const String& ident) { 8880 const String& ident) {
8884 TRACE_PARSER("ResolveIdentInCurrentLibraryScope"); 8881 TRACE_PARSER("ResolveIdentInCurrentLibraryScope");
8885 const Object& obj = 8882 const Object& obj =
8886 Object::Handle(ResolveNameInCurrentLibraryScope(ident)); 8883 Object::Handle(ResolveNameInCurrentLibraryScope(ident));
8887 if (obj.IsClass()) { 8884 if (obj.IsClass()) {
8888 const Class& cls = Class::Cast(obj); 8885 const Class& cls = Class::Cast(obj);
8889 return new PrimaryNode(ident_pos, Class::ZoneHandle(cls.raw())); 8886 return new PrimaryNode(ident_pos, Class::ZoneHandle(cls.raw()));
8890 } else if (obj.IsField()) { 8887 } else if (obj.IsField()) {
8891 const Field& field = Field::Cast(obj); 8888 const Field& field = Field::Cast(obj);
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
8925 Object::Handle(ResolveNameInPrefixScope(prefix, name)); 8922 Object::Handle(ResolveNameInPrefixScope(prefix, name));
8926 if (obj.IsClass()) { 8923 if (obj.IsClass()) {
8927 return Class::Cast(obj).raw(); 8924 return Class::Cast(obj).raw();
8928 } 8925 }
8929 return Class::null(); 8926 return Class::null();
8930 } 8927 }
8931 8928
8932 8929
8933 // Do a lookup for the identifier in the scope of the specified 8930 // Do a lookup for the identifier in the scope of the specified
8934 // library prefix. This means trying to resolve it locally in all of the 8931 // library prefix. This means trying to resolve it locally in all of the
8935 // libraries present in the library prefix. If there are multiple libraries 8932 // libraries present in the library prefix.
8936 // with the name, issue an ambiguous reference error.
8937 AstNode* Parser::ResolveIdentInPrefixScope(intptr_t ident_pos, 8933 AstNode* Parser::ResolveIdentInPrefixScope(intptr_t ident_pos,
8938 const LibraryPrefix& prefix, 8934 const LibraryPrefix& prefix,
8939 const String& ident) { 8935 const String& ident) {
8940 TRACE_PARSER("ResolveIdentInPrefixScope"); 8936 TRACE_PARSER("ResolveIdentInPrefixScope");
8941 Object& obj = Object::Handle(ResolveNameInPrefixScope(prefix, ident)); 8937 Object& obj = Object::Handle(ResolveNameInPrefixScope(prefix, ident));
8942 if (obj.IsNull()) { 8938 if (obj.IsNull()) {
8943 // Unresolved prefixed primary identifier. 8939 // Unresolved prefixed primary identifier.
8944 ErrorMsg(ident_pos, "identifier '%s.%s' cannot be resolved", 8940 String& qualified_name = String::ZoneHandle(prefix.name());
8945 String::Handle(prefix.name()).ToCString(), 8941 qualified_name = String::Concat(qualified_name, Symbols::Dot());
8946 ident.ToCString()); 8942 qualified_name = String::Concat(qualified_name, ident);
8947 } 8943 qualified_name = Symbols::New(qualified_name);
8948 if (obj.IsClass()) { 8944 return new PrimaryNode(ident_pos, qualified_name);
8945 } else if (obj.IsClass()) {
8949 const Class& cls = Class::Cast(obj); 8946 const Class& cls = Class::Cast(obj);
8950 return new PrimaryNode(ident_pos, Class::ZoneHandle(cls.raw())); 8947 return new PrimaryNode(ident_pos, Class::ZoneHandle(cls.raw()));
8951 } else if (obj.IsField()) { 8948 } else if (obj.IsField()) {
8952 const Field& field = Field::Cast(obj); 8949 const Field& field = Field::Cast(obj);
8953 ASSERT(field.is_static()); 8950 ASSERT(field.is_static());
8954 return GenerateStaticFieldLookup(field, ident_pos); 8951 return GenerateStaticFieldLookup(field, ident_pos);
8955 } else if (obj.IsFunction()) { 8952 } else if (obj.IsFunction()) {
8956 const Function& func = Function::Cast(obj); 8953 const Function& func = Function::Cast(obj);
8957 ASSERT(func.is_static()); 8954 ASSERT(func.is_static());
8958 if (func.IsGetterFunction() || func.IsSetterFunction()) { 8955 if (func.IsGetterFunction() || func.IsSetterFunction()) {
8959 return new StaticGetterNode(ident_pos, 8956 return new StaticGetterNode(ident_pos,
8960 /* receiver */ NULL, 8957 /* receiver */ NULL,
8961 /* is_super_getter */ false, 8958 /* is_super_getter */ false,
8962 Class::ZoneHandle(func.Owner()), 8959 Class::ZoneHandle(func.Owner()),
8963 ident); 8960 ident);
8964 8961
8965 } else { 8962 } else {
8966 return new PrimaryNode(ident_pos, Function::ZoneHandle(func.raw())); 8963 return new PrimaryNode(ident_pos, Function::ZoneHandle(func.raw()));
8967 } 8964 }
8968 } else {
8969 // TODO(hausner): Should this be an error? It is not meaningful to
8970 // reference a library prefix defined in an imported library.
8971 ASSERT(obj.IsLibraryPrefix());
8972 } 8965 }
8973 // Lexically unresolved primary identifiers are referenced by their name. 8966 // All possible object types are handled above.
8974 return new PrimaryNode(ident_pos, ident); 8967 UNREACHABLE();
8968 return NULL;
8975 } 8969 }
8976 8970
8977 8971
8978 // Resolve identifier. Issue an error message if 8972 // Resolve identifier. Issue an error message if
8979 // the ident refers to a method and allow_closure_names is false. 8973 // the ident refers to a method and allow_closure_names is false.
8980 // If the name cannot be resolved, turn it into an instance field access 8974 // If the name cannot be resolved, turn it into an instance field access
8981 // if we're compiling an instance method, or issue an error message 8975 // if we're compiling an instance method, or generate
8982 // if we're compiling a static method. 8976 // throw NoSuchMethodError if we're compiling a static method.
8983 AstNode* Parser::ResolveIdent(intptr_t ident_pos, 8977 AstNode* Parser::ResolveIdent(intptr_t ident_pos,
8984 const String& ident, 8978 const String& ident,
8985 bool allow_closure_names) { 8979 bool allow_closure_names) {
8986 TRACE_PARSER("ResolveIdent"); 8980 TRACE_PARSER("ResolveIdent");
8987 // First try to find the variable in the local scope (block scope or 8981 // First try to find the variable in the local scope (block scope or
8988 // class scope). 8982 // class scope).
8989 AstNode* resolved = NULL; 8983 AstNode* resolved = NULL;
8990 ResolveIdentInLocalScope(ident_pos, ident, &resolved); 8984 ResolveIdentInLocalScope(ident_pos, ident, &resolved);
8991 if (resolved == NULL) { 8985 if (resolved == NULL) {
8992 // Check whether the identifier is a type parameter. 8986 // Check whether the identifier is a type parameter.
(...skipping 965 matching lines...) Expand 10 before | Expand all | Expand 10 after
9958 primary = ResolveIdentInCurrentLibraryScope(qual_ident.ident_pos, 9952 primary = ResolveIdentInCurrentLibraryScope(qual_ident.ident_pos,
9959 *qual_ident.ident); 9953 *qual_ident.ident);
9960 } 9954 }
9961 } else { 9955 } else {
9962 // This is a qualified identifier with a library prefix so resolve 9956 // This is a qualified identifier with a library prefix so resolve
9963 // the identifier locally in that library (we do not include the 9957 // the identifier locally in that library (we do not include the
9964 // libraries imported by that library). 9958 // libraries imported by that library).
9965 primary = ResolveIdentInPrefixScope(qual_ident.ident_pos, 9959 primary = ResolveIdentInPrefixScope(qual_ident.ident_pos,
9966 *qual_ident.lib_prefix, 9960 *qual_ident.lib_prefix,
9967 *qual_ident.ident); 9961 *qual_ident.ident);
9962 // If the identifier could not be resolved, throw a NoSuchMethodError.
9963 // Note: unlike in the case of an unqualified identifier, do not
9964 // interpret the unresolved identifier as an instance method or
9965 // instance getter call when compiling an instance method.
9966 // TODO(hausner): Ideally we should generate the NoSuchMethodError
9967 // later, when we know more about how the unresolved name is used.
9968 // For example, we don't know yet whether the unresolved name
9969 // refers to a getter or a setter. However, it is more awkward
9970 // to distinuish four NoSuchMethodError cases all over the place
9971 // in the parser. The four cases are: prefixed vs non-prefixed
9972 // name, static vs dynamic context in which the unresolved name
9973 // is used. We cheat a little here by looking at the next token
9974 // to determine whether we have an unresolved method call or
9975 // field access.
9976 if (primary->IsPrimaryNode() &&
9977 primary->AsPrimaryNode()->primary().IsString()) {
9978 InvocationMirror::Type call_type =
9979 CurrentToken() == Token::kLPAREN ?
9980 InvocationMirror::kMethod : InvocationMirror::kGetter;
9981 const String& unresolved_name =
9982 String::Cast(primary->AsPrimaryNode()->primary());
9983 primary = ThrowNoSuchMethodError(primary->token_pos(),
9984 current_class(),
9985 unresolved_name,
9986 NULL, // No arguments.
9987 InvocationMirror::kTopLevel,
9988 call_type);
9989 }
9968 } 9990 }
9969 ASSERT(primary != NULL); 9991 ASSERT(primary != NULL);
9970 } else if (CurrentToken() == Token::kTHIS) { 9992 } else if (CurrentToken() == Token::kTHIS) {
9971 LocalVariable* local = LookupLocalScope(Symbols::This()); 9993 LocalVariable* local = LookupLocalScope(Symbols::This());
9972 if (local == NULL) { 9994 if (local == NULL) {
9973 ErrorMsg("receiver 'this' is not in scope"); 9995 ErrorMsg("receiver 'this' is not in scope");
9974 } 9996 }
9975 primary = new LoadLocalNode(TokenPos(), local); 9997 primary = new LoadLocalNode(TokenPos(), local);
9976 ConsumeToken(); 9998 ConsumeToken();
9977 } else if (CurrentToken() == Token::kINTEGER) { 9999 } else if (CurrentToken() == Token::kINTEGER) {
(...skipping 416 matching lines...) Expand 10 before | Expand all | Expand 10 after
10394 void Parser::SkipQualIdent() { 10416 void Parser::SkipQualIdent() {
10395 ASSERT(IsIdentifier()); 10417 ASSERT(IsIdentifier());
10396 ConsumeToken(); 10418 ConsumeToken();
10397 if (CurrentToken() == Token::kPERIOD) { 10419 if (CurrentToken() == Token::kPERIOD) {
10398 ConsumeToken(); // Consume the kPERIOD token. 10420 ConsumeToken(); // Consume the kPERIOD token.
10399 ExpectIdentifier("identifier expected after '.'"); 10421 ExpectIdentifier("identifier expected after '.'");
10400 } 10422 }
10401 } 10423 }
10402 10424
10403 } // namespace dart 10425 } // namespace dart
OLDNEW
« no previous file with comments | « no previous file | tests/co19/co19-runtime.status » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698