Skip to content

Commit 56f0fbe

Browse files
committed
Initial trans of lambdas. Doesn't work with polymorphism yet.
1 parent 766e939 commit 56f0fbe

File tree

1 file changed

+61
-8
lines changed

1 file changed

+61
-8
lines changed

src/comp/middle/trans.rs

Lines changed: 61 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3720,6 +3720,19 @@ fn build_environment_heap(bcx: @block_ctxt, lltydescs: ValueRef[],
37203720
ret {ptr: r.box, ptrty: closure_ty, bcx: bcx};
37213721
}
37223722

3723+
fn build_copying_closure(cx: &@block_ctxt, upvars: &@ast::node_id[])
3724+
-> {ptr: ValueRef, ptrty: ty::t, bcx: @block_ctxt} {
3725+
let closure_vals: lval_result[] = ~[];
3726+
let closure_tys: ty::t[] = ~[];
3727+
for nid: ast::node_id in *upvars {
3728+
closure_vals += ~[trans_var(cx, cx.sp, nid)];
3729+
closure_tys += ~[ty::node_id_to_monotype(bcx_tcx(cx), nid)];
3730+
}
3731+
3732+
ret build_environment_heap(cx, cx.fcx.lltydescs,
3733+
closure_tys, closure_vals);
3734+
}
3735+
37233736
// Given a block context and a list of upvars, construct a closure that
37243737
// contains pointers to all of the upvars and all of the tydescs in
37253738
// scope. Return the ValueRef and TypeRef corresponding to the closure.
@@ -3785,6 +3798,43 @@ fn build_environment(cx: &@block_ctxt, upvars: &@ast::node_id[]) ->
37853798
ret {ptr: llenvptr, ptrty: llenvptrty};
37863799
}
37873800

3801+
fn load_environment_heap(enclosing_cx: &@block_ctxt, fcx: &@fn_ctxt,
3802+
envty: &ty::t, upvars: &@ast::node_id[]) {
3803+
let bcx = new_raw_block_ctxt(fcx, fcx.llcopyargs);
3804+
3805+
let llenvptr =
3806+
bcx.build.GEP(fcx.llenv, ~[C_int(0), C_int(abi::box_rc_field_body)]);
3807+
let llenvptrty = T_ptr(type_of(bcx_ccx(bcx), bcx.sp, envty));;
3808+
llenvptr = bcx.build.PointerCast(llenvptr, llenvptrty);
3809+
3810+
// Populate the upvars from the environment.
3811+
let llbindingsptr =
3812+
bcx.build.GEP(llenvptr,
3813+
~[C_int(0), C_int(abi::closure_elt_bindings)]);
3814+
let i = 0u;
3815+
for upvar_id: ast::node_id in *upvars {
3816+
let llupvarptr =
3817+
bcx.build.GEP(llbindingsptr, ~[C_int(0), C_int(i as int)]);
3818+
let def_id = ast::def_id_of_def(bcx_tcx(bcx).def_map.get(upvar_id));
3819+
fcx.llupvars.insert(def_id.node, llupvarptr);
3820+
i += 1u;
3821+
}
3822+
3823+
// Populate the type parameters from the environment.
3824+
let lltydescsptr =
3825+
bcx.build.GEP(llenvptr,
3826+
~[C_int(0), C_int(abi::closure_elt_ty_params)]);
3827+
let tydesc_count = std::ivec::len(enclosing_cx.fcx.lltydescs);
3828+
i = 0u;
3829+
while i < tydesc_count {
3830+
let lltydescptr =
3831+
bcx.build.GEP(lltydescsptr, ~[C_int(0), C_int(i as int)]);
3832+
fcx.lltydescs += ~[bcx.build.Load(lltydescptr)];
3833+
i += 1u;
3834+
}
3835+
}
3836+
3837+
37883838
// Given an enclosing block context, a new function context, a closure type,
37893839
// and a list of upvars, generate code to load and populate the environment
37903840
// with the upvars and type descriptors.
@@ -6399,21 +6449,24 @@ fn trans_closure(bcx_maybe: &option::t[@block_ctxt],
63996449
// Figure out if we need to build a closure and act accordingly
64006450
let closure = none;
64016451
alt f.proto {
6402-
ast::proto_block. {
6452+
ast::proto_block. | ast::proto_closure. {
64036453
let bcx = option::get(bcx_maybe);
64046454
let upvars = get_freevars(cx.ccx.tcx, id);
64056455

6406-
let llenv = build_environment(bcx, upvars);
6456+
let llenvptr = if (f.proto == ast::proto_block) {
6457+
let llenv = build_environment(bcx, upvars);
6458+
load_environment(bcx, fcx, llenv.ptrty, upvars);
6459+
llenv.ptr
6460+
} else {
6461+
let llenv = build_copying_closure(bcx, upvars);
6462+
load_environment_heap(bcx, fcx, llenv.ptrty, upvars);
6463+
llenv.ptr
6464+
};
64076465

6408-
// Generate code to load the environment out of the
6409-
// environment pointer.
6410-
load_environment(bcx, fcx, llenv.ptrty, upvars);
6411-
// Build the closure.
64126466
closure =
64136467
some(create_real_fn_pair(bcx, option::get(llfnty), llfndecl,
6414-
llenv.ptr));
6468+
llenvptr));
64156469
}
6416-
ast::proto_closure. { fail "copy capture not implemented yet"; }
64176470
_ { }
64186471
}
64196472

0 commit comments

Comments
 (0)