Skip to content
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

More work on anonymous objects. #399

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: 2 additions & 0 deletions src/comp/back/abi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ const int obj_field_box = 1;
const int obj_body_elt_tydesc = 0;
const int obj_body_elt_typarams = 1;
const int obj_body_elt_fields = 2;
const int obj_body_elt_with_obj = 3; /* The base object to which an anonymous
* object is attached */

const int fn_field_code = 0;
const int fn_field_box = 1;
Expand Down
2 changes: 1 addition & 1 deletion src/comp/front/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -379,7 +379,7 @@ type anon_obj = rec(
option::t[vec[obj_field]] fields,
vec[@method] methods,
// with_obj: the original object being extended, if it exists.
option::t[ident] with_obj);
option::t[@expr] with_obj);

type _mod = rec(vec[@view_item] view_items,
vec[@item] items);
Expand Down
4 changes: 2 additions & 2 deletions src/comp/front/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -820,13 +820,13 @@ fn parse_bottom_expr(&parser p) -> @ast::expr {
}

let vec[@ast::method] meths = [];
let option::t[ast::ident] with_obj = none[ast::ident];
let option::t[@ast::expr] with_obj = none[@ast::expr];

expect(p, token::LBRACE);

while (p.peek() != token::RBRACE) {
if (eat_word(p, "with")) {
with_obj = some[ast::ident](parse_ident(p));
with_obj = some[@ast::expr](parse_expr(p));
} else {
vec::push[@ast::method](meths,
parse_method(p));
Expand Down
13 changes: 7 additions & 6 deletions src/comp/middle/fold.rs
Original file line number Diff line number Diff line change
Expand Up @@ -336,7 +336,7 @@ type ast_fold[ENV] =
(fn(&ENV e,
&option::t[vec[ast::obj_field]] fields,
&vec[@ast::method] methods,
&option::t[ident] with_obj)
&option::t[@ast::expr] with_obj)
-> ast::anon_obj) fold_anon_obj,

// Env updates.
Expand Down Expand Up @@ -1001,11 +1001,11 @@ fn fold_anon_obj[ENV](&ENV env, &ast_fold[ENV] fld, &ast::anon_obj ob)
}

// with_obj
let option::t[ast::ident] with_obj = none[ast::ident];
let option::t[@ast::expr] with_obj = none[@ast::expr];
alt (ob.with_obj) {
case (none[ast::ident]) { }
case (some[ast::ident](?i)) {
with_obj = some[ast::ident](i);
case (none[@ast::expr]) { }
case (some[@ast::expr](?e)) {
with_obj = some[@ast::expr](fold_expr(env, fld, e));
}
}

Expand Down Expand Up @@ -1665,7 +1665,8 @@ fn identity_fold_obj[ENV](&ENV e,
fn identity_fold_anon_obj[ENV](&ENV e,
&option::t[vec[ast::obj_field]] fields,
&vec[@ast::method] methods,
&option::t[ident] with_obj) -> ast::anon_obj {
&option::t[@ast::expr] with_obj)
-> ast::anon_obj {
ret rec(fields=fields, methods=methods, with_obj=with_obj);
}

Expand Down
78 changes: 77 additions & 1 deletion src/comp/middle/trans.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4576,7 +4576,8 @@ fn trans_lval(&@block_ctxt cx, &@ast::expr e) -> lval_result {
}
case (_) {
cx.fcx.lcx.ccx.sess.span_unimpl(e.span,
"expr variant in trans_lval");
"expr variant in trans_lval: "
+ util::common::expr_to_str(e));
}
}
fail;
Expand Down Expand Up @@ -5547,6 +5548,10 @@ fn trans_expr(&@block_ctxt cx, &@ast::expr e) -> result {
ret trans_spawn(cx, dom, name, func, args, ann);
}

case (ast::expr_anon_obj(?anon_obj, ?tps, ?odid, ?ann)) {
ret trans_anon_obj(cx, e.span, anon_obj, tps, odid, ann);
}

case (_) {
// The expression is an lvalue. Fall through.
}
Expand Down Expand Up @@ -6111,6 +6116,77 @@ fn recv_val(&@block_ctxt cx, ValueRef lhs, &@ast::expr rhs,
ret res(bcx, lhs);
}


