Goose  Artifact [d94488663d]

Artifact d94488663db9dbd3b702f16334f39d3b45bb12ad1e0a17e17419d283c7df970b:

  • File bs/builtins/types/func/func.cpp — part of check-in [8a8e76084e] at 2019-03-02 21:01:51 on branch trunk — Function calls are now eagerly evaluated during parsing. (user: achavasse size: 3220)

#include "builtins/builtins.h"
#include "lex/lex.h"
#include "parse/parse.h"

using namespace empathy::builtins;
using namespace empathy::parse;

namespace empathy::builtins
{
    pair< Term, Term > GetFuncSigAndRType( const Value& func )
    {
        auto funcType = ValueFromIRExpr( func.type() );
        assert( funcType );

        auto decomp = Decompose( funcType->val(),
            Vec(
                Lit( "func"_sid ),
                SubTerm(),  // kind
                SubTerm(),  // return type
                SubTerm(),  // param types
                SubTerm()   // signature
            )
        );

        assert( decomp );
        auto&& [kind, rtype, ptypes, sig] = *decomp;
        return { sig, rtype };
    }

    ParamListKind CheckParamListKind( const Value& tup )
    {
        if( !IsTuple( tup ) )
            return ParamListKind::Invalid;

        auto result = ParamListKind::Regular;

        const auto& vec = *get< pvec >( tup.val().content() );
        for( auto&& x : vec.terms() )
        {
            auto v = ValueFromIRExpr( x );
            if( !v )
                return ParamListKind::Invalid;

            if( IsTDecl( *v ) || IsTNamedDecl( *v ) )
                result = ParamListKind::Template;
            else if( !IsDecl( *v ) && !v->isConstant() )
                return ParamListKind::Invalid;
        }

        return result;
    }

    void PerformLazyFuncParsing( const ptr< Env >& env, const Value& func )
    {
        const auto& content = func.val().content();
        const auto& pLLR = get< ptr< void > >( content );
        const auto& pFunc = static_pointer_cast< llr::Func >( pLLR );

        const auto* pToks = get_if< vector< Term > >( &pFunc->body() );
        if( !pToks )
            return;

        Context localContext( env, pFunc->identity() );
        auto tokProvider = make_shared< lex::VectorAdapter >( *pToks );
        auto r = make_shared< parse::Resolver >( tokProvider, localContext );
        Parser p( r );

        if( !p.parseExpression() )
            pFunc->body() = llr::Element();

        auto result  = p.result();
        if( !result || result->isConstant() )
            pFunc->body() = llr::Element();
        else
            pFunc->body() = *result->llr();
    }
}

namespace empathy::ir
{
    const Term& Bridge< FuncType >::Type()
    {
        static auto type = TSID( type );
        return type;
    }

    Value Bridge< FuncType >::ToValue( const FuncType& ft )
    {
        return Value( Type(), TVEC( TSID( func ), TSID( regular ),
            ft.returnType(), ft.paramTypes(), ft.signature() ) );
    }

    optional< FuncType > Bridge< FuncType >::FromValue( const Value& v )
    {
        auto typeVal = ValueFromIRExpr( v.type() );
        auto result = Decompose( typeVal->val(),
            Vec(
                Lit( "func"_sid ),
                Lit( "regular"_sid ),
                SubTerm(),  // return type
                SubTerm(),  // param types
                SubTerm()   // signature
            )
        );

        if( !result )
            return nullopt;

        auto&& [rtype, params, sig] = *result;
        return FuncType( move( rtype ), move( params ), move( sig ) );
    }
}