From c2684e5058415746c83e38676f91bfc32d2ee6eb Mon Sep 17 00:00:00 2001 From: John Hodge Date: Tue, 31 Mar 2015 22:40:04 +0800 Subject: Root-level typecheck now up to requiring Sized --- src/ast/ast.cpp | 55 +++++++++++++++++++++------------------------ src/ast/path.cpp | 38 +++++++++++++++++++++++++++---- src/ast/path.hpp | 3 +++ src/ast/provided_module.cpp | 24 ++++++++++++++++++++ src/convert/resolve.cpp | 21 +++++++++++++---- src/types.cpp | 23 ++++--------------- 6 files changed, 107 insertions(+), 57 deletions(-) (limited to 'src') diff --git a/src/ast/ast.cpp b/src/ast/ast.cpp index c071e139..0ebc3e4e 100644 --- a/src/ast/ast.cpp +++ b/src/ast/ast.cpp @@ -92,37 +92,42 @@ Impl Impl::make_concrete(const ::std::vector& types) const if( type_match < 0 ) return ::rust::option(); DEBUG("Type " << type << " matches " << type_match); + // 2. If a parameter was seen, do the more expensive generic checks // > Involves checking that parameters are valid - if( trait_match > 0 ) - { - throw CompileError::Todo("Generic-ised match of impl trait"); - } - if( type_match > 0 ) + if( m_params.ty_params().size() ) { - throw CompileError::Todo("Generic-ised match of impl type"); - } - // 3. Return success - - if( m_params.ty_params().size() > 0 ) + if( trait_match == 0 && type_match == 0 ) + throw CompileError::Generic( "Unbound generic in impl" ); + } + + if( !(trait_match == 0 && type_match == 0) ) { ::std::vector param_types(m_params.ty_params().size()); try { - auto c = [&](const char* name,const TypeRef& ty){ + auto c = [&](const char* name,const TypeRef& ty) { + if( strcmp(name, "Self") == 0 ) { + if( ty != type ) + throw CompileError::Generic(FMT("Self mismatch : " << ty)); + return ; + } int idx = m_params.find_name(name); assert( idx >= 0 ); assert( (unsigned)idx < param_types.size() ); param_types[idx].merge_with( ty ); }; - throw CompileError::Todo("Match arguments in path for m_trait"); - //m_trait.match_args(TypeRef(trait), c); + 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 + } + catch(const CompileError::Base& e) + { + DEBUG("No match - " << e.what()); + return ::rust::option(); + } + + if( param_types.size() > 0 ) + { for( auto& i : m_concrete_impls ) { if( i.first == param_types ) @@ -130,22 +135,12 @@ Impl Impl::make_concrete(const ::std::vector& types) const 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(); + return ::rust::option( *this ); } ::std::ostream& operator<<(::std::ostream& os, const Impl& impl) diff --git a/src/ast/path.cpp b/src/ast/path.cpp index 222ce918..80344d01 100644 --- a/src/ast/path.cpp +++ b/src/ast/path.cpp @@ -419,6 +419,29 @@ Path& Path::operator+=(const Path& other) return *this; } +void Path::match_args(const Path& other, ::std::function fcn) const +{ + if( m_nodes.size() != other.m_nodes.size() ) + throw ::std::runtime_error("Type mismatch (path size)"); + for( unsigned int i = 0; i < m_nodes.size(); i++ ) + { + auto& pn1 = m_nodes[i]; + auto& pn2 = other.m_nodes[i]; + if( pn1.name() != pn2.name() ) + throw ::std::runtime_error("Type mismatch (path component)"); + + if( pn1.args().size() != pn2.args().size() ) + throw ::std::runtime_error("Type mismatch (path component param count)"); + + for( unsigned int j = 0; j < pn1.args().size(); j ++ ) + { + auto& t1 = pn1.args()[j]; + auto& t2 = pn2.args()[j]; + t1.match_args( t2, fcn ); + } + } +} + int Path::equal_no_generic(const Path& x) const { if( m_class != x.m_class ) @@ -426,6 +449,7 @@ int Path::equal_no_generic(const Path& x) const if( m_crate != x.m_crate ) return -1; + bool conditional_match = false; unsigned int i = 0; for( const auto &e : m_nodes ) { @@ -437,15 +461,21 @@ int Path::equal_no_generic(const Path& x) const if( e.args().size() || xe.args().size() ) { - // - DEBUG("e = " << e << ", xe = " << xe); - throw CompileError::Todo("Handle Path::equal_no_generic with generic"); + DEBUG("e = " << e << ", xe = " << xe); + if( e.args().size() != xe.args().size() ) + throw CompileError::BugCheck("Generics should be resolved, and hence have the correct argument count"); + for( unsigned int j = 0; j < e.args().size(); j ++ ) + { + int rv = e.args()[j].equal_no_generic( xe.args()[j] ); + if(rv < 0) return rv; + if(rv > 0) conditional_match = true; + } } i ++; } - return 0; + return (conditional_match ? 1 : 0); } Ordering Path::ord(const Path& x) const diff --git a/src/ast/path.hpp b/src/ast/path.hpp index 1bf2ba7d..a2ca316b 100644 --- a/src/ast/path.hpp +++ b/src/ast/path.hpp @@ -255,6 +255,9 @@ public: /// Resolve generic arguments within the path void resolve_args(::std::function fcn); + /// Match args + void match_args(const Path& other, ::std::function fcn) const; + bool is_trivial() const { return m_class == RELATIVE && m_nodes.size() == 1 && m_nodes[0].args().size() == 0; } diff --git a/src/ast/provided_module.cpp b/src/ast/provided_module.cpp index bb1da26b..7bea81d4 100644 --- a/src/ast/provided_module.cpp +++ b/src/ast/provided_module.cpp @@ -12,7 +12,31 @@ void AST_InitProvidedModule() }); AST::Path copy_marker_path({AST::PathNode("marker"),AST::PathNode("Copy")}); + g_compiler_module.add_impl(AST::Impl(AST::TypeParams(), TypeRef(CORETYPE_U8), copy_marker_path)); + g_compiler_module.add_impl(AST::Impl(AST::TypeParams(), TypeRef(CORETYPE_U16), copy_marker_path)); + g_compiler_module.add_impl(AST::Impl(AST::TypeParams(), TypeRef(CORETYPE_U32), copy_marker_path)); + g_compiler_module.add_impl(AST::Impl(AST::TypeParams(), TypeRef(CORETYPE_U64), copy_marker_path)); + g_compiler_module.add_impl(AST::Impl(AST::TypeParams(), TypeRef(CORETYPE_UINT), copy_marker_path)); + + g_compiler_module.add_impl(AST::Impl(AST::TypeParams(), TypeRef(CORETYPE_I8), copy_marker_path)); + g_compiler_module.add_impl(AST::Impl(AST::TypeParams(), TypeRef(CORETYPE_I16), copy_marker_path)); + g_compiler_module.add_impl(AST::Impl(AST::TypeParams(), TypeRef(CORETYPE_I32), copy_marker_path)); + g_compiler_module.add_impl(AST::Impl(AST::TypeParams(), TypeRef(CORETYPE_I64), copy_marker_path)); + g_compiler_module.add_impl(AST::Impl(AST::TypeParams(), TypeRef(CORETYPE_INT), copy_marker_path)); + g_compiler_module.add_impl(AST::Impl(AST::TypeParams(), TypeRef(CORETYPE_F32), copy_marker_path)); g_compiler_module.add_impl(AST::Impl(AST::TypeParams(), TypeRef(CORETYPE_F64), copy_marker_path)); + + // A hacky default impl of 'Sized', with a negative impl on [T] + AST::Path sized_marker_path({AST::PathNode("marker"),AST::PathNode("Sized")}); + g_compiler_module.add_impl(AST::Impl(AST::TypeParams(), TypeRef(), copy_marker_path)); + AST::TypeParams tps; + tps.add_ty_param( AST::TypeParam("T") ); + g_compiler_module.add_impl(AST::Impl( + AST::Impl::TagNegative(), + ::std::move(tps), + TypeRef(TypeRef::TagUnsizedArray(), TypeRef(TypeRef::TagArg(), "T")), + copy_marker_path + )); } diff --git a/src/convert/resolve.cpp b/src/convert/resolve.cpp index 3e690f61..bca0f576 100644 --- a/src/convert/resolve.cpp +++ b/src/convert/resolve.cpp @@ -23,15 +23,15 @@ class CPathResolver: VAR, } type; ::std::string name; - AST::Path path; + TypeRef tr; LocalItem(): type(VAR), name() {} - LocalItem(Type t, ::std::string name, AST::Path path=AST::Path()): + LocalItem(Type t, ::std::string name, TypeRef tr=TypeRef()): type(t), name( ::std::move(name) ), - path( ::std::move(path) ) + tr( ::std::move(tr) ) {} friend ::std::ostream& operator<<(::std::ostream& os, const LocalItem& x) { @@ -60,7 +60,7 @@ public: virtual void start_scope() override; virtual void local_type(::std::string name, TypeRef type) override { - m_locals.push_back( LocalItem(LocalItem::TYPE, ::std::move(name)) ); + m_locals.push_back( LocalItem(LocalItem::TYPE, ::std::move(name), ::std::move(type)) ); } virtual void local_variable(bool _is_mut, ::std::string name, const TypeRef& _type) override { m_locals.push_back( LocalItem(LocalItem::VAR, ::std::move(name)) ); @@ -500,6 +500,19 @@ void CPathResolver::handle_type(TypeRef& type) // Not a type param, fall back to other checks } } + + //if( type.is_type_param() && type.type_param() == "Self" ) + //{ + // auto l = lookup_local(LocalItem::TYPE, "Self"); + // if( l.is_some() ) + // { + // type = l.unwrap().tr; + // DEBUG("Replacing Self with " << type); + // // TODO: Can this recurse? + // handle_type(type); + // return ; + // } + //} CASTIterator::handle_type(type); DEBUG("res = " << type); } diff --git a/src/types.cpp b/src/types.cpp index e9460886..329e93f8 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -245,25 +245,7 @@ void TypeRef::match_args(const TypeRef& other, ::std::function