aboutsummaryrefslogtreecommitdiff
path: root/src/comp/middle
diff options
context:
space:
mode:
Diffstat (limited to 'src/comp/middle')
-rw-r--r--src/comp/middle/capture.rs119
-rw-r--r--src/comp/middle/resolve.rs61
-rw-r--r--src/comp/middle/trans.rs3
3 files changed, 49 insertions, 134 deletions
diff --git a/src/comp/middle/capture.rs b/src/comp/middle/capture.rs
deleted file mode 100644
index 7124554a..00000000
--- a/src/comp/middle/capture.rs
+++ /dev/null
@@ -1,119 +0,0 @@
-import driver::session;
-import front::ast;
-import std::map::hashmap;
-import std::option;
-import std::option::some;
-import std::option::none;
-import std::_int;
-import std::_vec;
-import util::common;
-import resolve::def_map;
-
-type fn_id_of_local = std::map::hashmap[ast::def_id, ast::def_id];
-type env = rec(mutable vec[ast::def_id] current_context, // fn or obj
- def_map def_map,
- fn_id_of_local idmap,
- session::session sess);
-
-fn current_context(&env e) -> ast::def_id {
- ret e.current_context.(_vec::len(e.current_context) - 1u);
-}
-
-fn enter_item(@env e, &@ast::item i) {
- alt (i.node) {
- case (ast::item_fn(?name, _, _, ?id, _)) {
- _vec::push(e.current_context, id);
- }
- case (ast::item_obj(?name, _, _, ?ids, _)) {
- _vec::push(e.current_context, ids.ty);
- }
- case (_) {}
- }
-}
-
-fn leave_item(@env e, &@ast::item i) {
- alt (i.node) {
- case (ast::item_fn(?name, _, _, ?id, _)) {
- _vec::pop(e.current_context);
- }
- case (ast::item_obj(_, _, _, ?ids, _)) {
- _vec::pop(e.current_context);
- }
- case (_) {}
- }
-}
-
-fn walk_expr(@env e, &@ast::expr x) {
- alt (x.node) {
- case (ast::expr_for(?d, _, _, _)) {
- alt (d.node) {
- case (ast::decl_local(?local)) {
- e.idmap.insert(local.id, current_context(*e));
- }
- case (_) { }
- }
- }
- case (ast::expr_for_each(?d, _, _, _)) {
- alt (d.node) {
- case (ast::decl_local(?local)) {
- e.idmap.insert(local.id, current_context(*e));
- }
- case (_) { }
- }
- }
- case (ast::expr_path(?pt, ?ann)) {
- auto local_id;
- alt (e.def_map.get(ast::ann_tag(ann))) {
- case (ast::def_local(?id)) { local_id = id; }
- case (_) { ret; }
- }
- auto df = ast::def_id_of_def(e.def_map.get(ast::ann_tag(ann)));
- auto def_context = e.idmap.get(df);
-
- if (current_context(*e) != def_context) {
- e.sess.span_err(x.span,
- "attempted dynamic environment-capture");
- }
- }
- case (_) { }
- }
-}
-
-fn walk_block(@env e, &ast::block b) {
- for (@ast::stmt st in b.node.stmts) {
- alt (st.node) {
- case (ast::stmt_decl(?d,_)) {
- alt (d.node) {
- case (ast::decl_local(?loc)) {
- e.idmap.insert(loc.id, current_context(*e));
- }
- case (_) { }
- }
- }
- case (_) { }
- }
- }
-}
-
-fn check_for_captures(session::session sess, @ast::crate crate, def_map dm) {
- let vec[ast::def_id] curctx = vec();
- auto env = @rec(mutable current_context = curctx,
- def_map = dm,
- idmap = common::new_def_hash[ast::def_id](),
- sess = sess);
- auto visitor = rec(visit_item_pre = bind enter_item(env, _),
- visit_item_post = bind leave_item(env, _),
- visit_block_pre = bind walk_block(env, _),
- visit_expr_pre = bind walk_expr(env, _)
- with walk::default_visitor());
- walk::walk_crate(visitor, *crate);
-}
-
-// 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:
diff --git a/src/comp/middle/resolve.rs b/src/comp/middle/resolve.rs
index ce7a2376..11837033 100644
--- a/src/comp/middle/resolve.rs
+++ b/src/comp/middle/resolve.rs
@@ -317,8 +317,8 @@ fn resolve_import(&env e, &@ast::view_item it, &list[scope] sc) {
if (n_idents == 1u) {
register(e, defid, it.span, end_id,
- lookup_in_scope(e, sc, end_id, ns_value),
- lookup_in_scope(e, sc, end_id, ns_type));
+ lookup_in_scope(e, sc, it.span, end_id, ns_value),
+ lookup_in_scope(e, sc, it.span, end_id, ns_type));
} else {
auto dcur = lookup_in_scope_strict(e, sc, it.span, ids.(0), ns_value);
auto i = 1u;
@@ -394,7 +394,7 @@ fn lookup_path_strict(&env e, &list[scope] sc, &span sp, vec[ident] idents,
fn lookup_in_scope_strict(&env e, list[scope] sc, &span sp, ident id,
namespace ns) -> def {
- alt (lookup_in_scope(e, sc, id, ns)) {
+ alt (lookup_in_scope(e, sc, sp, id, ns)) {
case (none[def]) {
unresolved(e, sp, id, ns_name(ns));
fail;
@@ -405,7 +405,35 @@ fn lookup_in_scope_strict(&env e, list[scope] sc, &span sp, ident id,
}
}
-fn lookup_in_scope(&env e, list[scope] sc, ident id, namespace ns)
+fn scope_is_fn(&scope sc) -> bool {
+ ret alt (sc) {
+ case (scope_item(?it)) {
+ alt (it.node) {
+ case (ast::item_fn(_, _, _, _, _)) { true }
+ case (_) { false }
+ }
+ }
+ case (scope_native_item(_)) { true }
+ case (_) { false }
+ };
+}
+
+fn def_is_local(&def d) -> bool {
+ ret alt (d) {
+ case (ast::def_arg(_)) { true }
+ case (ast::def_local(_)) { true }
+ case (ast::def_binding(_)) { true }
+ case (_) { false }
+ };
+}
+fn def_is_obj_field(&def d) -> bool {
+ ret alt (d) {
+ case (ast::def_obj_field(_)) { true }
+ case (_) { false }
+ };
+}
+
+fn lookup_in_scope(&env e, list[scope] sc, &span sp, ident id, namespace ns)
-> option::t[def] {
fn in_scope(&env e, ident id, &scope s, namespace ns)
-> option::t[def] {
@@ -441,7 +469,6 @@ fn lookup_in_scope(&env e, list[scope] sc, ident id, namespace ns)
case (_) {}
}
}
-
case (scope_native_item(?it)) {
alt (it.node) {
case (ast::native_item_fn(_, _, ?decl, ?ty_params, _, _)){
@@ -449,7 +476,6 @@ fn lookup_in_scope(&env e, list[scope] sc, ident id, namespace ns)
}
}
}
-
case (scope_loop(?d)) {
if (ns == ns_value) {
alt (d.node) {
@@ -461,11 +487,9 @@ fn lookup_in_scope(&env e, list[scope] sc, ident id, namespace ns)
}
}
}
-
case (scope_block(?b)) {
ret lookup_in_block(id, b.node, ns);
}
-
case (scope_arm(?a)) {
if (ns == ns_value) {
ret lookup_in_pat(id, *a.pat);
@@ -475,16 +499,30 @@ fn lookup_in_scope(&env e, list[scope] sc, ident id, namespace ns)
ret none[def];
}
+ auto left_fn = false;
+ // Used to determine whether obj fields are in scope
+ auto left_fn_level2 = false;
while (true) {
alt (sc) {
case (nil[scope]) {
ret none[def];
}
case (cons[scope](?hd, ?tl)) {
- alt (in_scope(e, id, hd, ns)) {
- case (some[def](?x)) { ret some(x); }
- case (_) { sc = *tl; }
+ auto fnd = in_scope(e, id, hd, ns);
+ if (fnd != none[def]) {
+ auto df = option::get(fnd);
+ if ((left_fn && def_is_local(df)) ||
+ (left_fn_level2 && def_is_obj_field(df))) {
+ e.sess.span_err(sp, "attempted dynamic " +
+ "environment-capture");
+ }
+ ret fnd;
+ }
+ if (left_fn) { left_fn_level2 = true; }
+ if (ns == ns_value && !left_fn) {
+ left_fn = scope_is_fn(hd);
}
+ sc = *tl;
}
}
}
@@ -841,7 +879,6 @@ fn check_def_by_ns(def d, namespace ns) -> bool {
case (ast::def_const(?id)) { ns == ns_value }
case (ast::def_arg(?id)) { ns == ns_value }
case (ast::def_local(?id)) { ns == ns_value }
- case (ast::def_upvar(?id)) { ns == ns_value }
case (ast::def_variant(_, ?id)) { ns == ns_value }
case (ast::def_ty(?id)) { ns == ns_type }
case (ast::def_binding(?id)) { ns == ns_type }
diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs
index 78a7a16a..d822be17 100644
--- a/src/comp/middle/trans.rs
+++ b/src/comp/middle/trans.rs
@@ -3807,9 +3807,6 @@ fn collect_upvars(&@block_ctxt cx, &ast::block bloc,
case (ast::def_local(?did)) {
_vec::push[ast::def_id](e.refs, did);
}
- case (ast::def_upvar(?did)) {
- _vec::push[ast::def_id](e.refs, did);
- }
case (_) {}
}
}