summaryrefslogtreecommitdiff
path: root/src/ast
diff options
context:
space:
mode:
Diffstat (limited to 'src/ast')
-rw-r--r--src/ast/ast.cpp15
-rw-r--r--src/ast/path.cpp34
-rw-r--r--src/ast/path.hpp162
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; }