Goose  Check-in [fece958df9]

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

Overview
Comment:More cleanup around which builtin functions should be intrinsics/eager/non eager.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: fece958df97551340cf503e7f90ce4146a2d93667ba429cec287dcafb0e080de
User & Date: achavasse 2019-08-24 19:33:39.902
Context
2019-08-24
20:41
Make cast() eagerly evaluated once again, it was removed by mistake. check-in: 7fa6ff1937 user: achavasse tags: trunk
19:33
More cleanup around which builtin functions should be intrinsics/eager/non eager. check-in: fece958df9 user: achavasse tags: trunk
16:54
  • ExecuteFile is now a regular builtin function.
  • Added #Include, which works the same as the old ExecuteFile.
  • Added a CreateConstant() builtin func.
  • Used the above to cleanup the command line parsing code in empathy.em.
check-in: f1cab5f761 user: achavasse tags: trunk
Changes
Unified Diff Ignore Whitespace Patch
Changes to bs/builtins/api/compiler.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
43
44
45
46
47
48
49
50
51
52
53
54
#include "builtins/builtins.h"
#include "parse/parse.h"
#include "execute/execute.h"
#include "compiler.h"

using namespace empathy;

namespace empathy::builtins
{
    void SetupApiCompiler( Env& e )
    {
        weak_ptr< Env > pEnv = e.shared_from_this();

        RegisterBuiltinFunc< Eager< void > ( bool ) >( e, "#DiagnosticsEnableTraces"_sid,
            [pEnv]( bool enable )
            {







                DiagnosticsManager::GetInstance().setTraceMode( enable );
            } );

        RegisterBuiltinFunc< void ( bool ) >( e, "DiagnosticsForceColors"_sid,
            [pEnv]( bool enable )
            {
                DiagnosticsManager::GetInstance().setForceColors( enable );
            } );

        RegisterBuiltinFunc< Eager< void > ( uint32_t ) >( e, "#SetExecutionBudget"_sid,
            [pEnv]( uint32_t budget )
            {
                static bool used = false;








                if( used )
                {
                    DiagnosticsManager::GetInstance().emitErrorMessage( 0,
                        "#SetExecutionBudget can only be used once." );
                    return;
                }

                used = true;
                execute::VM::SetExecutionBudget( budget );
            } );

        RegisterBuiltinFunc< Eager< Value > ( Value, string ) >( e, "#ExternalFunction"_sid,
            [pEnv]( const Value& f, const string& symbol )
            {
                auto ft = FromValue< FuncType >( f );
                if( !ft )
                    return ToValue( "error"s ).setPoison();

                return ToValue( BuildExternalFunc( *ft, symbol ) );
            } );

        RegisterBuiltinFunc< void ( string, Value ) >( e, "CreateConstant"_sid,
            [pEnv]( const string& name, const Value& v )
            {













|
|

>
>
>
>
>
>
>
|








|
|


>
>
>
>
>
>
>









|


|




|







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

using namespace empathy;

namespace empathy::builtins
{
    void SetupApiCompiler( Env& e )
    {
        weak_ptr< Env > pEnv = e.shared_from_this();

        RegisterBuiltinFunc< Intrinsic< void ( bool ) > >( e, "#DiagnosticsEnableTraces"_sid,
            [pEnv]( const Value& enable )
            {
                if( !enable.isConstant() )
                {
                    DiagnosticsManager::GetInstance().emitErrorMessage( enable.locationId(),
                        "#DiagnosticsEnableTraces: the expression doesn't evaluate to a constant." );
                    return;
                }

                DiagnosticsManager::GetInstance().setTraceMode( *FromValue< bool >( enable ) );
            } );

        RegisterBuiltinFunc< void ( bool ) >( e, "DiagnosticsForceColors"_sid,
            [pEnv]( bool enable )
            {
                DiagnosticsManager::GetInstance().setForceColors( enable );
            } );

        RegisterBuiltinFunc< Intrinsic< void ( uint32_t ) > >( e, "#SetExecutionBudget"_sid,
            [pEnv]( const Value& budget )
            {
                static bool used = false;

                if( !budget.isConstant() )
                {
                    DiagnosticsManager::GetInstance().emitErrorMessage( budget.locationId(),
                        "#SetExecutionBudget: the expression doesn't evaluate to a constant." );
                    return;
                }

                if( used )
                {
                    DiagnosticsManager::GetInstance().emitErrorMessage( 0,
                        "#SetExecutionBudget can only be used once." );
                    return;
                }

                used = true;
                execute::VM::SetExecutionBudget( *FromValue< uint32_t >( budget ) );
            } );

        RegisterBuiltinFunc< Eager< Value > ( Value, string ) >( e, "ExternalFunction"_sid,
            [pEnv]( const Value& f, const string& symbol )
            {
                auto ft = FromValue< FuncType >( f );
                if( !ft )
                    return PoisonValue();

                return ToValue( BuildExternalFunc( *ft, symbol ) );
            } );

        RegisterBuiltinFunc< void ( string, Value ) >( e, "CreateConstant"_sid,
            [pEnv]( const string& name, const Value& v )
            {
87
88
89
90
91
92
93
94
95
96









97
98
99
100
101
102
103

                if( !result )
                    return ToValue< uint32_t >( 1 );

                return *result;
            } );

        RegisterBuiltinFunc< Eager< Value > ( string, Value, Value ) >( e, "#CompileFileToFunction"_sid,
            [pEnv]( const string& filename, const Value& rt, const Value& params ) -> Value
            {









                // Validate those generic value inputs
                if( !rt.isType() )
                {
                    DiagnosticsManager::GetInstance().emitErrorMessage( rt.locationId(),
                        "#CompileFileToFunction: type expected.", 0 );
                    return PoisonValue();
                }







|
|

>
>
>
>
>
>
>
>
>







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

                if( !result )
                    return ToValue< uint32_t >( 1 );

                return *result;
            } );

        RegisterBuiltinFunc< Intrinsic< Value ( string, Value, Value ) > >( e, "#CompileFileToFunction"_sid,
            [pEnv]( const Value& filenameVal, const Value& rt, const Value& params ) -> Value
            {
                if( !filenameVal.isConstant() )
                {
                    DiagnosticsManager::GetInstance().emitErrorMessage( filenameVal.locationId(),
                        "#CompileFileToFunction: the expression doesn't evaluate to a constant." );
                    return PoisonValue();
                }

                auto filename = *FromValue< string >( filenameVal );

                // Validate those generic value inputs
                if( !rt.isType() )
                {
                    DiagnosticsManager::GetInstance().emitErrorMessage( rt.locationId(),
                        "#CompileFileToFunction: type expected.", 0 );
                    return PoisonValue();
                }
Changes to bs/compiler.cpp.
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
        if( i > 1 )
            cmdArgs = cmdArgs + ' ';
        cmdArgs = cmdArgs + argv[i];
    }

    builtins::SetupBuiltins( *m_pEnv );

    builtins::RegisterBuiltinFunc< builtins::Eager< string > () >( *m_pEnv, "Args"_sid,
        [cmdArgs]()
        {
            return cmdArgs;
        } );

    builtins::RegisterBuiltinFunc< void ( string ) >( *m_pEnv, "Print"_sid,
        []( const string& str )







|







25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
        if( i > 1 )
            cmdArgs = cmdArgs + ' ';
        cmdArgs = cmdArgs + argv[i];
    }

    builtins::SetupBuiltins( *m_pEnv );

    builtins::RegisterBuiltinFunc< string() >( *m_pEnv, "Args"_sid,
        [cmdArgs]()
        {
            return cmdArgs;
        } );

    builtins::RegisterBuiltinFunc< void ( string ) >( *m_pEnv, "Print"_sid,
        []( const string& str )
Changes to bs/llr/call.cpp.
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78

        if( !argsAreConstant )
            return false;

        if( IsEagerBuiltinFunc( m_func ) )
            return true;

        if( IsBuiltinFunc( m_func ) )
            return false;

        const auto* pFuncLLR = GetFuncLLR( m_func );

        if( !pFuncLLR )
            return false;

        return pFuncLLR->canBeExecuted();
    }







<
<
<







62
63
64
65
66
67
68



69
70
71
72
73
74
75

        if( !argsAreConstant )
            return false;

        if( IsEagerBuiltinFunc( m_func ) )
            return true;




        const auto* pFuncLLR = GetFuncLLR( m_func );

        if( !pFuncLLR )
            return false;

        return pFuncLLR->canBeExecuted();
    }
Changes to lib/frontend.em.
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
if !CGModuleSetupTarget( module )
{
    Print( "Failed to setup llvm target.\n" )
    return 0
}

// Define the exit external function.
using exit = #ExternalFunction( void( uint( 32 ) returnCode ), "_exit" )

using main = #CompileFileToFunction( SourceToCompile, void, () )

// The entry point of the binary.
// We have to use "using" and an anonymous function, because otherwise
// it would create an overloadset and CGGenerateFunction wouldn't know
// how to deal with that.







|







15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
if !CGModuleSetupTarget( module )
{
    Print( "Failed to setup llvm target.\n" )
    return 0
}

// Define the exit external function.
using exit = ExternalFunction( void( uint( 32 ) returnCode ), "_exit" )

using main = #CompileFileToFunction( SourceToCompile, void, () )

// The entry point of the binary.
// We have to use "using" and an anonymous function, because otherwise
// it would create an overloadset and CGGenerateFunction wouldn't know
// how to deal with that.
Changes to samples/helloworld.em.
1
2
3
4
// No library yet, so we have to directly import the puts function from libc and call that.
using puts = #ExternalFunction( uint(32) ( pointer( uint(8) ) str ), "puts" )

puts( "hello world" )

|


1
2
3
4
// No library yet, so we have to directly import the puts function from libc and call that.
using puts = ExternalFunction( uint(32) ( pointer( uint(8) ) str ), "puts" )

puts( "hello world" )
Changes to tests/noprelude/codegen/func.em.
1
2
3
4
5
6
7
8
9
10
11
12
13
var module = CGModuleCreate( "testfuncmodule" )

using puts = #ExternalFunction( void( pointer( uint( 8 ) ) str ), "puts" )

// Used to somewhat test constant int loading
using lomarf = #ExternalFunction( void( sint( 32 ) gg ), "lomarf" )

void meh( bool b ) { puts( "lomarf" ) }
void meh( pointer( uint( 8 ) ) str ) { puts(str) meh( true ) meh( false ) }

using entryPoint = void( bool b ) { meh( !b ) meh( "whatever" ) lomarf( 219 ) }

CGGenerateFunction( module, entryPoint, "main" )


|


|







1
2
3
4
5
6
7
8
9
10
11
12
13
var module = CGModuleCreate( "testfuncmodule" )

using puts = ExternalFunction( void( pointer( uint( 8 ) ) str ), "puts" )

// Used to somewhat test constant int loading
using lomarf = ExternalFunction( void( sint( 32 ) gg ), "lomarf" )

void meh( bool b ) { puts( "lomarf" ) }
void meh( pointer( uint( 8 ) ) str ) { puts(str) meh( true ) meh( false ) }

using entryPoint = void( bool b ) { meh( !b ) meh( "whatever" ) lomarf( 219 ) }

CGGenerateFunction( module, entryPoint, "main" )
Changes to tests/noprelude/codegen/if.em.
1
2
3
4
5
6
7
8
9
10
var module = CGModuleCreate( "iftest" )

using puts = #ExternalFunction( void( pointer( uint( 8 ) ) str ), "puts" )

void meh( bool a, bool b )
{
    if a if !b puts( "lomarf" ) else puts( "blah" )
    else puts( "lol" )

    puts( "gg" )


|







1
2
3
4
5
6
7
8
9
10
var module = CGModuleCreate( "iftest" )

using puts = ExternalFunction( void( pointer( uint( 8 ) ) str ), "puts" )

void meh( bool a, bool b )
{
    if a if !b puts( "lomarf" ) else puts( "blah" )
    else puts( "lol" )

    puts( "gg" )
Changes to tests/noprelude/diagnostics/compile-bad-strlit.em.
1
2
3
4
5
6
7
8
using puts = #ExternalFunction( uint(32) ( pointer( uint(8) ) str ), "puts" )

// Various incorrect string literals, whose diagnostics need to be shown despite
// the lexing occuring during the tentative compile time execution phase
// during which most diagnostics are disabled.
puts( "good hex char code: \x41" )
puts( "bad hex char code: \xgg" )

|







1
2
3
4
5
6
7
8
using puts = ExternalFunction( uint(32) ( pointer( uint(8) ) str ), "puts" )

// Various incorrect string literals, whose diagnostics need to be shown despite
// the lexing occuring during the tentative compile time execution phase
// during which most diagnostics are disabled.
puts( "good hex char code: \x41" )
puts( "bad hex char code: \xgg" )

Changes to tests/noprelude/diagnostics/compile-calling-compiletime-func.em.
1
2
3
4
5
6
7
8
using putchar = #ExternalFunction( uint(32) ( uint(8) c ), "putchar" )

void put( ct_char c )
{
    putchar( 10 )
}

put( 'g' )
|







1
2
3
4
5
6
7
8
using putchar = ExternalFunction( uint(32) ( uint(8) c ), "putchar" )

void put( ct_char c )
{
    putchar( 10 )
}

put( 'g' )
Changes to tests/noprelude/diagnostics/compile-func-type-mismatch.em.
1
2
3
4
5
6
using puts = #ExternalFunction( uint(32) ( pointer( uint(8) ) str ), "puts" )

// Errors in the particular context of "file being compiled normally through the front-end"
// go through specific hoops that result in broken diagnostics all the time even though
// they otherwise work, so there's a specific test for that.
puts( 654654 )
|





1
2
3
4
5
6
using puts = ExternalFunction( uint(32) ( pointer( uint(8) ) str ), "puts" )

// Errors in the particular context of "file being compiled normally through the front-end"
// go through specific hoops that result in broken diagnostics all the time even though
// they otherwise work, so there's a specific test for that.
puts( 654654 )