diff options
author | John Hodge <tpg@ucc.asn.au> | 2017-09-04 22:57:01 +0800 |
---|---|---|
committer | John Hodge <tpg@ucc.asn.au> | 2017-09-04 22:57:01 +0800 |
commit | 88434990de083450940a23f2d4046867add8b5da (patch) | |
tree | 92e98d4f577c5bc427dfead4b30687275a868555 | |
parent | 96dddd40e187d8c9ecd4997ca3bec839f645db0a (diff) | |
download | mrust-88434990de083450940a23f2d4046867add8b5da.tar.gz |
MIR Gen - Partial support for trailing slice patterns
-rw-r--r-- | src/mir/from_hir.cpp | 38 | ||||
-rw-r--r-- | src/mir/from_hir_match.cpp | 52 |
2 files changed, 70 insertions, 20 deletions
diff --git a/src/mir/from_hir.cpp b/src/mir/from_hir.cpp index 2dc4d5b0..7773a81c 100644 --- a/src/mir/from_hir.cpp +++ b/src/mir/from_hir.cpp @@ -353,6 +353,21 @@ namespace { { ASSERT_BUG(sp, allow_refutable, "Refutable pattern not expected - " << pat); + struct H { + static ::HIR::BorrowType get_borrow_type(const Span& sp, const ::HIR::PatternBinding& pb) { + switch(pb.m_type) + { + case ::HIR::PatternBinding::Type::Move: + BUG(sp, "By-value pattern binding of a slice"); + case ::HIR::PatternBinding::Type::Ref: + return ::HIR::BorrowType::Shared; + case ::HIR::PatternBinding::Type::MutRef: + return ::HIR::BorrowType::Unique; + } + throw ""; + } + }; + // Acquire the slice size variable. ::MIR::LValue len_lval; if( e.extra_bind.is_valid() || e.trailing.size() > 0 ) @@ -372,19 +387,7 @@ namespace { ::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; - } + ::HIR::BorrowType bt = H::get_borrow_type(sp, e.extra_bind); ::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()) }) }) @@ -395,7 +398,14 @@ namespace { } if( e.trailing.size() > 0 ) { - TODO(sp, "Destructure slice using SplitSlice with trailing - " << pat); + for(size_t i = 0; i < e.trailing.size(); i ++) + { + // Dynamically create an index + auto sub_val = ::MIR::Param(::MIR::Constant::make_Uint({ e.trailing.size() - i, ::HIR::CoreType::Usize })); + ::MIR::LValue ofs_val = m_builder.lvalue_or_temp(sp, ::HIR::CoreType::Usize, ::MIR::RValue::make_BinOp({ len_lval.clone(), ::MIR::eBinOp::SUB, mv$(sub_val) }) ); + // Recurse with the indexed value + destructure_from_ex(sp, e.trailing[i], ::MIR::LValue::make_Index({ box$(lval.clone()), box$(ofs_val) }), allow_refutable); + } } } ) diff --git a/src/mir/from_hir_match.cpp b/src/mir/from_hir_match.cpp index 058bf2ab..d1a93b0f 100644 --- a/src/mir/from_hir_match.cpp +++ b/src/mir/from_hir_match.cpp @@ -13,6 +13,7 @@ void MIR_LowerHIR_Match( MirBuilder& builder, MirConverter& conv, ::HIR::ExprNode_Match& node, ::MIR::LValue match_val ); #define FIELD_DEREF 255 +#define FIELD_INDEX_MAX 128 struct field_path_t { @@ -1374,6 +1375,7 @@ void PatternRulesetBuilder::append_from(const Span& sp, const ::HIR::Pattern& pa PatternRulesetBuilder sub_builder { this->m_resolve }; sub_builder.m_field_path = m_field_path; sub_builder.m_field_path.push_back(0); + ASSERT_BUG(sp, pe.sub_patterns.size() < FIELD_INDEX_MAX, "Too many slice rules to fit encodng"); for(const auto& subpat : pe.sub_patterns) { sub_builder.append_from( sp, subpat, *e.inner ); @@ -1386,6 +1388,7 @@ void PatternRulesetBuilder::append_from(const Span& sp, const ::HIR::Pattern& pa (SplitSlice, PatternRulesetBuilder sub_builder { this->m_resolve }; sub_builder.m_field_path = m_field_path; + ASSERT_BUG(sp, pe.leading.size() < FIELD_INDEX_MAX, "Too many leading slice rules to fit encodng"); sub_builder.m_field_path.push_back(0); for(const auto& subpat : pe.leading) { @@ -1394,11 +1397,17 @@ void PatternRulesetBuilder::append_from(const Span& sp, const ::HIR::Pattern& pa } auto leading = mv$(sub_builder.m_rules); - sub_builder.m_field_path.back() = 0; if( pe.trailing.size() ) { // Needs a way of encoding the negative offset in the field path - TODO(sp, "SplitSlice on [T] with trailing - " << pat); + // - For now, just use a very high number (and assert that it's not more than 128) + ASSERT_BUG(sp, pe.trailing.size() < FIELD_INDEX_MAX, "Too many trailing slice rules to fit encodng"); + sub_builder.m_field_path.back() = FIELD_INDEX_MAX + (FIELD_INDEX_MAX - pe.trailing.size()); + for(const auto& subpat : pe.trailing) + { + sub_builder.append_from( sp, subpat, *e.inner ); + sub_builder.m_field_path.back() ++; + } } auto trailing = mv$(sub_builder.m_rules); @@ -1838,11 +1847,32 @@ namespace { (Array, assert(idx < e.size_val); cur_ty = &*e.inner; - lval = ::MIR::LValue::make_Field({ box$(lval), idx }); + if( idx < FIELD_INDEX_MAX ) + lval = ::MIR::LValue::make_Field({ box$(lval), idx }); + else { + idx -= FIELD_INDEX_MAX; + idx = FIELD_INDEX_MAX - idx; + TODO(sp, "Index " << idx << " from end of array " << lval); + } ), (Slice, cur_ty = &*e.inner; - lval = ::MIR::LValue::make_Field({ box$(lval), idx }); + if( idx < FIELD_INDEX_MAX ) + lval = ::MIR::LValue::make_Field({ box$(lval), idx }); + else { + idx -= FIELD_INDEX_MAX; + idx = FIELD_INDEX_MAX - idx; + TODO(sp, "Index " << idx << " from end of slice " << lval); + // 1. Create an LValue containing the size of this slice subtract `idx` + // TODO: Requires access to the MIR generator +#if 0 + auto len_lval = m_builder.lvalue_or_temp(sp, ::HIR::CoreType::Usize, ::MIR::RValue::make_DstMeta({ m_builder.get_ptr_to_dst(sp, lval).clone() })); + auto sub_val = ::MIR::Param(::MIR::Constant::make_Uint({ idx, ::HIR::CoreType::Usize })); + auto ofs_val = m_builder.lvalue_or_temp(sp, ::HIR::CoreType::Usize, ::MIR::RValue::make_BinOp({ mv$(len_lval), ::MIR::eBinOp::SUB, mv$(sub_val) }) ); + // Return _Index with that value + lval = ::MIR::LValue::make_Index({ box$(lval), box$(ofs_val) }); +#endif + } ), (Borrow, ASSERT_BUG(sp, idx == FIELD_DEREF, "Destructure of borrow doesn't correspond to a deref in the path"); @@ -2506,7 +2536,10 @@ namespace { for(auto& sr : leading) push_flat_rules(out_rules, mv$(sr)); // TODO: the trailing rules need a special path format. - ASSERT_BUG(Span(), trailing.size() == 0, "TODO: Handle SplitSlice with trailing"); + if( !e.trailing.empty() ) + { + TODO(Span(), "Handle SplitSlice with trailing"); + } for(auto& sr : trailing) push_flat_rules(out_rules, mv$(sr)); ), @@ -3290,9 +3323,16 @@ void MatchGenGrouped::gen_dispatch_splitslice(const field_path_t& field_path, co m_builder.set_cur_block(next); } + // 3. Recurse into trailing patterns if( e.trailing_len != 0 ) { - TODO(sp, "Handle trailing rules in SplitSlice - " << e.trailing); + auto next = m_builder.new_bb_unlinked(); + auto inner_set = t_rules_subset { 1, /*is_arm_indexes=*/false }; + inner_set.push_bb( e.trailing, next ); + auto inst = MatchGenGrouped { m_builder, sp, ty, val, {}, field_path.size() }; + inst.gen_for_slice(inner_set, 0, def_blk); + + m_builder.set_cur_block(next); } } |