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.
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.
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.
17 use ast::{Expr,Generics,Ident};
18 use ext::base::ExtCtxt;
19 use ext::build::AstBuilder;
20 use codemap::{Span,respan};
23 /// The types of pointers
24 pub enum PtrTy<'self> {
26 Managed(ast::Mutability), // @[mut]
27 Borrowed(Option<&'self str>, ast::Mutability), // &['lifetime] [mut]
30 /// A path, e.g. `::std::option::Option::<int>` (global). Has support
31 /// for type parameters and a lifetime.
32 pub struct Path<'self> {
34 lifetime: Option<&'self str>,
35 params: ~[~Ty<'self>],
39 impl<'self> Path<'self> {
40 pub fn new<'r>(path: ~[&'r str]) -> Path<'r> {
41 Path::new_(path, None, ~[], true)
43 pub fn new_local<'r>(path: &'r str) -> Path<'r> {
44 Path::new_(~[ path ], None, ~[], false)
46 pub fn new_<'r>(path: ~[&'r str],
47 lifetime: Option<&'r str>,
63 self_generics: &Generics)
65 cx.ty_path(self.to_path(cx, span, self_ty, self_generics), None)
71 self_generics: &Generics)
73 let idents = self.path.map(|s| cx.ident_of(*s) );
74 let lt = mk_lifetime(cx, span, &self.lifetime);
75 let tys = self.params.map(|t| t.to_ty(cx, span, self_ty, self_generics));
77 cx.path_all(span, self.global, idents, lt, tys)
81 /// A type. Supports pointers (except for *), Self, and literals
85 Ptr(~Ty<'self>, PtrTy<'self>),
86 // mod::mod::Type<[lifetime], [Params...]>, including a plain type
87 // parameter, and things like `int`
93 pub fn borrowed_ptrty<'r>() -> PtrTy<'r> {
94 Borrowed(None, ast::MutImmutable)
96 pub fn borrowed<'r>(ty: ~Ty<'r>) -> Ty<'r> {
97 Ptr(ty, borrowed_ptrty())
100 pub fn borrowed_explicit_self<'r>() -> Option<Option<PtrTy<'r>>> {
101 Some(Some(borrowed_ptrty()))
104 pub fn borrowed_self<'r>() -> Ty<'r> {
108 pub fn nil_ty() -> Ty<'static> {
112 fn mk_lifetime(cx: @ExtCtxt, span: Span, lt: &Option<&str>) -> Option<ast::Lifetime> {
114 Some(ref s) => Some(cx.lifetime(span, cx.ident_of(*s))),
119 impl<'self> Ty<'self> {
124 self_generics: &Generics)
127 Ptr(ref ty, ref ptr) => {
128 let raw_ty = ty.to_ty(cx, span, self_ty, self_generics);
131 cx.ty_uniq(span, raw_ty)
134 cx.ty_box(span, raw_ty, mutbl)
136 Borrowed(ref lt, mutbl) => {
137 let lt = mk_lifetime(cx, span, lt);
138 cx.ty_rptr(span, raw_ty, lt, mutbl)
142 Literal(ref p) => { p.to_ty(cx, span, self_ty, self_generics) }
144 cx.ty_path(self.to_path(cx, span, self_ty, self_generics), None)
146 Tuple(ref fields) => {
147 let ty = if fields.is_empty() {
150 ast::ty_tup(fields.map(|f| f.to_ty(cx, span, self_ty, self_generics)))
158 pub fn to_path(&self,
162 self_generics: &Generics)
166 let self_params = do self_generics.ty_params.map |ty_param| {
167 cx.ty_ident(span, ty_param.ident)
169 let lifetime = if self_generics.lifetimes.is_empty() {
172 Some(*self_generics.lifetimes.get(0))
175 cx.path_all(span, false, ~[self_ty], lifetime,
176 opt_vec::take_vec(self_params))
179 p.to_path(cx, span, self_ty, self_generics)
181 Ptr(*) => { cx.span_bug(span, "Pointer in a path in generic `deriving`") }
182 Tuple(*) => { cx.span_bug(span, "Tuple in a path in generic `deriving`") }
188 fn mk_ty_param(cx: @ExtCtxt, span: Span, name: &str, bounds: &[Path],
189 self_ident: Ident, self_generics: &Generics) -> ast::TyParam {
190 let bounds = opt_vec::from(
192 let path = b.to_path(cx, span, self_ident, self_generics);
193 cx.typarambound(path)
195 cx.typaram(cx.ident_of(name), bounds)
198 fn mk_generics(lifetimes: ~[ast::Lifetime], ty_params: ~[ast::TyParam]) -> Generics {
200 lifetimes: opt_vec::from(lifetimes),
201 ty_params: opt_vec::from(ty_params)
205 /// Lifetimes and bounds on type parameters
206 pub struct LifetimeBounds<'self> {
207 lifetimes: ~[&'self str],
208 bounds: ~[(&'self str, ~[Path<'self>])]
211 impl<'self> LifetimeBounds<'self> {
212 pub fn empty() -> LifetimeBounds<'static> {
214 lifetimes: ~[], bounds: ~[]
217 pub fn to_generics(&self,
221 self_generics: &Generics)
223 let lifetimes = do self.lifetimes.map |lt| {
224 cx.lifetime(span, cx.ident_of(*lt))
226 let ty_params = do self.bounds.map |t| {
228 &(ref name, ref bounds) => {
229 mk_ty_param(cx, span, *name, *bounds, self_ty, self_generics)
233 mk_generics(lifetimes, ty_params)
238 pub fn get_explicit_self(cx: @ExtCtxt, span: Span, self_ptr: &Option<PtrTy>)
239 -> (@Expr, ast::explicit_self) {
240 let self_path = cx.expr_self(span);
243 (self_path, respan(span, ast::sty_value(ast::MutImmutable)))
246 let self_ty = respan(
249 Send => ast::sty_uniq(ast::MutImmutable),
250 Managed(mutbl) => ast::sty_box(mutbl),
251 Borrowed(ref lt, mutbl) => {
252 let lt = lt.map(|s| cx.lifetime(span, cx.ident_of(s)));
253 ast::sty_region(lt, mutbl)
256 let self_expr = cx.expr_deref(span, self_path);