diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/hir_typeck/expr.cpp | 63 | ||||
-rw-r--r-- | src/hir_typeck/expr.hpp | 1 | ||||
-rw-r--r-- | src/hir_typeck/expr_context.cpp | 68 |
3 files changed, 86 insertions, 46 deletions
diff --git a/src/hir_typeck/expr.cpp b/src/hir_typeck/expr.cpp index cb335ad9..ed4d9965 100644 --- a/src/hir_typeck/expr.cpp +++ b/src/hir_typeck/expr.cpp @@ -1065,11 +1065,66 @@ namespace typeck { // - Index: Look for implementation of the Index trait void visit(::HIR::ExprNode_Index& node) override { - this->context.find_trait_impls(this->context.m_crate.get_lang_item_path(node.span(), "index"), node.m_value->m_res_type, [&](const auto& args) { - DEBUG("TODO: Insert index operator (if index arg matches)"); - return false; - }); + TRACE_FUNCTION_FR("_Index","_Index"); ::HIR::ExprVisitorDef::visit(node); + const auto& path_Index = this->context.m_crate.get_lang_item_path(node.span(), "index"); + + const auto& index_ty = this->context.get_type(node.m_index->m_res_type); + // NOTE: Indexing triggers autoderef + unsigned int deref_count = 0; + ::HIR::TypeRef tmp_type; // Temporary type used for handling Deref + const auto* current_ty = &node.m_value->m_res_type; + do { + const auto& ty = this->context.get_type(*current_ty); + DEBUG("_Index: (: " << ty << ")[: " << index_ty << "]"); + bool rv = this->context.find_trait_impls(path_Index, ty, [&](const auto& args) { + assert( args.m_types.size() == 1 ); + const auto& impl_index = args.m_types[0]; + + auto cmp = impl_index.compare_with_paceholders(node.span(), index_ty, this->context.callback_resolve_infer()); + if( cmp == ::HIR::Compare::Unequal) + return false; + if( cmp == ::HIR::Compare::Equal ) { + return true; + } + DEBUG("TODO: Handle fuzzy match index operator " << impl_index); + return false; + }); + if( rv ) { + break; + } + + deref_count += 1; + current_ty = this->context.autoderef(node.span(), ty, tmp_type); + } while( current_ty ); + + if( current_ty ) + { + if( deref_count > 0 ) + DEBUG("Adding " << deref_count << " dereferences"); + while( deref_count > 0 ) + { + node.m_value = ::HIR::ExprNodeP( new ::HIR::ExprNode_Deref(node.span(), mv$(node.m_value)) ); + this->context.add_ivars( node.m_value->m_res_type ); + deref_count -= 1; + } + + // Set output to `< "*current_ty" as Index<"index_ty> >::Output` + // TODO: Get the output type from the bound/impl in `find_trait_impls` + auto tp = ::HIR::GenericPath( path_Index ); + tp.m_params.m_types.push_back( index_ty.clone() ); + auto out_type = ::HIR::TypeRef::new_path( + ::HIR::Path(::HIR::Path::Data::Data_UfcsKnown { + box$(this->context.get_type(*current_ty).clone()), + mv$(tp), + "Output", + {} + }), + {} + ); + + this->context.apply_equality( node.span(), node.m_res_type, out_type ); + } } // - Deref: Look for impl of Deref void visit(::HIR::ExprNode_Deref& node) override diff --git a/src/hir_typeck/expr.hpp b/src/hir_typeck/expr.hpp index c4e8cdc4..749c7d1a 100644 --- a/src/hir_typeck/expr.hpp +++ b/src/hir_typeck/expr.hpp @@ -149,6 +149,7 @@ public: /// Locates a named method in a trait, and returns the path of the trait that contains it (with fixed parameters) bool trait_contains_method(const Span& sp, const ::HIR::GenericPath& trait_path, const ::HIR::Trait& trait_ptr, const ::std::string& name, ::HIR::GenericPath& out_path) const; + const ::HIR::TypeRef* autoderef(const Span& sp, const ::HIR::TypeRef& ty, ::HIR::TypeRef& tmp_type) const; /// Locate the named method by applying auto-dereferencing. /// \return Number of times deref was applied (or ~0 if _ was hit) unsigned int autoderef_find_method(const Span& sp, const ::HIR::TypeRef& top_ty, const ::std::string& method_name, /* Out -> */::HIR::Path& fcn_path) const; diff --git a/src/hir_typeck/expr_context.cpp b/src/hir_typeck/expr_context.cpp index 1bbcb96a..a52d9719 100644 --- a/src/hir_typeck/expr_context.cpp +++ b/src/hir_typeck/expr_context.cpp @@ -1562,6 +1562,30 @@ bool typeck::TypecheckContext::trait_contains_method(const Span& sp, const ::HIR // ------------------------------------------------------------------------------------------------------------------- // // ------------------------------------------------------------------------------------------------------------------- +const ::HIR::TypeRef* typeck::TypecheckContext::autoderef(const Span& sp, const ::HIR::TypeRef& ty, ::HIR::TypeRef& tmp_type) const +{ + TU_IFLET(::HIR::TypeRef::Data, ty.m_data, Borrow, e, + DEBUG("Deref " << ty << " into " << *e.inner); + return &*e.inner; + ) + else TU_IFLET(::HIR::TypeRef::Data, ty.m_data, Array, e, + DEBUG("Deref " << ty << " into [" << *e.inner << "]"); + tmp_type = ::HIR::TypeRef::new_slice( e.inner->clone() ); + return &tmp_type; + ) + else { + // TODO: Search for a Deref impl + bool succ = this->find_trait_impls(this->m_crate.get_lang_item_path(sp, "deref"), ty, [&](const auto& args) { + return true; + }); + if( succ ) { + TODO(sp, "Found a Deref impl for " << ty << ", use the output of it"); + } + else { + return nullptr; + } + } +} unsigned int typeck::TypecheckContext::autoderef_find_method(const Span& sp, const ::HIR::TypeRef& top_ty, const ::std::string& method_name, /* Out -> */::HIR::Path& fcn_path) const { unsigned int deref_count = 0; @@ -1584,27 +1608,7 @@ unsigned int typeck::TypecheckContext::autoderef_find_method(const Span& sp, con // 3. Dereference and try again deref_count += 1; - TU_IFLET(::HIR::TypeRef::Data, ty.m_data, Borrow, e, - DEBUG("Deref " << ty << " into " << *e.inner); - current_ty = &*e.inner; - ) - else TU_IFLET(::HIR::TypeRef::Data, ty.m_data, Array, e, - DEBUG("Deref " << ty << " into [" << *e.inner << "]"); - tmp_type = ::HIR::TypeRef::new_slice( e.inner->clone() ); - current_ty = &tmp_type; - ) - else { - // TODO: Search for a Deref impl - bool succ = this->find_trait_impls(this->m_crate.get_lang_item_path(sp, "deref"), ty, [&](const auto& args) { - return true; - }); - if( succ ) { - TODO(sp, "Found a Deref impl for " << ty << ", use the output of it"); - } - else { - current_ty = nullptr; - } - } + current_ty = this->autoderef(sp, ty, tmp_type); } while( current_ty ); TU_IFLET(::HIR::TypeRef::Data, this->get_type(top_ty).m_data, Borrow, e, @@ -1771,27 +1775,7 @@ unsigned int typeck::TypecheckContext::autoderef_find_field(const Span& sp, cons // 3. Dereference and try again deref_count += 1; - TU_IFLET(::HIR::TypeRef::Data, ty.m_data, Borrow, e, - DEBUG("Deref " << ty << " into " << *e.inner); - current_ty = &*e.inner; - ) - else TU_IFLET(::HIR::TypeRef::Data, ty.m_data, Array, e, - DEBUG("Deref " << ty << " into [" << *e.inner << "]"); - tmp_type = ::HIR::TypeRef::new_slice( e.inner->clone() ); - current_ty = &tmp_type; - ) - else { - // TODO: Search for a Deref impl - bool succ = this->find_trait_impls(this->m_crate.get_lang_item_path(sp, "deref"), ty, [&](const auto& args) { - return true; - }); - if( succ ) { - TODO(sp, "Found a Deref impl for " << ty << ", use the output of it"); - } - else { - current_ty = nullptr; - } - } + current_ty = this->autoderef(sp, ty, tmp_type); } while( current_ty ); TU_IFLET(::HIR::TypeRef::Data, this->get_type(top_ty).m_data, Borrow, e, |