From c47ac13386ac5a597ec822ea6d73bf62ca009954 Mon Sep 17 00:00:00 2001 From: John Hodge Date: Sat, 2 Apr 2016 12:06:07 +0800 Subject: Resolve - Start building an index of names avaliable in each module --- src/ast/ast.hpp | 108 +++++++++++++++++++++++-------------- src/ast/macro.hpp | 3 ++ src/expand/mod.cpp | 10 ++++ src/include/main_bindings.hpp | 1 + src/main.cpp | 3 +- src/resolve/index.cpp | 123 ++++++++++++++++++++++++++++++++++++++++++ src/resolve/use.cpp | 16 ++++++ 7 files changed, 222 insertions(+), 42 deletions(-) create mode 100644 src/resolve/index.cpp (limited to 'src') diff --git a/src/ast/ast.hpp b/src/ast/ast.hpp index 08e4b6a1..c86efe0f 100644 --- a/src/ast/ast.hpp +++ b/src/ast/ast.hpp @@ -14,6 +14,7 @@ #include "../coretypes.hpp" #include #include +#include #include #include "../parse/tokentree.hpp" @@ -461,6 +462,66 @@ typedef void fcn_visitor_t(const AST::Crate& crate, const AST::Module& mod, Func class Module: public Serialisable { +public: + class ItemRef + { + public: + enum Type + { + TAG_None, + TAG_Module, + TAG_Crate, + TAG_TypeAlias, + TAG_Function, + TAG_Trait, + TAG_Struct, + TAG_Enum, + TAG_Static, + TAG_Use, + }; + private: + Type m_type; + const void* m_ref; + public: + ItemRef(): m_type(TAG_None) {} + + Type tag() const { return m_type; } + bool is_None() const { return m_type == TAG_None; } + const Type& as_None() const { return m_type; } // HACK: Returns &Type in place of &void + #define _(ty,ident) \ + ItemRef(const ty& ref): m_type(TAG_##ident), m_ref(&ref) {} \ + bool is_##ident() const { return m_type == TAG_##ident; } \ + const ty& as_##ident() const { assert(m_type == TAG_##ident); return *(const ty*)m_ref; } + _(AST::Module, Module) + _(::std::string, Crate) + _(AST::TypeAlias, TypeAlias) + _(AST::Function, Function) + _(AST::Trait, Trait) + _(AST::Struct, Struct) + _(AST::Enum, Enum) + _(AST::Static, Static) + _(AST::Named, Use) + #undef _ + friend ::std::ostream& operator<<(::std::ostream& os, const ItemRef& x) { + switch(x.m_type) + { + #define _(ident) case TAG_##ident: return os << "ItemRef(" #ident ")"; + _(None) + _(Module) + _(Crate) + _(TypeAlias) + _(Function) + _(Trait) + _(Struct) + _(Enum) + _(Static) + _(Use) + #undef _ + } + throw ""; + } + }; +private: typedef ::std::vector< Named > itemlist_use_t; ::AST::Path m_my_path; @@ -481,9 +542,14 @@ class Module: // --- Runtime caches and state --- ::std::vector m_anon_modules; - + ::std::vector< NamedNS > m_macro_import_res; // Vec of imported macros (not serialised) ::std::vector< Named > m_macros; + +public: + ::std::unordered_map< ::std::string, ::std::pair > m_type_items; + ::std::unordered_map< ::std::string, ::std::pair > m_value_items; + public: Module() {} Module(::AST::Path path): @@ -541,46 +607,6 @@ public: void iterate_functions(fcn_visitor_t* visitor, const Crate& crate); const ::AST::Path& path() const { return m_my_path; } - class ItemRef - { - public: - enum Type - { - TAG_None, - TAG_Module, - TAG_Crate, - TAG_TypeAlias, - TAG_Function, - TAG_Trait, - TAG_Struct, - TAG_Enum, - TAG_Static, - TAG_Use, - }; - private: - Type m_type; - const void* m_ref; - public: - ItemRef(): m_type(TAG_None) {} - - Type tag() const { return m_type; } - bool is_None() const { return m_type == TAG_None; } - const Type& as_None() const { return m_type; } // HACK: Returns &Type in place of &void - #define _(ty,ident) \ - ItemRef(const ty& ref): m_type(TAG_##ident), m_ref(&ref) {} \ - bool is_##ident() const { return m_type == TAG_##ident; } \ - const ty& as_##ident() const { assert(m_type == TAG_##ident); return *(const ty*)m_ref; } - _(AST::Module, Module) - _(::std::string, Crate) - _(AST::TypeAlias, TypeAlias) - _(AST::Function, Function) - _(AST::Trait, Trait) - _(AST::Struct, Struct) - _(AST::Enum, Enum) - _(AST::Static, Static) - _(AST::Named, Use) - #undef _ - }; ItemRef find_item(const ::std::string& needle, bool allow_leaves = true, bool ignore_private_wildcard = true) const; ::std::vector>& items() { return m_items; } diff --git a/src/ast/macro.hpp b/src/ast/macro.hpp index 4804f52b..733023ca 100644 --- a/src/ast/macro.hpp +++ b/src/ast/macro.hpp @@ -42,6 +42,9 @@ public: m_ident = ""; m_input = TokenTree(); } + + ::AST::MetaItems& attrs() { return m_attrs; } + const ::AST::MetaItems& attrs() const { return m_attrs; } const Span& span() const { return m_span; } const ::std::string& name() const { return m_macro_name; } diff --git a/src/expand/mod.cpp b/src/expand/mod.cpp index d62a20db..cfbfc2e7 100644 --- a/src/expand/mod.cpp +++ b/src/expand/mod.cpp @@ -69,6 +69,10 @@ void Expand_Attrs(const ::AST::MetaItems& attrs, AttrStage stage, ::AST::Crate& Span mi_span, const ::std::string& name, const ::std::string& input_ident, const TokenTree& input_tt ) { + if( name == "" ) { + return ::std::unique_ptr(); + } + for( const auto& m : g_macros ) { if( name == m.first && m.second->expand_early() == is_early ) @@ -456,15 +460,20 @@ void Expand_Mod(bool is_early, ::AST::Crate& crate, LList mo { auto& mi = mod.macro_invs()[i]; DEBUG("> Macro invoke '"< mo Parse_ModRoot_Items(*ttl, mod, false, "-"); // - Any new macro invocations ends up at the end of the list and handled } + } } diff --git a/src/include/main_bindings.hpp b/src/include/main_bindings.hpp index afc6dea5..bd44bae0 100644 --- a/src/include/main_bindings.hpp +++ b/src/include/main_bindings.hpp @@ -20,6 +20,7 @@ extern void Expand(::AST::Crate& crate); extern void Process_Decorators(AST::Crate& crate); extern void Resolve_Use(::AST::Crate& crate); +extern void Resolve_Index(::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 38b200d0..34da5cb5 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -116,7 +116,8 @@ 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_Use(crate); // - Absolutise and resolve use statements + Resolve_Index(crate); // - Build up a per-module index of avalable names (faster and simpler later resolve) //Resolve_Absolutise(crate); //Resolve_UfcsPaths(crate); ResolvePaths(crate); diff --git a/src/resolve/index.cpp b/src/resolve/index.cpp new file mode 100644 index 00000000..4b6964fb --- /dev/null +++ b/src/resolve/index.cpp @@ -0,0 +1,123 @@ +/* + * Build up a name index in all modules (optimising lookups in later stages) + */ +#include +#include +#include + +void _add_item(AST::Module& mod, bool is_type, const ::std::string& name, bool is_pub, ::AST::PathBinding ir) +{ + DEBUG("Add " << (is_type ? "type" : "value") << " item '" << name << "': " << ir); + auto& list = (is_type ? mod.m_type_items : mod.m_value_items); + + if( false == list.insert( ::std::make_pair(name, ::std::make_pair(is_pub, mv$(ir))) ).second ) + { + ERROR(Span(), E0000, "Duplicate definition of name '" << name << "' in " << (is_type ? "type" : "value") << " scope (" << mod.path() << ")"); + } +} +void _add_item_type(AST::Module& mod, const ::std::string& name, bool is_pub, ::AST::PathBinding ir) +{ + _add_item(mod, true, name, is_pub, mv$(ir)); +} +void _add_item_value(AST::Module& mod, const ::std::string& name, bool is_pub, ::AST::PathBinding ir) +{ + _add_item(mod, false, name, is_pub, mv$(ir)); +} + +void Resolve_Index_Module(AST::Module& mod) +{ + TRACE_FUNCTION_F("mod = " << mod.path()); + for( const auto& i : mod.items() ) + { + TU_MATCH(AST::Item, (i.data), (e), + (None, + ), + // - Types/modules only + (Module, + _add_item_type(mod, i.name, i.is_pub, ::AST::PathBinding::make_Module({&e})); + ), + (Crate, + TODO(Span(), "Crate in Resolve_Index_Module"); + //_add_item_type(mod, i.name, i.is_pub, ::AST::PathBinding::make_Crate(e)); + ), + (Enum, + _add_item_type(mod, i.name, i.is_pub, ::AST::PathBinding::make_Enum({&e})); + ), + (Trait, + _add_item_type(mod, i.name, i.is_pub, ::AST::PathBinding::make_Trait({&e})); + ), + (Type, + _add_item_type(mod, i.name, i.is_pub, ::AST::PathBinding::make_TypeAlias({&e})); + ), + // - Mixed + (Struct, + _add_item_type(mod, i.name, i.is_pub, ::AST::PathBinding::make_Struct({&e})); + if( e.m_data.is_Struct() ) { + _add_item_value(mod, i.name, i.is_pub, ::AST::PathBinding::make_Struct({&e})); + } + ), + // - Values only + (Function, + _add_item_value(mod, i.name, i.is_pub, ::AST::PathBinding::make_Function({&e})); + ), + (Static, + _add_item_value(mod, i.name, i.is_pub, ::AST::PathBinding::make_Static({&e})); + ) + ) + } + + for( const auto& i : mod.imports() ) + { + 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"); + ), + (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"); + ), + + (Module, _add_item_type(mod, i.name, i.is_pub, b.clone()); ), + //(Crate, _add_item_type(mod, i.name, i.is_pub, b.clone()); ), + (Enum, _add_item_type(mod, i.name, i.is_pub, b.clone()); ), + (Trait, _add_item_type(mod, i.name, i.is_pub, b.clone()); ), + (TypeAlias, _add_item_type(mod, i.name, i.is_pub, b.clone()); ), + + (Struct, + _add_item_type(mod, i.name, i.is_pub, b.clone()); + ), + (Static , _add_item_value(mod, i.name, i.is_pub, b.clone()); ), + (Function, _add_item_value(mod, i.name, i.is_pub, b.clone()); ), + (EnumVar , _add_item_value(mod, i.name, i.is_pub, b.clone()); ) + ) + } + } + + for( auto& i : mod.items() ) + { + TU_MATCH_DEF(AST::Item, (i.data), (e), + ( + ), + (Module, + Resolve_Index_Module(e); + ) + ) + } +} + +void Resolve_Index(AST::Crate& crate) +{ + Resolve_Index_Module(crate.m_root_module); +} diff --git a/src/resolve/use.cpp b/src/resolve/use.cpp index 43bd074f..6eb837e6 100644 --- a/src/resolve/use.cpp +++ b/src/resolve/use.cpp @@ -96,6 +96,22 @@ 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) { + // HACK - Catch the possibiliy of a name clash (not sure if this is really an erro) + { + bool found = false; + for( const auto& item : mod.items() ) + { + if( item.data.is_None() ) + continue ; + if( item.name == des_item_name ) { + if( found ) { + TODO(span, "Duplicate name found resolving use statement searching in module " << mod.path()); + } + found = true; + } + } + } + for( const auto& item : mod.items() ) { if( item.data.is_None() ) -- cgit v1.2.3