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.
11 use deriving
::generic
::*;
12 use deriving
::generic
::ty
::*;
14 use syntax
::ast
::{MetaItem, Expr, BinOpKind, self}
;
15 use syntax
::codemap
::Span
;
16 use syntax
::ext
::base
::{ExtCtxt, Annotatable}
;
17 use syntax
::ext
::build
::AstBuilder
;
18 use syntax
::parse
::token
::InternedString
;
21 pub fn expand_deriving_ord(cx
: &mut ExtCtxt
,
25 push
: &mut FnMut(Annotatable
))
27 let inline
= cx
.meta_word(span
, InternedString
::new("inline"));
28 let attrs
= vec
!(cx
.attribute(span
, inline
));
29 let trait_def
= TraitDef
{
31 attributes
: Vec
::new(),
32 path
: path_std
!(cx
, core
::cmp
::Ord
),
33 additional_bounds
: Vec
::new(),
34 generics
: LifetimeBounds
::empty(),
39 generics
: LifetimeBounds
::empty(),
40 explicit_self
: borrowed_explicit_self(),
41 args
: vec
!(borrowed_self()),
42 ret_ty
: Literal(path_std
!(cx
, core
::cmp
::Ordering
)),
45 combine_substructure
: combine_substructure(Box
::new(|a
, b
, c
| {
50 associated_types
: Vec
::new(),
53 trait_def
.expand(cx
, mitem
, item
, push
)
57 pub fn ordering_collapsed(cx
: &mut ExtCtxt
,
59 self_arg_tags
: &[ast
::Ident
]) -> P
<ast
::Expr
> {
60 let lft
= cx
.expr_ident(span
, self_arg_tags
[0]);
61 let rgt
= cx
.expr_addr_of(span
, cx
.expr_ident(span
, self_arg_tags
[1]));
62 cx
.expr_method_call(span
, lft
, cx
.ident_of("cmp"), vec
![rgt
])
65 pub fn cs_cmp(cx
: &mut ExtCtxt
, span
: Span
,
66 substr
: &Substructure
) -> P
<Expr
> {
67 let test_id
= cx
.ident_of("__test");
68 let equals_path
= cx
.path_global(span
,
69 cx
.std_path(&["cmp", "Ordering", "Equal"]));
71 let cmp_path
= cx
.std_path(&["cmp", "Ord", "cmp"]);
76 let __test = ::std::cmp::Ord::cmp(&self_field1, &other_field1);
77 if other == ::std::cmp::Ordering::Equal {
78 let __test = ::std::cmp::Ord::cmp(&self_field2, &other_field2);
79 if __test == ::std::cmp::Ordering::Equal {
88 FIXME #6449: These `if`s could/should be `match`es.
91 // foldr nests the if-elses correctly, leaving the first field
92 // as the outermost one, and the last as the innermost.
94 |cx
, span
, old
, self_f
, other_fs
| {
96 // if __test == ::std::cmp::Ordering::Equal {
103 let other_f
= match (other_fs
.len(), other_fs
.get(0)) {
104 (1, Some(o_f
)) => o_f
,
105 _
=> cx
.span_bug(span
, "not exactly 2 arguments in `derive(PartialOrd)`"),
109 cx
.expr_addr_of(span
, self_f
),
110 cx
.expr_addr_of(span
, other_f
.clone()),
113 cx
.expr_call_global(span
, cmp_path
.clone(), args
)
116 let assign
= cx
.stmt_let(span
, false, test_id
, new
);
118 let cond
= cx
.expr_binary(span
, BinOpKind
::Eq
,
119 cx
.expr_ident(span
, test_id
),
120 cx
.expr_path(equals_path
.clone()));
121 let if_
= cx
.expr_if(span
,
123 old
, Some(cx
.expr_ident(span
, test_id
)));
124 cx
.expr_block(cx
.block(span
, vec
!(assign
), Some(if_
)))
126 cx
.expr_path(equals_path
.clone()),
127 Box
::new(|cx
, span
, (self_args
, tag_tuple
), _non_self_args
| {
128 if self_args
.len() != 2 {
129 cx
.span_bug(span
, "not exactly 2 arguments in `derives(Ord)`")
131 ordering_collapsed(cx
, span
, tag_tuple
)