Move collect_upvars into its own file.
This commit is contained in:
committed by
Brian Anderson
parent
2e6197aa95
commit
c4bcd0a44d
91
src/comp/middle/freevars.rs
Normal file
91
src/comp/middle/freevars.rs
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
// A pass that annotates for each loops with the free variables that
|
||||||
|
// they contain.
|
||||||
|
|
||||||
|
import std::map;
|
||||||
|
import std::map::*;
|
||||||
|
import syntax::ast;
|
||||||
|
import syntax::walk;
|
||||||
|
import driver::session;
|
||||||
|
import middle::ty;
|
||||||
|
import syntax::codemap::span;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Searches through part of the AST for all references to locals or
|
||||||
|
// upvars in this frame and returns the list of definition IDs thus found.
|
||||||
|
// Since we want to be able to collect upvars in some arbitrary piece
|
||||||
|
// of the AST, we take a walker function that we invoke with a visitor
|
||||||
|
// in order to start the search.
|
||||||
|
fn collect_upvars(&ty::ctxt tcx, &fn (&walk::ast_visitor) walker,
|
||||||
|
ast::node_id[] initial_decls) -> ast::node_id[] {
|
||||||
|
type env =
|
||||||
|
@rec(mutable ast::node_id[] refs,
|
||||||
|
hashmap[ast::node_id, ()] decls,
|
||||||
|
resolve::def_map def_map,
|
||||||
|
session::session sess);
|
||||||
|
|
||||||
|
fn walk_fn(env e, &ast::_fn f, &ast::ty_param[] tps, &span sp,
|
||||||
|
&ast::fn_ident i, ast::node_id nid) {
|
||||||
|
for (ast::arg a in f.decl.inputs) { e.decls.insert(a.id, ()); }
|
||||||
|
}
|
||||||
|
fn walk_expr(env e, &@ast::expr expr) {
|
||||||
|
alt (expr.node) {
|
||||||
|
case (ast::expr_path(?path)) {
|
||||||
|
if (! e.def_map.contains_key(expr.id)) {
|
||||||
|
e.sess.span_fatal(expr.span,
|
||||||
|
"internal error in collect_upvars");
|
||||||
|
}
|
||||||
|
alt (e.def_map.get(expr.id)) {
|
||||||
|
case (ast::def_arg(?did)) { e.refs += ~[did._1]; }
|
||||||
|
case (ast::def_local(?did)) { e.refs += ~[did._1]; }
|
||||||
|
case (ast::def_binding(?did)) { e.refs += ~[did._1]; }
|
||||||
|
case (_) { /* no-op */ }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case (_) { }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn walk_local(env e, &@ast::local local) {
|
||||||
|
e.decls.insert(local.node.id, ());
|
||||||
|
}
|
||||||
|
fn walk_pat(env e, &@ast::pat p) {
|
||||||
|
alt (p.node) {
|
||||||
|
case (ast::pat_bind(_)) {
|
||||||
|
e.decls.insert(p.id, ());
|
||||||
|
}
|
||||||
|
case (_) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let hashmap[ast::node_id, ()] decls = new_int_hash[()]();
|
||||||
|
for (ast::node_id decl in initial_decls) { decls.insert(decl, ()); }
|
||||||
|
|
||||||
|
let env e =
|
||||||
|
@rec(mutable refs=~[],
|
||||||
|
decls=decls,
|
||||||
|
def_map=tcx.def_map,
|
||||||
|
sess=tcx.sess);
|
||||||
|
auto visitor =
|
||||||
|
@rec(visit_fn_pre=bind walk_fn(e, _, _, _, _, _),
|
||||||
|
visit_local_pre=bind walk_local(e, _),
|
||||||
|
visit_expr_pre=bind walk_expr(e, _),
|
||||||
|
visit_pat_pre=bind walk_pat(e, _)
|
||||||
|
with walk::default_visitor());
|
||||||
|
walker(*visitor);
|
||||||
|
// Calculate (refs - decls). This is the set of captured upvars.
|
||||||
|
|
||||||
|
let ast::node_id[] result = ~[];
|
||||||
|
for (ast::node_id ref_id_ in e.refs) {
|
||||||
|
auto ref_id = ref_id_;
|
||||||
|
if (!decls.contains_key(ref_id)) { result += ~[ref_id]; }
|
||||||
|
}
|
||||||
|
ret result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Local Variables:
|
||||||
|
// mode: rust
|
||||||
|
// fill-column: 78;
|
||||||
|
// indent-tabs-mode: nil
|
||||||
|
// c-basic-offset: 4
|
||||||
|
// buffer-file-coding-system: utf-8-unix
|
||||||
|
// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
|
||||||
|
// End:
|
||||||
@@ -27,6 +27,7 @@ import syntax::ast;
|
|||||||
import syntax::walk;
|
import syntax::walk;
|
||||||
import driver::session;
|
import driver::session;
|
||||||
import middle::ty;
|
import middle::ty;
|
||||||
|
import middle::freevars;
|
||||||
import back::link;
|
import back::link;
|
||||||
import back::x86;
|
import back::x86;
|
||||||
import back::abi;
|
import back::abi;
|
||||||
@@ -4107,76 +4108,6 @@ fn trans_for(&@block_ctxt cx, &@ast::local local, &@ast::expr seq,
|
|||||||
|
|
||||||
// Iterator translation
|
// Iterator translation
|
||||||
|
|
||||||
// Searches through part of the AST for all references to locals or
|
|
||||||
// upvars in this frame and returns the list of definition IDs thus found.
|
|
||||||
// Since we want to be able to collect upvars in some arbitrary piece
|
|
||||||
// of the AST, we take a walker function that we invoke with a visitor
|
|
||||||
// in order to start the search.
|
|
||||||
fn collect_upvars(&@block_ctxt cx, &fn (&walk::ast_visitor) walker,
|
|
||||||
ast::node_id[] initial_decls) -> ast::node_id[] {
|
|
||||||
type env =
|
|
||||||
@rec(mutable ast::node_id[] refs,
|
|
||||||
hashmap[ast::node_id, ()] decls,
|
|
||||||
resolve::def_map def_map,
|
|
||||||
session::session sess);
|
|
||||||
|
|
||||||
fn walk_fn(env e, &ast::_fn f, &ast::ty_param[] tps, &span sp,
|
|
||||||
&ast::fn_ident i, ast::node_id nid) {
|
|
||||||
for (ast::arg a in f.decl.inputs) { e.decls.insert(a.id, ()); }
|
|
||||||
}
|
|
||||||
fn walk_expr(env e, &@ast::expr expr) {
|
|
||||||
alt (expr.node) {
|
|
||||||
case (ast::expr_path(?path)) {
|
|
||||||
if (! e.def_map.contains_key(expr.id)) {
|
|
||||||
e.sess.span_fatal(expr.span,
|
|
||||||
"internal error in collect_upvars");
|
|
||||||
}
|
|
||||||
alt (e.def_map.get(expr.id)) {
|
|
||||||
case (ast::def_arg(?did)) { e.refs += ~[did._1]; }
|
|
||||||
case (ast::def_local(?did)) { e.refs += ~[did._1]; }
|
|
||||||
case (ast::def_binding(?did)) { e.refs += ~[did._1]; }
|
|
||||||
case (_) { /* no-op */ }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case (_) { }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn walk_local(env e, &@ast::local local) {
|
|
||||||
e.decls.insert(local.node.id, ());
|
|
||||||
}
|
|
||||||
fn walk_pat(env e, &@ast::pat p) {
|
|
||||||
alt (p.node) {
|
|
||||||
case (ast::pat_bind(_)) {
|
|
||||||
e.decls.insert(p.id, ());
|
|
||||||
}
|
|
||||||
case (_) {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let hashmap[ast::node_id, ()] decls = new_int_hash[()]();
|
|
||||||
for (ast::node_id decl in initial_decls) { decls.insert(decl, ()); }
|
|
||||||
|
|
||||||
let env e =
|
|
||||||
@rec(mutable refs=~[],
|
|
||||||
decls=decls,
|
|
||||||
def_map=cx.fcx.lcx.ccx.tcx.def_map,
|
|
||||||
sess=cx.fcx.lcx.ccx.tcx.sess);
|
|
||||||
auto visitor =
|
|
||||||
@rec(visit_fn_pre=bind walk_fn(e, _, _, _, _, _),
|
|
||||||
visit_local_pre=bind walk_local(e, _),
|
|
||||||
visit_expr_pre=bind walk_expr(e, _),
|
|
||||||
visit_pat_pre=bind walk_pat(e, _)
|
|
||||||
with walk::default_visitor());
|
|
||||||
walker(*visitor);
|
|
||||||
// Calculate (refs - decls). This is the set of captured upvars.
|
|
||||||
|
|
||||||
let ast::node_id[] result = ~[];
|
|
||||||
for (ast::node_id ref_id_ in e.refs) {
|
|
||||||
auto ref_id = ref_id_;
|
|
||||||
if (!decls.contains_key(ref_id)) { result += ~[ref_id]; }
|
|
||||||
}
|
|
||||||
ret result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Finds the ValueRef associated with a variable in a function
|
// Finds the ValueRef associated with a variable in a function
|
||||||
// context. It checks locals, upvars, and args.
|
// context. It checks locals, upvars, and args.
|
||||||
fn find_variable(&@fn_ctxt fcx, ast::node_id nid) -> ValueRef {
|
fn find_variable(&@fn_ctxt fcx, ast::node_id nid) -> ValueRef {
|
||||||
@@ -4353,8 +4284,9 @@ fn trans_for_each(&@block_ctxt cx, &@ast::local local, &@ast::expr seq,
|
|||||||
// FIXME: possibly support alias-mode here?
|
// FIXME: possibly support alias-mode here?
|
||||||
auto decl_ty = node_id_type(lcx.ccx, local.node.id);
|
auto decl_ty = node_id_type(lcx.ccx, local.node.id);
|
||||||
auto decl_id = local.node.id;
|
auto decl_id = local.node.id;
|
||||||
auto upvars = collect_upvars(cx, bind walk::walk_block(_, body),
|
auto upvars = freevars::collect_upvars(cx.fcx.lcx.ccx.tcx,
|
||||||
~[decl_id]);
|
bind walk::walk_block(_, body),
|
||||||
|
~[decl_id]);
|
||||||
|
|
||||||
auto environment_data = build_environment(cx, upvars);
|
auto environment_data = build_environment(cx, upvars);
|
||||||
auto llenvptr = environment_data._0;
|
auto llenvptr = environment_data._0;
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ mod middle {
|
|||||||
mod resolve;
|
mod resolve;
|
||||||
mod typeck;
|
mod typeck;
|
||||||
mod alias;
|
mod alias;
|
||||||
|
mod freevars;
|
||||||
|
|
||||||
mod tstate {
|
mod tstate {
|
||||||
mod ck;
|
mod ck;
|
||||||
|
|||||||
Reference in New Issue
Block a user