@@ -26,6 +26,7 @@ use reflect::{MovePtr, MovePtrAdaptor, align};
26
26
use vec:: UnboxedVecRepr ;
27
27
use vec:: raw:: { VecRepr , SliceRepr } ;
28
28
pub use managed:: raw:: BoxRepr ;
29
+ use dvec:: DVec ;
29
30
30
31
/// Helpers
31
32
@@ -121,19 +122,36 @@ impl char : Repr {
121
122
122
123
// New implementation using reflect::MovePtr
123
124
125
+ enum VariantState {
126
+ Degenerate ,
127
+ TagMatch ,
128
+ TagMismatch ,
129
+ }
130
+
124
131
pub struct ReprVisitor {
125
132
mut ptr : * c_void ,
133
+ ptr_stk : DVec < * c_void > ,
134
+ var_stk : DVec < VariantState > ,
126
135
writer : @Writer
127
136
}
128
137
pub fn ReprVisitor ( ptr : * c_void , writer : @Writer ) -> ReprVisitor {
129
- ReprVisitor { ptr : ptr, writer : writer }
138
+ ReprVisitor { ptr : ptr,
139
+ ptr_stk : DVec ( ) ,
140
+ var_stk : DVec ( ) ,
141
+ writer : writer }
130
142
}
131
143
132
144
impl ReprVisitor : MovePtr {
133
145
#[ inline( always) ]
134
146
fn move_ptr ( adjustment : fn ( * c_void ) -> * c_void ) {
135
147
self . ptr = adjustment ( self . ptr ) ;
136
148
}
149
+ fn push_ptr ( ) {
150
+ self . ptr_stk . push ( self . ptr ) ;
151
+ }
152
+ fn pop_ptr ( ) {
153
+ self . ptr = self . ptr_stk . pop ( ) ;
154
+ }
137
155
}
138
156
139
157
impl ReprVisitor {
@@ -148,6 +166,18 @@ impl ReprVisitor {
148
166
true
149
167
}
150
168
169
+ #[ inline( always) ]
170
+ fn bump ( sz : uint ) {
171
+ do self . move_ptr ( ) |p| {
172
+ ( ( p as uint ) + sz) as * c_void
173
+ } ;
174
+ }
175
+
176
+ #[ inline( always) ]
177
+ fn bump_past < T > ( ) {
178
+ self . bump ( sys:: size_of :: < T > ( ) ) ;
179
+ }
180
+
151
181
#[ inline( always) ]
152
182
fn visit_inner ( inner : * TyDesc ) -> bool {
153
183
self . visit_ptr_inner ( self . ptr , inner)
@@ -402,23 +432,79 @@ impl ReprVisitor : TyVisitor {
402
432
true
403
433
}
404
434
405
- fn visit_enter_enum ( _n_variants : uint ,
435
+ fn visit_enter_enum ( n_variants : uint ,
406
436
_sz : uint , _align : uint ) -> bool {
437
+ if n_variants == 1 {
438
+ self . var_stk . push ( Degenerate )
439
+ } else {
440
+ self . var_stk . push ( TagMatch )
441
+ }
407
442
true
408
443
}
409
444
fn visit_enter_enum_variant ( _variant : uint ,
410
- _disr_val : int ,
411
- _n_fields : uint ,
412
- _name : & str ) -> bool { true }
413
- fn visit_enum_variant_field ( _i : uint , inner : * TyDesc ) -> bool {
414
- self . visit_inner ( inner)
445
+ disr_val : int ,
446
+ n_fields : uint ,
447
+ name : & str ) -> bool {
448
+ let mut write = false ;
449
+ match self . var_stk . pop ( ) {
450
+ Degenerate => {
451
+ write = true ;
452
+ self . var_stk . push ( Degenerate ) ;
453
+ }
454
+ TagMatch | TagMismatch => {
455
+ do self . get :: < int > ( ) |t| {
456
+ if disr_val == * t {
457
+ write = true ;
458
+ self . var_stk . push ( TagMatch ) ;
459
+ } else {
460
+ self . var_stk . push ( TagMismatch ) ;
461
+ }
462
+ } ;
463
+ self . bump_past :: < int > ( ) ;
464
+ }
465
+ }
466
+
467
+ if write {
468
+ self . writer . write_str ( name) ;
469
+ if n_fields > 0 {
470
+ self . writer . write_char ( '(' ) ;
471
+ }
472
+ }
473
+ true
474
+ }
475
+ fn visit_enum_variant_field ( i : uint , inner : * TyDesc ) -> bool {
476
+ match self . var_stk . last ( ) {
477
+ Degenerate | TagMatch => {
478
+ if i != 0 {
479
+ self . writer . write_str ( ", " ) ;
480
+ }
481
+ if ! self . visit_inner ( inner) {
482
+ return false ;
483
+ }
484
+ }
485
+ TagMismatch => ( )
486
+ }
487
+ true
415
488
}
416
489
fn visit_leave_enum_variant ( _variant : uint ,
417
490
_disr_val : int ,
418
- _n_fields : uint ,
419
- _name : & str ) -> bool { true }
491
+ n_fields : uint ,
492
+ _name : & str ) -> bool {
493
+ match self . var_stk . last ( ) {
494
+ Degenerate | TagMatch => {
495
+ if n_fields > 0 {
496
+ self . writer . write_char ( ')' ) ;
497
+ }
498
+ }
499
+ TagMismatch => ( )
500
+ }
501
+ true
502
+ }
420
503
fn visit_leave_enum ( _n_variants : uint ,
421
- _sz : uint , _align : uint ) -> bool { true }
504
+ _sz : uint , _align : uint ) -> bool {
505
+ self . var_stk . pop ( ) ;
506
+ true
507
+ }
422
508
423
509
fn visit_enter_fn ( _purity : uint , _proto : uint ,
424
510
_n_inputs : uint , _retstyle : uint ) -> bool { true }
0 commit comments