Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
| Comment: | Added a new type of template expression: TVec, along with a helper function to make it possible for parametric types to be constructed either normally or as a template expression when passed template parameters. Only used by LocalVar for now, parametric runtime types require some refactoring. |
|---|---|
| Downloads: | Tarball | ZIP archive |
| Timelines: | family | ancestors | descendants | both | trunk |
| Files: | files | file ages | folders |
| SHA3-256: |
27fc719d74bbfdc271f791239e68b425 |
| User & Date: | achavasse 2019-08-16 14:48:20.807 |
Context
|
2019-08-16
| ||
| 20:33 | Implemented variable declarations with local type inference. check-in: 5a361c8b86 user: achavasse tags: trunk | |
| 14:48 | Added a new type of template expression: TVec, along with a helper function to make it possible for parametric types to be constructed either normally or as a template expression when passed template parameters. Only used by LocalVar for now, parametric runtime types require some refactoring. check-in: 27fc719d74 user: achavasse tags: trunk | |
|
2019-08-15
| ||
| 22:58 | Implemented InitializeLocalVar() for the bool, ct_int and ct_string types. check-in: 6d69e387ac user: achavasse tags: trunk | |
Changes
Changes to bs/builtins/CMakeLists.txt.
| ︙ | ︙ | |||
20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
types/func/func.cpp
types/func/build.cpp
types/func/invoke.cpp
types/func/unify.cpp
types/intrinsic/intrinsic.cpp
types/template/tvar.cpp
types/template/tdecl.cpp
types/template/tnameddecl.cpp
types/template/tfunctype.cpp
types/template/tfunc.cpp
types/template/build.cpp
types/template/rules.cpp
| > | 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
types/func/func.cpp
types/func/build.cpp
types/func/invoke.cpp
types/func/unify.cpp
types/intrinsic/intrinsic.cpp
types/template/tvec.cpp
types/template/tvar.cpp
types/template/tdecl.cpp
types/template/tnameddecl.cpp
types/template/tfunctype.cpp
types/template/tfunc.cpp
types/template/build.cpp
types/template/rules.cpp
|
| ︙ | ︙ |
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 empathy::parse;
namespace empathy::builtins
{
const Term& RootIdentity()
{
| | | 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 empathy::parse;
namespace empathy::builtins
{
const Term& RootIdentity()
{
static auto identity = VEC( DomainCompileTime(), TSID( e0 ) );
return identity;
}
void RegisterRule( sema::Env& env, const StringId& name, parse::Rule&& rule )
{
parse::RegisterRule( env, AppendToVectorTerm( RootIdentity(), TERM( name ) ), move( rule ) );
}
|
| ︙ | ︙ |
Changes to bs/builtins/types/constrainedfunc/constrainedfunc.cpp.
| ︙ | ︙ | |||
13 14 15 16 17 18 19 |
{
static auto type = ValueToIRExpr( Value( TypeType(), TSID( constrainedfunc ) ) );
return type;
}
Value Bridge< builtins::ConstrainedFunc >::ToValue( const builtins::ConstrainedFunc& cf )
{
| | | 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
{
static auto type = ValueToIRExpr( Value( TypeType(), TSID( constrainedfunc ) ) );
return type;
}
Value Bridge< builtins::ConstrainedFunc >::ToValue( const builtins::ConstrainedFunc& cf )
{
return Value( Type(), VEC(
Quote( cf.constraintPat() ),
TERM( static_pointer_cast< void >( cf.invRule() ) ),
ValueToIRExpr( cf.func() ) ) );
}
optional< builtins::ConstrainedFunc > Bridge< builtins::ConstrainedFunc >::FromValue( const Value& v )
{
|
| ︙ | ︙ |
Changes to bs/builtins/types/constrainedfunc/invoke.cpp.
1 2 3 4 5 6 7 8 9 10 11 |
#include "builtins/builtins.h"
using namespace empathy::sema;
namespace empathy::builtins
{
class ConstrainedFuncInvocationRule : public InvocationRule
{
public:
Value resolveInvocation( const Context& c, uint32_t loc, const Value& callee, const Value& args ) const final
{
| | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
#include "builtins/builtins.h"
using namespace empathy::sema;
namespace empathy::builtins
{
class ConstrainedFuncInvocationRule : public InvocationRule
{
public:
Value resolveInvocation( const Context& c, uint32_t loc, const Value& callee, const Value& args ) const final
{
auto callPat = VEC( c.domain(), args.val(), MkHole( "_"_sid ) );
// Unify with the constraint pattern. We only care that there is at least one
// solution, and if so, we defer the actual call resolution to the contained
// function.
auto cfunc = FromValue< ConstrainedFunc >( callee );
assert( cfunc );
|
| ︙ | ︙ |
Changes to bs/builtins/types/constrainedfunc/unify.cpp.
1 2 3 4 5 6 7 8 9 |
#include "builtins/builtins.h"
using namespace empathy;
using namespace empathy::ir;
namespace empathy::builtins
{
void SetupConstrainedFuncUnification( Env& e )
{
| | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
#include "builtins/builtins.h"
using namespace empathy;
using namespace empathy::ir;
namespace empathy::builtins
{
void SetupConstrainedFuncUnification( Env& e )
{
auto funcTypePat = ValueToIRExpr( Value( TypeType(), VEC( TSID( func ),
ANYTERM( _ ), ANYTERM( _ ), ANYTERM( _ ), ANYTERM( _ ) ) ) );
auto tFuncTypePat = ValueToIRExpr( Value( TypeType(), VEC( TSID( texpr ), TSID( tfunc ),
ANYTERM( _ ), ANYTERM( _ ), ANYTERM( _ ) ) ) );
// func type param / constrainedfunc arg
e.unificationRuleSet()->addAsymRule(
ValueToIRExpr( ValuePattern( MkHole( "_"_sid ), move( funcTypePat ), MkHole( "_"_sid ) ) ),
|
| ︙ | ︙ |
Changes to bs/builtins/types/decl.cpp.
| ︙ | ︙ | |||
16 17 18 19 20 21 22 |
return !!result;
}
const Term& Decl::PatternTypeT::GetPattern()
{
static auto pattern = ValueToIRExpr(
| | | | 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 |
return !!result;
}
const Term& Decl::PatternTypeT::GetPattern()
{
static auto pattern = ValueToIRExpr(
Value( TypeType(), VEC( TSID( decl ), MkHole( "T"_sid ) ) ) );
return pattern;
}
}
namespace empathy::ir
{
Term Bridge< Decl >::Type( const Term& declType )
{
return ValueToIRExpr( Value( TypeType(), VEC( TSID( decl ), declType ) ) );
}
Value Bridge< Decl >::ToValue( const Decl& d )
{
return Value( Type( d.type() ), TERM( d.name() ) );
}
|
| ︙ | ︙ |
Changes to bs/builtins/types/func/bfunc.inl.
| ︙ | ︙ | |||
61 62 63 64 65 66 67 |
return PP::GetPattern();
}
};
template< typename... T >
Term BuildBuiltinFuncParamTypeList()
{
| | | | 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 |
return PP::GetPattern();
}
};
template< typename... T >
Term BuildBuiltinFuncParamTypeList()
{
return VEC( ValueToIRExpr( ValuePattern( sema::MkHole( "_"_sid ),
TypePatternHelper< T >::GetPattern(), sema::MkHole( "_"_sid ) ) )... );
}
template< typename R, typename... T >
const Term& Bridge< R ( T... ) >::Type()
{
static auto type = ValueToIRExpr( Value( TypeType(), VEC( TSID( func ),
builtins::is_eager_v< R > ? TSID( builtin_eager ) : TSID( builtin ),
sema::Quote( sema::DomainCompileTime() ), GetValueType< builtins::remove_eager_t< R > >(),
sema::Quote( BuildBuiltinFuncParamTypeList< T... >() )
) ) );
return type;
}
|
| ︙ | ︙ |
Changes to bs/builtins/types/func/build.cpp.
| ︙ | ︙ | |||
43 44 45 46 47 48 49 |
// we should invoke an overridable global function that can transform both the
// variable object and the function type. This way, we can implement/customize
// smart lexical captures from inside the language itself (and at a minimum, have
// a default implementation that denies access to outside variables with an error)
const auto& pEnv = c.env();
auto funcTypeTerm = ValueToIRExpr( ToValue( funcType ) );
| | | 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
// we should invoke an overridable global function that can transform both the
// variable object and the function type. This way, we can implement/customize
// smart lexical captures from inside the language itself (and at a minimum, have
// a default implementation that denies access to outside variables with an error)
const auto& pEnv = c.env();
auto funcTypeTerm = ValueToIRExpr( ToValue( funcType ) );
auto identity = VEC( c.domain(), funcIdentity, funcTypeTerm );
// This visibility rule mean that regardless of which domain this function is being compiled for,
// it will see the parent scope's compile time values.
// This makes sense for regular functions, but as noted above we'll need an additional
// import rule for lambda variable captures, which will probably need to be created when
// compiling the function, as we would need a separate one for each target domain.
c.env()->addVisibilityRule(
|
| ︙ | ︙ | |||
114 115 116 117 118 119 120 |
apvt.push_back( param );
else
apvt.push_back( ValueToIRExpr( ValuePattern( TSID( computed ), type, TERM( ptr< void >() ) ) ) );
return true;
} );
| | | 114 115 116 117 118 119 120 121 122 123 124 125 126 127 |
apvt.push_back( param );
else
apvt.push_back( ValueToIRExpr( ValuePattern( TSID( computed ), type, TERM( ptr< void >() ) ) ) );
return true;
} );
return VEC(
ftype.domain(),
TERM( make_shared< Vector >( apvt.persistent() ) ),
ftype.returnType()
);
}
}
|
Changes to bs/builtins/types/func/func.cpp.
1 2 3 4 5 6 7 8 9 10 11 12 |
#include "builtins/builtins.h"
#include "lex/lex.h"
#include "parse/parse.h"
using namespace empathy::builtins;
using namespace empathy::parse;
namespace empathy::builtins
{
const Term& FuncPattern::GetPattern()
{
static auto pattern = ValueToIRExpr(
| | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
#include "builtins/builtins.h"
#include "lex/lex.h"
#include "parse/parse.h"
using namespace empathy::builtins;
using namespace empathy::parse;
namespace empathy::builtins
{
const Term& FuncPattern::GetPattern()
{
static auto pattern = ValueToIRExpr(
Value( TypeType(), VEC( TSID( func ), MkHole( "llvmType"_sid ),
MkHole( "_"_sid ), MkHole( "_"_sid ), MkHole( "_"_sid ) ) ) );
return pattern;
}
bool IsFuncType( const Value& t )
{
|
| ︙ | ︙ | |||
44 45 46 47 48 49 50 |
SubTerm(), // return type
SubTerm() // param types
)
);
assert( typeDecomp );
auto&& [kind, domain, rtype, ptypes] = *typeDecomp;
| | | 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
SubTerm(), // return type
SubTerm() // param types
)
);
assert( typeDecomp );
auto&& [kind, domain, rtype, ptypes] = *typeDecomp;
return VEC( *Unquote( domain ), *Unquote( ptypes ), rtype );
}
Term GetFuncRType( const Value& func )
{
auto funcType = ValueFromIRExpr( func.type() );
assert( funcType );
|
| ︙ | ︙ | |||
263 264 265 266 267 268 269 |
const Term& Bridge< FuncType >::Type()
{
return TypeType();
}
Value Bridge< FuncType >::ToValue( const FuncType& ft )
{
| | | 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 |
const Term& Bridge< FuncType >::Type()
{
return TypeType();
}
Value Bridge< FuncType >::ToValue( const FuncType& ft )
{
return Value( Type(), VEC( TSID( func ), TERM( ft.llvmType() ),
Quote( ft.domain() ), ft.returnType(), Quote( ft.params() ) ) );
}
optional< FuncType > Bridge< FuncType >::FromValue( const Value& v )
{
auto result = Decompose( v.val(),
Vec(
|
| ︙ | ︙ | |||
297 298 299 300 301 302 303 |
}
Value Bridge< Func >::ToValue( const builtins::Func& func )
{
if( func.isExternal() )
return Value( Type( func ), TERM( *func.symbol() ) );
| | | 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 |
}
Value Bridge< Func >::ToValue( const builtins::Func& func )
{
if( func.isExternal() )
return Value( Type( func ), TERM( *func.symbol() ) );
return Value( Type( func ), VEC(
TERM( func.tokens() ), TERM( func.llr() ) ) );
}
optional< Func > Bridge< Func >::FromValue( const Value& v )
{
auto funcTypeVal = ValueFromIRExpr( v.type() );
if( !funcTypeVal )
|
| ︙ | ︙ |
Changes to bs/builtins/types/func/invoke.cpp.
| ︙ | ︙ | |||
10 11 12 13 14 15 16 |
Value resolveInvocation( const Context& c, uint32_t loc, const Value& callee, const Value& args ) const final
{
optional< UnificationContext > bestUC;
optional< Term > bestSol;
bool ambiguous = false;
auto sig = GetFuncSig( callee );
| | | 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
Value resolveInvocation( const Context& c, uint32_t loc, const Value& callee, const Value& args ) const final
{
optional< UnificationContext > bestUC;
optional< Term > bestSol;
bool ambiguous = false;
auto sig = GetFuncSig( callee );
auto callPat = VEC( c.domain(), args.val(), MkHole( "_"_sid ) );
for( auto&& [s, uc] : FullUnify( sig, callPat, c ) )
{
if( !bestSol || uc.score() > bestUC->score() )
{
bestUC = uc;
bestSol = s;
ambiguous = false;
|
| ︙ | ︙ | |||
106 107 108 109 110 111 112 |
return pRule;
}
void SetupFunctionInvocationRule( Env& e )
{
e.invocationRuleSet()->addRule(
ValueToIRExpr( ValuePattern( ANYTERM( _ ),
| | | 106 107 108 109 110 111 112 113 114 115 116 117 118 |
return pRule;
}
void SetupFunctionInvocationRule( Env& e )
{
e.invocationRuleSet()->addRule(
ValueToIRExpr( ValuePattern( ANYTERM( _ ),
ValueToIRExpr( Value( TypeType(), VEC( TSID( func ),
ANYTERM( _ ), ANYTERM( _ ), ANYTERM( _ ), ANYTERM( _ ) ) ) ),
ANYTERM( _ ) ) ),
GetFuncInvocationRule() );
}
}
|
Changes to bs/builtins/types/func/unify.cpp.
1 2 3 4 5 6 7 8 9 |
#include "builtins/builtins.h"
using namespace empathy;
using namespace empathy::ir;
namespace empathy::builtins
{
void SetupFunctionUnification( Env& e )
{
| | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
#include "builtins/builtins.h"
using namespace empathy;
using namespace empathy::ir;
namespace empathy::builtins
{
void SetupFunctionUnification( Env& e )
{
auto funcTypePat = ValueToIRExpr( Value( TypeType(), VEC( TSID( func ),
ANYTERM( _ ), ANYTERM( _ ), ANYTERM( _ ), ANYTERM( _ ) ) ) );
auto tFuncTypePat = ValueToIRExpr( Value( TypeType(), VEC( TSID( texpr ), TSID( tfunc ),
ANYTERM( _ ), ANYTERM( _ ), ANYTERM( _ ) ) ) );
e.unificationRuleSet()->addAsymRule(
ValueToIRExpr( ValuePattern( MkHole( "_"_sid ), move( tFuncTypePat ), MkHole( "_"_sid ) ) ),
ValueToIRExpr( ValuePattern(
|
| ︙ | ︙ |
Changes to bs/builtins/types/intrinsic/intrinsic.inl.
1 2 3 4 5 6 7 8 |
#ifndef EMPATHY_BUILTINS_TYPES_INTRINSIC_INL
#define EMPATHY_BUILTINS_TYPES_INTRINSIC_INL
namespace empathy::ir
{
template< typename R, typename... T >
const Term& Bridge< builtins::Intrinsic< R ( T... ) > >::Type()
{
| | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
#ifndef EMPATHY_BUILTINS_TYPES_INTRINSIC_INL
#define EMPATHY_BUILTINS_TYPES_INTRINSIC_INL
namespace empathy::ir
{
template< typename R, typename... T >
const Term& Bridge< builtins::Intrinsic< R ( T... ) > >::Type()
{
static auto type = ValueToIRExpr( Value( TypeType(), VEC( TSID( func ), TSID( intrinsic ),
sema::Quote( sema::DomainAny() ), GetValueType< Value >(),
sema::Quote( BuildBuiltinFuncParamTypeList< T... >() )
) ) );
return type;
}
template< typename R, typename... T >
|
| ︙ | ︙ |
Changes to bs/builtins/types/localvar/localvar.cpp.
| ︙ | ︙ | |||
83 84 85 86 87 88 89 |
Term Bridge< LocalVar >::Type( const Term& type )
{
return ValueToIRExpr( ToValue< LocalVarType >( type ) );
}
Value Bridge< LocalVar >::ToValue( const LocalVar& lv )
{
| | | 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 |
Term Bridge< LocalVar >::Type( const Term& type )
{
return ValueToIRExpr( ToValue< LocalVarType >( type ) );
}
Value Bridge< LocalVar >::ToValue( const LocalVar& lv )
{
return Value( Type( lv.type() ), VEC( TERM( lv.cfgId() ), TERM( lv.index() ) ) );
}
optional< LocalVar > Bridge< LocalVar >::FromValue( const Value& v )
{
auto t = FromValue< LocalVarType >( *ValueFromIRExpr( v.type() ) );
if( !t )
return nullopt;
|
| ︙ | ︙ |
Changes to bs/builtins/types/overloadset/unify.cpp.
1 2 3 4 5 6 7 8 9 |
#include "builtins/builtins.h"
using namespace empathy;
using namespace empathy::ir;
namespace empathy::builtins
{
void SetupOverloadSetUnification( Env& e )
{
| | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
#include "builtins/builtins.h"
using namespace empathy;
using namespace empathy::ir;
namespace empathy::builtins
{
void SetupOverloadSetUnification( Env& e )
{
auto funcTypePat = ValueToIRExpr( Value( TypeType(), VEC( TSID( func ),
ANYTERM( _ ), ANYTERM( _ ), ANYTERM( _ ), ANYTERM( _ ) ) ) );
auto tFuncTypePat = ValueToIRExpr( Value( TypeType(), VEC( TSID( texpr ), TSID( tfunc ),
ANYTERM( _ ), ANYTERM( _ ), ANYTERM( _ ) ) ) );
// func type param / overloadset arg
e.unificationRuleSet()->addAsymRule(
ValueToIRExpr( ValuePattern( MkHole( "_"_sid ), move( funcTypePat ), MkHole( "_"_sid ) ) ),
|
| ︙ | ︙ |
Changes to bs/builtins/types/runtime/array.cpp.
| ︙ | ︙ | |||
23 24 25 26 27 28 29 |
}
}
namespace empathy::ir
{
Value Bridge< ArrayType >::ToValue( const ArrayType& a )
{
| | | 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
}
}
namespace empathy::ir
{
Value Bridge< ArrayType >::ToValue( const ArrayType& a )
{
return Value( Type(), VEC( TSID( rt_type ),
TERM( llvm::ArrayType::get( GetLLVMType( *ValueFromIRExpr( a.m_containedType ) ), a.m_count ) ),
TSID( array ), TERM( a.m_count ), a.m_containedType ) );
}
optional< ArrayType > Bridge< ArrayType >::FromValue( const Value& v )
{
auto result = Decompose( v.val(),
|
| ︙ | ︙ |
Changes to bs/builtins/types/runtime/basic.cpp.
| ︙ | ︙ | |||
24 25 26 27 28 29 30 |
{
return ToValue( IntegerType( numBits, true ) );
} );
}
const Term& IntegerType::Pattern::GetPattern()
{
| | | | | | | | | 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 |
{
return ToValue( IntegerType( numBits, true ) );
} );
}
const Term& IntegerType::Pattern::GetPattern()
{
static auto pattern = ValueToIRExpr( Value( TypeType(), VEC( TSID( rt_type ),
MkHole( "llvmType"_sid ),
TSID( integer ), MkHole( "size"_sid ), MkHole( "signedness"_sid ) ) ) );
return pattern;
}
const Term& IntegerType::PatternSigned::GetPattern()
{
static auto pattern = ValueToIRExpr( Value( TypeType(), VEC( TSID( rt_type ),
MkHole( "llvmType"_sid ),
TSID( integer ), MkHole( "size"_sid ), TERM( 1U ) ) ) );
return pattern;
}
const Term& IntegerType::PatternUnsigned::GetPattern()
{
static auto pattern = ValueToIRExpr( Value( TypeType(), VEC( TSID( rt_type ),
MkHole( "llvmType"_sid ),
TSID( integer ), MkHole( "size"_sid ), TERM( 0U ) ) ) );
return pattern;
}
}
namespace empathy::ir
{
//// Half
Value Bridge< HalfFloatType >::ToValue( const HalfFloatType& i )
{
return Value( Type(), VEC( TSID( rt_type ),
TERM( llvm::Type::getHalfTy( GetLLVMContext() ) ),
TSID( half ) ) );
}
optional< HalfFloatType > Bridge< HalfFloatType >::FromValue( const Value& v )
{
if( v != ToValue( HalfFloatType() ) )
return nullopt;
return {};
}
//// Float
Value Bridge< FloatType >::ToValue( const FloatType& i )
{
return Value( Type(), VEC( TSID( rt_type ),
TERM( llvm::Type::getFloatTy( GetLLVMContext() ) ),
TSID( float ) ) );
}
optional< FloatType > Bridge< FloatType >::FromValue( const Value& v )
{
if( v != ToValue( FloatType() ) )
return nullopt;
return {};
}
//// Double
Value Bridge< DoubleFloatType >::ToValue( const DoubleFloatType& i )
{
return Value( Type(), VEC( TSID( rt_type ),
TERM( llvm::Type::getDoubleTy( GetLLVMContext() ) ),
TSID( double ) ) );
}
optional< DoubleFloatType > Bridge< DoubleFloatType >::FromValue( const Value& v )
{
if( v != ToValue( DoubleFloatType() ) )
return nullopt;
return {};
}
//// Integer
Value Bridge< IntegerType >::ToValue( const IntegerType& i )
{
return Value( Type(), VEC( TSID( rt_type ),
TERM( llvm::IntegerType::get( GetLLVMContext(), i.m_numBits ) ),
TSID( integer ), TERM( i.m_numBits ), i.m_signed ? TERM( 1U ) : TERM( 0U ) ) );
}
optional< IntegerType > Bridge< IntegerType >::FromValue( const Value& v )
{
auto result = Decompose( v.val(),
|
| ︙ | ︙ |
Changes to bs/builtins/types/runtime/pointer.cpp.
| ︙ | ︙ | |||
23 24 25 26 27 28 29 |
}
}
namespace empathy::ir
{
Value Bridge< PointerType >::ToValue( const PointerType& p )
{
| | | 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
}
}
namespace empathy::ir
{
Value Bridge< PointerType >::ToValue( const PointerType& p )
{
return Value( Type(), VEC( TSID( rt_type ),
TERM( llvm::PointerType::getUnqual( GetLLVMType( *ValueFromIRExpr( p.m_pointedType ) ) ) ),
TSID( pointer ), p.m_pointedType ) );
}
optional< PointerType > Bridge< PointerType >::FromValue( const Value& v )
{
auto result = Decompose( v.val(),
|
| ︙ | ︙ |
Changes to bs/builtins/types/runtime/struct.cpp.
| ︙ | ︙ | |||
59 60 61 62 63 64 65 |
for( auto&& mt : s.m_memberTypes->terms() )
elements.emplace_back( GetLLVMType( *ValueFromIRExpr( mt ) ) );
auto* pllvmType = llvm::StructType::get( GetLLVMContext(), elements, s.m_packed );
if( s.m_identity )
{
| | | | 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 |
for( auto&& mt : s.m_memberTypes->terms() )
elements.emplace_back( GetLLVMType( *ValueFromIRExpr( mt ) ) );
auto* pllvmType = llvm::StructType::get( GetLLVMContext(), elements, s.m_packed );
if( s.m_identity )
{
return Value( Type(), VEC( TSID( rt_type ), TERM( pllvmType ),
TSID( struct ), TERM( s.m_packed ? 1U : 0U ),
Quote( *s.m_identity ), TERM( s.m_memberTypes ) ) );
}
return Value( Type(), VEC( TSID( rt_type ), TERM( pllvmType ),
TSID( struct ), TERM( s.m_packed ? 1U : 0U ),
TERM( s.m_memberTypes ) ) );
}
optional< StructType > Bridge< StructType >::FromValue( const Value& v )
{
auto result = Decompose( v.val(),
|
| ︙ | ︙ |
Changes to bs/builtins/types/runtime/unify.cpp.
1 2 3 4 5 6 7 8 9 |
#include "builtins/builtins.h"
using namespace empathy;
using namespace empathy::ir;
namespace empathy::builtins
{
void SetupRuntimeTypesUnification( Env& e )
{
| | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
#include "builtins/builtins.h"
using namespace empathy;
using namespace empathy::ir;
namespace empathy::builtins
{
void SetupRuntimeTypesUnification( Env& e )
{
auto rtIntTypePattern = Value( TypeType(), VEC( TSID( rt_type ),
ANYTERM( _ ),
TSID( integer ), ANYTERM( _ ), ANYTERM( _ ) ) );
// ct_int type against a IntegerType type:
// return the IntegerType type. We don't care if the
// ct_int fits at this point, this will be dealt with by
// the ct_int value unification rule below.
|
| ︙ | ︙ | |||
116 117 118 119 120 121 122 |
}
auto* llvmType = static_cast< llvm::IntegerType* >( GetLLVMType( *rttypeVal ) );
co_yield { ValueToIRExpr(
BuildComputedValue( lhsVal->type(), llr::LoadConstInt( llvmType, move( valToLoad ) ) ) ), c };
} );
| | | | 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 |
}
auto* llvmType = static_cast< llvm::IntegerType* >( GetLLVMType( *rttypeVal ) );
co_yield { ValueToIRExpr(
BuildComputedValue( lhsVal->type(), llr::LoadConstInt( llvmType, move( valToLoad ) ) ) ), c };
} );
auto rtInt8TypePattern = Value( TypeType(), VEC( TSID( rt_type ),
ANYTERM( _ ),
TSID( integer ), TERM( 8U ), ANYTERM( _ ) ) );
auto rtInt8PtrTypePattern = Value( TypeType(), VEC( TSID( rt_type ),
ANYTERM( _ ),
TSID( pointer ), ValueToIRExpr( rtInt8TypePattern ) ) );
// ct_int type against a char*:
// return the char* type.
e.unificationRuleSet()->addSymRule(
ValueToIRExpr( rtInt8PtrTypePattern ),
|
| ︙ | ︙ |
Changes to bs/builtins/types/template/build.cpp.
| ︙ | ︙ | |||
53 54 55 56 57 58 59 |
if( !rtSig )
{
DiagnosticsManager::GetInstance().emitErrorMessage( ValueFromIRExpr( tft.returnType() )->locationId(),
"Invalid template return type or texpr." );
return nullopt;
}
| | | 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
if( !rtSig )
{
DiagnosticsManager::GetInstance().emitErrorMessage( ValueFromIRExpr( tft.returnType() )->locationId(),
"Invalid template return type or texpr." );
return nullopt;
}
return VEC(
tft.domain(),
TERM( make_shared< Vector >( vt.persistent() ) ),
*rtSig );
}
Value BuildTFunc( const Context& c, const TFuncType& tft, const Term& identity, const Value& params, ptr< void > body )
{
|
| ︙ | ︙ | |||
103 104 105 106 107 108 109 |
if( !rtArgPat )
{
DiagnosticsManager::GetInstance().emitErrorMessage( ValueFromIRExpr( ftype->returnType() )->locationId(),
"Invalid template return type or texpr." );
return nullopt;
}
| | | 103 104 105 106 107 108 109 110 111 112 113 114 115 116 |
if( !rtArgPat )
{
DiagnosticsManager::GetInstance().emitErrorMessage( ValueFromIRExpr( ftype->returnType() )->locationId(),
"Invalid template return type or texpr." );
return nullopt;
}
return VEC(
ftype->domain(),
TERM( make_shared< Vector >( apvt.persistent() ) ),
*rtArgPat
);
}
}
|
Changes to bs/builtins/types/template/invoke.cpp.
| ︙ | ︙ | |||
14 15 16 17 18 19 20 |
auto tf = FromValue< TFunc >( callee );
assert( tf );
optional< UnificationContext > bestUC;
optional< Term > bestSol;
bool ambiguous = false;
| | | 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
auto tf = FromValue< TFunc >( callee );
assert( tf );
optional< UnificationContext > bestUC;
optional< Term > bestSol;
bool ambiguous = false;
auto callPat = VEC( c.domain(), args.val(), MkHole( "_"_sid ) );
for( auto&& [s, uc] : FullUnify( tf->signature(), callPat, c ) )
{
if( !bestSol || uc.score() > bestUC->score() )
{
bestUC = uc;
bestSol = s;
|
| ︙ | ︙ | |||
104 105 106 107 108 109 110 |
return pRule;
}
void SetupTemplateFunctionInvocationRule( Env& e )
{
e.invocationRuleSet()->addRule(
ValueToIRExpr( ValuePattern( TSID( constant ),
| | | 104 105 106 107 108 109 110 111 112 113 114 115 116 |
return pRule;
}
void SetupTemplateFunctionInvocationRule( Env& e )
{
e.invocationRuleSet()->addRule(
ValueToIRExpr( ValuePattern( TSID( constant ),
ValueToIRExpr( Value( TypeType(), VEC( TSID( texpr ), TSID( tfunc ),
ANYTERM( _ ), ANYTERM( _ ), ANYTERM( _ ) ) ) ),
ANYTERM( _ ) ) ),
GetTFuncInvocationRule() );
}
}
|
Changes to bs/builtins/types/template/rules.cpp.
| ︙ | ︙ | |||
149 150 151 152 153 154 155 156 157 158 159 160 161 162 |
}
optional< Term > buildArgPattern( const Context& c, const Value& val ) const final
{
return buildSignature( c, val );
}
};
class ConstantTemplateRule : public TemplateRule
{
optional< Term > buildSignature( const Context& c, const Value& val ) const final
{
return ValueToIRExpr( val );
}
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 |
}
optional< Term > buildArgPattern( const Context& c, const Value& val ) const final
{
return buildSignature( c, val );
}
};
class TVecTemplateRule : public TemplateRule
{
optional< Term > buildSignature( const Context& c, const Value& val ) const final
{
auto tvec = FromValue< TVec >( val );
assert( tvec );
immer::vector< Term > v;
auto vt = v.transient();
for( auto&& x : tvec->content()->terms() )
{
auto s = BuildTemplateSignature( c, x );
if( !s )
return nullopt;
vt.push_back( move( *s ) );
}
return TERM( make_shared< Vector >( vt.persistent() ) );
}
Value buildParamDecl( const Context& c, const Value& param, const Value& arg ) const final
{
return arg;
}
void setup( const Context& c, UnificationContext& uc, const Value& val ) const final
{
auto tvec = FromValue< TVec >( val );
assert( tvec );
for( auto&& x : tvec->content()->terms() )
TemplateSetup( c, uc, x );
}
optional< Term > buildArgPattern( const Context& c, const Value& val ) const final
{
auto tvec = FromValue< TVec >( val );
assert( tvec );
immer::vector< Term > v;
auto vt = v.transient();
for( auto&& x : tvec->content()->terms() )
{
auto s = BuildTemplateArgPattern( c, x );
if( !s )
return nullopt;
vt.push_back( move( *s ) );
}
return TERM( make_shared< Vector >( vt.persistent() ) );
}
};
class ConstantTemplateRule : public TemplateRule
{
optional< Term > buildSignature( const Context& c, const Value& val ) const final
{
return ValueToIRExpr( val );
}
|
| ︙ | ︙ | |||
203 204 205 206 207 208 209 |
return buildSignature( c, val );
}
};
void SetupTemplateRules( Env& e )
{
// Decl
| | > > > > > | | 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 293 294 295 296 297 298 299 300 301 302 |
return buildSignature( c, val );
}
};
void SetupTemplateRules( Env& e )
{
// Decl
auto declTypePat = ValueToIRExpr( Value( TypeType(), VEC( TSID( decl ), ANYTERM( _ ) ) ) );
e.templateRuleSet()->addRule(
ValueToIRExpr( ValuePattern( TSID( constant ), declTypePat, ANYTERM( _ ) ) ),
make_shared< DeclTemplateRule >() );
// TNamedDecl
e.templateRuleSet()->addRule(
ValueToIRExpr( ValuePattern( TSID( constant ), GetValueType< TNamedDecl >(), ANYTERM( _ ) ) ),
make_shared< TNamedDeclTemplateRule >() );
// TDecl
e.templateRuleSet()->addRule(
ValueToIRExpr( ValuePattern( TSID( constant ), GetValueType< TDecl >(), ANYTERM( _ ) ) ),
make_shared< TDeclTemplateRule >() );
// TVar
e.templateRuleSet()->addRule(
ValueToIRExpr( ValuePattern( TSID( constant ), GetValueType< TVar >(), ANYTERM( _ ) ) ),
make_shared< TVarTemplateRule >() );
// TVec
e.templateRuleSet()->addRule(
ValueToIRExpr( ValuePattern( TSID( constant ), GetValueType< TVec >(), ANYTERM( _ ) ) ),
make_shared< TVecTemplateRule >() );
// Constant
e.templateRuleSet()->addRule(
ValueToIRExpr( ValuePattern( TSID( constant ), ANYTERM( _ ), ANYTERM( _ ) ) ),
make_shared< ConstantTemplateRule >() );
// TFuncType
auto tFuncTypePat = ValueToIRExpr( Value( TypeType(), VEC( TSID( texpr ), TSID( tfunc ),
ANYTERM( _ ), ANYTERM( _ ) ) ) );
e.templateRuleSet()->addRule( tFuncTypePat,
make_shared< TFuncTypeTemplateRule >() );
}
}
|
Changes to bs/builtins/types/template/tdecl.cpp.
| ︙ | ︙ | |||
16 17 18 19 20 21 22 |
{
static auto type = ValueToIRExpr( Value( TypeType(), TSID( tdecl ) ) );
return type;
}
Value Bridge< TDecl >::ToValue( const TDecl& td )
{
| | | 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
{
static auto type = ValueToIRExpr( Value( TypeType(), TSID( tdecl ) ) );
return type;
}
Value Bridge< TDecl >::ToValue( const TDecl& td )
{
return Value( Type(), VEC( td.type(), TERM( td.name() ) ) );
}
optional< TDecl > Bridge< TDecl >::FromValue( const Value& v )
{
if( !IsTDecl( v ) )
return nullopt;
|
| ︙ | ︙ |
Changes to bs/builtins/types/template/tfunc.cpp.
| ︙ | ︙ | |||
10 11 12 13 14 15 16 |
Term Bridge< TFunc >::Type( const builtins::TFunc& tf )
{
return ValueToIRExpr( ::ToValue( tf.type() ) );
}
Value Bridge< TFunc >::ToValue( const TFunc& tf )
{
| | | 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
Term Bridge< TFunc >::Type( const builtins::TFunc& tf )
{
return ValueToIRExpr( ::ToValue( tf.type() ) );
}
Value Bridge< TFunc >::ToValue( const TFunc& tf )
{
return Value( Type( tf ), VEC( Quote( tf.signature() ), tf.identity(),
TERM( tf.toks() ) ) );
}
optional< TFunc > Bridge< TFunc >::FromValue( const Value& v )
{
auto typeVal = ValueFromIRExpr( v.type() );
auto type = ::FromValue< TFuncType >( *typeVal );
|
| ︙ | ︙ |
Changes to bs/builtins/types/template/tfunctype.cpp.
| ︙ | ︙ | |||
28 29 30 31 32 33 34 |
const Term& Bridge< TFuncType >::Type()
{
return TypeType();
}
Value Bridge< TFuncType >::ToValue( const TFuncType& tft )
{
| | | 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
const Term& Bridge< TFuncType >::Type()
{
return TypeType();
}
Value Bridge< TFuncType >::ToValue( const TFuncType& tft )
{
return Value( Type(), VEC( TSID( texpr ), TSID( tfunc ),
tft.domain(), tft.returnType(), tft.params() ) );
}
optional< TFuncType > Bridge< TFuncType >::FromValue( const Value& v )
{
auto result = Decompose( v.val(),
Vec(
|
| ︙ | ︙ |
Changes to bs/builtins/types/template/tnameddecl.cpp.
| ︙ | ︙ | |||
16 17 18 19 20 21 22 |
{
static auto type = ValueToIRExpr( Value( TypeType(), TSID( tnameddecl ) ) );
return type;
}
Value Bridge< TNamedDecl >::ToValue( const TNamedDecl& td )
{
| | | 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
{
static auto type = ValueToIRExpr( Value( TypeType(), TSID( tnameddecl ) ) );
return type;
}
Value Bridge< TNamedDecl >::ToValue( const TNamedDecl& td )
{
return Value( Type(), VEC( td.type(), TERM( td.name() ) ) );
}
optional< TNamedDecl > Bridge< TNamedDecl >::FromValue( const Value& v )
{
if( !IsTNamedDecl( v ) )
return nullopt;
|
| ︙ | ︙ |
Changes to bs/builtins/types/template/tvar.cpp.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
#include "builtins/builtins.h"
using namespace empathy::builtins;
namespace empathy::builtins
{
bool IsTExpr( const Value& te )
{
if( te.isConstant() )
{
const auto* ppVec = get_if< pvec >( &te.val() );
if( ppVec && !( *ppVec )->empty()
&&( **ppVec )[0] == TSID( texpr ) )
| > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
#include "builtins/builtins.h"
using namespace empathy::builtins;
namespace empathy::builtins
{
bool IsTExpr( const optional< Value >& te )
{
return te && IsTExpr( *te );
}
bool IsTExpr( const Value& te )
{
if( te.isConstant() )
{
const auto* ppVec = get_if< pvec >( &te.val() );
if( ppVec && !( *ppVec )->empty()
&&( **ppVec )[0] == TSID( texpr ) )
|
| ︙ | ︙ | |||
36 37 38 39 40 41 42 |
}
}
namespace empathy::ir
{
const Term& Bridge< TVar >::Type()
{
| | | 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
}
}
namespace empathy::ir
{
const Term& Bridge< TVar >::Type()
{
static auto type = ValueToIRExpr( Value( TypeType(), VEC( TSID( texpr ), TSID( tvar ) ) ) );
return type;
}
Value Bridge< TVar >::ToValue( TVar&& td )
{
return Value( Type(), TERM( td.name() ) );
}
|
| ︙ | ︙ |
Changes to bs/builtins/types/template/tvar.h.
| ︙ | ︙ | |||
12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
const auto& name() const { return m_name; }
private:
StringId m_name;
};
extern bool IsTExpr( const Value& te );
extern bool IsTVar( const Value& tv );
}
namespace empathy::ir
{
template<>
| > | 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
const auto& name() const { return m_name; }
private:
StringId m_name;
};
extern bool IsTExpr( const optional< Value >& te );
extern bool IsTExpr( const Value& te );
extern bool IsTVar( const Value& tv );
}
namespace empathy::ir
{
template<>
|
| ︙ | ︙ |
Added bs/builtins/types/template/tvec.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 |
#include "builtins/builtins.h"
using namespace empathy::builtins;
namespace empathy::ir
{
const Term& Bridge< TVec >::Type()
{
static auto type = ValueToIRExpr( Value( TypeType(), VEC( TSID( texpr ), TSID( tvec ) ) ) );
return type;
}
Value Bridge< TVec >::ToValue( const TVec& tv )
{
return Value( Type(), tv.content() );
}
optional< TVec > Bridge< TVec >::FromValue( const Value& tv )
{
if( tv.type() != GetValueType< TVec >() )
return nullopt;
auto result = Decompose( tv.val(),
Val< pvec >()
);
if( !result )
return nullopt;
return TVec( move( *result ) );
}
}
|
Added bs/builtins/types/template/tvec.h.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 |
#ifndef EMPATHY_BUILTINS_TYPES_TEMPLATE_TVEC_H
#define EMPATHY_BUILTINS_TYPES_TEMPLATE_TVEC_H
namespace empathy::builtins
{
class TVec
{
public:
template< typename T >
TVec( T&& content ) :
m_content( forward< T >( content ) )
{}
const auto& content() const { return m_content; }
private:
pvec m_content;
};
// Construct either a normal Vector term or a TVec.
// If any of the provided term is a TExpr, construct a TVec.
//
// This is used to construct ir expressions for parametric types,
// 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( ValueFromIRExpr( terms ) ) || ... ) )
return ValueToIRExpr( ToValue( TVec( move( vec ) ) ) );
return vec;
}
#define TVEC( ... ) BuildVecOrTVec( __VA_ARGS__ )
}
namespace empathy::ir
{
template<>
struct Bridge< builtins::TVec >
{
static const Term& Type();
static Value ToValue( const builtins::TVec& tv );
static optional< builtins::TVec > FromValue( const Value& v );
};
}
#endif
|
Changes to bs/builtins/types/template/uni-tdecl.cpp.
| ︙ | ︙ | |||
41 42 43 44 45 46 47 |
uc.setRHSNamespaceIndex( savedRHSNamespaceIndex );
}
}
void SetupTDeclUnification( Env& e )
{
| | | | | 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 |
uc.setRHSNamespaceIndex( savedRHSNamespaceIndex );
}
}
void SetupTDeclUnification( Env& e )
{
auto tDeclPat = ValueToIRExpr( Value( GetValueType< TDecl >(), VEC( ANYTERM( _ ), ANYTERM( _ ) ) ) );
e.unificationRuleSet()->addHalfUnificationRule( tDeclPat,
[]( const Term& lhs, UnificationContext& c ) -> UniGen
{
auto tdecl = FromValue< TDecl >( *ValueFromIRExpr( lhs ) );
assert( tdecl );
co_yield HalfUnify( tdecl->type(), c );
} );
e.unificationRuleSet()->addSymRule( tDeclPat, ANYTERM( _ ), UnifyTDecl );
e.unificationRuleSet()->addSymRule( tDeclPat, UnifyTDecl );
// tfunc tdecl param / tfunc arg
auto tFuncTypePat = ValueToIRExpr( Value( TypeType(), VEC( TSID( texpr ), TSID( tfunc ),
ANYTERM( _ ), ANYTERM( _ ), ANYTERM( _ ) ) ) );
auto tDeclTFuncPat = ValueToIRExpr( Value( GetValueType< TDecl >(), VEC( tFuncTypePat, ANYTERM( _ ) ) ) );
e.unificationRuleSet()->addAsymRule(
tDeclTFuncPat,
ValueToIRExpr( ValuePattern(
TSID( constant ),
|
| ︙ | ︙ |
Changes to bs/builtins/types/template/unify.cpp.
1 2 3 4 5 6 7 8 9 |
#include "builtins/builtins.h"
using namespace empathy;
using namespace empathy::ir;
namespace empathy::builtins
{
void SetupTemplateFunctionUnification( Env& e )
{
| | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
#include "builtins/builtins.h"
using namespace empathy;
using namespace empathy::ir;
namespace empathy::builtins
{
void SetupTemplateFunctionUnification( Env& e )
{
auto funcTypePat = ValueToIRExpr( Value( TypeType(), VEC( TSID( func ),
ANYTERM( _ ), ANYTERM( _ ), ANYTERM( _ ), ANYTERM( _ ) ) ) );
auto tFuncTypePat = ValueToIRExpr( Value( TypeType(), VEC( TSID( texpr ), TSID( tfunc ),
ANYTERM( _ ), ANYTERM( _ ), ANYTERM( _ ) ) ) );
// func type param / tfunc arg
e.unificationRuleSet()->addAsymRule(
ValueToIRExpr( ValuePattern( MkHole( "_"_sid ), move( funcTypePat ), MkHole( "_"_sid ) ) ),
|
| ︙ | ︙ |
Changes to bs/builtins/types/tuple/tuple.cpp.
1 2 3 4 5 6 7 8 9 |
#include "builtins/builtins.h"
using namespace empathy;
using namespace empathy::ir;
namespace empathy::builtins
{
Value MkTupleType( const Term& state, const Term& types )
{
| | | | | | | 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"
using namespace empathy;
using namespace empathy::ir;
namespace empathy::builtins
{
Value MkTupleType( const Term& state, const Term& types )
{
return Value( TypeType(), VEC( TSID( tuple ), state, types ) );
}
const Value& EmptyTupleType()
{
static auto type = MkTupleType( TSID( opened ), VEC() );
return type;
}
const Value& EmptyClosedTupleType()
{
static auto type = MkTupleType( TSID( closed ), VEC() );
return type;
}
const Value& EmptyTuple()
{
static auto val = Value( ValueToIRExpr( EmptyTupleType() ), VEC() );
return val;
}
const Value& EmptyClosedTuple()
{
static auto val = Value( ValueToIRExpr( EmptyClosedTupleType() ), VEC() );
return val;
}
Value AppendToTupleType( const Value& tuptype, const Value& type )
{
auto decomp = Decompose( tuptype.val(),
Vec(
|
| ︙ | ︙ |
Changes to bs/builtins/types/tuple/tuple.inl.
| ︙ | ︙ | |||
65 66 67 68 69 70 71 |
}
}
// Val
template< typename T, size_t... I >
auto BuildTupleValue( const T& tup, index_sequence< I... > )
{
| | | 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 |
}
}
// Val
template< typename T, size_t... I >
auto BuildTupleValue( const T& tup, index_sequence< I... > )
{
return VEC( ValueToIRExpr( ToValue( get< I >( tup ) ) )... );
}
template< typename... T >
Value Bridge< tuple< T... > >::ToValue( const tuple< T... >& x )
{
auto val = BuildTupleValue( x, index_sequence_for< T... >() );
return Value( Type(), move( val ) );
|
| ︙ | ︙ |
Changes to bs/builtins/types/tuple/unify.cpp.
| ︙ | ︙ | |||
9 10 11 12 13 14 15 |
{
// Single element tuple unwrapping rule: if we encounter such a tuple, attempt to unify
// its contained value with whatever's on the other side.
e.unificationRuleSet()->addSymRule(
ValueToIRExpr( ValuePattern(
ANYTERM( _ ),
| | | 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
{
// Single element tuple unwrapping rule: if we encounter such a tuple, attempt to unify
// its contained value with whatever's on the other side.
e.unificationRuleSet()->addSymRule(
ValueToIRExpr( ValuePattern(
ANYTERM( _ ),
ValueToIRExpr( MkTupleType( ANYTERM( _ ), VEC( ANYTERM( _ ) ) ) ),
ANYTERM( _ ) ) ),
ANYTERM( _ ),
[]( const Term& lhs, const Term& rhs, UnificationContext& c ) -> UniGen
{
auto tup = ValueFromIRExpr( lhs );
|
| ︙ | ︙ | |||
34 35 36 37 38 39 40 |
// template parameters to be peeled off). So here's a rule for this case which
// leaves the tuple unchanged. It will take priority over the above rule in
// those cases because it matches a more specific pattern.
e.unificationRuleSet()->addSymRule(
ValueToIRExpr( ValuePattern(
ANYTERM( _ ),
| | | 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
// template parameters to be peeled off). So here's a rule for this case which
// leaves the tuple unchanged. It will take priority over the above rule in
// those cases because it matches a more specific pattern.
e.unificationRuleSet()->addSymRule(
ValueToIRExpr( ValuePattern(
ANYTERM( _ ),
ValueToIRExpr( MkTupleType( ANYTERM( _ ), VEC( ANYTERM( _ ) ) ) ),
ANYTERM( _ ) ) ),
ValueToIRExpr( ValuePattern( ANYTERM( _ ), HolePattern(), ANYTERM( _ ) ) ),
[]( const Term& lhs, const Term& rhs, UnificationContext& c ) -> UniGen
{
co_yield { lhs, c };
} );
}
}
|
Changes to bs/builtins/types/types.h.
| ︙ | ︙ | |||
9 10 11 12 13 14 15 16 17 18 19 20 21 22 | #include "func/bfunc.h" #include "func/func.h" #include "func/build.h" #include "intrinsic/intrinsic.h" #include "template/tvar.h" #include "template/tdecl.h" #include "template/tnameddecl.h" #include "template/tfunctype.h" #include "template/tfunc.h" #include "template/build.h" #include "template/rules.h" | > | 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | #include "func/bfunc.h" #include "func/func.h" #include "func/build.h" #include "intrinsic/intrinsic.h" #include "template/tvar.h" #include "template/tvec.h" #include "template/tdecl.h" #include "template/tnameddecl.h" #include "template/tfunctype.h" #include "template/tfunc.h" #include "template/build.h" #include "template/rules.h" |
| ︙ | ︙ |
Changes to bs/ir/term.h.
| ︙ | ︙ | |||
60 61 62 63 64 65 66 | } #define TERM( x ) ir::Term( x ) #define TSTR( x ) TERM( string( x ) ) #define TSID( x ) TERM( #x##_sid ) #define ANYTERM( x ) TERM( ir::AnyTerm( #x##_sid ) ) #define VECOFLENGTH( x ) TERM( ir::VecOfLength( #x##_sid ) ) | | | 60 61 62 63 64 65 66 67 68 69 70 | } #define TERM( x ) ir::Term( x ) #define TSTR( x ) TERM( string( x ) ) #define TSID( x ) TERM( #x##_sid ) #define ANYTERM( x ) TERM( ir::AnyTerm( #x##_sid ) ) #define VECOFLENGTH( x ) TERM( ir::VecOfLength( #x##_sid ) ) #define VEC( ... ) TERM( ir::Vector::Make( __VA_ARGS__ ) ) #define REPEAT( x ) ir::Repetition( x ) #endif |
Changes to bs/ir/tests/match-terms-trie.cpp.
| ︙ | ︙ | |||
8 9 10 11 12 13 14 |
SCENARIO( "Match works", "[match]" )
{
WHEN( "Matching various expressions against various patterns stored in a trie" )
{
auto pat0 = ANYTERM( a );
| | | | | | | | | | | | | | | | | | | | | | | | | | | | 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 |
SCENARIO( "Match works", "[match]" )
{
WHEN( "Matching various expressions against various patterns stored in a trie" )
{
auto pat0 = ANYTERM( a );
auto pat1 = VEC(
VEC( TSTR( "foo" ), TSTR( "bar" ) ),
VEC(),
VEC( TSTR( "foo" ), TSTR( "bar" ) ),
VEC( TSTR( "foo" ), TSTR( "bar" ) )
);
auto expr1 = pat1;
auto pat2 = VEC(
VEC( ANYTERM( a ), TSTR( "bar" ) ),
VEC(),
VEC( ANYTERM( a ), TSTR( "bar" ) ),
VEC( ANYTERM( a ), TSTR( "bar" ) )
);
auto expr2 = VEC(
VEC( TSTR( "meh" ), TSTR( "bar" ) ),
VEC(),
VEC( TSTR( "meh" ), TSTR( "bar" ) ),
VEC( TSTR( "meh" ), TSTR( "bar" ) )
);
auto pat3 = VEC(
ANYTERM( x ),
VEC( ANYTERM( a ), TSTR( "bar" ) ),
ANYTERM( z ),
ANYTERM( z )
);
auto expr3 = VEC(
TSID( a ),
VEC( TSTR( "meh" ), TSTR( "bar" ) ),
TSID( b ),
TSID( b )
);
auto pat4 = VEC(
VEC( ANYTERM( a ), TSTR( "bar" ) ),
ANYTERM( y ),
ANYTERM( y ),
ANYTERM( y )
);
auto expr4 = VEC(
VEC( TSTR( "huh" ), TSTR( "bar" ) ),
VEC(),
VEC(),
VEC()
);
Trie< string > testTrie1;
testTrie1 = Merge( testTrie1, pat0, []( auto&& ){ return "pat0"s; } );
testTrie1 = Merge( testTrie1, pat1, []( auto&& ){ return "pat1"s; } );
testTrie1 = Merge( testTrie1, pat2, []( auto&& ){ return "pat2"s; } );
testTrie1 = Merge( testTrie1, pat3, []( auto&& ){ return "pat3"s; } );
|
| ︙ | ︙ |
Changes to bs/ir/tests/match-terms.cpp.
| ︙ | ︙ | |||
8 9 10 11 12 13 14 |
SCENARIO( "Match works", "[match]" )
{
WHEN( "Matching various expressions against various patterns" )
{
auto pat0 = ANYTERM( a );
| | | | | | | | | | | | | | | | | | | | | | | | | | | | 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 |
SCENARIO( "Match works", "[match]" )
{
WHEN( "Matching various expressions against various patterns" )
{
auto pat0 = ANYTERM( a );
auto pat1 = VEC(
VEC( TSTR( "foo" ), TSTR( "bar" ) ),
VEC(),
VEC( TSTR( "foo" ), TSTR( "bar" ) ),
VEC( TSTR( "foo" ), TSTR( "bar" ) )
);
auto expr1 = pat1;
auto pat2 = VEC(
VEC( ANYTERM( a ), TSTR( "bar" ) ),
VEC(),
VEC( ANYTERM( a ), TSTR( "bar" ) ),
VEC( ANYTERM( a ), TSTR( "bar" ) )
);
auto expr2 = VEC(
VEC( TSTR( "meh" ), TSTR( "bar" ) ),
VEC(),
VEC( TSTR( "meh" ), TSTR( "bar" ) ),
VEC( TSTR( "meh" ), TSTR( "bar" ) )
);
auto pat3 = VEC(
ANYTERM( x ),
VEC( ANYTERM( a ), TSTR( "bar" ) ),
ANYTERM( z ),
ANYTERM( z )
);
auto expr3 = VEC(
TSID( a ),
VEC( TSTR( "meh" ), TSTR( "bar" ) ),
TSID( b ),
TSID( b )
);
auto pat4 = VEC(
VEC( ANYTERM( a ), TSTR( "bar" ) ),
ANYTERM( y ),
ANYTERM( y ),
ANYTERM( y )
);
auto expr4 = VEC(
VEC( TSTR( "huh" ), TSTR( "bar" ) ),
VEC(),
VEC(),
VEC()
);
THEN( "Matching the terms and patterns work as expected" )
{
auto s10 = Match( expr1, pat0 );
auto s11 = Match( expr1, pat1 );
auto s12 = Match( expr1, pat2 );
|
| ︙ | ︙ |
Changes to bs/ir/tests/match-tries.cpp.
| ︙ | ︙ | |||
8 9 10 11 12 13 14 |
SCENARIO( "Match works", "[match]" )
{
WHEN( "Matching various expressions against various patterns stored in a trie" )
{
auto pat0 = ANYTERM( a );
| | | | | | | | | | | | | | | | | | | | | | | | | | | | 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 |
SCENARIO( "Match works", "[match]" )
{
WHEN( "Matching various expressions against various patterns stored in a trie" )
{
auto pat0 = ANYTERM( a );
auto pat1 = VEC(
VEC( TSTR( "foo" ), TSTR( "bar" ) ),
VEC(),
VEC( TSTR( "foo" ), TSTR( "bar" ) ),
VEC( TSTR( "foo" ), TSTR( "bar" ) )
);
auto expr1 = pat1;
auto pat2 = VEC(
VEC( ANYTERM( a ), TSTR( "bar" ) ),
VEC(),
VEC( ANYTERM( a ), TSTR( "bar" ) ),
VEC( ANYTERM( a ), TSTR( "bar" ) )
);
auto expr2 = VEC(
VEC( TSTR( "meh" ), TSTR( "bar" ) ),
VEC(),
VEC( TSTR( "meh" ), TSTR( "bar" ) ),
VEC( TSTR( "meh" ), TSTR( "bar" ) )
);
auto pat3 = VEC(
ANYTERM( x ),
VEC( ANYTERM( a ), TSTR( "bar" ) ),
ANYTERM( z ),
ANYTERM( z )
);
auto expr3 = VEC(
TSID( a ),
VEC( TSTR( "meh" ), TSTR( "bar" ) ),
TSID( b ),
TSID( b )
);
auto pat4 = VEC(
VEC( ANYTERM( a ), TSTR( "bar" ) ),
ANYTERM( y ),
ANYTERM( y ),
ANYTERM( y )
);
auto expr4 = VEC(
VEC( TSTR( "huh" ), TSTR( "bar" ) ),
VEC(),
VEC(),
VEC()
);
Trie< string > testPatTrie;
testPatTrie = Merge( testPatTrie, pat0, []( auto&& ){ return "pat0"s; } );
testPatTrie = Merge( testPatTrie, pat1, []( auto&& ){ return "pat1"s; } );
testPatTrie = Merge( testPatTrie, pat2, []( auto&& ){ return "pat2"s; } );
testPatTrie = Merge( testPatTrie, pat3, []( auto&& ){ return "pat3"s; } );
|
| ︙ | ︙ |
Changes to bs/ir/tests/merge-tries.cpp.
| ︙ | ︙ | |||
8 9 10 11 12 13 14 |
SCENARIO( "Merge works", "[merge]" )
{
WHEN( "Merging tries together" )
{
auto pat0 = ANYTERM( a );
| | | | | | | | | | | | | | | | | | | | | | | | | | | | 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 |
SCENARIO( "Merge works", "[merge]" )
{
WHEN( "Merging tries together" )
{
auto pat0 = ANYTERM( a );
auto pat1 = VEC(
VEC( TSTR( "foo" ), TSTR( "bar" ) ),
VEC(),
VEC( TSTR( "foo" ), TSTR( "bar" ) ),
VEC( TSTR( "foo" ), TSTR( "bar" ) )
);
auto pat2 = VEC(
VEC( ANYTERM( a ), TSTR( "bar" ) ),
VEC(),
VEC( ANYTERM( a ), TSTR( "bar" ) ),
VEC( ANYTERM( a ), TSTR( "bar" ) )
);
auto pat3 = VEC(
ANYTERM( x ),
VEC( ANYTERM( a ), TSTR( "bar" ) ),
ANYTERM( z ),
ANYTERM( z )
);
auto pat4 = VEC(
VEC( ANYTERM( a ), TSTR( "bar" ) ),
ANYTERM( y ),
ANYTERM( y ),
ANYTERM( y )
);
auto pat5 = VEC(
VEC( TSTR( "foo" ), ANYTERM( b ) ),
ANYTERM( y ),
ANYTERM( y ),
VEC( TSTR( "foo" ), ANYTERM( b ) )
);
auto pat6 = VEC(
ANYTERM( x ),
VEC( TSTR( "foo" ), TSTR( "bar" ) ),
VEC( TSTR( "foo" ), TSTR( "bar" ) ),
VEC( TSTR( "foo" ), TSTR( "baz" ) )
);
auto pat7 = VEC(
ANYTERM( v ),
ANYTERM( w ),
ANYTERM( v ),
VEC( TSTR( "foo" ), TSTR( "bar" ) )
);
auto pat8 = VEC(
ANYTERM( x ),
VEC( ANYTERM( a ), TSTR( "bar" ) ),
ANYTERM( x ),
VEC( TSTR( "foo" ), ANYTERM( b ) )
);
Trie<> testTrie1;
testTrie1 = Merge( testTrie1, pat0 );
testTrie1 = Merge( testTrie1, pat1 );
testTrie1 = Merge( testTrie1, pat2 );
testTrie1 = Merge( testTrie1, pat3 );
|
| ︙ | ︙ |
Changes to bs/ir/tests/merge.cpp.
| ︙ | ︙ | |||
8 9 10 11 12 13 14 |
SCENARIO( "Merge works", "[merge]" )
{
WHEN( "Merging multiple terms into a trie" )
{
auto pat0 = ANYTERM( a );
| | | | | | | | | | | | | | | | | | | | | | | | | | | | 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 |
SCENARIO( "Merge works", "[merge]" )
{
WHEN( "Merging multiple terms into a trie" )
{
auto pat0 = ANYTERM( a );
auto pat1 = VEC(
VEC( TSTR( "foo" ), TSTR( "bar" ) ),
VEC(),
VEC( TSTR( "foo" ), TSTR( "bar" ) ),
VEC( TSTR( "foo" ), TSTR( "bar" ) )
);
auto pat2 = VEC(
VEC( ANYTERM( a ), TSTR( "bar" ) ),
VEC(),
VEC( ANYTERM( a ), TSTR( "bar" ) ),
VEC( ANYTERM( a ), TSTR( "bar" ) )
);
auto pat3 = VEC(
ANYTERM( x ),
VEC( ANYTERM( a ), TSTR( "bar" ) ),
ANYTERM( z ),
ANYTERM( z )
);
auto pat4 = VEC(
VEC( ANYTERM( a ), TSTR( "bar" ) ),
ANYTERM( y ),
ANYTERM( y ),
ANYTERM( y )
);
auto pat5 = VEC(
VEC( TSTR( "foo" ), ANYTERM( b ) ),
ANYTERM( y ),
ANYTERM( y ),
VEC( TSTR( "foo" ), ANYTERM( b ) )
);
auto pat6 = VEC(
ANYTERM( x ),
VEC( TSTR( "foo" ), TSTR( "bar" ) ),
VEC( TSTR( "foo" ), TSTR( "bar" ) ),
VEC( TSTR( "foo" ), TSTR( "baz" ) )
);
auto pat7 = VEC(
ANYTERM( v ),
ANYTERM( w ),
ANYTERM( v ),
VEC( TSTR( "foo" ), TSTR( "bar" ) )
);
auto pat8 = VEC(
ANYTERM( x ),
VEC( ANYTERM( a ), TSTR( "bar" ) ),
ANYTERM( x ),
VEC( TSTR( "foo" ), ANYTERM( b ) )
);
Trie<> testTrie1;
testTrie1 = Merge( testTrie1, pat0 );
testTrie1 = Merge( testTrie1, pat1 );
testTrie1 = Merge( testTrie1, pat2 );
testTrie1 = Merge( testTrie1, pat3 );
|
| ︙ | ︙ |
Changes to bs/ir/value.cpp.
| ︙ | ︙ | |||
13 14 15 16 17 18 19 |
);
return !!result;
}
const Term& TypeType()
{
| | | 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
);
return !!result;
}
const Term& TypeType()
{
static auto typeType = VEC( TSID( type ), TERM( 0U ),
static_cast< LocationId >( 0 ) );
return typeType;
}
// A generic poisoned value of "type" type.
const Value& PoisonType()
{
|
| ︙ | ︙ | |||
43 44 45 46 47 48 49 |
// Special case for type's type
if( v.isType() )
{
auto result = Decompose( v.val(),
Val< uint32_t >()
);
if( result )
| | | | | | 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 |
// Special case for type's type
if( v.isType() )
{
auto result = Decompose( v.val(),
Val< uint32_t >()
);
if( result )
return VEC( TSID( type ), TERM( result->get() ),
static_cast< LocationId >( v.locationId() ) );
}
return VEC( TSID( value ), TSID( constant ), v.type(), v.val(),
static_cast< LocationId >( v.locationId() ) );
}
return VEC( TSID( value ), TSID( computed ), v.type(),
TERM( static_pointer_cast< void >( v.llr() ) ),
static_cast< LocationId >( v.locationId() ) );
}
optional< Value > ValueFromIRExpr( const Term& t )
{
// Special case for type's type
auto typedecomp = Decompose( t,
Vec(
Lit( "type"_sid ),
Val< uint32_t >(),
Val< LocationId >()
)
);
if( typedecomp )
{
auto&& [universeIndex, loc] = *typedecomp;
return Value( VEC( TSID( type ), TERM( universeIndex + 1 ) ), TERM( universeIndex ),
static_cast< uint32_t >( loc ) );
}
auto result = Decompose( t,
Vec(
Lit( "value"_sid ),
Val< StringId >(),
|
| ︙ | ︙ | |||
100 101 102 103 104 105 106 |
return nullopt;
return Value( type, static_pointer_cast< llr::Instruction >( ptr< void >( *llr ) ), static_cast< uint32_t >( locationId ) );
}
Term ValueToIRExpr( const ValuePattern& v )
{
| | | 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 |
return nullopt;
return Value( type, static_pointer_cast< llr::Instruction >( ptr< void >( *llr ) ), static_cast< uint32_t >( locationId ) );
}
Term ValueToIRExpr( const ValuePattern& v )
{
return VEC( TSID( value ), v.sort(), v.type(), v.val(), static_cast< LocationId >( v.locationId() ) );
}
optional< ValuePattern > ValuePatternFromIRExpr( const Term& t )
{
auto result = Decompose( t,
Vec(
Lit( "value"_sid ),
|
| ︙ | ︙ |
Changes to bs/sema/env.cpp.
| ︙ | ︙ | |||
22 23 24 25 26 27 28 |
result = val;
return Status::Success;
} ) );
}
void Env::storeValue( const Term& idPat, const Term& contextIdPat, const ptr< ValueProvider >& valp )
{
| | | 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
result = val;
return Status::Success;
} ) );
}
void Env::storeValue( const Term& idPat, const Term& contextIdPat, const ptr< ValueProvider >& valp )
{
m_valueStore = Merge( m_valueStore, VEC( idPat, contextIdPat ),
[valp]( auto&& oldValp )
{
if( !oldValp )
return valp;
// If another value provider was already registered with the same pattern,
// combine them through a lambda that will call them both and check for ambiguousness.
|
| ︙ | ︙ | |||
59 60 61 62 63 64 65 |
Env::Status Env::retrieveValue( const Term& id, const Term& contextId, Term& result )
{
MatchSolution bestSol;
ptr< ValueProvider > bestProvider;
bool ambiguous = false;
| | | 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
Env::Status Env::retrieveValue( const Term& id, const Term& contextId, Term& result )
{
MatchSolution bestSol;
ptr< ValueProvider > bestProvider;
bool ambiguous = false;
auto pat = VEC( id, contextId );
for( auto&& [s, provider] : Match( pat, m_valueStore ) )
{
if( !bestProvider || s > bestSol )
{
bestSol = s;
bestProvider = provider;
|
| ︙ | ︙ |
Changes to bs/sema/hole.cpp.
1 2 3 4 5 6 7 8 |
#include "sema.h"
namespace empathy::sema
{
Term MkHole( const Hole& h )
{
return visit( [&]( auto&& x )
{
| | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
#include "sema.h"
namespace empathy::sema
{
Term MkHole( const Hole& h )
{
return visit( [&]( auto&& x )
{
return SetComplexity( VEC( TSID( hole ), TERM( x ) ), 0 );
}, h );
}
const Term& HolePattern()
{
static auto hp = VEC( TSID( hole ), ANYTERM( _ ) );
return hp;
}
optional< Hole > HoleFromIRExpr( const Term& t )
{
auto resultUnnamed = Decompose( t,
Vec(
|
| ︙ | ︙ |
Changes to bs/sema/postprocess.cpp.
1 2 3 4 5 6 |
#include "sema.h"
namespace empathy::sema
{
Term WrapWithPostprocFunc( const Term& t, const ptr< PostProcFunc >& pp )
{
| | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
#include "sema.h"
namespace empathy::sema
{
Term WrapWithPostprocFunc( const Term& t, const ptr< PostProcFunc >& pp )
{
return SetComplexity( VEC( TSID( postproc ),
TERM( static_pointer_cast< void >( pp ) ),
t ), 0 );
}
Term WrapWithPostprocFunc( const Term& t, PostProcFunc&& pp )
{
return SetComplexity( VEC( TSID( postproc ),
TERM( static_pointer_cast< void >( make_shared< PostProcFunc >( move( pp ) ) ) ),
t ), 0 );
}
optional< pair< Term, ptr< PostProcFunc > > > UnwrapPostprocFunc( const Term& ppt )
{
auto result = Decompose( ppt,
|
| ︙ | ︙ |
Changes to bs/sema/tests/unify-holes.cpp.
| ︙ | ︙ | |||
11 12 13 14 15 16 17 |
namespace
{
// Verifies that the unification of lhs and rhs yields only one solution, that it is complete,
// and that this solution is the expected one.
void CheckForUniqueSolution( const Term& lhs, const Term& rhs, const Term& expectedSolution, const UnificationScore& expectedScore )
{
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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 95 96 97 98 99 100 101 102 |
namespace
{
// Verifies that the unification of lhs and rhs yields only one solution, that it is complete,
// and that this solution is the expected one.
void CheckForUniqueSolution( const Term& lhs, const Term& rhs, const Term& expectedSolution, const UnificationScore& expectedScore )
{
Context ctxt( make_shared< Env >(), VEC( TSID( e0 ) ), GetValueType< void >() );
auto g = FullUnify( lhs, rhs, ctxt );
auto it = g.begin();
REQUIRE( it != g.end() );
auto&& [e,c] = *it;
REQUIRE( c.numUnknownValues() == 0 );
REQUIRE( c.score() == expectedScore );
auto sol = Substitute( e, c );
REQUIRE( sol == expectedSolution );
++it;
REQUIRE( it == g.end() );
}
void CheckForNoSolution( const Term& lhs, const Term& rhs )
{
Context ctxt( make_shared< Env >(), VEC( TSID( e0 ) ), GetValueType< void >() );
auto g = FullUnify( lhs, rhs, ctxt );
auto it = g.begin();
REQUIRE( it == g.end() );
}
}
SCENARIO( "Unify works", "[unify]" )
{
WHEN( "Unifying various expressions" )
{
auto expr0 = MkHole( "a"_sid );
auto expr1 = VEC( TSTR( "foo" ), TSTR( "bar" ) );
auto expr2 = VEC( MkHole( "a"_sid ), MkHole( "a"_sid ) );
auto expr3 = VEC( TSTR( "meh" ), TSTR( "meh" ) );
auto expr4 = VEC( MkHole( "a"_sid ), TSTR( "bar" ) );
auto expr5 = VEC( TSTR( "foo" ), MkHole( "b"_sid ) );
auto expr6 = VEC( MkHole( "a"_sid ), MkHole( "a"_sid ) );
auto expr7 = VEC( TSTR( "foo" ), MkHole( "b"_sid ) );
auto expr8 = VEC( MkHole( "a"_sid ), MkHole( "a"_sid ) );
auto expr9 = VEC( expr5, expr1 );
auto expr10 = VEC( MkHole( "x"_sid ), expr4, MkHole( "z"_sid ), MkHole( "z"_sid ) );
auto expr11 = VEC( expr5, MkHole( "y"_sid ), MkHole( "y"_sid ), expr5 );
auto expr12 = VEC( VEC( MkHole( "a"_sid ), TSTR( "foo" ) ), MkHole( "a"_sid ) );
auto expr13 = VEC( MkHole( "b"_sid ), MkHole( "b"_sid ) );
THEN( "Unifications yields the expected solutions" )
{
CheckForUniqueSolution( expr0, expr1, VEC( TSTR( "foo" ), TSTR( "bar" ) ), { 1, 1 } );
CheckForUniqueSolution( expr2, expr3, VEC( TSTR( "meh" ), TSTR( "meh" ) ), { 2, 1 } );
CheckForNoSolution( expr2, expr1 );
CheckForUniqueSolution( expr4, expr5, VEC( TSTR( "foo" ), TSTR( "bar" ) ), { 2, 2 } );
CheckForUniqueSolution( expr6, expr7, VEC( TSTR( "foo" ), TSTR( "foo" ) ), { 2, 2 } );
CheckForUniqueSolution( expr8, expr9,
VEC(
VEC( TSTR( "foo" ), TSTR( "bar" ) ),
VEC( TSTR( "foo" ), TSTR( "bar" ) )
),
{ 4, 2 }
);
CheckForUniqueSolution( expr10, expr11,
VEC(
VEC( TSTR( "foo" ), TSTR( "bar" ) ),
VEC( TSTR( "foo" ), TSTR( "bar" ) ),
VEC( TSTR( "foo" ), TSTR( "bar" ) ),
VEC( TSTR( "foo" ), TSTR( "bar" ) )
),
{ 5, 5 }
);
CheckForNoSolution( expr12, expr13 );
}
}
}
|
Changes to bs/sema/tests/utrie-merge.cpp.
| ︙ | ︙ | |||
26 27 28 29 30 31 32 |
auto vec8 = Vector::Make( MkHole( "a"_sid ), MkHole( "c"_sid ) );
auto vec9 = Vector::Make( TERM( vec5 ), TERM( vec1 ) );
auto vec10 = Vector::Make( MkHole( "x"_sid ), TERM( vec4 ), MkHole( "z"_sid ), MkHole( "z"_sid ) );
auto vec11 = Vector::Make( TERM( vec5 ), MkHole( "y"_sid ), MkHole( "y"_sid ), TERM( vec5 ) );
| | | | 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 |
auto vec8 = Vector::Make( MkHole( "a"_sid ), MkHole( "c"_sid ) );
auto vec9 = Vector::Make( TERM( vec5 ), TERM( vec1 ) );
auto vec10 = Vector::Make( MkHole( "x"_sid ), TERM( vec4 ), MkHole( "z"_sid ), MkHole( "z"_sid ) );
auto vec11 = Vector::Make( TERM( vec5 ), MkHole( "y"_sid ), MkHole( "y"_sid ), TERM( vec5 ) );
auto vec12 = Vector::Make( VEC( MkHole( "a"_sid ), TSTR( "foo" ) ), MkHole( "a"_sid ) );
auto vec13 = Vector::Make( MkHole( "b"_sid ), MkHole( "b"_sid ) );
auto trie = UTrie< string >().merge( *vec1, []( auto&& ){ return "vec1"s; } );
trie = trie->merge( *vec2, []( auto&& ){ return "vec2"s; } );
trie = trie->merge( *vec3, []( auto&& ){ return "vec3"s; } );
trie = trie->merge( *vec4, []( auto&& ){ return "vec4"s; } );
trie = trie->merge( *vec5, []( auto&& ){ return "vec5"s; } );
trie = trie->merge( *vec6, []( auto&& ){ return "vec6"s; } );
trie = trie->merge( *vec7, []( auto&& ){ return "vec7"s; } );
trie = trie->merge( *vec8, []( auto&& ){ return "vec8"s; } );
trie = trie->merge( *vec9, []( auto&& ){ return "vec9"s; } );
trie = trie->merge( *vec10, []( auto&& ){ return "vec10"s; } );
trie = trie->merge( *vec11, []( auto&& ){ return "vec11"s; } );
trie = trie->merge( *vec12, []( auto&& ){ return "vec12"s; } );
trie = trie->merge( *vec13, []( auto&& ){ return "vec13"s; } );
THEN( "Half-unifications yields the expected solutions" )
{
Context ctxt( make_shared< Env >(), VEC( TSID( e0 ) ), GetValueType< void >() );
UnificationContext context( ctxt );
vector< pair< string, UnificationScore > > results;
for( auto&& [lv, s,content,uc] : trie->halfUnify( context ) )
results.emplace_back( content, uc.score() );
|
| ︙ | ︙ |
Changes to bs/sema/tests/utrie-unify.cpp.
| ︙ | ︙ | |||
9 10 11 12 13 14 15 |
using namespace empathy::sema;
using namespace empathy::builtins;
namespace
{
auto GetSortedSolutions( ptr< UTrie< string > >& trie, const Vector& vec )
{
| | | 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
using namespace empathy::sema;
using namespace empathy::builtins;
namespace
{
auto GetSortedSolutions( ptr< UTrie< string > >& trie, const Vector& vec )
{
Context ctxt( make_shared< Env >(), VEC( TSID( e0 ) ), GetValueType< void >() );
UnificationContext context( ctxt );
vector< tuple< Term, string, UnificationScore > > solutions;
for( auto&& [lv, v,content,c] : trie->unify( vec, context ) )
{
if( c.numUnknownValues() )
|
| ︙ | ︙ | |||
49 50 51 52 53 54 55 |
auto vec5 = Vector::Make( TSTR( "foo" ), MkHole( "b"_sid ) );
auto vec9 = Vector::Make( TERM( vec5 ), TERM( vec1 ) );
auto vec10 = Vector::Make( MkHole( "x"_sid ), TERM( vec4 ), MkHole( "z"_sid ), MkHole( "z"_sid ) );
auto vec11 = Vector::Make( TERM( vec5 ), MkHole( "y"_sid ), MkHole( "y"_sid ), TERM( vec5 ) );
| | | | | | | | | | | | | | | | 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 |
auto vec5 = Vector::Make( TSTR( "foo" ), MkHole( "b"_sid ) );
auto vec9 = Vector::Make( TERM( vec5 ), TERM( vec1 ) );
auto vec10 = Vector::Make( MkHole( "x"_sid ), TERM( vec4 ), MkHole( "z"_sid ), MkHole( "z"_sid ) );
auto vec11 = Vector::Make( TERM( vec5 ), MkHole( "y"_sid ), MkHole( "y"_sid ), TERM( vec5 ) );
auto vec12 = Vector::Make( VEC( MkHole( "a"_sid ), TSTR( "foo" ) ), MkHole( "a"_sid ) );
auto vec13 = Vector::Make( MkHole( "b"_sid ), MkHole( "b"_sid ) );
auto trie = UTrie< string >().merge( *vec2, []( auto&& ){ return "vec2"s; } );
trie = trie->merge( *vec4, []( auto&& ){ return "vec4"s; } );
trie = trie->merge( *vec10, []( auto&& ){ return "vec10"s; } );
trie = trie->merge( *vec12, []( auto&& ){ return "vec12"s; } );
THEN( "We obtain the expected solutions" )
{
auto sols1 = GetSortedSolutions( trie, *vec1 );
auto sols3 = GetSortedSolutions( trie, *vec3 );
auto sols5 = GetSortedSolutions( trie, *vec5 );
auto sols9 = GetSortedSolutions( trie, *vec9 );
auto sols11 = GetSortedSolutions( trie, *vec11 );
auto sols13 = GetSortedSolutions( trie, *vec13 );
REQUIRE( sols1.size() == 1 );
REQUIRE( sols1[0] == make_tuple( VEC( TSTR( "foo" ), TSTR( "bar" ) ), "vec4"s, UnificationScore( 2, 1 ) ) );
REQUIRE( sols3.size() == 1 );
REQUIRE( sols3[0] == make_tuple( VEC( TSTR( "meh" ), TSTR( "meh" ) ), "vec2"s, UnificationScore( 2, 1 ) ) );
REQUIRE( sols5.size() == 2 );
REQUIRE( sols5[0] == make_tuple( VEC( TSTR( "foo" ), TSTR( "foo" ) ), "vec2"s, UnificationScore( 2, 2 ) ) );
REQUIRE( sols5[1] == make_tuple( VEC( TSTR( "foo" ), TSTR( "bar" ) ), "vec4"s, UnificationScore( 2, 2 ) ) );
REQUIRE( sols9.size() == 1 );
REQUIRE( sols9[0] == make_tuple(
VEC(
VEC( TSTR( "foo" ), TSTR( "bar" ) ),
VEC( TSTR( "foo" ), TSTR( "bar" ) )
), "vec2"s, UnificationScore( 4, 2 ) )
);
REQUIRE( sols11.size() == 1 );
REQUIRE( sols11[0] == make_tuple(
VEC(
VEC( TSTR( "foo" ), TSTR( "bar" ) ),
VEC( TSTR( "foo" ), TSTR( "bar" ) ),
VEC( TSTR( "foo" ), TSTR( "bar" ) ),
VEC( TSTR( "foo" ), TSTR( "bar" ) )
), "vec10"s, UnificationScore( 5, 5 ) )
);
REQUIRE( sols13.size() == 1 );
REQUIRE( sols13[0] == make_tuple( VEC( TSTR( "bar" ), TSTR( "bar" ) ), "vec4"s, UnificationScore( 2, 2 ) ) );
}
}
}
|
Changes to bs/sema/uni-holes.cpp.
1 2 3 4 5 6 7 8 9 |
#include "sema.h"
namespace empathy::sema
{
void SetupHoleUnificationRules( UnificationRuleSet& ruleSet )
{
// Hole half-unification: Convert it to a numbered hole,
// If the name wasn't already known, add 1 to the score's unique holes count.
ruleSet.addHalfUnificationRule(
| | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
#include "sema.h"
namespace empathy::sema
{
void SetupHoleUnificationRules( UnificationRuleSet& ruleSet )
{
// Hole half-unification: Convert it to a numbered hole,
// If the name wasn't already known, add 1 to the score's unique holes count.
ruleSet.addHalfUnificationRule(
VEC( TSID( hole ), ANYTERM( _ ) ),
[]( const Term& lhs, UnificationContext& c ) -> UniGen
{
auto lh = *HoleFromIRExpr( lhs );
if( holds_alternative< StringId >( lh ) )
{
// This is a named hole: look up its name.
|
| ︙ | ︙ | |||
38 39 40 41 42 43 44 |
if( !c.isHoleLocked( get< uint32_t >( lh ) ) )
co_yield { lhs, c };
}
} );
// Hole vs anything
ruleSet.addSymRule(
| | | 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
if( !c.isHoleLocked( get< uint32_t >( lh ) ) )
co_yield { lhs, c };
}
} );
// Hole vs anything
ruleSet.addSymRule(
VEC( TSID( hole ), ANYTERM( _ ) ),
ANYTERM( _ ),
[]( const Term& lhs, const Term& rhs, UnificationContext& c ) -> UniGen
{
auto h = *HoleFromIRExpr( lhs );
uint32_t index = 0;
// Remember the previous complexity count so we know how much complexity
|
| ︙ | ︙ | |||
108 109 110 111 112 113 114 |
c.flip();
}
} );
// Hole vs hole
ruleSet.addAsymRule(
| | | | 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 |
c.flip();
}
} );
// Hole vs hole
ruleSet.addAsymRule(
VEC( TSID( hole ), ANYTERM( _ ) ),
VEC( TSID( hole ), ANYTERM( _ ) ),
[]( const Term& lhs, const Term& rhs, UnificationContext& c ) -> UniGen
{
auto lh = *HoleFromIRExpr( lhs );
auto rh = *HoleFromIRExpr( rhs );
StringId lname;
StringId rname;
|
| ︙ | ︙ |
Changes to bs/sema/uni-postproc.cpp.
1 2 3 4 5 6 7 8 9 |
#include "sema.h"
namespace empathy::sema
{
// When encountering a postprocess wrapper during unification, strip it away
// and unify the content. The wrapper will be put back by the inner unification
// rule.
void SetupPostProcUnificationRules( UnificationRuleSet& ruleSet )
{
| | | | | 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 "sema.h"
namespace empathy::sema
{
// When encountering a postprocess wrapper during unification, strip it away
// and unify the content. The wrapper will be put back by the inner unification
// rule.
void SetupPostProcUnificationRules( UnificationRuleSet& ruleSet )
{
ruleSet.addSymRule( VEC( TSID( postproc ), ANYTERM( _ ), ANYTERM( _ ) ), ANYTERM( _ ),
[]( const Term& lhs, const Term& rhs, UnificationContext& c ) -> UniGen
{
auto unwrap = UnwrapPostprocFunc( lhs );
if( !unwrap )
co_return;
auto&& [t,pp] = *unwrap;
co_yield Unify( t, rhs, c );
for( auto&& [s,c] : Unify( t, rhs, c ) )
co_yield { t, c };
} );
ruleSet.addAsymRule(
VEC( TSID( postproc ), ANYTERM( _ ), ANYTERM( _ ) ),
VEC( TSID( postproc ), ANYTERM( _ ), ANYTERM( _ ) ),
[]( const Term& lhs, const Term& rhs, UnificationContext& c ) -> UniGen
{
auto unwrap = UnwrapPostprocFunc( lhs );
if( !unwrap )
co_return;
auto&& [t,pp] = *unwrap;
for( auto&& [s,c] : Unify( t, rhs, c ) )
co_yield { t, c };
} );
}
}
|
Changes to bs/sema/uni-quote.cpp.
1 2 3 4 5 6 |
#include "sema.h"
namespace empathy::sema
{
Term Quote( const Term& t )
{
| | | | | 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 |
#include "sema.h"
namespace empathy::sema
{
Term Quote( const Term& t )
{
return SetComplexity( VEC( TSID( quote ), t ), 0 );
}
optional< Term > Unquote( const Term& t )
{
auto result = Decompose( t,
Vec(
Lit( "quote"_sid ),
SubTerm()
)
);
if( !result )
return nullopt;
auto&& [quoted] = *result;
return quoted;
}
void SetupQuoteUnificationRules( UnificationRuleSet& ruleSet )
{
ruleSet.addHalfUnificationRule( VEC( TSID( quote ), ANYTERM( _ ) ),
[]( const Term& lhs, UnificationContext& c ) -> UniGen
{
co_yield { lhs, c };
} );
ruleSet.addSymRule( VEC( TSID( quote ), ANYTERM( _ ) ),
[]( const Term& lhs, const Term& rhs, UnificationContext& c ) -> UniGen
{
if( lhs == rhs )
co_yield { lhs, c };
} );
}
}
|
Changes to bs/sema/uni-ruleset.cpp.
| ︙ | ︙ | |||
9 10 11 12 13 14 15 |
SetupPostProcUnificationRules( *this );
SetupHoleUnificationRules( *this );
SetupQuoteUnificationRules( *this );
}
void UnificationRuleSet::addSymRule( const Term& pat, UniFunc f )
{
| | | | | | 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 |
SetupPostProcUnificationRules( *this );
SetupHoleUnificationRules( *this );
SetupQuoteUnificationRules( *this );
}
void UnificationRuleSet::addSymRule( const Term& pat, UniFunc f )
{
m_uniRules = Merge( m_uniRules, VEC( pat, pat ), [&]( auto&& ){ return f; } );
}
UniGen FlippedContextAdapter( const Term& lhs, const Term& rhs, UnificationContext& c, UnificationRuleSet::UniFunc f )
{
for( auto&& [e,c] : f( rhs, lhs, c.flip() ) )
co_yield { move( e ), c.flip() };
c.flip();
}
void UnificationRuleSet::addSymRule( const Term& pat1, const Term& pat2, UniFunc f )
{
m_uniRules = Merge( m_uniRules, VEC( pat1, pat2 ), [&]( auto&& ){ return f; } );
m_uniRules = Merge( m_uniRules, VEC( pat2, pat1 ),
[&]( auto&& ){ return UniFunc( [&,f]( auto&& lhs, auto&& rhs, auto&& c ) -> UniGen
{
return FlippedContextAdapter( lhs, rhs, c, f );
} ); }
);
}
void UnificationRuleSet::addAsymRule( const Term& pat1, const Term& pat2, UniFunc f )
{
m_uniRules = Merge( m_uniRules, VEC( pat1, pat2 ), [&]( auto&& ){ return f; } );
}
void UnificationRuleSet::addHalfUnificationRule( const Term& pat, HalfUniFunc f )
{
m_halfUniRules = Merge( m_halfUniRules, pat, [&]( auto&& ){ return f; } );
}
|
Changes to bs/sema/unify.cpp.
| ︙ | ︙ | |||
38 39 40 41 42 43 44 |
{
const auto& rules = context.rules()->uniRules();
MatchSolution bestSol;
UnificationRuleSet::UniFunc bestFunc;
bool ambiguous = false;
| | | 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
{
const auto& rules = context.rules()->uniRules();
MatchSolution bestSol;
UnificationRuleSet::UniFunc bestFunc;
bool ambiguous = false;
auto expr = VEC( lhs, rhs );
for( auto&& [s, func] : Match( expr, rules ) )
{
if( !bestFunc || s > bestSol )
{
bestSol = s;
bestFunc = func;
ambiguous = false;
|
| ︙ | ︙ |