diff options
-rw-r--r-- | src/mir/from_hir.cpp | 8 | ||||
-rw-r--r-- | src/mir/from_hir_match.cpp | 154 |
2 files changed, 81 insertions, 81 deletions
diff --git a/src/mir/from_hir.cpp b/src/mir/from_hir.cpp index b21c8fc5..500db069 100644 --- a/src/mir/from_hir.cpp +++ b/src/mir/from_hir.cpp @@ -247,7 +247,13 @@ namespace { else { ASSERT_BUG(sp, allow_refutable, "Refutable pattern not expected - " << pat); - TODO(sp, "Destructure slice using " << pat); + + // TODO: Emit code to triple-check the size? Or just assume that match did that correctly. + for(unsigned int i = 0; i < e.sub_patterns.size(); i ++) + { + const auto& subpat = e.sub_patterns[i]; + destructure_from_ex(sp, subpat, ::MIR::LValue::make_Field({ box$(lval.clone()), i }), allow_refutable ); + } } ), (SplitSlice, diff --git a/src/mir/from_hir_match.cpp b/src/mir/from_hir_match.cpp index 18e22b14..72c4b5f9 100644 --- a/src/mir/from_hir_match.cpp +++ b/src/mir/from_hir_match.cpp @@ -18,6 +18,10 @@ TAGGED_UNION_EX(PatternRule, (), Any,( (Any, struct {}), // Enum variant (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; }), // Boolean (different to Constant because of how restricted it is) (Bool, bool), // General value @@ -953,6 +957,10 @@ void MIR_LowerHIR_Match_DecisionTree( MirBuilder& builder, MirConverter& conv, : (Variant, os << e.idx << " [" << e.sub_rules << "]"; ), + // Enum variant + (Slice, + os << "len=" << e.len << " [" << e.sub_rules << "]"; + ), // Boolean (different to Constant because of how restricted it is) (Bool, os << (e ? "true" : "false"); @@ -994,6 +1002,19 @@ void MIR_LowerHIR_Match_DecisionTree( MirBuilder& builder, MirConverter& conv, : } return ::OrdEqual; ), + (Slice, + if( le.len != re.len ) + return ::ord(le.len, re.len); + // Wait? Why would the rule count be the same? + assert( le.sub_rules.size() == re.sub_rules.size() ); + for(unsigned int i = 0; i < le.sub_rules.size(); i ++) + { + auto cmp = rule_is_before(le.sub_rules[i], re.sub_rules[i]); + if( cmp != ::OrdEqual ) + return cmp; + } + return ::OrdEqual; + ), (Bool, return ::ord( le, re ); ), @@ -1380,13 +1401,33 @@ void PatternRulesetBuilder::append_from(const Span& sp, const ::HIR::Pattern& pa m_field_path.pop_back(); ), (Slice, - // TODO: Slice patterns, sequential comparison/sub-match - if( pat.m_data.is_Any() ) { + TU_MATCH_DEF(::HIR::Pattern::Data, (pat.m_data), (pe), + ( + BUG(sp, "Matching over [T] with invalid pattern - " << pat); + ), + (Any, // Value, don't add anything - } - else { - BUG(sp, "Hit match over `[T]` - must be `&[T]`"); - } + ), + (Slice, + // Sub-patterns + 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.sub_patterns) + { + sub_builder.append_from( sp, subpat, *e.inner ); + sub_builder.m_field_path.back() ++; + } + + // Encodes length check and sub-pattern rules + 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); + ) + ) ), (Borrow, TU_MATCH_DEF( ::HIR::Pattern::Data, (pat.m_data), (pe), @@ -1401,24 +1442,8 @@ void PatternRulesetBuilder::append_from(const Span& sp, const ::HIR::Pattern& pa this->append_from( sp, *pe.sub, *e.inner ); m_field_path.pop_back(); ), - (Slice, - if( e.inner->m_data.is_Slice() ) { - TODO(sp, "Match &[T] with Slice - " << pat); - } - else { - BUG(sp, "Matching borrow invalid pattern - " << pat); - } - ), - (SplitSlice, - if( e.inner->m_data.is_Slice() ) { - TODO(sp, "Match &[T] with SplitSlice - " << pat); - } - else { - BUG(sp, "Matching borrow invalid pattern - " << pat); - } - ), (Value, - // TODO: Check type? Also handle named values and byte strings. + // TODO: Check type? if( pe.val.is_String() ) { const auto& s = pe.val.as_String(); this->push_rule( PatternRule::make_Value(s) ); @@ -1432,6 +1457,7 @@ void PatternRulesetBuilder::append_from(const Span& sp, const ::HIR::Pattern& pa this->push_rule( PatternRule::make_Value( mv$(data) ) ); } + // TODO: Handle named values else { BUG(sp, "Matching borrow invalid pattern - " << pat); } @@ -1621,6 +1647,15 @@ void DecisionTreeNode::populate_tree_from_rule(const Span& sp, const PatternRule assert( m_field_path == rule.field_path ); } + #define GET_BRANCHES(fld, var) (({if( fld.is_Unset() ) {\ + fld = Values::make_##var({}); \ + } \ + else if( !fld.is_##var() ) { \ + BUG(sp, "Mismatched rules - have " #var ", but have seen " << fld.tag_str()); \ + }}), \ + fld.as_##var()) + + TU_MATCHA( (rule), (e), (Any, { if( m_default.is_Unset() ) { @@ -1646,13 +1681,7 @@ void DecisionTreeNode::populate_tree_from_rule(const Span& sp, const PatternRule } }), (Variant, { - if( m_branches.is_Unset() ) { - m_branches = Values::make_Variant({}); - } - if( !m_branches.is_Variant() ) { - BUG(sp, "Mismatched rules"); - } - auto& be = m_branches.as_Variant(); + auto& be = GET_BRANCHES(m_branches, Variant); auto it = ::std::find_if( be.begin(), be.end(), [&](const auto& x){ return x.first >= e.idx; }); // If this variant isn't yet processed, add a new subtree for it @@ -1698,14 +1727,14 @@ void DecisionTreeNode::populate_tree_from_rule(const Span& sp, const PatternRule and_then(it->second); } }), + (Slice, + //auto& be = GET_BRANCHES(m_branches, Slice); + // TODO: How to encode slice patterns in the DT? + // - SplitSlice throws a spanner in the works, and means that using the length isn't feasable + TODO(sp, "Slice rules - " << rule); + ), (Bool, - if( m_branches.is_Unset() ) { - m_branches = Values::make_Bool({}); - } - else if( !m_branches.is_Bool() ) { - BUG(sp, "Mismatched rules"); - } - auto& be = m_branches.as_Bool(); + auto& be = GET_BRANCHES(m_branches, Bool); auto& branch = (e ? be.true_branch : be.false_branch); if( branch.is_Unset() ) { @@ -1730,15 +1759,9 @@ void DecisionTreeNode::populate_tree_from_rule(const Span& sp, const PatternRule (Value, TU_MATCHA( (e), (ve), (Int, - // TODO: De-duplicate this code between Uint and Float - if( m_branches.is_Unset() ) { - m_branches = Values::make_Signed({}); - } - else if( !m_branches.is_Signed() ) { - BUG(sp, "Mismatched rules - have Signed, but have seen " << m_branches.tag_str()); - } - auto& be = m_branches.as_Signed(); + auto& be = GET_BRANCHES(m_branches, Signed); + // TODO: De-duplicate this code between Uint and Float from_rule_value(sp, be, ve, "Signed", rule.field_path, [&](auto& branch) { if( rule_count > 1 ) { @@ -1753,13 +1776,7 @@ void DecisionTreeNode::populate_tree_from_rule(const Span& sp, const PatternRule }); ), (Uint, - if( m_branches.is_Unset() ) { - m_branches = Values::make_Unsigned({}); - } - else if( !m_branches.is_Unsigned() ) { - BUG(sp, "Mismatched rules - have Unsigned, but have seen " << m_branches.tag_str()); - } - auto& be = m_branches.as_Unsigned(); + auto& be = GET_BRANCHES(m_branches, Unsigned); from_rule_value(sp, be, ve, "Unsigned", rule.field_path, [&](auto& branch) { @@ -1775,13 +1792,7 @@ void DecisionTreeNode::populate_tree_from_rule(const Span& sp, const PatternRule }); ), (Float, - if( m_branches.is_Unset() ) { - m_branches = Values::make_Float({}); - } - else if( !m_branches.is_Float() ) { - BUG(sp, "Mismatched rules - have Float, but have seen " << m_branches.tag_str()); - } - auto& be = m_branches.as_Float(); + auto& be = GET_BRANCHES(m_branches, Float); from_rule_value(sp, be, ve, "Float", rule.field_path, [&](auto& branch) { @@ -1802,13 +1813,7 @@ void DecisionTreeNode::populate_tree_from_rule(const Span& sp, const PatternRule TODO(sp, "Value patterns - Bytes"); ), (StaticString, - if( m_branches.is_Unset() ) { - m_branches = Values::make_String({}); - } - else if( !m_branches.is_String() ) { - BUG(sp, "Mismatched rules"); - } - auto& be = m_branches.as_String(); + auto& be = GET_BRANCHES(m_branches, String); auto it = ::std::find_if(be.begin(), be.end(), [&](const auto& v){ return v.first >= ve; }); if( it == be.end() || it->first != ve ) { @@ -1839,17 +1844,12 @@ void DecisionTreeNode::populate_tree_from_rule(const Span& sp, const PatternRule ASSERT_BUG(sp, e.first.tag() == e.last.tag(), ""); TU_MATCHA( (e.first, e.last), (ve_start, ve_end), (Int, + //auto& be = GET_BRANCHES(m_branches, Signed); TODO(sp, "ValueRange patterns - Int"); ), (Uint, // TODO: Share code between the three numeric groups - if( m_branches.is_Unset() ) { - m_branches = Values::make_Unsigned({}); - } - else if( !m_branches.is_Unsigned() ) { - BUG(sp, "Mismatched rules - have Unsigned, seen " << m_branches.tag_str()); - } - auto& be = m_branches.as_Unsigned(); + auto& be = GET_BRANCHES(m_branches, Unsigned); from_rule_valuerange(sp, be, ve_start, ve_end, "Unsigned", rule.field_path, [&](auto& branch) { if( rule_count > 1 ) @@ -1865,13 +1865,7 @@ void DecisionTreeNode::populate_tree_from_rule(const Span& sp, const PatternRule }); ), (Float, - if( m_branches.is_Unset() ) { - m_branches = Values::make_Float({}); - } - else if( !m_branches.is_Float() ) { - BUG(sp, "Mismatched rules - have Float, seen " << m_branches.tag_str()); - } - auto& be = m_branches.as_Float(); + auto& be = GET_BRANCHES(m_branches, Float); from_rule_valuerange(sp, be, ve_start, ve_end, "Float", rule.field_path, [&](auto& branch) { if( rule_count > 1 ) |