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