about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorBrian Anderson <andersrb@gmail.com>2011-04-24 19:40:01 -0400
committerBrian Anderson <andersrb@gmail.com>2011-05-01 16:57:36 -0400
commit459b0ec8339da2b7ba2f76c3fd110f5b3e971a73 (patch)
treee9e7365d9eb768d7ec236d3ca47af0158831b1bf /src
parent40624e35d74e5d200ae689c02753f0d60924e668 (diff)
downloadrust-459b0ec8339da2b7ba2f76c3fd110f5b3e971a73.tar.gz
rust-459b0ec8339da2b7ba2f76c3fd110f5b3e971a73.zip
Implement simple module export
Diffstat (limited to 'src')
-rw-r--r--src/comp/middle/resolve.rs72
-rw-r--r--src/test/compile-fail/export-boot.rs19
-rw-r--r--src/test/compile-fail/export.rs4
-rw-r--r--src/test/compile-fail/export2.rs25
-rw-r--r--src/test/run-pass/export-non-interference2.rs18
-rw-r--r--src/test/run-pass/export-non-interference3.rs19
6 files changed, 143 insertions, 14 deletions
diff --git a/src/comp/middle/resolve.rs b/src/comp/middle/resolve.rs
index 8ea91916a52..82975112816 100644
--- a/src/comp/middle/resolve.rs
+++ b/src/comp/middle/resolve.rs
@@ -27,8 +27,17 @@ tag scope {
     scope_arm(ast.arm);
 }
 
