#include "g0api/g0api.h"
#include "eir/eir.h"
#include "builtins/helpers.h"
using namespace goose;
using namespace goose::g0api;
namespace
{
template< typename T >
void SetupWrapperForType( Env& e, StringId name, const ptr< OverloadSet >& pEquals, const ptr< OverloadSet >& pNotEquals )
{
DefineConstant( e, name, GetValueType< TypeWrapper< T > >() );
using reftype = CustomPattern< Value, ReferenceType::PatternMutableOfType< TypeWrapper< T > > >;
auto type = ValueToEIR( ToValue( builtins::ReferenceType( GetValueType< TypeWrapper< T > >(), TSID( mut ) ) ) );
RegisterBuiltinFunc< Intrinsic< Value ( reftype ) > >( e, e.extInitialize(),
[]( auto&& c, const Value& r )
{
// Do nothing: the types we're wrapping are default initialized anyway.
// The only purpose of this Initialize overload is to let goose know that
// the type has a default initialization.
return Value( GetValueType< void >(), 0U );
} );
using constreftype = CustomPattern<
TypeWrapper< T >, ReferenceType::PatternConstOfType< TypeWrapper< T > > >;
RegisterBuiltinFunc< bool ( constreftype, constreftype ) >( e, pEquals,
[]( const TypeWrapper< T >& lhs, const TypeWrapper< T >& rhs )
{
return lhs.get() == rhs.get();
} );
RegisterBuiltinFunc< bool ( constreftype, constreftype ) >( e, pNotEquals,
[]( const TypeWrapper< T >& lhs, const TypeWrapper< T >& rhs )
{
return lhs.get() != rhs.get();
} );
RegisterBuiltinFunc< string ( TypeWrapper< T > ) >( e, "ToString"_sid,
[]( const TypeWrapper< T >& t )
{
stringstream sstr;
sstr << t.get();
return sstr.str();
} );
}
}
namespace goose::g0api
{
void SetupTypeWrappers( Env& e )
{
auto pEquals = GetOverloadSet( e, "operator_equals"_sid );
auto pNotEquals = GetOverloadSet( e, "operator_not_equals"_sid );
////////////////////////////
// EIR types
////////////////////////////
SetupWrapperForType< Term >( e, "Term"_sid, pEquals, pNotEquals );
SetupWrapperForType< LocationId >( e, "LocationId"_sid, pEquals, pNotEquals );
SetupWrapperForType< StringId >( e, "StringId"_sid, pEquals, pNotEquals );
SetupWrapperForType< Hole >( e, "Hole"_sid, pEquals, pNotEquals );
SetupWrapperForType< AnyTerm >( e, "AnyTerm"_sid, pEquals, pNotEquals );
SetupWrapperForType< VecOfLength >( e, "VecOfLength"_sid, pEquals, pNotEquals );
SetupWrapperForType< pvec >( e, "Vec"_sid, pEquals, pNotEquals );
SetupWrapperForType< APSInt >( e, "FixedInt"_sid, pEquals, pNotEquals );
SetupWrapperForType< Value >( e, "Value"_sid, pEquals, pNotEquals );
////////////////////////////
// CIR types
////////////////////////////
SetupWrapperForType< ptr< CFG > >( e, "CFG"_sid, pEquals, pNotEquals );
SetupWrapperForType< ptr< BasicBlock > >( e, "BasicBlock"_sid, pEquals, pNotEquals );
SetupWrapperForType< ptr< Instruction > >( e, "Instruction"_sid, pEquals, pNotEquals );
SetupWrapperForType< ptr< Terminator > >( e, "Terminator"_sid, pEquals, pNotEquals );
////////////////////////////
// ReferenceType
////////////////////////////
SetupWrapperForType< ptr< ReferenceType > >( e, "RefTypeDesc"_sid, pEquals, pNotEquals );
RegisterBuiltinFunc< bool ( TypeWrapper< Term >, TermRef< TypeWrapper< ptr< ReferenceType > > > ) >( e, "EIRToRefTypeDesc"_sid,
[]( const TypeWrapper< Term >& t, TermRef< TypeWrapper< ptr< ReferenceType > > >& out )
{
auto val = EIRToValue( t.get() );
if( !val )
return false;
auto refType = FromValue< ReferenceType >( *val );
if( !refType )
return false;
out = make_shared< ReferenceType >( move( *refType ) );
return true;
} );
RegisterBuiltinFunc< TypeWrapper< Term > ( TypeWrapper< ptr< ReferenceType > > ) >( e, "RefTypeDescToEIR"_sid,
[]( TypeWrapper< ptr< ReferenceType > >& rt ) -> TypeWrapper< Term >
{
return ValueToEIR( ToValue( *rt.get() ) );
} );
RegisterBuiltinFunc< TypeWrapper< ptr< ReferenceType > > ( TypeWrapper< Term >, TypeWrapper< Term > ) >( e, "MkRefTypeDesc"_sid,
[]( const TypeWrapper< Term >& type, const TypeWrapper< Term >& bhv ) -> TypeWrapper< ptr< ReferenceType > >
{
return make_shared< ReferenceType >( type, bhv );
} );
RegisterBuiltinFunc< tuple< TypeWrapper< Term >, TypeWrapper< Term > > ( TypeWrapper< ptr< ReferenceType > >) >( e, "UnpackRefTypeDesc"_sid,
[]( const TypeWrapper< ptr< ReferenceType > >& refType ) -> tuple< TypeWrapper< Term >, TypeWrapper< Term > >
{
return { refType->type(), refType->behavior() };
} );
////////////////////////////
// Predicates
////////////////////////////
RegisterBuiltinFunc< bool ( TypeWrapper< Value >, TermRef< TypeWrapper< pvec > > ) >( e, "GetTypePredicates"_sid,
[]( const TypeWrapper< Value >& type, TermRef< TypeWrapper< pvec > >& out )
{
auto ppPreds = GetTypePredicates( type );
if( !ppPreds || !( *ppPreds ) )
return false;
const auto& preds = **ppPreds;
if( !preds.m_predicates )
return false;
out = preds.m_predicates;
return true;
} );
}
}