From afbfbec7595cddc00700c5c13bc9e1d7ae6ff78e Mon Sep 17 00:00:00 2001 From: John Hodge Date: Fri, 8 Jul 2016 18:01:34 +1000 Subject: HIR Typecheck CS - Field accesses --- src/hir_typeck/expr_cs.cpp | 47 +++++++++++++++++++++++++++++++++++++++++++--- src/hir_typeck/helpers.hpp | 2 +- 2 files changed, 45 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/hir_typeck/expr_cs.cpp b/src/hir_typeck/expr_cs.cpp index 75869284..91e6e351 100644 --- a/src/hir_typeck/expr_cs.cpp +++ b/src/hir_typeck/expr_cs.cpp @@ -1373,7 +1373,6 @@ namespace { deref_res_types.pop_back(); node.m_value = ::HIR::ExprNodeP( new ::HIR::ExprNode_Deref(node.span(), mv$(node.m_value)) ); node.m_value->m_res_type = mv$(ty); - this->context.add_ivars( node.m_value->m_res_type ); deref_count -= 1; } @@ -1512,13 +1511,55 @@ namespace { } this->context.equate_types(node.span(), node.m_res_type, node.m_cache.m_arg_types.back()); + // TODO: Apply derefs! + node.m_method_path = mv$(fcn_path); this->m_completed = true; } } void visit(::HIR::ExprNode_Field& node) override { - // TODO: - TODO(node.span(), "ExprNode_Field - revisit"); + const auto& field_name = node.m_field; + TRACE_FUNCTION_F("(Field) name=" << field_name << ", ty = " << this->context.m_ivars.fmt_type(node.m_value->m_res_type)); + ::HIR::TypeRef out_type; + + // Using autoderef, locate this field + 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; + ::std::vector< ::HIR::TypeRef> deref_res_types; + + do { + const auto& ty = *current_ty; + if( ty.m_data.is_Infer() ) { + current_ty = nullptr; + break; + } + if( this->context.m_resolve.find_field(node.span(), ty, field_name, out_type) ) { + this->context.equate_types(node.span(), node.m_res_type, out_type); + break; + } + + deref_count += 1; + current_ty = this->context.m_resolve.autoderef(node.span(), ty, tmp_type); + if( current_ty ) + deref_res_types.push_back( current_ty->clone() ); + } while(current_ty); + + if( current_ty ) + { + if( deref_count > 0 ) + DEBUG("Adding " << deref_count << " dereferences"); + assert( deref_count == deref_res_types.size() ); + while( !deref_res_types.empty() ) + { + auto ty = mv$(deref_res_types.back()); + deref_res_types.pop_back(); + node.m_value = ::HIR::ExprNodeP( new ::HIR::ExprNode_Deref(node.span(), mv$(node.m_value)) ); + node.m_value->m_res_type = mv$(ty); + } + + m_completed = true; + } } void visit(::HIR::ExprNode_Literal& node) override { diff --git a/src/hir_typeck/helpers.hpp b/src/hir_typeck/helpers.hpp index 56106cf1..5d613a5c 100644 --- a/src/hir_typeck/helpers.hpp +++ b/src/hir_typeck/helpers.hpp @@ -177,9 +177,9 @@ public: /// Apply an automatic dereference const ::HIR::TypeRef* autoderef(const Span& sp, const ::HIR::TypeRef& ty, ::HIR::TypeRef& tmp_type) const; + bool find_field(const Span& sp, const ::HIR::TypeRef& ty, const ::std::string& name, /* Out -> */::HIR::TypeRef& field_type) const; private: bool find_method(const Span& sp, const HIR::t_trait_list& traits, const ::HIR::TypeRef& ty, const ::std::string& method_name, /* Out -> */::HIR::Path& fcn_path) const; - bool find_field(const Span& sp, const ::HIR::TypeRef& ty, const ::std::string& name, /* Out -> */::HIR::TypeRef& field_type) const; /// 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; -- cgit v1.2.3