summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJohn Hodge <tpg@mutabah.net>2015-03-23 15:00:02 +0800
committerJohn Hodge <tpg@mutabah.net>2015-03-23 15:00:02 +0800
commit802c2c5d616d537ed8becea81c2ee6b48ae8f078 (patch)
tree3af733445b819980c8fa9ed5ec1c2dc4d85e7b20 /src
parentd004d8293e289942a99a2137ce0a0455cf078b0d (diff)
downloadmrust-802c2c5d616d537ed8becea81c2ee6b48ae8f078.tar.gz
Move item lookup from AST::Path to AST::Module
Diffstat (limited to 'src')
-rw-r--r--src/ast/ast.cpp124
-rw-r--r--src/ast/ast.hpp38
-rw-r--r--src/ast/path.cpp322
-rw-r--r--src/convert/resolve.cpp4
4 files changed, 297 insertions, 191 deletions
diff --git a/src/ast/ast.cpp b/src/ast/ast.cpp
index 42052c5e..a695c6f5 100644
--- a/src/ast/ast.cpp
+++ b/src/ast/ast.cpp
@@ -491,6 +491,130 @@ void Module::iterate_functions(fcn_visitor_t *visitor, const Crate& crate)
}
}
+template<typename T>
+typename ::std::vector<Item<T> >::const_iterator find_named(const ::std::vector<Item<T> >& vec, const ::std::string& name)
+{
+ return ::std::find_if(vec.begin(), vec.end(), [&name](const Item<T>& x) {
+ return x.name == name;
+ });
+}
+
+Module::ItemRef Module::find_item(const ::std::string& needle) const
+{
+ TRACE_FUNCTION_F("needle = " << needle);
+ // Sub-modules
+ {
+ auto& sms = submods();
+ auto it = ::std::find_if(sms.begin(), sms.end(), [&needle](const ::std::pair<Module,bool>& x) {
+ return x.first.name() == needle;
+ });
+ if( it != sms.end() ) {
+ return ItemRef(it->first);
+ }
+ }
+
+ // External crates
+ {
+ auto& crates = this->extern_crates();
+ auto it = find_named(crates, needle);
+ if( it != crates.end() ) {
+ return ItemRef(it->data);
+ }
+ }
+
+ // Type Aliases
+ {
+ auto& items = this->type_aliases();
+ auto it = find_named(items, needle);
+ if( it != items.end() ) {
+ return ItemRef(it->data);
+ }
+ }
+
+ // Functions
+ {
+ auto& items = this->functions();
+ auto it = find_named(items, needle);
+ if( it != items.end() ) {
+ return ItemRef(it->data);
+ }
+ }
+
+ // Traits
+ {
+ auto& items = this->traits();
+ auto it = find_named(items, needle);
+ if( it != items.end() ) {
+ return ItemRef(it->data);
+ }
+ }
+
+ // Structs
+ {
+ auto& items = this->structs();
+ auto it = find_named(items, needle);
+ if( it != items.end() ) {
+ return ItemRef(it->data);
+ }
+ }
+
+ // Enums
+ {
+ auto& items = this->enums();
+ auto it = find_named(items, needle);
+ if( it != items.end() ) {
+ return ItemRef(it->data);
+ }
+ }
+
+ // Statics
+ {
+ auto& items = this->statics();
+ auto it = find_named(items, needle);
+ if( it != items.end() ) {
+ return ItemRef(it->data);
+ }
+ }
+
+ // - Re-exports
+ // > Comes last, as it's a potentially expensive operation
+ {
+ for( const auto& imp : this->imports() )
+ {
+ if( !imp.is_pub )
+ {
+ // not public, ignore
+ }
+ else if( imp.name == needle )
+ {
+ return ItemRef(imp);
+ }
+ else if( imp.name == "" )
+ {
+ // Loop avoidance, don't check this
+ //if( &imp.data == this )
+ // continue ;
+ //
+ //if( !imp.data.is_bound() )
+ //{
+ // // not yet bound, so run resolution (recursion)
+ // DEBUG("Recursively resolving pub wildcard use " << imp.data);
+ // //imp.data.resolve(root_crate);
+ // throw ParseError::Todo("Path::resolve() wildcard re-export call resolve");
+ //}
+
+ throw ParseError::Todo("Path::resolve() wildcard re-export");
+ }
+ else
+ {
+ // Can't match, ignore
+ }
+ }
+ }
+
+ return Module::ItemRef();
+}
+
SERIALISE_TYPE(TypeAlias::, "AST_TypeAlias", {
s << m_params;
s << m_type;
diff --git a/src/ast/ast.hpp b/src/ast/ast.hpp
index ece9704f..60621036 100644
--- a/src/ast/ast.hpp
+++ b/src/ast/ast.hpp
@@ -596,6 +596,44 @@ public:
void iterate_functions(fcn_visitor_t* visitor, const Crate& crate);
const ::std::string& name() const { return m_name; }
+ class ItemRef
+ {
+ public:
+ enum Type
+ {
+ ITEM_none,
+ ITEM_Module,
+ ITEM_Crate,
+ ITEM_TypeAlias,
+ ITEM_Function,
+ ITEM_Trait,
+ ITEM_Struct,
+ ITEM_Enum,
+ ITEM_Static,
+ ITEM_Use,
+ };
+ private:
+ Type m_type;
+ const void* m_ref;
+ public:
+ ItemRef(): m_type(ITEM_none) {}
+
+ Type type() { return m_type; }
+ #define _(ty,ident) \
+ ItemRef(const ty& ref): m_type(ITEM_##ident), m_ref(&ref) {} \
+ const ty& unwrap_##ident() { assert(m_type == ITEM_##ident); m_type = ITEM_none; return *(const ty*)m_ref; }
+ _(Module, Module)
+ _(::std::string, Crate)
+ _(TypeAlias, TypeAlias)
+ _(Function, Function)
+ _(Trait, Trait)
+ _(Struct, Struct)
+ _(Enum, Enum)
+ _(Static, Static)
+ _(Item<Path>, Use)
+ #undef _
+ };
+ ItemRef find_item(const ::std::string& needle) const;
::std::vector<MetaItem>& attrs() { return m_attrs; }
itemlist_fcn_t& functions() { return m_functions; }
diff --git a/src/ast/path.cpp b/src/ast/path.cpp
index 7eab20dd..3e93e888 100644
--- a/src/ast/path.cpp
+++ b/src/ast/path.cpp
@@ -100,207 +100,151 @@ void Path::resolve(const Crate& root_crate)
continue ;
}
- // Sub-modules
+ auto item = mod->find_item(node.name());
+ switch( item.type() )
{
- auto& sms = mod->submods();
- auto it = ::std::find_if(sms.begin(), sms.end(), [&node](const ::std::pair<Module,bool>& x) {
- return x.first.name() == node.name();
- });
- if( it != sms.end() )
- {
- DEBUG("Sub-module '" << node.name() << "'");
- if( node.args().size() )
- throw ParseError::Generic("Generic params applied to module");
- mod = &it->first;
- continue;
+ // Not found
+ case AST::Module::ItemRef::ITEM_none:
+ // TODO: If parent node is anon, backtrack and try again
+ throw ParseError::Generic("Unable to find component '" + node.name() + "'");
+ break;
+
+ // Sub-module
+ case AST::Module::ItemRef::ITEM_Module:
+ DEBUG("Sub-module : " << node.name());
+ if( node.args().size() )
+ throw ParseError::Generic("Generic params applied to module");
+ mod = &item.unwrap_Module();
+ break;
+
+ // Crate
+ case AST::Module::ItemRef::ITEM_Crate: {
+ const ::std::string& crate_name = item.unwrap_Crate();
+ DEBUG("Extern crate '" << node.name() << "' = '" << crate_name << "'");
+ if( node.args().size() )
+ throw ParseError::Generic("Generic params applied to extern crate");
+ m_crate = crate_name;
+ slice_from = i+1;
+ mod = &root_crate.get_root_module(crate_name);
+ break; }
+
+ // Type Alias
+ case AST::Module::ItemRef::ITEM_TypeAlias: {
+ const auto& ta = item.unwrap_TypeAlias();
+ DEBUG("Type alias <"<<ta.params()<<"> " << ta.type());
+ //if( node.args().size() != ta.params().size() )
+ // throw ParseError::Generic("Param count mismatch when referencing type alias");
+ // Make a copy of the path, replace params with it, then replace *this?
+ // - Maybe leave that up to other code?
+ if( is_last ) {
+ m_binding_type = ALIAS;
+ m_binding.alias_ = &ta;
+ goto ret;
}
- }
- // External crates
- {
- auto& crates = mod->extern_crates();
- auto it = find_named(crates, node.name());
- if( it != crates.end() )
- {
- DEBUG("Extern crate '" << node.name() << "' = '" << it->data << "'");
- if( node.args().size() )
- throw ParseError::Generic("Generic params applied to extern crate");
- m_crate = it->data;
- slice_from = i+1;
- mod = &root_crate.get_root_module(it->data);
- continue;
+ else {
+ throw ParseError::Todo("Path::resolve() type method");
}
- }
-
- // Type Aliases
- {
- auto& items = mod->type_aliases();
- auto it = find_named(items, node.name());
- if( it != items.end() )
- {
- DEBUG("Type alias <"<<it->data.params()<<"> " << it->data.type());
- //if( node.args().size() != it->data.params().size() )
- // throw ParseError::Generic("Param count mismatch when referencing type alias");
- // Make a copy of the path, replace params with it, then replace *this?
- // - Maybe leave that up to other code?
- if( is_last ) {
- m_binding_type = ALIAS;
- m_binding.alias_ = &it->data;
- goto ret;
- }
- else {
- throw ParseError::Todo("Path::resolve() type method");
- }
+ break; }
+
+ // Function
+ case AST::Module::ItemRef::ITEM_Function: {
+ const auto& fn = item.unwrap_Function();
+ DEBUG("Found function");
+ if( is_last ) {
+ m_binding_type = FUNCTION;
+ m_binding.func_ = &fn;
+ goto ret;
}
- }
-
- // - Functions
- {
- auto& items = mod->functions();
- auto it = find_named(items, node.name());
- if( it != items.end() )
- {
- DEBUG("Found function");
- if( is_last ) {
- m_binding_type = FUNCTION;
- m_binding.func_ = &it->data;
- goto ret;
- }
- else {
- throw ParseError::Generic("Import of function, too many extra nodes");
- }
+ else {
+ throw ParseError::Generic("Import of function, too many extra nodes");
}
- }
-
- // - Traits
- {
- auto& items = mod->traits();
- auto it = find_named(items, node.name());
- if( it != items.end() )
- {
- DEBUG("Found trait");
- if( is_last ) {
- m_binding_type = TRAIT;
- m_binding.trait_ = &it->data;
- goto ret;
- }
- else if( is_sec_last ) {
- m_binding_type = TRAIT_METHOD;
- m_binding.trait_ = &it->data;
- goto ret;
- }
- else {
- throw ParseError::Generic("Import of trait, too many extra nodes");
- }
+ break; }
+
+ // Trait
+ case AST::Module::ItemRef::ITEM_Trait: {
+ const auto& t = item.unwrap_Trait();
+ DEBUG("Found trait");
+ if( is_last ) {
+ m_binding_type = TRAIT;
+ m_binding.trait_ = &t;
+ goto ret;
}
- }
- // - Structs
- {
- auto& items = mod->structs();
- auto it = find_named(items, node.name());
- if( it != items.end() )
- {
- DEBUG("Found struct");
- if( is_last ) {
- bind_struct(it->data, node.args());
- goto ret;
- }
- else if( is_sec_last ) {
- throw ParseError::Todo("Path::resolve() struct method");
- }
- else {
- throw ParseError::Generic("Import of struct, too many extra nodes");
- }
+ else if( is_sec_last ) {
+ m_binding_type = TRAIT_METHOD;
+ m_binding.trait_ = &t;
+ goto ret;
}
- }
- // - Enums (and variants)
- {
- auto& enums = mod->enums();
- auto it = find_named(enums, node.name());
- if( it != enums.end() )
- {
- DEBUG("Found enum");
- if( is_last ) {
- bind_enum(it->data, node.args());
- goto ret;
- }
- else if( is_sec_last ) {
- bind_enum_var(it->data, m_nodes[i+1].name(), node.args());
- goto ret;
- }
- else {
- throw ParseError::Generic("Binding path to enum, too many extra nodes");
- }
+ else {
+ throw ParseError::Generic("Import of trait, too many extra nodes");
}
- }
- // - Constants / statics
- {
- auto& items = mod->statics();
- auto it = find_named(items, node.name());
- if( it != items.end() )
- {
- DEBUG("Found static/const");
- if( is_last ) {
- if( node.args().size() )
- throw ParseError::Generic("Unexpected generic params on static/const");
- bind_static(it->data);
- goto ret;
- }
- else {
- throw ParseError::Generic("Binding path to static, trailing nodes");
- }
+ break; }
+
+ // Struct
+ case AST::Module::ItemRef::ITEM_Struct: {
+ const auto& str = item.unwrap_Struct();
+ DEBUG("Found struct");
+ if( is_last ) {
+ bind_struct(str, node.args());
+ goto ret;
}
- }
+ else if( is_sec_last ) {
+ throw ParseError::Todo("Path::resolve() struct method");
+ }
+ else {
+ throw ParseError::Generic("Import of struct, too many extra nodes");
+ }
+ break; }
- // - Re-exports
- // > Comes last, as it's a potentially expensive operation
- {
- for( const auto& imp : mod->imports() )
+ // Enum / enum variant
+ case AST::Module::ItemRef::ITEM_Enum: {
+ const auto& enm = item.unwrap_Enum();
+ DEBUG("Found enum");
+ if( is_last ) {
+ bind_enum(enm, node.args());
+ goto ret;
+ }
+ else if( is_sec_last ) {
+ bind_enum_var(enm, m_nodes[i+1].name(), node.args());
+ goto ret;
+ }
+ else {
+ throw ParseError::Generic("Binding path to enum, too many extra nodes");
+ }
+ break; }
+
+ case AST::Module::ItemRef::ITEM_Static: {
+ const auto& st = item.unwrap_Static();
+ DEBUG("Found static/const");
+ if( is_last ) {
+ if( node.args().size() )
+ throw ParseError::Generic("Unexpected generic params on static/const");
+ bind_static(st);
+ goto ret;
+ }
+ else {
+ throw ParseError::Generic("Binding path to static, trailing nodes");
+ }
+ break; }
+
+ //
+ case AST::Module::ItemRef::ITEM_Use: {
+ const auto& imp = item.unwrap_Use();
+ // replace nodes 0:i with the source path
+ DEBUG("Re-exported path " << imp.data);
+ AST::Path newpath = imp.data;
+ for( unsigned int j = i+1; j < m_nodes.size(); j ++ )
{
- if( !imp.is_pub )
- {
- // not public, ignore
- }
- else if( imp.name == node.name() )
- {
- // replace nodes 0:i with the source path
- DEBUG("Re-exported path " << imp.data);
- AST::Path newpath = imp.data;
- for( unsigned int j = i+1; j < m_nodes.size(); j ++ )
- {
- newpath.m_nodes.push_back( m_nodes[j] );
- }
- DEBUG("- newpath = " << newpath);
- // TODO: This should check for recursion somehow
- newpath.resolve(root_crate);
-
- *this = newpath;
- DEBUG("Alias resolved, *this = " << *this);
- return ;
- }
- else if( imp.name == "" )
- {
- // Loop avoidance, don't check this
- if( &imp.data == this )
- continue ;
-
- if( !imp.data.is_bound() )
- {
- // not yet bound, so run resolution (recursion)
- DEBUG("Recursively resolving pub wildcard use " << imp.data);
- //imp.data.resolve(root_crate);
- throw ParseError::Todo("Path::resolve() wildcard re-export call resolve");
- }
-
- throw ParseError::Todo("Path::resolve() wildcard re-export");
- }
- else
- {
- // Can't match, ignore
- }
+ newpath.m_nodes.push_back( m_nodes[j] );
}
+ DEBUG("- newpath = " << newpath);
+ // TODO: This should check for recursion somehow
+ newpath.resolve(root_crate);
+
+ *this = newpath;
+ DEBUG("Alias resolved, *this = " << *this);
+ break; }
}
- throw ParseError::Generic("Unable to find component '" + node.name() + "'");
}
// We only reach here if the path points to a module
@@ -465,7 +409,8 @@ void Path::print_pretty(::std::ostream& os) const
{
case Path::RELATIVE: s << "RELATIVE"; break;
case Path::ABSOLUTE: s << "ABSOLUTE"; break;
- case Path::LOCAL: s << "LOCAL"; break;
+ case Path::LOCAL: s << "LOCAL"; break;
+ case Path::UFCS: s << "UFCS"; break;
}
return s;
}
@@ -476,6 +421,7 @@ void operator>>(Deserialiser& s, Path::Class& pc)
if(n == "RELATIVE") pc = Path::RELATIVE;
else if(n == "ABSOLUTE") pc = Path::ABSOLUTE;
else if(n == "LOCAL") pc = Path::LOCAL;
+ else if(n == "UFCS") pc = Path::UFCS;
else throw ::std::runtime_error("Unknown path class : " + n);
}
SERIALISE_TYPE(Path::, "AST_Path", {
diff --git a/src/convert/resolve.cpp b/src/convert/resolve.cpp
index 9439297f..2de4ae44 100644
--- a/src/convert/resolve.cpp
+++ b/src/convert/resolve.cpp
@@ -450,9 +450,6 @@ void ResolvePaths_HandleModule_Use(const AST::Crate& crate, const AST::Path& mod
::std::vector<AST::Path> new_imports;
for( auto& imp : mod.imports() )
{
- // TODO: Handle 'super' and 'self' imports
- // - Any other type of import will be absolute
-
if( !imp.data.is_absolute() )
{
if( imp.data[0].name() == "super" ) {
@@ -466,6 +463,7 @@ void ResolvePaths_HandleModule_Use(const AST::Crate& crate, const AST::Path& mod
}
else {
auto newpath = modpath + imp.data;
+ // TODO: Undo anon modules until item is found
DEBUG("Absolutised path " << imp.data << " into " << newpath);
imp.data = ::std::move(newpath);
}