]>
Commit | Line | Data |
---|---|---|
d9579d0f AL |
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 | ||
9cc50fc6 SL |
11 | use deriving::generic::*; |
12 | use deriving::generic::ty::*; | |
13 | ||
5bcae85e SL |
14 | use syntax::ast::{BinOpKind, Expr, MetaItem}; |
15 | use syntax::ext::base::{Annotatable, ExtCtxt}; | |
9cc50fc6 SL |
16 | use syntax::ext::build::AstBuilder; |
17 | use syntax::parse::token::InternedString; | |
18 | use syntax::ptr::P; | |
3157f602 | 19 | use syntax_pos::Span; |
d9579d0f AL |
20 | |
21 | pub fn expand_deriving_partial_eq(cx: &mut ExtCtxt, | |
22 | span: Span, | |
23 | mitem: &MetaItem, | |
62682a34 | 24 | item: &Annotatable, |
5bcae85e | 25 | push: &mut FnMut(Annotatable)) { |
d9579d0f AL |
26 | // structures are equal if all fields are equal, and non equal, if |
27 | // any fields are not equal or if the enum variants are different | |
28 | fn cs_eq(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> P<Expr> { | |
5bcae85e SL |
29 | cs_fold(true, // use foldl |
30 | |cx, span, subexpr, self_f, other_fs| { | |
31 | let other_f = match (other_fs.len(), other_fs.get(0)) { | |
32 | (1, Some(o_f)) => o_f, | |
33 | _ => cx.span_bug(span, "not exactly 2 arguments in `derive(PartialEq)`"), | |
34 | }; | |
d9579d0f | 35 | |
5bcae85e | 36 | let eq = cx.expr_binary(span, BinOpKind::Eq, self_f, other_f.clone()); |
d9579d0f | 37 | |
5bcae85e SL |
38 | cx.expr_binary(span, BinOpKind::And, subexpr, eq) |
39 | }, | |
40 | cx.expr_bool(span, true), | |
41 | Box::new(|cx, span, _, _| cx.expr_bool(span, false)), | |
42 | cx, | |
43 | span, | |
44 | substr) | |
d9579d0f AL |
45 | } |
46 | fn cs_ne(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> P<Expr> { | |
5bcae85e SL |
47 | cs_fold(true, // use foldl |
48 | |cx, span, subexpr, self_f, other_fs| { | |
49 | let other_f = match (other_fs.len(), other_fs.get(0)) { | |
50 | (1, Some(o_f)) => o_f, | |
51 | _ => cx.span_bug(span, "not exactly 2 arguments in `derive(PartialEq)`"), | |
52 | }; | |
d9579d0f | 53 | |
5bcae85e | 54 | let eq = cx.expr_binary(span, BinOpKind::Ne, self_f, other_f.clone()); |
d9579d0f | 55 | |
5bcae85e SL |
56 | cx.expr_binary(span, BinOpKind::Or, subexpr, eq) |
57 | }, | |
58 | cx.expr_bool(span, false), | |
59 | Box::new(|cx, span, _, _| cx.expr_bool(span, true)), | |
60 | cx, | |
61 | span, | |
62 | substr) | |
d9579d0f AL |
63 | } |
64 | ||
65 | macro_rules! md { | |
66 | ($name:expr, $f:ident) => { { | |
67 | let inline = cx.meta_word(span, InternedString::new("inline")); | |
68 | let attrs = vec!(cx.attribute(span, inline)); | |
69 | MethodDef { | |
70 | name: $name, | |
71 | generics: LifetimeBounds::empty(), | |
72 | explicit_self: borrowed_explicit_self(), | |
73 | args: vec!(borrowed_self()), | |
74 | ret_ty: Literal(path_local!(bool)), | |
75 | attributes: attrs, | |
62682a34 | 76 | is_unsafe: false, |
a7813a04 | 77 | unify_fieldless_variants: true, |
d9579d0f AL |
78 | combine_substructure: combine_substructure(Box::new(|a, b, c| { |
79 | $f(a, b, c) | |
80 | })) | |
81 | } | |
82 | } } | |
83 | } | |
84 | ||
54a0048b SL |
85 | // avoid defining `ne` if we can |
86 | // c-like enums, enums without any fields and structs without fields | |
87 | // can safely define only `eq`. | |
88 | let mut methods = vec![md!("eq", cs_eq)]; | |
89 | if !is_type_without_fields(item) { | |
90 | methods.push(md!("ne", cs_ne)); | |
91 | } | |
92 | ||
d9579d0f AL |
93 | let trait_def = TraitDef { |
94 | span: span, | |
95 | attributes: Vec::new(), | |
96 | path: path_std!(cx, core::cmp::PartialEq), | |
97 | additional_bounds: Vec::new(), | |
98 | generics: LifetimeBounds::empty(), | |
e9174d1e | 99 | is_unsafe: false, |
9e0c209e | 100 | supports_unions: false, |
54a0048b | 101 | methods: methods, |
d9579d0f AL |
102 | associated_types: Vec::new(), |
103 | }; | |
62682a34 | 104 | trait_def.expand(cx, mitem, item, push) |
d9579d0f | 105 | } |