From a81a116e57d46765b9ec36fc31376d5c4a91b04d Mon Sep 17 00:00:00 2001 From: John Hodge Date: Sun, 15 Jan 2017 11:54:11 +0800 Subject: MIR From HIR - Fix bug in handling single-value ranges --- src/mir/from_hir_match.cpp | 48 +++++++++++++++++++++++++--------------------- 1 file changed, 26 insertions(+), 22 deletions(-) (limited to 'src/mir/from_hir_match.cpp') diff --git a/src/mir/from_hir_match.cpp b/src/mir/from_hir_match.cpp index 227c46f3..f5e083bf 100644 --- a/src/mir/from_hir_match.cpp +++ b/src/mir/from_hir_match.cpp @@ -2291,6 +2291,27 @@ namespace } // Common code for numerics (Int, Uint, and Float) + template + static void from_rule_value( + const Span& sp, + ::std::vector< ::std::pair< DecisionTreeNode::Range, DecisionTreeNode::Branch> >& be, T ve, + const char* name, const field_path_t& field_path, ::std::function and_then + ) + { + auto it = ::std::find_if(be.begin(), be.end(), [&](const auto& v){ return v.first.end >= ve; }); + if( it == be.end() || it->first.start > ve ) { + it = be.insert( it, ::std::make_pair( DecisionTreeNode::Range { ve,ve }, new_branch_subtree(field_path) ) ); + } + else if( it->first.start == ve && it->first.end == ve ) { + // Equal, continue and add sub-pat + } + else { + // Collide or overlap! + TODO(sp, "Value patterns - " << name << " - Overlapping - " << it->first.start << " <= " << ve << " <= " << it->first.end); + } + and_then( it->second ); + } + template static void from_rule_valuerange( const Span& sp, @@ -2298,9 +2319,13 @@ namespace const char* name, const field_path_t& field_path, ::std::function and_then ) { + TRACE_FUNCTION_F("be=[" << FMT_CB(os, for(const auto& i:be) os << i.first <<" , ";) << "], new=" << ve_start << "..." << ve_end); ASSERT_BUG(sp, ve_start <= ve_end, "Range pattern with a start after the end - " << ve_start << "..." << ve_end); - TRACE_FUNCTION_F("[" << FMT_CB(os, for(const auto& i:be) os << i.first <<" , ";) << "]"); + if( ve_start == ve_end ) { + from_rule_value(sp, be, ve_start, name, field_path, and_then); + return ; + } // - Find the first entry that ends after the new one starts. auto it = ::std::find_if(be.begin(), be.end(), [&](const auto& v){ return v.first.end >= ve_start; }); while(ve_start < ve_end) @@ -2355,27 +2380,6 @@ namespace } } } - - template - static void from_rule_value( - const Span& sp, - ::std::vector< ::std::pair< DecisionTreeNode::Range, DecisionTreeNode::Branch> >& be, T ve, - const char* name, const field_path_t& field_path, ::std::function and_then - ) - { - auto it = ::std::find_if(be.begin(), be.end(), [&](const auto& v){ return v.first.end >= ve; }); - if( it == be.end() || it->first.start > ve ) { - it = be.insert( it, ::std::make_pair( DecisionTreeNode::Range { ve,ve }, new_branch_subtree(field_path) ) ); - } - else if( it->first.start == ve && it->first.end == ve ) { - // Equal, continue and add sub-pat - } - else { - // Collide or overlap! - TODO(sp, "Value patterns - " << name << " - Overlapping - " << it->first.start << " <= " << ve << " <= " << it->first.end); - } - and_then( it->second ); - } } void DecisionTreeNode::populate_tree_from_rule(const Span& sp, const PatternRule* first_rule, unsigned int rule_count, ::std::function and_then) { -- cgit v1.2.3