Goose  Artifact [e676659c76]

Artifact e676659c76ce1dc3e17c4632e305dcbe604f707b86ca3281fe069b3441e85807:

  • File bs/builtins/operators/colon.cpp — part of check-in [c22f37bc75] at 2019-02-20 22:34:56 on branch trunk — Implemented the colon infix operator to explicitely build a Decl, TDecl or TNamedDecl. It will be useful in the future to build TDecls with a more complex TExpr than just a TVar on the rhs, it can be omitted otherwise. (user: achavasse size: 2527)

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

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

// Colon is a low level operator: it doesn't necessarily expect a value rhs operand,
// it can also accept an identifier.
// So we can't use the convenient operator wrapper rule.
namespace
{
    optional< uint32_t > InfixColonPrecedence( const Parser& p, const Term& t )
    {
        return precedence::ColonOp;
    }

    bool ParseInfixColonOperator( Parser& p, const Term& t, uint32_t prec )
    {
        const auto& leftVal = p.lastValue();
        if( !leftVal )
            return false;

        const auto& next = p.resolver()->lookAhead();
        const auto* name = get_if< StringId >( &next->content() );

        if( name )
        {
            // The rhs is an identifier: build either a Decl or a TNamedDecl.
            if( leftVal->type() == TSID( type ) )
            {
                p.resolver()->consumeUnresolved();
                auto type = ValueToIRExpr( *p.pop() );
                p.push( ToValue( builtins::Decl( move( type ), *name ) ) );
                return true;
            }
            else if( builtins::IsTExpr( *leftVal ) )
            {
                p.resolver()->consumeUnresolved();
                auto texpr = ValueToIRExpr( *p.pop() );
                p.push( ToValue( builtins::TNamedDecl( move( texpr ), *name ) ) );
                return true;
            }

            return false;
        }

        // Parse the right hand side, if it's a TExpr build a TDecl.
        // Otherwise, error out.
        auto np = p.makeNestedParser();
        if( !np.parseExpression( prec + 1 ) )
        {
            // TODO error mgmt
            cout << "expected an identifier or a template expression as the right hand side of the ':' operator.";
            return false;
        }

        auto rightVal = np.result();
        if( !rightVal || !IsTExpr( *rightVal ) )
        {
            // TODO error mgmt
            cout << "expected an identifier or a template expression as the right hand side of the ':' operator.";
            return false;
        }

        p.push( ToValue( TDecl( ValueToIRExpr( *p.pop() ), ValueToIRExpr( *rightVal ) ) ) );
        return true;
    }
}

namespace empathy::builtins
{
    void SetupColonOp( Env& e )
    {
        Rule r( InfixColonPrecedence, ParseInfixColonOperator );
        RegisterRule( e, ":"_sid, move( r ) );
    }
}