/* * Function.h * * Created on: Jun 12, 2010 * Author: Peter Goodman * Version: $Id$ */ #ifndef FUNCTION_H_ #define FUNCTION_H_ #include #include "Null.h" namespace tdop { /// forward declaration template class VariadicFunction; /// main function, this is what we use to access the function in a dynamic /// way. template class Function { protected: size_t num_seen_args; const size_t num_args; /// don't allow this type of function to be constructed on its own Function(const size_t na) : num_seen_args(0), num_args(na) { } virtual void curryImpl(const size_t curr_arg, void *val_ptr) { (void) curr_arg; (void) val_ptr; } public: virtual T0 apply(void) = 0; /// main curry method, add in an argument template void curry(T var) { assert(num_args > num_seen_args); this->curryImpl(num_seen_args++, reinterpret_cast(&var)); } /// clear out the stored info void clear(void) { num_seen_args = 0; } virtual Function *copy(void) const { return 0; } }; /// base variadic function template class VariadicFunction : public Function { }; /// 0-argument variadic function template class VariadicFunction : public Function { typedef T0 (FuncT)(void); typedef VariadicFunction SelfT; private: FuncT *func_ptr; public: VariadicFunction(FuncT *func) : Function(0), func_ptr(func) { } virtual T0 apply(void) { this->num_seen_args = 0; return func_ptr(); } virtual Function *copy(void) const { return new SelfT(func_ptr); } protected: virtual void curryImpl(const size_t, void *) { assert(false); } }; /// 1-argument variadic function template class VariadicFunction : public Function { typedef T1 (FuncT)(T0); typedef VariadicFunction SelfT; private: T0 a0; FuncT *func_ptr; public: VariadicFunction(FuncT *func) : Function(1), func_ptr(func) { } virtual T1 apply(void) { assert(this->num_args == this->num_seen_args); return func_ptr(a0); } virtual Function *copy(void) const { SelfT *ptr(new SelfT(func_ptr)); ptr->a0 = a0; return ptr; } protected: virtual void curryImpl(const size_t curr_arg, void *val_ptr) { switch(curr_arg) { case 0: a0 = *(reinterpret_cast(val_ptr)); break; default: assert(false); } } }; /// 2-argument variadic function template class VariadicFunction : public Function { typedef T2 (FuncT)(T0, T1); typedef VariadicFunction SelfT; private: T0 a0; T1 a1; FuncT *func_ptr; public: VariadicFunction(FuncT *func) : Function(2), func_ptr(func) { } virtual T2 apply(void) { assert(this->num_args == this->num_seen_args); return func_ptr(a0, a1); } virtual Function *copy(void) const { SelfT *ptr(new SelfT(func_ptr)); ptr->a0 = a0; ptr->a1 = a1; return ptr; } protected: virtual void curryImpl(const size_t curr_arg, void *val_ptr) { switch(curr_arg) { case 0: a0 = *(reinterpret_cast(val_ptr)); break; case 1: a1 = *(reinterpret_cast(val_ptr)); break; default: assert(false); } } }; /// 3-argument variadic function template class VariadicFunction : public Function { typedef T3 (FuncT)(T0, T1, T2); typedef VariadicFunction SelfT; private: T0 a0; T1 a1; T2 a2; FuncT *func_ptr; public: VariadicFunction(FuncT *func) : Function(3), func_ptr(func) { } virtual T3 apply(void) { assert(this->num_args == this->num_seen_args); return func_ptr(a0, a2, a2); } virtual Function *copy(void) const { SelfT *ptr(new SelfT(func_ptr)); ptr->a0 = a0; ptr->a1 = a1; ptr->a2 = a2; return ptr; } protected: virtual void curryImpl(const size_t curr_arg, void *val_ptr) { switch(curr_arg) { case 0: a0 = *(reinterpret_cast(val_ptr)); break; case 1: a1 = *(reinterpret_cast(val_ptr)); break; case 2: a2 = *(reinterpret_cast(val_ptr)); break; default: assert(false); } } }; } #endif /* FUNCTION_H_ */