diff --git a/src/libcore/reflect.rs b/src/libcore/reflect.rs index 28c6031263b..268d5e1baa6 100644 --- a/src/libcore/reflect.rs +++ b/src/libcore/reflect.rs @@ -28,6 +28,8 @@ use libc::c_void; */ pub trait MovePtr { fn move_ptr(adjustment: fn(*c_void) -> *c_void); + fn push_ptr(); + fn pop_ptr(); } /// Helper function for alignment calculation. @@ -402,6 +404,7 @@ impl MovePtrAdaptor: TyVisitor { disr_val: int, n_fields: uint, name: &str) -> bool { + self.inner.push_ptr(); if ! self.inner.visit_enter_enum_variant(variant, disr_val, n_fields, name) { return false; @@ -410,7 +413,9 @@ impl MovePtrAdaptor: TyVisitor { } fn visit_enum_variant_field(i: uint, inner: *TyDesc) -> bool { + unsafe { self.align((*inner).align); } if ! self.inner.visit_enum_variant_field(i, inner) { return false; } + unsafe { self.bump((*inner).size); } true } @@ -422,6 +427,7 @@ impl MovePtrAdaptor: TyVisitor { n_fields, name) { return false; } + self.inner.pop_ptr(); true } @@ -429,6 +435,7 @@ impl MovePtrAdaptor: TyVisitor { if ! self.inner.visit_leave_enum(n_variants, sz, align) { return false; } + self.bump(sz); true } diff --git a/src/libcore/repr.rs b/src/libcore/repr.rs index d3ed4f31515..111070e5b24 100644 --- a/src/libcore/repr.rs +++ b/src/libcore/repr.rs @@ -26,6 +26,7 @@ use reflect::{MovePtr, MovePtrAdaptor, align}; use vec::UnboxedVecRepr; use vec::raw::{VecRepr, SliceRepr}; pub use managed::raw::BoxRepr; +use dvec::DVec; /// Helpers @@ -121,12 +122,23 @@ impl char : Repr { // New implementation using reflect::MovePtr +enum VariantState { + Degenerate, + TagMatch, + TagMismatch, +} + pub struct ReprVisitor { mut ptr: *c_void, + ptr_stk: DVec<*c_void>, + var_stk: DVec, writer: @Writer } pub fn ReprVisitor(ptr: *c_void, writer: @Writer) -> ReprVisitor { - ReprVisitor { ptr: ptr, writer: writer } + ReprVisitor { ptr: ptr, + ptr_stk: DVec(), + var_stk: DVec(), + writer: writer } } impl ReprVisitor : MovePtr { @@ -134,6 +146,12 @@ impl ReprVisitor : MovePtr { fn move_ptr(adjustment: fn(*c_void) -> *c_void) { self.ptr = adjustment(self.ptr); } + fn push_ptr() { + self.ptr_stk.push(self.ptr); + } + fn pop_ptr() { + self.ptr = self.ptr_stk.pop(); + } } impl ReprVisitor { @@ -148,6 +166,18 @@ impl ReprVisitor { true } + #[inline(always)] + fn bump(sz: uint) { + do self.move_ptr() |p| { + ((p as uint) + sz) as *c_void + }; + } + + #[inline(always)] + fn bump_past() { + self.bump(sys::size_of::()); + } + #[inline(always)] fn visit_inner(inner: *TyDesc) -> bool { self.visit_ptr_inner(self.ptr, inner) @@ -402,23 +432,79 @@ impl ReprVisitor : TyVisitor { true } - fn visit_enter_enum(_n_variants: uint, + fn visit_enter_enum(n_variants: uint, _sz: uint, _align: uint) -> bool { + if n_variants == 1 { + self.var_stk.push(Degenerate) + } else { + self.var_stk.push(TagMatch) + } true } fn visit_enter_enum_variant(_variant: uint, - _disr_val: int, - _n_fields: uint, - _name: &str) -> bool { true } - fn visit_enum_variant_field(_i: uint, inner: *TyDesc) -> bool { - self.visit_inner(inner) + disr_val: int, + n_fields: uint, + name: &str) -> bool { + let mut write = false; + match self.var_stk.pop() { + Degenerate => { + write = true; + self.var_stk.push(Degenerate); + } + TagMatch | TagMismatch => { + do self.get::() |t| { + if disr_val == *t { + write = true; + self.var_stk.push(TagMatch); + } else { + self.var_stk.push(TagMismatch); + } + }; + self.bump_past::(); + } + } + + if write { + self.writer.write_str(name); + if n_fields > 0 { + self.writer.write_char('('); + } + } + true + } + fn visit_enum_variant_field(i: uint, inner: *TyDesc) -> bool { + match self.var_stk.last() { + Degenerate | TagMatch => { + if i != 0 { + self.writer.write_str(", "); + } + if ! self.visit_inner(inner) { + return false; + } + } + TagMismatch => () + } + true } fn visit_leave_enum_variant(_variant: uint, _disr_val: int, - _n_fields: uint, - _name: &str) -> bool { true } + n_fields: uint, + _name: &str) -> bool { + match self.var_stk.last() { + Degenerate | TagMatch => { + if n_fields > 0 { + self.writer.write_char(')'); + } + } + TagMismatch => () + } + true + } fn visit_leave_enum(_n_variants: uint, - _sz: uint, _align: uint) -> bool { true } + _sz: uint, _align: uint) -> bool { + self.var_stk.pop(); + true + } fn visit_enter_fn(_purity: uint, _proto: uint, _n_inputs: uint, _retstyle: uint) -> bool { true }