From 9ee0137018f6e0a20b07e4192be703d0864e6b13 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Thu, 7 Jun 2012 13:51:35 -0700 Subject: [PATCH] Refactor reflect.rs, begin visiting type substructures. --- src/rustc/front/intrinsic.rs | 38 +++--- src/rustc/middle/trans/reflect.rs | 153 ++++++++++++++++-------- src/test/run-pass/reflect-visit-type.rs | 47 ++++++-- 3 files changed, 160 insertions(+), 78 deletions(-) diff --git a/src/rustc/front/intrinsic.rs b/src/rustc/front/intrinsic.rs index 45c47982b2f..4f24f9dccf2 100644 --- a/src/rustc/front/intrinsic.rs +++ b/src/rustc/front/intrinsic.rs @@ -30,20 +30,30 @@ mod intrinsic { fn visit_char() -> bool; fn visit_str() -> bool; - // FIXME: possibly pair these as enter/leave calls - // not just enter with implicit number of subsequent - // calls. (#2402) - fn visit_vec_of(mutbl: uint) -> bool; - fn visit_box_of(mutbl: uint) -> bool; - fn visit_uniq_of(mutbl: uint) -> bool; - fn visit_ptr_of(mutbl: uint) -> bool; - fn visit_rptr_of(mutbl: uint) -> bool; - fn visit_rec_of(n_fields: uint) -> bool; - fn visit_rec_field(name: str/&, mutbl: uint) -> bool; - fn visit_tup_of(n_fields: uint) -> bool; - fn visit_tup_field(mutbl: uint) -> bool; - fn visit_enum_of(n_variants: uint) -> bool; - fn visit_enum_variant(name: str/&) -> bool; + fn visit_estr_box() -> bool; + fn visit_estr_uniq() -> bool; + fn visit_estr_slice() -> bool; + fn visit_estr_fixed(sz: uint) -> bool; + + fn visit_enter_box(mtbl: uint) -> bool; + fn visit_leave_box(mtbl: uint) -> bool; + fn visit_enter_uniq(mtbl: uint) -> bool; + fn visit_leave_uniq(mtbl: uint) -> bool; + fn visit_enter_ptr(mtbl: uint) -> bool; + fn visit_leave_ptr(mtbl: uint) -> bool; + fn visit_enter_rptr(mtbl: uint) -> bool; + fn visit_leave_rptr(mtbl: uint) -> bool; + + fn visit_enter_vec(mtbl: uint) -> bool; + fn visit_leave_vec(mtbl: uint) -> bool; + fn visit_enter_evec_box(mtbl: uint) -> bool; + fn visit_leave_evec_box(mtbl: uint) -> bool; + fn visit_enter_evec_uniq(mtbl: uint) -> bool; + fn visit_leave_evec_uniq(mtbl: uint) -> bool; + fn visit_enter_evec_slice(mtbl: uint) -> bool; + fn visit_leave_evec_slice(mtbl: uint) -> bool; + fn visit_enter_evec_fixed(mtbl: uint, sz: uint) -> bool; + fn visit_leave_evec_fixed(mtbl: uint, sz: uint) -> bool; } #[abi = "rust-intrinsic"] diff --git a/src/rustc/middle/trans/reflect.rs b/src/rustc/middle/trans/reflect.rs index 09c5ebbf96a..cf929353ab4 100644 --- a/src/rustc/middle/trans/reflect.rs +++ b/src/rustc/middle/trans/reflect.rs @@ -10,45 +10,102 @@ import type_of::*; import ast::def_id; import util::ppaux::ty_to_str; -fn visit_ty_steps(bcx: block, t: ty::t, - step: fn(bcx: block, - tyname: str, - args: [ValueRef]) -> block, - sub: fn(bcx: block, t: ty::t) -> block) -> block { +enum reflector = { + visitor_val: ValueRef, + visitor_methods: @[ty::method], + mut bcx: block +}; - let ccx = bcx.ccx(); +impl methods for reflector { - alt ty::get(t).struct { - ty::ty_bot { step(bcx, "visit_bot", []) } - ty::ty_nil { step(bcx, "visit_nil", []) } - ty::ty_bool { step(bcx, "visit_bool", []) } - ty::ty_int(ast::ty_i) { step(bcx, "visit_int", []) } - ty::ty_int(ast::ty_char) { step(bcx, "visit_char", []) } - ty::ty_int(ast::ty_i8) { step(bcx, "visit_i8", []) } - ty::ty_int(ast::ty_i16) { step(bcx, "visit_i16", []) } - ty::ty_int(ast::ty_i32) { step(bcx, "visit_i32", []) } - ty::ty_int(ast::ty_i64) { step(bcx, "visit_i64", []) } - ty::ty_uint(ast::ty_u) { step(bcx, "visit_uint", []) } - ty::ty_uint(ast::ty_u8) { step(bcx, "visit_u8", []) } - ty::ty_uint(ast::ty_u16) { step(bcx, "visit_u16", []) } - ty::ty_uint(ast::ty_u32) { step(bcx, "visit_u32", []) } - ty::ty_uint(ast::ty_u64) { step(bcx, "visit_u64", []) } - ty::ty_float(ast::ty_f) { step(bcx, "visit_float", []) } - ty::ty_float(ast::ty_f32) { step(bcx, "visit_f32", []) } - ty::ty_float(ast::ty_f64) { step(bcx, "visit_f64", []) } - ty::ty_str { step(bcx, "visit_str", []) } + fn c_uint(u: uint) -> ValueRef { + C_uint(self.bcx.ccx(), u) + } - ty::ty_vec(mt) { - let bcx = step(bcx, "visit_vec_of", - [C_uint(ccx, mt.mutbl as uint)]); - sub(bcx, mt.ty) - } + fn visit(ty_name: str, args: [ValueRef]) { + let tcx = self.bcx.tcx(); + let mth_idx = option::get(ty::method_idx("visit_" + ty_name, + *self.visitor_methods)); + let mth_ty = ty::mk_fn(tcx, self.visitor_methods[mth_idx].fty); + let v = self.visitor_val; + let get_lval = {|bcx| + impl::trans_iface_callee(bcx, v, mth_ty, mth_idx) + }; + self.bcx = + trans_call_inner(self.bcx, none, mth_ty, ty::mk_bool(tcx), + get_lval, arg_vals(args), ignore); + } - _ { - // Ideally this would be an unimpl, but sadly we have - // to pretend we can visit everything at this point. - step(bcx, "visit_bot", []) - } + fn visit_tydesc(t: ty::t) { + self.bcx = + call_tydesc_glue(self.bcx, self.visitor_val, t, + abi::tydesc_field_visit_glue); + } + + fn bracketed_mt(bracket_name: str, mt: ty::mt, extra: [ValueRef]) { + self.visit("enter_" + bracket_name, + [self.c_uint(mt.mutbl as uint)] + extra); + self.visit_tydesc(mt.ty); + self.visit("leave_" + bracket_name, + [self.c_uint(mt.mutbl as uint)] + extra); + } + + fn vstore_name_and_extra(vstore: ty::vstore, + f: fn(str,[ValueRef])) { + alt vstore { + ty::vstore_fixed(n) { f("fixed", [self.c_uint(n)]) } + ty::vstore_slice(_) { f("slice", []) } + ty::vstore_uniq { f("uniq", []);} + ty::vstore_box { f("box", []); } + } + } + + fn leaf(name: str) { + self.visit(name, []); + } + + // Entrypoint + fn visit_ty(t: ty::t) { + + alt ty::get(t).struct { + ty::ty_bot { self.leaf("bot") } + ty::ty_nil { self.leaf("nil") } + ty::ty_bool { self.leaf("bool") } + ty::ty_int(ast::ty_i) { self.leaf("int") } + ty::ty_int(ast::ty_char) { self.leaf("char") } + ty::ty_int(ast::ty_i8) { self.leaf("i8") } + ty::ty_int(ast::ty_i16) { self.leaf("i16") } + ty::ty_int(ast::ty_i32) { self.leaf("i32") } + ty::ty_int(ast::ty_i64) { self.leaf("i64") } + ty::ty_uint(ast::ty_u) { self.leaf("uint") } + ty::ty_uint(ast::ty_u8) { self.leaf("u8") } + ty::ty_uint(ast::ty_u16) { self.leaf("u16") } + ty::ty_uint(ast::ty_u32) { self.leaf("u32") } + ty::ty_uint(ast::ty_u64) { self.leaf("u64") } + ty::ty_float(ast::ty_f) { self.leaf("float") } + ty::ty_float(ast::ty_f32) { self.leaf("f32") } + ty::ty_float(ast::ty_f64) { self.leaf("f64") } + ty::ty_str { self.leaf("str") } + + ty::ty_vec(mt) { self.bracketed_mt("vec", mt, []) } + ty::ty_estr(vst) { + self.vstore_name_and_extra(vst) {|name, extra| + self.visit("estr_" + name, extra) + } + } + ty::ty_evec(mt, vst) { + self.vstore_name_and_extra(vst) {|name, extra| + self.bracketed_mt("evec_" + name, mt, extra) + } + } + ty::ty_box(mt) { self.bracketed_mt("box", mt, []) } + ty::ty_uniq(mt) { self.bracketed_mt("uniq", mt, []) } + ty::ty_ptr(mt) { self.bracketed_mt("ptr", mt, []) } + ty::ty_rptr(_, mt) { self.bracketed_mt("rptr", mt, []) } + + // FIXME: finish these. + _ { self.visit("bot", []) } + } } } @@ -56,21 +113,13 @@ fn visit_ty_steps(bcx: block, t: ty::t, fn emit_calls_to_iface_visit_ty(bcx: block, t: ty::t, visitor_val: ValueRef, visitor_iid: def_id) -> block { - let tcx = bcx.tcx(); - let methods = ty::iface_methods(tcx, visitor_iid); - visit_ty_steps(bcx, t, - {|bcx, mth_name, args| - let mth_idx = option::get(ty::method_idx(mth_name, - *methods)); - let mth_ty = ty::mk_fn(tcx, methods[mth_idx].fty); - let get_lval = {|bcx| - impl::trans_iface_callee(bcx, visitor_val, - mth_ty, mth_idx) - }; - trans_call_inner(bcx, none, mth_ty, ty::mk_bool(tcx), - get_lval, arg_vals(args), ignore) - }, - {|bcx, t_sub| - call_tydesc_glue(bcx, visitor_val, t_sub, - abi::tydesc_field_visit_glue)}) + + let r = reflector({ + visitor_val: visitor_val, + visitor_methods: ty::iface_methods(bcx.tcx(), visitor_iid), + mut bcx: bcx + }); + + r.visit_ty(t); + ret r.bcx; } diff --git a/src/test/run-pass/reflect-visit-type.rs b/src/test/run-pass/reflect-visit-type.rs index 4b92e518b2e..7cd373756f7 100644 --- a/src/test/run-pass/reflect-visit-type.rs +++ b/src/test/run-pass/reflect-visit-type.rs @@ -47,17 +47,38 @@ impl of intrinsic::ty_visitor for my_visitor { fn visit_char() -> bool { true } fn visit_str() -> bool { true } - fn visit_vec_of(_mutbl: uint) -> bool { true } - fn visit_box_of(_mutbl: uint) -> bool { true } - fn visit_uniq_of(_mutbl: uint) -> bool { true } - fn visit_ptr_of(_mutbl: uint) -> bool { true } - fn visit_rptr_of(_mutbl: uint) -> bool { true } - fn visit_rec_of(_n_fields: uint) -> bool { true } - fn visit_rec_field(_name: str/&, _mutbl: uint) -> bool { true } - fn visit_tup_of(_n_fields: uint) -> bool { true } - fn visit_tup_field(_mutbl: uint) -> bool { true } - fn visit_enum_of(_n_variants: uint) -> bool { true } - fn visit_enum_variant(_name: 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 { + self.types += ["["]; + #error("visited enter-vec"); + true + } + fn visit_leave_vec(_mtbl: uint) -> bool { + self.types += ["]"]; + #error("visited leave-vec"); + 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 main() { @@ -68,9 +89,11 @@ fn main() { intrinsic::visit_ty::(vv); intrinsic::visit_ty::(vv); intrinsic::visit_ty::(vv); + intrinsic::visit_ty::<[int]>(vv); for v.types.each {|s| io::println(#fmt("type: %s", s)); } - assert v.types == ["bool", "int", "i8", "i16"]; + assert v.types == ["bool", "int", "i8", "i16", + "[", "int", "]"]; }