libcore: Make enum logging significantly less clownshoes.

Fixes the log-knows-the-names* tests.
This commit is contained in:
Patrick Walton 2012-09-14 11:21:16 -07:00
parent 127c0d40ac
commit bbfc6f8945

View File

@ -118,12 +118,29 @@ impl char : Repr {
fn write_repr(writer: @Writer) { writer.write_char(self); } fn write_repr(writer: @Writer) { writer.write_char(self); }
} }
enum EnumVisitState {
PreVariant, // We're before the variant we're interested in.
InVariant, // We're inside the variant we're interested in.
PostVariant // We're after the variant we're interested in.
}
impl EnumVisitState : cmp::Eq {
pure fn eq(&&other: EnumVisitState) -> bool {
(self as uint) == (other as uint)
}
pure fn ne(&&other: EnumVisitState) -> bool { !self.eq(other) }
}
struct EnumState {
end_ptr: *c_void,
state: EnumVisitState
}
/// XXX: This should not use a boxed writer! /// XXX: This should not use a boxed writer!
struct ReprPrinter { struct ReprPrinter {
mut ptr: *c_void, mut ptr: *c_void,
writer: @Writer, // XXX: This should not use a boxed trait. writer: @Writer, // XXX: This should not use a boxed trait.
mut skip: bool, enum_stack: DVec<EnumState>
enum_stack: DVec<*c_void>
} }
/// FIXME (issue #3462): This is horrible. /// FIXME (issue #3462): This is horrible.
@ -467,8 +484,9 @@ impl ReprPrinterWrapper : TyVisitor {
self.printer.align(align); self.printer.align(align);
// Write in the location of the end of this enum. // Write in the location of the end of this enum.
let new_pos = self.printer.ptr as uint + sz; let end_ptr = transmute(self.printer.ptr as uint + sz);
self.printer.enum_stack.push(transmute(new_pos)); let new_state = EnumState { end_ptr: end_ptr, state: PreVariant };
self.printer.enum_stack.push(new_state);
true true
} }
@ -479,20 +497,26 @@ impl ReprPrinterWrapper : TyVisitor {
_n_fields: uint, _n_fields: uint,
name: &str) -> bool { name: &str) -> bool {
unsafe { unsafe {
let disr_ptr = self.printer.ptr as *int; let stack = &self.printer.enum_stack;
if *disr_ptr == disr_val { let mut enum_state = stack.last();
self.printer.skip = false; // Don't skip this variant. match enum_state.state {
self.printer.writer.write_str(name); PreVariant => {
self.printer.bump(sys::size_of::<int>()); let disr_ptr = self.printer.ptr as *int;
} else { if *disr_ptr == disr_val {
self.printer.skip = true; // Skip this variant. enum_state.state = InVariant;
self.printer.writer.write_str(name);
self.printer.bump(sys::size_of::<int>());
stack.set_elt(stack.len() - 1, enum_state);
}
}
InVariant | PostVariant => {}
} }
true true
} }
} }
fn visit_enum_variant_field(i: uint, inner: *TyDesc) -> bool { fn visit_enum_variant_field(i: uint, inner: *TyDesc) -> bool {
if !self.printer.skip { if self.printer.enum_stack.last().state == InVariant {
if i == 0 { if i == 0 {
self.printer.writer.write_char('('); self.printer.writer.write_char('(');
} else { } else {
@ -508,14 +532,21 @@ impl ReprPrinterWrapper : TyVisitor {
_disr_val: int, _disr_val: int,
n_fields: uint, n_fields: uint,
_name: &str) -> bool { _name: &str) -> bool {
if !self.printer.skip && n_fields >= 1 { let stack = &self.printer.enum_stack;
self.printer.writer.write_char(')'); let mut enum_state = stack.last();
match enum_state.state {
InVariant => {
if n_fields >= 1 { self.printer.writer.write_char(')'); }
enum_state.state = PostVariant;
stack.set_elt(stack.len() - 1, enum_state);
}
PreVariant | PostVariant => {}
} }
true true
} }
fn visit_leave_enum(_n_variants: uint, _sz: uint, _align: uint) -> bool { fn visit_leave_enum(_n_variants: uint, _sz: uint, _align: uint) -> bool {
self.printer.ptr = self.printer.enum_stack.pop(); self.printer.ptr = self.printer.enum_stack.pop().end_ptr;
true true
} }
@ -564,7 +595,6 @@ pub fn write_repr<T>(writer: @Writer, object: &T) {
let repr_printer = @ReprPrinter { let repr_printer = @ReprPrinter {
ptr: ptr, ptr: ptr,
writer: writer, writer: writer,
skip: false,
enum_stack: DVec() enum_stack: DVec()
}; };