Goose  Artifact [01a412779e]

Artifact 01a412779edf93d3fbdfd6cbd9aeb4a3fd78ec7520b1856ad824bc7521eb941b:

  • File bs/builtins/operators/where.cpp — part of check-in [e1ede8dafa] at 2021-11-25 20:30:26 on branch trunk —
    • simplified ref parsing implementation by using the parser's infix parsing rule helper
    • refactored "requires" and "ensures": they are now simply infix operators that take a function type on the lhs and a proposition list on the rhs
    (user: zlodo size: 3122)

#include "builtins/builtins.h"
#include "precedence.h"

using namespace goose;
using namespace goose::eir;
using namespace goose::parse;
using namespace goose::builtins;

namespace goose::builtins
{
    void SetupWhereOp( Env& e )
    {
        auto wherePrecedence = []( const Parser& p ) -> optional< uint32_t >
        {
            auto lastVal = p.peekLastValue();
            if( !lastVal )
                return nullopt;

            if( !IsType( p.context(), *lastVal ) )
                return nullopt;

            if( !GetTypePredicates( *lastVal ) )
                return nullopt;

            return precedence::ContractOp;
        };

        auto parseWhere = []( Parser& p, LocationId locationId, uint32_t prec )
        {
            auto& dm = DiagnosticsManager::GetInstance();

            auto next = p.resolver()->lookAheadUnresolved();
            if( !next )
            {
                dm.emitSyntaxErrorMessage( p.resolver()->currentLocation(), "'[' expected after 'where'.", 0 );
                return false;
            }

            auto decomp = Decompose( next->first, Val< Delimiter >() );
            if( !decomp || *decomp != Delimiter::OpenBracket )
            {
                dm.emitSyntaxErrorMessage( p.resolver()->currentLocation(), "'[' expected after 'where'.", 0 );
                return false;
            }

            auto type = *p.popValue();
            auto preds = *GetTypePredicates( type );
            if( preds )
                preds = make_shared< Propositions >( *preds );
            else
            {
                preds = make_shared< Propositions >();
                auto& c = p.context();

                // Create a new identity for the predicates, which imports everything from the parent identity
                // and also makes @val visible as a placeholder for the type's value.
                preds->setIdentity( VEC( Env::NewUniqueId() ) );
                c.env()->addVisibilityRule( c.identity(), preds->identity() );

                auto typeTerm = ValueToEIR( type );

                auto name = "@val"_sid;
                auto valuePlaceholderIdentity = AppendToVectorTerm( preds->identity(), TERM( name ) );
                c.env()->storeValue( valuePlaceholderIdentity, ANYTERM( _ ),
                    ValueToEIR( BuildComputedValue( typeTerm, cir::Placeholder( typeTerm, name ) ) ) );
            }

            preds->unparsed().emplace_back();
            auto& toks = preds->unparsed().back();

            auto g = p.resolver()->consumeUnit();

            // Strip the start and end brackets
            auto beg = g.begin();
            advance( beg, 1 );
            move( beg, g.end(), back_inserter( toks ) );
            auto loc = Location::CreateSpanningLocation( type.locationId(), toks.back().second );
            toks.resize( toks.size() - 1 );

            p.pushValue( Value( type.type(), InjectPredicatesIntoStdType( type.val(), preds ) )
                .setLocationId( loc ) );
            return true;
        };

        RegisterRule( e, "where"_sid, Rule( wherePrecedence, parseWhere ) );
    }
}