diff --git a/src/lib/meta/trait.hpp b/src/lib/meta/trait.hpp index a12055522..3ee151a81 100644 --- a/src/lib/meta/trait.hpp +++ b/src/lib/meta/trait.hpp @@ -367,8 +367,10 @@ namespace meta { TRAIT_IS_NARROWING (int64_t, int32_t) TRAIT_IS_NARROWING (int64_t, int16_t) TRAIT_IS_NARROWING (int64_t, int8_t) + TRAIT_IS_NARROWING (int64_t, char) TRAIT_IS_NARROWING (int32_t, int16_t) TRAIT_IS_NARROWING (int32_t, int8_t) + TRAIT_IS_NARROWING (int32_t, char) TRAIT_IS_NARROWING (int16_t, int8_t) TRAIT_IS_NARROWING (int16_t, short) TRAIT_IS_NARROWING (int16_t, char) diff --git a/src/proc/control/command-argument-holder.hpp b/src/proc/control/command-argument-holder.hpp index 120ad9c78..221e787a1 100644 --- a/src/proc/control/command-argument-holder.hpp +++ b/src/proc/control/command-argument-holder.hpp @@ -72,7 +72,7 @@ namespace control { { } private: - virtual bool isValid () const { return false; } + virtual bool isValid () const override { return false; } }; @@ -111,13 +111,14 @@ namespace control { ArgumentHolder& operator= (ArgumentHolder const&); - typedef Closure ArgHolder; - typedef MementoTie MemHolder; + using ArgHolder = Closure; + using MemHolder = MementoTie; - typedef InPlaceBuffer > ArgumentBuff; - typedef InPlaceBuffer > MementoBuff; + using ArgumentBuff = InPlaceBuffer>; + using MementoBuff = InPlaceBuffer>; - typedef typename ArgHolder::ArgTuple ArgTuple; + using ArgTuple = typename ArgHolder::ArgTuple; + using Args = typename Types::Seq; /* ====== in-place storage buffers ====== */ @@ -130,12 +131,14 @@ namespace control { /* ==== proxied CmdClosure interface ==== */ public: - virtual bool isValid () const + virtual bool + isValid () const override { return arguments_->isValid(); } - virtual bool isCaptured() const + virtual bool + isCaptured() const override { return memento_->isValid(); } @@ -143,16 +146,32 @@ namespace control { /** assign a new parameter tuple to this */ - virtual void bindArguments (Arguments& args) - { - if (!arguments_->isValid()) - storeTuple (args.get()); - else - arguments_->bindArguments(args); - } + virtual void + bindArguments (Arguments& args) override + { + if (!arguments_->isValid()) + storeTuple (args.get()); + else + arguments_->bindArguments (args); + } + + /** assign a new set of parameter values to this. + * @note the values are passed packaged into a sequence + * of GenNode elements. This is the usual way + * arguments are passed from the UI-Bus + */ + virtual void + bindArguments (lib::diff::Rec const& paramData) override + { + if (!arguments_->isValid()) + storeTuple (buildTuple (paramData)); + else + arguments_->bindArguments (paramData); + } - virtual void invoke (CmdFunctor const& func) + virtual void + invoke (CmdFunctor const& func) override { if (!isValid()) throw lumiera::error::State ("Lifecycle error: can't bind functor, " @@ -163,7 +182,8 @@ namespace control { } - virtual operator string() const + virtual + operator string() const override { return "Command-State{ arguments=" + (*arguments_? string(*arguments_) : "unbound") @@ -198,7 +218,7 @@ namespace control { /** assist with creating a clone copy; * this results in invocation of the copy ctor */ void - accept (CommandImplCloneBuilder& visitor) const + accept (CommandImplCloneBuilder& visitor) const override { visitor.buildCloneContext (*this); } diff --git a/src/proc/control/command-closure.hpp b/src/proc/control/command-closure.hpp index 48f6c41dd..21aa47cdd 100644 --- a/src/proc/control/command-closure.hpp +++ b/src/proc/control/command-closure.hpp @@ -73,6 +73,7 @@ #include "lib/meta/function-closure.hpp" #include "lib/meta/function-erasure.hpp" #include "lib/meta/tuple-helper.hpp" +#include "lib/meta/tuple-record-init.hpp" #include "lib/meta/maybe-compare.hpp" #include "lib/format-cout.hpp" #include "lib/util.hpp" @@ -97,6 +98,7 @@ namespace control { using lib::meta::FunErasure; using lib::meta::StoreFunction; using lib::meta::NullType; + using lib::meta::buildTuple; using lib::meta::equals_safeInvoke; using lib::TypedAllocationManager; @@ -136,6 +138,7 @@ namespace control { virtual bool isCaptured () const =0; ///< does this closure hold captured UNDO state? virtual bool equals (CmdClosure const&) const =0; ///< is equivalent to the given other closure? virtual void bindArguments (Arguments&) =0; ///< store a set of parameter values within this closure + virtual void bindArguments (lib::diff::Rec const&) =0; ///< store a set of parameter values, passed as GenNode sequence virtual void invoke (CmdFunctor const&) =0; ///< invoke functor using the stored parameter values virtual void accept (CommandImplCloneBuilder&) const =0; ///< assist with creating clone closure without disclosing concrete type }; @@ -146,9 +149,9 @@ namespace control { class AbstractClosure : public CmdClosure { - bool isValid() const { return false; } - bool isCaptured() const { return false; } - void accept (CommandImplCloneBuilder&) const {} + bool isValid() const override { return false; } + bool isCaptured() const override { return false; } + void accept (CommandImplCloneBuilder&) const override {} }; @@ -245,11 +248,22 @@ namespace control { /** assign a new parameter tuple to this */ void - bindArguments (Arguments& args) + bindArguments (Arguments& args) override { params_ = args.get(); } + /** assign a new set of parameter values to this. + * @note the values are passed packaged into a sequence + * of GenNode elements. This is the usual way + * arguments are passed from the UI-Bus + */ + void + bindArguments (lib::diff::Rec const& paramData) override + { + params_ = buildTuple (paramData); + } + /** Core operation: use the embedded argument tuple for invoking a functor * @param unboundFunctor an function object, whose function arguments are @@ -260,7 +274,7 @@ namespace control { * Thus this function can't be const. */ void - invoke (CmdFunctor const& unboundFunctor) + invoke (CmdFunctor const& unboundFunctor) override { TupleApplicator apply_this_arguments(params_); apply_this_arguments (unboundFunctor.getFun()); @@ -268,7 +282,7 @@ namespace control { - operator string() const + operator string() const override { std::ostringstream buff; params_.dump (buff << "Closure(" ); @@ -282,14 +296,14 @@ namespace control { } - bool isValid () const { return true; } + bool isValid () const override { return true; } /// Supporting equality comparisons... 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 not (c1 == c2); } bool - equals (CmdClosure const& other) const + equals (CmdClosure const& other) const override { const Closure* toCompare = dynamic_cast (&other); return (toCompare) diff --git a/src/proc/control/command-def.hpp b/src/proc/control/command-def.hpp index 1c4e0e19c..13b4dcc8e 100644 --- a/src/proc/control/command-def.hpp +++ b/src/proc/control/command-def.hpp @@ -61,7 +61,6 @@ #include "proc/control/command-registry.hpp" #include "proc/control/command-signature.hpp" #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" diff --git a/src/proc/control/command-impl.hpp b/src/proc/control/command-impl.hpp index 43eaae805..672a8400b 100644 --- a/src/proc/control/command-impl.hpp +++ b/src/proc/control/command-impl.hpp @@ -162,7 +162,13 @@ namespace control { void setArguments (Arguments& args) { - pClo_->bindArguments(args); + pClo_->bindArguments (args); + } + + void + setArguments (lib::diff::Rec const& paramData) + { + pClo_->bindArguments (paramData); } void invokeOperation() { do_(*pClo_); } diff --git a/src/proc/control/command.cpp b/src/proc/control/command.cpp index f3605c40e..bcea3f989 100644 --- a/src/proc/control/command.cpp +++ b/src/proc/control/command.cpp @@ -249,6 +249,18 @@ namespace control { } + /** @internal forward a `Record`, which was + * typically received via UI-Bus, down to the CommandImpl. + * @remarks this is how command arguments are actually + * passed from UI to the Session core + */ + void + Command::setArguments (lib::diff::Rec const& paramData) + { + ___check_notBottom (this, "Binding arguments of"); + _Handle::impl().setArguments(paramData); + } + /** @return the number of command \em definitions currently registered */ size_t diff --git a/src/proc/control/command.hpp b/src/proc/control/command.hpp index 639ccb52f..97f5fa855 100644 --- a/src/proc/control/command.hpp +++ b/src/proc/control/command.hpp @@ -195,6 +195,7 @@ namespace control { private: void setArguments (Arguments&); + void setArguments (lib::diff::Rec const&); static bool equivalentImpl (Command const&, Command const&); }; @@ -234,7 +235,8 @@ namespace control { inline Command& Command::bindArg (lib::diff::Rec const& paramData) { - UNIMPLEMENTED ("how to accept a GenNode-Rec and unpack it into our argument holder..."); + this->setArguments (paramData); + return *this; } diff --git a/tests/gui/bus-term-test.cpp b/tests/gui/bus-term-test.cpp index 1d55d63ca..d73bbca18 100644 --- a/tests/gui/bus-term-test.cpp +++ b/tests/gui/bus-term-test.cpp @@ -53,6 +53,9 @@ namespace test { using proc::control::LUMIERA_ERROR_INVALID_ARGUMENTS; using proc::control::LUMIERA_ERROR_UNBOUND_ARGUMENTS; + using lumiera::error::LUMIERA_ERROR_INDEX_BOUNDS; ////////TODO + using lumiera::error::LUMIERA_ERROR_WRONG_TYPE; ////////TODO + namespace { // test fixture... }//(End) test fixture @@ -188,15 +191,15 @@ namespace test { // we cannot invoke commands prior to binding arguments VERIFY_ERROR (UNBOUND_ARGUMENTS, mock.issueCommand(cmd) ); + + // proper argument typing is ensured while dispatching the bind message. + VERIFY_ERROR (INDEX_BOUNDS, mock.prepareCommand(cmd, Rec({"lalala"})) ); ////////////TODO : shall we care to get INVALID_ARGUMENTS here?? ////////////////////////////////////////////////////////////////////////////////////////////////////TODO WIP cout << "____Nexus-Log_________________\n" << util::join(gui::test::Nexus::getLog(), "\n") << "\n───╼━━━━━━━━━╾────────────────"<