From 56c6c65186ef37ef1592515f5f7b0062acb49153 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Fri, 8 Jun 2012 19:00:51 -0700 Subject: [PATCH] Add preliminary test of walking data pointers via reflection. --- src/test/run-pass/reflect-visit-data.rs | 303 ++++++++++++++++++++++++ 1 file changed, 303 insertions(+) create mode 100644 src/test/run-pass/reflect-visit-data.rs diff --git a/src/test/run-pass/reflect-visit-data.rs b/src/test/run-pass/reflect-visit-data.rs new file mode 100644 index 000000000000..dc5b6ea60e84 --- /dev/null +++ b/src/test/run-pass/reflect-visit-data.rs @@ -0,0 +1,303 @@ +import libc::c_void; + +iface data_cursor { + fn set_ptr(p: *c_void); + fn get_ptr() -> *c_void; +} + +enum my_visitor = @{ + mut ptr: *c_void, + mut vals: [str] +}; + +impl methods for my_visitor { + fn get(f: fn(T)) { + unsafe { + f(*(self.ptr as *T)); + } + } +} + +impl of data_cursor for my_visitor { + fn set_ptr(p: *c_void) { self.ptr = p; } + fn get_ptr() -> *c_void { self.ptr } +} + +impl of intrinsic::ty_visitor for my_visitor { + + fn visit_bot() -> bool { true } + fn visit_nil() -> bool { true } + fn visit_bool() -> bool { + self.get::() {|b| + self.vals += [bool::to_str(b)]; + } + true + } + fn visit_int() -> bool { + self.get::() {|i| + self.vals += [int::to_str(i, 10u)]; + } + true + } + fn visit_i8() -> bool { true } + fn visit_i16() -> bool { true } + fn visit_i32() -> bool { true } + fn visit_i64() -> bool { true } + + fn visit_uint() -> bool { true } + fn visit_u8() -> bool { true } + fn visit_u16() -> bool { true } + fn visit_u32() -> bool { true } + fn visit_u64() -> bool { true } + + fn visit_float() -> bool { true } + fn visit_f32() -> bool { true } + fn visit_f64() -> bool { true } + + fn visit_char() -> bool { true } + fn visit_str() -> bool { true } + + fn visit_estr_box() -> bool { true } + fn visit_estr_uniq() -> bool { true } + fn visit_estr_slice() -> bool { true } + fn visit_estr_fixed(_sz: uint) -> bool { true } + + fn visit_enter_box(_mtbl: uint) -> bool { true } + fn visit_leave_box(_mtbl: uint) -> bool { true } + fn visit_enter_uniq(_mtbl: uint) -> bool { true } + fn visit_leave_uniq(_mtbl: uint) -> bool { true } + fn visit_enter_ptr(_mtbl: uint) -> bool { true } + fn visit_leave_ptr(_mtbl: uint) -> bool { true } + fn visit_enter_rptr(_mtbl: uint) -> bool { true } + fn visit_leave_rptr(_mtbl: uint) -> bool { true } + + fn visit_enter_vec(_mtbl: uint) -> bool { true } + fn visit_leave_vec(_mtbl: uint) -> bool { true } + fn visit_enter_evec_box(_mtbl: uint) -> bool { true } + fn visit_leave_evec_box(_mtbl: uint) -> bool { true } + fn visit_enter_evec_uniq(_mtbl: uint) -> bool { true } + fn visit_leave_evec_uniq(_mtbl: uint) -> bool { true } + fn visit_enter_evec_slice(_mtbl: uint) -> bool { true } + fn visit_leave_evec_slice(_mtbl: uint) -> bool { true } + fn visit_enter_evec_fixed(_mtbl: uint, _sz: uint) -> bool { true } + fn visit_leave_evec_fixed(_mtbl: uint, _sz: uint) -> bool { true } + + fn visit_enter_rec(_n_fields: uint) -> bool { true } + fn visit_enter_rec_field(_mtbl: uint, _i: uint, + _name: str/&) -> bool { true } + fn visit_leave_rec_field(_mtbl: uint, _i: uint, + _name: str/&) -> bool { true } + fn visit_leave_rec(_n_fields: uint) -> bool { true } + + fn visit_enter_class(_n_fields: uint) -> bool { true } + fn visit_enter_class_field(_mtbl: uint, _i: uint, + _name: str/&) -> bool { true } + fn visit_leave_class_field(_mtbl: uint, _i: uint, + _name: str/&) -> bool { true } + fn visit_leave_class(_n_fields: uint) -> bool { true } + + fn visit_enter_tup(_n_fields: uint) -> bool { true } + fn visit_enter_tup_field(_i: uint) -> bool { true } + fn visit_leave_tup_field(_i: uint) -> bool { true } + fn visit_leave_tup(_n_fields: uint) -> bool { true } + + fn visit_enter_fn(_purity: uint, _proto: uint, + _n_inputs: uint, _retstyle: uint) -> bool { true } + fn visit_enter_fn_input(_i: uint, _mode: uint) -> bool { true } + fn visit_leave_fn_input(_i: uint, _mode: uint) -> bool { true } + fn visit_enter_fn_output(_retstyle: uint) -> bool { true } + fn visit_leave_fn_output(_retstyle: uint) -> bool { true } + fn visit_leave_fn(_purity: uint, _proto: uint, + _n_inputs: uint, _retstyle: uint) -> bool { true } + + fn visit_enter_enum(_n_variants: uint) -> bool { true } + fn visit_enter_enum_variant(_variant: uint, + _disr_val: int, + _n_fields: uint, + _name: str/&) -> bool { true } + fn visit_enter_enum_variant_field(_i: uint) -> bool { true } + fn visit_leave_enum_variant_field(_i: uint) -> bool { true } + fn visit_leave_enum_variant(_variant: uint, + _disr_val: int, + _n_fields: uint, + _name: str/&) -> bool { true } + fn visit_leave_enum(_n_variants: uint) -> bool { true } + + fn visit_iface() -> bool { true } + fn visit_enter_res() -> bool { true } + fn visit_leave_res() -> bool { true } + fn visit_var() -> bool { true } + fn visit_var_integral() -> bool { true } + fn visit_param(_i: uint) -> bool { true } + fn visit_self() -> bool { true } + fn visit_type() -> bool { true } + fn visit_opaque_box() -> bool { true } + fn visit_enter_constr() -> bool { true } + fn visit_leave_constr() -> bool { true } + fn visit_closure_ptr(_ck: uint) -> bool { true } +} + +enum data_visitor = { + inner: V +}; + +fn align_to(size: uint, align: uint) -> uint { + ((size + align) - 1u) & !(align - 1u) +} + +impl dv of + intrinsic::ty_visitor for data_visitor { + + fn move_ptr(f: fn(*c_void) -> *c_void) { + self.inner.set_ptr(f(self.inner.get_ptr())); + } + + fn bump(sz: uint) { + self.move_ptr() {|p| + ((p as uint) + sz) as *c_void + } + } + + fn align_to() { + self.move_ptr() {|p| + align_to::(p as uint, + sys::min_align_of::()) as *c_void + } + } + + fn bump_past() { + self.bump(sys::size_of::()); + } + + fn visit_bot() -> bool { + self.align_to::(); + self.inner.visit_bot(); + self.bump_past::(); + true + } + fn visit_nil() -> bool { true } + fn visit_bool() -> bool { + self.align_to::(); + self.inner.visit_bool(); + self.bump_past::(); + true + } + fn visit_int() -> bool { + self.align_to::(); + self.inner.visit_int(); + self.bump_past::(); + true + } + fn visit_i8() -> bool { true } + fn visit_i16() -> bool { true } + fn visit_i32() -> bool { true } + fn visit_i64() -> bool { true } + + fn visit_uint() -> bool { true } + fn visit_u8() -> bool { true } + fn visit_u16() -> bool { true } + fn visit_u32() -> bool { true } + fn visit_u64() -> bool { true } + + fn visit_float() -> bool { true } + fn visit_f32() -> bool { true } + fn visit_f64() -> bool { true } + + fn visit_char() -> bool { true } + fn visit_str() -> bool { true } + + fn visit_estr_box() -> bool { true } + fn visit_estr_uniq() -> bool { true } + fn visit_estr_slice() -> bool { true } + fn visit_estr_fixed(_sz: uint) -> bool { true } + + fn visit_enter_box(_mtbl: uint) -> bool { true } + fn visit_leave_box(_mtbl: uint) -> bool { true } + fn visit_enter_uniq(_mtbl: uint) -> bool { true } + fn visit_leave_uniq(_mtbl: uint) -> bool { true } + fn visit_enter_ptr(_mtbl: uint) -> bool { true } + fn visit_leave_ptr(_mtbl: uint) -> bool { true } + fn visit_enter_rptr(_mtbl: uint) -> bool { true } + fn visit_leave_rptr(_mtbl: uint) -> bool { true } + + fn visit_enter_vec(_mtbl: uint) -> bool { true } + fn visit_leave_vec(_mtbl: uint) -> bool { true } + fn visit_enter_evec_box(_mtbl: uint) -> bool { true } + fn visit_leave_evec_box(_mtbl: uint) -> bool { true } + fn visit_enter_evec_uniq(_mtbl: uint) -> bool { true } + fn visit_leave_evec_uniq(_mtbl: uint) -> bool { true } + fn visit_enter_evec_slice(_mtbl: uint) -> bool { true } + fn visit_leave_evec_slice(_mtbl: uint) -> bool { true } + fn visit_enter_evec_fixed(_mtbl: uint, _sz: uint) -> bool { true } + fn visit_leave_evec_fixed(_mtbl: uint, _sz: uint) -> bool { true } + + fn visit_enter_rec(_n_fields: uint) -> bool { true } + fn visit_enter_rec_field(_mtbl: uint, _i: uint, + _name: str/&) -> bool { true } + fn visit_leave_rec_field(_mtbl: uint, _i: uint, + _name: str/&) -> bool { true } + fn visit_leave_rec(_n_fields: uint) -> bool { true } + + fn visit_enter_class(_n_fields: uint) -> bool { true } + fn visit_enter_class_field(_mtbl: uint, _i: uint, + _name: str/&) -> bool { true } + fn visit_leave_class_field(_mtbl: uint, _i: uint, + _name: str/&) -> bool { true } + fn visit_leave_class(_n_fields: uint) -> bool { true } + + fn visit_enter_tup(_n_fields: uint) -> bool { true } + fn visit_enter_tup_field(_i: uint) -> bool { true } + fn visit_leave_tup_field(_i: uint) -> bool { true } + fn visit_leave_tup(_n_fields: uint) -> bool { true } + + fn visit_enter_fn(_purity: uint, _proto: uint, + _n_inputs: uint, _retstyle: uint) -> bool { true } + fn visit_enter_fn_input(_i: uint, _mode: uint) -> bool { true } + fn visit_leave_fn_input(_i: uint, _mode: uint) -> bool { true } + fn visit_enter_fn_output(_retstyle: uint) -> bool { true } + fn visit_leave_fn_output(_retstyle: uint) -> bool { true } + fn visit_leave_fn(_purity: uint, _proto: uint, + _n_inputs: uint, _retstyle: uint) -> bool { true } + + fn visit_enter_enum(_n_variants: uint) -> bool { true } + fn visit_enter_enum_variant(_variant: uint, + _disr_val: int, + _n_fields: uint, + _name: str/&) -> bool { true } + fn visit_enter_enum_variant_field(_i: uint) -> bool { true } + fn visit_leave_enum_variant_field(_i: uint) -> bool { true } + fn visit_leave_enum_variant(_variant: uint, + _disr_val: int, + _n_fields: uint, + _name: str/&) -> bool { true } + fn visit_leave_enum(_n_variants: uint) -> bool { true } + + fn visit_iface() -> bool { true } + fn visit_enter_res() -> bool { true } + fn visit_leave_res() -> bool { true } + fn visit_var() -> bool { true } + fn visit_var_integral() -> bool { true } + fn visit_param(_i: uint) -> bool { true } + fn visit_self() -> bool { true } + fn visit_type() -> bool { true } + fn visit_opaque_box() -> bool { true } + fn visit_enter_constr() -> bool { true } + fn visit_leave_constr() -> bool { true } + fn visit_closure_ptr(_ck: uint) -> bool { true } +} + +fn main() { + let r = (1,2,3,true,false); + let p = ptr::addr_of(r) as *c_void; + let u = my_visitor(@{mut ptr: p, + mut vals: []}); + let v = data_visitor({inner: u}); + let vv = v as intrinsic::ty_visitor; + intrinsic::visit_ty::<(int,int,int,bool,bool)>(vv); + + for u.vals.each {|s| + io::println(#fmt("val: %s", s)); + } + assert u.vals == ["1", "2", "3", "true", "false"]; + + }