1
- // Copyright 2012- 2013 The Rust Project Developers. See the COPYRIGHT
1
+ // Copyright 2013 The Rust Project Developers. See the COPYRIGHT
2
2
// file at the top-level directory of this distribution and at
3
3
// http://rust-lang.org/COPYRIGHT.
4
4
//
8
8
// option. This file may not be copied, modified, or distributed
9
9
// except according to those terms.
10
10
11
- use ast;
12
- use ast :: * ;
11
+ use ast:: { meta_item , item , expr } ;
12
+ use codemap :: span ;
13
13
use ext:: base:: ext_ctxt;
14
14
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:: * ;
19
16
20
17
pub fn expand_deriving_iter_bytes( cx : @ext_ctxt ,
21
18
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 )
30
42
}
31
43
32
44
pub fn expand_deriving_obsolete( cx : @ext_ctxt ,
@@ -39,217 +51,43 @@ pub fn expand_deriving_obsolete(cx: @ext_ctxt,
39
51
in_items
40
52
}
41
53
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
236
72
}
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
+ } ;
237
80
238
- // Create the pattern body.
239
- let match_body_block = build:: mk_block_ ( cx, span, stmts) ;
81
+ stmts. push ( call_iterbytes ( discriminant) ) ;
240
82
241
- // Create the arm.
242
- ast:: arm {
243
- pats : ~[ pat ] ,
244
- guard : None ,
245
- body : match_body_block,
83
+ fields = fs;
246
84
}
247
- } ;
85
+ _ => cx. span_bug ( span, "Impossible substructure in `deriving(IterBytes)`" )
86
+ }
248
87
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
+ }
252
91
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