Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
| Comment: |
|
|---|---|
| Downloads: | Tarball | ZIP archive |
| Timelines: | family | ancestors | descendants | both | trunk |
| Files: | files | file ages | folders |
| SHA3-256: |
55beba911a4ffa60cb195b8e8d2a9f64 |
| User & Date: | achavasse 2021-09-12 16:48:57.348 |
Context
|
2021-09-12
| ||
| 21:38 |
| |
| 16:48 |
| |
| 13:43 | Small cleanup check-in: 9345aa6eae user: achavasse tags: trunk | |
Changes
Changes to bs/builtins/builtins.cpp.
| ︙ | ︙ | |||
20 21 22 23 24 25 26 |
e.extConvertFuncArg() = CreateOverloadSet( e, "ConvertFuncArg"_sid );
SetupBuiltinTypes( e );
SetupBuiltinOperators( e );
SetupBuiltinStatements( e );
}
| | | 20 21 22 23 24 25 26 27 28 29 30 31 32 |
e.extConvertFuncArg() = CreateOverloadSet( e, "ConvertFuncArg"_sid );
SetupBuiltinTypes( e );
SetupBuiltinOperators( e );
SetupBuiltinStatements( e );
}
const Term& RootG0Identity()
{
static auto identity = VEC( TSID( g0 ) );
return identity;
}
}
|
Changes to bs/builtins/builtins.h.
| ︙ | ︙ | |||
8 9 10 11 12 13 14 |
namespace goose::builtins
{
using namespace eir;
using namespace sema;
using namespace diagnostics;
| | | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
namespace goose::builtins
{
using namespace eir;
using namespace sema;
using namespace diagnostics;
extern const Term& RootG0Identity();
}
#include "codegen/codegen.h"
#include "types/types.h"
#include "operators/operators.h"
#include "statements/statements.h"
|
| ︙ | ︙ |
Changes to bs/builtins/helpers.cpp.
1 2 3 4 5 6 7 8 9 |
#include "builtins/builtins.h"
#include "builtins/helpers.h"
using namespace goose::parse;
namespace goose::builtins
{
void RegisterRule( sema::Env& env, const StringId& name, parse::Rule&& rule )
{
| | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
#include "builtins/builtins.h"
#include "builtins/helpers.h"
using namespace goose::parse;
namespace goose::builtins
{
void RegisterRule( sema::Env& env, const StringId& name, parse::Rule&& rule )
{
parse::RegisterRule( env, AppendToVectorTerm( RootG0Identity(), TERM( name ) ), move( rule ) );
}
ptr< cir::BasicBlock > ParseSubStatement( Parser& p, uint32_t precedence )
{
auto next = p.resolver()->lookAheadUnresolved();
if( !next )
return nullptr;
|
| ︙ | ︙ | |||
53 54 55 56 57 58 59 |
if( holds_alternative< NoUnification >( us ) )
return ValUnifyError::NoSolution;
if( holds_alternative< AmbiguousTypeCheck >( us ) )
return ValUnifyError::Ambiguous;
auto&& [s,_] = get< TCSol >( us );
| | | 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
if( holds_alternative< NoUnification >( us ) )
return ValUnifyError::NoSolution;
if( holds_alternative< AmbiguousTypeCheck >( us ) )
return ValUnifyError::Ambiguous;
auto&& [s,_] = get< TCSol >( us );
return *EIRToValue( s );
}
pvec ParseExpressionList( Parser& p, uint32_t precedence, const pvec& pVec )
{
while( p.parseExpression( precedence ) )
{
auto val = p.popValue();
|
| ︙ | ︙ |
Changes to bs/builtins/helpers.h.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
#ifndef GOOSE_BUILTINS_HELPERS_H
#define GOOSE_BUILTINS_HELPERS_H
#include "parse/parse.h"
namespace goose::builtins
{
extern void RegisterRule( sema::Env& env, const StringId& name, parse::Rule&& rule );
// Utility function used to parse flow control statements, such as if and loops.
// This parses a sub statement, which can be enclosed in a brace block or not.
// It will get its own scope, with visibility rules setup to see the current
// scope.
// It returns a pointer to the final basic block generated by the statement.
| > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
#ifndef GOOSE_BUILTINS_HELPERS_H
#define GOOSE_BUILTINS_HELPERS_H
#include "parse/parse.h"
namespace goose::builtins
{
template< typename T >
void DefineConstant( sema::Env& env, StringId name, T&& val )
{
env.storeValue( AppendToVectorTerm( RootG0Identity(), TERM( name ) ), ANYTERM( _ ), forward< T >( val ) );
}
extern void RegisterRule( sema::Env& env, const StringId& name, parse::Rule&& rule );
// Utility function used to parse flow control statements, such as if and loops.
// This parses a sub statement, which can be enclosed in a brace block or not.
// It will get its own scope, with visibility rules setup to see the current
// scope.
// It returns a pointer to the final basic block generated by the statement.
|
| ︙ | ︙ |
Changes to bs/builtins/operators/arith.cpp.
| ︙ | ︙ | |||
44 45 46 47 48 49 50 |
{
return BuildComputedValue( GetValueType< BigInt >(),
Sub( ToValue( BigInt() ), operand ) );
} ),
ForType< CustomPattern< IntegerType, IntegerType::PatternSigned > >(
[]( auto&& c, auto&& operand ) -> Value
{
| | | 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
{
return BuildComputedValue( GetValueType< BigInt >(),
Sub( ToValue( BigInt() ), operand ) );
} ),
ForType< CustomPattern< IntegerType, IntegerType::PatternSigned > >(
[]( auto&& c, auto&& operand ) -> Value
{
auto opTypeVal = *EIRToValue( operand.type() );
auto opType = *FromValue< IntegerType >( opTypeVal );
return BuildComputedValue( operand.type(),
Sub( Value( operand.type(), APSInt( opType.m_numBits, false ) ),
operand ) );
} )
),
LeftAssInfixOp( "operator_sub"_sid, precedence::AddSubOp,
|
| ︙ | ︙ |
Changes to bs/builtins/operators/assignment.cpp.
| ︙ | ︙ | |||
16 17 18 19 20 21 22 |
// Generic function to perform the assignation of a builtin runtime type
// to a mutable reference of that same type.
auto BuiltinTypeAssignment = []( auto&& c, auto&& lhs, auto&& rhs ) -> Value
{
G_VAL_ASSERT( lhs, !lhs.isConstant() );
| | | | 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
// Generic function to perform the assignation of a builtin runtime type
// to a mutable reference of that same type.
auto BuiltinTypeAssignment = []( auto&& c, auto&& lhs, auto&& rhs ) -> Value
{
G_VAL_ASSERT( lhs, !lhs.isConstant() );
auto refType = *FromValue< ReferenceType >( *EIRToValue( lhs.type() ) );
if( !ParseTypePredicates( c, *EIRToValue( refType.type() ) ) )
return PoisonValue();
const auto& cb = c.codeBuilder();
if( !cb )
{
DiagnosticsManager::GetInstance().emitSyntaxErrorMessage( 0, "assignments are not allowed here." );
return PoisonValue();
|
| ︙ | ︙ |
Changes to bs/builtins/operators/dollar.cpp.
| ︙ | ︙ | |||
31 32 33 34 35 36 37 |
// body, refering to a bound TVar, so we just return the stored value.
// Otherwise, we're in a template declaration and have to construct a new TVar.
Term result;
switch( c.env()->retrieveValue( captureIdentity, c.identity(), result ) )
{
case sema::Env::Status::Success:
| | | 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
// body, refering to a bound TVar, so we just return the stored value.
// Otherwise, we're in a template declaration and have to construct a new TVar.
Term result;
switch( c.env()->retrieveValue( captureIdentity, c.identity(), result ) )
{
case sema::Env::Status::Success:
return *EIRToValue( result );
case sema::Env::Status::AmbiguousMatch:
DiagnosticsManager::GetInstance().emitErrorMessage( locationId,
format( "unexpected ambiguous match when resolving '${}'.", name ) );
return PoisonValue();
default:
|
| ︙ | ︙ |
Changes to bs/builtins/operators/dot.cpp.
| ︙ | ︙ | |||
29 30 31 32 33 34 35 |
if( !rhs.isConstant() )
{
DiagnosticsManager::GetInstance().emitErrorMessage( rhs.locationId(),
"the right operand for the dot operator needs to be a constant." );
return PoisonValue();
}
| | | | 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
if( !rhs.isConstant() )
{
DiagnosticsManager::GetInstance().emitErrorMessage( rhs.locationId(),
"the right operand for the dot operator needs to be a constant." );
return PoisonValue();
}
auto refType = *FromValue< ReferenceType >( *EIRToValue( lhs.type() ) );
auto tupType = *EIRToValue( refType.type() );
uint32_t index = *FromValue< uint32_t >( rhs );
if( index >= TupleTypeSize( tupType ) )
{
DiagnosticsManager::GetInstance().emitErrorMessage( rhs.locationId(),
"the index is out of range." );
return PoisonValue();
|
| ︙ | ︙ |
Changes to bs/builtins/operators/helpers.h.
1 2 3 4 5 6 7 8 9 10 11 12 |
#ifndef GOOSE_BUILTINS_OPERATORS_HELPERS_H
#define GOOSE_BUILTINS_OPERATORS_HELPERS_H
#include "builtins/helpers.h"
namespace goose::builtins
{
using namespace goose::parse;
template< typename... R >
void BuildParseRule( sema::Env& env, const StringId& name, R&&... ruleBuilders )
{
| | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
#ifndef GOOSE_BUILTINS_OPERATORS_HELPERS_H
#define GOOSE_BUILTINS_OPERATORS_HELPERS_H
#include "builtins/helpers.h"
namespace goose::builtins
{
using namespace goose::parse;
template< typename... R >
void BuildParseRule( sema::Env& env, const StringId& name, R&&... ruleBuilders )
{
parse::BuildParseRule( env, name, AppendToVectorTerm( RootG0Identity(), TERM( name ) ),
forward< R >( ruleBuilders )... );
}
struct UnaryOpTag {};
struct BinaryOpTag {};
template< typename... R >
|
| ︙ | ︙ |
Changes to bs/builtins/operators/intrinsic.cpp.
| ︙ | ︙ | |||
32 33 34 35 36 37 38 |
{
auto ovl = *FromValue< Overload >( operand );
if( !ovl.callee().isConstant() )
return PoisonValue();
auto result = InvokeOverloadSet( c, intrinsicOp,
| | | 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
{
auto ovl = *FromValue< Overload >( operand );
if( !ovl.callee().isConstant() )
return PoisonValue();
auto result = InvokeOverloadSet( c, intrinsicOp,
MakeTuple( *EIRToValue( ovl.callee().type() ) ) );
if( result.isPoison() )
return PoisonValue();
return ToValue(
Overload( ovl.ovlSet(),
Value( ValueToEIR( result ), ovl.callee().val() ).setLocationId( ovl.callee().locationId()
|
| ︙ | ︙ |
Changes to bs/builtins/operators/logic.cpp.
| ︙ | ︙ | |||
26 27 28 29 30 31 32 |
BuildParseRule( e, "~"_sid,
PrefixOp( "operator_bitwise_not"_sid, precedence::UnaryOps,
BuildGenericTupleOperator(),
ForType< CustomPattern< IntegerType, IntegerType::Pattern > >( []( auto&& c, auto&& operand ) -> Value
{
| | | 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
BuildParseRule( e, "~"_sid,
PrefixOp( "operator_bitwise_not"_sid, precedence::UnaryOps,
BuildGenericTupleOperator(),
ForType< CustomPattern< IntegerType, IntegerType::Pattern > >( []( auto&& c, auto&& operand ) -> Value
{
auto opTypeVal = *EIRToValue( operand.type() );
auto opType = *FromValue< IntegerType >( opTypeVal );
return BuildComputedValue( operand.type(),
Xor( operand,
Value( operand.type(), APSInt::getMaxValue( opType.m_numBits, true ) )
) );
} )
)
|
| ︙ | ︙ | |||
112 113 114 115 116 117 118 |
auto rhsIndex = cfg->getNewTemporaryIndex();
pRhsBB->emplace_back( CreateTemporary( rhsIndex, rhs ) );
pRhsBB->setTerminator( Branch( pSuccBB ) );
auto resultIndex = cfg->getNewTemporaryIndex();
// Build the Phi instruction that will collect the final result.
| | | 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 |
auto rhsIndex = cfg->getNewTemporaryIndex();
pRhsBB->emplace_back( CreateTemporary( rhsIndex, rhs ) );
pRhsBB->setTerminator( Branch( pSuccBB ) );
auto resultIndex = cfg->getNewTemporaryIndex();
// Build the Phi instruction that will collect the final result.
auto phi = Phi( *EIRToValue( GetValueType< bool >() ), 2,
resultIndex );
// If coming directly from the lhs BB, we know the result is true.
phi.setIncoming( predBB, ToValue( true ) );
// Otherwise, the result is whatever was computed by the rhs block.
phi.setIncoming( pRhsBB, BuildComputedValue( GetValueType< bool >(),
|
| ︙ | ︙ | |||
187 188 189 190 191 192 193 |
auto rhsIndex = cfg->getNewTemporaryIndex();
pRhsBB->emplace_back( CreateTemporary( rhsIndex, rhs ) );
pRhsBB->setTerminator( Branch( pSuccBB ) );
auto resultIndex = cfg->getNewTemporaryIndex();
// Build the Phi instruction that will collect the final result.
| | | 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 |
auto rhsIndex = cfg->getNewTemporaryIndex();
pRhsBB->emplace_back( CreateTemporary( rhsIndex, rhs ) );
pRhsBB->setTerminator( Branch( pSuccBB ) );
auto resultIndex = cfg->getNewTemporaryIndex();
// Build the Phi instruction that will collect the final result.
auto phi = Phi( *EIRToValue( GetValueType< bool >() ), 2,
resultIndex );
// If coming directly from the lhs BB, we know the result is true.
phi.setIncoming( predBB, ToValue( false ) );
// Otherwise, the result is whatever was computed by the rhs block.
phi.setIncoming( pRhsBB, BuildComputedValue( GetValueType< bool >(),
|
| ︙ | ︙ | |||
234 235 236 237 238 239 240 |
auto cfg = cb->cfg();
assert( cfg );
// Shifting for a number of bits equal or larger than the bitsize
// of lhs is an undefined behavior, so we require verification that
// it won't happen.
// Extract the integer type of lhs to retreieve its bit size.
| | | 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 |
auto cfg = cb->cfg();
assert( cfg );
// Shifting for a number of bits equal or larger than the bitsize
// of lhs is an undefined behavior, so we require verification that
// it won't happen.
// Extract the integer type of lhs to retreieve its bit size.
auto lhsType = *FromValue< IntegerType >( *EIRToValue( lhs.type() ) );
auto bitSizeValue = Value( rhs.type(), APSInt::get( lhsType.m_numBits) );
auto cond = ULT( rhs, bitSizeValue );
DiagnosticsManager::GetInstance().defineCustomDiagnostic(
cond.locationId(), "assert"_sid, "the shift amount may be equal or greater than the bitsize." );
|
| ︙ | ︙ | |||
280 281 282 283 284 285 286 |
auto cfg = cb->cfg();
assert( cfg );
// Shifting for a number of bits equal or larger than the bitsize
// of lhs is an undefined behavior, so we require verification that
// it won't happen.
// Extract the integer type of lhs to retreieve its bit size.
| | | 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 |
auto cfg = cb->cfg();
assert( cfg );
// Shifting for a number of bits equal or larger than the bitsize
// of lhs is an undefined behavior, so we require verification that
// it won't happen.
// Extract the integer type of lhs to retreieve its bit size.
auto lhsType = *FromValue< IntegerType >( *EIRToValue( lhs.type() ) );
auto bitSizeValue = Value( rhs.type(), APSInt::get( lhsType.m_numBits) );
auto cond = ULT( rhs, bitSizeValue );
DiagnosticsManager::GetInstance().defineCustomDiagnostic(
cond.locationId(), "assert"_sid, "the shift amount may be equal or greater than the bitsize." );
|
| ︙ | ︙ | |||
311 312 313 314 315 316 317 |
auto cfg = cb->cfg();
assert( cfg );
// Shifting for a number of bits equal or larger than the bitsize
// of lhs is an undefined behavior, so we require verification that
// it won't happen.
// Extract the integer type of lhs to retreieve its bit size.
| | | 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 |
auto cfg = cb->cfg();
assert( cfg );
// Shifting for a number of bits equal or larger than the bitsize
// of lhs is an undefined behavior, so we require verification that
// it won't happen.
// Extract the integer type of lhs to retreieve its bit size.
auto lhsType = *FromValue< IntegerType >( *EIRToValue( lhs.type() ) );
auto bitSizeValue = Value( rhs.type(), APSInt::get( lhsType.m_numBits) );
auto cond = ULT( rhs, bitSizeValue );
DiagnosticsManager::GetInstance().defineCustomDiagnostic(
cond.locationId(), "assert"_sid, "the shift amount may be equal or greater than the bitsize." );
|
| ︙ | ︙ |
Changes to bs/builtins/operators/tuple.h.
| ︙ | ︙ | |||
43 44 45 46 47 48 49 |
}
auto result = EmptyTuple();
ForEachInTuples( lhs, rhs, [&]( auto&& lhs, auto&& rhs )
{
auto r = InvokeOverloadSet( c, pOvlSet,
| | | 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
}
auto result = EmptyTuple();
ForEachInTuples( lhs, rhs, [&]( auto&& lhs, auto&& rhs )
{
auto r = InvokeOverloadSet( c, pOvlSet,
MakeTuple( *EIRToValue( lhs ), *EIRToValue( rhs ) ) );
// Super inefficient, but that's far from the biggest such problem.
// This is just the bootstrap compiler anyway. Should hopefully be able to
// easily make more optimized stuff when rewriting the self hosted compiler,
// some day far away in the future.
result = AppendToTuple( result, r );
return true;
|
| ︙ | ︙ |
Changes to bs/builtins/statements/break.cpp.
| ︙ | ︙ | |||
35 36 37 38 39 40 41 |
// Emit cleanups for all live variables in the scopes that we are breaking through.
cb->destroyAllLiveValuesFromBreakScope( p.context(), cb->breakableScopeLevels() );
cfg->currentBB()->setTerminator( cir::Break( cb->breakableScopeLevels() ) );
return true;
};
| | < < < | 35 36 37 38 39 40 41 42 43 44 |
// Emit cleanups for all live variables in the scopes that we are breaking through.
cb->destroyAllLiveValuesFromBreakScope( p.context(), cb->breakableScopeLevels() );
cfg->currentBB()->setTerminator( cir::Break( cb->breakableScopeLevels() ) );
return true;
};
RegisterRule( e, "break"_sid, Rule( handleBreak ) );
}
}
|
Changes to bs/builtins/statements/continue.cpp.
| ︙ | ︙ | |||
35 36 37 38 39 40 41 |
// Emit cleanups for all live variables in the scopes that we are continuing through.
cb->destroyAllLiveValuesFromBreakScope( p.context(), cb->continuableScopeLevels() );
cfg->currentBB()->setTerminator( cir::Continue( cb->continuableScopeLevels() ) );
return true;
};
| | < < < | 35 36 37 38 39 40 41 42 43 44 |
// Emit cleanups for all live variables in the scopes that we are continuing through.
cb->destroyAllLiveValuesFromBreakScope( p.context(), cb->continuableScopeLevels() );
cfg->currentBB()->setTerminator( cir::Continue( cb->continuableScopeLevels() ) );
return true;
};
RegisterRule( e, "continue"_sid, Rule( handleContinue ) );
}
}
|
Changes to bs/builtins/statements/hif.cpp.
| ︙ | ︙ | |||
125 126 127 128 129 130 131 |
}
}
}
return true;
};
| | < < < | 125 126 127 128 129 130 131 132 133 134 |
}
}
}
return true;
};
RegisterRule( e, "#if"_sid, Rule( handleHIf ) );
}
}
|
Changes to bs/builtins/statements/if.cpp.
| ︙ | ︙ | |||
133 134 135 136 137 138 139 |
// successor block was created: it means all our code paths
// are already terminated and there is no point in emitting any more
// instructions.
cfg->setCurrentBB( pSuccBB );
return true;
};
| | < < < | 133 134 135 136 137 138 139 140 141 142 |
// successor block was created: it means all our code paths
// are already terminated and there is no point in emitting any more
// instructions.
cfg->setCurrentBB( pSuccBB );
return true;
};
RegisterRule( e, "if"_sid, Rule( handleIf ) );
}
}
|
Changes to bs/builtins/statements/return.cpp.
| ︙ | ︙ | |||
79 80 81 82 83 84 85 |
return true;
}
cb->emitTerminator( p.resolver()->currentLocation(), cir::Ret( get< Value >( converted ) ) );
return true;
};
| | < < < | 79 80 81 82 83 84 85 86 87 88 |
return true;
}
cb->emitTerminator( p.resolver()->currentLocation(), cir::Ret( get< Value >( converted ) ) );
return true;
};
RegisterRule( e, "return"_sid, Rule( handleReturn ) );
}
}
|
Changes to bs/builtins/statements/using.cpp.
1 2 3 4 5 6 7 8 9 10 |
#include "builtins/builtins.h"
#include "parse/parse.h"
#include "precedence.h"
using namespace goose;
using namespace goose::eir;
using namespace goose::parse;
namespace goose::builtins
{
| > | 1 2 3 4 5 6 7 8 9 10 11 |
#include "builtins/builtins.h"
#include "parse/parse.h"
#include "precedence.h"
#include "builtins/helpers.h"
using namespace goose;
using namespace goose::eir;
using namespace goose::parse;
namespace goose::builtins
{
|
| ︙ | ︙ | |||
75 76 77 78 79 80 81 |
return true;
}
context.env()->storeValue( localIdentity, ANYTERM( _ ), ValueToEIR( *np.popValue() ) );
return true;
};
| | < < < | 76 77 78 79 80 81 82 83 84 85 |
return true;
}
context.env()->storeValue( localIdentity, ANYTERM( _ ), ValueToEIR( *np.popValue() ) );
return true;
};
RegisterRule( e, "using"_sid, Rule( handleUsing ) );
}
}
|
Changes to bs/builtins/statements/while.cpp.
| ︙ | ︙ | |||
138 139 140 141 142 143 144 |
get< Value >( converted ),
pBodyBB, pSuccBB ) );
cfg->setCurrentBB( pSuccBB );
return true;
};
| | < < < | 138 139 140 141 142 143 144 145 146 147 |
get< Value >( converted ),
pBodyBB, pSuccBB ) );
cfg->setCurrentBB( pSuccBB );
return true;
};
RegisterRule( e, "while"_sid, Rule( handleWhile ) );
}
}
|
Changes to bs/builtins/types/basic.cpp.
1 2 3 4 5 6 7 8 9 10 11 |
#include "builtins/builtins.h"
#include "builtins/helpers.h"
using namespace goose;
using namespace goose::sema;
using namespace goose::builtins;
namespace goose::builtins
{
void SetupBasicTypes( Env& e )
{
| | | | | | | | | | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
#include "builtins/builtins.h"
#include "builtins/helpers.h"
using namespace goose;
using namespace goose::sema;
using namespace goose::builtins;
namespace goose::builtins
{
void SetupBasicTypes( Env& e )
{
DefineConstant( e, "type"_sid, TypeType() );
DefineConstant( e, "void"_sid, GetValueType< void >() );
DefineConstant( e, "bool"_sid, GetValueType< bool >() );
DefineConstant( e, "ct_int"_sid, GetValueType< BigInt >() );
DefineConstant( e, "ct_char"_sid, GetValueType< char32_t >() );
DefineConstant( e, "ct_string"_sid, GetValueType< string >() );
// bool literals
DefineConstant( e, "true"_sid, ValueToEIR( ToValue( true ) ) );
DefineConstant( e, "false"_sid, ValueToEIR( ToValue( false ) ) );
// _ and var are both aliases for an anonymous tvar ($_)
DefineConstant( e, "_"_sid, ValueToEIR( ToValue( TVar( "_"_sid ) ) ) );
DefineConstant( e, "var"_sid, ValueToEIR( ToValue( TVar( "_"_sid ) ) ) );
}
const Term& ValuePatternT::GetPattern()
{
static auto pattern = HOLE( "T"_sid, TSID( tvar ) );
return pattern;
}
|
| ︙ | ︙ |
Changes to bs/builtins/types/constrainedfunc/constrainedfunc.cpp.
| ︙ | ︙ | |||
38 39 40 41 42 43 44 |
if( !result )
return nullopt;
auto&& [constraintPat, pInvRule, func] = *result;
return builtins::ConstrainedFunc(
*Unquote( constraintPat ),
static_pointer_cast< InvocationRule >( pInvRule ),
| | | 38 39 40 41 42 43 44 45 46 47 |
if( !result )
return nullopt;
auto&& [constraintPat, pInvRule, func] = *result;
return builtins::ConstrainedFunc(
*Unquote( constraintPat ),
static_pointer_cast< InvocationRule >( pInvRule ),
*EIRToValue( func ) );
}
}
|
Changes to bs/builtins/types/constrainedfunc/typecheck.cpp.
| ︙ | ︙ | |||
27 28 29 30 31 32 33 |
SubTerm(),
Val< LocationId >()
)
);
assert( ldecomp );
auto&& [sort, type, val, locId] = *ldecomp;
| | | | 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
SubTerm(),
Val< LocationId >()
)
);
assert( ldecomp );
auto&& [sort, type, val, locId] = *ldecomp;
auto callPat = BuildCallPatternFromFuncType( *EIRToValue( type ) );
auto rhsVal = *EIRToValue( rhs );
auto cfunc = FromValue< ConstrainedFunc >( rhsVal );
assert( cfunc );
auto localC = tcc;
for( auto&& [s, tcc] : TypeCheck( callPat, cfunc->constraintPat(), localC ) )
{
if( Postprocess( s, tcc ) )
|
| ︙ | ︙ | |||
69 70 71 72 73 74 75 |
SubTerm(),
Val< LocationId >()
)
);
assert( ldecomp );
auto&& [sort, type, val, locId] = *ldecomp;
| | | | 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 |
SubTerm(),
Val< LocationId >()
)
);
assert( ldecomp );
auto&& [sort, type, val, locId] = *ldecomp;
auto callPat = BuildArgPatternFromTFuncType( tcc.context(), *EIRToValue( type ) );
assert( callPat );
auto rhsVal = *EIRToValue( rhs );
auto cfunc = FromValue< ConstrainedFunc >( rhsVal );
assert( cfunc );
auto localC = tcc;
for( auto&& [s, tcc] : TypeCheck( *callPat, cfunc->constraintPat(), localC ) )
{
if( Postprocess( s, tcc ) )
|
| ︙ | ︙ |
Changes to bs/builtins/types/decl.cpp.
1 2 3 4 5 6 7 8 |
#include "builtins/builtins.h"
using namespace goose::builtins;
namespace goose::builtins
{
bool IsDecl( const Value& d )
{
| | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
#include "builtins/builtins.h"
using namespace goose::builtins;
namespace goose::builtins
{
bool IsDecl( const Value& d )
{
auto typeVal = EIRToValue( d.type() );
auto result = Decompose( typeVal->val(),
Vec(
Lit( "decl"_sid ),
SubTerm()
)
);
|
| ︙ | ︙ | |||
36 37 38 39 40 41 42 |
Value Bridge< Decl >::ToValue( const Decl& d )
{
return Value( Type( d.type() ), TERM( d.name() ) );
}
optional< Decl > Bridge< Decl >::FromValue( const Value& v )
{
| | | 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
Value Bridge< Decl >::ToValue( const Decl& d )
{
return Value( Type( d.type() ), TERM( d.name() ) );
}
optional< Decl > Bridge< Decl >::FromValue( const Value& v )
{
auto typeVal = EIRToValue( v.type() );
auto result = Decompose( typeVal->val(),
Vec(
Lit( "decl"_sid ),
SubTerm()
)
);
|
| ︙ | ︙ |
Changes to bs/builtins/types/extensibility/valuewrapper.cpp.
| ︙ | ︙ | |||
21 22 23 24 25 26 27 |
if( v.type() != Type() )
return nullopt;
auto uq = Unquote( v.val() );
if( !uq )
return nullopt;
| | | 21 22 23 24 25 26 27 28 29 30 |
if( v.type() != Type() )
return nullopt;
auto uq = Unquote( v.val() );
if( !uq )
return nullopt;
return EIRToValue( *uq );
}
}
|
Changes to bs/builtins/types/func/bfunc.cpp.
1 2 3 4 5 6 |
#include "builtins/builtins.h"
namespace goose::builtins
{
bool IsBuiltinFunc( const Value& func )
{
| | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
#include "builtins/builtins.h"
namespace goose::builtins
{
bool IsBuiltinFunc( const Value& func )
{
auto funcType = EIRToValue( func.type() );
assert( funcType );
auto decomp = Decompose( funcType->val(),
Vec(
Lit( "func"_sid ),
Lit( "builtin"_sid ),
SubTerm(), // return type
|
| ︙ | ︙ | |||
33 34 35 36 37 38 39 |
);
return !!decomp;
}
bool IsNonEagerBuiltinFunc( const Value& func )
{
| | | | 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
);
return !!decomp;
}
bool IsNonEagerBuiltinFunc( const Value& func )
{
auto funcType = EIRToValue( func.type() );
assert( funcType );
auto decomp = Decompose( funcType->val(),
Vec(
Lit( "func"_sid ),
Lit( "builtin"_sid ),
SubTerm(), // return type
SubTerm(), // param types
SubTerm(), // verif info
SubTerm() // flags
)
);
return !!decomp;
}
bool IsEagerBuiltinFunc( const Value& func )
{
auto funcType = EIRToValue( func.type() );
assert( funcType );
auto decomp = Decompose( funcType->val(),
Vec(
Lit( "func"_sid ),
Lit( "builtin_eager"_sid ),
SubTerm(), // return type
|
| ︙ | ︙ |
Changes to bs/builtins/types/func/bfunc.inl.
1 2 3 4 5 6 7 8 9 |
#ifndef GOOSE_BUILTINS_TYPES_BFUNC_INL
#define GOOSE_BUILTINS_TYPES_BFUNC_INL
namespace goose::builtins
{
template< typename FT, typename F >
ptr< FuncVerificationInfos > RegisterBuiltinFunc( Env& env, const StringId& name, F&& func )
{
ptr< OverloadSet > pOvlSet;
| | | | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
#ifndef GOOSE_BUILTINS_TYPES_BFUNC_INL
#define GOOSE_BUILTINS_TYPES_BFUNC_INL
namespace goose::builtins
{
template< typename FT, typename F >
ptr< FuncVerificationInfos > RegisterBuiltinFunc( Env& env, const StringId& name, F&& func )
{
ptr< OverloadSet > pOvlSet;
auto identity = AppendToVectorTerm( RootG0Identity(), TERM( name ) );
Term result;
switch( env.retrieveValue( identity, RootG0Identity(), result ) )
{
case sema::Env::Status::Success:
pOvlSet = *FromValue< ptr< OverloadSet > >( *EIRToValue( result ) );
break;
case sema::Env::Status::NoMatch:
pOvlSet = make_shared< OverloadSet >( identity );
env.storeValue( identity, ANYTERM( _ ), ValueToEIR( ToValue( pOvlSet ) ) );
break;
case sema::Env::Status::AmbiguousMatch:
G_ERROR( "ambiguous match while registering builtin func "s + name.str() );
}
return RegisterBuiltinFunc< FT >( env, pOvlSet, forward< F >( func ) );
}
template< typename FT, typename F >
ptr< FuncVerificationInfos > RegisterBuiltinFunc( Env& env, ptr< OverloadSet > pOvlSet, F&& func )
{
auto fvi = make_shared< builtins::FuncVerificationInfos >( RootG0Identity() );
if( !pOvlSet->add( env, ToValue< FT >( forward< F >( func ), fvi ), GetFuncInvocationRule() ) )
G_ERROR( "duplicate overload registered for builtin func." );
return fvi;
}
}
|
| ︙ | ︙ |
Changes to bs/builtins/types/func/bintrinsic.cpp.
1 2 3 4 5 6 |
#include "builtins/builtins.h"
namespace goose::builtins
{
bool IsBuiltinIntrinsicFunc( const Value& func )
{
| | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
#include "builtins/builtins.h"
namespace goose::builtins
{
bool IsBuiltinIntrinsicFunc( const Value& func )
{
auto funcType = EIRToValue( func.type() );
assert( funcType );
auto decomp = Decompose( funcType->val(),
Vec(
Lit( "func"_sid ),
Lit( "intrinsic_builtin"_sid ),
SubTerm(), // return type
|
| ︙ | ︙ |
Changes to bs/builtins/types/func/build.cpp.
| ︙ | ︙ | |||
24 25 26 27 28 29 30 |
ForEachInTuple( params, [&]( auto&& param )
{
if( IsDecl( param ) )
{
auto decl = *FromValue< Decl >( param );
auto type = InvokeOverloadSet( c, c.env()->extConvertFuncParam(),
| | | 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
ForEachInTuple( params, [&]( auto&& param )
{
if( IsDecl( param ) )
{
auto decl = *FromValue< Decl >( param );
auto type = InvokeOverloadSet( c, c.env()->extConvertFuncParam(),
MakeTuple( *EIRToValue( decl.type() ) ) );
if( type.isPoison() )
{
failed = true;
return false;
}
tv->append( BuildParamPat( c, type, param.locationId() ) );
|
| ︙ | ︙ |
Changes to bs/builtins/types/func/compile.cpp.
| ︙ | ︙ | |||
113 114 115 116 117 118 119 |
Val< LocationId >()
)
);
assert( result );
auto&& [sort, type, val, locId] = *result;
| | | | 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 |
Val< LocationId >()
)
);
assert( result );
auto&& [sort, type, val, locId] = *result;
if( !ParseTypePredicates( c, *EIRToValue( type ) ) )
predsOk = false;
return true;
} );
if( !predsOk )
return false;
// Perform lazy parsing on return type predicates
if( !ParseTypePredicates( c, *EIRToValue( f.type().returnType() ) ) )
return false;
// If the function already have a cir body, nothing to do.
if( pFuncCIR->body() )
return true;
if( !f.tokens() )
|
| ︙ | ︙ | |||
155 156 157 158 159 160 161 |
// Create the local variable bindings to access the function params
// from inside the body, as well as the signature.
// TODO: for intrinsic functions, we need to expose the CodeBuilder
// as it is an ilmplicit extra param
uint32_t varId = 0;
for( auto&& t : f.paramsDecl()->terms() )
{
| | | 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 |
// Create the local variable bindings to access the function params
// from inside the body, as well as the signature.
// TODO: for intrinsic functions, we need to expose the CodeBuilder
// as it is an ilmplicit extra param
uint32_t varId = 0;
for( auto&& t : f.paramsDecl()->terms() )
{
auto param = *EIRToValue( t );
if( !IsDecl( param ) )
continue;
auto decl = *FromValue< Decl >( param );
auto paramIdentity = AppendToVectorTerm( bodyIdentity, TERM( decl.name() ) );
|
| ︙ | ︙ |
Changes to bs/builtins/types/func/func.cpp.
| ︙ | ︙ | |||
40 41 42 43 44 45 46 |
}
bool IsIntrinsicFunc( const Value& f )
{
if( !f.isConstant() )
return false;
| | | 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
}
bool IsIntrinsicFunc( const Value& f )
{
if( !f.isConstant() )
return false;
auto typeVal = EIRToValue( f.type() );
return typeVal && IsIntrinsicFuncType( *typeVal );
}
bool IsFuncType( const Value& t )
{
auto result = Decompose( t.val(),
Vec(
|
| ︙ | ︙ | |||
78 79 80 81 82 83 84 |
);
return !!result;
}
Term GetFuncSig( const Value& func )
{
| | | 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 |
);
return !!result;
}
Term GetFuncSig( const Value& func )
{
auto funcType = EIRToValue( func.type() );
assert( funcType );
return GetFuncSigFromType( *funcType );
}
Term GetFuncSigFromType( const Value& funcType )
{
auto typeDecomp = Decompose( funcType.val(),
|
| ︙ | ︙ | |||
103 104 105 106 107 108 109 |
auto&& [kind, rtype, ptypes, vinf, varArg] = *typeDecomp;
return PrependToVectorTerm( *Unquote( ptypes ), rtype );
}
Term GetFuncRType( const Value& func )
{
| | | 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 |
auto&& [kind, rtype, ptypes, vinf, varArg] = *typeDecomp;
return PrependToVectorTerm( *Unquote( ptypes ), rtype );
}
Term GetFuncRType( const Value& func )
{
auto funcType = EIRToValue( func.type() );
assert( funcType );
auto typeDecomp = Decompose( funcType->val(),
Vec(
Lit( "func"_sid ),
SubTerm(), // kind
SubTerm(), // return type
|
| ︙ | ︙ | |||
142 143 144 145 146 147 148 |
return ParamListKind::Invalid;
auto result = ParamListKind::Regular;
const auto& vec = *get< pvec >( tup.val() );
for( auto&& x : vec.terms() )
{
| | | 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 |
return ParamListKind::Invalid;
auto result = ParamListKind::Regular;
const auto& vec = *get< pvec >( tup.val() );
for( auto&& x : vec.terms() )
{
auto v = EIRToValue( x );
if( !v )
return ParamListKind::Invalid;
if( IsTDecl( *v ) || IsTNamedDecl( *v ) || IsTExpr( *v ) )
result = ParamListKind::Template;
else if( !IsDecl( *v ) && !v->isConstant() )
return ParamListKind::Invalid;
|
| ︙ | ︙ | |||
167 168 169 170 171 172 173 |
bool failed = false;
ForEachInVectorTerms( ft.params(), unifiedArgs, [&]( auto&& p, auto&& a )
{
auto vp = ValuePatternFromEIR( p );
if( vp->val() == HOLE( "_"_sid ) )
{
auto convertedArg = InvokeOverloadSet( c, c.env()->extConvertFuncArg(),
| | | 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 |
bool failed = false;
ForEachInVectorTerms( ft.params(), unifiedArgs, [&]( auto&& p, auto&& a )
{
auto vp = ValuePatternFromEIR( p );
if( vp->val() == HOLE( "_"_sid ) )
{
auto convertedArg = InvokeOverloadSet( c, c.env()->extConvertFuncArg(),
MakeTuple( *EIRToValue( a ), *EIRToValue( vp->type() ) ) );
if( convertedArg.isPoison() )
{
failed = true;
return false;
}
av->append( ValueToEIR( convertedArg ) );
|
| ︙ | ︙ | |||
199 200 201 202 203 204 205 |
bool failed = false;
ForEachInVectorTerms( ft.params(), typeCheckedArgs, [&]( auto&& p, auto&& a )
{
auto vp = ValuePatternFromEIR( p );
if( vp->val() == HOLE( "_"_sid ) )
{
| | | 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 |
bool failed = false;
ForEachInVectorTerms( ft.params(), typeCheckedArgs, [&]( auto&& p, auto&& a )
{
auto vp = ValuePatternFromEIR( p );
if( vp->val() == HOLE( "_"_sid ) )
{
auto wrappedArg = ToValue( ValueWrapper( *EIRToValue( a ) ) );
av->append( ValueToEIR( wrappedArg ) );
}
return true;
} );
if( failed )
|
| ︙ | ︙ | |||
301 302 303 304 305 306 307 |
}
optional< Func > Bridge< Func >::FromValue( const Value& v )
{
if( !v.isConstant() || v.isPoison() )
return nullopt;
| | | 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 |
}
optional< Func > Bridge< Func >::FromValue( const Value& v )
{
if( !v.isConstant() || v.isPoison() )
return nullopt;
auto funcTypeVal = EIRToValue( v.type() );
if( !funcTypeVal )
return nullopt;
auto funcType = ::FromValue< FuncType >( *funcTypeVal );
if( !funcType )
return nullopt;
|
| ︙ | ︙ |
Changes to bs/builtins/types/func/invoke.cpp.
| ︙ | ︙ | |||
55 56 57 58 59 60 61 |
if( IsBuiltinFunc( preparedCallee ) )
return BuildComputedValue( typeCheckedRType, cir::Call( preparedCallee, move( typeCheckedArgs ) ) );
if( IsBuiltinIntrinsicFunc( preparedCallee ) )
return GetBuiltinIntrinsicFuncWrapper( preparedCallee )( c, move( typeCheckedArgs ) );
| | | 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 |
if( IsBuiltinFunc( preparedCallee ) )
return BuildComputedValue( typeCheckedRType, cir::Call( preparedCallee, move( typeCheckedArgs ) ) );
if( IsBuiltinIntrinsicFunc( preparedCallee ) )
return GetBuiltinIntrinsicFuncWrapper( preparedCallee )( c, move( typeCheckedArgs ) );
auto ft = *FromValue< FuncType >( *EIRToValue( preparedCallee.type() ) );
if( ft.intrinsic() )
{
// Intrinsic call: we insert the code builder wrapper as first param,
// wrap all args with ValueWrapper, and execute the function directly.
auto argList = BuildArgListForIntrinsicCall( c, ft, typeCheckedArgs );
if( !argList )
|
| ︙ | ︙ |
Changes to bs/builtins/types/func/lower.cpp.
| ︙ | ︙ | |||
9 10 11 12 13 14 15 |
optional< FuncType > LowerFunctionTypeForRuntime( const Context& c, const FuncType& ft )
{
// If the passed function already have an associated llvm type,
// we have nothing to do.
if( ft.llvmType() )
return ft;
| | | 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
optional< FuncType > LowerFunctionTypeForRuntime( const Context& c, const FuncType& ft )
{
// If the passed function already have an associated llvm type,
// we have nothing to do.
if( ft.llvmType() )
return ft;
auto rt = LowerTypeForRuntime( c, *EIRToValue( ft.returnType() ) );
if( !rt )
return nullopt;
vector< llvm::Type* > paramTypes;
const auto& paramVec = *get< pvec >( ft.params() );
paramTypes.reserve( paramVec.terms().size() );
|
| ︙ | ︙ | |||
37 38 39 40 41 42 43 |
{
success = false;
return false;
}
if( vp->val() == HOLE( "_"_sid ) )
{
| | | 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
{
success = false;
return false;
}
if( vp->val() == HOLE( "_"_sid ) )
{
auto type = LowerTypeForRuntime( c, *EIRToValue( vp->type() ) );
if( !type )
{
success = false;
return false;
}
paramTypes.emplace_back( GetLLVMType( *type ) );
|
| ︙ | ︙ |
Changes to bs/builtins/types/func/typecheck.cpp.
| ︙ | ︙ | |||
67 68 69 70 71 72 73 |
ValueToEIR( ValuePattern(
TSID( constant ),
FuncTypePattern(),
ANYTERM( _ ) ) ),
[]( const Term& lhs, const Term& rhs, const TypeCheckingContext& tcc ) -> TCGen
{
| | | 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 |
ValueToEIR( ValuePattern(
TSID( constant ),
FuncTypePattern(),
ANYTERM( _ ) ) ),
[]( const Term& lhs, const Term& rhs, const TypeCheckingContext& tcc ) -> TCGen
{
auto rhsVal = *EIRToValue( rhs );
if( IsBuiltinFunc( rhsVal ) )
{
co_yield { rhs, tcc };
co_return;
}
|
| ︙ | ︙ | |||
116 117 118 119 120 121 122 |
Val< LocationId >()
)
);
assert( ldecomp );
auto&& [sort, type, val, locId] = *ldecomp;
| | | | 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 |
Val< LocationId >()
)
);
assert( ldecomp );
auto&& [sort, type, val, locId] = *ldecomp;
auto callPat = BuildArgPatternFromTFuncType( tcc.context(), *EIRToValue( type ) );
assert( callPat );
auto rhsVal = *EIRToValue( rhs );
auto sig = GetFuncSig( rhsVal );
for( auto&& [s, tcc] : TypeCheck( sig, *callPat, tcc ) )
{
if( IsBuiltinFunc( rhsVal ) )
{
co_yield { ValueToEIR( rhsVal ), tcc };
|
| ︙ | ︙ |
Changes to bs/builtins/types/init.cpp.
| ︙ | ︙ | |||
23 24 25 26 27 28 29 |
// all types at runtime will have to go through their own specialization
// or partial specialization of this, since it will have to emit specialized
// binary runtime code.
RegisterBuiltinFunc< Intrinsic< Value ( MutRefOfTypeT, ValueOfTypeT ) > >( e, e.extInitialize(),
[]( auto&& c, const Value& r, const Value& initVal )
{
G_VAL_ASSERT( r, !r.isConstant() );
| | | | | 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
// all types at runtime will have to go through their own specialization
// or partial specialization of this, since it will have to emit specialized
// binary runtime code.
RegisterBuiltinFunc< Intrinsic< Value ( MutRefOfTypeT, ValueOfTypeT ) > >( e, e.extInitialize(),
[]( auto&& c, const Value& r, const Value& initVal )
{
G_VAL_ASSERT( r, !r.isConstant() );
auto refType = *FromValue< ReferenceType >( *EIRToValue( r.type() ) );
return BuildComputedValue( GetValueType< void >(),
Store( r.cir(), refType.type(), initVal, r.locationId() ) );
} );
// Default initialization for ct_int vars
RegisterBuiltinFunc< Intrinsic< Value ( CTIntMutRefType ) > >( e, e.extInitialize(),
[]( auto&& c, const Value& r )
{
G_VAL_ASSERT( r, !r.isConstant() );
auto refType = *FromValue< ReferenceType >( *EIRToValue( r.type() ) );
return BuildComputedValue( GetValueType< void >(),
Store( r.cir(), refType.type(), ToValue( BigInt() ), r.locationId() ) );
} );
// Default initialization for ct_string vars
RegisterBuiltinFunc< Intrinsic< Value ( CTStringMutRefType ) > >( e, e.extInitialize(),
[]( auto&& c, const Value& r )
{
G_VAL_ASSERT( r, !r.isConstant() );
auto refType = *FromValue< ReferenceType >( *EIRToValue( r.type() ) );
return BuildComputedValue( GetValueType< void >(),
Store( r.cir(), refType.type(), ToValue( ""s ), r.locationId() ) );
} );
}
}
|
Changes to bs/builtins/types/localvar/localvar.cpp.
| ︙ | ︙ | |||
27 28 29 30 31 32 33 |
auto index = cfg->getNewTemporaryIndex();
auto bb = cfg->currentBB();
if( !bb )
return PoisonValue();
| | | 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
auto index = cfg->getNewTemporaryIndex();
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();
LocalVar lv( name, ValueToEIR( typeVal ), index );
|
| ︙ | ︙ | |||
169 170 171 172 173 174 175 |
SubTerm(), // locvar
SubTerm() // initializer
)
);
auto&& [type, initializer] = *callDecomp;
| | | | | 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 |
SubTerm(), // locvar
SubTerm() // initializer
)
);
auto&& [type, initializer] = *callDecomp;
if( !ParseTypePredicates( c, *EIRToValue( type ) ) )
return PoisonValue();
auto index = cfg->getNewTemporaryIndex();
// 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.
uint32_t typeLoc = EIRToValue( typeTExpr )->locationId();
LocalVar lv( name, type, index );
bb->emplace_back( AllocVar( EIRToValue( lv.type() )->setLocationId( typeLoc ), index ) );
DiagnosticsContext dc( 0, "When invoking Initialize." );
auto initResult = InvokeOverloadSet( c,
c.env()->extInitialize(),
MakeTuple( ToValue( lv ).setLocationId( locId ), initVal ) );
|
| ︙ | ︙ | |||
255 256 257 258 259 260 261 |
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 )
{
| | | 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 |
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
|
| ︙ | ︙ |
Changes to bs/builtins/types/localvar/typecheck.cpp.
| ︙ | ︙ | |||
18 19 20 21 22 23 24 |
ValueToEIR( ValuePattern(
ANYTERM( _ ),
localVarPattern,
ANYTERM( _ ) ) ),
[]( const Term& lhs, const Term& rhs, const TypeCheckingContext& tcc ) -> TCGen
{
| | | | 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
ValueToEIR( ValuePattern(
ANYTERM( _ ),
localVarPattern,
ANYTERM( _ ) ) ),
[]( const Term& lhs, const Term& rhs, const TypeCheckingContext& tcc ) -> TCGen
{
auto lvarType = *FromValue< LocalVarType >( *EIRToValue( ValuePatternFromEIR( lhs )->type() ) );
auto rhsVal = *ValuePatternFromEIR( rhs );
auto rvarType = *FromValue< LocalVarType >( *EIRToValue( rhsVal.type() ) );
for( auto&& [s, tcc] : Unify( lvarType.type(), rvarType.type(), tcc ) )
{
co_yield { ValueToEIR( Value( ValueToEIR( ToValue( LocalVarType( s ) ) ),
rhsVal.val() ).setLocationId( rhsVal.locationId() ) ), tcc };
}
} );
|
| ︙ | ︙ |
Changes to bs/builtins/types/overloadset/helpers.cpp.
1 2 3 4 5 6 7 |
#include "builtins/builtins.h"
#include "execute/execute.h"
namespace goose::builtins
{
ptr< OverloadSet > CreateOverloadSet( Env& env, const StringId& name )
{
| | | | | | | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
#include "builtins/builtins.h"
#include "execute/execute.h"
namespace goose::builtins
{
ptr< OverloadSet > CreateOverloadSet( Env& env, const StringId& name )
{
auto identity = AppendToVectorTerm( RootG0Identity(), TERM( name ) );
auto pOvlSet = make_shared< OverloadSet >( identity );
env.storeValue( identity, ANYTERM( _ ), ValueToEIR( ToValue( pOvlSet ) ) );
return pOvlSet;
}
ptr< OverloadSet > GetOverloadSet( Env& env, const StringId& name )
{
auto identity = AppendToVectorTerm( RootG0Identity(), TERM( name ) );
Term result;
switch( env.retrieveValue( identity, RootG0Identity(), result ) )
{
case sema::Env::Status::Success:
return *FromValue< ptr< OverloadSet > >( *EIRToValue( result ) );
case sema::Env::Status::NoMatch:
G_ERROR( format( "fatal: overload set {} not found", name ) );
case sema::Env::Status::AmbiguousMatch:
G_ERROR( format( "fatal: ambiguous match for overload set {}", name ) );
}
return nullptr;
}
ptr< OverloadSet > GetOrCreateOverloadSet( Env& env, const StringId& name )
{
auto identity = AppendToVectorTerm( RootG0Identity(), TERM( name ) );
Term result;
switch( env.retrieveValue( identity, RootG0Identity(), result ) )
{
case sema::Env::Status::Success:
return *FromValue< ptr< OverloadSet > >( *EIRToValue( result ) );
case sema::Env::Status::NoMatch:
{
auto pOvlSet = make_shared< OverloadSet >( identity );
env.storeValue( identity, ANYTERM( _ ), ValueToEIR( ToValue( pOvlSet ) ) );
return pOvlSet;
}
|
| ︙ | ︙ |
Changes to bs/builtins/types/overloadset/typecheck.cpp.
| ︙ | ︙ | |||
27 28 29 30 31 32 33 |
SubTerm(),
Val< LocationId >()
)
);
assert( ldecomp );
auto&& [sort, type, val, locId] = *ldecomp;
| | | | 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
SubTerm(),
Val< LocationId >()
)
);
assert( ldecomp );
auto&& [sort, type, val, locId] = *ldecomp;
auto callPat = BuildCallPatternFromFuncType( *EIRToValue( type ) );
auto rhsVal = *EIRToValue( rhs );
auto os = *FromValue< ptr< OverloadSet > >( rhsVal );
auto rhsLocId = rhsVal.locationId();
// Create a new named hole namespace to isolate holes from the passed function from those in
// the called function.
auto savedRHSNamespaceIndex = tcc.RHSNamespaceIndex();
|
| ︙ | ︙ | |||
93 94 95 96 97 98 99 |
SubTerm(),
Val< LocationId >()
)
);
assert( ldecomp );
auto&& [sort, type, val, locId] = *ldecomp;
| | | | 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 |
SubTerm(),
Val< LocationId >()
)
);
assert( ldecomp );
auto&& [sort, type, val, locId] = *ldecomp;
auto callPat = BuildArgPatternFromTFuncType( tcc.context(), *EIRToValue( type ) );
assert( callPat );
auto rhsVal = *EIRToValue( rhs );
auto os = *FromValue< ptr< OverloadSet > >( rhsVal );
auto rhsLocId = rhsVal.locationId();
// Create a new named hole namespace to isolate holes from the called functions from those
// in the call expression.
auto savedRHSNamespaceIndex = tcc.RHSNamespaceIndex();
|
| ︙ | ︙ |
Changes to bs/builtins/types/param.h.
1 2 3 4 5 6 7 8 9 10 |
#ifndef GOOSE_BUILTINS_TYPES_PARAM_H
#define GOOSE_BUILTINS_TYPES_PARAM_H
namespace goose::builtins
{
template< typename T, typename V >
auto ParamPat( T&& type, V&& val )
{
// If the type is a tuple of type, convert it to the type of a tuple.
// (the type of a tuple is just a list of values, so just extract the value part of the tuple)
| | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
#ifndef GOOSE_BUILTINS_TYPES_PARAM_H
#define GOOSE_BUILTINS_TYPES_PARAM_H
namespace goose::builtins
{
template< typename T, typename V >
auto ParamPat( T&& type, V&& val )
{
// If the type is a tuple of type, convert it to the type of a tuple.
// (the type of a tuple is just a list of values, so just extract the value part of the tuple)
if( auto typeVal = EIRToValue( type ); typeVal && IsTuple( *typeVal ) )
return ValueToEIR( Value( ValueToEIR( TupleOfTypesToTupleType( *typeVal ) ), HOLE( "_"_sid ) ) );
return ValueToEIR( Value( forward< T >( type ), forward< V >( val ) ) );
}
template< typename T >
auto ParamPat( T&& type )
{
// If the type is a tuple of type, convert it to the type of a tuple.
// (the type of a tuple is just a list of values, so just extract the value part of the tuple)
if( auto typeVal = EIRToValue( type ); typeVal && IsTuple( *typeVal ) )
return ValueToEIR( ValuePattern( HOLE( "_"_sid ), ValueToEIR( TupleOfTypesToTupleType( *typeVal ) ), HOLE( "_"_sid ) ) );
return ValueToEIR( ValuePattern( TSID( param ), forward< T >( type ), HOLE( "_"_sid ) ) );
}
// This special param pattern forces the argument to be passed as it without any typechecking.
struct ForwarderPattern
|
| ︙ | ︙ |
Changes to bs/builtins/types/pretty.cpp.
| ︙ | ︙ | |||
12 13 14 15 16 17 18 |
auto& pp = PrettyPrinter::GetInstance();
pp.addRule( TypeType(), [&]( auto&& out, auto&& t ) { out << "TypeType"; return true; } );
pp.addRule( ValueToEIR( ValuePattern( TSID( constant ), ANYTERM(_), ANYTERM(_) ) ),
[&]( auto&& out, auto&& t )
{
| | | | | | | | 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 |
auto& pp = PrettyPrinter::GetInstance();
pp.addRule( TypeType(), [&]( auto&& out, auto&& t ) { out << "TypeType"; return true; } );
pp.addRule( ValueToEIR( ValuePattern( TSID( constant ), ANYTERM(_), ANYTERM(_) ) ),
[&]( auto&& out, auto&& t )
{
auto v = *EIRToValue( t );
auto ty = EIRToValue( v.type() );
out << "constant[ ";
pp.print( out, ty ? ty->val() : v.type() );
out << " ]{ ";
pp.print( out, v.val() );
out << " }";
return true;
} );
pp.addRule( ValueToEIR( ValuePattern( TSID( constant ), TypeType(), ANYTERM(_) ) ),
[&]( auto&& out, auto&& t )
{
auto v = *EIRToValue( t );
out << "type[ ";
pp.print( out, v.val() );
out << " ]";
return true;
} );
pp.addRule( ValueToEIR( ValuePattern( TSID( computed ), ANYTERM(_), ANYTERM(_) ) ),
[&]( auto&& out, auto&& t )
{
auto v = *EIRToValue( t );
auto ty = EIRToValue( v.type() );
out << "value[ ";
pp.print( out, ty ? ty->val() : v.type() );
out << " ]";
if( v.cir() )
out << "{ " << *v.cir() << " }";
return true;
} );
pp.addRule( ValueToEIR( ValuePattern( TSID( constant ),
ValueToEIR( Value( TypeType(), VEC( TSID( decl ), ANYTERM( _ ) ) ) ),
ANYTERM( _ ) ) ),
[&]( auto&& out, auto&& t )
{
auto decl = *FromValue< Decl >( *EIRToValue( t ) );
out << "decl(" << decl.type() << ", " << decl.name() << ")";
return true;
} );
pp.addRule( GetValueType< bool >(), [&]( auto&& out, auto&& t ) { out << "bool"; return true; } );
pp.addRule( MkStdType( TSID( bool ) ), [&]( auto&& out, auto&& t ) { out << "bool"; return true; } );
|
| ︙ | ︙ |
Changes to bs/builtins/types/reference/init.cpp.
| ︙ | ︙ | |||
10 11 12 13 14 15 16 |
{
RegisterBuiltinFunc< Intrinsic< Value ( CustomPattern< Value,
ReferenceType::PatternMutableOf< ReferenceType::PatternXOfTypeT > >,
CustomPattern< Value, ReferenceType::PatternXOfTypeT > ) > >( e, e.extInitialize(),
[]( auto&& c, const Value& r, const Value& initVal )
{
G_VAL_ASSERT( r, !r.isConstant() );
| | | 10 11 12 13 14 15 16 17 18 19 20 21 22 |
{
RegisterBuiltinFunc< Intrinsic< Value ( CustomPattern< Value,
ReferenceType::PatternMutableOf< ReferenceType::PatternXOfTypeT > >,
CustomPattern< Value, ReferenceType::PatternXOfTypeT > ) > >( e, e.extInitialize(),
[]( auto&& c, const Value& r, const Value& initVal )
{
G_VAL_ASSERT( r, !r.isConstant() );
auto refType = *FromValue< ReferenceType >( *EIRToValue( r.type() ) );
return BuildComputedValue( GetValueType< void >(),
Store( r.cir(), refType.type(), initVal, r.locationId() ) );
} );
}
}
|
Changes to bs/builtins/types/reference/lower.cpp.
| ︙ | ︙ | |||
9 10 11 12 13 14 15 |
void SetupReferenceLowering( Env& e )
{
RegisterBuiltinFunc< Intrinsic< Value ( TypePatternParam< Value, ReferenceType::PatternAny > ) > >( e, e.extLowerTypeForRuntime(),
[]( const Context& c, const Value& refType )
{
auto rt = *FromValue< ReferenceType >( refType );
| | | 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
void SetupReferenceLowering( Env& e )
{
RegisterBuiltinFunc< Intrinsic< Value ( TypePatternParam< Value, ReferenceType::PatternAny > ) > >( e, e.extLowerTypeForRuntime(),
[]( const Context& c, const Value& refType )
{
auto rt = *FromValue< ReferenceType >( refType );
auto loweredType = LowerTypeForRuntime( c, *EIRToValue( rt.type() ) );
if( !loweredType || loweredType->isPoison() )
return PoisonValue();
return ToValue( PointerType( ValueToEIR( *loweredType ) ) );
} );
}
}
|
Changes to bs/builtins/types/reference/parse.cpp.
1 2 3 4 5 6 7 8 9 10 |
#include "builtins/builtins.h"
#include "parse/parse.h"
#include "precedence.h"
using namespace goose;
using namespace goose::eir;
using namespace goose::parse;
namespace goose::builtins
{
| > | 1 2 3 4 5 6 7 8 9 10 11 |
#include "builtins/builtins.h"
#include "parse/parse.h"
#include "precedence.h"
#include "builtins/helpers.h"
using namespace goose;
using namespace goose::eir;
using namespace goose::parse;
namespace goose::builtins
{
|
| ︙ | ︙ | |||
54 55 56 57 58 59 60 |
auto loc = Location::CreateSpanningLocation( locationId, type->locationId() );
ReferenceType rt( ValueToEIR( *type ), move( bhv ) );
p.pushValue( ToDeclValue( rt ).setLocationId( loc ) );
return true;
};
| | < < < | 55 56 57 58 59 60 61 62 63 64 |
auto loc = Location::CreateSpanningLocation( locationId, type->locationId() );
ReferenceType rt( ValueToEIR( *type ), move( bhv ) );
p.pushValue( ToDeclValue( rt ).setLocationId( loc ) );
return true;
};
RegisterRule( e, "ref"_sid, Rule( parseRefType ) );
}
}
|
Changes to bs/builtins/types/reference/reference.cpp.
1 2 3 4 5 6 7 8 9 10 11 |
#include "builtins/builtins.h"
#include "parse/parse.h"
using namespace goose::builtins;
using namespace goose::cir;
using namespace goose::parse;
namespace goose::builtins
{
bool IsReferenceType( const Term& t )
{
| | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
#include "builtins/builtins.h"
#include "parse/parse.h"
using namespace goose::builtins;
using namespace goose::cir;
using namespace goose::parse;
namespace goose::builtins
{
bool IsReferenceType( const Term& t )
{
auto result = Decompose( EIRToValue( t )->val(),
Vec(
Lit( "reference"_sid ),
SubTerm(),
SubTerm()
)
);
|
| ︙ | ︙ |
Changes to bs/builtins/types/reference/typecheck.cpp.
| ︙ | ︙ | |||
9 10 11 12 13 14 15 |
using namespace goose::builtins;
auto refTypePattern = ValueToEIR(
Value( GetValueType< ReferenceType >(), TVEC( TSID( reference ), ANYTERM( _ ), ANYTERM( _ ) ) ) );
TCGen TypeCheckingDereference( const Term& lhs, const Term& rhs, TypeCheckingContext tcc )
{
| | | | | 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
using namespace goose::builtins;
auto refTypePattern = ValueToEIR(
Value( GetValueType< ReferenceType >(), TVEC( TSID( reference ), ANYTERM( _ ), ANYTERM( _ ) ) ) );
TCGen TypeCheckingDereference( const Term& lhs, const Term& rhs, TypeCheckingContext tcc )
{
auto refval = EIRToValue( rhs );
if( !refval )
co_return;
auto refType = FromValue< ReferenceType >( *EIRToValue( refval->type() ) );
if( !refType )
co_return;
auto content = ValueToEIR( BuildComputedValue( refType->type(),
cir::Load( refval->cir(), refType->type() ) )
.setLocationId( refval->locationId() ) );
// TypeCheck the param with the ref's content
co_yield TypeCheck( lhs, content, tcc );
}
TCGen TypeCheckingBuildTempRef( const Term& lhs, const Term& rhs, const TypeCheckingContext& tcc )
{
if( !tcc.context().codeBuilder() )
co_return;
if( !tcc.context().codeBuilder()->cfg() )
co_return;
auto lRefType = *FromValue< ReferenceType >( *EIRToValue( ValuePatternFromEIR( lhs )->type() ) );
if( lRefType.behavior() == TSID( mut ) )
co_return;
auto lhsPat = ValueToEIR( ValuePattern( TSID( param ), lRefType.type(), HOLE( "_"_sid ) ) );
for( auto&& [s,tcc] : TypeCheck( lhsPat, rhs, tcc ) )
|
| ︙ | ︙ | |||
63 64 65 66 67 68 69 |
SubTerm()
)
);
assert( result );
auto&& [ref, rhs] = *result;
| | | 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 |
SubTerm()
)
);
assert( result );
auto&& [ref, rhs] = *result;
auto rhsVal = *EIRToValue( rhs );
auto refPat = *ValuePatternFromEIR( ref );
auto tempIndex = tcc.context().codeBuilder()->cfg()->getNewTemporaryIndex();
return ValueToEIR( BuildComputedValue( refPat.type(), TempAddr( tempIndex, rhsVal ) )
.setLocationId( rhsVal.locationId() ) );
} );
|
| ︙ | ︙ | |||
111 112 113 114 115 116 117 |
ValueToEIR( ValuePattern(
ANYTERM( _ ),
refTypePattern,
ANYTERM( _ ) ) ),
[]( const Term& lhs, const Term& rhs, const TypeCheckingContext& tcc ) -> TCGen
{
| | | | 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 |
ValueToEIR( ValuePattern(
ANYTERM( _ ),
refTypePattern,
ANYTERM( _ ) ) ),
[]( const Term& lhs, const Term& rhs, const TypeCheckingContext& tcc ) -> TCGen
{
auto lRefType = *FromValue< ReferenceType >( *EIRToValue( ValuePatternFromEIR( lhs )->type() ) );
auto rhsVal = *ValuePatternFromEIR( rhs );
auto rRefType = *FromValue< ReferenceType >( *EIRToValue( rhsVal.type() ) );
// Type check the behaviors
for( auto&& [b, tcc] : TypeCheck( lRefType.behavior(), rRefType.behavior(), tcc ) )
{
// Check the types
for( auto&& [t, tcc] : TypeCheck( lRefType.type(), rRefType.type(), tcc ) )
{
|
| ︙ | ︙ | |||
212 213 214 215 216 217 218 |
localVarPattern,
ANYTERM( _ ) ) ),
[]( const Term& lhs, const Term& rhs, const TypeCheckingContext& tcc ) -> TCGen
{
auto ltype = ValuePatternFromEIR( lhs )->type();
| | | 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 |
localVarPattern,
ANYTERM( _ ) ) ),
[]( const Term& lhs, const Term& rhs, const TypeCheckingContext& tcc ) -> TCGen
{
auto ltype = ValuePatternFromEIR( lhs )->type();
auto lvval = *EIRToValue( rhs );
auto locvar = FromValue< LocalVar >( lvval );
if( !locvar )
co_return;
auto ref = ValueToEIR( ToValue( BuildLocalVarMutRef( *locvar ) )
.setLocationId( lvval.locationId() ) );
|
| ︙ | ︙ |
Changes to bs/builtins/types/runtime/array.cpp.
| ︙ | ︙ | |||
19 20 21 22 23 24 25 |
return ToValue( ArrayType( ValueToEIR( containedType ), count ) );
} );
}
llvm::Type* GetLLVMType( const ArrayType& a )
{
| | | 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
return ToValue( ArrayType( ValueToEIR( containedType ), count ) );
} );
}
llvm::Type* GetLLVMType( const ArrayType& a )
{
return llvm::ArrayType::get( GetLLVMType( *EIRToValue( a.m_containedType ) ), a.m_count );
}
}
namespace goose::eir
{
Value Bridge< ArrayType >::ToValue( const ArrayType& a )
{
|
| ︙ | ︙ |
Changes to bs/builtins/types/runtime/basic.cpp.
1 2 3 4 5 6 7 8 9 10 11 12 |
#include "builtins/builtins.h"
#include "codegen/codegen.h"
#include "builtins/helpers.h"
using namespace goose;
using namespace goose::builtins;
using namespace goose::codegen;
namespace goose::builtins
{
void SetupRuntimeBasicTypes( Env& e )
{
| | | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
#include "builtins/builtins.h"
#include "codegen/codegen.h"
#include "builtins/helpers.h"
using namespace goose;
using namespace goose::builtins;
using namespace goose::codegen;
namespace goose::builtins
{
void SetupRuntimeBasicTypes( Env& e )
{
DefineConstant( e, "half"_sid, ValueToEIR( ToValue( HalfFloatType() ) ) );
DefineConstant( e, "float"_sid, ValueToEIR( ToValue( FloatType() ) ) );
DefineConstant( e, "double"_sid, ValueToEIR( ToValue( DoubleFloatType() ) ) );
RegisterBuiltinFunc< Eager< Value > ( uint32_t ) >( e, "uint"_sid,
[]( uint32_t numBits )
{
return ToValue( IntegerType( numBits ) );
} );
|
| ︙ | ︙ |
Changes to bs/builtins/types/runtime/init.cpp.
| ︙ | ︙ | |||
14 15 16 17 18 19 20 |
using IntegerType = CustomPattern< IntegerType, IntegerType::Pattern >;
// Initialization for integer vars
RegisterBuiltinFunc< Intrinsic< Value ( IntegerMutRefType, IntegerType ) > >( e, e.extInitialize(),
[]( auto&& c, const Value& r, const Value& initVal )
{
G_VAL_ASSERT( r, !r.isConstant() );
| | | 14 15 16 17 18 19 20 21 22 23 24 25 26 |
using IntegerType = CustomPattern< IntegerType, IntegerType::Pattern >;
// Initialization for integer vars
RegisterBuiltinFunc< Intrinsic< Value ( IntegerMutRefType, IntegerType ) > >( e, e.extInitialize(),
[]( auto&& c, const Value& r, const Value& initVal )
{
G_VAL_ASSERT( r, !r.isConstant() );
auto refType = *FromValue< ReferenceType >( *EIRToValue( r.type() ) );
return BuildComputedValue( GetValueType< void >(),
Store( r.cir(), refType.type(), initVal, r.locationId() ) );
} );
}
}
|
Changes to bs/builtins/types/runtime/pointer.cpp.
1 2 3 4 5 6 7 8 9 10 11 |
#include "builtins/builtins.h"
#include "builtins/helpers.h"
using namespace goose;
using namespace goose::builtins;
namespace goose::builtins
{
void SetupRuntimePointerType( Env& e )
{
// null pointer literal
| | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
#include "builtins/builtins.h"
#include "builtins/helpers.h"
using namespace goose;
using namespace goose::builtins;
namespace goose::builtins
{
void SetupRuntimePointerType( Env& e )
{
// null pointer literal
e.storeValue( AppendToVectorTerm( RootG0Identity(), TSID( nullptr ) ), ANYTERM( _ ), ValueToEIR( ToValue( NullPointer() ) ) );
RegisterBuiltinFunc< Eager< Value > ( Value ) >( e, "pointer"_sid,
[]( const Value& pointedType )
{
if( !GetLLVMType( pointedType ) )
{
// TODO come up with some lightweight builtin option type
// for the builtin apis, because this is a very bullshit
// way to handle errors
return ToValue( "error"s );
}
return ToValue( PointerType( ValueToEIR( pointedType ) ) );
} );
}
llvm::Type* GetLLVMType( const PointerType& p )
{
return llvm::PointerType::getUnqual( GetLLVMType( *EIRToValue( p.m_pointedType ) ) );
}
}
namespace goose::eir
{
Value Bridge< PointerType >::ToValue( const PointerType& p )
{
|
| ︙ | ︙ | |||
87 88 89 90 91 92 93 |
{
static auto val = Value( Type(), TSID( nullptr ) );
return val;
}
optional< NullPointer > Bridge< NullPointer >::FromValue( const Value& v )
{
| | | 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 |
{
static auto val = Value( Type(), TSID( nullptr ) );
return val;
}
optional< NullPointer > Bridge< NullPointer >::FromValue( const Value& v )
{
if( !FromValue< NullPointerType >( *EIRToValue( v.type() ) ) )
return nullopt;
auto result = Decompose( v.val(),
Lit( "nullptr"_sid )
);
if( !result )
return nullopt;
return NullPointer();
}
}
|
Changes to bs/builtins/types/runtime/record.cpp.
| ︙ | ︙ | |||
44 45 46 47 48 49 50 |
llvm::Type* GetLLVMType( const RecordType& rt )
{
vector< llvm::Type* > elements;
elements.reserve( rt.m_memberTypes->terms().size() );
for( auto&& mt : rt.m_memberTypes->terms() )
{
| | | 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
llvm::Type* GetLLVMType( const RecordType& rt )
{
vector< llvm::Type* > elements;
elements.reserve( rt.m_memberTypes->terms().size() );
for( auto&& mt : rt.m_memberTypes->terms() )
{
auto llvmType = GetLLVMType( *EIRToValue( mt ) );
assert( llvmType );
elements.emplace_back( llvmType );
}
return llvm::StructType::get( GetLLVMContext(), elements, rt.m_packed );
}
}
|
| ︙ | ︙ |
Changes to bs/builtins/types/runtime/typecheck.cpp.
| ︙ | ︙ | |||
29 30 31 32 33 34 35 |
[]( const Term& lhs, const Term& rhs, TypeCheckingContext tcc ) -> TCGen
{
// The rhs might not be constant. It can happen even with ct_int if the rhs is a
// fake argument pattern generated to unify a higher-order function param.
// It means that we are unifying a function parameter against any ct_int value,
// which we can't (because we have to know the value to safely convert it),
// so we reject it.
| | | | | 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
[]( const Term& lhs, const Term& rhs, TypeCheckingContext tcc ) -> TCGen
{
// The rhs might not be constant. It can happen even with ct_int if the rhs is a
// fake argument pattern generated to unify a higher-order function param.
// It means that we are unifying a function parameter against any ct_int value,
// which we can't (because we have to know the value to safely convert it),
// so we reject it.
auto rhsVal = *EIRToValue( rhs );
if( !rhsVal.isConstant() )
co_return;
auto lhsVal = ValuePatternFromEIR( lhs );
if( !lhsVal )
co_return;
auto s = HalfUnify( lhsVal->type(), tcc );
if( !s )
co_return;
auto wrapped = WrapWithPostprocFunc( *s,
[rhs]( const Term& t, TypeCheckingContext tcc ) -> optional< Term >
{
auto argVal = EIRToValue( rhs );
assert( argVal );
auto ct = *FromValue< BigInt >( *argVal );
auto rttypeVal = EIRToValue( t );
assert( rttypeVal );
auto rttype = FromValue< IntegerType >( *rttypeVal );
assert( rttype );
APSInt valToLoad;
|
| ︙ | ︙ |
Changes to bs/builtins/types/template/build.cpp.
| ︙ | ︙ | |||
30 31 32 33 34 35 36 |
{
auto v = make_shared< Vector >();
v->reserve( VecSize( tft.params() ) + 1 );
auto rtSig = BuildTemplateSignature( c, tft.returnType() );
if( !rtSig )
{
| | | | 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
{
auto v = make_shared< Vector >();
v->reserve( VecSize( tft.params() ) + 1 );
auto rtSig = BuildTemplateSignature( c, tft.returnType() );
if( !rtSig )
{
DiagnosticsManager::GetInstance().emitErrorMessage( EIRToValue( tft.returnType() )->locationId(),
"Invalid template return type or texpr." );
return nullopt;
}
v->append( move( *rtSig ) );
bool success = true;
ForEachInVectorTerm( tft.params(), [&]( auto&& param )
{
auto teSig = BuildTemplateSignature( c, param );
if( !teSig )
{
DiagnosticsManager::GetInstance().emitErrorMessage( EIRToValue( param )->locationId(),
"Invalid template parameter." );
success = false;
return false;
}
v->append( move( *teSig ) );
return true;
|
| ︙ | ︙ | |||
78 79 80 81 82 83 84 |
auto apv = make_shared< Vector >();
apv->reserve( VecSize( ftype->params() ) + 1 );
auto rtArgPat = BuildTemplateArgPattern( c, ftype->returnType() );
if( !rtArgPat )
{
| | | | 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 |
auto apv = make_shared< Vector >();
apv->reserve( VecSize( ftype->params() ) + 1 );
auto rtArgPat = BuildTemplateArgPattern( c, ftype->returnType() );
if( !rtArgPat )
{
DiagnosticsManager::GetInstance().emitErrorMessage( EIRToValue( ftype->returnType() )->locationId(),
"Invalid template return type or texpr." );
return nullopt;
}
apv->append( move( *rtArgPat ) );
bool success = true;
ForEachInVectorTerm( ftype->params(), [&]( auto&& param )
{
auto teArgPat = BuildTemplateArgPattern( c, param );
if( !teArgPat )
{
DiagnosticsManager::GetInstance().emitErrorMessage( EIRToValue( param )->locationId(),
"Invalid template parameter." );
success = false;
return false;
}
apv->append( move( *teArgPat ) );
return true;
|
| ︙ | ︙ |
Changes to bs/builtins/types/template/instantiate.cpp.
| ︙ | ︙ | |||
26 27 28 29 30 31 32 |
{
auto p = BuildTemplateParam( c, param, arg );
instanceParams = AppendToTuple( instanceParams, p );
return true;
} );
// Build the instance function type and identity
| | | | 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
{
auto p = BuildTemplateParam( c, param, arg );
instanceParams = AppendToTuple( instanceParams, p );
return true;
} );
// Build the instance function type and identity
auto returnType = *EIRToValue( unifiedRType );
auto instanceType = BuildFuncType( c, returnType, instanceParams );
if( !instanceType )
return PoisonValue();
instanceType->setIntrinsic( tf->type().intrinsic() );
auto instanceSig = GetFuncSigFromType( ToValue( *instanceType ) );
auto instanceIdentity = AppendToVectorTerm( tf->identity(), instanceSig );
// Look for an already existing instanced function
Value instanceFunc = PoisonValue();
Term result;
switch( c.env()->retrieveValue( instanceIdentity, c.identity(), result ) )
{
case Env::Status::Success:
instanceFunc = *EIRToValue( result );
break;
case Env::Status::NoMatch:
{
// Prepare the verification statements
instanceType->verifInfos()->setPreCondToks( tf->type().preCondToks() );
instanceType->verifInfos()->setPostCondToks( tf->type().postCondToks() );
|
| ︙ | ︙ |
Changes to bs/builtins/types/template/pretty.cpp.
| ︙ | ︙ | |||
12 13 14 15 16 17 18 |
auto& pp = PrettyPrinter::GetInstance();
pp.addRule( ValueToEIR( ValuePattern( TSID( constant ),
ValueToEIR( Value( TypeType(), VEC( TSID( texpr ), TSID( tvar ) ) ) ),
ANYTERM( _ ) ) ),
[&]( auto&& out, auto&& t )
{
| | | | | 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
auto& pp = PrettyPrinter::GetInstance();
pp.addRule( ValueToEIR( ValuePattern( TSID( constant ),
ValueToEIR( Value( TypeType(), VEC( TSID( texpr ), TSID( tvar ) ) ) ),
ANYTERM( _ ) ) ),
[&]( auto&& out, auto&& t )
{
auto tvar = *FromValue< TVar >( *EIRToValue( t ) );
out << '$' << tvar.name();
return true;
} );
pp.addRule( ValueToEIR( ValuePattern( TSID( constant ),
ValueToEIR( Value( TypeType(), VEC( TSID( texpr ), TSID( ttvar ) ) ) ),
ANYTERM( _ ) ) ),
[&]( auto&& out, auto&& t )
{
auto tvar = *FromValue< TTVar >( *EIRToValue( t ) );
out << "$$" << tvar.name();
return true;
} );
pp.addRule( ValueToEIR( ValuePattern( TSID( constant ),
ValueToEIR( Value( TypeType(), TSID( tnameddecl ) ) ),
VEC( ANYTERM( _ ), ANYTERM( _ ) ) ) ),
[&]( auto&& out, auto&& t )
{
auto decl = *FromValue< TNamedDecl >( *EIRToValue( t ) );
out << "tnameddecl(" << decl.type() << ", " << decl.name() << ")";
return true;
} );
}
}
|
Changes to bs/builtins/types/template/rules.cpp.
| ︙ | ︙ | |||
36 37 38 39 40 41 42 |
tcc.eraseLHSName( name );
}
class DeclTemplateRule : public TemplateRule
{
optional< Term > buildSignature( const Context& c, const Term& val ) const final
{
| | | | | | | | | | | | | | | | | | 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 |
tcc.eraseLHSName( name );
}
class DeclTemplateRule : public TemplateRule
{
optional< Term > buildSignature( const Context& c, const Term& val ) const final
{
auto decl = FromValue< Decl >( *EIRToValue( val ) );
assert( decl );
return ParamPat( decl->type() );
}
Value buildParamDecl( const Context& c, const Term& param, const Term& arg ) const final
{
return *EIRToValue( param );
}
optional< Term > buildArgPattern( const Context& c, const Term& val ) const final
{
auto decl = FromValue< Decl >( *EIRToValue( val ) );
assert( decl );
return ValueToEIR( ValuePattern( TSID( computed ), decl->type(), TERM( ptr< void >() ) ) );
}
};
class TNamedDeclTemplateRule : public TemplateRule
{
optional< Term > buildSignature( const Context& c, const Term& val ) const final
{
auto tnd = FromValue< TNamedDecl >( *EIRToValue( val ) );
assert( tnd );
auto typeSig = BuildTemplateSignature( c, tnd->type() );
if( !typeSig )
return nullopt;
return ParamPat( *typeSig );
}
Value buildParamDecl( const Context& c, const Term& param, const Term& argEIR ) const final
{
auto tnd = FromValue< TNamedDecl >( *EIRToValue( param ) );
assert( tnd );
auto arg = *EIRToValue( argEIR );
return ToValue( Decl( arg.type(), tnd->name() ) );
}
void setup( const Context& c, TypeCheckingContext& tcc, const Term& val ) const final
{
auto tnd = FromValue< TNamedDecl >( *EIRToValue( val ) );
assert( tnd );
TemplateSetup( c, tcc, tnd->type() );
}
optional< Term > buildArgPattern( const Context& c, const Term& val ) const final
{
auto tnd = FromValue< TNamedDecl >( *EIRToValue( val ) );
assert( tnd );
auto typeSig = BuildTemplateArgPattern( c, tnd->type() );
if( !typeSig )
return nullopt;
return ValueToEIR( ValuePattern( TSID( computed ), *typeSig, TERM( ptr< void >() ) ) );
}
};
class TDeclTemplateRule : public TemplateRule
{
optional< Term > buildSignature( const Context& c, const Term& val ) const final
{
return val;
}
Value buildParamDecl( const Context& c, const Term& param, const Term& arg ) const final
{
return *EIRToValue( arg );
}
void setup( const Context& c, TypeCheckingContext& tcc, const Term& val ) const final
{
auto tdecl = FromValue< TDecl >( *EIRToValue( val ) );
assert( tdecl );
TemplateSetup( c, tcc, tdecl->type() );
setupTVar( c, tcc, tdecl->name() );
}
optional< Term > buildArgPattern( const Context& c, const Term& val ) const final
{
return buildSignature( c, val );
}
};
class TVarTemplateRule : public TemplateRule
{
optional< Term > buildSignature( const Context& c, const Term& val ) const final
{
auto tvar = FromValue< TVar >( *EIRToValue( val ) );
assert( tvar );
return HOLE( tvar->name(), TSID( tvar ) );
}
Value buildParamDecl( const Context& c, const Term& param, const Term& arg ) const final
{
return *EIRToValue( arg );
}
void setup( const Context& c, TypeCheckingContext& tcc, const Term& val ) const final
{
auto tvar = FromValue< TVar >( *EIRToValue( val ) );
assert( tvar );
setupTVar( c, tcc, tvar->name() );
}
optional< Term > buildArgPattern( const Context& c, const Term& val ) const final
{
return buildSignature( c, val );
}
};
class TTVarTemplateRule : public TemplateRule
{
optional< Term > buildSignature( const Context& c, const Term& val ) const final
{
auto ttvar = FromValue< TTVar >( *EIRToValue( val ) );
assert( ttvar );
return HOLE( ttvar->name(), TSID( fwd ) );
}
Value buildParamDecl( const Context& c, const Term& param, const Term& arg ) const final
{
return *EIRToValue( arg );
}
void setup( const Context& c, TypeCheckingContext& tcc, const Term& val ) const final
{
auto ttvar = FromValue< TTVar >( *EIRToValue( val ) );
assert( ttvar );
setupTVar( c, tcc, ttvar->name() );
}
optional< Term > buildArgPattern( const Context& c, const Term& val ) const final
{
return buildSignature( c, val );
|
| ︙ | ︙ | |||
201 202 203 204 205 206 207 |
}
return v;
}
Value buildParamDecl( const Context& c, const Term& param, const Term& arg ) const final
{
| | | 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 |
}
return v;
}
Value buildParamDecl( const Context& c, const Term& param, const Term& arg ) const final
{
return *EIRToValue( arg );
}
void setup( const Context& c, TypeCheckingContext& tcc, const Term& t ) const final
{
auto tvec = TVecFromEIR( t );
assert( tvec );
|
| ︙ | ︙ | |||
237 238 239 240 241 242 243 |
}
};
class ValueTemplateRule : public TemplateRule
{
optional< Term > buildSignature( const Context& c, const Term& valEIR ) const final
{
| | | | | | | 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 |
}
};
class ValueTemplateRule : public TemplateRule
{
optional< Term > buildSignature( const Context& c, const Term& valEIR ) const final
{
auto val = *EIRToValue( valEIR );
auto vsig = BuildTemplateSignature( c, val.val() );
if( IsType( c, val ) )
return ParamPat( val.type(), vsig ? move( *vsig ) : val.val() );
auto tsig = BuildTemplateSignature( c, val.type() );
return ParamPat( tsig ? move( *tsig ) : val.type(), vsig ? move( *vsig ) : val.val() );
}
Value buildParamDecl( const Context& c, const Term& val, const Term& arg ) const final
{
return *EIRToValue( val );
}
void setup( const Context& c, TypeCheckingContext& tcc, const Term& valEIR ) const final
{
auto val = *EIRToValue( valEIR );
TemplateSetup( c, tcc, val.type() );
TemplateSetup( c, tcc, val.val() );
}
optional< Term > buildArgPattern( const Context& c, const Term& val ) const final
{
return buildSignature( c, val );
}
};
class TFuncTypeTemplateRule : public TemplateRule
{
optional< Term > buildSignature( const Context& c, const Term& val ) const final
{
return val;
}
Value buildParamDecl( const Context& c, const Term& param, const Term& arg ) const final
{
return *EIRToValue( arg );
}
void setup( const Context& c, TypeCheckingContext& tcc, const Term& val ) const final
{
auto tft = FromValue< TFuncType >( *EIRToValue( val ) );
assert( tft );
ForEachInVectorTerm( tft->params(), [&]( auto&& param )
{
TemplateSetup( c, tcc, param );
return true;
} );
|
| ︙ | ︙ |
Changes to bs/builtins/types/template/tc-tdecl.cpp.
1 2 3 4 5 6 7 8 9 10 11 |
#include "builtins/builtins.h"
namespace goose::builtins
{
Term BuildArgPatternFromTDecl( const TDecl& td )
{
return ValueToEIR( ValuePattern( HOLE( "_"_sid ), td.type(), HOLE( "_"_sid ) ) );
}
TCGen TypeCheckTDecl( const Term& lhs, const Term& rhs, TypeCheckingContext tcc )
{
| | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
#include "builtins/builtins.h"
namespace goose::builtins
{
Term BuildArgPatternFromTDecl( const TDecl& td )
{
return ValueToEIR( ValuePattern( HOLE( "_"_sid ), td.type(), HOLE( "_"_sid ) ) );
}
TCGen TypeCheckTDecl( const Term& lhs, const Term& rhs, TypeCheckingContext tcc )
{
auto tdecl = FromValue< TDecl >( *EIRToValue( lhs ) );
assert( tdecl );
auto tdeclHole = HOLE( tdecl->name() );
auto pat = ValueToEIR( Value( tdecl->type(), HOLE( "_"_sid ) ) );
for( auto&& [s,tcc] : Unify( pat, rhs, tcc ) )
|
| ︙ | ︙ | |||
34 35 36 37 38 39 40 |
void SetupTDeclTypeChecking( Env& e )
{
auto tDeclPat = ValueToEIR( Value( GetValueType< TDecl >(), VEC( ANYTERM( _ ), ANYTERM( _ ) ) ) );
e.typeCheckingRuleSet()->addHalfUnificationRule( TCRINFOS, tDeclPat,
[]( const Term& lhs, TypeCheckingContext& c )
{
| | | 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
void SetupTDeclTypeChecking( Env& e )
{
auto tDeclPat = ValueToEIR( Value( GetValueType< TDecl >(), VEC( ANYTERM( _ ), ANYTERM( _ ) ) ) );
e.typeCheckingRuleSet()->addHalfUnificationRule( TCRINFOS, tDeclPat,
[]( const Term& lhs, TypeCheckingContext& c )
{
auto tdecl = FromValue< TDecl >( *EIRToValue( lhs ) );
assert( tdecl );
return HalfUnify( tdecl->type(), c );
} );
e.typeCheckingRuleSet()->addTypeCheckingRule( TCRINFOS, tDeclPat, ANYTERM( _ ), TypeCheckTDecl );
e.typeCheckingRuleSet()->addTypeCheckingRule( TCRINFOS, tDeclPat, tDeclPat, TypeCheckTDecl );
|
| ︙ | ︙ | |||
56 57 58 59 60 61 62 |
ValueToEIR( ValuePattern(
TSID( constant ),
TFuncTypePattern(),
ANYTERM( _ ) ) ),
[]( const Term& lhs, const Term& rhs, TypeCheckingContext tcc ) -> TCGen
{
| | | | | 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 |
ValueToEIR( ValuePattern(
TSID( constant ),
TFuncTypePattern(),
ANYTERM( _ ) ) ),
[]( const Term& lhs, const Term& rhs, TypeCheckingContext tcc ) -> TCGen
{
auto tdecl = FromValue< TDecl >( *EIRToValue( lhs ) );
assert( tdecl );
auto tfuncType = FromValue< TFuncType >( *EIRToValue( tdecl->type() ) );
assert( tfuncType );
auto callPat = BuildArgPatternFromTDecl( *tdecl );
auto tdeclHole = HOLE( tdecl->name() );
auto rhsVal = *EIRToValue( rhs );
auto constraintPat = BuildTFuncSignature( tcc.context(), *tfuncType );
assert( constraintPat );
ConstrainedFunc cfunc( *constraintPat, GetTFuncInvocationRule(), rhsVal );
auto cFuncTerm = ValueToEIR( ToValue( move( cfunc ) ) );
|
| ︙ | ︙ | |||
111 112 113 114 115 116 117 |
ValueToEIR( ValuePattern(
TSID( constant ),
GetValueType< ptr< sema::OverloadSet > >(),
ANYTERM( _ ) ) ),
[]( const Term& lhs, const Term& rhs, TypeCheckingContext tcc ) -> TCGen
{
| | | | | 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 |
ValueToEIR( ValuePattern(
TSID( constant ),
GetValueType< ptr< sema::OverloadSet > >(),
ANYTERM( _ ) ) ),
[]( const Term& lhs, const Term& rhs, TypeCheckingContext tcc ) -> TCGen
{
auto tdecl = FromValue< TDecl >( *EIRToValue( lhs ) );
assert( tdecl );
auto tfuncType = FromValue< TFuncType >( *EIRToValue( tdecl->type() ) );
assert( tfuncType );
auto callPat = BuildArgPatternFromTDecl( *tdecl );
auto tdeclHole = HOLE( tdecl->name() );
auto rhsVal = *EIRToValue( rhs );
auto constraintPat = BuildTFuncSignature( tcc.context(), *tfuncType );
assert( constraintPat );
ConstrainedFunc cfunc( *constraintPat, GetOverloadSetInvocationRule(), rhsVal );
auto cFuncTerm = ValueToEIR( ToValue( move( cfunc ) ) );
|
| ︙ | ︙ |
Changes to bs/builtins/types/template/tfunc.cpp.
| ︙ | ︙ | |||
16 17 18 19 20 21 22 |
{
return Value( Type( tf ), VEC( Quote( tf.signature() ), tf.identity(),
TERM( tf.toks() ) ) );
}
optional< TFunc > Bridge< TFunc >::FromValue( const Value& v )
{
| | | 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
{
return Value( Type( tf ), VEC( Quote( tf.signature() ), tf.identity(),
TERM( tf.toks() ) ) );
}
optional< TFunc > Bridge< TFunc >::FromValue( const Value& v )
{
auto typeVal = EIRToValue( v.type() );
auto type = ::FromValue< TFuncType >( *typeVal );
if( !type )
return nullopt;
auto result = Decompose( v.val(),
Vec(
SubTerm(), // signature
|
| ︙ | ︙ |
Changes to bs/builtins/types/template/tfunctype.cpp.
| ︙ | ︙ | |||
22 23 24 25 26 27 28 |
);
return !!result;
}
bool IsTFunc( const Value& t )
{
| | | 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
);
return !!result;
}
bool IsTFunc( const Value& t )
{
return IsTFuncType( *EIRToValue( t.type() ) );
}
const Term& TFuncPattern::GetPattern()
{
static auto pattern = ValueToEIR(
Value( TypeType(), VEC( TSID( texpr ), TSID( tfunc ), HOLE( "_"_sid ),
HOLE( "_"_sid ), HOLE( "_"_sid ),
|
| ︙ | ︙ |
Changes to bs/builtins/types/template/tvar.cpp.
| ︙ | ︙ | |||
17 18 19 20 21 22 23 |
if( ppVec && !( *ppVec )->empty()
&&( **ppVec )[0] == TSID( texpr ) )
{
return true;
}
}
| | | 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
if( ppVec && !( *ppVec )->empty()
&&( **ppVec )[0] == TSID( texpr ) )
{
return true;
}
}
auto typeVal = EIRToValue( te.type() );
if( !typeVal )
return false;
const auto* ppVec = get_if< pvec >( &typeVal->val() );
if( !ppVec )
return false;
|
| ︙ | ︙ |
Changes to bs/builtins/types/template/tvec.h.
| ︙ | ︙ | |||
27 28 29 30 31 32 33 |
// so that they are automatically turned into a suitable TExpr if
// TExprs are passed as parameters.
template< typename... T >
extern Term BuildVecOrTVec( T&&... terms )
{
auto vec = Vector::Make( terms... );
| | | 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
// so that they are automatically turned into a suitable TExpr if
// TExprs are passed as parameters.
template< typename... T >
extern Term BuildVecOrTVec( T&&... terms )
{
auto vec = Vector::Make( terms... );
if( ( IsTExpr( EIRToValue( terms ) ) || ... ) )
return TVecToEIR( TVec( move( vec ) ) );
return vec;
}
#define TVEC( ... ) BuildVecOrTVec( __VA_ARGS__ )
}
|
| ︙ | ︙ |
Changes to bs/builtins/types/template/typecheck.cpp.
| ︙ | ︙ | |||
27 28 29 30 31 32 33 |
SubTerm(),
Val< LocationId >()
)
);
assert( ldecomp );
auto&& [sort, type, val, locId] = *ldecomp;
| | | | 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
SubTerm(),
Val< LocationId >()
)
);
assert( ldecomp );
auto&& [sort, type, val, locId] = *ldecomp;
auto callPat = BuildCallPatternFromFuncType( *EIRToValue( type ) );
auto rhsVal = *EIRToValue( rhs );
auto tf = *FromValue< TFunc >( rhsVal );
// Create a new named hole namespace to isolate holes from the passed function from those in
// the called function.
auto savedRHSNamespaceIndex = tcc.RHSNamespaceIndex();
auto localNSId = tcc.newNamespaceIndex();
tcc.setRHSNamespaceIndex( localNSId );
|
| ︙ | ︙ | |||
85 86 87 88 89 90 91 |
SubTerm(),
Val< LocationId >()
)
);
assert( ldecomp );
auto&& [sort, type, val, locId] = *ldecomp;
| | | | 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 |
SubTerm(),
Val< LocationId >()
)
);
assert( ldecomp );
auto&& [sort, type, val, locId] = *ldecomp;
auto callPat = BuildArgPatternFromTFuncType( tcc.context(), *EIRToValue( type ) );
assert( callPat );
auto rhsVal = *EIRToValue( rhs );
auto tf = *FromValue< TFunc >( rhsVal );
// Create a new named hole namespace to isolate holes from the passed function from those in
// the called function.
auto savedRHSNamespaceIndex = tcc.RHSNamespaceIndex();
auto localNSId = tcc.newNamespaceIndex();
tcc.setRHSNamespaceIndex( localNSId );
|
| ︙ | ︙ |
Changes to bs/builtins/types/tuple/init.cpp.
1 2 3 4 5 6 7 8 9 10 11 12 |
#include "builtins/builtins.h"
#include "parse/parse.h"
using namespace goose::parse;
using namespace goose::cir;
namespace goose::builtins
{
void InitTuple( const Context& c, const Value& tupRef, const Value& initTup )
{
G_VAL_ASSERT( tupRef, !tupRef.isConstant() );
| | | | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
#include "builtins/builtins.h"
#include "parse/parse.h"
using namespace goose::parse;
using namespace goose::cir;
namespace goose::builtins
{
void InitTuple( const Context& c, const Value& tupRef, const Value& initTup )
{
G_VAL_ASSERT( tupRef, !tupRef.isConstant() );
auto lrefType = *FromValue< ReferenceType >( *EIRToValue( tupRef.type() ) );
uint32_t index = 0;
auto tupType = *EIRToValue( lrefType.type() );
if( TupleTypeSize( tupType ) != TupleSize( initTup ) )
{
DiagnosticsManager::GetInstance().emitErrorMessage( 0, "Incompatible tuple sizes." );
return;
}
ForEachInTupleType( tupType, [&]( auto&& t )
{
auto elemType = *EIRToValue( t );
// Create a mutable reference to the element to initialize
ReferenceType rt( t, TSID( mut ) );
auto elemRef = BuildComputedValue( ValueToEIR( ToValue( rt ) ),
Select( tupRef.cir(), index ) ).setLocationId( elemType.locationId() );
auto elemInit = *EIRToValue( GetTupleElement( initTup, index++ ) );
DiagnosticsContext dc( elemType.locationId(), "When invoking Initialize." );
auto init = InvokeOverloadSet( c, c.env()->extInitialize(),
MakeTuple( elemRef, move( elemInit ) ) );
DiagnosticsContext dc2( elemType.locationId(), "When invoking DropValue." );
InvokeOverloadSet( c, c.env()->extDropValue(),
|
| ︙ | ︙ | |||
49 50 51 52 53 54 55 |
// Tuples default initialization: attempt to default initialize every element.
RegisterBuiltinFunc< Intrinsic< void (
CustomPattern< Value, ReferenceType::PatternMutable< TuplePattern > >
) > >( e, e.extInitialize(),
[]( const Context& c, const Value& tupRef )
{
G_VAL_ASSERT( tupRef, !tupRef.isConstant() );
| | | | | 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 |
// Tuples default initialization: attempt to default initialize every element.
RegisterBuiltinFunc< Intrinsic< void (
CustomPattern< Value, ReferenceType::PatternMutable< TuplePattern > >
) > >( e, e.extInitialize(),
[]( const Context& c, const Value& tupRef )
{
G_VAL_ASSERT( tupRef, !tupRef.isConstant() );
auto refType = *FromValue< ReferenceType >( *EIRToValue( tupRef.type() ) );
uint32_t index = 0;
auto tupType = *EIRToValue( refType.type() );
ForEachInTupleType( tupType, [&]( auto&& t )
{
auto elemType = *EIRToValue( t );
// Create a mutable reference to the element to initialize
ReferenceType rt( t, TSID( mut ) );
auto elemRef = BuildComputedValue( ValueToEIR( ToValue( rt ) ),
Select( tupRef.cir(), index++ ) ).setLocationId( elemType.locationId() );
DiagnosticsContext dc( elemType.locationId(), "When invoking Initialize." );
|
| ︙ | ︙ |
Changes to bs/builtins/types/tuple/lower.cpp.
| ︙ | ︙ | |||
12 13 14 15 16 17 18 |
[]( const Context& c, const Value& tupType )
{
RecordType rt;
bool success = true;
ForEachInTupleType( tupType, [&]( auto&& t )
{
| | | 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
[]( const Context& c, const Value& tupType )
{
RecordType rt;
bool success = true;
ForEachInTupleType( tupType, [&]( auto&& t )
{
auto loweredType = LowerTypeForRuntime( c, *EIRToValue( t ) );
if( !loweredType || loweredType->isPoison() )
{
success = false;
return false;
}
rt.m_memberTypes->append( ValueToEIR( *loweredType ) );
|
| ︙ | ︙ |
Changes to bs/builtins/types/tuple/tuple.cpp.
| ︙ | ︙ | |||
15 16 17 18 19 20 21 |
{
static auto val = Value( ValueToEIR( EmptyClosedTupleType() ), VEC() );
return val;
}
Value AppendToTuple( const Value& tup, const ValuePattern& valPat )
{
| | | | | | | | | | | | | 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 |
{
static auto val = Value( ValueToEIR( EmptyClosedTupleType() ), VEC() );
return val;
}
Value AppendToTuple( const Value& tup, const ValuePattern& valPat )
{
auto tupType = EIRToValue( tup.type() );
assert( tupType );
auto result = Value(
ValueToEIR( AppendToTupleType( *tupType, valPat.type() ) ),
AppendToVectorTerm( tup.val(), ValueToEIR( valPat ) ) );
if( tup.isPoison() || valPat.isPoison() )
result.setPoison();
return result;
}
Value AppendToTuple( const Value& tup, const Value& val )
{
auto tupType = EIRToValue( tup.type() );
auto valType = EIRToValue( val.type() );
assert( tupType );
assert( valType );
auto result = Value(
ValueToEIR( AppendToTupleType( *tupType, *valType ) ),
AppendToVectorTerm( tup.val(), ValueToEIR( val ) ) );
if( tup.isPoison() || val.isPoison() )
result.setPoison();
return result;
}
Value PrependToTuple( const Value& val, const Value& tup )
{
auto tupType = EIRToValue( tup.type() );
auto valType = EIRToValue( val.type() );
assert( tupType );
assert( valType );
auto result = Value(
ValueToEIR( PrependToTupleType( *valType, *tupType ) ),
PrependToVectorTerm( tup.val(), ValueToEIR( val ) ) );
if( tup.isPoison() || val.isPoison() )
result.setPoison();
return result;
}
Value ConcatenateTuples( const Value& ltup, const Value& rtup )
{
auto ltupType = EIRToValue( ltup.type() );
auto rtupType = EIRToValue( rtup.type() );
assert( ltupType );
assert( rtupType );
auto result = Value(
ValueToEIR( ConcatenateTupleTypes( *ltupType, *rtupType ) ),
ConcatenateVectorTerms( ltup.val(), rtup.val() ) );
if( ltup.isPoison() || rtup.isPoison() )
result.setPoison();
return result;
}
bool IsTuple( const Value& t )
{
auto typeVal = EIRToValue( t.type() );
if( !typeVal || !typeVal->isConstant() )
return false;
auto result = Decompose( typeVal->val(),
Vec(
Lit( "tuple"_sid ),
SubTerm(),
SubTerm()
)
);
return !!result;
}
bool IsOpenTuple( const Value& t )
{
if( !t.isConstant() )
return false;
auto typeVal = EIRToValue( t.type() );
auto result = Decompose( typeVal->val(),
Vec(
Lit( "tuple"_sid ),
Lit( "open"_sid ),
SubTerm()
)
);
return !!result;
}
Value CloseTuple( const Value& tup )
{
auto tupType = EIRToValue( tup.type() );
return Value( ValueToEIR( ToClosedTupleType( *tupType ) ),
tup.val() ).setLocationId( tup.locationId() );
}
size_t TupleSize( const Value& tup )
{
const auto& vec = *get< pvec >( tup.val() );
return vec.terms().size();
}
const Term& GetTupleElementType( const Value& tup, uint32_t index )
{
return GetTupleTypeElement( *EIRToValue( tup.type() ), index );
}
const Term& GetTupleElement( const Value& tup, uint32_t index )
{
const auto& vec = *get< pvec >( tup.val() );
return vec.terms()[index];
}
|
| ︙ | ︙ |
Changes to bs/builtins/types/tuple/tuple.inl.
| ︙ | ︙ | |||
16 17 18 19 20 21 22 |
{
// Check that the tuple's payload is a vector. It might be a hole.
if( !holds_alternative< pvec >( tup.val() ) )
return;
ForEachInVectorTerm( tup.val(), [&]( auto&& t )
{
| | | 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
{
// Check that the tuple's payload is a vector. It might be a hole.
if( !holds_alternative< pvec >( tup.val() ) )
return;
ForEachInVectorTerm( tup.val(), [&]( auto&& t )
{
return func( *EIRToValue( t ) );
} );
}
template< typename F >
void ForEachInTupleType( const Value& tupType, F&& func )
{
auto decomp = Decompose( tupType.val(),
|
| ︙ | ︙ | |||
102 103 104 105 106 107 108 |
template< typename H, typename... T >
static Value BuildTupleType( const Value& typeSoFar )
{
if constexpr( sizeof...( T ) > 1 )
{
return BuildTupleType< T... >( builtins::AppendToTupleType( typeSoFar,
| | | | 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 |
template< typename H, typename... T >
static Value BuildTupleType( const Value& typeSoFar )
{
if constexpr( sizeof...( T ) > 1 )
{
return BuildTupleType< T... >( builtins::AppendToTupleType( typeSoFar,
*EIRToValue( GetValueType< H >() ) ) );
}
else
return builtins::AppendToTupleType( typeSoFar, *EIRToValue( GetValueType< H >() ) );
}
template< typename... T >
const Term& Bridge< tuple< T... > >::Type()
{
if constexpr( sizeof... ( T ) == 0 )
{
|
| ︙ | ︙ | |||
144 145 146 147 148 149 150 |
template< typename TT, size_t... I >
optional< TT > BuildTupleFromValueVec( const Vector& vec, index_sequence< I... > )
{
if constexpr( sizeof... ( I ) == 0 )
return TT();
else
{
| | | 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 |
template< typename TT, size_t... I >
optional< TT > BuildTupleFromValueVec( const Vector& vec, index_sequence< I... > )
{
if constexpr( sizeof... ( I ) == 0 )
return TT();
else
{
auto values = make_tuple( EIRToValue( vec[I] )... );
if( ( !get< I >( values ) || ... ) )
return nullopt;
auto items = make_tuple( FromValue< tuple_element_t< I, TT > >( *get< I >( values ) )... );
if( ( !get< I >( items ) || ... ) )
return nullopt;
|
| ︙ | ︙ |
Changes to bs/builtins/types/tuple/tupletype.cpp.
| ︙ | ︙ | |||
46 47 48 49 50 51 52 |
Value MkTupleType( const Term& state, const Term& types )
{
return Value( TypeType(), VEC( TSID( tuple ), state, types ) );
}
extern Value TupleOfTypesToTupleType( const Value& tup )
{
| | | 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
Value MkTupleType( const Term& state, const Term& types )
{
return Value( TypeType(), VEC( TSID( tuple ), state, types ) );
}
extern Value TupleOfTypesToTupleType( const Value& tup )
{
auto typeVal = EIRToValue( tup.type() );
auto result = Decompose( typeVal->val(),
Vec(
Lit( "tuple"_sid ),
SubTerm(),
SubTerm()
)
);
|
| ︙ | ︙ |
Changes to bs/builtins/types/tuple/typecheck.cpp.
| ︙ | ︙ | |||
68 69 70 71 72 73 74 |
TSID( constant ),
ValueToEIR( MkTupleType( ANYTERM( _ ), VECOFLENGTH( L ) ) ),
VECOFLENGTH( L ) ) ),
[]( const Term& lhs, const Term& rhs, const TypeCheckingContext& tcc ) -> TCGen
{
auto ltup = ValuePatternFromEIR( lhs );
| | | | | | | 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 |
TSID( constant ),
ValueToEIR( MkTupleType( ANYTERM( _ ), VECOFLENGTH( L ) ) ),
VECOFLENGTH( L ) ) ),
[]( const Term& lhs, const Term& rhs, const TypeCheckingContext& tcc ) -> TCGen
{
auto ltup = ValuePatternFromEIR( lhs );
auto rtup = EIRToValue( rhs );
if( !ltup || !rtup )
co_return;
auto tupType = *EIRToValue( ltup->type() );
assert( TupleTypeSize( tupType ) == TupleSize( *rtup ) );
co_yield TypeCheckConstantTuple( tcc, tupType, *rtup, 0, EmptyTuple() );
} );
e.typeCheckingRuleSet()->addTypeCheckingRule( TCRINFOS,
ValueToEIR( ValuePattern(
ANYTERM( _ ),
ValueToEIR( MkTupleType( ANYTERM( _ ), VECOFLENGTH( L ) ) ),
ANYTERM( _ ) ) ),
ValueToEIR( ValuePattern(
TSID( computed ),
ValueToEIR( MkTupleType( ANYTERM( _ ), VECOFLENGTH( L ) ) ),
ANYTERM( _ ) ) ),
[]( const Term& lhs, const Term& rhs, const TypeCheckingContext& tcc ) -> TCGen
{
auto ltup = ValuePatternFromEIR( lhs );
auto rtup = EIRToValue( rhs );
if( !ltup || !rtup || !tcc.context().codeBuilder() )
co_return;
auto tupType = *EIRToValue( ltup->type() );
assert( TupleTypeSize( tupType ) == TupleTypeSize( *EIRToValue( rtup->type() ) ) );
auto tempIndex = tcc.context().codeBuilder()->cfg()->getNewTemporaryIndex();
auto rtupref = BuildComputedValue( ValueToEIR( ToValue( ReferenceType{ rtup->type(), TSID( const ) } ) ),
cir::TempAddr( tempIndex, *rtup ) );
co_yield TypeCheckComputedTuple( tcc, tupType, *rtup, rtupref, 0, EmptyTuple() );
|
| ︙ | ︙ | |||
126 127 128 129 130 131 132 |
ValueToEIR( ValuePattern(
TSID( constant ),
ValueToEIR( MkTupleType( ANYTERM( _ ), VEC( ANYTERM( _ ) ) ) ),
ANYTERM( _ ) ) ),
[]( const Term& lhs, const Term& rhs, const TypeCheckingContext& tcc ) -> TCGen
{
| | | 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 |
ValueToEIR( ValuePattern(
TSID( constant ),
ValueToEIR( MkTupleType( ANYTERM( _ ), VEC( ANYTERM( _ ) ) ) ),
ANYTERM( _ ) ) ),
[]( const Term& lhs, const Term& rhs, const TypeCheckingContext& tcc ) -> TCGen
{
auto tup = EIRToValue( rhs );
if( !tup )
co_return;
const auto& vec1 = *get< pvec >( tup->val() );
co_yield TypeCheck( lhs, vec1[0], tcc );
} );
|
| ︙ | ︙ | |||
148 149 150 151 152 153 154 |
ValueToEIR( ValuePattern(
TSID( constant ),
ANYTERM( _ ),
ANYTERM( _ ) ) ),
[]( const Term& lhs, const Term& rhs, const TypeCheckingContext& tcc ) -> TCGen
{
| | | 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 |
ValueToEIR( ValuePattern(
TSID( constant ),
ANYTERM( _ ),
ANYTERM( _ ) ) ),
[]( const Term& lhs, const Term& rhs, const TypeCheckingContext& tcc ) -> TCGen
{
auto tup = EIRToValue( lhs );
if( !tup )
co_return;
const auto& vec1 = *get< pvec >( tup->val() );
// In some cases, the tuple may not be an actual tuple value but merely
// a pattern for a tuple value, with a hole instead of its content vector.
|
| ︙ | ︙ |
Changes to bs/cir/call.cpp.
| ︙ | ︙ | |||
12 13 14 15 16 17 18 |
if( IsExternalFunc( m_func ) )
return false;
bool argsCanBeExecuted = true;
ForEachInVectorTerm( m_args, [&]( auto&& arg )
{
| | | 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
if( IsExternalFunc( m_func ) )
return false;
bool argsCanBeExecuted = true;
ForEachInVectorTerm( m_args, [&]( auto&& arg )
{
if( !IsValueConstantOrExecutable( *EIRToValue( arg ) ) )
{
argsCanBeExecuted = false;
return false;
}
return true;
} );
|
| ︙ | ︙ | |||
53 54 55 56 57 58 59 |
if( IsExternalFunc( m_func ) )
return false;
bool argsAreConstant = true;
ForEachInVectorTerm( m_args, [&]( auto&& arg )
{
| | | 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
if( IsExternalFunc( m_func ) )
return false;
bool argsAreConstant = true;
ForEachInVectorTerm( m_args, [&]( auto&& arg )
{
if( !CanValueBeEagerlyEvaluated( *EIRToValue( arg ) ) )
{
argsAreConstant = false;
return false;
}
return true;
} );
|
| ︙ | ︙ |
Changes to bs/codegen/instructions.cpp.
| ︙ | ︙ | |||
53 54 55 56 57 58 59 |
const auto& vec = *get< pvec >( call.args() );
vector< llvm::Value* > args;
args.reserve( vec.terms().size() );
for( auto&& a : vec.terms() )
{
| | | 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
const auto& vec = *get< pvec >( call.args() );
vector< llvm::Value* > args;
args.reserve( vec.terms().size() );
for( auto&& a : vec.terms() )
{
auto* parg = buildValue( inf, *EIRToValue( a ) );
if( !parg )
return nullptr;
args.emplace_back( parg );
}
return m_llvmBuilder.CreateCall( llvm::FunctionCallee( llvmCallee ), args );
|
| ︙ | ︙ | |||
110 111 112 113 114 115 116 |
auto* pAlloca = buildAlloca( inf, GetLLVMType( *type ) );
createTemporary( inf, av.index(), pAlloca );
return pAlloca;
}
llvm::Value* Module::buildInstruction( Infos& inf, const cir::Load& load )
{
| | | 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 |
auto* pAlloca = buildAlloca( inf, GetLLVMType( *type ) );
createTemporary( inf, av.index(), pAlloca );
return pAlloca;
}
llvm::Value* Module::buildInstruction( Infos& inf, const cir::Load& load )
{
auto type = LowerTypeForRuntime( inf.context, *EIRToValue( load.type() ) );
if( !type )
return nullptr;
auto* llvmType = GetLLVMType( *type );
assert( llvmType );
auto* ptrVal = buildInstruction( inf, *load.addr() );
|
| ︙ | ︙ |
Changes to bs/codegen/value.cpp.
| ︙ | ︙ | |||
28 29 30 31 32 33 34 |
{
return *b ?
llvm::ConstantInt::getTrue( GetLLVMContext() ) :
llvm::ConstantInt::getFalse( GetLLVMContext() );
}
else if( auto intVal = FromValue< APSInt >( *val ) )
{
| | | | | | | 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
{
return *b ?
llvm::ConstantInt::getTrue( GetLLVMContext() ) :
llvm::ConstantInt::getFalse( GetLLVMContext() );
}
else if( auto intVal = FromValue< APSInt >( *val ) )
{
return llvm::ConstantInt::get( GetLLVMType( *EIRToValue( val->type() ) ),
*FromValue< APSInt >( *val ) );
}
else if( auto ptType = FromValue< PointerType >( *EIRToValue( val->type() ) ) )
{
return buildConstantPointer( inf, *ptType, *val );
}
else if( auto recType = FromValue< RecordType >( *EIRToValue( val->type() ) ) )
{
llvm::SmallVector< llvm::Constant*, 8 > members;
assert( holds_alternative< pvec >( val->val() ) );
bool success = true;
ForEachInVectorTerm( val->val(), [&]( auto&& t )
{
auto* pMemberVal = buildConstant( inf, *EIRToValue( t ) );
if( !pMemberVal )
{
success = false;
return false;
}
members.push_back( pMemberVal );
return true;
} );
if( !success )
return nullptr;
return llvm::ConstantStruct::get( static_cast< llvm::StructType* >
( GetLLVMType( *EIRToValue( val->type() ) ) ), members );
}
DiagnosticsManager::GetInstance().emitErrorMessage(
v.locationId(), "constants with compile time types are not supported.", 0 );
return nullptr;
}
|
| ︙ | ︙ | |||
98 99 100 101 102 103 104 |
else
pGlob = it->second;
return pGlob;
}
return llvm::ConstantPointerNull::get( static_cast< llvm::PointerType* >
| | | 98 99 100 101 102 103 104 105 106 |
else
pGlob = it->second;
return pGlob;
}
return llvm::ConstantPointerNull::get( static_cast< llvm::PointerType* >
( GetLLVMType( *EIRToValue( v.type() ) ) ) );
}
|
Changes to bs/compile/compiler.cpp.
| ︙ | ︙ | |||
56 57 58 59 60 61 62 |
llvm::InitializeAllTargetMCs();
llvm::InitializeAllAsmPrinters();
llvm::InitializeAllAsmParsers();
}
uint32_t Compiler::execute( const string& filename )
{
| | | | 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 |
llvm::InitializeAllTargetMCs();
llvm::InitializeAllAsmPrinters();
llvm::InitializeAllAsmParsers();
}
uint32_t Compiler::execute( const string& filename )
{
auto locVarsIdentity = AppendToVectorTerm( builtins::RootG0Identity(), TSID( locvars ) );
m_pEnv->addVisibilityRule( builtins::RootG0Identity(), locVarsIdentity );
auto result = LoadAndExecuteFile( m_pEnv, filename, locVarsIdentity, GetValueType< uint32_t >(), ToValue< uint32_t >( 1 ) );
if( DiagnosticsManager::GetInstance().errorsWereEmitted() )
return 1;
if( !result )
{
|
| ︙ | ︙ |
Changes to bs/eir/term.h.
| ︙ | ︙ | |||
56 57 58 59 60 61 62 |
LocationId,
string,
StringId,
Delimiter,
Hole,
AnyTerm,
VecOfLength,
| < < | > > > | 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 |
LocationId,
string,
StringId,
Delimiter,
Hole,
AnyTerm,
VecOfLength,
pvec,
// Representation for ct_int, the compile time only integers
// with "unlimited" precision
BigInt,
// Compile time representation for normal, fixed size integers
APSInt,
ptr< void >,
void*
>;
extern bool operator==( const Term& lhs, const Term& rhs );
extern bool operator!=( const Term& lhs, const Term& rhs );
struct STerm
{
|
| ︙ | ︙ |
Changes to bs/eir/value.cpp.
| ︙ | ︙ | |||
56 57 58 59 60 61 62 |
}
return VEC( TSID( value ), TSID( computed ), v.type(),
TERM( static_pointer_cast< void >( v.cir() ) ),
static_cast< LocationId >( v.locationId() ) );
}
| | | 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 |
}
return VEC( TSID( value ), TSID( computed ), v.type(),
TERM( static_pointer_cast< void >( v.cir() ) ),
static_cast< LocationId >( v.locationId() ) );
}
optional< Value > EIRToValue( const Term& t )
{
// Special case for type's type
auto typedecomp = Decompose( t,
Vec(
Lit( "type"_sid ),
Val< uint32_t >(),
Val< LocationId >()
|
| ︙ | ︙ |
Changes to bs/eir/value.h.
| ︙ | ︙ | |||
10 11 12 13 14 15 16 |
{
class Value;
class ValuePattern;
extern const Term& TypeType();
extern Term ValueToEIR( const Value& v );
| | | 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
{
class Value;
class ValuePattern;
extern const Term& TypeType();
extern Term ValueToEIR( const Value& v );
extern optional< Value > EIRToValue( const Term& t );
extern Term ValueToEIR( const ValuePattern& v );
extern optional< ValuePattern > ValuePatternFromEIR( const Term& t );
class Value
{
public:
|
| ︙ | ︙ |
Changes to bs/execute/vm.cpp.
| ︙ | ︙ | |||
76 77 78 79 80 81 82 |
bool poisoned = false;
const auto& vec = *get< pvec >( call.args() );
if( IsBuiltinFunc( func ) )
{
auto newVec = vec.transform( [&]( auto&& x ) -> optional< Term >
{
| | | 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 |
bool poisoned = false;
const auto& vec = *get< pvec >( call.args() );
if( IsBuiltinFunc( func ) )
{
auto newVec = vec.transform( [&]( auto&& x ) -> optional< Term >
{
auto val = EIRToValue( x );
assert( val );
auto newVal = Evaluate( *val, *this );
if( newVal.isPoison() )
poisoned = true;
if( !newVal.isConstant() )
|
| ︙ | ︙ | |||
110 111 112 113 114 115 116 |
if( !pFunc || !pFunc->isValid() )
return PoisonValue();
auto savedStackSize = m_stack.size();
for( auto&& a : vec.terms() )
{
| | | 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 |
if( !pFunc || !pFunc->isValid() )
return PoisonValue();
auto savedStackSize = m_stack.size();
for( auto&& a : vec.terms() )
{
auto val = EIRToValue( a );
assert( val );
auto newVal = Evaluate( *val, *this );
if( newVal.isPoison() )
{
m_stack.resize( savedStackSize );
return PoisonValue();
|
| ︙ | ︙ | |||
180 181 182 183 184 185 186 |
if( !baseAddr || baseAddr->isPoison() )
return nullopt;
auto pvoid = FromValue< Term* >( *baseAddr );
if( !pvoid )
return nullopt;
| | | 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 |
if( !baseAddr || baseAddr->isPoison() )
return nullopt;
auto pvoid = FromValue< Term* >( *baseAddr );
if( !pvoid )
return nullopt;
auto val = EIRToValue( *static_cast< Term* >( pvoid ) );
if( !val )
return nullopt;
// We only support tuples now. In the future, Select will also be used to
// add an offset to another pointer.
// Everything else (structs, classes, containers, etc.) should build on top
// of those two fundamental types.
|
| ︙ | ︙ | |||
214 215 216 217 218 219 220 |
optional< Value > VM::execute( const cir::GetTemporary& gt )
{
auto stackIndex = gt.index() + m_currentFrameStart;
if( stackIndex >= m_stack.size() )
return nullopt;
| | | 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 |
optional< Value > VM::execute( const cir::GetTemporary& gt )
{
auto stackIndex = gt.index() + m_currentFrameStart;
if( stackIndex >= m_stack.size() )
return nullopt;
return EIRToValue( *m_stack[stackIndex] );
}
optional< Value > VM::execute( const cir::AllocVar& av )
{
auto stackIndex = m_currentFrameStart + av.index();
if( m_stack.size() <= stackIndex )
|
| ︙ | ︙ | |||
238 239 240 241 242 243 244 |
if( !baseAddr || baseAddr->isPoison() )
return nullopt;
auto addr = FromValue< Term* >( *baseAddr );
if( !addr )
return nullopt;
| | | 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 |
if( !baseAddr || baseAddr->isPoison() )
return nullopt;
auto addr = FromValue< Term* >( *baseAddr );
if( !addr )
return nullopt;
return EIRToValue( *addr );
}
optional< Value > VM::execute( const cir::Store& s )
{
auto baseAddr = execute( *s.addr() );
if( !baseAddr || baseAddr->isPoison() )
return nullopt;
|
| ︙ | ︙ | |||
367 368 369 370 371 372 373 |
return make_shared< Term >( TSID( UNINITIALIZED ) );
auto tupContent = make_shared< Vector >();
tupContent->reserve( TupleTypeSize( type ) );
ForEachInTupleType( type, [&]( auto&& t )
{
| | | 367 368 369 370 371 372 373 374 375 376 377 378 379 |
return make_shared< Term >( TSID( UNINITIALIZED ) );
auto tupContent = make_shared< Vector >();
tupContent->reserve( TupleTypeSize( type ) );
ForEachInTupleType( type, [&]( auto&& t )
{
tupContent->append( *BuildUninitializedValue( *EIRToValue( t ) ) );
return true;
} );
return make_shared< Term >( ValueToEIR( Value( ValueToEIR( type ), TERM( move( tupContent ) ) ) ) );
}
|
Changes to bs/g0api/cgapi/func.cpp.
| ︙ | ︙ | |||
8 9 10 11 12 13 14 |
void SetupApiCGFunc( Env& e )
{
weak_ptr< Env > pEnv = e.shared_from_this();
RegisterBuiltinFunc< bool ( ptr< codegen::Module >, CustomPattern< Value, FuncPattern > ) >( e, "CGGenerateFunction"_sid,
[pEnv]( const ptr< codegen::Module >& module, const Value& f )
{
| | | | | | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
void SetupApiCGFunc( Env& e )
{
weak_ptr< Env > pEnv = e.shared_from_this();
RegisterBuiltinFunc< bool ( ptr< codegen::Module >, CustomPattern< Value, FuncPattern > ) >( e, "CGGenerateFunction"_sid,
[pEnv]( const ptr< codegen::Module >& module, const Value& f )
{
if( !IsFuncType( *EIRToValue( f.type() ) ) )
return false;
sema::Context c( pEnv.lock(), RootG0Identity() );
DiagnosticsContext dc( 0, true );
VerbosityContext vc( Verbosity::Normal, true );
auto func = CompileFunc( c, f );
if( func.isPoison() || DiagnosticsManager::GetInstance().errorsWereEmitted() )
return false;
auto llvmFunc = module->getOrCreateFunc( c, *FromValue< Func >( func ) );
return !!llvmFunc;
} );
RegisterBuiltinFunc< bool ( ptr< codegen::Module >, CustomPattern< Value, FuncPattern >, string ) >( e, "CGGenerateFunction"_sid,
[pEnv]( const ptr< codegen::Module >& module, const Value& f, const string& name )
{
if( !IsFuncType( *EIRToValue( f.type() ) ) )
return false;
sema::Context c( pEnv.lock(), RootG0Identity() );
DiagnosticsContext dc( 0, true );
VerbosityContext vc( Verbosity::Normal, true );
auto func = CompileFunc( c, f );
if( func.isPoison() || DiagnosticsManager::GetInstance().errorsWereEmitted() )
return false;
auto llvmFunc = module->getOrCreateFunc( c, *FromValue< Func >( func ), name, llvm::Function::ExternalLinkage );
return !!llvmFunc;
} );
}
}
|
Changes to bs/g0api/compiler.cpp.
| ︙ | ︙ | |||
129 130 131 132 133 134 135 |
{
DiagnosticsManager::GetInstance().emitErrorMessage( v.locationId(),
"CreateConstant: the expression doesn't evaluate to a constant." );
return;
}
pEnv.lock()->storeValue(
| | | 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 |
{
DiagnosticsManager::GetInstance().emitErrorMessage( v.locationId(),
"CreateConstant: the expression doesn't evaluate to a constant." );
return;
}
pEnv.lock()->storeValue(
AppendToVectorTerm( RootG0Identity(), StringId( name.c_str() ) ),
ANYTERM( _ ), ValueToEIR( v ) );
} );
RegisterBuiltinFunc< Intrinsic< uint32_t ( string ) > >( e, "#Include"_sid,
[pEnv]( auto&& c, const Value& fnameval ) -> Value
{
auto filename = *FromValue< string >( fnameval );
|
| ︙ | ︙ | |||
155 156 157 158 159 160 161 |
} );
RegisterBuiltinFunc< uint32_t ( string ) >( e, "ExecuteFile"_sid,
[pEnv]( const string& filename ) -> Value
{
// For now generate an unique identity for the file to execute. Later we might want to
// pass an identity as parameters as a wrapped term.
| | | | 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 |
} );
RegisterBuiltinFunc< uint32_t ( string ) >( e, "ExecuteFile"_sid,
[pEnv]( const string& filename ) -> Value
{
// For now generate an unique identity for the file to execute. Later we might want to
// pass an identity as parameters as a wrapped term.
auto identity = AppendToVectorTerm( RootG0Identity(),
TERM( StringId( Env::NewUniqueId() ) ) );
auto locVarsIdentity = AppendToVectorTerm( identity, TSID( locvars ) );
auto env = pEnv.lock();
env->addVisibilityRule( builtins::RootG0Identity(), identity );
env->addVisibilityRule( identity, locVarsIdentity );
auto result = Compiler::LoadAndExecuteFile( env, filename, locVarsIdentity,
GetValueType< uint32_t >(), ToValue< uint32_t >( 0 ) );
if( !result )
return ToValue< uint32_t >( 0 );
|
| ︙ | ︙ | |||
201 202 203 204 205 206 207 |
DiagnosticsManager::GetInstance().emitErrorMessage( params.locationId(),
"#CompileFileToFunction: template parameter lists are not supported.", 0 );
return PoisonValue();
}
// TODO at some point we'll want to pass the base identity to use as a param but
// let's wait and see how the module and namespace stuff pans out first
| | | | | 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 |
DiagnosticsManager::GetInstance().emitErrorMessage( params.locationId(),
"#CompileFileToFunction: template parameter lists are not supported.", 0 );
return PoisonValue();
}
// TODO at some point we'll want to pass the base identity to use as a param but
// let's wait and see how the module and namespace stuff pans out first
sema::Context localC( pEnv.lock(), builtins::RootG0Identity(), ValueToEIR( rt ) );
auto ftype = BuildFuncType( localC, rt, params );
if( !ftype )
return PoisonValue();
auto funcIdentity = AppendToVectorTerm( builtins::RootG0Identity(),
TERM( StringId( Env::NewUniqueId() ) ) );
c.env()->addVisibilityRule( builtins::RootG0Identity(), funcIdentity );
auto locVarsIdentity = AppendToVectorTerm( funcIdentity, TSID( locvars ) );
c.env()->addVisibilityRule( funcIdentity, locVarsIdentity );
auto func = BuildFunc( localC, *ftype, funcIdentity, params, nullptr, c );
const auto& pFuncCIR = func.cir();
|
| ︙ | ︙ |
Added bs/g0api/extensibility/extensibility.h.
> > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
#ifndef GOOSE_G0_API_EXTENSIBILITY_H
#define GOOSE_G0_API_EXTENSIBILITY_H
namespace goose::g0api
{
extern void SetupTermExtensibilityFuncs( Env& e );
static inline void SetupApiExtensibility( Env& e )
{
SetupTermExtensibilityFuncs( e );
}
}
#endif
|
Added bs/g0api/extensibility/term.cpp.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
#include "g0api/g0api.h"
#include "eir/eir.h"
#include "parse/parse.h"
#include "builtins/helpers.h"
using namespace goose;
using namespace goose::parse;
using namespace goose::builtins;
namespace goose::g0api
{
void SetupTermExtensibilityFuncs( Env& e )
{
// Constants.
DefineConstant( e, "DelimiterOpenParen"_sid, ValueToEIR( ToValue( BigInt::FromU32( static_cast< uint32_t >( Delimiter::OpenParen ) ) ) ) );
DefineConstant( e, "DelimiterOpenBrace"_sid, ValueToEIR( ToValue( BigInt::FromU32( static_cast< uint32_t >( Delimiter::OpenBrace ) ) ) ) );
DefineConstant( e, "DelimiterOpenBracket"_sid, ValueToEIR( ToValue( BigInt::FromU32( static_cast< uint32_t >( Delimiter::OpenBracket ) ) ) ) );
DefineConstant( e, "DelimiterCloseParen"_sid, ValueToEIR( ToValue( BigInt::FromU32( static_cast< uint32_t >( Delimiter::CloseParen ) ) ) ) );
DefineConstant( e, "DelimiterCloseBrace"_sid, ValueToEIR( ToValue( BigInt::FromU32( static_cast< uint32_t >( Delimiter::CloseBrace ) ) ) ) );
DefineConstant( e, "DelimiterCloseBracket"_sid, ValueToEIR( ToValue( BigInt::FromU32( static_cast< uint32_t >( Delimiter::CloseBracket ) ) ) ) );
// These must match the order of the Term variant.
DefineConstant( e, "TermTypeUInt32"_sid, ValueToEIR( ToValue( BigInt::FromU32( 0 ) ) ) );
DefineConstant( e, "TermTypeLocationId"_sid, ValueToEIR( ToValue( BigInt::FromU32( 1 ) ) ) );
DefineConstant( e, "TermTypeString"_sid, ValueToEIR( ToValue( BigInt::FromU32( 2 ) ) ) );
DefineConstant( e, "TermTypeStringId"_sid, ValueToEIR( ToValue( BigInt::FromU32( 3 ) ) ) );
DefineConstant( e, "TermTypeDelimiter"_sid, ValueToEIR( ToValue( BigInt::FromU32( 4 ) ) ) );
DefineConstant( e, "TermTypeHole"_sid, ValueToEIR( ToValue( BigInt::FromU32( 5 ) ) ) );
DefineConstant( e, "TermTypeAnyTerm"_sid, ValueToEIR( ToValue( BigInt::FromU32( 6 ) ) ) );
DefineConstant( e, "TermTypeVecOfLength"_sid, ValueToEIR( ToValue( BigInt::FromU32( 7 ) ) ) );
DefineConstant( e, "TermTypeVec"_sid, ValueToEIR( ToValue( BigInt::FromU32( 8 ) ) ) );
DefineConstant( e, "TermTypeBigInt"_sid, ValueToEIR( ToValue( BigInt::FromU32( 9 ) ) ) );
DefineConstant( e, "TermTypeFixedInt"_sid, ValueToEIR( ToValue( BigInt::FromU32( 10 ) ) ) );
DefineConstant( e, "TermTypeInternal "_sid, ValueToEIR( ToValue( BigInt::FromU32( 11 ) ) ) );
}
}
|
Changes to bs/g0api/g0api.h.
| ︙ | ︙ | |||
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
{
using namespace sema;
using namespace builtins;
}
#include "support/support.h"
#include "cgapi/cgapi.h"
namespace goose::g0api
{
extern void SetupApiString( Env& e );
extern void SetupApiCompiler( Env& e );
static inline void SetupG0Api( Env& e )
{
SetupApiString( e );
SetupApiCompiler( e );
SetupApiSupport( e );
SetupApiCodeGen( e );
}
}
#endif
| > > | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
{
using namespace sema;
using namespace builtins;
}
#include "support/support.h"
#include "cgapi/cgapi.h"
#include "extensibility/extensibility.h"
namespace goose::g0api
{
extern void SetupApiString( Env& e );
extern void SetupApiCompiler( Env& e );
static inline void SetupG0Api( Env& e )
{
SetupApiString( e );
SetupApiCompiler( e );
SetupApiSupport( e );
SetupApiCodeGen( e );
SetupApiExtensibility( e );
}
}
#endif
|
Changes to bs/g0api/meson.build.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
goose_g0api = library( 'goose-g0api',
'string.cpp',
'compiler.cpp',
'support/cast.cpp',
'support/verification.cpp',
'cgapi/module.cpp',
'cgapi/mangle.cpp',
'cgapi/func.cpp',
'cgapi/linker.cpp',
include_directories: bsinc,
dependencies: fmt_dep
)
| > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
goose_g0api = library( 'goose-g0api',
'string.cpp',
'compiler.cpp',
'support/cast.cpp',
'support/verification.cpp',
'cgapi/module.cpp',
'cgapi/mangle.cpp',
'cgapi/func.cpp',
'cgapi/linker.cpp',
'extensibility/term.cpp',
include_directories: bsinc,
dependencies: fmt_dep
)
|
Changes to bs/parse/func.cpp.
| ︙ | ︙ | |||
63 64 65 66 67 68 69 |
return true;
}
bool Parser::parseFunctionDeclaration( const Value& decl, const Value& paramsDecl )
{
auto d = FromValue< Decl >( decl );
| | | 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 |
return true;
}
bool Parser::parseFunctionDeclaration( const Value& decl, const Value& paramsDecl )
{
auto d = FromValue< Decl >( decl );
if( !parseFuncType( *EIRToValue( d->type() ), paramsDecl ) )
return false;
const auto& c = context();
auto funcIdentity = TakeVectorTerm( c.identity(), VecSize( c.identity() ) - 1 );
get< pvec >( funcIdentity )->terms().back() = TERM( d->name() );
|
| ︙ | ︙ |
Changes to bs/parse/overload.cpp.
| ︙ | ︙ | |||
83 84 85 86 87 88 89 |
Val< ptr< void > >(),
SubTerm()
)
);
assert( decomp );
auto&& [pOvlSet, callee] = *decomp;
| | | 83 84 85 86 87 88 89 90 91 92 |
Val< ptr< void > >(),
SubTerm()
)
);
assert( decomp );
auto&& [pOvlSet, callee] = *decomp;
return Overload( static_pointer_cast< sema::OverloadSet >( pOvlSet ), *EIRToValue( *Unquote( callee ) ) );
}
}
|
Changes to bs/parse/parser.cpp.
| ︙ | ︙ | |||
229 230 231 232 233 234 235 |
return parsePrefix( strid, prec );
}
bool Parser::parsePrefix( const pvec& vec, uint32_t prec )
{
auto t = *m_resolver->lookAhead();
| | | 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 |
return parsePrefix( strid, prec );
}
bool Parser::parsePrefix( const pvec& vec, uint32_t prec )
{
auto t = *m_resolver->lookAhead();
auto val = EIRToValue( t.first );
if( !val )
return false;
if( val->isPoison() )
DiagnosticsManager::GetInstance().setCurrentVerbosityLevel( Verbosity::Silent );
// If the term is a prefix rule value, invoke its parsePrefix() function.
|
| ︙ | ︙ | |||
254 255 256 257 258 259 260 |
m_resolver->consume();
return ( *rule )->parsePrefix( *this, t.second, prec );
}
optional< uint32_t > Parser::getPrecedence( const Term& t, const pvec& vec )
{
| | | 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 |
m_resolver->consume();
return ( *rule )->parsePrefix( *this, t.second, prec );
}
optional< uint32_t > Parser::getPrecedence( const Term& t, const pvec& vec )
{
auto val = EIRToValue( t );
if( !val )
return nullopt;
if( val->type() == GetValueType< ptr< OverloadSet > >() )
{
if( !peekLastValue() )
return nullopt;
|
| ︙ | ︙ | |||
284 285 286 287 288 289 290 |
return ( *rule )->getPrecedence( *this );
}
bool Parser::parseInfix( const pvec& vec, uint32_t prec )
{
auto t = *m_resolver->lookAhead();
| | | 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 |
return ( *rule )->getPrecedence( *this );
}
bool Parser::parseInfix( const pvec& vec, uint32_t prec )
{
auto t = *m_resolver->lookAhead();
auto val = EIRToValue( t.first );
if( !val )
return false;
if( val->isPoison() )
DiagnosticsManager::GetInstance().setCurrentVerbosityLevel( Verbosity::Silent );
if( val->type() == GetValueType< ptr< OverloadSet > >() )
|
| ︙ | ︙ |
Changes to bs/parse/tfunc.cpp.
| ︙ | ︙ | |||
42 43 44 45 46 47 48 |
return true;
}
bool Parser::parseTemplateFunctionTNamedDecl( const Value& tnamedDecl, const Value& paramsDecl )
{
auto d = FromValue< TNamedDecl >( tnamedDecl );
| | | 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
return true;
}
bool Parser::parseTemplateFunctionTNamedDecl( const Value& tnamedDecl, const Value& paramsDecl )
{
auto d = FromValue< TNamedDecl >( tnamedDecl );
if( !parseTFuncType( *EIRToValue( d->type() ), paramsDecl ) )
return false;
const auto& c = context();
auto tfuncIdentity = TakeVectorTerm( c.identity(), VecSize( c.identity() ) - 1 );
get< pvec >( tfuncIdentity )->terms().back() = TERM( d->name() );
|
| ︙ | ︙ |
Changes to bs/sema/lower.cpp.
| ︙ | ︙ | |||
18 19 20 21 22 23 24 |
return nullopt;
return result;
}
optional< Value > LowerConstantForRuntime( const Context& c, const Value& val )
{
| | | | 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
return nullopt;
return result;
}
optional< Value > LowerConstantForRuntime( const Context& c, const Value& val )
{
if( val.type() == GetValueType< bool >() || IsRuntimeType( *EIRToValue( val.type() ) ) )
return val;
DiagnosticsContext dc( val.locationId(), "When invoking LowerConstantForRuntime." );
auto result = InvokeOverloadSet( c, c.env()->extLowerConstantForRuntime(), AppendToTuple( EmptyTuple(), val ) );
if( result.isPoison() || !IsRuntimeType( *EIRToValue( result.type() ) ) )
return nullopt;
return result;
}
optional< Value > LowerTypeForVerification( const Context& c, const Value& type )
{
|
| ︙ | ︙ |
Changes to bs/verify/call.cpp.
| ︙ | ︙ | |||
28 29 30 31 32 33 34 |
// Inject the arguments in the context.
// They will be picked up by getVars instructions when refered to
// by the verification conditions.
uint32_t index = 0;
ForEachInVectorTerm( instr.args(), [&]( auto&& t )
{
| | | 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
// Inject the arguments in the context.
// They will be picked up by getVars instructions when refered to
// by the verification conditions.
uint32_t index = 0;
ForEachInVectorTerm( instr.args(), [&]( auto&& t )
{
auto arg = *EIRToValue( t );
if( auto zv = BuildZ3ExprFromValue( b, arg ) )
cb.setVar( index++, move( *zv ) );
return true;
} );
|
| ︙ | ︙ | |||
77 78 79 80 81 82 83 |
if( retExpr )
cb.setPlaceholder( "@result"_sid, retExpr->expr );
// Check preconditions.
const auto& preConds = fvi->preConditions();
ForEachInVectorTerm( preConds, [&]( auto&& t )
{
| | | | 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 |
if( retExpr )
cb.setPlaceholder( "@result"_sid, retExpr->expr );
// Check preconditions.
const auto& preConds = fvi->preConditions();
ForEachInVectorTerm( preConds, [&]( auto&& t )
{
auto val = *EIRToValue( t );
if( auto zv = BuildZ3ExprFromValue( cb, val ) )
{
DiagnosticsContext dc( instr.func().locationId(), "At this call." );
b.checkAssertion( zv->expr, val.locationId() );
}
return true;
} );
// Add the return type's predicates as assumptions.
ForEachPredicate( cb, ft.returnType(), retExpr->expr, [&]( auto&& z3expr, auto locId )
{
b.assume( z3expr );
} );
// Add postconditions as assumptions.
const auto& postConds = fvi->postConditions();
ForEachInVectorTerm( postConds, [&]( auto&& t )
{
if( auto zv = BuildZ3ExprFromValue( cb, *EIRToValue( t ) ) )
b.assume( zv->expr );
return true;
} );
return retExpr;
}
}
|
Changes to bs/verify/comptime.cpp.
| ︙ | ︙ | |||
94 95 96 97 98 99 100 |
// by the verification conditions.
uint32_t index = 0;
bool eagerEvalFailed = false;
ForEachInVectorTerm( instr.args(), [&]( auto&& t )
{
| | | 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 |
// by the verification conditions.
uint32_t index = 0;
bool eagerEvalFailed = false;
ForEachInVectorTerm( instr.args(), [&]( auto&& t )
{
auto arg = EIRToValue( t );
if( !arg->isConstant() )
{
execute::VM vm;
arg = execute::Evaluate( *arg, vm );
if( !arg->isConstant() )
|
| ︙ | ︙ | |||
158 159 160 161 162 163 164 |
return true;
} );
// Check preconditions.
const auto& preConds = fvi->preConditions();
ForEachInVectorTerm( preConds, [&]( auto&& t )
{
| | | 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 |
return true;
} );
// Check preconditions.
const auto& preConds = fvi->preConditions();
ForEachInVectorTerm( preConds, [&]( auto&& t )
{
auto val = *EIRToValue( t );
if( auto zv = BuildZ3ExprFromValue( b, val ) )
{
DiagnosticsContext dc( instr.func().locationId(), "At this compilation-time call." );
b.checkAssertion( zv->expr, val.locationId() );
}
return true;
} );
return !b.hasCheckFailed();
}
}
|
Changes to bs/verify/condition.cpp.
| ︙ | ︙ | |||
47 48 49 50 51 52 53 |
bool Condition::addConditionsList( const pvec& assList )
{
bool success = true;
ForEachInVectorTerm( assList, [&]( auto&& t )
{
| | | 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
bool Condition::addConditionsList( const pvec& assList )
{
bool success = true;
ForEachInVectorTerm( assList, [&]( auto&& t )
{
auto val = *EIRToValue( t );
if( val.isPoison() )
{
success = false;
return false;
}
if( val.type() != GetValueType< bool >() )
|
| ︙ | ︙ |
Changes to bs/verify/func.cpp.
| ︙ | ︙ | |||
94 95 96 97 98 99 100 |
// Add assumptions of the function's requirements
const auto& reqs = m_func->type().verifInfos()->preConditions();
ForEachInVectorTerm( reqs, [&]( auto&& t )
{
// Don't do any error handling here, it should already have been taken care of
// by the condition verifier.
| | | 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 |
// Add assumptions of the function's requirements
const auto& reqs = m_func->type().verifInfos()->preConditions();
ForEachInVectorTerm( reqs, [&]( auto&& t )
{
// Don't do any error handling here, it should already have been taken care of
// by the condition verifier.
if( auto zv = BuildZ3ExprFromValue( m_builder, *EIRToValue( t ) ) )
m_builder.assume( zv->expr );
return true;
} );
}
bool result = buildZ3Expressions( *m_cfg->entryBB(), nullptr );
|
| ︙ | ︙ |
Changes to bs/verify/helpers.inl.
1 2 3 4 5 6 7 8 9 10 |
#ifndef GOOSE_HELPERS_INL
#define GOOSE_HELPERS_INL
#include "builtins/helpers.h"
namespace goose::verify
{
template< typename F >
void ForEachPredicate( Builder& b, const Term& t, const z3::expr& valExpr, F&& func )
{
| | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
#ifndef GOOSE_HELPERS_INL
#define GOOSE_HELPERS_INL
#include "builtins/helpers.h"
namespace goose::verify
{
template< typename F >
void ForEachPredicate( Builder& b, const Term& t, const z3::expr& valExpr, F&& func )
{
auto type = *EIRToValue( t );
auto optTypePreds = builtins::GetTypePredicates( type );
if( !optTypePreds || !*optTypePreds )
return;
auto& tp = **optTypePreds;
const auto* prevValPH = b.retrievePlaceholder( "@val"_sid );
b.setPlaceholder( "@val"_sid, valExpr );
ForEachInVectorTerm( tp.m_predicates, [&]( auto&& p )
{
auto predVal = *EIRToValue( p );
if( auto zv = BuildZ3ExprFromValue( b, predVal ) )
func( zv->expr, predVal.locationId() );
return true;
} );
if( prevValPH )
|
| ︙ | ︙ |
Changes to bs/verify/storage.cpp.
| ︙ | ︙ | |||
44 45 46 47 48 49 50 |
if( !tinfo )
return nullopt;
// The only aggregate type that we handle for now are tuples.
// TODO: arrays
auto elemType = GetTupleTypeElement( val->type, s.memberIndex() );
auto elemExpr = tinfo->proj( val->expr, s.memberIndex() );
| | | 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
if( !tinfo )
return nullopt;
// The only aggregate type that we handle for now are tuples.
// TODO: arrays
auto elemType = GetTupleTypeElement( val->type, s.memberIndex() );
auto elemExpr = tinfo->proj( val->expr, s.memberIndex() );
return Z3Val{ move( elemExpr ), *EIRToValue( elemType ) };
}
using SelectPath = llvm::SmallVector< uint32_t, 8 >;
optional< z3::expr > ModifyAggregate( Builder& b, const Z3Val& aggregate, const SelectPath& path, uint32_t index, Z3Val&& valToStore )
{
auto tinfo = TypeCache::GetInstance()->getTypeInfo( b.context(), ValueToEIR( aggregate.type ) );
if( !tinfo )
|
| ︙ | ︙ | |||
77 78 79 80 81 82 83 |
if( i == elemIndex )
{
// If we didn't reach the end of the path yet, recurse.
// Otherwise, it means we finally reached the nested member that we wanted to modify,
// so push the new value.
if( index > 0 )
{
| | | 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 |
if( i == elemIndex )
{
// If we didn't reach the end of the path yet, recurse.
// Otherwise, it means we finally reached the nested member that we wanted to modify,
// so push the new value.
if( index > 0 )
{
auto newElem = ModifyAggregate( b, Z3Val{ move( elemExpr ), *EIRToValue( elemType ) }, path, --index, move( valToStore ) );
if( !newElem )
return nullopt;
args.push_back( move( *newElem ) );
}
else
args.push_back( valToStore.expr );
|
| ︙ | ︙ |
Changes to bs/verify/terminator.cpp.
| ︙ | ︙ | |||
43 44 45 46 47 48 49 |
const auto& postConds = m_func->type().verifInfos()->postConditions();
bool success = true;
ForEachInVectorTerm( postConds, [&]( auto&& t )
{
// Don't do any error handling here, it should already have been taken care of
// by the condition verifier.
| | | 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
const auto& postConds = m_func->type().verifInfos()->postConditions();
bool success = true;
ForEachInVectorTerm( postConds, [&]( auto&& t )
{
// Don't do any error handling here, it should already have been taken care of
// by the condition verifier.
auto cond = *EIRToValue( t );
if( auto zv = BuildZ3ExprFromValue( cb, cond ) )
{
bool succ = false;
// TODO: we don't have a useful location here in the case of a return from a void func.
// we'll have to add it to the ret statement. The case can only happen when checking post conditions
|
| ︙ | ︙ |
Changes to bs/verify/type.cpp.
| ︙ | ︙ | |||
98 99 100 101 102 103 104 |
}
return nullopt;
}
optional< TypeInfo > TypeCache::CreateTypeInfo( const sema::Context& c, const Term& type )
{
| | | 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 |
}
return nullopt;
}
optional< TypeInfo > TypeCache::CreateTypeInfo( const sema::Context& c, const Term& type )
{
auto typeVal = *EIRToValue( type );
auto tinfo = CreateTypeInfoForBasicType( c, typeVal );
if( tinfo )
return tinfo;
// The only non aggregate type that we handle at the moment are tuples.
// Other higher level types such as structs and classes need to be lowered
|
| ︙ | ︙ |
Changes to bs/verify/value.cpp.
| ︙ | ︙ | |||
13 14 15 16 17 18 19 |
return nullopt;
auto tinfo = TypeCache::GetInstance()->getTypeInfo( b.context(), loweredVal->type() );
if( !tinfo )
return nullopt;
auto zexpr = tinfo->build( b, *loweredVal );
| | | | 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
return nullopt;
auto tinfo = TypeCache::GetInstance()->getTypeInfo( b.context(), loweredVal->type() );
if( !tinfo )
return nullopt;
auto zexpr = tinfo->build( b, *loweredVal );
return Z3Val { move( zexpr ), *EIRToValue( val.type() ) };
}
optional< Z3Val > BuildZ3ConstantFromType( Builder& b, const Value& type, const string& name )
{
auto tinfo = TypeCache::GetInstance()->getTypeInfo( b.context(), ValueToEIR( type ) );
if( !tinfo )
return nullopt;
assert( tinfo->sort );
return Z3Val { GetZ3Context().constant( name.c_str(), *tinfo->sort ), type };
}
optional< Z3Val > BuildZ3ConstantFromType( Builder& b, const Term& type, const string& name )
{
auto tinfo = TypeCache::GetInstance()->getTypeInfo( b.context(), type );
if( !tinfo )
return nullopt;
assert( tinfo->sort );
return Z3Val { GetZ3Context().constant( name.c_str(), *tinfo->sort ), *EIRToValue( type ) };
}
z3::expr GetAsBitVec( const z3::expr& expr, const Value& type )
{
if( expr.is_bv() )
return expr;
|
| ︙ | ︙ | |||
124 125 126 127 128 129 130 |
return nullopt;
auto rhs = BuildZ3ExprFromValue( b, instr.rhs() );
if( !rhs )
return nullopt;
if( lhs->expr.get_sort().sort_kind() == rhs->expr.get_sort().sort_kind() )
| | | | | 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 |
return nullopt;
auto rhs = BuildZ3ExprFromValue( b, instr.rhs() );
if( !rhs )
return nullopt;
if( lhs->expr.get_sort().sort_kind() == rhs->expr.get_sort().sort_kind() )
return Z3Val{ func( lhs->expr, rhs->expr, lhs->type ), *EIRToValue( GetValueType< bool >() ) };
// If we are trying to do an operation on a mix of bitvec and int,
// convert the int to a bitvec first.
if( lhs->expr.is_bv() )
{
assert( rhs->expr.is_int() );
return Z3Val{ func( lhs->expr, GetAsBitVec( *rhs ), lhs->type ), *EIRToValue( GetValueType< bool >() ) };
}
else
{
assert( lhs->expr.is_int() );
return Z3Val{ func( GetAsBitVec( *lhs ), rhs->expr, lhs->type ), *EIRToValue( GetValueType< bool >() ) };
}
return nullopt;
}
template< typename T >
optional< Z3Val > BuildZ3Op( Builder& b, const T& instr )
|
| ︙ | ︙ | |||
402 403 404 405 406 407 408 |
return nullopt;
}
optional< Z3Val > BuildZ3Op( Builder& b, const Placeholder& instr )
{
const auto* expr = b.retrievePlaceholder( instr.name() );
if( expr )
| | | 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 |
return nullopt;
}
optional< Z3Val > BuildZ3Op( Builder& b, const Placeholder& instr )
{
const auto* expr = b.retrievePlaceholder( instr.name() );
if( expr )
return Z3Val{ *expr, *EIRToValue( instr.type() ) };
return BuildZ3ConstantFromType( b, instr.type(), format( "p{}", instr.name() ) );
}
optional< Z3Val > BuildZ3Op( Builder& b, const cir::Instruction& instr )
{
return visit( [&]( auto&& e )
|
| ︙ | ︙ |