|
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