1 #ifndef HALIDE_VAR_H
2 #define HALIDE_VAR_H
3 
4 /** \file
5  * Defines the Var - the front-end variable
6  */
7 #include <string>
8 #include <vector>
9 
10 #include "Expr.h"
11 
12 namespace Halide {
13 
14 /** A Halide variable, to be used when defining functions. It is just
15  * a name, and can be reused in places where no name conflict will
16  * occur. It can be used in the left-hand-side of a function
17  * definition, or as an Expr. As an Expr, it always has type
18  * Int(32). */
19 class Var {
20     /* The expression representing the Var. Guaranteed to be an
21      * Internal::Variable of type Int(32). Created once on
22      * construction of the Var to avoid making a fresh Expr every time
23      * the Var is used in a context in which is will be converted to
24      * one. */
25     Expr e;
26 
27 public:
28     /** Construct a Var with the given name */
29     Var(const std::string &n);
30 
31     /** Construct a Var with an automatically-generated unique name. */
32     Var();
33 
34     /** Get the name of a Var */
35     const std::string &name() const;
36 
37     /** Test if two Vars are the same. This simply compares the names. */
same_as(const Var & other)38     bool same_as(const Var &other) const {
39         return name() == other.name();
40     }
41 
42     /** Implicit var constructor. Implicit variables are injected
43      * automatically into a function call if the number of arguments
44      * to the function are fewer than its dimensionality and a
45      * placeholder ("_") appears in its argument list. Defining a
46      * function to equal an expression containing implicit variables
47      * similarly appends those implicit variables, in the same order,
48      * to the left-hand-side of the definition where the placeholder
49      * ('_') appears.
50      *
51      * For example, consider the definition:
52      *
53      \code
54      Func f, g;
55      Var x, y;
56      f(x, y) = 3;
57      \endcode
58      *
59      * A call to f with the placeholder symbol _
60      * will have implicit arguments injected automatically, so f(2, _)
61      * is equivalent to f(2, _0), where _0 = ImplicitVar<0>(), and f(_)
62      * (and indeed f when cast to an Expr) is equivalent to f(_0, _1).
63      * The following definitions are all equivalent, differing only in the
64      * variable names.
65      *
66      \code
67      g(_) = f*3;
68      g(_) = f(_)*3;
69      g(x, _) = f(x, _)*3;
70      g(x, y) = f(x, y)*3;
71      \endcode
72      *
73      * These are expanded internally as follows:
74      *
75      \code
76      g(_0, _1) = f(_0, _1)*3;
77      g(_0, _1) = f(_0, _1)*3;
78      g(x, _0) = f(x, _0)*3;
79      g(x, y) = f(x, y)*3;
80      \endcode
81      *
82      * The following, however, defines g as four dimensional:
83      \code
84      g(x, y, _) = f*3;
85      \endcode
86      *
87      * It is equivalent to:
88      *
89      \code
90      g(x, y, _0, _1) = f(_0, _1)*3;
91      \endcode
92      *
93      * Expressions requiring differing numbers of implicit variables
94      * can be combined. The left-hand-side of a definition injects
95      * enough implicit variables to cover all of them:
96      *
97      \code
98      Func h;
99      h(x) = x*3;
100      g(x) = h + (f + f(x)) * f(x, y);
101      \endcode
102      *
103      * expands to:
104      *
105      \code
106      Func h;
107      h(x) = x*3;
108      g(x, _0, _1) = h(_0) + (f(_0, _1) + f(x, _0)) * f(x, y);
109      \endcode
110      *
111      * The first ten implicits, _0 through _9, are predeclared in this
112      * header and can be used for scheduling. They should never be
113      * used as arguments in a declaration or used in a call.
114      *
115      * While it is possible to use Var::implicit or the predeclared
116      * implicits to create expressions that can be treated as small
117      * anonymous functions (e.g. Func(_0 + _1)) this is considered
118      * poor style. Instead use \ref lambda.
119      */
120     static Var implicit(int n);
121 
122     /** Return whether a variable name is of the form for an implicit argument.
123      * TODO: This is almost guaranteed to incorrectly fire on user
124      * declared variables at some point. We should likely prevent
125      * user Var declarations from making names of this form.
126      */
127     //{
128     static bool is_implicit(const std::string &name);
is_implicit()129     bool is_implicit() const {
130         return is_implicit(name());
131     }
132     //}
133 
134     /** Return the argument index for a placeholder argument given its
135      *  name. Returns 0 for _0, 1 for _1, etc. Returns -1 if
136      *  the variable is not of implicit form.
137      */
138     //{
implicit_index(const std::string & name)139     static int implicit_index(const std::string &name) {
140         return is_implicit(name) ? atoi(name.c_str() + 1) : -1;
141     }
implicit_index()142     int implicit_index() const {
143         return implicit_index(name());
144     }
145     //}
146 
147     /** Test if a var is the placeholder variable _ */
148     //{
is_placeholder(const std::string & name)149     static bool is_placeholder(const std::string &name) {
150         return name == "_";
151     }
is_placeholder()152     bool is_placeholder() const {
153         return is_placeholder(name());
154     }
155     //}
156 
157     /** A Var can be treated as an Expr of type Int(32) */
158     operator const Expr &() const {
159         return e;
160     }
161 
162     /** A Var that represents the location outside the outermost loop. */
outermost()163     static Var outermost() {
164         return Var("__outermost");
165     }
166 };
167 
168 template<int N = -1>
169 struct ImplicitVar {
to_varImplicitVar170     Var to_var() const {
171         if (N >= 0) {
172             return Var::implicit(N);
173         } else {
174             return Var("_");
175         }
176     }
177 
VarImplicitVar178     operator Var() const {
179         return to_var();
180     }
ExprImplicitVar181     operator Expr() const {
182         return to_var();
183     }
184 };
185 
186 /** A placeholder variable for inferred arguments. See \ref Var::implicit */
187 static constexpr ImplicitVar<> _;
188 
189 /** The first ten implicit Vars for use in scheduling. See \ref Var::implicit */
190 // @{
191 static constexpr ImplicitVar<0> _0;
192 static constexpr ImplicitVar<1> _1;
193 static constexpr ImplicitVar<2> _2;
194 static constexpr ImplicitVar<3> _3;
195 static constexpr ImplicitVar<4> _4;
196 static constexpr ImplicitVar<5> _5;
197 static constexpr ImplicitVar<6> _6;
198 static constexpr ImplicitVar<7> _7;
199 static constexpr ImplicitVar<8> _8;
200 static constexpr ImplicitVar<9> _9;
201 // @}
202 
203 namespace Internal {
204 
205 /** Make a list of unique arguments for definitions with unnamed
206     arguments. */
207 std::vector<Var> make_argument_list(int dimensionality);
208 
209 }  // namespace Internal
210 
211 }  // namespace Halide
212 
213 #endif
214