Skip to content

File model_definition_transitions.hpp

File List > backends > cxx > include > zmbt > mapping > model_definition_transitions.hpp

Go to the documentation of this file

#ifndef ZMBT_MAPPING_MODEL_DEFINITION_TRANSITIONS_HPP_
#define ZMBT_MAPPING_MODEL_DEFINITION_TRANSITIONS_HPP_

#include <boost/json.hpp>
#include <boost/mp11.hpp>
#include <zmbt/core/aliases.hpp>
#include <zmbt/core/format_string.hpp>
#include <zmbt/core/json_node.hpp>
#include <zmbt/core/parameter.hpp>
#include <zmbt/expr/expression.hpp>
#include <zmbt/expr/api.hpp>
#include <zmbt/expr/operator.hpp>
#include <zmbt/model/traits.hpp>
#include <cstddef>
#include <tuple>
#include <utility>

#include "model_definition_helper.hpp"
#include "zmbt/mapping/model_definition.hpp"
#include "zmbt/mapping/model_definition_node.hpp"



namespace zmbt {
namespace mapping {


template <class Target>
struct ModelDefinition::T_OnTrigger : protected virtual ModelDefinition::BaseTransition
{

    template <class... T>
    Target OnTrigger(boost::json::string_view key, T&&... fmtargs)
    {
        state().set_deferred_param("/trigger", key | expr::Format(fmtargs...));
        return transit_to<Target>();
    }

    Target OnTrigger(Param const& key)
    {
        state().params("/%s/pointers/+", key) = "/trigger";
        state().model("/trigger") = key;
        return transit_to<Target>();
    }

    Target OnTrigger(Param const& ifc, Param const& obj)
    {
        state().model("/trigger") = {
            {"obj", obj},
            {"ifc", ifc},
        };
        state().params("/%s/pointers/+", obj) = "/trigger/obj";
        state().params("/%s/pointers/+", ifc) = "/trigger/ifc";
        return transit_to<Target>();
    }


    template <class O, class I>
    require_literal<O, I, Target>
    OnTrigger(I&& ifc, O&& obj) {
        auto key = state().env.RegisterAnonymousTrigger(ifc, obj);
        return OnTrigger(key);
    }

    template <class I>
    require_cal<I, Target>
    OnTrigger(I&& ifc) {
        static_assert(!is_member_pointer<I>::value, "");
        return OnTrigger(std::forward<I>(ifc), ifc_host_nullptr<I>);
    }


    template <class I>
    require_cal<I, Target>
    OnTrigger(I&& ifc, Param const& obj)
    {
        state().model("/trigger") = {
            {"ifc", state().env.RegisterParametricTriggerIfc(ifc)}
        };
        state().params("/%s/pointers/+", obj) = "/trigger/obj";
        return transit_to<Target>();
    }

    template <class H>
    require_obj<H, Target>
    OnTrigger(Param const& ifc, H&& obj)
    {
        state().model("/trigger") = {
            {"obj", state().env.RegisterParametricTriggerObj(obj)}
        };
        state().params("/%s/pointers/+", ifc) = "/trigger/ifc";
        return transit_to<Target>();
    }
};


template <class Target>
struct ModelDefinition::T_Repeat : protected virtual ModelDefinition::BaseTransition
{
    Target Repeat(std::size_t N)
    {
        state().model("/repeat_trigger") = N;
        return transit_to<Target>();
    }

    Target Repeat(Param const& N)
    {
        state().model("/repeat_trigger") = N;
        state().params("/%s/pointers/+", N) = "/repeat_trigger";
        return transit_to<Target>();
    }
};



template <class Target>
struct ModelDefinition::T_Filter : protected virtual ModelDefinition::BaseTransition
{

    Target Return(lang::Expression const& e = "")
    {
        state().set_channel_sp("return", e);
        return transit_to<Target>();
    }

    template <class T, class... Rest>
    Target Return(boost::json::string_view fmt, T&& arg1, Rest&&... args_rest)
    {
        return Return(fmt | expr::Fmt(arg1, args_rest...));
    }

