#ifndef GOOSE_EIR_TERM_H
#define GOOSE_EIR_TERM_H
namespace goose::eir
{
class Vector;
using pvec = ptr< Vector >;
// We use a distinct type to store locations so that we can handle it differently
// in the pattern matching algorithms. We consider all LocationId to be equal to one another
// regardless of their value. This way we can keep it around in IR expessions without having
// to construct specific patterns to ignore it. (The fact that the location at which two value
// are defined might be different is never relevant)
enum class LocationId : uint32_t {};
enum class Delimiter
{
OpenParen,
OpenBrace,
OpenBracket,
CloseParen,
CloseBrace,
CloseBracket
};
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;
bool operator<( const Hole& rhs ) const;
bool operator==( const Hole& rhs ) const;
private:
StringId m_name;
ptr< STerm > m_flavor = make_shared< STerm >();
};
using Term = variant
<
uint32_t,
LocationId,
string,
StringId,
Delimiter,
Hole,
AnyTerm,
VecOfLength,
ptr< void >,
void*,
pvec,
// Representation for ct_int, the compile time only integers
// with "unlimited" precision
BigInt,
// Compile time representation for normal, fixed size integers
APSInt
>;
extern bool operator==( const Term& lhs, const Term& rhs );
extern bool operator!=( const Term& lhs, const Term& rhs );
struct STerm
{
Term content;
};
inline Hole::Hole( const StringId& name ) : Hole( name, Term( AnyTerm( "_"_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 >;
}
#define TERM( x ) eir::Term( x )
#define TSTR( x ) TERM( string( x ) )
#define TSID( x ) TERM( #x##_sid )
#define HOLE( ... ) TERM( ( eir::Hole{ __VA_ARGS__ } ) )
#define ANYTERM( x ) TERM( eir::AnyTerm( #x##_sid ) )
#define VECOFLENGTH( x ) TERM( eir::VecOfLength( #x##_sid ) )
#define VEC( ... ) TERM( eir::Vector::Make( __VA_ARGS__ ) )
#define REPEAT( x ) eir::Repetition( x )
#endif