Skip to content

Support for self-calls that take arguments. #317

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/comp/front/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(ident, vec[@expr], ann);
expr_self_method(ident, 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);
Expand Down
13 changes: 10 additions & 3 deletions src/comp/front/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -893,14 +893,14 @@ impure fn parse_bottom_expr(parser p) -> @ast.expr {
p.bump();
expect(p, token.DOT);
// The rest is a call expression.
auto e = parse_ident(p);
let @ast.expr f = parse_self_method(p);
auto pf = parse_expr;
auto es = parse_seq[@ast.expr](token.LPAREN,
token.RPAREN,
some(token.COMMA),
pf, p);
hi = es.span;
ex = ast.expr_call_self(e, es.node, ast.ann_none);
ex = ast.expr_call(f, es.node, ast.ann_none);
}

case (_) {
Expand Down Expand Up @@ -966,6 +966,13 @@ impure fn extend_expr_by_ident(parser p, span lo, span hi,
ret @spanned(lo, hi, e_);
}

impure fn parse_self_method(parser p) -> @ast.expr {
auto lo = p.get_span();
let ast.ident f_name = parse_ident(p);
auto hi = p.get_span();
ret @spanned(lo, hi, ast.expr_self_method(f_name, ast.ann_none));
}

impure fn parse_dot_or_call_expr(parser p) -> @ast.expr {
auto lo = p.get_span();
auto e = parse_bottom_expr(p);
Expand Down Expand Up @@ -1634,7 +1641,7 @@ fn stmt_ends_with_semi(@ast.stmt stmt) -> bool {
case (ast.expr_tup(_,_)) { ret true; }
case (ast.expr_rec(_,_,_)) { ret true; }
case (ast.expr_call(_,_,_)) { ret true; }
case (ast.expr_call_self(_,_,_)){ ret true; }
case (ast.expr_self_method(_,_)){ ret false; }
case (ast.expr_binary(_,_,_,_)) { ret true; }
case (ast.expr_unary(_,_,_)) { ret true; }
case (ast.expr_lit(_,_)) { ret true; }
Expand Down
18 changes: 8 additions & 10 deletions src/comp/middle/fold.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,7 @@ type ast_fold[ENV] =
ann a) -> @expr) fold_expr_call,

(fn(&ENV e, &span sp,
ident id, vec[@expr] args,
ann a) -> @expr) fold_expr_call_self,
ident id, ann a) -> @expr) fold_expr_self_method,

