#include "cir/cir.h"

namespace goose::cir
{
    void AppendInstrSeq( InstrSeq& is, InstrSeq&& isToAppend )
    {
        is.splice( is.end(), isToAppend );

        // TODO update canBeExecuted, store it in InstrSeq?
    }

    void AppendInstrSeq( InstrSeq& is, const InstrSeq& isToAppend )
    {
        for( auto&& instr : isToAppend )
            AppendToInstrSeq( is, instr );
    }

    void AppendValue( InstrSeq& is, Value&& v )
    {
        if( v.cir() )
            AppendToInstrSeq( is, move( *v.cir() ) );
        else
            is.emplace_back( PushConstant( move( v ) ) );
    }

    void AppendValue( InstrSeq& is, const Value& v )
    {
        if( v.cir() )
            AppendToInstrSeq( is, *v.cir() );
        else
            is.emplace_back( PushConstant( v ) );
    }

    bool IsValueConstantOrExecutable( const eir::Value& val )
    {
        if( val.isConstant() )
            return true;

        for( const auto& instr : *val.cir() )
        {
            if( !instr.canBeExecuted() )
                return false;
        }

        return true;
    }

    bool CanValueBeEagerlyEvaluated( const eir::Value& val )
    {
        if( val.isConstant() )
            return true;

        for( const auto& instr : *val.cir() )
        {
            if( !instr.canBeEagerlyEvaluated() )
                return false;
        }

        return true;
    }

    bool DoesInstrSeqHaveSideEffects( const InstrSeq& is )
    {
        for( auto&& instr : is )
        {
            if( instr.haveSideEffects() )
                return true;
        }

        return false;
    }
}
