aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/comp/front/ast.rs2
-rw-r--r--src/comp/front/parser.rs4
-rw-r--r--src/comp/front/token.rs2
-rw-r--r--src/comp/middle/fold.rs11
-rw-r--r--src/comp/middle/trans.rs178
-rw-r--r--src/comp/middle/typeck.rs12
-rw-r--r--src/comp/pretty/pprust.rs8
7 files changed, 99 insertions, 118 deletions
diff --git a/src/comp/front/ast.rs b/src/comp/front/ast.rs
index 61450a1b..d41e6d60 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 1e0a9042..31e470be 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 5ac9d662..dcfafadf 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 d7a18783..77c89836 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 6e3550bd..b61aa244 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 10cbd6d5..e105c7a9 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 28f64c89..7e0fb6cb 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)) {