10
10
11
11
use core:: prelude:: * ;
12
12
13
+ use ast;
13
14
use ast:: { meta_item, item, expr} ;
14
15
use codemap:: span;
15
16
use ext:: base:: ExtCtxt ;
@@ -21,104 +22,86 @@ pub fn expand_deriving_ord(cx: @ExtCtxt,
21
22
mitem : @meta_item ,
22
23
in_items: ~[ @item] ) -> ~[ @item] {
23
24
macro_rules! md (
24
- ( $name: expr, $less : expr, $equal: expr) => {
25
+ ( $name: expr, $op : expr, $equal: expr) => {
25
26
MethodDef {
26
27
name : $name,
27
28
generics : LifetimeBounds :: empty( ) ,
28
29
explicit_self : borrowed_explicit_self( ) ,
29
30
args : ~[ borrowed_self( ) ] ,
30
31
ret_ty : Literal ( Path :: new( ~[ "bool" ] ) ) ,
31
32
const_nonmatching : false ,
32
- combine_substructure : |cx, span, substr |
33
- cs_ord( $less, $equal, cx, span, substr)
33
+ combine_substructure : |cx, span, substr | cs_op( $op, $equal, cx, span, substr)
34
34
}
35
35
}
36
36
) ;
37
37
38
-
39
-
40
38
let trait_def = TraitDef {
41
39
path : Path :: new ( ~[ "std" , "cmp" , "Ord" ] ) ,
42
- // XXX: Ord doesn't imply Eq yet
43
- additional_bounds : ~[ Literal ( Path :: new ( ~[ "std" , "cmp" , "Eq" ] ) ) ] ,
40
+ additional_bounds : ~[ ] ,
44
41
generics : LifetimeBounds :: empty ( ) ,
45
42
methods : ~[
46
- md ! ( "lt" , true , false ) ,
47
- md ! ( "le" , true , true ) ,
43
+ md ! ( "lt" , true , false ) ,
44
+ md ! ( "le" , true , true ) ,
48
45
md ! ( "gt" , false , false ) ,
49
46
md ! ( "ge" , false , true )
50
47
]
51
48
} ;
52
-
53
- expand_deriving_generic ( cx, span, mitem, in_items,
54
- & trait_def)
49
+ trait_def. expand ( cx, span, mitem, in_items)
55
50
}
56
51
57
- /// `less`: is this `lt` or `le`? `equal`: is this `le` or `ge`?
58
- fn cs_ord ( less: bool, equal: bool ,
59
- cx: @ExtCtxt , span: span,
60
- substr: & Substructure ) -> @expr {
61
- let binop = if less {
62
- cx. ident_of ( "lt" )
63
- } else {
64
- cx. ident_of ( "gt" )
65
- } ;
66
- let base = cx. expr_bool ( span, equal) ;
67
-
52
+ /// Strict inequality.
53
+ fn cs_op ( less: bool, equal: bool , cx: @ExtCtxt , span: span, substr: & Substructure ) -> @expr {
54
+ let op = if less { ast:: lt} else { ast:: gt} ;
68
55
cs_fold (
69
56
false , // need foldr,
70
57
|cx, span, subexpr, self_f, other_fs| {
71
58
/*
72
-
73
- build up a series of nested ifs from the inside out to get
74
- lexical ordering (hence foldr), i.e.
59
+ build up a series of chain ||'s and &&'s from the inside
60
+ out (hence foldr) to get lexical ordering, i.e. for op ==
61
+ `ast::lt`
75
62
76
63
```
77
- if self.f1 `binop` other.f1 {
78
- true
79
- } else if self.f1 == other.f1 {
80
- if self.f2 `binop` other.f2 {
81
- true
82
- } else if self.f2 == other.f2 {
83
- `equal`
84
- } else {
85
- false
86
- }
87
- } else {
88
- false
89
- }
64
+ self.f1 < other.f1 || (!(other.f1 < self.f1) &&
65
+ (self.f2 < other.f2 || (!(other.f2 < self.f2) &&
66
+ (false)
67
+ ))
68
+ )
90
69
```
91
70
92
- The inner "`equal`" case is only reached if the two
93
- items have all fields equal.
71
+ The optimiser should remove the redundancy. We explicitly
72
+ get use the binops to avoid auto-deref derefencing too many
73
+ layers of pointers, if the type includes pointers.
94
74
*/
95
- if other_fs. len ( ) != 1 {
96
- cx. span_bug ( span, "Not exactly 2 arguments in `deriving(Ord)`" ) ;
97
- }
75
+ let other_f = match other_fs {
76
+ [ o_f] => o_f,
77
+ _ => cx. span_bug ( span, "Not exactly 2 arguments in `deriving(Ord)`" )
78
+ } ;
79
+
80
+ let cmp = cx. expr_binary ( span, op,
81
+ cx. expr_deref ( span, self_f) ,
82
+ cx. expr_deref ( span, other_f) ) ;
98
83
99
- let cmp = cx. expr_method_call ( span,
100
- self_f , cx. ident_of ( "eq" ) , other_fs . to_owned ( ) ) ;
101
- let elseif = cx. expr_if ( span, cmp ,
102
- subexpr , Some ( cx. expr_bool ( span, false ) ) ) ;
84
+ let not_cmp = cx. expr_unary ( span, ast :: not ,
85
+ cx. expr_binary ( span , op ,
86
+ cx. expr_deref ( span, other_f ) ,
87
+ cx. expr_deref ( span, self_f ) ) ) ;
103
88
104
- let cmp = cx. expr_method_call ( span,
105
- self_f, binop, other_fs. to_owned ( ) ) ;
106
- cx. expr_if ( span, cmp,
107
- cx. expr_bool ( span, true ) , Some ( elseif) )
89
+ let and = cx. expr_binary ( span, ast:: and, not_cmp, subexpr) ;
90
+ cx. expr_binary ( span, ast:: or, cmp, and)
108
91
} ,
109
- base ,
92
+ cx . expr_bool ( span , equal ) ,
110
93
|cx, span, args, _| {
111
94
// nonmatching enums, order by the order the variants are
112
95
// written
113
96
match args {
114
97
[ ( self_var, _, _) ,
115
98
( other_var, _, _) ] =>
116
99
cx. expr_bool ( span,
117
- if less {
118
- self_var < other_var
119
- } else {
120
- self_var > other_var
121
- } ) ,
100
+ if less {
101
+ self_var < other_var
102
+ } else {
103
+ self_var > other_var
104
+ } ) ,
122
105
_ => cx. span_bug ( span, "Not exactly 2 arguments in `deriving(Ord)`" )
123
106
}
124
107
} ,
0 commit comments