diff options
author | John Hodge <tpg@mutabah.net> | 2016-03-30 13:19:02 +0800 |
---|---|---|
committer | John Hodge <tpg@mutabah.net> | 2016-03-30 13:19:02 +0800 |
commit | 8f77e93357eeb45a31b14af91cd749a379da5179 (patch) | |
tree | 892e7362210557ef97cf3928fe84e75c32b76311 /src | |
parent | 210b1a17340e3ed3a8da9c29588f5a0db0d5e435 (diff) | |
download | mrust-8f77e93357eeb45a31b14af91cd749a379da5179.tar.gz |
Resolve - Working on new `use` resolution code
Diffstat (limited to 'src')
-rw-r--r-- | src/ast/path.cpp | 4 | ||||
-rw-r--r-- | src/ast/path.hpp | 12 | ||||
-rw-r--r-- | src/expand/mod.cpp | 2 | ||||
-rw-r--r-- | src/hir/from_ast.cpp | 2 | ||||
-rw-r--r-- | src/include/main_bindings.hpp | 1 | ||||
-rw-r--r-- | src/main.cpp | 5 | ||||
-rw-r--r-- | src/resolve/use.cpp | 223 |
7 files changed, 245 insertions, 4 deletions
diff --git a/src/ast/path.cpp b/src/ast/path.cpp index 032c57b4..60dee881 100644 --- a/src/ast/path.cpp +++ b/src/ast/path.cpp @@ -31,6 +31,10 @@ namespace AST { ) return os; } +PathBinding PathBinding::clone() const +{ + assert(!"TODO: PathBinding::clone()"); +} // --- AST::PathNode PathNode::PathNode(::std::string name, ::std::vector<TypeRef> args): diff --git a/src/ast/path.hpp b/src/ast/path.hpp index d2f6302e..bf0ff59a 100644 --- a/src/ast/path.hpp +++ b/src/ast/path.hpp @@ -28,7 +28,7 @@ class Trait; class Static; class Function; -TAGGED_UNION(PathBinding, Unbound, +TAGGED_UNION_EX(PathBinding, (), Unbound, ( (Unbound, struct { }), (Module, struct { @@ -72,6 +72,12 @@ TAGGED_UNION(PathBinding, Unbound, (Variable, struct { unsigned int slot; }) + ), + (), (), + ( + public: + PathBinding clone() const; + ) ); extern ::std::ostream& operator<<(::std::ostream& os, const PathBinding& x); @@ -343,6 +349,10 @@ public: void bind_type_alias(const TypeAlias& ent, const ::std::vector<TypeRef>& args={}) { m_binding = PathBinding::make_TypeAlias({&ent}); } + + void bind(::AST::PathBinding pb) { + m_binding = mv$(pb); + } }; } // namespace AST diff --git a/src/expand/mod.cpp b/src/expand/mod.cpp index 1fdf56c1..d62a20db 100644 --- a/src/expand/mod.cpp +++ b/src/expand/mod.cpp @@ -482,7 +482,7 @@ void Expand_Mod(bool is_early, ::AST::Crate& crate, LList<const AST::Module*> mo DEBUG("Items"); for( auto& i : mod.items() ) { - DEBUG("- " << i.name << " :: " << i.data.attrs); + DEBUG("- " << i.name << " (" << ::AST::Item::tag_to_str(i.data.tag()) << ") :: " << i.data.attrs); ::AST::Path path = modpath + i.name; auto attrs = mv$(i.data.attrs); diff --git a/src/hir/from_ast.cpp b/src/hir/from_ast.cpp index 7bf0fa74..4da703f9 100644 --- a/src/hir/from_ast.cpp +++ b/src/hir/from_ast.cpp @@ -8,7 +8,7 @@ /// \brief Converts the AST into HIR format /// /// - Removes all possibility for unexpanded macros -/// - Performs name resolution and partial UFCS conversion? (TODO: This should be done on the AST, as it requires two passes with state) +/// - Performs name resolution and partial UFCS conversion? /// - Performs desugaring of for/if-let/while-let/... ::HIR::Crate LowerHIR_FromAST(::AST::Crate crate) { diff --git a/src/include/main_bindings.hpp b/src/include/main_bindings.hpp index 016b2f27..afc6dea5 100644 --- a/src/include/main_bindings.hpp +++ b/src/include/main_bindings.hpp @@ -19,6 +19,7 @@ extern void Expand(::AST::Crate& crate); /// Process #[] decorators extern void Process_Decorators(AST::Crate& crate); +extern void Resolve_Use(::AST::Crate& crate); /// Resolve all in-text paths to absolute variants extern void ResolvePaths(AST::Crate& crate); diff --git a/src/main.cpp b/src/main.cpp index a2a6f26f..38b200d0 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -22,7 +22,7 @@ int g_debug_indent_level = 0; bool debug_enabled()
{
- return true;
+ return g_cur_phase != "Parse";
}
::std::ostream& debug_output(int indent, const char* function)
{
@@ -116,6 +116,9 @@ int main(int argc, char *argv[]) // - This does name checking on types and free functions.
// - Resolves all identifiers/paths to references
CompilePhaseV("Resolve", [&]() {
+ Resolve_Use(crate);
+ //Resolve_Absolutise(crate);
+ //Resolve_UfcsPaths(crate);
ResolvePaths(crate);
});
diff --git a/src/resolve/use.cpp b/src/resolve/use.cpp new file mode 100644 index 00000000..254a2374 --- /dev/null +++ b/src/resolve/use.cpp @@ -0,0 +1,223 @@ +/* + * Absolutise and check all 'use' statements + */ +#include <main_bindings.hpp> +#include <ast/crate.hpp> +#include <ast/ast.hpp> + +void Resolve_Use_Mod(const ::AST::Crate& crate, ::AST::Module& mod, ::AST::Path path); +::AST::Path Resolve_Use_AbsolutisePath(const ::AST::Path& base_path, ::AST::Path path); +::AST::PathBinding Resolve_Use_GetBinding(const Span& span, const ::AST::Crate& crate, const ::AST::Path& path); + +void Resolve_Use(::AST::Crate& crate) +{ + Resolve_Use_Mod(crate, crate.m_root_module, ::AST::Path("", {})); +} + +::AST::Path Resolve_Use_AbsolutisePath(const Span& span, const ::AST::Path& base_path, ::AST::Path path) +{ + TU_MATCH(::AST::Path::Class, (path.m_class), (e), + (Invalid, + // Should never happen + BUG(span, "Invalid path class encountered"); + ), + (Local, + // Wait, how is this already known? + BUG(span, "Local path class in use statement"); + ), + (UFCS, + // Wait, how is this already known? + BUG(span, "UFCS path class in use statement"); + ), + (Relative, + return base_path + path; + ), + (Self, + return base_path + path; + ), + (Super, + assert(e.count >= 1); + AST::Path np(base_path.crate(), {}); + if( e.count > base_path.nodes().size() ) { + ERROR(span, E0000, "Too many `super` components"); + } + for( unsigned int i = 0; i < base_path.nodes().size() - e.count; i ++ ) + np.nodes().push_back( base_path.nodes()[i] ); + np += path; + return np; + ), + (Absolute, + // Leave as is + return path; + ) + ) + throw "BUG: Reached end of Resolve_Use_AbsolutisePath"; +} + +void Resolve_Use_Mod(const ::AST::Crate& crate, ::AST::Module& mod, ::AST::Path path) +{ + TRACE_FUNCTION_F("path = " << path << ", mod.path() = " << mod.path()); + for(auto& use_stmt : mod.imports()) + { + const Span span; + use_stmt.data = Resolve_Use_AbsolutisePath(span, path, mv$(use_stmt.data)); + if( !use_stmt.data.m_class.is_Absolute() ) + BUG(span, "Use path is not absolute after absolutisation"); + + // TODO: Is this a valid assertion? + if( use_stmt.data.crate() != "" ) + BUG(span, "Use path crate was set before resolve"); + + use_stmt.data.bind( Resolve_Use_GetBinding(span, crate, use_stmt.data) ); + + // - If doing a glob, ensure the item type is valid + if( use_stmt.name == "" ) + { + TU_MATCH_DEF(::AST::PathBinding, (use_stmt.data.binding()), (e), + ( + ERROR(span, E0000, "Wildcard import of invalid item type"); + ), + (Enum, + ), + (Module, + ) + ) + } + } + + for(auto& i : mod.items()) + { + if( i.data.is_Module() ) + { + Resolve_Use_Mod(crate, i.data.as_Module(), path + i.name); + } + } +} + +::AST::PathBinding Resolve_Use_GetBinding_Mod(const Span& span, const ::AST::Crate& crate, const ::AST::Module& mod, const ::std::string& des_item_name) +{ + for( const auto& item : mod.items() ) + { + if( item.data.is_None() ) + continue ; + + if( item.name == des_item_name ) { + TU_MATCH(::AST::Item, (item.data), (e), + (None, + // IMPOSSIBLe - Handled above + ), + (Crate, + //return ::AST::PathBinding::make_Crate({&e}); + TODO(span, "Handle importing from a crate"); + ), + (Type, + return ::AST::PathBinding::make_TypeAlias({&e}); + ), + (Trait, + return ::AST::PathBinding::make_Trait({&e}); + ), + + (Function, + return ::AST::PathBinding::make_Function({&e}); + ), + (Static, + return ::AST::PathBinding::make_Static({&e}); + ), + (Struct, + return ::AST::PathBinding::make_Struct({&e}); + ), + (Enum, + return ::AST::PathBinding::make_Enum({&e}); + ), + (Module, + return ::AST::PathBinding::make_Module({&e}); + ) + ) + break ; + } + } + + // Imports + for( const auto& imp : mod.imports() ) + { + if( imp.name == des_item_name ) { + DEBUG("- Named import " << imp.name << " = " << imp.data); + if( imp.data.binding().is_Unbound() ) { + DEBUG(" > Needs resolve"); + const Span sp2; + return Resolve_Use_GetBinding(sp2, crate, Resolve_Use_AbsolutisePath(sp2, mod.path(), imp.data)); + } + else { + return imp.data.binding().clone(); + } + } + if( imp.is_pub && imp.name == "" ) { + const Span sp2; + // INEFFICIENT! Resolves and throws away the result (because we can't/shouldn't mutate here) + ::AST::PathBinding binding_; + const auto* binding = &imp.data.binding(); + if( binding->is_Unbound() ) { + DEBUG("Temp resolving wildcard " << imp.data); + binding_ = Resolve_Use_GetBinding(sp2, crate, Resolve_Use_AbsolutisePath(sp2, mod.path(), imp.data)); + binding = &binding_; + } + + TU_MATCH_DEF(::AST::PathBinding, ((*binding)), (e), + ( + BUG(sp2, "Wildcard import expanded to an invalid item class"); + ), + (Module, + TODO(span, "Look up wildcard in module"); + ), + (Enum, + TODO(span, "Look up wildcard in enum"); + ) + ) + } + } + + ERROR(span, E0000, "Could not find node '" << des_item_name << "' in module " << mod.path()); +} + +::AST::PathBinding Resolve_Use_GetBinding(const Span& span, const ::AST::Crate& crate, const ::AST::Path& path) +{ + 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()); + TU_MATCH_DEF(::AST::PathBinding, (b), (e), + ( + ERROR(span, E0000, "Unexpected item type in import"); + ), + (Enum, + const auto& enum_ = *e.enum_; + i += 1; + if( i != nodes.size() - 1 ) { + ERROR(span, E0000, "Encountered enum at unexpected location in import"); + } + + const auto& node2 = nodes[i]; + int variant_index = -1; + for( unsigned int j = 0; j < enum_.variants().size(); j ++ ) + { + if( enum_.variants()[j].m_name == node2.name() ) { + variant_index = j; + break ; + } + } + if( variant_index < 0 ) { + ERROR(span, E0000, "Unknown enum variant '" << node2.name() << "'"); + } + + return ::AST::PathBinding::make_EnumVar({&enum_, static_cast<unsigned int>(variant_index)}); + ), + (Module, + mod = e.module_; + ) + ) + } + + return Resolve_Use_GetBinding_Mod(span, crate, *mod, nodes.back().name()); +} + |