]>
Commit | Line | Data |
---|---|---|
223e47cc LB |
1 | // Copyright 2012-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 | ||
1a4d82fc JJ |
11 | use ast::{MetaItem, Item, Expr}; |
12 | use codemap::Span; | |
970d7e83 LB |
13 | use ext::base::ExtCtxt; |
14 | use ext::build::AstBuilder; | |
15 | use ext::deriving::generic::*; | |
1a4d82fc JJ |
16 | use ext::deriving::generic::ty::*; |
17 | use parse::token::InternedString; | |
18 | use ptr::P; | |
223e47cc | 19 | |
1a4d82fc JJ |
20 | pub fn expand_deriving_clone<F>(cx: &mut ExtCtxt, |
21 | span: Span, | |
22 | mitem: &MetaItem, | |
23 | item: &Item, | |
24 | push: F) where | |
25 | F: FnOnce(P<Item>), | |
26 | { | |
27 | let inline = cx.meta_word(span, InternedString::new("inline")); | |
28 | let attrs = vec!(cx.attribute(span, inline)); | |
970d7e83 | 29 | let trait_def = TraitDef { |
1a4d82fc JJ |
30 | span: span, |
31 | attributes: Vec::new(), | |
85aaf69f | 32 | path: path_std!(cx, core::clone::Clone), |
1a4d82fc | 33 | additional_bounds: Vec::new(), |
970d7e83 | 34 | generics: LifetimeBounds::empty(), |
1a4d82fc | 35 | methods: vec!( |
970d7e83 LB |
36 | MethodDef { |
37 | name: "clone", | |
38 | generics: LifetimeBounds::empty(), | |
39 | explicit_self: borrowed_explicit_self(), | |
1a4d82fc | 40 | args: Vec::new(), |
85aaf69f | 41 | ret_ty: Self_, |
1a4d82fc | 42 | attributes: attrs, |
c34b1796 | 43 | combine_substructure: combine_substructure(Box::new(|c, s, sub| { |
1a4d82fc | 44 | cs_clone("Clone", c, s, sub) |
c34b1796 | 45 | })), |
970d7e83 | 46 | } |
85aaf69f SL |
47 | ), |
48 | associated_types: Vec::new(), | |
223e47cc LB |
49 | }; |
50 | ||
1a4d82fc | 51 | trait_def.expand(cx, mitem, item, push) |
223e47cc LB |
52 | } |
53 | ||
970d7e83 LB |
54 | fn cs_clone( |
55 | name: &str, | |
1a4d82fc JJ |
56 | cx: &mut ExtCtxt, trait_span: Span, |
57 | substr: &Substructure) -> P<Expr> { | |
58 | let ctor_path; | |
970d7e83 | 59 | let all_fields; |
1a4d82fc | 60 | let fn_path = vec![ |
85aaf69f | 61 | cx.ident_of_std("core"), |
1a4d82fc JJ |
62 | cx.ident_of("clone"), |
63 | cx.ident_of("Clone"), | |
64 | cx.ident_of("clone"), | |
65 | ]; | |
85aaf69f | 66 | let subcall = |field: &FieldInfo| { |
1a4d82fc JJ |
67 | let args = vec![cx.expr_addr_of(field.span, field.self_.clone())]; |
68 | ||
69 | cx.expr_call_global(field.span, fn_path.clone(), args) | |
70 | }; | |
970d7e83 LB |
71 | |
72 | match *substr.fields { | |
73 | Struct(ref af) => { | |
1a4d82fc | 74 | ctor_path = cx.path(trait_span, vec![substr.type_ident]); |
970d7e83 | 75 | all_fields = af; |
223e47cc | 76 | } |
970d7e83 | 77 | EnumMatching(_, variant, ref af) => { |
1a4d82fc | 78 | ctor_path = cx.path(trait_span, vec![substr.type_ident, variant.node.name]); |
970d7e83 LB |
79 | all_fields = af; |
80 | }, | |
1a4d82fc JJ |
81 | EnumNonMatchingCollapsed (..) => { |
82 | cx.span_bug(trait_span, | |
83 | &format!("non-matching enum variants in \ | |
c34b1796 | 84 | `derive({})`", name)) |
1a4d82fc JJ |
85 | } |
86 | StaticEnum(..) | StaticStruct(..) => { | |
87 | cx.span_bug(trait_span, | |
c34b1796 | 88 | &format!("static method in `derive({})`", name)) |
1a4d82fc | 89 | } |
223e47cc LB |
90 | } |
91 | ||
1a4d82fc JJ |
92 | if all_fields.len() >= 1 && all_fields[0].name.is_none() { |
93 | // enum-like | |
94 | let subcalls = all_fields.iter().map(subcall).collect(); | |
95 | let path = cx.expr_path(ctor_path); | |
96 | cx.expr_call(trait_span, path, subcalls) | |
97 | } else { | |
98 | // struct-like | |
99 | let fields = all_fields.iter().map(|field| { | |
100 | let ident = match field.name { | |
101 | Some(i) => i, | |
102 | None => { | |
103 | cx.span_bug(trait_span, | |
104 | &format!("unnamed field in normal struct in \ | |
c34b1796 | 105 | `derive({})`", name)) |
1a4d82fc | 106 | } |
970d7e83 | 107 | }; |
1a4d82fc JJ |
108 | cx.field_imm(field.span, ident, subcall(field)) |
109 | }).collect::<Vec<_>>(); | |
970d7e83 | 110 | |
1a4d82fc JJ |
111 | if fields.is_empty() { |
112 | // no fields, so construct like `None` | |
113 | cx.expr_path(ctor_path) | |
114 | } else { | |
115 | cx.expr_struct(trait_span, ctor_path, fields) | |
223e47cc | 116 | } |
970d7e83 | 117 | } |
223e47cc | 118 | } |