libsyntax: Implement deriving for struct-like enum variants. r=brson

This commit is contained in:
Patrick Walton 2012-12-10 13:04:04 -08:00
parent efb9b74718
commit 9d23029648
3 changed files with 68 additions and 16 deletions

View File

@ -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)

View File

@ -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`");

View File

@ -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);
}