Skip to content

Commit 1cf2108

Browse files
committed
libsyntax: convert #[deriving(IterBytes)] to generic deriving
1 parent b20eb97 commit 1cf2108

File tree

1 file changed

+61
-223
lines changed

1 file changed

+61
-223
lines changed
+61-223
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
1+
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
22
// file at the top-level directory of this distribution and at
33
// http://rust-lang.org/COPYRIGHT.
44
//
@@ -8,25 +8,37 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
use ast;
12-
use ast::*;
11+
use ast::{meta_item, item, expr};
12+
use codemap::span;
1313
use ext::base::ext_ctxt;
1414
use ext::build;
15-
use ext::deriving::*;
16-
use codemap::{span, spanned};
17-
use ast_util;
18-
use opt_vec;
15+
use ext::deriving::generic::*;
1916

2017
pub fn expand_deriving_iter_bytes(cx: @ext_ctxt,
2118
span: span,
22-
_mitem: @meta_item,
23-
in_items: ~[@item])
24-
-> ~[@item] {
25-
expand_deriving(cx,
26-
span,
27-
in_items,
28-
expand_deriving_iter_bytes_struct_def,
29-
expand_deriving_iter_bytes_enum_def)
19+
mitem: @meta_item,
20+
in_items: ~[@item]) -> ~[@item] {
21+
let trait_def = TraitDef {
22+
path: Path::new(~[~"core", ~"to_bytes", ~"IterBytes"]),
23+
additional_bounds: ~[],
24+
generics: LifetimeBounds::empty(),
25+
methods: ~[
26+
MethodDef {
27+
name: ~"iter_bytes",
28+
generics: LifetimeBounds::empty(),
29+
self_ty: borrowed_explicit_self(),
30+
args: ~[
31+
Literal(Path::new(~[~"bool"])),
32+
Literal(Path::new(~[~"core", ~"to_bytes", ~"Cb"]))
33+
],
34+
ret_ty: nil_ty(),
35+
const_nonmatching: false,
36+
combine_substructure: iter_bytes_substructure
37+
}
38+
]
39+
};
40+
41+
expand_deriving_generic(cx, span, mitem, in_items, &trait_def)
3042
}
3143

