1
Fork 0

Get very simple impl method calls to compile

Resolution is still dumb, and no self support yet.
This commit is contained in:
Marijn Haverbeke 2011-12-14 14:38:25 +01:00
parent 6a16f57c0a
commit 1dd2f1ec03
6 changed files with 103 additions and 60 deletions

View file

@ -171,8 +171,8 @@ fn compile_input(sess: session::session, cfg: ast::crate_cfg, input: str,
time(time_passes, "const checking",
bind middle::check_const::check_crate(sess, crate));
let ty_cx = ty::mk_ctxt(sess, def_map, ext_map, ast_map, freevars);
time(time_passes, "typechecking",
bind typeck::check_crate(ty_cx, impl_map, crate));
let method_map = time(time_passes, "typechecking",
bind typeck::check_crate(ty_cx, impl_map, crate));
time(time_passes, "block-use checking",
bind middle::block_use::check_crate(ty_cx, crate));
time(time_passes, "function usage",
@ -190,7 +190,7 @@ fn compile_input(sess: session::session, cfg: ast::crate_cfg, input: str,
let last_uses = time(time_passes, "last use finding",
bind last_use::find_last_uses(crate, def_map, ref_map, ty_cx));
time(time_passes, "kind checking",
bind kind::check_crate(ty_cx, last_uses, crate));
bind kind::check_crate(ty_cx, method_map, last_uses, crate));
if sess.get_opts().no_trans { ret; }
let outputs = build_output_filenames(input, outdir, output, sess);
@ -199,7 +199,8 @@ fn compile_input(sess: session::session, cfg: ast::crate_cfg, input: str,
time(time_passes, "translation",
bind trans::trans_crate(sess, crate, ty_cx,
outputs.obj_filename, exp_map, ast_map,
mut_map, copy_map, last_uses));
mut_map, copy_map, last_uses,
method_map));
time(time_passes, "LLVM passes",
bind link::write::run_passes(sess, llmod, outputs.obj_filename));

View file

@ -30,12 +30,15 @@ type rval_map = std::map::hashmap<node_id, ()>;
type ctx = {tcx: ty::ctxt,
rval_map: rval_map,
method_map: typeck::method_map,
last_uses: last_use::last_uses};
fn check_crate(tcx: ty::ctxt, last_uses: last_use::last_uses,
crate: @crate) -> rval_map {
fn check_crate(tcx: ty::ctxt, method_map: typeck::method_map,
last_uses: last_use::last_uses, crate: @crate)
-> rval_map {
let ctx = {tcx: tcx,
rval_map: std::map::new_int_hash(),
method_map: method_map,
last_uses: last_uses};
let visit = visit::mk_vt(@{
visit_expr: check_expr,
@ -150,7 +153,8 @@ fn maybe_copy(cx: ctx, ex: @expr) {
}
fn check_copy_ex(cx: ctx, ex: @expr, _warn: bool) {
if ty::expr_is_lval(cx.tcx, ex) && !cx.last_uses.contains_key(ex.id) {
if ty::expr_is_lval(cx.method_map, cx.tcx, ex) &&
!cx.last_uses.contains_key(ex.id) {
let ty = ty::expr_ty(cx.tcx, ex);
check_copy(cx, ty, ex.span);
// FIXME turn this on again once vector types are no longer unique.

View file

@ -13,7 +13,7 @@
// but many TypeRefs correspond to one ty::t; for instance, tup(int, int,
// int) and rec(x=int, y=int, z=int) will have the same TypeRef.
import core::{either, str, uint, option, vec};
import core::{either, str, int, uint, option, vec};
import std::{map, time};
import std::map::hashmap;
import std::map::{new_int_hash, new_str_hash};
@ -948,8 +948,6 @@ fn get_derived_tydesc(cx: @block_ctxt, t: ty::t, escapes: bool,
&static_ti: option::t<@tydesc_info>) -> result {
alt cx.fcx.derived_tydescs.find(t) {
some(info) {
// If the tydesc escapes in this context, the cached derived
// tydesc also has to be one that was marked as escaping.
if !(escapes && !info.escapes) && storage == tps_normal {
@ -2606,8 +2604,9 @@ fn trans_external_path(cx: @block_ctxt, did: ast::def_id,
type_of_ty_param_kinds_and_ty(lcx, cx.sp, tpt));
}
fn lval_static_fn(bcx: @block_ctxt, tpt: ty::ty_param_kinds_and_ty,
fn_id: ast::def_id, id: ast::node_id) -> lval_maybe_callee {
fn lval_static_fn(bcx: @block_ctxt, fn_id: ast::def_id, id: ast::node_id)
-> lval_maybe_callee {
let tpt = ty::lookup_item_type(bcx_tcx(bcx), fn_id);
let val = if fn_id.crate == ast::local_crate {
// Internal reference.
assert (bcx_ccx(bcx).item_ids.contains_key(fn_id.node));
@ -2698,17 +2697,13 @@ fn trans_var(cx: @block_ctxt, sp: span, def: ast::def, id: ast::node_id)
let ccx = bcx_ccx(cx);
alt def {
ast::def_fn(did, _) | ast::def_native_fn(did, _) {
let tyt = ty::lookup_item_type(ccx.tcx, did);
ret lval_static_fn(cx, tyt, did, id);
ret lval_static_fn(cx, did, id);
}
ast::def_variant(tid, vid) {
let v_tyt = ty::lookup_item_type(ccx.tcx, vid);
alt ty::struct(ccx.tcx, v_tyt.ty) {
ty::ty_fn(_, _, _, _, _) {
if vec::len(ty::tag_variant_with_id(ccx.tcx, tid, vid).args) > 0u {
// N-ary variant.
ret lval_static_fn(cx, v_tyt, vid, id);
}
_ {
ret lval_static_fn(cx, vid, id);
} else {
// Nullary variant.
let tag_ty = node_id_type(ccx, id);
let alloc_result = alloc_ty(cx, tag_ty);
@ -2724,7 +2719,6 @@ fn trans_var(cx: @block_ctxt, sp: span, def: ast::def, id: ast::node_id)
} else { C_int(ccx, 0) };
Store(bcx, d, lldiscrimptr);
ret lval_no_env(bcx, lltagptr, temporary);
}
}
}
ast::def_const(did) {
@ -2838,15 +2832,30 @@ fn trans_index(cx: @block_ctxt, sp: span, base: @ast::expr, idx: @ast::expr,
ret lval_owned(next_cx, elt);
}
// This is for impl methods, not obj methods.
fn trans_method_callee(bcx: @block_ctxt, e: @ast::expr, base: @ast::expr,
did: ast::def_id) -> lval_maybe_callee {
let bcx = trans_expr(bcx, base, ignore); // FIXME pass self
lval_static_fn(bcx, did, e.id)
}
fn trans_callee(bcx: @block_ctxt, e: @ast::expr) -> lval_maybe_callee {
alt e.node {
ast::expr_path(p) { ret trans_path(bcx, p, e.id); }
ast::expr_field(base, ident) {
let method_map = bcx_ccx(bcx).method_map;
// Lval means this is a record field, so not a method
if !ty::expr_is_lval(bcx_tcx(bcx), e) {
let of = trans_object_field(bcx, base, ident);
ret {bcx: of.bcx, val: of.mthptr, kind: owned,
env: obj_env(of.objptr), generic: none};
if !ty::expr_is_lval(method_map, bcx_tcx(bcx), e) {
alt method_map.find(e.id) {
some(did) { // An impl method
ret trans_method_callee(bcx, e, base, did);
}
none. { // An object method
let of = trans_object_field(bcx, base, ident);
ret {bcx: of.bcx, val: of.mthptr, kind: owned,
env: obj_env(of.objptr), generic: none};
}
}
}
}
ast::expr_self_method(ident) {
@ -3466,7 +3475,7 @@ fn trans_expr_save_in(bcx: @block_ctxt, e: @ast::expr, dest: ValueRef)
// use trans_temp_expr.
fn trans_temp_lval(bcx: @block_ctxt, e: @ast::expr) -> lval_result {
let bcx = bcx;
if ty::expr_is_lval(bcx_tcx(bcx), e) {
if ty::expr_is_lval(bcx_ccx(bcx).method_map, bcx_tcx(bcx), e) {
ret trans_lval(bcx, e);
} else {
let tcx = bcx_tcx(bcx);
@ -3504,7 +3513,9 @@ fn trans_temp_expr(bcx: @block_ctxt, e: @ast::expr) -> result {
// - exprs with non-immediate type never get dest=by_val
fn trans_expr(bcx: @block_ctxt, e: @ast::expr, dest: dest) -> @block_ctxt {
let tcx = bcx_tcx(bcx);
if ty::expr_is_lval(tcx, e) { ret lval_to_dps(bcx, e, dest); }
if ty::expr_is_lval(bcx_ccx(bcx).method_map, tcx, e) {
ret lval_to_dps(bcx, e, dest);
}
alt e.node {
ast::expr_if(cond, thn, els) | ast::expr_if_check(cond, thn, els) {
@ -3544,7 +3555,9 @@ fn trans_expr(bcx: @block_ctxt, e: @ast::expr, dest: dest) -> @block_ctxt {
ret trans_closure::trans_bind(bcx, f, args, e.id, dest);
}
ast::expr_copy(a) {
if !ty::expr_is_lval(tcx, a) { ret trans_expr(bcx, a, dest); }
if !ty::expr_is_lval(bcx_ccx(bcx).method_map, tcx, a) {
ret trans_expr(bcx, a, dest);
}
else { ret lval_to_dps(bcx, a, dest); }
}
ast::expr_cast(val, _) {
@ -3945,7 +3958,8 @@ fn init_local(bcx: @block_ctxt, local: @ast::local) -> @block_ctxt {
alt local.node.init {
some(init) {
if init.op == ast::init_assign ||
!ty::expr_is_lval(bcx_tcx(bcx), init.expr) {
!ty::expr_is_lval(bcx_ccx(bcx).method_map, bcx_tcx(bcx),
init.expr) {
bcx = trans_expr_save_in(bcx, init.expr, llptr);
} else { // This is a move from an lval, must perform an actual move
let sub = trans_lval(bcx, init.expr);
@ -4641,6 +4655,18 @@ fn trans_tag_variant(cx: @local_ctxt, tag_id: ast::node_id,
finish_fn(fcx, lltop);
}
fn trans_impl(cx: @local_ctxt, name: ast::ident, methods: [@ast::method]) {
let sub_cx = extend_path(cx, name);
for m in methods {
alt cx.ccx.item_ids.find(m.node.id) {
some(llfndecl) {
trans_fn(extend_path(sub_cx, m.node.ident), m.span, m.node.meth,
llfndecl, none, [], m.node.id);
}
}
}
}
// FIXME: this should do some structural hash-consing to avoid
// duplicate constants. I think. Maybe LLVM has a magical mode
@ -4949,10 +4975,7 @@ fn trans_item(cx: @local_ctxt, item: ast::item) {
with *extend_path(cx, item.ident)};
trans_obj(sub_cx, item.span, ob, ctor_id, tps);
}
ast::item_impl(_, _, _) {
fail "FIXME[impl]";
}
ast::item_impl(_, _, ms) { trans_impl(cx, item.ident, ms); }
ast::item_res(dtor, dtor_id, tps, ctor_id) {
trans_res_ctor(cx, item.span, dtor, ctor_id, tps);
@ -5167,8 +5190,6 @@ fn raw_native_fn_type(ccx: @crate_ctxt, sp: span, args: [ty::arg],
ret T_fn(type_of_explicit_args(ccx, sp, args), type_of(ccx, sp, ret_ty));
}
fn item_path(item: @ast::item) -> [str] { ret [item.ident]; }
fn link_name(i: @ast::native_item) -> str {
alt attr::get_meta_item_value_str_by_name(i.attrs, "link_name") {
none. { ret i.ident; }
@ -5259,12 +5280,12 @@ fn collect_item_1(ccx: @crate_ctxt, abi: @mutable option::t<ast::native_abi>,
}
_ { }
}
visit::visit_item(i, pt + item_path(i), v);
visit::visit_item(i, pt + [i.ident], v);
}
fn collect_item_2(ccx: @crate_ctxt, i: @ast::item, &&pt: [str],
v: vt<[str]>) {
let new_pt = pt + item_path(i);
let new_pt = pt + [i.ident];
visit::visit_item(i, new_pt, v);
alt i.node {
ast::item_fn(f, tps) {
@ -5278,6 +5299,13 @@ fn collect_item_2(ccx: @crate_ctxt, i: @ast::item, &&pt: [str],
ccx.obj_methods.insert(m.node.id, ());
}
}
ast::item_impl(_, _, methods) {
let name = ccx.names.next(i.ident);
for m in methods {
register_fn(ccx, i.span, pt + [name, m.node.ident],
"impl_method", [], m.node.id);
}
}
ast::item_res(_, dtor_id, tps, ctor_id) {
register_fn(ccx, i.span, new_pt, "res_ctor", tps, ctor_id);
// Note that the destructor is associated with the item's id, not
@ -5307,7 +5335,7 @@ fn collect_items(ccx: @crate_ctxt, crate: @ast::crate) {
fn collect_tag_ctor(ccx: @crate_ctxt, i: @ast::item, &&pt: [str],
v: vt<[str]>) {
let new_pt = pt + item_path(i);
let new_pt = pt + [i.ident];
visit::visit_item(i, new_pt, v);
alt i.node {
ast::item_tag(variants, tps) {
@ -5333,7 +5361,7 @@ fn collect_tag_ctors(ccx: @crate_ctxt, crate: @ast::crate) {
// The constant translation pass.
fn trans_constant(ccx: @crate_ctxt, it: @ast::item, &&pt: [str],
v: vt<[str]>) {
let new_pt = pt + item_path(it);
let new_pt = pt + [it.ident];
visit::visit_item(it, new_pt, v);
alt it.node {
ast::item_tag(variants, _) {
@ -5520,7 +5548,7 @@ fn write_abi_version(ccx: @crate_ctxt) {
fn trans_crate(sess: session::session, crate: @ast::crate, tcx: ty::ctxt,
output: str, emap: resolve::exp_map, amap: ast_map::map,
mut_map: mut::mut_map, copy_map: alias::copy_map,
last_uses: last_use::last_uses)
last_uses: last_use::last_uses, method_map: typeck::method_map)
-> (ModuleRef, link::link_meta) {
let sha = std::sha1::mk_sha1();
let link_meta = link::build_link_meta(sess, *crate, output, sha);
@ -5595,6 +5623,7 @@ fn trans_crate(sess: session::session, crate: @ast::crate, tcx: ty::ctxt,
mut_map: mut_map,
copy_map: copy_map,
last_uses: last_uses,
method_map: method_map,
stats:
{mutable n_static_tydescs: 0u,
mutable n_derived_tydescs: 0u,

View file

@ -104,6 +104,7 @@ type crate_ctxt =
mut_map: mut::mut_map,
copy_map: alias::copy_map,
last_uses: last_use::last_uses,
method_map: typeck::method_map,
stats: stats,
upcalls: @upcall::upcalls,
rust_object_type: TypeRef,

View file

@ -1672,15 +1672,18 @@ fn expr_has_ty_params(cx: ctxt, expr: @ast::expr) -> bool {
ret node_id_has_type_params(cx, expr.id);
}
fn expr_is_lval(tcx: ty::ctxt, e: @ast::expr) -> bool {
fn expr_is_lval(method_map: typeck::method_map, tcx: ty::ctxt,
e: @ast::expr) -> bool {
alt e.node {
ast::expr_path(_) | ast::expr_index(_, _) |
ast::expr_unary(ast::deref., _) { true }
ast::expr_field(base, ident) {
let basety = type_autoderef(tcx, expr_ty(tcx, base));
alt struct(tcx, basety) {
ty_obj(_) { false }
ty_rec(_) { true }
method_map.contains_key(e.id) ? false : {
let basety = type_autoderef(tcx, expr_ty(tcx, base));
alt struct(tcx, basety) {
ty_obj(_) { false }
ty_rec(_) { true }
}
}
}
_ { false }

View file

@ -18,7 +18,9 @@ import std::map::{hashmap, new_int_hash};
import option::{none, some};
import syntax::print::pprust::*;
export check_crate;
export check_crate, method_map;
type method_map = hashmap<ast::node_id, ast::def_id>;
type ty_table = hashmap<ast::def_id, ty::t>;
@ -35,6 +37,7 @@ tag obj_info {
type crate_ctxt = {mutable obj_infos: [obj_info],
impl_map: resolve::impl_map,
method_map: method_map,
tcx: ty::ctxt};
type fn_ctxt =
@ -74,22 +77,21 @@ fn lookup_def(fcx: @fn_ctxt, sp: span, id: ast::node_id) -> ast::def {
// Returns the type parameter count and the type for the given definition.
fn ty_param_kinds_and_ty_for_def(fcx: @fn_ctxt, sp: span, defn: ast::def) ->
ty_param_kinds_and_ty {
let no_kinds: [ast::kind] = [];
alt defn {
ast::def_arg(id, _) {
assert (fcx.locals.contains_key(id.node));
let typ = ty::mk_var(fcx.ccx.tcx, lookup_local(fcx, sp, id.node));
ret {kinds: no_kinds, ty: typ};
ret {kinds: [], ty: typ};
}
ast::def_local(id, _) {
assert (fcx.locals.contains_key(id.node));
let typ = ty::mk_var(fcx.ccx.tcx, lookup_local(fcx, sp, id.node));
ret {kinds: no_kinds, ty: typ};
ret {kinds: [], ty: typ};
}
ast::def_obj_field(id, _) {
assert (fcx.locals.contains_key(id.node));
let typ = ty::mk_var(fcx.ccx.tcx, lookup_local(fcx, sp, id.node));
ret {kinds: no_kinds, ty: typ};
ret {kinds: [], ty: typ};
}
ast::def_self(id) { fail "FIXME[impl]"; }
ast::def_fn(id, _) { ret ty::lookup_item_type(fcx.ccx.tcx, id); }
@ -99,12 +101,12 @@ fn ty_param_kinds_and_ty_for_def(fcx: @fn_ctxt, sp: span, defn: ast::def) ->
ast::def_binding(id) {
assert (fcx.locals.contains_key(id.node));
let typ = ty::mk_var(fcx.ccx.tcx, lookup_local(fcx, sp, id.node));
ret {kinds: no_kinds, ty: typ};
ret {kinds: [], ty: typ};
}
ast::def_mod(_) {
// Hopefully part of a path.
// TODO: return a type that's more poisonous, perhaps?
ret {kinds: no_kinds, ty: ty::mk_nil(fcx.ccx.tcx)};
ret {kinds: [], ty: ty::mk_nil(fcx.ccx.tcx)};
}
ast::def_ty(_) {
fcx.ccx.tcx.sess.span_fatal(sp, "expected value but found type");
@ -410,11 +412,10 @@ fn ast_ty_to_ty(tcx: ty::ctxt, mode: mode, &&ast_ty: @ast::ty) -> ty::t {
fn ty_of_item(tcx: ty::ctxt, mode: mode, it: @ast::item)
-> ty::ty_param_kinds_and_ty {
let no_kinds: [ast::kind] = [];
alt it.node {
ast::item_const(t, _) {
let typ = ast_ty_to_ty(tcx, mode, t);
let tpt = {kinds: no_kinds, ty: typ};
let tpt = {kinds: [], ty: typ};
tcx.tcache.insert(local_def(it.id), tpt);
ret tpt;
}
@ -463,7 +464,6 @@ fn ty_of_item(tcx: ty::ctxt, mode: mode, it: @ast::item)
}
fn ty_of_native_item(tcx: ty::ctxt, mode: mode, it: @ast::native_item)
-> ty::ty_param_kinds_and_ty {
let no_kinds: [ast::kind] = [];
alt it.node {
ast::native_item_fn(fn_decl, params) {
ret ty_of_native_fn_decl(tcx, mode, fn_decl, params,
@ -475,7 +475,7 @@ fn ty_of_native_item(tcx: ty::ctxt, mode: mode, it: @ast::native_item)
none. { }
}
let t = ty::mk_native(tcx, ast_util::local_def(it.id));
let tpt = {kinds: no_kinds, ty: t};
let tpt = {kinds: [], ty: t};
tcx.tcache.insert(local_def(it.id), tpt);
ret tpt;
}
@ -698,9 +698,11 @@ mod collect {
}
ast::item_impl(_, _, ms) {
for m in ms {
write::ty_only(cx.tcx, m.node.id,
ty::method_ty_to_fn_ty(cx.tcx, ty_of_method(
cx.tcx, m_collect, m)));
let ty = ty::method_ty_to_fn_ty(
cx.tcx, ty_of_method(cx.tcx, m_collect, m));
cx.tcx.tcache.insert(local_def(m.node.id),
{kinds: [], ty: ty});
write::ty_only(cx.tcx, m.node.id, ty);
}
}
ast::item_obj(object, ty_params, ctor_id) {
@ -2179,6 +2181,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier,
let f_ty = ty::mk_fn(fcx.ccx.tcx, mt.proto, mt.inputs,
mt.output, mt.cf, mt.constrs);
write::ty_only_fixup(fcx, id, f_ty);
fcx.ccx.method_map.insert(id, local_def(method.node.id));
}
_ {
base_t = do_autoderef(fcx, expr.span, base_t);
@ -2695,13 +2698,14 @@ fn check_for_main_fn(tcx: ty::ctxt, crate: @ast::crate) {
}
fn check_crate(tcx: ty::ctxt, impl_map: resolve::impl_map,
crate: @ast::crate) {
crate: @ast::crate) -> method_map {
collect::collect_item_types(tcx, crate);
let obj_infos: [obj_info] = [];
let ccx = @{mutable obj_infos: obj_infos,
impl_map: impl_map,
method_map: std::map::new_int_hash(),
tcx: tcx};
let visit =
visit::mk_simple_visitor(@{visit_item: bind check_item(ccx, _)
@ -2709,6 +2713,7 @@ fn check_crate(tcx: ty::ctxt, impl_map: resolve::impl_map,
visit::visit_crate(*crate, (), visit);
check_for_main_fn(tcx, crate);
tcx.sess.abort_if_errors();
ccx.method_map
}
//
// Local Variables: