Goose  Artifact [11f5fd3706]

Artifact 11f5fd3706eb814c15629c965cdc117c36de628b858c08e72747dd8c133a6701:

  • File bs/sema/invocation.cpp — part of check-in [48a020a1fa] at 2019-08-17 14:49:29 on branch trunk —
    • Intrinsics automatically set their domain depending on the domain restrictions of the builtin types that they use.
    • Declaring a local variable of a compile-time only type is now properly rejected during codegen.
    • Improved error messages for operators and extension point invocations.
    (user: achavasse size: 2387)

#include "sema.h"
#include "builtins/builtins.h"

namespace empathy::sema
{
    ptr< InvocationRule > GetInvocationRule( const Env& e, const Value& callee )
    {
        const auto& rules = e.invocationRuleSet()->rules();

        MatchSolution bestSol;
        ptr< InvocationRule > pBestRule;
        bool ambiguous = false;

        auto calleeTerm = ValueToIRExpr( callee );

        for( auto&& [s, rule] : Match( calleeTerm, rules ) )
        {
            if( !pBestRule || s > bestSol )
            {
                bestSol = s;
                pBestRule = rule;
                ambiguous = false;
                continue;
            }

            if( s < bestSol )
                continue;

            ambiguous = true;
        }

        // Let's not really worry about how to properly report this for now.
        if( ambiguous )
            throw runtime_error( "ambiguous invocation rule" );

        return pBestRule;
    }

    bool CanBeInvoked( const Context& c, const Value& callee )
    {
        return !!GetInvocationRule( *c.env(), callee );
    }

    Value ResolveInvocation( const Context& c, const ptr< InvocationRule >& pInvRule, const Value& callee, const Value& args )
    {
        auto loc = Location::CreateSpanningLocation( callee.locationId(), args.locationId() );

        // If the current domain isn't compile time and the args are constant, attempt to resolve it as a compile time invocation
        // first.
        if( args.isConstant() && c.domain() != DomainCompileTime() && builtins::IsTupleConstant( args ) )
        {
            // This is a speculative attempt at compile time execution. It it doesn't work, we'll
            // just try to resolve the invocation in its originally intended domain.
            // So don't display any error message during the attempt.
            VerbosityContext vc( Verbosity::Silent );

            Context localC( c.env(), InjectDomainIntoIdentity( c.identity(), DomainCompileTime() ) );
            auto result = pInvRule->resolveInvocation( localC, loc, callee, args ).setLocationId( loc );
            if( !result.isPoison() )
                return result;
        }

        if( loc == ~0 )
            DiagnosticsManager::GetInstance().setCurrentVerbosityLevel( Verbosity::SilentLocally );

        return pInvRule->resolveInvocation( c, loc, callee, args ).setLocationId( loc );
    }
}