    Target Args(lang::Expression const& e = "$default")
    {
        state().set_channel_sp("args", e);
        return transit_to<Target>();
    }

    template <class T, class... Rest>
    Target Args(boost::json::string_view fmt, T&& arg1, Rest&&... args_rest)
    {
        return Args(fmt | expr::Format(arg1, args_rest...));
    }

    Target Exception()
    {
        state().cur_channel()["kind"] = "exception";
        state().cur_channel()["signal_path"] = "";
        return transit_to<Target>();
    }

    Target Timestamp()
    {
        state().cur_channel()["kind"] = "ts";
        state().cur_channel()["signal_path"] = "";
        return transit_to<Target>();
    }

    Target ThreadId()
    {
        state().cur_channel()["kind"] = "tid";
        state().cur_channel()["signal_path"] = "";
        return transit_to<Target>();
    }

    Target CallCount()
    {
        state().cur_channel()["kind"] = "call_count";
        state().cur_channel()["signal_path"] = "";
        return transit_to<Target>();
    }
};


template <class Target>
struct ModelDefinition::T_As : protected virtual ModelDefinition::BaseTransition
{
    Target As(boost::json::string_view ref)
    {
        state().cur_pipe()["overload"] = ref;
        return transit_to<Target>();
    }

    Target As(lang::Operator const& op)
    {
        return As(op.annotation());
    }
};


template <class Target>
struct ModelDefinition::T_Take : protected virtual ModelDefinition::BaseTransition
{
    Target Take(lang::Expression const& expr)
    {
        state().cur_channel()["transform"] = expr;
        return transit_to<Target>();
    }
};


template <class Target>
struct ModelDefinition::T_Alias : protected virtual ModelDefinition::BaseTransition
{
    Target Alias(boost::json::string_view alias)
    {
        state().cur_channel()["alias"] = alias;
        return transit_to<Target>();
    }
};


template <class Target>
struct ModelDefinition::T_At : protected virtual ModelDefinition::BaseTransition
{
    template <class C>
    require_not_str<C, Target>
    At(C&& cal, object_id const& obj)
    {
        state().add_channel(obj, std::forward<C>(cal));
        return transit_to<Target>();
    }

    template <class C>
    require_not_str<C, Target>
    At(C&& cal, Param const& obj)
    {
        state().add_channel(obj, std::forward<C>(cal));
        return transit_to<Target>();
    }


    template <class C>
    require_not_str<C, Target>
    At(C&& cal)
    {
        state().add_channel(std::forward<C>(cal));
        return transit_to<Target>();
    }

    template <class... T>
    Target
    At(boost::json::string_view key, T&&... fmtargs)
    {
        state().add_channel(key | expr::Fmt(fmtargs...));
        return transit_to<Target>();
    }
};


template <class Target>
struct ModelDefinition::T_ContinuePipe : protected virtual ModelDefinition::BaseTransition
{
    Target Blend()
    {
        state().continue_pipe("blend");
        return transit_to<Target>();
    }

    Target Group()
    {
        state().continue_pipe("group");
        return transit_to<Target>();
    }
};


template <class Target>
struct ModelDefinition::T_TerminatePipe : protected virtual ModelDefinition::BaseTransition
{
    Target Inject()
    {
        state().head_pipe_type_.emplace_null();
        state().cur_pipe()["column"] = state().test_column_count_++;
        state().cur_pipe()["role"] = "inject";
        return transit_to<Target>();
    }
    Target Inject(lang::Expression const& expr)
    {
        state().head_pipe_type_.emplace_null();
        state().cur_pipe()["role"] = "inject";
        state().set_expr(expr);
        return transit_to<Target>();
    }

    Target Expect()
    {
        state().head_pipe_type_.emplace_null();
        state().cur_pipe()["column"] = state().test_column_count_++;
        state().cur_pipe()["role"] = "expect";
        return transit_to<Target>();
    }
    Target Expect(lang::Expression const& expr)
    {
        state().head_pipe_type_.emplace_null();
        state().cur_pipe()["role"] = "expect";
        state().set_expr(expr);
        return transit_to<Target>();
    }

