diff options
| author | John Hodge <tpg@mutabah.net> | 2016-11-19 13:25:02 +0800 | 
|---|---|---|
| committer | John Hodge <tpg@mutabah.net> | 2016-11-19 13:25:02 +0800 | 
| commit | 2180c09510dab95e89667dd62c68ad581c9dcd3f (patch) | |
| tree | b196692be75362d24f1b5cb26b9e51b637596733 /src | |
| parent | 482a2ef80fed80d860522046c5b1e0466b6b8eb0 (diff) | |
| download | mrust-2180c09510dab95e89667dd62c68ad581c9dcd3f.tar.gz | |
MIR Gen Match - Sanity check in node merge
Diffstat (limited to 'src')
| -rw-r--r-- | src/mir/from_hir_match.cpp | 139 | 
1 files changed, 107 insertions, 32 deletions
| diff --git a/src/mir/from_hir_match.cpp b/src/mir/from_hir_match.cpp index 2708fca3..2ab80000 100644 --- a/src/mir/from_hir_match.cpp +++ b/src/mir/from_hir_match.cpp @@ -14,6 +14,24 @@ void MIR_LowerHIR_Match( MirBuilder& builder, MirConverter& conv, ::HIR::ExprNod  #define FIELD_DEREF 255 +struct field_path_t +{ +    ::std::vector<uint8_t>  data; +     +    size_t size() const { return data.size(); } +    void push_back(uint8_t v) { data.push_back(v); } +    void pop_back() { data.pop_back(); } +    uint8_t& back() { return data.back(); } +     +    bool operator==(const field_path_t& x) const { return data == x.data; } +     +    friend ::std::ostream& operator<<(::std::ostream& os, const field_path_t& x) { +        for(const auto idx : x.data) +            os << "." << static_cast<unsigned int>(idx); +        return os; +    } +}; +  TAGGED_UNION_EX(PatternRule, (), Any,(      // _ pattern      (Any, struct {}), @@ -31,7 +49,6 @@ TAGGED_UNION_EX(PatternRule, (), Any,(      ),      ( , field_path(mv$(x.field_path)) ), (field_path = mv$(x.field_path);),      ( -        typedef ::std::vector<uint8_t>  field_path_t;          field_path_t    field_path;      )      ); @@ -68,7 +85,7 @@ struct PatternRulesetBuilder      const StaticTraitResolve&   m_resolve;      bool m_is_impossible;      ::std::vector<PatternRule>  m_rules; -    PatternRule::field_path_t   m_field_path; +    field_path_t   m_field_path;      PatternRulesetBuilder(const StaticTraitResolve& resolve):          m_resolve(resolve), @@ -251,10 +268,7 @@ void MIR_LowerHIR_Match( MirBuilder& builder, MirConverter& conv, ::HIR::ExprNod  // --------------------------------------------------------------------  ::std::ostream& operator<<(::std::ostream& os, const PatternRule& x)  { -    os <<"{"; -    for(const auto idx : x.field_path) -        os << "." << static_cast<unsigned int>(idx); -    os << "}="; +    os << "{" << x.field_path << "}=";      TU_MATCHA( (x), (e),      (Any,          os << "_"; @@ -357,7 +371,7 @@ void PatternRulesetBuilder::push_rule(PatternRule r)  void PatternRulesetBuilder::append_from_lit(const Span& sp, const ::HIR::Literal& lit, const ::HIR::TypeRef& ty)  { -    TRACE_FUNCTION_F("lit="<<lit<<", ty="<<ty<<",   m_field_path.size()=" <<m_field_path.size() << " " << (m_field_path.empty() ? 0 : m_field_path.back()) ); +    TRACE_FUNCTION_F("lit="<<lit<<", ty="<<ty<<",   m_field_path=[" << m_field_path << "]");      TU_MATCHA( (ty.m_data), (e),      (Infer,   BUG(sp, "Ivar for in match type"); ), @@ -585,7 +599,7 @@ void PatternRulesetBuilder::append_from_lit(const Span& sp, const ::HIR::Literal  }  void PatternRulesetBuilder::append_from(const Span& sp, const ::HIR::Pattern& pat, const ::HIR::TypeRef& ty)  { -    TRACE_FUNCTION_F("pat="<<pat<<", ty="<<ty<<",   m_field_path.size()=" <<m_field_path.size() << " " << (m_field_path.empty() ? 0 : m_field_path.back()) ); +    TRACE_FUNCTION_F("pat="<<pat<<", ty="<<ty<<",   m_field_path=[" << m_field_path << "]");      struct H {          static uint64_t get_pattern_value_int(const Span& sp, const ::HIR::Pattern& pat, const ::HIR::Pattern::Value& val) {              TU_MATCH_DEF( ::HIR::Pattern::Value, (val), (e), @@ -1086,7 +1100,7 @@ namespace {      void get_ty_and_val(          const Span& sp,          const ::HIR::TypeRef& top_ty, const ::MIR::LValue& top_val, -        const PatternRule::field_path_t& field_path, unsigned int field_path_ofs, +        const field_path_t& field_path, unsigned int field_path_ofs,          /*Out ->*/ ::HIR::TypeRef& out_ty, ::MIR::LValue& out_val          )      { @@ -1098,7 +1112,7 @@ namespace {          ASSERT_BUG(sp, field_path_ofs <= field_path.size(), "Field path offset " << field_path_ofs << " is larger than the path [" << field_path << "]");          for(unsigned int i = field_path_ofs; i < field_path.size(); i ++ )          { -            auto idx = field_path[i]; +            auto idx = field_path.data[i];              TU_MATCHA( (cur_ty->m_data), (e),              (Infer,   BUG(sp, "Ivar for in match type"); ), @@ -1640,15 +1654,15 @@ struct DecisionTreeNode          );      // TODO: Arm specialisation? -    bool is_specialisation; -    PatternRule::field_path_t   m_field_path; +    field_path_t   m_field_path;      Values  m_branches;      Branch  m_default; -    DecisionTreeNode( PatternRule::field_path_t field_path ): -        is_specialisation(false)/*, +    DecisionTreeNode( field_path_t field_path ):          // TODO: This is commented out fo a reason, but I don't know why. -        m_field_path( mv$(field_path) ) // */ +        //m_field_path( mv$(field_path) ), +        m_branches(), +        m_default()      {}      static Branch clone(const Branch& b); @@ -1691,7 +1705,7 @@ struct DecisionTreeNode      ::MIR::LValue get_field(const ::MIR::LValue& base, unsigned int base_depth) const {          ::MIR::LValue   cur = base.clone();          for(unsigned int i = base_depth; i < m_field_path.size(); i ++ ) { -            const auto idx = m_field_path[i]; +            const auto idx = m_field_path.data[i];              if( idx == FIELD_DEREF ) {                  cur = ::MIR::LValue::make_Deref({ box$(cur) });              } @@ -1783,7 +1797,7 @@ struct DecisionTreeGen          const Span& sp,          const DecisionTreeNode::Branch& default_branch,          const DecisionTreeNode::Values::Data_Variant& branches, -        const PatternRule::field_path_t& field_path,   // used to know when to stop handling sub-nodes +        const field_path_t& field_path,   // used to know when to stop handling sub-nodes          const ::HIR::TypeRef& ty, ::MIR::LValue val,          ::std::function<void(const DecisionTreeNode&)> and_then          ); @@ -1791,14 +1805,14 @@ struct DecisionTreeGen          const Span& sp,          const DecisionTreeNode::Branch& default_branch,          const DecisionTreeNode::Values::Data_Slice& branches, -        const PatternRule::field_path_t& field_path, +        const field_path_t& field_path,          const ::HIR::TypeRef& ty, ::MIR::LValue val,          ::std::function<void(const DecisionTreeNode&)> and_then          );      void generate_tree_code__enum(          const Span& sp,          const DecisionTreeNode& node, const ::HIR::TypeRef& fake_ty, const ::MIR::LValue& val, -        const PatternRule::field_path_t& path_prefix, +        const field_path_t& path_prefix,          ::std::function<void(const DecisionTreeNode&)> and_then          );  }; @@ -1861,6 +1875,68 @@ void MIR_LowerHIR_Match_DecisionTree( MirBuilder& builder, MirConverter& conv, :      ASSERT_BUG(node.span(), !builder.block_active(), "Decision tree didn't terminate the final block");  } +#if 0 +DecisionTreeNode MIR_LowerHIR_Match_DecisionTree__MakeTree(const Span& sp, t_arm_rules& arm_rules) +{ +    ::std::vector<unsigned int> indexes; +    ::std::vector< slice<PatternRule> > rules; +    for(unsigned i = 0; i < arm_rules.size(); i ++) +    { +        rules.push_back( arm_rules[i].m_rules ); +        indexes.push_back(i); +    } +     +    return MIR_LowerHIR_Match_DecisionTree__MakeTree_Node(sp, indexes, rules); +} +DecisionTreeNode MIR_LowerHIR_Match_DecisionTree__MakeTree_Node(const Span& sp, slice<unsigned int> arm_indexes, slice< slice<PaternRule>> arm_rules) +{ +    assert( arm_indexes.size() == arm_rules.size() ); +    assert( arm_rules.size() > 1 ); +    assert( arm_rules[0].size() > 0 ); +     +    // 1. Sort list (should it already be sorted?) +    for(const auto& rules : arm_rules) +    { +        ASSERT_BUG(sp, rules.size() != arm_rules[0].size(), ""); +    } +     +    // 2. Detect all arms being `_` and move on to the next condition +    while( ::std::all_of(arm_rules.begin(), arm_rules.end(), [](const auto& r){ return r.m_rules[0].is_Any(); }) ) +    { +        // Delete first rule from all and continue. +        if( arm_rules[0].size() == 1 ) { +            // No rules left? +            BUG(sp, "Duplicate match arms"); +        } +         +        for(auto& rules : arm_rules) +        { +            rules = rules.subslice_from(1); +        } +    } +     +    // We have a codition. +    for(const auto& rules : arm_rules) +    { +        ASSERT_BUG(sp, rules[0].is_Any() || rules[0].tag() == arm_rules[0][0].tag(), "Mismatched rules in match"); +    } +     +    bool has_any = arm_rules.back()[0].is_Any(); +     +    // All rules must either be _ or the same type, and can't all be _ +    switch( arm_rules[0][0].tag() ) +    { +    case PatternRule::TAGDEAD:  throw ""; +    case PatternRule::TAG_Any:  throw ""; +     +    case PatternRule::TAG_Variant: +        break; +    // TODO: Value and ValueRange can appear together. +    // - They also overlap in non-trivial ways. +    } +} +#endif +  // ----------------------------  // DecisionTreeNode  // ---------------------------- @@ -1926,7 +2002,6 @@ DecisionTreeNode::Values DecisionTreeNode::clone(const DecisionTreeNode::Values&  DecisionTreeNode DecisionTreeNode::clone() const {      DecisionTreeNode    rv(m_field_path);      rv.m_field_path = m_field_path; -    rv.is_specialisation = is_specialisation;      rv.m_branches = clone(m_branches);      rv.m_default = clone(m_default);      return rv; @@ -1935,7 +2010,7 @@ DecisionTreeNode DecisionTreeNode::clone() const {  // Helpers for `populate_tree_from_rule`  namespace  { -    DecisionTreeNode::Branch new_branch_subtree(PatternRule::field_path_t path) +    DecisionTreeNode::Branch new_branch_subtree(field_path_t path)      {          return DecisionTreeNode::Branch( box$(DecisionTreeNode( mv$(path) )) );      } @@ -1945,7 +2020,7 @@ namespace      static void from_rule_valuerange(          const Span& sp,          ::std::vector< ::std::pair< DecisionTreeNode::Range<T>, DecisionTreeNode::Branch> >& be, T ve_start, T ve_end, -        const char* name, const PatternRule::field_path_t& field_path, ::std::function<void(DecisionTreeNode::Branch&)> and_then +        const char* name, const field_path_t& field_path, ::std::function<void(DecisionTreeNode::Branch&)> and_then          )      {          ASSERT_BUG(sp, ve_start < ve_end, "Range pattern with one value - " << ve_start << "..." << ve_end); @@ -2010,7 +2085,7 @@ namespace      static void from_rule_value(          const Span& sp,          ::std::vector< ::std::pair< DecisionTreeNode::Range<T>, DecisionTreeNode::Branch> >& be, T ve, -        const char* name, const PatternRule::field_path_t& field_path, ::std::function<void(DecisionTreeNode::Branch&)> and_then +        const char* name, const field_path_t& field_path, ::std::function<void(DecisionTreeNode::Branch&)> and_then          )      {          auto it = ::std::find_if(be.begin(), be.end(), [&](const auto& v){ return v.first.end >= ve; }); @@ -2593,6 +2668,9 @@ void DecisionTreeNode::unify_from(const Branch& b)          DEBUG("TODO - Unify mismatched arms? - " << b.as_Subtree()->m_branches.tag_str() << " and " << m_branches.tag_str());          return ;      } +    if( b.is_Subtree() ) { +        ASSERT_BUG(Span(), this->m_field_path == b.as_Subtree()->m_field_path, "Unifiying DTNs with mismatched paths - " << this->m_field_path << " != " << b.as_Subtree()->m_field_path); +    }      TU_MATCHA( (m_branches), (dst),      (Unset, @@ -2705,10 +2783,7 @@ void DecisionTreeNode::unify_from(const Branch& b)      return os;  }  ::std::ostream& operator<<(::std::ostream& os, const DecisionTreeNode& x) { -    os << "DTN ["; -    for(const auto idx : x.m_field_path) -        os << "." << static_cast<unsigned int>(idx); -    os << "] { "; +    os << "DTN [" << x.m_field_path << "] { ";      TU_MATCHA( (x.m_branches), (e),      (Unset,          os << "!, "; @@ -3200,7 +3275,7 @@ void DecisionTreeGen::generate_branches_Enum(      const Span& sp,      const DecisionTreeNode::Branch& default_branch,      const DecisionTreeNode::Values::Data_Variant& branches, -    const PatternRule::field_path_t& field_path, +    const field_path_t& field_path,      const ::HIR::TypeRef& ty, ::MIR::LValue val,      ::std::function<void(const DecisionTreeNode&)> and_then      ) @@ -3315,7 +3390,7 @@ void DecisionTreeGen::generate_branches_Slice(      const Span& sp,      const DecisionTreeNode::Branch& default_branch,      const DecisionTreeNode::Values::Data_Slice& branches, -    const PatternRule::field_path_t& field_path, +    const field_path_t& field_path,      const ::HIR::TypeRef& ty, ::MIR::LValue val,      ::std::function<void(const DecisionTreeNode&)> and_then      ) @@ -3393,14 +3468,14 @@ void DecisionTreeGen::generate_branches_Slice(  }  namespace { -    bool path_starts_with(const PatternRule::field_path_t& test, const PatternRule::field_path_t& prefix) +    bool path_starts_with(const field_path_t& test, const field_path_t& prefix)      {          //DEBUG("test="<<test<<", prefix="<<prefix);          if( test.size() < prefix.size() )          {              return false;          } -        else if( ! ::std::equal(prefix.begin(), prefix.end(), test.begin()) ) +        else if( ! ::std::equal(prefix.data.begin(), prefix.data.end(), test.data.begin()) )          {              return false;          } @@ -3414,7 +3489,7 @@ namespace {  void DecisionTreeGen::generate_tree_code__enum(      const Span& sp,      const DecisionTreeNode& node, const ::HIR::TypeRef& fake_ty, const ::MIR::LValue& val, -    const PatternRule::field_path_t& path_prefix, +    const field_path_t& path_prefix,      ::std::function<void(const DecisionTreeNode&)> and_then      )  { | 
