Goose  Artifact [b36f25efb0]

Artifact b36f25efb0e77ec823a4d5272e7f7261a6b54eb12733f16b5ce5b4b0f702a343:

  • File bs/sema/postprocess.cpp — part of check-in [c3f897359f] at 2020-06-20 14:32:02 on branch trunk —
    • Got rid of the gross system of performing unifications twice in all cases. It's only really needed when invoking template functions.
    • Since the above had the unexpected side effect of fixing the tuple Initialize() overloads not being called, fixed those (which were actually broken).
    (user: achavasse size: 2560)

#include "sema.h"

namespace goose::sema
{
    Term WrapWithPostprocFunc( const Term& t, const ptr< PostProcFunc >& pp )
    {
        return SetComplexity( VEC( TSID( postproc ),
            TERM( static_pointer_cast< void >( pp ) ),
            t ), 0 );
    }

    Term WrapWithPostprocFunc( const Term& t, PostProcFunc&& pp )
    {
        return SetComplexity( VEC( TSID( postproc ),
            TERM( static_pointer_cast< void >( make_shared< PostProcFunc >( move( pp ) ) ) ),
            t ), 0 );
    }

    optional< pair< Term, ptr< PostProcFunc > > > UnwrapPostprocFunc( const Term& ppt )
    {
        auto result = Decompose( ppt,
            Vec(
                Lit( "postproc"_sid ),
                Val< ptr< void > >(),
                SubTerm()
            )
        );

        if( !result )
            return nullopt;

        auto&& [pPP, t] = *result;
        return make_pair( t, static_pointer_cast< PostProcFunc >( pPP ) );
    }

    optional< Term > Postprocess( const Term& src, UnificationContext& uc )
    {
        if( auto optHole = HoleFromIRExpr( src ) )
        {
            const auto& hole = *optHole;

            if( !hole.name.isNumerical() )
            {
                // If the name is not found, output it as is.
                auto index = uc.getLHSHoleIndex( hole.name );
                if( index == UnificationContext::InvalidIndex )
                    return src;

                const auto& val = uc.getValue( index );
                if( !val )
                    return src;

                return Postprocess( *val, uc );
            }
            else
            {
                const auto& optVal = uc.getValue( hole.name.id() );
                if( !optVal )
                    return HOLE( "_"_sid );

                return Postprocess( *optVal, uc );
            }
        }

        if( !holds_alternative< pvec >( src ) )
            return src;

        if( auto optPP = UnwrapPostprocFunc( src ) )
        {
            auto val = Postprocess( optPP->first, uc );
            if( !val )
                return nullopt;

            return ( *optPP->second )( *val, uc );
        }

        const auto& vec = *get< pvec >( src );

        auto outputTerms = make_shared< Vector >();
        outputTerms->reserve( vec.terms().size() );

        for( auto&& t : vec.terms() )
        {
            auto newT = Postprocess( t, uc );
            if( !newT )
                return nullopt;

            outputTerms->append( move( *newT ) );
        }

        return outputTerms;
    }
}