    Target ExpectBatch(lang::Expression const& expr)
    {
        state().head_pipe_type_.emplace_null();
        state().cur_pipe()["role"] = "expect_batch";
        state().set_expr(expr);
        return transit_to<Target>();

    }
    Target ExpectBatch()
    {
        state().head_pipe_type_.emplace_null();
        state().cur_pipe()["column"] = state().test_column_count_++;
        state().cur_pipe()["role"] = "expect_batch";
        return transit_to<Target>();
    }

    Target ExpectOne(lang::Expression const& expr)
    {
        state().head_pipe_type_.emplace_null();
        state().cur_pipe()["role"] = "expect_one";
        state().set_expr(expr);
        return transit_to<Target>();
    }
    Target ExpectOne()
    {
        state().head_pipe_type_.emplace_null();
        state().cur_pipe()["column"] = state().test_column_count_++;
        state().cur_pipe()["role"] = "expect_one";
        return transit_to<Target>();
    }

    // TODO: add Assert* clauses
};


template <class Target>
struct ModelDefinition::T_Test : protected virtual ModelDefinition::BaseTransition
{
    Target Test()
    {
        return transit_to<Target>()();
    }
    Target Test(lang::Expression const& e0)
    {
        return transit_to<Target>()(e0);
    }
    Target Test(lang::Expression const& e0, lang::Expression const& e1)
    {
        return transit_to<Target>()(e0, e1);
    }
    Target Test(lang::Expression const& e0, lang::Expression const& e1, lang::Expression const& e2)
    {
        return transit_to<Target>()(e0, e1, e2);
    }
    Target Test(lang::Expression const& e0, lang::Expression const& e1, lang::Expression const& e2, lang::Expression const& e3)
    {
        return transit_to<Target>()(e0, e1, e2, e3);
    }
    Target Test(lang::Expression const& e0, lang::Expression const& e1, lang::Expression const& e2, lang::Expression const& e3,
                    lang::Expression const& e4)
    {
        return transit_to<Target>()(e0, e1, e2, e3, e4);
    }
    Target Test(lang::Expression const& e0, lang::Expression const& e1, lang::Expression const& e2, lang::Expression const& e3,
                    lang::Expression const& e4, lang::Expression const& e5)
    {
        return transit_to<Target>()(e0, e1, e2, e3, e4, e5);
    }
    Target Test(lang::Expression const& e0, lang::Expression const& e1, lang::Expression const& e2, lang::Expression const& e3,
                    lang::Expression const& e4, lang::Expression const& e5, lang::Expression const& e6)
    {
        return transit_to<Target>()(e0, e1, e2, e3, e4, e5, e6);
    }
    Target Test(lang::Expression const& e0, lang::Expression const& e1, lang::Expression const& e2, lang::Expression const& e3,
                    lang::Expression const& e4, lang::Expression const& e5, lang::Expression const& e6, lang::Expression const& e7)
    {
        return transit_to<Target>()(e0, e1, e2, e3, e4, e5, e6, e7);
    }

    template <class... Rest>
    Target Test(lang::Expression const& e0, lang::Expression const& e1, lang::Expression const& e2, lang::Expression const& e3,
                    lang::Expression const& e4, lang::Expression const& e5, lang::Expression const& e6, lang::Expression const& e7,
                    Rest&&... rest)
    {
        return transit_to<Target>()(e0, e1, e2, e3, e4, e5, e6, e7, lang::Expression(rest)...);
    }
};


template <class Target>
struct ModelDefinition::T_TestRow : protected virtual ModelDefinition::BaseTransition
{
    Target operator[](boost::json::string_view comment)
    {
        state().set_comment(comment);
        return transit_to<Target>();
    }

    Target operator()()
    {
        state().add_test_case({});
        return transit_to<Target>();
    }

