First working monomorphic type-reflection.
This commit is contained in:
parent
5dbf881e87
commit
2585384c97
@ -18,6 +18,7 @@ mod intrinsic {
|
||||
}
|
||||
|
||||
iface ty_visitor {
|
||||
fn visit_bot();
|
||||
fn visit_nil();
|
||||
fn visit_bool();
|
||||
|
||||
@ -36,6 +37,8 @@ mod intrinsic {
|
||||
fn visit_float();
|
||||
fn visit_f32();
|
||||
fn visit_f64();
|
||||
|
||||
fn visit_char();
|
||||
fn visit_str();
|
||||
|
||||
fn visit_vec(cells_mut: bool,
|
||||
@ -68,6 +71,7 @@ mod intrinsic {
|
||||
iface val_visitor {
|
||||
|
||||
// Basic types we can visit directly.
|
||||
fn visit_bot();
|
||||
fn visit_nil();
|
||||
fn visit_bool(b: &bool);
|
||||
|
||||
@ -87,6 +91,8 @@ mod intrinsic {
|
||||
fn visit_f32(f: &f32);
|
||||
fn visit_f64(f: &f64);
|
||||
|
||||
fn visit_char(c: &char);
|
||||
|
||||
// Vecs and strs we can provide a stub view of.
|
||||
fn visit_str(repr: &vec::unsafe::vec_repr,
|
||||
visit_cell: fn(uint,self));
|
||||
|
@ -782,7 +782,7 @@ fn trans_intrinsic(ccx: @crate_ctxt, decl: ValueRef, item: @ast::native_item,
|
||||
ref_id: option<ast::node_id>) {
|
||||
let fcx = new_fn_ctxt_w_id(ccx, path, decl, item.id,
|
||||
some(substs), some(item.span));
|
||||
let bcx = top_scope_block(fcx, none), lltop = bcx.llbb;
|
||||
let mut bcx = top_scope_block(fcx, none), lltop = bcx.llbb;
|
||||
let tp_ty = substs.tys[0], lltp_ty = type_of::type_of(ccx, tp_ty);
|
||||
alt check item.ident {
|
||||
"size_of" {
|
||||
@ -835,27 +835,83 @@ fn trans_intrinsic(ccx: @crate_ctxt, decl: ValueRef, item: @ast::native_item,
|
||||
fcx.llretptr);
|
||||
}
|
||||
"visit_ty" {
|
||||
let vp_ty = substs.tys[1], _llvp_ty = type_of::type_of(ccx, vp_ty);
|
||||
|
||||
// signature: fn visit_ty<T,V:ty_visitor>(tv: V);
|
||||
|
||||
let tp_ty = substs.tys[0];
|
||||
let vp_ty = substs.tys[1];
|
||||
let visitor = get_param(decl, first_real_arg);
|
||||
// FIXME: implement a proper iface-call. Nontrivial.
|
||||
Call(bcx, visitor, []);
|
||||
|
||||
// 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.
|
||||
|
||||
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_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);
|
||||
}
|
||||
_ {
|
||||
ccx.sess.span_bug(item.span,
|
||||
"non-static callee in 'visit_ty' intrinsinc");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
"visit_val" {
|
||||
let vp_ty = substs.tys[1], _llvp_ty = type_of::type_of(ccx, vp_ty);
|
||||
let val = get_param(decl, first_real_arg);
|
||||
let visitor = get_param(decl, first_real_arg + 1u);
|
||||
// FIXME: implement a proper iface-call. Nontrivial.
|
||||
Call(bcx, visitor, [val]);
|
||||
bcx.sess().unimpl("trans::native::visit_val");
|
||||
}
|
||||
|
||||
"visit_val_pair" {
|
||||
let vp_ty = substs.tys[1], _llvp_ty = type_of::type_of(ccx, vp_ty);
|
||||
let a = get_param(decl, first_real_arg);
|
||||
let b = get_param(decl, first_real_arg + 1u);
|
||||
let visitor = get_param(decl, first_real_arg + 2u);
|
||||
// FIXME: implement a proper iface-call. Nontrivial.
|
||||
Call(bcx, visitor, [a, b]);
|
||||
bcx.sess().unimpl("trans::native::visit_val_pair");
|
||||
}
|
||||
}
|
||||
build_return(bcx);
|
||||
|
@ -76,9 +76,9 @@ fn type_uses_for(ccx: @crate_ctxt, fn_id: def_id, n_tps: uint)
|
||||
ast_map::node_native_item(i@@{node: native_item_fn(_, _), _}, abi, _) {
|
||||
if abi == native_abi_rust_intrinsic {
|
||||
let flags = alt check i.ident {
|
||||
"size_of" |
|
||||
"pref_align_of" | "min_align_of" | "init" |
|
||||
"reinterpret_cast" { use_repr }
|
||||
"visit_ty" | "visit_val" | "visit_val_pair" { 3u }
|
||||
"size_of" | "pref_align_of" | "min_align_of" |
|
||||
"init" | "reinterpret_cast" { use_repr }
|
||||
"get_tydesc" | "needs_drop" { use_tydesc }
|
||||
"forget" | "addr_of" { 0u }
|
||||
};
|
||||
|
130
src/test/run-pass/reflect-visit-type.rs
Normal file
130
src/test/run-pass/reflect-visit-type.rs
Normal file
@ -0,0 +1,130 @@
|
||||
// xfail-test
|
||||
//
|
||||
// This works on stage2 currently. Once we have a snapshot
|
||||
// and some fiddling with inject_intrinsic (and possibly another
|
||||
// snapshot after _that_) it can be un-xfailed and changed
|
||||
// to use the intrinsic:: interface and native module.
|
||||
//
|
||||
|
||||
iface ty_visitor {
|
||||
fn visit_bot();
|
||||
fn visit_nil();
|
||||
fn visit_bool();
|
||||
|
||||
fn visit_int();
|
||||
fn visit_i8();
|
||||
fn visit_i16();
|
||||
fn visit_i32();
|
||||
fn visit_i64();
|
||||
|
||||
fn visit_uint();
|
||||
fn visit_u8();
|
||||
fn visit_u16();
|
||||
fn visit_u32();
|
||||
fn visit_u64();
|
||||
|
||||
fn visit_float();
|
||||
fn visit_f32();
|
||||
fn visit_f64();
|
||||
|
||||
fn visit_char();
|
||||
fn visit_str();
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
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_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() { }
|
||||
fn visit_u8() { }
|
||||
fn visit_u16() { }
|
||||
fn visit_u32() { }
|
||||
fn visit_u64() { }
|
||||
|
||||
fn visit_float() { }
|
||||
fn visit_f32() { }
|
||||
fn visit_f64() { }
|
||||
|
||||
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)) { }
|
||||
}
|
||||
|
||||
#[abi = "rust-intrinsic"]
|
||||
native mod rusti {
|
||||
fn visit_ty<T,V:ty_visitor>(tv: V);
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let v = my_visitor({mut types: []});
|
||||
|
||||
rusti::visit_ty::<bool,my_visitor>(v);
|
||||
rusti::visit_ty::<int,my_visitor>(v);
|
||||
rusti::visit_ty::<i8,my_visitor>(v);
|
||||
rusti::visit_ty::<i16,my_visitor>(v);
|
||||
|
||||
for v.types.each {|s|
|
||||
io::println(#fmt("type: %s", s));
|
||||
}
|
||||
assert v.types == ["bool", "int", "i8", "i16"];
|
||||
}
|
Loading…
Reference in New Issue
Block a user