summaryrefslogtreecommitdiff
path: root/src/ast
diff options
context:
space:
mode:
Diffstat (limited to 'src/ast')
-rw-r--r--src/ast/ast.cpp73
-rw-r--r--src/ast/ast.hpp30
-rw-r--r--src/ast/path.cpp73
-rw-r--r--src/ast/path.hpp137
4 files changed, 165 insertions, 148 deletions
diff --git a/src/ast/ast.cpp b/src/ast/ast.cpp
index f0d38199..f7ebaa2b 100644
--- a/src/ast/ast.cpp
+++ b/src/ast/ast.cpp
@@ -265,7 +265,7 @@ bool Crate::check_impls_wildcard(const Path& trait, const TypeRef& type) const
bool Crate::find_impl(const Path& trait, const TypeRef& type, Impl** out_impl, ::std::vector<TypeRef>* out_params) const
{
- DEBUG("trait = " << trait << ", type = " << type);
+ TRACE_FUNCTION_F("trait = " << trait << ", type = " << type);
// If no params output provided, use a dud locaton
::std::vector<TypeRef> dud_params;
@@ -288,26 +288,31 @@ bool Crate::find_impl(const Path& trait, const TypeRef& type, Impl** out_impl, :
// TODO: Handle more complex bounds like "[T]: Trait"
if( type.is_type_param() )
{
- assert(type.type_params_ptr());
- // Obtain the relevant TypeParams structure
- const TypeParams& tps = *type.type_params_ptr();
- // - TODO: this structure should be pointed to by TypeRef
- // Search bounds for type: trait
- for( const auto& bound : tps.bounds() )
+ if( trait.is_valid() )
{
- DEBUG("bound = " << bound);
- if( bound.is_trait() && bound.test() == type && bound.bound() == trait ) {
- // If found, success!
- DEBUG("- Success!");
- // TODO: What should be returned, kinda need to return a boolean
- if(out_impl) throw CompileError::BugCheck("find_impl - Asking for a concrete impl, but generic passed");
- return true;
+ assert(type.type_params_ptr());
+ // Search bounds for type: trait
+ for( const auto& bound : type.type_params_ptr()->bounds() )
+ {
+ DEBUG("bound = " << bound);
+ if( bound.is_trait() && bound.test() == type && bound.bound() == trait ) {
+ // If found, success!
+ DEBUG("- Success!");
+ // TODO: What should be returned, kinda need to return a boolean
+ if(out_impl) throw CompileError::BugCheck("find_impl - Asking for a concrete impl, but generic passed");
+ return true;
+ }
}
+ // Else, failure
+ DEBUG("- No impl :(");
+ //if(out_impl) throw CompileError::BugCheck("find_impl - Asking for a concrete impl, but generic passed");
+ return false;
+ }
+ else
+ {
+ DEBUG("- No inherent impl for generic params");
+ return false;
}
- // Else, failure
- DEBUG("- No impl :(");
- if(out_impl) throw CompileError::BugCheck("find_impl - Asking for a concrete impl, but generic passed");
- return false;
}
// TODO: Do a sort to allow a binary search
@@ -644,7 +649,7 @@ Module::ItemRef Module::find_item(const ::std::string& needle, bool allow_leaves
// continue ;
//
const auto& binding = imp.data.binding();
- if( !binding.is_bound() )
+ if( binding.is_Unbound() )
{
// not yet bound, so run resolution (recursion)
DEBUG("Recursively resolving pub wildcard use " << imp.data);
@@ -652,22 +657,27 @@ Module::ItemRef Module::find_item(const ::std::string& needle, bool allow_leaves
throw ParseError::Todo("Path::resolve() wildcard re-export call resolve");
}
- switch(binding.type())
- {
- case AST::PathBinding::UNBOUND:
+ TU_MATCH_DEF(AST::PathBinding, (binding), (info),
+ // - any other type - error
+ (
+ DEBUG("ERROR: Import of invalid class : " << imp.data);
+ throw ParseError::Generic("Wildcard import of non-module/enum");
+ ),
+ (Unbound,
throw ParseError::BugCheck("Wildcard import path not bound");
+ ),
// - If it's a module, recurse
- case AST::PathBinding::MODULE: {
- auto rv = binding.bound_module().find_item(needle);
+ (Module,
+ auto rv = info.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);
//return rv;
}
- break; }
+ ),
// - If it's an enum, search for this name and then pass to resolve
- case AST::PathBinding::ENUM: {
- auto& vars = binding.bound_enum().variants();
+ (Enum,
+ auto& vars = info.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; });
@@ -676,13 +686,8 @@ Module::ItemRef Module::find_item(const ::std::string& needle, bool allow_leaves
return ItemRef(imp);
//throw ParseError::Todo("Handle lookup_path_in_module for wildcard imports - enum");
}
-
- break; }
- // - otherwise, error
- default:
- DEBUG("ERROR: Import of invalid class : " << imp.data);
- throw ParseError::Generic("Wildcard import of non-module/enum");
- }
+ )
+ )
}
else
{
diff --git a/src/ast/ast.hpp b/src/ast/ast.hpp
index b913e334..c04a8927 100644
--- a/src/ast/ast.hpp
+++ b/src/ast/ast.hpp
@@ -54,6 +54,36 @@ public:
SERIALISABLE_PROTOTYPES();
};
+#if 0
+TAGGED_UNION( GenericBound, Lifetime,
+ // Lifetime bound: 'test must be valid for 'bound
+ (Lifetime, (
+ ::std::string test;
+ ::std::string bound;
+ )),
+ // Standard trait bound: "Type: [for<'a>] Trait"
+ (IsTrait, (
+ TypeRef type;
+ ::std::vector< ::std::string> hrls; // Higher-ranked lifetimes
+ AST::Path trait;
+ )),
+ // Removed trait bound: "Type: ?Trait"
+ (MaybeTrait, (
+ TypeRef type;
+ AST::Path trait;
+ )),
+ // Negative trait bound: "Type: !Trait"
+ (NotTrait, (
+ TypeRef type;
+ AST::Path trait;
+ )),
+ // Type equality: "Type = Replacement"
+ (Equality, (
+ TypeRef type;
+ TypeRef replacement;
+ ))
+ );
+#endif
class GenericBound:
public Serialisable
{
diff --git a/src/ast/path.cpp b/src/ast/path.cpp
index b3b3ab56..863902e6 100644
--- a/src/ast/path.cpp
+++ b/src/ast/path.cpp
@@ -11,6 +11,27 @@
namespace AST {
+// --- AST::PathBinding
+::std::ostream& operator<<(::std::ostream& os, const PathBinding& x) {
+ TU_MATCH(PathBinding, (x), (i),
+ (Unbound, os << "UNBOUND"; ),
+ (Module, os << "Module"; ),
+ (Trait, os << "Trait"; ),
+ (Struct, os << "Struct"; ),
+ (Enum, os << "Enum"; ),
+ (Static, os << "Static"; ),
+ (Function, os << "Function";),
+ (EnumVar, os << "EnumVar(" << i.idx << ")"; ),
+ (TypeAlias, os << "TypeAlias";),
+ (StructMethod, os << "StructMethod"; ),
+ (TraitMethod, os << "TraitMethod"; ),
+
+ (TypeParameter, os << "TypeParameter(" << i.level << " # " << i.idx << ")"; ),
+ (Variable, os << "Variable(" << i.slot << ")"; )
+ )
+ return os;
+}
+
// --- AST::PathNode
PathNode::PathNode(::std::string name, ::std::vector<TypeRef> args):
m_name(name),
@@ -96,14 +117,17 @@ AST::Path::Path(const Path& x):
void Path::resolve(const Crate& root_crate, bool expect_params)
{
TRACE_FUNCTION_F("*this = "<< *this);
- if( m_class.is_Absolute() ) {
- resolve_absolute(root_crate, expect_params);
- }
- else if(m_class.is_UFCS()) {
- resolve_ufcs(root_crate, expect_params);
+ if( m_binding.is_Unbound() )
+ {
+ if( m_class.is_Absolute() ) {
+ resolve_absolute(root_crate, expect_params);
+ }
+ else if(m_class.is_UFCS()) {
+ resolve_ufcs(root_crate, expect_params);
+ }
+ else
+ throw ParseError::BugCheck("Calling Path::resolve on non-absolute path");
}
- else
- throw ParseError::BugCheck("Calling Path::resolve on non-absolute path");
}
void Path::resolve_absolute(const Crate& root_crate, bool expect_params)
{
@@ -192,7 +216,7 @@ void Path::resolve_absolute(const Crate& root_crate, bool expect_params)
// - Maybe leave that up to other code?
if( is_last ) {
check_param_counts(ta.params(), expect_params, nodes[i]);
- m_binding = PathBinding(&ta);
+ m_binding = PathBinding::make_TypeAlias( {&ta} );
goto ret;
}
else {
@@ -206,7 +230,7 @@ void Path::resolve_absolute(const Crate& root_crate, bool expect_params)
DEBUG("Found function");
if( is_last ) {
check_param_counts(fn.params(), expect_params, nodes[i]);
- m_binding = PathBinding(&fn);
+ m_binding = PathBinding::make_Function({&fn});
goto ret;
}
else {
@@ -220,13 +244,13 @@ void Path::resolve_absolute(const Crate& root_crate, bool expect_params)
DEBUG("Found trait");
if( is_last ) {
check_param_counts(t.params(), expect_params, nodes[i]);
- m_binding = PathBinding(&t);
+ m_binding = PathBinding::make_Trait({&t});
goto ret;
}
else if( is_sec_last ) {
check_param_counts(t.params(), expect_params, nodes[i]);
// TODO: Also check params on item
- m_binding = PathBinding(PathBinding::TagItem(), &t);
+ m_binding = PathBinding::make_TraitMethod( {&t, nodes[i+1].name()} );
goto ret;
}
else {
@@ -321,7 +345,7 @@ void Path::resolve_absolute(const Crate& root_crate, bool expect_params)
}
// We only reach here if the path points to a module
- m_binding = PathBinding(mod);
+ m_binding = PathBinding::make_Module({mod});
ret:
if( slice_from > 0 )
{
@@ -406,7 +430,7 @@ void Path::resolve_ufcs(const Crate& root_crate, bool expect_params)
{
if( it.name == node.name() ) {
check_param_counts(it.data.params(), expect_params, node);
- m_binding = PathBinding(&it.data);
+ m_binding = PathBinding::make_Function( {&it.data} );
goto _impl_item_bound;
}
}
@@ -424,16 +448,16 @@ void Path::resolve_ufcs(const Crate& root_crate, bool expect_params)
void Path::resolve_ufcs_trait(const AST::Path& trait_path, AST::PathNode& node)
{
- if(trait_path.m_binding.type() != PathBinding::TRAIT)
+ if( !trait_path.m_binding.is_Trait() )
throw ParseError::Generic("Path::resolve_ufcs - Trait in UFCS path is not a trait");
- const auto& trait_def = trait_path.m_binding.bound_trait();
+ const auto& trait_def = *trait_path.m_binding.as_Trait().trait_;
// Check that the requested item exists within the trait, and bind to that item
for( const auto& fn : trait_def.functions() )
{
if( fn.name == node.name() ) {
check_param_counts(fn.data.params(), true, node);
- m_binding = PathBinding(&fn.data);
+ m_binding = PathBinding::make_Function( {&fn.data} );
goto _trait_item_bound;
}
}
@@ -441,7 +465,7 @@ void Path::resolve_ufcs_trait(const AST::Path& trait_path, AST::PathNode& node)
{
if( it.name == node.name() ) {
check_param_counts(it.data.params(), true, node);
- m_binding = PathBinding(&it.data);
+ m_binding = PathBinding::make_TypeAlias( {&it.data} );
goto _trait_item_bound;
}
}
@@ -483,10 +507,15 @@ void Path::check_param_counts(const TypeParams& params, bool expect_params, Path
}
}
}
+
+void Path::bind_variable(unsigned int slot)
+{
+ m_binding = PathBinding::make_Variable({slot});
+}
void Path::bind_enum(const Enum& ent, const ::std::vector<TypeRef>& args)
{
DEBUG("Bound to enum");
- m_binding = PathBinding(&ent);
+ m_binding = PathBinding::make_Enum({&ent});
}
void Path::bind_enum_var(const Enum& ent, const ::std::string& name, const ::std::vector<TypeRef>& args)
{
@@ -508,7 +537,7 @@ void Path::bind_enum_var(const Enum& ent, const ::std::string& name, const ::std
//}
DEBUG("Bound to enum variant '" << name << "' (#" << idx << ")");
- m_binding = PathBinding(&ent, idx);
+ m_binding = PathBinding::make_EnumVar({&ent, idx});
}
void Path::bind_struct(const Struct& ent, const ::std::vector<TypeRef>& args)
{
@@ -522,16 +551,16 @@ void Path::bind_struct(const Struct& ent, const ::std::vector<TypeRef>& args)
//}
DEBUG("Bound to struct");
- m_binding = PathBinding(&ent);
+ m_binding = PathBinding::make_Struct({&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 = PathBinding(PathBinding::TagItem(), &ent);
+ m_binding = PathBinding::make_StructMethod({&ent, member_node.name()});
}
void Path::bind_static(const Static& ent)
{
- m_binding = PathBinding(&ent);
+ m_binding = PathBinding::make_Static({&ent});
}
void Path::resolve_args(::std::function<TypeRef(const char*)> fcn)
diff --git a/src/ast/path.hpp b/src/ast/path.hpp
index 7bb50bee..04de1aeb 100644
--- a/src/ast/path.hpp
+++ b/src/ast/path.hpp
@@ -27,102 +27,54 @@ class Trait;
class Static;
class Function;
-//TAGGED_UNION(PathBinding, Unbound,
-// (Module, (const Module* module_; ) ),
-// (Enum, (const Enum* enum_; ) ),
-// (Struct, (const Struct* struct_; ) ),
-// (Trait, (const Trait* trait_; ) ),
-// (Static, (const Static* static_; ) ),
-// (Function, (const Function* func_; ) ),
-// (EnumVar, (const Enum* enum_; unsigned int idx; ) ),
-// (TypeAlias, (const TypeAlias* alias_; ) ),
-// (StructMethod, (const Struct* struct_; ::std::string name; ) ),
-// (TraitMethod, (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 {
+TAGGED_UNION(PathBinding, Unbound,
+ (Unbound, (
+ )),
+ (Module, (
const Module* module_;
+ )),
+ (Enum, (
const Enum* enum_;
- const Struct* struct_;
- struct {
- const Struct* struct_;
- unsigned int idx;
- } structitem;
- const Trait* trait_;
- const Static* static_;
+ )),
+ (Struct, (
+ const Struct* struct_;
+ )),
+ (Trait, (
+ const Trait* trait_;
+ )),
+ (Static, (
+ const Static* static_;
+ )),
+ (Function, (
const Function* func_;
- EnumVar enumvar_;
- const TypeAlias* alias_;
- } m_binding;
+ )),
+ (EnumVar, (
+ const Enum* enum_;
+ unsigned int idx;
+ )),
+ (TypeAlias, (
+ const TypeAlias* alias_;
+ )),
+ (StructMethod, (
+ const Struct* struct_;
+ ::std::string name;
+ )),
+ (TraitMethod, (
+ const Trait* struct_;
+ ::std::string name;
+ )),
+
+ (TypeParameter, (
+ unsigned int level;
+ unsigned int idx;
+ )),
+ (Variable, (
+ unsigned int slot;
+ ))
+ );
+
+extern ::std::ostream& operator<<(::std::ostream& os, const PathBinding& x);
-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
@@ -325,6 +277,7 @@ public:
bool is_concrete() const;
const PathBinding& binding() const { return m_binding; }
+ void bind_variable(unsigned int slot);
::std::vector<PathNode>& nodes() {
TU_MATCH(Class, (m_class), (ent),