3244
pub fn expand_deriving_obsolete(cx: @ext_ctxt,
@@ -39,217 +51,43 @@ pub fn expand_deriving_obsolete(cx: @ext_ctxt,
3951
in_items
4052
}
4153

42-
fn create_derived_iter_bytes_impl(cx: @ext_ctxt,
43-
span: span,
44-
type_ident: ident,
45-
generics: &Generics,
46-
method: @method)
47-
-> @item {
48-
let methods = [ method ];
49-
let trait_path = ~[
50-
cx.ident_of(~"core"),
51-
cx.ident_of(~"to_bytes"),
52-
cx.ident_of(~"IterBytes")
53-
];
54-
let trait_path = build::mk_raw_path_global(span, trait_path);
55-
create_derived_impl(cx, span, type_ident, generics, methods, trait_path,
56-
opt_vec::Empty, opt_vec::Empty)
57-
}
58-
59-
// Creates a method from the given set of statements conforming to the
60-
// signature of the `iter_bytes` method.
61-
fn create_iter_bytes_method(cx: @ext_ctxt,
62-
span: span,
63-
statements: ~[@stmt])
64-
-> @method {
65-
// Create the `lsb0` parameter.
66-
let bool_ident = cx.ident_of(~"bool");
67-
let lsb0_arg_type = build::mk_simple_ty_path(cx, span, bool_ident);
68-
let lsb0_ident = cx.ident_of(~"__lsb0");
69-
let lsb0_arg = build::mk_arg(cx, span, lsb0_ident, lsb0_arg_type);
70-
71-
// Create the `f` parameter.
72-
let core_ident = cx.ident_of(~"core");
73-
let to_bytes_ident = cx.ident_of(~"to_bytes");
74-
let cb_ident = cx.ident_of(~"Cb");
75-
let core_to_bytes_cb_ident = ~[ core_ident, to_bytes_ident, cb_ident ];
76-
let f_arg_type = build::mk_ty_path(cx, span, core_to_bytes_cb_ident);
77-
let f_ident = cx.ident_of(~"__f");
78-
let f_arg = build::mk_arg(cx, span, f_ident, f_arg_type);
79-
80-
// Create the type of the return value.
81-
let output_type = @ast::Ty { id: cx.next_id(), node: ty_nil, span: span };
82-
83-
// Create the function declaration.
84-
let inputs = ~[ lsb0_arg, f_arg ];
85-
let fn_decl = build::mk_fn_decl(inputs, output_type);
86-
87-
// Create the body block.
88-
let body_block = build::mk_block_(cx, span, statements);
89-
90-
// Create the method.
91-
let self_ty = spanned { node: sty_region(None, m_imm), span: span };
92-
let method_ident = cx.ident_of(~"iter_bytes");
93-
@ast::method {
94-
ident: method_ident,
95-
attrs: ~[],
96-
generics: ast_util::empty_generics(),
97-
self_ty: self_ty,
98-
purity: impure_fn,
99-
decl: fn_decl,
100-
body: body_block,
101-
id: cx.next_id(),
102-
span: span,
103-
self_id: cx.next_id(),
104-
vis: public
105-
}
106-
}
107-
108-
fn call_substructure_iter_bytes_method(cx: @ext_ctxt,
109-
span: span,
110-
self_field: @expr)
111-
-> @stmt {
112-
// Gather up the parameters we want to chain along.
113-
let lsb0_ident = cx.ident_of(~"__lsb0");
114-
let f_ident = cx.ident_of(~"__f");
115-
let lsb0_expr = build::mk_path(cx, span, ~[ lsb0_ident ]);
116-
let f_expr = build::mk_path(cx, span, ~[ f_ident ]);
117-
118-
// Call the substructure method.
119-
let iter_bytes_ident = cx.ident_of(~"iter_bytes");
120-
let self_call = build::mk_method_call(cx,
121-
span,
122-
self_field,
123-
iter_bytes_ident,
124-
~[ lsb0_expr, f_expr ]);
125-
126-
// Create a statement out of this expression.
127-
build::mk_stmt(cx, span, self_call)
128-
}
129-
130-
fn expand_deriving_iter_bytes_struct_def(cx: @ext_ctxt,
131-
span: span,
132-
struct_def: &struct_def,
133-
type_ident: ident,
134-
generics: &Generics)
135-
-> @item {
136-
// Create the method.
137-
let method = expand_deriving_iter_bytes_struct_method(cx,
138-
span,
139-
struct_def);
140-
141-
// Create the implementation.
142-
return create_derived_iter_bytes_impl(cx,
143-
span,
144-
type_ident,
145-
generics,
146-
method);
147-
}
148-
149-
fn expand_deriving_iter_bytes_enum_def(cx: @ext_ctxt,
150-
span: span,
151-
enum_definition: &enum_def,
152-
type_ident: ident,
153-
generics: &Generics)
154-
-> @item {
155-
// Create the method.
156-
let method = expand_deriving_iter_bytes_enum_method(cx,
157-
span,
158-
enum_definition);
159-
160-
// Create the implementation.
161-
return create_derived_iter_bytes_impl(cx,
162-
span,
163-
type_ident,
164-
generics,
165-
method);
166-
}
167-
168-
fn expand_deriving_iter_bytes_struct_method(cx: @ext_ctxt,
169-
span: span,
170-
struct_def: &struct_def)
171-
-> @method {
172-
let self_ident = cx.ident_of(~"self");
173-
174-
// Create the body of the method.
175-
let mut statements = ~[];
176-
for struct_def.fields.each |struct_field| {
177-
match struct_field.node.kind {
178-
named_field(ident, _, _) => {
179-
// Create the accessor for this field.
180-
let self_field = build::mk_access(cx,
181-
span,
182-
~[ self_ident ],
183-
ident);
184-
185-
// Call the substructure method.
186-
let stmt = call_substructure_iter_bytes_method(cx,
187-
span,
188-
self_field);
189-
statements.push(stmt);
190-
}
191-
unnamed_field => {
192-
cx.span_unimpl(span,
193-
~"unnamed fields with `deriving(IterBytes)`");
194-
}
195-
}
196-
}
197-
198-
// Create the method itself.
199-
return create_iter_bytes_method(cx, span, statements);
200-
}
201-
202-
fn expand_deriving_iter_bytes_enum_method(cx: @ext_ctxt,
203-
span: span,
204-
enum_definition: &enum_def)
205-
-> @method {
206-
// Create the arms of the match in the method body.
207-
let arms = do enum_definition.variants.mapi |i, variant| {
208-
// Create the matching pattern.
209-
let pat = create_enum_variant_pattern(cx, span, variant, ~"__self");
210-
211-
// Determine the discriminant. We will feed this value to the byte
212-
// iteration function.
213-
let discriminant;
214-
match variant.node.disr_expr {
215-
Some(copy disr_expr) => discriminant = disr_expr,
216-
None => discriminant = build::mk_uint(cx, span, i),
217-
}
218-
219-
// Feed the discriminant to the byte iteration function.
220-
let mut stmts = ~[];
221-
let discrim_stmt = call_substructure_iter_bytes_method(cx,
222-
span,
223-
discriminant);
224-
stmts.push(discrim_stmt);
225-
226-
// Feed each argument in this variant to the byte iteration function
227-
// as well.
228-
for uint::range(0, variant_arg_count(cx, span, variant)) |j| {
229-
// Create the expression for this field.
230-
let field_ident = cx.ident_of(~"__self_" + j.to_str());
231-
let field = build::mk_path(cx, span, ~[ field_ident ]);
232-
233-
// Call the substructure method.
234-
let stmt = call_substructure_iter_bytes_method(cx, span, field);
235-
stmts.push(stmt);
54+
fn iter_bytes_substructure(cx: @ext_ctxt, span: span, substr: &Substructure) -> @expr {
55+
let lsb0_f = match substr.nonself_args {
56+
[l, f] => ~[l, f],
57+
_ => cx.span_bug(span, "Incorrect number of arguments in `deriving(IterBytes)`")
58+
};
59+
let iter_bytes_ident = substr.method_ident;
60+
let call_iterbytes = |thing_expr| {
61+
build::mk_stmt(
62+
cx, span,
63+
build::mk_method_call(cx, span,
64+
thing_expr, iter_bytes_ident,
65+
copy lsb0_f))
66+
};
67+
let mut stmts = ~[];
68+
let fields;
69+
match *substr.fields {
70+
Struct(ref fs) => {
71+
fields = fs
23672
}
73+
EnumMatching(copy index, ref variant, ref fs) => {
74+
// Determine the discriminant. We will feed this value to the byte
75+
// iteration function.
76+
let discriminant = match variant.node.disr_expr {
77+
Some(copy d)=> d,
78+
None => build::mk_uint(cx, span, index)
79+
};
23780

238-
// Create the pattern body.
239-
let match_body_block = build::mk_block_(cx, span, stmts);
81+
stmts.push(call_iterbytes(discriminant));
24082

241-
// Create the arm.
242-
ast::arm {
243-
pats: ~[ pat ],
244-
guard: None,
245-
body: match_body_block,
83+
fields = fs;
24684
}
247-
};
85+
_ => cx.span_bug(span, "Impossible substructure in `deriving(IterBytes)`")
86+
}
24887

249-
// Create the method body.
250-
let self_match_expr = expand_enum_or_struct_match(cx, span, arms);
251-
let self_match_stmt = build::mk_stmt(cx, span, self_match_expr);
88+
for fields.each |&(_, field, _)| {
89+
stmts.push(call_iterbytes(field));
90+
}
25291

253-
// Create the method.
254-
create_iter_bytes_method(cx, span, ~[ self_match_stmt ])
255-
}
92+
build::mk_block(cx, span, ~[], stmts, None)
93+
}

0 commit comments

Comments
 (0)