]> git.lizzy.rs Git - rust.git/commitdiff
syntax: move ext/deriving.rs to ext/deriving/mod.rs
authorAndrew Paseltiner <apaseltiner@gmail.com>
Tue, 19 Mar 2013 11:45:47 +0000 (07:45 -0400)
committerAndrew Paseltiner <apaseltiner@gmail.com>
Tue, 19 Mar 2013 22:41:19 +0000 (18:41 -0400)
src/libsyntax/ext/deriving.rs [deleted file]
src/libsyntax/ext/deriving/mod.rs [new file with mode: 0644]
src/libsyntax/syntax.rc

diff --git a/src/libsyntax/ext/deriving.rs b/src/libsyntax/ext/deriving.rs
deleted file mode 100644 (file)
index a6165e5..0000000
+++ /dev/null
@@ -1,1267 +0,0 @@
-// Copyright 2012 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.
-
-/// The compiler code necessary to implement the #[deriving_eq] and
-/// #[deriving_iter_bytes] extensions.
-
-use core::prelude::*;
-
-use ast;
-use ast::{TraitTyParamBound, Ty, and, bind_by_ref, binop, deref, enum_def};
-use ast::{enum_variant_kind, expr, expr_match, ident, impure_fn, item, item_};
-use ast::{item_enum, item_impl, item_struct, Generics};
-use ast::{m_imm, meta_item, method};
-use ast::{named_field, or, pat, pat_ident, pat_wild, public, pure_fn};
-use ast::{stmt, struct_def, struct_variant_kind};
-use ast::{sty_by_ref, sty_region, tuple_variant_kind, ty_nil, TyParam};
-use ast::{TyParamBound, ty_path, ty_rptr, unnamed_field, variant};
-use ext::base::ext_ctxt;
-use ext::build;
-use codemap::{span, spanned};
-use parse::token::special_idents::clownshoes_extensions;
-use ast_util;
-use opt_vec;
-
-use core::uint;
-
-enum Junction {
-    Conjunction,
-    Disjunction,
-}
-
-pub impl Junction {
-    fn to_binop(self) -> binop {
-        match self {
-            Conjunction => and,
-            Disjunction => or,
-        }
-    }
-}
-
-type ExpandDerivingStructDefFn = &'self fn(@ext_ctxt,
-                                          span,
-                                          x: &struct_def,
-                                          ident,
-                                          y: &Generics) -> @item;
-type ExpandDerivingEnumDefFn = &'self fn(@ext_ctxt,
-                                        span,
-                                        x: &enum_def,
-                                        ident,
-                                        y: &Generics) -> @item;
-
-pub fn expand_meta_deriving(cx: @ext_ctxt,
-                            _span: span,
-                            mitem: @meta_item,
-                            in_items: ~[@item])
-                         -> ~[@item] {
-    use ast::{meta_list, meta_name_value, meta_word};
-
-    match mitem.node {
-        meta_name_value(_, l) => {
-            cx.span_err(l.span, ~"unexpected value in `deriving`");
-            in_items
-        }
-        meta_word(_) | meta_list(_, []) => {
-            cx.span_warn(mitem.span, ~"empty trait list in `deriving`");
-            in_items
-        }
-        meta_list(_, titems) => {
-            do titems.foldr(in_items) |&titem, in_items| {
-                match titem.node {
-                    meta_name_value(tname, _) |
-                    meta_list(tname, _) |
-                    meta_word(tname) => {
-                        match *tname {
-                            ~"Clone" => expand_deriving_clone(cx,
-                                titem.span, titem, in_items),
-                            ~"Eq" => expand_deriving_eq(cx, titem.span,
-                                titem, in_items),
-                            ~"IterBytes" => expand_deriving_iter_bytes(cx,
-                                titem.span, titem, in_items),
-                            tname => {
-                                cx.span_err(titem.span, fmt!("unknown \
-                                    `deriving` trait: `%s`", tname));
-                                in_items
-                            }
-                        }
-                    }
-                }
-            }
-        }
-    }
-}
-
-pub fn expand_deriving_eq(cx: @ext_ctxt,
-                          span: span,
-                          _mitem: @meta_item,
-                          in_items: ~[@item])
-                       -> ~[@item] {
-    expand_deriving(cx,
-                    span,
-                    in_items,
-                    expand_deriving_eq_struct_def,
-                    expand_deriving_eq_enum_def)
-}
-
-pub fn expand_deriving_iter_bytes(cx: @ext_ctxt,
-                                  span: span,
-                                  _mitem: @meta_item,
-                                  in_items: ~[@item])
-                               -> ~[@item] {
-    expand_deriving(cx,
-                    span,
-                    in_items,
-                    expand_deriving_iter_bytes_struct_def,
-                    expand_deriving_iter_bytes_enum_def)
-}
-
-pub fn expand_deriving_clone(cx: @ext_ctxt,
-                             span: span,
-                             _: @meta_item,
-                             in_items: ~[@item])
-                          -> ~[@item] {
-    expand_deriving(cx,
-                    span,
-                    in_items,
-                    expand_deriving_clone_struct_def,
-                    expand_deriving_clone_enum_def)
-}
-
-fn expand_deriving(cx: @ext_ctxt,
-                   span: span,
-                   in_items: ~[@item],
-                   expand_deriving_struct_def: ExpandDerivingStructDefFn,
-                   expand_deriving_enum_def: ExpandDerivingEnumDefFn)
-                -> ~[@item] {
-    let mut result = ~[];
-    for in_items.each |item| {
-        result.push(copy *item);
-        match item.node {
-            item_struct(struct_def, ref generics) => {
-                result.push(expand_deriving_struct_def(cx,
-                                                       span,
-                                                       struct_def,
-                                                       item.ident,
-                                                       generics));
-            }
-            item_enum(ref enum_definition, ref generics) => {
-                result.push(expand_deriving_enum_def(cx,
-                                                     span,
-                                                     enum_definition,
-                                                     item.ident,
-                                                     generics));
-            }
-            _ => ()
-        }
-    }
-    result
-}
-
-fn create_impl_item(cx: @ext_ctxt, span: span, +item: item_) -> @item {
-    @ast::item {
-        ident: clownshoes_extensions,
-        attrs: ~[],
-        id: cx.next_id(),
-        node: item,
-        vis: public,
-        span: span,
-    }
-}
-
-/// Creates a method from the given expression, the signature of which
-/// conforms to the `eq` or `ne` method.
-fn create_eq_method(cx: @ext_ctxt,
-                    span: span,
-                    method_ident: ident,
-                    type_ident: ident,
-                    generics: &Generics,
-                    body: @expr)
-                 -> @method {
-    // Create the type of the `other` parameter.
-    let arg_path_type = create_self_type_with_params(cx,
-                                                     span,
-                                                     type_ident,
-                                                     generics);
-    let arg_type = ty_rptr(
-        None,
-        ast::mt { ty: arg_path_type, mutbl: m_imm }
-    );
-    let arg_type = @ast::Ty {
-        id: cx.next_id(),
-        node: arg_type,
-        span: span,
-    };
-
-    // Create the `other` parameter.
-    let other_ident = cx.ident_of(~"__other");
-    let arg = build::mk_arg(cx, span, other_ident, arg_type);
-
-    // Create the type of the return value.
-    let bool_ident = cx.ident_of(~"bool");
-    let output_type = build::mk_raw_path(span, ~[ bool_ident ]);
-    let output_type = ty_path(output_type, cx.next_id());
-    let output_type = @ast::Ty {
-        id: cx.next_id(),
-        node: output_type,
-        span: span,
-    };
-
-    // Create the function declaration.
-    let fn_decl = build::mk_fn_decl(~[ arg ], output_type);
-
-    // Create the body block.
-    let body_block = build::mk_simple_block(cx, span, body);
-
-    // Create the method.
-    let self_ty = spanned { node: sty_region(None, m_imm), span: span };
-    @ast::method {
-        ident: method_ident,
-        attrs: ~[],
-        generics: ast_util::empty_generics(),
-        self_ty: self_ty,
-        purity: impure_fn,
-        decl: fn_decl,
-        body: body_block,
-        id: cx.next_id(),
-        span: span,
-        self_id: cx.next_id(),
-        vis: public
-    }
-}
-
-fn create_self_type_with_params(cx: @ext_ctxt,
-                                span: span,
-                                type_ident: ident,
-                                generics: &Generics)
-                             -> @Ty {
-    // Create the type parameters on the `self` path.
-    let mut self_ty_params = ~[];
-    for generics.ty_params.each |ty_param| {
-        let self_ty_param = build::mk_simple_ty_path(cx,
-                                                     span,
-                                                     ty_param.ident);
-        self_ty_params.push(self_ty_param);
-    }
-
-    // Create the type of `self`.
-    let self_type = build::mk_raw_path_(span,
-                                        ~[ type_ident ],
-                                        self_ty_params);
-    let self_type = ty_path(self_type, cx.next_id());
-    @ast::Ty { id: cx.next_id(), node: self_type, span: span }
-}
-
-fn create_derived_impl(cx: @ext_ctxt,
-                       span: span,
-                       type_ident: ident,
-                       generics: &Generics,
-                       methods: &[@method],
-                       trait_path: &[ident])
-                    -> @item {
-    /*!
-     *
-     * Given that we are deriving a trait `Tr` for a type `T<'a, ...,
-     * 'z, A, ..., Z>`, creates an impl like:
-     *
-     *      impl<'a, ..., 'z, A:Tr, ..., Z: Tr> Tr for T<A, ..., Z> { ... }
-     *
-     * FIXME(#5090): Remove code duplication between this and the
-     * code in auto_encode.rs
-     */
-
-    // Copy the lifetimes
-    let impl_lifetimes = generics.lifetimes.map(|l| {
-        build::mk_lifetime(cx, l.span, l.ident)
-    });
-
-    // Create the type parameters.
-    let impl_ty_params = generics.ty_params.map(|ty_param| {
-        let bound = build::mk_ty_path_global(cx,
-                                             span,
-                                             trait_path.map(|x| *x));
-        let bounds = @opt_vec::with(TraitTyParamBound(bound));
-        build::mk_ty_param(cx, ty_param.ident, bounds)
-    });
-
-    // Create the reference to the trait.
-    let trait_path = ast::path {
-        span: span,
-        global: true,
-        idents: trait_path.map(|x| *x),
-        rp: None,
-        types: ~[]
-    };
-    let trait_path = @trait_path;
-    let trait_ref = ast::trait_ref {
-        path: trait_path,
-        ref_id: cx.next_id()
-    };
-    let trait_ref = @trait_ref;
-
-    // Create the type of `self`.
-    let self_type = create_self_type_with_params(cx,
-                                                 span,
-                                                 type_ident,
-                                                 generics);
-
-    // Create the impl item.
-    let impl_item = item_impl(Generics {lifetimes: impl_lifetimes,
-                                        ty_params: impl_ty_params},
-                              Some(trait_ref),
-                              self_type,
-                              methods.map(|x| *x));
-    return create_impl_item(cx, span, impl_item);
-}
-
-fn create_derived_eq_impl(cx: @ext_ctxt,
-                          span: span,
-                          type_ident: ident,
-                          generics: &Generics,
-                          eq_method: @method,
-                          ne_method: @method)
-                       -> @item {
-    let methods = [ eq_method, ne_method ];
-    let trait_path = [
-        cx.ident_of(~"core"),
-        cx.ident_of(~"cmp"),
-        cx.ident_of(~"Eq")
-    ];
-    create_derived_impl(cx, span, type_ident, generics, methods, trait_path)
-}
-
-fn create_derived_iter_bytes_impl(cx: @ext_ctxt,
-                                  span: span,
-                                  type_ident: ident,
-                                  generics: &Generics,
-                                  method: @method)
-                               -> @item {
-    let methods = [ method ];
-    let trait_path = [
-        cx.ident_of(~"core"),
-        cx.ident_of(~"to_bytes"),
-        cx.ident_of(~"IterBytes")
-    ];
-    create_derived_impl(cx, span, type_ident, generics, methods, trait_path)
-}
-
-fn create_derived_clone_impl(cx: @ext_ctxt,
-                             span: span,
-                             type_ident: ident,
-                             generics: &Generics,
-                             method: @method)
-                          -> @item {
-    let methods = [ method ];
-    let trait_path = [
-        cx.ident_of(~"core"),
-        cx.ident_of(~"clone"),
-        cx.ident_of(~"Clone"),
-    ];
-    create_derived_impl(cx, span, type_ident, generics, methods, trait_path)
-}
-
-// Creates a method from the given set of statements conforming to the
-// signature of the `iter_bytes` method.
-fn create_iter_bytes_method(cx: @ext_ctxt,
-                            span: span,
-                            +statements: ~[@stmt])
-                         -> @method {
-    // Create the `lsb0` parameter.
-    let bool_ident = cx.ident_of(~"bool");
-    let lsb0_arg_type = build::mk_simple_ty_path(cx, span, bool_ident);
-    let lsb0_ident = cx.ident_of(~"__lsb0");
-    let lsb0_arg = build::mk_arg(cx, span, lsb0_ident, lsb0_arg_type);
-
-    // Create the `f` parameter.
-    let core_ident = cx.ident_of(~"core");
-    let to_bytes_ident = cx.ident_of(~"to_bytes");
-    let cb_ident = cx.ident_of(~"Cb");
-    let core_to_bytes_cb_ident = ~[ core_ident, to_bytes_ident, cb_ident ];
-    let f_arg_type = build::mk_ty_path(cx, span, core_to_bytes_cb_ident);
-    let f_ident = cx.ident_of(~"__f");
-    let f_arg = build::mk_arg(cx, span, f_ident, f_arg_type);
-
-    // Create the type of the return value.
-    let output_type = @ast::Ty { id: cx.next_id(), node: ty_nil, span: span };
-
-    // Create the function declaration.
-    let inputs = ~[ lsb0_arg, f_arg ];
-    let fn_decl = build::mk_fn_decl(inputs, output_type);
-
-    // Create the body block.
-    let body_block = build::mk_block_(cx, span, statements);
-
-    // Create the method.
-    let self_ty = spanned { node: sty_region(None, m_imm), span: span };
-    let method_ident = cx.ident_of(~"iter_bytes");
-    @ast::method {
-        ident: method_ident,
-        attrs: ~[],
-        generics: ast_util::empty_generics(),
-        self_ty: self_ty,
-        purity: impure_fn,
-        decl: fn_decl,
-        body: body_block,
-        id: cx.next_id(),
-        span: span,
-        self_id: cx.next_id(),
-        vis: public
-    }
-}
-
-// Creates a method from the given expression conforming to the signature of
-// the `clone` method.
-fn create_clone_method(cx: @ext_ctxt,
-                       span: span,
-                       +type_ident: ast::ident,
-                       generics: &Generics,
-                       expr: @ast::expr)
-                    -> @method {
-    // Create the type parameters of the return value.
-    let mut output_ty_params = ~[];
-    for generics.ty_params.each |ty_param| {
-        let path = build::mk_ty_path(cx, span, ~[ ty_param.ident ]);
-        output_ty_params.push(path);
-    }
-
-    // Create the type of the return value.
-    let output_type_path = build::mk_raw_path_(span,
-                                               ~[ type_ident ],
-                                               output_ty_params);
-    let output_type = ast::ty_path(output_type_path, cx.next_id());
-    let output_type = @ast::Ty {
-        id: cx.next_id(),
-        node: output_type,
-        span: span
-    };
-
-    // Create the function declaration.
-    let fn_decl = build::mk_fn_decl(~[], output_type);
-
-    // Create the body block.
-    let body_block = build::mk_simple_block(cx, span, expr);
-
-    // Create the self type and method identifier.
-    let self_ty = spanned { node: sty_region(None, m_imm), span: span };
-    let method_ident = cx.ident_of(~"clone");
-
-    // Create the method.
-    @ast::method {
-        ident: method_ident,
-        attrs: ~[],
-        generics: ast_util::empty_generics(),
-        self_ty: self_ty,
-        purity: impure_fn,
-        decl: fn_decl,
-        body: body_block,
-        id: cx.next_id(),
-        span: span,
-        self_id: cx.next_id(),
-        vis: public,
-    }
-}
-
-fn create_subpatterns(cx: @ext_ctxt,
-                      span: span,
-                      prefix: ~str,
-                      n: uint)
-                   -> ~[@pat] {
-    let mut subpats = ~[];
-    for uint::range(0, n) |_i| {
-        // Create the subidentifier.
-        let index = subpats.len().to_str();
-        let ident = cx.ident_of(prefix + index);
-
-        // Create the subpattern.
-        let subpath = build::mk_raw_path(span, ~[ ident ]);
-        let subpat = pat_ident(bind_by_ref(m_imm), subpath, None);
-        let subpat = build::mk_pat(cx, span, subpat);
-        subpats.push(subpat);
-    }
-    return subpats;
-}
-
-fn is_struct_tuple(struct_def: &struct_def) -> bool {
-    struct_def.fields.len() > 0 && struct_def.fields.all(|f| {
-        match f.node.kind {
-            named_field(*) => false,
-            unnamed_field => true
-        }
-    })
-}
-
-fn create_enum_variant_pattern(cx: @ext_ctxt,
-                               span: span,
-                               variant: &variant,
-                               prefix: ~str)
-                            -> @pat {
-    let variant_ident = variant.node.name;
-    match variant.node.kind {
-        tuple_variant_kind(ref variant_args) => {
-            if variant_args.len() == 0 {
-                return build::mk_pat_ident_with_binding_mode(
-                    cx, span, variant_ident, ast::bind_infer);
-            }
-
-            let matching_path = build::mk_raw_path(span, ~[ variant_ident ]);
-            let subpats = create_subpatterns(cx,
-                                             span,
-                                             prefix,
-                                             variant_args.len());
-
-            return build::mk_pat_enum(cx, span, matching_path, subpats);
-        }
-        struct_variant_kind(struct_def) => {
-            let matching_path = build::mk_raw_path(span, ~[ variant_ident ]);
-            let subpats = create_subpatterns(cx,
-                                             span,
-                                             prefix,
-                                             struct_def.fields.len());
-
-            let field_pats = do struct_def.fields.mapi |i, struct_field| {
-                let ident = match struct_field.node.kind {
-                    named_field(ident, _, _) => ident,
-                    unnamed_field => {
-                        cx.span_bug(span, ~"unexpected unnamed field");
-                    }
-                };
-                ast::field_pat { ident: ident, pat: subpats[i] }
-            };
-
-            build::mk_pat_struct(cx, span, matching_path, field_pats)
-        }
-        enum_variant_kind(*) => {
-            cx.span_unimpl(span, ~"enum variants for `deriving`");
-        }
-    }
-}
-
-fn call_substructure_eq_method(cx: @ext_ctxt,
-                               span: span,
-                               self_field: @expr,
-                               other_field_ref: @expr,
-                               method_ident: ident,
-                               junction: Junction,
-                               chain_expr: &mut Option<@expr>) {
-    // Call the substructure method.
-    let self_method = build::mk_access_(cx, span, self_field, method_ident);
-    let self_call = build::mk_call_(cx,
-                                    span,
-                                    self_method,
-                                    ~[ other_field_ref ]);
-
-    // Connect to the outer expression if necessary.
-    *chain_expr = match *chain_expr {
-        None => Some(self_call),
-        Some(copy old_outer_expr) => {
-            let binop = junction.to_binop();
-            let chain_expr = build::mk_binary(cx,
-                                              span,
-                                              binop,
-                                              old_outer_expr,
-                                              self_call);
-            Some(chain_expr)
-        }
-    };
-}
-
-fn finish_eq_chain_expr(cx: @ext_ctxt,
-                        span: span,
-                        chain_expr: Option<@expr>,
-                        junction: Junction)
-                     -> @expr {
-    match chain_expr {
-        None => {
-            match junction {
-                Conjunction => build::mk_bool(cx, span, true),
-                Disjunction => build::mk_bool(cx, span, false),
-            }
-        }
-        Some(ref outer_expr) => *outer_expr,
-    }
-}
-
-fn call_substructure_iter_bytes_method(cx: @ext_ctxt,
-                                       span: span,
-                                       self_field: @expr)
-                                    -> @stmt {
-    // Gather up the parameters we want to chain along.
-    let lsb0_ident = cx.ident_of(~"__lsb0");
-    let f_ident = cx.ident_of(~"__f");
-    let lsb0_expr = build::mk_path(cx, span, ~[ lsb0_ident ]);
-    let f_expr = build::mk_path(cx, span, ~[ f_ident ]);
-
-    // Call the substructure method.
-    let iter_bytes_ident = cx.ident_of(~"iter_bytes");
-    let self_method = build::mk_access_(cx,
-                                        span,
-                                        self_field,
-                                        iter_bytes_ident);
-    let self_call = build::mk_call_(cx,
-                                    span,
-                                    self_method,
-                                    ~[ lsb0_expr, f_expr ]);
-
-    // Create a statement out of this expression.
-    build::mk_stmt(cx, span, self_call)
-}
-
-fn call_substructure_clone_method(cx: @ext_ctxt,
-                                  span: span,
-                                  self_field: @expr)
-                               -> @expr {
-    // Call the substructure method.
-    let clone_ident = cx.ident_of(~"clone");
-    let self_method = build::mk_access_(cx, span, self_field, clone_ident);
-    build::mk_call_(cx, span, self_method, ~[])
-}
-
-fn variant_arg_count(cx: @ext_ctxt, span: span, variant: &variant) -> uint {
-    match variant.node.kind {
-        tuple_variant_kind(ref args) => args.len(),
-        struct_variant_kind(ref struct_def) => struct_def.fields.len(),
-        enum_variant_kind(*) => {
-            cx.span_bug(span, ~"variant_arg_count: enum variants deprecated")
-        }
-    }
-}
-
-fn expand_deriving_eq_struct_def(cx: @ext_ctxt,
-                                 span: span,
-                                 struct_def: &struct_def,
-                                 type_ident: ident,
-                                 generics: &Generics)
-                              -> @item {
-    // Create the methods.
-    let eq_ident = cx.ident_of(~"eq");
-    let ne_ident = cx.ident_of(~"ne");
-
-    let derive_struct_fn = if is_struct_tuple(struct_def) {
-        expand_deriving_eq_struct_tuple_method
-    } else {
-        expand_deriving_eq_struct_method
-    };
-
-    let eq_method = derive_struct_fn(cx,
-                                     span,
-                                     struct_def,
-                                     eq_ident,
-                                     type_ident,
-                                     generics,
-                                     Conjunction);
-    let ne_method = derive_struct_fn(cx,
-                                     span,
-                                     struct_def,
-                                     ne_ident,
-                                     type_ident,
-                                     generics,
-                                     Disjunction);
-
-    // Create the implementation.
-    return create_derived_eq_impl(cx,
-                                  span,
-                                  type_ident,
-                                  generics,
-                                  eq_method,
-                                  ne_method);
-}
-
-fn expand_deriving_eq_enum_def(cx: @ext_ctxt,
-                               span: span,
-                               enum_definition: &enum_def,
-                               type_ident: ident,
-                               generics: &Generics)
-                            -> @item {
-    // Create the methods.
-    let eq_ident = cx.ident_of(~"eq");
-    let ne_ident = cx.ident_of(~"ne");
-    let eq_method = expand_deriving_eq_enum_method(cx,
-                                                   span,
-                                                   enum_definition,
-                                                   eq_ident,
-                                                   type_ident,
-                                                   generics,
-                                                   Conjunction);
-    let ne_method = expand_deriving_eq_enum_method(cx,
-                                                   span,
-                                                   enum_definition,
-                                                   ne_ident,
-                                                   type_ident,
-                                                   generics,
-                                                   Disjunction);
-
-    // Create the implementation.
-    return create_derived_eq_impl(cx,
-                                  span,
-                                  type_ident,
-                                  generics,
-                                  eq_method,
-                                  ne_method);
-}
-
-fn expand_deriving_iter_bytes_struct_def(cx: @ext_ctxt,
-                                         span: span,
-                                         struct_def: &struct_def,
-                                         type_ident: ident,
-                                         generics: &Generics)
-                                      -> @item {
-    // Create the method.
-    let method = expand_deriving_iter_bytes_struct_method(cx,
-                                                          span,
-                                                          struct_def);
-
-    // Create the implementation.
-    return create_derived_iter_bytes_impl(cx,
-                                          span,
-                                          type_ident,
-                                          generics,
-                                          method);
-}
-
-fn expand_deriving_iter_bytes_enum_def(cx: @ext_ctxt,
-                                       span: span,
-                                       enum_definition: &enum_def,
-                                       type_ident: ident,
-                                       generics: &Generics)
-                                    -> @item {
-    // Create the method.
-    let method = expand_deriving_iter_bytes_enum_method(cx,
-                                                        span,
-                                                        enum_definition);
-
-    // Create the implementation.
-    return create_derived_iter_bytes_impl(cx,
-                                          span,
-                                          type_ident,
-                                          generics,
-                                          method);
-}
-
-fn expand_deriving_clone_struct_def(cx: @ext_ctxt,
-                                    span: span,
-                                    struct_def: &struct_def,
-                                    type_ident: ident,
-                                    generics: &Generics)
-                                 -> @item {
-    // Create the method.
-    let method = if !is_struct_tuple(struct_def) {
-        expand_deriving_clone_struct_method(cx,
-                                            span,
-                                            struct_def,
-                                            type_ident,
-                                            generics)
-    } else {
-        expand_deriving_clone_tuple_struct_method(cx,
-                                                  span,
-                                                  struct_def,
-                                                  type_ident,
-                                                  generics)
-    };
-
-    // Create the implementation.
-    create_derived_clone_impl(cx, span, type_ident, generics, method)
-}
-
-fn expand_deriving_clone_enum_def(cx: @ext_ctxt,
-                                  span: span,
-                                  enum_definition: &enum_def,
-                                  type_ident: ident,
-                                  generics: &Generics)
-                               -> @item {
-    // Create the method.
-    let method = expand_deriving_clone_enum_method(cx,
-                                                   span,
-                                                   enum_definition,
-                                                   type_ident,
-                                                   generics);
-
-    // Create the implementation.
-    create_derived_clone_impl(cx, span, type_ident, generics, method)
-}
-
-fn expand_deriving_eq_struct_method(cx: @ext_ctxt,
-                                    span: span,
-                                    struct_def: &struct_def,
-                                    method_ident: ident,
-                                    type_ident: ident,
-                                    generics: &Generics,
-                                    junction: Junction)
-                                 -> @method {
-    let self_ident = cx.ident_of(~"self");
-    let other_ident = cx.ident_of(~"__other");
-
-    // Create the body of the method.
-    let mut outer_expr = None;
-    for struct_def.fields.each |struct_field| {
-        match struct_field.node.kind {
-            named_field(ident, _, _) => {
-                // Create the accessor for the other field.
-                let other_field = build::mk_access(cx,
-                                                   span,
-                                                   ~[ other_ident ],
-                                                   ident);
-                let other_field_ref = build::mk_addr_of(cx,
-                                                        span,
-                                                        other_field);
-
-                // Create the accessor for this field.
-                let self_field = build::mk_access(cx,
-                                                  span,
-                                                  ~[ self_ident ],
-                                                  ident);
-
-                // Call the substructure method.
-                call_substructure_eq_method(cx,
-                                            span,
-                                            self_field,
-                                            other_field_ref,
-                                            method_ident,
-                                            junction,
-                                            &mut outer_expr);
-            }
-            unnamed_field => {
-                cx.span_unimpl(span, ~"unnamed fields with `deriving_eq`");
-            }
-        }
-    }
-
-    // Create the method itself.
-    let body = finish_eq_chain_expr(cx, span, outer_expr, junction);
-    return create_eq_method(cx,
-                            span,
-                            method_ident,
-                            type_ident,
-                            generics,
-                            body);
-}
-
-fn expand_deriving_iter_bytes_struct_method(cx: @ext_ctxt,
-                                            span: span,
-                                            struct_def: &struct_def)
-                                         -> @method {
-    let self_ident = cx.ident_of(~"self");
-
-    // Create the body of the method.
-    let mut statements = ~[];
-    for struct_def.fields.each |struct_field| {
-        match struct_field.node.kind {
-            named_field(ident, _, _) => {
-                // Create the accessor for this field.
-                let self_field = build::mk_access(cx,
-                                                  span,
-                                                  ~[ self_ident ],
-                                                  ident);
-
-                // Call the substructure method.
-                let stmt = call_substructure_iter_bytes_method(cx,
-                                                               span,
-                                                               self_field);
-                statements.push(stmt);
-            }
-            unnamed_field => {
-                cx.span_unimpl(span,
-                               ~"unnamed fields with `deriving_iter_bytes`");
-            }
-        }
-    }
-
-    // Create the method itself.
-    return create_iter_bytes_method(cx, span, statements);
-}
-
-fn expand_deriving_clone_struct_method(cx: @ext_ctxt,
-                                       span: span,
-                                       struct_def: &struct_def,
-                                       type_ident: ident,
-                                       generics: &Generics)
-                                    -> @method {
-    let self_ident = cx.ident_of(~"self");
-
-    // Create the new fields.
-    let mut fields = ~[];
-    for struct_def.fields.each |struct_field| {
-        match struct_field.node.kind {
-            named_field(ident, _, _) => {
-                // Create the accessor for this field.
-                let self_field = build::mk_access(cx,
-                                                  span,
-                                                  ~[ self_ident ],
-                                                  ident);
-
-                // Call the substructure method.
-                let call = call_substructure_clone_method(cx,
-                                                          span,
-                                                          self_field);
-
-                let field = build::Field { ident: ident, ex: call };
-                fields.push(field);
-            }
-            unnamed_field => {
-                cx.span_bug(span,
-                            ~"unnamed fields in \
-                              expand_deriving_clone_struct_method");
-            }
-        }
-    }
-
-    // Create the struct literal.
-    let struct_literal = build::mk_struct_e(cx,
-                                            span,
-                                            ~[ type_ident ],
-                                            fields);
-    create_clone_method(cx, span, type_ident, generics, struct_literal)
-}
-
-fn expand_deriving_clone_tuple_struct_method(cx: @ext_ctxt,
-                                             span: span,
-                                             struct_def: &struct_def,
-                                             type_ident: ident,
-                                             generics: &Generics)
-                                          -> @method {
-    // Create the pattern for the match.
-    let matching_path = build::mk_raw_path(span, ~[ type_ident ]);
-    let field_count = struct_def.fields.len();
-    let subpats = create_subpatterns(cx, span, ~"__self", field_count);
-    let pat = build::mk_pat_enum(cx, span, matching_path, subpats);
-
-    // Create the new fields.
-    let mut subcalls = ~[];
-    for uint::range(0, struct_def.fields.len()) |i| {
-        // Create the expression for this field.
-        let field_ident = cx.ident_of(~"__self" + i.to_str());
-        let field = build::mk_path(cx, span, ~[ field_ident ]);
-
-        // Call the substructure method.
-        let subcall = call_substructure_clone_method(cx, span, field);
-        subcalls.push(subcall);
-    }
-
-    // Create the call to the struct constructor.
-    let call = build::mk_call(cx, span, ~[ type_ident ], subcalls);
-
-    // Create the pattern body.
-    let match_body_block = build::mk_simple_block(cx, span, call);
-
-    // Create the arm.
-    let arm = ast::arm {
-        pats: ~[ pat ],
-        guard: None,
-        body: match_body_block
-    };
-
-    // Create the method body.
-    let self_match_expr = expand_enum_or_struct_match(cx, span, ~[ arm ]);
-
-    // Create the method.
-    create_clone_method(cx, span, type_ident, generics, self_match_expr)
-}
-
-fn expand_deriving_eq_enum_method(cx: @ext_ctxt,
-                                  span: span,
-                                  enum_definition: &enum_def,
-                                  method_ident: ident,
-                                  type_ident: ident,
-                                  generics: &Generics,
-                                  junction: Junction)
-                               -> @method {
-    let self_ident = cx.ident_of(~"self");
-    let other_ident = cx.ident_of(~"__other");
-
-    let is_eq;
-    match junction {
-        Conjunction => is_eq = true,
-        Disjunction => is_eq = false,
-    }
-
-    // Create the arms of the self match in the method body.
-    let mut self_arms = ~[];
-    for enum_definition.variants.each |self_variant| {
-        let mut other_arms = ~[];
-
-        // Create the matching pattern.
-        let matching_pat = create_enum_variant_pattern(cx,
-                                                       span,
-                                                       self_variant,
-                                                       ~"__other");
-
-        // Create the matching pattern body.
-        let mut matching_body_expr = None;
-        for uint::range(0, variant_arg_count(cx, span, self_variant)) |i| {
-            // Create the expression for the other field.
-            let other_field_ident = cx.ident_of(~"__other" + i.to_str());
-            let other_field = build::mk_path(cx,
-                                             span,
-                                             ~[ other_field_ident ]);
-
-            // Create the expression for this field.
-            let self_field_ident = cx.ident_of(~"__self" + i.to_str());
-            let self_field = build::mk_path(cx, span, ~[ self_field_ident ]);
-
-            // Call the substructure method.
-            call_substructure_eq_method(cx,
-                                        span,
-                                        self_field,
-                                        other_field,
-                                        method_ident,
-                                        junction,
-                                        &mut matching_body_expr);
-        }
-
-        let matching_body_expr = finish_eq_chain_expr(cx,
-                                                      span,
-                                                      matching_body_expr,
-                                                      junction);
-        let matching_body_block = build::mk_simple_block(cx,
-                                                         span,
-                                                         matching_body_expr);
-
-        // Create the matching arm.
-        let matching_arm = ast::arm {
-            pats: ~[ matching_pat ],
-            guard: None,
-            body: matching_body_block
-        };
-        other_arms.push(matching_arm);
-
-        // Maybe generate a non-matching case. If there is only one
-        // variant then there will always be a match.
-        if enum_definition.variants.len() > 1 {
-            // Create the nonmatching pattern.
-            let nonmatching_pat = @ast::pat {
-                id: cx.next_id(),
-                node: pat_wild,
-                span: span
-            };
-
-            // Create the nonmatching pattern body.
-            let nonmatching_expr = build::mk_bool(cx, span, !is_eq);
-            let nonmatching_body_block =
-                build::mk_simple_block(cx,
-                                       span,
-                                       nonmatching_expr);
-
-            // Create the nonmatching arm.
-            let nonmatching_arm = ast::arm {
-                pats: ~[ nonmatching_pat ],
-                guard: None,
-                body: nonmatching_body_block,
-            };
-            other_arms.push(nonmatching_arm);
-        }
-
-        // Create the self pattern.
-        let self_pat = create_enum_variant_pattern(cx,
-                                                   span,
-                                                   self_variant,
-                                                   ~"__self");
-
-        // Create the self pattern body.
-        let other_expr = build::mk_path(cx, span, ~[ other_ident ]);
-        let other_expr = build::mk_unary(cx, span, deref, other_expr);
-        let other_match_expr = expr_match(other_expr, other_arms);
-        let other_match_expr = build::mk_expr(cx,
-                                              span,
-                                              other_match_expr);
-        let other_match_body_block = build::mk_simple_block(cx,
-                                                            span,
-                                                            other_match_expr);
-
-        // Create the self arm.
-        let self_arm = ast::arm {
-            pats: ~[ self_pat ],
-            guard: None,
-            body: other_match_body_block,
-        };
-        self_arms.push(self_arm);
-    }
-
-    // Create the method body.
-    let self_expr = build::mk_path(cx, span, ~[ self_ident ]);
-    let self_expr = build::mk_unary(cx, span, deref, self_expr);
-    let self_match_expr = expr_match(self_expr, self_arms);
-    let self_match_expr = build::mk_expr(cx, span, self_match_expr);
-
-    // Create the method.
-    return create_eq_method(cx,
-                            span,
-                            method_ident,
-                            type_ident,
-                            generics,
-                            self_match_expr);
-}
-
-fn expand_deriving_eq_struct_tuple_method(cx: @ext_ctxt,
-                                          span: span,
-                                          struct_def: &struct_def,
-                                          method_ident: ident,
-                                          type_ident: ident,
-                                          generics: &Generics,
-                                          junction: Junction)
-                                        -> @method {
-    let self_str = ~"self";
-    let other_str = ~"__other";
-    let type_path = build::mk_raw_path(span, ~[type_ident]);
-    let fields = copy struct_def.fields;
-
-    // Create comparison expression, comparing each of the fields
-    let mut match_body = None;
-    for fields.eachi |i, _| {
-        let other_field_ident = cx.ident_of(other_str + i.to_str());
-        let other_field = build::mk_path(cx, span, ~[ other_field_ident ]);
-
-        let self_field_ident = cx.ident_of(self_str + i.to_str());
-        let self_field = build::mk_path(cx, span, ~[ self_field_ident ]);
-
-        call_substructure_eq_method(cx, span, self_field, other_field,
-            method_ident, junction, &mut match_body);
-    }
-    let match_body = finish_eq_chain_expr(cx, span, match_body, junction);
-
-    // Create arm for the '__other' match, containing the comparison expr
-    let other_subpats = create_subpatterns(cx, span, other_str, fields.len());
-    let other_arm = ast::arm {
-        pats: ~[ build::mk_pat_enum(cx, span, type_path, other_subpats) ],
-        guard: None,
-        body: build::mk_simple_block(cx, span, match_body),
-    };
-
-    // Create the match on '__other'
-    let other_expr = build::mk_path(cx, span, ~[ cx.ident_of(other_str) ]);
-    let other_expr = build::mk_unary(cx, span, deref, other_expr);
-    let other_match_expr = expr_match(other_expr, ~[other_arm]);
-    let other_match_expr = build::mk_expr(cx, span, other_match_expr);
-
-    // Create arm for the 'self' match, which contains the '__other' match
-    let self_subpats = create_subpatterns(cx, span, self_str, fields.len());
-    let self_arm = ast::arm {
-        pats: ~[build::mk_pat_enum(cx, span, type_path, self_subpats)],
-        guard: None,
-        body: build::mk_simple_block(cx, span, other_match_expr),
-    };
-
-    // Create the match on 'self'
-    let self_expr = build::mk_path(cx, span, ~[ cx.ident_of(self_str) ]);
-    let self_expr = build::mk_unary(cx, span, deref, self_expr);
-    let self_match_expr = expr_match(self_expr, ~[self_arm]);
-    let self_match_expr = build::mk_expr(cx, span, self_match_expr);
-
-    create_eq_method(cx, span, method_ident,
-        type_ident, generics, self_match_expr)
-}
-
-fn expand_enum_or_struct_match(cx: @ext_ctxt,
-                               span: span,
-                               arms: ~[ ast::arm ])
-                            -> @expr {
-    let self_ident = cx.ident_of(~"self");
-    let self_expr = build::mk_path(cx, span, ~[ self_ident ]);
-    let self_expr = build::mk_unary(cx, span, deref, self_expr);
-    let self_match_expr = expr_match(self_expr, arms);
-    build::mk_expr(cx, span, self_match_expr)
-}
-
-fn expand_deriving_iter_bytes_enum_method(cx: @ext_ctxt,
-                                          span: span,
-                                          enum_definition: &enum_def)
-                                       -> @method {
-    // Create the arms of the match in the method body.
-    let arms = do enum_definition.variants.mapi |i, variant| {
-        // Create the matching pattern.
-        let pat = create_enum_variant_pattern(cx, span, variant, ~"__self");
-
-        // Determine the discriminant. We will feed this value to the byte
-        // iteration function.
-        let discriminant;
-        match variant.node.disr_expr {
-            Some(copy disr_expr) => discriminant = disr_expr,
-            None => discriminant = build::mk_uint(cx, span, i),
-        }
-
-        // Feed the discriminant to the byte iteration function.
-        let mut stmts = ~[];
-        let discrim_stmt = call_substructure_iter_bytes_method(cx,
-                                                               span,
-                                                               discriminant);
-        stmts.push(discrim_stmt);
-
-        // Feed each argument in this variant to the byte iteration function
-        // as well.
-        for uint::range(0, variant_arg_count(cx, span, variant)) |j| {
-            // Create the expression for this field.
-            let field_ident = cx.ident_of(~"__self" + j.to_str());
-            let field = build::mk_path(cx, span, ~[ field_ident ]);
-
-            // Call the substructure method.
-            let stmt = call_substructure_iter_bytes_method(cx, span, field);
-            stmts.push(stmt);
-        }
-
-        // Create the pattern body.
-        let match_body_block = build::mk_block_(cx, span, stmts);
-
-        // Create the arm.
-        ast::arm {
-            pats: ~[ pat ],
-            guard: None,
-            body: match_body_block,
-        }
-    };
-
-    // Create the method body.
-    let self_match_expr = expand_enum_or_struct_match(cx, span, arms);
-    let self_match_stmt = build::mk_stmt(cx, span, self_match_expr);
-
-    // Create the method.
-    create_iter_bytes_method(cx, span, ~[ self_match_stmt ])
-}
-
-fn expand_deriving_clone_enum_method(cx: @ext_ctxt,
-                                     span: span,
-                                     enum_definition: &enum_def,
-                                     type_ident: ident,
-                                     generics: &Generics)
-                                  -> @method {
-    // Create the arms of the match in the method body.
-    let arms = do enum_definition.variants.map |variant| {
-        // Create the matching pattern.
-        let pat = create_enum_variant_pattern(cx, span, variant, ~"__self");
-
-        // Iterate over the variant arguments, creating the subcalls.
-        let mut subcalls = ~[];
-        for uint::range(0, variant_arg_count(cx, span, variant)) |j| {
-            // Create the expression for this field.
-            let field_ident = cx.ident_of(~"__self" + j.to_str());
-            let field = build::mk_path(cx, span, ~[ field_ident ]);
-
-            // Call the substructure method.
-            let subcall = call_substructure_clone_method(cx, span, field);
-            subcalls.push(subcall);
-        }
-
-        // Create the call to the enum variant (if necessary).
-        let call = if subcalls.len() > 0 {
-            build::mk_call(cx, span, ~[ variant.node.name ], subcalls)
-        } else {
-            build::mk_path(cx, span, ~[ variant.node.name ])
-        };
-
-        // Create the pattern body.
-        let match_body_block = build::mk_simple_block(cx, span, call);
-
-        // Create the arm.
-        ast::arm { pats: ~[ pat ], guard: None, body: match_body_block }
-    };
-
-    // Create the method body.
-    let self_match_expr = expand_enum_or_struct_match(cx, span, arms);
-
-    // Create the method.
-    create_clone_method(cx, span, type_ident, generics, self_match_expr)
-}
-
diff --git a/src/libsyntax/ext/deriving/mod.rs b/src/libsyntax/ext/deriving/mod.rs
new file mode 100644 (file)
index 0000000..a6165e5
--- /dev/null
@@ -0,0 +1,1267 @@
+// Copyright 2012 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.
+
+/// The compiler code necessary to implement the #[deriving_eq] and
+/// #[deriving_iter_bytes] extensions.
+
+use core::prelude::*;
+
+use ast;
+use ast::{TraitTyParamBound, Ty, and, bind_by_ref, binop, deref, enum_def};
+use ast::{enum_variant_kind, expr, expr_match, ident, impure_fn, item, item_};
+use ast::{item_enum, item_impl, item_struct, Generics};
+use ast::{m_imm, meta_item, method};
+use ast::{named_field, or, pat, pat_ident, pat_wild, public, pure_fn};
+use ast::{stmt, struct_def, struct_variant_kind};
+use ast::{sty_by_ref, sty_region, tuple_variant_kind, ty_nil, TyParam};
+use ast::{TyParamBound, ty_path, ty_rptr, unnamed_field, variant};
+use ext::base::ext_ctxt;
+use ext::build;
+use codemap::{span, spanned};
+use parse::token::special_idents::clownshoes_extensions;
+use ast_util;
+use opt_vec;
+
+use core::uint;
+
+enum Junction {
+    Conjunction,
+    Disjunction,
+}
+
+pub impl Junction {
+    fn to_binop(self) -> binop {
+        match self {
+            Conjunction => and,
+            Disjunction => or,
+        }
+    }
+}
+
+type ExpandDerivingStructDefFn = &'self fn(@ext_ctxt,
+                                          span,
+                                          x: &struct_def,
+                                          ident,
+                                          y: &Generics) -> @item;
+type ExpandDerivingEnumDefFn = &'self fn(@ext_ctxt,
+                                        span,
+                                        x: &enum_def,
+                                        ident,
+                                        y: &Generics) -> @item;
+
+pub fn expand_meta_deriving(cx: @ext_ctxt,
+                            _span: span,
+                            mitem: @meta_item,
+                            in_items: ~[@item])
+                         -> ~[@item] {
+    use ast::{meta_list, meta_name_value, meta_word};
+
+    match mitem.node {
+        meta_name_value(_, l) => {
+            cx.span_err(l.span, ~"unexpected value in `deriving`");
+            in_items
+        }
+        meta_word(_) | meta_list(_, []) => {
+            cx.span_warn(mitem.span, ~"empty trait list in `deriving`");
+            in_items
+        }
+        meta_list(_, titems) => {
+            do titems.foldr(in_items) |&titem, in_items| {
+                match titem.node {
+                    meta_name_value(tname, _) |
+                    meta_list(tname, _) |
+                    meta_word(tname) => {
+                        match *tname {
+                            ~"Clone" => expand_deriving_clone(cx,
+                                titem.span, titem, in_items),
+                            ~"Eq" => expand_deriving_eq(cx, titem.span,
+                                titem, in_items),
+                            ~"IterBytes" => expand_deriving_iter_bytes(cx,
+                                titem.span, titem, in_items),
+                            tname => {
+                                cx.span_err(titem.span, fmt!("unknown \
+                                    `deriving` trait: `%s`", tname));
+                                in_items
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
+
+pub fn expand_deriving_eq(cx: @ext_ctxt,
+                          span: span,
+                          _mitem: @meta_item,
+                          in_items: ~[@item])
+                       -> ~[@item] {
+    expand_deriving(cx,
+                    span,
+                    in_items,
+                    expand_deriving_eq_struct_def,
+                    expand_deriving_eq_enum_def)
+}
+
+pub fn expand_deriving_iter_bytes(cx: @ext_ctxt,
+                                  span: span,
+                                  _mitem: @meta_item,
+                                  in_items: ~[@item])
+                               -> ~[@item] {
+    expand_deriving(cx,
+                    span,
+                    in_items,
+                    expand_deriving_iter_bytes_struct_def,
+                    expand_deriving_iter_bytes_enum_def)
+}
+
+pub fn expand_deriving_clone(cx: @ext_ctxt,
+                             span: span,
+                             _: @meta_item,
+                             in_items: ~[@item])
+                          -> ~[@item] {
+    expand_deriving(cx,
+                    span,
+                    in_items,
+                    expand_deriving_clone_struct_def,
+                    expand_deriving_clone_enum_def)
+}
+
+fn expand_deriving(cx: @ext_ctxt,
+                   span: span,
+                   in_items: ~[@item],
+                   expand_deriving_struct_def: ExpandDerivingStructDefFn,
+                   expand_deriving_enum_def: ExpandDerivingEnumDefFn)
+                -> ~[@item] {
+    let mut result = ~[];
+    for in_items.each |item| {
+        result.push(copy *item);
+        match item.node {
+            item_struct(struct_def, ref generics) => {
+                result.push(expand_deriving_struct_def(cx,
+                                                       span,
+                                                       struct_def,
+                                                       item.ident,
+                                                       generics));
+            }
+            item_enum(ref enum_definition, ref generics) => {
+                result.push(expand_deriving_enum_def(cx,
+                                                     span,
+                                                     enum_definition,
+                                                     item.ident,
+                                                     generics));
+            }
+            _ => ()
+        }
+    }
+    result
+}
+
+fn create_impl_item(cx: @ext_ctxt, span: span, +item: item_) -> @item {
+    @ast::item {
+        ident: clownshoes_extensions,
+        attrs: ~[],
+        id: cx.next_id(),
+        node: item,
+        vis: public,
+        span: span,
+    }
+}
+
+/// Creates a method from the given expression, the signature of which
+/// conforms to the `eq` or `ne` method.
+fn create_eq_method(cx: @ext_ctxt,
+                    span: span,
+                    method_ident: ident,
+                    type_ident: ident,
+                    generics: &Generics,
+                    body: @expr)
+                 -> @method {
+    // Create the type of the `other` parameter.
+    let arg_path_type = create_self_type_with_params(cx,
+                                                     span,
+                                                     type_ident,
+                                                     generics);
+    let arg_type = ty_rptr(
+        None,
+        ast::mt { ty: arg_path_type, mutbl: m_imm }
+    );
+    let arg_type = @ast::Ty {
+        id: cx.next_id(),
+        node: arg_type,
+        span: span,
+    };
+
+    // Create the `other` parameter.
+    let other_ident = cx.ident_of(~"__other");
+    let arg = build::mk_arg(cx, span, other_ident, arg_type);
+
+    // Create the type of the return value.
+    let bool_ident = cx.ident_of(~"bool");
+    let output_type = build::mk_raw_path(span, ~[ bool_ident ]);
+    let output_type = ty_path(output_type, cx.next_id());
+    let output_type = @ast::Ty {
+        id: cx.next_id(),
+        node: output_type,
+        span: span,
+    };
+
+    // Create the function declaration.
+    let fn_decl = build::mk_fn_decl(~[ arg ], output_type);
+
+    // Create the body block.
+    let body_block = build::mk_simple_block(cx, span, body);
+
+    // Create the method.
+    let self_ty = spanned { node: sty_region(None, m_imm), span: span };
+    @ast::method {
+        ident: method_ident,
+        attrs: ~[],
+        generics: ast_util::empty_generics(),
+        self_ty: self_ty,
+        purity: impure_fn,
+        decl: fn_decl,
+        body: body_block,
+        id: cx.next_id(),
+        span: span,
+        self_id: cx.next_id(),
+        vis: public
+    }
+}
+
+fn create_self_type_with_params(cx: @ext_ctxt,
+                                span: span,
+                                type_ident: ident,
+                                generics: &Generics)
+                             -> @Ty {
+    // Create the type parameters on the `self` path.
+    let mut self_ty_params = ~[];
+    for generics.ty_params.each |ty_param| {
+        let self_ty_param = build::mk_simple_ty_path(cx,
+                                                     span,
+                                                     ty_param.ident);
+        self_ty_params.push(self_ty_param);
+    }
+
+    // Create the type of `self`.
+    let self_type = build::mk_raw_path_(span,
+                                        ~[ type_ident ],
+                                        self_ty_params);
+    let self_type = ty_path(self_type, cx.next_id());
+    @ast::Ty { id: cx.next_id(), node: self_type, span: span }
+}
+
+fn create_derived_impl(cx: @ext_ctxt,
+                       span: span,
+                       type_ident: ident,
+                       generics: &Generics,
+                       methods: &[@method],
+                       trait_path: &[ident])
+                    -> @item {
+    /*!
+     *
+     * Given that we are deriving a trait `Tr` for a type `T<'a, ...,
+     * 'z, A, ..., Z>`, creates an impl like:
+     *
+     *      impl<'a, ..., 'z, A:Tr, ..., Z: Tr> Tr for T<A, ..., Z> { ... }
+     *
+     * FIXME(#5090): Remove code duplication between this and the
+     * code in auto_encode.rs
+     */
+
+    // Copy the lifetimes
+    let impl_lifetimes = generics.lifetimes.map(|l| {
+        build::mk_lifetime(cx, l.span, l.ident)
+    });
+
+    // Create the type parameters.
+    let impl_ty_params = generics.ty_params.map(|ty_param| {
+        let bound = build::mk_ty_path_global(cx,
+                                             span,
+                                             trait_path.map(|x| *x));
+        let bounds = @opt_vec::with(TraitTyParamBound(bound));
+        build::mk_ty_param(cx, ty_param.ident, bounds)
+    });
+
+    // Create the reference to the trait.
+    let trait_path = ast::path {
+        span: span,
+        global: true,
+        idents: trait_path.map(|x| *x),
+        rp: None,
+        types: ~[]
+    };
+    let trait_path = @trait_path;
+    let trait_ref = ast::trait_ref {
+        path: trait_path,
+        ref_id: cx.next_id()
+    };
+    let trait_ref = @trait_ref;
+
+    // Create the type of `self`.
+    let self_type = create_self_type_with_params(cx,
+                                                 span,
+                                                 type_ident,
+                                                 generics);
+
+    // Create the impl item.
+    let impl_item = item_impl(Generics {lifetimes: impl_lifetimes,
+                                        ty_params: impl_ty_params},
+                              Some(trait_ref),
+                              self_type,
+                              methods.map(|x| *x));
+    return create_impl_item(cx, span, impl_item);
+}
+
+fn create_derived_eq_impl(cx: @ext_ctxt,
+                          span: span,
+                          type_ident: ident,
+                          generics: &Generics,
+                          eq_method: @method,
+                          ne_method: @method)
+                       -> @item {
+    let methods = [ eq_method, ne_method ];
+    let trait_path = [
+        cx.ident_of(~"core"),
+        cx.ident_of(~"cmp"),
+        cx.ident_of(~"Eq")
+    ];
+    create_derived_impl(cx, span, type_ident, generics, methods, trait_path)
+}
+
+fn create_derived_iter_bytes_impl(cx: @ext_ctxt,
+                                  span: span,
+                                  type_ident: ident,
+                                  generics: &Generics,
+                                  method: @method)
+                               -> @item {
+    let methods = [ method ];
+    let trait_path = [
+        cx.ident_of(~"core"),
+        cx.ident_of(~"to_bytes"),
+        cx.ident_of(~"IterBytes")
+    ];
+    create_derived_impl(cx, span, type_ident, generics, methods, trait_path)
+}
+
+fn create_derived_clone_impl(cx: @ext_ctxt,
+                             span: span,
+                             type_ident: ident,
+                             generics: &Generics,
+                             method: @method)
+                          -> @item {
+    let methods = [ method ];
+    let trait_path = [
+        cx.ident_of(~"core"),
+        cx.ident_of(~"clone"),
+        cx.ident_of(~"Clone"),
+    ];
+    create_derived_impl(cx, span, type_ident, generics, methods, trait_path)
+}
+
+// Creates a method from the given set of statements conforming to the
+// signature of the `iter_bytes` method.
+fn create_iter_bytes_method(cx: @ext_ctxt,
+                            span: span,
+                            +statements: ~[@stmt])
+                         -> @method {
+    // Create the `lsb0` parameter.
+    let bool_ident = cx.ident_of(~"bool");
+    let lsb0_arg_type = build::mk_simple_ty_path(cx, span, bool_ident);
+    let lsb0_ident = cx.ident_of(~"__lsb0");
+    let lsb0_arg = build::mk_arg(cx, span, lsb0_ident, lsb0_arg_type);
+
+    // Create the `f` parameter.
+    let core_ident = cx.ident_of(~"core");
+    let to_bytes_ident = cx.ident_of(~"to_bytes");
+    let cb_ident = cx.ident_of(~"Cb");
+    let core_to_bytes_cb_ident = ~[ core_ident, to_bytes_ident, cb_ident ];
+    let f_arg_type = build::mk_ty_path(cx, span, core_to_bytes_cb_ident);
+    let f_ident = cx.ident_of(~"__f");
+    let f_arg = build::mk_arg(cx, span, f_ident, f_arg_type);
+
+    // Create the type of the return value.
+    let output_type = @ast::Ty { id: cx.next_id(), node: ty_nil, span: span };
+
+    // Create the function declaration.
+    let inputs = ~[ lsb0_arg, f_arg ];
+    let fn_decl = build::mk_fn_decl(inputs, output_type);
+
+    // Create the body block.
+    let body_block = build::mk_block_(cx, span, statements);
+
+    // Create the method.
+    let self_ty = spanned { node: sty_region(None, m_imm), span: span };
+    let method_ident = cx.ident_of(~"iter_bytes");
+    @ast::method {
+        ident: method_ident,
+        attrs: ~[],
+        generics: ast_util::empty_generics(),
+        self_ty: self_ty,
+        purity: impure_fn,
+        decl: fn_decl,
+        body: body_block,
+        id: cx.next_id(),
+        span: span,
+        self_id: cx.next_id(),
+        vis: public
+    }
+}
+
+// Creates a method from the given expression conforming to the signature of
+// the `clone` method.
+fn create_clone_method(cx: @ext_ctxt,
+                       span: span,
+                       +type_ident: ast::ident,
+                       generics: &Generics,
+                       expr: @ast::expr)
+                    -> @method {
+    // Create the type parameters of the return value.
+    let mut output_ty_params = ~[];
+    for generics.ty_params.each |ty_param| {
+        let path = build::mk_ty_path(cx, span, ~[ ty_param.ident ]);
+        output_ty_params.push(path);
+    }
+
+    // Create the type of the return value.
+    let output_type_path = build::mk_raw_path_(span,
+                                               ~[ type_ident ],
+                                               output_ty_params);
+    let output_type = ast::ty_path(output_type_path, cx.next_id());
+    let output_type = @ast::Ty {
+        id: cx.next_id(),
+        node: output_type,
+        span: span
+    };
+
+    // Create the function declaration.
+    let fn_decl = build::mk_fn_decl(~[], output_type);
+
+    // Create the body block.
+    let body_block = build::mk_simple_block(cx, span, expr);
+
+    // Create the self type and method identifier.
+    let self_ty = spanned { node: sty_region(None, m_imm), span: span };
+    let method_ident = cx.ident_of(~"clone");
+
+    // Create the method.
+    @ast::method {
+        ident: method_ident,
+        attrs: ~[],
+        generics: ast_util::empty_generics(),
+        self_ty: self_ty,
+        purity: impure_fn,
+        decl: fn_decl,
+        body: body_block,
+        id: cx.next_id(),
+        span: span,
+        self_id: cx.next_id(),
+        vis: public,
+    }
+}
+
+fn create_subpatterns(cx: @ext_ctxt,
+                      span: span,
+                      prefix: ~str,
+                      n: uint)
+                   -> ~[@pat] {
+    let mut subpats = ~[];
+    for uint::range(0, n) |_i| {
+        // Create the subidentifier.
+        let index = subpats.len().to_str();
+        let ident = cx.ident_of(prefix + index);
+
+        // Create the subpattern.
+        let subpath = build::mk_raw_path(span, ~[ ident ]);
+        let subpat = pat_ident(bind_by_ref(m_imm), subpath, None);
+        let subpat = build::mk_pat(cx, span, subpat);
+        subpats.push(subpat);
+    }
+    return subpats;
+}
+
+fn is_struct_tuple(struct_def: &struct_def) -> bool {
+    struct_def.fields.len() > 0 && struct_def.fields.all(|f| {
+        match f.node.kind {
+            named_field(*) => false,
+            unnamed_field => true
+        }
+    })
+}
+
+fn create_enum_variant_pattern(cx: @ext_ctxt,
+                               span: span,
+                               variant: &variant,
+                               prefix: ~str)
+                            -> @pat {
+    let variant_ident = variant.node.name;
+    match variant.node.kind {
+        tuple_variant_kind(ref variant_args) => {
+            if variant_args.len() == 0 {
+                return build::mk_pat_ident_with_binding_mode(
+                    cx, span, variant_ident, ast::bind_infer);
+            }
+
+            let matching_path = build::mk_raw_path(span, ~[ variant_ident ]);
+            let subpats = create_subpatterns(cx,
+                                             span,
+                                             prefix,
+                                             variant_args.len());
+
+            return build::mk_pat_enum(cx, span, matching_path, subpats);
+        }
+        struct_variant_kind(struct_def) => {
+            let matching_path = build::mk_raw_path(span, ~[ variant_ident ]);
+            let subpats = create_subpatterns(cx,
+                                             span,
+                                             prefix,
+                                             struct_def.fields.len());
+
+            let field_pats = do struct_def.fields.mapi |i, struct_field| {
+                let ident = match struct_field.node.kind {
+                    named_field(ident, _, _) => ident,
+                    unnamed_field => {
+                        cx.span_bug(span, ~"unexpected unnamed field");
+                    }
+                };
+                ast::field_pat { ident: ident, pat: subpats[i] }
+            };
+
+            build::mk_pat_struct(cx, span, matching_path, field_pats)
+        }
+        enum_variant_kind(*) => {
+            cx.span_unimpl(span, ~"enum variants for `deriving`");
+        }
+    }
+}
+
+fn call_substructure_eq_method(cx: @ext_ctxt,
+                               span: span,
+                               self_field: @expr,
+                               other_field_ref: @expr,
+                               method_ident: ident,
+                               junction: Junction,
+                               chain_expr: &mut Option<@expr>) {
+    // Call the substructure method.
+    let self_method = build::mk_access_(cx, span, self_field, method_ident);
+    let self_call = build::mk_call_(cx,
+                                    span,
+                                    self_method,
+                                    ~[ other_field_ref ]);
+
+    // Connect to the outer expression if necessary.
+    *chain_expr = match *chain_expr {
+        None => Some(self_call),
+        Some(copy old_outer_expr) => {
+            let binop = junction.to_binop();
+            let chain_expr = build::mk_binary(cx,
+                                              span,
+                                              binop,
+                                              old_outer_expr,
+                                              self_call);
+            Some(chain_expr)
+        }
+    };
+}
+
+fn finish_eq_chain_expr(cx: @ext_ctxt,
+                        span: span,
+                        chain_expr: Option<@expr>,
+                        junction: Junction)
+                     -> @expr {
+    match chain_expr {
+        None => {
+            match junction {
+                Conjunction => build::mk_bool(cx, span, true),
+                Disjunction => build::mk_bool(cx, span, false),
+            }
+        }
+        Some(ref outer_expr) => *outer_expr,
+    }
+}
+
+fn call_substructure_iter_bytes_method(cx: @ext_ctxt,
+                                       span: span,
+                                       self_field: @expr)
+                                    -> @stmt {
+    // Gather up the parameters we want to chain along.
+    let lsb0_ident = cx.ident_of(~"__lsb0");
+    let f_ident = cx.ident_of(~"__f");
+    let lsb0_expr = build::mk_path(cx, span, ~[ lsb0_ident ]);
+    let f_expr = build::mk_path(cx, span, ~[ f_ident ]);
+
+    // Call the substructure method.
+    let iter_bytes_ident = cx.ident_of(~"iter_bytes");
+    let self_method = build::mk_access_(cx,
+                                        span,
+                                        self_field,
+                                        iter_bytes_ident);
+    let self_call = build::mk_call_(cx,
+                                    span,
+                                    self_method,
+                                    ~[ lsb0_expr, f_expr ]);
+
+    // Create a statement out of this expression.
+    build::mk_stmt(cx, span, self_call)
+}
+
+fn call_substructure_clone_method(cx: @ext_ctxt,
+                                  span: span,
+                                  self_field: @expr)
+                               -> @expr {
+    // Call the substructure method.
+    let clone_ident = cx.ident_of(~"clone");
+    let self_method = build::mk_access_(cx, span, self_field, clone_ident);
+    build::mk_call_(cx, span, self_method, ~[])
+}
+
+fn variant_arg_count(cx: @ext_ctxt, span: span, variant: &variant) -> uint {
+    match variant.node.kind {
+        tuple_variant_kind(ref args) => args.len(),
+        struct_variant_kind(ref struct_def) => struct_def.fields.len(),
+        enum_variant_kind(*) => {
+            cx.span_bug(span, ~"variant_arg_count: enum variants deprecated")
+        }
+    }
+}
+
+fn expand_deriving_eq_struct_def(cx: @ext_ctxt,
+                                 span: span,
+                                 struct_def: &struct_def,
+                                 type_ident: ident,
+                                 generics: &Generics)
+                              -> @item {
+    // Create the methods.
+    let eq_ident = cx.ident_of(~"eq");
+    let ne_ident = cx.ident_of(~"ne");
+
+    let derive_struct_fn = if is_struct_tuple(struct_def) {
+        expand_deriving_eq_struct_tuple_method
+    } else {
+        expand_deriving_eq_struct_method
+    };
+
+    let eq_method = derive_struct_fn(cx,
+                                     span,
+                                     struct_def,
+                                     eq_ident,
+                                     type_ident,
+                                     generics,
+                                     Conjunction);
+    let ne_method = derive_struct_fn(cx,
+                                     span,
+                                     struct_def,
+                                     ne_ident,
+                                     type_ident,
+                                     generics,
+                                     Disjunction);
+
+    // Create the implementation.
+    return create_derived_eq_impl(cx,
+                                  span,
+                                  type_ident,
+                                  generics,
+                                  eq_method,
+                                  ne_method);
+}
+
+fn expand_deriving_eq_enum_def(cx: @ext_ctxt,
+                               span: span,
+                               enum_definition: &enum_def,
+                               type_ident: ident,
+                               generics: &Generics)
+                            -> @item {
+    // Create the methods.
+    let eq_ident = cx.ident_of(~"eq");
+    let ne_ident = cx.ident_of(~"ne");
+    let eq_method = expand_deriving_eq_enum_method(cx,
+                                                   span,
+                                                   enum_definition,
+                                                   eq_ident,
+                                                   type_ident,
+                                                   generics,
+                                                   Conjunction);
+    let ne_method = expand_deriving_eq_enum_method(cx,
+                                                   span,
+                                                   enum_definition,
+                                                   ne_ident,
+                                                   type_ident,
+                                                   generics,
+                                                   Disjunction);
+
+    // Create the implementation.
+    return create_derived_eq_impl(cx,
+                                  span,
+                                  type_ident,
+                                  generics,
+                                  eq_method,
+                                  ne_method);
+}
+
+fn expand_deriving_iter_bytes_struct_def(cx: @ext_ctxt,
+                                         span: span,
+                                         struct_def: &struct_def,
+                                         type_ident: ident,
+                                         generics: &Generics)
+                                      -> @item {
+    // Create the method.
+    let method = expand_deriving_iter_bytes_struct_method(cx,
+                                                          span,
+                                                          struct_def);
+
+    // Create the implementation.
+    return create_derived_iter_bytes_impl(cx,
+                                          span,
+                                          type_ident,
+                                          generics,
+                                          method);
+}
+
+fn expand_deriving_iter_bytes_enum_def(cx: @ext_ctxt,
+                                       span: span,
+                                       enum_definition: &enum_def,
+                                       type_ident: ident,
+                                       generics: &Generics)
+                                    -> @item {
+    // Create the method.
+    let method = expand_deriving_iter_bytes_enum_method(cx,
+                                                        span,
+                                                        enum_definition);
+
+    // Create the implementation.
+    return create_derived_iter_bytes_impl(cx,
+                                          span,
+                                          type_ident,
+                                          generics,
+                                          method);
+}
+
+fn expand_deriving_clone_struct_def(cx: @ext_ctxt,
+                                    span: span,
+                                    struct_def: &struct_def,
+                                    type_ident: ident,
+                                    generics: &Generics)
+                                 -> @item {
+    // Create the method.
+    let method = if !is_struct_tuple(struct_def) {
+        expand_deriving_clone_struct_method(cx,
+                                            span,
+                                            struct_def,
+                                            type_ident,
+                                            generics)
+    } else {
+        expand_deriving_clone_tuple_struct_method(cx,
+                                                  span,
+                                                  struct_def,
+                                                  type_ident,
+                                                  generics)
+    };
+
+    // Create the implementation.
+    create_derived_clone_impl(cx, span, type_ident, generics, method)
+}
+
+fn expand_deriving_clone_enum_def(cx: @ext_ctxt,
+                                  span: span,
+                                  enum_definition: &enum_def,
+                                  type_ident: ident,
+                                  generics: &Generics)
+                               -> @item {
+    // Create the method.
+    let method = expand_deriving_clone_enum_method(cx,
+                                                   span,
+                                                   enum_definition,
+                                                   type_ident,
+                                                   generics);
+
+    // Create the implementation.
+    create_derived_clone_impl(cx, span, type_ident, generics, method)
+}
+
+fn expand_deriving_eq_struct_method(cx: @ext_ctxt,
+                                    span: span,
+                                    struct_def: &struct_def,
+                                    method_ident: ident,
+                                    type_ident: ident,
+                                    generics: &Generics,
+                                    junction: Junction)
+                                 -> @method {
+    let self_ident = cx.ident_of(~"self");
+    let other_ident = cx.ident_of(~"__other");
+
+    // Create the body of the method.
+    let mut outer_expr = None;
+    for struct_def.fields.each |struct_field| {
+        match struct_field.node.kind {
+            named_field(ident, _, _) => {
+                // Create the accessor for the other field.
+                let other_field = build::mk_access(cx,
+                                                   span,
+                                                   ~[ other_ident ],
+                                                   ident);
+                let other_field_ref = build::mk_addr_of(cx,
+                                                        span,
+                                                        other_field);
+
+                // Create the accessor for this field.
+                let self_field = build::mk_access(cx,
+                                                  span,
+                                                  ~[ self_ident ],
+                                                  ident);
+
+                // Call the substructure method.
+                call_substructure_eq_method(cx,
+                                            span,
+                                            self_field,
+                                            other_field_ref,
+                                            method_ident,
+                                            junction,
+                                            &mut outer_expr);
+            }
+            unnamed_field => {
+                cx.span_unimpl(span, ~"unnamed fields with `deriving_eq`");
+            }
+        }
+    }
+
+    // Create the method itself.
+    let body = finish_eq_chain_expr(cx, span, outer_expr, junction);
+    return create_eq_method(cx,
+                            span,
+                            method_ident,
+                            type_ident,
+                            generics,
+                            body);
+}
+
+fn expand_deriving_iter_bytes_struct_method(cx: @ext_ctxt,
+                                            span: span,
+                                            struct_def: &struct_def)
+                                         -> @method {
+    let self_ident = cx.ident_of(~"self");
+
+    // Create the body of the method.
+    let mut statements = ~[];
+    for struct_def.fields.each |struct_field| {
+        match struct_field.node.kind {
+            named_field(ident, _, _) => {
+                // Create the accessor for this field.
+                let self_field = build::mk_access(cx,
+                                                  span,
+                                                  ~[ self_ident ],
+                                                  ident);
+
+                // Call the substructure method.
+                let stmt = call_substructure_iter_bytes_method(cx,
+                                                               span,
+                                                               self_field);
+                statements.push(stmt);
+            }
+            unnamed_field => {
+                cx.span_unimpl(span,
+                               ~"unnamed fields with `deriving_iter_bytes`");
+            }
+        }
+    }
+
+    // Create the method itself.
+    return create_iter_bytes_method(cx, span, statements);
+}
+
+fn expand_deriving_clone_struct_method(cx: @ext_ctxt,
+                                       span: span,
+                                       struct_def: &struct_def,
+                                       type_ident: ident,
+                                       generics: &Generics)
+                                    -> @method {
+    let self_ident = cx.ident_of(~"self");
+
+    // Create the new fields.
+    let mut fields = ~[];
+    for struct_def.fields.each |struct_field| {
+        match struct_field.node.kind {
+            named_field(ident, _, _) => {
+                // Create the accessor for this field.
+                let self_field = build::mk_access(cx,
+                                                  span,
+                                                  ~[ self_ident ],
+                                                  ident);
+
+                // Call the substructure method.
+                let call = call_substructure_clone_method(cx,
+                                                          span,
+                                                          self_field);
+
+                let field = build::Field { ident: ident, ex: call };
+                fields.push(field);
+            }
+            unnamed_field => {
+                cx.span_bug(span,
+                            ~"unnamed fields in \
+                              expand_deriving_clone_struct_method");
+            }
+        }
+    }
+
+    // Create the struct literal.
+    let struct_literal = build::mk_struct_e(cx,
+                                            span,
+                                            ~[ type_ident ],
+                                            fields);
+    create_clone_method(cx, span, type_ident, generics, struct_literal)
+}
+
+fn expand_deriving_clone_tuple_struct_method(cx: @ext_ctxt,
+                                             span: span,
+                                             struct_def: &struct_def,
+                                             type_ident: ident,
+                                             generics: &Generics)
+                                          -> @method {
+    // Create the pattern for the match.
+    let matching_path = build::mk_raw_path(span, ~[ type_ident ]);
+    let field_count = struct_def.fields.len();
+    let subpats = create_subpatterns(cx, span, ~"__self", field_count);
+    let pat = build::mk_pat_enum(cx, span, matching_path, subpats);
+
+    // Create the new fields.
+    let mut subcalls = ~[];
+    for uint::range(0, struct_def.fields.len()) |i| {
+        // Create the expression for this field.
+        let field_ident = cx.ident_of(~"__self" + i.to_str());
+        let field = build::mk_path(cx, span, ~[ field_ident ]);
+
+        // Call the substructure method.
+        let subcall = call_substructure_clone_method(cx, span, field);
+        subcalls.push(subcall);
+    }
+
+    // Create the call to the struct constructor.
+    let call = build::mk_call(cx, span, ~[ type_ident ], subcalls);
+
+    // Create the pattern body.
+    let match_body_block = build::mk_simple_block(cx, span, call);
+
+    // Create the arm.
+    let arm = ast::arm {
+        pats: ~[ pat ],
+        guard: None,
+        body: match_body_block
+    };
+
+    // Create the method body.
+    let self_match_expr = expand_enum_or_struct_match(cx, span, ~[ arm ]);
+
+    // Create the method.
+    create_clone_method(cx, span, type_ident, generics, self_match_expr)
+}
+
+fn expand_deriving_eq_enum_method(cx: @ext_ctxt,
+                                  span: span,
+                                  enum_definition: &enum_def,
+                                  method_ident: ident,
+                                  type_ident: ident,
+                                  generics: &Generics,
+                                  junction: Junction)
+                               -> @method {
+    let self_ident = cx.ident_of(~"self");
+    let other_ident = cx.ident_of(~"__other");
+
+    let is_eq;
+    match junction {
+        Conjunction => is_eq = true,
+        Disjunction => is_eq = false,
+    }
+
+    // Create the arms of the self match in the method body.
+    let mut self_arms = ~[];
+    for enum_definition.variants.each |self_variant| {
+        let mut other_arms = ~[];
+
+        // Create the matching pattern.
+        let matching_pat = create_enum_variant_pattern(cx,
+                                                       span,
+                                                       self_variant,
+                                                       ~"__other");
+
+        // Create the matching pattern body.
+        let mut matching_body_expr = None;
+        for uint::range(0, variant_arg_count(cx, span, self_variant)) |i| {
+            // Create the expression for the other field.
+            let other_field_ident = cx.ident_of(~"__other" + i.to_str());
+            let other_field = build::mk_path(cx,
+                                             span,
+                                             ~[ other_field_ident ]);
+
+            // Create the expression for this field.
+            let self_field_ident = cx.ident_of(~"__self" + i.to_str());
+            let self_field = build::mk_path(cx, span, ~[ self_field_ident ]);
+
+            // Call the substructure method.
+            call_substructure_eq_method(cx,
+                                        span,
+                                        self_field,
+                                        other_field,
+                                        method_ident,
+                                        junction,
+                                        &mut matching_body_expr);
+        }
+
+        let matching_body_expr = finish_eq_chain_expr(cx,
+                                                      span,
+                                                      matching_body_expr,
+                                                      junction);
+        let matching_body_block = build::mk_simple_block(cx,
+                                                         span,
+                                                         matching_body_expr);
+
+        // Create the matching arm.
+        let matching_arm = ast::arm {
+            pats: ~[ matching_pat ],
+            guard: None,
+            body: matching_body_block
+        };
+        other_arms.push(matching_arm);
+
+        // Maybe generate a non-matching case. If there is only one
+        // variant then there will always be a match.
+        if enum_definition.variants.len() > 1 {
+            // Create the nonmatching pattern.
+            let nonmatching_pat = @ast::pat {
+                id: cx.next_id(),
+                node: pat_wild,
+                span: span
+            };
+
+            // Create the nonmatching pattern body.
+            let nonmatching_expr = build::mk_bool(cx, span, !is_eq);
+            let nonmatching_body_block =
+                build::mk_simple_block(cx,
+                                       span,
+                                       nonmatching_expr);
+
+            // Create the nonmatching arm.
+            let nonmatching_arm = ast::arm {
+                pats: ~[ nonmatching_pat ],
+                guard: None,
+                body: nonmatching_body_block,
+            };
+            other_arms.push(nonmatching_arm);
+        }
+
+        // Create the self pattern.
+        let self_pat = create_enum_variant_pattern(cx,
+                                                   span,
+                                                   self_variant,
+                                                   ~"__self");
+
+        // Create the self pattern body.
+        let other_expr = build::mk_path(cx, span, ~[ other_ident ]);
+        let other_expr = build::mk_unary(cx, span, deref, other_expr);
+        let other_match_expr = expr_match(other_expr, other_arms);
+        let other_match_expr = build::mk_expr(cx,
+                                              span,
+                                              other_match_expr);
+        let other_match_body_block = build::mk_simple_block(cx,
+                                                            span,
+                                                            other_match_expr);
+
+        // Create the self arm.
+        let self_arm = ast::arm {
+            pats: ~[ self_pat ],
+            guard: None,
+            body: other_match_body_block,
+        };
+        self_arms.push(self_arm);
+    }
+
+    // Create the method body.
+    let self_expr = build::mk_path(cx, span, ~[ self_ident ]);
+    let self_expr = build::mk_unary(cx, span, deref, self_expr);
+    let self_match_expr = expr_match(self_expr, self_arms);
+    let self_match_expr = build::mk_expr(cx, span, self_match_expr);
+
+    // Create the method.
+    return create_eq_method(cx,
+                            span,
+                            method_ident,
+                            type_ident,
+                            generics,
+                            self_match_expr);
+}
+
+fn expand_deriving_eq_struct_tuple_method(cx: @ext_ctxt,
+                                          span: span,
+                                          struct_def: &struct_def,
+                                          method_ident: ident,
+                                          type_ident: ident,
+                                          generics: &Generics,
+                                          junction: Junction)
+                                        -> @method {
+    let self_str = ~"self";
+    let other_str = ~"__other";
+    let type_path = build::mk_raw_path(span, ~[type_ident]);
+    let fields = copy struct_def.fields;
+
+    // Create comparison expression, comparing each of the fields
+    let mut match_body = None;
+    for fields.eachi |i, _| {
+        let other_field_ident = cx.ident_of(other_str + i.to_str());
+        let other_field = build::mk_path(cx, span, ~[ other_field_ident ]);
+
+        let self_field_ident = cx.ident_of(self_str + i.to_str());
+        let self_field = build::mk_path(cx, span, ~[ self_field_ident ]);
+
+        call_substructure_eq_method(cx, span, self_field, other_field,
+            method_ident, junction, &mut match_body);
+    }
+    let match_body = finish_eq_chain_expr(cx, span, match_body, junction);
+
+    // Create arm for the '__other' match, containing the comparison expr
+    let other_subpats = create_subpatterns(cx, span, other_str, fields.len());
+    let other_arm = ast::arm {
+        pats: ~[ build::mk_pat_enum(cx, span, type_path, other_subpats) ],
+        guard: None,
+        body: build::mk_simple_block(cx, span, match_body),
+    };
+
+    // Create the match on '__other'
+    let other_expr = build::mk_path(cx, span, ~[ cx.ident_of(other_str) ]);
+    let other_expr = build::mk_unary(cx, span, deref, other_expr);
+    let other_match_expr = expr_match(other_expr, ~[other_arm]);
+    let other_match_expr = build::mk_expr(cx, span, other_match_expr);
+
+    // Create arm for the 'self' match, which contains the '__other' match
+    let self_subpats = create_subpatterns(cx, span, self_str, fields.len());
+    let self_arm = ast::arm {
+        pats: ~[build::mk_pat_enum(cx, span, type_path, self_subpats)],
+        guard: None,
+        body: build::mk_simple_block(cx, span, other_match_expr),
+    };
+
+    // Create the match on 'self'
+    let self_expr = build::mk_path(cx, span, ~[ cx.ident_of(self_str) ]);
+    let self_expr = build::mk_unary(cx, span, deref, self_expr);
+    let self_match_expr = expr_match(self_expr, ~[self_arm]);
+    let self_match_expr = build::mk_expr(cx, span, self_match_expr);
+
+    create_eq_method(cx, span, method_ident,
+        type_ident, generics, self_match_expr)
+}
+
+fn expand_enum_or_struct_match(cx: @ext_ctxt,
+                               span: span,
+                               arms: ~[ ast::arm ])
+                            -> @expr {
+    let self_ident = cx.ident_of(~"self");
+    let self_expr = build::mk_path(cx, span, ~[ self_ident ]);
+    let self_expr = build::mk_unary(cx, span, deref, self_expr);
+    let self_match_expr = expr_match(self_expr, arms);
+    build::mk_expr(cx, span, self_match_expr)
+}
+
+fn expand_deriving_iter_bytes_enum_method(cx: @ext_ctxt,
+                                          span: span,
+                                          enum_definition: &enum_def)
+                                       -> @method {
+    // Create the arms of the match in the method body.
+    let arms = do enum_definition.variants.mapi |i, variant| {
+        // Create the matching pattern.
+        let pat = create_enum_variant_pattern(cx, span, variant, ~"__self");
+
+        // Determine the discriminant. We will feed this value to the byte
+        // iteration function.
+        let discriminant;
+        match variant.node.disr_expr {
+            Some(copy disr_expr) => discriminant = disr_expr,
+            None => discriminant = build::mk_uint(cx, span, i),
+        }
+
+        // Feed the discriminant to the byte iteration function.
+        let mut stmts = ~[];
+        let discrim_stmt = call_substructure_iter_bytes_method(cx,
+                                                               span,
+                                                               discriminant);
+        stmts.push(discrim_stmt);
+
+        // Feed each argument in this variant to the byte iteration function
+        // as well.
+        for uint::range(0, variant_arg_count(cx, span, variant)) |j| {
+            // Create the expression for this field.
+            let field_ident = cx.ident_of(~"__self" + j.to_str());
+            let field = build::mk_path(cx, span, ~[ field_ident ]);
+
+            // Call the substructure method.
+            let stmt = call_substructure_iter_bytes_method(cx, span, field);
+            stmts.push(stmt);
+        }
+
+        // Create the pattern body.
+        let match_body_block = build::mk_block_(cx, span, stmts);
+
+        // Create the arm.
+        ast::arm {
+            pats: ~[ pat ],
+            guard: None,
+            body: match_body_block,
+        }
+    };
+
+    // Create the method body.
+    let self_match_expr = expand_enum_or_struct_match(cx, span, arms);
+    let self_match_stmt = build::mk_stmt(cx, span, self_match_expr);
+
+    // Create the method.
+    create_iter_bytes_method(cx, span, ~[ self_match_stmt ])
+}
+
+fn expand_deriving_clone_enum_method(cx: @ext_ctxt,
+                                     span: span,
+                                     enum_definition: &enum_def,
+                                     type_ident: ident,
+                                     generics: &Generics)
+                                  -> @method {
+    // Create the arms of the match in the method body.
+    let arms = do enum_definition.variants.map |variant| {
+        // Create the matching pattern.
+        let pat = create_enum_variant_pattern(cx, span, variant, ~"__self");
+
+        // Iterate over the variant arguments, creating the subcalls.
+        let mut subcalls = ~[];
+        for uint::range(0, variant_arg_count(cx, span, variant)) |j| {
+            // Create the expression for this field.
+            let field_ident = cx.ident_of(~"__self" + j.to_str());
+            let field = build::mk_path(cx, span, ~[ field_ident ]);
+
+            // Call the substructure method.
+            let subcall = call_substructure_clone_method(cx, span, field);
+            subcalls.push(subcall);
+        }
+
+        // Create the call to the enum variant (if necessary).
+        let call = if subcalls.len() > 0 {
+            build::mk_call(cx, span, ~[ variant.node.name ], subcalls)
+        } else {
+            build::mk_path(cx, span, ~[ variant.node.name ])
+        };
+
+        // Create the pattern body.
+        let match_body_block = build::mk_simple_block(cx, span, call);
+
+        // Create the arm.
+        ast::arm { pats: ~[ pat ], guard: None, body: match_body_block }
+    };
+
+    // Create the method body.
+    let self_match_expr = expand_enum_or_struct_match(cx, span, arms);
+
+    // Create the method.
+    create_clone_method(cx, span, type_ident, generics, self_match_expr)
+}
+
index 912846d9f0f8b762a62eaf8d47fedca7163ad41f..01ed707b0aef6b346568b7ba1501d7cb52c5c63e 100644 (file)
@@ -64,6 +64,8 @@ pub mod ext {
     pub mod expand;
 
     pub mod quote;
+
+    #[path = "deriving/mod.rs"]
     pub mod deriving;
 
     pub mod build;