Goose  Check-in [51f288ba2a]

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:
  • Implemented a generic wrapper for the simple native types that can be embedded in Terms
  • Added more specific overloads for the assignment operator that should work only on builtin types, so that library and user defined types will be able to choose whether they're copyable
  • The EIR representation for all builtin runtime types are now prefixed with "rt_type" to more easily write generic matching rules against them
  • EIR: Fixed long standing bugs in Enumerate and Decompose that surfaced because of the above
  • Miscellaneous code cleaning
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 51f288ba2a8f7d88286f18555ff40cbd6a8d132bd5ce986b6cb79e15e97dae42
User & Date: achavasse 2021-09-13 21:52:06.673
Context
2021-09-15
00:11
Added a test for, and fixed tctrie variable length vector type checking check-in: c1b565fdda user: achavasse tags: trunk
2021-09-13
21:52
  • Implemented a generic wrapper for the simple native types that can be embedded in Terms
  • Added more specific overloads for the assignment operator that should work only on builtin types, so that library and user defined types will be able to choose whether they're copyable
  • The EIR representation for all builtin runtime types are now prefixed with "rt_type" to more easily write generic matching rules against them
  • EIR: Fixed long standing bugs in Enumerate and Decompose that surfaced because of the above
  • Miscellaneous code cleaning
check-in: 51f288ba2a user: achavasse tags: trunk
2021-09-12
23:52
Repo: syntax color theme change check-in: b4fe430e44 user: achavasse tags: trunk
Changes
Unified Diff Ignore Whitespace Patch
Changes to bs/builtins/helpers.cpp.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include "builtins/builtins.h"
#include "builtins/helpers.h"

using namespace goose::parse;

namespace goose::builtins
{
    void RegisterRule( sema::Env& env, const StringId& name, parse::Rule&& rule )
    {
        parse::RegisterRule( env, AppendToVectorTerm( RootG0Identity(), TERM( name ) ), move( rule ) );
    }

