Compare commits
9 Commits
Author | SHA1 | Date |
---|---|---|
Nicolas Pierron | 00ad497494 | |
Nicolas Pierron | b0d21c1db8 | |
Nicolas Pierron | 99e554e0e0 | |
Nicolas Pierron | e0406330fa | |
Nicolas Pierron | 405c763aa8 | |
Nicolas Pierron | 61198a89a1 | |
Nicolas Pierron | 02a4ea0617 | |
Nicolas Pierron | adc5231106 | |
Lluís Batlle i Rossell | d34e538025 |
|
@ -0,0 +1,112 @@
|
|||
// This file contains macro used to define the grammar. You should use
|
||||
// these to define the macro named TRM_GRAMMAR_NODES(Interface, Final)
|
||||
// before inluding any of the libterm files.
|
||||
|
||||
#ifndef _LIBTERM_GRAMMAR_HH
|
||||
# define _LIBTERM_GRAMMAR_HH
|
||||
|
||||
# include "pp.hh"
|
||||
|
||||
|
||||
// These macro are used to define how to manipulate each argument. If the
|
||||
// argument should be given by reference or by copy. You should use
|
||||
// references when the element goes over a specific size and if you accept
|
||||
// to see it living on the stack. You should use copies when the element is
|
||||
// small and if you prefer to have it inside a register.
|
||||
|
||||
# define TRM_TYPE_REF(Type, Name) (const Type&, Type &, Name)
|
||||
# define TRM_TYPE_COPY(Type, Name) (const Type, Type &, Name)
|
||||
# define TRM_TYPE_TERM(Type, Name) TRM_TYPE_COPY(A ## Type, Name)
|
||||
|
||||
|
||||
// These macro are used as shortcuts for the declaration of common type of
|
||||
// grammar nodes.
|
||||
|
||||
# define TRM_GRAMMAR_NODE_BINOP(Final, Name) \
|
||||
Final( \
|
||||
Name, Expr, \
|
||||
(2, (TRM_TYPE_TERM(Expr, lhs), TRM_TYPE_TERM(Expr, rhs))), \
|
||||
(0,()) \
|
||||
)
|
||||
|
||||
# define TRM_GRAMMAR_NODE_SINGLETON(Final, Name) \
|
||||
Final(Name, Expr, (0,()), (0,()))
|
||||
|
||||
|
||||
// Handle the different usage of the variables and attributes. Arguments
|
||||
// are suffixed with a '_' and attributes are not. These macro are
|
||||
// expecting the result of the TRM_TYPE macros as argument.
|
||||
|
||||
# define TRM_CONST_ABSTRACT_COPY_DECL_(Copy, Ref, Name) Copy Name;
|
||||
# define TRM_CONST_ABSTRACT_COPY_ARG_(Copy, Ref, Name) Copy Name ## _
|
||||
# define TRM_ABSTRACT_REF_ARG_(Copy, Ref, Name) Ref Name ## _
|
||||
# define TRM_INIT_ATTRIBUTES_(Copy, Ref, Name) Name (Name ## _)
|
||||
# define TRM_ARGUMENTS_(Copy, Ref, Name) Name ## _
|
||||
# define TRM_COPY_PTR_ATTR_IN_ARG_(Copy, Ref, Name) Name ## _ = ptr-> Name;
|
||||
# define TRM_LESS_RHS_OR_(Copy, Ref, Name) Name < arg_rhs. Name ||
|
||||
|
||||
// These macro are shortcuts used to remove extra parenthesies added by
|
||||
// TRM_TYPE_* macros. Without such parenthesies TRM_APPLY_HELPER won't be
|
||||
// able to give the argument to these macros and arrays won't be well
|
||||
// formed.
|
||||
|
||||
# define TRM_CONST_ABSTRACT_COPY_DECL(Elt) TRM_CONST_ABSTRACT_COPY_DECL_ Elt
|
||||
# define TRM_CONST_ABSTRACT_COPY_ARG(Elt) TRM_CONST_ABSTRACT_COPY_ARG_ Elt
|
||||
# define TRM_ABSTRACT_REF_ARG(Elt) TRM_ABSTRACT_REF_ARG_ Elt
|
||||
# define TRM_INIT_ATTRIBUTES(Elt) TRM_INIT_ATTRIBUTES_ Elt
|
||||
# define TRM_ARGUMENTS(Elt) TRM_ARGUMENTS_ Elt
|
||||
# define TRM_COPY_PTR_ATTR_IN_ARG(Elt) TRM_COPY_PTR_ATTR_IN_ARG_ Elt
|
||||
# define TRM_LESS_RHS_OR(Elt) TRM_LESS_RHS_OR_ Elt
|
||||
|
||||
|
||||
|
||||
/*
|
||||
// Test case. This should be moved inside the libexpr or generated in
|
||||
// another manner.
|
||||
# define TRM_GAMMAR_NODES(Interface, Final)
|
||||
Interface(Loc, Term, TRM_NIL, TRM_NIL)
|
||||
Interface(Pattern, Term, TRM_NIL, TRM_NIL)
|
||||
Interface(Expr, Term, TRM_NIL, TRM_NIL)
|
||||
Final(Pos, Loc, (TRM_TYPE_REF(std::string, file)
|
||||
TRM_TYPE_COPY(int, line)
|
||||
TRM_TYPE_COPY(int, column)), TRM_NIL)
|
||||
Final(NoPos, Loc, TRM_NIL, TRM_NIL)
|
||||
Final(String, Expr, (TRM_TYPE_REF(std::string, value)), TRM_NIL)
|
||||
Final(Var, Expr, (TRM_TYPE_REF(std::string, name)), TRM_NIL)
|
||||
Final(Path, Expr, (TRM_TYPE_REF(std::string, filename)), TRM_NIL)
|
||||
Final(Int, Expr, (TRM_TYPE_COPY(int, value)), TRM_NIL)
|
||||
Final(Function, Expr, (TRM_TYPE_TERM(Pattern, pattern)
|
||||
TRM_TYPE_TERM(Expr, body)
|
||||
TRM_TYPE_TERM(Pos, position)), TRM_NIL)
|
||||
Final(Assert, Expr, (TRM_TYPE_TERM(Expr, cond)
|
||||
TRM_TYPE_TERM(Expr, body)
|
||||
TRM_TYPE_TERM(Pos, position)), TRM_NIL)
|
||||
Final(With, Expr, (TRM_TYPE_TERM(Expr, set)
|
||||
TRM_TYPE_TERM(Expr, body)
|
||||
TRM_TYPE_TERM(Pos, position)), TRM_NIL)
|
||||
Final(If, Expr, (TRM_TYPE_TERM(Expr, cond)
|
||||
TRM_TYPE_TERM(Expr, thenPart)
|
||||
TRM_TYPE_TERM(Expr, elsePart)), TRM_NIL)
|
||||
Final(OpNot, Expr, (TRM_TYPE_TERM(Expr, cond)), TRM_NIL)
|
||||
TRM_GRAMMAR_NODE_BINOP(Final, OpEq)
|
||||
TRM_GRAMMAR_NODE_BINOP(Final, OpNEq)
|
||||
TRM_GRAMMAR_NODE_BINOP(Final, OpAnd)
|
||||
TRM_GRAMMAR_NODE_BINOP(Final, OpOr)
|
||||
TRM_GRAMMAR_NODE_BINOP(Final, OpImpl)
|
||||
TRM_GRAMMAR_NODE_BINOP(Final, OpUpdate)
|
||||
TRM_GRAMMAR_NODE_BINOP(Final, SubPath)
|
||||
TRM_GRAMMAR_NODE_BINOP(Final, OpHasAttr)
|
||||
TRM_GRAMMAR_NODE_BINOP(Final, OpPlus)
|
||||
TRM_GRAMMAR_NODE_BINOP(Final, OpConcat)
|
||||
Final(Call, Expr, (TRM_TYPE_TERM(Expr, function)
|
||||
TRM_TYPE_TERM(Expr, argument)), TRM_NIL)
|
||||
Final(Select, Expr, (TRM_TYPE_TERM(Expr, set)
|
||||
TRM_TYPE_TERM(Var, var)), TRM_NIL)
|
||||
Final(BlackHole, Expr, TRM_NIL, TRM_NIL)
|
||||
Final(Undefined, Expr, TRM_NIL, TRM_NIL)
|
||||
Final(Removed, Expr, TRM_NIL, TRM_NIL)
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#endif
|
|
@ -0,0 +1,94 @@
|
|||
|
||||
#ifndef _LIBTERM_PP_HH
|
||||
# define _LIBTERM_PP_HH
|
||||
|
||||
# include <boost/preprocessor/tuple.hpp>
|
||||
# include <boost/preprocessor/seq.hpp>
|
||||
# include <boost/preprocessor/cat.hpp>
|
||||
# include <boost/preprocessor/array.hpp>
|
||||
|
||||
// a few shortcuts to keep things clear.
|
||||
|
||||
# define TRM_NIL
|
||||
# define TRM_NIL_ARGS(...)
|
||||
# define TRM_EMPTY_ARRAY (0, ())
|
||||
|
||||
# define TRM_SEQ_HEAD BOOST_PP_SEQ_HEAD
|
||||
# define TRM_SEQ_TAIL BOOST_PP_SEQ_TAIL
|
||||
|
||||
# define TRM_ARRAY_DATA BOOST_PP_ARRAY_DATA
|
||||
# define TRM_ARRAY_SIZE BOOST_PP_ARRAY_SIZE
|
||||
# define TRM_ARRAY_ELEM BOOST_PP_ARRAY_ELEM
|
||||
# define TRM_SEQ_TO_ARRAY BOOST_PP_SEQ_TO_ARRAY
|
||||
# define TRM_ARRAY_TO_SEQ(Array) \
|
||||
BOOST_PP_TUPLE_TO_SEQ(TRM_ARRAY_SIZE(Array), TRM_ARRAY_DATA(Array))
|
||||
|
||||
// TRM_EVAL macros are used to do the convertion of array to sequence and to
|
||||
// provide a default case when the array cannot be converted into a
|
||||
// sequence. This case happens when you need to convert a zero size array.
|
||||
|
||||
# define TRM_EVAL_0(Macro1, Macro2, Array, Default) Default
|
||||
# define TRM_EVAL_1(Macro1, Macro2, Array, Default) \
|
||||
Macro1(Macro2, TRM_ARRAY_TO_SEQ(Array))
|
||||
|
||||
# define TRM_EVAL_2 TRM_EVAL_1
|
||||
# define TRM_EVAL_3 TRM_EVAL_1
|
||||
# define TRM_EVAL_4 TRM_EVAL_1
|
||||
|
||||
# define TRM_EVAL_II(eval) eval
|
||||
# define TRM_EVAL_I(n, _) TRM_EVAL_ ## n
|
||||
# define TRM_EVAL(Macro1, Macro2, Array, Default) \
|
||||
TRM_EVAL_II(TRM_EVAL_I Array (Macro1, Macro2, Array, Default))
|
||||
|
||||
# define TRM_DEFAULT1(D0) D0
|
||||
|
||||
// Default TRM_<fun> are taking an array and return a sequence. To keep the
|
||||
// same type, you need to specify which type you expect to have. The reason
|
||||
// is that array support to have no values where sequence do not support it.
|
||||
// On the contrary, all operations are well defined on sequences but none
|
||||
// are defined on arrays.
|
||||
|
||||
# define TRM_MAP_HELPER(R, Macro, Elt) (Macro(Elt))
|
||||
# define TRM_MAP_(Macro, Seq) \
|
||||
BOOST_PP_SEQ_FOR_EACH(TRM_MAP_HELPER, Macro, Seq)
|
||||
# define TRM_MAP_SEQ(Macro, Seq) \
|
||||
TRM_MAP_(Macro, Seq)
|
||||
# define TRM_MAP_ARRAY_(Macro, Seq) \
|
||||
TRM_SEQ_TO_ARRAY(TRM_MAP_SEQ(Macro, Seq))
|
||||
# define TRM_MAP_ARRAY(Macro, Array) \
|
||||
TRM_EVAL(TRM_MAP_ARRAY_, Macro, Array, \
|
||||
TRM_DEFAULT1(TRM_EMPTY_ARRAY) \
|
||||
)
|
||||
# define TRM_MAP(Macro, Array) \
|
||||
TRM_EVAL(TRM_MAP_SEQ, Macro, Array, \
|
||||
TRM_DEFAULT1(TRM_NIL) \
|
||||
)
|
||||
|
||||
// Apply a macro on all elements (array / sequence)
|
||||
|
||||
# define TRM_APPLY_HELPER(R, Macro, Elt) Macro(Elt)
|
||||
# define TRM_APPLY_(Macro, Seq) \
|
||||
BOOST_PP_SEQ_FOR_EACH(TRM_APPLY_HELPER, Macro, Seq)
|
||||
# define TRM_APPLY_SEQ(Macro, Seq) \
|
||||
TRM_APPLY_(Macro, Seq)
|
||||
# define TRM_APPLY(Macro, Array) \
|
||||
TRM_EVAL(TRM_APPLY_, Macro, Array, \
|
||||
TRM_DEFAULT1(TRM_NIL) \
|
||||
)
|
||||
|
||||
// Apply a macro on all elements (array / sequence) and separate them by a
|
||||
// comma.
|
||||
|
||||
# define TRM_SEPARATE_COMMA_HELPER(Elt) , Elt
|
||||
# define TRM_SEPARATE_COMMA_(_, Seq) \
|
||||
TRM_SEQ_HEAD(Seq) \
|
||||
TRM_APPLY_SEQ(TRM_SEPARATE_COMMA_HELPER, TRM_SEQ_TAIL(Seq))
|
||||
# define TRM_SEPARATE_COMMA_SEQ(Seq) \
|
||||
TRM_SEPARATE_COMMA(TRM_SEQ_TO_ARRAY(Seq))
|
||||
# define TRM_SEPARATE_COMMA(Array) \
|
||||
TRM_EVAL(TRM_SEPARATE_COMMA_, dummy, Array, \
|
||||
TRM_DEFAULT1(TRM_NIL) \
|
||||
)
|
||||
|
||||
|
||||
#endif
|
|
@ -0,0 +1,202 @@
|
|||
|
||||
#ifndef _LIBTERM_TERM_CLASS_FWD_HH
|
||||
# define _LIBTERM_TERM_CLASS_FWD_HH
|
||||
|
||||
# include <set>
|
||||
# include "visitor_fwd.hh"
|
||||
|
||||
namespace term
|
||||
{
|
||||
// Performance issue: Abstract classes should be copied where fully
|
||||
// defined terms should be used with constant references. An ATerm is
|
||||
// only composed by a pointer and should not use any virtual method. By
|
||||
// following this rule, the compiler can optimize the size to the size of
|
||||
// its members (which is a pointer).
|
||||
|
||||
class ATermImpl
|
||||
{
|
||||
public:
|
||||
ATermImpl();
|
||||
virtual ~ATermImpl();
|
||||
|
||||
public:
|
||||
virtual ATerm accept(ATermVisitor& v) const = 0;
|
||||
};
|
||||
|
||||
|
||||
class ATerm
|
||||
{
|
||||
public:
|
||||
ATerm(const ATerm& t);
|
||||
ATerm();
|
||||
|
||||
protected:
|
||||
ATerm(const ATermImpl* ptr);
|
||||
|
||||
public:
|
||||
ATerm accept(ATermVisitor& v) const;
|
||||
|
||||
public:
|
||||
bool operator== (const ATerm& rhs) const;
|
||||
bool operator!= (const ATerm& rhs) const;
|
||||
bool operator <(const ATerm& rhs) const;
|
||||
operator bool();
|
||||
|
||||
public:
|
||||
const ATermImpl* get_ptr() const;
|
||||
|
||||
protected:
|
||||
const ATermImpl* ptr_;
|
||||
};
|
||||
|
||||
|
||||
struct Term : public ATermImpl
|
||||
{
|
||||
public:
|
||||
typedef Term this_type;
|
||||
typedef ATerm term;
|
||||
|
||||
public:
|
||||
bool operator <(const this_type&) const;
|
||||
};
|
||||
|
||||
|
||||
// [
|
||||
|
||||
// Declare the constructor
|
||||
# define TRM_IMPL_CTR_DECL(Name, Base, Attributes, BaseArgs) \
|
||||
Name ( TRM_SEPARATE_COMMA( \
|
||||
TRM_MAP_ARRAY(TRM_CONST_ABSTRACT_COPY_ARG, Attributes) \
|
||||
) );
|
||||
|
||||
// Declare the make method which create an abstract term.
|
||||
# define TRM_IMPL_MAKE_DECL(Name, Base, Attributes, BaseArgs) \
|
||||
static \
|
||||
term \
|
||||
make( \
|
||||
TRM_SEPARATE_COMMA( \
|
||||
TRM_MAP_ARRAY(TRM_CONST_ABSTRACT_COPY_ARG, Attributes) \
|
||||
) \
|
||||
);
|
||||
|
||||
// Declare all the attributes of the current class.
|
||||
# define TRM_ATTRIBUTE_DECLS(Name, Base, Attributes, BaseArgs) \
|
||||
public: \
|
||||
TRM_APPLY(TRM_CONST_ABSTRACT_COPY_DECL, Attributes)
|
||||
|
||||
|
||||
// A class which provide static method (no virtual) to access the
|
||||
// implementation of the term. This class is a wrapper over a pointer which
|
||||
// should derivate from the ATerm class.
|
||||
# define TRM_ABSTRACT_INTERFACE(Name, Base, Attributes, BaseArgs) \
|
||||
class A ## Name : public A ## Base \
|
||||
{ \
|
||||
typedef A ## Base parent; \
|
||||
\
|
||||
public: \
|
||||
A ## Name (const A ## Name& t); \
|
||||
A ## Name (); \
|
||||
\
|
||||
protected: \
|
||||
explicit A ## Name (const ATermImpl* ptr); \
|
||||
};
|
||||
|
||||
// Add the implementation class as a friend class to provide access to the
|
||||
// private constructor. This reduce interaction with the implementation of
|
||||
// the terms.
|
||||
# define TRM_ABSTRACT_FINAL(Name, Base, Attributes, BaseArgs) \
|
||||
class A ## Name : public A ## Base \
|
||||
{ \
|
||||
typedef A ## Base parent; \
|
||||
\
|
||||
public: \
|
||||
A ## Name (const A ## Name& t); \
|
||||
A ## Name (); \
|
||||
\
|
||||
const Name & \
|
||||
operator* () const; \
|
||||
\
|
||||
const Name* \
|
||||
operator-> () const; \
|
||||
\
|
||||
protected: \
|
||||
explicit A ## Name (const ATermImpl* ptr); \
|
||||
\
|
||||
friend class Name; \
|
||||
};
|
||||
|
||||
# define TRM_IMPL_INTERFACE(Name, Base, Attributes, BaseArgs) \
|
||||
class Name : public Base \
|
||||
{ \
|
||||
typedef Name this_type; \
|
||||
typedef Base parent; \
|
||||
\
|
||||
public: \
|
||||
bool operator <(const Name& arg_rhs) const; \
|
||||
\
|
||||
protected: \
|
||||
TRM_IMPL_CTR_DECL(Name, Base, Attributes, BaseArgs) \
|
||||
\
|
||||
public: \
|
||||
TRM_ATTRIBUTE_DECLS(Name, Base, Attributes, BaseArgs) \
|
||||
};
|
||||
|
||||
# define TRM_IMPL_FINAL(Name, Base, Attributes, BaseArgs) \
|
||||
class Name : public Base \
|
||||
{ \
|
||||
typedef Name this_type; \
|
||||
typedef Base parent; \
|
||||
public: \
|
||||
typedef A ## Name term; \
|
||||
typedef std::set<this_type> term_set_type; \
|
||||
\
|
||||
public: \
|
||||
TRM_IMPL_MAKE_DECL(Name, Base, Attributes, BaseArgs) \
|
||||
ATerm accept(ATermVisitor& v) const; \
|
||||
bool operator <(const Name& arg_rhs) const; \
|
||||
\
|
||||
protected: \
|
||||
TRM_IMPL_CTR_DECL(Name, Base, Attributes, BaseArgs) \
|
||||
\
|
||||
public: \
|
||||
TRM_ATTRIBUTE_DECLS(Name, Base, Attributes, BaseArgs) \
|
||||
\
|
||||
private: \
|
||||
\
|
||||
static \
|
||||
const ATermImpl* \
|
||||
get_identity(const this_type& t); \
|
||||
\
|
||||
static \
|
||||
term_set_type& set_instance(); \
|
||||
};
|
||||
|
||||
|
||||
TRM_GRAMMAR_NODES(TRM_ABSTRACT_INTERFACE, TRM_ABSTRACT_FINAL)
|
||||
TRM_GRAMMAR_NODES(TRM_IMPL_INTERFACE, TRM_IMPL_FINAL)
|
||||
|
||||
# undef TRM_ABSTRACT_INTERFACE
|
||||
# undef TRM_ABSTRACT_FINAL
|
||||
# undef TRM_IMPL_INTERFACE
|
||||
# undef TRM_IMPL_FINAL
|
||||
|
||||
# undef TRM_IMPL_CTR_DECL
|
||||
# undef TRM_ATTRIBUTE_DECLS
|
||||
# undef TRM_IMPL_MAKE_DECL
|
||||
// ]
|
||||
|
||||
|
||||
# define TRM_GENERIC_MAKE_DECL(Name, Base, Attributes, BaseArgs) \
|
||||
Name :: term \
|
||||
make ## Name( \
|
||||
TRM_SEPARATE_COMMA( \
|
||||
TRM_MAP_ARRAY(TRM_CONST_ABSTRACT_COPY_ARG, Attributes) \
|
||||
) \
|
||||
);
|
||||
|
||||
TRM_GRAMMAR_NODES(TRM_NIL_ARGS, TRM_GENERIC_MAKE_DECL)
|
||||
|
||||
# undef TRM_GENERIC_MAKE_DECL
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,28 @@
|
|||
|
||||
#ifndef _LIBTERM_TERM_FWD_HH
|
||||
# define _LIBTERM_TERM_FWD_HH
|
||||
|
||||
# include "grammar.hh"
|
||||
|
||||
// Types prefixed by an 'A' are the terms which should be manipulated by the
|
||||
// user. The 'A' letter stands for Abstract. Their content should be
|
||||
// limited to a pointer and they must not use any virtual keyword. On the
|
||||
// other hand, the implementation of terms can declare more than one
|
||||
// attribute and use virtual keywords as long as they don't cost too much.
|
||||
|
||||
namespace term
|
||||
{
|
||||
class ATerm;
|
||||
class ATermImpl; // should be renamed to TermImpl
|
||||
|
||||
# define TRM_DECLARE(Name, Base, Attributes, BaseArgs) \
|
||||
class A ## Name; \
|
||||
class Name;
|
||||
|
||||
TRM_GRAMMAR_NODES(TRM_DECLARE, TRM_DECLARE)
|
||||
|
||||
# undef TRM_DECLARE
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,269 @@
|
|||
|
||||
#ifndef _LIBTERM_TERM_HH
|
||||
# define _LIBTERM_TERM_HH
|
||||
|
||||
# include "term.hh"
|
||||
# include "visitor.hh"
|
||||
|
||||
namespace term
|
||||
{
|
||||
inline
|
||||
ATermImpl::ATermImpl()
|
||||
{
|
||||
}
|
||||
|
||||
inline
|
||||
ATermImpl::~ATermImpl()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
inline
|
||||
ATerm::ATerm(const ATerm& t)
|
||||
: ptr_(t.ptr_)
|
||||
{
|
||||
}
|
||||
|
||||
inline
|
||||
ATerm::ATerm()
|
||||
: ptr_(0)
|
||||
{
|
||||
}
|
||||
|
||||
inline
|
||||
ATerm::ATerm(const ATermImpl* ptr)
|
||||
: ptr_(ptr)
|
||||
{
|
||||
}
|
||||
|
||||
inline
|
||||
ATerm
|
||||
ATerm::accept(ATermVisitor& v) const
|
||||
{
|
||||
return ptr_->accept(v);
|
||||
}
|
||||
|
||||
inline
|
||||
bool
|
||||
ATerm::operator== (const ATerm& rhs) const
|
||||
{
|
||||
return ptr_ == rhs.ptr_;
|
||||
}
|
||||
|
||||
inline
|
||||
bool
|
||||
ATerm::operator!= (const ATerm& rhs) const
|
||||
{
|
||||
return ptr_ != rhs.ptr_;
|
||||
}
|
||||
|
||||
inline
|
||||
bool
|
||||
ATerm::operator <(const ATerm& rhs) const
|
||||
{
|
||||
return ptr_ < rhs.ptr_;
|
||||
}
|
||||
|
||||
inline
|
||||
ATerm::operator bool()
|
||||
{
|
||||
return ptr_;
|
||||
}
|
||||
|
||||
inline
|
||||
const ATermImpl*
|
||||
ATerm::get_ptr() const
|
||||
{
|
||||
return ptr_;
|
||||
}
|
||||
|
||||
|
||||
inline
|
||||
bool
|
||||
Term::operator <(const this_type&) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// define the contructors of the Abstract terms. These constructors are
|
||||
// just delegating the work to the ATerm constructors.
|
||||
# define TRM_ABSTRACT_CTR(Name, Base, Attributes, BaseArgs) \
|
||||
inline \
|
||||
A ## Name :: A ## Name (const A ## Name& t) : \
|
||||
parent(t) \
|
||||
{ \
|
||||
} \
|
||||
\
|
||||
inline \
|
||||
A ## Name :: A ## Name () : \
|
||||
parent() \
|
||||
{ \
|
||||
} \
|
||||
\
|
||||
inline \
|
||||
A ## Name :: A ## Name (const ATermImpl* ptr) : \
|
||||
parent(ptr) \
|
||||
{ \
|
||||
}
|
||||
|
||||
TRM_GRAMMAR_NODES(TRM_ABSTRACT_CTR, TRM_ABSTRACT_CTR)
|
||||
|
||||
# undef TRM_ABSTRACT_CTR
|
||||
|
||||
|
||||
// Give acces to the implementation in order to get access to each field of
|
||||
// the term.
|
||||
# define TRM_ABSTRACT_FINAL_ACCESS(Name, Base, Attributes, BaseArgs) \
|
||||
inline \
|
||||
const Name & \
|
||||
A ## Name :: operator* () const \
|
||||
{ \
|
||||
return *static_cast<const Name *>(ptr_); \
|
||||
} \
|
||||
\
|
||||
inline \
|
||||
const Name* \
|
||||
A ## Name :: operator-> () const \
|
||||
{ \
|
||||
return static_cast<const Name *>(ptr_); \
|
||||
}
|
||||
|
||||
TRM_GRAMMAR_NODES(TRM_NIL_ARGS, TRM_ABSTRACT_FINAL_ACCESS)
|
||||
|
||||
# undef TRM_ABSTRACT_FINAL_ACCESS
|
||||
|
||||
|
||||
|
||||
// Initialized all attributes of the current class and call the base class
|
||||
// with the expected arguments.
|
||||
# define TRM_IMPL_CTR(Name, Base, Attributes, BaseArgs) \
|
||||
inline \
|
||||
Name :: Name ( \
|
||||
TRM_SEPARATE_COMMA( \
|
||||
TRM_MAP_ARRAY(TRM_CONST_ABSTRACT_COPY_ARG, Attributes) \
|
||||
) \
|
||||
) \
|
||||
: TRM_SEPARATE_COMMA_SEQ( \
|
||||
TRM_MAP(TRM_INIT_ATTRIBUTES, Attributes) \
|
||||
( parent(TRM_SEPARATE_COMMA( \
|
||||
TRM_MAP_ARRAY(TRM_ARGUMENTS, BaseArgs) \
|
||||
)) \
|
||||
) \
|
||||
) \
|
||||
{ \
|
||||
}
|
||||
|
||||
TRM_GRAMMAR_NODES(TRM_IMPL_CTR, TRM_IMPL_CTR)
|
||||
|
||||
# undef TRM_IMPL_CTR
|
||||
|
||||
|
||||
// This operator is used for checking if the current ellement has not been
|
||||
// create before. It compares each attributes of the current class and
|
||||
// delegate other attribute comparison to his parent class.
|
||||
# define TRM_IMPL_LESS(Name, Base, Attributes, BaseArgs) \
|
||||
inline \
|
||||
bool \
|
||||
Name :: operator <(const Name& arg_rhs) const \
|
||||
{ \
|
||||
return TRM_APPLY(TRM_LESS_RHS_OR, Attributes) \
|
||||
parent::operator < (arg_rhs); \
|
||||
}
|
||||
|
||||
TRM_GRAMMAR_NODES(TRM_IMPL_LESS, TRM_IMPL_LESS)
|
||||
|
||||
# undef TRM_IMPL_LESS
|
||||
|
||||
|
||||
// This method is used to provide maximal sharing among node of the same
|
||||
// types. This create the class with the private constructor and register
|
||||
// it if this is not already done. It returns a term which has a small
|
||||
// memory impact (only a pointer) which refers to the created element.
|
||||
# define TRM_IMPL_FINAL_MAKE(Name, Base, Attributes, BaseArgs) \
|
||||
inline \
|
||||
Name :: term \
|
||||
Name :: make( \
|
||||
TRM_SEPARATE_COMMA( \
|
||||
TRM_MAP_ARRAY(TRM_CONST_ABSTRACT_COPY_ARG, Attributes) \
|
||||
) \
|
||||
) \
|
||||
{ \
|
||||
return term(get_identity(this_type( \
|
||||
TRM_SEPARATE_COMMA( \
|
||||
TRM_MAP_ARRAY(TRM_ARGUMENTS, Attributes) \
|
||||
) \
|
||||
))); \
|
||||
}
|
||||
|
||||
TRM_GRAMMAR_NODES(TRM_NIL_ARGS, TRM_IMPL_FINAL_MAKE)
|
||||
|
||||
# undef TRM_IMPL_FINAL_MAKE
|
||||
|
||||
|
||||
// Handle visit from the ATermVisitor and forward them to the Abstract term
|
||||
// of the current term.
|
||||
# define TRM_IMPL_FINAL_VISIT(Name, Base, Attributes, BaseArgs) \
|
||||
inline \
|
||||
ATerm \
|
||||
Name :: accept(ATermVisitor& v) const \
|
||||
{ \
|
||||
return v.visit(term(this)); \
|
||||
}
|
||||
|
||||
TRM_GRAMMAR_NODES(TRM_NIL_ARGS, TRM_IMPL_FINAL_VISIT)
|
||||
|
||||
# undef TRM_IMPL_FINAL_VISIT
|
||||
|
||||
|
||||
// These functions are used to provide maximal sharing between the terms.
|
||||
// All terms are stored inside a set only the address the element contained
|
||||
// in the set is used.
|
||||
# define TRM_IMPL_FINAL_SHARED(Name, Base, Attributes, BaseArgs) \
|
||||
inline \
|
||||
const ATermImpl* \
|
||||
Name :: get_identity(const this_type& t) \
|
||||
{ \
|
||||
return static_cast<const ATermImpl*>( \
|
||||
&*set_instance().insert(t).first \
|
||||
); \
|
||||
} \
|
||||
\
|
||||
inline \
|
||||
Name :: term_set_type& \
|
||||
Name :: set_instance() \
|
||||
{ \
|
||||
static term_set_type set; \
|
||||
return set; \
|
||||
}
|
||||
|
||||
TRM_GRAMMAR_NODES(TRM_NIL_ARGS, TRM_IMPL_FINAL_SHARED)
|
||||
|
||||
# undef TRM_IMPL_FINAL_SHARED
|
||||
|
||||
|
||||
// Improve user experience by providing function to create Abstract terms
|
||||
// without any manipulation of the implementation class names.
|
||||
# define TRM_GENERIC_MAKE(Name, Base, Attributes, BaseArgs) \
|
||||
inline \
|
||||
Name :: term \
|
||||
make ## Name( \
|
||||
TRM_SEPARATE_COMMA( \
|
||||
TRM_MAP_ARRAY(TRM_CONST_ABSTRACT_COPY_ARG, Attributes) \
|
||||
) \
|
||||
) \
|
||||
{ \
|
||||
return Name :: make( \
|
||||
TRM_SEPARATE_COMMA( \
|
||||
TRM_MAP_ARRAY(TRM_ARGUMENTS, Attributes) \
|
||||
) \
|
||||
); \
|
||||
}
|
||||
|
||||
TRM_GRAMMAR_NODES(TRM_NIL_ARGS, TRM_GENERIC_MAKE)
|
||||
|
||||
# undef TRM_GENERIC_MAKE
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,56 @@
|
|||
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
|
||||
#define TRM_GRAMMAR_NODES(Interface, Final) \
|
||||
Interface(Expr, Term, (0, ()), (0, ())) \
|
||||
TRM_GRAMMAR_NODE_BINOP(Final, Plus) \
|
||||
Final(Int, Expr, (1, (TRM_TYPE_COPY(int, value))), (0, ()))
|
||||
|
||||
#include "term_impl.hh"
|
||||
#include "visitor_impl.hh"
|
||||
#undef TRM_GRAMMAR_NODES
|
||||
|
||||
using namespace term;
|
||||
|
||||
struct Eval : public ATermVisitor
|
||||
{
|
||||
int run(const ATerm t)
|
||||
{
|
||||
return as<AInt>(t.accept(*this))->value;
|
||||
}
|
||||
|
||||
ATerm visit(const APlus p)
|
||||
{
|
||||
return Int::make(run(p->lhs) + run(p->rhs));
|
||||
}
|
||||
};
|
||||
|
||||
#define CHECK(Cond, Msg) \
|
||||
if (Cond) \
|
||||
{ \
|
||||
good++; \
|
||||
std::cout << "Ok: " << Msg << std::endl; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
std::cout << "Ko: " << Msg << std::endl; \
|
||||
} \
|
||||
tests++
|
||||
|
||||
int main()
|
||||
{
|
||||
unsigned good, tests;
|
||||
|
||||
using namespace term;
|
||||
AInt a = makeInt(1);
|
||||
AInt b = makeInt(2);
|
||||
AInt c = makeInt(1);
|
||||
Eval e;
|
||||
|
||||
CHECK(a == c, "Terms are shared.");
|
||||
CHECK(!as<APlus>(a), "Bad convertion returns a zero ATerm.");
|
||||
CHECK(as<AInt>(a) == a, "Good convertion returns the same ATerm.");
|
||||
CHECK(e.run(makePlus(a, makePlus(b, c))) == 4, "Visitors are working.");
|
||||
return tests - good;
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
|
||||
#ifndef _LIBTERM_VISITOR_CLASS_FWD_HH
|
||||
# define _LIBTERM_VISITOR_CLASS_FWD_HH
|
||||
|
||||
# include "term.hh"
|
||||
|
||||
namespace term
|
||||
{
|
||||
// base class for visitor implementation.
|
||||
class ATermVisitor
|
||||
{
|
||||
public:
|
||||
# define TRM_VISITOR(Name, Base, Attributes, BaseArgs) \
|
||||
virtual ATerm visit(const A ## Name);
|
||||
|
||||
TRM_VISITOR(Term, TRM_NIL, TRM_NIL, TRM_NIL)
|
||||
TRM_GRAMMAR_NODES(TRM_VISITOR, TRM_VISITOR)
|
||||
# undef TRM_VISITOR
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
|
||||
#ifndef _LIBTERM_VISITOR_FWD_HH
|
||||
# define _LIBTERM_VISITOR_FWD_HH
|
||||
|
||||
# include "term_fwd.hh"
|
||||
|
||||
// Types prefixed by an 'A' are the terms which should be manipulated by the
|
||||
// user. The 'A' letter stands for Abstract. Their content should be
|
||||
// limited to a pointer and they must not use any virtual keyword. On the
|
||||
// other hand, the implementation of terms can declare more than one
|
||||
// attribute and use virtual keywords as long as they don't cost too much.
|
||||
|
||||
namespace term
|
||||
{
|
||||
// base class for visitor implementation.
|
||||
class ATermVisitor;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,57 @@
|
|||
|
||||
#ifndef _LIBTERM_VISITOR_HH
|
||||
# define _LIBTERM_VISITOR_HH
|
||||
|
||||
# include "visitor.hh"
|
||||
# include "term.hh"
|
||||
|
||||
namespace term
|
||||
{
|
||||
|
||||
// definition of the ATermVisitor visit functions.
|
||||
# define TRM_VISITOR(Name, Base, Attributes, BaseArgs) \
|
||||
ATerm \
|
||||
ATermVisitor::visit(const A ## Name t) { \
|
||||
return t; \
|
||||
}
|
||||
|
||||
TRM_VISITOR(Term, TRM_NIL, TRM_NIL, TRM_NIL)
|
||||
TRM_GRAMMAR_NODES(TRM_VISITOR, TRM_VISITOR)
|
||||
|
||||
# undef TRM_VISITOR
|
||||
|
||||
namespace impl
|
||||
{
|
||||
template <typename T>
|
||||
class asVisitor : ATermVisitor
|
||||
{
|
||||
public:
|
||||
asVisitor(ATerm t)
|
||||
: res()
|
||||
{
|
||||
t.accept(*this);
|
||||
}
|
||||
|
||||
ATerm visit(const T t)
|
||||
{
|
||||
return res = t;
|
||||
}
|
||||
|
||||
public:
|
||||
T res;
|
||||
};
|
||||
}
|
||||
|
||||
// This function will return a zero ATerm if the element does not have the
|
||||
// expected type.
|
||||
template <typename T>
|
||||
inline
|
||||
T as(ATerm t)
|
||||
{
|
||||
impl::asVisitor<T> v(t);
|
||||
return v.res;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue