Advertisement
Guest User

Untitled

a guest
Oct 13th, 2016
133
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 12.25 KB | None | 0 0
  1. namespace ep
  2. {
  3.     namespace details
  4.     {
  5.  
  6.         namespace detail
  7.         {
  8.             template<unsigned... digits>
  9.             struct to_chars
  10.             {
  11.                 static const char value[];
  12.             };
  13.  
  14.             template<unsigned... digits>
  15.             const char to_chars<digits...>::value[] = { 'a', 'r', 'g', ( '0' + digits )..., 0 };
  16.  
  17.             template<unsigned rem, unsigned... digits>
  18.             struct explode : explode<rem / 10, rem % 10, digits...>
  19.             { };
  20.  
  21.             template<unsigned... digits>
  22.             struct explode<0, digits...> : to_chars<digits...>
  23.             { };
  24.         }
  25.  
  26.         template<unsigned num>
  27.         struct arg_pos_to_string : detail::explode<num>
  28.         { };
  29.  
  30.         struct _Ref_ptr
  31.         { };
  32.  
  33.         template<typename T>
  34.         struct callable_traits;
  35.  
  36.         template<typename Ret, typename...Params>
  37.         struct callable_traits<Ret( Params... )>
  38.         {
  39.             static constexpr auto size = sizeof...( Params );
  40.             using result_type = Ret;
  41.  
  42.             template<size_t pos>
  43.             struct arg_t
  44.             {
  45.                 using type = typename std::tuple_element<pos, std::tuple<Params...>>::type;
  46.             };
  47.         };
  48.  
  49.         template<typename _Deduce, bool ref = std::is_base_of<_Ref_ptr, _Deduce>::value>
  50.         struct _Var_deducer
  51.         {
  52.             static _Deduce deduce( ep::variable_ptr &ptr )
  53.             {
  54.                 return *ptr->get_ref( )->clone( )->get_pointer<_Deduce>( );
  55.             }
  56.         };
  57.  
  58.         template<typename _Deduce>
  59.         struct _Var_deducer<_Deduce*, false>
  60.         {
  61.             static _Deduce *deduce( ep::variable_ptr &ptr )
  62.             {
  63.                 return ptr->get_ref( )->get_pointer<_Deduce>( );
  64.             }
  65.         };
  66.  
  67.         template<typename _Deduce>
  68.         struct _Var_deducer<_Deduce&, false>
  69.         {
  70.             static _Deduce &deduce( ep::variable_ptr &ptr )
  71.             {
  72.                 return *ptr->get_ref( )->get_pointer<_Deduce>( );
  73.             }
  74.         };
  75.  
  76.         template<typename _Deduce>
  77.         struct _Var_deducer<_Deduce, true>
  78.         {
  79.             static _Deduce deduce( ep::variable_ptr &ptr )
  80.             {
  81.                 return _Deduce( ptr );
  82.             }
  83.         };
  84.  
  85.         template<>
  86.         struct _Var_deducer<variable_ptr, false>
  87.         {
  88.             static variable_ptr deduce( ep::variable_ptr &ptr )
  89.             {
  90.                 return ptr;
  91.             }
  92.         };
  93.  
  94.         template<size_t pos, size_t max, typename Traits, typename Ret = typename Traits::result_type>
  95.         struct _Caller
  96.         {
  97.             template<typename Func, typename...Deduced>
  98.             static auto
  99.                 _Process_and_call( ep::variable_list &a,
  100.                                    Func &&f,
  101.                                    Deduced&&...deduced )
  102.             {
  103.                 using arg_type = typename Traits::template arg_t<pos>::type;
  104.                 return _Caller<pos + 1, max, Traits>::_Process_and_call( a,
  105.                                                                          std::forward<Func>( f ),
  106.                                                                          std::forward<Deduced>( deduced )...,
  107.                                                                          _Var_deducer<arg_type>::deduce( a[pos] ) );
  108.             }
  109.         };
  110.  
  111.         template<size_t max, typename Traits, typename Ret>
  112.         struct _Caller<max, max, Traits, Ret>
  113.         {
  114.             template<typename Func, typename...Deduced>
  115.             static typename Traits::result_type
  116.                 _Process_and_call( ep::variable_list &a,
  117.                                    Func &&f,
  118.                                    Deduced&&...deduced )
  119.             {
  120.                 return std::forward<Func>( f )( std::forward<Deduced>( deduced )... );
  121.             }
  122.         };
  123.  
  124.         template<size_t max, typename Traits>
  125.         struct _Caller<max, max, Traits, void>
  126.         {
  127.             template<typename Func, typename...Deduced>
  128.             static ep::value_reference_ptr
  129.                 _Process_and_call( ep::variable_list &a,
  130.                                    Func &&f,
  131.                                    Deduced&&...deduced )
  132.             {
  133.                 std::forward<Func>( f )( std::forward<Deduced>( deduced )... );
  134.                 return ep::void_return;
  135.             }
  136.         };
  137.  
  138.         template<size_t pos, size_t max, typename traits>
  139.         struct _Arg_emplacer
  140.         {
  141.             static void emplace( ep::method_argument_list &list )
  142.             {
  143.                 using arg_t = typename traits::template arg_t<pos>::type;
  144.                 list.emplace_back( new ep::method_argument( arg_pos_to_string<pos>::value,
  145.                                                             std::is_reference<arg_t>::value || std::is_base_of<_Ref_ptr, arg_t>::value ) );
  146.                 _Arg_emplacer<pos + 1, max, traits>::emplace( list );
  147.             }
  148.         };
  149.  
  150.         template<size_t max, typename traits>
  151.         struct _Arg_emplacer<max, max, traits>
  152.         {
  153.             static void emplace( ep::method_argument_list &list )
  154.             { }
  155.         };
  156.  
  157.         template<typename T>
  158.         struct _Build_method_from_t
  159.         {
  160.             template<typename _Invalid>
  161.             static ep::method_ptr _Build( std::string, _Invalid &&invalid )
  162.             {
  163.                 throw;
  164.             }
  165.         };
  166.  
  167.         template<typename Ret, typename T, typename...Params>
  168.         struct _Build_method_from_t<Ret( T::* )( Params... ) const>
  169.         {
  170.             template<typename _Func>
  171.             static ep::method_ptr _Build( std::string name, _Func &&functor )
  172.             {
  173.                 using traits = callable_traits<Ret( Params... )>;
  174.                 ep::method_argument_list args;
  175.                 auto method = [func = std::function<Ret( Params... )>( std::forward<_Func>( functor ) )]( ep::variable_list fargs,
  176.                                                                                                           ep::dispatch_engine_ptr )
  177.                 {
  178.                     return _Caller<0, traits::size, traits>::_Process_and_call( fargs,
  179.                                                                                 func );
  180.                 };
  181.                 _Arg_emplacer<0, traits::size, traits>::emplace( args );
  182.                 return std::make_shared<ep::method>( std::move( name ),
  183.                                                      std::move( args ),
  184.                                                      std::move( method ) );
  185.             }
  186.         };
  187.  
  188.         template<typename Ret, typename T>
  189.         struct _Build_method_from_t<Ret( T::* )( ) const>
  190.         {
  191.             template<typename _Func>
  192.             static ep::method_ptr _Build( std::string name, _Func &&functor )
  193.             {
  194.                 using traits = callable_traits<Ret( )>;
  195.                 ep::method_argument_list args;
  196.                 auto method = [func = std::function<Ret( )>( std::forward<_Func>( functor ) )]( ep::variable_list fargs,
  197.                                                                                                 ep::dispatch_engine_ptr )
  198.                 {
  199.                     return func( );
  200.                 };
  201.                 _Arg_emplacer<0, traits::size, traits>::emplace( args );
  202.                 return std::make_shared<ep::method>( std::move( name ),
  203.                                                      std::move( args ),
  204.                                                      std::move( method ) );
  205.             }
  206.         };
  207.  
  208.         template<typename T>
  209.         struct _Build_member_method_from_t
  210.         {
  211.             template<typename _Invalid>
  212.             static ep::method_ptr _Build( std::string name,
  213.                                           _Invalid && )
  214.             {
  215.                 static_assert( false, "_Build_member_method_from_t expects callable object as T" );
  216.             }
  217.         };
  218.  
  219.         template<typename Ret, typename T, typename...Params>
  220.         struct _Build_member_method_from_t<Ret( T::* )( Params... ) const>
  221.         {
  222.             template<typename _Func>
  223.             static ep::method_ptr _Build( std::string name,
  224.                                           _Func &&functor )
  225.             {
  226.                 using traits = callable_traits<Ret( Params... )>;
  227.                 ep::method_argument_list args;
  228.                 auto method = [func = std::function<Ret( Params... )>( std::forward<_Func>( functor ) )]( ep::variable_list fargs,
  229.                                                                                                           ep::dispatch_engine_ptr )
  230.                 {
  231.                     return _Caller<0, traits::size, traits>::_Process_and_call( fargs,
  232.                                                                                 func );
  233.                 };
  234.                 _Arg_emplacer<1, traits::size, traits>::emplace( args );
  235.                 return std::make_shared<ep::method>( std::move( name ),
  236.                                                      std::move( args ),
  237.                                                      std::move( method ) );
  238.             }
  239.         };
  240.  
  241.         template<typename Ret, typename T>
  242.         struct _Build_member_method_from_t<Ret( T::* )( ) const>
  243.         {
  244.             template<typename _Func>
  245.             static ep::method_ptr _Build( std::string name,
  246.                                           _Func &&functor )
  247.             {
  248.                 using traits = callable_traits<Ret( )>;
  249.                 ep::method_argument_list args;
  250.                 auto method = [func = std::function<Ret( )>( std::forward<_Func>( functor ) )]( ep::variable_list fargs,
  251.                                                                                                 ep::dispatch_engine_ptr )
  252.                 {
  253.                     return _Caller<0, traits::size, traits>::_Process_and_call( fargs,
  254.                                                                                 func );
  255.                 };
  256.                 _Arg_emplacer<1, traits::size, traits>::emplace( args );
  257.                 return std::make_shared<ep::method>( std::move( name ),
  258.                                                      std::move( args ),
  259.                                                      std::move( method ) );
  260.             }
  261.         };
  262.  
  263.         template<typename..._Specialization>
  264.         struct create_type_impl;
  265.  
  266.         template<>
  267.         struct create_type_impl<>
  268.         {
  269.             static ep::type_info_ptr _Do( ep::type_info_ptr ti )
  270.             {
  271.                 return std::move( ti );
  272.             }
  273.         };
  274.  
  275.         template<typename Str, typename T, typename..._Specialization>
  276.         struct create_type_impl<Str, T, _Specialization...>
  277.         {
  278.             static ep::type_info_ptr _Do( ep::type_info_ptr ti,
  279.                                           Str &&str,
  280.                                           T &&t,
  281.                                           _Specialization&&...spec )
  282.             {
  283.                 ti->add_method( std::move( _Build_member_method_from_t<decltype( &T::operator() )>::_Build( std::forward<Str>( str ),
  284.                                                                                                             std::forward<T>( t ) ) ) );
  285.                 return create_type_impl<_Specialization...>::_Do( std::move( ti ),
  286.                                                                   std::forward<_Specialization>( spec )... );
  287.             }
  288.         };
  289.  
  290.         template<typename Str, typename T>
  291.         struct create_type_impl<Str, T>
  292.         {
  293.             static ep::type_info_ptr _Do( ep::type_info_ptr ti,
  294.                                           Str &&str,
  295.                                           T &&t )
  296.             {
  297.                 ti->add_method( std::move( _Build_member_method_from_t<decltype( &T::operator() )>::_Build( std::forward<Str>( str ),
  298.                                                                                                             std::forward<T>( t ) ) ) );
  299.                 return std::move( ti );
  300.             }
  301.         };
  302.  
  303.         template<size_t arity, size_t mod = arity % 2>
  304.         struct _Check_arity_impl;
  305.  
  306.         template<typename..._Arity>
  307.         struct _Check_arity
  308.         {
  309.             static constexpr bool value = _Check_arity_impl<sizeof...( _Arity )>::value;
  310.         };
  311.  
  312.         template<>
  313.         struct _Check_arity<>
  314.         {
  315.             static constexpr bool value = true;
  316.         };
  317.  
  318.  
  319.         template<size_t arity>
  320.         struct _Check_arity_impl<arity, 0>
  321.         {
  322.             static constexpr bool value = false;
  323.         };
  324.  
  325.         template<size_t arity, size_t mod>
  326.         struct _Check_arity_impl
  327.         {
  328.             static constexpr bool value = true;
  329.         };
  330.     }
  331.  
  332.     template<typename _Dtor, typename _Ctor, typename..._Specialization>
  333.     static ep::type_info_ptr create_type( std::string name, _Dtor &&dtor, _Ctor &&ctor, _Specialization&&...spec )
  334.     {
  335.         static_assert( !details::_Check_arity<_Specialization...>::value,
  336.                        "uneven arity, expects arity of pattern (StrConvertable, Callable, Continuation...)" );
  337.         return details::create_type_impl<_Specialization...>::_Do( std::make_shared<ep::type_info>( std::move( name ),
  338.                                                                                                     std::forward<_Dtor>( dtor ),
  339.                                                                                                     std::forward<_Ctor>( ctor ) ),
  340.                                                                    std::forward<_Specialization>( spec )... );
  341.     }
  342.  
  343.     template<typename _Ctor, typename _Dtor, typename _Clone, typename..._Specialization>
  344.     static void add_type( ep::module_ptr &module,
  345.                           std::string name,
  346.                           _Ctor &&ctor,
  347.                           _Dtor &&dtor,
  348.                           _Clone &&clone,
  349.                           _Specialization&&...spec )
  350.     {
  351.         auto engine = module->get_engine( );
  352.         auto type = create_type( name,
  353.                                  std::forward<_Dtor>( dtor ),
  354.                                  std::forward<_Clone>( clone ),
  355.                                  std::forward<_Specialization>( spec )... );
  356.         engine->add_method( details::_Build_method_from_t<decltype( &_Ctor::operator() )>::_Build( std::move( name ),
  357.                                                                                                    std::forward<_Ctor>( ctor ) ) );
  358.         engine->add_type( std::move( type ) );
  359.  
  360.     }
  361.  
  362.     template<typename _Ctor, typename _Dtor, typename _Clone, typename..._Specialization>
  363.     static void add_type( ep::dispatch_engine_ptr &engine,
  364.                           std::string name,
  365.                           _Ctor &&ctor,
  366.                           _Dtor &&dtor,
  367.                           _Clone &&clone,
  368.                           _Specialization&&...spec )
  369.     {
  370.         auto type = create_type( name,
  371.                                  std::forward<_Dtor>( dtor ),
  372.                                  std::forward<_Clone>( clone ),
  373.                                  std::forward<_Specialization>( spec )... );
  374.  
  375.         engine->add_method( details::_Build_method_from_t<decltype( &_Ctor::operator() )>::_Build( std::move( name ),
  376.                                                                                                    std::forward<_Ctor>( ctor ) ) );
  377.         engine->add_type( std::move( type ) );
  378.     }
  379.  
  380.     template<typename Str, typename T>
  381.     static auto make_method( Str && str,
  382.                              T &&t )
  383.     {
  384.         return details::_Build_method_from_t<decltype( &T::operator() )>::_Build( std::forward<Str>( str ),
  385.                                                                                   std::forward<T>( t ) );
  386.     }
  387.  
  388.     template<typename T, typename...Ts>
  389.     static plugin_list load_plugins_impl( plugin_list &output, T &&t, Ts&&...ts )
  390.     {
  391.         output.emplace_back( load_plugin( std::forward<T>( t ) ) );
  392.         return load_plugins_impl( output, std::forward<Ts>( ts )... );
  393.     }
  394.  
  395.     template<typename T>
  396.     static plugin_list load_plugins_impl( plugin_list &output, T &&t )
  397.     {
  398.         output.emplace_back( load_plugin( std::forward<T>( t ) ) );
  399.         return output;
  400.     }
  401.  
  402.     template<typename...Ts>
  403.     static plugin_list load_plugins( Ts&&...ts )
  404.     {
  405.         plugin_list list;
  406.         return load_plugins_impl( list, std::forward<Ts>( ts )... );
  407.     }
  408.  
  409.     // wrapper for passing variable_ptr as reference
  410.     struct argument_ptr_ref
  411.         : public details::_Ref_ptr
  412.     {
  413.         using ref = void;
  414.         variable_ptr variable;
  415.  
  416.         argument_ptr_ref( ep::variable_ptr &ptr )
  417.             : variable( ptr )
  418.         { }
  419.     };
  420.  
  421.  
  422. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement