Goose  Artifact [0e0c1c59c0]

Artifact 0e0c1c59c00b621016040bfc3bec9d240f062ec167f59c72480725219ed087b8:

  • File bs/builtins/statements/hif.cpp — part of check-in [4464b9355c] at 2019-07-31 10:10:18 on branch trunk — Small cleanup. (user: achavasse size: 4276)

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

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

namespace empathy::builtins
{
    void SetupHIfStmt( Env& e )
    {
        auto handleHIf = []( Parser& p, const Term& t, uint32_t prec )
        {
            auto pPrecBB = p.currentBB();

            auto np = p.makeNestedParser();
            if( !np.parseExpression( precedence::IfStmt ) )
            {
                cout << "expected an expression following the #if statement.\n";
                return false;
            }

            auto condVal = np.popValue();
            if( !condVal )
            {
                cout << "expected an expression following the #if statement.\n";
                return false;
            }

            const auto& context = p.resolver()->context();
            auto converted = ConvertValueToType( context, *condVal, GetValueType< bool >() );
            if( holds_alternative< ValUnifyError >( converted ) )
            {
                switch( get< ValUnifyError >( converted ) )
                {
                    case ValUnifyError::NoSolution:
                        cout << "#if condition doesn't evaluate to a bool constant.\n";
                        break;

                    case ValUnifyError::Ambiguous:
                        cout << "ambiguous #if condition bool conversion.\n";
                        break;
                }

                return false;
            }

            auto condBool = get< Value >( converted );

            if( !condBool.isConstant() )
            {
                cout << "#if condition doesn't evaluate to a bool constant.";
                return false;
            }

            auto cond = FromValue< bool >( condBool );
            if( !cond )
            {
                cout << "#if condition doesn't evaluate to a bool constant.";
                return false;
            }

            auto next = p.resolver()->lookAheadUnresolved();
            if( !next )
            {
                cout << "#if: brace block expected.\n";
                return false;
            }

            auto decomp = Decompose( *next, Val< Delimiter >() );
            if( !decomp || *decomp != Delimiter::OpenBrace )
            {
                cout << "#if: brace block expected.\n";
                return false;
            }

            // Deal with the then block.
            if( *cond )
            {
                if( !p.parseBraceBlock() )
                    return false;
            }
            else
            {
                // Skip the block.
                p.resolver()->consumeNewLines();
                for( auto&& tok : p.resolver()->consumeUnit() )
                {}
            }

            next = p.resolver()->lookAheadUnresolved();
            if( next )
            {
                const auto* nextSid = get_if< StringId >( &next->content() );
                if( nextSid && *nextSid == "#else"_sid )
                {
                    p.resolver()->consumeUnresolved();

                    auto next = p.resolver()->lookAheadUnresolved();
                    auto decomp = Decompose( *next, Val< Delimiter >() );
                    if( !decomp || *decomp != Delimiter::OpenBrace )
                    {
                        cout << "#else: brace block expected.\n";
                        return false;
                    }

                    // Deal with the else block.
                    if( !*cond )
                    {
                        if( !p.parseBraceBlock() )
                            return false;
                    }
                    else
                    {
                        // Skip the block.
                        p.resolver()->consumeNewLines();
                        for( auto&& tok : p.resolver()->consumeUnit() )
                        {}
                    }
                }
            }

            return true;
        };

        Rule r( handleHIf );
        auto ruleVal = ToValue( move( r ) );
        auto ruleTerm = ValueToIRExpr( ruleVal );
        e.storeValue( AppendToVectorTerm( RootIdentity(), TSID( #if ) ), ANYTERM( _ ), ruleTerm );
    }
}