summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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
-rw-r--r--src/convert/ast_iterate.cpp25
-rw-r--r--src/convert/resolve.cpp182
-rw-r--r--src/convert/typecheck_bounds.cpp4
-rw-r--r--src/convert/typecheck_expr.cpp65
-rw-r--r--src/convert/typecheck_params.cpp78
-rw-r--r--src/include/tagged_union.hpp27
-rw-r--r--src/types.cpp30
-rw-r--r--src/types.hpp8
12 files changed, 436 insertions, 296 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),
diff --git a/src/convert/ast_iterate.cpp b/src/convert/ast_iterate.cpp
index 72cfd009..10eaf80b 100644
--- a/src/convert/ast_iterate.cpp
+++ b/src/convert/ast_iterate.cpp
@@ -178,25 +178,26 @@ void CASTIterator::handle_pattern(AST::Pattern& pat, const TypeRef& type_hint)
const auto& hint_binding = hint_path.binding();
const auto& pat_binding = pat_path.binding();
DEBUG("Pat: " << pat_path << ", Type: " << type_hint.path());
- switch( hint_binding.type() )
- {
- case AST::PathBinding::UNBOUND:
+ TU_MATCH_DEF( AST::PathBinding, (hint_binding), (info),
+ (
+ throw ::std::runtime_error(FMT("Bad type in tuple struct pattern : " << type_hint.path()))
+ ),
+ (Unbound,
throw ::std::runtime_error("Unbound path in pattern");
- case AST::PathBinding::ENUM: {
+ ),
+ (Enum,
// The pattern's path must refer to a variant of the hint path
// - Actual type params are checked by the 'handle_pattern_enum' code
- if( pat_binding.type() != AST::PathBinding::ENUM_VAR )
+ if( !pat_binding.is_EnumVar() )
throw ::std::runtime_error(FMT("Paths in pattern are invalid"));
- if( pat_binding.bound_enumvar().enum_ != &hint_binding.bound_enum() )
+ if( pat_binding.as_EnumVar().enum_ != info.enum_ )
throw ::std::runtime_error(FMT("Paths in pattern are invalid"));
- const auto& enm = *pat_binding.bound_enumvar().enum_;
- auto idx = pat_binding.bound_enumvar().idx;
+ const auto& enm = *pat_binding.as_EnumVar().enum_;
+ auto idx = pat_binding.as_EnumVar().idx;
auto& var = enm.variants().at(idx);
handle_pattern_enum(pat_path[-2].args(), hint_path[-1].args(), enm.params(), var, v.sub_patterns);
- break; }
- default:
- throw ::std::runtime_error(FMT("Bad type in tuple struct pattern : " << type_hint.path()));
- }
+ )
+ )
}
break; }
}
diff --git a/src/convert/resolve.cpp b/src/convert/resolve.cpp
index 901a3acb..821d4810 100644
--- a/src/convert/resolve.cpp
+++ b/src/convert/resolve.cpp
@@ -89,9 +89,11 @@ public:
::rust::option<const LocalItem&> lookup_local(LocalItem::Type type, const ::std::string& name) const;
- bool find_local_item(AST::Path& path, bool allow_variables);
- bool find_mod_item(AST::Path& path);
- bool find_super_mod_item(AST::Path& path);
+ bool find_local_item(AST::Path& path, const ::std::string& name, bool allow_variables);
+ //bool find_local_item(AST::Path& path, bool allow_variables);
+ bool find_mod_item(AST::Path& path, const ::std::string& name);
+ bool find_self_mod_item(AST::Path& path, const ::std::string& name);
+ bool find_super_mod_item(AST::Path& path, const ::std::string& name);
bool find_type_param(const ::std::string& name);
// TODO: Handle a block and obtain the local module (if any)
@@ -319,11 +321,11 @@ void CPathResolver::end_scope()
// > Search local use definitions (function-level)
// - TODO: Local use statements (scoped)
// > Search module-level definitions
-bool lookup_path_in_module(const AST::Crate& crate, const AST::Module& module, const AST::Path& mod_path, AST::Path& path)
+bool lookup_path_in_module(const AST::Crate& crate, const AST::Module& module, const AST::Path& mod_path, AST::Path& path, const ::std::string& name, bool is_leaf)
{
TRACE_FUNCTION_F("mod_path="<<mod_path);
// - Allow leaf nodes if path is a single node, don't skip private wildcard imports
- auto item = module.find_item(path[0].name(), (path.size() == 1), false);
+ auto item = module.find_item(name, is_leaf, false);
switch(item.type())
{
case AST::Module::ItemRef::ITEM_none:
@@ -358,6 +360,9 @@ bool lookup_path_in_module(const AST::Crate& crate, const AST::Module& module, c
return true;
}
}
+bool lookup_path_in_module(const AST::Crate& crate, const AST::Module& module, const AST::Path& mod_path, AST::Path& path) {
+ return lookup_path_in_module(crate, module, mod_path, path, path[0].name(), path.size() == 1);
+}
/// Perform path resolution within a generic definition block
void CPathResolver::handle_params(AST::TypeParams& params)
@@ -445,7 +450,7 @@ void CPathResolver::handle_path_int(AST::Path& path, CASTIterator::PathMode mode
INDENT();
// Already absolute, our job is done
// - However, if the path isn't bound, bind it
- if( !path.binding().is_bound() ) {
+ if( path.binding().is_Unbound() ) {
path.resolve(m_crate);
}
else {
@@ -460,11 +465,38 @@ void CPathResolver::handle_path_int(AST::Path& path, CASTIterator::PathMode mode
// > Variable: (wait, how is this known already?)
// - 'self'
case AST::Path::Class::Local:
- //if(
- // 1. Check for local items
- // 2. Type parameters (ONLY when in expression mode)
- // 3. Module items
- //throw ::std::runtime_error("TODO: Local in CPathResolver::handle_path_int");
+ if( !path.binding().is_Unbound() )
+ {
+ DEBUG("- Path " << path << " already bound");
+ }
+ else
+ {
+ const auto& info = path.m_class.as_Local();
+ // 1. Check for local items
+ if( this->find_local_item(path, info.name, (mode == CASTIterator::MODE_EXPR)) ) {
+ path.resolve(m_crate);
+ break ;
+ }
+ else {
+ // No match, fall through
+ }
+ // 2. Type parameters (ONLY when in type mode)
+ if( mode == CASTIterator::MODE_TYPE ) {
+ throw ::std::runtime_error("TODO: Local in CPathResolver::handle_path_int type param");
+ }
+ // 3. Module items
+ if( this->find_mod_item(path, info.name) ) {
+ path.resolve(m_crate);
+ break;
+ }
+ else {
+ }
+
+ DEBUG("no matches found for path = " << path);
+ if( mode != MODE_BIND )
+ throw ParseError::Generic("CPathResolver::handle_path - Name resolution failed (Local)");
+ return ;
+ }
break;
case AST::Path::Class::Relative:
@@ -472,8 +504,8 @@ void CPathResolver::handle_path_int(AST::Path& path, CASTIterator::PathMode mode
// > Return values: name or path
{
bool allow_variables = (mode == CASTIterator::MODE_EXPR && path.is_trivial());
- if( this->find_local_item(path, allow_variables) ) {
- //path.resolve(m_crate);
+ if( this->find_local_item(path, path[0].name(), allow_variables) ) {
+ path.resolve(m_crate);
break ;
}
else {
@@ -495,13 +527,14 @@ void CPathResolver::handle_path_int(AST::Path& path, CASTIterator::PathMode mode
auto newpath = AST::Path(AST::Path::TagUfcs(), TypeRef(TypeRef::TagArg(), path[0].name()), TypeRef());
newpath.add_tailing(path);
path = mv$(newpath);
+ handle_path_ufcs(path, mode);
}
else {
// Mark as local
- // - TODO: Also need to annotate
// - TODO: Not being trivial is an error, not a bug
assert( path.is_trivial() );
path = AST::Path(AST::Path::TagLocal(), path[0].name());
+ // - TODO: Need to bind this to the source parameter block
}
break;
}
@@ -509,7 +542,8 @@ void CPathResolver::handle_path_int(AST::Path& path, CASTIterator::PathMode mode
// 3. current module
{
- if( this->find_mod_item(path) ) {
+ if( this->find_mod_item(path, path[0].name()) ) {
+ path.resolve(m_crate);
break;
}
else {
@@ -524,7 +558,7 @@ void CPathResolver::handle_path_int(AST::Path& path, CASTIterator::PathMode mode
// Module relative
case AST::Path::Class::Self:{
- if( this->find_mod_item(path) ) {
+ if( this->find_self_mod_item(path, path[0].name()) ) {
break;
}
else {
@@ -535,7 +569,7 @@ void CPathResolver::handle_path_int(AST::Path& path, CASTIterator::PathMode mode
break; }
// Parent module relative
case AST::Path::Class::Super:{
- if( this->find_super_mod_item(path) ) {
+ if( this->find_super_mod_item(path, path[0].name()) ) {
break;
}
else {
@@ -547,25 +581,76 @@ void CPathResolver::handle_path_int(AST::Path& path, CASTIterator::PathMode mode
}
// TODO: Are there any reasons not to be bound at this point?
- //assert( path.binding().is_bound() );
+ //assert( !path.binding().is_Unbound() );
}
void CPathResolver::handle_path_ufcs(AST::Path& path, CASTIterator::PathMode mode)
{
+ assert(path.m_class.is_UFCS());
auto& info = path.m_class.as_UFCS();
+ TRACE_FUNCTION_F("info={< " << *info.type << " as " << *info.trait << ">::" << info.nodes << "}");
+ const ::std::string& item_name = info.nodes[0].name();
// 1. Handle sub-types
handle_type(*info.type);
handle_type(*info.trait);
// 2. Handle wildcard traits (locate in inherent impl, or from an in-scope trait)
if( info.trait->is_wildcard() )
{
- DEBUG("Searching for impls when trait is _");
+ DEBUG("Searching for impls when trait is _ (trait = " << *info.trait << ")");
// Search applicable type parameters for known implementations
// 1. Inherent
AST::Impl* impl_ptr;
::std::vector<TypeRef> params;
- if( m_crate.find_impl(AST::Path(), *info.type, &impl_ptr, &params) )
+ if( info.type->is_type_param() && info.type->type_param() == "Self" )
+ {
+ throw ParseError::Todo("CPathResolver::handle_path_ufcs - Handle '<Self as _>::...'");
+ }
+ else if( info.type->is_type_param() )
+ {
+ DEBUG("Checking applicable generic bounds");
+ const auto& tp = *info.type->type_params_ptr();
+ assert(&tp != nullptr);
+ bool success = false;
+
+ // Enumerate bounds
+ for( const auto& bound : tp.bounds() )
+ {
+ DEBUG("bound = " << bound);
+ if( bound.is_trait() && bound.test() == *info.type )
+ {
+ const auto& t = *bound.bound().binding().as_Trait().trait_;
+ {
+ const auto& fcns = t.functions();
+ auto it = ::std::find_if( fcns.begin(), fcns.end(), [&](const AST::Item<AST::Function>& a) { return a.name == item_name; } );
+ if( it != fcns.end() ) {
+ // Found it.
+ if( info.nodes.size() != 1 )
+ throw ParseError::Generic("CPathResolver::handle_path_ufcs - Multiple arguments");
+ *info.trait = bound.bound();
+ success = true;
+ break;
+ }
+ }
+ {
+ const auto& types = t.types();
+ auto it = ::std::find_if( types.begin(), types.end(), [&](const AST::Item<AST::TypeAlias>& a) { return a.name == item_name; } );
+ if( it != types.end() ) {
+ // Found it.
+ *info.trait = bound.bound();
+ success = true;
+ break;
+ }
+ }
+ }
+ }
+
+ if( !success )
+ throw ParseError::Todo("CPathResolver::handle_path_ufcs - UFCS, find trait for generic");
+ // - re-handle, to ensure that the bound is resolved
+ handle_type(*info.trait);
+ }
+ else if( m_crate.find_impl(AST::Path(), *info.type, &impl_ptr, &params) )
{
DEBUG("Found matching inherent impl");
// - Mark as being from the inherent, and move along
@@ -573,16 +658,18 @@ void CPathResolver::handle_path_ufcs(AST::Path& path, CASTIterator::PathMode mod
*info.trait = TypeRef(TypeRef::TagInvalid());
}
else
- {
- // Iterate all traits in scope, and find one that is impled for this type
- throw ParseError::Todo("CPathResolver::handle_path - UFCS, find trait");
+ {
+ // Iterate all traits in scope, and find one that is implemented for this type
+ // - TODO: Iterate traits to find match for <Type as _>
+ throw ParseError::Todo("CPathResolver::handle_path_ufcs - UFCS, find trait");
}
}
// 3. Call resolve to attempt binding
path.resolve(m_crate);
}
-bool CPathResolver::find_local_item(AST::Path& path, bool allow_variables) {
+bool CPathResolver::find_local_item(AST::Path& path, const ::std::string& name, bool allow_variables)
+{
TRACE_FUNCTION_F("path="<<path<<", allow_variables="<<allow_variables);
// Search current scopes for a name
// - This should search both the expression stack
@@ -594,8 +681,9 @@ bool CPathResolver::find_local_item(AST::Path& path, bool allow_variables) {
{
for( auto it2 = s.locals.rbegin(); it2 != s.locals.rend(); ++it2 )
{
- if( *it2 == path[0].name() ) {
- path = AST::Path(AST::Path::TagLocal(), path[0].name());
+ if( *it2 == name ) {
+ path = AST::Path(AST::Path::TagLocal(), name);
+ path.bind_variable(0);
return true;
}
}
@@ -603,19 +691,29 @@ bool CPathResolver::find_local_item(AST::Path& path, bool allow_variables) {
if( s.module != nullptr )
{
DEBUG("- Looking in sub-module '" << s.module_path << "'");
- if( lookup_path_in_module(m_crate, *s.module, s.module_path, path) )
+ if( lookup_path_in_module(m_crate, *s.module, s.module_path, path, name, path.is_trivial()) )
return true;
}
}
return false;
}
-bool CPathResolver::find_mod_item(AST::Path& path) {
+bool CPathResolver::find_mod_item(AST::Path& path, const ::std::string& name) {
+ const AST::Module* mod = m_module;
+ do {
+ if( lookup_path_in_module(m_crate, *mod, m_module_path, path, name, path.size()==1) )
+ return true;
+ if( mod->name() == "" )
+ throw ParseError::Todo("Handle anon modules when resoling unqualified relative paths");
+ } while( mod->name() == "" );
+ return false;
+}
+bool CPathResolver::find_self_mod_item(AST::Path& path, const ::std::string& name) {
if( m_module->name() == "" )
throw ParseError::Todo("Correct handling of 'self' in anon modules");
- return lookup_path_in_module(m_crate, *m_module, m_module_path, path);
+ return lookup_path_in_module(m_crate, *m_module, m_module_path, path, name, path.size()==1);
}
-bool CPathResolver::find_super_mod_item(AST::Path& path) {
+bool CPathResolver::find_super_mod_item(AST::Path& path, const ::std::string& name) {
if( m_module->name() == "" )
throw ParseError::Todo("Correct handling of 'super' in anon modules");
@@ -628,7 +726,7 @@ bool CPathResolver::find_super_mod_item(AST::Path& path) {
// 2. Resolve that path
super_path.resolve(m_crate);
// 3. Call lookup_path_in_module
- return lookup_path_in_module(m_crate, super_path.binding().bound_module(), super_path, path);
+ return lookup_path_in_module(m_crate, *super_path.binding().as_Module().module_, super_path, path, name, path.size()==1);
}
bool CPathResolver::find_type_param(const ::std::string& name) {
for( auto it = m_locals.end(); it -- != m_locals.begin(); )
@@ -810,24 +908,22 @@ void ResolvePaths_HandleModule_Use(const AST::Crate& crate, const AST::Path& mod
// If wildcard, make sure it's sane
if( imp.name == "" )
{
- switch(imp.data.binding().type())
- {
- case AST::PathBinding::UNBOUND:
- throw ParseError::BugCheck("path unbound after calling .resolve()");
- case AST::PathBinding::MODULE:
- break;
- case AST::PathBinding::ENUM:
- break;
-
- default:
+ TU_MATCH_DEF(AST::PathBinding, (imp.data.binding()), (info),
+ (
throw ParseError::Generic("Wildcard imports are only allowed on modules and enums");
- }
+ ),
+ (Unbound,
+ throw ParseError::BugCheck("path unbound after calling .resolve()");
+ ),
+ (Module, (void)0;),
+ (Enum, (void)0;)
+ )
}
}
for( auto& new_imp : new_imports )
{
- if( not new_imp.binding().is_bound() ) {
+ if( new_imp.binding().is_Unbound() ) {
new_imp.resolve(crate, false);
}
mod.add_alias(false, new_imp, new_imp[new_imp.size()-1].name());
diff --git a/src/convert/typecheck_bounds.cpp b/src/convert/typecheck_bounds.cpp
index 4112bf27..1216e959 100644
--- a/src/convert/typecheck_bounds.cpp
+++ b/src/convert/typecheck_bounds.cpp
@@ -25,9 +25,9 @@ void CGenericBoundChecker::handle_params(AST::TypeParams& params)
if( bound.is_trait() )
{
auto& trait = bound.bound();
- assert(trait.binding().is_bound());
+ assert( !trait.binding().is_Unbound() );
DEBUG("trait = " << trait);
- if( trait.binding().type() != AST::PathBinding::TRAIT )
+ if( trait.binding().is_Trait() )
{
//throw CompileError::BoundNotTrait( bound.lex_scope(), bound.param(), trait );
throw ::std::runtime_error(FMT("TODO - Bound " << trait << " not a trait : " << trait.binding()));
diff --git a/src/convert/typecheck_expr.cpp b/src/convert/typecheck_expr.cpp
index 8a4bc84f..e2bd1857 100644
--- a/src/convert/typecheck_expr.cpp
+++ b/src/convert/typecheck_expr.cpp
@@ -300,14 +300,16 @@ void CTC_NodeVisitor::visit(AST::ExprNode_NamedValue& node)
if( p.is_absolute() )
{
// grab bound item
- switch(p.binding().type())
- {
- case AST::PathBinding::STATIC:
- node.get_res_type() = p.binding().bound_static().type();
- break;
- case AST::PathBinding::ENUM_VAR: {
- const AST::Enum& enm = *p.binding().bound_enumvar().enum_;
- auto idx = p.binding().bound_enumvar().idx;
+ TU_MATCH_DEF(AST::PathBinding, (p.binding()), (info),
+ (
+ throw ::std::runtime_error( FMT("Unknown binding type on named value : "<<p) );
+ ),
+ (Static,
+ node.get_res_type() = info.static_->type();
+ ),
+ (EnumVar,
+ const AST::Enum& enm = *info.enum_;
+ auto idx = info.idx;
// Enum variant:
// - Check that this variant takes no arguments
if( enm.variants()[idx].m_sub_types.size() > 0 )
@@ -322,10 +324,8 @@ void CTC_NodeVisitor::visit(AST::ExprNode_NamedValue& node)
while(pn.args().size() < num_params)
pn.args().push_back( TypeRef() );
node.get_res_type() = TypeRef(tp);
- break; }
- default:
- throw ::std::runtime_error( FMT("Unknown binding type on named value : "<<p) );
- }
+ )
+ )
}
else
{
@@ -415,16 +415,16 @@ void CTC_NodeVisitor::visit(AST::ExprNode_Field& node)
// TODO Move this logic to types.cpp?
const AST::Path& p = tr->path();
- switch( p.binding().type() )
- {
- case AST::PathBinding::STRUCT: {
+ TU_MATCH_DEF( AST::PathBinding, (p.binding()), (info),
+ (
+ throw ::std::runtime_error("TODO: Get field from non-structure");
+ ),
+ (Struct,
const AST::PathNode& lastnode = p.nodes().back();
- AST::Struct& s = const_cast<AST::Struct&>( p.binding().bound_struct() );
+ AST::Struct& s = const_cast<AST::Struct&>( *info.struct_ );
node.get_res_type().merge_with( s.get_field_type(node.m_name.c_str(), lastnode.args()) );
- break; }
- default:
- throw ::std::runtime_error("TODO: Get field from non-structure");
- }
+ )
+ )
DEBUG("deref_count = " << deref_count);
for( unsigned i = 0; i < deref_count; i ++ )
{
@@ -575,9 +575,12 @@ void CTC_NodeVisitor::visit(AST::ExprNode_CallPath& node)
argtypes.push_back( arg->get_res_type() );
}
- if(node.m_path.binding().type() == AST::PathBinding::FUNCTION)
- {
- const AST::Function& fcn = node.m_path.binding().bound_func();
+ TU_MATCH_DEF( AST::PathBinding, (node.m_path.binding()), (info),
+ (
+ throw ::std::runtime_error("CallPath on non-function");
+ ),
+ (Function,
+ const AST::Function& fcn = *info.func_;
if( fcn.params().ty_params().size() > 0 )
{
@@ -586,11 +589,10 @@ void CTC_NodeVisitor::visit(AST::ExprNode_CallPath& node)
DEBUG("ExprNode_CallPath - rt = " << fcn.rettype());
node.get_res_type().merge_with( fcn.rettype() );
- }
- else if(node.m_path.binding().type() == AST::PathBinding::ENUM_VAR)
- {
- const AST::Enum& enm = *node.m_path.binding().bound_enumvar().enum_;
- const unsigned int idx = node.m_path.binding().bound_enumvar().idx;
+ ),
+ (EnumVar,
+ const AST::Enum& enm = *info.enum_;
+ const unsigned int idx = info.idx;
auto& path_node_enum = node.m_path[node.m_path.size()-2];
m_tc.check_enum_variant(path_node_enum.args(), argtypes, enm.params(), enm.variants().at(idx));
@@ -601,11 +603,8 @@ void CTC_NodeVisitor::visit(AST::ExprNode_CallPath& node)
DEBUG("ExprNode_CallPath - enum t = " << ty);
node.get_res_type().merge_with(ty);
- }
- else
- {
- throw ::std::runtime_error("CallPath on non-function");
- }
+ )
+ )
}
void Typecheck_Expr(AST::Crate& crate)
diff --git a/src/convert/typecheck_params.cpp b/src/convert/typecheck_params.cpp
index f3fe5047..e8cbbc05 100644
--- a/src/convert/typecheck_params.cpp
+++ b/src/convert/typecheck_params.cpp
@@ -235,43 +235,57 @@ void CGenericParamChecker::handle_path(AST::Path& path, CASTIterator::PathMode p
{
TRACE_FUNCTION_F("path = " << path);
AST::PathNode& last_node = path[path.size()-1];
- const AST::TypeParams* params = nullptr;
- switch(path.binding().type())
- {
- case AST::PathBinding::UNBOUND:
- throw CompileError::BugCheck( FMT("CGenericParamChecker::handle_path - Unbound path : " << path) );
- case AST::PathBinding::MODULE:
- DEBUG("WTF - Module path, isn't this invalid at this stage?");
- break;
- case AST::PathBinding::TRAIT:
- params = &path.binding().bound_trait().params();
- if(0)
- case AST::PathBinding::STRUCT:
- params = &path.binding().bound_struct().params();
- if(0)
- case AST::PathBinding::ENUM:
- params = &path.binding().bound_enum().params();
-
- {
+ auto comm = [&](const AST::TypeParams& params) {
auto lt = find_type_by_name("Self");
TypeRef self_type; // =TypeRef(TypeRef::TagPath(), path)
if( lt )
self_type = lt->fixed_type;
- check_generic_params(*params, last_node.args(), self_type, (m_within_expr > 0));
- }
- break;
- case AST::PathBinding::ALIAS:
- params = &path.binding().bound_alias().params();
- if(0)
- case AST::PathBinding::FUNCTION:
- params = &path.binding().bound_func().params();
-
- check_generic_params(*params, last_node.args(), TypeRef(TypeRef::TagInvalid()), (m_within_expr > 0));
- break;
- default:
- throw ::std::runtime_error("Unknown path type in CGenericParamChecker::handle_path");
- }
+ check_generic_params(params, last_node.args(), self_type, (m_within_expr > 0));
+ };
+
+ TU_MATCH( AST::PathBinding, (path.binding()), (info),
+ (Unbound,
+ throw CompileError::BugCheck( FMT("CGenericParamChecker::handle_path - Unbound path : " << path) );
+ ),
+ (Module,
+ DEBUG("WTF - Module path, isn't this invalid at this stage?");
+ ),
+ (Trait,
+ comm( info.trait_->params() );
+ ),
+ (Struct,
+ comm( info.struct_->params() );
+ ),
+ (Enum,
+ comm( info.enum_->params() );
+ ),
+ (TypeAlias,
+ comm( info.alias_->params() );
+ ),
+ (Function,
+ check_generic_params(info.func_->params(), last_node.args(), TypeRef(TypeRef::TagInvalid()), (m_within_expr > 0));
+ ),
+
+ (EnumVar,
+ throw ::std::runtime_error("TODO: handle_path EnumVar");
+ ),
+ (Static,
+ throw ::std::runtime_error("TODO: handle_path Static");
+ ),
+ (StructMethod,
+ throw ::std::runtime_error("TODO: handle_path StructMethod");
+ ),
+ (TraitMethod,
+ throw ::std::runtime_error("TODO: handle_path TraitMethod");
+ ),
+ (TypeParameter,
+ throw ::std::runtime_error("TODO: handle_path TypeParameter");
+ ),
+ (Variable,
+ throw ::std::runtime_error("TODO: handle_path Variable");
+ )
+ )
}
void CGenericParamChecker::handle_expr(AST::ExprNode& root)
diff --git a/src/include/tagged_union.hpp b/src/include/tagged_union.hpp
index 24152b5e..5ff3bf48 100644
--- a/src/include/tagged_union.hpp
+++ b/src/include/tagged_union.hpp
@@ -35,6 +35,7 @@
#define TU_FIRST(a, ...) a
// Argument iteration
+#define _DISP1(n, _1) n _1
#define _DISP2(n, _1, _2) n _1 n _2
#define _DISP3(n, v, v2, v3) n v n v2 n v3 // _DISP2(n, __VA_ARGS__)
#define _DISP4(n, v, v2, v3, v4) n v n v2 n v3 n v4 // #define _DISP4(n, v, ...) n v _DISP3(n, __VA_ARGS__)
@@ -42,12 +43,15 @@
#define _DISP6(n, v, ...) n v _DISP5(n, __VA_ARGS__)
#define _DISP7(n, v, ...) n v _DISP6(n, __VA_ARGS__)
#define _DISP8(n, v, ...) n v _DISP7(n, __VA_ARGS__)
-#define _DISP9(n, a1,a2,a3,a4, b1,b2,b3,b4, c1) _DISP4(n, a1,a2,a3,a4) _DISP3(n, b1,b2,b3) _DISP2(n, b4,c1) //n v _DISP8(n, __VA_ARGS__)
-#define _DISP10(n, a1,a2,a3,a4, b1,b2,b3,b4, c1,c2) _DISP4(n, a1,a2,a3,a4) _DISP4(n, b1,b2,b3,b4) _DISP2(n, c1,c2) //n v _DISP9(n, __VA_ARGS__)
-#define _DISP11(n, a1,a2,a3,a4, b1,b2,b3,b4, c1,c2,c3) _DISP4(n, a1,a2,a3,a4) _DISP4(n, b1,b2,b3,b4) _DISP2(n, c1,c2,c3) //n v _DISP10(n, __VA_ARGS__)
-#define _DISP12(n, a1,a2,a3,a4, b1,b2,b3,b4, c1,c2,c3,c4) _DISP4(n, a1,a2,a3,a4) _DISP4(n, b1,b2,b3,b4) _DISP4(n, c1,c2,c3,c4) //n v _DISP11(n, __VA_ARGS__)
+#define _DISP9(n, a1,a2,a3,a4, b1,b2,b3,b4, c1) _DISP4(n, a1,a2,a3,a4) _DISP3(n, b1,b2,b3) _DISP2(n, b4,c1)
+#define _DISP10(n, a1,a2,a3,a4, b1,b2,b3,b4, c1,c2) _DISP4(n, a1,a2,a3,a4) _DISP4(n, b1,b2,b3,b4) _DISP2(n, c1,c2)
+#define _DISP11(n, a1,a2,a3,a4, b1,b2,b3,b4, c1,c2,c3) _DISP4(n, a1,a2,a3,a4) _DISP4(n, b1,b2,b3,b4) _DISP2(n, c1,c2,c3)
+#define _DISP12(n, a1,a2,a3,a4, b1,b2,b3,b4, c1,c2,c3,c4) _DISP4(n, a1,a2,a3,a4) _DISP4(n, b1,b2,b3,b4) _DISP4(n, c1,c2,c3,c4)
+#define _DISP13(n, a1,a2,a3,a4,a5, b1,b2,b3,b4, c1,c2,c3,c4) _DISP5(n, a1,a2,a3,a4,a5) _DISP4(n, b1,b2,b3,b4) _DISP4(n, c1,c2,c3,c4)
+#define _DISP14(n, a1,a2,a3,a4,a5, b1,b2,b3,b4,b5, c1,c2,c3,c4) _DISP5(n, a1,a2,a3,a4,a5) _DISP5(n, b1,b2,b3,b4,b5) _DISP4(n, c1,c2,c3,c4)
#define TU_DISPA(n, a) n a
+#define TU_DISPA1(n, a, _1) TU_DISPA(n, (TU_EXP a, TU_EXP _1))
#define TU_DISPA2(n, a, _1, _2) TU_DISPA(n, (TU_EXP a, TU_EXP _1))/*
*/ TU_DISPA(n, (TU_EXP a, TU_EXP _2))
#define TU_DISPA3(n, a, _1, _2, _3) \
@@ -60,11 +64,16 @@
#define TU_DISPA7(n, a, a1,a2,a3, b1,b2, c1,c2) TU_DISPA3(n,a, a1,a2,a3) TU_DISPA2(n,a, b1,b2) TU_DISPA2(n,a, c1,c2)
#define TU_DISPA8(n, a, a1,a2,a3, b1,b2,b3, c1,c2) TU_DISPA3(n,a, a1,a2,a3) TU_DISPA3(n,a, b1,b2,b3) TU_DISPA2(n,a, c1,c2)
#define TU_DISPA9(n, a, a1,a2,a3, b1,b2,b3, c1,c2,c3) TU_DISPA3(n,a, a1,a2,a3) TU_DISPA3(n,a, b1,b2,b3) TU_DISPA3(n,a, c1,c2,c3)
+#define TU_DISPA10(n, a, a1,a2,a3, b1,b2,b3, c1,c2,c3, d1) TU_DISPA3(n,a, a1,a2,a3) TU_DISPA3(n,a, b1,b2,b3) TU_DISPA3(n,a, c1,c2,c3) TU_DISPA(n,a, d1)
+#define TU_DISPA11(n, a, a1,a2,a3, b1,b2,b3, c1,c2,c3, d1,d2) TU_DISPA3(n,a, a1,a2,a3) TU_DISPA3(n,a, b1,b2,b3) TU_DISPA3(n,a, c1,c2,c3) TU_DISPA2(n,a, d1,d2)
+#define TU_DISPA12(n, a, a1,a2,a3, b1,b2,b3, c1,c2,c3, d1,d2,d3) TU_DISPA3(n,a, a1,a2,a3) TU_DISPA3(n,a, b1,b2,b3) TU_DISPA3(n,a, c1,c2,c3) TU_DISPA3(n,a, d1,d2,d3)
+#define TU_DISPA13(n, a, a1,a2,a3,a4, b1,b2,b3, c1,c2,c3, d1,d2,d3) TU_DISPA4(n,a, a1,a2,a3,a4) TU_DISPA3(n,a, b1,b2,b3) TU_DISPA3(n,a, c1,c2,c3) TU_DISPA3(n,a, d1,d2,d3)
+#define TU_DISPA14(n, a, a1,a2,a3,a4, b1,b2,b3,b4, c1,c2,c3, d1,d2,d3) TU_DISPA4(n,a, a1,a2,a3,a4) TU_DISPA4(n,a, b1,b2,b3,b4) TU_DISPA3(n,a, c1,c2,c3) TU_DISPA3(n,a, d1,d2,d3)
// Macro to obtain a numbered macro for argument counts
// - Raw variant
-#define TU_GM_I(SUF,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,COUNT,...) SUF##COUNT
-#define TU_GM(SUF,...) TU_GM_I(SUF,__VA_ARGS__,12,11,10,9,8,7,6,5,4,3,2,1)
+#define TU_GM_I(SUF,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,COUNT,...) SUF##COUNT
+#define TU_GM(SUF,...) TU_GM_I(SUF,__VA_ARGS__,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1)
// - _DISP based variant (for iteration)
#define TU_GMX(...) TU_GM(_DISP,__VA_ARGS__)
#define TU_GMA(...) TU_GM(TU_DISPA,__VA_ARGS__)
@@ -83,12 +92,18 @@
#define MAXS10(a, b, c, d, e, f, g, h, i, j) MAX2(MAXS5(a, b, c, d, e), MAXS5(f, g, h, i, j))
#define MAXS11(a, b, c, d, e, f, g, h, i, j, k) MAX2(MAXS6(a, b, c, d, e, f), MAXS5(g, h, i, j, k))
#define MAXS12(a, b, c, d, e, f, g, h, i, j, k, l) MAX2(MAXS6(a, b, c, d, e, f), MAXS6(g, h, i, j, k, l))
+#define MAXS13(a1,a2,a3,a4,a5,a6,a7, b1,b2,b3,b4,b5,b6) MAX2(MAXS7(a1,a2,a3,a4,a5,a6,a7), MAXS6(b1,b2,b3,b4,b5,b6))
+#define MAXS14(a1,a2,a3,a4,a5,a6,a7, b1,b2,b3,b4,b5,b6,b7) MAX2(MAXS7(a1,a2,a3,a4,a5,a6,a7), MAXS7(b1,b2,b3,b4,b5,b6,b7))
// "match"-like statement
// TU_MATCH(Class, m_data, ent, (Variant, CODE), (Variant2, CODE))
#define TU_MATCH(CLASS, VAR, NAME, ...) switch( TU_FIRST VAR.tag()) {/*
*/ TU_MATCH_ARMS(CLASS, VAR, NAME, __VA_ARGS__)/*
*/}
+#define TU_MATCH_DEF(CLASS, VAR, NAME, DEF, ...) switch( TU_FIRST VAR.tag()) {/*
+*/ TU_MATCH_ARMS(CLASS, VAR, NAME, __VA_ARGS__)/*
+*/ default: {TU_EXP DEF;} break;/*
+*/}
#define TU_MATCH_BIND1(TAG, VAR, NAME) /*MATCH_BIND*/ auto& NAME = VAR.as_##TAG(); (void)&NAME;
#define TU_MATCH_BIND2_(TAG, v1,v2, n1,n2) TU_MATCH_BIND1(TAG, v1, n1) TU_MATCH_BIND1(TAG, v2, n2)
#define TU_MATCH_BIND2(...) TU_MATCH_BIND2_(__VA_ARGS__)
diff --git a/src/types.cpp b/src/types.cpp
index 4761846d..ee6588a5 100644
--- a/src/types.cpp
+++ b/src/types.cpp
@@ -369,10 +369,12 @@ bool TypeRef::impls_wildcard(const AST::Crate& crate, const AST::Path& trait) co
// - same for enums, tuples, arrays, pointers...
// - traits check the Self bounds
// CATCH: Need to handle recursion, keep a list of currently processing paths and assume true if found
- switch(ent.path.binding().type())
- {
- case AST::PathBinding::STRUCT: {
- const auto &s = ent.path.binding().bound_struct();
+ TU_MATCH_DEF(AST::PathBinding, (ent.path.binding()), (info),
+ (
+ throw CompileError::Todo("wildcard impls - auto determine path");
+ ),
+ (Struct,
+ const auto &s = *info.struct_;
GenericResolveClosure resolve_fn( s.params(), ent.path.nodes().back().args() );
for(const auto& fld : s.fields())
{
@@ -383,9 +385,10 @@ bool TypeRef::impls_wildcard(const AST::Crate& crate, const AST::Path& trait) co
if( !crate.find_impl(trait, fld_ty, nullptr, nullptr) )
return false;
}
- return true; }
- case AST::PathBinding::ENUM: {
- const auto& i = ent.path.binding().bound_enum();
+ return true;
+ ),
+ (Enum,
+ const auto& i = *info.enum_;
GenericResolveClosure resolve_fn( i.params(), ent.path.nodes().back().args() );
for( const auto& var : i.variants() )
{
@@ -399,10 +402,9 @@ bool TypeRef::impls_wildcard(const AST::Crate& crate, const AST::Path& trait) co
return false;
}
}
- return true; }
- default:
- throw CompileError::Todo("wildcard impls - auto determine path");
- }
+ return true;
+ )
+ )
)
// MultiDST is special - It only impls if this trait is in the list
// (or if a listed trait requires/impls the trait)
@@ -569,11 +571,11 @@ Ordering TypeRef::ord(const TypeRef& x) const
return OrdEqual;
)
_(Generic,
- if( m_tagged_ptr != x.m_tagged_ptr )
+ if( ent.params != x_ent.params )
{
DEBUG(*this << " == " << x);
- if( m_tagged_ptr ) DEBUG("- (L) " << *type_params_ptr());
- if( x.m_tagged_ptr ) DEBUG("- (R) " << *x.type_params_ptr());
+ if( ent.params ) DEBUG("- (L) " << *ent.params);
+ if( x_ent.params ) DEBUG("- (R) " << *x_ent.params);
throw ::std::runtime_error("BUGCHECK - Can't compare mismatched generic types");
}
else {
diff --git a/src/types.hpp b/src/types.hpp
index 17d01bb3..7612e743 100644
--- a/src/types.hpp
+++ b/src/types.hpp
@@ -98,9 +98,6 @@ TAGGED_UNION(TypeData, None,
class TypeRef:
public Serialisable
{
- /// A generic pointer, used for tagging with extra information
- /// e.g. The source TypeParams for GENERIC
- const void* m_tagged_ptr;
public:
TypeData m_data;
@@ -232,10 +229,9 @@ public:
bool is_type_param() const { return m_data.is_Generic(); }
const ::std::string& type_param() const { return m_data.as_Generic().name; }
- void set_type_params_ptr(const AST::TypeParams& p) { assert(is_type_param()); m_tagged_ptr = &p; };
+ void set_type_params_ptr(const AST::TypeParams& p) { m_data.as_Generic().params = &p; };
const AST::TypeParams* type_params_ptr() const {
- assert(is_type_param());
- return reinterpret_cast<const AST::TypeParams*>(m_tagged_ptr);
+ return reinterpret_cast<const AST::TypeParams*>( m_data.as_Generic().params );
}
bool is_reference() const { return m_data.is_Borrow(); }