summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/ast/ast.hpp3
-rw-r--r--src/main.cpp2
-rw-r--r--src/resolve/index.cpp85
-rw-r--r--src/resolve/use.cpp223
4 files changed, 203 insertions, 110 deletions
diff --git a/src/ast/ast.hpp b/src/ast/ast.hpp
index 9cf9b236..1e0466a3 100644
--- a/src/ast/ast.hpp
+++ b/src/ast/ast.hpp
@@ -421,8 +421,9 @@ private:
struct UseStmt
{
Span sp;
- ::AST::Path path;
::AST::MetaItems attrs;
+ ::AST::Path path;
+ ::AST::PathBinding alt_binding;
UseStmt()
{}
diff --git a/src/main.cpp b/src/main.cpp
index 2cd4b3e4..6361a3b0 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -36,7 +36,7 @@ void init_debug_list()
g_debug_disable_map.insert( "Resolve Use" );
//g_debug_disable_map.insert( "Resolve Index" );
- g_debug_disable_map.insert( "Resolve Absolute" );
+ //g_debug_disable_map.insert( "Resolve Absolute" );
g_debug_disable_map.insert( "HIR Lower" );
diff --git a/src/resolve/index.cpp b/src/resolve/index.cpp
index a8f92027..7ae6cde1 100644
--- a/src/resolve/index.cpp
+++ b/src/resolve/index.cpp
@@ -133,42 +133,57 @@ void Resolve_Index_Module_Base(const AST::Crate& crate, AST::Module& mod)
if( i.name != "" )
{
const auto& sp = i.data.sp;
- const auto& b = i.data.path.binding();
- TU_MATCH(::AST::PathBinding, (b), (e),
- (Unbound,
- BUG(sp, "Import left unbound ("<<i.data.path<<")");
- ),
- (Variable,
- BUG(sp, "Import was bound to variable");
- ),
- (TypeParameter,
- BUG(sp, "Import was bound to type parameter");
- ),
- (TraitMethod,
- BUG(sp, "Import was bound to trait method");
- ),
- (StructMethod,
- BUG(sp, "Import was bound to struct method");
- ),
-
- (Crate , _add_item(sp, mod, IndexName::Namespace, i.name, i.is_pub, i.data.path); ),
- (Module, _add_item(sp, mod, IndexName::Namespace, i.name, i.is_pub, i.data.path); ),
- (Enum, _add_item_type(sp, mod, i.name, i.is_pub, i.data.path); ),
- (Trait, _add_item_type(sp, mod, i.name, i.is_pub, i.data.path); ),
- (TypeAlias, _add_item_type(sp, mod, i.name, i.is_pub, i.data.path); ),
-
- (Struct,
- _add_item_type(sp, mod, i.name, i.is_pub, i.data.path);
- // TODO: Items from extern crates don't populate e.struct_ correctly
- // - If the struct is a tuple-like struct, it presents in the value namespace
- if( e.struct_ && e.struct_->m_data.is_Tuple() ) {
- _add_item_value(sp, mod, i.name, i.is_pub, i.data.path);
+ struct H {
+ static void handle_pb(const Span& sp, AST::Module& mod, const AST::Named<AST::UseStmt>& i, const AST::PathBinding& pb, bool allow_collide)
+ {
+ TU_MATCH(::AST::PathBinding, (pb), (e),
+ (Unbound,
+ ),
+ (Variable,
+ BUG(sp, "Import was bound to variable");
+ ),
+ (TypeParameter,
+ BUG(sp, "Import was bound to type parameter");
+ ),
+ (TraitMethod,
+ BUG(sp, "Import was bound to trait method");
+ ),
+ (StructMethod,
+ BUG(sp, "Import was bound to struct method");
+ ),
+
+ (Crate , _add_item(sp, mod, IndexName::Namespace, i.name, i.is_pub, i.data.path, !allow_collide); ),
+ (Module, _add_item(sp, mod, IndexName::Namespace, i.name, i.is_pub, i.data.path, !allow_collide); ),
+ (Enum, _add_item_type(sp, mod, i.name, i.is_pub, i.data.path, !allow_collide); ),
+ (Trait, _add_item_type(sp, mod, i.name, i.is_pub, i.data.path, !allow_collide); ),
+ (TypeAlias,_add_item_type(sp, mod, i.name, i.is_pub, i.data.path, !allow_collide); ),
+
+ (Struct,
+ _add_item_type(sp, mod, i.name, i.is_pub, i.data.path, !allow_collide);
+ // TODO: Items from extern crates don't populate e.struct_ correctly
+ // - If the struct is a tuple-like struct, it presents in the value namespace
+ if( e.struct_ && e.struct_->m_data.is_Tuple() ) {
+ _add_item_value(sp, mod, i.name, i.is_pub, i.data.path, !allow_collide);
+ }
+ ),
+ (Static , _add_item_value(sp, mod, i.name, i.is_pub, i.data.path, !allow_collide); ),
+ (Function, _add_item_value(sp, mod, i.name, i.is_pub, i.data.path, !allow_collide); ),
+ (EnumVar , _add_item_value(sp, mod, i.name, i.is_pub, i.data.path, !allow_collide); )
+ )
}
- ),
- (Static , _add_item_value(sp, mod, i.name, i.is_pub, i.data.path); ),
- (Function, _add_item_value(sp, mod, i.name, i.is_pub, i.data.path); ),
- (EnumVar , _add_item_value(sp, mod, i.name, i.is_pub, i.data.path); )
- )
+ };
+ if( i.data.path.binding().is_Unbound() ) {
+ BUG(sp, "Import left unbound ("<<i.data.path<<")");
+ }
+ else {
+ H::handle_pb(sp, mod, i, i.data.path.binding(), false);
+ }
+ if( i.data.alt_binding.is_Unbound() ) {
+ // Doesn't matter
+ }
+ else {
+ H::handle_pb(sp, mod, i, i.data.alt_binding, true);
+ }
}
else
{
diff --git a/src/resolve/use.cpp b/src/resolve/use.cpp
index 9c280500..709c488a 100644
--- a/src/resolve/use.cpp
+++ b/src/resolve/use.cpp
@@ -7,9 +7,16 @@
#include <ast/expr.hpp>
#include <hir/hir.hpp>
+enum class Lookup
+{
+ Any,
+ Type,
+ Value,
+};
+
::AST::Path Resolve_Use_AbsolutisePath(const ::AST::Path& base_path, ::AST::Path path);
void Resolve_Use_Mod(const ::AST::Crate& crate, ::AST::Module& mod, ::AST::Path path, slice< const ::AST::Module* > parent_modules={});
-::AST::PathBinding Resolve_Use_GetBinding(const Span& span, const ::AST::Crate& crate, const ::AST::Path& path, slice< const ::AST::Module* > parent_modules);
+::AST::PathBinding Resolve_Use_GetBinding(const Span& span, const ::AST::Crate& crate, const ::AST::Path& path, slice< const ::AST::Module* > parent_modules, Lookup allow=Lookup::Any);
void Resolve_Use(::AST::Crate& crate)
@@ -77,8 +84,6 @@ void Resolve_Use_Mod(const ::AST::Crate& crate, ::AST::Module& mod, ::AST::Path
if( !use_stmt.data.path.m_class.is_Absolute() )
BUG(span, "Use path is not absolute after absolutisation");
- // TODO: Handle case where a use can resolve to two different items (one value, one type/namespace)
- // - Easiest way is with an extra binding slot
use_stmt.data.path.bind( Resolve_Use_GetBinding(span, crate, use_stmt.data.path, parent_modules) );
// - If doing a glob, ensure the item type is valid
@@ -94,6 +99,36 @@ void Resolve_Use_Mod(const ::AST::Crate& crate, ::AST::Module& mod, ::AST::Path
)
)
}
+ else
+ {
+ // TODO: Handle case where a use can resolve to two different items (one value, one type/namespace)
+ // - Easiest way is with an extra binding slot
+ Lookup allow = Lookup::Any;
+ switch( use_stmt.data.path.binding().tag() )
+ {
+ case ::AST::PathBinding::TAG_Crate:
+ case ::AST::PathBinding::TAG_Module:
+ case ::AST::PathBinding::TAG_Trait:
+ case ::AST::PathBinding::TAG_TypeAlias:
+ case ::AST::PathBinding::TAG_Enum:
+ allow = Lookup::Value;
+ break;
+ case ::AST::PathBinding::TAG_Struct:
+ allow = Lookup::Value;
+ break;
+ case ::AST::PathBinding::TAG_EnumVar:
+ allow = Lookup::Value;
+ break;
+ case ::AST::PathBinding::TAG_Static:
+ case ::AST::PathBinding::TAG_Function:
+ allow = Lookup::Type;
+ break;
+ default:
+ break;
+ }
+ ASSERT_BUG(span, allow != Lookup::Any, "");
+ use_stmt.data.alt_binding = Resolve_Use_GetBinding(span, crate, use_stmt.data.path, parent_modules, allow);
+ }
}
for(auto& i : mod.items())
@@ -103,15 +138,7 @@ void Resolve_Use_Mod(const ::AST::Crate& crate, ::AST::Module& mod, ::AST::Path
Resolve_Use_Mod(crate, i.data.as_Module(), path + i.name);
}
}
- /*
- unsigned int idx = 0;
- for(auto& mp : mod.anon_mods())
- {
- Resolve_Use_Mod(crate, *mp, path + FMT("#" << idx));
- idx ++;
- }
- */
- // TODO: Handle anon modules by iterating code (allowing correct item mappings)
+ // - Handle anon modules by iterating code (allowing correct item mappings)
struct NV:
public AST::NodeVisitorDef
@@ -179,7 +206,13 @@ void Resolve_Use_Mod(const ::AST::Crate& crate, ::AST::Module& mod, ::AST::Path
}
}
-::AST::PathBinding Resolve_Use_GetBinding_Mod(const Span& span, const ::AST::Crate& crate, const ::AST::Module& mod, const ::std::string& des_item_name, slice< const ::AST::Module* > parent_modules)
+::AST::PathBinding Resolve_Use_GetBinding_Mod(
+ const Span& span,
+ const ::AST::Crate& crate, const ::AST::Module& mod,
+ const ::std::string& des_item_name,
+ slice< const ::AST::Module* > parent_modules,
+ Lookup allow
+ )
{
// HACK - Catch the possibiliy of a name clash (not sure if this is really an error)
{
@@ -222,29 +255,39 @@ void Resolve_Use_Mod(const ::AST::Crate& crate, ::AST::Module& mod, ::AST::Path
BUG(span, "Hit MacroInv in use resolution");
),
(Crate,
- return ::AST::PathBinding::make_Crate({ &crate.m_extern_crates.at(e.name) });
+ if( allow != Lookup::Value )
+ return ::AST::PathBinding::make_Crate({ &crate.m_extern_crates.at(e.name) });
),
(Type,
- return ::AST::PathBinding::make_TypeAlias({&e});
+ if( allow != Lookup::Value )
+ return ::AST::PathBinding::make_TypeAlias({&e});
),
(Trait,
- return ::AST::PathBinding::make_Trait({&e});
+ if( allow != Lookup::Value )
+ return ::AST::PathBinding::make_Trait({&e});
),
(Function,
- return ::AST::PathBinding::make_Function({&e});
+ if( allow != Lookup::Type )
+ return ::AST::PathBinding::make_Function({&e});
),
(Static,
- return ::AST::PathBinding::make_Static({&e});
+ if( allow != Lookup::Type )
+ return ::AST::PathBinding::make_Static({&e});
),
(Struct,
- return ::AST::PathBinding::make_Struct({&e});
+ if( allow != Lookup::Value )
+ return ::AST::PathBinding::make_Struct({&e});
+ if( e.m_data.is_Tuple() && allow != Lookup::Type )
+ return ::AST::PathBinding::make_Struct({&e});
),
(Enum,
- return ::AST::PathBinding::make_Enum({&e});
+ if( allow != Lookup::Value )
+ return ::AST::PathBinding::make_Enum({&e});
),
(Module,
- return ::AST::PathBinding::make_Module({&e});
+ if( allow != Lookup::Value )
+ return ::AST::PathBinding::make_Module({&e});
)
)
break ;
@@ -260,9 +303,34 @@ void Resolve_Use_Mod(const ::AST::Crate& crate, ::AST::Module& mod, ::AST::Path
if( imp.data.path.binding().is_Unbound() ) {
DEBUG(" > Needs resolve");
// TODO: Handle possibility of recursion
- return Resolve_Use_GetBinding(sp2, crate, Resolve_Use_AbsolutisePath(sp2, mod.path(), imp.data.path), parent_modules);
+ return Resolve_Use_GetBinding(sp2, crate, Resolve_Use_AbsolutisePath(sp2, mod.path(), imp.data.path), parent_modules, allow);
}
else {
+ if( allow != Lookup::Any )
+ {
+ switch( imp.data.path.binding().tag() )
+ {
+ case ::AST::PathBinding::TAG_Crate:
+ case ::AST::PathBinding::TAG_Module:
+ case ::AST::PathBinding::TAG_Trait:
+ case ::AST::PathBinding::TAG_TypeAlias:
+ case ::AST::PathBinding::TAG_Enum:
+ if( allow != Lookup::Type )
+ continue;
+ break;
+ case ::AST::PathBinding::TAG_Struct:
+ break;
+ case ::AST::PathBinding::TAG_EnumVar:
+ break;
+ case ::AST::PathBinding::TAG_Static:
+ case ::AST::PathBinding::TAG_Function:
+ if( allow != Lookup::Value )
+ continue;
+ break;
+ default:
+ break;
+ }
+ }
return imp.data.path.binding().clone();
}
}
@@ -293,14 +361,17 @@ void Resolve_Use_Mod(const ::AST::Crate& crate, ::AST::Module& mod, ::AST::Path
if( mod.path().nodes().size() > 0 && mod.path().nodes().back().name()[0] == '#' ) {
assert( parent_modules.size() > 0 );
- return Resolve_Use_GetBinding_Mod(span, crate, *parent_modules.back(), des_item_name, parent_modules.subslice(0, parent_modules.size()-1));
+ return Resolve_Use_GetBinding_Mod(span, crate, *parent_modules.back(), des_item_name, parent_modules.subslice(0, parent_modules.size()-1), allow);
}
else {
- ERROR(span, E0000, "Could not find node '" << des_item_name << "' in module " << mod.path());
+ if( allow == Lookup::Any )
+ ERROR(span, E0000, "Could not find node '" << des_item_name << "' in module " << mod.path());
+ else
+ return ::AST::PathBinding::make_Unbound({});
}
}
-::AST::PathBinding Resolve_Use_GetBinding__ext(const Span& span, const ::AST::Crate& crate, const ::AST::Path& path, const AST::ExternCrate& ec, unsigned int start)
+::AST::PathBinding Resolve_Use_GetBinding__ext(const Span& span, const ::AST::Crate& crate, const ::AST::Path& path, const AST::ExternCrate& ec, unsigned int start, Lookup allow)
{
const auto& nodes = path.nodes();
const ::HIR::Module* hmod = &ec.m_hir->m_root_module;
@@ -333,74 +404,80 @@ void Resolve_Use_Mod(const ::AST::Crate& crate, ::AST::Module& mod, ::AST::Path
)
)
}
- auto it = hmod->m_mod_items.find(nodes.back().name());
- if( it != hmod->m_mod_items.end() ) {
- TU_MATCHA( (it->second->ent), (e),
- (Import,
- TODO(span, "Recurse to get binding for an import");
- ),
- (Module,
- return ::AST::PathBinding::make_Module({nullptr, &e});
- ),
- (TypeAlias,
- return ::AST::PathBinding::make_TypeAlias({nullptr});
- ),
- (Enum,
- return ::AST::PathBinding::make_Enum({nullptr});
- ),
- (Struct,
- return ::AST::PathBinding::make_Struct({nullptr});
- ),
- (Trait,
- return ::AST::PathBinding::make_Trait({nullptr});
+ if( allow != Lookup::Value )
+ {
+ auto it = hmod->m_mod_items.find(nodes.back().name());
+ if( it != hmod->m_mod_items.end() ) {
+ TU_MATCHA( (it->second->ent), (e),
+ (Import,
+ TODO(span, "Recurse to get binding for an import");
+ ),
+ (Module,
+ return ::AST::PathBinding::make_Module({nullptr, &e});
+ ),
+ (TypeAlias,
+ return ::AST::PathBinding::make_TypeAlias({nullptr});
+ ),
+ (Enum,
+ return ::AST::PathBinding::make_Enum({nullptr});
+ ),
+ (Struct,
+ return ::AST::PathBinding::make_Struct({nullptr});
+ ),
+ (Trait,
+ return ::AST::PathBinding::make_Trait({nullptr});
+ )
)
- )
+ }
}
- auto it2 = hmod->m_value_items.find(nodes.back().name());
- if( it2 != hmod->m_value_items.end() ) {
- TU_MATCHA( (it2->second->ent), (e),
- (Import,
- TODO(span, "Recurse to get binding for an import");
- ),
- (Constant,
- return ::AST::PathBinding::make_Static({ nullptr });
- ),
- (Static,
- return ::AST::PathBinding::make_Static({ nullptr });
- ),
- (StructConstant,
- return ::AST::PathBinding::make_Struct({ nullptr });
- ),
- (Function,
- return ::AST::PathBinding::make_Function({ nullptr });
- ),
- (StructConstructor,
- return ::AST::PathBinding::make_Struct({ nullptr });
+ if( allow != Lookup::Type )
+ {
+ auto it2 = hmod->m_value_items.find(nodes.back().name());
+ if( it2 != hmod->m_value_items.end() ) {
+ TU_MATCHA( (it2->second->ent), (e),
+ (Import,
+ TODO(span, "Recurse to get binding for an import");
+ ),
+ (Constant,
+ return ::AST::PathBinding::make_Static({ nullptr });
+ ),
+ (Static,
+ return ::AST::PathBinding::make_Static({ nullptr });
+ ),
+ (StructConstant,
+ return ::AST::PathBinding::make_Struct({ nullptr });
+ ),
+ (Function,
+ return ::AST::PathBinding::make_Function({ nullptr });
+ ),
+ (StructConstructor,
+ return ::AST::PathBinding::make_Struct({ nullptr });
+ )
)
- )
+ }
}
- TODO(span, "Get binding within an extern crate");
+ return ::AST::PathBinding::make_Unbound({});
}
-::AST::PathBinding Resolve_Use_GetBinding(const Span& span, const ::AST::Crate& crate, const ::AST::Path& path, slice< const ::AST::Module* > parent_modules)
+::AST::PathBinding Resolve_Use_GetBinding(const Span& span, const ::AST::Crate& crate, const ::AST::Path& path, slice< const ::AST::Module* > parent_modules, Lookup allow)
{
if( path.m_class.is_Absolute() && path.m_class.as_Absolute().crate != "" ) {
const auto& path_abs = path.m_class.as_Absolute();
- return Resolve_Use_GetBinding__ext(span, crate, path, crate.m_extern_crates.at( path_abs.crate ), 0);
+ return Resolve_Use_GetBinding__ext(span, crate, path, crate.m_extern_crates.at( path_abs.crate ), 0, allow);
}
const AST::Module* mod = &crate.m_root_module;
const auto& nodes = path.nodes();
for( unsigned int i = 0; i < nodes.size()-1; i ++ )
{
- auto b = Resolve_Use_GetBinding_Mod(span, crate, *mod, nodes[i].name(), parent_modules);
+ auto b = Resolve_Use_GetBinding_Mod(span, crate, *mod, nodes[i].name(), parent_modules, Lookup::Type);
TU_MATCH_DEF(::AST::PathBinding, (b), (e),
(
ERROR(span, E0000, "Unexpected item type in import");
),
(Crate,
- return Resolve_Use_GetBinding__ext(span, crate, path, *e.crate_, i+1);
+ return Resolve_Use_GetBinding__ext(span, crate, path, *e.crate_, i+1, allow);
),
(Enum,
const auto& enum_ = *e.enum_;
@@ -430,6 +507,6 @@ void Resolve_Use_Mod(const ::AST::Crate& crate, ::AST::Module& mod, ::AST::Path
)
}
- return Resolve_Use_GetBinding_Mod(span, crate, *mod, nodes.back().name(), parent_modules);
+ return Resolve_Use_GetBinding_Mod(span, crate, *mod, nodes.back().name(), parent_modules, allow);
}