Goose  Artifact [150860d05c]

Artifact 150860d05c427586c0587c2b53137b27eb5ab201d46fab94e888e9b90f7babde:

  • File bs/builtins/types/func/typecheck.cpp — part of check-in [2d2defb442] at 2021-08-29 21:49:39 on branch trunk —
    • Type predicates' identity and placeholder are now created immediately, rather than when parsing their content
    • Added missing type predicates lazy parsing during typechecking
    • Fixed a type checking rule falling back to unification, which is no longer needed
    (user: achavasse size: 5289)

#include "builtins/builtins.h"

using namespace goose;
using namespace goose::eir;

namespace goose::builtins
{
    void SetupFunctionTypeChecking( Env& e )
    {
        // Default param rule: we basically treat it like a regular value.
        // Things that need a more specific rule for params can override this with
        // more specific pattern.
        e.typeCheckingRuleSet()->addTypeCheckingRule( TCRINFOS,

            ValueToEIR( ValuePattern(
                TSID( param ),
                ANYTERM( _ ),
                ANYTERM( _ ) ) ),

            ValueToEIR( ValuePattern(
                ANYTERM( _ ),
                ANYTERM( _ ),
                ANYTERM( _ ) ) ),

        []( const Term& lhs, const Term& rhs, const TypeCheckingContext& tcc ) -> TCGen
        {
            auto lhsVal = *ValuePatternFromEIR( lhs );
            lhsVal.sort() = HOLE( "_"_sid );
            co_yield TypeCheck( ValueToEIR( lhsVal ), rhs, tcc );
        } );

        // Constant param rule
        e.typeCheckingRuleSet()->addTypeCheckingRule( TCRINFOS,

            ValueToEIR( ValuePattern(
                TSID( constant ),
                ANYTERM( _ ),
                ANYTERM( _ ) ) ),

            ValueToEIR( ValuePattern(
                TSID( constant ),
                ANYTERM( _ ),
                ANYTERM( _ ) ) ),

        []( const Term& lhs, const Term& rhs, const TypeCheckingContext& tcc ) -> TCGen
        {
            auto lhsVal = *ValuePatternFromEIR( lhs );
            auto rhsVal = *ValuePatternFromEIR( rhs );

            // Check the types
            for( auto&& [ut,tcc] : TypeCheck( lhsVal.type(), rhsVal.type(), tcc ) )
            {
                // Check the contents
                for( auto&& [uv,tcc] : TypeCheck( lhsVal.val(), rhsVal.val(), tcc ) )
                {
                    ValuePattern result( move( ut ), move( uv ), rhsVal.locationId() );
                    co_yield { ValueToEIR( move( result ) ), tcc };
                }
            }
        } );

        auto funcTypePat = ValueToEIR( Value( TypeType(), VEC( TSID( func ),
            ANYTERM( _ ), ANYTERM( RT ), ANYTERM( P ), ANYTERM( _ ), ANYTERM( VA ) ) ) );

        auto tFuncTypePat = ValueToEIR( Value( TypeType(), VEC( TSID( texpr ), TSID( tfunc ),
            ANYTERM( _ ), ANYTERM( _ ), ANYTERM( _ ), ANYTERM( _ ) ) ) );

        // func type param / func arg
        e.typeCheckingRuleSet()->addTypeCheckingRule( TCRINFOS,

            ParamPat( funcTypePat ),

            ValueToEIR( ValuePattern(
                TSID( constant ),
                funcTypePat,
                ANYTERM( _ ) ) ),

        []( const Term& lhs, const Term& rhs, const TypeCheckingContext& tcc ) -> TCGen
        {
            auto rhsVal = *ValueFromEIR( rhs );

            if( IsBuiltinFunc( rhsVal ) )
            {
                co_yield { rhs, tcc };
                co_return;
            }

            auto wrapped = WrapWithPostprocFunc( rhs, [rhsVal]( const Term& t, const TypeCheckingContext& tcc )
                -> optional< Term >
            {
                DiagnosticsContext dc( 0, true );
                VerbosityContext vc( Verbosity::Normal, true );

                auto func = CompileFunc( tcc.context(), rhsVal );
                if( func.isPoison() )
                    return nullopt;

                return ValueToEIR( func );
            } );

            co_yield { move( wrapped ), tcc };
        } );

        // tfunc type param / func arg
        e.typeCheckingRuleSet()->addTypeCheckingRule( TCRINFOS,

            ParamPat( move( tFuncTypePat ) ),

            ValueToEIR( ValuePattern(
                TSID( constant ),
                move( funcTypePat ),
                ANYTERM( _ ) ) ),

        []( const Term& lhs, const Term& rhs, const TypeCheckingContext& tcc ) -> TCGen
        {
            auto ldecomp = Decompose( lhs,
                Vec(
                    Lit( "value"_sid ),
                    SubTerm(),
                    SubTerm(),
                    SubTerm(),
                    Val< LocationId >()
                )
            );
            assert( ldecomp );

            auto&& [sort, type, val, locId] = *ldecomp;

            auto callPat = BuildArgPatternFromTFuncType( tcc.context(), *ValueFromEIR( type ) );
            assert( callPat );

            auto rhsVal = *ValueFromEIR( rhs );
            auto sig = GetFuncSig( rhsVal );

            for( auto&& [s, tcc] : TypeCheck( sig, *callPat, tcc ) )
            {
                if( IsBuiltinFunc( rhsVal ) )
                {
                    co_yield { ValueToEIR( rhsVal ), tcc };
                    continue;
                }

                auto wrapped = WrapWithPostprocFunc( s, [rhsVal]( const Term& t, const TypeCheckingContext& tcc )
                    -> optional< Term >
                {
                    DiagnosticsContext dc( 0, true );
                    VerbosityContext vc( Verbosity::Normal, true );

                    auto func = CompileFunc( tcc.context(), rhsVal );
                    if( func.isPoison() )
                        return nullopt;

                    return ValueToEIR( func );
                } );

                co_yield { move( wrapped ), tcc };
            }
        } );
    }
}