]>
Commit | Line | Data |
---|---|---|
e9174d1e SL |
1 | // Copyright 2015 The Rust Project Developers. See the COPYRIGHT |
2 | // file at the top-level directory of this distribution and at | |
3 | // http://rust-lang.org/COPYRIGHT. | |
4 | // | |
5 | // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | |
6 | // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | |
7 | // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | |
8 | // option. This file may not be copied, modified, or distributed | |
9 | // except according to those terms. | |
10 | ||
11 | //! Translates expressions into MIR. As a caller into this module, you | |
12 | //! have many options, but the first thing you have to decide is | |
13 | //! whether you are evaluating this expression for its *value*, its | |
14 | //! *location*, or as a *constant*. | |
15 | //! | |
16 | //! Typically, you want the value: e.g., if you are doing `expr_a + | |
17 | //! expr_b`, you want the values of those expressions. In that case, | |
18 | //! you want one of the following functions. Note that if the expr has | |
19 | //! a type that is not `Copy`, then using any of these functions will | |
20 | //! "move" the value out of its current home (if any). | |
21 | //! | |
22 | //! - `into` -- writes the value into a specific location, which | |
23 | //! should be uninitialized | |
24 | //! - `as_operand` -- evaluates the value and yields an `Operand`, | |
25 | //! suitable for use as an argument to an `Rvalue` | |
26 | //! - `as_temp` -- evaluates into a temporary; this is similar to `as_operand` | |
27 | //! except it always returns a fresh lvalue, even for constants | |
28 | //! - `as_rvalue` -- yields an `Rvalue`, suitable for use in an assignment; | |
29 | //! as of this writing, never needed outside of the `expr` module itself | |
30 | //! | |
31 | //! Sometimes though want the expression's *location*. An example | |
32 | //! would be during a match statement, or the operand of the `&` | |
33 | //! operator. In that case, you want `as_lvalue`. This will create a | |
34 | //! temporary if necessary. | |
35 | //! | |
36 | //! Finally, if it's a constant you seek, then call | |
37 | //! `as_constant`. This creates a `Constant<H>`, but naturally it can | |
38 | //! only be used on constant expressions and hence is needed only in | |
39 | //! very limited contexts. | |
40 | //! | |
41 | //! ### Implementation notes | |
42 | //! | |
43 | //! For any given kind of expression, there is generally one way that | |
44 | //! can be translated most naturally. This is specified by the | |
45 | //! `Category::of` function in the `category` module. For example, a | |
46 | //! struct expression (or other expression that creates a new value) | |
47 | //! is typically easiest to write in terms of `as_rvalue` or `into`, | |
48 | //! whereas a reference to a field is easiest to write in terms of | |
49 | //! `as_lvalue`. (The exception to this is scope and paren | |
50 | //! expressions, which have no category.) | |
51 | //! | |
52 | //! Therefore, the various functions above make use of one another in | |
53 | //! a descending fashion. For any given expression, you should pick | |
54 | //! the most suitable spot to implement it, and then just let the | |
55 | //! other fns cycle around. The handoff works like this: | |
56 | //! | |
57 | //! - `into(lv)` -> fallback is to create a rvalue with `as_rvalue` and assign it to `lv` | |
58 | //! - `as_rvalue` -> fallback is to create an Operand with `as_operand` and use `Rvalue::use` | |
59 | //! - `as_operand` -> either invokes `as_constant` or `as_temp` | |
60 | //! - `as_constant` -> (no fallback) | |
61 | //! - `as_temp` -> creates a temporary and either calls `as_lvalue` or `into` | |
62 | //! - `as_lvalue` -> for rvalues, falls back to `as_temp` and returns that | |
63 | //! | |
64 | //! As you can see, there is a cycle where `into` can (in theory) fallback to `as_temp` | |
65 | //! which can fallback to `into`. So if one of the `ExprKind` variants is not, in fact, | |
66 | //! implemented in the category where it is supposed to be, there will be a problem. | |
67 | //! | |
68 | //! Of those fallbacks, the most interesting one is `as_temp`, because | |
69 | //! it discriminates based on the category of the expression. This is | |
70 | //! basically the point where the "by value" operations are bridged | |
71 | //! over to the "by reference" mode (`as_lvalue`). | |
72 | ||
73 | mod as_constant; | |
74 | mod as_lvalue; | |
75 | mod as_rvalue; | |
76 | mod as_operand; | |
77 | mod as_temp; | |
78 | mod category; | |
79 | mod into; |