Goose  Check-in [27fc719d74]

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: 27fc719d74bbfdc271f791239e68b4253b5ee917b175586e112d5269a629b0eb
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
Unified Diff Ignore Whitespace Patch
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
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 = TVEC( 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 ) );
    }









|







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
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(), TVEC(
            Quote( cf.constraintPat() ),
            TERM( static_pointer_cast< void >( cf.invRule() ) ),
            ValueToIRExpr( cf.func() ) ) );
    }

    optional< builtins::ConstrainedFunc > Bridge< builtins::ConstrainedFunc >::FromValue( const Value& v )
    {







|







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
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 = TVEC( 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 );












|







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
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(), TVEC( TSID( func ),
            ANYTERM( _ ), ANYTERM( _ ), ANYTERM( _ ), ANYTERM( _ ) ) ) );

        auto tFuncTypePat = ValueToIRExpr( Value( TypeType(), TVEC( TSID( texpr ), TSID( tfunc ),
            ANYTERM( _ ), ANYTERM( _ ), ANYTERM( _ ) ) ) );

        // func type param / constrainedfunc arg
        e.unificationRuleSet()->addAsymRule(

            ValueToIRExpr( ValuePattern( MkHole( "_"_sid ), move( funcTypePat ), MkHole( "_"_sid ) ) ),










|


|







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
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(), TVEC( TSID( decl ), MkHole( "T"_sid ) ) ) );

        return pattern;
    }
}

namespace empathy::ir
{
    Term Bridge< Decl >::Type( const Term& declType )
    {
        return ValueToIRExpr( Value( TypeType(), TVEC( TSID( decl ), declType ) ) );
    }

    Value Bridge< Decl >::ToValue( const Decl& d )
    {
        return Value( Type( d.type() ), TERM( d.name() ) );
    }








|









|







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
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
            return PP::GetPattern();
        }
    };

    template< typename... T >
    Term BuildBuiltinFuncParamTypeList()
    {
        return TVEC( 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(), TVEC( 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;
    }








|






|







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
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 = TVEC( 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(







|







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
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 TVEC(
            ftype.domain(),
            TERM( make_shared< Vector >( apvt.persistent() ) ),
            ftype.returnType()
        );
    }
}







|






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
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(), TVEC( TSID( func ), MkHole( "llvmType"_sid ),
            MkHole( "_"_sid ), MkHole( "_"_sid ), MkHole( "_"_sid ) ) ) );

        return pattern;
    }

    bool IsFuncType( const Value& t )
    {












|







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
51
52
53
54
55
56
57
58
                SubTerm(),  // return type
                SubTerm()   // param types
            )
        );
        assert( typeDecomp );
        auto&& [kind, domain, rtype, ptypes] = *typeDecomp;

        return TVEC( *Unquote( domain ), *Unquote( ptypes ), rtype );
    }

    Term GetFuncRType( const Value& func )
    {
        auto funcType = ValueFromIRExpr( func.type() );
        assert( funcType );








|







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
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(), TVEC( 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(







|







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
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 ), TVEC(
            TERM( func.tokens() ), TERM( func.llr() ) ) );
    }

    optional< Func > Bridge< Func >::FromValue( const Value& v )
    {
        auto funcTypeVal = ValueFromIRExpr( v.type() );
        if( !funcTypeVal )







|







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
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 = TVEC( 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;







|







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
113
114
115
116
117
118
        return pRule;
    }

    void SetupFunctionInvocationRule( Env& e )
    {
        e.invocationRuleSet()->addRule(
            ValueToIRExpr( ValuePattern( ANYTERM( _ ),
                ValueToIRExpr( Value( TypeType(), TVEC( TSID( func ),
                ANYTERM( _ ), ANYTERM( _ ), ANYTERM( _ ), ANYTERM( _ ) ) ) ),
                ANYTERM( _ ) ) ),
            GetFuncInvocationRule() );
    }
}







