about summary refs log tree commit diff
diff options
context:
space:
mode:
authorLindsey Kuper <lkuper@mozilla.com>2011-04-05 14:18:44 -0700
committerGraydon Hoare <graydon@mozilla.com>2011-04-05 14:54:48 -0700
commitb8bb2e118e9815316320f946ef3fc7e6909ed7c9 (patch)
tree6b550692b0b086bde56c621f5ffd428e7dcc1b08
parent8703c8067fb8a22ec9b296efea162aac3e7f9521 (diff)
downloadrust-b8bb2e118e9815316320f946ef3fc7e6909ed7c9.tar.gz
rust-b8bb2e118e9815316320f946ef3fc7e6909ed7c9.zip
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()
-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 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)) {