@@ -15,7 +15,7 @@ use core::prelude::*;
15
15
16
16
use ast;
17
17
use ast:: { TraitTyParamBound , Ty , and, bind_by_ref, binop, deref, enum_def} ;
18
- use ast:: { enum_variant_kind, expr, expr_match, ident, item, item_} ;
18
+ use ast:: { enum_variant_kind, expr, expr_match, ident, impure_fn , item, item_} ;
19
19
use ast:: { item_enum, item_impl, item_struct, Generics } ;
20
20
use ast:: { m_imm, meta_item, method} ;
21
21
use ast:: { named_field, or, pat, pat_ident, pat_wild, public, pure_fn} ;
@@ -84,6 +84,18 @@ pub fn expand_deriving_iter_bytes(cx: ext_ctxt,
84
84
expand_deriving_iter_bytes_enum_def )
85
85
}
86
86
87
+ pub fn expand_deriving_clone( cx : ext_ctxt ,
88
+ span : span ,
89
+ _: @meta_item ,
90
+ in_items: ~[ @item] )
91
+ -> ~[ @item] {
92
+ expand_deriving ( cx ,
93
+ span ,
94
+ in_items ,
95
+ expand_deriving_clone_struct_def ,
96
+ expand_deriving_clone_enum_def )
97
+ }
98
+
87
99
fn expand_deriving ( cx : ext_ctxt ,
88
100
span : span ,
89
101
in_items : ~[ @item] ,
@@ -303,6 +315,21 @@ fn create_derived_iter_bytes_impl(cx: ext_ctxt,
303
315
create_derived_impl ( cx, span, type_ident, generics, methods, trait_path)
304
316
}
305
317
318
+ fn create_derived_clone_impl ( cx : ext_ctxt ,
319
+ span : span ,
320
+ type_ident : ident ,
321
+ generics : & Generics ,
322
+ method : @method )
323
+ -> @item {
324
+ let methods = [ method ] ;
325
+ let trait_path = [
326
+ cx. ident_of ( ~"core") ,
327
+ cx. ident_of ( ~"clone") ,
328
+ cx. ident_of ( ~"Clone ") ,
329
+ ] ;
330
+ create_derived_impl ( cx, span, type_ident, generics, methods, trait_path)
331
+ }
332
+
306
333
// Creates a method from the given set of statements conforming to the
307
334
// signature of the `iter_bytes` method.
308
335
fn create_iter_bytes_method ( cx : ext_ctxt ,
@@ -352,6 +379,58 @@ fn create_iter_bytes_method(cx: ext_ctxt,
352
379
}
353
380
}
354
381
382
+ // Creates a method from the given expression conforming to the signature of
383
+ // the `clone` method.
384
+ fn create_clone_method ( cx : ext_ctxt ,
385
+ span : span ,
386
+ +type_ident : ast:: ident ,
387
+ generics : & Generics ,
388
+ expr : @ast:: expr )
389
+ -> @method {
390
+ // Create the type parameters of the return value.
391
+ let mut output_ty_params = ~[ ] ;
392
+ for generics. ty_params. each |ty_param| {
393
+ let path = build:: mk_ty_path ( cx, span, ~[ ty_param. ident ] ) ;
394
+ output_ty_params. push ( path) ;
395
+ }
396
+
397
+ // Create the type of the return value.
398
+ let output_type_path = build:: mk_raw_path_ ( span,
399
+ ~[ type_ident ] ,
400
+ output_ty_params) ;
401
+ let output_type = ast:: ty_path ( output_type_path, cx. next_id ( ) ) ;
402
+ let output_type = @ast:: Ty {
403
+ id : cx. next_id ( ) ,
404
+ node : output_type,
405
+ span : span
406
+ } ;
407
+
408
+ // Create the function declaration.
409
+ let fn_decl = build:: mk_fn_decl ( ~[ ] , output_type) ;
410
+
411
+ // Create the body block.
412
+ let body_block = build:: mk_simple_block ( cx, span, expr) ;
413
+
414
+ // Create the self type and method identifier.
415
+ let self_ty = spanned { node : sty_region ( m_imm) , span : span } ;
416
+ let method_ident = cx. ident_of ( ~"clone") ;
417
+
418
+ // Create the method.
419
+ @ast:: method {
420
+ ident : method_ident,
421
+ attrs : ~[ ] ,
422
+ generics : ast_util:: empty_generics ( ) ,
423
+ self_ty : self_ty,
424
+ purity : impure_fn,
425
+ decl : fn_decl,
426
+ body : body_block,
427
+ id : cx. next_id ( ) ,
428
+ span : span,
429
+ self_id : cx. next_id ( ) ,
430
+ vis : public,
431
+ }
432
+ }
433
+
355
434
fn create_subpatterns ( cx : ext_ctxt ,
356
435
span : span ,
357
436
prefix : ~str ,
@@ -372,6 +451,15 @@ fn create_subpatterns(cx: ext_ctxt,
372
451
return dvec:: unwrap ( subpats) ;
373
452
}
374
453
454
+ fn is_struct_tuple ( struct_def : & struct_def ) -> bool {
455
+ struct_def. fields . len ( ) > 0 && struct_def. fields . all ( |f| {
456
+ match f. node . kind {
457
+ named_field( * ) => false ,
458
+ unnamed_field => true
459
+ }
460
+ } )
461
+ }
462
+
375
463
fn create_enum_variant_pattern ( cx : ext_ctxt ,
376
464
span : span ,
377
465
variant : & variant ,
@@ -488,6 +576,16 @@ fn call_substructure_iter_bytes_method(cx: ext_ctxt,
488
576
build:: mk_stmt ( cx, span, self_call)
489
577
}
490
578
579
+ fn call_substructure_clone_method ( cx : ext_ctxt ,
580
+ span : span ,
581
+ self_field: @expr)
582
+ -> @expr {
583
+ // Call the substructure method.
584
+ let clone_ident = cx. ident_of ( ~"clone") ;
585
+ let self_method = build:: mk_access_ ( cx, span, self_field, clone_ident) ;
586
+ build:: mk_call_ ( cx, span, self_method, ~[ ] )
587
+ }
588
+
491
589
fn variant_arg_count ( cx : ext_ctxt , span : span , variant : & variant ) -> uint {
492
590
match variant. node . kind {
493
591
tuple_variant_kind( ref args) => args. len ( ) ,
@@ -508,21 +606,12 @@ fn expand_deriving_eq_struct_def(cx: ext_ctxt,
508
606
let eq_ident = cx. ident_of ( ~"eq") ;
509
607
let ne_ident = cx. ident_of ( ~"ne") ;
510
608
511
- let is_struct_tuple =
512
- struct_def. fields . len ( ) > 0 && struct_def. fields . all ( |f| {
513
- match f. node . kind {
514
- named_field( * ) => false ,
515
- unnamed_field => true
516
- }
517
- } ) ;
518
-
519
- let derive_struct_fn = if is_struct_tuple {
609
+ let derive_struct_fn = if is_struct_tuple ( struct_def) {
520
610
expand_deriving_eq_struct_tuple_method
521
611
} else {
522
612
expand_deriving_eq_struct_method
523
613
} ;
524
614
525
-
526
615
let eq_method = derive_struct_fn ( cx,
527
616
span,
528
617
struct_def,
@@ -618,6 +707,48 @@ fn expand_deriving_iter_bytes_enum_def(cx: ext_ctxt,
618
707
method) ;
619
708
}
620
709
710
+ fn expand_deriving_clone_struct_def ( cx : ext_ctxt ,
711
+ span : span ,
712
+ struct_def : & struct_def ,
713
+ type_ident : ident ,
714
+ generics : & Generics )
715
+ -> @item {
716
+ // Create the method.
717
+ let method = if !is_struct_tuple ( struct_def) {
718
+ expand_deriving_clone_struct_method ( cx,
719
+ span,
720
+ struct_def,
721
+ type_ident,
722
+ generics)
723
+ } else {
724
+ expand_deriving_clone_tuple_struct_method ( cx,
725
+ span,
726
+ struct_def,
727
+ type_ident,
728
+ generics)
729
+ } ;
730
+
731
+ // Create the implementation.
732
+ create_derived_clone_impl ( cx, span, type_ident, generics, method)
733
+ }
734
+
735
+ fn expand_deriving_clone_enum_def ( cx : ext_ctxt ,
736
+ span : span ,
737
+ enum_definition : & enum_def ,
738
+ type_ident : ident ,
739
+ generics : & Generics )
740
+ -> @item {
741
+ // Create the method.
742
+ let method = expand_deriving_clone_enum_method ( cx,
743
+ span,
744
+ enum_definition,
745
+ type_ident,
746
+ generics) ;
747
+
748
+ // Create the implementation.
749
+ create_derived_clone_impl ( cx, span, type_ident, generics, method)
750
+ }
751
+
621
752
fn expand_deriving_eq_struct_method ( cx : ext_ctxt ,
622
753
span : span ,
623
754
struct_def : & struct_def ,
@@ -709,6 +840,93 @@ fn expand_deriving_iter_bytes_struct_method(cx: ext_ctxt,
709
840
return create_iter_bytes_method ( cx, span, statements) ;
710
841
}
711
842
843
+ fn expand_deriving_clone_struct_method ( cx : ext_ctxt ,
844
+ span : span ,
845
+ struct_def : & struct_def ,
846
+ type_ident : ident ,
847
+ generics : & Generics )
848
+ -> @method {
849
+ let self_ident = cx. ident_of ( ~"self ") ;
850
+
851
+ // Create the new fields.
852
+ let mut fields = ~[ ] ;
853
+ for struct_def. fields. each |struct_field| {
854
+ match struct_field. node . kind {
855
+ named_field( ident, _, _) => {
856
+ // Create the accessor for this field.
857
+ let self_field = build:: mk_access ( cx,
858
+ span,
859
+ ~[ self_ident ] ,
860
+ ident) ;
861
+
862
+ // Call the substructure method.
863
+ let call = call_substructure_clone_method ( cx,
864
+ span,
865
+ self_field) ;
866
+
867
+ let field = build:: Field { ident : ident, ex : call } ;
868
+ fields. push ( field) ;
869
+ }
870
+ unnamed_field => {
871
+ cx. span_bug ( span,
872
+ ~"unnamed fields in \
873
+ expand_deriving_clone_struct_method") ;
874
+ }
875
+ }
876
+ }
877
+
878
+ // Create the struct literal.
879
+ let struct_literal = build:: mk_struct_e ( cx,
880
+ span,
881
+ ~[ type_ident ] ,
882
+ fields) ;
883
+ create_clone_method ( cx, span, type_ident, generics, struct_literal)
884
+ }
885
+
886
+ fn expand_deriving_clone_tuple_struct_method ( cx : ext_ctxt ,
887
+ span : span ,
888
+ struct_def : & struct_def ,
889
+ type_ident : ident ,
890
+ generics : & Generics )
891
+ -> @method {
892
+ // Create the pattern for the match.
893
+ let matching_path = build:: mk_raw_path ( span, ~[ type_ident ] ) ;
894
+ let field_count = struct_def. fields . len ( ) ;
895
+ let subpats = create_subpatterns ( cx, span, ~"__self", field_count) ;
896
+ let pat = build:: mk_pat_enum ( cx, span, matching_path, subpats) ;
897
+
898
+ // Create the new fields.
899
+ let mut subcalls = ~[ ] ;
900
+ for uint:: range( 0 , struct_def. fields. len( ) ) |i| {
901
+ // Create the expression for this field.
902
+ let field_ident = cx. ident_of ( ~"__self" + i. to_str ( ) ) ;
903
+ let field = build:: mk_path ( cx, span, ~[ field_ident ] ) ;
904
+
905
+ // Call the substructure method.
906
+ let subcall = call_substructure_clone_method ( cx, span, field) ;
907
+ subcalls. push ( subcall) ;
908
+ }
909
+
910
+ // Create the call to the struct constructor.
911
+ let call = build:: mk_call ( cx, span, ~[ type_ident ] , subcalls) ;
912
+
913
+ // Create the pattern body.
914
+ let match_body_block = build:: mk_simple_block ( cx, span, call) ;
915
+
916
+ // Create the arm.
917
+ let arm = ast:: arm {
918
+ pats : ~[ pat ] ,
919
+ guard : None ,
920
+ body : match_body_block
921
+ } ;
922
+
923
+ // Create the method body.
924
+ let self_match_expr = expand_enum_or_struct_match ( cx, span, ~[ arm ] ) ;
925
+
926
+ // Create the method.
927
+ create_clone_method ( cx, span, type_ident, generics, self_match_expr)
928
+ }
929
+
712
930
fn expand_deriving_eq_enum_method ( cx : ext_ctxt ,
713
931
span : span ,
714
932
enum_definition : & enum_def ,
@@ -904,6 +1122,17 @@ fn expand_deriving_eq_struct_tuple_method(cx: ext_ctxt,
904
1122
type_ident, generics, self_match_expr)
905
1123
}
906
1124
1125
+ fn expand_enum_or_struct_match ( cx : ext_ctxt ,
1126
+ span : span ,
1127
+ arms : ~[ ast:: arm ] )
1128
+ -> @expr {
1129
+ let self_ident = cx. ident_of ( ~"self ") ;
1130
+ let self_expr = build:: mk_path ( cx, span, ~[ self_ident ] ) ;
1131
+ let self_expr = build:: mk_unary ( cx, span, deref, self_expr) ;
1132
+ let self_match_expr = expr_match ( self_expr, arms) ;
1133
+ build:: mk_expr ( cx, span, self_match_expr)
1134
+ }
1135
+
907
1136
fn expand_deriving_iter_bytes_enum_method ( cx : ext_ctxt ,
908
1137
span : span ,
909
1138
enum_definition : & enum_def )
@@ -953,14 +1182,54 @@ fn expand_deriving_iter_bytes_enum_method(cx: ext_ctxt,
953
1182
} ;
954
1183
955
1184
// Create the method body.
956
- let self_ident = cx. ident_of ( ~"self ") ;
957
- let self_expr = build:: mk_path ( cx, span, ~[ self_ident ] ) ;
958
- let self_expr = build:: mk_unary ( cx, span, deref, self_expr) ;
959
- let self_match_expr = expr_match ( self_expr, arms) ;
960
- let self_match_expr = build:: mk_expr ( cx, span, self_match_expr) ;
1185
+ let self_match_expr = expand_enum_or_struct_match ( cx, span, arms) ;
961
1186
let self_match_stmt = build:: mk_stmt ( cx, span, self_match_expr) ;
962
1187
963
1188
// Create the method.
964
1189
create_iter_bytes_method ( cx, span, ~[ self_match_stmt ] )
965
1190
}
966
1191
1192
+ fn expand_deriving_clone_enum_method ( cx : ext_ctxt ,
1193
+ span : span ,
1194
+ enum_definition : & enum_def ,
1195
+ type_ident : ident ,
1196
+ generics : & Generics )
1197
+ -> @method {
1198
+ // Create the arms of the match in the method body.
1199
+ let arms = do enum_definition. variants . map |variant| {
1200
+ // Create the matching pattern.
1201
+ let pat = create_enum_variant_pattern ( cx, span, variant, ~"__self") ;
1202
+
1203
+ // Iterate over the variant arguments, creating the subcalls.
1204
+ let mut subcalls = ~[ ] ;
1205
+ for uint:: range( 0 , variant_arg_count( cx, span, variant) ) |j| {
1206
+ // Create the expression for this field.
1207
+ let field_ident = cx. ident_of ( ~"__self" + j. to_str ( ) ) ;
1208
+ let field = build:: mk_path ( cx, span, ~[ field_ident ] ) ;
1209
+
1210
+ // Call the substructure method.
1211
+ let subcall = call_substructure_clone_method ( cx, span, field) ;
1212
+ subcalls. push ( subcall) ;
1213
+ }
1214
+
1215
+ // Create the call to the enum variant (if necessary).
1216
+ let call = if subcalls. len ( ) > 0 {
1217
+ build:: mk_call ( cx, span, ~[ variant. node . name ] , subcalls)
1218
+ } else {
1219
+ build:: mk_path ( cx, span, ~[ variant. node . name ] )
1220
+ } ;
1221
+
1222
+ // Create the pattern body.
1223
+ let match_body_block = build:: mk_simple_block ( cx, span, call) ;
1224
+
1225
+ // Create the arm.
1226
+ ast:: arm { pats : ~[ pat ] , guard : None , body : match_body_block }
1227
+ } ;
1228
+
1229
+ // Create the method body.
1230
+ let self_match_expr = expand_enum_or_struct_match ( cx, span, arms) ;
1231
+
1232
+ // Create the method.
1233
+ create_clone_method ( cx, span, type_ident, generics, self_match_expr)
1234
+ }
1235
+
0 commit comments