Skip to content

Anonymous objects #373

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 8 commits 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
8 changes: 8 additions & 0 deletions src/comp/front/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,7 @@ tag expr_ {
expr_check(@expr, ann);
expr_port(ann);
expr_chan(@expr, ann);
expr_anon_obj(anon_obj, vec[ty_param], obj_def_ids, ann);
}

type lit = spanned[lit_];
Expand Down Expand Up @@ -371,6 +372,13 @@ type _obj = rec(vec[obj_field] fields,
vec[@method] methods,
option::t[@method] dtor);

type anon_obj = rec(
// New fields and methods, if they exist.
option::t[vec[obj_field]] fields,
vec[@method] methods,
// with_obj: the original object being extended, if it exists.
option::t[ident] with_obj);

type _mod = rec(vec[@view_item] view_items,
vec[@item] items);

Expand Down
54 changes: 53 additions & 1 deletion src/comp/front/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -773,6 +773,59 @@ fn parse_bottom_expr(parser p) -> @ast::expr {
some(token::COMMA),
pf, hi, p);
ex = ast::expr_vec(es, mut, p.get_ann());
} else if (eat_word(p, "obj")) {
// Anonymous object

// FIXME: Can anonymous objects have ty params?
auto ty_params = parse_ty_params(p);

// Only make people type () if they're actually adding new fields
let option::t[vec[ast::obj_field]] fields =
none[vec[ast::obj_field]];
if (p.peek() == token::LPAREN) {
auto pf = parse_obj_field;
hi = p.get_hi_pos();
expect(p, token::LPAREN);


fields = some[vec[ast::obj_field]]
(parse_seq_to_end[ast::obj_field]
(token::RPAREN,
some(token::COMMA),
pf, hi, p));
}

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

expect(p, token::LBRACE);

while (p.peek() != token::RBRACE) {
if (eat_word(p, "with")) {
with_obj = some[ast::ident](parse_ident(p));
} else {
_vec::push[@ast::method](meths,
parse_method(p));
}
}

hi = p.get_hi_pos();
expect(p, token::RBRACE);

// fields and methods may be *additional* or *overriding* fields
// and methods if there's a with_obj, or they may be the *only*
// fields and methods if there's no with_obj.

// We don't need to pull ".node" out of fields because it's not a
// "spanned".
let ast::anon_obj ob = rec(fields=fields,
methods=meths,
with_obj=with_obj);

auto odid = rec(ty=p.next_def_id(), ctor=p.next_def_id());

ex = ast::expr_anon_obj(ob, ty_params, odid, p.get_ann());

} else if (eat_word(p, "rec")) {
expect(p, token::LPAREN);
auto fields = vec(parse_field(p));
Expand All @@ -795,7 +848,6 @@ fn parse_bottom_expr(parser p) -> @ast::expr {
} else {
unexpected(p, p.peek());
}

}

ex = ast::expr_rec(fields, base, p.get_ann());
Expand Down
121 changes: 101 additions & 20 deletions src/comp/middle/fold.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ type ast_fold[ENV] =
@rec
(
// Path fold:
(fn(&ENV e, &span sp, &ast::path_ p) -> path) fold_path,
(fn(&ENV e, &span sp, &ast::path_ p)
-> path) fold_path,

// Type folds.
(fn(&ENV e, &span sp) -> @ty) fold_ty_nil,
Expand All @@ -56,10 +57,10 @@ type ast_fold[ENV] =
(fn(&ENV e, &span sp, &vec[mt] elts) -> @ty) fold_ty_tup,

(fn(&ENV e, &span sp,
&vec[ast::ty_field] elts) -> @ty) fold_ty_rec,
&vec[ast::ty_field] elts) -> @ty) fold_ty_rec,

(fn(&ENV e, &span sp,
&vec[ast::ty_method] meths) -> @ty) fold_ty_obj,
&vec[ast::ty_method] meths) -> @ty) fold_ty_obj,

