core: fix remaining repr bugs, r=burningtree.

This commit is contained in:
Graydon Hoare 2012-12-18 14:35:08 -08:00
parent b46e25bdc8
commit 6d4fbd4f9e
2 changed files with 103 additions and 10 deletions

View File

@ -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<V: TyVisitor MovePtr> MovePtrAdaptor<V>: 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<V: TyVisitor MovePtr> MovePtrAdaptor<V>: 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<V: TyVisitor MovePtr> MovePtrAdaptor<V>: TyVisitor {
n_fields, name) {
return false;
}
self.inner.pop_ptr();
true
}
@ -429,6 +435,7 @@ impl<V: TyVisitor MovePtr> MovePtrAdaptor<V>: TyVisitor {
if ! self.inner.visit_leave_enum(n_variants, sz, align) {
return false;
}
self.bump(sz);
true
}

View File

@ -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<VariantState>,
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<T>() {
self.bump(sys::size_of::<T>());
}
#[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::<int>() |t| {
if disr_val == *t {
write = true;
self.var_stk.push(TagMatch);
} else {
self.var_stk.push(TagMismatch);
}
};
self.bump_past::<int>();
}
}
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 }