From f5819ef88927734bcc36769b50d1b69de377b5db Mon Sep 17 00:00:00 2001 From: John Hodge Date: Tue, 31 Mar 2015 10:14:08 +0800 Subject: Fully convert trait name in 'impl' to be a AST:Path --- src/ast/ast.cpp | 13 ++++++++----- src/ast/ast.hpp | 14 +++++++------- src/ast/path.hpp | 2 ++ src/common.hpp | 2 +- src/convert/ast_iterate.cpp | 3 ++- src/convert/typecheck_expr.cpp | 4 ++-- src/convert/typecheck_params.cpp | 15 ++++++++++++++- src/dump_as_rust.cpp | 2 +- src/parse/root.cpp | 12 +++++++----- 9 files changed, 44 insertions(+), 23 deletions(-) (limited to 'src') diff --git a/src/ast/ast.cpp b/src/ast/ast.cpp index f5d87d72..b8e6d381 100644 --- a/src/ast/ast.cpp +++ b/src/ast/ast.cpp @@ -78,9 +78,10 @@ Impl Impl::make_concrete(const ::std::vector& types) const */ } -::rust::option Impl::matches(const TypeRef& trait, const TypeRef& type) +::rust::option Impl::matches(const Path& trait, const TypeRef& type) { DEBUG("this = " << *this); + if( m_params.ty_params().size() > 0 ) { ::std::vector param_types(m_params.ty_params().size()); @@ -92,7 +93,8 @@ Impl Impl::make_concrete(const ::std::vector& types) const assert( (unsigned)idx < param_types.size() ); param_types[idx].merge_with( ty ); }; - m_trait.match_args(trait, c); + throw CompileError::Todo("Match arguments in path for m_trait"); + //m_trait.match_args(TypeRef(trait), c); m_type.match_args(type, c); // Check that conditions match @@ -180,12 +182,13 @@ const Module& Crate::get_root_module(const ::std::string& name) const { throw ParseError::Generic("crate name unknown"); } -::rust::option Crate::find_impl(const TypeRef& trait, const TypeRef& type) +::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.is_wildcard() && !type.is_path() ) + if( trait == Path() && !type.is_path() ) { // You can only have 'impl { }' for user-defined types (i.e. paths) // - Return failure @@ -801,7 +804,7 @@ bool TypeParams::check_params(Crate& crate, ::std::vector& types, bool { const auto& trait = bound.bound(); // Check if 'type' impls 'trait' - if( !crate.find_impl(type, trait).is_some() ) + if( !crate.find_impl(trait, trait).is_some() ) { throw ::std::runtime_error( FMT("No matching impl of "<, Impl > > m_concrete_impls; public: Impl(): m_is_negative(false) {} - Impl(TypeParams params, TypeRef impl_type, TypeRef trait_type): + Impl(TypeParams params, TypeRef impl_type, Path trait_type): m_params( move(params) ), m_trait( move(trait_type) ), m_type( move(impl_type) ), @@ -457,7 +457,7 @@ public: {} struct TagNegative {}; - Impl(TagNegative, TypeParams params, TypeRef impl_type, TypeRef trait_type): + Impl(TagNegative, TypeParams params, TypeRef impl_type, Path trait_type): m_params( move(params) ), m_trait( move(trait_type) ), m_type( move(impl_type) ), @@ -472,20 +472,20 @@ public: } const TypeParams& params() const { return m_params; } - const TypeRef& trait() const { return m_trait; } + const Path& trait() const { return m_trait; } const TypeRef& type() const { return m_type; } const ItemList& functions() const { return m_functions; } const ItemList& types() const { return m_types; } TypeParams& params() { return m_params; } - TypeRef& trait() { return m_trait; } + Path& trait() { return m_trait; } TypeRef& type() { return m_type; } ItemList& functions() { return m_functions; } ItemList& types() { return m_types; } Impl make_concrete(const ::std::vector& types) const; - ::rust::option matches(const TypeRef& trait, const TypeRef& type); + ::rust::option matches(const Path& trait, const TypeRef& type); friend ::std::ostream& operator<<(::std::ostream& os, const Impl& impl); SERIALISABLE_PROTOTYPES(); @@ -693,7 +693,7 @@ public: void post_parse(); - ::rust::option find_impl(const TypeRef& trait, const TypeRef& type); + ::rust::option find_impl(const Path& trait, const TypeRef& type); Function& lookup_method(const TypeRef& type, const char *name); void load_extern_crate(::std::string name); diff --git a/src/ast/path.hpp b/src/ast/path.hpp index 94af94da..2355c88b 100644 --- a/src/ast/path.hpp +++ b/src/ast/path.hpp @@ -266,6 +266,8 @@ public: Ordering ord(const Path& x) const; bool operator==(const Path& x) const { return ord(x) == OrdEqual; } + bool operator!=(const Path& x) const { return ord(x) != OrdEqual; } + bool operator<(const Path& x) const { return ord(x) != OrdLess; } SERIALISABLE_PROTOTYPES(); void print_pretty(::std::ostream& os) const; diff --git a/src/common.hpp b/src/common.hpp index 4c8d5f23..8ab37682 100644 --- a/src/common.hpp +++ b/src/common.hpp @@ -27,7 +27,7 @@ Ordering ord(const ::std::vector& l, const ::std::vector& r) unsigned int i = 0; for(const auto& it : l) { - if( i > r.size() ) + if( i >= r.size() ) return OrdGreater; auto rv = it.ord(r[i]); diff --git a/src/convert/ast_iterate.cpp b/src/convert/ast_iterate.cpp index c6293393..a80b1f7f 100644 --- a/src/convert/ast_iterate.cpp +++ b/src/convert/ast_iterate.cpp @@ -287,7 +287,8 @@ void CASTIterator::handle_impl(AST::Path modpath, AST::Impl& impl) handle_params( impl.params() ); // Trait - handle_type( impl.trait() ); + if( impl.trait() != AST::Path() ) + handle_path( impl.trait(), MODE_TYPE ); // Type handle_type( impl.type() ); diff --git a/src/convert/typecheck_expr.cpp b/src/convert/typecheck_expr.cpp index 57678e94..4fb7f174 100644 --- a/src/convert/typecheck_expr.cpp +++ b/src/convert/typecheck_expr.cpp @@ -503,7 +503,7 @@ void CTC_NodeVisitor::visit(AST::ExprNode_CallMethod& node) else { // 2. Find inherent impl - auto oimpl = m_tc.m_crate.find_impl(TypeRef(), ltype); + auto oimpl = m_tc.m_crate.find_impl(AST::Path(), ltype); if( oimpl.is_some() ) { AST::Impl& impl = oimpl.unwrap(); @@ -522,7 +522,7 @@ void CTC_NodeVisitor::visit(AST::ExprNode_CallMethod& node) // 2. Iterate in-scope traits m_tc.iterate_traits( [&](const TypeRef& trait) { // TODO: Check trait first, then find an impl - auto oimpl = m_tc.m_crate.find_impl(trait, ltype); + auto oimpl = m_tc.m_crate.find_impl(trait.path(), ltype); if( oimpl.is_some() ) { AST::Impl& impl = oimpl.unwrap(); diff --git a/src/convert/typecheck_params.cpp b/src/convert/typecheck_params.cpp index 28c4e72a..2e4bc97c 100644 --- a/src/convert/typecheck_params.cpp +++ b/src/convert/typecheck_params.cpp @@ -30,7 +30,14 @@ class CGenericParamChecker: }; // name == "" indicates edge of a scope ::std::vector m_types_stack; + + AST::Crate& m_crate; public: + CGenericParamChecker(AST::Crate& c): + m_crate(c) + { + } + virtual void handle_path(AST::Path& path, CASTIterator::PathMode pm) override; virtual void handle_expr(AST::ExprNode& root) override; void start_scope() override; @@ -114,6 +121,12 @@ bool CGenericParamChecker::has_impl(const TypeRef& type, const AST::Path& trait) else { // Search all known impls of this trait (TODO: keep a list at the crate level) for a match to this type + auto i = m_crate.find_impl(trait, trait); + if( i.is_none() ) { + DEBUG("- Nope"); + return false; + } + throw CompileError::Todo( FMT("Search for impls on " << type << " for trait " << trait) ); } @@ -299,7 +312,7 @@ const CGenericParamChecker::LocalType* CGenericParamChecker::find_type_by_name(c void Typecheck_GenericParams(AST::Crate& crate) { DEBUG(" >>> "); - CGenericParamChecker chk; + CGenericParamChecker chk(crate); chk.handle_module(AST::Path({}), crate.root_module()); DEBUG(" <<< "); } diff --git a/src/dump_as_rust.cpp b/src/dump_as_rust.cpp index bac9d104..45c5df5d 100644 --- a/src/dump_as_rust.cpp +++ b/src/dump_as_rust.cpp @@ -636,7 +636,7 @@ void RustPrinter::handle_module(const AST::Module& mod) m_os << "\n"; m_os << indent() << "impl"; print_params(i.params()); - if( i.trait() != TypeRef() ) + if( !(i.trait() == AST::Path()) ) { m_os << " " << i.trait() << " for"; } diff --git a/src/parse/root.cpp b/src/parse/root.cpp index eefe0d52..2beac535 100644 --- a/src/parse/root.cpp +++ b/src/parse/root.cpp @@ -651,13 +651,13 @@ AST::Impl Parse_Impl(TokenStream& lex, bool is_unsafe/*=false*/) } // 2. Either a trait name (with type params), or the type to impl - TypeRef trait_type; + AST::Path trait_path; TypeRef impl_type; // - Handle negative impls, which must be a trait // "impl !Trait for Type {}" if( GET_TOK(tok, lex) == TOK_EXCLAM ) { - trait_type = Parse_Type(lex); + trait_path = Parse_Path(lex, PATH_GENERIC_TYPE); GET_CHECK_TOK(tok, lex, TOK_RWORD_FOR); impl_type = Parse_Type(lex); @@ -671,7 +671,7 @@ AST::Impl Parse_Impl(TokenStream& lex, bool is_unsafe/*=false*/) GET_CHECK_TOK(tok, lex, TOK_BRACE_CLOSE); return AST::Impl(AST::Impl::TagNegative(), ::std::move(params), - ::std::move(impl_type), ::std::move(trait_type) + ::std::move(impl_type), ::std::move(trait_path) ); } else @@ -684,7 +684,9 @@ AST::Impl Parse_Impl(TokenStream& lex, bool is_unsafe/*=false*/) if( GET_TOK(tok, lex) == TOK_RWORD_FOR ) { - trait_type = impl_type; + if( !impl_type.is_path() ) + throw ParseError::Generic(lex, "Trait was not a path"); + trait_path = impl_type.path(); // Implementing a trait for another type, get the target type if( GET_TOK(tok, lex) == TOK_DOUBLE_DOT ) { @@ -712,7 +714,7 @@ AST::Impl Parse_Impl(TokenStream& lex, bool is_unsafe/*=false*/) } GET_CHECK_TOK(tok, lex, TOK_BRACE_OPEN); - AST::Impl impl( ::std::move(params), ::std::move(impl_type), ::std::move(trait_type) ); + AST::Impl impl( ::std::move(params), ::std::move(impl_type), ::std::move(trait_path) ); // A sequence of method implementations while( GET_TOK(tok, lex) != TOK_BRACE_CLOSE ) -- cgit v1.2.3