diff --git a/src/proc/control/argument-erasure.hpp b/src/proc/control/argument-erasure.hpp index 003a38391..fc825024d 100644 --- a/src/proc/control/argument-erasure.hpp +++ b/src/proc/control/argument-erasure.hpp @@ -1,5 +1,5 @@ /* - ARGUMENT-TUPLE-ACCEPT.hpp - helper template providing a bind(...) member function + ARGUMENT-ERASURE.hpp - helper for passing on a dynamic typed argument tuple Copyright (C) Lumiera.org 2009, Hermann Vosseler @@ -21,478 +21,31 @@ */ -/** @file argument-tuple-accept.hpp - ** The AcceptArgumentBinding template allows to mix in a \c bind(...) function. - ** Thereby, the correct number and types of arguments is derived according to - ** the function signature given as template parameter. This helper template is - ** used for the ArgumentHolder and generally for binding the arguments when - ** defining Proc-Layer commands. - ** - ** @see CommandDef - ** @see ArgumentHolder - ** @see argument-tuple-accept-test.cpp - ** - */ +#ifndef CONTROL_ARGUMENT_ERASURE_H +#define CONTROL_ARGUMENT_ERASURE_H - -#ifndef CONTROL_ARGUMENT_TUPLE_ACCEPT_H -#define CONTROL_ARGUMENT_TUPLE_ACCEPT_H - -#include "lib/meta/typelist.hpp" -#include "lib/meta/function.hpp" -#include "lib/meta/tuple.hpp" +#include "lib/error.hpp" namespace control { - namespace bind_arg { // internals.... - - using namespace lumiera::typelist; - - - /** @internal mix in a function operator */ - template< class TAR, class BA, class RET - , typename TYPES - > - struct AcceptArgs ; - - - /* specialisations for 0...9 Arguments.... */ - - template< class TAR, class BA, class RET - > //____________________________________ - struct AcceptArgs > ///< Accept dummy binding (0 Arguments) - : BA - { - RET - operator() () - { - return static_cast (this) -> bindArg (tuple::makeNullTuple() ); - } - }; - - - template< class TAR, class BA, class RET - , typename T1 - > //_______________________________ - struct AcceptArgs > ///< Accept binding for 1 Argument - : BA - { - RET - operator() (T1 a1) - { - return static_cast (this) -> bindArg (tuple::make (a1)); - } - }; - - - template< class TAR, class BA, class RET - , typename T1 - , typename T2 - > //________________________________ - struct AcceptArgs > ///< Accept binding for 2 Arguments - : BA - { - RET - operator() (T1 a1, T2 a2) - { - return static_cast (this) -> bindArg (tuple::make (a1,a2)); - } - }; - - - template< class TAR, class BA, class RET - , typename T1 - , typename T2 - , typename T3 - > //________________________________ - struct AcceptArgs > ///< Accept binding for 3 Arguments - : BA - { - RET - operator() (T1 a1, T2 a2, T3 a3) - { - return static_cast (this) -> bindArg (tuple::make (a1,a2,a3)); - } - }; - - - template< class TAR, class BA, class RET - , typename T1 - , typename T2 - , typename T3 - , typename T4 - > //________________________________ - struct AcceptArgs > ///< Accept binding for 4 Arguments - : BA - { - RET - operator() (T1 a1, T2 a2, T3 a3, T4 a4) - { - return static_cast (this) -> bindArg (tuple::make (a1,a2,a3,a4)); - } - }; - - - template< class TAR, class BA, class RET - , typename T1 - , typename T2 - , typename T3 - , typename T4 - , typename T5 - > //________________________________ - struct AcceptArgs > ///< Accept binding for 5 Arguments - : BA - { - RET - operator() (T1 a1, T2 a2, T3 a3, T4 a4, T5 a5) - { - return static_cast (this) -> bindArg (tuple::make (a1,a2,a3,a4,a5)); - } - }; - - - template< class TAR, class BA, class RET - , typename T1 - , typename T2 - , typename T3 - , typename T4 - , typename T5 - , typename T6 - > //________________________________ - struct AcceptArgs > ///< Accept binding for 6 Arguments - : BA - { - RET - operator() (T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6) - { - return static_cast (this) -> bindArg (tuple::make (a1,a2,a3,a4,a5,a6)); - } - }; - - - template< class TAR, class BA, class RET - , typename T1 - , typename T2 - , typename T3 - , typename T4 - , typename T5 - , typename T6 - , typename T7 - > //________________________________ - struct AcceptArgs > ///< Accept binding for 7 Arguments - : BA - { - RET - operator() (T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7) - { - return static_cast (this) -> bindArg (tuple::make (a1,a2,a3,a4,a5,a6,a7)); - } - }; - - - template< class TAR, class BA, class RET - , typename T1 - , typename T2 - , typename T3 - , typename T4 - , typename T5 - , typename T6 - , typename T7 - , typename T8 - > //________________________________ - struct AcceptArgs > ///< Accept binding for 8 Arguments - : BA - { - RET - operator() (T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8) - { - return static_cast (this) -> bindArg (tuple::make (a1,a2,a3,a4,a5,a6,a7,a8)); - } - }; - - - template< class TAR, class BA, class RET - , typename T1 - , typename T2 - , typename T3 - , typename T4 - , typename T5 - , typename T6 - , typename T7 - , typename T8 - , typename T9 - > //________________________________ - struct AcceptArgs > ///< Accept binding for 9 Arguments - : BA - { - RET - operator() (T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, T9 a9) - { - return static_cast (this) -> bindArg (tuple::make (a1,a2,a3,a4,a5,a6,a7,a8,a9)); - } - }; - - - - /** @internal mix in a \c bind() function - */ - template< class TAR, class BA, class RET - , typename TYPES - > - struct AcceptBind ; - - - /* specialisations for 0...9 Arguments.... */ - - template< class TAR, class BA, class RET - > //____________________________________ - struct AcceptBind > ///< Accept dummy binding (0 Arguments) - : BA - { - RET - bind () - { - return static_cast (this) -> bindArg (tuple::makeNullTuple() ); - } - }; - - - template< class TAR, class BA, class RET - , typename T1 - > //_______________________________ - struct AcceptBind > ///< Accept binding for 1 Argument - : BA - { - RET - bind (T1 a1) - { - return static_cast (this) -> bindArg (tuple::make (a1)); - } - }; - - - template< class TAR, class BA, class RET - , typename T1 - , typename T2 - > //________________________________ - struct AcceptBind > ///< Accept binding for 2 Arguments - : BA - { - RET - bind (T1 a1, T2 a2) - { - return static_cast (this) -> bindArg (tuple::make (a1,a2)); - } - }; - - - template< class TAR, class BA, class RET - , typename T1 - , typename T2 - , typename T3 - > //________________________________ - struct AcceptBind > ///< Accept binding for 3 Arguments - : BA - { - RET - bind (T1 a1, T2 a2, T3 a3) - { - return static_cast (this) -> bindArg (tuple::make (a1,a2,a3)); - } - }; - - - template< class TAR, class BA, class RET - , typename T1 - , typename T2 - , typename T3 - , typename T4 - > //________________________________ - struct AcceptBind > ///< Accept binding for 4 Arguments - : BA - { - RET - bind (T1 a1, T2 a2, T3 a3, T4 a4) - { - return static_cast (this) -> bindArg (tuple::make (a1,a2,a3,a4)); - } - }; - - - template< class TAR, class BA, class RET - , typename T1 - , typename T2 - , typename T3 - , typename T4 - , typename T5 - > //________________________________ - struct AcceptBind > ///< Accept binding for 5 Arguments - : BA - { - RET - bind (T1 a1, T2 a2, T3 a3, T4 a4, T5 a5) - { - return static_cast (this) -> bindArg (tuple::make (a1,a2,a3,a4,a5)); - } - }; - - - template< class TAR, class BA, class RET - , typename T1 - , typename T2 - , typename T3 - , typename T4 - , typename T5 - , typename T6 - > //________________________________ - struct AcceptBind > ///< Accept binding for 6 Arguments - : BA - { - RET - bind (T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6) - { - return static_cast (this) -> bindArg (tuple::make (a1,a2,a3,a4,a5,a6)); - } - }; - - - template< class TAR, class BA, class RET - , typename T1 - , typename T2 - , typename T3 - , typename T4 - , typename T5 - , typename T6 - , typename T7 - > //________________________________ - struct AcceptBind > ///< Accept binding for 7 Arguments - : BA - { - RET - bind (T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7) - { - return static_cast (this) -> bindArg (tuple::make (a1,a2,a3,a4,a5,a6,a7)); - } - }; - - - template< class TAR, class BA, class RET - , typename T1 - , typename T2 - , typename T3 - , typename T4 - , typename T5 - , typename T6 - , typename T7 - , typename T8 - > //________________________________ - struct AcceptBind > ///< Accept binding for 8 Arguments - : BA - { - RET - bind (T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8) - { - return static_cast (this) -> bindArg (tuple::make (a1,a2,a3,a4,a5,a6,a7,a8)); - } - }; - - - template< class TAR, class BA, class RET - , typename T1 - , typename T2 - , typename T3 - , typename T4 - , typename T5 - , typename T6 - , typename T7 - , typename T8 - , typename T9 - > //________________________________ - struct AcceptBind > ///< Accept binding for 9 Arguments - : BA - { - RET - bind (T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, T9 a9) - { - return static_cast (this) -> bindArg (tuple::make (a1,a2,a3,a4,a5,a6,a7,a8,a9)); - } - }; - - - - template - struct _Type - { - typedef typename FunctionSignature< function >::Args Args; - typedef typename FunctionSignature< function >::Ret Ret; - typedef Tuple ArgTuple; - typedef SIG Sig; - }; - - template - struct _Type > - { - typedef TYPES Args; - typedef void Ret; - typedef Tuple ArgTuple; - typedef typename FunctionTypedef::Sig Sig; - }; - - struct Dummy {}; - - - } // (END) impl details (bind_arg) - /** Helper Template for building a Functor or function-like class: - * Mix in a function call operator, which mimics the specified signature SIG . - * This template is to be used as a base class to inherit the target type TAR from; - * this target type is assumed to provide a function \bindArg(Tuple) -- - * where \c TYPES... is the sequence of types found in the provided Signature SIG. - */ - template - class AcceptArgumentTuple - : public bind_arg::AcceptArgs::Ret - , typename bind_arg::_Type::Args> - { - }; - - - /** Helper Template for Proc-Layer control::Command : mix in a \c bind(...) function - * @param SIG function signature to mimic (regarding the arguments and return type) - * @param TAR the target class providing a function \c bindArg(Tuple >) - * @param BASE the base class for inheritance chaining - */ - template - class AcceptArgumentBinding - : public bind_arg::AcceptBind::Ret - , typename bind_arg::_Type::Args> - { - }; - - - /** Variation of AcceptArgumentBinding, allowing to control the return type - * of the generated \c bind(...) functions independently from SIG - */ - template - class AcceptArgumentBindingRet - : public bind_arg::AcceptBind::Args> - { - }; - - /** - * Adapter interface for invoking an argument binding (e.g. as defined through - * AcceptArgumentBinding) \em without the need to disclose the concrete type - * actually accepting the bind call. This is an application of "type erasure" + * Adapter interface for invoking an argument binding for a command + * \em without the need to disclose the concrete types and number of arguments. + * At the receiver side, the concrete type can be restored by a dynamic cast. + * This requires the receiver somehow to know the desired argument types; + * usually this receiver will be an implementation object, whose exact + * type has been erased after definition, while the implementation + * internally of course knows the type and thus can perform an + * dynamic cast on the passed on argument tuple */ struct Arguments; @@ -528,10 +81,8 @@ namespace control { { } }; - - - - + + } // namespace control #endif diff --git a/src/proc/control/argument-tuple-accept.hpp b/src/proc/control/argument-tuple-accept.hpp index 003a38391..8a7d2d2f7 100644 --- a/src/proc/control/argument-tuple-accept.hpp +++ b/src/proc/control/argument-tuple-accept.hpp @@ -489,49 +489,8 @@ namespace control { - /** - * Adapter interface for invoking an argument binding (e.g. as defined through - * AcceptArgumentBinding) \em without the need to disclose the concrete type - * actually accepting the bind call. This is an application of "type erasure" - */ - struct Arguments; - - template - struct TypedArguments; - struct Arguments - { - virtual ~Arguments() {} - - template - TUP const& - get () - { - TypedArguments* dest = dynamic_cast*> (this); - if (!dest) - throw lumiera::error::Invalid("Wrong type or number of arguments"); - - return dest->args_; - } - }; - - - template - struct TypedArguments - : Arguments - { - TUP const& args_; - - TypedArguments (TUP const& a) - : args_(a) - { } - }; - - - - - } // namespace control #endif diff --git a/src/proc/control/command-argument-holder.hpp b/src/proc/control/command-argument-holder.hpp index cdb3f2d73..189a8f84e 100644 --- a/src/proc/control/command-argument-holder.hpp +++ b/src/proc/control/command-argument-holder.hpp @@ -22,7 +22,7 @@ /** @file command-argument-holder.hpp - ** A passive container record holding the actual command arguments & UNDO state. + ** A passive container record holding the actual command arguments & UNDO state. ** While all command objects themselves have a common type (type erasure), ** the actual argument tuple and the state memento for UNDO can't. Especially, ** the size of arguments and memento will depend on their respective types. diff --git a/src/proc/control/command-binding.hpp b/src/proc/control/command-binding.hpp index 35b81b575..14532ecbb 100644 --- a/src/proc/control/command-binding.hpp +++ b/src/proc/control/command-binding.hpp @@ -43,21 +43,15 @@ #ifndef CONTROL_COMMAND_BINDING_H #define CONTROL_COMMAND_BINDING_H -//#include "pre.hpp" -//#include "include/symbol.hpp" #include "lib/meta/typelist.hpp" #include "lib/meta/tuple.hpp" -//#include - namespace control { namespace com { ///< Proc-Layer command implementation details -// using lumiera::Symbol; -// using std::tr1::shared_ptr; using namespace lumiera::typelist; @@ -65,7 +59,12 @@ namespace com { ///< Proc-Layer command implementation details /** - * @todo Type-comment + * Building block for commands, allowing to mix in + * a set of \c bind(...) function for up to nine arbitrary arguments. + * All these functions will package the argument values into a Tuple + * (record) and forward the call to a \c bindArg(Tuple) function + * on the target class. The latter function is asumed to perform a + * run-time check to detect calls with invalid signature. */ template class ArgumentBinder @@ -203,10 +202,8 @@ namespace com { ///< Proc-Layer command implementation details } }; - ////////////////TODO currently just fleshing out the API.... - - + }} // namespace control::com diff --git a/src/proc/control/command-closure.hpp b/src/proc/control/command-closure.hpp index d0e2cf247..fc3e70d0f 100644 --- a/src/proc/control/command-closure.hpp +++ b/src/proc/control/command-closure.hpp @@ -23,6 +23,17 @@ /** @file command-closure.hpp ** A closure enabling self-contained execution of commands within the ProcDispatcher. + ** After defining a proc-layer command, at some point the function arguments + ** of the contained operation are "closed" by storing concrete argument values. + ** These values will later on be fed to the operation when the command is invoked. + ** + ** Most of the command machinery accesses this function closure through the interface + ** CmdClosure, while, when defining a command, subclasses typed to the specific + ** function arguments are created. Especially, there is an ArgumentHolder template, + ** which is used to define the storage for the concrete arguments. This ArgumentHolder + ** internally contains an Closure instance (where SIG is the signature of the + ** actual command operation function), which implements the invocation of the + ** operation function with the stored argument tuple. ** //TODO ** ** @see Command @@ -44,7 +55,7 @@ #include "lib/meta/tuple.hpp" #include "lib/format.hpp" #include "lib/util.hpp" -#include "proc/control/argument-tuple-accept.hpp" ////TODO better factor out struct TypedArguments +#include "proc/control/argument-erasure.hpp" #include "proc/control/typed-allocation-manager.hpp" #include @@ -54,17 +65,10 @@ #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 lumiera::typelist::FunctionSignature; using lumiera::typelist::Tuple; using lumiera::typelist::BuildTupleAccessor; @@ -72,9 +76,8 @@ namespace control { using lumiera::typelist::FunErasure; using lumiera::typelist::StoreFunction; using lumiera::typelist::NullType; - + using util::unConst; - using std::tr1::function; using std::ostream; using std::string; @@ -118,6 +121,7 @@ namespace control { + /** Helper for accessing an individual function parameter */ template < typename TY , class BASE @@ -260,9 +264,7 @@ namespace control { friend bool operator== (Closure const& c1, Closure const& c2) { return compare (c1.params_, c2.params_); } friend bool operator!= (Closure const& c1, Closure const& c2) { return ! (c1 == c2); } }; - - - ////////////////TODO currently just fleshing out the API.... + diff --git a/src/proc/control/command-def.hpp b/src/proc/control/command-def.hpp index 3d952fe80..16b494102 100644 --- a/src/proc/control/command-def.hpp +++ b/src/proc/control/command-def.hpp @@ -28,7 +28,7 @@ ** \em defining the concrete operations to be encapsulated into a command. To ** create a command, you need to provide three functors (for the actual operation, ** the undo operation and for capturing undo state prior to invoking the operation). - ** Besides, you provide a \em binding, thus creating a closue out of these three + ** Besides, you provide a \em binding, thus creating a closure out of these three ** function objects and a set of actual parameters. This closure effectively is ** the command, which in a last step can be either dispatched, stored or ** invoked immediately. @@ -49,6 +49,7 @@ //#include "pre.hpp" #include "lib/error.hpp" +#include "include/logging.h" #include "include/symbol.hpp" #include "proc/control/command.hpp" #include "proc/control/command-impl.hpp" /////TODO: any chance to get rid of this import here?? @@ -57,11 +58,12 @@ #include "proc/control/command-mutation.hpp" #include "proc/control/command-closure.hpp" #include "proc/control/argument-tuple-accept.hpp" +#include "lib/bool-checkable.hpp" #include "lib/meta/function.hpp" #include "lib/meta/typelist.hpp" #include "lib/meta/typelist-util.hpp" #include "lib/meta/tuple.hpp" -#include "lib/bool-checkable.hpp" +#include "lib/util.hpp" #include #include @@ -71,9 +73,10 @@ namespace control { - using lumiera::Symbol; using std::tr1::shared_ptr; using std::tr1::function; + using lumiera::Symbol; + using util::cStr; using lumiera::typelist::FunctionSignature; using lumiera::typelist::FunctionTypedef; @@ -82,7 +85,7 @@ namespace control { using lumiera::typelist::Tuple; - namespace stage { ///< helpers for the building up a command definition + namespace stage { ///< helpers for building up a command definition @@ -99,7 +102,7 @@ namespace control { CompletedDefinition (Command& definedCommand) : prototype_(definedCommand) { - + TRACE (command_dbg, "Completed definition of %s.", cStr(prototype_)); } typedef HandlingPattern::ID PattID; @@ -144,9 +147,7 @@ namespace control { , operFunctor_(commandOperation) , captFunctor_(undoCapOperation) , undoFunctor_() - { - cout << showSizeof(undoCapOperation) << endl; - } + { } CompletedDefinition @@ -182,8 +183,8 @@ namespace control { - - + + template struct BasicDefinition { @@ -238,7 +239,9 @@ namespace control { CommandDef (Symbol cmdID) : id_(cmdID) , prototype_(Command::fetchDef(cmdID)) - { } + { + TRACE (command_dbg, "starting CommandDef('%s')...", cmdID); + } template stage::BasicDefinition @@ -252,7 +255,6 @@ namespace control { bool isValid() const; }; - ////////////////TODO currently just fleshing out the API.... diff --git a/src/proc/control/command-mutation.hpp b/src/proc/control/command-mutation.hpp index 92a5c876b..bfc5b66af 100644 --- a/src/proc/control/command-mutation.hpp +++ b/src/proc/control/command-mutation.hpp @@ -22,7 +22,7 @@ /** @file command-mutation.hpp - ** Core of a Proc-Layer command: functor containing the actual operation to be executed. + ** Core of a Proc-Layer command: functor containing the operation to be executed. ** Each command holds two of these functors: one representing the actual operation ** and one to undo the effect of this operation. The latter involves the capturing ** and storing of a "memento" value behind the scenes. But towards Command, the @@ -34,7 +34,7 @@ ** Mutation objects are to be created based on a concrete function object, which then ** gets embedded into a type erasure container, thus disposing the specific type information. ** Moreover, building on this lib::OpaqueHolder yields a fixed size storage for Mutation objects, - ** allowing them to be embedded immediately within the Command instance. + ** allowing them to be embedded immediately within the CommandImpl frame. ** ** Later on, any command needs to be made ready for execution by binding it to a specific ** execution environment, which especially includes the target objects to be mutated by the diff --git a/src/proc/control/command-registry.hpp b/src/proc/control/command-registry.hpp index fba0ad032..9dd5206a9 100644 --- a/src/proc/control/command-registry.hpp +++ b/src/proc/control/command-registry.hpp @@ -80,7 +80,7 @@ namespace control { /** register a command (Frontend) under the given ID * @return either the new command, or an already existing - * command registered under the given ID*/ + * command registered under the given ID */ Command track (Symbol cmdID, Command const& commandHandle) { diff --git a/src/proc/control/command.cpp b/src/proc/control/command.cpp index eca322e58..ec3303063 100644 --- a/src/proc/control/command.cpp +++ b/src/proc/control/command.cpp @@ -22,7 +22,16 @@ /** @file command.cpp - ** //TODO + ** Implementation of the command frontend. + ** Within this file, the implementation level of the command frontend + ** is linked to the implementation of the command registry. Client code + ** is shielded from those implementation classes and need only include + ** command.hpp + ** + ** More specifically, the actual number and type of arguments and the + ** concrete functions implementing the command operation are known only + ** at the time of the command definition; this detailed type information + ** is erased afterwards, allowing client code to use a simple frontend. ** ** @see command.hpp ** @see command-registry.hpp @@ -38,9 +47,6 @@ #include "proc/control/command-impl.hpp" #include "proc/control/command-registry.hpp" #include "proc/control/handling-pattern.hpp" -//#include "proc/mobject/mobject-ref.hpp" -//#include "proc/mobject/mobject.hpp" -//#include "proc/mobject/placement.hpp" #include #include @@ -68,11 +74,11 @@ namespace control { lumiera::Singleton CommandRegistry::instance; - + Command::~Command() { } - + /** */ Command Command::get (Symbol cmdID) @@ -248,7 +254,7 @@ namespace control { return repr.str(); } - + @@ -295,7 +301,7 @@ namespace control { { return impl().setHandlingPattern(pattID); } - + diff --git a/src/proc/control/command.hpp b/src/proc/control/command.hpp index 642e8cbbe..18f4ca36e 100644 --- a/src/proc/control/command.hpp +++ b/src/proc/control/command.hpp @@ -22,8 +22,26 @@ /** @file command.hpp - ** //TODO - ** + ** Proc-Layer command frontend. + ** A \b command is a functor, which can be invoked according to a pre-defined HandlingPattern. + ** Most notably, command invocation can be scheduled and logged with the serialiser, and the effect + ** of any command invocation can be \em undone later on by invoking the "undo operation" defined + ** alongside with the command's operation. The command operation is defined through a C/C++ function + ** and may receive an arbitrary number and type of arguments. After setting up such a CommandDef , + ** it can be referred for use through a symbolic ID. Before being able to invoke the command, concrete + ** function arguments need to be provided (this is called "binding" or "closing the function arguments"). + ** These function arguments are stored within the command definition and remain opaque to the client code + ** actually invoking the command. Behind the scenes, there is a CommandRegistry, holding an index of the + ** registered commands and managing the storage for command definitions and arguments. The actual + ** Command object used by client code is a small, copyable and ref-counting handle to this + ** stored definition backend. + ** + ** //TODO maybe summarise how UNDO works? + ** + ** @see command-def.hpp + ** @see command-use1-test.cpp + ** @see command-use2-test.cpp + ** @see command-use3-test.cpp ** @see ProcDispatcher ** @see Session ** @@ -35,15 +53,15 @@ #define CONTROL_COMMAND_H #include "pre.hpp" +#include "lib/error.hpp" #include "include/symbol.hpp" #include "proc/control/command-binding.hpp" -#include "proc/control/command-mutation.hpp" /////TODO: do we need to expose this here? -#include "proc/control/command-closure.hpp" +#include "proc/control/argument-erasure.hpp" #include "proc/control/handling-pattern.hpp" #include "lib/bool-checkable.hpp" +#include "lib/meta/tuple.hpp" #include "lib/handle.hpp" -//#include #include ///////////////////////////////////////////TODO: define an C-API representation here, make the header multilingual! @@ -55,14 +73,16 @@ namespace control { using std::string; using lumiera::Symbol; using std::tr1::shared_ptr; + using lumiera::typelist::Tuple; + LUMIERA_ERROR_DECLARE (UNBOUND_ARGUMENTS); ///< Command functor not yet usable, because arguments aren't bound LUMIERA_ERROR_DECLARE (INVALID_COMMAND); ///< Unknown or insufficiently defined command LUMIERA_ERROR_DECLARE (DUPLICATE_COMMAND); ///< Attempt to redefine an already existing command definition LUMIERA_ERROR_DECLARE (INVALID_ARGUMENTS); ///< Arguments provided for binding doesn't match stored command function parameters - - + + typedef void* FuncPtr; class CommandDef; @@ -70,12 +90,23 @@ namespace control { /** - * @todo Type-comment + * Handle object representing a single Command instance to be used by client code. + * Commands are accessed \link #get through a symbolic ID \endlink; there need to be + * a CommandDef somewhere to specify the actual operation and to define, how the + * effect of the command can be undone. Moreover, the command's definition + * refers to a HandlingPattern, which describes how the command is actually + * to be executed (the default is to schedule it within the ProcDispatcher) + * + * Client code usually just + * - creates a command instance by referring to a command ID + * - maybe binds to concrete arguments (e.g. a target object) + * - triggers command execution through operator() + * - maybe checks the return value for errors */ class Command : public com::ArgumentBinder // actually implemented as ref counting Handle - > + > // { typedef lib::Handle _Handle; @@ -177,7 +208,7 @@ namespace control { return ! (c1 == c2); } - + } // namespace control diff --git a/src/proc/control/handling-patterns.hpp b/src/proc/control/handling-patterns.hpp index 7b3d94d2b..b692aafae 100644 --- a/src/proc/control/handling-patterns.hpp +++ b/src/proc/control/handling-patterns.hpp @@ -146,7 +146,7 @@ namespace control { /** access the singleton instance for a given ID */ HandlingPattern const& - getPatternInstance (HandlingPattern::ID id) + getPatternInstance (size_t id) { REQUIRE (id < patternTable.size()); return patternTable[id] ();