diff options
Diffstat (limited to 'src/ast')
-rw-r--r-- | src/ast/ast.cpp | 15 | ||||
-rw-r--r-- | src/ast/path.cpp | 34 | ||||
-rw-r--r-- | src/ast/path.hpp | 162 |
3 files changed, 116 insertions, 95 deletions
diff --git a/src/ast/ast.cpp b/src/ast/ast.cpp index 11632996..efd1e830 100644 --- a/src/ast/ast.cpp +++ b/src/ast/ast.cpp @@ -500,7 +500,8 @@ Module::ItemRef Module::find_item(const ::std::string& needle, bool allow_leaves //if( &imp.data == this )
// continue ;
//
- if( !imp.data.is_bound() )
+ const auto& binding = imp.data.binding();
+ if( !binding.is_bound() )
{
// not yet bound, so run resolution (recursion)
DEBUG("Recursively resolving pub wildcard use " << imp.data);
@@ -508,13 +509,13 @@ Module::ItemRef Module::find_item(const ::std::string& needle, bool allow_leaves throw ParseError::Todo("Path::resolve() wildcard re-export call resolve");
}
- switch(imp.data.binding_type())
+ switch(binding.type())
{
- case AST::Path::UNBOUND:
+ case AST::PathBinding::UNBOUND:
throw ParseError::BugCheck("Wildcard import path not bound");
// - If it's a module, recurse
- case AST::Path::MODULE: {
- auto rv = imp.data.bound_module().find_item(needle);
+ case AST::PathBinding::MODULE: {
+ auto rv = binding.bound_module().find_item(needle);
if( rv.type() != Module::ItemRef::ITEM_none ) {
// Don't return RV, return the import (so caller can rewrite path if need be)
return ItemRef(imp);
@@ -522,8 +523,8 @@ Module::ItemRef Module::find_item(const ::std::string& needle, bool allow_leaves }
break; }
// - If it's an enum, search for this name and then pass to resolve
- case AST::Path::ENUM: {
- auto& vars = imp.data.bound_enum().variants();
+ case AST::PathBinding::ENUM: {
+ auto& vars = binding.bound_enum().variants();
// Damnit C++ "let it = vars.find(|a| a.name == needle);"
auto it = ::std::find_if(vars.begin(), vars.end(),
[&needle](const EnumVariant& ev) { return ev.m_name == needle; });
diff --git a/src/ast/path.cpp b/src/ast/path.cpp index 9548730e..2cfd6b98 100644 --- a/src/ast/path.cpp +++ b/src/ast/path.cpp @@ -151,8 +151,7 @@ void Path::resolve(const Crate& root_crate) // Make a copy of the path, replace params with it, then replace *this? // - Maybe leave that up to other code? if( is_last ) { - m_binding_type = ALIAS; - m_binding.alias_ = &ta; + m_binding = PathBinding(&ta); goto ret; } else { @@ -165,8 +164,7 @@ void Path::resolve(const Crate& root_crate) const auto& fn = item.unwrap_Function(); DEBUG("Found function"); if( is_last ) { - m_binding_type = FUNCTION; - m_binding.func_ = &fn; + m_binding = PathBinding(&fn); goto ret; } else { @@ -179,13 +177,11 @@ void Path::resolve(const Crate& root_crate) const auto& t = item.unwrap_Trait(); DEBUG("Found trait"); if( is_last ) { - m_binding_type = TRAIT; - m_binding.trait_ = &t; + m_binding = PathBinding(&t); goto ret; } else if( is_sec_last ) { - m_binding_type = TRAIT_METHOD; - m_binding.trait_ = &t; + m_binding = PathBinding(PathBinding::TagItem(), &t); goto ret; } else { @@ -282,7 +278,7 @@ void Path::resolve(const Crate& root_crate) } // We only reach here if the path points to a module - bind_module(*mod); + m_binding = PathBinding(mod); ret: if( slice_from > 0 ) { @@ -291,16 +287,10 @@ ret: } return ; } -void Path::bind_module(const Module& mod) -{ - m_binding_type = MODULE; - m_binding.module_ = &mod; -} void Path::bind_enum(const Enum& ent, const ::std::vector<TypeRef>& args) { DEBUG("Bound to enum"); - m_binding_type = ENUM; - m_binding.enum_ = &ent; + m_binding = PathBinding(&ent); //if( args.size() > 0 ) //{ // if( args.size() != ent.params().size() ) @@ -328,8 +318,7 @@ void Path::bind_enum_var(const Enum& ent, const ::std::string& name, const ::std //} DEBUG("Bound to enum variant '" << name << "' (#" << idx << ")"); - m_binding_type = ENUM_VAR; - m_binding.enumvar = {&ent, idx}; + m_binding = PathBinding(&ent, idx); } void Path::bind_struct(const Struct& ent, const ::std::vector<TypeRef>& args) { @@ -343,19 +332,16 @@ void Path::bind_struct(const Struct& ent, const ::std::vector<TypeRef>& args) //} DEBUG("Bound to struct"); - m_binding_type = STRUCT; - m_binding.struct_ = &ent; + m_binding = PathBinding(&ent); } void Path::bind_struct_member(const Struct& ent, const ::std::vector<TypeRef>& args, const PathNode& member_node) { DEBUG("Binding to struct item. This needs to be deferred"); - m_binding_type = STRUCT_METHOD; - m_binding.struct_ = &ent; + m_binding = PathBinding(PathBinding::TagItem(), &ent); } void Path::bind_static(const Static& ent) { - m_binding_type = STATIC; - m_binding.static_ = &ent; + m_binding = PathBinding(&ent); } diff --git a/src/ast/path.hpp b/src/ast/path.hpp index 03aeab23..b3af8c52 100644 --- a/src/ast/path.hpp +++ b/src/ast/path.hpp @@ -25,6 +25,102 @@ class Trait; class Static; class Function; +//TAGGED_ENUM(Binding, Unbound, +// (BndModule, (const Module* module_; ) ), +// (BndEnum, (const Enum* enum_; ) ), +// (BndStruct, (const Struct* struct_; ) ), +// (BndTrait, (const Trait* trait_; ) ), +// (BndStatic, (const Static* static_; ) ), +// (BndFunction, (const Function* func_; ) ), +// (BndEnumVar, (const Enum* enum_; unsigned int idx; ) ), +// (BndTypeAlias, (const TypeAlias* alias_; ) ), +// (BndStructMethod, (const Struct* struct_; ::std::string name; ) ), +// (BndTraitMethod, (const Trait* struct_; ::std::string name; ) ) +// ); +class PathBinding +{ +public: + enum BindingType { + UNBOUND, + MODULE, + ALIAS, + ENUM, + STRUCT, + TRAIT, + + STRUCT_METHOD, + TRAIT_METHOD, + ENUM_VAR, + FUNCTION, + STATIC, + }; + struct EnumVar { + const Enum* enum_; + unsigned int idx; + }; +private: + BindingType m_binding_type = UNBOUND; + union { + const Module* module_; + const Enum* enum_; + const Struct* struct_; + struct { + const Struct* struct_; + unsigned int idx; + } structitem; + const Trait* trait_; + const Static* static_; + const Function* func_; + EnumVar enumvar_; + const TypeAlias* alias_; + } m_binding; + +public: + PathBinding(): m_binding_type(UNBOUND) {} + + bool is_bound() const { return m_binding_type != UNBOUND; } + BindingType type() const { return m_binding_type; } + #define _(t, n, v)\ + PathBinding(const t* i): m_binding_type(v) { m_binding.n##_ = i; } \ + const t& bound_##n() const { assert(m_binding_type == v); return *m_binding.n##_; } + _(Module, module, MODULE) + _(Trait, trait, TRAIT) + _(Struct, struct, STRUCT) + _(Enum, enum, ENUM) + _(Function, func, FUNCTION) + _(Static, static, STATIC) + _(TypeAlias, alias, ALIAS) + //_(EnumVar, enumvar, ENUM_VAR) + #undef _ + PathBinding(const Enum* enm, unsigned int i): + m_binding_type(ENUM_VAR) + { + m_binding.enumvar_ = {enm, i}; + } + const EnumVar& bound_enumvar() const { assert(m_binding_type == ENUM_VAR); return m_binding.enumvar_; } + + struct TagItem {}; + PathBinding(TagItem, const Trait* t): m_binding_type(TRAIT_METHOD) { m_binding.trait_ = t; } + PathBinding(TagItem, const Struct* i): m_binding_type(STRUCT_METHOD) { m_binding.struct_ = i; } + + friend ::std::ostream& operator<<(::std::ostream& os, const PathBinding& x) { + switch(x.m_binding_type) + { + case UNBOUND: os << "UNBOUND"; break; + case MODULE: os << "Module"; break; + case TRAIT: os << "Trait"; break; + case STRUCT: os << "Struct"; break; + case ENUM: os << "Enum"; break; + case FUNCTION: os << "Function";break; + case STATIC: os << "Static"; break; + case ALIAS: os << "Alias"; break; + case STRUCT_METHOD: os << "StructMethod"; break; + case TRAIT_METHOD: os << "TraitMethod"; break; + case ENUM_VAR: os << "EnumVar(" << x.m_binding.enumvar_.idx << ")"; break; + } + return os; + } +}; class PathNode: public ::Serialisable @@ -48,33 +144,6 @@ public: class Path: public ::Serialisable { -public: - enum BindingType { - UNBOUND, - MODULE, - ALIAS, - ENUM, - STRUCT, - TRAIT, - - STRUCT_METHOD, - TRAIT_METHOD, - ENUM_VAR, - FUNCTION, - STATIC, - }; - //TAGGED_ENUM(Binding, Unbound, - // (BndModule, (const Module* module_; ) ), - // (BndEnum, (const Enum* enum_; ) ), - // (BndStruct, (const Struct* struct_; ) ), - // (BndTrait, (const Trait* trait_; ) ), - // (BndStatic, (const Static* static_; ) ), - // (BndFunction, (const Function* func_; ) ), - // (BndEnumVar, (const Enum* enum_; unsigned int idx; ) ), - // (BndTypeAlias, (const TypeAlias* alias_; ) ), - // (BndStructMethod, (const Struct* struct_; ::std::string name; ) ), - // (BndTraitMethod, (const Trait* struct_; ::std::string name; ) ) - // ); private: enum Class { RELATIVE, @@ -95,24 +164,7 @@ private: ::std::vector<TypeRef> m_ufcs; ::std::vector<PathNode> m_nodes; - BindingType m_binding_type = UNBOUND; - union { - const Module* module_; - const Enum* enum_; - const Struct* struct_; - struct { - const Struct* struct_; - unsigned int idx; - } structitem; - const Trait* trait_; - const Static* static_; - const Function* func_; - struct { - const Enum* enum_; - unsigned int idx; - } enumvar; - const TypeAlias* alias_; - } m_binding; + PathBinding m_binding; public: Path(): m_class(RELATIVE) @@ -196,25 +248,7 @@ public: bool is_relative() const { return m_class == RELATIVE; } size_t size() const { return m_nodes.size(); } - bool is_bound() const { return m_binding_type != UNBOUND; } - BindingType binding_type() const { return m_binding_type; } - #define _(t, n, v) const t& bound_##n() const { assert(m_binding_type == v); return *m_binding.n##_; } - _(Module, module, MODULE) - _(Trait, trait, TRAIT) - _(Struct, struct, STRUCT) - //_(Enum, enum, ENUM) - _(Function, func, FUNCTION) - _(Static, static, STATIC) - _(TypeAlias, alias, ALIAS) - #undef _ - const Enum& bound_enum() const { - assert(m_binding_type == ENUM || m_binding_type == ENUM_VAR); // Kinda evil, given that it has its own union entry - return *m_binding.enum_; - } - const unsigned int bound_idx() const { - assert(m_binding_type == ENUM_VAR); - return m_binding.enumvar.idx; - } + const PathBinding& binding() const { return m_binding; } ::std::vector<PathNode>& nodes() { return m_nodes; } const ::std::vector<PathNode>& nodes() const { return m_nodes; } |