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

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

Issue 23484020: Update handling of ambiguous name references (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 | « runtime/vm/parser.h ('k') | runtime/vm/parser_test.cc » ('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 1682 matching lines...) Expand 10 before | Expand all | Expand 10 after
1693 // Lookup class in the core lib which also contains various VM 1693 // Lookup class in the core lib which also contains various VM
1694 // helper methods and classes. Allow look up of private classes. 1694 // helper methods and classes. Allow look up of private classes.
1695 static RawClass* LookupCoreClass(const String& class_name) { 1695 static RawClass* LookupCoreClass(const String& class_name) {
1696 const Library& core_lib = Library::Handle(Library::CoreLibrary()); 1696 const Library& core_lib = Library::Handle(Library::CoreLibrary());
1697 String& name = String::Handle(class_name.raw()); 1697 String& name = String::Handle(class_name.raw());
1698 if (class_name.CharAt(0) == Scanner::kPrivateIdentifierStart) { 1698 if (class_name.CharAt(0) == Scanner::kPrivateIdentifierStart) {
1699 // Private identifiers are mangled on a per script basis. 1699 // Private identifiers are mangled on a per script basis.
1700 name = String::Concat(name, String::Handle(core_lib.private_key())); 1700 name = String::Concat(name, String::Handle(core_lib.private_key()));
1701 name = Symbols::New(name); 1701 name = Symbols::New(name);
1702 } 1702 }
1703 return core_lib.LookupClass(name, NULL); // No ambiguity error expected. 1703 return core_lib.LookupClass(name);
1704 } 1704 }
1705 1705
1706 1706
1707 static const String& PrivateCoreLibName(const String& str) { 1707 static const String& PrivateCoreLibName(const String& str) {
1708 const Library& core_lib = Library::Handle(Library::CoreLibrary()); 1708 const Library& core_lib = Library::Handle(Library::CoreLibrary());
1709 const String& private_name = String::ZoneHandle(core_lib.PrivateName(str)); 1709 const String& private_name = String::ZoneHandle(core_lib.PrivateName(str));
1710 return private_name; 1710 return private_name;
1711 } 1711 }
1712 1712
1713 1713
(...skipping 6731 matching lines...) Expand 10 before | Expand all | Expand 10 after
8445 return; 8445 return;
8446 } 8446 }
8447 *type = type_parameter.raw(); 8447 *type = type_parameter.raw();
8448 return; 8448 return;
8449 } 8449 }
8450 } 8450 }
8451 // The referenced class may not have been parsed yet. It would be wrong 8451 // The referenced class may not have been parsed yet. It would be wrong
8452 // to resolve it too early to an imported class of the same name. 8452 // to resolve it too early to an imported class of the same name.
8453 if (finalization > ClassFinalizer::kResolveTypeParameters) { 8453 if (finalization > ClassFinalizer::kResolveTypeParameters) {
8454 // Resolve classname in the scope of the current library. 8454 // Resolve classname in the scope of the current library.
8455 Error& error = Error::Handle();
8456 resolved_type_class = ResolveClassInCurrentLibraryScope( 8455 resolved_type_class = ResolveClassInCurrentLibraryScope(
8457 unresolved_class.token_pos(), 8456 unresolved_class_name);
8458 unresolved_class_name,
8459 &error);
8460 if (!error.IsNull()) {
8461 if ((finalization == ClassFinalizer::kCanonicalizeWellFormed) ||
8462 FLAG_error_on_bad_type) {
8463 *type = ClassFinalizer::NewFinalizedMalformedType(
8464 error,
8465 scope_class,
8466 unresolved_class.token_pos(),
8467 "cannot resolve class '%s'",
8468 unresolved_class_name.ToCString());
8469 } else {
8470 // Map the malformed type to dynamic and ignore type arguments.
8471 *type = Type::DynamicType();
8472 }
8473 return;
8474 }
8475 } 8457 }
8476 } else { 8458 } else {
8477 LibraryPrefix& lib_prefix = 8459 LibraryPrefix& lib_prefix =
8478 LibraryPrefix::Handle(unresolved_class.library_prefix()); 8460 LibraryPrefix::Handle(unresolved_class.library_prefix());
8479 // Resolve class name in the scope of the library prefix. 8461 // Resolve class name in the scope of the library prefix.
8480 Error& error = Error::Handle(); 8462 resolved_type_class =
8481 resolved_type_class = ResolveClassInPrefixScope( 8463 ResolveClassInPrefixScope(lib_prefix, unresolved_class_name);
8482 unresolved_class.token_pos(),
8483 lib_prefix,
8484 unresolved_class_name,
8485 &error);
8486 if (!error.IsNull()) {
8487 if ((finalization == ClassFinalizer::kCanonicalizeWellFormed) ||
8488 FLAG_error_on_bad_type) {
8489 *type = ClassFinalizer::NewFinalizedMalformedType(
8490 error,
8491 scope_class,
8492 unresolved_class.token_pos(),
8493 "cannot resolve class '%s'",
8494 unresolved_class_name.ToCString());
8495 } else {
8496 // Map the malformed type to dynamic and ignore type arguments.
8497 *type = Type::DynamicType();
8498 }
8499 return;
8500 }
8501 } 8464 }
8502 // At this point, we can only have a parameterized_type. 8465 // At this point, we can only have a parameterized_type.
8503 const Type& parameterized_type = Type::Cast(*type); 8466 const Type& parameterized_type = Type::Cast(*type);
8504 if (!resolved_type_class.IsNull()) { 8467 if (!resolved_type_class.IsNull()) {
8505 // Replace unresolved class with resolved type class. 8468 // Replace unresolved class with resolved type class.
8506 parameterized_type.set_type_class(resolved_type_class); 8469 parameterized_type.set_type_class(resolved_type_class);
8507 } else if (finalization >= ClassFinalizer::kCanonicalize) { 8470 } else if (finalization >= ClassFinalizer::kCanonicalize) {
8508 if ((finalization == ClassFinalizer::kCanonicalizeWellFormed) || 8471 if ((finalization == ClassFinalizer::kCanonicalizeWellFormed) ||
8509 FLAG_error_on_bad_type) { 8472 FLAG_error_on_bad_type) {
8510 ClassFinalizer::FinalizeMalformedType( 8473 ClassFinalizer::FinalizeMalformedType(
(...skipping 367 matching lines...) Expand 10 before | Expand all | Expand 10 after
8878 obj = lib.LookupLocalObject(accessor_name); 8841 obj = lib.LookupLocalObject(accessor_name);
8879 if (!obj.IsNull()) { 8842 if (!obj.IsNull()) {
8880 return obj.raw(); 8843 return obj.raw();
8881 } 8844 }
8882 accessor_name = Field::SetterName(name); 8845 accessor_name = Field::SetterName(name);
8883 obj = lib.LookupLocalObject(accessor_name); 8846 obj = lib.LookupLocalObject(accessor_name);
8884 return obj.raw(); 8847 return obj.raw();
8885 } 8848 }
8886 8849
8887 8850
8888 static RawObject* LookupNameInImport(Isolate* isolate,
8889 const Namespace& ns,
8890 const String& name) {
8891 // If the given name is filtered out by the import, don't look it up, nor its
8892 // getter and setter names.
8893 if (ns.HidesName(name)) {
8894 return Object::null();
8895 }
8896 Object& obj = Object::Handle(isolate);
8897 obj = ns.Lookup(name);
8898 if (!obj.IsNull()) {
8899 return obj.raw();
8900 }
8901 String& accessor_name = String::Handle(isolate, Field::GetterName(name));
8902 obj = ns.Lookup(accessor_name);
8903 if (!obj.IsNull()) {
8904 return obj.raw();
8905 }
8906 accessor_name = Field::SetterName(name);
8907 obj = ns.Lookup(accessor_name);
8908 return obj.raw();
8909 }
8910
8911
8912 // Resolve a name by checking the global scope of the current 8851 // Resolve a name by checking the global scope of the current
8913 // library. If not found in the current library, then look in the scopes 8852 // library. If not found in the current library, then look in the scopes
8914 // of all libraries that are imported without a library prefix. 8853 // of all libraries that are imported without a library prefix.
8915 // Issue an error if the name is not found in the global scope 8854 RawObject* Parser::ResolveNameInCurrentLibraryScope(const String& name) {
8916 // of the current library, but is defined in more than one imported
8917 // library, i.e. if the name cannot be resolved unambiguously.
8918 RawObject* Parser::ResolveNameInCurrentLibraryScope(intptr_t ident_pos,
8919 const String& name,
8920 Error* error) {
8921 TRACE_PARSER("ResolveNameInCurrentLibraryScope"); 8855 TRACE_PARSER("ResolveNameInCurrentLibraryScope");
8922 HANDLESCOPE(isolate()); 8856 HANDLESCOPE(isolate());
8923 Object& obj = Object::Handle(isolate(), 8857 Object& obj = Object::Handle(isolate(),
8924 LookupNameInLibrary(isolate(), library_, name)); 8858 LookupNameInLibrary(isolate(), library_, name));
8925 if (obj.IsNull()) { 8859 if (!obj.IsNull()) {
8926 // Name is not found in current library. Check scope of all 8860 return obj.raw();
8927 // imported libraries.
8928 String& first_lib_url = String::Handle(isolate());
8929 Namespace& import = Namespace::Handle(isolate());
8930 intptr_t num_imports = library_.num_imports();
8931 Object& imported_obj = Object::Handle(isolate());
8932 Library& lib = Library::Handle(isolate());
8933 for (int i = 0; i < num_imports; i++) {
8934 import = library_.ImportAt(i);
8935 imported_obj = LookupNameInImport(isolate(), import, name);
8936 if (!imported_obj.IsNull()) {
8937 lib ^= import.library();
8938 if (!first_lib_url.IsNull()) {
8939 // Found duplicate definition.
8940 Error& ambiguous_ref_error = Error::Handle();
8941 if (first_lib_url.raw() == lib.url()) {
8942 ambiguous_ref_error = FormatErrorMsg(
8943 script_, ident_pos, "Error",
8944 "ambiguous reference to '%s', "
8945 "as library '%s' is imported multiple times",
8946 name.ToCString(),
8947 first_lib_url.ToCString());
8948 } else {
8949 ambiguous_ref_error = FormatErrorMsg(
8950 script_, ident_pos, "Error",
8951 "ambiguous reference: "
8952 "'%s' is defined in library '%s' and also in '%s'",
8953 name.ToCString(),
8954 first_lib_url.ToCString(),
8955 String::Handle(lib.url()).ToCString());
8956 }
8957 if (error == NULL) {
8958 // Report a compile time error since the caller is not interested
8959 // in the error.
8960 ErrorMsg(ambiguous_ref_error);
8961 }
8962 *error = ambiguous_ref_error.raw();
8963 return Object::null();
8964 } else {
8965 first_lib_url = lib.url();
8966 obj = imported_obj.raw();
8967 }
8968 }
8969 }
8970 } 8861 }
8971 return obj.raw(); 8862 return library_.LookupImportedObject(name);
8972 } 8863 }
8973 8864
8974 8865
8975 RawClass* Parser::ResolveClassInCurrentLibraryScope(intptr_t ident_pos, 8866 RawClass* Parser::ResolveClassInCurrentLibraryScope(const String& name) {
8976 const String& name,
8977 Error* error) {
8978 const Object& obj = 8867 const Object& obj =
8979 Object::Handle(ResolveNameInCurrentLibraryScope(ident_pos, name, error)); 8868 Object::Handle(ResolveNameInCurrentLibraryScope(name));
8980 if (obj.IsClass()) { 8869 if (obj.IsClass()) {
8981 return Class::Cast(obj).raw(); 8870 return Class::Cast(obj).raw();
8982 } 8871 }
8983 return Class::null(); 8872 return Class::null();
8984 } 8873 }
8985 8874
8986 8875
8987 // Resolve an identifier by checking the global scope of the current 8876 // Resolve an identifier by checking the global scope of the current
8988 // 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
8989 // of all libraries that are imported without a library prefix. 8878 // of all libraries that are imported without a library prefix.
8990 // Issue an error if the identifier is not found in the global scope 8879 // Issue an error if the identifier is not found in the global scope
8991 // of the current library, but is defined in more than one imported 8880 // of the current library, but is defined in more than one imported
8992 // library, i.e. if the identifier cannot be resolved unambiguously. 8881 // library, i.e. if the identifier cannot be resolved unambiguously.
8993 AstNode* Parser::ResolveIdentInCurrentLibraryScope(intptr_t ident_pos, 8882 AstNode* Parser::ResolveIdentInCurrentLibraryScope(intptr_t ident_pos,
8994 const String& ident) { 8883 const String& ident) {
8995 TRACE_PARSER("ResolveIdentInCurrentLibraryScope"); 8884 TRACE_PARSER("ResolveIdentInCurrentLibraryScope");
8996 const Object& obj = 8885 const Object& obj =
8997 Object::Handle(ResolveNameInCurrentLibraryScope(ident_pos, ident, NULL)); 8886 Object::Handle(ResolveNameInCurrentLibraryScope(ident));
8998 if (obj.IsClass()) { 8887 if (obj.IsClass()) {
8999 const Class& cls = Class::Cast(obj); 8888 const Class& cls = Class::Cast(obj);
9000 return new PrimaryNode(ident_pos, Class::ZoneHandle(cls.raw())); 8889 return new PrimaryNode(ident_pos, Class::ZoneHandle(cls.raw()));
9001 } else if (obj.IsField()) { 8890 } else if (obj.IsField()) {
9002 const Field& field = Field::Cast(obj); 8891 const Field& field = Field::Cast(obj);
9003 ASSERT(field.is_static()); 8892 ASSERT(field.is_static());
9004 return GenerateStaticFieldLookup(field, ident_pos); 8893 return GenerateStaticFieldLookup(field, ident_pos);
9005 } else if (obj.IsFunction()) { 8894 } else if (obj.IsFunction()) {
9006 const Function& func = Function::Cast(obj); 8895 const Function& func = Function::Cast(obj);
9007 ASSERT(func.is_static()); 8896 ASSERT(func.is_static());
9008 if (func.IsGetterFunction() || func.IsSetterFunction()) { 8897 if (func.IsGetterFunction() || func.IsSetterFunction()) {
9009 return new StaticGetterNode(ident_pos, 8898 return new StaticGetterNode(ident_pos,
9010 /* receiver */ NULL, 8899 /* receiver */ NULL,
9011 /* is_super_getter */ false, 8900 /* is_super_getter */ false,
9012 Class::ZoneHandle(func.Owner()), 8901 Class::ZoneHandle(func.Owner()),
9013 ident); 8902 ident);
9014 8903
9015 } else { 8904 } else {
9016 return new PrimaryNode(ident_pos, Function::ZoneHandle(func.raw())); 8905 return new PrimaryNode(ident_pos, Function::ZoneHandle(func.raw()));
9017 } 8906 }
9018 } else { 8907 } else {
9019 ASSERT(obj.IsNull() || obj.IsLibraryPrefix()); 8908 ASSERT(obj.IsNull() || obj.IsLibraryPrefix());
9020 } 8909 }
9021 // Lexically unresolved primary identifiers are referenced by their name. 8910 // Lexically unresolved primary identifiers are referenced by their name.
9022 return new PrimaryNode(ident_pos, ident); 8911 return new PrimaryNode(ident_pos, ident);
9023 } 8912 }
9024 8913
9025 8914
9026 RawObject* Parser::ResolveNameInPrefixScope(intptr_t ident_pos, 8915 RawObject* Parser::ResolveNameInPrefixScope(const LibraryPrefix& prefix,
9027 const LibraryPrefix& prefix, 8916 const String& name) {
9028 const String& name,
9029 Error* error) {
9030 TRACE_PARSER("ResolveNameInPrefixScope");
9031 HANDLESCOPE(isolate()); 8917 HANDLESCOPE(isolate());
9032 Namespace& import = Namespace::Handle(isolate()); 8918 return prefix.LookupObject(name);
9033 String& first_lib_url = String::Handle(isolate());
9034 Object& obj = Object::Handle(isolate());
9035 Object& resolved_obj = Object::Handle(isolate());
9036 const Array& imports = Array::Handle(isolate(), prefix.imports());
9037 Library& lib = Library::Handle(isolate());
9038 for (intptr_t i = 0; i < prefix.num_imports(); i++) {
9039 import ^= imports.At(i);
9040 resolved_obj = LookupNameInImport(isolate(), import, name);
9041 if (!resolved_obj.IsNull()) {
9042 obj = resolved_obj.raw();
9043 lib = import.library();
9044 if (first_lib_url.IsNull()) {
9045 first_lib_url = lib.url();
9046 } else {
9047 // Found duplicate definition.
9048 Error& ambiguous_ref_error = Error::Handle();
9049 if (first_lib_url.raw() == lib.url()) {
9050 ambiguous_ref_error = FormatErrorMsg(
9051 script_, ident_pos, "Error",
9052 "ambiguous reference: '%s.%s' is imported multiple times",
9053 String::Handle(prefix.name()).ToCString(),
9054 name.ToCString());
9055 } else {
9056 ambiguous_ref_error = FormatErrorMsg(
9057 script_, ident_pos, "Error",
9058 "ambiguous reference: '%s.%s' is defined in '%s' and '%s'",
9059 String::Handle(prefix.name()).ToCString(),
9060 name.ToCString(),
9061 first_lib_url.ToCString(),
9062 String::Handle(lib.url()).ToCString());
9063 }
9064 if (error == NULL) {
9065 // Report a compile time error since the caller is not interested
9066 // in the error.
9067 ErrorMsg(ambiguous_ref_error);
9068 }
9069 *error = ambiguous_ref_error.raw();
9070 return Object::null();
9071 }
9072 }
9073 }
9074 return obj.raw();
9075 } 8919 }
9076 8920
9077 8921
9078 RawClass* Parser::ResolveClassInPrefixScope(intptr_t ident_pos, 8922 RawClass* Parser::ResolveClassInPrefixScope(const LibraryPrefix& prefix,
9079 const LibraryPrefix& prefix, 8923 const String& name) {
9080 const String& name,
9081 Error* error) {
9082 const Object& obj = 8924 const Object& obj =
9083 Object::Handle(ResolveNameInPrefixScope(ident_pos, prefix, name, error)); 8925 Object::Handle(ResolveNameInPrefixScope(prefix, name));
9084 if (obj.IsClass()) { 8926 if (obj.IsClass()) {
9085 return Class::Cast(obj).raw(); 8927 return Class::Cast(obj).raw();
9086 } 8928 }
9087 return Class::null(); 8929 return Class::null();
9088 } 8930 }
9089 8931
9090 8932
9091 // Do a lookup for the identifier in the scope of the specified 8933 // Do a lookup for the identifier in the scope of the specified
9092 // library prefix. This means trying to resolve it locally in all of the 8934 // library prefix. This means trying to resolve it locally in all of the
9093 // libraries present in the library prefix. If there are multiple libraries 8935 // libraries present in the library prefix. If there are multiple libraries
9094 // with the name, issue an ambiguous reference error. 8936 // with the name, issue an ambiguous reference error.
9095 AstNode* Parser::ResolveIdentInPrefixScope(intptr_t ident_pos, 8937 AstNode* Parser::ResolveIdentInPrefixScope(intptr_t ident_pos,
9096 const LibraryPrefix& prefix, 8938 const LibraryPrefix& prefix,
9097 const String& ident) { 8939 const String& ident) {
9098 TRACE_PARSER("ResolveIdentInPrefixScope"); 8940 TRACE_PARSER("ResolveIdentInPrefixScope");
9099 Object& obj = 8941 Object& obj = Object::Handle(ResolveNameInPrefixScope(prefix, ident));
9100 Object::Handle(ResolveNameInPrefixScope(ident_pos, prefix, ident, NULL));
9101 if (obj.IsNull()) { 8942 if (obj.IsNull()) {
9102 // Unresolved prefixed primary identifier. 8943 // Unresolved prefixed primary identifier.
9103 ErrorMsg(ident_pos, "identifier '%s.%s' cannot be resolved", 8944 ErrorMsg(ident_pos, "identifier '%s.%s' cannot be resolved",
9104 String::Handle(prefix.name()).ToCString(), 8945 String::Handle(prefix.name()).ToCString(),
9105 ident.ToCString()); 8946 ident.ToCString());
9106 } 8947 }
9107 if (obj.IsClass()) { 8948 if (obj.IsClass()) {
9108 const Class& cls = Class::Cast(obj); 8949 const Class& cls = Class::Cast(obj);
9109 return new PrimaryNode(ident_pos, Class::ZoneHandle(cls.raw())); 8950 return new PrimaryNode(ident_pos, Class::ZoneHandle(cls.raw()));
9110 } else if (obj.IsField()) { 8951 } else if (obj.IsField()) {
(...skipping 1442 matching lines...) Expand 10 before | Expand all | Expand 10 after
10553 void Parser::SkipQualIdent() { 10394 void Parser::SkipQualIdent() {
10554 ASSERT(IsIdentifier()); 10395 ASSERT(IsIdentifier());
10555 ConsumeToken(); 10396 ConsumeToken();
10556 if (CurrentToken() == Token::kPERIOD) { 10397 if (CurrentToken() == Token::kPERIOD) {
10557 ConsumeToken(); // Consume the kPERIOD token. 10398 ConsumeToken(); // Consume the kPERIOD token.
10558 ExpectIdentifier("identifier expected after '.'"); 10399 ExpectIdentifier("identifier expected after '.'");
10559 } 10400 }
10560 } 10401 }
10561 10402
10562 } // namespace dart 10403 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/parser.h ('k') | runtime/vm/parser_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698