/* COMMAND-CLOSURE.hpp - defining execution targets and parameters for commands Copyright (C) Lumiera.org 2009, Hermann Vosseler This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /** @file command-closure.hpp ** A closure enabling self-contained execution of commands within the ProcDispatcher. ** //TODO ** ** @see Command ** @see ProcDispatcher ** */ #ifndef CONTROL_COMMAND_CLOSURE_H #define CONTROL_COMMAND_CLOSURE_H //#include "pre.hpp" #include "lib/meta/typelist.hpp" #include "lib/meta/function.hpp" #include "lib/meta/function-closure.hpp" #include "lib/meta/function-erasure.hpp" #include "lib/meta/tuple.hpp" #include "lib/util.hpp" #include #include #include #include #include "lib/test/test-helper.hpp" /////////////////TODO remove this using lib::test::showSizeof; using std::cout; //////////////////////////////////TODO remove this using std::endl; namespace control { // using lumiera::Symbol; // using std::tr1::shared_ptr; using util::unConst; using std::string; using std::ostream; using std::tr1::function; using lumiera::typelist::FunctionSignature; using lumiera::typelist::Tuple; using lumiera::typelist::BuildTupleAccessor; using lumiera::typelist::TupleApplicator; using lumiera::typelist::FunErasure; using lumiera::typelist::StoreFunction; using lumiera::typelist::NullType; /** * A neutral container internally holding * the functor used to implement the Command */ typedef FunErasure CmdFunctor; class CmdClosure; typedef std::tr1::shared_ptr PClosure; ///< smart-ptr type used for handling concrete closures /** Interface */ class CmdClosure { public: virtual ~CmdClosure() {} virtual PClosure clone() const =0; virtual operator string() const =0; virtual CmdFunctor bindArguments (CmdFunctor&) =0; }; inline ostream& operator<< (ostream& os, const CmdClosure& clo) { return os << string(clo); } template < typename TY , class BASE , class TUP , uint idx > class ParamAccessor : public BASE { TY & element() { return BASE::template getAt(); } TY const& element() const { return unConst(this)->template getAt(); } public: ParamAccessor(TUP const& tuple) : BASE(tuple) { cout << showSizeof(element()) << endl; //////////TODO remove this test code } string dump (string const& prefix = "(") const { return BASE::dump (prefix+element()+","); } ////////////////////TODO the real access operations (e.g. for serialising) go here }; template class ParamAccessor : public TUP { public: ParamAccessor(TUP const& tuple) : TUP(tuple) { } ////////////////////TODO the recursion-end of the access operations goes here string dump (string const& prefix ="(") const { if (1 < prefix.length()) // remove trailing comma... return prefix.substr (0, prefix.length()-1) +")"; else return prefix+")"; } }; template class Closure : public CmdClosure { typedef typename FunctionSignature< function >::Args Args; typedef Tuple ArgTuple; typedef BuildTupleAccessor BuildAccessor; typedef typename BuildAccessor::Accessor ParamStorageTuple; ParamStorageTuple params_; public: Closure (ArgTuple const& args) : params_(BuildAccessor(args)) { } /** Core operation: use the embedded argument tuple * to close a given functor over its arguments. * @param unboundFunctor an function object, whose * function arguments are required to match * the types of the embedded ParamStorageTuple * @return new functor object containing the function, * which is created by binding all arguments of the * input functor. * @note ASSERTION failure if the function signature * doesn't match the argument types tuple. * @note when finally invoked, the functor, which is * bound here to the argument tuple, might actually * \em modify the param values. Thus this function * can't be const. */ CmdFunctor bindArguments (CmdFunctor& unboundFunctor) { return CmdFunctor (TupleApplicator (params_) .bind ( unboundFunctor.getFun()) ); } /** create a clone copy of this concrete closure, * hidden behind the generic CmdClosure interface * and owned by a shared_ptr PClo. */ PClosure clone() const { return PClosure (new Closure (this->params_)); } operator string() const { UNIMPLEMENTED ("how to do a string conversion on the variable argument tuple??"); } }; /** * Special kind of Closure, which \em decorates an existing Closure * and provides a captured state memento as additional parameter on invocation. * * @todo concept isn't clear yet. Multiple MementoClosurese are to decorate a single Closure; * they have to match and extract the concrete type of the Closure and the provided Memento, * but the latter needs to be erased immediately. Basically, MementoClosure must be able * to stand-in for an simple parameter closure. */ class MementoClosure : public CmdClosure { }; ////////////////TODO currently just fleshing out the API.... } // namespace control #endif