I am developing functional domain specific embedded language within C++ to translate formulas into working code as concisely and accurately as possible.
I posted a proto
my prototype (still needs lots of work obviously, and comments)
// #include "tensor/tensor.hpp"
// #include "typename.hpp"
#include
#include
#include
#define BOOST_FUSION_INVOKE_FUNCTION_OBJECT_MAX_ARITY PHOENIX_ARG_LIMIT
#include
#include
#include
#include
#include
#include
#include
#include
namespace range_ {
namespace detail {
namespace phoenix = boost::phoenix;
namespace fusion = boost::fusion;
/// undefined or implicit object
struct undefined {};
template
struct index {
// index(boost::phoenix::argument) {}
typedef phoenix::actor > argument;
argument arg() const { return argument(); }
};
template
struct functional {
typedef phoenix::actor > type;
static type form(const T& t) { return type(t); }
};
template
struct functional, U> {
typedef phoenix::actor type;
static type form(const T& t) { return type(t); }
};
template
struct functional {
typedef typename functional::type type;
static type form(const undefined&) { return type(T()); }
};
template
struct expression;
template
struct expression {
typedef functional lower_function;
typedef functional upper_function;
expression(const L &lower, const U& upper, const C &cdr)
: lower_(lower), upper_(upper), cdr_(cdr) {}
template
expression operator()(const E &c) const {
return expression(lower_, upper_, c);
}
template
void operator[](const F &f) const {
#define TEXT(z, n, text) text
#define UNDEFINED_ARGUMENTS BOOST_PP_ENUM(PHOENIX_ARG_LIMIT, TEXT, undefined())
evaluate(f, fusion::make_vector(UNDEFINED_ARGUMENTS));
#undef TEXT
#undef UNDEFINED_ARGUMENTS
}
L lower_;
U upper_;
C cdr_;
const L& left() const { return lower_; }
const C& cdr() const {return cdr_; }
template
typename functional::type begin() const {
return functional::form(lower_);
}
template
typename functional::type end() const {
return functional::form(upper_);
}
template
void evaluate(const F &f, const A &arguments) const {
T i = this->begin()(arguments);
#define AS_VECTOR(var, expr) BOOST_AUTO(var, fusion::as_vector(expr))
#define ADVANCE_C(seq) fusion::advance_c(fusion::begin(seq))
AS_VECTOR(b, fusion::erase(arguments, ADVANCE_C(arguments)));
AS_VECTOR(a, fusion::insert_range(b, ADVANCE_C(b),
fusion::vector_tie(i)));
#undef ADVANCE_C
#undef AS_VECTOR
while (fusion::invoke_function_object(this->end(), a)) {
this->apply(cdr_, f, a);
++i;
}
}
template
void apply(const E &e, const F &f, const V &variables) const {
e.template evaluate(f, variables);
}
template
void apply(const undefined&, const F &f, const V &variables) const {
fusion::invoke_function_object(f, fusion::as_vector(variables));
}
};
template
expression
make_expression(const L &lower, const U& upper) {
return expression(lower, upper, undefined());
}
template
expression
make_expression(const expression &expr, const U& right) {
return expression(expr.left(), right, undefined());
}
template
expression >
operator,(const expression &e1,
const expression &e2) {
return e2(e1);
}
#define ARGUMENT(N) phoenix::actor >
#define ACTOR_COMPOSITE(O,L,R) \
phoenix::actor::type>
#define LOWER_BOUND_OPERATOR(op, eval, param) \
template \
expression \
operator op (const param& left, const index &i) { \
return make_expression(left, undefined()); \
}
#define UPPER_BOUND_OPERATOR_INDEX(op, eval, param) \
template \
expression \
operator op (const index &i, const param& e) { \
return make_expression(undefined(), \
(ARGUMENT(N)() op e)); \
}
#define UPPER_BOUND_OPERATOR_EXPRESSION(op, eval) \
template \
expression \
operator op (const expression &left, \
const T& right) { \
return make_expression(left, (ARGUMENT(N)() op right)); \
}
#define UPPER_BOUND_OPERATOR(op, eval) \
UPPER_BOUND_OPERATOR_INDEX(op, eval, T) \
UPPER_BOUND_OPERATOR_INDEX(op, eval, phoenix::actor) \
UPPER_BOUND_OPERATOR_EXPRESSION(op, eval)
LOWER_BOUND_OPERATOR( < , phoenix::less_eval, T)
LOWER_BOUND_OPERATOR( < , phoenix::less_eval, phoenix::actor)
LOWER_BOUND_OPERATOR( <= , phoenix::less_equal_eval, T)
LOWER_BOUND_OPERATOR( <= , phoenix::less_equal_eval, phoenix::actor)
UPPER_BOUND_OPERATOR( < , phoenix::less_eval)
UPPER_BOUND_OPERATOR( <= , phoenix::less_equal_eval)
}
}
namespace index {
using namespace boost::phoenix;
boost::phoenix::actor > const i;
boost::phoenix::actor > const j;
boost::phoenix::actor > const k;
boost::phoenix::actor > const l;
template
range_::detail::index range(const boost::phoenix::actor<
boost::phoenix::argument >&) {
return range_::detail::index();
}
template
range_::detail::index range(const boost::phoenix::actor<
boost::phoenix::argument >&,
const F &f) {
// return range_::detail::index();
throw std::exception("not implemented");
}
}
int main(){
using namespace index;
// formula domain language rough prototype
// stuff in brackets can be any valid phoenix lambda expression
// physicist notation, lower bound may be implicit
(range(i) <= j, 3 <= range(j) < 4)[std::cout << i << " " << j << std::endl];
// implicit physicist notation, not done yet
//(range(i) < range(j) < 4)[...]
// programmer notation, same as above , but order is reversed
(3 <= range(j) < 4)(range(i) <= j)[std::cout << i << " " << j << std::endl];
// ignore, some early prototype for lambda tensor
// size_t N = 4;
// tensor::tensor<4> T(N,N,N,N);
// tensor::function > T_(T);
// (range(j) < 4)(range(i) <= j)[std::cout << T_(i,j,0,0)];
// (range(i) < j, range(j) < N)[T_(i,j,0,0) = T_(j,i,0,0)];
// sum(j < val(N))[T_(i,j,0,0)];
}