diff options
| author | John Hodge <tpg@mutabah.net> | 2016-11-19 16:38:45 +0800 | 
|---|---|---|
| committer | John Hodge <tpg@mutabah.net> | 2016-11-19 16:38:45 +0800 | 
| commit | da1552c48ebc9ae2c0a9a891bdb01491dffb0ff3 (patch) | |
| tree | 4c90a0181a4617aa56946d6f6e65e760ed91a4f3 /src | |
| parent | 18442f4a3a3d5fc838f4703651b6f925d3e0c2f2 (diff) | |
| download | mrust-da1552c48ebc9ae2c0a9a891bdb01491dffb0ff3.tar.gz | |
MIR Gen Match - Rough Slice and SplitSlice support
Diffstat (limited to 'src')
| -rw-r--r-- | src/mir/from_hir.cpp | 45 | ||||
| -rw-r--r-- | src/mir/from_hir_match.cpp | 88 | 
2 files changed, 110 insertions, 23 deletions
| diff --git a/src/mir/from_hir.cpp b/src/mir/from_hir.cpp index 4a4b84e7..9d71ea01 100644 --- a/src/mir/from_hir.cpp +++ b/src/mir/from_hir.cpp @@ -280,28 +280,43 @@ namespace {              (SplitSlice,                  // These are only refutable if T is [T]                  bool ty_is_array = false; -                m_builder.with_val_type(sp, lval, [&ty_is_array](const auto& ty){ -                    ty_is_array = ty.m_data.is_Array(); +                unsigned int array_size = 0; +                m_builder.with_val_type(sp, lval, [&ty_is_array,&array_size](const auto& ty){ +                    if( ty.m_data.is_Array() ) { +                        array_size = ty.m_data.as_Array().size_val; +                        ty_is_array = true; +                    } +                    else { +                        ty_is_array = false; +                    }                      });                  if( ty_is_array )                  { -                    // TODO: Assert array size -                    //for(unsigned int i = 0; i < e.leading.size(); i ++) -                    //{ -                    //    auto idx = 0 + i; -                    //    destructure_from_ex(sp, e.leading[i], ::MIR::LValue::make_Index({ box$( lval.clone() ), box$(lval_idx) }), allow_refutable ); -                    //} -                    //for(unsigned int i = 0; i < e.trailing.size(); i ++) -                    //{ -                    //    auto idx = 0 + i; -                    //    destructure_from_ex(sp, e.leading[i], ::MIR::LValue::make_Index({ box$( lval.clone() ), box$(lval_idx) }), allow_refutable ); -                    //} -                    TODO(sp, "Destructure array using SplitSlice - " << pat); +                    assert(array_size >= e.leading.size() + e.trailing.size()); +                    for(unsigned int i = 0; i < e.leading.size(); i ++) +                    { +                        unsigned int idx = 0 + i; +                        destructure_from_ex(sp, e.leading[i], ::MIR::LValue::make_Field({ box$(lval.clone()), idx }), allow_refutable ); +                    } +                    for(unsigned int i = 0; i < e.trailing.size(); i ++) +                    { +                        unsigned int idx = array_size - e.trailing.size() + i; +                        destructure_from_ex(sp, e.trailing[i], ::MIR::LValue::make_Field({ box$(lval.clone()), idx }), allow_refutable ); +                    }                  }                  else                  {                      ASSERT_BUG(sp, allow_refutable, "Refutable pattern not expected - " << pat); -                    TODO(sp, "Destructure slice using SplitSlice - " << pat); +                    // TODO: Acquire the slice size variable. +                    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.trailing.size() > 0 ) +                    { +                        TODO(sp, "Destructure slice using SplitSlice with trailing - " << pat); +                    }                  }                  )              ) diff --git a/src/mir/from_hir_match.cpp b/src/mir/from_hir_match.cpp index 8eb61a5f..15034587 100644 --- a/src/mir/from_hir_match.cpp +++ b/src/mir/from_hir_match.cpp @@ -39,8 +39,9 @@ TAGGED_UNION_EX(PatternRule, (), Any,(      (Variant, struct { unsigned int idx; ::std::vector<PatternRule> sub_rules; }),      // Slice (includes desired length)      (Slice, struct { unsigned int len; ::std::vector<PatternRule> sub_rules; }), -    // TODO: SplitSlice encoding - how are the tail patterns to be encoded? -    //(SplitSlice, struct { unsigned int len; ::std::vector<PatternRule> sub_rules; }), +    // SplitSlice +    // TODO: How can the negative offsets in the `trailing` be handled correctly? (both here and in the destructure) +    (SplitSlice, struct { unsigned int min_len; ::std::vector<PatternRule> leading, trailing; }),      // Boolean (different to Constant because of how restricted it is)      (Bool, bool),      // General value @@ -277,10 +278,14 @@ void MIR_LowerHIR_Match( MirBuilder& builder, MirConverter& conv, ::HIR::ExprNod      (Variant,          os << e.idx << " [" << e.sub_rules << "]";          ), -    // Enum variant +    // Slice pattern      (Slice,          os << "len=" << e.len << " [" << e.sub_rules << "]";          ), +    // SplitSlice +    (SplitSlice, +        os << "len>=" << e.min_len << " [" << e.leading << ", ..., " << e.trailing << "]"; +        ),      // Boolean (different to Constant because of how restricted it is)      (Bool,          os << (e ? "true" : "false"); @@ -335,6 +340,9 @@ void MIR_LowerHIR_Match( MirBuilder& builder, MirConverter& conv, ::HIR::ExprNod          }          return ::OrdEqual;          ), +    (SplitSlice, +        TODO(Span(), "Order PatternRule::SplitSlice"); +        ),      (Bool,          return ::ord( le, re );          ), @@ -1036,9 +1044,27 @@ void PatternRulesetBuilder::append_from(const Span& sp, const ::HIR::Pattern& pa              this->push_rule( PatternRule::make_Slice({ static_cast<unsigned int>(pe.sub_patterns.size()), mv$(sub_builder.m_rules) }) );              ),          (SplitSlice, -            // 1. Length minimum check -            // 2. Sub-patterns (handling trailing) -            TODO(sp, "Match [T] with SplitSlice - " << pat); +            PatternRulesetBuilder   sub_builder { this->m_resolve }; +            sub_builder.m_field_path = m_field_path; +            sub_builder.m_field_path.push_back(0); +            for(const auto& subpat : pe.leading) +            { +                sub_builder.append_from( sp, subpat, *e.inner ); +                sub_builder.m_field_path.back() ++; +            } +            auto leading = mv$(sub_builder.m_rules); +             +            sub_builder.m_field_path.back() = 0; +            if( pe.trailing.size() ) +            { +                TODO(sp, "SplitSlice on [T] with trailing - " << pat); +            } +            auto trailing = mv$(sub_builder.m_rules); +             +            this->push_rule( PatternRule::make_SplitSlice({ +                static_cast<unsigned int>(pe.leading.size() + pe.trailing.size()), +                mv$(leading), mv$(trailing) +                }) );              )          )          ), @@ -1541,7 +1567,7 @@ int MIR_LowerHIR_Match_Simple__GeneratePattern(MirBuilder& builder, const Span&              #endif              ),          (Slice, -            ASSERT_BUG(sp, rule.is_Slice() || (rule.is_Value() && rule.as_Value().is_Bytes()), "Can only match slice with Bytes or Slice rules - " << rule); +            ASSERT_BUG(sp, rule.is_Slice() || rule.is_SplitSlice() || (rule.is_Value() && rule.as_Value().is_Bytes()), "Can only match slice with Bytes or Slice rules - " << rule);              if( rule.is_Value() ) {                  ASSERT_BUG(sp, *te.inner == ::HIR::CoreType::U8, "Bytes pattern on non-&[u8]");                  auto cloned_val = ::MIR::Constant( rule.as_Value().as_Bytes() ); @@ -1553,8 +1579,50 @@ int MIR_LowerHIR_Match_Simple__GeneratePattern(MirBuilder& builder, const Span&                  builder.end_block( ::MIR::Terminator::make_If({ mv$(cmp_lval), succ_bb, fail_bb }) );                  builder.set_cur_block(succ_bb);              } +            else if( rule.is_Slice() ) { +                const auto& re = rule.as_Slice(); +                 +                // Compare length +                auto test_lval = builder.lvalue_or_temp(sp, ::HIR::CoreType::Usize, ::MIR::RValue( ::MIR::Constant::make_Uint(re.len) )); +                auto len_val = builder.lvalue_or_temp(sp, ::HIR::CoreType::Usize, ::MIR::RValue::make_DstMeta({ val.clone() })); +                auto cmp_lval = builder.lvalue_or_temp(sp, ::HIR::CoreType::Bool, ::MIR::RValue::make_BinOp({ mv$(len_val), ::MIR::eBinOp::EQ, mv$(test_lval) })); +                 +                auto len_succ_bb = builder.new_bb_unlinked(); +                builder.end_block( ::MIR::Terminator::make_If({ mv$(cmp_lval), len_succ_bb, fail_bb }) ); +                builder.set_cur_block(len_succ_bb); +                 +                // Recurse checking values +                MIR_LowerHIR_Match_Simple__GeneratePattern(builder, sp, +                    re.sub_rules.data(), re.sub_rules.size(), +                    top_ty, top_val, field_path_ofs, +                    fail_bb +                    ); +            } +            else if( rule.is_SplitSlice() ) { +                const auto& re = rule.as_SplitSlice(); +                 +                // Compare length +                auto test_lval = builder.lvalue_or_temp(sp, ::HIR::CoreType::Usize, ::MIR::RValue( ::MIR::Constant::make_Uint(re.min_len) )); +                auto len_val = builder.lvalue_or_temp(sp, ::HIR::CoreType::Usize, ::MIR::RValue::make_DstMeta({ val.clone() })); +                auto cmp_lval = builder.lvalue_or_temp(sp, ::HIR::CoreType::Bool, ::MIR::RValue::make_BinOp({ mv$(len_val), ::MIR::eBinOp::LT, mv$(test_lval) })); +                 +                auto len_succ_bb = builder.new_bb_unlinked(); +                builder.end_block( ::MIR::Terminator::make_If({ mv$(cmp_lval), fail_bb, len_succ_bb }) );   // if len < test : FAIL +                builder.set_cur_block(len_succ_bb); +                 +                MIR_LowerHIR_Match_Simple__GeneratePattern(builder, sp, +                    re.leading.data(), re.leading.size(), +                    top_ty, top_val, field_path_ofs, +                    fail_bb +                    ); +                 +                if( re.trailing.size() > 0 ) +                { +                    TODO(sp, "Match over Slice using SplitSlice with trailing - " << rule); +                } +            }              else { -                TODO(sp, "Match over Slice - " << rule); +                BUG(sp, "Invalid rule type for slice - " << rule);              }              ),          (Tuple, @@ -2245,6 +2313,10 @@ void DecisionTreeNode::populate_tree_from_rule(const Span& sp, const PatternRule              and_then(it->second);          }          ), +    (SplitSlice, +        //auto& be = GET_BRANCHES(m_branches, Slice); +        TODO(sp, "SplitSlice in DTN - " << rule); +        ),      (Bool,          auto& be = GET_BRANCHES(m_branches, Bool); | 
