diff options
author | John Hodge <tpg@mutabah.net> | 2016-04-02 12:06:07 +0800 |
---|---|---|
committer | John Hodge <tpg@mutabah.net> | 2016-04-02 12:06:07 +0800 |
commit | c47ac13386ac5a597ec822ea6d73bf62ca009954 (patch) | |
tree | 7fe7dd24850cabf5fafb0a79b1b2531104d35345 | |
parent | d5b39c4fcf80a1e84aee6080351dc990c0aa8963 (diff) | |
download | mrust-c47ac13386ac5a597ec822ea6d73bf62ca009954.tar.gz |
Resolve - Start building an index of names avaliable in each module
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | src/ast/ast.hpp | 108 | ||||
-rw-r--r-- | src/ast/macro.hpp | 3 | ||||
-rw-r--r-- | src/expand/mod.cpp | 10 | ||||
-rw-r--r-- | src/include/main_bindings.hpp | 1 | ||||
-rw-r--r-- | src/main.cpp | 3 | ||||
-rw-r--r-- | src/resolve/index.cpp | 123 | ||||
-rw-r--r-- | src/resolve/use.cpp | 16 |
8 files changed, 223 insertions, 43 deletions
@@ -34,7 +34,7 @@ OBJ += expand/format_args.o OBJ += expand/concat.o expand/stringify.o expand/file_line.o OBJ += expand/derive.o expand/lang_item.o OBJ += expand/std_prelude.o -OBJ += resolve/use.o +OBJ += resolve/use.o resolve/index.o OBJ += hir/from_ast.o OBJ += dump_as_rust.o OBJ += convert/ast_iterate.o 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 <memory>
#include <map>
+#include <unordered_map>
#include <algorithm>
#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<UseStmt>, 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<UseStmt> > itemlist_use_t;
::AST::Path m_my_path;
@@ -481,9 +542,14 @@ class Module: // --- Runtime caches and state ---
::std::vector<Module*> m_anon_modules;
-
+
::std::vector< NamedNS<const MacroRules*> > m_macro_import_res; // Vec of imported macros (not serialised)
::std::vector< Named<MacroRules> > m_macros;
+
+public:
+ ::std::unordered_map< ::std::string, ::std::pair<bool, PathBinding> > m_type_items;
+ ::std::unordered_map< ::std::string, ::std::pair<bool, PathBinding> > 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<UseStmt>, Use)
- #undef _
- };
ItemRef find_item(const ::std::string& needle, bool allow_leaves = true, bool ignore_private_wildcard = true) const;
::std::vector<Named<Item>>& 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<TokenStream>(); + } + 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<const AST::Module*> mo { auto& mi = mod.macro_invs()[i]; DEBUG("> Macro invoke '"<<mi.name()<<"'"); + if( mi.name() != "" ) { // Move out of the module to avoid invalidation if a new macro invocation is added auto mi_owned = mv$(mi); + auto& attrs = mi.attrs(); + Expand_Attrs(attrs, stage_pre(is_early), [&](const auto& d, const auto& a){ d.handle(a, crate, mi_owned); }); + auto ttl = Expand_Macro(is_early, crate, modstack, mod, mi_owned); if( ! ttl.get() ) { + Expand_Attrs(attrs, stage_post(is_early), [&](const auto& d, const auto& a){ d.handle(a, crate, mi_owned); }); // - Return ownership to the list mod.macro_invs()[i] = mv$(mi_owned); } @@ -475,6 +484,7 @@ void Expand_Mod(bool is_early, ::AST::Crate& crate, LList<const AST::Module*> 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 <ast/ast.hpp> +#include <ast/crate.hpp> +#include <main_bindings.hpp> + +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() ) |