diff options
-rw-r--r-- | src/ast/ast.cpp | 73 | ||||
-rw-r--r-- | src/ast/ast.hpp | 30 | ||||
-rw-r--r-- | src/ast/path.cpp | 73 | ||||
-rw-r--r-- | src/ast/path.hpp | 137 | ||||
-rw-r--r-- | src/convert/ast_iterate.cpp | 25 | ||||
-rw-r--r-- | src/convert/resolve.cpp | 182 | ||||
-rw-r--r-- | src/convert/typecheck_bounds.cpp | 4 | ||||
-rw-r--r-- | src/convert/typecheck_expr.cpp | 65 | ||||
-rw-r--r-- | src/convert/typecheck_params.cpp | 78 | ||||
-rw-r--r-- | src/include/tagged_union.hpp | 27 | ||||
-rw-r--r-- | src/types.cpp | 30 | ||||
-rw-r--r-- | src/types.hpp | 8 |
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, ¶ms) )
+ 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, ¶ms) )
{
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(); }
|