|





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
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(), TVEC( TSID( func ),
            ANYTERM( _ ), ANYTERM( _ ), ANYTERM( _ ), ANYTERM( _ ) ) ) );

        auto tFuncTypePat = ValueToIRExpr( Value( TypeType(), TVEC( TSID( texpr ), TSID( tfunc ),
            ANYTERM( _ ), ANYTERM( _ ), ANYTERM( _ ) ) ) );

        e.unificationRuleSet()->addAsymRule(

            ValueToIRExpr( ValuePattern( MkHole( "_"_sid ), move( tFuncTypePat ), MkHole( "_"_sid ) ) ),

            ValueToIRExpr( ValuePattern(









|


|







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
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(), TVEC( TSID( func ), TSID( intrinsic ),
            sema::Quote( sema::DomainAny() ), GetValueType< Value >(),
            sema::Quote( BuildBuiltinFuncParamTypeList< T... >() )
        ) ) );
        return type;
    }

    template< typename R, typename... T >








|







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
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() ), TVEC( 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;







|







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
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(), TVEC( TSID( func ),
            ANYTERM( _ ), ANYTERM( _ ), ANYTERM( _ ), ANYTERM( _ ) ) ) );

        auto tFuncTypePat = ValueToIRExpr( Value( TypeType(), TVEC( TSID( texpr ), TSID( tfunc ),
            ANYTERM( _ ), ANYTERM( _ ), ANYTERM( _ ) ) ) );

        // func type param / overloadset arg
        e.unificationRuleSet()->addAsymRule(

            ValueToIRExpr( ValuePattern( MkHole( "_"_sid ), move( funcTypePat ), MkHole( "_"_sid ) ) ),










|


|







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
30
31
32
33
34
35
36
37
    }
}

