]> git.lizzy.rs Git - rust.git/blob - src/librustc_mir/build/matches/util.rs
Fix BTreeMap example typo
[rust.git] / src / librustc_mir / build / matches / util.rs
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 use build::{BlockAnd, BlockAndExtension, Builder};
12 use build::matches::MatchPair;
13 use hair::*;
14 use rustc::mir::repr::*;
15 use std::u32;
16
17 impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
18     pub fn field_match_pairs<'pat>(&mut self,
19                                    lvalue: Lvalue<'tcx>,
20                                    subpatterns: &'pat [FieldPattern<'tcx>])
21                                    -> Vec<MatchPair<'pat, 'tcx>> {
22         subpatterns.iter()
23                    .map(|fieldpat| {
24                        let lvalue = lvalue.clone().field(fieldpat.field,
25                                                          fieldpat.pattern.ty);
26                        MatchPair::new(lvalue, &fieldpat.pattern)
27                    })
28                    .collect()
29     }
30
31     /// When processing an array/slice pattern like `lv @ [x, y, ..s, z]`,
32     /// this function converts the prefix (`x`, `y`) and suffix (`z`) into
33     /// distinct match pairs:
34     ///
35     /// ```rust,ignore
36     ///     lv[0 of 3] @ x  // see ProjectionElem::ConstantIndex (and its Debug impl)
37     ///     lv[1 of 3] @ y  // to explain the `[x of y]` notation
38     ///     lv[-1 of 3] @ z
39     /// ```
40     ///
41     /// If a slice like `s` is present, then the function also creates
42     /// a temporary like:
43     ///
44     /// ```rust,ignore
45     ///     tmp0 = lv[2..-1] // using the special Rvalue::Slice
46     /// ```
47     ///
48     /// and creates a match pair `tmp0 @ s`
49     pub fn prefix_suffix_slice<'pat>(&mut self,
50                                      match_pairs: &mut Vec<MatchPair<'pat, 'tcx>>,
51                                      block: BasicBlock,
52                                      lvalue: Lvalue<'tcx>,
53                                      prefix: &'pat [Pattern<'tcx>],
54                                      opt_slice: Option<&'pat Pattern<'tcx>>,
55                                      suffix: &'pat [Pattern<'tcx>])
56                                      -> BlockAnd<()> {
57         // If there is a `..P` pattern, create a temporary `t0` for
58         // the slice and then a match pair `t0 @ P`:
59         if let Some(slice) = opt_slice {
60             let prefix_len = prefix.len();
61             let suffix_len = suffix.len();
62             let rvalue = Rvalue::Slice {
63                 input: lvalue.clone(),
64                 from_start: prefix_len,
65                 from_end: suffix_len,
66             };
67             let temp = self.temp(slice.ty.clone()); // no need to schedule drop, temp is always copy
68             let source_info = self.source_info(slice.span);
69             self.cfg.push_assign(block, source_info, &temp, rvalue);
70             match_pairs.push(MatchPair::new(temp, slice));
71         }
72
73         self.prefix_suffix(match_pairs, lvalue, prefix, suffix);
74
75         block.unit()
76     }
77
78     /// Helper for `prefix_suffix_slice` which just processes the prefix and suffix.
79     fn prefix_suffix<'pat>(&mut self,
80                            match_pairs: &mut Vec<MatchPair<'pat, 'tcx>>,
81                            lvalue: Lvalue<'tcx>,
82                            prefix: &'pat [Pattern<'tcx>],
83                            suffix: &'pat [Pattern<'tcx>]) {
84         let min_length = prefix.len() + suffix.len();
85         assert!(min_length < u32::MAX as usize);
86         let min_length = min_length as u32;
87
88         let prefix_pairs: Vec<_> =
89             prefix.iter()
90                   .enumerate()
91                   .map(|(idx, subpattern)| {
92                       let elem = ProjectionElem::ConstantIndex {
93                           offset: idx as u32,
94                           min_length: min_length,
95                           from_end: false,
96                       };
97                       let lvalue = lvalue.clone().elem(elem);
98                       MatchPair::new(lvalue, subpattern)
99                   })
100                   .collect();
101
102         let suffix_pairs: Vec<_> =
103             suffix.iter()
104                   .rev()
105                   .enumerate()
106                   .map(|(idx, subpattern)| {
107                       let elem = ProjectionElem::ConstantIndex {
108                           offset: (idx+1) as u32,
109                           min_length: min_length,
110                           from_end: true,
111                       };
112                       let lvalue = lvalue.clone().elem(elem);
113                       MatchPair::new(lvalue, subpattern)
114                   })
115                   .collect();
116
117         match_pairs.extend(prefix_pairs.into_iter().chain(suffix_pairs));
118     }
119 }
120
121 impl<'pat, 'tcx> MatchPair<'pat, 'tcx> {
122     pub fn new(lvalue: Lvalue<'tcx>, pattern: &'pat Pattern<'tcx>) -> MatchPair<'pat, 'tcx> {
123         MatchPair {
124             lvalue: lvalue,
125             pattern: pattern,
126             slice_len_checked: false,
127         }
128     }
129 }