Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
| Comment: | Refactored some template rules and type checking rules to avoid calling BuildTemplateSignature from inside type checking rules |
|---|---|
| Downloads: | Tarball | ZIP archive |
| Timelines: | family | ancestors | descendants | both | trunk |
| Files: | files | file ages | folders |
| SHA3-256: |
64224a915fbf330ec7d4fa6901c36852 |
| User & Date: | zlodo 2022-07-04 17:45:47.410 |
Context
|
2022-07-04
| ||
| 21:20 | typechecking: refactor type checking context to be able to hold more sub-context information than hole namespace indices check-in: 9fd8a2a87e user: zlodo tags: trunk | |
| 17:45 | Refactored some template rules and type checking rules to avoid calling BuildTemplateSignature from inside type checking rules check-in: 64224a915f user: zlodo tags: trunk | |
|
2022-07-02
| ||
| 14:22 | Vararg templates: function param decls with open tuple types are expanded into multiple params check-in: ecd5b0e89a user: zlodo tags: trunk | |
Changes
Changes to bs/builtins/types/constrainedfunc/typecheck.cpp.
| ︙ | ︙ | |||
48 49 50 51 52 53 54 |
}
}
} );
// tfunc type param / constrainedfunc arg
e.typeCheckingRuleSet()->addTypeCheckingRule( TCRINFOS,
| | > > > > | | 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 |
}
}
} );
// tfunc type param / constrainedfunc arg
e.typeCheckingRuleSet()->addTypeCheckingRule( TCRINFOS,
ValueToEIR( ValuePattern(
ANYTERM( _ ),
TFuncTypeSigPattern( ANYTERM( _ ), ANYTERM( _ ) ),
ANYTERM( _ ) ) ),
ValueToEIR( ValuePattern(
TSID( constant ),
GetValueType< builtins::ConstrainedFunc >(),
ANYTERM( _ ) ) ),
[]( const Term& lhs, const Term& rhs, const TypeCheckingContext& tcc ) -> TCGen
{
auto ldecomp = Decompose( lhs,
Vec(
Lit( "value"_sid ),
SubTerm(),
SubTerm(),
SubTerm(),
Val< LocationId >()
)
);
assert( ldecomp );
auto&& [sort, type, val, locId] = *ldecomp;
auto [tfType,_] = DecomposeTFTSig( type );
auto callPat = BuildArgPatternFromTFuncType( tcc.context(), *EIRToValue( tfType ) );
assert( callPat );
auto rhsVal = *EIRToValue( rhs );
auto cfunc = FromValue< ConstrainedFunc >( rhsVal );
assert( cfunc );
auto localC = tcc;
|
| ︙ | ︙ |
Changes to bs/builtins/types/func/build.cpp.
| ︙ | ︙ | |||
23 24 25 26 27 28 29 |
uint32_t varId = 0;
ForEachInTuple( params, [&]( auto&& param )
{
if( IsDecl( param ) )
{
auto decl = *FromValue< Decl >( param );
| < < < < < < < | 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
uint32_t varId = 0;
ForEachInTuple( params, [&]( auto&& param )
{
if( IsDecl( param ) )
{
auto decl = *FromValue< Decl >( param );
// Handle parameter packs (open tuples)
auto declType = *EIRToValue( decl.type() );
if( IsOpenTuple( declType ) )
{
ForEachInTuple( declType, [&]( auto&& type )
{
tv->append( BuildParamPat( c, type, param.locationId() ) );
|
| ︙ | ︙ |
Changes to bs/builtins/types/func/typecheck.cpp.
| ︙ | ︙ | |||
94 95 96 97 98 99 100 |
co_yield { move( wrapped ), tcc };
} );
// tfunc type param / func arg
e.typeCheckingRuleSet()->addTypeCheckingRule( TCRINFOS,
| | | | | 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 |
co_yield { move( wrapped ), tcc };
} );
// tfunc type param / func arg
e.typeCheckingRuleSet()->addTypeCheckingRule( TCRINFOS,
ParamPat( TFuncTypeSigPattern( ANYTERM( _ ), ANYTERM( _ ) ) ),
ValueToEIR( ValuePattern(
TSID( constant ),
FuncTypePattern(),
ANYTERM( _ ) ) ),
[]( const Term& lhs, const Term& rhs, const TypeCheckingContext& tcc ) -> TCGen
{
auto ldecomp = Decompose( lhs,
Vec(
Lit( "value"_sid ),
SubTerm(),
SubTerm(),
SubTerm(),
Val< LocationId >()
)
);
assert( ldecomp );
auto&& [sort, type, val, locId] = *ldecomp;
auto [tfType,_] = DecomposeTFTSig( type );
auto callPat = BuildArgPatternFromTFuncType( tcc.context(), *EIRToValue( tfType ) );
assert( callPat );
auto rhsVal = *EIRToValue( rhs );
auto sig = GetFuncSig( rhsVal );
for( auto&& [s, tcc] : TypeCheck( sig, *callPat, tcc ) )
{
|
| ︙ | ︙ |
Changes to bs/builtins/types/overloadset/typecheck.cpp.
| ︙ | ︙ | |||
71 72 73 74 75 76 77 |
} );
// tfunc type param / overloadset arg
e.typeCheckingRuleSet()->addTypeCheckingRule( TCRINFOS,
ValueToEIR( ValuePattern(
ANYTERM( _ ),
| | | 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 |
} );
// tfunc type param / overloadset arg
e.typeCheckingRuleSet()->addTypeCheckingRule( TCRINFOS,
ValueToEIR( ValuePattern(
ANYTERM( _ ),
TFuncTypeSigPattern( ANYTERM( _ ), ANYTERM( _ ) ),
ANYTERM( _ ) ) ),
ValueToEIR( ValuePattern(
TSID( constant ),
GetValueType< ptr< sema::OverloadSet > >(),
ANYTERM( _ ) ) ),
|
| ︙ | ︙ | |||
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 |
SubTerm(),
Val< LocationId >()
)
);
assert( ldecomp );
auto&& [sort, type, val, locId] = *ldecomp;
auto [tfType,_] = DecomposeTFTSig( type );
auto callPat = BuildArgPatternFromTFuncType( tcc.context(), *EIRToValue( tfType ) );
assert( callPat );
auto rhsVal = *EIRToValue( rhs );
auto os = *FromValue< ptr< OverloadSet > >( rhsVal );
auto rhsLocId = rhsVal.locationId();
|
| ︙ | ︙ |
Changes to bs/builtins/types/template/rules/tdecl.cpp.
1 2 3 4 5 6 7 8 9 |
#include "builtins/builtins.h"
namespace goose::builtins
{
class TDeclTemplateRule : public TemplateRule
{
optional< Term > buildSignature( const Context& c, const Term& val ) const final
{
auto td = *FromValue< TDecl >( *EIRToValue( val ) );
| > > > | > > | 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"
namespace goose::builtins
{
class TDeclTemplateRule : public TemplateRule
{
optional< Term > buildSignature( const Context& c, const Term& val ) const final
{
auto td = *FromValue< TDecl >( *EIRToValue( val ) );
auto sig = BuildTemplateSignature( c, td.type() );
if( !sig )
return nullopt;
return TDeclSigPattern( TERM( td.name() ), move( *sig ) );
}
Value buildParamDecl( const Context& c, const Term& param, const Term& arg ) const final
{
return *EIRToValue( arg );
}
|
| ︙ | ︙ |
Changes to bs/builtins/types/template/rules/tfunctype.cpp.
1 2 3 4 5 6 7 8 |
#include "builtins/builtins.h"
namespace goose::builtins
{
class TFuncTypeTemplateRule : public TemplateRule
{
optional< Term > buildSignature( const Context& c, const Term& val ) const final
{
| > > > > | > > | 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"
namespace goose::builtins
{
class TFuncTypeTemplateRule : public TemplateRule
{
optional< Term > buildSignature( const Context& c, const Term& val ) const final
{
auto tfuncType = FromValue< TFuncType >( *EIRToValue( val ) );
auto sig = BuildTFuncSignature( c, *tfuncType );
if( !sig )
return nullopt;
return TFuncTypeSigPattern( val, move( *sig ) );
}
Value buildParamDecl( const Context& c, const Term& param, const Term& arg ) const final
{
return *EIRToValue( arg );
}
|
| ︙ | ︙ |
Changes to bs/builtins/types/template/tc-tdecl.cpp.
1 2 3 4 |
#include "builtins/builtins.h"
namespace goose::builtins
{
| | < < | | | | < < < | | | < | < < < | | | | | < < | | < < < | | 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 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 |
#include "builtins/builtins.h"
namespace goose::builtins
{
Term BuildArgPatternFromTDecl( const Context& c, Term&& sig )
{
return ValueToEIR( ValuePattern( HOLE( "_"_sid ), move( sig ), HOLE( "_"_sid ) ) );
}
void SetupTDeclTypeChecking( Env& e )
{
auto tDeclPat = TDeclSigPattern( ANYTERM( _ ), ANYTERM( _ ) );
e.typeCheckingRuleSet()->addHalfUnificationRule( TCRINFOS, tDeclPat,
[]( const Term& lhs, TypeCheckingContext& c )
{
auto [name,sig] = DecomposeTDSig( lhs );
return HalfUnify( sig, c );
} );
e.typeCheckingRuleSet()->addTypeCheckingRule( TCRINFOS, tDeclPat, ANYTERM( _ ),
[]( const Term& lhs, const Term& rhs, TypeCheckingContext tcc ) -> TCGen
{
auto [name,typeSig] = DecomposeTDSig( lhs );
auto tdeclHole = HOLE( name );
auto pat = ValueToEIR( Value( move( typeSig ), HOLE( "_"_sid ) ) );
for( auto&& [s,tcc] : TypeCheck( pat, rhs, tcc ) )
{
// We need to typecheck the result with a hole named after the decl. However, since both sides of
// this unification orignally appeared on the LHS, we need to setup RHS to alias the LHS namespace for this.
auto savedRHSNamespaceIndex = tcc.RHSNamespaceIndex();
tcc.setRHSNamespaceIndex( tcc.LHSNamespaceIndex() );
for( auto&& [s,tcc] : TypeCheck( s, tdeclHole, tcc ) )
{
tcc.setRHSNamespaceIndex( savedRHSNamespaceIndex );
co_yield { s, tcc };
}
}
} );
e.typeCheckingRuleSet()->addUnificationRule( TCRINFOS, tDeclPat, ANYTERM( _ ),
[]( const Term& lhs, const Term& rhs, TypeCheckingContext tcc ) -> TCGen
{
auto [name,typeSig] = DecomposeTDSig( lhs );
auto tdeclHole = HOLE( name );
auto pat = ValueToEIR( Value( move( typeSig ), HOLE( "_"_sid ) ) );
for( auto&& [s,tcc] : Unify( pat, rhs, tcc ) )
{
// We need to unify the result with a hole named after the decl. However, since both sides of
// this unification orignally appeared on the LHS, we need to setup RHS to alias the LHS namespace for this.
auto savedRHSNamespaceIndex = tcc.RHSNamespaceIndex();
tcc.setRHSNamespaceIndex( tcc.LHSNamespaceIndex() );
for( auto&& [s,tcc] : Unify( s, tdeclHole, tcc ) )
{
tcc.setRHSNamespaceIndex( savedRHSNamespaceIndex );
co_yield { s, tcc };
}
}
} );
// tfunc tdecl param / tfunc arg
auto tDeclTFuncPat = TDeclSigPattern( ANYTERM( _ ), TFuncTypeSigPattern( ANYTERM( _ ), ANYTERM( _ ) ) );
e.typeCheckingRuleSet()->addTypeCheckingRule( TCRINFOS,
tDeclTFuncPat,
ValueToEIR( ValuePattern(
TSID( constant ),
TFuncTypePattern(),
ANYTERM( _ ) ) ),
[]( const Term& lhs, const Term& rhs, TypeCheckingContext tcc ) -> TCGen
{
auto [name,typeSig] = DecomposeTDSig( lhs );
auto [_,tfSig] = DecomposeTFTSig( typeSig );
auto callPat = BuildArgPatternFromTDecl( tcc.context(), move( typeSig ) );
auto tdeclHole = HOLE( name );
auto rhsVal = *EIRToValue( rhs );
ConstrainedFunc cfunc( tfSig, GetTFuncInvocationRule(), rhsVal );
auto cFuncTerm = ValueToEIR( ToValue( move( cfunc ) ) );
// Create a new named hole namespace to isolate holes from the passed function from those in
// the called function.
auto savedRHSNamespaceIndex = tcc.RHSNamespaceIndex();
tcc.setRHSNamespaceIndex( tcc.newNamespaceIndex() );
|
| ︙ | ︙ | |||
135 136 137 138 139 140 141 |
ValueToEIR( ValuePattern(
TSID( constant ),
GetValueType< ptr< sema::OverloadSet > >(),
ANYTERM( _ ) ) ),
[]( const Term& lhs, const Term& rhs, TypeCheckingContext tcc ) -> TCGen
{
| | | < < | | < < < | | 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 |
ValueToEIR( ValuePattern(
TSID( constant ),
GetValueType< ptr< sema::OverloadSet > >(),
ANYTERM( _ ) ) ),
[]( const Term& lhs, const Term& rhs, TypeCheckingContext tcc ) -> TCGen
{
auto [name,typeSig] = DecomposeTDSig( lhs );
auto [_,tfSig] = DecomposeTFTSig( typeSig );
auto callPat = BuildArgPatternFromTDecl( tcc.context(), move( typeSig ) );
auto tdeclHole = HOLE( name );
auto rhsVal = *EIRToValue( rhs );
ConstrainedFunc cfunc( tfSig, GetOverloadSetInvocationRule(), rhsVal );
auto cFuncTerm = ValueToEIR( ToValue( move( cfunc ) ) );
// Create a new named hole namespace to isolate holes from the passed function from those in
// the called function.
auto savedRHSNamespaceIndex = tcc.RHSNamespaceIndex();
tcc.setRHSNamespaceIndex( tcc.newNamespaceIndex() );
|
| ︙ | ︙ |
Changes to bs/builtins/types/template/tdecl.cpp.
1 2 3 4 5 6 7 8 9 10 11 |
#include "builtins/builtins.h"
using namespace goose::builtins;
namespace goose::builtins
{
bool IsTDecl( const Value& td )
{
return td.type() == GetValueType< TDecl >();
}
| | | < < < < < | | < | > | | | 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 |
#include "builtins/builtins.h"
using namespace goose::builtins;
namespace goose::builtins
{
bool IsTDecl( const Value& td )
{
return td.type() == GetValueType< TDecl >();
}
Term TDeclSigPattern( const Term& name, Term&& sig )
{
return VEC( TSID( tdecl_sig ), name, move( sig ) );
}
tuple< StringId, Term > DecomposeTDSig( const Term& tdsig )
{
auto result = Decompose( tdsig,
Vec(
Lit( "tdecl_sig"_sid ),
Val< StringId >(),
SubTerm()
)
);
auto&& [name,sig] = *result;
return { name, sig };
}
}
namespace goose::eir
{
const Term& Bridge< TDecl >::Type()
{
|
| ︙ | ︙ |
Changes to bs/builtins/types/template/tdecl.h.
| ︙ | ︙ | |||
22 23 24 25 26 27 28 |
private:
Term m_type;
StringId m_name;
};
extern bool IsTDecl( const Value& td );
| | < | | 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
private:
Term m_type;
StringId m_name;
};
extern bool IsTDecl( const Value& td );
extern Term TDeclSigPattern( const Term& name, Term&& sig );
extern tuple< StringId, Term > DecomposeTDSig( const Term& tdsig );
}
namespace goose::eir
{
template<>
struct Bridge< builtins::TDecl >
{
|
| ︙ | ︙ |
Changes to bs/builtins/types/template/tfunctype.cpp.
| ︙ | ︙ | |||
41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
const Term& TFuncTypePattern()
{
static auto tFuncTypePat = ValueToEIR( Value( TypeType(), VEC( TSID( texpr ), TSID( tfunc ),
ANYTERM( _ ), ANYTERM( _ ), ANYTERM( _ ), ANYTERM( _ ), ANYTERM( _ ) ) ) );
return tFuncTypePat;
}
}
namespace goose::eir
{
const Term& Bridge< TFuncType >::Type()
{
return TypeType();
| > > > > > > > > > > > > > > | 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 |
const Term& TFuncTypePattern()
{
static auto tFuncTypePat = ValueToEIR( Value( TypeType(), VEC( TSID( texpr ), TSID( tfunc ),
ANYTERM( _ ), ANYTERM( _ ), ANYTERM( _ ), ANYTERM( _ ), ANYTERM( _ ) ) ) );
return tFuncTypePat;
}
tuple< Term, Term > DecomposeTFTSig( const Term& tdsig )
{
auto result = Decompose( tdsig,
Vec(
Lit( "tfunctype_sig"_sid ),
SubTerm(),
SubTerm()
)
);
auto&& [type,sig] = *result;
return { type, sig };
}
}
namespace goose::eir
{
const Term& Bridge< TFuncType >::Type()
{
return TypeType();
|
| ︙ | ︙ |
Changes to bs/builtins/types/template/tfunctype.h.
| ︙ | ︙ | |||
50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
// Helper to provide generic param patterns for template functions.
struct TFuncPattern
{
static const Term& GetPattern();
};
extern const Term& TFuncTypePattern();
}
namespace goose::eir
{
template<>
struct Bridge< builtins::TFuncType >
{
| > > > > > > > | 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 |
// Helper to provide generic param patterns for template functions.
struct TFuncPattern
{
static const Term& GetPattern();
};
extern const Term& TFuncTypePattern();
static inline Term TFuncTypeSigPattern( const Term& type, Term&& sig )
{
return VEC( TSID( tfunctype_sig ), type, move( sig ) );
}
extern tuple< Term, Term > DecomposeTFTSig( const Term& tdsig );
}
namespace goose::eir
{
template<>
struct Bridge< builtins::TFuncType >
{
|
| ︙ | ︙ |
Changes to bs/builtins/types/template/typecheck.cpp.
| ︙ | ︙ | |||
64 65 66 67 68 69 70 |
co_yield { move( wrapped ), tcc };
}
} );
// tfunc type param / tfunc arg
e.typeCheckingRuleSet()->addTypeCheckingRule( TCRINFOS,
| | > | | 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 |
co_yield { move( wrapped ), tcc };
}
} );
// tfunc type param / tfunc arg
e.typeCheckingRuleSet()->addTypeCheckingRule( TCRINFOS,
ParamPat( TFuncTypeSigPattern( ANYTERM( _ ), ANYTERM( _ ) ) ),
ValueToEIR( ValuePattern(
TSID( constant ),
TFuncTypePattern(),
ANYTERM( _ ) ) ),
[]( const Term& lhs, const Term& rhs, TypeCheckingContext tcc ) -> TCGen
{
auto ldecomp = Decompose( lhs,
Vec(
Lit( "value"_sid ),
SubTerm(),
SubTerm(),
SubTerm(),
Val< LocationId >()
)
);
assert( ldecomp );
auto&& [sort, type, val, locId] = *ldecomp;
auto [tfType,_] = DecomposeTFTSig( type );
auto callPat = BuildArgPatternFromTFuncType( tcc.context(), *EIRToValue( tfType ) );
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.
|
| ︙ | ︙ |