namespace empathy::ir
{
    Value Bridge< ArrayType >::ToValue( const ArrayType& a )
    {
        return Value( Type(), TVEC( 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(),







|







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
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(), TVEC( 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(), TVEC( 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(), TVEC( 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(), TVEC( 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(), TVEC( 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(), TVEC( 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(), TVEC( 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(),







|








|








|












|















|















|















|







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
30
31
32
33
34
35
36
37
    }
}

namespace empathy::ir
{
    Value Bridge< PointerType >::ToValue( const PointerType& p )
    {
        return Value( Type(), TVEC( 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(),







|







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
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(), TVEC( TSID( rt_type ), TERM( pllvmType ),
                TSID( struct ), TERM( s.m_packed ? 1U : 0U ),
                Quote( *s.m_identity ), TERM( s.m_memberTypes ) ) );
        }

        return Value( Type(), TVEC( 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(),







|




|







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
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(), TVEC( 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.









|







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
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(), TVEC( TSID( rt_type ),
            ANYTERM( _ ),
            TSID( integer ), TERM( 8U ), ANYTERM( _ ) ) );

        auto rtInt8PtrTypePattern = Value( TypeType(), TVEC( TSID( rt_type ),
            ANYTERM( _ ),
            TSID( pointer ), ValueToIRExpr( rtInt8TypePattern ) ) );

        // ct_int type against a char*:
        // return the char* type.
        e.unificationRuleSet()->addSymRule(
            ValueToIRExpr( rtInt8PtrTypePattern ),







|



|







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
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 TVEC(
            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 )
    {







|







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
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 TVEC(
            ftype->domain(),
            TERM( make_shared< Vector >( apvt.persistent() ) ),
            *rtArgPat
        );
    }
}







|






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
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 = TVEC( 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;







|







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
111
112
113
114
115
116
        return pRule;
    }

    void SetupTemplateFunctionInvocationRule( Env& e )
    {
        e.invocationRuleSet()->addRule(
            ValueToIRExpr( ValuePattern( TSID( constant ),
                ValueToIRExpr( Value( TypeType(), TVEC( TSID( texpr ), TSID( tfunc ),
                    ANYTERM( _ ), ANYTERM( _ ), ANYTERM( _ ) ) ) ),
                ANYTERM( _ ) ) ),
            GetTFuncInvocationRule() );
    }
}







|





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
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229





230
231
232
233
234
235
236
237
238
239
240
241
242
            return buildSignature( c, val );
        }
    };

    void SetupTemplateRules( Env& e )
    {
        // Decl
        auto declTypePat = ValueToIRExpr( Value( TypeType(), TVEC( 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 >() );






        // Constant
        e.templateRuleSet()->addRule(
            ValueToIRExpr( ValuePattern( TSID( constant ), ANYTERM( _ ), ANYTERM( _ ) ) ),
            make_shared< ConstantTemplateRule >() );

        // TFuncType
        auto tFuncTypePat = ValueToIRExpr( Value( TypeType(), TVEC( TSID( texpr ), TSID( tfunc ),
            ANYTERM( _ ), ANYTERM( _ ) ) ) );

        e.templateRuleSet()->addRule( tFuncTypePat,
            make_shared< TFuncTypeTemplateRule >() );
    }
}







|



















>
>
>
>
>






|






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
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(), TVEC( td.type(), TERM( td.name() ) ) );
    }

    optional< TDecl > Bridge< TDecl >::FromValue( const Value& v )
    {
        if( !IsTDecl( v ) )
            return nullopt;








|







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
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 ), TVEC( 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 );







|







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
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(), TVEC( TSID( texpr ), TSID( tfunc ),
            tft.domain(), tft.returnType(), tft.params() ) );
    }

    optional< TFuncType > Bridge< TFuncType >::FromValue( const Value& v )
    {
        auto result = Decompose( v.val(),
            Vec(







|







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
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(), TVEC( td.type(), TERM( td.name() ) ) );
    }

    optional< TNamedDecl > Bridge< TNamedDecl >::FromValue( const Value& v )
    {
        if( !IsTNamedDecl( v ) )
            return nullopt;








|







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
43
44
45
46
47
48
49
50
    }
}

namespace empathy::ir
{
    const Term& Bridge< TVar >::Type()
    {
        static auto type = ValueToIRExpr( Value( TypeType(), TVEC( TSID( texpr ), TSID( tvar ) ) ) );
        return type;
    }

    Value Bridge< TVar >::ToValue( TVar&& td )
    {
        return Value( Type(), TERM( td.name() ) );
    }







|







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
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 >(), TVEC( 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(), TVEC( TSID( texpr ), TSID( tfunc ),
            ANYTERM( _ ), ANYTERM( _ ), ANYTERM( _ ) ) ) );

        auto tDeclTFuncPat = ValueToIRExpr( Value( GetValueType< TDecl >(), TVEC( tFuncTypePat, ANYTERM( _ ) ) ) );

        e.unificationRuleSet()->addAsymRule(

            tDeclTFuncPat,

            ValueToIRExpr( ValuePattern(
                TSID( constant ),







|













|


|







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
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(), TVEC( TSID( func ),
            ANYTERM( _ ), ANYTERM( _ ), ANYTERM( _ ), ANYTERM( _ ) ) ) );

        auto tFuncTypePat = ValueToIRExpr( Value( TypeType(), TVEC( TSID( texpr ), TSID( tfunc ),
            ANYTERM( _ ), ANYTERM( _ ), ANYTERM( _ ) ) ) );

        // func type param / tfunc arg
        e.unificationRuleSet()->addAsymRule(

            ValueToIRExpr( ValuePattern( MkHole( "_"_sid ), move( funcTypePat ), MkHole( "_"_sid ) ) ),










|


|







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
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(), TVEC( TSID( tuple ), state, types ) );
    }

    const Value& EmptyTupleType()
    {
        static auto type = MkTupleType( TSID( opened ), TVEC() );
        return type;
    }

    const Value& EmptyClosedTupleType()
    {
        static auto type = MkTupleType( TSID( closed ), TVEC() );
        return type;
    }

    const Value& EmptyTuple()
    {
        static auto val = Value( ValueToIRExpr( EmptyTupleType() ), TVEC() );
        return val;
    }

    const Value& EmptyClosedTuple()
    {
        static auto val = Value( ValueToIRExpr( EmptyClosedTupleType() ), TVEC() );
        return val;
    }

    Value AppendToTupleType( const Value& tuptype, const Value& type )
    {
        auto decomp = Decompose( tuptype.val(),
            Vec(









|




|





|





|





|







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
72
73
74
75
76
77
78
79
        }
    }

    // Val
    template< typename T, size_t... I >
    auto BuildTupleValue( const T& tup, index_sequence< I... > )
    {
        return TVEC( 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 ) );







|







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
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( _ ), TVEC( ANYTERM( _ ) ) ) ),
                ANYTERM( _ ) ) ),

            ANYTERM( _ ),

        []( const Term& lhs, const Term& rhs, UnificationContext& c ) -> UniGen
        {
            auto tup = ValueFromIRExpr( lhs );







|







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
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( _ ), TVEC( ANYTERM( _ ) ) ) ),
                ANYTERM( _ ) ) ),

