diff --git a/src/rustc/front/intrinsic.rs b/src/rustc/front/intrinsic.rs index cac3b4f5416..47559052cd4 100644 --- a/src/rustc/front/intrinsic.rs +++ b/src/rustc/front/intrinsic.rs @@ -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; diff --git a/src/rustc/middle/trans/reflect.rs b/src/rustc/middle/trans/reflect.rs index 12b1d28dbc9..0fbb7983281 100644 --- a/src/rustc/middle/trans/reflect.rs +++ b/src/rustc/middle/trans/reflect.rs @@ -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") } diff --git a/src/test/run-pass/reflect-visit-type.rs b/src/test/run-pass/reflect-visit-type.rs index 599e8fd99b7..9066f7999c2 100644 --- a/src/test/run-pass/reflect-visit-type.rs +++ b/src/test/run-pass/reflect-visit-type.rs @@ -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 }