+// This indicates whether we're searching up the scope chain
+// or whether we've found a path component and started following
+// it back down, which has an effect on export visibility
+tag search_direction {
+    up;
+    down;
+}
+
 type env = rec(list[scope] scopes,
-               session.session sess);
+               session.session sess,
+               search_direction direction);
 
 tag namespace {
     ns_value;
@@ -148,7 +157,8 @@ fn find_final_def(&env e, import_map index,
             auto len = _vec.len[ident](idents);
             auto rest_idents = _vec.slice[ident](idents, 1u, len);
             auto empty_e = rec(scopes = nil[scope],
-                               sess = e.sess);
+                               sess = e.sess,
+                               direction = down);
             auto tmp_e = update_env_for_item(empty_e, i);
             auto next_i = rest_idents.(0);
             auto next_ = lookup_name_wrapped(tmp_e, next_i, ns);
@@ -172,7 +182,9 @@ fn find_final_def(&env e, import_map index,
                 -> def_wrap {
             auto len = _vec.len[ident](idents);
             auto rest_idents = _vec.slice[ident](idents, 1u, len);
-            auto empty_e = rec(scopes = nil[scope], sess = e.sess);
+            auto empty_e = rec(scopes = nil[scope],
+                               sess = e.sess,
+                               direction = down);
             auto tmp_e = update_env_for_external_mod(empty_e, mod_id, idents);
             auto next_i = rest_idents.(0);
             auto next_ = lookup_name_wrapped(tmp_e, next_i, ns);
@@ -347,8 +359,40 @@ fn lookup_name_wrapped(&env e, ast.ident i, namespace ns)
         fail;
     }
 
-    fn check_mod(ast.ident i, ast._mod m, namespace ns)
+    fn check_mod(&env e, ast.ident i, ast._mod m, namespace ns)
             -> option.t[def_wrap] {
+
+        fn visible(&env e, ast.ident i, ast._mod m) -> bool {
+
+            alt (e.direction) {
+                case (up) {
+                    ret true;
+                }
+                case (down) {
+                    // fall through
+                }
+            }
+
+            auto count = 0;
+            for (@ast.view_item vi in m.view_items) {
+                alt (vi.node) {
+                    case (ast.view_item_export(?id)) {
+                        if (_str.eq(i, id)) {
+                            ret true;
+                        }
+                        count += 1;
+                    }
+                    case (_) { /* fall through */ }
+                }
+            }
+            // If there are no declared exports then everything is exported
+            if (count == 0) {
+                ret true;
+            } else {
+                ret false;
+            }
+        }
+
         alt (m.index.find(i)) {
             case (some[ast.mod_index_entry](?ent)) {
                 alt (ent) {
@@ -356,7 +400,9 @@ fn lookup_name_wrapped(&env e, ast.ident i, namespace ns)
                         ret some(found_def_view(view_item));
                     }
                     case (ast.mie_item(?item)) {
-                        ret some(found_def_item(item, ns));
+                        if (visible(e, i, m)) {
+                            ret some(found_def_item(item, ns));
+                        }
                     }
                     case (ast.mie_tag_variant(?item, ?variant_idx)) {
                         alt (item.node) {
@@ -453,12 +499,12 @@ fn lookup_name_wrapped(&env e, ast.ident i, namespace ns)
         }
     }
 
-    fn in_scope(&session.session sess, ast.ident identifier, &scope s,
+    fn in_scope(&env e, ast.ident identifier, &scope s,
             namespace ns) -> option.t[def_wrap] {
         alt (s) {
 
             case (scope_crate(?c)) {
-                ret check_mod(identifier, c.node.module, ns);
+                ret check_mod(e, identifier, c.node.module, ns);
             }
 
             case (scope_item(?it)) {
@@ -494,7 +540,7 @@ fn lookup_name_wrapped(&env e, ast.ident i, namespace ns)
                         }
                     }
                     case (ast.item_mod(_, ?m, _)) {
-                        ret check_mod(identifier, m, ns);
+                        ret check_mod(e, identifier, m, ns);
                     }
                     case (ast.item_native_mod(_, ?m, _)) {
                         ret check_native_mod(identifier, m);
@@ -522,7 +568,7 @@ fn lookup_name_wrapped(&env e, ast.ident i, namespace ns)
             }
 
             case (scope_external_mod(?mod_id, ?path)) {
-                ret lookup_external_def(sess, mod_id._0, path);
+                ret lookup_external_def(e.sess, mod_id._0, path);
             }
 
             case (scope_loop(?d)) {
@@ -558,7 +604,7 @@ fn lookup_name_wrapped(&env e, ast.ident i, namespace ns)
             ret none[tup(@env, def_wrap)];
         }
         case (cons[scope](?hd, ?tl)) {
-            auto x = in_scope(e.sess, i, hd, ns);
+            auto x = in_scope(e, i, hd, ns);
             alt (x) {
                 case (some[def_wrap](?x)) {
                     ret some(tup(@e, x));
@@ -737,7 +783,8 @@ fn resolve_imports(session.session sess, @ast.crate crate) -> @ast.crate {
                 with *fld );
 
     auto e = rec(scopes = nil[scope],
-                 sess = sess);
+                 sess = sess,
+                 direction = up);
 
     ret fold.fold_crate[env](e, fld, crate);
 }
@@ -761,7 +808,8 @@ fn resolve_crate(session.session sess, @ast.crate crate) -> @ast.crate {
                 with *fld );
 
     auto e = rec(scopes = nil[scope],
-                 sess = sess);
+                 sess = sess,
+                 direction = up);
 
     ret fold.fold_crate[env](e, fld, new_crate);
 }
diff --git a/src/test/compile-fail/export-boot.rs b/src/test/compile-fail/export-boot.rs
new file mode 100644
index 00000000000..7a9fc776fe9
--- /dev/null
+++ b/src/test/compile-fail/export-boot.rs
@@ -0,0 +1,19 @@
+// xfail-stage0
+// error-pattern: unknown module item
+
+// rustboot has a different error message than rustc
+// this test can die with rustboot, or rustc's error can change
+
+mod foo {
+  export x;
+  fn x(int y) {
+    log y;
+  }
+  fn z(int y) {
+    log y;
+  }
+}
+
+fn main() {
+  foo.z(10);
+}
diff --git a/src/test/compile-fail/export.rs b/src/test/compile-fail/export.rs
index 84e87c2e561..d54e515c6a5 100644
--- a/src/test/compile-fail/export.rs
+++ b/src/test/compile-fail/export.rs
@@ -1,5 +1,5 @@
-// xfail-stage0
-// error-pattern: unknown module item
+// xfail-boot
+// error-pattern: unresolved name
 mod foo {
   export x;
   fn x(int y) {
diff --git a/src/test/compile-fail/export2.rs b/src/test/compile-fail/export2.rs
new file mode 100644
index 00000000000..18e84ddc035
--- /dev/null
+++ b/src/test/compile-fail/export2.rs
@@ -0,0 +1,25 @@
+// xfail-boot
+// error-pattern: unresolved name
+
+mod foo {
+  export x;
+
+  fn x() {
+    bar.x();
+  }
+}
+
+mod bar {
+  export y;
+
+  fn x() {
+    log "x";
+  }
+
+  fn y() {
+  }
+}
+
+fn main() {
+  foo.x();
+}
diff --git a/src/test/run-pass/export-non-interference2.rs b/src/test/run-pass/export-non-interference2.rs
new file mode 100644
index 00000000000..e5b324e4aa7
--- /dev/null
+++ b/src/test/run-pass/export-non-interference2.rs
@@ -0,0 +1,18 @@
+mod foo {
+
+  export bar;
+
+  mod bar {
+    fn y() {
+      x();
+    }
+  }
+
+  fn x() {
+    log "x";
+  }
+}
+
+fn main() {
+  foo.bar.y();
+}
diff --git a/src/test/run-pass/export-non-interference3.rs b/src/test/run-pass/export-non-interference3.rs
new file mode 100644
index 00000000000..c52b13f7ec7
--- /dev/null
+++ b/src/test/run-pass/export-non-interference3.rs
@@ -0,0 +1,19 @@
+mod foo {
+  export x;
+
+  fn x() {
+    bar.x();
+  }
+}
+
+mod bar {
+  export x;
+
+  fn x() {
+    log "x";
+  }
+}
+
+fn main() {
+  foo.x();
+}