summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJohn Hodge <tpg@mutabah.net>2016-07-02 14:39:54 +0800
committerJohn Hodge <tpg@mutabah.net>2016-07-02 14:40:18 +0800
commit82806102bd9075e25f326484249f3c63a58160f5 (patch)
treef6fd67d849e24fddfc479230340c8929b0b73f26 /src
parente2b52c8f7c72b1587eca350d6957c3d9fca0900d (diff)
downloadmrust-82806102bd9075e25f326484249f3c63a58160f5.tar.gz
HIR - CS Typecheck work, Store 'is_struct' flag in StructLiteral node
Diffstat (limited to 'src')
-rw-r--r--src/hir/expr.hpp4
-rw-r--r--src/hir/from_ast_expr.cpp11
-rw-r--r--src/hir_typeck/expr_cs.cpp172
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)
+{
+}