Further on the path toward self-awareness.

Mostly:

  * Merciless refactoring of trans.rs so that trans_call can work for
    self-calls as well as other kinds of calls

Also:

  * Various changes to go with having idents, rather than exprs, in
    expr_call_self AST nodes
  * Added missing case for SELF token to token.to_str()
This commit is contained in:
Lindsey Kuper 2011-04-05 14:18:44 -07:00 committed by Graydon Hoare
parent 8703c8067f
commit b8bb2e118e
7 changed files with 99 additions and 118 deletions

View file

@ -258,7 +258,7 @@ tag expr_ {
expr_tup(vec[elt], ann);
expr_rec(vec[field], option.t[@expr], ann);
expr_call(@expr, vec[@expr], ann);
expr_call_self(@expr, vec[@expr], ann);
expr_call_self(ident, vec[@expr], ann);
expr_bind(@expr, vec[option.t[@expr]], ann);
expr_spawn(spawn_dom, option.t[str], @expr, vec[@expr], ann);
expr_binary(binop, @expr, @expr, ann);

View file

@ -887,10 +887,12 @@ impure fn parse_bottom_expr(parser p) -> @ast.expr {
}
case (token.SELF) {
log "parsing a self-call...";
p.bump();
expect(p, token.DOT);
// The rest is a call expression.
auto e = parse_bottom_expr(p);
auto e = parse_ident(p);
auto pf = parse_expr;
auto es = parse_seq[@ast.expr](token.LPAREN,
token.RPAREN,

View file

@ -348,6 +348,8 @@ fn to_str(token t) -> str {
/* Object type */
case (OBJ) { ret "obj"; }
case (SELF) { ret "self"; }
/* Comm and task types */
case (CHAN) { ret "chan"; }

View file

@ -88,7 +88,7 @@ type ast_fold[ENV] =
ann a) -> @expr) fold_expr_call,
(fn(&ENV e, &span sp,
@expr f, vec[@expr] args,
ident id, vec[@expr] args,
ann a) -> @expr) fold_expr_call_self,
(fn(&ENV e, &span sp,
@ -566,10 +566,9 @@ fn fold_expr[ENV](&ENV env, ast_fold[ENV] fld, &@expr e) -> @expr {
ret fld.fold_expr_call(env_, e.span, ff, aargs, t);
}
case (ast.expr_call_self(?f, ?args, ?t)) {
auto ff = fold_expr(env_, fld, f);
case (ast.expr_call_self(?ident, ?args, ?t)) {
auto aargs = fold_exprs(env_, fld, args);
ret fld.fold_expr_call_self(env_, e.span, ff, aargs, t);
ret fld.fold_expr_call_self(env_, e.span, ident, aargs, t);
}
case (ast.expr_bind(?f, ?args_opt, ?t)) {
@ -1185,9 +1184,9 @@ fn identity_fold_expr_call[ENV](&ENV env, &span sp, @expr f,
ret @respan(sp, ast.expr_call(f, args, a));
}
fn identity_fold_expr_call_self[ENV](&ENV env, &span sp, @expr f,
fn identity_fold_expr_call_self[ENV](&ENV env, &span sp, ident id,
vec[@expr] args, ann a) -> @expr {
ret @respan(sp, ast.expr_call_self(f, args, a));
ret @respan(sp, ast.expr_call_self(id, args, a));
}
fn identity_fold_expr_bind[ENV](&ENV env, &span sp, @expr f,

View file

@ -12,6 +12,7 @@ import std.option.none;
import front.ast;
import front.creader;
import pretty.pprust;
import driver.session;
import middle.ty;
import back.x86;
@ -114,12 +115,14 @@ state type crate_ctxt = rec(session.session sess,
vec[str] path,
std.sha1.sha1 sha);
type self_vt = rec(ValueRef v, @ty.t t);
state type fn_ctxt = rec(ValueRef llfn,
ValueRef lltaskptr,
ValueRef llenv,
ValueRef llretptr,
mutable BasicBlockRef llallocas,
mutable option.t[ValueRef] llself,
mutable option.t[self_vt] llself,
mutable option.t[ValueRef] lliterbody,
hashmap[ast.def_id, ValueRef] llargs,
hashmap[ast.def_id, ValueRef] llobjfields,
@ -3783,12 +3786,12 @@ fn trans_path(@block_ctxt cx, &ast.path p, &option.t[ast.def] dopt,
fail;
}
fn trans_field(@block_ctxt cx, &ast.span sp, @ast.expr base,
fn trans_field(@block_ctxt cx, &ast.span sp, ValueRef v, @ty.t t0,
&ast.ident field, &ast.ann ann) -> lval_result {
auto r = trans_expr(cx, base);
auto t = ty.expr_ty(base);
r = autoderef(r.bcx, r.val, t);
t = autoderefed_ty(t);
auto r = autoderef(cx, v, t0);
auto t = autoderefed_ty(t0);
alt (t.struct) {
case (ty.ty_tup(_)) {
let uint ix = ty.field_num(cx.fcx.ccx.sess, sp, field);
@ -3881,11 +3884,30 @@ fn trans_lval(@block_ctxt cx, @ast.expr e) -> lval_result {
ret trans_path(cx, p, dopt, ann);
}
case (ast.expr_field(?base, ?ident, ?ann)) {
ret trans_field(cx, e.span, base, ident, ann);
auto r = trans_expr(cx, base);
auto t = ty.expr_ty(base);
ret trans_field(r.bcx, e.span, r.val, t, ident, ann);
}
case (ast.expr_index(?base, ?idx, ?ann)) {
ret trans_index(cx, e.span, base, idx, ann);
}
// Kind of bizarre to pass an *entire* self-call here...but let's try
// it
case (ast.expr_call_self(?ident, _, ?ann)) {
alt (cx.fcx.llself) {
case (some[self_vt](?s_vt)) {
auto r = s_vt.v;
auto t = s_vt.t;
ret trans_field(cx, e.span, r, t, ident, ann);
}
case (_) {
// Shouldn't happen.
fail;
}
}
}
case (_) { cx.fcx.ccx.sess.unimpl("expr variant in trans_lval"); }
}
fail;
@ -4462,70 +4484,6 @@ fn trans_call(@block_ctxt cx, @ast.expr f,
ret res(bcx, retval);
}
fn trans_call_self(@block_ctxt cx, @ast.expr f,
option.t[ValueRef] lliterbody,
vec[@ast.expr] args,
&ast.ann ann) -> result {
log "translating a self-call";
auto f_res = trans_lval(cx, f);
auto faddr = f_res.res.val;
auto llenv = C_null(T_opaque_closure_ptr(cx.fcx.ccx.tn));
alt (f_res.llobj) {
case (some[ValueRef](_)) {
// It's a vtbl entry.
faddr = f_res.res.bcx.build.Load(faddr);
}
case (none[ValueRef]) {
// It's a closure.
auto bcx = f_res.res.bcx;
auto pair = faddr;
faddr = bcx.build.GEP(pair, vec(C_int(0),
C_int(abi.fn_field_code)));
faddr = bcx.build.Load(faddr);
auto llclosure = bcx.build.GEP(pair,
vec(C_int(0),
C_int(abi.fn_field_box)));
llenv = bcx.build.Load(llclosure);
}
}
auto fn_ty = ty.expr_ty(f);
auto ret_ty = ty.ann_to_type(ann);
auto args_res = trans_args(f_res.res.bcx,
llenv, f_res.llobj,
f_res.generic,
lliterbody,
args, fn_ty);
auto bcx = args_res._0;
auto llargs = args_res._1;
auto llretslot = args_res._2;
/*
log "calling: " + val_str(cx.fcx.ccx.tn, faddr);
for (ValueRef arg in llargs) {
log "arg: " + val_str(cx.fcx.ccx.tn, arg);
}
*/
bcx.build.FastCall(faddr, llargs);
auto retval = C_nil();
if (!ty.type_is_nil(ret_ty)) {
retval = load_scalar_or_boxed(bcx, llretslot, ret_ty);
// Retval doesn't correspond to anything really tangible in the frame,
// but it's a ref all the same, so we put a note here to drop it when
// we're done in this scope.
find_scope_cx(cx).cleanups +=
vec(clean(bind drop_ty(_, retval, ret_ty)));
}
ret res(bcx, retval);
}
fn trans_tup(@block_ctxt cx, vec[ast.elt] elts,
&ast.ann ann) -> result {
auto bcx = cx;
@ -4762,8 +4720,9 @@ fn trans_expr(@block_ctxt cx, @ast.expr e) -> result {
ret trans_call(cx, f, none[ValueRef], args, ann);
}
case (ast.expr_call_self(?f, ?args, ?ann)) {
ret trans_call_self(cx, f, none[ValueRef], args, ann);
case (ast.expr_call_self(?ident, ?args, ?ann)) {
// A weird hack to make self-calls work.
ret trans_call(cx, e, none[ValueRef], args, ann);
}
case (ast.expr_cast(?e, _, ?ann)) {
@ -5473,7 +5432,7 @@ fn new_fn_ctxt(@crate_ctxt cx,
llenv=llenv,
llretptr=llretptr,
mutable llallocas = llallocas,
mutable llself=none[ValueRef],
mutable llself=none[self_vt],
mutable lliterbody=none[ValueRef],
llargs=llargs,
llobjfields=llobjfields,
@ -5492,27 +5451,24 @@ fn new_fn_ctxt(@crate_ctxt cx,
fn create_llargs_for_fn_args(&@fn_ctxt cx,
ast.proto proto,
option.t[TypeRef] ty_self,
option.t[tup(TypeRef, @ty.t)] ty_self,
@ty.t ret_ty,
&vec[ast.arg] args,
&vec[ast.ty_param] ty_params) {
alt (ty_self) {
case (some[TypeRef](_)) {
cx.llself = some[ValueRef](cx.llenv);
}
case (_) {
}
}
auto arg_n = 3u;
if (ty_self == none[TypeRef]) {
for (ast.ty_param tp in ty_params) {
auto llarg = llvm.LLVMGetParam(cx.llfn, arg_n);
check (llarg as int != 0);
cx.lltydescs.insert(tp.id, llarg);
arg_n += 1u;
alt (ty_self) {
case (some[tup(TypeRef, @ty.t)](?tt)) {
cx.llself = some[self_vt](rec(v = cx.llenv, t = tt._1));
}
case (none[tup(TypeRef, @ty.t)]) {
for (ast.ty_param tp in ty_params) {
auto llarg = llvm.LLVMGetParam(cx.llfn, arg_n);
check (llarg as int != 0);
cx.lltydescs.insert(tp.id, llarg);
arg_n += 1u;
}
}
}
@ -5536,17 +5492,17 @@ fn create_llargs_for_fn_args(&@fn_ctxt cx,
// were passed and whatnot. Apparently mem2reg will mop up.
fn copy_any_self_to_alloca(@fn_ctxt fcx,
option.t[TypeRef] ty_self) {
option.t[tup(TypeRef, @ty.t)] ty_self) {
auto bcx = llallocas_block_ctxt(fcx);
alt (fcx.llself) {
case (some[ValueRef](?self_v)) {
case (some[self_vt](?s_vt)) {
alt (ty_self) {
case (some[TypeRef](?self_t)) {
auto a = alloca(bcx, self_t);
bcx.build.Store(self_v, a);
fcx.llself = some[ValueRef](a);
case (some[tup(TypeRef, @ty.t)](?tt)) {
auto a = alloca(bcx, tt._0);
bcx.build.Store(s_vt.v, a);
fcx.llself = some[self_vt](rec(v = a, t = s_vt.t));
}
}
}
@ -5608,7 +5564,7 @@ fn ret_ty_of_fn(ast.ann ann) -> @ty.t {
ret ret_ty_of_fn_ty(ty.ann_to_type(ann));
}
fn populate_fn_ctxt_from_llself(@fn_ctxt fcx, ValueRef llself) {
fn populate_fn_ctxt_from_llself(@fn_ctxt fcx, self_vt llself) {
auto bcx = llallocas_block_ctxt(fcx);
let vec[@ty.t] field_tys = vec();
@ -5625,7 +5581,7 @@ fn populate_fn_ctxt_from_llself(@fn_ctxt fcx, ValueRef llself) {
let TypeRef llobj_box_ty = T_obj_ptr(bcx.fcx.ccx.tn, n_typarams);
auto box_cell =
bcx.build.GEP(llself,
bcx.build.GEP(llself.v,
vec(C_int(0),
C_int(abi.obj_field_box)));
@ -5678,7 +5634,7 @@ fn populate_fn_ctxt_from_llself(@fn_ctxt fcx, ValueRef llself) {
}
fn trans_fn(@crate_ctxt cx, &ast._fn f, ast.def_id fid,
option.t[TypeRef] ty_self,
option.t[tup(TypeRef, @ty.t)] ty_self,
&vec[ast.ty_param] ty_params, &ast.ann ann) {
auto llfndecl = cx.item_ids.get(fid);
@ -5691,7 +5647,7 @@ fn trans_fn(@crate_ctxt cx, &ast._fn f, ast.def_id fid,
copy_any_self_to_alloca(fcx, ty_self);
alt (fcx.llself) {
case (some[ValueRef](?llself)) {
case (some[self_vt](?llself)) {
populate_fn_ctxt_from_llself(fcx, llself);
}
case (_) {
@ -5714,7 +5670,9 @@ fn trans_fn(@crate_ctxt cx, &ast._fn f, ast.def_id fid,
new_builder(fcx.llallocas).Br(lltop);
}
fn trans_vtbl(@crate_ctxt cx, TypeRef self_ty,
fn trans_vtbl(@crate_ctxt cx,
TypeRef llself_ty,
@ty.t self_ty,
&ast._obj ob,
&vec[ast.ty_param] ty_params) -> ValueRef {
let vec[ValueRef] methods = vec();
@ -5732,7 +5690,7 @@ fn trans_vtbl(@crate_ctxt cx, TypeRef self_ty,
alt (node_ann_type(cx, m.node.ann).struct) {
case (ty.ty_fn(?proto, ?inputs, ?output)) {
llfnty = type_of_fn_full(cx, proto,
some[TypeRef](self_ty),
some[TypeRef](llself_ty),
inputs, output,
_vec.len[ast.ty_param](ty_params));
}
@ -5744,7 +5702,8 @@ fn trans_vtbl(@crate_ctxt cx, TypeRef self_ty,
cx.item_ids.insert(m.node.id, llfn);
cx.item_symbols.insert(m.node.id, s);
trans_fn(mcx, m.node.meth, m.node.id, some[TypeRef](self_ty),
trans_fn(mcx, m.node.meth, m.node.id,
some[tup(TypeRef, @ty.t)](tup(llself_ty, self_ty)),
ty_params, m.node.ann);
methods += vec(llfn);
}
@ -5775,7 +5734,8 @@ fn trans_obj(@crate_ctxt cx, &ast._obj ob, ast.def_id oid,
auto fcx = new_fn_ctxt(cx, llctor_decl);
create_llargs_for_fn_args(fcx, ast.proto_fn,
none[TypeRef], ret_ty_of_fn(ann),
none[tup(TypeRef, @ty.t)],
ret_ty_of_fn(ann),
fn_args, ty_params);
let vec[ty.arg] arg_tys = arg_tys_of_fn(ann);
@ -5784,9 +5744,10 @@ fn trans_obj(@crate_ctxt cx, &ast._obj ob, ast.def_id oid,
auto bcx = new_top_block_ctxt(fcx);
auto lltop = bcx.llbb;
auto llself_ty = type_of(cx, ret_ty_of_fn(ann));
auto self_ty = ret_ty_of_fn(ann);
auto llself_ty = type_of(cx, self_ty);
auto pair = bcx.fcx.llretptr;
auto vtbl = trans_vtbl(cx, llself_ty, ob, ty_params);
auto vtbl = trans_vtbl(cx, llself_ty, self_ty, ob, ty_params);
auto pair_vtbl = bcx.build.GEP(pair,
vec(C_int(0),
C_int(abi.obj_field_vtbl)));
@ -5907,7 +5868,8 @@ fn trans_tag_variant(@crate_ctxt cx, ast.def_id tag_id,
auto fcx = new_fn_ctxt(cx, llfndecl);
create_llargs_for_fn_args(fcx, ast.proto_fn,
none[TypeRef], ret_ty_of_fn(variant.node.ann),
none[tup(TypeRef, @ty.t)],
ret_ty_of_fn(variant.node.ann),
fn_args, ty_params);
let vec[@ty.t] ty_param_substs = vec();
@ -5995,7 +5957,7 @@ fn trans_item(@crate_ctxt cx, &ast.item item) {
alt (item.node) {
case (ast.item_fn(?name, ?f, ?tps, ?fid, ?ann)) {
auto sub_cx = extend_path(cx, name);
trans_fn(sub_cx, f, fid, none[TypeRef], tps, ann);
trans_fn(sub_cx, f, fid, none[tup(TypeRef, @ty.t)], tps, ann);
}
case (ast.item_obj(?name, ?ob, ?tps, ?oid, ?ann)) {
auto sub_cx = @rec(obj_typarams=tps,
@ -6803,7 +6765,7 @@ fn trans_vec_append_glue(@crate_ctxt cx) {
llenv=C_null(T_ptr(T_nil())),
llretptr=C_null(T_ptr(T_nil())),
mutable llallocas = llallocas,
mutable llself=none[ValueRef],
mutable llself=none[self_vt],
mutable lliterbody=none[ValueRef],
llargs=new_def_hash[ValueRef](),
llobjfields=new_def_hash[ValueRef](),

View file

@ -2110,6 +2110,18 @@ fn check_expr(&@fn_ctxt fcx, @ast.expr expr) -> @ast.expr {
ast.expr_call(f_1, args_1, ann));
}
case (ast.expr_call_self(?ident, ?args, _)) {
// FIXME: What's to check here?
// FIXME: These two lines are ripped off from the expr_call case;
// what should they be really?
auto rt_1 = plain_ty(ty.ty_nil);
auto ann = triv_ann(rt_1);
ret @fold.respan[ast.expr_](expr.span,
ast.expr_call_self(ident, args, ann));
}
case (ast.expr_spawn(?dom, ?name, ?f, ?args, _)) {
auto result = check_call(fcx, f, args);
auto f_1 = result._0;

View file

@ -454,9 +454,9 @@ impure fn print_expr(ps s, &@ast.expr expr) {
commasep_exprs(s, args);
pclose(s);
}
case (ast.expr_call_self(?func,?args,_)) {
case (ast.expr_call_self(?ident,?args,_)) {
wrd(s.s, "self.");
print_expr(s, func);
print_ident(s, ident);
popen(s);
commasep_exprs(s, args);
pclose(s);
@ -723,6 +723,10 @@ impure fn print_decl(ps s, @ast.decl decl) {
end(s.s);
}
impure fn print_ident(ps s, ast.ident ident) {
wrd(s.s, ident);
}
impure fn print_for_decl(ps s, @ast.decl decl) {
alt (decl.node) {
case (ast.decl_local(?loc)) {