about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Sullivan <sully@msully.net>2011-08-04 15:44:53 -0700
committerMichael Sullivan <sully@msully.net>2011-08-04 16:18:12 -0700
commit95680474e27064a5745e9477a04765247285fb87 (patch)
tree19db4712b973fffb1c830fbbfe613717892e31fd
parentae3312002a87d673ae97a9e75455060fcd111069 (diff)
Use lambdas in the freevars pass.
-rw-r--r--src/comp/middle/freevars.rs114
1 files changed, 50 insertions, 64 deletions
diff --git a/src/comp/middle/freevars.rs b/src/comp/middle/freevars.rs
index 8cd898b5813..2290ff1fa5e 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 {