Refactor reflect.rs, begin visiting type substructures.

This commit is contained in:
Graydon Hoare 2012-06-07 13:51:35 -07:00
parent a494cc1598
commit 9ee0137018
3 changed files with 160 additions and 78 deletions

View File

@ -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"]

View File

@ -10,44 +10,101 @@ 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", []) }
ty::ty_vec(mt) {
let bcx = step(bcx, "visit_vec_of",
[C_uint(ccx, mt.mutbl as uint)]);
sub(bcx, mt.ty)
fn c_uint(u: uint) -> ValueRef {
C_uint(self.bcx.ccx(), u)
}
_ {
// 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(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);
}
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;
}

View File

@ -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::<int>(vv);
intrinsic::visit_ty::<i8>(vv);
intrinsic::visit_ty::<i16>(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", "]"];
}