#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 SetupDollarOp( Env& e )
{
// Dollar is a low level operator: it doesn't expect a value rhs operand, but just an identifier ir element.
// So we can't use the convenient operator wrapper rule.
Rule r( []( Parser& p, const Term& t, uint32_t prec )
{
auto nameTerm = p.resolver()->consumeUnresolved();
if( !nameTerm )
{
cout << t.location() << ": expected an identifier after '$'.\n";
return false;
}
const auto* name = get_if< StringId >( &nameTerm->content() );
if( !name )
{
cout << nameTerm->location() << ": expected an identifier after '$'.\n";
return false;
}
const auto& c = p.resolver()->context();
// Template name bindings are stored with a "$$" prefix so they don't
// collide with regular names.
auto captureIdentity = AppendToVectorTerm( c.identity(),
TERM( "$$"_sid ), TERM( *name ) );
// Look up the TVar name. If it exists, then we're inside of a template function
// body, refering to a bound TVar, so we just return the stored value.
// Otherwise, we're in a template declaration and have to construct a new TVar.
Term result;
switch( c.env()->retrieveValue( captureIdentity, c, result ) )
{
case sema::Env::Status::Success:
p.push( ValueFromIRExpr( result ) );
return true;
case sema::Env::Status::AmbiguousMatch:
cout << t.location() << ": unexpected ambiguous match when resolving '$" << *name << "'.\n";
return false;
}
// No bound value was found: construct a TVar.
p.push( ToValue( TVar( *name ) ) );
return true;
} );
RegisterRule( e, "$"_sid, move( r ) );
}
}