summaryrefslogtreecommitdiff
path: root/src/ast/ast.cpp
diff options
context:
space:
mode:
authorJohn Hodge <tpg@mutabah.net>2015-04-01 22:19:24 +0800
committerJohn Hodge <tpg@mutabah.net>2015-04-01 22:19:24 +0800
commit60dae965fdb55552d9328356dcfa36c015c6ef83 (patch)
treec7e653bc2305047570aff0afcd3b9a8fc7cd1661 /src/ast/ast.cpp
parentc2684e5058415746c83e38676f91bfc32d2ee6eb (diff)
downloadmrust-60dae965fdb55552d9328356dcfa36c015c6ef83.tar.gz
More work on wildcard impls
Diffstat (limited to 'src/ast/ast.cpp')
-rw-r--r--src/ast/ast.cpp172
1 files changed, 109 insertions, 63 deletions
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<TypeRef>& types) const
+bool ImplDef::matches(::std::vector<TypeRef>& 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&> 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<Impl&>();
+ return false;
DEBUG("Trait " << trait << " matches " << trait_match);
int type_match = m_type.equal_no_generic(type);
if( type_match < 0 )
- return ::rust::option<Impl&>();
+ 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<TypeRef>& 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<TypeRef> 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<TypeRef>& 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<TypeRef>& types) const
catch(const CompileError::Base& e)
{
DEBUG("No match - " << e.what());
- return ::rust::option<Impl&>();
+ 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&> Impl::matches(const Path& trait, const TypeRef& type)
+{
+ //DEBUG("this = " << *this);
+ ::std::vector<TypeRef> param_types;
+
+ if( m_def.matches(param_types, trait, type) == false )
+ {
+ return ::rust::option<Impl&>();
+ }
+ else
+ {
if( param_types.size() > 0 )
{
for( auto& i : m_concrete_impls )
@@ -143,19 +135,54 @@ Impl Impl::make_concrete(const ::std::vector<TypeRef>& types) const
return ::rust::option<Impl&>( *this );
}
+Impl Impl::make_concrete(const ::std::vector<TypeRef>& 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<Impl&> 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 <type> { }' for user-defined types (i.e. paths)
- // - Return failure
- return ::rust::option<Impl&>();
+ Impl& impl = *implptr;
+ ::rust::option<Impl&> 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<Impl&>(oimpl);
+ //}
+ throw CompileError::Todo("wildcard impls");
+ }
+
}
for( auto implptr : m_impl_index )