Make for-each bodies close over their parent's iterbody
Closes issue #639
This commit is contained in:
parent
7ed556cf8e
commit
b41fd61045
1 changed files with 19 additions and 6 deletions
|
@ -4488,15 +4488,20 @@ fn collect_upvars(&@block_ctxt cx, &ast::block bloc,
|
||||||
// contains pointers to all of the upvars and all of the tydescs in
|
// contains pointers to all of the upvars and all of the tydescs in
|
||||||
// scope. Return the ValueRef and TypeRef corresponding to the closure.
|
// scope. Return the ValueRef and TypeRef corresponding to the closure.
|
||||||
fn build_environment(&@block_ctxt cx, &ast::node_id[] upvars) ->
|
fn build_environment(&@block_ctxt cx, &ast::node_id[] upvars) ->
|
||||||
tup(ValueRef, TypeRef)
|
tup(ValueRef, TypeRef) {
|
||||||
{
|
|
||||||
auto upvar_count = std::ivec::len(upvars);
|
auto upvar_count = std::ivec::len(upvars);
|
||||||
|
auto has_iterbody = !option::is_none(cx.fcx.lliterbody);
|
||||||
|
if (has_iterbody) { upvar_count += 1u; }
|
||||||
auto llbindingsptr;
|
auto llbindingsptr;
|
||||||
|
|
||||||
if (upvar_count > 0u) {
|
if (upvar_count > 0u) {
|
||||||
// Gather up the upvars.
|
// Gather up the upvars.
|
||||||
let ValueRef[] llbindings = ~[];
|
let ValueRef[] llbindings = ~[];
|
||||||
let TypeRef[] llbindingtys = ~[];
|
let TypeRef[] llbindingtys = ~[];
|
||||||
|
if (has_iterbody) {
|
||||||
|
llbindings += ~[option::get(cx.fcx.lliterbody)];
|
||||||
|
llbindingtys += ~[val_ty(llbindings.(0))];
|
||||||
|
}
|
||||||
for (ast::node_id nid in upvars) {
|
for (ast::node_id nid in upvars) {
|
||||||
auto llbinding;
|
auto llbinding;
|
||||||
alt (cx.fcx.lllocals.find(nid)) {
|
alt (cx.fcx.lllocals.find(nid)) {
|
||||||
|
@ -4566,9 +4571,7 @@ fn build_environment(&@block_ctxt cx, &ast::node_id[] upvars) ->
|
||||||
// and a list of upvars, generate code to load and populate the environment
|
// and a list of upvars, generate code to load and populate the environment
|
||||||
// with the upvars and type descriptors.
|
// with the upvars and type descriptors.
|
||||||
fn load_environment(&@block_ctxt cx, &@fn_ctxt fcx,
|
fn load_environment(&@block_ctxt cx, &@fn_ctxt fcx,
|
||||||
TypeRef llenvptrty, &ast::node_id[] upvars)
|
TypeRef llenvptrty, &ast::node_id[] upvars) {
|
||||||
{
|
|
||||||
auto upvar_count = std::ivec::len(upvars);
|
|
||||||
auto copy_args_bcx = new_raw_block_ctxt(fcx, fcx.llcopyargs);
|
auto copy_args_bcx = new_raw_block_ctxt(fcx, fcx.llcopyargs);
|
||||||
|
|
||||||
// Populate the upvars from the environment.
|
// Populate the upvars from the environment.
|
||||||
|
@ -4581,7 +4584,17 @@ fn load_environment(&@block_ctxt cx, &@fn_ctxt fcx,
|
||||||
auto llremotebindingsptr =
|
auto llremotebindingsptr =
|
||||||
copy_args_bcx.build.Load(llremotebindingsptrptr);
|
copy_args_bcx.build.Load(llremotebindingsptrptr);
|
||||||
auto i = 0u;
|
auto i = 0u;
|
||||||
while (i < upvar_count) {
|
auto end = std::ivec::len(upvars);
|
||||||
|
if (!option::is_none(cx.fcx.lliterbody)) {
|
||||||
|
end += 1u;
|
||||||
|
i += 1u;
|
||||||
|
auto lliterbodyptr =
|
||||||
|
copy_args_bcx.build.GEP(llremotebindingsptr,
|
||||||
|
~[C_int(0), C_int(0)]);
|
||||||
|
auto lliterbody = copy_args_bcx.build.Load(lliterbodyptr);
|
||||||
|
fcx.lliterbody = some(lliterbody);
|
||||||
|
}
|
||||||
|
while (i < end) {
|
||||||
auto upvar_id = upvars.(i);
|
auto upvar_id = upvars.(i);
|
||||||
auto llupvarptrptr =
|
auto llupvarptrptr =
|
||||||
copy_args_bcx.build.GEP(llremotebindingsptr,
|
copy_args_bcx.build.GEP(llremotebindingsptr,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue