// 2020/08/28 - Created by netcan: https://github.com/netcan #pragma once #include "../core/flow_builder.hpp" #include "meta_macro.hpp" #include "task_analyzer.hpp" #include "task_trait.hpp" namespace tf { namespace dsl { struct EmptyContext {}; template class TaskDsl { using Links = Unique_t::type...>>>; using Analyzer = typename Links::template exportTo; using AllTasks = typename Analyzer::AllTasks; template struct TaskCbWithContext { using type = TaskCb; }; using TasksCB = typename Map_t::template exportTo; using OneToOneLinkSet = typename Analyzer::OneToOneLinkSet; template struct OneToOneLinkInstanceType { using type = typename OneToOneLink::template InstanceType; }; using OneToOneLinkInstances = typename Map_t::template exportTo; public: constexpr TaskDsl(FlowBuilder &flow_builder, const CONTEXT &context = {}) { build_tasks_cb(flow_builder, context, std::make_index_sequence{}); build_links(std::make_index_sequence{}); } template Task &get_task() { constexpr size_t TasksCBSize = std::tuple_size::value; constexpr size_t TaskIndex = TupleElementByF_v::template apply>; static_assert(TaskIndex < TasksCBSize, "fatal: not find TaskCb in TasksCB"); return std::get(tasksCb_).task_; } private: template void build_tasks_cb(FlowBuilder &flow_builder, const CONTEXT &context, std::index_sequence) { auto _ = {0, (std::get(tasksCb_).build(flow_builder, context), 0)...}; (void)_; } template void build_links(std::index_sequence) { auto _ = {0, (std::get(links_).build(tasksCb_), 0)...}; (void)_; } private: TasksCB tasksCb_; OneToOneLinkInstances links_; }; template constexpr TaskDsl taskDsl(FlowBuilder &flow_builder, CONTEXT &&context = {}) { return {flow_builder, context}; } } // namespace dsl } // namespace tf /////////////////////////////////////////////////////////////////////////////// #define TF_CHAIN(link) , link->void #define TF_CONTEXT_1(name) tf::dsl::EmptyContext #define TF_CONTEXT_2(name, context) context #define TF_CAPTURE_THIS_1 #define TF_CAPTURE_THIS_2 *this /////////////////////////////////////////////////////////////////////////////// // make_task(TASK_NAME, { return a action lambda }) #define make_task(name, ...) \ struct TF_GET_FIRST name : tf::dsl::TaskSignature, \ TF_PASTE(TF_CONTEXT_, TF_GET_ARG_COUNT name) \ name { \ using _ContextType = TF_PASTE(TF_CONTEXT_, TF_GET_ARG_COUNT name) name; \ TF_GET_FIRST name(const _ContextType &context) : _ContextType(context) {} \ auto operator()() { \ return [TF_PASTE(TF_CAPTURE_THIS_, TF_GET_ARG_COUNT name)] __VA_ARGS__; \ } \ } // some_tasks(A, B, C) means SomeTask #define some_tasks(...) auto (*)(tf::dsl::SomeTask<__VA_ARGS__>) // same as some_tasks #define fork_tasks(...) some_tasks(__VA_ARGS__) // same as some_tasks #define merge_tasks(...) some_tasks(__VA_ARGS__) // task(A) means a task A #define task(Task) auto (*)(Task) // taskbuild(...) build a task dsl graph #define build_taskflow(...) tf::dsl::taskDsl