diff options
author | John Hodge <tpg@mutabah.net> | 2016-12-27 20:23:01 +1100 |
---|---|---|
committer | John Hodge <tpg@mutabah.net> | 2016-12-27 20:23:01 +1100 |
commit | f0a84933ab3fa31f10001808eeb7e98dd6f8318e (patch) | |
tree | f6dc68b57b03cd7b3c00403e0d5430e16462fa0d /src | |
parent | 0233c7901361960db9414a104907ce708e8e01d1 (diff) | |
download | mrust-f0a84933ab3fa31f10001808eeb7e98dd6f8318e.tar.gz |
MIR Gen - Add support for capturing rest of slice patterns
Diffstat (limited to 'src')
-rw-r--r-- | src/hir/pattern.cpp | 24 | ||||
-rw-r--r-- | src/mir/check.cpp | 2 | ||||
-rw-r--r-- | src/mir/from_hir.cpp | 48 |
3 files changed, 62 insertions, 12 deletions
diff --git a/src/hir/pattern.cpp b/src/hir/pattern.cpp index 74528aeb..f51d7990 100644 --- a/src/hir/pattern.cpp +++ b/src/hir/pattern.cpp @@ -30,17 +30,21 @@ namespace HIR { ) return os; } + ::std::ostream& operator<<(::std::ostream& os, const PatternBinding& x) { + if( x.m_mutable ) + os << "mut "; + switch(x.m_type) + { + case PatternBinding::Type::Move: break; + case PatternBinding::Type::Ref: os << "ref "; break; + case PatternBinding::Type::MutRef: os << "ref mut "; break; + } + os << x.m_name << "/*"<<x.m_slot<<"*/" << " @ "; + return os; + } ::std::ostream& operator<<(::std::ostream& os, const Pattern& x) { if( x.m_binding.is_valid() ) { - if( x.m_binding.m_mutable ) - os << "mut "; - switch(x.m_binding.m_type) - { - case PatternBinding::Type::Move: break; - case PatternBinding::Type::Ref: os << "ref "; break; - case PatternBinding::Type::MutRef: os << "ref mut "; break; - } - os << x.m_binding.m_name << "/*"<<x.m_binding.m_slot<<"*/" << " @ "; + os << x.m_binding; } TU_MATCH(Pattern::Data, (x.m_data), (e), (Any, @@ -126,7 +130,7 @@ namespace HIR { for(const auto& s : e.leading) os << s << ", "; if( e.extra_bind.is_valid() ) { - os << e.extra_bind.m_name << " @ "; + os << e.extra_bind; } os << ".. "; for(const auto& s : e.trailing) diff --git a/src/mir/check.cpp b/src/mir/check.cpp index 48ba487b..ffcc4523 100644 --- a/src/mir/check.cpp +++ b/src/mir/check.cpp @@ -235,6 +235,8 @@ void MIR_Validate(const StaticTraitResolve& resolve, const ::HIR::ItemPath& path for(const auto& b : to_visit_blocks) if( b.first == idx && b.second == vs) return ; + if( block_start_states.at(idx) == vs ) + return ; to_visit_blocks.push_back( ::std::make_pair(idx, mv$(vs)) ); }; to_visit_blocks.push_back( ::std::make_pair(0, ValStates{ args.size(), fcn.temporaries.size(), fcn.named_variables.size() }) ); diff --git a/src/mir/from_hir.cpp b/src/mir/from_hir.cpp index bdc3dda2..5e8bf757 100644 --- a/src/mir/from_hir.cpp +++ b/src/mir/from_hir.cpp @@ -280,12 +280,17 @@ namespace { // These are only refutable if T is [T] bool ty_is_array = false; unsigned int array_size = 0; - m_builder.with_val_type(sp, lval, [&ty_is_array,&array_size](const auto& ty){ + ::HIR::TypeRef inner_type; + m_builder.with_val_type(sp, lval, [&ty_is_array,&array_size,&e,&inner_type](const auto& ty){ if( ty.m_data.is_Array() ) { array_size = ty.m_data.as_Array().size_val; + if( e.extra_bind.is_valid() ) + inner_type = ty.m_data.as_Array().inner->clone(); ty_is_array = true; } else { + if( e.extra_bind.is_valid() ) + inner_type = ty.m_data.as_Slice().inner->clone(); ty_is_array = false; } }); @@ -297,6 +302,10 @@ namespace { unsigned int idx = 0 + i; destructure_from_ex(sp, e.leading[i], ::MIR::LValue::make_Field({ box$(lval.clone()), idx }), allow_refutable ); } + if( e.extra_bind.is_valid() ) + { + TODO(sp, "Destructure array obtaining remainder"); + } for(unsigned int i = 0; i < e.trailing.size(); i ++) { unsigned int idx = array_size - e.trailing.size() + i; @@ -306,12 +315,47 @@ namespace { else { ASSERT_BUG(sp, allow_refutable, "Refutable pattern not expected - " << pat); - // TODO: Acquire the slice size variable. + + // Acquire the slice size variable. + ::MIR::LValue len_lval; + if( e.extra_bind.is_valid() || e.trailing.size() > 0 ) + { + len_lval = m_builder.lvalue_or_temp(sp, ::HIR::CoreType::Usize, ::MIR::RValue::make_DstMeta({ lval.clone() })); + } + for(unsigned int i = 0; i < e.leading.size(); i ++) { unsigned int idx = i; destructure_from_ex(sp, e.leading[i], ::MIR::LValue::make_Field({ box$(lval.clone()), idx }), allow_refutable ); } + if( e.extra_bind.is_valid() ) + { + // 1. Obtain remaining length + auto sub_val = m_builder.lvalue_or_temp(sp, ::HIR::CoreType::Usize, ::MIR::RValue::make_Constant( e.leading.size() + e.trailing.size() )); + ::MIR::LValue len_val = m_builder.lvalue_or_temp(sp, ::HIR::CoreType::Usize, ::MIR::RValue::make_BinOp({ len_lval.clone(), ::MIR::eBinOp::SUB, mv$(sub_val) }) ); + + // 2. Obtain pointer to element + ::HIR::BorrowType bt = ::HIR::BorrowType::Owned; + switch(e.extra_bind.m_type) + { + case ::HIR::PatternBinding::Type::Move: + BUG(sp, "By-value pattern binding of a slice"); + throw ""; + case ::HIR::PatternBinding::Type::Ref: + bt = ::HIR::BorrowType::Shared; + break; + case ::HIR::PatternBinding::Type::MutRef: + bt = ::HIR::BorrowType::Unique; + break; + } + ::MIR::LValue ptr_val = m_builder.lvalue_or_temp(sp, + ::HIR::TypeRef::new_pointer( bt, inner_type.clone() ), + ::MIR::RValue::make_Borrow({ 0, bt, ::MIR::LValue::make_Field({ box$(lval.clone()), static_cast<unsigned int>(e.leading.size()) }) }) + ); + + // Construct fat pointer + m_builder.push_stmt_assign( sp, ::MIR::LValue::make_Variable(e.extra_bind.m_slot), ::MIR::RValue::make_MakeDst({ mv$(ptr_val), mv$(len_val) }) ); + } if( e.trailing.size() > 0 ) { TODO(sp, "Destructure slice using SplitSlice with trailing - " << pat); |