summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJohn Hodge <tpg@mutabah.net>2016-12-27 20:23:01 +1100
committerJohn Hodge <tpg@mutabah.net>2016-12-27 20:23:01 +1100
commitf0a84933ab3fa31f10001808eeb7e98dd6f8318e (patch)
treef6dc68b57b03cd7b3c00403e0d5430e16462fa0d /src
parent0233c7901361960db9414a104907ce708e8e01d1 (diff)
downloadmrust-f0a84933ab3fa31f10001808eeb7e98dd6f8318e.tar.gz
MIR Gen - Add support for capturing rest of slice patterns
Diffstat (limited to 'src')
-rw-r--r--src/hir/pattern.cpp24
-rw-r--r--src/mir/check.cpp2
-rw-r--r--src/mir/from_hir.cpp48
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);