diff options
-rw-r--r-- | src/ast/ast.hpp | 3 | ||||
-rw-r--r-- | src/main.cpp | 2 | ||||
-rw-r--r-- | src/resolve/index.cpp | 85 | ||||
-rw-r--r-- | src/resolve/use.cpp | 223 |
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); } |