command frontend sort-of written now, pending integration test
This commit is contained in:
parent
5988b1d697
commit
b9763b6c16
11 changed files with 110 additions and 562 deletions
|
|
@ -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 <Ichthyostega@web.de>
|
||||
|
|
@ -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<TAR,BA,RET, Types<> > ///< Accept dummy binding (0 Arguments)
|
||||
: BA
|
||||
{
|
||||
RET
|
||||
operator() ()
|
||||
{
|
||||
return static_cast<TAR*> (this) -> bindArg (tuple::makeNullTuple() );
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template< class TAR, class BA, class RET
|
||||
, typename T1
|
||||
> //_______________________________
|
||||
struct AcceptArgs<TAR,BA,RET, Types<T1> > ///< Accept binding for 1 Argument
|
||||
: BA
|
||||
{
|
||||
RET
|
||||
operator() (T1 a1)
|
||||
{
|
||||
return static_cast<TAR*> (this) -> bindArg (tuple::make (a1));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template< class TAR, class BA, class RET
|
||||
, typename T1
|
||||
, typename T2
|
||||
> //________________________________
|
||||
struct AcceptArgs<TAR,BA,RET, Types<T1,T2> > ///< Accept binding for 2 Arguments
|
||||
: BA
|
||||
{
|
||||
RET
|
||||
operator() (T1 a1, T2 a2)
|
||||
{
|
||||
return static_cast<TAR*> (this) -> bindArg (tuple::make (a1,a2));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template< class TAR, class BA, class RET
|
||||
, typename T1
|
||||
, typename T2
|
||||
, typename T3
|
||||
> //________________________________
|
||||
struct AcceptArgs<TAR,BA,RET, Types<T1,T2,T3> > ///< Accept binding for 3 Arguments
|
||||
: BA
|
||||
{
|
||||
RET
|
||||
operator() (T1 a1, T2 a2, T3 a3)
|
||||
{
|
||||
return static_cast<TAR*> (this) -> bindArg (tuple::make (a1,a2,a3));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template< class TAR, class BA, class RET
|
||||
, typename T1
|
||||
, typename T2
|
||||
, typename T3
|
||||
, typename T4
|
||||
> //________________________________
|
||||
struct AcceptArgs<TAR,BA,RET, Types<T1,T2,T3,T4> > ///< Accept binding for 4 Arguments
|
||||
: BA
|
||||
{
|
||||
RET
|
||||
operator() (T1 a1, T2 a2, T3 a3, T4 a4)
|
||||
{
|
||||
return static_cast<TAR*> (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<TAR,BA,RET, Types<T1,T2,T3,T4,T5> > ///< Accept binding for 5 Arguments
|
||||
: BA
|
||||
{
|
||||
RET
|
||||
operator() (T1 a1, T2 a2, T3 a3, T4 a4, T5 a5)
|
||||
{
|
||||
return static_cast<TAR*> (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<TAR,BA,RET, Types<T1,T2,T3,T4,T5,T6> > ///< Accept binding for 6 Arguments
|
||||
: BA
|
||||
{
|
||||
RET
|
||||
operator() (T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6)
|
||||
{
|
||||
return static_cast<TAR*> (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<TAR,BA,RET, Types<T1,T2,T3,T4,T5,T6,T7> > ///< 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<TAR*> (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<TAR,BA,RET, Types<T1,T2,T3,T4,T5,T6,T7,T8> > ///< 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<TAR*> (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<TAR,BA,RET, Types<T1,T2,T3,T4,T5,T6,T7,T8,T9> > ///< 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<TAR*> (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<TAR,BA,RET, Types<> > ///< Accept dummy binding (0 Arguments)
|
||||
: BA
|
||||
{
|
||||
RET
|
||||
bind ()
|
||||
{
|
||||
return static_cast<TAR*> (this) -> bindArg (tuple::makeNullTuple() );
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template< class TAR, class BA, class RET
|
||||
, typename T1
|
||||
> //_______________________________
|
||||
struct AcceptBind<TAR,BA,RET, Types<T1> > ///< Accept binding for 1 Argument
|
||||
: BA
|
||||
{
|
||||
RET
|
||||
bind (T1 a1)
|
||||
{
|
||||
return static_cast<TAR*> (this) -> bindArg (tuple::make (a1));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template< class TAR, class BA, class RET
|
||||
, typename T1
|
||||
, typename T2
|
||||
> //________________________________
|
||||
struct AcceptBind<TAR,BA,RET, Types<T1,T2> > ///< Accept binding for 2 Arguments
|
||||
: BA
|
||||
{
|
||||
RET
|
||||
bind (T1 a1, T2 a2)
|
||||
{
|
||||
return static_cast<TAR*> (this) -> bindArg (tuple::make (a1,a2));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template< class TAR, class BA, class RET
|
||||
, typename T1
|
||||
, typename T2
|
||||
, typename T3
|
||||
> //________________________________
|
||||
struct AcceptBind<TAR,BA,RET, Types<T1,T2,T3> > ///< Accept binding for 3 Arguments
|
||||
: BA
|
||||
{
|
||||
RET
|
||||
bind (T1 a1, T2 a2, T3 a3)
|
||||
{
|
||||
return static_cast<TAR*> (this) -> bindArg (tuple::make (a1,a2,a3));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template< class TAR, class BA, class RET
|
||||
, typename T1
|
||||
, typename T2
|
||||
, typename T3
|
||||
, typename T4
|
||||
> //________________________________
|
||||
struct AcceptBind<TAR,BA,RET, Types<T1,T2,T3,T4> > ///< Accept binding for 4 Arguments
|
||||
: BA
|
||||
{
|
||||
RET
|
||||
bind (T1 a1, T2 a2, T3 a3, T4 a4)
|
||||
{
|
||||
return static_cast<TAR*> (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<TAR,BA,RET, Types<T1,T2,T3,T4,T5> > ///< Accept binding for 5 Arguments
|
||||
: BA
|
||||
{
|
||||
RET
|
||||
bind (T1 a1, T2 a2, T3 a3, T4 a4, T5 a5)
|
||||
{
|
||||
return static_cast<TAR*> (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<TAR,BA,RET, Types<T1,T2,T3,T4,T5,T6> > ///< Accept binding for 6 Arguments
|
||||
: BA
|
||||
{
|
||||
RET
|
||||
bind (T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6)
|
||||
{
|
||||
return static_cast<TAR*> (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<TAR,BA,RET, Types<T1,T2,T3,T4,T5,T6,T7> > ///< 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<TAR*> (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<TAR,BA,RET, Types<T1,T2,T3,T4,T5,T6,T7,T8> > ///< 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<TAR*> (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<TAR,BA,RET, Types<T1,T2,T3,T4,T5,T6,T7,T8,T9> > ///< 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<TAR*> (this) -> bindArg (tuple::make (a1,a2,a3,a4,a5,a6,a7,a8,a9));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
template<typename SIG>
|
||||
struct _Type
|
||||
{
|
||||
typedef typename FunctionSignature< function<SIG> >::Args Args;
|
||||
typedef typename FunctionSignature< function<SIG> >::Ret Ret;
|
||||
typedef Tuple<Args> ArgTuple;
|
||||
typedef SIG Sig;
|
||||
};
|
||||
|
||||
template<typename TYPES>
|
||||
struct _Type<Tuple<TYPES> >
|
||||
{
|
||||
typedef TYPES Args;
|
||||
typedef void Ret;
|
||||
typedef Tuple<TYPES> ArgTuple;
|
||||
typedef typename FunctionTypedef<void, TYPES>::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<TYPES..>) --
|
||||
* where \c TYPES... is the sequence of types found in the provided Signature SIG.
|
||||
*/
|
||||
template<typename SIG, class TAR, class BASE =bind_arg::Dummy>
|
||||
class AcceptArgumentTuple
|
||||
: public bind_arg::AcceptArgs<TAR,BASE, typename bind_arg::_Type<SIG>::Ret
|
||||
, typename bind_arg::_Type<SIG>::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<Types<T1...> >)
|
||||
* @param BASE the base class for inheritance chaining
|
||||
*/
|
||||
template<typename SIG, class TAR, class BASE =bind_arg::Dummy>
|
||||
class AcceptArgumentBinding
|
||||
: public bind_arg::AcceptBind<TAR,BASE, typename bind_arg::_Type<SIG>::Ret
|
||||
, typename bind_arg::_Type<SIG>::Args>
|
||||
{
|
||||
};
|
||||
|
||||
|
||||
/** Variation of AcceptArgumentBinding, allowing to control the return type
|
||||
* of the generated \c bind(...) functions independently from SIG
|
||||
*/
|
||||
template<typename RET, typename SIG, class TAR, class BASE =bind_arg::Dummy>
|
||||
class AcceptArgumentBindingRet
|
||||
: public bind_arg::AcceptBind<TAR,BASE, RET
|
||||
, typename bind_arg::_Type<SIG>::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
|
||||
|
|
|
|||
|
|
@ -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<typename TUP>
|
||||
struct TypedArguments;
|
||||
|
||||
|
||||
struct Arguments
|
||||
{
|
||||
virtual ~Arguments() {}
|
||||
|
||||
template<typename TUP>
|
||||
TUP const&
|
||||
get ()
|
||||
{
|
||||
TypedArguments<TUP>* dest = dynamic_cast<TypedArguments<TUP>*> (this);
|
||||
if (!dest)
|
||||
throw lumiera::error::Invalid("Wrong type or number of arguments");
|
||||
|
||||
return dest->args_;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<typename TUP>
|
||||
struct TypedArguments
|
||||
: Arguments
|
||||
{
|
||||
TUP const& args_;
|
||||
|
||||
TypedArguments (TUP const& a)
|
||||
: args_(a)
|
||||
{ }
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
} // namespace control
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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 <tr1/memory>
|
||||
|
||||
|
||||
|
||||
|
||||
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<TYPES...>) function
|
||||
* on the target class. The latter function is asumed to perform a
|
||||
* run-time check to detect calls with invalid signature.
|
||||
*/
|
||||
template<class TAR, class BA>
|
||||
class ArgumentBinder
|
||||
|
|
@ -203,10 +202,8 @@ namespace com { ///< Proc-Layer command implementation details
|
|||
}
|
||||
|
||||
};
|
||||
////////////////TODO currently just fleshing out the API....
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}} // namespace control::com
|
||||
|
|
|
|||
|
|
@ -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<SIG> 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 <tr1/memory>
|
||||
|
|
@ -54,17 +65,10 @@
|
|||
#include <string>
|
||||
|
||||
|
||||
#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....
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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 <tr1/memory>
|
||||
#include <tr1/functional>
|
||||
|
|
@ -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<SIG>
|
||||
|
|
@ -182,8 +183,8 @@ namespace control {
|
|||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
template<typename SIG>
|
||||
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<typename SIG>
|
||||
stage::BasicDefinition<SIG>
|
||||
|
|
@ -252,7 +255,6 @@ namespace control {
|
|||
bool isValid() const;
|
||||
};
|
||||
|
||||
////////////////TODO currently just fleshing out the API....
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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 <boost/format.hpp>
|
||||
#include <sstream>
|
||||
|
|
@ -68,11 +74,11 @@ namespace control {
|
|||
lumiera::Singleton<CommandRegistry> 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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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 <tr1/memory>
|
||||
#include <string>
|
||||
|
||||
///////////////////////////////////////////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<Command // accepts arbitrary bind(..) calls (with runtime check)
|
||||
, lib::Handle<CommandImpl> // actually implemented as ref counting Handle
|
||||
>
|
||||
> //
|
||||
{
|
||||
typedef lib::Handle<CommandImpl> _Handle;
|
||||
|
||||
|
|
@ -177,7 +208,7 @@ namespace control {
|
|||
return ! (c1 == c2);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
} // namespace control
|
||||
|
|
|
|||
|
|
@ -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] ();
|
||||
|
|
|
|||
Loading…
Reference in a new issue