(fn(&ENV e, &span sp,
ast::proto proto,
Expand All @@ -78,7 +79,7 @@ type ast_fold[ENV] =
&ann a) -> @expr) fold_expr_vec,

(fn(&ENV e, &span sp,
&vec[ast::elt] es, &ann a) -> @expr) fold_expr_tup,
&vec[ast::elt] es, &ann a) -> @expr) fold_expr_tup,

(fn(&ENV e, &span sp,
&vec[ast::field] fields,
Expand Down Expand Up @@ -110,7 +111,7 @@ type ast_fold[ENV] =
&ann a) -> @expr) fold_expr_unary,

(fn(&ENV e, &span sp,
&@ast::lit, &ann a) -> @expr) fold_expr_lit,
&@ast::lit, &ann a) -> @expr) fold_expr_lit,

(fn(&ENV e, &span sp,
&@ast::expr e, &@ast::ty ty,
Expand Down Expand Up @@ -186,10 +187,10 @@ type ast_fold[ENV] =
(fn(&ENV e, &span sp, &ann a) -> @expr) fold_expr_cont,

(fn(&ENV e, &span sp,
&option::t[@expr] rv, &ann a) -> @expr) fold_expr_ret,
&option::t[@expr] rv, &ann a) -> @expr) fold_expr_ret,

(fn(&ENV e, &span sp,
&option::t[@expr] rv, &ann a) -> @expr) fold_expr_put,
&option::t[@expr] rv, &ann a) -> @expr) fold_expr_put,

(fn(&ENV e, &span sp,
&@expr e, &ann a) -> @expr) fold_expr_be,
Expand All @@ -209,10 +210,15 @@ type ast_fold[ENV] =
(fn(&ENV e, &span sp,
&@expr e, &ann a) -> @expr) fold_expr_chan,

(fn(&ENV e, &span sp,
&ast::anon_obj ob,
&vec[ast::ty_param] tps,
&ast::obj_def_ids odid,
&ann a) -> @expr) fold_expr_anon_obj,

// Decl folds.
(fn(&ENV e, &span sp,
&@ast::local local) -> @decl) fold_decl_local,
&@ast::local local) -> @decl) fold_decl_local,

(fn(&ENV e, &span sp,
&@item item) -> @decl) fold_decl_item,
Expand All @@ -223,7 +229,7 @@ type ast_fold[ENV] =
&ann a) -> @pat) fold_pat_wild,

(fn(&ENV e, &span sp,
&@ast::lit lit, &ann a) -> @pat) fold_pat_lit,
&@ast::lit lit, &ann a) -> @pat) fold_pat_lit,

(fn(&ENV e, &span sp,
&ident i, &def_id did, &ann a) -> @pat) fold_pat_bind,
Expand Down Expand Up @@ -259,10 +265,11 @@ type ast_fold[ENV] =
&def_id id, &ann a) -> @native_item) fold_native_item_fn,

(fn(&ENV e, &span sp, &ident ident,
&ast::_mod m, &def_id id) -> @item) fold_item_mod,
&ast::_mod m, &def_id id) -> @item) fold_item_mod,

(fn(&ENV e, &span sp, &ident ident,
&ast::native_mod m, &def_id id) -> @item) fold_item_native_mod,
&ast::native_mod m, &def_id id)
-> @item) fold_item_native_mod,

(fn(&ENV e, &span sp, &ident ident,
&@ty t, &vec[ast::ty_param] ty_params,
Expand All @@ -279,13 +286,14 @@ type ast_fold[ENV] =
(fn(&ENV e, &span sp, &ident ident,
&ast::_obj ob,
&vec[ast::ty_param] ty_params,
&ast::obj_def_ids odid, &ann a) -> @item) fold_item_obj,
&ast::obj_def_ids odid, &ann a)
-> @item) fold_item_obj,

// View Item folds.
(fn(&ENV e, &span sp, &ident ident,
&vec[@meta_item] meta_items,
&def_id id,
&option::t[int]) -> @view_item) fold_view_item_use,
&option::t[int]) -> @view_item) fold_view_item_use,

