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

Unified Diff: runtime/vm/object.cc

Issue 19662003: Refactor resolution code in the vm to properly handle ambiguity errors. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 5 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 side-by-side diff with in-line comments
Download patch
Index: runtime/vm/object.cc
===================================================================
--- runtime/vm/object.cc (revision 25291)
+++ runtime/vm/object.cc (working copy)
@@ -159,7 +159,8 @@
const char* function_name) {
ASSERT(!lib.IsNull());
const Class& cls = Class::Handle(
- lib.LookupClassAllowPrivate(String::Handle(String::New(class_name))));
+ lib.LookupClassAllowPrivate(String::Handle(String::New(class_name)),
+ NULL)); // No ambiguity error expected.
ASSERT(!cls.IsNull());
const Function& function =
Function::Handle(
@@ -2108,8 +2109,12 @@
RawClass* Class::NewNativeWrapper(const Library& library,
const String& name,
int field_count) {
- Class& cls = Class::Handle(library.LookupClass(name));
+ String& ambiguity_error_msg = String::Handle();
+ Class& cls = Class::Handle(library.LookupClass(name, &ambiguity_error_msg));
if (cls.IsNull()) {
+ if (!ambiguity_error_msg.IsNull()) {
+ return Class::null();
+ }
cls = New(name, Script::Handle(), Scanner::kDummyTokenIndex);
cls.SetFields(Object::empty_array());
cls.SetFunctions(Object::empty_array());
@@ -6631,82 +6636,48 @@
}
-RawField* Library::LookupFieldAllowPrivate(const String& name) const {
- // First check if name is found in the local scope of the library.
- Object& obj = Object::Handle(LookupLocalField(name));
- if (!obj.IsNull()) {
+RawField* Library::LookupFieldAllowPrivate(const String& name,
+ String* ambiguity_error_msg) const {
+ Object& obj = Object::Handle(
+ LookupObjectAllowPrivate(name, ambiguity_error_msg));
+ if (obj.IsField()) {
return Field::Cast(obj).raw();
}
-
- // Do not look up private names in imported libraries.
- if (ShouldBePrivate(name)) {
- return Field::null();
- }
-
- // Now check if name is found in any imported libs.
- const Array& imports = Array::Handle(this->imports());
- Namespace& import = Namespace::Handle();
- for (intptr_t j = 0; j < this->num_imports(); j++) {
- import ^= imports.At(j);
- obj = import.Lookup(name);
- if (!obj.IsNull() && obj.IsField()) {
- return Field::Cast(obj).raw();
- }
- }
return Field::null();
}
RawField* Library::LookupLocalField(const String& name) const {
- Isolate* isolate = Isolate::Current();
- Field& field = Field::Handle(isolate, Field::null());
- Object& obj = Object::Handle(isolate, Object::null());
- obj = LookupLocalObject(name);
- if (obj.IsNull() && ShouldBePrivate(name)) {
- String& private_name = String::Handle(isolate, PrivateName(name));
- obj = LookupLocalObject(private_name);
+ Object& obj = Object::Handle(LookupLocalObjectAllowPrivate(name));
+ if (obj.IsField()) {
+ return Field::Cast(obj).raw();
}
- if (!obj.IsNull()) {
- if (obj.IsField()) {
- field ^= obj.raw();
- return field.raw();
- }
- }
-
- // No field found.
return Field::null();
}
-RawFunction* Library::LookupFunctionAllowPrivate(const String& name) const {
- // First check if name is found in the local scope of the library.
- Function& function = Function::Handle(LookupLocalFunction(name));
- if (!function.IsNull()) {
- return function.raw();
+RawFunction* Library::LookupFunctionAllowPrivate(
+ const String& name,
+ String* ambiguity_error_msg) const {
+ Object& obj = Object::Handle(
+ LookupObjectAllowPrivate(name, ambiguity_error_msg));
+ if (obj.IsFunction()) {
+ return Function::Cast(obj).raw();
}
+ return Function::null();
+}
- // Do not look up private names in imported libraries.
- if (ShouldBePrivate(name)) {
- return Function::null();
- }
- // Now check if name is found in any imported libs.
- const Array& imports = Array::Handle(this->imports());
- Namespace& import = Namespace::Handle();
- Object& obj = Object::Handle();
- for (intptr_t j = 0; j < this->num_imports(); j++) {
- import ^= imports.At(j);
- obj = import.Lookup(name);
- if (!obj.IsNull() && obj.IsFunction()) {
- function ^= obj.raw();
- return function.raw();
- }
+RawFunction* Library::LookupLocalFunction(const String& name) const {
+ Object& obj = Object::Handle(LookupLocalObjectAllowPrivate(name));
+ if (obj.IsFunction()) {
+ return Function::Cast(obj).raw();
}
return Function::null();
}
-RawFunction* Library::LookupLocalFunction(const String& name) const {
+RawObject* Library::LookupLocalObjectAllowPrivate(const String& name) const {
Isolate* isolate = Isolate::Current();
Object& obj = Object::Handle(isolate, Object::null());
obj = LookupLocalObject(name);
@@ -6714,42 +6685,91 @@
String& private_name = String::Handle(isolate, PrivateName(name));
obj = LookupLocalObject(private_name);
}
- if (obj.IsFunction()) {
- return Function::Cast(obj).raw();
+ return obj.raw();
+}
+
+
+RawObject* Library::LookupObjectAllowPrivate(
+ const String& name,
+ String* ambiguity_error_msg) const {
+ // First check if name is found in the local scope of the library.
+ Object& obj = Object::Handle(LookupLocalObjectAllowPrivate(name));
+ if (!obj.IsNull()) {
+ return obj.raw();
}
- // No function found.
- return Function::null();
+ // Do not look up private names in imported libraries.
+ if (ShouldBePrivate(name)) {
+ return Object::null();
+ }
+
+ // Now check if name is found in any imported libs. It is a compile-time error
+ // if the name is found in more than one import and actually used.
+ return LookupImportedObject(name, ambiguity_error_msg);
}
-// TODO(regis): This should take an Error* ambiguity_error parameter.
-RawObject* Library::LookupObject(const String& name) const {
+RawObject* Library::LookupObject(const String& name,
+ String* ambiguity_error_msg) const {
// First check if name is found in the local scope of the library.
Object& obj = Object::Handle(LookupLocalObject(name));
if (!obj.IsNull()) {
return obj.raw();
}
- // Now check if name is found in any imported libs.
- // TODO(regis): This does not seem correct. It should be an error if the name
- // is found in more than one import and actually used.
- const Array& imports = Array::Handle(this->imports());
+ // Now check if name is found in any imported libs. It is a compile-time error
+ // if the name is found in more than one import and actually used.
+ return LookupImportedObject(name, ambiguity_error_msg);
+}
+
+
+RawObject* Library::LookupImportedObject(const String& name,
+ String* ambiguity_error_msg) const {
+ Object& obj = Object::Handle();
Namespace& import = Namespace::Handle();
- for (intptr_t j = 0; j < this->num_imports(); j++) {
- import ^= imports.At(j);
+ Library& import_lib = Library::Handle();
+ String& first_import_lib_url = String::Handle();
+ Object& found_obj = Object::Handle();
+ for (intptr_t i = 0; i < num_imports(); i++) {
+ import ^= ImportAt(i);
obj = import.Lookup(name);
if (!obj.IsNull()) {
- return obj.raw();
+ import_lib = import.library();
+ if (!first_import_lib_url.IsNull()) {
+ // Found duplicate definition.
+ const intptr_t kMessageBufferSize = 512;
+ char message_buffer[kMessageBufferSize];
+ if (first_import_lib_url.raw() == url()) {
+ OS::SNPrint(message_buffer,
+ kMessageBufferSize,
+ "ambiguous reference to '%s', "
+ "as library '%s' is imported multiple times",
+ name.ToCString(),
+ first_import_lib_url.ToCString());
+ } else {
+ OS::SNPrint(message_buffer,
+ kMessageBufferSize,
+ "ambiguous reference: "
+ "'%s' is defined in library '%s' and also in '%s'",
+ name.ToCString(),
+ first_import_lib_url.ToCString(),
+ String::Handle(url()).ToCString());
+ }
+ ASSERT(ambiguity_error_msg != NULL);
siva 2013/07/22 22:21:46 The one issue with asserting here for the NULL is
regis 2013/07/22 23:51:27 As suggested, I changed the callers in tests to pa
+ *ambiguity_error_msg = String::New(message_buffer);
+ return Object::null();
+ }
+ first_import_lib_url = url();
+ found_obj = obj.raw();
}
}
- return Object::null();
+ return found_obj.raw();
}
-// TODO(regis): This should take an Error* ambiguity_error parameter.
-RawClass* Library::LookupClass(const String& name) const {
- Object& obj = Object::Handle(LookupObject(name));
- if (!obj.IsNull() && obj.IsClass()) {
+RawClass* Library::LookupClass(const String& name,
+ String* ambiguity_error_msg) const {
+ Object& obj = Object::Handle(LookupObject(name, ambiguity_error_msg));
+ if (obj.IsClass()) {
return Class::Cast(obj).raw();
}
return Class::null();
@@ -6758,18 +6778,20 @@
RawClass* Library::LookupLocalClass(const String& name) const {
Object& obj = Object::Handle(LookupLocalObject(name));
- if (!obj.IsNull() && obj.IsClass()) {
+ if (obj.IsClass()) {
return Class::Cast(obj).raw();
}
return Class::null();
}
-RawClass* Library::LookupClassAllowPrivate(const String& name) const {
+RawClass* Library::LookupClassAllowPrivate(const String& name,
+ String* ambiguity_error_msg) const {
// See if the class is available in this library or in the top level
// scope of any imported library.
Isolate* isolate = Isolate::Current();
- const Class& cls = Class::Handle(isolate, LookupClass(name));
+ const Class& cls = Class::Handle(isolate, LookupClass(name,
+ ambiguity_error_msg));
if (!cls.IsNull()) {
return cls.raw();
}
@@ -6783,7 +6805,6 @@
return Class::Cast(obj).raw();
}
}
-
return Class::null();
}
@@ -7206,18 +7227,54 @@
}
-RawClass* LibraryPrefix::LookupLocalClass(const String& class_name) const {
+RawClass* LibraryPrefix::LookupClass(const String& class_name,
+ String* ambiguity_error_msg) const {
Array& imports = Array::Handle(this->imports());
Object& obj = Object::Handle();
Namespace& import = Namespace::Handle();
+ Library& import_lib = Library::Handle();
+ String& first_import_lib_url = String::Handle();
+ Object& found_obj = Object::Handle();
for (intptr_t i = 0; i < num_imports(); i++) {
import ^= imports.At(i);
obj = import.Lookup(class_name);
- if (!obj.IsNull() && obj.IsClass()) {
- // TODO(hausner):
- return Class::Cast(obj).raw();
+ if (!obj.IsNull()) {
+ import_lib = import.library();
+ if (!first_import_lib_url.IsNull()) {
+ // Found duplicate definition.
+ const intptr_t kMessageBufferSize = 512;
+ char message_buffer[kMessageBufferSize];
+ if (first_import_lib_url.raw() == import_lib.url()) {
+ OS::SNPrint(message_buffer,
+ kMessageBufferSize,
+ "ambiguous reference to '%s', "
+ "as library '%s' is imported multiple times via "
+ "prefix '%s'",
+ class_name.ToCString(),
+ first_import_lib_url.ToCString(),
+ String::Handle(name()).ToCString());
+ } else {
+ OS::SNPrint(message_buffer,
+ kMessageBufferSize,
+ "ambiguous reference: "
+ "'%s' is defined in library '%s' and also in '%s', "
+ "both imported via prefix '%s'",
+ class_name.ToCString(),
+ first_import_lib_url.ToCString(),
+ String::Handle(import_lib.url()).ToCString(),
+ String::Handle(name()).ToCString());
+ }
+ ASSERT(ambiguity_error_msg != NULL);
+ *ambiguity_error_msg = String::New(message_buffer);
+ return Class::null();
+ }
+ first_import_lib_url = import_lib.url();
+ found_obj = obj.raw();
}
}
+ if (found_obj.IsClass()) {
+ return Class::Cast(found_obj).raw();
+ }
return Class::null();
}
@@ -7415,10 +7472,10 @@
func = Function::null(); \
if (strcmp(#class_name, "::") == 0) { \
str = Symbols::New(#function_name); \
- func = lib.LookupFunctionAllowPrivate(str); \
+ func = lib.LookupFunctionAllowPrivate(str, NULL); \
} else { \
str = String::New(#class_name); \
- cls = lib.LookupClassAllowPrivate(str); \
+ cls = lib.LookupClassAllowPrivate(str, NULL); \
if (!cls.IsNull()) { \
if (#function_name[0] == '.') { \
str = String::New(#class_name#function_name); \

Powered by Google App Engine
This is Rietveld 408576698