Skip to content

Commit 8cbb957

Browse files
msullivanbrson
authored andcommitted
---
yaml --- r: 3997 b: refs/heads/master c: f8c6d28 h: refs/heads/master i: 3995: 9b824f8 v: v3
1 parent 55d6277 commit 8cbb957

File tree

5 files changed

+70
-19
lines changed

5 files changed

+70
-19
lines changed

[refs]

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
---
2-
refs/heads/master: c4bcd0a44d64d43a5c1dfde73d4e3f94e2419da7
2+
refs/heads/master: f8c6d282f8438fd2e3229d1d7a428df462f52076

trunk/src/comp/driver/rustc.rs

+7-2
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import syntax::codemap;
1010
import front::attr;
1111
import middle::trans;
1212
import middle::resolve;
13+
import middle::freevars;
1314
import middle::ty;
1415
import middle::typeck;
1516
import middle::tstate::ck;
@@ -131,7 +132,10 @@ fn compile_input(session::session sess, ast::crate_cfg cfg, str input,
131132
auto d =
132133
time(time_passes, "resolution",
133134
bind resolve::resolve_crate(sess, ast_map, crate));
134-
auto ty_cx = ty::mk_ctxt(sess, d._0, d._1, ast_map);
135+
auto freevars =
136+
time(time_passes, "freevar finding",
137+
bind freevars::annotate_freevars(sess, d._0, crate));
138+
auto ty_cx = ty::mk_ctxt(sess, d._0, d._1, ast_map, freevars);
135139
time[()](time_passes, "typechecking",
136140
bind typeck::check_crate(ty_cx, crate));
137141
if (sess.get_opts().run_typestate) {
@@ -196,7 +200,8 @@ fn pretty_print_input(session::session sess, ast::crate_cfg cfg,
196200
case (ppm_typed) {
197201
auto amap = middle::ast_map::map_crate(*crate);
198202
auto d = resolve::resolve_crate(sess, amap, crate);
199-
auto ty_cx = ty::mk_ctxt(sess, d._0, d._1, amap);
203+
auto freevars = freevars::annotate_freevars(sess, d._0, crate);
204+
auto ty_cx = ty::mk_ctxt(sess, d._0, d._1, amap, freevars);
200205
typeck::check_crate(ty_cx, crate);
201206
ann = rec(pre=ann_paren_for_expr,
202207
post=bind ann_typed_post(ty_cx, _));

trunk/src/comp/middle/freevars.rs

+56-9
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,29 @@
1-
// A pass that annotates for each loops with the free variables that
2-
// they contain.
1+
// A pass that annotates for each loops and functions with the free
2+
// variables that they contain.
33

44
import std::map;
55
import std::map::*;
66
import syntax::ast;
77
import syntax::walk;
88
import driver::session;
9-
import middle::ty;
9+
import middle::resolve;
1010
import syntax::codemap::span;
1111

12+
export annotate_freevars;
13+
export freevar_set;
14+
export freevar_map;
1215

16+
type freevar_set = ast::node_id[];
17+
type freevar_map = hashmap[ast::node_id, freevar_set];
1318

1419
// Searches through part of the AST for all references to locals or
1520
// upvars in this frame and returns the list of definition IDs thus found.
1621
// Since we want to be able to collect upvars in some arbitrary piece
1722
// of the AST, we take a walker function that we invoke with a visitor
1823
// in order to start the search.
19-
fn collect_upvars(&ty::ctxt tcx, &fn (&walk::ast_visitor) walker,
20-
ast::node_id[] initial_decls) -> ast::node_id[] {
24+
fn collect_freevars(&resolve::def_map def_map, &session::session sess,
25+
&fn (&walk::ast_visitor) walker,
26+
ast::node_id[] initial_decls) -> ast::node_id[] {
2127
type env =
2228
@rec(mutable ast::node_id[] refs,
2329
hashmap[ast::node_id, ()] decls,
@@ -33,7 +39,7 @@ fn collect_upvars(&ty::ctxt tcx, &fn (&walk::ast_visitor) walker,
3339
case (ast::expr_path(?path)) {
3440
if (! e.def_map.contains_key(expr.id)) {
3541
e.sess.span_fatal(expr.span,
36-
"internal error in collect_upvars");
42+
"internal error in collect_freevars");
3743
}
3844
alt (e.def_map.get(expr.id)) {
3945
case (ast::def_arg(?did)) { e.refs += ~[did._1]; }
@@ -62,17 +68,17 @@ fn collect_upvars(&ty::ctxt tcx, &fn (&walk::ast_visitor) walker,
6268
let env e =
6369
@rec(mutable refs=~[],
6470
decls=decls,
65-
def_map=tcx.def_map,
66-
sess=tcx.sess);
71+
def_map=def_map,
72+
sess=sess);
6773
auto visitor =
6874
@rec(visit_fn_pre=bind walk_fn(e, _, _, _, _, _),
6975
visit_local_pre=bind walk_local(e, _),
7076
visit_expr_pre=bind walk_expr(e, _),
7177
visit_pat_pre=bind walk_pat(e, _)
7278
with walk::default_visitor());
7379
walker(*visitor);
74-
// Calculate (refs - decls). This is the set of captured upvars.
7580

81+
// Calculate (refs - decls). This is the set of captured upvars.
7682
let ast::node_id[] result = ~[];
7783
for (ast::node_id ref_id_ in e.refs) {
7884
auto ref_id = ref_id_;
@@ -81,6 +87,47 @@ fn collect_upvars(&ty::ctxt tcx, &fn (&walk::ast_visitor) walker,
8187
ret result;
8288
}
8389

90+
// Build a map from every function and for-each body to a set of the
91+
// freevars contained in it. The implementation is not particularly
92+
// efficient as it fully recomputes the free variables at every
93+
// node of interest rather than building up the free variables in
94+
// one pass. This could be improved upon if it turns out to matter.
95+
fn annotate_freevars(&session::session sess, &resolve::def_map def_map,
96+
&@ast::crate crate) -> freevar_map {
97+
type env =
98+
rec(freevar_map freevars,
99+
resolve::def_map def_map,
100+
session::session sess);
101+
102+
fn walk_fn(env e, &ast::_fn f, &ast::ty_param[] tps, &span sp,
103+
&ast::fn_ident i, ast::node_id nid) {
104+
auto walker = bind walk::walk_fn(_, f, tps, sp, i, nid);
105+
auto vars = collect_freevars(e.def_map, e.sess, walker, ~[]);
106+
e.freevars.insert(nid, vars);
107+
}
108+
fn walk_expr(env e, &@ast::expr expr) {
109+
alt (expr.node) {
110+
ast::expr_for_each(?local, _, ?body) {
111+
auto vars = collect_freevars(e.def_map, e.sess,
112+
bind walk::walk_block(_, body),
113+
~[local.node.id]);
114+
e.freevars.insert(body.node.id, vars);
115+
}
116+
_ {}
117+
}
118+
}
119+
120+
let env e =
121+
rec(freevars = new_int_hash(), def_map=def_map, sess=sess);
122+
auto visitor =
123+
rec(visit_fn_pre=bind walk_fn(e, _, _, _, _, _),
124+
visit_expr_pre=bind walk_expr(e, _)
125+
with walk::default_visitor());
126+
walk::walk_crate(visitor, *crate);
127+
128+
ret e.freevars;
129+
}
130+
84131
// Local Variables:
85132
// mode: rust
86133
// fill-column: 78;

trunk/src/comp/middle/trans.rs

+3-6
Original file line numberDiff line numberDiff line change
@@ -4276,17 +4276,14 @@ fn trans_for_each(&@block_ctxt cx, &@ast::local local, &@ast::expr seq,
42764276
*
42774277
*/
42784278

4279-
// Step 1: walk body and figure out which references it makes
4280-
// escape. This could be determined upstream, and probably ought
4281-
// to be so, eventualy.
4279+
// Step 1: Generate code to build an environment containing pointers
4280+
// to all of the upvars
42824281
auto lcx = cx.fcx.lcx;
42834282

42844283
// FIXME: possibly support alias-mode here?
42854284
auto decl_ty = node_id_type(lcx.ccx, local.node.id);
42864285
auto decl_id = local.node.id;
4287-
auto upvars = freevars::collect_upvars(cx.fcx.lcx.ccx.tcx,
4288-
bind walk::walk_block(_, body),
4289-
~[decl_id]);
4286+
auto upvars = cx.fcx.lcx.ccx.tcx.freevars.get(body.node.id);
42904287

42914288
auto environment_data = build_environment(cx, upvars);
42924289
auto llenvptr = environment_data._0;

trunk/src/comp/middle/ty.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,7 @@ type ctxt =
210210
resolve::def_map def_map,
211211
node_type_table node_types,
212212
ast_map::map items,
213+
freevars::freevar_map freevars,
213214

214215
constr_table fn_constrs,
215216
type_cache tcache,
@@ -392,7 +393,7 @@ fn mk_rcache() -> creader_cache {
392393
}
393394

394395
fn mk_ctxt(session::session s, resolve::def_map dm, constr_table cs,
395-
ast_map::map amap) -> ctxt {
396+
ast_map::map amap, freevars::freevar_map freevars) -> ctxt {
396397
let node_type_table ntt =
397398
@smallintmap::mk[ty::ty_param_substs_opt_and_ty]();
398399
auto tcache = new_def_hash[ty::ty_param_count_and_ty]();
@@ -403,6 +404,7 @@ fn mk_ctxt(session::session s, resolve::def_map dm, constr_table cs,
403404
def_map=dm,
404405
node_types=ntt,
405406
items=amap,
407+
freevars=freevars,
406408
fn_constrs=cs,
407409
tcache=tcache,
408410
rcache=mk_rcache(),

0 commit comments

Comments
 (0)