            ValueToIRExpr( ValuePattern( ANYTERM( _ ), HolePattern(), ANYTERM( _ ) ) ),

        []( const Term& lhs, const Term& rhs, UnificationContext& c ) -> UniGen
        {
            co_yield { lhs, c };
        } );
    }
}







|










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
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 TVEC( ... )         TERM( ir::Vector::Make( __VA_ARGS__ ) )
#define REPEAT( x )         ir::Repetition( x )

#endif







|



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
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 = TVEC(
            TVEC( TSTR( "foo" ), TSTR( "bar" ) ),
            TVEC(),
            TVEC( TSTR( "foo" ), TSTR( "bar" ) ),
            TVEC( TSTR( "foo" ), TSTR( "bar" ) )
        );

        auto expr1 = pat1;

        auto pat2 = TVEC(
            TVEC( ANYTERM( a ), TSTR( "bar" ) ),
            TVEC(),
            TVEC( ANYTERM( a ), TSTR( "bar" ) ),
            TVEC( ANYTERM( a ), TSTR( "bar" ) )
        );

        auto expr2 = TVEC(
            TVEC( TSTR( "meh" ), TSTR( "bar" ) ),
            TVEC(),
            TVEC( TSTR( "meh" ), TSTR( "bar" ) ),
            TVEC( TSTR( "meh" ), TSTR( "bar" ) )
        );

        auto pat3 = TVEC(
            ANYTERM( x ),
            TVEC( ANYTERM( a ), TSTR( "bar" ) ),
            ANYTERM( z ),
            ANYTERM( z )
        );

        auto expr3 = TVEC(
            TSID( a ),
            TVEC( TSTR( "meh" ), TSTR( "bar" ) ),
            TSID( b ),
            TSID( b )
        );

        auto pat4 = TVEC(
            TVEC( ANYTERM( a ), TSTR( "bar" ) ),
            ANYTERM( y ),
            ANYTERM( y ),
            ANYTERM( y )
        );

        auto expr4 = TVEC(
            TVEC( TSTR( "huh" ), TSTR( "bar" ) ),
            TVEC(),
            TVEC(),
            TVEC()
        );

        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; } );







|
|
|
|
|




|
|
|
|
|


|
|
|
|
|


|

|




|

|




|
|





