From 76f199888f65fd21ffdae7c3518748098fdc0726 Mon Sep 17 00:00:00 2001 From: "John Hodge (sonata)" Date: Sun, 25 Jan 2015 17:59:48 +0800 Subject: Hacked in dumping as rust --- src/ast/ast.cpp | 193 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 187 insertions(+), 6 deletions(-) (limited to 'src/ast/ast.cpp') diff --git a/src/ast/ast.cpp b/src/ast/ast.cpp index 80bc3c57..7f3430f2 100644 --- a/src/ast/ast.cpp +++ b/src/ast/ast.cpp @@ -67,6 +67,87 @@ SERIALISE_TYPE_S(Pattern, { s.item(m_path); }); +Impl Impl::make_concrete(const ::std::vector& types) const +{ + DEBUG("types={" << types << "}"); + 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 TypeRef& trait, const TypeRef& type) +{ + DEBUG("this = " << *this); + if( m_params.n_params() ) + { + ::std::vector param_types(m_params.n_params()); + try + { + auto c = [&](const char* name,const TypeRef& ty){ + int idx = m_params.find_name(name); + assert( idx >= 0 ); + assert( (unsigned)idx < m_params.n_params() ); + param_types[idx].merge_with( ty ); + }; + m_trait.match_args(trait, c); + m_type.match_args(type, c); + + // Check that conditions match + // - TODO: Requires locating/checking trait implementations on types + + // The above two will throw if matching failed, so if we get here, it's a match + for( auto& i : m_concrete_impls ) + { + if( i.first == param_types ) + { + return ::rust::option(i.second); + } + } + m_concrete_impls.push_back( make_pair(param_types, this->make_concrete(param_types)) ); + return ::rust::option( m_concrete_impls.back().second ); + } + catch( const ::std::runtime_error& e ) + { + DEBUG("No match - " << e.what()); + } + } + else + { + if( m_trait == trait && m_type == type ) + { + return ::rust::option( *this ); + } + } + return ::rust::option(); +} ::std::ostream& operator<<(::std::ostream& os, const Impl& impl) { @@ -89,6 +170,25 @@ Crate::Crate(): m_load_std(true) { } + +static void iterate_module(Module& mod, ::std::function fcn) +{ + fcn(mod); + for( auto& sm : mod.submods() ) + iterate_module(sm.first, fcn); +} + +void Crate::post_parse() +{ + // Iterate all modules, grabbing pointers to all impl blocks + iterate_module(m_root_module, [this](Module& mod){ + for( auto& impl : mod.impls() ) + { + m_impl_index.push_back( &impl ); + } + }); +} + void Crate::iterate_functions(fcn_visitor_t* visitor) { m_root_module.iterate_functions(visitor, *this); @@ -107,6 +207,8 @@ const Module& Crate::get_root_module(const ::std::string& name) const { ::rust::option Crate::find_impl(const TypeRef& trait, const TypeRef& type) { + DEBUG("trait = " << trait << ", type = " << type); + // TODO: Support autoderef here? NO if( trait.is_wildcard() && !type.is_path() ) { @@ -118,10 +220,11 @@ const Module& Crate::get_root_module(const ::std::string& name) const { for( auto implptr : m_impl_index ) { Impl& impl = *implptr; - // TODO: Pass to impl for comparison (handles type params) - if( impl.trait() == trait && impl.type() == type ) + // TODO: What if there's two impls that match this combination? + ::rust::option oimpl = impl.matches(trait, type); + if( oimpl.is_some() ) { - return ::rust::option(impl); + return oimpl.unwrap(); } } DEBUG("No impl of " << trait << " for " << type); @@ -319,12 +422,12 @@ TypeRef Struct::get_field_type(const char *name, const ::std::vector& a // TODO: Should the bounds be checked here? Or is the count sufficient? for(const auto& f : m_fields) { - if( f.first == name ) + if( f.name == name ) { // Found it! if( args.size() ) { - TypeRef res = f.second; + TypeRef res = f.data; res.resolve_args( [&](const char *argname){ for(unsigned int i = 0; i < m_params.n_params(); i ++) { @@ -338,7 +441,7 @@ TypeRef Struct::get_field_type(const char *name, const ::std::vector& a } else { - return f.second; + return f.data; } } } @@ -411,6 +514,84 @@ int TypeParams::find_name(const char* name) const return -1; } +bool TypeParams::check_params(Crate& crate, const ::std::vector& types) const +{ + return check_params( crate, const_cast< ::std::vector&>(types), false ); +} +bool TypeParams::check_params(Crate& crate, ::std::vector& types, bool allow_infer) const +{ + // XXX: Make sure all params are types + { + for(const auto& p : m_params) + assert(p.is_type()); + } + + // Check parameter counts + if( types.size() > m_params.size() ) + { + throw ::std::runtime_error(FMT("Too many generic params ("<