about summary refs log tree commit diff
path: root/src/libsyntax
diff options
context:
space:
mode:
authorPatrick Walton <pcwalton@mimiga.net>2012-11-20 18:27:13 -0800
committerPatrick Walton <pcwalton@mimiga.net>2012-11-21 10:27:34 -0800
commit57588edf3bc2450fd1daff4ec2565fe5edbedcef (patch)
treed9b8fede85d1d85f31731d1c83131ed4400362d1 /src/libsyntax
parentb053f0b5e68233f664d087f06fc5ebaec2f19f97 (diff)
downloadrust-57588edf3bc2450fd1daff4ec2565fe5edbedcef.tar.gz
rust-57588edf3bc2450fd1daff4ec2565fe5edbedcef.zip
libsyntax: Implement deriving via a syntax extension for the `IterBytes` trait. r=brson
Diffstat (limited to 'src/libsyntax')
-rw-r--r--src/libsyntax/ext/base.rs3
-rw-r--r--src/libsyntax/ext/build.rs47
-rw-r--r--src/libsyntax/ext/deriving.rs489
3 files changed, 416 insertions, 123 deletions
diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs
index ba5d34bfdb4..480cbfe0060 100644
--- a/src/libsyntax/ext/base.rs
+++ b/src/libsyntax/ext/base.rs
@@ -100,6 +100,9 @@ fn syntax_expander_table() -> HashMap<~str, syntax_extension> {
     syntax_expanders.insert(~"deriving_eq",
                             item_decorator(
                                 ext::deriving::expand_deriving_eq));
+    syntax_expanders.insert(~"deriving_iter_bytes",
+                            item_decorator(
+                                ext::deriving::expand_deriving_iter_bytes));
 
     // Quasi-quoting expanders
     syntax_expanders.insert(~"quote_tokens",
diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs
index f08bc3cc7bd..6656007b50e 100644
--- a/src/libsyntax/ext/build.rs
+++ b/src/libsyntax/ext/build.rs
@@ -141,6 +141,18 @@ fn mk_block(cx: ext_ctxt, sp: span,
                span: sp };
     mk_expr(cx, sp, ast::expr_block(blk))
 }
+fn mk_block_(cx: ext_ctxt, sp: span, +stmts: ~[@ast::stmt]) -> ast::blk {
+    {
+        node: {
+            view_items: ~[],
+            stmts: move stmts,
+            expr: None,
+            id: cx.next_id(),
+            rules: ast::default_blk
+        },
+        span: sp
+    }
+}
 fn mk_simple_block(cx: ext_ctxt, span: span, expr: @ast::expr) -> ast::blk {
     let block = {
         view_items: ~[],
@@ -177,4 +189,39 @@ fn mk_bool(cx: ext_ctxt, span: span, value: bool) -> @ast::expr {
     let lit_expr = ast::expr_lit(@{ node: ast::lit_bool(value), span: span });
     build::mk_expr(cx, span, move lit_expr)
 }
+fn mk_stmt(cx: ext_ctxt, span: span, expr: @ast::expr) -> @ast::stmt {
+    let stmt_ = ast::stmt_semi(expr, cx.next_id());
+    @{ node: move stmt_, span: span }
+}
+fn mk_ty_path(cx: ext_ctxt,
+              span: span,
+              idents: ~[ ast::ident ])
+           -> @ast::Ty {
+    let ty = build::mk_raw_path(span, idents);
+    let ty = ast::ty_path(ty, cx.next_id());
+    let ty = @{ id: cx.next_id(), node: move ty, span: span };
+    ty
+}
+fn mk_simple_ty_path(cx: ext_ctxt,
+                     span: span,
+                     ident: ast::ident)
+                  -> @ast::Ty {
+    mk_ty_path(cx, span, ~[ ident ])
+}
+fn mk_arg(cx: ext_ctxt,
+          span: span,
+          ident: ast::ident,
+          ty: @ast::Ty)
+       -> ast::arg {
+    let arg_pat = mk_pat_ident(cx, span, ident);
+    {
+        mode: ast::infer(cx.next_id()),
+        ty: ty,
+        pat: arg_pat,
+        id: cx.next_id()
+    }
+}
+fn mk_fn_decl(+inputs: ~[ast::arg], output: @ast::Ty) -> ast::fn_decl {
+    { inputs: move inputs, output: output, cf: ast::return_val }
+}
 
diff --git a/src/libsyntax/ext/deriving.rs b/src/libsyntax/ext/deriving.rs
index 8e5c8253716..cf8aa764eea 100644
--- a/src/libsyntax/ext/deriving.rs
+++ b/src/libsyntax/ext/deriving.rs
@@ -1,5 +1,5 @@
 /// The compiler code necessary to implement the #[deriving_eq] and
-/// #[deriving_ord] extensions.
+/// #[deriving_iter_bytes] extensions.
 
 use ast::{and, bind_by_ref, binop, blk, default_blk, deref, enum_def};
 use ast::{enum_variant_kind, expr};
@@ -7,9 +7,9 @@ use ast::{expr_, expr_addr_of, expr_binary, expr_call, expr_field, expr_lit};
 use ast::{expr_match, expr_path, expr_unary, ident, infer, item, item_};
 use ast::{item_class, item_enum, item_impl, lit_bool, m_imm, meta_item};
 use ast::{method, named_field, or, pat, pat_ident, pat_wild, path, public};
-use ast::{pure_fn, re_anon, return_val, struct_def, struct_variant_kind};
-use ast::{sty_region, tuple_variant_kind, ty_path};
-use ast::{ty_rptr, unnamed_field, variant};
+use ast::{pure_fn, re_anon, return_val, stmt, struct_def};
+use ast::{struct_variant_kind, sty_by_ref, sty_region, tuple_variant_kind};
+use ast::{ty_nil, ty_path, ty_rptr, unnamed_field, variant};
 use base::ext_ctxt;
 use codemap::span;
 use parse::token::special_idents::clownshoes_extensions;
@@ -28,11 +28,47 @@ impl Junction {
     }
 }
 
+type ExpandDerivingStructDefFn = &fn(ext_ctxt,
+                                     span,
+                                     x: &struct_def,
+                                     ident)
+                                  -> @item;
+type ExpandDerivingEnumDefFn   = &fn(ext_ctxt,
+                                     span,
+                                     x: &enum_def,
+                                     ident)
+                                  -> @item;
+
 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)
+}
+
+fn expand_deriving(cx: ext_ctxt,
+                   span: span,
+                   in_items: ~[@item],
+                   expand_deriving_struct_def: ExpandDerivingStructDefFn,
+                   expand_deriving_enum_def: ExpandDerivingEnumDefFn)
+                -> ~[@item] {
     let result = dvec::DVec();
     for in_items.each |item| {
         result.push(copy *item);
@@ -68,33 +104,21 @@ fn create_impl_item(cx: ext_ctxt, span: span, +item: item_) -> @item {
 
 /// Creates a method from the given expression, the signature of which
 /// conforms to the `eq` or `ne` method.
-fn create_method(cx: ext_ctxt,
-                 span: span,
-                 method_ident: ident,
-                 type_ident: ident,
-                 body: @expr)
-              -> @method {
+fn create_eq_method(cx: ext_ctxt,
+                    span: span,
+                    method_ident: ident,
+                    type_ident: ident,
+                    body: @expr)
+                 -> @method {
     // Create the type of the `other` parameter.
-    let arg_path_type = build::mk_raw_path(span, ~[ type_ident ]);
-    let arg_path_type = ty_path(arg_path_type, cx.next_id());
-    let arg_path_type = @{
-        id: cx.next_id(),
-        node: move arg_path_type,
-        span: span
-    };
+    let arg_path_type = build::mk_simple_ty_path(cx, span, type_ident);
     let arg_region = @{ id: cx.next_id(), node: re_anon };
     let arg_type = ty_rptr(arg_region, { ty: arg_path_type, mutbl: m_imm });
     let arg_type = @{ id: cx.next_id(), node: move arg_type, span: span };
 
     // Create the `other` parameter.
     let other_ident = cx.ident_of(~"__other");
-    let arg_pat = build::mk_pat_ident(cx, span, other_ident);
-    let arg = {
-        mode: infer(cx.next_id()),
-        ty: arg_type,
-        pat: arg_pat,
-        id: cx.next_id()
-    };
+    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");
@@ -107,11 +131,7 @@ fn create_method(cx: ext_ctxt,
     };
 
     // Create the function declaration.
-    let fn_decl = {
-        inputs: ~[ move arg ],
-        output: output_type,
-        cf: return_val
-    };
+    let fn_decl = build::mk_fn_decl(~[ move arg ], output_type);
 
     // Create the body block.
     let body_block = build::mk_simple_block(cx, span, body);
@@ -136,28 +156,20 @@ fn create_method(cx: ext_ctxt,
 fn create_derived_impl(cx: ext_ctxt,
                        span: span,
                        type_ident: ident,
-                       eq_method: @method,
-                       ne_method: @method)
+                       methods: &[@method],
+                       trait_path: &[ast::ident])
                     -> @item {
-    // Create the reference to the `core::cmp::Eq` trait.
-    let core_ident = cx.ident_of(~"core");
-    let cmp_ident = cx.ident_of(~"cmp");
-    let eq_ident = cx.ident_of(~"Eq");
-    let core_cmp_eq_idents = ~[
-        move core_ident,
-        move cmp_ident,
-        move eq_ident
-    ];
-    let core_cmp_eq_path = {
+    // Create the reference to the trait.
+    let trait_path = {
         span: span,
         global: false,
-        idents: move core_cmp_eq_idents,
+        idents: trait_path.map(|x| *x),
         rp: None,
         types: ~[]
     };
-    let core_cmp_eq_path = @move core_cmp_eq_path;
+    let trait_path = @move trait_path;
     let trait_ref = {
-        path: core_cmp_eq_path,
+        path: trait_path,
         ref_id: cx.next_id(),
         impl_id: cx.next_id(),
     };
@@ -172,10 +184,87 @@ fn create_derived_impl(cx: ext_ctxt,
     let impl_item = item_impl(~[],
                               Some(trait_ref),
                               self_type,
-                              ~[ eq_method, ne_method ]);
+                              methods.map(|x| *x));
     return create_impl_item(cx, span, move impl_item);
 }
 
+fn create_derived_eq_impl(cx: ext_ctxt,
+                          span: span,
+                          type_ident: ident,
+                          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, methods, trait_path)
+}
+
+fn create_derived_iter_bytes_impl(cx: ext_ctxt,
+                                  span: span,
+                                  type_ident: ident,
+                                  method: @method)
+                               -> @item {
+    let trait_path = [
+        cx.ident_of(~"core"),
+        cx.ident_of(~"to_bytes"),
+        cx.ident_of(~"IterBytes")
+    ];
+    create_derived_impl(cx, span, type_ident, [ method ], 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 = @{ id: cx.next_id(), node: ty_nil, span: span };
+
+    // Create the function declaration.
+    let inputs = ~[ move lsb0_arg, move f_arg ];
+    let fn_decl = build::mk_fn_decl(move inputs, output_type);
+
+    // Create the body block.
+    let body_block = build::mk_block_(cx, span, move statements);
+
+    // Create the method.
+    let self_ty = { node: sty_by_ref, span: span };
+    let method_ident = cx.ident_of(~"iter_bytes");
+    return @{
+        ident: method_ident,
+        attrs: ~[],
+        tps: ~[],
+        self_ty: self_ty,
+        purity: pure_fn,
+        decl: move fn_decl,
+        body: move body_block,
+        id: cx.next_id(),
+        span: span,
+        self_id: cx.next_id(),
+        vis: public
+    }
+}
+
 fn create_enum_variant_pattern(cx: ext_ctxt,
                                span: span,
                                variant: &ast::variant,
@@ -214,13 +303,13 @@ fn create_enum_variant_pattern(cx: ext_ctxt,
     }
 }
 
-fn call_substructure_method(cx: ext_ctxt,
-                            span: span,
-                            self_field: @expr,
-                            other_field_ref: @expr,
-                            method_ident: ident,
-                            junction: Junction,
-                            chain_expr: &mut Option<@expr>) {
+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,
@@ -243,11 +332,11 @@ fn call_substructure_method(cx: ext_ctxt,
     };
 }
 
-fn finish_chain_expr(cx: ext_ctxt,
-                     span: span,
-                     chain_expr: Option<@expr>,
-                     junction: Junction)
-                  -> @expr {
+fn finish_eq_chain_expr(cx: ext_ctxt,
+                        span: span,
+                        chain_expr: Option<@expr>,
+                        junction: Junction)
+                     -> @expr {
     match chain_expr {
         None => {
             match junction {
@@ -259,6 +348,31 @@ fn finish_chain_expr(cx: ext_ctxt,
     }
 }
 
+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 variant_arg_count(cx: ext_ctxt, span: span, variant: &variant) -> uint {
     match variant.node.kind {
         tuple_variant_kind(args) => args.len(),
@@ -269,38 +383,66 @@ fn variant_arg_count(cx: ext_ctxt, span: span, variant: &variant) -> uint {
     }
 }
 
-fn expand_deriving_struct_def(cx: ext_ctxt,
-                              span: span,
-                              struct_def: &struct_def,
-                              type_ident: ident)
-                           -> @item {
+fn expand_deriving_eq_struct_def(cx: ext_ctxt,
+                                 span: span,
+                                 struct_def: &struct_def,
+                                 type_ident: ident)
+                              -> @item {
     // Create the methods.
     let eq_ident = cx.ident_of(~"eq");
     let ne_ident = cx.ident_of(~"ne");
-    let eq_method = expand_deriving_struct_method(cx,
-                                                  span,
-                                                  struct_def,
-                                                  eq_ident,
-                                                  type_ident,
-                                                  Conjunction);
-    let ne_method = expand_deriving_struct_method(cx,
-                                                  span,
-                                                  struct_def,
-                                                  ne_ident,
-                                                  type_ident,
-                                                  Disjunction);
+    let eq_method = expand_deriving_eq_struct_method(cx,
+                                                     span,
+                                                     struct_def,
+                                                     eq_ident,
+                                                     type_ident,
+                                                     Conjunction);
+    let ne_method = expand_deriving_eq_struct_method(cx,
+                                                     span,
+                                                     struct_def,
+                                                     ne_ident,
+                                                     type_ident,
+                                                     Disjunction);
 
     // Create the implementation.
-    return create_derived_impl(cx, span, type_ident, eq_method, ne_method);
+    return create_derived_eq_impl(cx, span, type_ident, eq_method, ne_method);
 }
 
-fn expand_deriving_struct_method(cx: ext_ctxt,
-                                 span: span,
-                                 struct_def: &struct_def,
-                                 method_ident: ident,
-                                 type_ident: ident,
-                                 junction: Junction)
-                              -> @method {
+fn expand_deriving_iter_bytes_struct_def(cx: ext_ctxt,
+                                         span: span,
+                                         struct_def: &struct_def,
+                                         type_ident: ident)
+                                      -> @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, method);
+}
+
+fn expand_deriving_iter_bytes_enum_def(cx: ext_ctxt,
+                                       span: span,
+                                       enum_definition: &enum_def,
+                                       type_ident: ident)
+                                    -> @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, method);
+}
+
+fn expand_deriving_eq_struct_method(cx: ext_ctxt,
+                                    span: span,
+                                    struct_def: &struct_def,
+                                    method_ident: ident,
+                                    type_ident: ident,
+                                    junction: Junction)
+                                 -> @method {
     let self_ident = cx.ident_of(~"self");
     let other_ident = cx.ident_of(~"__other");
 
@@ -325,13 +467,13 @@ fn expand_deriving_struct_method(cx: ext_ctxt,
                                                   ident);
 
                 // Call the substructure method.
-                call_substructure_method(cx,
-                                         span,
-                                         self_field,
-                                         other_field_ref,
-                                         method_ident,
-                                         junction,
-                                         &mut outer_expr);
+                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`");
@@ -340,42 +482,77 @@ fn expand_deriving_struct_method(cx: ext_ctxt,
     }
 
     // Create the method itself.
-    let body = finish_chain_expr(cx, span, outer_expr, junction);
-    return create_method(cx, span, method_ident, type_ident, body);
+    let body = finish_eq_chain_expr(cx, span, outer_expr, junction);
+    return create_eq_method(cx, span, method_ident, type_ident, body);
 }
 
-fn expand_deriving_enum_def(cx: ext_ctxt,
-                            span: span,
-                            enum_definition: &enum_def,
-                            type_ident: ident)
-                         -> @item {
+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 statements = dvec::DVec();
+    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.
+    let statements = dvec::unwrap(move statements);
+    return create_iter_bytes_method(cx, span, move statements);
+}
+
+fn expand_deriving_eq_enum_def(cx: ext_ctxt,
+                               span: span,
+                               enum_definition: &enum_def,
+                               type_ident: ident)
+                            -> @item {
     // Create the methods.
     let eq_ident = cx.ident_of(~"eq");
     let ne_ident = cx.ident_of(~"ne");
-    let eq_method = expand_deriving_enum_method(cx,
+    let eq_method = expand_deriving_eq_enum_method(cx,
                                                 span,
                                                 enum_definition,
                                                 eq_ident,
                                                 type_ident,
                                                 Conjunction);
-    let ne_method = expand_deriving_enum_method(cx,
-                                                span,
-                                                enum_definition,
-                                                ne_ident,
-                                                type_ident,
-                                                Disjunction);
+    let ne_method = expand_deriving_eq_enum_method(cx,
+                                                   span,
+                                                   enum_definition,
+                                                   ne_ident,
+                                                   type_ident,
+                                                   Disjunction);
 
     // Create the implementation.
-    return create_derived_impl(cx, span, type_ident, eq_method, ne_method);
+    return create_derived_eq_impl(cx, span, type_ident, eq_method, ne_method);
 }
 
-fn expand_deriving_enum_method(cx: ext_ctxt,
-                               span: span,
-                               enum_definition: &enum_def,
-                               method_ident: ident,
-                               type_ident: ident,
-                               junction: Junction)
-                            -> @method {
+fn expand_deriving_eq_enum_method(cx: ext_ctxt,
+                                  span: span,
+                                  enum_definition: &enum_def,
+                                  method_ident: ident,
+                                  type_ident: ident,
+                                  junction: Junction)
+                               -> @method {
     let self_ident = cx.ident_of(~"self");
     let other_ident = cx.ident_of(~"__other");
 
@@ -410,19 +587,19 @@ fn expand_deriving_enum_method(cx: ext_ctxt,
             let self_field = build::mk_path(cx, span, ~[ self_field_ident ]);
 
             // Call the substructure method.
-            call_substructure_method(cx,
-                                     span,
-                                     self_field,
-                                     other_field,
-                                     method_ident,
-                                     junction,
-                                     &mut matching_body_expr);
+            call_substructure_eq_method(cx,
+                                        span,
+                                        self_field,
+                                        other_field,
+                                        method_ident,
+                                        junction,
+                                        &mut matching_body_expr);
         }
 
-        let matching_body_expr = finish_chain_expr(cx,
-                                                   span,
-                                                   matching_body_expr,
-                                                   junction);
+        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);
@@ -491,6 +668,72 @@ fn expand_deriving_enum_method(cx: ext_ctxt,
     let self_match_expr = build::mk_expr(cx, span, move self_match_expr);
 
     // Create the method.
-    return create_method(cx, span, method_ident, type_ident, self_match_expr);
+    return create_eq_method(cx,
+                            span,
+                            method_ident,
+                            type_ident,
+                            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 = dvec::DVec();
+    for enum_definition.variants.eachi |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 stmts = dvec::DVec();
+        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 stmts = dvec::unwrap(move stmts);
+        let match_body_block = build::mk_block_(cx, span, move stmts);
+
+        // Create the arm.
+        let arm = {
+            pats: ~[ pat ],
+            guard: None,
+            body: move match_body_block
+        };
+        arms.push(move arm);
+    }
+
+    // Create the method body.
+    let self_ident = cx.ident_of(~"self");
+    let self_expr = build::mk_path(cx, span, ~[ self_ident ]);
+    let arms = dvec::unwrap(move arms);
+    let self_match_expr = expr_match(self_expr, move arms);
+    let self_match_expr = build::mk_expr(cx, span, move self_match_expr);
+    let self_match_stmt = build::mk_stmt(cx, span, self_match_expr);
+
+    // Create the method.
+    return create_iter_bytes_method(cx, span, ~[ self_match_stmt ]);
 }