|
8 | 8 | // option. This file may not be copied, modified, or distributed |
9 | 9 | // except according to those terms. |
10 | 10 |
|
| 11 | +use ast; |
11 | 12 | use ast::{MetaItem, item, expr}; |
12 | 13 | use codemap::span; |
13 | 14 | use ext::base::ExtCtxt; |
@@ -40,40 +41,70 @@ pub fn expand_deriving_totalord(cx: @ExtCtxt, |
40 | 41 | } |
41 | 42 |
|
42 | 43 |
|
43 | | -pub fn ordering_const(cx: @ExtCtxt, span: span, cnst: Ordering) -> @expr { |
| 44 | +pub fn ordering_const(cx: @ExtCtxt, span: span, cnst: Ordering) -> ast::Path { |
44 | 45 | let cnst = match cnst { |
45 | 46 | Less => "Less", |
46 | 47 | Equal => "Equal", |
47 | 48 | Greater => "Greater" |
48 | 49 | }; |
49 | | - cx.expr_path( |
50 | | - cx.path_global(span, |
51 | | - ~[cx.ident_of("std"), |
52 | | - cx.ident_of("cmp"), |
53 | | - cx.ident_of(cnst)])) |
| 50 | + cx.path_global(span, |
| 51 | + ~[cx.ident_of("std"), |
| 52 | + cx.ident_of("cmp"), |
| 53 | + cx.ident_of(cnst)]) |
54 | 54 | } |
55 | 55 |
|
56 | 56 | pub fn cs_cmp(cx: @ExtCtxt, span: span, |
57 | 57 | substr: &Substructure) -> @expr { |
| 58 | + let test_id = cx.ident_of("__test"); |
| 59 | + let equals_path = ordering_const(cx, span, Equal); |
58 | 60 |
|
| 61 | + /* |
| 62 | + Builds: |
| 63 | +
|
| 64 | + let __test = self_field1.cmp(&other_field2); |
| 65 | + if other == ::std::cmp::Equal { |
| 66 | + let __test = self_field2.cmp(&other_field2); |
| 67 | + if __test == ::std::cmp::Equal { |
| 68 | + ... |
| 69 | + } else { |
| 70 | + __test |
| 71 | + } |
| 72 | + } else { |
| 73 | + __test |
| 74 | + } |
| 75 | +
|
| 76 | + FIXME #6449: These `if`s could/should be `match`es. |
| 77 | + */ |
59 | 78 | cs_same_method_fold( |
60 | | - // foldr (possibly) nests the matches in lexical_ordering better |
| 79 | + // foldr nests the if-elses correctly, leaving the first field |
| 80 | + // as the outermost one, and the last as the innermost. |
61 | 81 | false, |
62 | 82 | |cx, span, old, new| { |
63 | | - cx.expr_call_global(span, |
64 | | - ~[cx.ident_of("std"), |
65 | | - cx.ident_of("cmp"), |
66 | | - cx.ident_of("lexical_ordering")], |
67 | | - ~[old, new]) |
| 83 | + // let __test = new; |
| 84 | + // if __test == ::std::cmp::Equal { |
| 85 | + // old |
| 86 | + // } else { |
| 87 | + // __test |
| 88 | + // } |
| 89 | + |
| 90 | + let assign = cx.stmt_let(span, false, test_id, new); |
| 91 | + |
| 92 | + let cond = cx.expr_binary(span, ast::eq, |
| 93 | + cx.expr_ident(span, test_id), |
| 94 | + cx.expr_path(equals_path.clone())); |
| 95 | + let if_ = cx.expr_if(span, |
| 96 | + cond, |
| 97 | + old, Some(cx.expr_ident(span, test_id))); |
| 98 | + cx.expr_block(cx.block(span, ~[assign], Some(if_))) |
68 | 99 | }, |
69 | | - ordering_const(cx, span, Equal), |
| 100 | + cx.expr_path(equals_path.clone()), |
70 | 101 | |cx, span, list, _| { |
71 | 102 | match list { |
72 | 103 | // an earlier nonmatching variant is Less than a |
73 | | - // later one |
| 104 | + // later one. |
74 | 105 | [(self_var, _, _), |
75 | | - (other_var, _, _)] => ordering_const(cx, span, |
76 | | - self_var.cmp(&other_var)), |
| 106 | + (other_var, _, _)] => cx.expr_path(ordering_const(cx, span, |
| 107 | + self_var.cmp(&other_var))), |
77 | 108 | _ => cx.span_bug(span, "Not exactly 2 arguments in `deriving(TotalOrd)`") |
78 | 109 | } |
79 | 110 | }, |
|
0 commit comments