|
|
|
|
|







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
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 = TVEC(
            TVEC( TSTR( "foo" ), TSTR( "bar" ) ),
            TVEC(),
            TVEC( TSTR( "foo" ), TSTR( "bar" ) ),
            TVEC( TSTR( "foo" ), TSTR( "bar" ) )
        );

        auto expr1 = pat1;

        auto pat2 = TVEC(
            TVEC( ANYTERM( a ), TSTR( "bar" ) ),
            TVEC(),
            TVEC( ANYTERM( a ), TSTR( "bar" ) ),
            TVEC( ANYTERM( a ), TSTR( "bar" ) )
        );

        auto expr2 = TVEC(
            TVEC( TSTR( "meh" ), TSTR( "bar" ) ),
            TVEC(),
            TVEC( TSTR( "meh" ), TSTR( "bar" ) ),
            TVEC( TSTR( "meh" ), TSTR( "bar" ) )
        );

        auto pat3 = TVEC(
            ANYTERM( x ),
            TVEC( ANYTERM( a ), TSTR( "bar" ) ),
            ANYTERM( z ),
            ANYTERM( z )
        );

        auto expr3 = TVEC(
                TSID( a ),
                TVEC( TSTR( "meh" ), TSTR( "bar" ) ),
                TSID( b ),
                TSID( b )
        );

        auto pat4 = TVEC(
            TVEC( ANYTERM( a ), TSTR( "bar" ) ),
            ANYTERM( y ),
            ANYTERM( y ),
            ANYTERM( y )
        );

        auto expr4 = TVEC(
            TVEC( TSTR( "huh" ), TSTR( "bar" ) ),
            TVEC(),
            TVEC(),
            TVEC()
        );

        THEN( "Matching the terms and patterns work as expected" )
        {
            auto s10 = Match( expr1, pat0 );
            auto s11 = Match( expr1, pat1 );
            auto s12 = Match( expr1, pat2 );







|
|
|
|
|




|
|
|
|
|


|
|
|
|
|


|

|




|

|




|
|





|
|
|
|
|







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
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 = TVEC(
            TVEC( TSTR( "foo" ), TSTR( "bar" ) ),
            TVEC(),
            TVEC( TSTR( "foo" ), TSTR( "bar" ) ),
            TVEC( TSTR( "foo" ), TSTR( "bar" ) )
        );

        auto expr1 = pat1;

        auto pat2 = TVEC(
            TVEC( ANYTERM( a ), TSTR( "bar" ) ),
            TVEC(),
            TVEC( ANYTERM( a ), TSTR( "bar" ) ),
            TVEC( ANYTERM( a ), TSTR( "bar" ) )
        );

        auto expr2 = TVEC(
            TVEC( TSTR( "meh" ), TSTR( "bar" ) ),
            TVEC(),
            TVEC( TSTR( "meh" ), TSTR( "bar" ) ),
            TVEC( TSTR( "meh" ), TSTR( "bar" ) )
        );

        auto pat3 = TVEC(
            ANYTERM( x ),
            TVEC( ANYTERM( a ), TSTR( "bar" ) ),
            ANYTERM( z ),
            ANYTERM( z )
        );

        auto expr3 = TVEC(
            TSID( a ),
            TVEC( TSTR( "meh" ), TSTR( "bar" ) ),
            TSID( b ),
            TSID( b )
        );

        auto pat4 = TVEC(
            TVEC( ANYTERM( a ), TSTR( "bar" ) ),
            ANYTERM( y ),
            ANYTERM( y ),
            ANYTERM( y )
        );

        auto expr4 = TVEC(
            TVEC( TSTR( "huh" ), TSTR( "bar" ) ),
            TVEC(),
            TVEC(),
            TVEC()
        );

        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; } );







|
|
|
|
|




|
|
|
|
|


|
|
|
|
|


|

|




|

|




|
|





|
|
|
|
|







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
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 = TVEC(
                TVEC( TSTR( "foo" ), TSTR( "bar" ) ),
                TVEC(),
                TVEC( TSTR( "foo" ), TSTR( "bar" ) ),
                TVEC( TSTR( "foo" ), TSTR( "bar" ) )
        );

        auto pat2 = TVEC(
                TVEC( ANYTERM( a ), TSTR( "bar" ) ),
                TVEC(),
                TVEC( ANYTERM( a ), TSTR( "bar" ) ),
                TVEC( ANYTERM( a ), TSTR( "bar" ) )
        );

        auto pat3 = TVEC(
                ANYTERM( x ),
                TVEC( ANYTERM( a ), TSTR( "bar" ) ),
                ANYTERM( z ),
                ANYTERM( z )
        );

        auto pat4 = TVEC(
                TVEC( ANYTERM( a ), TSTR( "bar" ) ),
                ANYTERM( y ),
                ANYTERM( y ),
                ANYTERM( y )
        );

        auto pat5 = TVEC(
            TVEC( TSTR( "foo" ), ANYTERM( b ) ),
            ANYTERM( y ),
            ANYTERM( y ),
            TVEC( TSTR( "foo" ), ANYTERM( b ) )
        );

        auto pat6 = TVEC(
            ANYTERM( x ),
            TVEC( TSTR( "foo" ), TSTR( "bar" ) ),
            TVEC( TSTR( "foo" ), TSTR( "bar" ) ),
            TVEC( TSTR( "foo" ), TSTR( "baz" ) )
        );

        auto pat7 = TVEC(
            ANYTERM( v ),
            ANYTERM( w ),
            ANYTERM( v ),
            TVEC( TSTR( "foo" ), TSTR( "bar" ) )
        );

        auto pat8 = TVEC(
            ANYTERM( x ),
            TVEC( ANYTERM( a ), TSTR( "bar" ) ),
            ANYTERM( x ),
            TVEC( TSTR( "foo" ), ANYTERM( b ) )
        );

        Trie<> testTrie1;
        testTrie1 = Merge( testTrie1, pat0 );
        testTrie1 = Merge( testTrie1, pat1 );
        testTrie1 = Merge( testTrie1, pat2 );
        testTrie1 = Merge( testTrie1, pat3 );