    Target operator()(lang::Expression const& e0)
    {
        state().add_test_case({e0});
        return transit_to<Target>();
    }
    Target operator()(lang::Expression const& e0, lang::Expression const& e1)
    {
        state().add_test_case({e0, e1});
        return transit_to<Target>();
    }
    Target operator()(lang::Expression const& e0, lang::Expression const& e1, lang::Expression const& e2)
    {
        state().add_test_case({e0, e1, e2});
        return transit_to<Target>();
    }
    Target operator()(lang::Expression const& e0, lang::Expression const& e1, lang::Expression const& e2, lang::Expression const& e3)
    {
        state().add_test_case({e0, e1, e2, e3});
        return transit_to<Target>();
    }
    Target operator()(lang::Expression const& e0, lang::Expression const& e1, lang::Expression const& e2, lang::Expression const& e3,
                          lang::Expression const& e4)
    {
        state().add_test_case({e0, e1, e2, e3, e4});
        return transit_to<Target>();
    }
    Target operator()(lang::Expression const& e0, lang::Expression const& e1, lang::Expression const& e2, lang::Expression const& e3,
                          lang::Expression const& e4, lang::Expression const& e5)
    {
        state().add_test_case({e0, e1, e2, e3, e4, e5});
        return transit_to<Target>();
    }
    Target operator()(lang::Expression const& e0, lang::Expression const& e1, lang::Expression const& e2, lang::Expression const& e3,
                          lang::Expression const& e4, lang::Expression const& e5, lang::Expression const& e6)
    {
        state().add_test_case({e0, e1, e2, e3, e4, e5, e6});
        return transit_to<Target>();
    }
    Target operator()(lang::Expression const& e0, lang::Expression const& e1, lang::Expression const& e2, lang::Expression const& e3,
                          lang::Expression const& e4, lang::Expression const& e5, lang::Expression const& e6, lang::Expression const& e7)
    {
        state().add_test_case({e0, e1, e2, e3, e4, e5, e6, e7});
        return transit_to<Target>();
    }

    template <class... Rest>
    Target operator()(lang::Expression const& e0, lang::Expression const& e1, lang::Expression const& e2, lang::Expression const& e3,
                          lang::Expression const& e4, lang::Expression const& e5, lang::Expression const& e6, lang::Expression const& e7,
                          Rest&&... rest)
    {
        state().add_test_case({e0, e1, e2, e3, e4, e5, e6, e7, lang::Expression(rest)...});
        return transit_to<Target>();
    }
};


template <class Target>
struct ModelDefinition::T_Description : protected virtual ModelDefinition::BaseTransition
{
    template <class... T>
    Target Description(boost::json::string_view comment, T&&... args)
    {
        state().set_deferred_param("/description", comment | expr::Format(args...));
        return transit_to<Target>();
    }
};


template <class Target>
struct ModelDefinition::T_Param : protected virtual ModelDefinition::BaseTransition
{

    Target Zip(Param const& p, boost::json::value const& v0)
    {
        state().init_zip();
        return transit_to<Target>()(p, v0);
    }
    Target Zip(Param const& p, boost::json::value const& v0, boost::json::value const& v1)
    {
        state().init_zip();
        return transit_to<Target>()(p, v0, v1);
    }

