Goose  Artifact [a1f431708a]

Artifact a1f431708ab96257ed87e03a3324adb18b77ae981a435d840a64d99d4fc6f900:

  • File bs/builtins/types/func/invoke.cpp — part of check-in [eab1b7ec57] at 2019-02-13 21:03:55 on branch trunk — Split the builtin types directory into sub directories. (user: achavasse size: 3042)
  • File bs/builtins/types/inv-func.cpp — part of check-in [ca43fee365] at 2019-02-12 21:18:10 on branch trunk — Func: implement lazy body parsing. (user: achavasse size: 3042)

#include "builtins/builtins.h"

using namespace empathy::sema;

namespace empathy::builtins
{
    class FunctionInvocationRule : public InvocationRule
    {
        public:
            virtual optional< Value > resolveInvocation( const ptr< Env >& env, const Value& callee, const Value& args ) const override
            {
                PerformLazyFuncParsing( env, callee );

                UnificationContext uc( env );

                optional< UnificationContext > bestUC;
                optional< Term > bestSol;
                bool ambiguous = false;
                auto&& [sig, rtype] = getSignatureAndRType( env, callee );

                for( auto&& [s, uc] : Unify( sig, args.val(), uc ) )
                {
                    if( !bestSol || uc.score() > bestUC->score() )
                    {
                        bestUC = uc;
                        bestSol = s;
                        ambiguous = false;
                        continue;
                    }

                    if( uc.score() < bestUC->score() )
                        continue;

                    ambiguous = true;
                }

                if( ambiguous )
                {
                    // TODO error mgmt
                    cout << "ambiguous function call.\n";
                    return nullopt;
                }

                if( !bestSol )
                {
                    // TODO error mgmt
                    cout << "function arguments mismatch.\n";
                    return nullopt;
                }

                auto unifiedArgs = Substitute( *bestSol, *bestUC );
                return Value( rtype, make_shared< llr::Element >( llr::Call( callee, unifiedArgs ) ) );
            }

            virtual Term getSignature( const ptr< Env >& env, const Value& callee ) const override
            {
                return getSignatureAndRType( env, callee ).first;
            }

        private:
            pair< Term, Term > getSignatureAndRType( const ptr< Env >& env, const Value& callee ) const
            {
                // Extract the signature from the type
                auto valType = ValueFromIRExpr( callee.type() );
                assert( valType );

                auto decomp = Decompose( valType->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 };
            }
    };

    void SetupFunctionInvocationRule( Env& e )
    {
        e.invocationRuleSet()->addRule(
            ValueToIRExpr( Value( TSID( type ), TVEC( TSID( func ),
                ANYTERM( k ), ANYTERM( rt ), ANYTERM( p ), ANYTERM( sig ) ) ) ),
                make_shared< FunctionInvocationRule >() );
    }
}