summaryrefslogtreecommitdiff
path: root/src/resolve
diff options
context:
space:
mode:
Diffstat (limited to 'src/resolve')
-rw-r--r--src/resolve/absolute.cpp238
-rw-r--r--src/resolve/index.cpp3
-rw-r--r--src/resolve/use.cpp12
3 files changed, 236 insertions, 17 deletions
diff --git a/src/resolve/absolute.cpp b/src/resolve/absolute.cpp
index 5685ae82..a41ef04a 100644
--- a/src/resolve/absolute.cpp
+++ b/src/resolve/absolute.cpp
@@ -197,7 +197,7 @@ struct Context
}
return rv;
}
- bool lookup_in_mod(const ::AST::Module& mod, const ::std::string& name, LookupMode mode, ::AST::Path& path) const {
+ static bool lookup_in_mod(const ::AST::Module& mod, const ::std::string& name, LookupMode mode, ::AST::Path& path) {
switch(mode)
{
case LookupMode::Namespace:
@@ -386,9 +386,211 @@ void Resolve_Absolute_PathNodes(/*const*/ Context& context, const Span& sp, ::st
}
}
}
+
+void Resolve_Absolute_Path_BindUFCS(Context& context, const Span& sp, Context::LookupMode& mode, ::AST::Path& path)
+{
+ const auto& ufcs = path.m_class.as_UFCS();
+
+ if( ufcs.nodes.size() > 1 )
+ {
+ // More than one node, break into inner UFCS
+ TODO(sp, "Split multi-node UFCS - " << path);
+ }
+ if( ufcs.nodes.size() == 0 ) {
+
+ if( mode == Context::LookupMode::Type && ! ufcs.trait ) {
+ return ;
+ }
+
+ BUG(sp, "UFCS with no nodes encountered - " << path);
+ }
+ const auto& node = ufcs.nodes.at(0);
+
+ if( ufcs.trait && ufcs.trait->is_valid() )
+ {
+ // Trait is specified, definitely a trait item
+ // - Must resolve here
+ if( ! ufcs.trait->binding().is_Trait() ) {
+ ERROR(sp, E0000, "UFCS trait was not a trait - " << *ufcs.trait);
+ }
+ const auto& tr = *ufcs.trait->binding().as_Trait().trait_;
+
+ switch(mode)
+ {
+ case Context::LookupMode::Pattern:
+ ERROR(sp, E0000, "Invalid use of UFCS in pattern");
+ break;
+ case Context::LookupMode::Namespace:
+ case Context::LookupMode::Type:
+ for( const auto& item : tr.items() )
+ {
+ if( item.name != node.name() ) {
+ break;
+ }
+ TU_MATCH_DEF(::AST::Item, (item.data), (e),
+ (
+ // TODO: Error
+ ),
+ (Type,
+ // Resolve to asociated type
+ )
+ )
+ }
+ break;
+ case Context::LookupMode::Constant:
+ case Context::LookupMode::Variable:
+ for( const auto& item : tr.items() )
+ {
+ if( item.name != node.name() ) {
+ break;
+ }
+ TU_MATCH_DEF(::AST::Item, (item.data), (e),
+ (
+ // TODO: Error
+ ),
+ (Static,
+ // Resolve to asociated type
+ )
+ )
+ }
+ break;
+ }
+ }
+ else
+ {
+ // Trait is unknown or inherent, search for items on the type (if known) otherwise leave it until type resolution
+ // - Methods can't be known until typeck (after the impl map is created)
+ }
+}
+void Resolve_Absolute_Path_BindAbsolute(Context& context, const Span& sp, Context::LookupMode& mode, ::AST::Path& path)
+{
+ const auto& path_abs = path.m_class.as_Absolute();
+
+ if( path_abs.crate != "" ) {
+ // TODO: Handle items from other crates (back-converting HIR paths)
+ TODO(sp, "Handle binding to items from extern crates");
+ }
+
+ const ::AST::Module* mod = &context.m_crate.m_root_module;
+ for(unsigned int i = 0; i < path_abs.nodes.size() - 1; i ++ )
+ {
+ const auto& n = path_abs.nodes[i];
+
+ //::AST::Path tmp;
+ //if( ! Context::lookup_in_mod(*mod, e.name(), Context::LookupMode::Namespace, tmp) ) {
+ // ERROR(sp, E0000, "Couldn't find path component '" << e.name() << "' of " << path);
+ //}
+
+
+ if( n.name()[0] == '#' ) {
+ if( n.args().size() > 0 ) {
+ ERROR(sp, E0000, "Type parameters were not expected here");
+ }
+
+ if( n.name() == "#" ) {
+ TODO(sp, "magic module");
+ }
+
+ char c;
+ unsigned int idx;
+ ::std::stringstream ss( n.name() );
+ ss >> c;
+ ss >> idx;
+ assert( idx < mod->anon_mods().size() );
+ mod = mod->anon_mods()[idx];
+ }
+ else
+ {
+ auto it = mod->m_namespace_items.find( n.name() );
+ if( it == mod->m_namespace_items.end() ) {
+ ERROR(sp, E0000, "Couldn't find path component '" << n.name() << "' of " << path);
+ }
+ const auto& name_ref = it->second;
+
+ TU_MATCH_DEF(::AST::PathBinding, (name_ref.path.binding()), (e),
+ (
+ ERROR(sp, E0000, "Encountered non-namespace item '" << n.name() << "' ("<<name_ref.path<<") in path " << path);
+ ),
+ (Trait,
+ auto trait_path = ::AST::Path(name_ref.path);
+ if( n.args().size() )
+ trait_path.nodes().back().args() = mv$(n.args());
+ auto new_path = ::AST::Path(::AST::Path::TagUfcs(), ::TypeRef(), mv$(trait_path));
+ for( unsigned int j = i+1; j < path_abs.nodes.size(); j ++ )
+ new_path.nodes().push_back( mv$(path_abs.nodes[j]) );
+
+ path = mv$(new_path);
+ return Resolve_Absolute_Path_BindUFCS(context, sp, mode, path);
+ ),
+ (Enum,
+ if( name_ref.is_import ) {
+ TODO(sp, "Replace path component with new path - " << path << "[.."<<i<<"] with " << name_ref.path);
+ }
+ else {
+ const auto& last_node = path_abs.nodes.back();
+ for( const auto& var : e.enum_->variants() ) {
+ if( var.m_name == last_node.name() ) {
+
+ if( i != path_abs.nodes.size() - 2 ) {
+ ERROR(sp, E0000, "Unexpected enum in path " << path);
+ }
+ // NOTE: Type parameters for enums go after the _variant_
+ if( n.args().size() ) {
+ ERROR(sp, E0000, "Type parameters were not expected here (enum params go on the variant)");
+ }
+
+ path.bind_enum_var(*e.enum_, var.m_name);
+ return;
+ }
+ }
+
+ auto type_path = ::AST::Path(name_ref.path);
+ if( n.args().size() )
+ type_path.nodes().back().args() = mv$(n.args());
+ auto new_path = ::AST::Path(::AST::Path::TagUfcs(), ::TypeRef(sp, mv$(type_path)), ::AST::Path());
+ for( unsigned int j = i+1; j < path_abs.nodes.size(); j ++ )
+ new_path.nodes().push_back( mv$(path_abs.nodes[j]) );
+
+ path = mv$(new_path);
+ return Resolve_Absolute_Path_BindUFCS(context, sp, mode, path);
+ }
+ ),
+ (Struct,
+ auto type_path = ::AST::Path(name_ref.path);
+ if( n.args().size() )
+ type_path.nodes().back().args() = mv$(n.args());
+ auto new_path = ::AST::Path(::AST::Path::TagUfcs(), ::TypeRef(sp, mv$(type_path)), ::AST::Path());
+ for( unsigned int j = i+1; j < path_abs.nodes.size(); j ++ )
+ new_path.nodes().push_back( mv$(path_abs.nodes[j]) );
+
+ path = mv$(new_path);
+ return Resolve_Absolute_Path_BindUFCS(context, sp, mode, path);
+ ),
+ (Module,
+ if( name_ref.is_import ) {
+ TODO(sp, "Replace path component with new path - " << path << "[.."<<i<<"] with " << name_ref.path);
+ }
+ else {
+ mod = e.module_;
+ }
+ )
+ )
+ }
+ }
+
+ // Set binding to binding of node in last module
+ ::AST::Path tmp;
+ if( ! Context::lookup_in_mod(*mod, path_abs.nodes.back().name(), mode, tmp) ) {
+ ERROR(sp, E0000, "Couldn't find path component '" << path_abs.nodes.back().name() << "' of " << path);
+ }
+ assert( ! tmp.binding().is_Unbound() );
+
+ path.bind( tmp.binding().clone() );
+}
+
void Resolve_Absolute_Path(/*const*/ Context& context, const Span& sp, Context::LookupMode mode, ::AST::Path& path)
{
- DEBUG("mode = " << mode << ", path = " << path);
+ TRACE_FUNCTION_F("mode = " << mode << ", path = " << path);
TU_MATCH(::AST::Path::Class, (path.m_class), (e),
(Invalid,
@@ -428,12 +630,12 @@ void Resolve_Absolute_Path(/*const*/ Context& context, const Span& sp, Context::
else {
// Look up value
auto p = context.lookup(sp, e.nodes[0].name(), mode);
- DEBUG("Found val - " << p);
+ DEBUG("Found val - " << p << " for " << path);
path = mv$(p);
}
if( !path.is_trivial() )
- Resolve_Absolute_PathNodes(context, Span(), path.nodes());
+ Resolve_Absolute_PathNodes(context, sp, path.nodes());
),
(Self,
DEBUG("- Self");
@@ -458,27 +660,29 @@ void Resolve_Absolute_Path(/*const*/ Context& context, const Span& sp, Context::
// TODO: Resolve to the actual item?
if( !path.is_trivial() )
- Resolve_Absolute_PathNodes(context, Span(), np_nodes);
+ Resolve_Absolute_PathNodes(context, sp, np_nodes);
path = mv$(np);
),
(Absolute,
DEBUG("- Absolute");
// Nothing to do (TODO: Bind?)
- Resolve_Absolute_PathNodes(context, Span(), e.nodes);
+ Resolve_Absolute_PathNodes(context, sp, e.nodes);
),
(UFCS,
DEBUG("- UFCS");
Resolve_Absolute_Type(context, *e.type);
if( e.trait ) {
- Resolve_Absolute_Path(context, Span(), Context::LookupMode::Type, *e.trait);
+ Resolve_Absolute_Path(context, sp, Context::LookupMode::Type, *e.trait);
}
- Resolve_Absolute_PathNodes(context, Span(), e.nodes);
+ Resolve_Absolute_PathNodes(context, sp, e.nodes);
)
)
- #if 0
+ // TODO: Should this be deferred until the HIR?
+ // - Doing it here so the HIR lowering has a bit more information
+ // - Also handles splitting "absolute" paths into UFCS
TU_MATCH_DEF(::AST::Path::Class, (path.m_class), (e),
(
BUG(sp, "Path wasn't absolutised correctly");
@@ -487,20 +691,17 @@ void Resolve_Absolute_Path(/*const*/ Context& context, const Span& sp, Context::
// TODO: Ensure that local paths are bound to the variable/type index
),
(Absolute,
- if( e.crate != "" ) {
- // TODO: Handle items from other crates (back-converting HIR paths)
- }
- TODO(sp, "Bind absolute paths to relevant items (and expand)");
+ Resolve_Absolute_Path_BindAbsolute(context, sp, mode, path);
),
(UFCS,
- // TODO: Resolve UFCS to item class (if possible)
+ Resolve_Absolute_Path_BindUFCS(context, sp, mode, path);
)
)
- #endif
}
void Resolve_Absolute_Type(Context& context, TypeRef& type)
{
+ TRACE_FUNCTION_F("type = " << type);
const auto& sp = type.span();
TU_MATCH(TypeData, (type.m_data), (e),
(None,
@@ -544,6 +745,13 @@ void Resolve_Absolute_Type(Context& context, TypeRef& type)
),
(Path,
Resolve_Absolute_Path(context, type.span(), Context::LookupMode::Type, e.path);
+ TU_IFLET(::AST::Path::Class, e.path.m_class, UFCS, ufcs,
+ if( ufcs.nodes.size() == 0 && ! ufcs.trait ) {
+ type = mv$(*ufcs.type);
+ return ;
+ }
+ assert( ufcs.nodes.size() == 1);
+ )
),
(TraitObject,
//context.push_lifetimes( e.hrls );
diff --git a/src/resolve/index.cpp b/src/resolve/index.cpp
index b98c3b8e..0155455d 100644
--- a/src/resolve/index.cpp
+++ b/src/resolve/index.cpp
@@ -42,7 +42,8 @@ void _add_item(AST::Module& mod, IndexName location, const ::std::string& name,
DEBUG("Add " << location << " item '" << name << "': " << ir);
auto& list = get_mod_index(mod, location);
- if( false == list.insert(::std::make_pair(name, ::AST::Module::IndexEnt { is_pub, mv$(ir) } )).second )
+ bool was_import = (ir != mod.path() + name);
+ if( false == list.insert(::std::make_pair(name, ::AST::Module::IndexEnt { is_pub, was_import, mv$(ir) } )).second )
{
if( error_on_collision )
{
diff --git a/src/resolve/use.cpp b/src/resolve/use.cpp
index 2d86be13..2ebdc058 100644
--- a/src/resolve/use.cpp
+++ b/src/resolve/use.cpp
@@ -35,7 +35,17 @@ void Resolve_Use(::AST::Crate& crate)
return base_path + path;
),
(Self,
- return base_path + path;
+ // EVIL HACK: If the current module is an anon module, refer to the parent
+ if( base_path.nodes().back().name()[0] == '#' ) {
+ AST::Path np("", {});
+ for( unsigned int i = 0; i < base_path.nodes().size() - 1; i ++ )
+ np.nodes().push_back( base_path.nodes()[i] );
+ np += path;
+ return np;
+ }
+ else {
+ return base_path + path;
+ }
),
(Super,
assert(e.count >= 1);