#include "builtins/builtins.h"
#include "parse/parse.h"
using namespace goose::builtins;
using namespace goose::cir;
using namespace goose::parse;
namespace goose::builtins
{
const Term& LocalVar::PatternAny::GetPattern()
{
static auto pattern = GetValueType< LocalVar >( HOLE( "_"_sid ) );
return pattern;
}
const Term& LocalVar::PatternAnyOfTypeT::GetPattern()
{
static auto pattern = GetValueType< LocalVar >( HOLE( "T"_sid ) );
return pattern;
}
Value DeclareLocalVar( const Context& c, const Term& type, StringId name,
const optional< Value >& initializer, LocationId locId )
{
auto cfg = GetCFG( c );
if( !cfg )
return PoisonValue();
auto bb = cfg->currentBB();
if( !bb )
return PoisonValue();
Value typeVal = *EIRToValue( type );
if( !typeVal.isType() )
typeVal = ToType( c, typeVal );
if( !ParseTypePredicates( c, typeVal ) )
return PoisonValue();
auto index = cfg->nextValueIndex();
LocalVar lv( name, ValueToEIR( typeVal ), index );
bb->append( AllocVar( lv.type(), index, locId ) );
Value initResult;
{
DiagnosticsContext dc( 0, "When invoking _Initialize." );
if( initializer )
{
initResult = InvokeOverloadSet( c, c.env()->extInitialize(),
MakeClosedTuple( ToValue( lv ).setLocationId( locId ), *initializer ), locId );
}
else
{
initResult = InvokeOverloadSet( c, c.env()->extInitialize(),
MakeClosedTuple( ToValue( lv ).setLocationId( locId ) ), locId );
}
}
if( !initResult.isPoison() )
{
DiagnosticsContext dc2( initResult.locationId(), "When invoking _DropValue." );
InvokeOverloadSet( c, c.env()->extDropValue(),
MakeClosedTuple( c.builder(), move( initResult ) ), initResult.locationId() );
}
auto locVar = ToValue( lv );
auto identity = AppendToVectorTerm( c.identity(), name );
c.env()->storeValue( identity, ANYTERM( _ ), ValueToEIR( locVar ) );
DeclareValue( c, locVar, lv.index() );
return locVar;
}
Value DeclareLocalVarWithTypeInference( const Context& c, const Term& typeTExpr, StringId name,
const Value& initVal, LocationId locId )
{
auto cfg = GetCFG( c );
if( !cfg )
return PoisonValue();
auto bb = cfg->currentBB();
if( !bb )
return PoisonValue();
auto type = InferTypeFromTExprAndInitializer( c, typeTExpr, initVal );
if( type.isPoison() )
return PoisonValue();
auto index = cfg->nextValueIndex();
// Retrieve the texpr's location and set it on the inferred type. This way if an
// error occurs later with it, for instance when calling LowerTypeForRuntime on it during
// codegen, it will have a meaningful location for the error message to attach itself on.
LocalVar lv( name, ValueToEIR( type ), index );
bb->append( AllocVar( lv.type(), index, locId ) );
DiagnosticsContext dc( 0, "When invoking _Initialize." );
auto initResult = InvokeOverloadSet( c, c.env()->extInitialize(),
MakeClosedTuple( ToValue( lv ).setLocationId( locId ), initVal ) );
if( !initResult.isPoison() )
{
DiagnosticsContext dc2( initResult.locationId(), "When invoking _DropValue." );
InvokeOverloadSet(
c, c.env()->extDropValue(), MakeClosedTuple( c.builder(), move( initResult ) ) );
}
auto locVar = ToValue( lv );
if( name != ""_sid )
{
auto identity = AppendToVectorTerm( c.identity(), name );
c.env()->storeValue( identity, ANYTERM( _ ), ValueToEIR( locVar ) );
}
DeclareValue( c, locVar, lv.index() );
return locVar;
}
} // namespace goose::builtins
namespace goose::eir
{
const Term& Bridge< LocalVarType >::Type()
{
return TypeType();
}
Value Bridge< LocalVarType >::ToValue( const LocalVarType& t )
{
return Value( Type(), TVEC( TSID( ct_type ), TSID( local_var ), t.type() ) );
}
Value Bridge< LocalVarType >::ToValue( const Term& type )
{
return Value( Type(), TVEC( TSID( ct_type ), TSID( local_var ), type ) );
}
optional< LocalVarType > Bridge< LocalVarType >::FromValue( const Value& v )
{
auto result =
Decompose( v.val(), Vec( Lit( "ct_type"_sid ), Lit( "local_var"_sid ), SubTerm() ) );
if( !result )
return nullopt;
auto&& [type] = *result;
return LocalVarType( move( type ) );
}
Term Bridge< LocalVar >::Type( const Term& type )
{
return ValueToEIR( ToValue< LocalVarType >( type ) );
}
Value Bridge< LocalVar >::ToValue( const LocalVar& lv )
{
return Value( Type( lv.type() ), VEC( TERM( lv.name() ), TERM( lv.index() ) ) );
}
optional< LocalVar > Bridge< LocalVar >::FromValue( const Value& v )
{
auto t = FromValue< LocalVarType >( *EIRToValue( v.type() ) );
if( !t )
return nullopt;
if( !v.isConstant() )
{
// This is an abstract local variable value, this may happen when
// typechecking abstract arguments while resolving function typed parameters
return LocalVar( move( t->type() ) );
}
auto result = Decompose( v.val(), Vec( Val< StringId >(), Val< uint64_t >() ) );
if( !result )
return nullopt;
auto&& [name, index] = *result;
return LocalVar( name, move( t->type() ), index );
}
} // namespace goose::eir