diff options
author | John Hodge <tpg@mutabah.net> | 2016-07-02 14:39:54 +0800 |
---|---|---|
committer | John Hodge <tpg@mutabah.net> | 2016-07-02 14:40:18 +0800 |
commit | 82806102bd9075e25f326484249f3c63a58160f5 (patch) | |
tree | f6fd67d849e24fddfc479230340c8929b0b73f26 /src | |
parent | e2b52c8f7c72b1587eca350d6957c3d9fca0900d (diff) | |
download | mrust-82806102bd9075e25f326484249f3c63a58160f5.tar.gz |
HIR - CS Typecheck work, Store 'is_struct' flag in StructLiteral node
Diffstat (limited to 'src')
-rw-r--r-- | src/hir/expr.hpp | 4 | ||||
-rw-r--r-- | src/hir/from_ast_expr.cpp | 11 | ||||
-rw-r--r-- | src/hir_typeck/expr_cs.cpp | 172 |
3 files changed, 152 insertions, 35 deletions
diff --git a/src/hir/expr.hpp b/src/hir/expr.hpp index 67548069..36fd8bef 100644 --- a/src/hir/expr.hpp +++ b/src/hir/expr.hpp @@ -580,14 +580,16 @@ struct ExprNode_StructLiteral: typedef ::std::vector< ::std::pair< ::std::string, ExprNodeP > > t_values; ::HIR::GenericPath m_path; + bool m_is_struct; ::HIR::ExprNodeP m_base_value; t_values m_values; ::std::vector< ::HIR::TypeRef> m_value_types; - ExprNode_StructLiteral(Span sp, ::HIR::GenericPath path, ::HIR::ExprNodeP base_value, t_values values): + ExprNode_StructLiteral(Span sp, ::HIR::GenericPath path, bool is_struct, ::HIR::ExprNodeP base_value, t_values values): ExprNode( mv$(sp) ), m_path( mv$(path) ), + m_is_struct( is_struct ), m_base_value( mv$(base_value) ), m_values( mv$(values) ) { diff --git a/src/hir/from_ast_expr.cpp b/src/hir/from_ast_expr.cpp index 13b0f47c..f0190c1b 100644 --- a/src/hir/from_ast_expr.cpp +++ b/src/hir/from_ast_expr.cpp @@ -117,15 +117,15 @@ struct LowerHIR_ExprNode_Visitor: if( v.m_left ) { if( v.m_right ) { - m_rv.reset( new ::HIR::ExprNode_StructLiteral(v.span(), mv$(path_Range), nullptr, mv$(values)) ); + m_rv.reset( new ::HIR::ExprNode_StructLiteral(v.span(), mv$(path_Range), true, nullptr, mv$(values)) ); } else { - m_rv.reset( new ::HIR::ExprNode_StructLiteral(v.span(), mv$(path_RangeFrom), nullptr, mv$(values)) ); + m_rv.reset( new ::HIR::ExprNode_StructLiteral(v.span(), mv$(path_RangeFrom), true, nullptr, mv$(values)) ); } } else { if( v.m_right ) { - m_rv.reset( new ::HIR::ExprNode_StructLiteral(v.span(), mv$(path_RangeTo), nullptr, mv$(values)) ); + m_rv.reset( new ::HIR::ExprNode_StructLiteral(v.span(), mv$(path_RangeTo), true, nullptr, mv$(values)) ); } else { m_rv.reset( new ::HIR::ExprNode_UnitVariant(v.span(), mv$(path_RangeFull), true) ); @@ -142,13 +142,13 @@ struct LowerHIR_ExprNode_Visitor: ::HIR::ExprNode_StructLiteral::t_values values; values.push_back( ::std::make_pair( ::std::string("start"), LowerHIR_ExprNode_Inner( *v.m_left ) ) ); values.push_back( ::std::make_pair( ::std::string("end") , LowerHIR_ExprNode_Inner( *v.m_right ) ) ); - m_rv.reset( new ::HIR::ExprNode_StructLiteral(v.span(), mv$(path_RangeInclusive_NonEmpty), nullptr, mv$(values)) ); + m_rv.reset( new ::HIR::ExprNode_StructLiteral(v.span(), mv$(path_RangeInclusive_NonEmpty), true, nullptr, mv$(values)) ); } else { ::HIR::ExprNode_StructLiteral::t_values values; values.push_back( ::std::make_pair( ::std::string("end") , LowerHIR_ExprNode_Inner( *v.m_right ) ) ); - m_rv.reset( new ::HIR::ExprNode_StructLiteral(v.span(), mv$(path_RangeToInclusive), nullptr, mv$(values)) ); + m_rv.reset( new ::HIR::ExprNode_StructLiteral(v.span(), mv$(path_RangeToInclusive), true, nullptr, mv$(values)) ); } break; } case ::AST::ExprNode_BinOp::PLACE_IN: @@ -513,6 +513,7 @@ struct LowerHIR_ExprNode_Visitor: values.push_back( ::std::make_pair(val.first, LowerHIR_ExprNode_Inner(*val.second)) ); m_rv.reset( new ::HIR::ExprNode_StructLiteral( v.span(), LowerHIR_GenericPath(v.get_pos(), v.m_path), + v.m_path.binding().is_Struct(), LowerHIR_ExprNode_Inner_Opt(v.m_base_value.get()), mv$(values) ) ); diff --git a/src/hir_typeck/expr_cs.cpp b/src/hir_typeck/expr_cs.cpp index 25fd87a1..878fef85 100644 --- a/src/hir_typeck/expr_cs.cpp +++ b/src/hir_typeck/expr_cs.cpp @@ -16,6 +16,11 @@ // PLAN: Build up a set of conditions that are easier to solve struct Context { + struct Binding + { + ::HIR::TypeRef ty; + unsigned int ivar; + }; struct IVar { //unsigned int unified_with; @@ -37,6 +42,9 @@ struct Context ::HIR::ExprNodeP* node_ptr_ptr; }; + const ::HIR::Crate& m_crate; + + ::std::vector<Binding> bindings; ::std::vector<IVar> ivars; ::std::vector<TyEq> links; @@ -45,6 +53,9 @@ 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) + {} void add_ivars(::HIR::TypeRef& ty); // - Equate two types, with no possibility of coercion @@ -53,9 +64,12 @@ struct Context void equate_types(const Span& sp, const ::HIR::TypeRef& l, const ::HIR::TypeRef& r); // - Equate two types, allowing inferrence void equate_types_coerce(const Span& sp, const ::HIR::TypeRef& l, ::HIR::ExprNodeP& node_ptr); + // - Equate + void equate_types_assoc(const Span& sp, const ::HIR::TypeRef& l, const ::HIR::SimplePath& trait, const ::std::vector< ::HIR::TypeRef>& ty_args, const ::HIR::TypeRef& impl_ty, const char *name); - // - Add a pattern binding + // - Add a pattern binding (forcing the type to match) void add_binding(const Span& sp, ::HIR::Pattern& pat, ::HIR::TypeRef& type); + const ::HIR::TypeRef& get_var(const Span& sp, unsigned int idx) const; // - Add a revisit entry void add_revisit(::HIR::ExprNode& node); @@ -80,6 +94,7 @@ public: void visit(::HIR::ExprNode_Block& node) override { + TRACE_FUNCTION_F("{ ... }"); this->context.push_traits( node.m_traits ); for( unsigned int i = 0; i < node.m_nodes.size(); i ++ ) @@ -91,6 +106,8 @@ public: } else { // TODO: Ignore? or force to ()? - Depends on inner + // - Blocks (and block-likes) are forced to () + // - What if they were '({});'? Then they're left dangling } snp->visit(*this); } @@ -99,7 +116,9 @@ public: } void visit(::HIR::ExprNode_Return& node) override { + TRACE_FUNCTION_F("return ..."); this->context.add_ivars( node.m_value->m_res_type ); + this->context.equate_types_coerce(node.span(), this->ret_type, node.m_value); node.m_value->visit( *this ); @@ -107,13 +126,15 @@ public: void visit(::HIR::ExprNode_Loop& node) override { - this->context.add_ivars( node.m_code->m_res_type ); - this->context.equate_types(node.span(), this->ret_type, node.m_code->m_res_type); + TRACE_FUNCTION_F("loop { ... }"); + + // TODO: Node must return ()? node.m_code->visit( *this ); } void visit(::HIR::ExprNode_LoopControl& node) override { + TRACE_FUNCTION_F((node.m_continue ? "continue" : "break") << " '" << node.m_label); // Nothing } @@ -183,16 +204,39 @@ public: void visit(::HIR::ExprNode_Assign& node) override { TRACE_FUNCTION_F("... = ..."); + this->context.add_ivars( node.m_slot ->m_res_type ); + this->context.add_ivars( node.m_value->m_res_type ); + // Plain assignment can't be overloaded, requires equal types if( node.m_op == ::HIR::ExprNode_Assign::Op::None ) { this->context.equate_types_coerce(node.span(), node.m_slot->m_res_type, node.m_value); - - node.m_slot->visit( *this ); - node.m_value->visit( *this ); } else { - // TODO: Type inferrence using the += + // Type inferrence using the += + // - "" as type name to indicate that it's just using the trait magic? + const char *lang_item = nullptr; + switch( node.m_op ) + { + case ::HIR::ExprNode_Assign::Op::None: throw ""; + case ::HIR::ExprNode_Assign::Op::Add: lang_item = "add_assign"; break; + case ::HIR::ExprNode_Assign::Op::Sub: lang_item = "sub_assign"; break; + case ::HIR::ExprNode_Assign::Op::Mul: lang_item = "mul_assign"; break; + case ::HIR::ExprNode_Assign::Op::Div: lang_item = "div_assign"; break; + case ::HIR::ExprNode_Assign::Op::Mod: lang_item = "rem_assign"; break; + case ::HIR::ExprNode_Assign::Op::And: lang_item = "bitand_assign"; break; + case ::HIR::ExprNode_Assign::Op::Or : lang_item = "bitor_assign" ; break; + case ::HIR::ExprNode_Assign::Op::Xor: lang_item = "bitxor_assign"; break; + case ::HIR::ExprNode_Assign::Op::Shr: lang_item = "shl_assign"; break; + case ::HIR::ExprNode_Assign::Op::Shl: lang_item = "shr_assign"; break; + } + assert(lang_item); + const auto& trait_path = this->context.m_crate.get_lang_item_path(node.span(), lang_item); + + this->context.equate_types_assoc(node.span(), ::HIR::TypeRef(), trait_path, ::make_vec1(node.m_value->m_res_type.clone()), node.m_slot->m_res_type.clone(), ""); } + + node.m_slot->visit( *this ); + node.m_value->visit( *this ); } void visit(::HIR::ExprNode_BinOp& node) override { @@ -207,11 +251,25 @@ public: case ::HIR::ExprNode_BinOp::Op::CmpLt: case ::HIR::ExprNode_BinOp::Op::CmpLtE: case ::HIR::ExprNode_BinOp::Op::CmpGt: - case ::HIR::ExprNode_BinOp::Op::CmpGtE: + case ::HIR::ExprNode_BinOp::Op::CmpGtE: { this->context.equate_types(node.span(), node.m_res_type, ::HIR::TypeRef(::HIR::CoreType::Bool)); - // Revisit to handle inferrence from trait impls - this->context.add_revisit(node); - break; + + const char* item_name = nullptr; + switch(node.m_op) + { + case ::HIR::ExprNode_BinOp::Op::CmpEqu: item_name = "eq"; break; + case ::HIR::ExprNode_BinOp::Op::CmpNEqu: item_name = "eq"; break; + case ::HIR::ExprNode_BinOp::Op::CmpLt: item_name = "ord"; break; + case ::HIR::ExprNode_BinOp::Op::CmpLtE: item_name = "ord"; break; + case ::HIR::ExprNode_BinOp::Op::CmpGt: item_name = "ord"; break; + case ::HIR::ExprNode_BinOp::Op::CmpGtE: item_name = "ord"; break; + default: break; + } + assert(item_name); + const auto& op_trait = this->context.m_crate.get_lang_item_path(node.span(), item_name); + + this->context.equate_types_assoc(node.span(), ::HIR::TypeRef(), op_trait, ::make_vec1(node.m_right->m_res_type.clone()), node.m_left->m_res_type.clone(), ""); + break; } case ::HIR::ExprNode_BinOp::Op::BoolAnd: case ::HIR::ExprNode_BinOp::Op::BoolOr: @@ -219,11 +277,37 @@ public: this->context.equate_types(node.span(), node.m_left ->m_res_type, ::HIR::TypeRef(::HIR::CoreType::Bool)); this->context.equate_types(node.span(), node.m_right->m_res_type, ::HIR::TypeRef(::HIR::CoreType::Bool)); break; - default: - // Revisit to handle inferrence from trait impls - this->context.add_revisit(node); - //this->context.add_assoc(node.span(), node.m_res_type, op_trait(node.m_op), {node.m_left->m_res_type.clone(), node.m_res_type->m_res_type.clone()}, "Output"); - break; + default: { + const char* item_name = nullptr; + switch(node.m_op) + { + case ::HIR::ExprNode_BinOp::Op::CmpEqu: throw ""; + case ::HIR::ExprNode_BinOp::Op::CmpNEqu: throw ""; + case ::HIR::ExprNode_BinOp::Op::CmpLt: throw ""; + case ::HIR::ExprNode_BinOp::Op::CmpLtE: throw ""; + case ::HIR::ExprNode_BinOp::Op::CmpGt: throw ""; + case ::HIR::ExprNode_BinOp::Op::CmpGtE: throw ""; + case ::HIR::ExprNode_BinOp::Op::BoolAnd: throw ""; + case ::HIR::ExprNode_BinOp::Op::BoolOr: throw ""; + + case ::HIR::ExprNode_BinOp::Op::Add: item_name = "add"; break; + case ::HIR::ExprNode_BinOp::Op::Sub: item_name = "sub"; break; + case ::HIR::ExprNode_BinOp::Op::Mul: item_name = "mul"; break; + case ::HIR::ExprNode_BinOp::Op::Div: item_name = "div"; break; + case ::HIR::ExprNode_BinOp::Op::Mod: item_name = "rem"; break; + + case ::HIR::ExprNode_BinOp::Op::And: item_name = "bitand"; break; + case ::HIR::ExprNode_BinOp::Op::Or: item_name = "bitor"; break; + case ::HIR::ExprNode_BinOp::Op::Xor: item_name = "bitxor"; break; + + case ::HIR::ExprNode_BinOp::Op::Shr: item_name = "shr"; break; + case ::HIR::ExprNode_BinOp::Op::Shl: item_name = "shl"; break; + } + assert(item_name); + const auto& op_trait = this->context.m_crate.get_lang_item_path(node.span(), item_name); + + this->context.equate_types_assoc(node.span(), node.m_res_type, op_trait, ::make_vec1(node.m_right->m_res_type.clone()), node.m_left->m_res_type.clone(), "Output"); + break; } } node.m_left ->visit( *this ); node.m_right->visit( *this ); @@ -235,16 +319,16 @@ public: switch(node.m_op) { case ::HIR::ExprNode_UniOp::Op::Ref: - //this->context.equate_types(node.span(), node.m_res_type, ::HIR::TypeRef::new_borrow(::HIR::BorrowType::Shared, node.m_value->m_res_type.clone())); + // TODO: Can Ref/RefMut trigger coercions? + this->context.equate_types(node.span(), node.m_res_type, ::HIR::TypeRef::new_borrow(::HIR::BorrowType::Shared, node.m_value->m_res_type.clone())); break; case ::HIR::ExprNode_UniOp::Op::RefMut: - //this->context.equate_types(node.span(), node.m_res_type, ::HIR::TypeRef::new_borrow(::HIR::BorrowType::Unique, node.m_value->m_res_type.clone())); + this->context.equate_types(node.span(), node.m_res_type, ::HIR::TypeRef::new_borrow(::HIR::BorrowType::Unique, node.m_value->m_res_type.clone())); break; case ::HIR::ExprNode_UniOp::Op::Invert: + this->context.equate_types_assoc(node.span(), node.m_res_type, this->context.m_crate.get_lang_item_path(node.span(), "not"), {}, node.m_value->m_res_type.clone(), "Output"); case ::HIR::ExprNode_UniOp::Op::Negate: - // TODO: Revisit to handle traits - this->context.add_revisit(node); - //this->context.add_assoc(node.span(), node.m_res_type, op_trait(node.m_op), {}, node.m_value->m_res_type.clone(), "Output"); + this->context.equate_types_assoc(node.span(), node.m_res_type, this->context.m_crate.get_lang_item_path(node.span(), "minus"), {}, node.m_value->m_res_type.clone(), "Output"); break; } node.m_value->visit( *this ); @@ -266,8 +350,8 @@ public: this->context.add_ivars( node.m_value->m_res_type ); this->context.add_ivars( node.m_index->m_res_type ); - this->context.add_revisit(node); - //this->context.add_assoc(node.span(), node.m_res_type, lang_item("index"), {node.m_index->m_res_type.clone()}, node.m_value->m_res_type.clone(), "Output"); + const auto& op_trait = this->context.m_crate.get_lang_item_path(node.span(), "index"); + this->context.equate_types_assoc(node.span(), node.m_res_type, op_trait, ::make_vec1(node.m_index->m_res_type.clone()), node.m_value->m_res_type.clone(), "Output"); node.m_value->visit( *this ); node.m_index->visit( *this ); @@ -277,7 +361,8 @@ public: TRACE_FUNCTION_F("*..."); this->context.add_ivars( node.m_value->m_res_type ); - //this->context.add_assoc(node.span(), node.m_res_type, lang_item("deref"), {}, node.m_value->m_res_type.clone(), "Output"); + const auto& op_trait = this->context.m_crate.get_lang_item_path(node.span(), "deref"); + this->context.equate_types_assoc(node.span(), node.m_res_type, op_trait, {}, node.m_value->m_res_type.clone(), "Target"); node.m_value->visit( *this ); } @@ -289,7 +374,8 @@ public: this->context.add_ivars( val->m_res_type ); } - // TODO: Cleanly equate with enum/struct + // TODO: Result type + // TODO: Bind fields with type params for( auto& val : node.m_args ) { val->visit( *this ); @@ -297,12 +383,13 @@ public: } void visit(::HIR::ExprNode_StructLiteral& node) override { - TRACE_FUNCTION_F(node.m_path << "{...} [" << (true /*node.m_is_struct*/ ? "struct" : "enum") << "]"); + TRACE_FUNCTION_F(node.m_path << "{...} [" << (node.m_is_struct ? "struct" : "enum") << "]"); for( auto& val : node.m_values ) { this->context.add_ivars( val.second->m_res_type ); } - // TODO: Cleanly equate with enum/struct + // TODO: Result type + // TODO: Bind fields with type params for( auto& val : node.m_values ) { val.second->visit( *this ); @@ -435,14 +522,30 @@ public: { TRACE_FUNCTION_F(node.m_name << "{" << node.m_slot << "}"); - // TODO: Bind result to variable's ivar + this->context.equate_types(node.span(), node.m_res_type, this->context.get_var(node.span(), node.m_slot)); } void visit(::HIR::ExprNode_Closure& node) override { TRACE_FUNCTION_F("|...| ..."); + for(auto& arg : node.m_args) { + this->context.add_ivars( arg.second ); + this->context.add_binding( node.span(), arg.first, arg.second ); + } + this->context.add_ivars( node.m_return ); + this->context.add_ivars( node.m_code->m_res_type ); - // TODO: Closure + // Closure result type + ::HIR::TypeRef::Data::Data_Closure ty_data; + for(auto& arg : node.m_args) { + ty_data.m_arg_types.push_back( arg.second.clone() ); + } + ty_data.m_rettype = box$( node.m_return.clone() ); + this->context.equate_types( node.span(), node.m_res_type, ::HIR::TypeRef( ::HIR::TypeRef::Data::make_Closure(mv$(ty_data)) ) ); + + this->context.equate_types_coerce( node.span(), node.m_return, node.m_code ); + + node.m_code->visit( *this ); } }; @@ -463,9 +566,20 @@ void Context::equate_types_coerce(const Span& sp, const ::HIR::TypeRef& l, ::HIR } void Context::add_binding(const Span& sp, ::HIR::Pattern& pat, ::HIR::TypeRef& type) { } +const ::HIR::TypeRef& Context::get_var(const Span& sp, unsigned int idx) const { + if( idx < this->bindings.size() ) { + return this->bindings[idx].ty; + } + else { + BUG(sp, "get_var - Binding index out of range"); + } +} void Context::add_revisit(::HIR::ExprNode& node) { } void Context::push_traits(const t_trait_list& list) { } void Context::pop_traits(const t_trait_list& list) { } +void Context::equate_types_assoc(const Span& sp, const ::HIR::TypeRef& l, const ::HIR::SimplePath& trait, const ::std::vector< ::HIR::TypeRef>& ty_args, const ::HIR::TypeRef& impl_ty, const char *name) +{ +} |