1010
1111use core:: prelude:: * ;
1212
13+ use ast;
1314use ast:: { meta_item, item, expr} ;
1415use codemap:: span;
1516use ext:: base:: ExtCtxt ;
@@ -21,104 +22,86 @@ pub fn expand_deriving_ord(cx: @ExtCtxt,
2122 mitem : @meta_item ,
2223 in_items: ~[ @item] ) -> ~[ @item] {
2324 macro_rules! md (
24- ( $name: expr, $less : expr, $equal: expr) => {
25+ ( $name: expr, $op : expr, $equal: expr) => {
2526 MethodDef {
2627 name : $name,
2728 generics : LifetimeBounds :: empty( ) ,
2829 explicit_self : borrowed_explicit_self( ) ,
2930 args : ~[ borrowed_self( ) ] ,
3031 ret_ty : Literal ( Path :: new( ~[ "bool" ] ) ) ,
3132 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)
3434 }
3535 }
3636 ) ;
3737
38-
39-
4038 let trait_def = TraitDef {
4139 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 : ~[ ] ,
4441 generics : LifetimeBounds :: empty ( ) ,
4542 methods : ~[
46- md ! ( "lt" , true , false ) ,
47- md ! ( "le" , true , true ) ,
43+ md ! ( "lt" , true , false ) ,
44+ md ! ( "le" , true , true ) ,
4845 md ! ( "gt" , false , false ) ,
4946 md ! ( "ge" , false , true )
5047 ]
5148 } ;
52-
53- expand_deriving_generic ( cx, span, mitem, in_items,
54- & trait_def)
49+ trait_def. expand ( cx, span, mitem, in_items)
5550}
5651
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} ;
6855 cs_fold (
6956 false , // need foldr,
7057 |cx, span, subexpr, self_f, other_fs| {
7158 /*
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`
7562
7663 ```
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+ )
9069 ```
9170
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.
9474 */
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) ) ;
9883
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 ) ) ) ;
10388
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)
10891 } ,
109- base ,
92+ cx . expr_bool ( span , equal ) ,
11093 |cx, span, args, _| {
11194 // nonmatching enums, order by the order the variants are
11295 // written
11396 match args {
11497 [ ( self_var, _, _) ,
11598 ( other_var, _, _) ] =>
11699 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+ } ) ,
122105 _ => cx. span_bug ( span, "Not exactly 2 arguments in `deriving(Ord)`" )
123106 }
124107 } ,
0 commit comments