#include "builtins/builtins.h"
#include "lex/lex.h"
#include "parse/parse.h"
#include "builtins/helpers.h"
using namespace goose::parse;
namespace goose::builtins
{
const Term& EmptyPredicates()
{
static auto ep = VEC( TSID( predicates ), TERM( ptr< void >() ) );
return ep;
}
optional< ptr< TypePredicates > > GetTypePredicates( const Value& t )
{
if( !t.isType() )
return nullopt;
auto vec = Decompose( t.val(),
Val< pvec >()
);
if( !vec )
return nullopt;
if( vec->get()->terms().size() < 3 )
return nullopt;
auto result = Decompose( vec->get()->terms()[1],
Vec(
Lit( "predicates"_sid ),
Val< ptr< void > >()
)
);
if( !result )
return nullopt;
auto&& [pt] = *result;
return static_pointer_cast< TypePredicates >( pt );
}
Term InjectPredicatesIntoStdType( const Term& t, const ptr< TypePredicates >& predicates )
{
Term result( t );
auto vec = Decompose( t,
Val< pvec >()
);
assert( vec );
assert( vec->get()->terms().size() >= 3 );
vec->get()->terms()[1] = VEC( TSID( predicates ), static_pointer_cast< void >( predicates ) );
return result;
}
bool ParseTypePredicates( const Context& c, const Value& type )
{
auto optTypePreds = GetTypePredicates( type );
if( !optTypePreds || !*optTypePreds )
return true;
auto& tp = **optTypePreds;
return ParseTypePredicates( c, tp );
}
bool ParseTypePredicates( const Context& c, TypePredicates& tp )
{
if( tp.m_unparsedPredicates.empty() )
return true;
Context localContext( c.env(), tp.m_identity );
for( auto&& toks : tp.m_unparsedPredicates )
{
auto tokProvider = lex::MakeVectorAdapter( toks );
auto r = make_shared< parse::Resolver >( tokProvider, localContext );
Parser p( r );
if( !ParseExpressionList( p, precedence::VerificationPredicate + 1, tp.m_predicates ) )
{
tp.m_unparsedPredicates.clear();
return false;
}
}
tp.m_unparsedPredicates.clear();
// Context isn't relevant for unsatisfiable conditions errors.
DiagnosticsContext dc( 0, true );
// verify that the verification statements are satisfiable
verify::Condition vsv( c );
if( !vsv.addConditionsList( tp.m_predicates ) )
return false;
return vsv.verify();
}
}