#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 );
}
}