Goose  Artifact [6b3b40cfb0]

Artifact 6b3b40cfb034690a32cc36a4efe3f99d93f6bd1131c7f0139e53a4de8502c611:

  • File bs/builtins/operators/helpers.h — part of check-in [2efa23555d] at 2019-08-11 01:26:17 on branch trunk —
    • ir: created a new type for LocationId which is handled in a specific way so that two LocationIds are always considered equal by pattern matching. This prevent the values' locationIds stored in ir expressions from fucking up everything.
    • propagate value locations in a few places: in the parser, when resolving invocations and when doing eager evaluation. There are probably a lot of other places still missing.
    • converted all the builtin statements to use the DiagnosticsManager.
    (user: achavasse size: 3923)

#ifndef EMPATHY_BUILTINS_OPERATORS_HELPERS_H
#define EMPATHY_BUILTINS_OPERATORS_HELPERS_H

#include "builtins/helpers.h"

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

    template< typename... R >
    void BuildParseRule( sema::Env& env, const StringId& name, R&&... ruleBuilders )
    {
        parse::BuildParseRule( env, name, AppendToVectorTerm( RootIdentity(), TERM( name ) ),
            forward< R >( ruleBuilders )... );
    }

    struct UnaryOpTag {};
    struct BinaryOpTag {};

    template< typename... R >
    auto PrefixOp( StringId funcName, uint32_t precedence, R&&... rules )
    {
        return [&,precedence,funcName]( auto&& e, auto&& r, auto&& name )
        {
            MakePrefixOp( e, r, name, precedence,
                BuildOpFunc< UnaryOpTag >( e, funcName, forward< R >( rules )... ) );
        };
    }

    template< typename... R >
    auto PostfixOp( StringId funcName, uint32_t precedence, R&&... rules )
    {
        return [&,precedence,funcName]( auto&& e, auto&& r, auto&& name )
        {
            MakePostfixOp( e, r, name, precedence,
                BuildOpFunc< UnaryOpTag >( e, funcName, forward< R >( rules )... ) );
        };
    }

    template< typename... R >
    auto LeftAssInfixOp( StringId funcName, uint32_t precedence, R&&... rules )
    {
        return [&,precedence,funcName]( auto&& e, auto&& r, auto&& name )
        {
            MakeLeftAssInfixOp( e, r, name, precedence,
                BuildOpFunc< BinaryOpTag >( e, funcName, forward< R >( rules )... ) );
        };
    }

    template< typename... R >
    auto RightAssInfixOp( StringId funcName, uint32_t precedence, R&&... rules )
    {
        return [&,precedence,funcName]( auto&& e, auto&& r, auto&& name )
        {
            MakeRightAssInfixOp( e, r, name, precedence,
                BuildOpFunc< BinaryOpTag >( e, funcName, forward< R >( rules )... ) );
        };
    }

    template< typename tag, typename... R >
    auto BuildOpFunc( Env& e, StringId funcName, R&&... ruleBuilders )
    {
        auto pOvlSet = CreateOverloadSet( e, funcName );
        ( ( ruleBuilders( e, pOvlSet, tag() ) ), ... );

        return [pOvlSet]< typename... O >( Parser& p, O&&... operands )
        {
            return InvokeOverloadSet( p.resolver()->context(), pOvlSet, MakeTuple( operands... ) );
        };
    }

    template< typename T, typename I, typename RT = T >
    auto ForType()
    {
        return []< typename tag >( auto&& e, auto&& pOvlSet, tag t )
        {
            using intrinsicType = Intrinsic< Value ( T, T ) >;
            auto intrinsicFunc = []( const Value& lhs, const Value& rhs )
            {
                return BuildComputedValue( GetValueType< RT >(), I( lhs, rhs ) );
            };

            pOvlSet->add( e, ToValue< intrinsicType >( move( intrinsicFunc ) ), GetFuncInvocationRule() );
        };
    }

    template< typename T, typename F >
    auto ForType( F&& func )
    {
        return [&]< typename tag >( auto&& e, auto&& pOvlSet, tag t )
        {
            if constexpr( is_same_v< tag, UnaryOpTag > )
            {
                using intrinsicType = Intrinsic< Value ( T ) >;
                pOvlSet->add( e, ToValue< intrinsicType >( forward< F >( func ) ), GetFuncInvocationRule() );
            }
            else
            {
                using intrinsicType = Intrinsic< Value ( T, T ) >;
                pOvlSet->add( e, ToValue< intrinsicType >( forward< F >( func ) ), GetFuncInvocationRule() );
            }
        };
    }

    template< typename T1, typename T2, typename F >
    auto ForTypes( F&& func )
    {
        return [&]< typename tag >( auto&& e, auto&& pOvlSet, tag t )
        {
            using intrinsicType = Intrinsic< Value ( T1, T2 ) >;
            pOvlSet->add( e, ToValue< intrinsicType >( forward< F >( func ) ), GetFuncInvocationRule() );
        };
    }
}

#endif