Skip to content

Commit 67ffd45

Browse files
committed
---
yaml --- r: 3292 b: refs/heads/master c: 84005fa h: refs/heads/master v: v3
1 parent 650369b commit 67ffd45

File tree

11 files changed

+310
-65
lines changed

11 files changed

+310
-65
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
---
2-
refs/heads/master: 718ee98f43e7feecb38249a3519174054e3b7c79
2+
refs/heads/master: 84005fadbf8854df069a3caf02c9493866b550be

trunk/src/comp/front/ast.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -409,14 +409,16 @@ type method_ = rec(ident ident, _fn meth, node_id id);
409409
type method = spanned[method_];
410410

411411
type obj_field = rec(mutability mut, @ty ty, ident ident, node_id id);
412+
type anon_obj_field = rec(mutability mut, @ty ty, @expr expr, ident ident,
413+
node_id id);
412414

413415
type _obj =
414416
rec(vec[obj_field] fields, vec[@method] methods, option::t[@method] dtor);
415417

416418
type anon_obj =
417419
rec(
418420
// New fields and methods, if they exist.
419-
option::t[vec[obj_field]] fields,
421+
option::t[vec[anon_obj_field]] fields,
420422
vec[@method] methods,
421423

422424
// with_obj: the original object being extended, if it exists.

trunk/src/comp/front/parser.rs

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -793,16 +793,15 @@ fn parse_bottom_expr(&parser p) -> @ast::expr {
793793
// Anonymous object
794794

795795
// FIXME: Can anonymous objects have ty params?
796-
797796
auto ty_params = parse_ty_params(p);
798-
// Only make people type () if they're actually adding new fields
799797

800-
let option::t[vec[ast::obj_field]] fields = none;
798+
// Only make people type () if they're actually adding new fields
799+
let option::t[vec[ast::anon_obj_field]] fields = none;
801800
if (p.peek() == token::LPAREN) {
802801
p.bump();
803802
fields =
804803
some(parse_seq_to_end(token::RPAREN, some(token::COMMA),
805-
parse_obj_field, p));
804+
parse_anon_obj_field, p));
806805
}
807806
let vec[@ast::method] meths = [];
808807
let option::t[@ast::expr] with_obj = none;
@@ -820,7 +819,6 @@ fn parse_bottom_expr(&parser p) -> @ast::expr {
820819

821820
// We don't need to pull ".node" out of fields because it's not a
822821
// "spanned".
823-
824822
let ast::anon_obj ob =
825823
rec(fields=fields, methods=meths, with_obj=with_obj);
826824
auto odid = rec(ty=p.get_id(), ctor=p.get_id());
@@ -1730,6 +1728,16 @@ fn parse_obj_field(&parser p) -> ast::obj_field {
17301728
ret rec(mut=mut, ty=ty, ident=ident, id=p.get_id());
17311729
}
17321730

1731+
fn parse_anon_obj_field(&parser p) -> ast::anon_obj_field {
1732+
auto mut = parse_mutability(p);
1733+
auto ty = parse_ty(p);
1734+
auto ident = parse_value_ident(p);
1735+
expect(p, token::EQ);
1736+
auto expr = parse_expr(p);
1737+
ret rec(mut=mut, ty=ty, expr=expr, ident=ident, id=p.next_def_id(),
1738+
ann=p.get_ann());
1739+
}
1740+
17331741
fn parse_method(&parser p) -> @ast::method {
17341742
auto lo = p.get_lo_pos();
17351743
auto proto = parse_proto(p);

trunk/src/comp/middle/trans.rs

Lines changed: 175 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ import link::crate_meta_extras_hash;
6969
import pretty::ppaux::ty_to_str;
7070
import pretty::ppaux::ty_to_short_str;
7171
import pretty::pprust::expr_to_str;
72+
import pretty::pprust::path_to_str;
7273

7374
obj namegen(mutable int i) {
7475
fn next(str prefix) -> str { i += 1; ret prefix + istr(i); }
@@ -6500,23 +6501,38 @@ fn trans_anon_obj(@block_ctxt bcx, &span sp, &ast::anon_obj anon_obj,
65006501

65016502
assert (vec::len(ty_params) == 0u);
65026503
auto ccx = bcx.fcx.lcx.ccx;
6504+
6505+
let vec[ast::anon_obj_field] additional_fields = [];
6506+
let vec[result] additional_field_vals = [];
6507+
let vec[ty::t] additional_field_tys = [];
6508+
alt (anon_obj.fields) {
6509+
case (none) { }
6510+
case (some(?fields)) {
6511+
additional_fields = fields;
6512+
for (ast::anon_obj_field f in fields) {
6513+
additional_field_tys += [node_ann_type(ccx, f.ann)];
6514+
additional_field_vals += [trans_expr(bcx, f.expr)];
6515+
}
6516+
}
6517+
}
6518+
65036519
// If with_obj (the object being extended) exists, translate it, producing
65046520
// a result.
6505-
6506-
let option::t[result] with_obj_val = none[result];
6521+
let option::t[result] with_obj_val = none;
6522+
let ty::t with_obj_ty = ty::mk_type(ccx.tcx);
65076523
alt (anon_obj.with_obj) {
65086524
case (none) { }
65096525
case (some(?e)) {
65106526
// Translating with_obj returns a ValueRef (pointer to a 2-word
6511-
// value) wrapped in a result. We want to allocate space for this
6512-
// value in our outer object, then copy it into the outer object.
6513-
6514-
with_obj_val = some[result](trans_expr(bcx, e));
6527+
// value) wrapped in a result.
6528+
with_obj_val = some[result](trans_expr(bcx, e));
6529+
with_obj_ty = node_ann_type(ccx, ty::expr_ann(e));
65156530
}
65166531
}
6517-
// FIXME (part of issue #417): all of the following code is copypasta from
6518-
// trans_obj for translating the anonymous wrapper object. Eventually we
6519-
// should abstract this code out of trans_anon_obj and trans_obj.
6532+
// FIXME (part of issue #538): much of the following code is copypasta
6533+
// from trans_obj for translating the anonymous wrapper object.
6534+
// Eventually we might want to abstract this code out of trans_anon_obj
6535+
// and trans_obj.
65206536

65216537
auto self_ty = ty::node_id_to_type(ccx.tcx, id);
65226538
auto llself_ty = type_of(ccx, sp, self_ty);
@@ -6535,52 +6551,168 @@ fn trans_anon_obj(@block_ctxt bcx, &span sp, &ast::anon_obj anon_obj,
65356551
// Make a vtable for the outer object. create_vtbl() wants an ast::_obj
65366552
// and all we have is an ast::anon_obj, so we need to roll our own.
65376553

6538-
let vec[ast::obj_field] addtl_fields = [];
6539-
alt (anon_obj.fields) {
6540-
case (none) { }
6541-
case (some(?fields)) { addtl_fields = fields; }
6542-
}
6543-
let ast::_obj wrapper_obj =
6544-
rec(fields=addtl_fields,
6545-
methods=anon_obj.methods,
6546-
dtor=none[@ast::method]);
6547-
auto vtbl =
6548-
create_vtbl(bcx.fcx.lcx, llself_ty, self_ty, wrapper_obj, ty_params);
6554+
fn anon_obj_field_to_obj_field(&ast::anon_obj_field f) -> ast::obj_field {
6555+
ret rec(mut=f.mut, ty=f.ty, ident=f.ident, id=f.id, ann=f.ann);
6556+
}
6557+
let ast::_obj wrapper_obj = rec(
6558+
fields = vec::map(anon_obj_field_to_obj_field, additional_fields),
6559+
methods = anon_obj.methods,
6560+
dtor = none[@ast::method]);
6561+
auto vtbl = create_vtbl(bcx.fcx.lcx, llself_ty, self_ty, wrapper_obj,
6562+
ty_params);
6563+
65496564
bcx.build.Store(vtbl, pair_vtbl);
6550-
// FIXME (part of issue #417): This vtable needs to contain "forwarding
6565+
// FIXME (part of issue #538): Where do we fill in the field *values* from
6566+
// the outer object?
6567+
6568+
// FIXME (part of issue #539): This vtable needs to contain "forwarding
65516569
// slots" for the methods that exist in the with_obj, as well. How do we
65526570
// do that?
65536571

65546572
// Next we have to take care of the other half of the pair we're
65556573
// returning: a boxed (reference-counted) tuple containing a tydesc,
6556-
// typarams, and fields.
6557-
6558-
// FIXME (part of issue #417): Because this is an anonymous object, we
6559-
// also have to fill in the with_obj field of this tuple.
6574+
// typarams, fields, and a pointer to our with_obj.
65606575

65616576
let TypeRef llbox_ty = T_opaque_obj_ptr(ccx.tn);
6562-
alt (anon_obj.fields) {
6563-
case (none) {
6564-
// If the object we're translating has no fields or type
6565-
// parameters, there's not much to do.
65666577

6567-
// Store null into pair, if no args or typarams.
6578+
if (vec::len[ast::ty_param](ty_params) == 0u &&
6579+
vec::len[ast::anon_obj_field](additional_fields) == 0u) {
6580+
// If the object we're translating has no fields or type parameters,
6581+
// there's not much to do.
6582+
6583+
// Store null into pair, if no args or typarams.
6584+
bcx.build.Store(C_null(llbox_ty), pair_box);
6585+
} else {
65686586

6569-
bcx.build.Store(C_null(llbox_ty), pair_box);
6587+
// Synthesize a tuple type for fields: [field, ...]
6588+
let ty::t fields_ty = ty::mk_imm_tup(ccx.tcx, additional_field_tys);
6589+
6590+
// Tydescs are run-time instantiations of typarams. We're not
6591+
// actually supporting typarams for anon objs yet, but let's
6592+
// create space for them in case we ever want them.
6593+
let ty::t tydesc_ty = ty::mk_type(ccx.tcx);
6594+
let vec[ty::t] tps = [];
6595+
for (ast::ty_param tp in ty_params) {
6596+
vec::push[ty::t](tps, tydesc_ty);
65706597
}
6571-
case (some(?fields)) {
6572-
// For the moment let's pretend that there are no additional
6573-
// fields.
6598+
// Synthesize a tuple type for typarams: [typaram, ...]
6599+
let ty::t typarams_ty = ty::mk_imm_tup(ccx.tcx, tps);
6600+
6601+
// Tuple type for body:
6602+
// [tydesc_ty, [typaram, ...], [field, ...], with_obj]
6603+
let ty::t body_ty =
6604+
ty::mk_imm_tup(ccx.tcx, [tydesc_ty, typarams_ty,
6605+
fields_ty, with_obj_ty]);
6606+
6607+
// Hand this type we've synthesized off to trans_malloc_boxed, which
6608+
// allocates a box, including space for a refcount.
6609+
auto box = trans_malloc_boxed(bcx, body_ty);
6610+
bcx = box.bcx;
6611+
6612+
// mk_imm_box throws a refcount into the type we're synthesizing,
6613+
// so that it looks like:
6614+
// [rc, [tydesc_ty, [typaram, ...], [field, ...], with_obj]]
6615+
let ty::t boxed_body_ty = ty::mk_imm_box(ccx.tcx, body_ty);
6616+
6617+
// Grab onto the refcount and body parts of the box we allocated.
6618+
auto rc =
6619+
GEP_tup_like(bcx, boxed_body_ty, box.val,
6620+
[0, abi::box_rc_field_refcnt]);
6621+
bcx = rc.bcx;
6622+
auto body =
6623+
GEP_tup_like(bcx, boxed_body_ty, box.val,
6624+
[0, abi::box_rc_field_body]);
6625+
bcx = body.bcx;
6626+
bcx.build.Store(C_int(1), rc.val);
65746627

6575-
bcx.fcx.lcx.ccx.sess.unimpl("anon objs don't support " +
6576-
"adding fields yet");
6577-
// FIXME (issue #417): drop these fields into the newly created
6578-
// object.
6628+
// Put together a tydesc for the body, so that the object can later be
6629+
// freed by calling through its tydesc.
65796630

6631+
// Every object (not just those with type parameters) needs to have a
6632+
// tydesc to describe its body, since all objects have unknown type to
6633+
// the user of the object. So the tydesc is needed to keep track of
6634+
// the types of the object's fields, so that the fields can be freed
6635+
// later.
6636+
6637+
auto body_tydesc =
6638+
GEP_tup_like(bcx, body_ty, body.val,
6639+
[0, abi::obj_body_elt_tydesc]);
6640+
bcx = body_tydesc.bcx;
6641+
auto ti = none[@tydesc_info];
6642+
auto body_td = get_tydesc(bcx, body_ty, true, ti);
6643+
lazily_emit_tydesc_glue(bcx, abi::tydesc_field_drop_glue, ti);
6644+
lazily_emit_tydesc_glue(bcx, abi::tydesc_field_free_glue, ti);
6645+
bcx = body_td.bcx;
6646+
bcx.build.Store(body_td.val, body_tydesc.val);
6647+
6648+
// Copy the object's type parameters and fields into the space we
6649+
// allocated for the object body. (This is something like saving the
6650+
// lexical environment of a function in its closure: the "captured
6651+
// typarams" are any type parameters that are passed to the object
6652+
// constructor and are then available to the object's methods.
6653+
// Likewise for the object's fields.)
6654+
6655+
// Copy typarams into captured typarams.
6656+
auto body_typarams =
6657+
GEP_tup_like(bcx, body_ty, body.val,
6658+
[0, abi::obj_body_elt_typarams]);
6659+
bcx = body_typarams.bcx;
6660+
let int i = 0;
6661+
for (ast::ty_param tp in ty_params) {
6662+
auto typaram = bcx.fcx.lltydescs.(i);
6663+
auto capture =
6664+
GEP_tup_like(bcx, typarams_ty, body_typarams.val, [0, i]);
6665+
bcx = capture.bcx;
6666+
bcx = copy_val(bcx, INIT, capture.val, typaram,
6667+
tydesc_ty).bcx;
6668+
i += 1;
6669+
}
6670+
6671+
// Copy additional fields into the object's body.
6672+
auto body_fields =
6673+
GEP_tup_like(bcx, body_ty, body.val,
6674+
[0, abi::obj_body_elt_fields]);
6675+
bcx = body_fields.bcx;
6676+
i = 0;
6677+
for (ast::anon_obj_field f in additional_fields) {
6678+
// FIXME (part of issue #538): make this work eventually, when we
6679+
// have additional field exprs in the AST.
6680+
6681+
auto field_val = load_if_immediate(
6682+
bcx,
6683+
additional_field_vals.(i).val,
6684+
additional_field_tys.(i));
6685+
6686+
// what was the type of arg_tys.(i)? What's the type of
6687+
// additional_field_tys.(i) ?
6688+
6689+
// arg_tys is a vector of ty::arg, so arg_tys.(i) is a ty::arg,
6690+
// which is a record of mode and t. Meanwhile,
6691+
// additional_field_tys is a vec of ty::t. So how about I just
6692+
// don't index into it?
6693+
6694+
auto field =
6695+
GEP_tup_like(bcx, fields_ty, body_fields.val, [0, i]);
6696+
bcx = field.bcx;
6697+
bcx = copy_val(bcx, INIT, field.val,
6698+
additional_field_vals.(i).val,
6699+
additional_field_tys.(i)).bcx;
6700+
i += 1;
65806701
}
6702+
6703+
// Copy a pointer to the with_obj into the object's body. (TODO: Is
6704+
// it necessary to use GEP_tup_like here?)
6705+
auto body_with_obj =
6706+
GEP_tup_like(bcx, body_ty, body.val,
6707+
[0, abi::obj_body_elt_with_obj]);
6708+
bcx = body_with_obj.bcx;
6709+
6710+
// Store box ptr in outer pair.
6711+
auto p = bcx.build.PointerCast(box.val, llbox_ty);
6712+
bcx.build.Store(p, pair_box);
65816713
}
6582-
// Return the object we built.
65836714

6715+
// Return the object we built.
65846716
ret res(bcx, pair);
65856717
}
65866718

@@ -7306,7 +7438,7 @@ fn trans_obj(@local_ctxt cx, &span sp, &ast::_obj ob, ast::node_id ctor_id,
73067438
// typarams, and fields.
73077439

73087440
// FIXME: What about with_obj? Do we have to think about it here?
7309-
// (Pertains to issue #417.)
7441+
// (Pertains to issues #538/#539/#540/#543.)
73107442

73117443
let TypeRef llbox_ty = T_opaque_obj_ptr(ccx.tn);
73127444
// FIXME: we should probably also allocate a box for empty objs that have
@@ -7612,6 +7744,9 @@ fn decl_fn_and_pair(&@crate_ctxt ccx, &span sp, vec[str] path, str flav,
76127744
}
76137745
}
76147746

7747+
// Create a closure: a pair containing (1) a ValueRef, pointing to where the
7748+
// fn's definition is in the executable we're creating, and (2) a pointer to
7749+
// space for the function's environment.
76157750
fn create_fn_pair(&@crate_ctxt cx, str ps, TypeRef llfnty, ValueRef llfn,
76167751
bool external) -> ValueRef {
76177752
auto gvar =

trunk/src/comp/middle/typeck.rs

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2087,16 +2087,27 @@ fn check_expr(&@fn_ctxt fcx, &@ast::expr expr) {
20872087

20882088
// We're entering an object, so gather up the info we need.
20892089

2090-
let vec[ast::obj_field] fields = [];
2090+
let vec[ast::anon_obj_field] fields = [];
20912091
alt (anon_obj.fields) {
20922092
case (none) { }
20932093
case (some(?v)) { fields = v; }
20942094
}
2095+
2096+
// FIXME: this is duplicated between here and trans -- it should
2097+
// appear in one place
2098+
fn anon_obj_field_to_obj_field(&ast::anon_obj_field f)
2099+
-> ast::obj_field {
2100+
ret rec(mut=f.mut, ty=f.ty, ident=f.ident, id=f.id);
2101+
}
2102+
20952103
let ast::node_id di = obj_def_ids.ty;
20962104
vec::push[obj_info](fcx.ccx.obj_infos,
2097-
rec(obj_fields=fields, this_obj=di));
2098-
// Typecheck 'with_obj', if it exists.
2105+
rec(obj_fields=
2106+
vec::map(anon_obj_field_to_obj_field,
2107+
fields),
2108+
this_obj=di));
20992109

2110+
// Typecheck 'with_obj', if it exists.
21002111
let option::t[@ast::expr] with_obj = none[@ast::expr];
21012112
alt (anon_obj.with_obj) {
21022113
case (none) { }
@@ -2108,9 +2119,9 @@ fn check_expr(&@fn_ctxt fcx, &@ast::expr expr) {
21082119
check_expr(fcx, e);
21092120
}
21102121
}
2122+
21112123
// FIXME: These next three functions are largely ripped off from
21122124
// similar ones in collect::. Is there a better way to do this?
2113-
21142125
fn ty_of_arg(@crate_ctxt ccx, &ast::arg a) -> ty::arg {
21152126
auto ty_mode = ast_mode_to_mode(a.mode);
21162127
ret rec(mode=ty_mode, ty=ast_ty_to_ty_crate(ccx, a.ty));

trunk/src/comp/middle/visit.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -372,8 +372,9 @@ fn visit_expr[E](&@expr ex, &E e, &vt[E] v) {
372372
alt (anon_obj.fields) {
373373
case (none) { }
374374
case (some(?fields)) {
375-
for (obj_field f in fields) {
375+
for (anon_obj_field f in fields) {
376376
vt(v).visit_ty(f.ty, e, v);
377+
vt(v).visit_expr(f.expr, e, v);
377378
}
378379
}
379380
}

0 commit comments

Comments
 (0)