|
|
|
|
|


|
|
|
|
|


|

|




|
|





|
|


|


|

|
|
|


|



|


|

|

|







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
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 = TVEC(
            TVEC( TSTR( "foo" ), TSTR( "bar" ) ),
            TVEC(),
            TVEC( TSTR( "foo" ), TSTR( "bar" ) ),
            TVEC( TSTR( "foo" ), TSTR( "bar" ) )
        );

        auto pat2 = TVEC(
            TVEC( ANYTERM( a ), TSTR( "bar" ) ),
            TVEC(),
            TVEC( ANYTERM( a ), TSTR( "bar" ) ),
            TVEC( ANYTERM( a ), TSTR( "bar" ) )
        );

        auto pat3 = TVEC(
            ANYTERM( x ),
            TVEC( ANYTERM( a ), TSTR( "bar" ) ),
            ANYTERM( z ),
            ANYTERM( z )
        );

        auto pat4 = TVEC(
            TVEC( ANYTERM( a ), TSTR( "bar" ) ),
            ANYTERM( y ),
            ANYTERM( y ),
            ANYTERM( y )
        );

        auto pat5 = TVEC(
            TVEC( TSTR( "foo" ), ANYTERM( b ) ),
            ANYTERM( y ),
            ANYTERM( y ),
            TVEC( TSTR( "foo" ), ANYTERM( b ) )
        );

        auto pat6 = TVEC(
            ANYTERM( x ),
            TVEC( TSTR( "foo" ), TSTR( "bar" ) ),
            TVEC( TSTR( "foo" ), TSTR( "bar" ) ),
            TVEC( TSTR( "foo" ), TSTR( "baz" ) )
        );

        auto pat7 = TVEC(
            ANYTERM( v ),
            ANYTERM( w ),
            ANYTERM( v ),
            TVEC( TSTR( "foo" ), TSTR( "bar" ) )
        );

        auto pat8 = TVEC(
            ANYTERM( x ),
            TVEC( ANYTERM( a ), TSTR( "bar" ) ),
            ANYTERM( x ),
            TVEC( TSTR( "foo" ), ANYTERM( b ) )
        );

        Trie<> testTrie1;
        testTrie1 = Merge( testTrie1, pat0 );
        testTrie1 = Merge( testTrie1, pat1 );
        testTrie1 = Merge( testTrie1, pat2 );
        testTrie1 = Merge( testTrie1, pat3 );







|
|
|
|
|


|
|
|
|
|


|

|




|
|





|
|


|


|

|
|
|


|



|


|

|