(fn(&ENV e, &span sp, &ident i,
&vec[ident] idents,
Expand All @@ -301,26 +309,33 @@ type ast_fold[ENV] =

(fn(&ENV e, &fn_decl decl,
ast::proto proto,
&block body) -> ast::_fn) fold_fn,
&block body) -> ast::_fn) fold_fn,

(fn(&ENV e,
&vec[arg] inputs,
&@ty output,
&purity p) -> ast::fn_decl) fold_fn_decl,
&purity p) -> ast::fn_decl) fold_fn_decl,

(fn(&ENV e, &ast::_mod m) -> ast::_mod) fold_mod,
(fn(&ENV e, &ast::_mod m) -> ast::_mod) fold_mod,

(fn(&ENV e, &ast::native_mod m) -> ast::native_mod) fold_native_mod,
(fn(&ENV e, &ast::native_mod m)
-> ast::native_mod) fold_native_mod,

(fn(&ENV e, &span sp,
&vec[@ast::crate_directive] cdirs,
&ast::_mod m) -> @ast::crate) fold_crate,
&ast::_mod m) -> @ast::crate) fold_crate,

(fn(&ENV e,
&vec[ast::obj_field] fields,
&vec[@ast::method] methods,
&option::t[@ast::method] dtor)
-> ast::_obj) fold_obj,
-> ast::_obj) fold_obj,

(fn(&ENV e,
&option::t[vec[ast::obj_field]] fields,
&vec[@ast::method] methods,
&option::t[ident] with_obj)
-> ast::anon_obj) fold_anon_obj,

// Env updates.
(fn(&ENV e, &@ast::crate c) -> ENV) update_env_for_crate,
Expand Down Expand Up @@ -828,6 +843,12 @@ fn fold_expr[ENV](&ENV env, &ast_fold[ENV] fld, &@expr e) -> @expr {
auto t2 = fld.fold_ann(env_, t);
ret fld.fold_expr_chan(env_, e.span, ee, t2);
}

case (ast::expr_anon_obj(?ob, ?tps, ?odid, ?t)) {
auto ee = fold_anon_obj(env_, fld, ob);
auto t2 = fld.fold_ann(env_, t);
ret fld.fold_expr_anon_obj(env_, e.span, ee, tps, odid, t2);
}
}

fail;
Expand Down Expand Up @@ -930,7 +951,6 @@ fn fold_method[ENV](&ENV env, &ast_fold[ENV] fld,
ret @rec(node=rec(meth=meth with m.node) with *m);
}