    Target Zip(Param const& p,
        boost::json::value const& v0,
        boost::json::value const& v1,
        boost::json::value const& v2
    )
    {
        state().init_zip();
        return transit_to<Target>()(p, v0, v1, v2);
    }
    Target Zip(Param const& p,
        boost::json::value const& v0,
        boost::json::value const& v1,
        boost::json::value const& v2,
        boost::json::value const& v3
    )
    {
        state().init_zip();
        return transit_to<Target>()(p, v0, v1, v2, v3);
    }
    Target Zip(Param const& p,
        boost::json::value const& v0,
        boost::json::value const& v1,
        boost::json::value const& v2,
        boost::json::value const& v3,
        boost::json::value const& v4
    )
    {
        state().init_zip();
        return transit_to<Target>()(p, v0, v1, v2, v3, v4);
    }
    Target Zip(Param const& p,
        boost::json::value const& v0,
        boost::json::value const& v1,
        boost::json::value const& v2,
        boost::json::value const& v3,
        boost::json::value const& v4,
        boost::json::value const& v5
    )
    {
        state().init_zip();
        return transit_to<Target>()(p, v0, v1, v2, v3, v4, v5);
    }
    Target Zip(Param const& p,
        boost::json::value const& v0,
        boost::json::value const& v1,
        boost::json::value const& v2,
        boost::json::value const& v3,
        boost::json::value const& v4,
        boost::json::value const& v5,
        boost::json::value const& v6
    )
    {
        state().init_zip();
        return transit_to<Target>()(p, v0, v1, v2, v3, v4, v5, v6);
    }
    Target Zip(Param const& p,
        boost::json::value const& v0,
        boost::json::value const& v1,
        boost::json::value const& v2,
        boost::json::value const& v3,
        boost::json::value const& v4,
        boost::json::value const& v5,
        boost::json::value const& v6,
        boost::json::value const& v7
    )
    {
        state().init_zip();
        return transit_to<Target>()(p, v0, v1, v2, v3, v4, v5, v6, v7);
    }

    template <class... A>
    Target Zip(Param const& p,
        boost::json::value const& v0,
        boost::json::value const& v1,
        boost::json::value const& v2,
        boost::json::value const& v3,
        boost::json::value const& v4,
        boost::json::value const& v5,
        boost::json::value const& v6,
        boost::json::value const& v7,
        A&&... args
    )
    {
        state().init_zip();
        return transit_to<Target>()(p, v0, v1, v2, v3, v4, v5, v6, v7, std::forward<A>(args)...);
    }
    template <class... A>
    Target Zip(Param const& p, A&&... args)
    {
        state().init_zip();
        return transit_to<Target>()(p, std::forward<A>(args)...);
    }

    Target Prod(Param const& p, boost::json::value const& v0)
    {
        state().init_prod();
        return transit_to<Target>()(p, v0);
    }
    Target Prod(Param const& p, boost::json::value const& v0, boost::json::value const& v1)
    {
        state().init_prod();
        return transit_to<Target>()(p, v0, v1);
    }

    Target Prod(Param const& p,
        boost::json::value const& v0,
        boost::json::value const& v1,
        boost::json::value const& v2
    )
    {
        state().init_prod();
        return transit_to<Target>()(p, v0, v1, v2);
    }
    Target Prod(Param const& p,
        boost::json::value const& v0,
        boost::json::value const& v1,
        boost::json::value const& v2,
        boost::json::value const& v3
    )
    {
        state().init_prod();
        return transit_to<Target>()(p, v0, v1, v2, v3);
    }
    Target Prod(Param const& p,
        boost::json::value const& v0,
        boost::json::value const& v1,
        boost::json::value const& v2,
        boost::json::value const& v3,
        boost::json::value const& v4
    )
    {
        state().init_prod();
        return transit_to<Target>()(p, v0, v1, v2, v3, v4);
    }
    Target Prod(Param const& p,
        boost::json::value const& v0,
        boost::json::value const& v1,
        boost::json::value const& v2,
        boost::json::value const& v3,
        boost::json::value const& v4,
        boost::json::value const& v5
    )
    {
        state().init_prod();
        return transit_to<Target>()(p, v0, v1, v2, v3, v4, v5);
    }
    Target Prod(Param const& p,
        boost::json::value const& v0,
        boost::json::value const& v1,
        boost::json::value const& v2,
        boost::json::value const& v3,
        boost::json::value const& v4,
        boost::json::value const& v5,
        boost::json::value const& v6
    )
    {
        state().init_prod();
        return transit_to<Target>()(p, v0, v1, v2, v3, v4, v5, v6);
    }
    Target Prod(Param const& p,
        boost::json::value const& v0,
        boost::json::value const& v1,
        boost::json::value const& v2,
        boost::json::value const& v3,
        boost::json::value const& v4,
        boost::json::value const& v5,
        boost::json::value const& v6,
        boost::json::value const& v7
    )
    {
        state().init_prod();
        return transit_to<Target>()(p, v0, v1, v2, v3, v4, v5, v6, v7);
    }

