From b8bb2e118e9815316320f946ef3fc7e6909ed7c9 Mon Sep 17 00:00:00 2001 From: Lindsey Kuper Date: Tue, 5 Apr 2011 14:18:44 -0700 Subject: [PATCH] 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() --- src/comp/front/ast.rs | 2 +- src/comp/front/parser.rs | 4 +- src/comp/front/token.rs | 2 + src/comp/middle/fold.rs | 11 ++- src/comp/middle/trans.rs | 178 +++++++++++++++----------------------- src/comp/middle/typeck.rs | 12 +++ src/comp/pretty/pprust.rs | 8 +- 7 files changed, 99 insertions(+), 118 deletions(-) diff --git a/src/comp/front/ast.rs b/src/comp/front/ast.rs index 61450a1bd9a..d41e6d60686 100644 --- a/src/comp/front/ast.rs +++ b/src/comp/front/ast.rs @@ -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); diff --git a/src/comp/front/parser.rs b/src/comp/front/parser.rs index 1e0a9042eef..31e470be84b 100644 --- a/src/comp/front/parser.rs +++ b/src/comp/front/parser.rs @@ -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, diff --git a/src/comp/front/token.rs b/src/comp/front/token.rs index 5ac9d662f1c..dcfafadf202 100644 --- a/src/comp/front/token.rs +++ b/src/comp/front/token.rs @@ -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"; } diff --git a/src/comp/middle/fold.rs b/src/comp/middle/fold.rs index d7a18783cbb..77c898366af 100644 --- a/src/comp/middle/fold.rs +++ b/src/comp/middle/fold.rs @@ -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, diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 6e3550bde35..b61aa244ad5 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -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](), diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs index 10cbd6d5be8..e105c7a9106 100644 --- a/src/comp/middle/typeck.rs +++ b/src/comp/middle/typeck.rs @@ -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; diff --git a/src/comp/pretty/pprust.rs b/src/comp/pretty/pprust.rs index 28f64c89d2c..7e0fb6cb7c9 100644 --- a/src/comp/pretty/pprust.rs +++ b/src/comp/pretty/pprust.rs @@ -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)) {