Skip to content

Commit 3042321

Browse files
committed
syntax: split deriving module into submodules for each trait
1 parent 18a594f commit 3042321

File tree

5 files changed

+1062
-977
lines changed

5 files changed

+1062
-977
lines changed

src/libsyntax/ext/base.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
1+
// Copyright 2012-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
//
@@ -153,13 +153,13 @@ pub fn syntax_expander_table() -> SyntaxEnv {
153153
ext::deriving::expand_meta_deriving)));
154154
syntax_expanders.insert(@~"deriving_eq",
155155
@SE(ItemDecorator(
156-
ext::deriving::expand_deriving_eq)));
156+
ext::deriving::eq::expand_deriving_eq)));
157157
syntax_expanders.insert(@~"deriving_iter_bytes",
158158
@SE(ItemDecorator(
159-
ext::deriving::expand_deriving_iter_bytes)));
159+
ext::deriving::iter_bytes::expand_deriving_iter_bytes)));
160160
syntax_expanders.insert(@~"deriving_clone",
161161
@SE(ItemDecorator(
162-
ext::deriving::expand_deriving_clone)));
162+
ext::deriving::clone::expand_deriving_clone)));
163163

164164
// Quasi-quoting expanders
165165
syntax_expanders.insert(@~"quote_tokens",

src/libsyntax/ext/deriving/clone.rs

+289
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,289 @@
1+
// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
use core::prelude::*;
12+
13+
use ast;
14+
use ast::{TraitTyParamBound, Ty, and, bind_by_ref, binop, deref, enum_def};
15+
use ast::{enum_variant_kind, expr, expr_match, ident, impure_fn, item, item_};
16+
use ast::{item_enum, item_impl, item_struct, Generics};
17+
use ast::{m_imm, meta_item, method};
18+
use ast::{named_field, or, pat, pat_ident, pat_wild, public, pure_fn};
19+
use ast::{stmt, struct_def, struct_variant_kind};
20+
use ast::{sty_by_ref, sty_region, tuple_variant_kind, ty_nil, TyParam};
21+
use ast::{TyParamBound, ty_path, ty_rptr, unnamed_field, variant};
22+
use ext::base::ext_ctxt;
23+
use ext::build;
24+
use ext::deriving::*;
25+
use codemap::{span, spanned};
26+
use ast_util;
27+
28+
use core::uint;
29+
30+
pub fn expand_deriving_clone(cx: @ext_ctxt,
31+
span: span,
32+
_: @meta_item,
33+
in_items: ~[@item])
34+
-> ~[@item] {
35+
expand_deriving(cx,
36+
span,
37+
in_items,
38+
expand_deriving_clone_struct_def,
39+
expand_deriving_clone_enum_def)
40+
}
41+
42+
fn create_derived_clone_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(~"clone"),
52+
cx.ident_of(~"Clone"),
53+
];
54+
create_derived_impl(cx, span, type_ident, generics, methods, trait_path)
55+
}
56+
// Creates a method from the given expression conforming to the signature of
57+
// the `clone` method.
58+
fn create_clone_method(cx: @ext_ctxt,
59+
span: span,
60+
+type_ident: ast::ident,
61+
generics: &Generics,
62+
expr: @ast::expr)
63+
-> @method {
64+
// Create the type parameters of the return value.
65+
let mut output_ty_params = ~[];
66+
for generics.ty_params.each |ty_param| {
67+
let path = build::mk_ty_path(cx, span, ~[ ty_param.ident ]);
68+
output_ty_params.push(path);
69+
}
70+
71+
// Create the type of the return value.
72+
let output_type_path = build::mk_raw_path_(span,
73+
~[ type_ident ],
74+
output_ty_params);
75+
let output_type = ast::ty_path(output_type_path, cx.next_id());
76+
let output_type = @ast::Ty {
77+
id: cx.next_id(),
78+
node: output_type,
79+
span: span
80+
};
81+
82+
// Create the function declaration.
83+
let fn_decl = build::mk_fn_decl(~[], output_type);
84+
85+
// Create the body block.
86+
let body_block = build::mk_simple_block(cx, span, expr);
87+
88+
// Create the self type and method identifier.
89+
let self_ty = spanned { node: sty_region(None, m_imm), span: span };
90+
let method_ident = cx.ident_of(~"clone");
91+
92+
// Create the method.
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_clone_method(cx: @ext_ctxt,
109+
span: span,
110+
self_field: @expr)
111+
-> @expr {
112+
// Call the substructure method.
113+
let clone_ident = cx.ident_of(~"clone");
114+
let self_method = build::mk_access_(cx, span, self_field, clone_ident);
115+
build::mk_call_(cx, span, self_method, ~[])
116+
}
117+
118+
fn expand_deriving_clone_struct_def(cx: @ext_ctxt,
119+
span: span,
120+
struct_def: &struct_def,
121+
type_ident: ident,
122+
generics: &Generics)
123+
-> @item {
124+
// Create the method.
125+
let method = if !is_struct_tuple(struct_def) {
126+
expand_deriving_clone_struct_method(cx,
127+
span,
128+
struct_def,
129+
type_ident,
130+
generics)
131+
} else {
132+
expand_deriving_clone_tuple_struct_method(cx,
133+
span,
134+
struct_def,
135+
type_ident,
136+
generics)
137+
};
138+
139+
// Create the implementation.
140+
create_derived_clone_impl(cx, span, type_ident, generics, method)
141+
}
142+
143+
fn expand_deriving_clone_enum_def(cx: @ext_ctxt,
144+
span: span,
145+
enum_definition: &enum_def,
146+
type_ident: ident,
147+
generics: &Generics)
148+
-> @item {
149+
// Create the method.
150+
let method = expand_deriving_clone_enum_method(cx,
151+
span,
152+
enum_definition,
153+
type_ident,
154+
generics);
155+
156+
// Create the implementation.
157+
create_derived_clone_impl(cx, span, type_ident, generics, method)
158+
}
159+
160+
fn expand_deriving_clone_struct_method(cx: @ext_ctxt,
161+
span: span,
162+
struct_def: &struct_def,
163+
type_ident: ident,
164+
generics: &Generics)
165+
-> @method {
166+
let self_ident = cx.ident_of(~"self");
167+
168+
// Create the new fields.
169+
let mut fields = ~[];
170+
for struct_def.fields.each |struct_field| {
171+
match struct_field.node.kind {
172+
named_field(ident, _, _) => {
173+
// Create the accessor for this field.
174+
let self_field = build::mk_access(cx,
175+
span,
176+
~[ self_ident ],
177+
ident);
178+
179+
// Call the substructure method.
180+
let call = call_substructure_clone_method(cx,
181+
span,
182+
self_field);
183+
184+
let field = build::Field { ident: ident, ex: call };
185+
fields.push(field);
186+
}
187+
unnamed_field => {
188+
cx.span_bug(span,
189+
~"unnamed fields in \
190+
expand_deriving_clone_struct_method");
191+
}
192+
}
193+
}
194+
195+
// Create the struct literal.
196+
let struct_literal = build::mk_struct_e(cx,
197+
span,
198+
~[ type_ident ],
199+
fields);
200+
create_clone_method(cx, span, type_ident, generics, struct_literal)
201+
}
202+
203+
fn expand_deriving_clone_tuple_struct_method(cx: @ext_ctxt,
204+
span: span,
205+
struct_def: &struct_def,
206+
type_ident: ident,
207+
generics: &Generics)
208+
-> @method {
209+
// Create the pattern for the match.
210+
let matching_path = build::mk_raw_path(span, ~[ type_ident ]);
211+
let field_count = struct_def.fields.len();
212+
let subpats = create_subpatterns(cx, span, ~"__self", field_count);
213+
let pat = build::mk_pat_enum(cx, span, matching_path, subpats);
214+
215+
// Create the new fields.
216+
let mut subcalls = ~[];
217+
for uint::range(0, struct_def.fields.len()) |i| {
218+
// Create the expression for this field.
219+
let field_ident = cx.ident_of(~"__self" + i.to_str());
220+
let field = build::mk_path(cx, span, ~[ field_ident ]);
221+
222+
// Call the substructure method.
223+
let subcall = call_substructure_clone_method(cx, span, field);
224+
subcalls.push(subcall);
225+
}
226+
227+
// Create the call to the struct constructor.
228+
let call = build::mk_call(cx, span, ~[ type_ident ], subcalls);
229+
230+
// Create the pattern body.
231+
let match_body_block = build::mk_simple_block(cx, span, call);
232+
233+
// Create the arm.
234+
let arm = ast::arm {
235+
pats: ~[ pat ],
236+
guard: None,
237+
body: match_body_block
238+
};
239+
240+
// Create the method body.
241+
let self_match_expr = expand_enum_or_struct_match(cx, span, ~[ arm ]);
242+
243+
// Create the method.
244+
create_clone_method(cx, span, type_ident, generics, self_match_expr)
245+
}
246+
247+
fn expand_deriving_clone_enum_method(cx: @ext_ctxt,
248+
span: span,
249+
enum_definition: &enum_def,
250+
type_ident: ident,
251+
generics: &Generics)
252+
-> @method {
253+
// Create the arms of the match in the method body.
254+
let arms = do enum_definition.variants.map |variant| {
255+
// Create the matching pattern.
256+
let pat = create_enum_variant_pattern(cx, span, variant, ~"__self");
257+
258+
// Iterate over the variant arguments, creating the subcalls.
259+
let mut subcalls = ~[];
260+
for uint::range(0, variant_arg_count(cx, span, variant)) |j| {
261+
// Create the expression for this field.
262+
let field_ident = cx.ident_of(~"__self" + j.to_str());
263+
let field = build::mk_path(cx, span, ~[ field_ident ]);
264+
265+
// Call the substructure method.
266+
let subcall = call_substructure_clone_method(cx, span, field);
267+
subcalls.push(subcall);
268+
}
269+
270+
// Create the call to the enum variant (if necessary).
271+
let call = if subcalls.len() > 0 {
272+
build::mk_call(cx, span, ~[ variant.node.name ], subcalls)
273+
} else {
274+
build::mk_path(cx, span, ~[ variant.node.name ])
275+
};
276+
277+
// Create the pattern body.
278+
let match_body_block = build::mk_simple_block(cx, span, call);
279+
280+
// Create the arm.
281+
ast::arm { pats: ~[ pat ], guard: None, body: match_body_block }
282+
};
283+
284+
// Create the method body.
285+
let self_match_expr = expand_enum_or_struct_match(cx, span, arms);
286+
287+
// Create the method.
288+
create_clone_method(cx, span, type_ident, generics, self_match_expr)
289+
}

0 commit comments

Comments
 (0)