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 use ast::{MetaItem, Item, Expr};
14 use ext::base::ExtCtxt;
15 use ext::build::AstBuilder;
16 use ext::deriving::generic::*;
17 use parse::token::InternedString;
19 use std::cmp::{Ordering, Equal, Less, Greater};
21 pub fn expand_deriving_totalord(cx: &mut ExtCtxt,
26 let inline = cx.meta_word(span, InternedString::new("inline"));
27 let attrs = vec!(cx.attribute(span, inline));
28 let trait_def = TraitDef {
30 attributes: Vec::new(),
31 path: Path::new(vec!("std", "cmp", "TotalOrd")),
32 additional_bounds: Vec::new(),
33 generics: LifetimeBounds::empty(),
37 generics: LifetimeBounds::empty(),
38 explicit_self: borrowed_explicit_self(),
39 args: vec!(borrowed_self()),
40 ret_ty: Literal(Path::new(vec!("std", "cmp", "Ordering"))),
42 const_nonmatching: false,
43 combine_substructure: combine_substructure(|a, b, c| {
50 trait_def.expand(cx, mitem, item, push)
54 pub fn ordering_const(cx: &mut ExtCtxt, span: Span, cnst: Ordering) -> ast::Path {
55 let cnst = match cnst {
61 vec!(cx.ident_of("std"),
66 pub fn cs_cmp(cx: &mut ExtCtxt, span: Span,
67 substr: &Substructure) -> @Expr {
68 let test_id = cx.ident_of("__test");
69 let equals_path = ordering_const(cx, span, Equal);
74 let __test = self_field1.cmp(&other_field2);
75 if other == ::std::cmp::Equal {
76 let __test = self_field2.cmp(&other_field2);
77 if __test == ::std::cmp::Equal {
86 FIXME #6449: These `if`s could/should be `match`es.
89 // foldr nests the if-elses correctly, leaving the first field
90 // as the outermost one, and the last as the innermost.
92 |cx, span, old, new| {
94 // if __test == ::std::cmp::Equal {
100 let assign = cx.stmt_let(span, false, test_id, new);
102 let cond = cx.expr_binary(span, ast::BiEq,
103 cx.expr_ident(span, test_id),
104 cx.expr_path(equals_path.clone()));
105 let if_ = cx.expr_if(span,
107 old, Some(cx.expr_ident(span, test_id)));
108 cx.expr_block(cx.block(span, vec!(assign), Some(if_)))
110 cx.expr_path(equals_path.clone()),
111 |cx, span, list, _| {
113 // an earlier nonmatching variant is Less than a
116 (other_var, _, _)] => {
117 let order = ordering_const(cx, span, self_var.cmp(&other_var));
120 _ => cx.span_bug(span, "not exactly 2 arguments in `deriving(TotalOrd)`")