diff options
author | John Hodge <tpg@mutabah.net> | 2016-07-03 12:08:29 +0800 |
---|---|---|
committer | John Hodge <tpg@mutabah.net> | 2016-07-03 12:08:29 +0800 |
commit | e6fa6b6369935d3f9aca3d608d1e5669d0e59574 (patch) | |
tree | d8926dff29f00f334c040bc1be2027ff5da9c09c | |
parent | 1d4f1e5081cbd6ed17f3ebfe5766f2c5834e95e7 (diff) | |
download | mrust-e6fa6b6369935d3f9aca3d608d1e5669d0e59574.tar.gz |
HIR Typecheck CS - Almost ready to invoke
-rw-r--r-- | src/hir_typeck/expr_cs.cpp | 232 |
1 files changed, 217 insertions, 15 deletions
diff --git a/src/hir_typeck/expr_cs.cpp b/src/hir_typeck/expr_cs.cpp index a241790b..d96bbf76 100644 --- a/src/hir_typeck/expr_cs.cpp +++ b/src/hir_typeck/expr_cs.cpp @@ -41,6 +41,8 @@ struct Context }; const ::HIR::Crate& m_crate; + const ::HIR::GenericParams* m_impl_params; + const ::HIR::GenericParams* m_item_params; ::std::vector<Binding> m_bindings; HMTypeInferrence m_ivars; @@ -50,9 +52,12 @@ struct Context /// Nodes that need revisiting (e.g. method calls when the receiver isn't known) ::std::vector< ::HIR::ExprNode*> to_visit; - Context(const ::HIR::Crate& crate): - m_crate(crate) - {} + Context(const ::HIR::Crate& crate, const ::HIR::GenericParams* impl_params, const ::HIR::GenericParams* item_params): + m_crate(crate), + m_impl_params( impl_params ), + m_item_params( item_params ) + { + } void add_ivars(::HIR::TypeRef& ty); // - Equate two types, with no possibility of coercion @@ -91,9 +96,10 @@ class ExprVisitor_Enum: // TEMP: List of in-scope traits for buildup ::HIR::t_trait_list m_traits; public: - ExprVisitor_Enum(Context& context, const ::HIR::TypeRef& ret_type): + ExprVisitor_Enum(Context& context, ::HIR::t_trait_list base_traits, const ::HIR::TypeRef& ret_type): context(context), - ret_type(ret_type) + ret_type(ret_type), + m_traits( mv$(base_traits) ) { } @@ -609,6 +615,7 @@ private: TODO(sp, "Hit a UfcsUnknown (" << path << ") - Is this an error?"); ), (UfcsInherent, + // TODO: What if this types has ivars? // - Locate function (and impl block) const ::HIR::TypeImpl* impl_ptr = nullptr; this->context.m_crate.find_type_impls(*e.type, [&](const auto& ty)->const auto& { @@ -1030,16 +1037,6 @@ private: }; -void Typecheck_Code_CS(Context context, const ::HIR::TypeRef& result_type, ::HIR::ExprPtr& expr) -{ - ExprVisitor_Enum visitor(context, result_type); - expr->visit(visitor); - - context.equate_types(expr->span(), result_type, expr->m_res_type); - - // TODO: Run -} - void Context::add_ivars(::HIR::TypeRef& ty) { TU_MATCH(::HIR::TypeRef::Data, (ty.m_data), (e), (Infer, @@ -1550,3 +1547,208 @@ void fix_param_count(const Span& sp, Context& context, const ::HIR::Path& path, void fix_param_count(const Span& sp, Context& context, const ::HIR::GenericPath& path, const ::HIR::GenericParams& param_defs, ::HIR::PathParams& params) { fix_param_count_(sp, context, path, param_defs, params); } + +namespace { + struct ModuleState + { + ::HIR::Crate& m_crate; + + ::HIR::GenericParams* m_impl_generics; + ::HIR::GenericParams* m_item_generics; + + ::std::vector< ::std::pair< const ::HIR::SimplePath*, const ::HIR::Trait* > > m_traits; + + ModuleState(::HIR::Crate& crate): + m_crate(crate), + m_impl_generics(nullptr), + m_item_generics(nullptr) + {} + + template<typename T> + class NullOnDrop { + T*& ptr; + public: + NullOnDrop(T*& ptr): + ptr(ptr) + {} + ~NullOnDrop() { + ptr = nullptr; + } + }; + NullOnDrop< ::HIR::GenericParams> set_impl_generics(::HIR::GenericParams& gps) { + assert( !m_impl_generics ); + m_impl_generics = &gps; + return NullOnDrop< ::HIR::GenericParams>(m_impl_generics); + } + NullOnDrop< ::HIR::GenericParams> set_item_generics(::HIR::GenericParams& gps) { + assert( !m_item_generics ); + m_item_generics = &gps; + return NullOnDrop< ::HIR::GenericParams>(m_item_generics); + } + + void push_traits(const ::HIR::Module& mod) { + auto sp = Span(); + DEBUG("Module has " << mod.m_traits.size() << " in-scope traits"); + // - Push a NULL entry to prevent parent module import lists being searched + m_traits.push_back( ::std::make_pair(nullptr, nullptr) ); + for( const auto& trait_path : mod.m_traits ) { + DEBUG("Push " << trait_path); + m_traits.push_back( ::std::make_pair( &trait_path, &this->m_crate.get_trait_by_path(sp, trait_path) ) ); + } + } + void pop_traits(const ::HIR::Module& mod) { + DEBUG("Module has " << mod.m_traits.size() << " in-scope traits"); + for(unsigned int i = 0; i < mod.m_traits.size(); i ++ ) + m_traits.pop_back(); + m_traits.pop_back(); + } + }; +} + + +typedef ::std::vector< ::std::pair<::HIR::Pattern, ::HIR::TypeRef> > t_args; +void Typecheck_Code_CS(const ModuleState& ms, t_args& args, const ::HIR::TypeRef& result_type, ::HIR::ExprPtr& expr) +{ + Context context { ms.m_crate, ms.m_impl_generics, ms.m_item_generics }; + + for( auto& arg : args ) { + context.add_binding( Span(), arg.first, arg.second ); + } + + ExprVisitor_Enum visitor(context, ms.m_traits, result_type); + expr->visit(visitor); + + context.equate_types(expr->span(), result_type, expr->m_res_type); + + // TODO: Run +} + + +namespace { + + class OuterVisitor: + public ::HIR::Visitor + { + ModuleState m_ms; + public: + OuterVisitor(::HIR::Crate& crate): + m_ms(crate) + { + } + + + public: + void visit_module(::HIR::PathChain p, ::HIR::Module& mod) override + { + m_ms.push_traits(mod); + ::HIR::Visitor::visit_module(p, mod); + m_ms.pop_traits(mod); + } + + // NOTE: This is left here to ensure that any expressions that aren't handled by higher code cause a failure + void visit_expr(::HIR::ExprPtr& exp) { + TODO(Span(), "visit_expr"); + } + + void visit_trait(::HIR::PathChain p, ::HIR::Trait& item) override + { + auto _ = this->m_ms.set_impl_generics(item.m_params); + ::HIR::Visitor::visit_trait(p, item); + } + + void visit_type_impl(::HIR::TypeImpl& impl) override + { + TRACE_FUNCTION_F("impl " << impl.m_type); + auto _ = this->m_ms.set_impl_generics(impl.m_params); + + const auto& mod = this->m_ms.m_crate.get_mod_by_path(Span(), impl.m_src_module); + m_ms.push_traits(mod); + ::HIR::Visitor::visit_type_impl(impl); + m_ms.pop_traits(mod); + } + void visit_trait_impl(const ::HIR::SimplePath& trait_path, ::HIR::TraitImpl& impl) override + { + TRACE_FUNCTION_F("impl " << trait_path << " for " << impl.m_type); + auto _ = this->m_ms.set_impl_generics(impl.m_params); + + const auto& mod = this->m_ms.m_crate.get_mod_by_path(Span(), impl.m_src_module); + m_ms.push_traits(mod); + ::HIR::Visitor::visit_trait_impl(trait_path, impl); + m_ms.pop_traits(mod); + } + void visit_marker_impl(const ::HIR::SimplePath& trait_path, ::HIR::MarkerImpl& impl) override + { + TRACE_FUNCTION_F("impl " << trait_path << " for " << impl.m_type << " { }"); + auto _ = this->m_ms.set_impl_generics(impl.m_params); + + const auto& mod = this->m_ms.m_crate.get_mod_by_path(Span(), impl.m_src_module); + m_ms.push_traits(mod); + ::HIR::Visitor::visit_marker_impl(trait_path, impl); + m_ms.pop_traits(mod); + } + + void visit_type(::HIR::TypeRef& ty) override + { + TU_IFLET(::HIR::TypeRef::Data, ty.m_data, Array, e, + this->visit_type( *e.inner ); + DEBUG("Array size " << ty); + t_args tmp; + Typecheck_Code_CS( m_ms, tmp, ::HIR::TypeRef(::HIR::CoreType::Usize), e.size ); + ) + else { + ::HIR::Visitor::visit_type(ty); + } + } + // ------ + // Code-containing items + // ------ + void visit_function(::HIR::PathChain p, ::HIR::Function& item) override { + auto _ = this->m_ms.set_item_generics(item.m_params); + if( item.m_code ) + { + DEBUG("Function code " << p); + Typecheck_Code_CS( m_ms, item.m_args, item.m_return, item.m_code ); + } + } + void visit_static(::HIR::PathChain p, ::HIR::Static& item) override { + //auto _ = this->m_ms.set_item_generics(item.m_params); + if( item.m_value ) + { + DEBUG("Static value " << p); + t_args tmp; + Typecheck_Code_CS(m_ms, tmp, item.m_type, item.m_value); + } + } + void visit_constant(::HIR::PathChain p, ::HIR::Constant& item) override { + auto _ = this->m_ms.set_item_generics(item.m_params); + if( item.m_value ) + { + DEBUG("Const value " << p); + t_args tmp; + Typecheck_Code_CS(m_ms, tmp, item.m_type, item.m_value); + } + } + void visit_enum(::HIR::PathChain p, ::HIR::Enum& item) override { + auto _ = this->m_ms.set_item_generics(item.m_params); + + // TODO: Use a different type depding on repr() + auto enum_type = ::HIR::TypeRef(::HIR::CoreType::Usize); + + // TODO: Check types too? + for(auto& var : item.m_variants) + { + TU_IFLET(::HIR::Enum::Variant, var.second, Value, e, + DEBUG("Enum value " << p << " - " << var.first); + t_args tmp; + Typecheck_Code_CS(m_ms, tmp, enum_type, e); + ) + } + } + }; +} + +//void Typecheck_Expressions(::HIR::Crate& crate) +//{ +// OuterVisitor visitor { crate }; +// visitor.visit_crate( crate ); +//} |