    ptr< cir::BasicBlock > ParseSubStatement( Parser& p, uint32_t precedence )
    {
        auto next = p.resolver()->lookAheadUnresolved();







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include "builtins/builtins.h"
#include "builtins/helpers.h"

using namespace goose::parse;

namespace goose::builtins
{
    void RegisterRule( sema::Env& env, StringId name, parse::Rule&& rule )
    {
        parse::RegisterRule( env, AppendToVectorTerm( RootG0Identity(), TERM( name ) ), move( rule ) );
    }

    ptr< cir::BasicBlock > ParseSubStatement( Parser& p, uint32_t precedence )
    {
        auto next = p.resolver()->lookAheadUnresolved();
Changes to bs/builtins/helpers.h.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#ifndef GOOSE_BUILTINS_HELPERS_H
#define GOOSE_BUILTINS_HELPERS_H

#include "parse/parse.h"

namespace goose::builtins
{
    template< typename T >
    void DefineConstant( sema::Env& env, StringId name, T&& val )
    {
        env.storeValue( AppendToVectorTerm( RootG0Identity(), TERM( name ) ), ANYTERM( _ ), forward< T >( val ) );
    }

    extern void RegisterRule( sema::Env& env, const StringId& name, parse::Rule&& rule );

    // Utility function used to parse flow control statements, such as if and loops.
    // This parses a sub statement, which can be enclosed in a brace block or not.
    // It will get its own scope, with visibility rules setup to see the current
    // scope.
    // It returns a pointer to the final basic block generated by the statement.
    ptr< cir::BasicBlock > ParseSubStatement( parse::Parser& p, uint32_t precedence );













|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#ifndef GOOSE_BUILTINS_HELPERS_H
#define GOOSE_BUILTINS_HELPERS_H

#include "parse/parse.h"

namespace goose::builtins
{
    template< typename T >
    void DefineConstant( sema::Env& env, StringId name, T&& val )
    {
        env.storeValue( AppendToVectorTerm( RootG0Identity(), TERM( name ) ), ANYTERM( _ ), forward< T >( val ) );
    }

    extern void RegisterRule( sema::Env& env, StringId name, parse::Rule&& rule );

    // Utility function used to parse flow control statements, such as if and loops.
    // This parses a sub statement, which can be enclosed in a brace block or not.
    // It will get its own scope, with visibility rules setup to see the current
    // scope.
    // It returns a pointer to the final basic block generated by the statement.
    ptr< cir::BasicBlock > ParseSubStatement( parse::Parser& p, uint32_t precedence );
54
55
56
57
58
59
60


















61
62
63
    template< typename I, typename L >
    auto MkStdRTType( I&& identity, L&& llvmType )
    {
        return VEC( forward< I >( identity ), EmptyPredicates(), forward< L >( llvmType ) );
    }

    extern pvec ParseExpressionList( parse::Parser& p, uint32_t precedence, const pvec& pVec = make_shared< Vector >() );


















}

#endif







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>



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
    template< typename I, typename L >
    auto MkStdRTType( I&& identity, L&& llvmType )
    {
        return VEC( forward< I >( identity ), EmptyPredicates(), forward< L >( llvmType ) );
    }

    extern pvec ParseExpressionList( parse::Parser& p, uint32_t precedence, const pvec& pVec = make_shared< Vector >() );

    struct CTTypePattern
    {
        static const Term& GetPattern()
        {
            static auto pat = VEC( TSID( ct_type ), REPEAT( HOLE( "_"_sid ) ) );
            return pat;
        }
    };

    struct RTTypePattern
    {
        static const Term& GetPattern()
        {
            static auto pat = VEC( TSID( rt_type ), REPEAT( HOLE( "_"_sid ) ) );
            return pat;
        }
    };
}

#endif
Changes to bs/builtins/operators/assignment.cpp.
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

namespace goose::builtins
{
    void SetupAssignmentOps( Env& e )
    {
        auto assOp = GetOrCreateOverloadSet( e, "operator_assign"_sid );

        // Generic function to perform the assignation of a builtin runtime type
        // to a mutable reference of that same type.
        auto BuiltinTypeAssignment = []( auto&& c, auto&& lhs, auto&& rhs ) -> Value
        {
            G_VAL_ASSERT( lhs, !lhs.isConstant() );

            auto refType = *FromValue< ReferenceType >( *EIRToValue( lhs.type() ) );








|







10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

namespace goose::builtins
{
    void SetupAssignmentOps( Env& e )
    {
        auto assOp = GetOrCreateOverloadSet( e, "operator_assign"_sid );

        // Generic function to perform the assignation of a builtin type
        // to a mutable reference of that same type.
        auto BuiltinTypeAssignment = []( auto&& c, auto&& lhs, auto&& rhs ) -> Value
        {
            G_VAL_ASSERT( lhs, !lhs.isConstant() );

            auto refType = *FromValue< ReferenceType >( *EIRToValue( lhs.type() ) );

158
159
160
161
162
163
164




165
166
167
168








169
170
171
172
173
174
175
176
177
178

                // Assignment with a tnameddecl to the left and a value to the right:
                // Local variable declaration and initialization with type inference.
                ForTypes< CustomPattern< TNamedDecl, TNamedDecl::Pattern >, CustomPattern< Value, ForwarderPattern > >( TNamedDeclAssignment ),

                ForType< CustomPattern< Value, TuplePattern > >( TupleAssignment ),





                // Mutable ref assignment
                ForTypes< CustomPattern< Value, ReferenceType::PatternAnyMutableOfTypeT >,
                    CustomPattern< Value, ValuePatternT > >( BuiltinTypeAssignment ),









                // Explicit overload for assigning an rt_int to an rt_int reference:
                // We need this to be able to assign a ct_int to a rt_int: the generic version
                // above can't perform the necessary implicit conversion.
                ForTypes< CustomPattern< Value, ReferenceType::PatternMutable< IntegerType::Pattern > >,
                    CustomPattern< Value, IntegerType::Pattern > >(
                    BuiltinTypeAssignment )
            )
        );
    }
}







>
>
>
>
|



>
>
>
>
>
>
>
>










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

                // Assignment with a tnameddecl to the left and a value to the right:
                // Local variable declaration and initialization with type inference.
                ForTypes< CustomPattern< TNamedDecl, TNamedDecl::Pattern >, CustomPattern< Value, ForwarderPattern > >( TNamedDeclAssignment ),

                ForType< CustomPattern< Value, TuplePattern > >( TupleAssignment ),

                // TODO: this overload is too general and should be removed, because it pretty
                // much makes everything copiable by default. The two overloads below
                // should be used instead, but they currently don't work (probably
                // because they're the first overloads involving variadic patterns and
                // that stuff has never been tested)
                ForTypes< CustomPattern< Value, ReferenceType::PatternAnyMutableOfTypeT >,
                    CustomPattern< Value, ValuePatternT > >( BuiltinTypeAssignment ),

                // Mutable ref assignment for compile time builtin types
                ForTypes< CustomPattern< Value, ReferenceType::PatternMutableOf< CTTypePattern > >,
                    CustomPattern< Value, ValuePatternT > >( BuiltinTypeAssignment ),

                // Mutable ref assignment for run time builtin types
                ForTypes< CustomPattern< Value, ReferenceType::PatternMutableOf< RTTypePattern > >,
                    CustomPattern< Value, ValuePatternT > >( BuiltinTypeAssignment ),

                // Explicit overload for assigning an rt_int to an rt_int reference:
                // We need this to be able to assign a ct_int to a rt_int: the generic version
                // above can't perform the necessary implicit conversion.
                ForTypes< CustomPattern< Value, ReferenceType::PatternMutable< IntegerType::Pattern > >,
                    CustomPattern< Value, IntegerType::Pattern > >(
                    BuiltinTypeAssignment )
            )
        );
    }
}
Changes to bs/builtins/operators/dollar.cpp.
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
//
// Also, it works both as a prefix operator to construct a TVar,
// and as an infix operator (with a decl or TEXpr as the left value) to
// construct a Decl of the form "<type> $FOO" or a TDecl of the form
// "<TExpr> $FOO" (for instance $T $FOO)
namespace
{
    Value BuildOrRetrieveTVar( const Context& c, uint32_t locationId, const StringId& name, bool forwarding )
    {
        if( name == "_"_sid )
            return forwarding ? ToValue( TTVar( "_"_sid ) ) : ToValue( TVar( "_"_sid ) );

        // Template name bindings are stored with a "$$" prefix so they don't
        // collide with regular names.
        auto captureIdentity = AppendToVectorTerm( c.identity(),







|







13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
//
// Also, it works both as a prefix operator to construct a TVar,
// and as an infix operator (with a decl or TEXpr as the left value) to
// construct a Decl of the form "<type> $FOO" or a TDecl of the form
// "<TExpr> $FOO" (for instance $T $FOO)
namespace
{
    Value BuildOrRetrieveTVar( const Context& c, uint32_t locationId, StringId name, bool forwarding )
    {
        if( name == "_"_sid )
            return forwarding ? ToValue( TTVar( "_"_sid ) ) : ToValue( TVar( "_"_sid ) );

        // Template name bindings are stored with a "$$" prefix so they don't
        // collide with regular names.
        auto captureIdentity = AppendToVectorTerm( c.identity(),
Changes to bs/builtins/operators/helpers.h.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#ifndef GOOSE_BUILTINS_OPERATORS_HELPERS_H
#define GOOSE_BUILTINS_OPERATORS_HELPERS_H

#include "builtins/helpers.h"

namespace goose::builtins
{
    using namespace goose::parse;

    template< typename... R >
    void BuildParseRule( sema::Env& env, const StringId& name, R&&... ruleBuilders )
    {
        parse::BuildParseRule( env, name, AppendToVectorTerm( RootG0Identity(), TERM( name ) ),
            forward< R >( ruleBuilders )... );
    }

    struct UnaryOpTag {};
    struct BinaryOpTag {};










|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#ifndef GOOSE_BUILTINS_OPERATORS_HELPERS_H
#define GOOSE_BUILTINS_OPERATORS_HELPERS_H

#include "builtins/helpers.h"

namespace goose::builtins
{
    using namespace goose::parse;

    template< typename... R >
    void BuildParseRule( sema::Env& env, StringId name, R&&... ruleBuilders )
    {
        parse::BuildParseRule( env, name, AppendToVectorTerm( RootG0Identity(), TERM( name ) ),
            forward< R >( ruleBuilders )... );
    }

    struct UnaryOpTag {};
    struct BinaryOpTag {};
Changes to bs/builtins/types/basic.cpp.
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
        static auto type = ValueToEIR( Value( TypeType(), TSID( void ) ) );
        return type;
    }

    // bool
    const Term& Bridge< bool >::Type()
    {
        static auto type = ValueToEIR( Value( TypeType(), MkStdType( TSID( bool ) ) ) );
        return type;
    }

    Value Bridge< bool >::ToValue( bool x )
    {
        return Value( Type(), TERM( x ? 1U : 0U ) );
    }







|







40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
        static auto type = ValueToEIR( Value( TypeType(), TSID( void ) ) );
        return type;
    }

    // bool
    const Term& Bridge< bool >::Type()
    {
        static auto type = ValueToEIR( Value( TypeType(), MkStdType( TSID( rt_type ), TSID( bool ) ) ) );
        return type;
    }

    Value Bridge< bool >::ToValue( bool x )
    {
        return Value( Type(), TERM( x ? 1U : 0U ) );
    }
Changes to bs/builtins/types/decl.h.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#ifndef GOOSE_BUILTINS_TYPES_DECL_H
#define GOOSE_BUILTINS_TYPES_DECL_H

namespace goose::builtins
{
    class Decl
    {
        public:
            template< typename T >
            Decl( T&& type, const StringId& name ) :
                m_type( forward< T >( type ) ),
                m_name( name )
            {}

            const auto& type() const { return m_type; }
            const auto& name() const { return m_name; }










|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#ifndef GOOSE_BUILTINS_TYPES_DECL_H
#define GOOSE_BUILTINS_TYPES_DECL_H

namespace goose::builtins
{
    class Decl
    {
        public:
            template< typename T >
            Decl( T&& type, StringId name ) :
                m_type( forward< T >( type ) ),
                m_name( name )
            {}

            const auto& type() const { return m_type; }
            const auto& name() const { return m_name; }

Changes to bs/builtins/types/func/bfunc.h.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#ifndef GOOSE_BUILTINS_TYPES_BFUNC_H
#define GOOSE_BUILTINS_TYPES_BFUNC_H

namespace goose::builtins
{
    class FuncVerificationInfos;

    using BuiltinFuncWrapper = function< Value ( const Term& argVec ) >;

    template< typename F >
    ptr< FuncVerificationInfos > RegisterBuiltinFunc( Env& env, const StringId& name, F&& func );

    template< typename FT, typename F >
    ptr< FuncVerificationInfos > RegisterBuiltinFunc( Env& env, ptr< OverloadSet > pOvlSet, F&& func );

    extern bool IsBuiltinFunc( const Value& func );
    extern bool IsEagerBuiltinFunc( const Value& func );
    extern bool IsNonEagerBuiltinFunc( const Value& func );










|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#ifndef GOOSE_BUILTINS_TYPES_BFUNC_H
#define GOOSE_BUILTINS_TYPES_BFUNC_H

namespace goose::builtins
{
    class FuncVerificationInfos;

    using BuiltinFuncWrapper = function< Value ( const Term& argVec ) >;

    template< typename F >
    ptr< FuncVerificationInfos > RegisterBuiltinFunc( Env& env, StringId name, F&& func );

    template< typename FT, typename F >
    ptr< FuncVerificationInfos > RegisterBuiltinFunc( Env& env, ptr< OverloadSet > pOvlSet, F&& func );

    extern bool IsBuiltinFunc( const Value& func );
    extern bool IsEagerBuiltinFunc( const Value& func );
    extern bool IsNonEagerBuiltinFunc( const Value& func );
Changes to bs/builtins/types/func/bfunc.inl.
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
#ifndef GOOSE_BUILTINS_TYPES_BFUNC_INL
#define GOOSE_BUILTINS_TYPES_BFUNC_INL

namespace goose::builtins
{
    template< typename FT, typename F >
    ptr< FuncVerificationInfos > RegisterBuiltinFunc( Env& env, const StringId& name, F&& func )
    {
        ptr< OverloadSet > pOvlSet;
        auto identity = AppendToVectorTerm( RootG0Identity(), TERM( name ) );

        Term result;

        switch( env.retrieveValue( identity, RootG0Identity(), result ) )
        {
            case sema::Env::Status::Success:
                pOvlSet = *FromValue< ptr< OverloadSet > >( *EIRToValue( result ) );
                break;

            case sema::Env::Status::NoMatch:
                pOvlSet = make_shared< OverloadSet >( identity );
                env.storeValue( identity, ANYTERM( _ ), ValueToEIR( ToValue( pOvlSet ) ) );
                break;

            case sema::Env::Status::AmbiguousMatch:
                G_ERROR( "ambiguous match while registering builtin func "s + name.str() );
        }

        return RegisterBuiltinFunc< FT >( env, pOvlSet, forward< F >( func ) );
    }

    template< typename FT, typename F >
    ptr< FuncVerificationInfos > RegisterBuiltinFunc( Env& env, ptr< OverloadSet > pOvlSet, F&& func )
    {
        auto fvi = make_shared< builtins::FuncVerificationInfos >( RootG0Identity() );






|

<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







1
2
3
4
5
6
7
8


9

















10
11
12
13
14
15
16
#ifndef GOOSE_BUILTINS_TYPES_BFUNC_INL
#define GOOSE_BUILTINS_TYPES_BFUNC_INL

namespace goose::builtins
{
    template< typename FT, typename F >
    ptr< FuncVerificationInfos > RegisterBuiltinFunc( Env& env, StringId name, F&& func )
    {


        auto pOvlSet = GetOrCreateOverloadSet( env, name );

















        return RegisterBuiltinFunc< FT >( env, pOvlSet, forward< F >( func ) );
    }

    template< typename FT, typename F >
    ptr< FuncVerificationInfos > RegisterBuiltinFunc( Env& env, ptr< OverloadSet > pOvlSet, F&& func )
    {
        auto fvi = make_shared< builtins::FuncVerificationInfos >( RootG0Identity() );
Changes to bs/builtins/types/overloadset/helpers.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
42
#include "builtins/builtins.h"
#include "execute/execute.h"

namespace goose::builtins
{
    ptr< OverloadSet > CreateOverloadSet( Env& env, const StringId& name )
    {
        auto identity = AppendToVectorTerm( RootG0Identity(), TERM( name ) );
        auto pOvlSet = make_shared< OverloadSet >( identity );
        env.storeValue( identity, ANYTERM( _ ), ValueToEIR( ToValue( pOvlSet ) ) );
        return pOvlSet;
    }

    ptr< OverloadSet > GetOverloadSet( Env& env, const StringId& name )
    {
        auto identity = AppendToVectorTerm( RootG0Identity(), TERM( name ) );

        Term result;

        switch( env.retrieveValue( identity, RootG0Identity(), result ) )
        {
            case sema::Env::Status::Success:
                return *FromValue< ptr< OverloadSet > >( *EIRToValue( result ) );

            case sema::Env::Status::NoMatch:
                G_ERROR( format( "fatal: overload set {} not found", name ) );

            case sema::Env::Status::AmbiguousMatch:
                G_ERROR( format( "fatal: ambiguous match for overload set {}", name ) );
        }

        return nullptr;
    }

    ptr< OverloadSet > GetOrCreateOverloadSet( Env& env, const StringId& name )
    {
        auto identity = AppendToVectorTerm( RootG0Identity(), TERM( name ) );

        Term result;

        switch( env.retrieveValue( identity, RootG0Identity(), result ) )
        {





|







|




















|







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
#include "builtins/builtins.h"
#include "execute/execute.h"

namespace goose::builtins
{
    ptr< OverloadSet > CreateOverloadSet( Env& env, StringId name )
    {
        auto identity = AppendToVectorTerm( RootG0Identity(), TERM( name ) );
        auto pOvlSet = make_shared< OverloadSet >( identity );
        env.storeValue( identity, ANYTERM( _ ), ValueToEIR( ToValue( pOvlSet ) ) );
        return pOvlSet;
    }

    ptr< OverloadSet > GetOverloadSet( Env& env, StringId name )
    {
        auto identity = AppendToVectorTerm( RootG0Identity(), TERM( name ) );

        Term result;

        switch( env.retrieveValue( identity, RootG0Identity(), result ) )
        {
            case sema::Env::Status::Success:
                return *FromValue< ptr< OverloadSet > >( *EIRToValue( result ) );

            case sema::Env::Status::NoMatch:
                G_ERROR( format( "fatal: overload set {} not found", name ) );

            case sema::Env::Status::AmbiguousMatch:
                G_ERROR( format( "fatal: ambiguous match for overload set {}", name ) );
        }

        return nullptr;
    }

    ptr< OverloadSet > GetOrCreateOverloadSet( Env& env, StringId name )
    {
        auto identity = AppendToVectorTerm( RootG0Identity(), TERM( name ) );

        Term result;

        switch( env.retrieveValue( identity, RootG0Identity(), result ) )
        {
Changes to bs/builtins/types/overloadset/helpers.h.
1
2
3
4
5
6
7
8
9
10
11
12
#ifndef GOOSE_BUILTINS_TYPES_OVERLOADSET_HELPERS_H
#define GOOSE_BUILTINS_TYPES_OVERLOADSET_HELPERS_H

namespace goose::builtins
{
    extern ptr< OverloadSet > CreateOverloadSet( Env& env, const StringId& name );
    extern ptr< OverloadSet > GetOverloadSet( Env& env, const StringId& name );
    extern ptr< OverloadSet > GetOrCreateOverloadSet( Env& env, const StringId& name );
    extern Value InvokeOverloadSet( const Context& c, const ptr< OverloadSet >& pOvlSet, Value args );
}

#endif





|
|
|




1
2
3
4
5
6
7
8
9
10
11
12
#ifndef GOOSE_BUILTINS_TYPES_OVERLOADSET_HELPERS_H
#define GOOSE_BUILTINS_TYPES_OVERLOADSET_HELPERS_H

namespace goose::builtins
{
    extern ptr< OverloadSet > CreateOverloadSet( Env& env, StringId name );
    extern ptr< OverloadSet > GetOverloadSet( Env& env, StringId name );
    extern ptr< OverloadSet > GetOrCreateOverloadSet( Env& env, StringId name );
    extern Value InvokeOverloadSet( const Context& c, const ptr< OverloadSet >& pOvlSet, Value args );
}

#endif
Changes to bs/builtins/types/pretty.cpp.
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
            {
                auto decl = *FromValue< Decl >( *EIRToValue( t ) );
                out << "decl(" << decl.type() << ", " << decl.name() << ")";
                return true;
            } );

        pp.addRule( GetValueType< bool >(), [&]( auto&& out, auto&& t ) { out << "bool"; return true; } );
        pp.addRule( MkStdType( TSID( bool ) ), [&]( auto&& out, auto&& t ) { out << "bool"; return true; } );

        pp.addRule( GetValueType< string >(), [&]( auto&& out, auto&& t ) { out << "ct_string"; return true; } );
        pp.addRule( MkStdType( TSID( ct_type ), TSID( ct_string ) ), [&]( auto&& out, auto&& t ) { out << "ct_string"; return true; } );

        pp.addRule( GetValueType< BigInt >(), [&]( auto&& out, auto&& t ) { out << "ct_int"; return true; } );
        pp.addRule( MkStdType( TSID( ct_type ), TSID( ct_int ) ), [&]( auto&& out, auto&& t ) { out << "ct_int"; return true; } );
    }







|







56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
            {
                auto decl = *FromValue< Decl >( *EIRToValue( t ) );
                out << "decl(" << decl.type() << ", " << decl.name() << ")";
                return true;
            } );

        pp.addRule( GetValueType< bool >(), [&]( auto&& out, auto&& t ) { out << "bool"; return true; } );
        pp.addRule( MkStdType( TSID( rt_type ), TSID( bool ) ), [&]( auto&& out, auto&& t ) { out << "bool"; return true; } );

        pp.addRule( GetValueType< string >(), [&]( auto&& out, auto&& t ) { out << "ct_string"; return true; } );
        pp.addRule( MkStdType( TSID( ct_type ), TSID( ct_string ) ), [&]( auto&& out, auto&& t ) { out << "ct_string"; return true; } );

        pp.addRule( GetValueType< BigInt >(), [&]( auto&& out, auto&& t ) { out << "ct_int"; return true; } );
        pp.addRule( MkStdType( TSID( ct_type ), TSID( ct_int ) ), [&]( auto&& out, auto&& t ) { out << "ct_int"; return true; } );
    }
Changes to bs/builtins/types/runtime/array.cpp.
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
    }
}

namespace goose::eir
{
    Value Bridge< ArrayType >::ToValue( const ArrayType& a )
    {
        return Value( Type(), MkStdRTType( TSID( array ),
            GetLLVMType( a ),
            TERM( a.m_count ), a.m_containedType ) );
    }

    optional< ArrayType > Bridge< ArrayType >::FromValue( const Value& v )
    {
        auto result = Decompose( v.val(),
            Vec(
                Lit( "array"_sid ),
                SubTerm(),
                Val< void* >(),

                Val< uint32_t >(),
                SubTerm()
            )
        );

        if( !result )
            return nullopt;







|
|







|


>







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

namespace goose::eir
{
    Value Bridge< ArrayType >::ToValue( const ArrayType& a )
    {
        return Value( Type(), MkStdRTType( TSID( rt_type ),
            GetLLVMType( a ), TSID( array ),
            TERM( a.m_count ), a.m_containedType ) );
    }

    optional< ArrayType > Bridge< ArrayType >::FromValue( const Value& v )
    {
        auto result = Decompose( v.val(),
            Vec(
                Lit( "rt_type"_sid ),
                SubTerm(),
                Val< void* >(),
                Lit( "array"_sid ),
                Val< uint32_t >(),
                SubTerm()
            )
        );

        if( !result )
            return nullopt;
Changes to bs/builtins/types/runtime/basic.cpp.
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
            {
                return ToValue( IntegerType( numBits, true ) );
            } );
    }

    const Term& IntegerType::Pattern::GetPattern()
    {
        static auto pattern = ValueToEIR( Value( TypeType(), MkStdRTType( TSID( integer ),
            nullptr,
            VEC( HOLE( "size"_sid ), HOLE( "signedness"_sid ) ) ) ) );

        return pattern;
    }

    const Term& IntegerType::PatternSigned::GetPattern()
    {
        static auto pattern = ValueToEIR( Value( TypeType(), MkStdRTType( TSID( integer ),
            nullptr,
            VEC( HOLE( "size"_sid ), TERM( 1U ) ) ) ) );

        return pattern;
    }

    const Term& IntegerType::PatternUnsigned::GetPattern()
    {
        static auto pattern = ValueToEIR( Value( TypeType(), MkStdRTType( TSID( integer ),
            nullptr,
            VEC( HOLE( "size"_sid ), TERM( 0U ) ) ) ) );

        return pattern;
    }

    const Term& IntegerType::PatternUnsigned32::GetPattern()
    {
        static auto pattern = ValueToEIR( Value( TypeType(), MkStdRTType( TSID( integer ),
            nullptr,
            VEC( TERM( 32U ), TERM( 0U ) ) ) ) );

        return pattern;
    }

    llvm::Type* GetLLVMType( const HalfFloatType& t )
    {







|
|







|
|







|
|







|
|







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
            {
                return ToValue( IntegerType( numBits, true ) );
            } );
    }

    const Term& IntegerType::Pattern::GetPattern()
    {
        static auto pattern = ValueToEIR( Value( TypeType(), MkStdRTType( TSID( rt_type ),
            nullptr, TSID( integer ),
            VEC( HOLE( "size"_sid ), HOLE( "signedness"_sid ) ) ) ) );

        return pattern;
    }

    const Term& IntegerType::PatternSigned::GetPattern()
    {
        static auto pattern = ValueToEIR( Value( TypeType(), MkStdRTType( TSID( rt_type ),
            nullptr, TSID( integer ),
            VEC( HOLE( "size"_sid ), TERM( 1U ) ) ) ) );

        return pattern;
    }

    const Term& IntegerType::PatternUnsigned::GetPattern()
    {
        static auto pattern = ValueToEIR( Value( TypeType(), MkStdRTType( TSID( rt_type ),
            nullptr, TSID( integer ),
            VEC( HOLE( "size"_sid ), TERM( 0U ) ) ) ) );

        return pattern;
    }

    const Term& IntegerType::PatternUnsigned32::GetPattern()
    {
        static auto pattern = ValueToEIR( Value( TypeType(), MkStdRTType( TSID( rt_type ),
            nullptr, TSID( integer ),
            VEC( TERM( 32U ), TERM( 0U ) ) ) ) );

        return pattern;
    }

    llvm::Type* GetLLVMType( const HalfFloatType& t )
    {
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144

145
146
147
148
149
150
151
}

namespace goose::eir
{
    //// Half
    Value Bridge< HalfFloatType >::ToValue( const HalfFloatType& t )
    {
        return Value( Type(), MkStdRTType( TSID( half ), GetLLVMType( t ) ) );
    }

    optional< HalfFloatType > Bridge< HalfFloatType >::FromValue( const Value& v )
    {
        if( v != ToValue( HalfFloatType() ) )
            return nullopt;

        return {};
    }

    //// Float
    Value Bridge< FloatType >::ToValue( const FloatType& t )
    {
        return Value( Type(), MkStdRTType( TSID( float ), GetLLVMType( t ) ) );
    }

    optional< FloatType > Bridge< FloatType >::FromValue( const Value& v )
    {
        if( v != ToValue( FloatType() ) )
            return nullopt;

        return {};
    }

    //// Double
    Value Bridge< DoubleFloatType >::ToValue( const DoubleFloatType& t )
    {
        return Value( Type(), MkStdRTType( TSID( double ), GetLLVMType( t ) ) );
    }

    optional< DoubleFloatType > Bridge< DoubleFloatType >::FromValue( const Value& v )
    {
        if( v != ToValue( DoubleFloatType() ) )
            return nullopt;

        return {};
    }

    //// Integer
    Value Bridge< IntegerType >::ToValue( const IntegerType& t )
    {
        return Value( Type(), MkStdRTType( TSID( integer ), GetLLVMType( t ),
            VEC( TERM( t.m_numBits ), t.m_signed ? TERM( 1U ) : TERM( 0U ) ) ) );
    }

    optional< IntegerType > Bridge< IntegerType >::FromValue( const Value& v )
    {
        auto result = Decompose( v.val(),
            Vec(
                Lit( "integer"_sid ),
                SubTerm(),
                Val< void* >(),

                Vec(
                    Val< uint32_t >(),
                    Val< uint32_t >()
                )
            )
        );








|













|













|













|







|


>







85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
}

namespace goose::eir
{
    //// Half
    Value Bridge< HalfFloatType >::ToValue( const HalfFloatType& t )
    {
        return Value( Type(), MkStdRTType( TSID( rt_type ), GetLLVMType( t ), TSID( half ) ) );
    }

    optional< HalfFloatType > Bridge< HalfFloatType >::FromValue( const Value& v )
    {
        if( v != ToValue( HalfFloatType() ) )
            return nullopt;

        return {};
    }

    //// Float
    Value Bridge< FloatType >::ToValue( const FloatType& t )
    {
        return Value( Type(), MkStdRTType( TSID( rt_type ), GetLLVMType( t ), TSID( float ) ) );
    }

    optional< FloatType > Bridge< FloatType >::FromValue( const Value& v )
    {
        if( v != ToValue( FloatType() ) )
            return nullopt;

        return {};
    }

    //// Double
    Value Bridge< DoubleFloatType >::ToValue( const DoubleFloatType& t )
    {
        return Value( Type(), MkStdRTType( TSID( rt_type ), GetLLVMType( t ), TSID( double ) ) );
    }

    optional< DoubleFloatType > Bridge< DoubleFloatType >::FromValue( const Value& v )
    {
        if( v != ToValue( DoubleFloatType() ) )
            return nullopt;

        return {};
    }

    //// Integer
    Value Bridge< IntegerType >::ToValue( const IntegerType& t )
    {
        return Value( Type(), MkStdRTType( TSID( rt_type ), GetLLVMType( t ), TSID( integer ),
            VEC( TERM( t.m_numBits ), t.m_signed ? TERM( 1U ) : TERM( 0U ) ) ) );
    }

    optional< IntegerType > Bridge< IntegerType >::FromValue( const Value& v )
    {
        auto result = Decompose( v.val(),
            Vec(
                Lit( "rt_type"_sid ),
                SubTerm(),
                Val< void* >(),
                Lit( "integer"_sid ),
                Vec(
                    Val< uint32_t >(),
                    Val< uint32_t >()
                )
            )
        );

Changes to bs/builtins/types/runtime/pointer.cpp.
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
    }
}

namespace goose::eir
{
    Value Bridge< PointerType >::ToValue( const PointerType& p )
    {
        return Value( Type(), MkStdRTType( TSID( pointer ),
            GetLLVMType( p ),
            p.m_pointedType ) );
    }

    optional< PointerType > Bridge< PointerType >::FromValue( const Value& v )
    {
        auto result = Decompose( v.val(),
            Vec(
                Lit( "pointer"_sid ),
                SubTerm(),
                Val< void* >(),

                SubTerm()
            )
        );

        if( !result )
            return nullopt;








|
|







|


>







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

namespace goose::eir
{
    Value Bridge< PointerType >::ToValue( const PointerType& p )
    {
        return Value( Type(), MkStdRTType( TSID( rt_type ),
            GetLLVMType( p ), TSID( pointer ),
            p.m_pointedType ) );
    }

    optional< PointerType > Bridge< PointerType >::FromValue( const Value& v )
    {
        auto result = Decompose( v.val(),
            Vec(
                Lit( "rt_type"_sid ),
                SubTerm(),
                Val< void* >(),
                Lit( "pointer"_sid ),
                SubTerm()
            )
        );

        if( !result )
            return nullopt;

Changes to bs/builtins/types/runtime/record.cpp.
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
    }
}

namespace goose::eir
{
    Value Bridge< RecordType >::ToValue( const RecordType& rt )
    {
        return Value( Type(), MkStdRTType( TSID( record ), GetLLVMType( rt ),
            TERM( rt.m_packed ? 1U : 0U ),
            TERM( rt.m_memberTypes ) ) );
    }

    optional< RecordType > Bridge< RecordType >::FromValue( const Value& v )
    {
        auto result = Decompose( v.val(),
            Vec(
                Lit( "record"_sid ),
                SubTerm(),
                Val< void* >(),

                Val< uint32_t >(),
                Val< pvec >()
            )
        );

        if( !result )
            return nullopt;







|








|


>







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

namespace goose::eir
{
    Value Bridge< RecordType >::ToValue( const RecordType& rt )
    {
        return Value( Type(), MkStdRTType( TSID( rt_type ), GetLLVMType( rt ), TSID( record ),
            TERM( rt.m_packed ? 1U : 0U ),
            TERM( rt.m_memberTypes ) ) );
    }

    optional< RecordType > Bridge< RecordType >::FromValue( const Value& v )
    {
        auto result = Decompose( v.val(),
            Vec(
                Lit( "rt_type"_sid ),
                SubTerm(),
                Val< void* >(),
                Lit( "record"_sid ),
                Val< uint32_t >(),
                Val< pvec >()
            )
        );

        if( !result )
            return nullopt;
Changes to bs/builtins/types/runtime/runtime.cpp.
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49

            if( !lt )
                return nullptr;

            if( lt->get() )
                return static_cast< llvm::Type* >( lt->get() );

            const auto& id = get< StringId >( vec->get()->terms()[0] );

            if( id == "bool"_sid )
                return llvm::Type::getInt1Ty( GetLLVMContext() );

            if( id == "integer"_sid )
            {
                if( auto it = FromValue< IntegerType >( t ) )







|







35
36
37
38
39
40
41
42
43
44
45
46
47
48
49

            if( !lt )
                return nullptr;

            if( lt->get() )
                return static_cast< llvm::Type* >( lt->get() );

            const auto& id = get< StringId >( vec->get()->terms()[3] );

            if( id == "bool"_sid )
                return llvm::Type::getInt1Ty( GetLLVMContext() );

            if( id == "integer"_sid )
            {
                if( auto it = FromValue< IntegerType >( t ) )
Changes to bs/builtins/types/runtime/typecheck.cpp.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include "builtins/builtins.h"
#include "builtins/helpers.h"

using namespace goose;
using namespace goose::eir;

namespace goose::builtins
{
    void SetupRuntimeTypesChecking( Env& e )
    {
        auto rtIntTypePattern = Value( TypeType(), MkStdType( TSID( integer ),
            VEC( ANYTERM( _ ), ANYTERM( _ ) ) ) );

        // Conversion rule for ct_int to runtime int:
        // we verify that the ct_int fits in the bitsize/signage
        // of the runtime int
        e.typeCheckingRuleSet()->addTypeCheckingRule( TCRINFOS,











|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include "builtins/builtins.h"
#include "builtins/helpers.h"

using namespace goose;
using namespace goose::eir;

namespace goose::builtins
{
    void SetupRuntimeTypesChecking( Env& e )
    {
        auto rtIntTypePattern = Value( TypeType(), MkStdType( TSID( rt_type ), TSID( integer ),
            VEC( ANYTERM( _ ), ANYTERM( _ ) ) ) );

        // Conversion rule for ct_int to runtime int:
        // we verify that the ct_int fits in the bitsize/signage
        // of the runtime int
        e.typeCheckingRuleSet()->addTypeCheckingRule( TCRINFOS,

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
                return TERM( valToLoad );
            } );

            co_yield { ValueToEIR( Value( *s, move( wrapped ) )
                .setLocationId( rhsVal.locationId() ) ), tcc };
        } );

        auto rtInt8TypePattern = Value( TypeType(), MkStdType( TSID( integer ),
            VEC( TERM( 8U ), ANYTERM( _ ) ) ) );

        auto rtInt8PtrTypePattern = Value( TypeType(), MkStdType( TSID( pointer ),
            ValueToEIR( rtInt8TypePattern ) ) );

        // ct_string type against a char*:
        // return the char* type.
        e.typeCheckingRuleSet()->addTypeCheckingRule( TCRINFOS,
            ValueToEIR( rtInt8PtrTypePattern ),
            GetValueType< string >(),
        []( const Term& lhs, const Term& rhs, TypeCheckingContext c ) -> TCGen
        {
            if( auto s = HalfUnify( lhs, c ) )
                co_yield { *s, c };
        } );

        auto ptrTypePattern = Value( TypeType(), MkStdType( TSID( pointer ),
            ANYTERM( _ ) ) );

        // nullptr constant type checking against a pointer of any type;
        // Yield a value of the given pointer type, with a 0 integer as its content.
        // This'll be recognized by codegen to emit a null pointer value of the right type.
        e.typeCheckingRuleSet()->addTypeCheckingRule( TCRINFOS,








|


|













|







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
                return TERM( valToLoad );
            } );

            co_yield { ValueToEIR( Value( *s, move( wrapped ) )
                .setLocationId( rhsVal.locationId() ) ), tcc };
        } );

        auto rtInt8TypePattern = Value( TypeType(), MkStdType( TSID( rt_type ), TSID( integer ),
            VEC( TERM( 8U ), ANYTERM( _ ) ) ) );

        auto rtInt8PtrTypePattern = Value( TypeType(), MkStdType( TSID( rt_type ), TSID( pointer ),
            ValueToEIR( rtInt8TypePattern ) ) );

        // ct_string type against a char*:
        // return the char* type.
        e.typeCheckingRuleSet()->addTypeCheckingRule( TCRINFOS,
            ValueToEIR( rtInt8PtrTypePattern ),
            GetValueType< string >(),
        []( const Term& lhs, const Term& rhs, TypeCheckingContext c ) -> TCGen
        {
            if( auto s = HalfUnify( lhs, c ) )
                co_yield { *s, c };
        } );

        auto ptrTypePattern = Value( TypeType(), MkStdType( TSID( rt_type ), TSID( pointer ),
            ANYTERM( _ ) ) );

        // nullptr constant type checking against a pointer of any type;
        // Yield a value of the given pointer type, with a 0 integer as its content.
        // This'll be recognized by codegen to emit a null pointer value of the right type.
        e.typeCheckingRuleSet()->addTypeCheckingRule( TCRINFOS,

Changes to bs/builtins/types/template/build.cpp.
1
2
3
4
5
6
7
8
9
10
11
12
#include "builtins/builtins.h"

namespace goose::builtins
{
    optional< TDecl > BuildTDecl( const Context& c, const Term& typeTExpr, const StringId& name )
    {
        auto typeSig = BuildTemplateSignature( c, typeTExpr );
        if( !typeSig )
            return nullopt;

        return TDecl( *typeSig, name );
    }




|







1
2
3
4
5
6
7
8
9
10
11
12
#include "builtins/builtins.h"

namespace goose::builtins
{
    optional< TDecl > BuildTDecl( const Context& c, const Term& typeTExpr, StringId name )
    {
        auto typeSig = BuildTemplateSignature( c, typeTExpr );
        if( !typeSig )
            return nullopt;

        return TDecl( *typeSig, name );
    }
Changes to bs/builtins/types/template/build.h.
1
2
3
4
5
6
7
8
9
10
11
12
13
#ifndef GOOSE_BUILTINS_TEMPLATE_BUILD_H
#define GOOSE_BUILTINS_TEMPLATE_BUILD_H

namespace goose::builtins
{
    extern optional< TDecl > BuildTDecl( const Context& c, const Term& typeTExpr, const StringId& name );
    extern TFuncType BuildTFuncType( const Value& returnType, const Value& params );
    extern optional< Term > BuildTFuncSignature( const Context& c, const TFuncType& tft );
    extern Value BuildTFunc( const Context& c, const TFuncType& tft, const Term& identity, const Value& params, ptr< void > body );

    extern optional< Term > BuildArgPatternFromTFuncType( const Context& c, const Value& tfuncType );
}






|







1
2
3
4
5
6
7
8
9
10
11
12
13
#ifndef GOOSE_BUILTINS_TEMPLATE_BUILD_H
#define GOOSE_BUILTINS_TEMPLATE_BUILD_H

namespace goose::builtins
{
    extern optional< TDecl > BuildTDecl( const Context& c, const Term& typeTExpr, StringId name );
    extern TFuncType BuildTFuncType( const Value& returnType, const Value& params );
    extern optional< Term > BuildTFuncSignature( const Context& c, const TFuncType& tft );
    extern Value BuildTFunc( const Context& c, const TFuncType& tft, const Term& identity, const Value& params, ptr< void > body );

    extern optional< Term > BuildArgPatternFromTFuncType( const Context& c, const Value& tfuncType );
}

Changes to bs/builtins/types/template/rules.cpp.
1
2
3
4
5
6
7
8
9
10
11
12
#include "builtins/builtins.h"

namespace goose::builtins
{
    static void setupTVar( const Context& c, TypeCheckingContext& tcc, const StringId& name )
    {
        // By convention, the callee's pattern will always be on the lhs of the type checking,
        // which means that the captures TVars will always be in the "left hand side" namespace
        // of the type checking context.
        auto varIndex = tcc.getLHSHoleIndex( name );
        if( varIndex == TypeCheckingContext::InvalidIndex )
            return;




|







1
2
3
4
5
6
7
8
9
10
11
12
#include "builtins/builtins.h"

namespace goose::builtins
{
    static void setupTVar( const Context& c, TypeCheckingContext& tcc, StringId name )
    {
        // By convention, the callee's pattern will always be on the lhs of the type checking,
        // which means that the captures TVars will always be in the "left hand side" namespace
        // of the type checking context.
        auto varIndex = tcc.getLHSHoleIndex( name );
        if( varIndex == TypeCheckingContext::InvalidIndex )
            return;
Changes to bs/builtins/types/template/tdecl.h.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#ifndef GOOSE_BUILTINS_TYPES_TEMPLATE_TDECL_H
#define GOOSE_BUILTINS_TYPES_TEMPLATE_TDECL_H

namespace goose::builtins
{
    extern void SetupTDeclTypeChecking( Env& e );
    extern TCGen UnifyTDecl( const Term& lhs, const Term& rhs, TypeCheckingContext c );
    extern Term BuildArgPatternFromTDecl( const Term& td );

    class TDecl
    {
        public:
            template< typename T >
            TDecl( T&& type, const StringId& name ) :
                m_type( forward< T >( type ) ),
                m_name( name )
            {}

            const auto& type() const { return m_type; }
            const auto& name() const { return m_name; }














|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#ifndef GOOSE_BUILTINS_TYPES_TEMPLATE_TDECL_H
#define GOOSE_BUILTINS_TYPES_TEMPLATE_TDECL_H

namespace goose::builtins
{
    extern void SetupTDeclTypeChecking( Env& e );
    extern TCGen UnifyTDecl( const Term& lhs, const Term& rhs, TypeCheckingContext c );
    extern Term BuildArgPatternFromTDecl( const Term& td );

    class TDecl
    {
        public:
            template< typename T >
            TDecl( T&& type, StringId name ) :
                m_type( forward< T >( type ) ),
                m_name( name )
            {}

            const auto& type() const { return m_type; }
            const auto& name() const { return m_name; }

Changes to bs/builtins/types/template/tnameddecl.h.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#ifndef GOOSE_BUILTINS_TYPES_TEMPLATE_TNAMEDDECL_H
#define GOOSE_BUILTINS_TYPES_TEMPLATE_TNAMEDDECL_H

namespace goose::builtins
{
    class TNamedDecl
    {
        public:
            template< typename T >
            TNamedDecl( T&& type, const StringId& name ) :
                m_type( forward< T >( type ) ),
                m_name( name )
            {}

            const auto& type() const { return m_type; }
            const auto& name() const { return m_name; }










|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#ifndef GOOSE_BUILTINS_TYPES_TEMPLATE_TNAMEDDECL_H
#define GOOSE_BUILTINS_TYPES_TEMPLATE_TNAMEDDECL_H

namespace goose::builtins
{
    class TNamedDecl
    {
        public:
            template< typename T >
            TNamedDecl( T&& type, StringId name ) :
                m_type( forward< T >( type ) ),
                m_name( name )
            {}

            const auto& type() const { return m_type; }
            const auto& name() const { return m_name; }

Changes to bs/builtins/types/template/ttvar.h.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#ifndef GOOSE_BUILTINS_TYPES_TEMPLATE_TTVAR_H
#define GOOSE_BUILTINS_TYPES_TEMPLATE_TTVAR_H

namespace goose::builtins
{
    class TTVar
    {
        public:
            TTVar( const StringId& name ) :
                m_name( name )
            {}

            const auto& name() const { return m_name; }

        private:
            StringId m_name;








|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#ifndef GOOSE_BUILTINS_TYPES_TEMPLATE_TTVAR_H
#define GOOSE_BUILTINS_TYPES_TEMPLATE_TTVAR_H

namespace goose::builtins
{
    class TTVar
    {
        public:
            TTVar( StringId name ) :
                m_name( name )
            {}

            const auto& name() const { return m_name; }

        private:
            StringId m_name;
Changes to bs/builtins/types/template/tvar.h.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#ifndef GOOSE_BUILTINS_TYPES_TEMPLATE_TVAR_H
#define GOOSE_BUILTINS_TYPES_TEMPLATE_TVAR_H

namespace goose::builtins
{
    class TVar
    {
        public:
            TVar( const StringId& name ) :
                m_name( name )
            {}

            const auto& name() const { return m_name; }

        private:
            StringId m_name;








|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#ifndef GOOSE_BUILTINS_TYPES_TEMPLATE_TVAR_H
#define GOOSE_BUILTINS_TYPES_TEMPLATE_TVAR_H

namespace goose::builtins
{
    class TVar
    {
        public:
            TVar( StringId name ) :
                m_name( name )
            {}

            const auto& name() const { return m_name; }

        private:
            StringId m_name;
Changes to bs/codegen/mangle.cpp.
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
//   p, P: a void* or ptr< void > term (unfortunately they have legitimate uses in some type identitiers
//      that we do need to be able to mangle)
//   x: an eir term placeholder.
//
// $: compressed string id: it is followed by the 0 based index of a previously encountered
//   StringId literal, in the order they were encountered.
//
// The letters V, o, v, t, q, u, r, R, n, l:
//   respectively the StringIDs: Value, Constant, void, type,
//   quote, func, param, predicates, anyflavor, bool.
//   (those are super recurrent StringIDs in every function identity, so they have dedicated
//   symbols to make things shorter. Note that none of those can be the letter a to f)
//
// Some types of Terms (wildcards such as AnyTerm, opaque pointer to c++ objects) are not meant
// to appear in an identity expression and will cause mangling to fail.








|
|







26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
//   p, P: a void* or ptr< void > term (unfortunately they have legitimate uses in some type identitiers
//      that we do need to be able to mangle)
//   x: an eir term placeholder.
//
// $: compressed string id: it is followed by the 0 based index of a previously encountered
//   StringId literal, in the order they were encountered.
//
// The letters V, o, v, t, T, q, u, r, R, n, l:
//   respectively the StringIDs: Value, Constant, void, type, rt_type,
//   quote, func, param, predicates, anyflavor, bool.
//   (those are super recurrent StringIDs in every function identity, so they have dedicated
//   symbols to make things shorter. Note that none of those can be the letter a to f)
//
// Some types of Terms (wildcards such as AnyTerm, opaque pointer to c++ objects) are not meant
// to appear in an identity expression and will cause mangling to fail.

100
101
102
103
104
105
106
107
108
109
110
111
112
113
114

            bool mangle( void* pv )
            {
                m_mangled << 'p';
                return true;
            }

            bool mangle( const StringId& strId )
            {
                // Some hard coded abbreviations for super recurrent stuff that ends up being present every time.
                // Not strictly necessary, but makes for shorter symbols.
                if( strId == "value"_sid )
                {
                    m_mangled << 'V';
                    return true;







|







100
101
102
103
104
105
106
107
108
109
110
111
112
113
114

            bool mangle( void* pv )
            {
                m_mangled << 'p';
                return true;
            }

            bool mangle( StringId strId )
            {
                // Some hard coded abbreviations for super recurrent stuff that ends up being present every time.
                // Not strictly necessary, but makes for shorter symbols.
                if( strId == "value"_sid )
                {
                    m_mangled << 'V';
                    return true;
129
130
131
132
133
134
135






136
137
138
139
140
141
142
                }

                if( strId == "type"_sid )
                {
                    m_mangled << 't';
                    return true;
                }







                if( strId == "quote"_sid )
                {
                    m_mangled << 'q';
                    return true;
                }








>
>
>
>
>
>







129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
                }

                if( strId == "type"_sid )
                {
                    m_mangled << 't';
                    return true;
                }

                if( strId == "rt_type"_sid )
                {
                    m_mangled << 'T';
                    return true;
                }

                if( strId == "quote"_sid )
                {
                    m_mangled << 'q';
                    return true;
                }

Changes to bs/diagnostics/diagnosticsmanager.cpp.
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
    {
        if( !m_vContextStack.empty() && m_vContextStack.back()->verbosity() != Verbosity::Normal )
            return;

        emitError( locationId, message, contextLevels );
    }

    void DiagnosticsManager::emitErrorMessage( uint32_t locationId, const StringId& errId, const string& message, uint32_t contextLevels )
    {
        if( !m_vContextStack.empty() && m_vContextStack.back()->verbosity() != Verbosity::Normal )
            return;

        auto it = m_customDiagnostics.find( make_pair( locationId, errId ) );
        if( it == m_customDiagnostics.end() )
            emitError( locationId, message, contextLevels );







|







20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
    {
        if( !m_vContextStack.empty() && m_vContextStack.back()->verbosity() != Verbosity::Normal )
            return;

        emitError( locationId, message, contextLevels );
    }

    void DiagnosticsManager::emitErrorMessage( uint32_t locationId, StringId errId, const string& message, uint32_t contextLevels )
    {
        if( !m_vContextStack.empty() && m_vContextStack.back()->verbosity() != Verbosity::Normal )
            return;

        auto it = m_customDiagnostics.find( make_pair( locationId, errId ) );
        if( it == m_customDiagnostics.end() )
            emitError( locationId, message, contextLevels );
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
    {
        Renderer r( llvm::outs() );

        r.addContext( locationId, Renderer::Squiggles,
            message, Renderer::Colors::Trace );
    }

    void DiagnosticsManager::defineCustomDiagnostic( uint32_t locationId, const StringId& errId, const string& message )
    {
        m_customDiagnostics.emplace( make_pair( locationId, errId ), message );
    }

    void DiagnosticsManager::emitError( uint32_t locationId, const string& message, uint32_t contextLevels )
    {
        if( m_emittedFirstError )







|







51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
    {
        Renderer r( llvm::outs() );

        r.addContext( locationId, Renderer::Squiggles,
            message, Renderer::Colors::Trace );
    }

    void DiagnosticsManager::defineCustomDiagnostic( uint32_t locationId, StringId errId, const string& message )
    {
        m_customDiagnostics.emplace( make_pair( locationId, errId ), message );
    }

    void DiagnosticsManager::emitError( uint32_t locationId, const string& message, uint32_t contextLevels )
    {
        if( m_emittedFirstError )
Changes to bs/diagnostics/diagnosticsmanager.h.
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
        friend class VerbosityContext;

        public:
            static DiagnosticsManager& GetInstance();

            void emitErrorMessage( uint32_t locationId, const string& message, uint32_t contextLevels = ~0 );

            void emitErrorMessage( uint32_t locationId, const StringId& errId, const string& message, uint32_t contextLevels = ~0 );

            // This is similar to standard error message, but it also set the verbosity level for the
            // current context to "Silent", as syntax errors are likely to cause cascading errors
            // for the rest of the scope.
            void emitSyntaxErrorMessage( uint32_t locationId, const string& message, uint32_t contextLevels = ~0 );

            // This is similar to emitErrorMessage, except it nevers display any context.
            void emitLexerErrorMessage( uint32_t locationId, const string& message );

            void emitTraceMessage( uint32_t locationId, const string& message );

            void defineCustomDiagnostic( uint32_t locationId, const StringId& errId, const string& message );

            // When enabled, all diagnostics contexts will be pretty printed on the standard output.
            void setTraceMode( bool enable )
            {
                m_traceMode = enable;
            }








|











|







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
        friend class VerbosityContext;

        public:
            static DiagnosticsManager& GetInstance();

            void emitErrorMessage( uint32_t locationId, const string& message, uint32_t contextLevels = ~0 );

            void emitErrorMessage( uint32_t locationId, StringId errId, const string& message, uint32_t contextLevels = ~0 );

            // This is similar to standard error message, but it also set the verbosity level for the
            // current context to "Silent", as syntax errors are likely to cause cascading errors
            // for the rest of the scope.
            void emitSyntaxErrorMessage( uint32_t locationId, const string& message, uint32_t contextLevels = ~0 );

            // This is similar to emitErrorMessage, except it nevers display any context.
            void emitLexerErrorMessage( uint32_t locationId, const string& message );

            void emitTraceMessage( uint32_t locationId, const string& message );

            void defineCustomDiagnostic( uint32_t locationId, StringId errId, const string& message );

            // When enabled, all diagnostics contexts will be pretty printed on the standard output.
            void setTraceMode( bool enable )
            {
                m_traceMode = enable;
            }

Changes to bs/eir/decompose.inl.
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
                return true;
        }
        else
        {
            get< IR >( result ) = move( res );

            if constexpr( IS < ( sizeof... ( S ) - 1 ) )
                Decompose< IR + 1, IS + 1 >( terms, specs, result );

            return true;
        }
    }

    template< typename... S >
    optional< typename VectorSpec< S... >::return_type > Decompose( const Term& t, const VectorSpec< S... >& spec )







|







70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
                return true;
        }
        else
        {
            get< IR >( result ) = move( res );

            if constexpr( IS < ( sizeof... ( S ) - 1 ) )
                return Decompose< IR + 1, IS + 1 >( terms, specs, result );

            return true;
        }
    }

    template< typename... S >
    optional< typename VectorSpec< S... >::return_type > Decompose( const Term& t, const VectorSpec< S... >& spec )
Changes to bs/eir/enumerate.inl.
89
90
91
92
93
94
95

96
97
98
99
100
101
102
103
    {
        for( auto&& [k, branch] : trie.m_fixedLengthBranches )
            co_yield Enumerate< U >( Vector(), branch );

        using rpt_node = ptr< TrieContainerRepetitionNode< U > >;
        for( auto&& [k, branch] : trie.m_variableLengthBranches )
        {

            for( auto&& [vecTerm, pRptNode] : Enumerate< rpt_node >( Vector(), branch ) )
            {
                for( auto&& [repetitionTerm, payload] : Enumerate< U >( pRptNode->m_repetition ) )
                {
                    auto pNewVec = make_shared< Vector >( *get< pvec >( vecTerm ) );
                    pNewVec->setRepetitionTerm( move( repetitionTerm ) );
                    co_yield { TERM( move( pNewVec ) ), payload };
                }







>
|







89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
    {
        for( auto&& [k, branch] : trie.m_fixedLengthBranches )
            co_yield Enumerate< U >( Vector(), branch );

        using rpt_node = ptr< TrieContainerRepetitionNode< U > >;
        for( auto&& [k, branch] : trie.m_variableLengthBranches )
        {
            Vector v;
            for( auto&& [vecTerm, pRptNode] : Enumerate< rpt_node >( move( v ), branch ) )
            {
                for( auto&& [repetitionTerm, payload] : Enumerate< U >( pRptNode->m_repetition ) )
                {
                    auto pNewVec = make_shared< Vector >( *get< pvec >( vecTerm ) );
                    pNewVec->setRepetitionTerm( move( repetitionTerm ) );
                    co_yield { TERM( move( pNewVec ) ), payload };
                }
Changes to bs/eir/match.h.
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
        public:
            size_t complexity() const { return m_complexity; }
            size_t numVars() const;

            MatchScore score() const { return MatchScore{ m_complexity, m_pVars ? m_pVars->size() : 0 }; }

            template< typename T >
            const T* getVar( const StringId& name ) const
            {
                if( name == "_"_sid )
                    return nullptr;

                if( !m_pVars )
                    return nullptr;

                auto it = m_pVars->find( name );
                if( it == m_pVars->end() )
                    return nullptr;

                return any_cast< T >( &it->second );
            }

            // Tries to set the variable. If it already exists but have a different
            // value, returns false.
            template< typename T >
            bool setVar( const StringId& name, T&& val )
            {
                if( name == "_"_sid )
                    return true;

                if( m_pVars )
                {
                    auto it = m_pVars->find( name );







|

















|







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
        public:
            size_t complexity() const { return m_complexity; }
            size_t numVars() const;

            MatchScore score() const { return MatchScore{ m_complexity, m_pVars ? m_pVars->size() : 0 }; }

            template< typename T >
            const T* getVar( StringId name ) const
            {
                if( name == "_"_sid )
                    return nullptr;

                if( !m_pVars )
                    return nullptr;

                auto it = m_pVars->find( name );
                if( it == m_pVars->end() )
                    return nullptr;

                return any_cast< T >( &it->second );
            }

            // Tries to set the variable. If it already exists but have a different
            // value, returns false.
            template< typename T >
            bool setVar( StringId name, T&& val )
            {
                if( name == "_"_sid )
                    return true;

                if( m_pVars )
                {
                    auto it = m_pVars->find( name );
Changes to bs/eir/term.h.
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
    struct STerm;

    class Hole
    {
        public:
            Hole() = default;

            Hole( const StringId& name );

            template< typename F >
            Hole( const StringId& name, F&& flavor ) :
                m_name( name ),
                m_flavor( make_shared< STerm >( STerm{ forward< F >( flavor ) } ) )
            {}

            const auto& name() const { return m_name; }
            const auto& flavor() const;








|


|







27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
    struct STerm;

    class Hole
    {
        public:
            Hole() = default;

            Hole( StringId name );

            template< typename F >
            Hole( StringId name, F&& flavor ) :
                m_name( name ),
                m_flavor( make_shared< STerm >( STerm{ forward< F >( flavor ) } ) )
            {}

            const auto& name() const { return m_name; }
            const auto& flavor() const;

77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
    extern bool operator!=( const Term& lhs, const Term& rhs );

    struct STerm
    {
        Term content;
    };

    inline Hole::Hole( const StringId& name ) : Hole( name, Term( "anyflavor"_sid ) ) {}
    inline const auto& Hole::flavor() const { return m_flavor->content; }

    extern ostream& operator<<( ostream& out, const Term& t );

    // A term associated with a location id.
    // Used to represent tokens and tokens/values coming out of the resolver.
    using TermLoc = pair< eir::Term, uint32_t >;







|







77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
    extern bool operator!=( const Term& lhs, const Term& rhs );

    struct STerm
    {
        Term content;
    };

    inline Hole::Hole( StringId name ) : Hole( name, Term( "anyflavor"_sid ) ) {}
    inline const auto& Hole::flavor() const { return m_flavor->content; }

    extern ostream& operator<<( ostream& out, const Term& t );

    // A term associated with a location id.
    // Used to represent tokens and tokens/values coming out of the resolver.
    using TermLoc = pair< eir::Term, uint32_t >;
Changes to bs/eir/tostring.cpp.
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
                    break;
            }
        }

        return out << delim;
    }

    ostream& ToString( ostream& out, const StringId& x )
    {
        return out << x;
    }

    ostream& ToString( ostream& out, const Delimiter& x )
    {
        const char* name = "";







|







36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
                    break;
            }
        }

        return out << delim;
    }

    ostream& ToString( ostream& out, StringId x )
    {
        return out << x;
    }

    ostream& ToString( ostream& out, const Delimiter& x )
    {
        const char* name = "";
Changes to bs/eir/tostring.h.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#ifndef GOOSE_EIR_TOSTRING_H
#define GOOSE_EIR_TOSTRING_H

namespace goose::eir
{
    class Vector;
    enum class Delimiter;

    extern ostream& ToString( ostream& out, const Term& t );

    extern ostream& ToString( ostream& out, const uint32_t& x );
    extern ostream& ToString( ostream& out, const LocationId& x );
    extern ostream& ToString( ostream& out, const string& x, char delim = '\'' );
    extern ostream& ToString( ostream& out, const StringId& x );
    extern ostream& ToString( ostream& out, const Delimiter& x );
    extern ostream& ToString( ostream& out, const Hole& x );
    extern ostream& ToString( ostream& out, const ptr< void >& x );
    extern ostream& ToString( ostream& out, const void* x );
    extern ostream& ToString( ostream& out, const ptr< Vector >& v );

    extern ostream& ToString( ostream& out, const BigInt& t );













|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#ifndef GOOSE_EIR_TOSTRING_H
#define GOOSE_EIR_TOSTRING_H

namespace goose::eir
{
    class Vector;
    enum class Delimiter;

    extern ostream& ToString( ostream& out, const Term& t );

    extern ostream& ToString( ostream& out, const uint32_t& x );
    extern ostream& ToString( ostream& out, const LocationId& x );
    extern ostream& ToString( ostream& out, const string& x, char delim = '\'' );
    extern ostream& ToString( ostream& out, StringId x );
    extern ostream& ToString( ostream& out, const Delimiter& x );
    extern ostream& ToString( ostream& out, const Hole& x );
    extern ostream& ToString( ostream& out, const ptr< void >& x );
    extern ostream& ToString( ostream& out, const void* x );
    extern ostream& ToString( ostream& out, const ptr< Vector >& v );

    extern ostream& ToString( ostream& out, const BigInt& t );
Changes to bs/eir/vector.h.
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
                    // structure intact will be used over solutions that
                    // don't.
                    m_weight += GetWeight( term ) * 2;
                    m_terms.emplace_back( forward< T >( term ) );
                }
                else
                {
                    setRepetitionTerm( forward< T >( term ) );
                }
            }

            template< typename... T >
            static auto Make( T&&... terms )
            {
                auto v = make_shared< Vector >();







|







67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
                    // structure intact will be used over solutions that
                    // don't.
                    m_weight += GetWeight( term ) * 2;
                    m_terms.emplace_back( forward< T >( term ) );
                }
                else
                {
                    setRepetitionTerm( term.m_term );
                }
            }

            template< typename... T >
            static auto Make( T&&... terms )
            {
                auto v = make_shared< Vector >();
Name change from bs/g0api/extensibility/term.cpp to bs/g0api/extensibility/eir.cpp.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include "g0api/g0api.h"
#include "eir/eir.h"
#include "parse/parse.h"
#include "builtins/helpers.h"

using namespace goose;
using namespace goose::parse;
using namespace goose::builtins;

namespace goose::g0api
{
    void SetupTermExtensibilityFuncs( Env& e )
    {
        // Constants.
        DefineConstant( e, "DelimiterOpenParen"_sid, ValueToEIR( ToValue( static_cast< uint8_t >( Delimiter::OpenParen ) ) ) );
        DefineConstant( e, "DelimiterOpenBrace"_sid, ValueToEIR( ToValue( static_cast< uint8_t >( Delimiter::OpenBrace ) ) ) );
        DefineConstant( e, "DelimiterOpenBracket"_sid, ValueToEIR( ToValue( static_cast< uint8_t >( Delimiter::OpenBracket ) ) ) );
        DefineConstant( e, "DelimiterCloseParen"_sid, ValueToEIR( ToValue( static_cast< uint8_t >( Delimiter::CloseParen ) ) ) );
        DefineConstant( e, "DelimiterCloseBrace"_sid, ValueToEIR( ToValue( static_cast< uint8_t >( Delimiter::CloseBrace ) ) ) );











|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include "g0api/g0api.h"
#include "eir/eir.h"
#include "parse/parse.h"
#include "builtins/helpers.h"

using namespace goose;
using namespace goose::parse;
using namespace goose::builtins;

namespace goose::g0api
{
    void SetupEIRExtensibilityFuncs( Env& e )
    {
        // Constants.
        DefineConstant( e, "DelimiterOpenParen"_sid, ValueToEIR( ToValue( static_cast< uint8_t >( Delimiter::OpenParen ) ) ) );
        DefineConstant( e, "DelimiterOpenBrace"_sid, ValueToEIR( ToValue( static_cast< uint8_t >( Delimiter::OpenBrace ) ) ) );
        DefineConstant( e, "DelimiterOpenBracket"_sid, ValueToEIR( ToValue( static_cast< uint8_t >( Delimiter::OpenBracket ) ) ) );
        DefineConstant( e, "DelimiterCloseParen"_sid, ValueToEIR( ToValue( static_cast< uint8_t >( Delimiter::CloseParen ) ) ) );
        DefineConstant( e, "DelimiterCloseBrace"_sid, ValueToEIR( ToValue( static_cast< uint8_t >( Delimiter::CloseBrace ) ) ) );
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
            VecOfLength,
            Vec,
            BigInt,
            FixedInt,
            Internal
        };

        // These must match the order of the Term variant.
        DefineConstant( e, "TermTypeUInt32"_sid, ValueToEIR( ToValue( static_cast< uint8_t >( TermType::UInt32 ) ) ) );
        DefineConstant( e, "TermTypeLocationId"_sid, ValueToEIR( ToValue( static_cast< uint8_t >( TermType::LocationId ) ) ) );
        DefineConstant( e, "TermTypeString"_sid, ValueToEIR( ToValue( static_cast< uint8_t >( TermType::String ) ) ) );
        DefineConstant( e, "TermTypeStringId"_sid, ValueToEIR( ToValue( static_cast< uint8_t >( TermType::StringId ) ) ) );
        DefineConstant( e, "TermTypeDelimiter"_sid, ValueToEIR( ToValue( static_cast< uint8_t >( TermType::Delimiter ) ) ) );
        DefineConstant( e, "TermTypeHole"_sid, ValueToEIR( ToValue( static_cast< uint8_t >( TermType::Hole ) ) ) );
        DefineConstant( e, "TermTypeAnyTerm"_sid, ValueToEIR( ToValue( static_cast< uint8_t >( TermType::AnyTerm ) ) ) );







<







32
33
34
35
36
37
38

39
40
41
42
43
44
45
            VecOfLength,
            Vec,
            BigInt,
            FixedInt,
            Internal
        };


        DefineConstant( e, "TermTypeUInt32"_sid, ValueToEIR( ToValue( static_cast< uint8_t >( TermType::UInt32 ) ) ) );
        DefineConstant( e, "TermTypeLocationId"_sid, ValueToEIR( ToValue( static_cast< uint8_t >( TermType::LocationId ) ) ) );
        DefineConstant( e, "TermTypeString"_sid, ValueToEIR( ToValue( static_cast< uint8_t >( TermType::String ) ) ) );
        DefineConstant( e, "TermTypeStringId"_sid, ValueToEIR( ToValue( static_cast< uint8_t >( TermType::StringId ) ) ) );
        DefineConstant( e, "TermTypeDelimiter"_sid, ValueToEIR( ToValue( static_cast< uint8_t >( TermType::Delimiter ) ) ) );
        DefineConstant( e, "TermTypeHole"_sid, ValueToEIR( ToValue( static_cast< uint8_t >( TermType::Hole ) ) ) );
        DefineConstant( e, "TermTypeAnyTerm"_sid, ValueToEIR( ToValue( static_cast< uint8_t >( TermType::AnyTerm ) ) ) );
Changes to bs/g0api/extensibility/extensibility.h.
1
2
3
4

5
6
7
8
9
10
11
12

13
14
15
16
17
#ifndef GOOSE_G0_API_EXTENSIBILITY_H
#define GOOSE_G0_API_EXTENSIBILITY_H

#include "termwrapper.h"

#include "termref.h"

namespace goose::g0api
{
    extern void SetupTermExtensibilityFuncs( Env& e );

    static inline void SetupApiExtensibility( Env& e )
    {

        SetupTermExtensibilityFuncs( e );
    }
}

#endif




>




|



>
|




1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#ifndef GOOSE_G0_API_EXTENSIBILITY_H
#define GOOSE_G0_API_EXTENSIBILITY_H

#include "termwrapper.h"
#include "typewrappers.h"
#include "termref.h"

namespace goose::g0api
{
    extern void SetupEIRExtensibilityFuncs( Env& e );

    static inline void SetupApiExtensibility( Env& e )
    {
        SetupTypeWrappers( e );
        SetupEIRExtensibilityFuncs( e );
    }
}

#endif
Added bs/g0api/extensibility/typewrappers.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
#include "g0api/g0api.h"
#include "eir/eir.h"
#include "builtins/helpers.h"

using namespace goose;
using namespace goose::g0api;

namespace
{
    template< typename T >
    void SetupWrapperForType( Env& e, StringId name )
    {
        DefineConstant( e, name, GetValueType< TypeWrapper< T > >() );

        using reftype = CustomPattern< Value, ReferenceType::PatternMutableOfType< TypeWrapper< T > > >;
        auto type = ValueToEIR( ToValue( builtins::ReferenceType( GetValueType< TypeWrapper< T > >(), TSID( mut ) ) ) );
        RegisterBuiltinFunc< Intrinsic< Value ( reftype ) > >( e, e.extInitialize(),
            []( auto&& c, const Value& r )
            {
                // Do nothing: the types we're wrapping are default initialized anyway.
                // The only purpose of this Initialize overload is to let goose know that
                // the type has a default initialization.
                return Value( GetValueType< void >(), 0U );
            } );

        // TODO: assignment operator, equality operator, inequality operator

    }
}

namespace goose::g0api
{
    void SetupTypeWrappers( Env& e )
    {
        SetupWrapperForType< LocationId >( e, "LocationId"_sid );
    }
}
Added bs/g0api/extensibility/typewrappers.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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
#ifndef GOOSE_G0API_EXTENSIBILITY_TYPEWRAPPERS_H
#define GOOSE_G0API_EXTENSIBILITY_TYPEWRAPPERS_H

namespace goose::g0api
{
    extern void SetupTypeWrappers( Env& e );

    template< typename T >
    class TypeWrapper
    {
        public:
            template< typename TT >
            TypeWrapper( TT&& val ) :
                m_val( forward< TT >( val ) )
            {}

            const auto& get() const
            {
                return m_val;
            }

            auto& get()
            {
                return m_val;
            }

        private:
            T m_val;
    };

    template< typename T >
    struct TypeWrapperTraits {};

    template<>
    struct TypeWrapperTraits< LocationId >
    {
        static auto typeId() { return "locationId"_sid; }
    };
}

namespace goose::eir
{
    template< typename T >
    struct Bridge< g0api::TypeWrapper< T > >
    {
        static const Term& Type()
        {
            static auto type = ValueToEIR( Value( TypeType(), VEC( TSID( ct_type ),
                TSID( g0api::TypeWrapperTraits< T >::typeId() ) ) ) );
            return type;
        }

        static Value ToValue( const g0api::TypeWrapper< T >& tw )
        {
            return Value( Type(), TERM( tw.get() ) );
        }

        static optional< T > FromValue( const Value& v )
        {
            if( v.type() != Type() )
                return nullopt;

            const auto* pVal = get_if< T >( v.val() );
            if( !pVal )
                return nullopt;

            return *pVal;
        }
    };
}

#endif
Changes to bs/g0api/meson.build.
1
2
3
4
5
6
7
8
9
10
11
12
13

14
15
16
17
18
goose_g0api = library( 'goose-g0api',
    'string.cpp',
    'compiler.cpp',

    'support/cast.cpp',
    'support/verification.cpp',

    'cgapi/module.cpp',
    'cgapi/mangle.cpp',
    'cgapi/func.cpp',
    'cgapi/linker.cpp',

    'extensibility/termwrapper.cpp',

    'extensibility/term.cpp',

    include_directories: bsinc,
    dependencies: fmt_dep
)













>
|




1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
goose_g0api = library( 'goose-g0api',
    'string.cpp',
    'compiler.cpp',

    'support/cast.cpp',
    'support/verification.cpp',

    'cgapi/module.cpp',
    'cgapi/mangle.cpp',
    'cgapi/func.cpp',
    'cgapi/linker.cpp',

    'extensibility/termwrapper.cpp',
    'extensibility/typewrappers.cpp',
    'extensibility/eir.cpp',

    include_directories: bsinc,
    dependencies: fmt_dep
)
Changes to bs/parse/parser.cpp.
1
2
3
4
5
6
7
8

#include "parse.h"
#include "builtins/builtins.h"

using namespace goose;
using namespace goose::parse;
using namespace goose::builtins;

<








1
2
3
4
5
6
7

#include "parse.h"
#include "builtins/builtins.h"

using namespace goose;
using namespace goose::parse;
using namespace goose::builtins;

147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
    auto tok = m_resolver->consume();
    pushValue( ToValue( strlit ).setLocationId( tok->second ) );
    return true;
}

// Standalone (ie not part of a grammar construct that expects them such as a decl), unresolved identifiers
// end up here.
bool Parser::parsePrefix( const StringId& strid, uint32_t )
{
    auto tok = m_resolver->consume();
    DiagnosticsManager::GetInstance().emitSyntaxErrorMessage( tok->second,
        "undefined identifier.", 0 );
    return true;
}

// Infix identifiers: if the left value is a type, then we have a decl.
optional< uint32_t > Parser::getPrecedence( const Term&, const StringId& strid )
{
    const auto& leftVal = peekLastValue();
    if( !leftVal )
        return nullopt;

    // If leftVal is a type, this is a decl, so set the precedence to Application.
    if( IsTExpr( *leftVal ) || IsType( context(), *leftVal ) )







|








|







146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
    auto tok = m_resolver->consume();
    pushValue( ToValue( strlit ).setLocationId( tok->second ) );
    return true;
}

// Standalone (ie not part of a grammar construct that expects them such as a decl), unresolved identifiers
// end up here.
bool Parser::parsePrefix( StringId strid, uint32_t )
{
    auto tok = m_resolver->consume();
    DiagnosticsManager::GetInstance().emitSyntaxErrorMessage( tok->second,
        "undefined identifier.", 0 );
    return true;
}

// Infix identifiers: if the left value is a type, then we have a decl.
optional< uint32_t > Parser::getPrecedence( const Term&, StringId strid )
{
    const auto& leftVal = peekLastValue();
    if( !leftVal )
        return nullopt;

    // If leftVal is a type, this is a decl, so set the precedence to Application.
    if( IsTExpr( *leftVal ) || IsType( context(), *leftVal ) )
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
        return precedence::FuncDecl;
    }

    return nullopt;
}

// An unbound infix identifier
bool Parser::parseInfix( const StringId& strid, uint32_t prec )
{
    const auto& leftVal = peekLastValue();
    if( !leftVal )
        return parsePrefix( strid, prec );

    auto nameTerm = m_resolver->consume();
    const auto* name = get_if< StringId >( &nameTerm->first );







|







193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
        return precedence::FuncDecl;
    }

    return nullopt;
}

// An unbound infix identifier
bool Parser::parseInfix( StringId strid, uint32_t prec )
{
    const auto& leftVal = peekLastValue();
    if( !leftVal )
        return parsePrefix( strid, prec );

    auto nameTerm = m_resolver->consume();
    const auto* name = get_if< StringId >( &nameTerm->first );
Changes to bs/parse/parser.h.
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126

            // Literals
            bool parsePrefix( const BigInt& intlit, uint32_t );
            bool parsePrefix( uint32_t charlit, uint32_t );
            bool parsePrefix( const string& strlit, uint32_t );

            // Unresolved identifiers
            bool parsePrefix( const StringId& strid, uint32_t );

            optional< uint32_t > getPrecedence( const Term&, const StringId& strid );
            bool parseInfix( const StringId& strid, uint32_t );

            // Vector terms (values)
            optional< uint32_t > getPrecedence( const Term&, const pvec& vec );
            bool parsePrefix( const pvec& vec, uint32_t prec );
            bool parseInfix( const pvec& vec, uint32_t prec );

            // Blocks







|

|
|







109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126

            // Literals
            bool parsePrefix( const BigInt& intlit, uint32_t );
            bool parsePrefix( uint32_t charlit, uint32_t );
            bool parsePrefix( const string& strlit, uint32_t );

            // Unresolved identifiers
            bool parsePrefix( StringId strid, uint32_t );

            optional< uint32_t > getPrecedence( const Term&, StringId strid );
            bool parseInfix( StringId strid, uint32_t );

            // Vector terms (values)
            optional< uint32_t > getPrecedence( const Term&, const pvec& vec );
            bool parsePrefix( const pvec& vec, uint32_t prec );
            bool parseInfix( const pvec& vec, uint32_t prec );

            // Blocks
Changes to bs/parse/rule-helpers.h.
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
}

namespace goose::parse
{
    void RegisterRule( sema::Env& env, const Term& identity, Rule&& rule );

    template< typename... R >
    void BuildParseRule( sema::Env& env, const StringId& name, const Term& identity, R&&... ruleBuilders )
    {
        Rule r;
        ( ( ruleBuilders( env, r, name ) ), ... );
        RegisterRule( env, identity, move( r ) );
    }

    template< typename F >







|







13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
}

namespace goose::parse
{
    void RegisterRule( sema::Env& env, const Term& identity, Rule&& rule );

    template< typename... R >
    void BuildParseRule( sema::Env& env, StringId name, const Term& identity, R&&... ruleBuilders )
    {
        Rule r;
        ( ( ruleBuilders( env, r, name ) ), ... );
        RegisterRule( env, identity, move( r ) );
    }

    template< typename F >
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
        return [&,precedence]( auto&& e, auto&& r, auto&& name )
        {
            MakeRightAssInfixOp( e, r, name, precedence, forward< F >( func ) );
        };
    }

    template< typename F >
    void MakePrefixOp( sema::Env& env, Rule& r, const StringId& name, uint32_t precedence, F&& func );

    template< typename F >
    void MakePostfixOp( sema::Env& env, Rule& r, const StringId& name, uint32_t precedence, F&& func );

    template< typename F >
    void MakeLeftAssInfixOp( sema::Env& env, Rule& r, const StringId& name, uint32_t precedence, F&& func );

    template< typename F >
    void MakeRightAssInfixOp( sema::Env& env, Rule& r, const StringId& name, uint32_t precedence, F&& func );
}

#endif







|


|


|


|



57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
        return [&,precedence]( auto&& e, auto&& r, auto&& name )
        {
            MakeRightAssInfixOp( e, r, name, precedence, forward< F >( func ) );
        };
    }

    template< typename F >
    void MakePrefixOp( sema::Env& env, Rule& r, StringId name, uint32_t precedence, F&& func );

    template< typename F >
    void MakePostfixOp( sema::Env& env, Rule& r, StringId name, uint32_t precedence, F&& func );

    template< typename F >
    void MakeLeftAssInfixOp( sema::Env& env, Rule& r, StringId name, uint32_t precedence, F&& func );

    template< typename F >
    void MakeRightAssInfixOp( sema::Env& env, Rule& r, StringId name, uint32_t precedence, F&& func );
}

#endif
Changes to bs/parse/rule-helpers.inl.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#ifndef GOOSE_PARSE_RULE_HELPERS_INL
#define GOOSE_PARSE_RULE_HELPERS_INL

namespace goose::parse
{
    template< typename F >
    void MakePrefixOp( sema::Env& env, Rule& r, const StringId& name, uint32_t precedence, F&& func )
    {
        r.setPrefixFunc( [=]( Parser& p, uint32_t locationId, uint32_t prec )
        {
            optional< Value > rightVal;

            {
                auto np = p.makeNestedParser();






|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
#ifndef GOOSE_PARSE_RULE_HELPERS_INL
#define GOOSE_PARSE_RULE_HELPERS_INL

namespace goose::parse
{
    template< typename F >
    void MakePrefixOp( sema::Env& env, Rule& r, StringId name, uint32_t precedence, F&& func )
    {
        r.setPrefixFunc( [=]( Parser& p, uint32_t locationId, uint32_t prec )
        {
            optional< Value > rightVal;

            {
                auto np = p.makeNestedParser();
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
            auto result = func( p, *rightVal );
            p.pushValue( move( result ).setLocationId( loc ) );
            return true;
        } );
    }

    template< typename F >
    void MakePostfixOp( sema::Env& env, Rule& r, const StringId& name, uint32_t precedence, F&& func )
    {
        r.setInfixFunc(
            [=]( const Parser& p ) { return precedence; },
            [=]( Parser& p, uint32_t locationId, uint32_t prec )
            {
                auto leftVal = p.popValue();
                if( !leftVal )







|







40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
            auto result = func( p, *rightVal );
            p.pushValue( move( result ).setLocationId( loc ) );
            return true;
        } );
    }

    template< typename F >
    void MakePostfixOp( sema::Env& env, Rule& r, StringId name, uint32_t precedence, F&& func )
    {
        r.setInfixFunc(
            [=]( const Parser& p ) { return precedence; },
            [=]( Parser& p, uint32_t locationId, uint32_t prec )
            {
                auto leftVal = p.popValue();
                if( !leftVal )
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
                auto loc = Location::CreateSpanningLocation( leftVal->locationId(), locationId );
                auto result = func( p, *leftVal );
                p.pushValue( move( result ).setLocationId( loc ) );
            } );
    }

    template< typename F >
    void MakeLeftAssInfixOp( sema::Env& env, Rule& r, const StringId& name, uint32_t precedence, F&& func )
    {
        r.setInfixFunc(
            [=]( const Parser& p ) { return precedence; },
            [=]( Parser& p, uint32_t locationId, uint32_t prec )
            {
                auto leftVal = p.popValue();
                if( !leftVal )







|







69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
                auto loc = Location::CreateSpanningLocation( leftVal->locationId(), locationId );
                auto result = func( p, *leftVal );
                p.pushValue( move( result ).setLocationId( loc ) );
            } );
    }

    template< typename F >
    void MakeLeftAssInfixOp( sema::Env& env, Rule& r, StringId name, uint32_t precedence, F&& func )
    {
        r.setInfixFunc(
            [=]( const Parser& p ) { return precedence; },
            [=]( Parser& p, uint32_t locationId, uint32_t prec )
            {
                auto leftVal = p.popValue();
                if( !leftVal )
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
                auto result = func( p, *leftVal, *rightVal );
                p.pushValue( move( result ).setLocationId( loc ) );
                return true;
            } );
    }

    template< typename F >
    void MakeRightAssInfixOp( sema::Env& env, Rule& r, const StringId& name, uint32_t precedence, F&& func )
    {
        r.setInfixFunc(
            [=]( const Parser& p ) { return precedence; },
            [=]( Parser& p, uint32_t locationId, uint32_t prec )
            {
                auto leftVal = p.popValue();
                if( !leftVal )







|







121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
                auto result = func( p, *leftVal, *rightVal );
                p.pushValue( move( result ).setLocationId( loc ) );
                return true;
            } );
    }

    template< typename F >
    void MakeRightAssInfixOp( sema::Env& env, Rule& r, StringId name, uint32_t precedence, F&& func )
    {
        r.setInfixFunc(
            [=]( const Parser& p ) { return precedence; },
            [=]( Parser& p, uint32_t locationId, uint32_t prec )
            {
                auto leftVal = p.popValue();
                if( !leftVal )
Changes to bs/sema/tc-context.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
#include "sema.h"

using namespace goose;
using namespace goose::sema;

TypeCheckingContext::TypeCheckingContext( const Context& c ) :
    m_context( c )
{}

TypeCheckingContext::TypeCheckingContext( Context&& c ) :
    m_context( move( c ) )
{}

uint32_t TypeCheckingContext::getLHSHoleIndex( const StringId& name ) const
{
    if( name == "_"_sid )
        return InvalidIndex;

    HoleName holeName( name, m_currentLHSNamespaceIndex );

    auto it = m_pCow->holeDict.find( holeName );
    if( it == m_pCow->holeDict.end() )
        return InvalidIndex;

    return it->second;
}

uint32_t TypeCheckingContext::getRHSHoleIndex( const StringId& name ) const
{
    if( name == "_"_sid )
        return InvalidIndex;

    HoleName holeName( name, m_currentRHSNamespaceIndex );

    auto it = m_pCow->holeDict.find( holeName );













|













|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#include "sema.h"

using namespace goose;
using namespace goose::sema;

TypeCheckingContext::TypeCheckingContext( const Context& c ) :
    m_context( c )
{}

TypeCheckingContext::TypeCheckingContext( Context&& c ) :
    m_context( move( c ) )
{}

uint32_t TypeCheckingContext::getLHSHoleIndex( StringId name ) const
{
    if( name == "_"_sid )
        return InvalidIndex;

    HoleName holeName( name, m_currentLHSNamespaceIndex );

    auto it = m_pCow->holeDict.find( holeName );
    if( it == m_pCow->holeDict.end() )
        return InvalidIndex;

    return it->second;
}

uint32_t TypeCheckingContext::getRHSHoleIndex( StringId name ) const
{
    if( name == "_"_sid )
        return InvalidIndex;

    HoleName holeName( name, m_currentRHSNamespaceIndex );

    auto it = m_pCow->holeDict.find( holeName );
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

    CoW( m_pCow )->values[index] = { m_pCow->values[index].m_term, true };

    if( !m_pCow->values[index].m_term )
        ++m_numUnknownValues;
}

void TypeCheckingContext::setLHSHoleIndex( const StringId& name, uint32_t index )
{
    if( name == "_"_sid )
    {
        ++m_numAnonymousHoles;
        return;
    }

    HoleName holeName( name, m_currentLHSNamespaceIndex );
    CoW( m_pCow )->holeDict.emplace( holeName, index );

    if( m_valuesAreRequired )
        setValueRequired( index );
}

void TypeCheckingContext::setRHSHoleIndex( const StringId& name, uint32_t index )
{
    if( name == "_"_sid )
    {
        ++m_numAnonymousHoles;
        return;
    }

    HoleName holeName( name, m_currentRHSNamespaceIndex );
    CoW( m_pCow )->holeDict.emplace( holeName, index );

    if( m_valuesAreRequired )
        setValueRequired( index );
}

void TypeCheckingContext::eraseLHSName( const StringId& name )
{
    HoleName holeName( name, m_currentLHSNamespaceIndex );
    CoW( m_pCow )->holeDict.erase( holeName );
}

void TypeCheckingContext::eraseRHSName( const StringId& name )
{
    HoleName holeName( name, m_currentRHSNamespaceIndex );
    CoW( m_pCow )->holeDict.erase( holeName );
}

bool TypeCheckingContext::isHoleLocked( uint32_t index ) const
{







|














|














|





|







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

    CoW( m_pCow )->values[index] = { m_pCow->values[index].m_term, true };

    if( !m_pCow->values[index].m_term )
        ++m_numUnknownValues;
}

void TypeCheckingContext::setLHSHoleIndex( StringId name, uint32_t index )
{
    if( name == "_"_sid )
    {
        ++m_numAnonymousHoles;
        return;
    }

    HoleName holeName( name, m_currentLHSNamespaceIndex );
    CoW( m_pCow )->holeDict.emplace( holeName, index );

    if( m_valuesAreRequired )
        setValueRequired( index );
}

void TypeCheckingContext::setRHSHoleIndex( StringId name, uint32_t index )
{
    if( name == "_"_sid )
    {
        ++m_numAnonymousHoles;
        return;
    }

    HoleName holeName( name, m_currentRHSNamespaceIndex );
    CoW( m_pCow )->holeDict.emplace( holeName, index );

    if( m_valuesAreRequired )
        setValueRequired( index );
}

void TypeCheckingContext::eraseLHSName( StringId name )
{
    HoleName holeName( name, m_currentLHSNamespaceIndex );
    CoW( m_pCow )->holeDict.erase( holeName );
}

void TypeCheckingContext::eraseRHSName( StringId name )
{
    HoleName holeName( name, m_currentRHSNamespaceIndex );
    CoW( m_pCow )->holeDict.erase( holeName );
}

bool TypeCheckingContext::isHoleLocked( uint32_t index ) const
{
Changes to bs/sema/tc-context.h.
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
            TypeCheckingContext( const Context& c );
            TypeCheckingContext( Context&& c );

            const auto& context() const { return m_context; }
            const auto& env() const { return m_context.env(); }
            const auto& rules() const { return env()->typeCheckingRuleSet(); }

            uint32_t getLHSHoleIndex( const StringId& name ) const;
            uint32_t getRHSHoleIndex( const StringId& name ) const;

            uint32_t createValue( bool required = false );

            void setLHSHoleIndex( const StringId& name, uint32_t index );
            void setRHSHoleIndex( const StringId& name, uint32_t index );

            void eraseLHSName( const StringId& name );
            void eraseRHSName( const StringId& name );

            uint32_t LHSNamespaceIndex() const { return m_currentLHSNamespaceIndex; }
            uint32_t RHSNamespaceIndex() const { return m_currentRHSNamespaceIndex; }

            void setLHSNamespaceIndex( uint32_t index ) { m_currentLHSNamespaceIndex = index; }
            void setRHSNamespaceIndex( uint32_t index ) { m_currentRHSNamespaceIndex = index; }








|
|



|
|

|
|







15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
            TypeCheckingContext( const Context& c );
            TypeCheckingContext( Context&& c );

            const auto& context() const { return m_context; }
            const auto& env() const { return m_context.env(); }
            const auto& rules() const { return env()->typeCheckingRuleSet(); }

            uint32_t getLHSHoleIndex( StringId name ) const;
            uint32_t getRHSHoleIndex( StringId name ) const;

            uint32_t createValue( bool required = false );

            void setLHSHoleIndex( StringId name, uint32_t index );
            void setRHSHoleIndex( StringId name, uint32_t index );

            void eraseLHSName( StringId name );
            void eraseRHSName( StringId name );

            uint32_t LHSNamespaceIndex() const { return m_currentLHSNamespaceIndex; }
            uint32_t RHSNamespaceIndex() const { return m_currentRHSNamespaceIndex; }

            void setLHSNamespaceIndex( uint32_t index ) { m_currentLHSNamespaceIndex = index; }
            void setRHSNamespaceIndex( uint32_t index ) { m_currentRHSNamespaceIndex = index; }

Changes to bs/util/stringid.h.
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

            explicit StringId( const char* pString, size_t size ) :
                StringId( string( pString, size ) )
            {}

            explicit StringId( uint32_t uniqueId );

            auto operator<=>( const StringId& rhs ) const
            {
                return m_id <=> rhs.m_id;
            }

            auto operator==( const StringId& rhs ) const
            {
                return m_id == rhs.m_id;
            }

            auto operator<( const StringId& rhs ) const
            {
                return m_id < rhs.m_id;
            }

            const string& str() const;

            friend ostream& operator<<( ostream& out, const StringId& sid )
            {
                return out << sid.str();
            }

            bool isNumerical() const { return !( m_id & stringMask ); }
            auto id() const { return m_id; }








|




|




|






|







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

            explicit StringId( const char* pString, size_t size ) :
                StringId( string( pString, size ) )
            {}

            explicit StringId( uint32_t uniqueId );

            auto operator<=>( StringId rhs ) const
            {
                return m_id <=> rhs.m_id;
            }

            auto operator==( StringId rhs ) const
            {
                return m_id == rhs.m_id;
            }

            auto operator<( StringId rhs ) const
            {
                return m_id < rhs.m_id;
            }

            const string& str() const;

            friend ostream& operator<<( ostream& out, StringId sid )
            {
                return out << sid.str();
            }

            bool isNumerical() const { return !( m_id & stringMask ); }
            auto id() const { return m_id; }

Changes to bs/verify/builder.cpp.
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
}

const Z3Val& Builder::setVar( uint32_t index, Z3Val&& v )
{
    return setVarForBasicBlock( m_currentBBIndex, index, move( v ) );
}

const z3::expr* Builder::retrievePlaceholder( const StringId& sid ) const
{
    auto it = m_placeholders.find( sid );
    if( it == m_placeholders.end() )
        return nullptr;

    return &it->second;
}

void Builder::setPlaceholder( const StringId& sid, const z3::expr& expr )
{
    m_placeholders.insert_or_assign( sid, expr );
}







|








|



164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
}

const Z3Val& Builder::setVar( uint32_t index, Z3Val&& v )
{
    return setVarForBasicBlock( m_currentBBIndex, index, move( v ) );
}

const z3::expr* Builder::retrievePlaceholder( StringId sid ) const
{
    auto it = m_placeholders.find( sid );
    if( it == m_placeholders.end() )
        return nullptr;

    return &it->second;
}

void Builder::setPlaceholder( StringId sid, const z3::expr& expr )
{
    m_placeholders.insert_or_assign( sid, expr );
}
Changes to bs/verify/builder.h.
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
            void assume( const z3::expr& e );
            bool checkAssertion( const z3::expr& e, uint32_t locationId );

            optional< Z3Val > retrieveVar( uint32_t index, uint32_t bbIndex = ~0 );
            optional< Z3Val > setVar( uint32_t index, const Value& val );
            const Z3Val& setVar( uint32_t index, Z3Val&& v );

            const z3::expr* retrievePlaceholder( const StringId& sid ) const;
            void setPlaceholder( const StringId& sid, const z3::expr& expr );

            uint32_t newUniqueId() { return m_nextUniqueId++; }

            bool hasCheckFailed() const { return m_checkFailed; }

            template< typename F >
            void setAssertionHandler( F&& handler )
            {
                m_assertionHandler = forward< F >( handler );
            }

            Z3Val& setVarForBasicBlock( uint32_t bbIndex, uint32_t index, Z3Val&& v );

       // private:
            optional< Z3Val > getVarForBasicBlock( uint32_t bbIndex, uint32_t index ) const;

            const sema::Context* m_context;
            z3::solver* m_solver = nullptr;
            Remapper* m_remapper = nullptr;

            ptr< cir::CFG > m_cfg;







|
|













|







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
            void assume( const z3::expr& e );
            bool checkAssertion( const z3::expr& e, uint32_t locationId );

            optional< Z3Val > retrieveVar( uint32_t index, uint32_t bbIndex = ~0 );
            optional< Z3Val > setVar( uint32_t index, const Value& val );
            const Z3Val& setVar( uint32_t index, Z3Val&& v );

            const z3::expr* retrievePlaceholder( StringId sid ) const;
            void setPlaceholder( StringId sid, const z3::expr& expr );

            uint32_t newUniqueId() { return m_nextUniqueId++; }

            bool hasCheckFailed() const { return m_checkFailed; }

            template< typename F >
            void setAssertionHandler( F&& handler )
            {
                m_assertionHandler = forward< F >( handler );
            }

            Z3Val& setVarForBasicBlock( uint32_t bbIndex, uint32_t index, Z3Val&& v );

        private:
            optional< Z3Val > getVarForBasicBlock( uint32_t bbIndex, uint32_t index ) const;

            const sema::Context* m_context;
            z3::solver* m_solver = nullptr;
            Remapper* m_remapper = nullptr;

            ptr< cir::CFG > m_cfg;
Changes to tests/g0/codegen/bitwiseops.ll.
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
  %8 = alloca i16, align 2
  store i8 %0, i8* %5, align 1
  store i8 %1, i8* %6, align 1
  store i16 %2, i16* %7, align 2
  store i16 %3, i16* %8, align 2
  %9 = load i8, i8* %5, align 1
  %10 = load i8, i8* %6, align 1
  %11 = call i8 @"_2_3s2:g0s3#1f#s6:lomarf_5Vo_3ti0_6up_5Vo_3ti0_4s7:integer_2RPp_2i8i0_2q_2_5Vr_5Vo_3ti0_4$3_2RPp_2i8i0hs1:_n_5Vr_5Vo_3ti0_4$3_2RPp_2i8i0h$4nPi0"(i8 %9, i8 %10)
  %12 = load i16, i16* %8, align 2
  %13 = call i16 @"_2_3s2:g0s3#1f#s6:lomarf_5Vo_3ti0_6up_5Vo_3ti0_4s7:integer_2RPp_2i10i1_2q_2_5Vr_5Vo_3ti0_4$3_2RPp_2i10i1hs1:_n_5Vr_5Vo_3ti0_4$3_2RPp_2i10i1h$4nPi0"(i16 219, i16 %12)
  %14 = load i16, i16* %8, align 2
  %15 = call i16 @"_2_3s2:g0s3#1f#s6:lomarf_5Vo_3ti0_6up_5Vo_3ti0_4s7:integer_2RPp_2i10i1_2q_2_5Vr_5Vo_3ti0_4$3_2RPp_2i10i1hs1:_n_5Vr_5Vo_3ti0_4$3_2RPp_2i10i1h$4nPi0"(i16 %14, i16 69)
  %16 = load i8, i8* %5, align 1
  %17 = load i8, i8* %6, align 1
  %18 = xor i8 %16, %17
  %19 = load i16, i16* %7, align 2
  %20 = load i16, i16* %8, align 2
  %21 = xor i16 %19, %20
  %22 = load i16, i16* %7, align 2







|

|

|







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
  %8 = alloca i16, align 2
  store i8 %0, i8* %5, align 1
  store i8 %1, i8* %6, align 1
  store i16 %2, i16* %7, align 2
  store i16 %3, i16* %8, align 2
  %9 = load i8, i8* %5, align 1
  %10 = load i8, i8* %6, align 1
  %11 = call i8 @"_2_3s2:g0s3#1f#s6:lomarf_5Vo_3ti0_6up_5Vo_3ti0_5T_2RPps7:integer_2i8i0_2q_2_5Vr_5Vo_3ti0_5T_2RPp$3_2i8i0hs1:_n_5Vr_5Vo_3ti0_5T_2RPp$3_2i8i0h$4nPi0"(i8 %9, i8 %10)
  %12 = load i16, i16* %8, align 2
  %13 = call i16 @"_2_3s2:g0s3#1f#s6:lomarf_5Vo_3ti0_6up_5Vo_3ti0_5T_2RPps7:integer_2i10i1_2q_2_5Vr_5Vo_3ti0_5T_2RPp$3_2i10i1hs1:_n_5Vr_5Vo_3ti0_5T_2RPp$3_2i10i1h$4nPi0"(i16 219, i16 %12)
  %14 = load i16, i16* %8, align 2
  %15 = call i16 @"_2_3s2:g0s3#1f#s6:lomarf_5Vo_3ti0_6up_5Vo_3ti0_5T_2RPps7:integer_2i10i1_2q_2_5Vr_5Vo_3ti0_5T_2RPp$3_2i10i1hs1:_n_5Vr_5Vo_3ti0_5T_2RPp$3_2i10i1h$4nPi0"(i16 %14, i16 69)
  %16 = load i8, i8* %5, align 1
  %17 = load i8, i8* %6, align 1
  %18 = xor i8 %16, %17
  %19 = load i16, i16* %7, align 2
  %20 = load i16, i16* %8, align 2
  %21 = xor i16 %19, %20
  %22 = load i16, i16* %7, align 2
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
  %38 = load i16, i16* %7, align 2
  %39 = shl i16 %38, 4
  %40 = load i16, i16* %7, align 2
  %41 = ashr i16 %40, 4
  ret void
}

define private i8 @"_2_3s2:g0s3#1f#s6:lomarf_5Vo_3ti0_6up_5Vo_3ti0_4s7:integer_2RPp_2i8i0_2q_2_5Vr_5Vo_3ti0_4$3_2RPp_2i8i0hs1:_n_5Vr_5Vo_3ti0_4$3_2RPp_2i8i0h$4nPi0"(i8 %0, i8 %1) {
  %3 = alloca i8, align 1
  %4 = alloca i8, align 1
  store i8 %0, i8* %3, align 1
  store i8 %1, i8* %4, align 1
  %5 = load i8, i8* %3, align 1
  %6 = load i8, i8* %4, align 1
  %7 = xor i8 %5, %6
  ret i8 %7
}

define private i16 @"_2_3s2:g0s3#1f#s6:lomarf_5Vo_3ti0_6up_5Vo_3ti0_4s7:integer_2RPp_2i10i1_2q_2_5Vr_5Vo_3ti0_4$3_2RPp_2i10i1hs1:_n_5Vr_5Vo_3ti0_4$3_2RPp_2i10i1h$4nPi0"(i16 %0, i16 %1) {
  %3 = alloca i16, align 2
  %4 = alloca i16, align 2
  store i16 %0, i16* %3, align 2
  store i16 %1, i16* %4, align 2
  %5 = load i16, i16* %3, align 2
  %6 = load i16, i16* %4, align 2
  %7 = xor i16 %5, %6
  ret i16 %7
}







|










|









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
  %38 = load i16, i16* %7, align 2
  %39 = shl i16 %38, 4
  %40 = load i16, i16* %7, align 2
  %41 = ashr i16 %40, 4
  ret void
}

define private i8 @"_2_3s2:g0s3#1f#s6:lomarf_5Vo_3ti0_6up_5Vo_3ti0_5T_2RPps7:integer_2i8i0_2q_2_5Vr_5Vo_3ti0_5T_2RPp$3_2i8i0hs1:_n_5Vr_5Vo_3ti0_5T_2RPp$3_2i8i0h$4nPi0"(i8 %0, i8 %1) {
  %3 = alloca i8, align 1
  %4 = alloca i8, align 1
  store i8 %0, i8* %3, align 1
  store i8 %1, i8* %4, align 1
  %5 = load i8, i8* %3, align 1
  %6 = load i8, i8* %4, align 1
  %7 = xor i8 %5, %6
  ret i8 %7
}

define private i16 @"_2_3s2:g0s3#1f#s6:lomarf_5Vo_3ti0_6up_5Vo_3ti0_5T_2RPps7:integer_2i10i1_2q_2_5Vr_5Vo_3ti0_5T_2RPp$3_2i10i1hs1:_n_5Vr_5Vo_3ti0_5T_2RPp$3_2i10i1h$4nPi0"(i16 %0, i16 %1) {
  %3 = alloca i16, align 2
  %4 = alloca i16, align 2
  store i16 %0, i16* %3, align 2
  store i16 %1, i16* %4, align 2
  %5 = load i16, i16* %3, align 2
  %6 = load i16, i16* %4, align 2
  %7 = xor i16 %5, %6
  ret i16 %7
}
Changes to tests/g0/codegen/func.ll.
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
; ModuleID = 'testfuncmodule'
source_filename = "testfuncmodule"

@.str0 = private constant [7 x i8] c"lomarf\00"
@.str1 = private constant [9 x i8] c"whatever\00"

define void @main(i1 %0) {
  %2 = alloca i1, align 1
  store i1 %0, i1* %2, align 1
  %3 = load i1, i1* %2, align 1
  %4 = xor i1 %3, true
  call void @"_2_3s2:g0s3#1f#s3:meh_5Vo_3ti0_6up_5Vo_3ti0v_2q_1_5Vr_5Vo_3ti0_3l_2RPphs1:_nPi0"(i1 %4)
  call void @"_2_3s2:g0s3#1f#s3:meh_5Vo_3ti0_6up_5Vo_3ti0v_2q_1_5Vr_5Vo_3ti0_4s7:pointer_2RPp_5Vo_3ti0_4s7:integer_2RPp_2i8i0hs1:_nPi0"([9 x i8]* @.str1)
  call void @lomarf(i32 219)
  ret void
}

define private void @"_2_3s2:g0s3#1f#s3:meh_5Vo_3ti0_6up_5Vo_3ti0v_2q_1_5Vr_5Vo_3ti0_3l_2RPphs1:_nPi0"(i1 %0) {
  %2 = alloca i1, align 1
  store i1 %0, i1* %2, align 1
  call void @puts([7 x i8]* @.str0)
  ret void
}

declare void @puts(i8*)

define private void @"_2_3s2:g0s3#1f#s3:meh_5Vo_3ti0_6up_5Vo_3ti0v_2q_1_5Vr_5Vo_3ti0_4s7:pointer_2RPp_5Vo_3ti0_4s7:integer_2RPp_2i8i0hs1:_nPi0"(i8* %0) {
  %2 = alloca i8*, align 8
  store i8* %0, i8** %2, align 8
  %3 = load i8*, i8** %2, align 8
  call void @puts(i8* %3)
  call void @"_2_3s2:g0s3#1f#s3:meh_5Vo_3ti0_6up_5Vo_3ti0v_2q_1_5Vr_5Vo_3ti0_3l_2RPphs1:_nPi0"(i1 true)
  call void @"_2_3s2:g0s3#1f#s3:meh_5Vo_3ti0_6up_5Vo_3ti0v_2q_1_5Vr_5Vo_3ti0_3l_2RPphs1:_nPi0"(i1 false)
  ret void
}

declare void @lomarf(i32)











|
|




|








|




|
|




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
; ModuleID = 'testfuncmodule'
source_filename = "testfuncmodule"

@.str0 = private constant [7 x i8] c"lomarf\00"
@.str1 = private constant [9 x i8] c"whatever\00"

define void @main(i1 %0) {
  %2 = alloca i1, align 1
  store i1 %0, i1* %2, align 1
  %3 = load i1, i1* %2, align 1
  %4 = xor i1 %3, true
  call void @"_2_3s2:g0s3#1f#s3:meh_5Vo_3ti0_6up_5Vo_3ti0v_2q_1_5Vr_5Vo_3ti0_4T_2RPplhs1:_nPi0"(i1 %4)
  call void @"_2_3s2:g0s3#1f#s3:meh_5Vo_3ti0_6up_5Vo_3ti0v_2q_1_5Vr_5Vo_3ti0_5T_2RPps7:pointer_5Vo_3ti0_5T_2RPps7:integer_2i8i0hs1:_nPi0"([9 x i8]* @.str1)
  call void @lomarf(i32 219)
  ret void
}

define private void @"_2_3s2:g0s3#1f#s3:meh_5Vo_3ti0_6up_5Vo_3ti0v_2q_1_5Vr_5Vo_3ti0_4T_2RPplhs1:_nPi0"(i1 %0) {
  %2 = alloca i1, align 1
  store i1 %0, i1* %2, align 1
  call void @puts([7 x i8]* @.str0)
  ret void
}

declare void @puts(i8*)

define private void @"_2_3s2:g0s3#1f#s3:meh_5Vo_3ti0_6up_5Vo_3ti0v_2q_1_5Vr_5Vo_3ti0_5T_2RPps7:pointer_5Vo_3ti0_5T_2RPps7:integer_2i8i0hs1:_nPi0"(i8* %0) {
  %2 = alloca i8*, align 8
  store i8* %0, i8** %2, align 8
  %3 = load i8*, i8** %2, align 8
  call void @puts(i8* %3)
  call void @"_2_3s2:g0s3#1f#s3:meh_5Vo_3ti0_6up_5Vo_3ti0v_2q_1_5Vr_5Vo_3ti0_4T_2RPplhs1:_nPi0"(i1 true)
  call void @"_2_3s2:g0s3#1f#s3:meh_5Vo_3ti0_6up_5Vo_3ti0v_2q_1_5Vr_5Vo_3ti0_4T_2RPplhs1:_nPi0"(i1 false)
  ret void
}

declare void @lomarf(i32)
Changes to tests/g0/codegen/if.ll.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
; ModuleID = 'iftest'
source_filename = "iftest"

@.str0 = private constant [7 x i8] c"lomarf\00"
@.str1 = private constant [3 x i8] c"gg\00"
@.str2 = private constant [5 x i8] c"blah\00"
@.str3 = private constant [4 x i8] c"lol\00"

define void @main() {
  call void @"_2_3s2:g0s3#1f#s3:meh_5Vo_3ti0_6up_5Vo_3ti0v_2q_2_5Vr_5Vo_3ti0_3l_2RPphs1:_n_5Vr_5Vo_3ti0_3l_2RPph$3nPi0"(i1 true, i1 false)
  call void @"_2_3s2:g0s3#1f#s3:meh_5Vo_3ti0_6up_5Vo_3ti0v_2q_2_5Vr_5Vo_3ti0_3l_2RPphs1:_n_5Vr_5Vo_3ti0_3l_2RPph$3nPi0"(i1 true, i1 true)
  call void @"_2_3s2:g0s3#1f#s3:meh_5Vo_3ti0_6up_5Vo_3ti0v_2q_2_5Vr_5Vo_3ti0_3l_2RPphs1:_n_5Vr_5Vo_3ti0_3l_2RPph$3nPi0"(i1 false, i1 false)
  ret void
}

define private void @"_2_3s2:g0s3#1f#s3:meh_5Vo_3ti0_6up_5Vo_3ti0v_2q_2_5Vr_5Vo_3ti0_3l_2RPphs1:_n_5Vr_5Vo_3ti0_3l_2RPph$3nPi0"(i1 %0, i1 %1) {
  %3 = alloca i1, align 1
  %4 = alloca i1, align 1
  store i1 %0, i1* %3, align 1
  store i1 %1, i1* %4, align 1
  %5 = load i1, i1* %3, align 1
  br i1 %5, label %6, label %12










|
|
|



|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
; ModuleID = 'iftest'
source_filename = "iftest"

@.str0 = private constant [7 x i8] c"lomarf\00"
@.str1 = private constant [3 x i8] c"gg\00"
@.str2 = private constant [5 x i8] c"blah\00"
@.str3 = private constant [4 x i8] c"lol\00"

define void @main() {
  call void @"_2_3s2:g0s3#1f#s3:meh_5Vo_3ti0_6up_5Vo_3ti0v_2q_2_5Vr_5Vo_3ti0_4T_2RPplhs1:_n_5Vr_5Vo_3ti0_4T_2RPplh$3nPi0"(i1 true, i1 false)
  call void @"_2_3s2:g0s3#1f#s3:meh_5Vo_3ti0_6up_5Vo_3ti0v_2q_2_5Vr_5Vo_3ti0_4T_2RPplhs1:_n_5Vr_5Vo_3ti0_4T_2RPplh$3nPi0"(i1 true, i1 true)
  call void @"_2_3s2:g0s3#1f#s3:meh_5Vo_3ti0_6up_5Vo_3ti0v_2q_2_5Vr_5Vo_3ti0_4T_2RPplhs1:_n_5Vr_5Vo_3ti0_4T_2RPplh$3nPi0"(i1 false, i1 false)
  ret void
}

define private void @"_2_3s2:g0s3#1f#s3:meh_5Vo_3ti0_6up_5Vo_3ti0v_2q_2_5Vr_5Vo_3ti0_4T_2RPplhs1:_n_5Vr_5Vo_3ti0_4T_2RPplh$3nPi0"(i1 %0, i1 %1) {
  %3 = alloca i1, align 1
  %4 = alloca i1, align 1
  store i1 %0, i1* %3, align 1
  store i1 %1, i1* %4, align 1
  %5 = load i1, i1* %3, align 1
  br i1 %5, label %6, label %12

Changes to tests/g0/codegen/logicops.ll.
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
; ModuleID = 'logic ops test'
source_filename = "logic ops test"

define void @main(i1 %0, i1 %1) {
  %3 = alloca i1, align 1
  %4 = alloca i1, align 1
  store i1 %0, i1* %3, align 1
  store i1 %1, i1* %4, align 1
  %5 = load i1, i1* %3, align 1
  %6 = load i1, i1* %4, align 1
  %7 = call i1 @"_2_3s2:g0s3#1f#s6:lomarf_5Vo_3ti0_6up_5Vo_3ti0_3l_2RPp_2q_2_5Vr_5Vo_3ti0_3l_2RPphs1:_n_5Vr_5Vo_3ti0_3l_2RPph$3nPi0"(i1 %5, i1 %6)
  %8 = load i1, i1* %3, align 1
  %9 = load i1, i1* %4, align 1
  %10 = call i1 @"_2_3s2:g0s3#1f#s4:blah_5Vo_3ti0_6up_5Vo_3ti0_3l_2RPp_2q_2_5Vr_5Vo_3ti0_3l_2RPphs1:_n_5Vr_5Vo_3ti0_3l_2RPph$3nPi0"(i1 %8, i1 %9)
  ret void
}

define private i1 @"_2_3s2:g0s3#1f#s6:lomarf_5Vo_3ti0_6up_5Vo_3ti0_3l_2RPp_2q_2_5Vr_5Vo_3ti0_3l_2RPphs1:_n_5Vr_5Vo_3ti0_3l_2RPph$3nPi0"(i1 %0, i1 %1) {
  %3 = alloca i1, align 1
  %4 = alloca i1, align 1
  store i1 %0, i1* %3, align 1
  store i1 %1, i1* %4, align 1
  %5 = load i1, i1* %3, align 1
  br i1 %5, label %8, label %6

6:                                                ; preds = %2
  %7 = load i1, i1* %4, align 1
  br label %8

8:                                                ; preds = %6, %2
  %9 = phi i1 [ true, %2 ], [ %7, %6 ]
  ret i1 %9
}

define private i1 @"_2_3s2:g0s3#1f#s4:blah_5Vo_3ti0_6up_5Vo_3ti0_3l_2RPp_2q_2_5Vr_5Vo_3ti0_3l_2RPphs1:_n_5Vr_5Vo_3ti0_3l_2RPph$3nPi0"(i1 %0, i1 %1) {
  %3 = alloca i1, align 1
  %4 = alloca i1, align 1
  store i1 %0, i1* %3, align 1
  store i1 %1, i1* %4, align 1
  %5 = load i1, i1* %3, align 1
  br i1 %5, label %6, label %8











|


|



|
















|







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
; ModuleID = 'logic ops test'
source_filename = "logic ops test"

define void @main(i1 %0, i1 %1) {
  %3 = alloca i1, align 1
  %4 = alloca i1, align 1
  store i1 %0, i1* %3, align 1
  store i1 %1, i1* %4, align 1
  %5 = load i1, i1* %3, align 1
  %6 = load i1, i1* %4, align 1
  %7 = call i1 @"_2_3s2:g0s3#1f#s6:lomarf_5Vo_3ti0_6up_5Vo_3ti0_4T_2RPpl_2q_2_5Vr_5Vo_3ti0_4T_2RPplhs1:_n_5Vr_5Vo_3ti0_4T_2RPplh$3nPi0"(i1 %5, i1 %6)
  %8 = load i1, i1* %3, align 1
  %9 = load i1, i1* %4, align 1
  %10 = call i1 @"_2_3s2:g0s3#1f#s4:blah_5Vo_3ti0_6up_5Vo_3ti0_4T_2RPpl_2q_2_5Vr_5Vo_3ti0_4T_2RPplhs1:_n_5Vr_5Vo_3ti0_4T_2RPplh$3nPi0"(i1 %8, i1 %9)
  ret void
}

define private i1 @"_2_3s2:g0s3#1f#s6:lomarf_5Vo_3ti0_6up_5Vo_3ti0_4T_2RPpl_2q_2_5Vr_5Vo_3ti0_4T_2RPplhs1:_n_5Vr_5Vo_3ti0_4T_2RPplh$3nPi0"(i1 %0, i1 %1) {
  %3 = alloca i1, align 1
  %4 = alloca i1, align 1
  store i1 %0, i1* %3, align 1
  store i1 %1, i1* %4, align 1
  %5 = load i1, i1* %3, align 1
  br i1 %5, label %8, label %6

6:                                                ; preds = %2
  %7 = load i1, i1* %4, align 1
  br label %8

8:                                                ; preds = %6, %2
  %9 = phi i1 [ true, %2 ], [ %7, %6 ]
  ret i1 %9
}

define private i1 @"_2_3s2:g0s3#1f#s4:blah_5Vo_3ti0_6up_5Vo_3ti0_4T_2RPpl_2q_2_5Vr_5Vo_3ti0_4T_2RPplhs1:_n_5Vr_5Vo_3ti0_4T_2RPplh$3nPi0"(i1 %0, i1 %1) {
  %3 = alloca i1, align 1
  %4 = alloca i1, align 1
  store i1 %0, i1* %3, align 1
  store i1 %1, i1* %4, align 1
  %5 = load i1, i1* %3, align 1
  br i1 %5, label %6, label %8