    template <class... A>
    Target Prod(Param const& p,
        boost::json::value const& v0,
        boost::json::value const& v1,
        boost::json::value const& v2,
        boost::json::value const& v3,
        boost::json::value const& v4,
        boost::json::value const& v5,
        boost::json::value const& v6,
        boost::json::value const& v7,
        A&&... args
    )
    {
        state().init_prod();
        return transit_to<Target>()(p, v0, v1, v2, v3, v4, v5, v6, v7, std::forward<A>(args)...);
    }
    template <class... A>
    Target Prod(Param const& p, A&&... args)
    {
        state().init_prod();
        return transit_to<Target>()(p, std::forward<A>(args)...);
    }

    Target Pairwise(Param const& p, boost::json::value const& v0)
    {
        state().init_pairwise();
        return transit_to<Target>()(p, v0);
    }
    Target Pairwise(Param const& p, boost::json::value const& v0, boost::json::value const& v1)
    {
        state().init_pairwise();
        return transit_to<Target>()(p, v0, v1);
    }

    Target Pairwise(Param const& p,
        boost::json::value const& v0,
        boost::json::value const& v1,
        boost::json::value const& v2
    )
    {
        state().init_pairwise();
        return transit_to<Target>()(p, v0, v1, v2);
    }
    Target Pairwise(Param const& p,
        boost::json::value const& v0,
        boost::json::value const& v1,
        boost::json::value const& v2,
        boost::json::value const& v3
    )
    {
        state().init_pairwise();
        return transit_to<Target>()(p, v0, v1, v2, v3);
    }
    Target Pairwise(Param const& p,
        boost::json::value const& v0,
        boost::json::value const& v1,
        boost::json::value const& v2,
        boost::json::value const& v3,
        boost::json::value const& v4
    )
    {
        state().init_pairwise();
        return transit_to<Target>()(p, v0, v1, v2, v3, v4);
    }
    Target Pairwise(Param const& p,
        boost::json::value const& v0,
        boost::json::value const& v1,
        boost::json::value const& v2,
        boost::json::value const& v3,
        boost::json::value const& v4,
        boost::json::value const& v5
    )
    {
        state().init_pairwise();
        return transit_to<Target>()(p, v0, v1, v2, v3, v4, v5);
    }
    Target Pairwise(Param const& p,
        boost::json::value const& v0,
        boost::json::value const& v1,
        boost::json::value const& v2,
        boost::json::value const& v3,
        boost::json::value const& v4,
        boost::json::value const& v5,
        boost::json::value const& v6
    )
    {
        state().init_pairwise();
        return transit_to<Target>()(p, v0, v1, v2, v3, v4, v5, v6);
    }
    Target Pairwise(Param const& p,
        boost::json::value const& v0,
        boost::json::value const& v1,
        boost::json::value const& v2,
        boost::json::value const& v3,
        boost::json::value const& v4,
        boost::json::value const& v5,
        boost::json::value const& v6,
        boost::json::value const& v7
    )
    {
        state().init_pairwise();
        return transit_to<Target>()(p, v0, v1, v2, v3, v4, v5, v6, v7);
    }

    template <class... A>
    Target Pairwise(Param const& p,
        boost::json::value const& v0,
        boost::json::value const& v1,
        boost::json::value const& v2,
        boost::json::value const& v3,
        boost::json::value const& v4,
        boost::json::value const& v5,
        boost::json::value const& v6,
        boost::json::value const& v7,
        A&&... args
    )
    {
        state().init_pairwise();
        return transit_to<Target>()(p, v0, v1, v2, v3, v4, v5, v6, v7, std::forward<A>(args)...);
    }
    template <class... A>
    Target Pairwise(Param const& p, A&&... args)
    {
        state().init_pairwise();
        return transit_to<Target>()(p, std::forward<A>(args)...);
    }
};


template <class Target>
struct ModelDefinition::T_CustomParam : protected virtual ModelDefinition::BaseTransition
{
    Target Parametrize(lang::Expression const&)
    {
        state().init_parametrize();
        return transit_to<Target>();
    }
};


template <class Target>
struct ModelDefinition::T_ParamRow : protected virtual ModelDefinition::BaseTransition
{
    template <class... A>
    Target operator()(Param const& p, A&&... args)
    {
        state().add_param_values_with_transform(p, args...);
        return transit_to<Target>();
    }

