Visit the substructure for classes and enums as well.

This commit is contained in:
Graydon Hoare 2012-06-08 15:35:55 -07:00
parent b8af02e219
commit d182c14247
3 changed files with 85 additions and 8 deletions

View File

@ -62,11 +62,29 @@ mod intrinsic {
/*, name: str/& */) -> bool;
fn visit_leave_rec(n_fields: uint) -> bool;
fn visit_enter_class(n_fields: uint) -> bool;
fn visit_enter_class_field(mtbl: uint, i: uint
/*, name: str/& */) -> bool;
fn visit_leave_class_field(mtbl: uint, i: uint
/*, name: str/& */) -> bool;
fn visit_leave_class(n_fields: uint) -> bool;
fn visit_enter_tup(n_fields: uint) -> bool;
fn visit_enter_tup_field(i: uint) -> bool;
fn visit_leave_tup_field(i: uint) -> bool;
fn visit_leave_tup(n_fields: uint) -> bool;
fn visit_enter_enum(n_variants: uint) -> bool;
fn visit_enter_enum_variant(variant: uint,
disr_val: int,
n_fields: uint) -> bool;
fn visit_enter_enum_variant_field(i: uint) -> bool;
fn visit_leave_enum_variant_field(i: uint) -> bool;
fn visit_leave_enum_variant(variant: uint,
disr_val: int,
n_fields: uint) -> bool;
fn visit_leave_enum(n_variants: uint) -> bool;
fn visit_enter_fn(purity: uint, proto: uint,
n_inputs: uint, retstyle: uint) -> bool;
fn visit_enter_fn_input(i: uint, mode: uint) -> bool;
@ -76,9 +94,6 @@ mod intrinsic {
fn visit_leave_fn(purity: uint, proto: uint,
n_inputs: uint, retstyle: uint) -> bool;
fn visit_class() -> bool;
fn visit_enum() -> bool;
fn visit_iface() -> bool;
fn visit_enter_res() -> bool;
fn visit_leave_res() -> bool;

View File

@ -22,6 +22,10 @@ impl methods for reflector {
C_uint(self.bcx.ccx(), u)
}
fn c_int(i: int) -> ValueRef {
C_int(self.bcx.ccx(), i)
}
fn visit(ty_name: str, args: [ValueRef]) {
let tcx = self.bcx.tcx();
let mth_idx = option::get(ty::method_idx("visit_" + ty_name,
@ -179,9 +183,52 @@ impl methods for reflector {
self.visit("leave_fn", extra);
}
// FIXME: these need substructure-walks
ty::ty_class(_, _) { self.leaf("class") }
ty::ty_enum(_, _) { self.leaf("enum") }
ty::ty_class(did, substs) {
let bcx = self.bcx;
let tcx = bcx.ccx().tcx;
let fields = ty::class_items_as_fields(tcx, did, substs);
self.visit("enter_class", [self.c_uint(vec::len(fields))]);
for fields.eachi {|i, field|
self.bracketed_mt("class_field", field.mt,
[self.c_uint(i)
/*
FIXME: doesn't work presently.
C_estr_slice(self.bcx.ccx(),
field.ident)
*/
]);
}
self.visit("leave_class", [self.c_uint(vec::len(fields))]);
}
// FIXME: visiting all the variants in turn is probably
// not ideal. It'll work but will get costly on big enums.
// Maybe let the visitor tell us if it wants to visit only
// a particular variant?
ty::ty_enum(did, substs) {
let bcx = self.bcx;
let tcx = bcx.ccx().tcx;
let variants = ty::substd_enum_variants(tcx, did, substs);
self.visit("enter_enum", [self.c_uint(vec::len(variants))]);
for variants.eachi {|i, v|
let extra = [self.c_uint(i),
self.c_int(v.disr_val),
self.c_uint(vec::len(v.args))
/*
FIXME: doesn't work presently.
C_estr_slice(self.bcx.ccx(),
v.name)
*/];
self.visit("enter_enum_variant", extra);
for v.args.eachi {|j, a|
self.bracketed_t("enum_variant_field", a,
[self.c_uint(j)]);
}
self.visit("leave_enum_variant", extra);
}
self.visit("leave_enum", [self.c_uint(vec::len(variants))]);
}
// Miscallaneous extra types
ty::ty_iface(_, _) { self.leaf("iface") }

View File

@ -87,6 +87,13 @@ impl of intrinsic::ty_visitor for my_visitor {
/*,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 }
@ -101,8 +108,16 @@ impl of intrinsic::ty_visitor for my_visitor {
fn visit_leave_fn(_purity: uint, _proto: uint,
_n_inputs: uint, _retstyle: uint) -> bool { true }
fn visit_class() -> bool { true }
fn visit_enum() -> bool { true }
fn visit_enter_enum(_n_variants: uint) -> bool { true }
fn visit_enter_enum_variant(_variant: uint,
_disr_val: int,
_n_fields: uint) -> 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) -> bool { true }
fn visit_leave_enum(_n_variants: uint) -> bool { true }
fn visit_iface() -> bool { true }
fn visit_enter_res() -> bool { true }