fn fold_obj[ENV](&ENV env, &ast_fold[ENV] fld, &ast::_obj ob) -> ast::_obj {

let vec[ast::obj_field] fields = vec();
Expand Down Expand Up @@ -962,6 +982,49 @@ fn fold_obj[ENV](&ENV env, &ast_fold[ENV] fld, &ast::_obj ob) -> ast::_obj {
ret fld.fold_obj(env, fields, meths, dtor);
}

fn fold_anon_obj[ENV](&ENV env, &ast_fold[ENV] fld, &ast::anon_obj ob)
-> ast::anon_obj {

// Fields
let option::t[vec[ast::obj_field]] fields = none[vec[ast::obj_field]];
alt (ob.fields) {
case (none[vec[ast::obj_field]]) { }
case (some[vec[ast::obj_field]](?v)) {
let vec[ast::obj_field] fields = vec();
for (ast::obj_field f in v) {
fields += vec(fold_obj_field(env, fld, f));
}
}
}

// with_obj
let option::t[ast::ident] with_obj = none[ast::ident];
alt (ob.with_obj) {
case (none[ast::ident]) { }
case (some[ast::ident](?i)) {
with_obj = some[ast::ident](i);
}
}

// Methods
let vec[@ast::method] meths = vec();
let vec[ast::ty_param] tp = vec();
for (@ast::method m in ob.methods) {
// Fake-up an ast::item for this method.
// FIXME: this is kinda awful. Maybe we should reformulate
// the way we store methods in the AST?
let @ast::item i = @rec(node=ast::item_fn(m.node.ident,
m.node.meth,
tp,
m.node.id,
m.node.ann),
span=m.span);
let ENV _env = fld.update_env_for_item(env, i);
_vec::push[@ast::method](meths, fold_method(_env, fld, m));
}
ret fld.fold_anon_obj(env, fields, meths, with_obj);
}

fn fold_view_item[ENV](&ENV env, &ast_fold[ENV] fld, &@view_item vi)
-> @view_item {

Expand Down Expand Up @@ -1410,6 +1473,14 @@ fn identity_fold_expr_chan[ENV](&ENV e, &span sp, &@expr x,
ret @respan(sp, ast::expr_chan(x, a));
}

fn identity_fold_expr_anon_obj[ENV](&ENV e, &span sp,
&ast::anon_obj ob,
&vec[ast::ty_param] tps,
&ast::obj_def_ids odid,
&ann a) -> @expr {
ret @respan(sp, ast::expr_anon_obj(ob, tps, odid, a));
}

// Decl identities.

fn identity_fold_decl_local[ENV](&ENV e, &span sp,
Expand Down Expand Up @@ -1584,6 +1655,12 @@ fn identity_fold_obj[ENV](&ENV e,
ret rec(fields=fields, methods=methods, dtor=dtor);
}

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 {
ret rec(fields=fields, methods=methods, with_obj=with_obj);
}

// Env update identities.

Expand Down Expand Up @@ -1707,6 +1784,9 @@ fn new_identity_fold[ENV]() -> ast_fold[ENV] {
fold_expr_port = bind identity_fold_expr_port[ENV](_,_,_),
fold_expr_chan = bind identity_fold_expr_chan[ENV](_,_,_,_),

fold_expr_anon_obj
= bind identity_fold_expr_anon_obj[ENV](_,_,_,_,_,_),

fold_decl_local = bind identity_fold_decl_local[ENV](_,_,_),
fold_decl_item = bind identity_fold_decl_item[ENV](_,_,_),

Expand Down Expand Up @@ -1746,6 +1826,7 @@ fn new_identity_fold[ENV]() -> ast_fold[ENV] {
fold_native_mod = bind identity_fold_native_mod[ENV](_,_),
fold_crate = bind identity_fold_crate[ENV](_,_,_,_),
fold_obj = bind identity_fold_obj[ENV](_,_,_,_),
fold_anon_obj = bind identity_fold_anon_obj[ENV](_,_,_,_),

update_env_for_crate = bind identity_update_env_for_crate[ENV](_,_),
update_env_for_item = bind identity_update_env_for_item[ENV](_,_),
Expand Down
10 changes: 7 additions & 3 deletions src/comp/middle/trans.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2885,10 +2885,14 @@ fn iter_sequence(@block_ctxt cx,
auto et = ty::mk_mach(cx.fcx.lcx.ccx.tcx, common::ty_u8);
ret iter_sequence_body(cx, v, et, f, true);
}
case (_) { fail; }
case (_) {

cx.fcx.lcx.ccx.sess.bug("unexpected type in " +
"trans::iter_sequence: " +
ty::ty_to_str(cx.fcx.lcx.ccx.tcx, t));
fail;
}
}
cx.fcx.lcx.ccx.sess.bug("bad type in trans::iter_sequence");
fail;
}

fn lazily_emit_all_tydesc_glue(&@block_ctxt cx,
Expand Down
1 change: 1 addition & 0 deletions src/comp/middle/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1710,6 +1710,7 @@ fn expr_ann(&@ast::expr e) -> ast::ann {
case (ast::expr_check(_,?a)) { ret a; }
case (ast::expr_port(?a)) { ret a; }
case (ast::expr_chan(_,?a)) { ret a; }
case (ast::expr_anon_obj(_,_,_,?a)) { ret a; }
case (ast::expr_break(?a)) { ret a; }
case (ast::expr_cont(?a)) { ret a; }
case (ast::expr_self_method(_, ?a)) { ret a; }
Expand Down
Loading