More work on reflection, now calls iface visitors back as well.
This commit is contained in:
parent
5428a22b95
commit
d899c3a579
@ -64,24 +64,13 @@ fn trans_method_callee(bcx: block, callee_id: ast::node_id,
|
||||
}
|
||||
}
|
||||
typeck::method_iface(_, off) {
|
||||
trans_iface_callee(bcx, self, callee_id, off)
|
||||
let {bcx, val} = trans_temp_expr(bcx, self);
|
||||
let fty = node_id_type(bcx, callee_id);
|
||||
trans_iface_callee(bcx, val, fty, off)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn trans_vtable_callee(bcx: block, env: callee_env, vtable: ValueRef,
|
||||
callee_id: ast::node_id, n_method: uint)
|
||||
-> lval_maybe_callee {
|
||||
let _icx = bcx.insn_ctxt("impl::trans_vtable_callee");
|
||||
let bcx = bcx, ccx = bcx.ccx();
|
||||
let fty = node_id_type(bcx, callee_id);
|
||||
let llfty = type_of::type_of_fn_from_ty(ccx, fty);
|
||||
let vtable = PointerCast(bcx, vtable,
|
||||
T_ptr(T_array(T_ptr(llfty), n_method + 1u)));
|
||||
let mptr = Load(bcx, GEPi(bcx, vtable, [0u, n_method]));
|
||||
{bcx: bcx, val: mptr, kind: owned, env: env}
|
||||
}
|
||||
|
||||
fn method_from_methods(ms: [@ast::method], name: ast::ident) -> ast::def_id {
|
||||
local_def(option::get(vec::find(ms, {|m| m.ident == name})).id)
|
||||
}
|
||||
@ -139,7 +128,9 @@ fn trans_monomorphized_callee(bcx: block, callee_id: ast::node_id,
|
||||
with lval}
|
||||
}
|
||||
typeck::vtable_iface(iid, tps) {
|
||||
trans_iface_callee(bcx, base, callee_id, n_method)
|
||||
let {bcx, val} = trans_temp_expr(bcx, base);
|
||||
let fty = node_id_type(bcx, callee_id);
|
||||
trans_iface_callee(bcx, val, fty, n_method)
|
||||
}
|
||||
typeck::vtable_param(n_param, n_bound) {
|
||||
fail "vtable_param left in monomorphized function's vtable substs";
|
||||
@ -148,18 +139,22 @@ fn trans_monomorphized_callee(bcx: block, callee_id: ast::node_id,
|
||||
}
|
||||
|
||||
// Method callee where the vtable comes from a boxed iface
|
||||
fn trans_iface_callee(bcx: block, base: @ast::expr,
|
||||
callee_id: ast::node_id, n_method: uint)
|
||||
fn trans_iface_callee(bcx: block, val: ValueRef,
|
||||
callee_ty: ty::t, n_method: uint)
|
||||
-> lval_maybe_callee {
|
||||
let _icx = bcx.insn_ctxt("impl::trans_iface_callee");
|
||||
let {bcx, val} = trans_temp_expr(bcx, base);
|
||||
let ccx = bcx.ccx();
|
||||
let vtable = Load(bcx, PointerCast(bcx, GEPi(bcx, val, [0u, 0u]),
|
||||
T_ptr(T_ptr(T_vtable()))));
|
||||
T_ptr(T_ptr(T_vtable()))));
|
||||
let box = Load(bcx, GEPi(bcx, val, [0u, 1u]));
|
||||
// FIXME[impl] I doubt this is alignment-safe
|
||||
let self = GEPi(bcx, box, [0u, abi::box_field_body]);
|
||||
let env = self_env(self, ty::mk_opaque_box(bcx.tcx()), some(box));
|
||||
trans_vtable_callee(bcx, env, vtable, callee_id, n_method)
|
||||
let llfty = type_of::type_of_fn_from_ty(ccx, callee_ty);
|
||||
let vtable = PointerCast(bcx, vtable,
|
||||
T_ptr(T_array(T_ptr(llfty), n_method + 1u)));
|
||||
let mptr = Load(bcx, GEPi(bcx, vtable, [0u, n_method]));
|
||||
{bcx: bcx, val: mptr, kind: owned, env: env}
|
||||
}
|
||||
|
||||
fn find_vtable_in_fn_ctxt(ps: param_substs, n_param: uint, n_bound: uint)
|
||||
|
@ -10,7 +10,7 @@ import lib::llvm::{ llvm, TypeRef, ValueRef,
|
||||
StructRetAttribute, ByValAttribute
|
||||
};
|
||||
import syntax::{ast, ast_util};
|
||||
import back::link;
|
||||
import back::{link, abi};
|
||||
import common::*;
|
||||
import build::*;
|
||||
import base::*;
|
||||
@ -842,63 +842,65 @@ fn trans_intrinsic(ccx: @crate_ctxt, decl: ValueRef, item: @ast::native_item,
|
||||
let vp_ty = substs.tys[1];
|
||||
let visitor = get_param(decl, first_real_arg);
|
||||
|
||||
// We're going to synthesize a monomorphized vtbl call here much
|
||||
// like what impl::trans_monomorphized_callee does, but without
|
||||
// having quite as much source machinery to go on.
|
||||
let (tyname, args) = alt ty::get(tp_ty).struct {
|
||||
ty::ty_bot { ("bot", []) }
|
||||
ty::ty_nil { ("nil", []) }
|
||||
ty::ty_bool { ("bool", []) }
|
||||
ty::ty_int(ast::ty_i) { ("int", []) }
|
||||
ty::ty_int(ast::ty_char) { ("char", []) }
|
||||
ty::ty_int(ast::ty_i8) { ("i8", []) }
|
||||
ty::ty_int(ast::ty_i16) { ("i16", []) }
|
||||
ty::ty_int(ast::ty_i32) { ("i32", []) }
|
||||
ty::ty_int(ast::ty_i64) { ("i64", []) }
|
||||
ty::ty_uint(ast::ty_u) { ("uint", []) }
|
||||
ty::ty_uint(ast::ty_u8) { ("u8", []) }
|
||||
ty::ty_uint(ast::ty_u16) { ("u16", []) }
|
||||
ty::ty_uint(ast::ty_u32) { ("u32", []) }
|
||||
ty::ty_uint(ast::ty_u64) { ("u64", []) }
|
||||
ty::ty_float(ast::ty_f) { ("float", []) }
|
||||
ty::ty_float(ast::ty_f32) { ("f32", []) }
|
||||
ty::ty_float(ast::ty_f64) { ("f64", []) }
|
||||
ty::ty_str { ("str", []) }
|
||||
_ {
|
||||
bcx.sess().unimpl("trans::native::visit_ty on "
|
||||
+ ty_to_str(ccx.tcx, tp_ty));
|
||||
}
|
||||
};
|
||||
|
||||
let mth_name = "visit_" + tyname;
|
||||
let dest = ignore;
|
||||
|
||||
alt impl::find_vtable_in_fn_ctxt(substs,
|
||||
1u, /* n_param */
|
||||
0u /* n_bound */ ) {
|
||||
|
||||
typeck::vtable_static(impl_did, impl_substs, sub_origins) {
|
||||
|
||||
let (tyname, args) = alt ty::get(tp_ty).struct {
|
||||
ty::ty_bot { ("bot", []) }
|
||||
ty::ty_nil { ("nil", []) }
|
||||
ty::ty_bool { ("bool", []) }
|
||||
ty::ty_int(ast::ty_i) { ("int", []) }
|
||||
ty::ty_int(ast::ty_char) { ("char", []) }
|
||||
ty::ty_int(ast::ty_i8) { ("i8", []) }
|
||||
ty::ty_int(ast::ty_i16) { ("i16", []) }
|
||||
ty::ty_int(ast::ty_i32) { ("i32", []) }
|
||||
ty::ty_int(ast::ty_i64) { ("i64", []) }
|
||||
ty::ty_uint(ast::ty_u) { ("uint", []) }
|
||||
ty::ty_uint(ast::ty_u8) { ("u8", []) }
|
||||
ty::ty_uint(ast::ty_u16) { ("u16", []) }
|
||||
ty::ty_uint(ast::ty_u32) { ("u32", []) }
|
||||
ty::ty_uint(ast::ty_u64) { ("u64", []) }
|
||||
ty::ty_float(ast::ty_f) { ("float", []) }
|
||||
ty::ty_float(ast::ty_f32) { ("f32", []) }
|
||||
ty::ty_float(ast::ty_f64) { ("f64", []) }
|
||||
ty::ty_str { ("str", []) }
|
||||
_ {
|
||||
bcx.sess().unimpl("trans::native::visit_ty on "
|
||||
+ ty_to_str(ccx.tcx, tp_ty));
|
||||
}
|
||||
};
|
||||
|
||||
let mth_id = impl::method_with_name(ccx, impl_did,
|
||||
"visit_" + tyname);
|
||||
let mth_id = impl::method_with_name(ccx, impl_did, mth_name);
|
||||
let mth_ty = ty::lookup_item_type(ccx.tcx, mth_id).ty;
|
||||
|
||||
// FIXME: is this safe? There is no callee AST node,
|
||||
// we're synthesizing it.
|
||||
let callee_id = (-1) as ast::node_id;
|
||||
|
||||
let dest = ignore;
|
||||
|
||||
bcx = trans_call_inner(bcx,
|
||||
mth_ty,
|
||||
ty::mk_nil(ccx.tcx),
|
||||
{|bcx|
|
||||
let lval =
|
||||
lval_static_fn_inner
|
||||
(bcx, mth_id, callee_id,
|
||||
impl_substs, some(sub_origins));
|
||||
{env: self_env(visitor, vp_ty, none)
|
||||
with lval}
|
||||
}, arg_vals(args), dest);
|
||||
let get_lval = {|bcx|
|
||||
let lval = lval_static_fn_inner(bcx, mth_id, callee_id,
|
||||
impl_substs,
|
||||
some(sub_origins));
|
||||
{env: self_env(visitor, vp_ty, none) with lval}
|
||||
};
|
||||
bcx = trans_call_inner(bcx, mth_ty, ty::mk_bool(ccx.tcx),
|
||||
get_lval, arg_vals(args), dest);
|
||||
}
|
||||
|
||||
typeck::vtable_iface(iid, _tps) {
|
||||
let methods = ty::iface_methods(ccx.tcx, iid);
|
||||
let mth_idx = option::get(ty::method_idx(mth_name, *methods));
|
||||
let mth_ty = ty::mk_fn(ccx.tcx, methods[mth_idx].fty);
|
||||
let get_lval = {|bcx|
|
||||
impl::trans_iface_callee(bcx, visitor, mth_ty, mth_idx)
|
||||
};
|
||||
bcx = trans_call_inner(bcx, mth_ty, ty::mk_bool(ccx.tcx),
|
||||
get_lval, arg_vals(args), dest);
|
||||
}
|
||||
|
||||
_ {
|
||||
ccx.sess.span_bug(item.span,
|
||||
"non-static callee in 'visit_ty' intrinsinc");
|
||||
|
@ -7,107 +7,105 @@
|
||||
//
|
||||
|
||||
iface ty_visitor {
|
||||
fn visit_bot();
|
||||
fn visit_nil();
|
||||
fn visit_bool();
|
||||
fn visit_bot() -> bool;
|
||||
fn visit_nil() -> bool;
|
||||
fn visit_bool() -> bool;
|
||||
|
||||
fn visit_int();
|
||||
fn visit_i8();
|
||||
fn visit_i16();
|
||||
fn visit_i32();
|
||||
fn visit_i64();
|
||||
fn visit_int() -> bool;
|
||||
fn visit_i8() -> bool;
|
||||
fn visit_i16() -> bool;
|
||||
fn visit_i32() -> bool;
|
||||
fn visit_i64() -> bool;
|
||||
|
||||
fn visit_uint();
|
||||
fn visit_u8();
|
||||
fn visit_u16();
|
||||
fn visit_u32();
|
||||
fn visit_u64();
|
||||
fn visit_uint() -> bool;
|
||||
fn visit_u8() -> bool;
|
||||
fn visit_u16() -> bool;
|
||||
fn visit_u32() -> bool;
|
||||
fn visit_u64() -> bool;
|
||||
|
||||
fn visit_float();
|
||||
fn visit_f32();
|
||||
fn visit_f64();
|
||||
fn visit_float() -> bool;
|
||||
fn visit_f32() -> bool;
|
||||
fn visit_f64() -> bool;
|
||||
|
||||
fn visit_char();
|
||||
fn visit_str();
|
||||
fn visit_char() -> bool;
|
||||
fn visit_str() -> bool;
|
||||
|
||||
fn visit_vec(cells_mut: bool,
|
||||
visit_cell: fn(uint, self));
|
||||
|
||||
fn visit_box(inner_mut: bool,
|
||||
visit_inner: fn(self));
|
||||
|
||||
fn visit_uniq(inner_mut: bool,
|
||||
visit_inner: fn(self));
|
||||
|
||||
fn visit_ptr(inner_mut: bool,
|
||||
visit_inner: fn(self));
|
||||
|
||||
fn visit_rptr(inner_mut: bool,
|
||||
visit_inner: fn(self));
|
||||
|
||||
fn visit_rec(n_fields: uint,
|
||||
field_name: fn(uint) -> str/&,
|
||||
field_mut: fn(uint) -> bool,
|
||||
visit_field: fn(uint, self));
|
||||
fn visit_tup(n_fields: uint,
|
||||
visit_field: fn(uint, self));
|
||||
fn visit_enum(n_variants: uint,
|
||||
variant: uint,
|
||||
variant_name: fn(uint) -> str/&,
|
||||
visit_variant: fn(uint, self));
|
||||
// FIXME: possibly pair these as enter/leave calls
|
||||
// not just enter with implicit number of subsequent
|
||||
// calls.
|
||||
fn visit_vec_of(is_mut: bool) -> bool;
|
||||
fn visit_box_of(is_mut: bool) -> bool;
|
||||
fn visit_uniq_of(is_mut: bool) -> bool;
|
||||
fn visit_ptr_of(is_mut: bool) -> bool;
|
||||
fn visit_rptr_of(is_mut: bool) -> bool;
|
||||
fn visit_rec_of(n_fields: uint) -> bool;
|
||||
fn visit_rec_field(name: str/&, is_mut: bool) -> bool;
|
||||
fn visit_tup_of(n_fields: uint) -> bool;
|
||||
fn visit_tup_field(is_mut: bool) -> bool;
|
||||
fn visit_enum_of(n_variants: uint) -> bool;
|
||||
fn visit_enum_variant(name: str/&) -> bool;
|
||||
}
|
||||
|
||||
enum my_visitor = { mut types: [str] };
|
||||
|
||||
impl of ty_visitor for my_visitor {
|
||||
fn visit_bot() { self.types += ["bot"] }
|
||||
fn visit_nil() { self.types += ["nil"] }
|
||||
fn visit_bool() { self.types += ["bool"] }
|
||||
fn visit_bot() -> bool {
|
||||
self.types += ["bot"];
|
||||
#error("visited bot type");
|
||||
true
|
||||
}
|
||||
fn visit_nil() -> bool {
|
||||
self.types += ["nil"];
|
||||
#error("visited nil type");
|
||||
true
|
||||
}
|
||||
fn visit_bool() -> bool {
|
||||
self.types += ["bool"];
|
||||
#error("visited bool type");
|
||||
true
|
||||
}
|
||||
fn visit_int() -> bool {
|
||||
self.types += ["int"];
|
||||
#error("visited int type");
|
||||
true
|
||||
}
|
||||
fn visit_i8() -> bool {
|
||||
self.types += ["i8"];
|
||||
#error("visited i8 type");
|
||||
true
|
||||
}
|
||||
fn visit_i16() -> bool {
|
||||
self.types += ["i16"];
|
||||
#error("visited i16 type");
|
||||
true
|
||||
}
|
||||
fn visit_i32() -> bool { true }
|
||||
fn visit_i64() -> bool { true }
|
||||
|
||||
fn visit_int() { self.types += ["int"] }
|
||||
fn visit_i8() { self.types += ["i8"] }
|
||||
fn visit_i16() { self.types += ["i16"] }
|
||||
fn visit_i32() { }
|
||||
fn visit_i64() { }
|
||||
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_uint() { }
|
||||
fn visit_u8() { }
|
||||
fn visit_u16() { }
|
||||
fn visit_u32() { }
|
||||
fn visit_u64() { }
|
||||
fn visit_float() -> bool { true }
|
||||
fn visit_f32() -> bool { true }
|
||||
fn visit_f64() -> bool { true }
|
||||
|
||||
fn visit_float() { }
|
||||
fn visit_f32() { }
|
||||
fn visit_f64() { }
|
||||
fn visit_char() -> bool { true }
|
||||
fn visit_str() -> bool { true }
|
||||
|
||||
fn visit_char() { }
|
||||
fn visit_str() { }
|
||||
|
||||
fn visit_vec(_cells_mut: bool,
|
||||
_visit_cell: fn(uint, my_visitor)) { }
|
||||
|
||||
fn visit_box(_inner_mut: bool,
|
||||
_visit_inner: fn(my_visitor)) { }
|
||||
|
||||
fn visit_uniq(_inner_mut: bool,
|
||||
_visit_inner: fn(my_visitor)) { }
|
||||
|
||||
fn visit_ptr(_inner_mut: bool,
|
||||
_visit_inner: fn(my_visitor)) { }
|
||||
|
||||
fn visit_rptr(_inner_mut: bool,
|
||||
_visit_inner: fn(my_visitor)) { }
|
||||
|
||||
fn visit_rec(_n_fields: uint,
|
||||
_field_name: fn(uint) -> str/&,
|
||||
_field_mut: fn(uint) -> bool,
|
||||
_visit_field: fn(uint, my_visitor)) { }
|
||||
fn visit_tup(_n_fields: uint,
|
||||
_visit_field: fn(uint, my_visitor)) { }
|
||||
fn visit_enum(_n_variants: uint,
|
||||
_variant: uint,
|
||||
_variant_name: fn(uint) -> str/&,
|
||||
_visit_variant: fn(uint, my_visitor)) { }
|
||||
fn visit_vec_of(_is_mut: bool) -> bool { true }
|
||||
fn visit_box_of(_is_mut: bool) -> bool { true }
|
||||
fn visit_uniq_of(_is_mut: bool) -> bool { true }
|
||||
fn visit_ptr_of(_is_mut: bool) -> bool { true }
|
||||
fn visit_rptr_of(_is_mut: bool) -> bool { true }
|
||||
fn visit_rec_of(_n_fields: uint) -> bool { true }
|
||||
fn visit_rec_field(_name: str/&, _is_mut: bool) -> bool { true }
|
||||
fn visit_tup_of(_n_fields: uint) -> bool { true }
|
||||
fn visit_tup_field(_is_mut: bool) -> bool { true }
|
||||
fn visit_enum_of(_n_variants: uint) -> bool { true }
|
||||
fn visit_enum_variant(_name: str/&) -> bool { true }
|
||||
}
|
||||
|
||||
#[abi = "rust-intrinsic"]
|
||||
@ -115,6 +113,13 @@ native mod rusti {
|
||||
fn visit_ty<T,V:ty_visitor>(tv: V);
|
||||
}
|
||||
|
||||
fn via_iface(v: ty_visitor) {
|
||||
rusti::visit_ty::<bool,ty_visitor>(v);
|
||||
rusti::visit_ty::<int,ty_visitor>(v);
|
||||
rusti::visit_ty::<i8,ty_visitor>(v);
|
||||
rusti::visit_ty::<i16,ty_visitor>(v);
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let v = my_visitor({mut types: []});
|
||||
|
||||
@ -127,4 +132,6 @@ fn main() {
|
||||
io::println(#fmt("type: %s", s));
|
||||
}
|
||||
assert v.types == ["bool", "int", "i8", "i16"];
|
||||
|
||||
via_iface(v as ty_visitor);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user