diff --git a/src/comp/middle/freevars.rs b/src/comp/middle/freevars.rs index 8cd898b5813c..2290ff1fa5e8 100644 --- a/src/comp/middle/freevars.rs +++ b/src/comp/middle/freevars.rs @@ -26,8 +26,8 @@ export def_lookup; // Throughout the compiler, variables are generally dealt with using the // node_ids of the reference sites and not the def_id of the definition // site. Thus we store a set are the definitions along with a vec of one -// referencing node_id per free variable. The set is useful for testing -// membership, the list of referencing sites is what you want for most +// "canonical" referencing node_id per free variable. The set is useful for +// testing membership, the list of referencing sites is what you want for most // other things. type freevar_set = hashset[ast::node_id]; type freevar_info = {defs: freevar_set, refs: @ast::node_id[]}; @@ -41,67 +41,61 @@ type freevar_map = hashmap[ast::node_id, freevar_info]; fn collect_freevars(def_map: &resolve::def_map, sess: &session::session, walker: &fn(&visit::vt[()]) , initial_decls: ast::node_id[]) -> freevar_info { - type env = - @{mutable refs: ast::node_id[], - decls: hashset[ast::node_id], - def_map: resolve::def_map, - sess: session::session}; + let decls = new_int_hash(); + for decl: ast::node_id in initial_decls { set_add(decls, decl); } + let refs = @mutable ~[]; - fn walk_fn(e: env, f: &ast::_fn, tps: &ast::ty_param[], sp: &span, - i: &ast::fn_ident, nid: ast::node_id) { - for a: ast::arg in f.decl.inputs { e.decls.insert(a.id, ()); } - } - fn walk_expr(e: env, expr: &@ast::expr) { + let walk_fn = lambda(f: &ast::_fn, tps: &ast::ty_param[], sp: &span, + i: &ast::fn_ident, nid: ast::node_id) { + for a: ast::arg in f.decl.inputs { set_add(decls, a.id); } + }; + let walk_expr = lambda(expr: &@ast::expr) { alt expr.node { ast::expr_path(path) { - if !e.def_map.contains_key(expr.id) { - e.sess.span_fatal(expr.span, - "internal error in collect_freevars"); + if !def_map.contains_key(expr.id) { + sess.span_fatal(expr.span, + "internal error in collect_freevars"); } - alt e.def_map.get(expr.id) { - ast::def_arg(did) { e.refs += ~[expr.id]; } - ast::def_local(did) { e.refs += ~[expr.id]; } - ast::def_binding(did) { e.refs += ~[expr.id]; } + alt def_map.get(expr.id) { + ast::def_arg(did) { *refs += ~[expr.id]; } + ast::def_local(did) { *refs += ~[expr.id]; } + ast::def_binding(did) { *refs += ~[expr.id]; } _ {/* no-op */ } } } _ { } } - } - fn walk_local(e: env, local: &@ast::local) { + }; + let walk_local = lambda(local: &@ast::local) { for each b: @ast::pat in ast::pat_bindings(local.node.pat) { - set_add(e.decls, b.id); + set_add(decls, b.id); } - } - fn walk_pat(e: env, p: &@ast::pat) { - alt p.node { ast::pat_bind(_) { set_add(e.decls, p.id); } _ { } } - } - let decls: hashset[ast::node_id] = new_int_hash(); - for decl: ast::node_id in initial_decls { set_add(decls, decl); } + }; + let walk_pat = lambda(p: &@ast::pat) { + alt p.node { ast::pat_bind(_) { set_add(decls, p.id); } _ { } } + }; - let e: env = - @{mutable refs: ~[], decls: decls, def_map: def_map, sess: sess}; walker(visit::mk_simple_visitor - (@{visit_local: bind walk_local(e, _), - visit_pat: bind walk_pat(e, _), - visit_expr: bind walk_expr(e, _), - visit_fn: bind walk_fn(e, _, _, _, _, _) + (@{visit_local: walk_local, + visit_pat: walk_pat, + visit_expr: walk_expr, + visit_fn: walk_fn with *visit::default_simple_visitor()})); // Calculate (refs - decls). This is the set of captured upvars. // We build a vec of the node ids of the uses and a set of the // node ids of the definitions. - let refs = ~[]; + let canonical_refs = ~[]; let defs = new_int_hash(); - for ref_id_: ast::node_id in e.refs { + for ref_id_: ast::node_id in *refs { let ref_id = ref_id_; let def_id = ast::def_id_of_def(def_map.get(ref_id)).node; if !decls.contains_key(def_id) && !defs.contains_key(def_id) { - refs += ~[ref_id]; + canonical_refs += ~[ref_id]; set_add(defs, def_id); } } - ret {defs: defs, refs: @refs}; + ret {defs: defs, refs: @canonical_refs}; } // Build a map from every function and for-each body to a set of the @@ -111,46 +105,38 @@ fn collect_freevars(def_map: &resolve::def_map, sess: &session::session, // one pass. This could be improved upon if it turns out to matter. fn annotate_freevars(sess: &session::session, def_map: &resolve::def_map, crate: &@ast::crate) -> freevar_map { - type env = - {freevars: freevar_map, - def_map: resolve::def_map, - sess: session::session}; + let freevars = new_int_hash(); - fn walk_fn(e: env, f: &ast::_fn, tps: &ast::ty_param[], sp: &span, - i: &ast::fn_ident, nid: ast::node_id) { - fn start_walk(f: &ast::_fn, tps: &ast::ty_param[], sp: &span, - i: &ast::fn_ident, nid: ast::node_id, - v: &visit::vt[()]) { + let walk_fn = lambda(f: &ast::_fn, tps: &ast::ty_param[], sp: &span, + i: &ast::fn_ident, nid: ast::node_id) { + let start_walk = lambda(v: &visit::vt[()]) { v.visit_fn(f, tps, sp, i, nid, (), v); - } - let walker = bind start_walk(f, tps, sp, i, nid, _); - let vars = collect_freevars(e.def_map, e.sess, walker, ~[]); - e.freevars.insert(nid, vars); - } - fn walk_expr(e: env, expr: &@ast::expr) { + }; + let vars = collect_freevars(def_map, sess, start_walk, ~[]); + freevars.insert(nid, vars); + }; + let walk_expr = lambda(expr: &@ast::expr) { alt expr.node { ast::expr_for_each(local, _, body) { - fn start_walk(b: &ast::blk, v: &visit::vt[()]) { - v.visit_block(b, (), v); - } + let start_walk = lambda(v: &visit::vt[()]) { + v.visit_block(body, (), v); + }; let bound = ast::pat_binding_ids(local.node.pat); let vars = - collect_freevars(e.def_map, e.sess, bind start_walk(body, _), - bound); - e.freevars.insert(body.node.id, vars); + collect_freevars(def_map, sess, start_walk, bound); + freevars.insert(body.node.id, vars); } _ { } } - } + }; - let e: env = {freevars: new_int_hash(), def_map: def_map, sess: sess}; let visitor = - visit::mk_simple_visitor(@{visit_fn: bind walk_fn(e, _, _, _, _, _), - visit_expr: bind walk_expr(e, _) + visit::mk_simple_visitor(@{visit_fn: walk_fn, + visit_expr: walk_expr with *visit::default_simple_visitor()}); visit::visit_crate(*crate, (), visitor); - ret e.freevars; + ret freevars; } fn get_freevar_info(tcx: &ty::ctxt, fid: ast::node_id) -> freevar_info {