1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
|
#include "builtins/builtins.h"
#include "parse/parse.h"
#include "precedence.h"
using namespace empathy;
using namespace empathy::ir;
using namespace empathy::parse;
namespace empathy::builtins
{
void SetupUsingStmt( Env& e )
{
auto handleUsing = []( Parser& p, const Term& t, uint32_t prec ) -> optional< Value >
{
p.resolver()->consumeNewLines();
auto nameTerm = p.resolver()->consume();
if( !nameTerm )
{
cout << t.location() << ": expected an identifier after 'using'.\n";
return nullopt;
}
const auto* name = get_if< StringId >( &nameTerm->content() );
if( !name )
{
cout << nameTerm->location() << ": expected an identifier after 'using'.\n";
return nullopt;
}
p.resolver()->consumeNewLines();
auto eqTerm = p.resolver()->consumeUnresolved();
if( !eqTerm )
{
cout << eqTerm->location() << ": expected '=' after 'using " << name->c_str() << "'.\n";
return nullopt;
}
const auto* eq = get_if< StringId >( &eqTerm->content() );
if( !eq || *eq != "="_sid )
{
cout << eqTerm->location() << ": expected '=' after 'using " << name->c_str() << "'.\n";
return nullopt;
}
p.resolver()->consumeNewLines();
// Store all the units following the equal sign until the next semicolon or newline.
vector< Term > toks;
while( !p.resolver()->eos() )
{
const auto& tok = p.resolver()->lookAheadUnresolved();
if( !tok )
break;
const auto* delim = get_if< Delimiter >( &tok->content() );
if( delim && *delim == Delimiter::Newline )
break;
const auto* id = get_if< StringId >( &tok->content() );
if( id && *id == ";"_sid )
break;
auto g = p.resolver()->consumeUnit();
move( g.begin(), g.end(), back_inserter( toks ) );
}
if( toks.empty() )
{
cout << eqTerm->location() << ": expected an expression after 'using " << name->c_str() << " ='.\n";
return nullopt;
}
const auto& context = p.resolver()->context();
// Create a local identity for the constant, from which the current identity will be visible.
// This is to avoid anything declared from within the using expression to leak outside,
// and also to make sure that whenever it will be parsed, it will have access to the current
|
|
<
|
|
<
|
|
|
>
>
>
|
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
|
#include "builtins/builtins.h"
#include "parse/parse.h"
#include "precedence.h"
using namespace empathy;
using namespace empathy::ir;
using namespace empathy::parse;
namespace empathy::builtins
{
void SetupUsingStmt( Env& e )
{
auto handleUsing = []( Parser& p, const Term& t, uint32_t prec )
{
auto nameTerm = p.resolver()->consume();
if( !nameTerm )
{
cout << t.location() << ": expected an identifier after 'using'.\n";
return false;
}
const auto* name = get_if< StringId >( &nameTerm->content() );
if( !name )
{
cout << nameTerm->location() << ": expected an identifier after 'using'.\n";
return false;
}
auto eqTerm = p.resolver()->consumeUnresolved();
if( !eqTerm )
{
cout << eqTerm->location() << ": expected '=' after 'using " << name->c_str() << "'.\n";
return false;
}
const auto* eq = get_if< StringId >( &eqTerm->content() );
if( !eq || *eq != "="_sid )
{
cout << eqTerm->location() << ": expected '=' after 'using " << name->c_str() << "'.\n";
return false;
}
p.resolver()->consumeNewLines();
// Store all the units following the equal sign until the next semicolon or newline.
vector< Term > toks;
while( !p.resolver()->eos() )
{
const auto& tok = p.resolver()->lookAheadRaw();
if( !tok )
break;
const auto* delim = get_if< Delimiter >( &tok->content() );
if( delim && *delim == Delimiter::Newline )
{
p.resolver()->consumeRaw();
break;
}
const auto* id = get_if< StringId >( &tok->content() );
if( id && *id == ";"_sid )
break;
auto g = p.resolver()->consumeUnit();
move( g.begin(), g.end(), back_inserter( toks ) );
}
if( toks.empty() )
{
cout << eqTerm->location() << ": expected an expression after 'using " << name->c_str() << " ='.\n";
return false;
}
const auto& context = p.resolver()->context();
// Create a local identity for the constant, from which the current identity will be visible.
// This is to avoid anything declared from within the using expression to leak outside,
// and also to make sure that whenever it will be parsed, it will have access to the current
|
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
|
if( holds_alternative< vector< Term > >( content ) )
{
Context localContext( c.env(), localIdentity );
auto tokProvider = make_shared< lex::VectorAdapter >( get< vector< Term > >( content ) );
auto r = make_shared< parse::Resolver >( tokProvider, localContext );
Parser p( r );
auto result = p.parse();
if( !result )
{
cout << "invalid using expression.\n";
return Env::Status::NoMatch;
}
content = ValueToIRExpr( *result );
}
result = get< Term >( content );
return Env::Status::Success;
};
context.env()->storeValue( localIdentity, ANYTERM( c ),
make_shared< Env::ValueProvider >( move( UsingValProvider ) ) );
// Parse whatever follows the using statement
return Parser( p.resolver() ).parse( prec );
};
Rule r( handleUsing );
auto ruleVal = ToValue( move( r ) );
auto ruleTerm = ValueToIRExpr( ruleVal );
e.storeValue( TVEC( TSID( e0 ), TSID( using ) ), ANYTERM( x ), ruleTerm );
}
}
|
>
>
>
>
>
>
|
<
|
|
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
|
if( holds_alternative< vector< Term > >( content ) )
{
Context localContext( c.env(), localIdentity );
auto tokProvider = make_shared< lex::VectorAdapter >( get< vector< Term > >( content ) );
auto r = make_shared< parse::Resolver >( tokProvider, localContext );
Parser p( r );
if( !p.parseExpression() )
{
cout << "invalid using expression.\n";
return Env::Status::NoMatch;
}
auto result = p.result();
if( !result )
{
cout << "invalid using expression.\n";
return Env::Status::NoMatch;
}
content = ValueToIRExpr( *result );
}
result = get< Term >( content );
return Env::Status::Success;
};
context.env()->storeValue( localIdentity, ANYTERM( c ),
make_shared< Env::ValueProvider >( move( UsingValProvider ) ) );
return true;
};
Rule r( handleUsing );
auto ruleVal = ToValue( move( r ) );
auto ruleTerm = ValueToIRExpr( ruleVal );
e.storeValue( TVEC( TSID( e0 ), TSID( using ) ), ANYTERM( x ), ruleTerm );
}
}
|