diff options
| author | Erick Tryzelaar <erick.tryzelaar@gmail.com> | 2015-04-02 09:14:53 -0700 |
|---|---|---|
| committer | Erick Tryzelaar <erick.tryzelaar@gmail.com> | 2015-04-15 19:48:09 -0700 |
| commit | 6557f4b2693af38910a9469a5a038f6a116419b2 (patch) | |
| tree | f7418f091e8d50767283842b4b5161a2d9573929 /src/libsyntax | |
| parent | abf0548b5caaa389a5b29813132d2cf4c8b0f1ed (diff) | |
| download | rust-6557f4b2693af38910a9469a5a038f6a116419b2.tar.gz rust-6557f4b2693af38910a9469a5a038f6a116419b2.zip | |
syntax: Rename deriving/cmp/* to match their current names
Diffstat (limited to 'src/libsyntax')
| -rw-r--r-- | src/libsyntax/ext/deriving/cmp/eq.rs | 86 | ||||
| -rw-r--r-- | src/libsyntax/ext/deriving/cmp/ord.rs | 184 | ||||
| -rw-r--r-- | src/libsyntax/ext/deriving/cmp/partial_eq.rs | 95 | ||||
| -rw-r--r-- | src/libsyntax/ext/deriving/cmp/partial_ord.rs | 238 | ||||
| -rw-r--r-- | src/libsyntax/ext/deriving/cmp/totaleq.rs | 69 | ||||
| -rw-r--r-- | src/libsyntax/ext/deriving/cmp/totalord.rs | 142 | ||||
| -rw-r--r-- | src/libsyntax/ext/deriving/mod.rs | 16 |
7 files changed, 415 insertions, 415 deletions
diff --git a/src/libsyntax/ext/deriving/cmp/eq.rs b/src/libsyntax/ext/deriving/cmp/eq.rs index c02af437b1c..6418450685e 100644 --- a/src/libsyntax/ext/deriving/cmp/eq.rs +++ b/src/libsyntax/ext/deriving/cmp/eq.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use ast::{MetaItem, Item, Expr, self}; +use ast::{MetaItem, Item, Expr}; use codemap::Span; use ext::base::ExtCtxt; use ext::build::AstBuilder; @@ -24,70 +24,44 @@ pub fn expand_deriving_eq<F>(cx: &mut ExtCtxt, push: F) where F: FnOnce(P<Item>), { - // structures are equal if all fields are equal, and non equal, if - // any fields are not equal or if the enum variants are different - fn cs_eq(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> P<Expr> { - cs_fold( - true, // use foldl - |cx, span, subexpr, self_f, other_fs| { - let other_f = match other_fs { - [ref o_f] => o_f, - _ => cx.span_bug(span, "not exactly 2 arguments in `derive(PartialEq)`") - }; - - let eq = cx.expr_binary(span, ast::BiEq, self_f, other_f.clone()); - - cx.expr_binary(span, ast::BiAnd, subexpr, eq) - }, - cx.expr_bool(span, true), - Box::new(|cx, span, _, _| cx.expr_bool(span, false)), - cx, span, substr) - } - fn cs_ne(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> P<Expr> { - cs_fold( - true, // use foldl - |cx, span, subexpr, self_f, other_fs| { - let other_f = match other_fs { - [ref o_f] => o_f, - _ => cx.span_bug(span, "not exactly 2 arguments in `derive(PartialEq)`") - }; - - let eq = cx.expr_binary(span, ast::BiNe, self_f, other_f.clone()); - - cx.expr_binary(span, ast::BiOr, subexpr, eq) - }, - cx.expr_bool(span, false), - Box::new(|cx, span, _, _| cx.expr_bool(span, true)), - cx, span, substr) + fn cs_total_eq_assert(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> P<Expr> { + cs_same_method(|cx, span, exprs| { + // create `a.<method>(); b.<method>(); c.<method>(); ...` + // (where method is `assert_receiver_is_total_eq`) + let stmts = exprs.into_iter().map(|e| cx.stmt_expr(e)).collect(); + let block = cx.block(span, stmts, None); + cx.expr_block(block) + }, + Box::new(|cx, sp, _, _| { + cx.span_bug(sp, "non matching enums in derive(Eq)?") }), + cx, + span, + substr) } - macro_rules! md { - ($name:expr, $f:ident) => { { - let inline = cx.meta_word(span, InternedString::new("inline")); - let attrs = vec!(cx.attribute(span, inline)); + let inline = cx.meta_word(span, InternedString::new("inline")); + let hidden = cx.meta_word(span, InternedString::new("hidden")); + let doc = cx.meta_list(span, InternedString::new("doc"), vec!(hidden)); + let attrs = vec!(cx.attribute(span, inline), + cx.attribute(span, doc)); + let trait_def = TraitDef { + span: span, + attributes: Vec::new(), + path: path_std!(cx, core::cmp::Eq), + additional_bounds: Vec::new(), + generics: LifetimeBounds::empty(), + methods: vec!( MethodDef { - name: $name, + name: "assert_receiver_is_total_eq", generics: LifetimeBounds::empty(), explicit_self: borrowed_explicit_self(), - args: vec!(borrowed_self()), - ret_ty: Literal(path_local!(bool)), + args: vec!(), + ret_ty: nil_ty(), attributes: attrs, combine_substructure: combine_substructure(Box::new(|a, b, c| { - $f(a, b, c) + cs_total_eq_assert(a, b, c) })) } - } } - } - - let trait_def = TraitDef { - span: span, - attributes: Vec::new(), - path: path_std!(cx, core::cmp::PartialEq), - additional_bounds: Vec::new(), - generics: LifetimeBounds::empty(), - methods: vec!( - md!("eq", cs_eq), - md!("ne", cs_ne) ), associated_types: Vec::new(), }; diff --git a/src/libsyntax/ext/deriving/cmp/ord.rs b/src/libsyntax/ext/deriving/cmp/ord.rs index 8ecd172b2f0..1de955856e7 100644 --- a/src/libsyntax/ext/deriving/cmp/ord.rs +++ b/src/libsyntax/ext/deriving/cmp/ord.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -pub use self::OrderingOp::*; - use ast; use ast::{MetaItem, Item, Expr}; use codemap::Span; @@ -20,114 +18,72 @@ use ext::deriving::generic::ty::*; use parse::token::InternedString; use ptr::P; -pub fn expand_deriving_ord<F>(cx: &mut ExtCtxt, - span: Span, - mitem: &MetaItem, - item: &Item, - push: F) where +pub fn expand_deriving_totalord<F>(cx: &mut ExtCtxt, + span: Span, + mitem: &MetaItem, + item: &Item, + push: F) where F: FnOnce(P<Item>), { - macro_rules! md { - ($name:expr, $op:expr, $equal:expr) => { { - let inline = cx.meta_word(span, InternedString::new("inline")); - let attrs = vec!(cx.attribute(span, inline)); + let inline = cx.meta_word(span, InternedString::new("inline")); + let attrs = vec!(cx.attribute(span, inline)); + let trait_def = TraitDef { + span: span, + attributes: Vec::new(), + path: path_std!(cx, core::cmp::Ord), + additional_bounds: Vec::new(), + generics: LifetimeBounds::empty(), + methods: vec!( MethodDef { - name: $name, + name: "cmp", generics: LifetimeBounds::empty(), explicit_self: borrowed_explicit_self(), args: vec!(borrowed_self()), - ret_ty: Literal(path_local!(bool)), + ret_ty: Literal(path_std!(cx, core::cmp::Ordering)), attributes: attrs, - combine_substructure: combine_substructure(Box::new(|cx, span, substr| { - cs_op($op, $equal, cx, span, substr) - })) + combine_substructure: combine_substructure(Box::new(|a, b, c| { + cs_cmp(a, b, c) + })), } - } } - } - - let ordering_ty = Literal(path_std!(cx, core::cmp::Ordering)); - let ret_ty = Literal(Path::new_(pathvec_std!(cx, core::option::Option), - None, - vec![box ordering_ty], - true)); - - let inline = cx.meta_word(span, InternedString::new("inline")); - let attrs = vec!(cx.attribute(span, inline)); - - let partial_cmp_def = MethodDef { - name: "partial_cmp", - generics: LifetimeBounds::empty(), - explicit_self: borrowed_explicit_self(), - args: vec![borrowed_self()], - ret_ty: ret_ty, - attributes: attrs, - combine_substructure: combine_substructure(Box::new(|cx, span, substr| { - cs_partial_cmp(cx, span, substr) - })) - }; - - let trait_def = TraitDef { - span: span, - attributes: vec![], - path: path_std!(cx, core::cmp::PartialOrd), - additional_bounds: vec![], - generics: LifetimeBounds::empty(), - methods: vec![ - partial_cmp_def, - md!("lt", true, false), - md!("le", true, true), - md!("gt", false, false), - md!("ge", false, true) - ], + ), associated_types: Vec::new(), }; + trait_def.expand(cx, mitem, item, push) } -#[derive(Copy, Clone)] -pub enum OrderingOp { - PartialCmpOp, LtOp, LeOp, GtOp, GeOp, -} -pub fn some_ordering_collapsed(cx: &mut ExtCtxt, - span: Span, - op: OrderingOp, - self_arg_tags: &[ast::Ident]) -> P<ast::Expr> { +pub fn ordering_collapsed(cx: &mut ExtCtxt, + span: Span, + self_arg_tags: &[ast::Ident]) -> P<ast::Expr> { let lft = cx.expr_ident(span, self_arg_tags[0]); let rgt = cx.expr_addr_of(span, cx.expr_ident(span, self_arg_tags[1])); - let op_str = match op { - PartialCmpOp => "partial_cmp", - LtOp => "lt", LeOp => "le", - GtOp => "gt", GeOp => "ge", - }; - cx.expr_method_call(span, lft, cx.ident_of(op_str), vec![rgt]) + cx.expr_method_call(span, lft, cx.ident_of("cmp"), vec![rgt]) } -pub fn cs_partial_cmp(cx: &mut ExtCtxt, span: Span, +pub fn cs_cmp(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> P<Expr> { let test_id = cx.ident_of("__test"); - let ordering = cx.path_global(span, - vec!(cx.ident_of_std("core"), - cx.ident_of("cmp"), - cx.ident_of("Ordering"), - cx.ident_of("Equal"))); - let ordering = cx.expr_path(ordering); - let equals_expr = cx.expr_some(span, ordering); + let equals_path = cx.path_global(span, + vec!(cx.ident_of_std("core"), + cx.ident_of("cmp"), + cx.ident_of("Ordering"), + cx.ident_of("Equal"))); - let partial_cmp_path = vec![ + let cmp_path = vec![ cx.ident_of_std("core"), cx.ident_of("cmp"), - cx.ident_of("PartialOrd"), - cx.ident_of("partial_cmp"), + cx.ident_of("Ord"), + cx.ident_of("cmp"), ]; /* Builds: - let __test = ::std::cmp::PartialOrd::partial_cmp(&self_field1, &other_field1); - if __test == ::std::option::Option::Some(::std::cmp::Ordering::Equal) { - let __test = ::std::cmp::PartialOrd::partial_cmp(&self_field2, &other_field2); - if __test == ::std::option::Option::Some(::std::cmp::Ordering::Equal) { + let __test = ::std::cmp::Ord::cmp(&self_field1, &other_field1); + if other == ::std::cmp::Ordering::Equal { + let __test = ::std::cmp::Ord::cmp(&self_field2, &other_field2); + if __test == ::std::cmp::Ordering::Equal { ... } else { __test @@ -144,7 +100,7 @@ pub fn cs_partial_cmp(cx: &mut ExtCtxt, span: Span, false, |cx, span, old, self_f, other_fs| { // let __test = new; - // if __test == Some(::std::cmp::Ordering::Equal) { + // if __test == ::std::cmp::Ordering::Equal { // old // } else { // __test @@ -161,77 +117,25 @@ pub fn cs_partial_cmp(cx: &mut ExtCtxt, span: Span, cx.expr_addr_of(span, other_f.clone()), ]; - cx.expr_call_global(span, partial_cmp_path.clone(), args) + cx.expr_call_global(span, cmp_path.clone(), args) }; let assign = cx.stmt_let(span, false, test_id, new); let cond = cx.expr_binary(span, ast::BiEq, cx.expr_ident(span, test_id), - equals_expr.clone()); + cx.expr_path(equals_path.clone())); let if_ = cx.expr_if(span, cond, old, Some(cx.expr_ident(span, test_id))); cx.expr_block(cx.block(span, vec!(assign), Some(if_))) }, - equals_expr.clone(), + cx.expr_path(equals_path.clone()), Box::new(|cx, span, (self_args, tag_tuple), _non_self_args| { if self_args.len() != 2 { - cx.span_bug(span, "not exactly 2 arguments in `derive(PartialOrd)`") + cx.span_bug(span, "not exactly 2 arguments in `derives(Ord)`") } else { - some_ordering_collapsed(cx, span, PartialCmpOp, tag_tuple) - } - }), - cx, span, substr) -} - -/// Strict inequality. -fn cs_op(less: bool, equal: bool, cx: &mut ExtCtxt, - span: Span, substr: &Substructure) -> P<Expr> { - let op = if less {ast::BiLt} else {ast::BiGt}; - cs_fold( - false, // need foldr, - |cx, span, subexpr, self_f, other_fs| { - /* - build up a series of chain ||'s and &&'s from the inside - out (hence foldr) to get lexical ordering, i.e. for op == - `ast::lt` - - ``` - self.f1 < other.f1 || (!(other.f1 < self.f1) && - (self.f2 < other.f2 || (!(other.f2 < self.f2) && - (false) - )) - ) - ``` - - The optimiser should remove the redundancy. We explicitly - get use the binops to avoid auto-deref dereferencing too many - layers of pointers, if the type includes pointers. - */ - let other_f = match other_fs { - [ref o_f] => o_f, - _ => cx.span_bug(span, "not exactly 2 arguments in `derive(PartialOrd)`") - }; - - let cmp = cx.expr_binary(span, op, self_f.clone(), other_f.clone()); - - let not_cmp = cx.expr_unary(span, ast::UnNot, - cx.expr_binary(span, op, other_f.clone(), self_f)); - - let and = cx.expr_binary(span, ast::BiAnd, not_cmp, subexpr); - cx.expr_binary(span, ast::BiOr, cmp, and) - }, - cx.expr_bool(span, equal), - Box::new(|cx, span, (self_args, tag_tuple), _non_self_args| { - if self_args.len() != 2 { - cx.span_bug(span, "not exactly 2 arguments in `derive(PartialOrd)`") - } else { - let op = match (less, equal) { - (true, true) => LeOp, (true, false) => LtOp, - (false, true) => GeOp, (false, false) => GtOp, - }; - some_ordering_collapsed(cx, span, op, tag_tuple) + ordering_collapsed(cx, span, tag_tuple) } }), cx, span, substr) diff --git a/src/libsyntax/ext/deriving/cmp/partial_eq.rs b/src/libsyntax/ext/deriving/cmp/partial_eq.rs new file mode 100644 index 00000000000..db53ea63e53 --- /dev/null +++ b/src/libsyntax/ext/deriving/cmp/partial_eq.rs @@ -0,0 +1,95 @@ +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use ast::{MetaItem, Item, Expr, self}; +use codemap::Span; +use ext::base::ExtCtxt; +use ext::build::AstBuilder; +use ext::deriving::generic::*; +use ext::deriving::generic::ty::*; +use parse::token::InternedString; +use ptr::P; + +pub fn expand_deriving_partial_eq<F>(cx: &mut ExtCtxt, + span: Span, + mitem: &MetaItem, + item: &Item, + push: F) where + F: FnOnce(P<Item>), +{ + // structures are equal if all fields are equal, and non equal, if + // any fields are not equal or if the enum variants are different + fn cs_eq(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> P<Expr> { + cs_fold( + true, // use foldl + |cx, span, subexpr, self_f, other_fs| { + let other_f = match other_fs { + [ref o_f] => o_f, + _ => cx.span_bug(span, "not exactly 2 arguments in `derive(PartialEq)`") + }; + + let eq = cx.expr_binary(span, ast::BiEq, self_f, other_f.clone()); + + cx.expr_binary(span, ast::BiAnd, subexpr, eq) + }, + cx.expr_bool(span, true), + Box::new(|cx, span, _, _| cx.expr_bool(span, false)), + cx, span, substr) + } + fn cs_ne(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> P<Expr> { + cs_fold( + true, // use foldl + |cx, span, subexpr, self_f, other_fs| { + let other_f = match other_fs { + [ref o_f] => o_f, + _ => cx.span_bug(span, "not exactly 2 arguments in `derive(PartialEq)`") + }; + + let eq = cx.expr_binary(span, ast::BiNe, self_f, other_f.clone()); + + cx.expr_binary(span, ast::BiOr, subexpr, eq) + }, + cx.expr_bool(span, false), + Box::new(|cx, span, _, _| cx.expr_bool(span, true)), + cx, span, substr) + } + + macro_rules! md { + ($name:expr, $f:ident) => { { + let inline = cx.meta_word(span, InternedString::new("inline")); + let attrs = vec!(cx.attribute(span, inline)); + MethodDef { + name: $name, + generics: LifetimeBounds::empty(), + explicit_self: borrowed_explicit_self(), + args: vec!(borrowed_self()), + ret_ty: Literal(path_local!(bool)), + attributes: attrs, + combine_substructure: combine_substructure(Box::new(|a, b, c| { + $f(a, b, c) + })) + } + } } + } + + let trait_def = TraitDef { + span: span, + attributes: Vec::new(), + path: path_std!(cx, core::cmp::PartialEq), + additional_bounds: Vec::new(), + generics: LifetimeBounds::empty(), + methods: vec!( + md!("eq", cs_eq), + md!("ne", cs_ne) + ), + associated_types: Vec::new(), + }; + trait_def.expand(cx, mitem, item, push) +} diff --git a/src/libsyntax/ext/deriving/cmp/partial_ord.rs b/src/libsyntax/ext/deriving/cmp/partial_ord.rs new file mode 100644 index 00000000000..4e162d82bbf --- /dev/null +++ b/src/libsyntax/ext/deriving/cmp/partial_ord.rs @@ -0,0 +1,238 @@ +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +pub use self::OrderingOp::*; + +use ast; +use ast::{MetaItem, Item, Expr}; +use codemap::Span; +use ext::base::ExtCtxt; +use ext::build::AstBuilder; +use ext::deriving::generic::*; +use ext::deriving::generic::ty::*; +use parse::token::InternedString; +use ptr::P; + +pub fn expand_deriving_partial_ord<F>(cx: &mut ExtCtxt, + span: Span, + mitem: &MetaItem, + item: &Item, + push: F) where + F: FnOnce(P<Item>), +{ + macro_rules! md { + ($name:expr, $op:expr, $equal:expr) => { { + let inline = cx.meta_word(span, InternedString::new("inline")); + let attrs = vec!(cx.attribute(span, inline)); + MethodDef { + name: $name, + generics: LifetimeBounds::empty(), + explicit_self: borrowed_explicit_self(), + args: vec!(borrowed_self()), + ret_ty: Literal(path_local!(bool)), + attributes: attrs, + combine_substructure: combine_substructure(Box::new(|cx, span, substr| { + cs_op($op, $equal, cx, span, substr) + })) + } + } } + } + + let ordering_ty = Literal(path_std!(cx, core::cmp::Ordering)); + let ret_ty = Literal(Path::new_(pathvec_std!(cx, core::option::Option), + None, + vec![box ordering_ty], + true)); + + let inline = cx.meta_word(span, InternedString::new("inline")); + let attrs = vec!(cx.attribute(span, inline)); + + let partial_cmp_def = MethodDef { + name: "partial_cmp", + generics: LifetimeBounds::empty(), + explicit_self: borrowed_explicit_self(), + args: vec![borrowed_self()], + ret_ty: ret_ty, + attributes: attrs, + combine_substructure: combine_substructure(Box::new(|cx, span, substr| { + cs_partial_cmp(cx, span, substr) + })) + }; + + let trait_def = TraitDef { + span: span, + attributes: vec![], + path: path_std!(cx, core::cmp::PartialOrd), + additional_bounds: vec![], + generics: LifetimeBounds::empty(), + methods: vec![ + partial_cmp_def, + md!("lt", true, false), + md!("le", true, true), + md!("gt", false, false), + md!("ge", false, true) + ], + associated_types: Vec::new(), + }; + trait_def.expand(cx, mitem, item, push) +} + +#[derive(Copy, Clone)] +pub enum OrderingOp { + PartialCmpOp, LtOp, LeOp, GtOp, GeOp, +} + +pub fn some_ordering_collapsed(cx: &mut ExtCtxt, + span: Span, + op: OrderingOp, + self_arg_tags: &[ast::Ident]) -> P<ast::Expr> { + let lft = cx.expr_ident(span, self_arg_tags[0]); + let rgt = cx.expr_addr_of(span, cx.expr_ident(span, self_arg_tags[1])); + let op_str = match op { + PartialCmpOp => "partial_cmp", + LtOp => "lt", LeOp => "le", + GtOp => "gt", GeOp => "ge", + }; + cx.expr_method_call(span, lft, cx.ident_of(op_str), vec![rgt]) +} + +pub fn cs_partial_cmp(cx: &mut ExtCtxt, span: Span, + substr: &Substructure) -> P<Expr> { + let test_id = cx.ident_of("__test"); + let ordering = cx.path_global(span, + vec!(cx.ident_of_std("core"), + cx.ident_of("cmp"), + cx.ident_of("Ordering"), + cx.ident_of("Equal"))); + let ordering = cx.expr_path(ordering); + let equals_expr = cx.expr_some(span, ordering); + + let partial_cmp_path = vec![ + cx.ident_of_std("core"), + cx.ident_of("cmp"), + cx.ident_of("PartialOrd"), + cx.ident_of("partial_cmp"), + ]; + + /* + Builds: + + let __test = ::std::cmp::PartialOrd::partial_cmp(&self_field1, &other_field1); + if __test == ::std::option::Option::Some(::std::cmp::Ordering::Equal) { + let __test = ::std::cmp::PartialOrd::partial_cmp(&self_field2, &other_field2); + if __test == ::std::option::Option::Some(::std::cmp::Ordering::Equal) { + ... + } else { + __test + } + } else { + __test + } + + FIXME #6449: These `if`s could/should be `match`es. + */ + cs_fold( + // foldr nests the if-elses correctly, leaving the first field + // as the outermost one, and the last as the innermost. + false, + |cx, span, old, self_f, other_fs| { + // let __test = new; + // if __test == Some(::std::cmp::Ordering::Equal) { + // old + // } else { + // __test + // } + + let new = { + let other_f = match other_fs { + [ref o_f] => o_f, + _ => cx.span_bug(span, "not exactly 2 arguments in `derive(PartialOrd)`"), + }; + + let args = vec![ + cx.expr_addr_of(span, self_f), + cx.expr_addr_of(span, other_f.clone()), + ]; + + cx.expr_call_global(span, partial_cmp_path.clone(), args) + }; + + let assign = cx.stmt_let(span, false, test_id, new); + + let cond = cx.expr_binary(span, ast::BiEq, + cx.expr_ident(span, test_id), + equals_expr.clone()); + let if_ = cx.expr_if(span, + cond, + old, Some(cx.expr_ident(span, test_id))); + cx.expr_block(cx.block(span, vec!(assign), Some(if_))) + }, + equals_expr.clone(), + Box::new(|cx, span, (self_args, tag_tuple), _non_self_args| { + if self_args.len() != 2 { + cx.span_bug(span, "not exactly 2 arguments in `derive(PartialOrd)`") + } else { + some_ordering_collapsed(cx, span, PartialCmpOp, tag_tuple) + } + }), + cx, span, substr) +} + +/// Strict inequality. +fn cs_op(less: bool, equal: bool, cx: &mut ExtCtxt, + span: Span, substr: &Substructure) -> P<Expr> { + let op = if less {ast::BiLt} else {ast::BiGt}; + cs_fold( + false, // need foldr, + |cx, span, subexpr, self_f, other_fs| { + /* + build up a series of chain ||'s and &&'s from the inside + out (hence foldr) to get lexical ordering, i.e. for op == + `ast::lt` + + ``` + self.f1 < other.f1 || (!(other.f1 < self.f1) && + (self.f2 < other.f2 || (!(other.f2 < self.f2) && + (false) + )) + ) + ``` + + The optimiser should remove the redundancy. We explicitly + get use the binops to avoid auto-deref dereferencing too many + layers of pointers, if the type includes pointers. + */ + let other_f = match other_fs { + [ref o_f] => o_f, + _ => cx.span_bug(span, "not exactly 2 arguments in `derive(PartialOrd)`") + }; + + let cmp = cx.expr_binary(span, op, self_f.clone(), other_f.clone()); + + let not_cmp = cx.expr_unary(span, ast::UnNot, + cx.expr_binary(span, op, other_f.clone(), self_f)); + + let and = cx.expr_binary(span, ast::BiAnd, not_cmp, subexpr); + cx.expr_binary(span, ast::BiOr, cmp, and) + }, + cx.expr_bool(span, equal), + Box::new(|cx, span, (self_args, tag_tuple), _non_self_args| { + if self_args.len() != 2 { + cx.span_bug(span, "not exactly 2 arguments in `derive(PartialOrd)`") + } else { + let op = match (less, equal) { + (true, true) => LeOp, (true, false) => LtOp, + (false, true) => GeOp, (false, false) => GtOp, + }; + some_ordering_collapsed(cx, span, op, tag_tuple) + } + }), + cx, span, substr) +} diff --git a/src/libsyntax/ext/deriving/cmp/totaleq.rs b/src/libsyntax/ext/deriving/cmp/totaleq.rs deleted file mode 100644 index 83164d242e8..00000000000 --- a/src/libsyntax/ext/deriving/cmp/totaleq.rs +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or -// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use ast::{MetaItem, Item, Expr}; -use codemap::Span; -use ext::base::ExtCtxt; -use ext::build::AstBuilder; -use ext::deriving::generic::*; -use ext::deriving::generic::ty::*; -use parse::token::InternedString; -use ptr::P; - -pub fn expand_deriving_totaleq<F>(cx: &mut ExtCtxt, - span: Span, - mitem: &MetaItem, - item: &Item, - push: F) where - F: FnOnce(P<Item>), -{ - fn cs_total_eq_assert(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> P<Expr> { - cs_same_method(|cx, span, exprs| { - // create `a.<method>(); b.<method>(); c.<method>(); ...` - // (where method is `assert_receiver_is_total_eq`) - let stmts = exprs.into_iter().map(|e| cx.stmt_expr(e)).collect(); - let block = cx.block(span, stmts, None); - cx.expr_block(block) - }, - Box::new(|cx, sp, _, _| { - cx.span_bug(sp, "non matching enums in derive(Eq)?") }), - cx, - span, - substr) - } - - let inline = cx.meta_word(span, InternedString::new("inline")); - let hidden = cx.meta_word(span, InternedString::new("hidden")); - let doc = cx.meta_list(span, InternedString::new("doc"), vec!(hidden)); - let attrs = vec!(cx.attribute(span, inline), - cx.attribute(span, doc)); - let trait_def = TraitDef { - span: span, - attributes: Vec::new(), - path: path_std!(cx, core::cmp::Eq), - additional_bounds: Vec::new(), - generics: LifetimeBounds::empty(), - methods: vec!( - MethodDef { - name: "assert_receiver_is_total_eq", - generics: LifetimeBounds::empty(), - explicit_self: borrowed_explicit_self(), - args: vec!(), - ret_ty: nil_ty(), - attributes: attrs, - combine_substructure: combine_substructure(Box::new(|a, b, c| { - cs_total_eq_assert(a, b, c) - })) - } - ), - associated_types: Vec::new(), - }; - trait_def.expand(cx, mitem, item, push) -} diff --git a/src/libsyntax/ext/deriving/cmp/totalord.rs b/src/libsyntax/ext/deriving/cmp/totalord.rs deleted file mode 100644 index 1de955856e7..00000000000 --- a/src/libsyntax/ext/deriving/cmp/totalord.rs +++ /dev/null @@ -1,142 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or -// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use ast; -use ast::{MetaItem, Item, Expr}; -use codemap::Span; -use ext::base::ExtCtxt; -use ext::build::AstBuilder; -use ext::deriving::generic::*; -use ext::deriving::generic::ty::*; -use parse::token::InternedString; -use ptr::P; - -pub fn expand_deriving_totalord<F>(cx: &mut ExtCtxt, - span: Span, - mitem: &MetaItem, - item: &Item, - push: F) where - F: FnOnce(P<Item>), -{ - let inline = cx.meta_word(span, InternedString::new("inline")); - let attrs = vec!(cx.attribute(span, inline)); - let trait_def = TraitDef { - span: span, - attributes: Vec::new(), - path: path_std!(cx, core::cmp::Ord), - additional_bounds: Vec::new(), - generics: LifetimeBounds::empty(), - methods: vec!( - MethodDef { - name: "cmp", - generics: LifetimeBounds::empty(), - explicit_self: borrowed_explicit_self(), - args: vec!(borrowed_self()), - ret_ty: Literal(path_std!(cx, core::cmp::Ordering)), - attributes: attrs, - combine_substructure: combine_substructure(Box::new(|a, b, c| { - cs_cmp(a, b, c) - })), - } - ), - associated_types: Vec::new(), - }; - - trait_def.expand(cx, mitem, item, push) -} - - -pub fn ordering_collapsed(cx: &mut ExtCtxt, - span: Span, - self_arg_tags: &[ast::Ident]) -> P<ast::Expr> { - let lft = cx.expr_ident(span, self_arg_tags[0]); - let rgt = cx.expr_addr_of(span, cx.expr_ident(span, self_arg_tags[1])); - cx.expr_method_call(span, lft, cx.ident_of("cmp"), vec![rgt]) -} - -pub fn cs_cmp(cx: &mut ExtCtxt, span: Span, - substr: &Substructure) -> P<Expr> { - let test_id = cx.ident_of("__test"); - let equals_path = cx.path_global(span, - vec!(cx.ident_of_std("core"), - cx.ident_of("cmp"), - cx.ident_of("Ordering"), - cx.ident_of("Equal"))); - - let cmp_path = vec![ - cx.ident_of_std("core"), - cx.ident_of("cmp"), - cx.ident_of("Ord"), - cx.ident_of("cmp"), - ]; - - /* - Builds: - - let __test = ::std::cmp::Ord::cmp(&self_field1, &other_field1); - if other == ::std::cmp::Ordering::Equal { - let __test = ::std::cmp::Ord::cmp(&self_field2, &other_field2); - if __test == ::std::cmp::Ordering::Equal { - ... - } else { - __test - } - } else { - __test - } - - FIXME #6449: These `if`s could/should be `match`es. - */ - cs_fold( - // foldr nests the if-elses correctly, leaving the first field - // as the outermost one, and the last as the innermost. - false, - |cx, span, old, self_f, other_fs| { - // let __test = new; - // if __test == ::std::cmp::Ordering::Equal { - // old - // } else { - // __test - // } - - let new = { - let other_f = match other_fs { - [ref o_f] => o_f, - _ => cx.span_bug(span, "not exactly 2 arguments in `derive(PartialOrd)`"), - }; - - let args = vec![ - cx.expr_addr_of(span, self_f), - cx.expr_addr_of(span, other_f.clone()), - ]; - - cx.expr_call_global(span, cmp_path.clone(), args) - }; - - let assign = cx.stmt_let(span, false, test_id, new); - - let cond = cx.expr_binary(span, ast::BiEq, - cx.expr_ident(span, test_id), - cx.expr_path(equals_path.clone())); - let if_ = cx.expr_if(span, - cond, - old, Some(cx.expr_ident(span, test_id))); - cx.expr_block(cx.block(span, vec!(assign), Some(if_))) - }, - cx.expr_path(equals_path.clone()), - Box::new(|cx, span, (self_args, tag_tuple), _non_self_args| { - if self_args.len() != 2 { - cx.span_bug(span, "not exactly 2 arguments in `derives(Ord)`") - } else { - ordering_collapsed(cx, span, tag_tuple) - } - }), - cx, span, substr) -} diff --git a/src/libsyntax/ext/deriving/mod.rs b/src/libsyntax/ext/deriving/mod.rs index 65554efdd68..f3327a4ef5f 100644 --- a/src/libsyntax/ext/deriving/mod.rs +++ b/src/libsyntax/ext/deriving/mod.rs @@ -65,14 +65,14 @@ pub mod show; pub mod default; pub mod primitive; +#[path="cmp/partial_eq.rs"] +pub mod partial_eq; #[path="cmp/eq.rs"] pub mod eq; -#[path="cmp/totaleq.rs"] -pub mod totaleq; +#[path="cmp/partial_ord.rs"] +pub mod partial_ord; #[path="cmp/ord.rs"] pub mod ord; -#[path="cmp/totalord.rs"] -pub mod totalord; pub mod generic; @@ -162,10 +162,10 @@ derive_traits! { "RustcDecodable" => decodable::expand_deriving_rustc_decodable, - "PartialEq" => eq::expand_deriving_eq, - "Eq" => totaleq::expand_deriving_totaleq, - "PartialOrd" => ord::expand_deriving_ord, - "Ord" => totalord::expand_deriving_totalord, + "PartialEq" => partial_eq::expand_deriving_partial_eq, + "Eq" => eq::expand_deriving_eq, + "PartialOrd" => partial_ord::expand_deriving_partial_ord, + "Ord" => ord::expand_deriving_ord, "Debug" => show::expand_deriving_show, |