/*

Suppose we create an anonymous object my_b from a regular object a:

obj a() {
fn foo() -> int {
ret 2;
}
fn bar() -> int {
ret self.foo();
}
}

auto my_a = a();
auto my_b = obj { fn baz() -> int { ret self.foo() } with my_a };

Here we're extending the my_a object with an additional method baz, creating
an object my_b. Since it's an object, my_b is a pair of a vtable pointer and
a body pointer:

my_b: [vtbl* | body*]

my_b's vtable has entries for foo, bar, and baz, whereas my_a's vtable has
only foo and bar. my_b's 3-entry vtable consists of two forwarding functions
and one real method.

my_b's body just contains the pair a: [ a_vtable | a_body ], wrapped up with
any additional fields that my_b added. None were added, so my_b is just the
wrapped inner object.

*/
fn trans_anon_obj(&@block_ctxt cx, &ast::span sp,
&ast::anon_obj anon_obj,
&vec[ast::ty_param] ty_params,
&ast::obj_def_ids oid,
&ast::ann ann) -> result {

let option::t[result] with_obj_val = none[result];
alt (anon_obj.with_obj) {
case (none[@ast::expr]) { }
case (some[@ast::expr](?e)) {
// Translating with_obj returns a pointer to a 2-word value. We
// want to allocate space for this value in our outer object, then
// copy it into the outer object.
with_obj_val = some[result](trans_expr(cx, e));
}
}

// For the anon obj's additional fields, if any exist, translate object
// constructor arguments to function arguments.
let option::t[vec[ast::obj_field]] addtl_fields
= none[vec[ast::obj_field]];
let vec[ast::arg] addtl_fn_args = [];

alt (anon_obj.fields) {
case (none[vec[ast::obj_field]]) { }
case (some[vec[ast::obj_field]](?fields)) {
for (ast::obj_field f in fields) {
addtl_fn_args += [rec(mode=ast::alias, ty=f.ty,
ident=f.ident, id=f.id)];
}
}
}

// TODO: everything else.

cx.fcx.lcx.ccx.sess.unimpl("support for anonymous objects");
fail;
}

fn init_local(&@block_ctxt cx, &@ast::local local) -> result {

// Make a note to drop this slot on the way out.
Expand Down
12 changes: 12 additions & 0 deletions src/comp/middle/tstate/pre_post_conditions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ import front::ast::expr_assert;
import front::ast::expr_cast;
import front::ast::expr_for;
import front::ast::expr_for_each;
import front::ast::expr_anon_obj;
import front::ast::stmt_decl;
import front::ast::stmt_expr;
import front::ast::block;
Expand Down Expand Up @@ -556,6 +557,17 @@ fn find_pre_post_expr(&fn_ctxt fcx, @expr e) -> () {
find_pre_post_expr(fcx, expanded);
copy_pre_post(fcx.ccx, a, expanded);
}
case (expr_anon_obj(?anon_obj, _, _, ?a)) {
alt (anon_obj.with_obj) {
case (some[@expr](?ex)) {
find_pre_post_expr(fcx, ex);
copy_pre_post(fcx.ccx, a, ex);
}
case (none[@expr]) {
clear_pp(expr_pp(fcx.ccx, e));
}
}
}
}
}

Expand Down
15 changes: 15 additions & 0 deletions src/comp/middle/tstate/states.rs
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ import front::ast::expr_assert;
import front::ast::expr_cast;
import front::ast::expr_for;
import front::ast::expr_for_each;
import front::ast::expr_anon_obj;
import front::ast::stmt_decl;
import front::ast::stmt_expr;
import front::ast::block;
Expand Down Expand Up @@ -578,6 +579,20 @@ fn find_pre_post_state_expr(&fn_ctxt fcx, &prestate pres, @expr e) -> bool {
case (expr_self_method(_, ?a)) {
ret pure_exp(fcx.ccx, a, pres);
}
case (expr_anon_obj(?anon_obj, _, _,?a)) {
alt (anon_obj.with_obj) {
case (some[@expr](?e)) {
changed = find_pre_post_state_expr(fcx, pres, e);
changed = extend_prestate_ann(fcx.ccx, a, pres) || changed;
changed = extend_poststate_ann(fcx.ccx, a,
expr_poststate(fcx.ccx, e)) || changed;
ret changed;
}
case (none[@expr]) {
ret pure_exp(fcx.ccx, a, pres);
}
}
}
}
}

Expand Down
Loading