(fn(&ENV e, &span sp,
@expr f, vec[option.t[@expr]] args,
Expand Down Expand Up @@ -569,9 +568,8 @@ 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(?ident, ?args, ?t)) {
auto aargs = fold_exprs(env_, fld, args);
ret fld.fold_expr_call_self(env_, e.span, ident, aargs, t);
case (ast.expr_self_method(?ident, ?t)) {
ret fld.fold_expr_self_method(env_, e.span, ident, t);
}

case (ast.expr_bind(?f, ?args_opt, ?t)) {
Expand Down Expand Up @@ -1187,9 +1185,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, ident id,
vec[@expr] args, ann a) -> @expr {
ret @respan(sp, ast.expr_call_self(id, args, a));
fn identity_fold_expr_self_method[ENV](&ENV env, &span sp, ident id,
ann a) -> @expr {
ret @respan(sp, ast.expr_self_method(id, a));
}

fn identity_fold_expr_bind[ENV](&ENV env, &span sp, @expr f,
Expand Down Expand Up @@ -1601,8 +1599,8 @@ fn new_identity_fold[ENV]() -> ast_fold[ENV] {
fold_expr_tup = bind identity_fold_expr_tup[ENV](_,_,_,_),
fold_expr_rec = bind identity_fold_expr_rec[ENV](_,_,_,_,_),
fold_expr_call = bind identity_fold_expr_call[ENV](_,_,_,_,_),
fold_expr_call_self
= bind identity_fold_expr_call_self[ENV](_,_,_,_,_),
fold_expr_self_method
= bind identity_fold_expr_self_method[ENV](_,_,_,_),
fold_expr_bind = bind identity_fold_expr_bind[ENV](_,_,_,_,_),
fold_expr_spawn = bind identity_fold_expr_spawn[ENV](_,_,_,_,_,_,_),
fold_expr_binary = bind identity_fold_expr_binary[ENV](_,_,_,_,_,_),
Expand Down
10 changes: 1 addition & 9 deletions src/comp/middle/trans.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3911,10 +3911,7 @@ fn trans_lval(@block_ctxt cx, @ast.expr e) -> lval_result {
C_int(abi.box_rc_field_body)));
ret lval_mem(sub.bcx, val);
}

// Kind of bizarre to pass an *entire* self-call here...but let's try
// it
case (ast.expr_call_self(?ident, _, ?ann)) {
case (ast.expr_self_method(?ident, ?ann)) {
alt (cx.fcx.llself) {
case (some[self_vt](?s_vt)) {
auto r = s_vt.v;
Expand Down Expand Up @@ -4766,11 +4763,6 @@ fn trans_expr(@block_ctxt cx, @ast.expr e) -> result {
ret trans_call(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)) {
ret trans_cast(cx, e, ann);
}
Expand Down
2 changes: 1 addition & 1 deletion src/comp/middle/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -764,7 +764,7 @@ fn expr_ty(@ast.expr expr) -> @t {
case (ast.expr_rec(_, _, ?ann)) { ret ann_to_type(ann); }
case (ast.expr_bind(_, _, ?ann)) { ret ann_to_type(ann); }
case (ast.expr_call(_, _, ?ann)) { ret ann_to_type(ann); }
case (ast.expr_call_self(_, _, ?ann)) { ret ann_to_type(ann); }
case (ast.expr_self_method(_, ?ann)) { ret ann_to_type(ann); }
case (ast.expr_spawn(_, _, _, _, ?ann))
{ ret ann_to_type(ann); }
case (ast.expr_binary(_, _, _, ?ann)) { ret ann_to_type(ann); }
Expand Down
61 changes: 48 additions & 13 deletions src/comp/middle/typeck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ import std.option;
import std.option.none;
import std.option.some;

import pretty.pprust;

import util.typestate_ann.ts_ann;

type ty_table = hashmap[ast.def_id, @ty.t];
Expand All @@ -49,6 +51,7 @@ type crate_ctxt = rec(session.session sess,
ty.type_cache type_cache,
@ty_item_table item_items,
vec[ast.obj_field] obj_fields,
option.t[ast.def_id] this_obj,
mutable int next_var_id);

type fn_ctxt = rec(@ty.t ret_ty,
Expand Down Expand Up @@ -1242,10 +1245,9 @@ fn demand_expr_full(&@fn_ctxt fcx, @ty.t expected, @ast.expr e,
ann_to_type(ann), adk);
e_1 = ast.expr_call(sube, es, triv_ann(t));
}
case (ast.expr_call_self(?sube, ?es, ?ann)) {
auto t = demand_full(fcx, e.span, expected,
ann_to_type(ann), adk);
e_1 = ast.expr_call_self(sube, es, triv_ann(t));
case (ast.expr_self_method(?id, ?ann)) {
auto t = demand(fcx, e.span, expected, ann_to_type(ann));
e_1 = ast.expr_self_method(id, triv_ann(t));
}
case (ast.expr_binary(?bop, ?lhs, ?rhs, ?ann)) {
auto t = demand(fcx, e.span, expected, ann_to_type(ann));
Expand Down Expand Up @@ -1572,6 +1574,8 @@ fn check_pat(&@fn_ctxt fcx, @ast.pat pat) -> @ast.pat {
}

fn check_expr(&@fn_ctxt fcx, @ast.expr expr) -> @ast.expr {
// log "typechecking expr " + pretty.pprust.expr_to_str(expr);

// A generic function to factor out common logic from call and bind
// expressions.
fn check_call_or_bind(&@fn_ctxt fcx, &@ast.expr f,
Expand Down Expand Up @@ -2125,16 +2129,44 @@ 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?
case (ast.expr_self_method(?id, _)) {
auto t = plain_ty(ty.ty_nil);
let @ty.t this_obj_ty;

// Grab the type of the current object
auto this_obj_id = fcx.ccx.this_obj;
alt (this_obj_id) {
case (some[ast.def_id](?def_id)) {
auto this_obj_tpt = fcx.ccx.type_cache.find(def_id);
alt (this_obj_tpt) {
case (some[ty_params_opt_and_ty](?tpt)) {
this_obj_ty = tpt._1;
}
case (_) { fail; }
}
}
case (_) { fail; }
}


// 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);
// Grab this method's type out of the current object type

// this_obj_ty is an @ty.t
alt (this_obj_ty.struct) {
case (ty.ty_obj(?methods)) {
for (ty.method method in methods) {
if (method.ident == id) {
t = ty.method_ty_to_fn_ty(method);
}
}
}
case (_) { fail; }
}

auto ann = triv_ann(t);

ret @fold.respan[ast.expr_](expr.span,
ast.expr_call_self(ident, args, ann));
ast.expr_self_method(id, ann));
}

case (ast.expr_spawn(?dom, ?name, ?f, ?args, _)) {
Expand Down Expand Up @@ -2596,8 +2628,10 @@ fn check_item_fn(&@crate_ctxt ccx, &span sp, ast.ident ident, &ast._fn f,

fn update_obj_fields(&@crate_ctxt ccx, @ast.item i) -> @crate_ctxt {
alt (i.node) {
case (ast.item_obj(_, ?ob, _, _, _)) {
ret @rec(obj_fields = ob.fields with *ccx);
case (ast.item_obj(_, ?ob, _, ?obj_def_ids, _)) {
let ast.def_id di = obj_def_ids.ty;
ret @rec(obj_fields = ob.fields,
this_obj = some[ast.def_id](di) with *ccx);
}
case (_) {
}
Expand All @@ -2617,6 +2651,7 @@ fn check_crate(session.session sess, @ast.crate crate) -> typecheck_result {
type_cache=result._1,
item_items=result._2,
obj_fields=fields,
this_obj=none[ast.def_id],
mutable next_var_id=0);

auto fld = fold.new_identity_fold[@crate_ctxt]();
Expand Down
5 changes: 1 addition & 4 deletions src/comp/pretty/pprust.rs
Original file line number Diff line number Diff line change
Expand Up @@ -454,12 +454,9 @@ impure fn print_expr(ps s, &@ast.expr expr) {
commasep_exprs(s, args);
pclose(s);
}
case (ast.expr_call_self(?ident,?args,_)) {
case (ast.expr_self_method(?ident,_)) {
wrd(s.s, "self.");
print_ident(s, ident);
popen(s);
commasep_exprs(s, args);
pclose(s);
}
case (ast.expr_bind(?func,?args,_)) {
impure fn print_opt(ps s, &option.t[@ast.expr] expr) {
Expand Down
19 changes: 19 additions & 0 deletions src/test/run-pass/obj-self-2.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// xfail-boot
fn main() {

obj foo() {
impure fn m1(mutable int i) {
i += 1;
log "hi!";
}
impure fn m2(mutable int i) {
i += 1;
self.m1(i);
}
}

auto a = foo();
let int i = 0;
a.m1(i);
a.m2(i);
}
31 changes: 31 additions & 0 deletions src/test/run-pass/obj-self-3.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// xfail-boot
fn main() {

obj foo() {
impure fn m1(mutable int i) -> int {
i += 1;
ret i;
}
impure fn m2(mutable int i) -> int {
ret self.m1(i);
}
impure fn m3(mutable int i) -> int {
i += 1;
ret self.m1(i);
}
}

auto a = foo();
let int i = 0;

// output should be: 0, 1, 2, 4
log i;
i = a.m1(i);
log i;
i = a.m2(i);
log i;
i = a.m3(i);
log i;
}