Goose  Artifact [025585a9a1]

Artifact 025585a9a1c7e1f022e7226ae1540485cf87b2b915b374155187c155d554f3ea:

  • File bs/sema/postprocess.cpp — part of check-in [176ee856a6] at 2021-02-12 23:57:22 on branch trunk — Added a "flavor" term to holes to be able to have specific rules for TVar holes and for forwarding holes. Refactored forwarding holes to use this, instead of being represented as compound expressions (which would probably have broken down horribly in some complex type checking scenarios) (user: achavasse size: 2577)

#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, TypeCheckingContext& tcc )
    {
        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 = tcc.getLHSHoleIndex( hole.name() );
                if( index == TypeCheckingContext::InvalidIndex )
                    return src;

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

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

                return Postprocess( *optVal, tcc );
            }
        }

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

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

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

        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, tcc );
            if( !newT )
                return nullopt;

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

        return outputTerms;
    }
}