my prototype (still needs lots of work obviously, and comments)
// #include "tensor/tensor.hpp"
// #include "typename.hpp"
#include <boost/spirit/home/phoenix/core/argument.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#define BOOST_FUSION_INVOKE_FUNCTION_OBJECT_MAX_ARITY PHOENIX_ARG_LIMIT
#include <boost/fusion/functional/invocation/limits.hpp>
#include <boost/fusion/functional.hpp>
#include <boost/fusion/include/intrinsic.hpp>
#include <boost/fusion/include/vector.hpp>
#include <boost/fusion/include/algorithm.hpp>
#include <boost/fusion/include/vector_tie.hpp>
#include <boost/fusion/include/make_vector.hpp>
#include <boost/typeof/typeof.hpp>
namespace range_ {
namespace detail {
namespace phoenix = boost::phoenix;
namespace fusion = boost::fusion;
/// undefined or implicit object
struct undefined {};
template<int N>
struct index {
// index(boost::phoenix::argument<N>) {}
typedef phoenix::actor<phoenix::argument<N> > argument;
argument arg() const { return argument(); }
};
template<typename T, typename U = void>
struct functional {
typedef phoenix::actor<phoenix::value<T> > type;
static type form(const T& t) { return type(t); }
};
template<typename T, typename U>
struct functional<phoenix::actor<T>, U> {
typedef phoenix::actor<T> type;
static type form(const T& t) { return type(t); }
};
template<typename T>
struct functional<undefined,T> {
typedef typename functional<T>::type type;
static type form(const undefined&) { return type(T()); }
};
template<int N, class L, class U, class T = undefined>
struct expression;
template<int N, class L, class U, class C>
struct expression {
typedef functional<L,U> lower_function;
typedef functional<U,L> upper_function;
expression(const L &lower, const U& upper, const C &cdr)
: lower_(lower), upper_(upper), cdr_(cdr) {}
template<class E>
expression<N, L, U, E> operator()(const E &c) const {
return expression<N, L, U, E>(lower_, upper_, c);
}
template<class F>
void operator[](const F &f) const {
#define TEXT(z, n, text) text
#define UNDEFINED_ARGUMENTS BOOST_PP_ENUM(PHOENIX_ARG_LIMIT, TEXT, undefined())
evaluate<int>(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 T>
typename functional<L,T>::type begin() const {
return functional<L,T>::form(lower_);
}
template<typename T>
typename functional<U,T>::type end() const {
return functional<U,T>::form(upper_);
}
template<typename T, class F, class A>
void evaluate(const F &f, const A &arguments) const {
T i = this->begin<T>()(arguments);
#define AS_VECTOR(var, expr) BOOST_AUTO(var, fusion::as_vector(expr))
#define ADVANCE_C(seq) fusion::advance_c<N>(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<T>(), a)) {
this->apply<T>(cdr_, f, a);
++i;
}
}
template<typename T, class E, class F, class V>
void apply(const E &e, const F &f, const V &variables) const {
e.template evaluate<T>(f, variables);
}
template<typename T, class F, class V>
void apply(const undefined&, const F &f, const V &variables) const {
fusion::invoke_function_object(f, fusion::as_vector(variables));
}
};
template<int N, class L, class U>
expression<N, L, U>
make_expression(const L &lower, const U& upper) {
return expression<N, L, U>(lower, upper, undefined());
}
template<int N, class L, class U>
expression<N, L, U>
make_expression(const expression<N, L, undefined> &expr, const U& right) {
return expression<N, L, U>(expr.left(), right, undefined());
}
template<int N1, class L1, class U1, class T1,
int N2, class L2, class U2>
expression<N2, L2, U2, expression<N1, L1, U1, T1> >
operator,(const expression<N1, L1, U1, T1> &e1,
const expression<N2, L2, U2> &e2) {
return e2(e1);
}
#define ARGUMENT(N) phoenix::actor<phoenix::argument<N> >
#define ACTOR_COMPOSITE(O,L,R) \
phoenix::actor<typename phoenix::as_composite<O, L, R>::type>
#define LOWER_BOUND_OPERATOR(op, eval, param) \
template <typename T, int N> \
expression<N, param, undefined> \
operator op (const param& left, const index<N> &i) { \
return make_expression<N>(left, undefined()); \
}
#define UPPER_BOUND_OPERATOR_INDEX(op, eval, param) \
template <typename T, int N> \
expression<N, undefined, \
ACTOR_COMPOSITE(eval, ARGUMENT(N), param)> \
operator op (const index<N> &i, const param& e) { \
return make_expression<N>(undefined(), \
(ARGUMENT(N)() op e)); \
}
#define UPPER_BOUND_OPERATOR_EXPRESSION(op, eval) \
template <typename T, int N, class E> \
expression<N, E, ACTOR_COMPOSITE(eval, ARGUMENT(N), T)> \
operator op (const expression<N, E, undefined> &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<T>) \
UPPER_BOUND_OPERATOR_EXPRESSION(op, eval)
LOWER_BOUND_OPERATOR( < , phoenix::less_eval, T)
LOWER_BOUND_OPERATOR( < , phoenix::less_eval, phoenix::actor<T>)
LOWER_BOUND_OPERATOR( <= , phoenix::less_equal_eval, T)
LOWER_BOUND_OPERATOR( <= , phoenix::less_equal_eval, phoenix::actor<T>)
UPPER_BOUND_OPERATOR( < , phoenix::less_eval)
UPPER_BOUND_OPERATOR( <= , phoenix::less_equal_eval)
}
}
namespace index {
using namespace boost::phoenix;
boost::phoenix::actor<boost::phoenix::argument<0> > const i;
boost::phoenix::actor<boost::phoenix::argument<1> > const j;
boost::phoenix::actor<boost::phoenix::argument<2> > const k;
boost::phoenix::actor<boost::phoenix::argument<3> > const l;
template<int N>
range_::detail::index<N> range(const boost::phoenix::actor<
boost::phoenix::argument<N> >&) {
return range_::detail::index<N>();
}
template<int N, class F>
range_::detail::index<N> range(const boost::phoenix::actor<
boost::phoenix::argument<N> >&,
const F &f) {
// return range_::detail::index<N>();
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<tensor::tensor<4> > 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)];
}