From d2796697427df6ef8c7ddc6e1ae366ccae4ffcea Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Mon, 10 Dec 2012 13:04:04 -0800 Subject: [PATCH] libsyntax: Implement `deriving` for struct-like enum variants --- src/libsyntax/ext/build.rs | 8 +++ src/libsyntax/ext/deriving.rs | 64 ++++++++++++++----- ...-via-extension-struct-like-enum-variant.rs | 12 ++++ 3 files changed, 68 insertions(+), 16 deletions(-) create mode 100644 src/test/run-pass/deriving-via-extension-struct-like-enum-variant.rs diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index 04a59d1fe4162..89a87ebd5e853 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -219,6 +219,14 @@ fn mk_pat_enum(cx: ext_ctxt, let pat = ast::pat_enum(path, Some(move subpats)); mk_pat(cx, span, move pat) } +fn mk_pat_struct(cx: ext_ctxt, + span: span, + path: @ast::path, + +field_pats: ~[ast::field_pat]) + -> @ast::pat { + let pat = ast::pat_struct(path, move field_pats, false); + mk_pat(cx, span, move pat) +} 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) diff --git a/src/libsyntax/ext/deriving.rs b/src/libsyntax/ext/deriving.rs index 2aca54446d74e..0f8a1a2322756 100644 --- a/src/libsyntax/ext/deriving.rs +++ b/src/libsyntax/ext/deriving.rs @@ -318,6 +318,26 @@ fn create_iter_bytes_method(cx: ext_ctxt, } } +fn create_subpatterns(cx: ext_ctxt, + span: span, + prefix: ~str, + n: uint) + -> ~[@pat] { + let subpats = dvec::DVec(); + 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, move subpat); + subpats.push(subpat); + } + return dvec::unwrap(move subpats); +} + fn create_enum_variant_pattern(cx: ext_ctxt, span: span, variant: &variant, @@ -330,25 +350,37 @@ fn create_enum_variant_pattern(cx: ext_ctxt, return build::mk_pat_ident(cx, span, variant_ident); } - let subpats = dvec::DVec(); - for variant_args.each |_variant_arg| { - // 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, move subpat); - subpats.push(subpat); - } - let matching_path = build::mk_raw_path(span, ~[ variant_ident ]); - let subpats = dvec::unwrap(move subpats); + let subpats = create_subpatterns(cx, + span, + prefix, + variant_args.len()); + return build::mk_pat_enum(cx, span, matching_path, move subpats); } - struct_variant_kind(*) => { - cx.span_unimpl(span, ~"struct variants for `deriving`"); + 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 = dvec::DVec(); + for struct_def.fields.eachi |i, struct_field| { + let ident = match struct_field.node.kind { + named_field(ident, _, _) => ident, + unnamed_field => { + cx.span_bug(span, ~"unexpected unnamed field"); + } + }; + field_pats.push({ ident: ident, pat: subpats[i] }); + } + let field_pats = dvec::unwrap(move field_pats); + + return build::mk_pat_struct(cx, + span, + matching_path, + move field_pats); } enum_variant_kind(*) => { cx.span_unimpl(span, ~"enum variants for `deriving`"); diff --git a/src/test/run-pass/deriving-via-extension-struct-like-enum-variant.rs b/src/test/run-pass/deriving-via-extension-struct-like-enum-variant.rs new file mode 100644 index 0000000000000..c5e41826a3540 --- /dev/null +++ b/src/test/run-pass/deriving-via-extension-struct-like-enum-variant.rs @@ -0,0 +1,12 @@ +#[deriving_eq] +enum S { + X { x: int, y: int }, + Y +} + +fn main() { + let x = X { x: 1, y: 2 }; + assert x == x; + assert !(x != x); +} +