From 6c1c5b39482158f078b5b10164c024edf345e386 Mon Sep 17 00:00:00 2001 From: Lindsey Kuper Date: Tue, 10 May 2011 19:52:22 -0700 Subject: [PATCH] More progress on anonymous objects. Still segfaulting on the method-overriding.rs test, though. --- src/comp/front/parser.rs | 17 +++--- src/comp/middle/fold.rs | 75 +++++++++++++++++++++++++- src/comp/middle/trans.rs | 10 ++-- src/comp/middle/ty.rs | 2 + src/test/run-pass/method-overriding.rs | 10 +++- 5 files changed, 100 insertions(+), 14 deletions(-) diff --git a/src/comp/front/parser.rs b/src/comp/front/parser.rs index cb7435d8132..267c752ee1f 100644 --- a/src/comp/front/parser.rs +++ b/src/comp/front/parser.rs @@ -807,24 +807,24 @@ fn parse_bottom_expr(parser p) -> @ast::expr { // 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) { + if (p.peek() == token::LPAREN) { auto pf = parse_obj_field; hi = p.get_hi_pos(); - expect(p, token.LPAREN); + expect(p, token::LPAREN); fields = some[vec[ast.obj_field]] (parse_seq_to_end[ast.obj_field] - (token.RPAREN, - some(token.COMMA), + (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) { + expect(p, token::LBRACE); + while (p.peek() != token::RBRACE) { alt (p.peek()) { - case (token.WITH) { + case (token::WITH) { with_obj = some[ast.ident](parse_ident(p)); } case (_) { @@ -833,7 +833,7 @@ fn parse_bottom_expr(parser p) -> @ast::expr { } } hi = p.get_hi_pos(); - expect(p, token.RBRACE); + 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 @@ -848,6 +848,7 @@ fn parse_bottom_expr(parser p) -> @ast::expr { auto odid = rec(ty=p.next_def_id(), ctor=p.next_def_id()); ex = ast.expr_anon_obj(ob, ty_params, odid, ast.ann_none); + } else if (eat_word(p, "bind")) { auto e = parse_expr_res(p, RESTRICT_NO_CALL_EXPRS); fn parse_expr_opt(parser p) -> option::t[@ast::expr] { diff --git a/src/comp/middle/fold.rs b/src/comp/middle/fold.rs index 5af85f14cbb..7d0fa9946a0 100644 --- a/src/comp/middle/fold.rs +++ b/src/comp/middle/fold.rs @@ -209,6 +209,10 @@ 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, // TODO: Is the ob arg supposed to be & or not? + vec[ast.ty_param] tps, + ast.obj_def_ids odid, ann a) -> @expr) fold_expr_anon_obj, // Decl folds. (fn(&ENV e, &span sp, @@ -322,6 +326,11 @@ type ast_fold[ENV] = &option::t[@ast::method] dtor) -> 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, (fn(&ENV e, &@item i) -> ENV) update_env_for_item, @@ -828,6 +837,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; @@ -930,7 +945,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(); @@ -962,6 +976,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 { @@ -1410,6 +1467,12 @@ 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, @@ -1584,6 +1647,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. @@ -1707,6 +1776,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](_,_,_), @@ -1746,6 +1818,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](_,_), diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 4f1636d4b50..fa50d857ae9 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -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, diff --git a/src/comp/middle/ty.rs b/src/comp/middle/ty.rs index a0c3a724c3e..fcde5e2cb89 100644 --- a/src/comp/middle/ty.rs +++ b/src/comp/middle/ty.rs @@ -1659,6 +1659,7 @@ fn pat_ty(&ctxt cx, &node_type_table ntt, &@ast::pat pat) -> t { fail; // not reached } +<<<<<<< HEAD fn expr_ann(&@ast::expr e) -> ast::ann { alt (e.node) { case (ast::expr_vec(_,_,?a)) { ret a; } @@ -1694,6 +1695,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; } diff --git a/src/test/run-pass/method-overriding.rs b/src/test/run-pass/method-overriding.rs index bf68ddd1e42..3fbb53ff6cf 100644 --- a/src/test/run-pass/method-overriding.rs +++ b/src/test/run-pass/method-overriding.rs @@ -1,7 +1,7 @@ // xfail-boot // xfail-stage0 use std; -import std._vec.len; + fn main() { obj a() { @@ -15,12 +15,18 @@ fn main() { auto my_a = a(); - // Step 1 is to add support for this "with" syntax + // Extending an object with a new method auto my_b = obj { fn baz() -> int { ret self.foo(); } with my_a }; + + // Extending an object with a new field + auto my_c = obj(quux) { with my_a } ; + + // Should this be legal? + auto my_d = obj() { with my_a } ; }