From 60dae965fdb55552d9328356dcfa36c015c6ef83 Mon Sep 17 00:00:00 2001 From: John Hodge Date: Wed, 1 Apr 2015 22:19:24 +0800 Subject: More work on wildcard impls --- src/ast/ast.cpp | 172 +++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 109 insertions(+), 63 deletions(-) (limited to 'src/ast/ast.cpp') diff --git a/src/ast/ast.cpp b/src/ast/ast.cpp index 0ebc3e4e..8a598977 100644 --- a/src/ast/ast.cpp +++ b/src/ast/ast.cpp @@ -38,59 +38,17 @@ SERIALISE_TYPE(MetaItem::, "AST_MetaItem", { s.item(m_sub_items); }) - -Impl Impl::make_concrete(const ::std::vector& types) const +bool ImplDef::matches(::std::vector& out_types, const Path& trait, const TypeRef& type) const { - DEBUG("types={" << types << "}"); - throw ParseError::Todo("Impl::make_concrete"); -/* - INDENT(); - - assert(m_params.n_params()); - - Impl ret( TypeParams(), m_trait, m_type ); - - auto resolver = [&](const char *name) { - int idx = m_params.find_name(name); - assert(idx >= 0); - return types[idx]; - }; - - ret.m_trait.resolve_args(resolver); - ret.m_type.resolve_args(resolver); - - for(const auto& fcn : m_functions) - { - TypeParams new_fcn_params = fcn.data.params(); - for( auto& b : new_fcn_params.bounds() ) - b.type().resolve_args(resolver); - TypeRef new_ret_type = fcn.data.rettype(); - new_ret_type.resolve_args(resolver); - Function::Arglist new_args = fcn.data.args(); - for( auto& t : new_args ) - t.second.resolve_args(resolver); - - ret.add_function( fcn.is_pub, fcn.name, Function( ::std::move(new_fcn_params), fcn.data.fcn_class(), ::std::move(new_ret_type), ::std::move(new_args), Expr() ) ); - } - - UNINDENT(); - return ret; -*/ -} - -::rust::option Impl::matches(const Path& trait, const TypeRef& type) -{ - //DEBUG("this = " << *this); - // 1. Check the type/trait counting parameters as wildcards (but flagging if one was seen) // > If that fails, just early return int trait_match = m_trait.equal_no_generic(trait); if( trait_match < 0 ) - return ::rust::option(); + return false; DEBUG("Trait " << trait << " matches " << trait_match); int type_match = m_type.equal_no_generic(type); if( type_match < 0 ) - return ::rust::option(); + return false; DEBUG("Type " << type << " matches " << type_match); // 2. If a parameter was seen, do the more expensive generic checks @@ -100,10 +58,12 @@ Impl Impl::make_concrete(const ::std::vector& types) const if( trait_match == 0 && type_match == 0 ) throw CompileError::Generic( "Unbound generic in impl" ); } - + + // If there was a fuzzy match, then make it less fuzzy. if( !(trait_match == 0 && type_match == 0) ) { - ::std::vector param_types(m_params.ty_params().size()); + out_types.clear(); + out_types.resize(m_params.ty_params().size()); try { auto c = [&](const char* name,const TypeRef& ty) { @@ -114,8 +74,8 @@ Impl Impl::make_concrete(const ::std::vector& types) const } int idx = m_params.find_name(name); assert( idx >= 0 ); - assert( (unsigned)idx < param_types.size() ); - param_types[idx].merge_with( ty ); + assert( (unsigned)idx < out_types.size() ); + out_types[idx].merge_with( ty ); }; m_trait.match_args(trait, c); m_type.match_args(type, c); @@ -123,9 +83,41 @@ Impl Impl::make_concrete(const ::std::vector& types) const catch(const CompileError::Base& e) { DEBUG("No match - " << e.what()); - return ::rust::option(); + return false; } - + + // TODO: Validate params against bounds? + } + + // Perfect match + return true; +} +::std::ostream& operator<<(::std::ostream& os, const ImplDef& impl) +{ + return os << "impl<" << impl.m_params << "> " << impl.m_trait << " for " << impl.m_type << ""; +} +SERIALISE_TYPE(ImplDef::, "AST_ImplDef", { + s << m_params; + s << m_trait; + s << m_type; +},{ + s.item(m_params); + s.item(m_trait); + s.item(m_type); +}) + + +::rust::option Impl::matches(const Path& trait, const TypeRef& type) +{ + //DEBUG("this = " << *this); + ::std::vector param_types; + + if( m_def.matches(param_types, trait, type) == false ) + { + return ::rust::option(); + } + else + { if( param_types.size() > 0 ) { for( auto& i : m_concrete_impls ) @@ -143,19 +135,54 @@ Impl Impl::make_concrete(const ::std::vector& types) const return ::rust::option( *this ); } +Impl Impl::make_concrete(const ::std::vector& types) const +{ + DEBUG("types={" << types << "}"); + throw ParseError::Todo("Impl::make_concrete"); +/* + INDENT(); + + assert(m_params.n_params()); + + Impl ret( TypeParams(), m_trait, m_type ); + + auto resolver = [&](const char *name) { + int idx = m_params.find_name(name); + assert(idx >= 0); + return types[idx]; + }; + + ret.m_trait.resolve_args(resolver); + ret.m_type.resolve_args(resolver); + + for(const auto& fcn : m_functions) + { + TypeParams new_fcn_params = fcn.data.params(); + for( auto& b : new_fcn_params.bounds() ) + b.type().resolve_args(resolver); + TypeRef new_ret_type = fcn.data.rettype(); + new_ret_type.resolve_args(resolver); + Function::Arglist new_args = fcn.data.args(); + for( auto& t : new_args ) + t.second.resolve_args(resolver); + + ret.add_function( fcn.is_pub, fcn.name, Function( ::std::move(new_fcn_params), fcn.data.fcn_class(), ::std::move(new_ret_type), ::std::move(new_args), Expr() ) ); + } + + UNINDENT(); + return ret; +*/ +} + ::std::ostream& operator<<(::std::ostream& os, const Impl& impl) { - return os << "impl<" << impl.m_params << "> " << impl.m_trait << " for " << impl.m_type << ""; + return os << impl.m_def; } SERIALISE_TYPE(Impl::, "AST_Impl", { - s << m_params; - s << m_trait; - s << m_type; + s << m_def; s << m_functions; },{ - s.item(m_params); - s.item(m_trait); - s.item(m_type); + s.item(m_def); s.item(m_functions); }) @@ -201,17 +228,36 @@ const Module& Crate::get_root_module(const ::std::string& name) const { throw ParseError::Generic("crate name unknown"); } +#if 0 +bool Crate::check_impls_wildcard(const Path& trait, const TypeRef& type) +{ + // 1. Look for a negative impl for this type + // 2. Look for a positive impl for this type (i.e. an unsafe impl) + // If none found, destructure the type + // - structs need all fields to impl this trait (cache result) + // - +} +#endif + ::rust::option Crate::find_impl(const Path& trait, const TypeRef& type) { // TODO: Do a sort to allow a binary search DEBUG("trait = " << trait << ", type = " << type); - // TODO: Support autoderef here? NO - if( trait == Path() && !type.is_path() ) + for( auto implptr : m_impl_index ) { - // You can only have 'impl { }' for user-defined types (i.e. paths) - // - Return failure - return ::rust::option(); + Impl& impl = *implptr; + ::rust::option oimpl = impl.matches(trait, TypeRef()); + if( oimpl.is_some() ) + { + // This is a wildcard trait, need to locate either a negative, or check contents + //if( check_impls_wildcard(trait, type) ) + //{ + // return ::rust::option(oimpl); + //} + throw CompileError::Todo("wildcard impls"); + } + } for( auto implptr : m_impl_index ) -- cgit v1.2.3