|







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
20
21
22
23
24
25
26
27
        );

        return !!result;
    }

    const Term& TypeType()
    {
        static auto typeType = TVEC( TSID( type ), TERM( 0U ),
            static_cast< LocationId >( 0 ) );
        return typeType;
    }

    // A generic poisoned value of "type" type.
    const Value& PoisonType()
    {







|







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
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 TVEC( TSID( type ), TERM( result->get() ),
                    static_cast< LocationId >( v.locationId() ) );
            }

            return TVEC( TSID( value ), TSID( constant ), v.type(), v.val(),
                static_cast< LocationId >( v.locationId() ) );
        }

        return TVEC( 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( TVEC( TSID( type ), TERM( universeIndex + 1 ) ), TERM( universeIndex ),
            static_cast< uint32_t >( loc ) );
        }

        auto result = Decompose( t,
            Vec(
               Lit( "value"_sid ),
               Val< StringId >(),







|



|



|


















|







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
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 TVEC( 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 ),







|







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
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, TVEC( 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.







|







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
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 = TVEC( id, contextId );

    for( auto&& [s, provider] : Match( pat, m_valueStore ) )
    {
        if( !bestProvider || s > bestSol )
        {
            bestSol = s;
            bestProvider = provider;







|







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
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( TVEC( TSID( hole ), TERM( x ) ), 0 );
        }, h );
    }

    const Term& HolePattern()
    {
        static auto hp = TVEC( TSID( hole ), ANYTERM( _ ) );
        return hp;
    }

    optional< Hole > HoleFromIRExpr( const Term& t )
    {
        auto resultUnnamed = Decompose( t,
            Vec(








|





|







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
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( TVEC( TSID( postproc ),
            TERM( static_pointer_cast< void >( pp ) ),
            t ), 0 );
    }

    Term WrapWithPostprocFunc( const Term& t, PostProcFunc&& pp )
    {
        return SetComplexity( TVEC( 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,






|






|







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
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 >(), TVEC( 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 >(), TVEC( 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 = TVEC( TSTR( "foo" ), TSTR( "bar" ) );

        auto expr2 = TVEC( MkHole( "a"_sid ), MkHole( "a"_sid ) );
        auto expr3 = TVEC( TSTR( "meh" ), TSTR( "meh" ) );

        auto expr4 = TVEC( MkHole( "a"_sid ), TSTR( "bar" ) );
        auto expr5 = TVEC( TSTR( "foo" ), MkHole( "b"_sid ) );

        auto expr6 = TVEC( MkHole( "a"_sid ), MkHole( "a"_sid ) );
        auto expr7 = TVEC( TSTR( "foo" ), MkHole( "b"_sid ) );

        auto expr8 = TVEC( MkHole( "a"_sid ), MkHole( "a"_sid ) );
        auto expr9 = TVEC( expr5, expr1 );

        auto expr10 = TVEC( MkHole( "x"_sid ), expr4,                   MkHole( "z"_sid ), MkHole( "z"_sid ) );
        auto expr11 = TVEC( expr5,                   MkHole( "y"_sid ), MkHole( "y"_sid ), expr5 );

        auto expr12 = TVEC( TVEC( MkHole( "a"_sid ), TSTR( "foo" ) ), MkHole( "a"_sid ) );
        auto expr13 = TVEC( MkHole( "b"_sid ),                        MkHole( "b"_sid ) );

        THEN( "Unifications yields the expected solutions" )
        {
            CheckForUniqueSolution( expr0, expr1, TVEC( TSTR( "foo" ), TSTR( "bar" ) ), { 1, 1 } );
            CheckForUniqueSolution( expr2, expr3, TVEC( TSTR( "meh" ), TSTR( "meh" ) ), { 2, 1 } );
            CheckForNoSolution( expr2, expr1 );
            CheckForUniqueSolution( expr4, expr5, TVEC( TSTR( "foo" ), TSTR( "bar" ) ), { 2, 2 } );
            CheckForUniqueSolution( expr6, expr7, TVEC( TSTR( "foo" ), TSTR( "foo" ) ), { 2, 2 } );

            CheckForUniqueSolution( expr8, expr9,
                TVEC(
                    TVEC( TSTR( "foo" ), TSTR( "bar" ) ),
                    TVEC( TSTR( "foo" ), TSTR( "bar" ) )
                ),
                { 4, 2 }
            );

            CheckForUniqueSolution( expr10, expr11,
                TVEC(
                    TVEC( TSTR( "foo" ), TSTR( "bar" ) ),
                    TVEC( TSTR( "foo" ), TSTR( "bar" ) ),
                    TVEC( TSTR( "foo" ), TSTR( "bar" ) ),
                    TVEC( TSTR( "foo" ), TSTR( "bar" ) )
                ),
                { 5, 5 }
            );

            CheckForNoSolution( expr12, expr13 );
        }
    }
}







|




















|













|

|
|

|
|

|
|

|
|

|
|

|
|



|
|

|
|


|
|
|





|
|
|
|
|








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
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( TVEC( 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 >(), TVEC( 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() );








|


















|







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
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 >(), TVEC( 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() )







|







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
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( TVEC( 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( TVEC( TSTR( "foo" ), TSTR( "bar" ) ), "vec4"s, UnificationScore( 2, 1 ) ) );

            REQUIRE( sols3.size() == 1 );
            REQUIRE( sols3[0] == make_tuple( TVEC( TSTR( "meh" ), TSTR( "meh" ) ), "vec2"s, UnificationScore( 2, 1 ) ) );

            REQUIRE( sols5.size() == 2 );
            REQUIRE( sols5[0] == make_tuple( TVEC( TSTR( "foo" ), TSTR( "foo" ) ), "vec2"s, UnificationScore( 2, 2 ) ) );
            REQUIRE( sols5[1] == make_tuple( TVEC( TSTR( "foo" ), TSTR( "bar" ) ), "vec4"s, UnificationScore( 2, 2 ) ) );

            REQUIRE( sols9.size() == 1 );
            REQUIRE( sols9[0] == make_tuple(
                TVEC(
                    TVEC( TSTR( "foo" ), TSTR( "bar" ) ),
                    TVEC( TSTR( "foo" ), TSTR( "bar" ) )
                ), "vec2"s, UnificationScore( 4, 2 ) )
            );

            REQUIRE( sols11.size() == 1 );
            REQUIRE( sols11[0] == make_tuple(
                TVEC(
                    TVEC( TSTR( "foo" ), TSTR( "bar" ) ),
                    TVEC( TSTR( "foo" ), TSTR( "bar" ) ),
                    TVEC( TSTR( "foo" ), TSTR( "bar" ) ),
                    TVEC( TSTR( "foo" ), TSTR( "bar" ) )
                ), "vec10"s, UnificationScore( 5, 5 ) )
            );

            REQUIRE( sols13.size() == 1 );
            REQUIRE( sols13[0] == make_tuple( TVEC( TSTR( "bar" ), TSTR( "bar" ) ), "vec4"s, UnificationScore( 2, 2 ) ) );
        }
    }
}







|

















|


|


|
|



|
|
|





|
|
|
|
|




|



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
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(
            TVEC( 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.









|







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
45
46
47
48
49
50
51
52
                if( !c.isHoleLocked( get< uint32_t >( lh ) ) )
                    co_yield { lhs, c };
            }
        } );

        // Hole vs anything
        ruleSet.addSymRule(
            TVEC( 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







|







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
115
116
117
118
119
120
121
122
123

                c.flip();
            }
        } );

        // Hole vs hole
        ruleSet.addAsymRule(
            TVEC( TSID( hole ), ANYTERM( _ ) ),
            TVEC( TSID( hole ), ANYTERM( _ ) ),
        []( const Term& lhs, const Term& rhs, UnificationContext& c ) -> UniGen
        {
            auto lh = *HoleFromIRExpr( lhs );
            auto rh = *HoleFromIRExpr( rhs );

            StringId lname;
            StringId rname;







|
|







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
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( TVEC( 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(
            TVEC( TSID( postproc ), ANYTERM( _ ), ANYTERM( _ ) ),
            TVEC( 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 };
            }  );
    }
}









|














|
|












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
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( TVEC( 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( TVEC( TSID( quote ), ANYTERM( _ ) ),
            []( const Term& lhs, UnificationContext& c ) -> UniGen
            {
                co_yield { lhs, c };
            } );

        ruleSet.addSymRule( TVEC( TSID( quote ), ANYTERM( _ ) ),
            []( const Term& lhs, const Term& rhs, UnificationContext& c ) -> UniGen
            {
                if( lhs == rhs )
                    co_yield { lhs, c };
            } );
    }
}






|




















|





|







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
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, TVEC( 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, TVEC( pat1, pat2 ), [&]( auto&& ){ return f; } );
    m_uniRules = Merge( m_uniRules, TVEC( 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, TVEC( pat1, pat2 ), [&]( auto&& ){ return f; } );
}

void UnificationRuleSet::addHalfUnificationRule( const Term& pat, HalfUniFunc f )
{
    m_halfUniRules = Merge( m_halfUniRules, pat, [&]( auto&& ){ return 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
45
46
47
48
49
50
51
52
    {
        const auto& rules = context.rules()->uniRules();

        MatchSolution bestSol;
        UnificationRuleSet::UniFunc bestFunc;
        bool ambiguous = false;

        auto expr = TVEC( lhs, rhs );
        for( auto&& [s, func] : Match( expr, rules ) )
        {
            if( !bestFunc || s > bestSol )
            {
                bestSol = s;
                bestFunc = func;
                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;