]> git.lizzy.rs Git - rust.git/blob - src/libsyntax/ext/deriving/ty.rs
Ignore tests broken by failing on ICE
[rust.git] / src / libsyntax / ext / deriving / ty.rs
1 // Copyright 2013 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 /*!
12 A mini version of ast::Ty, which is easier to use, and features an
13 explicit `Self` type to use when specifying impls to be derived.
14 */
15
16 use ast;
17 use ast::{P,Expr,Generics,Ident};
18 use ext::base::ExtCtxt;
19 use ext::build::AstBuilder;
20 use codemap::{Span,respan};
21 use owned_slice::OwnedSlice;
22
23 /// The types of pointers
24 pub enum PtrTy<'a> {
25     Send, // ~
26     Borrowed(Option<&'a str>, ast::Mutability), // &['lifetime] [mut]
27 }
28
29 /// A path, e.g. `::std::option::Option::<int>` (global). Has support
30 /// for type parameters and a lifetime.
31 pub struct Path<'a> {
32     pub path: Vec<&'a str> ,
33     pub lifetime: Option<&'a str>,
34     pub params: Vec<~Ty<'a>> ,
35     pub global: bool,
36 }
37
38 impl<'a> Path<'a> {
39     pub fn new<'r>(path: Vec<&'r str> ) -> Path<'r> {
40         Path::new_(path, None, Vec::new(), true)
41     }
42     pub fn new_local<'r>(path: &'r str) -> Path<'r> {
43         Path::new_(vec!( path ), None, Vec::new(), false)
44     }
45     pub fn new_<'r>(path: Vec<&'r str> ,
46                     lifetime: Option<&'r str>,
47                     params: Vec<~Ty<'r>> ,
48                     global: bool)
49                     -> Path<'r> {
50         Path {
51             path: path,
52             lifetime: lifetime,
53             params: params,
54             global: global
55         }
56     }
57
58     pub fn to_ty(&self,
59                  cx: &ExtCtxt,
60                  span: Span,
61                  self_ty: Ident,
62                  self_generics: &Generics)
63                  -> P<ast::Ty> {
64         cx.ty_path(self.to_path(cx, span, self_ty, self_generics), None)
65     }
66     pub fn to_path(&self,
67                    cx: &ExtCtxt,
68                    span: Span,
69                    self_ty: Ident,
70                    self_generics: &Generics)
71                    -> ast::Path {
72         let idents = self.path.iter().map(|s| cx.ident_of(*s)).collect();
73         let lt = mk_lifetimes(cx, span, &self.lifetime);
74         let tys = self.params.iter().map(|t| t.to_ty(cx, span, self_ty, self_generics)).collect();
75
76         cx.path_all(span, self.global, idents, lt, tys)
77     }
78 }
79
80 /// A type. Supports pointers (except for *), Self, and literals
81 pub enum Ty<'a> {
82     Self,
83     // &/~/@ Ty
84     Ptr(~Ty<'a>, PtrTy<'a>),
85     // mod::mod::Type<[lifetime], [Params...]>, including a plain type
86     // parameter, and things like `int`
87     Literal(Path<'a>),
88     // includes nil
89     Tuple(Vec<Ty<'a>> )
90 }
91
92 pub fn borrowed_ptrty<'r>() -> PtrTy<'r> {
93     Borrowed(None, ast::MutImmutable)
94 }
95 pub fn borrowed<'r>(ty: ~Ty<'r>) -> Ty<'r> {
96     Ptr(ty, borrowed_ptrty())
97 }
98
99 pub fn borrowed_explicit_self<'r>() -> Option<Option<PtrTy<'r>>> {
100     Some(Some(borrowed_ptrty()))
101 }
102
103 pub fn borrowed_self<'r>() -> Ty<'r> {
104     borrowed(box Self)
105 }
106
107 pub fn nil_ty() -> Ty<'static> {
108     Tuple(Vec::new())
109 }
110
111 fn mk_lifetime(cx: &ExtCtxt, span: Span, lt: &Option<&str>) -> Option<ast::Lifetime> {
112     match *lt {
113         Some(ref s) => Some(cx.lifetime(span, cx.ident_of(*s).name)),
114         None => None
115     }
116 }
117
118 fn mk_lifetimes(cx: &ExtCtxt, span: Span, lt: &Option<&str>) -> Vec<ast::Lifetime> {
119     match *lt {
120         Some(ref s) => vec!(cx.lifetime(span, cx.ident_of(*s).name)),
121         None => vec!()
122     }
123 }
124
125 impl<'a> Ty<'a> {
126     pub fn to_ty(&self,
127                  cx: &ExtCtxt,
128                  span: Span,
129                  self_ty: Ident,
130                  self_generics: &Generics)
131                  -> P<ast::Ty> {
132         match *self {
133             Ptr(ref ty, ref ptr) => {
134                 let raw_ty = ty.to_ty(cx, span, self_ty, self_generics);
135                 match *ptr {
136                     Send => {
137                         cx.ty_uniq(span, raw_ty)
138                     }
139                     Borrowed(ref lt, mutbl) => {
140                         let lt = mk_lifetime(cx, span, lt);
141                         cx.ty_rptr(span, raw_ty, lt, mutbl)
142                     }
143                 }
144             }
145             Literal(ref p) => { p.to_ty(cx, span, self_ty, self_generics) }
146             Self  => {
147                 cx.ty_path(self.to_path(cx, span, self_ty, self_generics), None)
148             }
149             Tuple(ref fields) => {
150                 let ty = if fields.is_empty() {
151                     ast::TyNil
152                 } else {
153                     ast::TyTup(fields.iter()
154                                      .map(|f| f.to_ty(cx, span, self_ty, self_generics))
155                                      .collect())
156                 };
157
158                 cx.ty(span, ty)
159             }
160         }
161     }
162
163     pub fn to_path(&self,
164                    cx: &ExtCtxt,
165                    span: Span,
166                    self_ty: Ident,
167                    self_generics: &Generics)
168                    -> ast::Path {
169         match *self {
170             Self => {
171                 let self_params = self_generics.ty_params.map(|ty_param| {
172                     cx.ty_ident(span, ty_param.ident)
173                 });
174                 let lifetimes = self_generics.lifetimes.clone();
175
176                 cx.path_all(span, false, vec!(self_ty), lifetimes,
177                             self_params.into_vec())
178             }
179             Literal(ref p) => {
180                 p.to_path(cx, span, self_ty, self_generics)
181             }
182             Ptr(..) => { cx.span_bug(span, "pointer in a path in generic `deriving`") }
183             Tuple(..) => { cx.span_bug(span, "tuple in a path in generic `deriving`") }
184         }
185     }
186 }
187
188
189 fn mk_ty_param(cx: &ExtCtxt, span: Span, name: &str, sized: ast::Sized, bounds: &[Path],
190                self_ident: Ident, self_generics: &Generics) -> ast::TyParam {
191     let bounds =
192         bounds.iter().map(|b| {
193             let path = b.to_path(cx, span, self_ident, self_generics);
194             cx.typarambound(path)
195         }).collect();
196     cx.typaram(span, cx.ident_of(name), sized, bounds, None)
197 }
198
199 fn mk_generics(lifetimes: Vec<ast::Lifetime> ,  ty_params: Vec<ast::TyParam> ) -> Generics {
200     Generics {
201         lifetimes: lifetimes,
202         ty_params: OwnedSlice::from_vec(ty_params)
203     }
204 }
205
206 /// Lifetimes and bounds on type parameters
207 pub struct LifetimeBounds<'a> {
208     pub lifetimes: Vec<&'a str>,
209     pub bounds: Vec<(&'a str, ast::Sized, Vec<Path<'a>>)>,
210 }
211
212 impl<'a> LifetimeBounds<'a> {
213     pub fn empty() -> LifetimeBounds<'static> {
214         LifetimeBounds {
215             lifetimes: Vec::new(), bounds: Vec::new()
216         }
217     }
218     pub fn to_generics(&self,
219                        cx: &ExtCtxt,
220                        span: Span,
221                        self_ty: Ident,
222                        self_generics: &Generics)
223                        -> Generics {
224         let lifetimes = self.lifetimes.iter().map(|lt| {
225             cx.lifetime(span, cx.ident_of(*lt).name)
226         }).collect();
227         let ty_params = self.bounds.iter().map(|t| {
228             match t {
229                 &(ref name, sized, ref bounds) => {
230                     mk_ty_param(cx,
231                                 span,
232                                 *name,
233                                 sized,
234                                 bounds.as_slice(),
235                                 self_ty,
236                                 self_generics)
237                 }
238             }
239         }).collect();
240         mk_generics(lifetimes, ty_params)
241     }
242 }
243
244
245 pub fn get_explicit_self(cx: &ExtCtxt, span: Span, self_ptr: &Option<PtrTy>)
246     -> (@Expr, ast::ExplicitSelf) {
247     let self_path = cx.expr_self(span);
248     match *self_ptr {
249         None => {
250             (self_path, respan(span, ast::SelfValue))
251         }
252         Some(ref ptr) => {
253             let self_ty = respan(
254                 span,
255                 match *ptr {
256                     Send => ast::SelfUniq,
257                     Borrowed(ref lt, mutbl) => {
258                         let lt = lt.map(|s| cx.lifetime(span, cx.ident_of(s).name));
259                         ast::SelfRegion(lt, mutbl)
260                     }
261                 });
262             let self_expr = cx.expr_deref(span, self_path);
263             (self_expr, self_ty)
264         }
265     }
266 }