Goose  Artifact [57c88137cd]

Artifact 57c88137cd0f8861efd2517cd59502eb005e756db758b5c6cae6401e56717dcd:

  • File bs/ir/match.h — part of check-in [fc6c22b8bc] at 2019-01-05 21:32:43 on branch trunk —
    • Changed the matching scoring system to add 2 to the complexity count for each literal value matched in the pattern.
    • Added hole unification tests.
    • Fixed various hole unification bugs.
    (user: achavasse size: 2828)

#ifndef EMPATHY_IR_MATCH_H
#define EMPATHY_IR_MATCH_H

namespace empathy::ir
{
    class MatchSolution
    {
        public:
            size_t complexity() const { return m_complexity; }
            size_t numVars() const;

            template< typename T >
            const T* getVar( const StringId& name ) const
            {
                if( !m_pVars )
                    return nullptr;

                auto it = m_pVars->find( name );
                if( it == m_pVars->end() )
                    return nullptr;

                return any_cast< T >( &it->second );
            }

            // Tries to set the variable. If it already exists but have a different
            // value, returns false.
            template< typename T >
            bool setVar( const StringId& name, T&& val )
            {
                if( m_pVars )
                {
                    auto it = m_pVars->find( name );
                    if( it != m_pVars->end() )
                    {
                        using TT = remove_constref_t< T >;
                        if( const auto* pExistingVal = any_cast< TT >( &it->second ) )
                            return *pExistingVal == val;

                        return false;
                    }
                }

                setupVars();
                m_pVars->emplace( name, forward< T >( val ) );
                return true;
            }

            void addComplexity( uint32_t n ) { m_complexity += n; }

            bool operator<( const MatchSolution& rhs ) const
            {
                if( m_complexity != rhs.m_complexity )
                    return m_complexity < rhs.m_complexity;

                return numVars() > rhs.numVars();
            }

            bool operator>( const MatchSolution& rhs ) const
            {
                if( m_complexity != rhs.m_complexity )
                    return m_complexity > rhs.m_complexity;

                return numVars() < rhs.numVars();
            }

        private:
            void setupVars();

            ptr< unordered_map< StringId, any > > m_pVars;
            uint32_t m_complexity = 0;    // Each matched structural element of the pattern (vector) adds 1,
                                          // each matched literal element of the pattern adds 2
    };

    extern optional< MatchSolution > Match( const Term& expression, const Term& pattern );

    template< typename U >
    static Generator< pair< MatchSolution, const U& > > Match( const Term& expression, const Trie< U >& patterns );

    template< typename U, typename V >
    static Generator< tuple< MatchSolution, const U&, const V& > > Match( const Trie< U >& expressions, const Trie< V >& patterns );

    extern Generator< MatchSolution > Match( const Term& expression, const Trie<>& patterns );
}

#endif