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:
parent
8703c8067f
commit
b8bb2e118e
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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"; }
|
||||
|
@ -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,
|
||||
|
@ -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](),
|
||||
|
@ -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;
|
||||
|
@ -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)) {
|
||||
|
Loading…
Reference in New Issue
Block a user