liuxiaolong
2021-07-20 58d904a328c0d849769b483e901a0be9426b8209
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
// Copyright (C) 2016-2018 T. Zachary Laine
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_YAP_ALGORITHM_FWD_HPP_INCLUDED
#define BOOST_YAP_ALGORITHM_FWD_HPP_INCLUDED
 
#include <boost/yap/config.hpp>
 
#include <boost/hana/integral_constant.hpp>
#include <boost/hana/tuple.hpp>
#include <boost/hana/core/is_a.hpp>
 
 
namespace boost { namespace yap {
 
    /** The enumeration representing all the kinds of expressions supported in
        YAP.
    */
    enum class expr_kind {
        expr_ref =
            0, ///< A (possibly \c const) reference to another expression.
 
        terminal = 1, ///< A terminal expression.
 
        // unary
        unary_plus = 2,  ///< \c +
        negate = 3,      ///< \c -
        dereference = 4, ///< \c *
        complement = 5,  ///< \c ~
        address_of = 6,  ///< \c &
        logical_not = 7, ///< \c !
        pre_inc = 8,     ///< \c ++
        pre_dec = 9,     ///< \c \-\-
        post_inc = 10,   ///< \c ++(int)
        post_dec = 11,   ///< \c \-\-(int)
 
        // binary
        shift_left = 12,         ///< \c <<
        shift_right = 13,        ///< \c >>
        multiplies = 14,         ///< \c *
        divides = 15,            ///< \c /
        modulus = 16,            ///< \c %
        plus = 17,               ///< \c +
        minus = 18,              ///< \c -
        less = 19,               ///< \c <
        greater = 20,            ///< \c >
        less_equal = 21,         ///< \c <=
        greater_equal = 22,      ///< \c >=
        equal_to = 23,           ///< \c ==
        not_equal_to = 24,       ///< \c !=
        logical_or = 25,         ///< \c ||
        logical_and = 26,        ///< \c &&
        bitwise_and = 27,        ///< \c &
        bitwise_or = 28,         ///< \c |
        bitwise_xor = 29,        ///< \c ^
        comma = 30,              ///< \c ,
        mem_ptr = 31,            ///< \c ->*
        assign = 32,             ///< \c =
        shift_left_assign = 33,  ///< \c <<=
        shift_right_assign = 34, ///< \c >>=
        multiplies_assign = 35,  ///< \c *=
        divides_assign = 36,     ///< \c /=
        modulus_assign = 37,     ///< \c %=
        plus_assign = 38,        ///< \c +=
        minus_assign = 39,       ///< \c -=
        bitwise_and_assign = 40, ///< \c &=
        bitwise_or_assign = 41,  ///< \c |=
        bitwise_xor_assign = 42, ///< \c ^=
        subscript = 43,          ///< \c []
 
        // ternary
        if_else = 44, ///< Analogous to \c ?: .
 
        // n-ary
        call = 45 ///< \c ()
    };
 
    /** The type used to represent the index of a placeholder terminal. */
    template<long long I>
    struct placeholder : hana::llong<I>
    {
    };
 
#ifdef BOOST_YAP_DOXYGEN
 
    /** A metafunction that evaluates to std::true_type if \a Expr is an
        Expression, and std::false_type otherwise. */
    template<typename Expr>
    struct is_expr;
 
#else
 
    template<expr_kind Kind, typename Tuple>
    struct expression;
 
    namespace detail {
 
        // void_t
 
        template<class...>
        using void_t = void;
 
        // remove_cv_ref
 
        template<typename T>
        struct remove_cv_ref : std::remove_cv<std::remove_reference_t<T>>
        {
        };
 
        template<typename T>
        using remove_cv_ref_t = typename remove_cv_ref<T>::type;
    }
 
    template<
        typename Expr,
        typename = detail::void_t<>,
        typename = detail::void_t<>>
    struct is_expr : std::false_type
    {
    };
 
    template<typename Expr>
    struct is_expr<
        Expr,
        detail::void_t<decltype(detail::remove_cv_ref_t<Expr>::kind)>,
        detail::void_t<decltype(std::declval<Expr>().elements)>>
        : std::integral_constant<
              bool,
              std::is_same<
                  std::remove_cv_t<decltype(
                      detail::remove_cv_ref_t<Expr>::kind)>,
                  expr_kind>::value &&
                  hana::is_a<
                      hana::tuple_tag,
                      decltype(std::declval<Expr>().elements)>>
    {
    };
 
#endif // BOOST_YAP_DOXYGEN
 
    /** A convenience alias for a terminal expression holding a \a T,
        instantiated from expression template \a expr_template. */
    template<template<expr_kind, class> class expr_template, typename T>
    using terminal = expr_template<expr_kind::terminal, hana::tuple<T>>;
 
    /** A convenience alias for a reference expression holding an expression
        \a T, instantiated from expression template \a expr_template. */
    template<template<expr_kind, class> class expr_template, typename T>
    using expression_ref = expr_template<
        expr_kind::expr_ref,
        hana::tuple<std::remove_reference_t<T> *>>;
 
#ifndef BOOST_YAP_DOXYGEN
 
    template<typename Expr, typename... T>
    constexpr decltype(auto) evaluate(Expr && expr, T &&... t);
 
    template<typename Expr, typename Transform, typename... Transforms>
    constexpr decltype(auto) transform(
        Expr && expr, Transform && transform, Transforms &&... transforms);
 
    template<typename Expr, typename Transform, typename... Transforms>
    constexpr decltype(auto) transform_strict(
        Expr && expr, Transform && transform, Transforms &&... transforms);
 
    template<typename T>
    constexpr decltype(auto) deref(T && x);
 
    template<typename Expr>
    constexpr decltype(auto) value(Expr && expr);
 
#endif // BOOST_YAP_DOXYGEN
 
    namespace literals {
 
        /** Creates literal placeholders.  Placeholder indices are 1-based. */
        template<char... c>
        constexpr auto operator"" _p()
        {
            using i = hana::llong<hana::ic_detail::parse<sizeof...(c)>({c...})>;
            static_assert(1 <= i::value, "Placeholders must be >= 1.");
            return expression<
                expr_kind::terminal,
                hana::tuple<placeholder<i::value>>>{};
        }
    }
 
    /** Used as the tag-type passed to a transform function written in the
        tag-transform form. */
    template<expr_kind Kind>
    struct expr_tag
    {
        static const expr_kind kind = Kind;
    };
 
    /** Used as the expression template returned by some operations inside YAP
        when YAP does not have an expression template it was told to use.  For
        instance, if transform() creates a new expression by transforming an
        existing expression's elements, it will attempt to create the new
        expression using the existing one's expression template.  If no such
        template exists because the existing expression was not made from an
        expression template, minimal_expr is used. */
    template<expr_kind Kind, typename Tuple>
    struct minimal_expr
    {
        static expr_kind const kind = Kind;
        Tuple elements;
    };
 
}}
 
#endif