summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Hodge <tpg@mutabah.net>2016-04-02 12:06:07 +0800
committerJohn Hodge <tpg@mutabah.net>2016-04-02 12:06:07 +0800
commitc47ac13386ac5a597ec822ea6d73bf62ca009954 (patch)
tree7fe7dd24850cabf5fafb0a79b1b2531104d35345
parentd5b39c4fcf80a1e84aee6080351dc990c0aa8963 (diff)
downloadmrust-c47ac13386ac5a597ec822ea6d73bf62ca009954.tar.gz
Resolve - Start building an index of names avaliable in each module
-rw-r--r--Makefile2
-rw-r--r--src/ast/ast.hpp108
-rw-r--r--src/ast/macro.hpp3
-rw-r--r--src/expand/mod.cpp10
-rw-r--r--src/include/main_bindings.hpp1
-rw-r--r--src/main.cpp3
-rw-r--r--src/resolve/index.cpp123
-rw-r--r--src/resolve/use.cpp16
8 files changed, 223 insertions, 43 deletions
diff --git a/Makefile b/Makefile
index ad44ec68..c671020e 100644
--- a/Makefile
+++ b/Makefile
@@ -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() )