    Target operator()(Param const& p, boost::json::value const& v0)
    {
        state().add_param_values(p, boost::json::array{v0});
        return transit_to<Target>();
    }
    Target operator()(Param const& p, boost::json::value const& v0, boost::json::value const& v1)
    {
        state().add_param_values(p, {v0, v1});
        return transit_to<Target>();
    }

    Target operator()(Param const& p,
        boost::json::value const& v0,
        boost::json::value const& v1,
        boost::json::value const& v2
    )
    {
        state().add_param_values(p, {v0, v1, v2});
        return transit_to<Target>();
    }
    Target operator()(Param const& p,
        boost::json::value const& v0,
        boost::json::value const& v1,
        boost::json::value const& v2,
        boost::json::value const& v3
    )
    {
        state().add_param_values(p, {v0, v1, v2, v3});
        return transit_to<Target>();
    }
    Target operator()(Param const& p,
        boost::json::value const& v0,
        boost::json::value const& v1,
        boost::json::value const& v2,
        boost::json::value const& v3,
        boost::json::value const& v4
    )
    {
        state().add_param_values(p, {v0, v1, v2, v3, v4});
        return transit_to<Target>();
    }
    Target operator()(Param const& p,
        boost::json::value const& v0,
        boost::json::value const& v1,
        boost::json::value const& v2,
        boost::json::value const& v3,
        boost::json::value const& v4,
        boost::json::value const& v5
    )
    {
        state().add_param_values(p, {v0, v1, v2, v3, v4, v5});
        return transit_to<Target>();
    }
    Target operator()(Param const& p,
        boost::json::value const& v0,
        boost::json::value const& v1,
        boost::json::value const& v2,
        boost::json::value const& v3,
        boost::json::value const& v4,
        boost::json::value const& v5,
        boost::json::value const& v6
    )
    {
        state().add_param_values(p, {v0, v1, v2, v3, v4, v5, v6});
        return transit_to<Target>();
    }
    Target operator()(Param const& p,
        boost::json::value const& v0,
        boost::json::value const& v1,
        boost::json::value const& v2,
        boost::json::value const& v3,
        boost::json::value const& v4,
        boost::json::value const& v5,
        boost::json::value const& v6,
        boost::json::value const& v7
    )
    {
        state().add_param_values(p, {v0, v1, v2, v3, v4, v5, v6, v7});
        return transit_to<Target>();
    }
    template <class... A>
    Target operator()(Param const& p,
        boost::json::value const& v0,
        boost::json::value const& v1,
        boost::json::value const& v2,
        boost::json::value const& v3,
        boost::json::value const& v4,
        boost::json::value const& v5,
        boost::json::value const& v6,
        boost::json::value const& v7,
        A&&... args
    )
    {
        state().add_param_values_with_transform(p, v0, v1, v2, v3, v4, v5, v6, v7, std::forward<A>(args)...);
        return transit_to<Target>();
    }
};


template <class Target>
struct ModelDefinition::T_PreRun : protected virtual ModelDefinition::BaseTransition
{
    template <class... T>
    Target PreRun(T&&... tasks)
    {
        boost::mp11::tuple_for_each(std::forward_as_tuple(tasks...), [&](auto&& task) { state().add_task(task, true); });
        return transit_to<Target>();
    }
};


template <class Target>
struct ModelDefinition::T_PostRun : protected virtual ModelDefinition::BaseTransition
{
    template <class... T>
    Target PostRun(T&&... tasks)
    {
        boost::mp11::tuple_for_each(std::forward_as_tuple(tasks...), [&](auto&& task) { state().add_task(task, false); });
        return transit_to<Target>();
    }
};

}  // namespace mapping
}  // namespace zmbt


#endif