From 1db718c2b3339604e0a0f24cddb908c6543d3cd6 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Sat, 25 Jul 2009 19:21:50 +0200 Subject: [PATCH] WIP more stubbing... --- src/lib/meta/tuple.hpp | 6 +- src/proc/control/argument-tuple-accept.hpp | 4 +- src/proc/control/command-argument-holder.hpp | 2 +- src/proc/control/command-binding.hpp | 213 ++++++++++++++++++ src/proc/control/command.cpp | 13 +- src/proc/control/command.hpp | 15 +- tests/45controller.tests | 2 +- .../control/argument-tuple-accept-test.cpp | 8 +- .../proc/control/command-use1-test.cpp | 4 +- .../proc/control/command-use2-test.cpp | 40 +++- 10 files changed, 280 insertions(+), 27 deletions(-) create mode 100644 src/proc/control/command-binding.hpp diff --git a/src/lib/meta/tuple.hpp b/src/lib/meta/tuple.hpp index 622246327..27f8538c1 100644 --- a/src/lib/meta/tuple.hpp +++ b/src/lib/meta/tuple.hpp @@ -390,7 +390,7 @@ namespace typelist{ , T6 a6 =T6() ) { - return Tuple > (a1,a2,a3,a4,a5,a6); + return Tuple > (a1,a2,a3,a4,a5,a6); } @@ -413,7 +413,7 @@ namespace typelist{ , T7 a7 =T7() ) { - return Tuple > (a1,a2,a3,a4,a5,a6,a7); + return Tuple > (a1,a2,a3,a4,a5,a6,a7); } @@ -438,7 +438,7 @@ namespace typelist{ , T8 a8 =T8() ) { - return Tuple > (a1,a2,a3,a4,a5,a6,a7,a8); + return Tuple > (a1,a2,a3,a4,a5,a6,a7,a8); } diff --git a/src/proc/control/argument-tuple-accept.hpp b/src/proc/control/argument-tuple-accept.hpp index faadebc89..fe618f7dc 100644 --- a/src/proc/control/argument-tuple-accept.hpp +++ b/src/proc/control/argument-tuple-accept.hpp @@ -22,7 +22,7 @@ /** @file argument-tuple-accept.hpp - ** The ArgumentTupleAccept template allows to mix in a \c bind(...) function. + ** The AcceptArgumentTuple 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 @@ -257,7 +257,7 @@ namespace control { * @param BASE the base class for inheritance chaining */ template - class ArgumentTupleAccept + class AcceptArgumentTuple : public bind_arg::AcceptArgs::Args> { }; diff --git a/src/proc/control/command-argument-holder.hpp b/src/proc/control/command-argument-holder.hpp index ef82f7fc6..50c784782 100644 --- a/src/proc/control/command-argument-holder.hpp +++ b/src/proc/control/command-argument-holder.hpp @@ -103,7 +103,7 @@ namespace control { */ template class ArgumentHolder - : public ArgumentTupleAccept< SIG // to derive the desired bind(..) signature + : public AcceptArgumentTuple< SIG // to derive the desired bind(..) signature , ArgumentHolder // target class providing the implementation , CmdClosure // base class to inherit from > diff --git a/src/proc/control/command-binding.hpp b/src/proc/control/command-binding.hpp new file mode 100644 index 000000000..79ae2f0c8 --- /dev/null +++ b/src/proc/control/command-binding.hpp @@ -0,0 +1,213 @@ +/* + COMMAND-BINDING.hpp - interface for various ways of binding command arguments + + 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-binding.hpp + ** Sub-include of command.hpp, providing an interface to various ways + ** of binding command arguments. While in some cases, a command will be + ** set up completely finished and closed over all it's arguments, usually + ** the CommandDef will just specify the command operation and undo function, + ** thus leaving the task of binding concrete arguments to the client code. + ** Thus, depending on the circumstances, there might be usage situations + ** where the exact number and type of arguments can be detected and checked + ** at compile time, while otherwise this check needs to be deferred to happen + ** at runtime, when the binding is actually invoked. + ** + ** @see Command + ** @see CommandDef + ** @see command-use1-test.cpp + ** + */ + + + +#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; + + + + + + /** + * @todo Type-comment + */ + template + class ArgumentBinder + : public BA + { + + public: + + + /** Arm up a command by binding it with concrete arguments. + * At this point, a run time type check is performed, to find out + * if the number and type of arguments of the stored operation function + * within the command matches the given argument pattern + */ + void + bind () + { + static_cast (this) -> bindArg (tuple::makeNullTuple()); + } + + + template + void //________________________________ + bind (T1 a1) ///< Accept binding with 1 Argument + { + static_cast (this) -> bindArg (tuple::make (a1)); + } + + + template< typename T1 + , typename T2 + > + void //________________________________ + bind (T1 a1, T2 a2) ///< Accept binding for 2 Arguments + { + static_cast (this) -> bindArg (tuple::make (a1,a2)); + } + + + template< typename T1 + , typename T2 + , typename T3 + > + void //________________________________ + bind (T1 a1, T2 a2, T3 a3) ///< Accept binding for 3 Arguments + { + static_cast (this) -> bindArg (tuple::make (a1,a2,a3)); + } + + + template< typename T1 + , typename T2 + , typename T3 + , typename T4 + > + void //________________________________ + bind (T1 a1, T2 a2, T3 a3, T4 a4) ///< Accept binding for 4 Arguments + { + static_cast (this) -> bindArg (tuple::make (a1,a2,a3,a4)); + } + + + template< typename T1 + , typename T2 + , typename T3 + , typename T4 + , typename T5 + > + void //________________________________ + bind (T1 a1, T2 a2, T3 a3, T4 a4, T5 a5) ///< Accept binding for 5 Arguments + { + static_cast (this) -> bindArg (tuple::make (a1,a2,a3,a4,a5)); + } + + + template< typename T1 + , typename T2 + , typename T3 + , typename T4 + , typename T5 + , typename T6 + > + void //________________________________ + bind (T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6) ///< Accept binding for 6 Arguments + { + static_cast (this) -> bindArg (tuple::make (a1,a2,a3,a4,a5,a6)); + } + + + template< typename T1 + , typename T2 + , typename T3 + , typename T4 + , typename T5 + , typename T6 + , typename T7 + > + void //________________________________ + bind (T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7) ///< Accept binding for 7 Arguments + { + static_cast (this) -> bindArg (tuple::make (a1,a2,a3,a4,a5,a6,a7)); + } + + + template< typename T1 + , typename T2 + , typename T3 + , typename T4 + , typename T5 + , typename T6 + , typename T7 + , typename T8 + > + void //________________________________ + bind (T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8) ///< Accept binding for 8 Arguments + { + static_cast (this) -> bindArg (tuple::make (a1,a2,a3,a4,a5,a6,a7,a8)); + } + + + template< typename T1 + , typename T2 + , typename T3 + , typename T4 + , typename T5 + , typename T6 + , typename T7 + , typename T8 + , typename T9 + > + void //________________________________ + bind (T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, T9 a9) ///< Accept binding for 9 Arguments + { + static_cast (this) -> bindArg (tuple::make (a1,a2,a3,a4,a5,a6,a7,a8,a9)); + } + + }; + ////////////////TODO currently just fleshing out the API.... + + + + + +}} // namespace control +#endif diff --git a/src/proc/control/command.cpp b/src/proc/control/command.cpp index fbdebf4ab..e8a0fb469 100644 --- a/src/proc/control/command.cpp +++ b/src/proc/control/command.cpp @@ -43,8 +43,10 @@ namespace control { + LUMIERA_ERROR_DEFINE (INVALID_COMMAND, "Unknown or insufficiently defined command"); + LUMIERA_ERROR_DEFINE (INVALID_ARGUMENTS, "Arguments provided for binding doesn't match stored command function parameters"); LUMIERA_ERROR_DEFINE (UNBOUND_ARGUMENTS, "Command mutation functor not yet usable, because arguments aren't bound"); - LUMIERA_ERROR_DEFINE (MISSING_MEMENTO, "Undo functor not yet usable, because no undo state has been captured"); + LUMIERA_ERROR_DEFINE (MISSING_MEMENTO, "Undo functor not yet usable, because no undo state has been captured"); @@ -142,6 +144,15 @@ namespace control { { UNIMPLEMENTED ("manage the default command handling pattern"); } + + + template + void + Command::bindArg (Tuple const& args) + { + UNIMPLEMENTED ("create an argument-binding, with runtime type check"); + } + diff --git a/src/proc/control/command.hpp b/src/proc/control/command.hpp index 7c16761e5..0a5b47828 100644 --- a/src/proc/control/command.hpp +++ b/src/proc/control/command.hpp @@ -34,8 +34,9 @@ #ifndef CONTROL_COMMAND_H #define CONTROL_COMMAND_H -//#include "pre.hpp" +#include "pre.hpp" #include "include/symbol.hpp" +#include "proc/control/command-binding.hpp" #include "proc/control/command-mutation.hpp" #include "proc/control/command-closure.hpp" #include "lib/bool-checkable.hpp" @@ -51,6 +52,11 @@ namespace control { using lumiera::Symbol; // using std::tr1::shared_ptr; + 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 (INVALID_ARGUMENTS); ///< Arguments provided for binding doesn't match stored command function parameters + + class HandlingPattern; @@ -59,7 +65,8 @@ namespace control { * @todo Type-comment */ class Command - : public lib::BoolCheckable + : public com::ArgumentBinder > { public: @@ -85,6 +92,10 @@ namespace control { HandlingPattern const& getDefaultHandlingPattern() const; + template + void bindArg (Tuple const&); + + /* === diagnostics === */ static size_t definition_count(); diff --git a/tests/45controller.tests b/tests/45controller.tests index a9f87cbf3..f8ea6c8e6 100644 --- a/tests/45controller.tests +++ b/tests/45controller.tests @@ -43,7 +43,7 @@ out: saved state: 11 END -TEST "build argument accepting function" ArgumentTupleAccept_test < @@ -63,7 +63,7 @@ namespace test { template class TestClass - : public ArgumentTupleAccept< SIG // to derive the desired signature + : public AcceptArgumentTuple< SIG // to derive the desired signature , TestClass // the target class providing the implementation , typename Tup::Ty // base class to inherit from > @@ -93,7 +93,7 @@ namespace test { * * @see control::CommandArgumentHolder */ - class ArgumentTupleAccept_test : public Test + class AcceptArgumentTuple_test : public Test { virtual void @@ -117,7 +117,7 @@ namespace test { /** Register this test class... */ - LAUNCHER (ArgumentTupleAccept_test, "unit controller"); + LAUNCHER (AcceptArgumentTuple_test, "unit controller"); }} // namespace control::test diff --git a/tests/components/proc/control/command-use1-test.cpp b/tests/components/proc/control/command-use1-test.cpp index bc43e2aaf..c6c3fdcc9 100644 --- a/tests/components/proc/control/command-use1-test.cpp +++ b/tests/components/proc/control/command-use1-test.cpp @@ -32,6 +32,7 @@ //#include "proc/mobject/placement.hpp" //#include "proc/mobject/placement-index.hpp" //#include "proc/mobject/explicitplacement.hpp" +#include "proc/control/command.hpp" #include "proc/control/command-def.hpp" //#include "lib/lumitime.hpp" #include "lib/util.hpp" @@ -224,7 +225,7 @@ namespace test { // note we've overwritten the previous undo state // and get the sate captured on the second invocation - c2.undo() + c2.undo(); ASSERT (randVal == command1::check_); c1.undo(); ASSERT (randVal + 23 == command1::check_); @@ -267,7 +268,6 @@ namespace test { // but because the miracle isn't yet defined, any use throws VERIFY_ERROR (INVALID_COMMAND, Command::get("miracle")); - VERIFY_ERROR (UNBOUND_ARGUMENTS, unbelievable.execSync() ); VERIFY_ERROR (INVALID_COMMAND, unbelievable.bind("abracadabra")); ASSERT (Command::remove("test.command1.1")); diff --git a/tests/components/proc/control/command-use2-test.cpp b/tests/components/proc/control/command-use2-test.cpp index 924f9e8c5..1069a06b0 100644 --- a/tests/components/proc/control/command-use2-test.cpp +++ b/tests/components/proc/control/command-use2-test.cpp @@ -32,7 +32,9 @@ //#include "proc/mobject/placement.hpp" //#include "proc/mobject/placement-index.hpp" //#include "proc/mobject/explicitplacement.hpp" +#include "proc/control/command.hpp" #include "proc/control/command-def.hpp" +#include "proc/control/handling-pattern.hpp" //#include "lib/lumitime.hpp" #include "lib/util.hpp" @@ -41,6 +43,7 @@ #include #include #include +#include //#include //#include #include @@ -62,6 +65,7 @@ namespace test { //using std::endl; // using lib::test::showSizeof; // using util::isSameObject; + using boost::lexical_cast; using util::contains; using boost::ref; @@ -73,6 +77,20 @@ namespace test { using lumiera::error::LUMIERA_ERROR_EXTERNAL; + /** diagnostics: checks if the given value has been written + * to the test protocol (string stream) of command2 + * Explanation: command2 accepts a function, invokes + * it and writes the result to the protocol stream. + */ + template + inline bool + protocolled (TY val2check) + { + return contains ( command2::check_.str() + , lexical_cast (val2check) + ); + } + @@ -95,7 +113,7 @@ namespace test { return str (fmt % randVal_); } - bool blowUp_ = false; + bool blowUp_; virtual void @@ -114,8 +132,8 @@ namespace test { .undoOperation (command2::undoIt) .bind (randFun, ref(blowUp_)); - // note: blowUp_ is bound via reference_wrapper, - // so we can pull the trigger to provoke an exception + //note : blowUp_ is bound via reference_wrapper, + // thus we can provoke an exception at will. blowUp_ = false; @@ -136,18 +154,18 @@ namespace test { { Command com = Command::get("test.command2"); - ASSERT (!contains (command2::check_, "invoked")); + ASSERT (!protocolled("invoked")); bool res = com(); ASSERT (res); - ASSERT (contains (command2::check_, "invoked")); - ASSERT (contains (command2::check_, randVal_)); + ASSERT (protocolled("invoked")); + ASSERT (protocolled(randVal_)); res = com.undo(); ASSERT (res); // UNDO invoked successfully - ASSERT (!contains (command2::check_, randVal_)); - ASSERT (contains (command2::check_, "UNDO")); + ASSERT (!protocolled(randVal_)); + ASSERT (protocolled("UNDO")); blowUp_ = true; string current = command2::check_.str(); @@ -174,7 +192,7 @@ namespace test { blowUp_ = false; com.exec(HandlingPattern::THROW_SYNC); - ASSERT (contains (command2::check_, randVal_)); + ASSERT (protocolled(randVal_)); blowUp_ = true; string current = command2::check_.str(); @@ -193,10 +211,10 @@ namespace test { blowUp_ = false; com2(); ASSERT (command2::check_.str() > current); - ASSERT (contains (command2::check_, randVal_)); + ASSERT (protocolled(randVal_)); com2.undo(); - ASSERT (!contains (command2::check_, randVal_)); + ASSERT (!protocolled(randVal_)); } };