about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorBrian Anderson <banderson@mozilla.com>2011-08-16 15:21:30 -0700
committerBrian Anderson <banderson@mozilla.com>2011-08-17 11:04:56 -0700
commitcd54e7772040cd268f911e9dfd088ad5f659f552 (patch)
treed12ac71b3f3ec50fe345d8064c87f8a5b44a9010 /src
parentc4ce463f3709c7a8a92941d2e4bfab6db5da550f (diff)
downloadrust-cd54e7772040cd268f911e9dfd088ad5f659f552.tar.gz
rust-cd54e7772040cd268f911e9dfd088ad5f659f552.zip
Allow multiple imports in a single statement
Like so: import foo::{bar, baz};

Issue #817
Diffstat (limited to 'src')
-rw-r--r--src/comp/middle/resolve.rs44
-rw-r--r--src/comp/syntax/ast.rs5
-rw-r--r--src/comp/syntax/parse/parser.rs39
-rw-r--r--src/comp/syntax/print/pprust.rs13
-rw-r--r--src/test/compile-fail/import-from-missing.rs11
-rw-r--r--src/test/compile-fail/import-from-none.rs8
-rw-r--r--src/test/compile-fail/import-from-path.rs2
-rw-r--r--src/test/compile-fail/import-from-rename.rs10
-rw-r--r--src/test/run-pass/import-from-native.rs15
-rw-r--r--src/test/run-pass/import-from.rs11
10 files changed, 155 insertions, 3 deletions
diff --git a/src/comp/middle/resolve.rs b/src/comp/middle/resolve.rs
index b87f3bbda4b..b879b37f9e8 100644
--- a/src/comp/middle/resolve.rs
+++ b/src/comp/middle/resolve.rs
@@ -61,6 +61,7 @@ type scopes = list<scope>;
 
 tag import_state {
     todo(@ast::view_item, scopes); // only used for explicit imports
+    todo_from(@ast::view_item, ast::import_ident, scopes);
 
     resolving(span);
     resolved(option::t<def>,
@@ -91,6 +92,7 @@ fn new_ext_hash() -> ext_hash {
 
 tag mod_index_entry {
     mie_view_item(@ast::view_item);
+    mie_import_ident(node_id);
     mie_item(@ast::item);
     mie_native_item(@ast::native_item);
     mie_tag_variant(/* tag item */@ast::item, /* variant index */uint);
@@ -173,6 +175,12 @@ fn map_crate(e: &@env, c: &@ast::crate) {
           ast::view_item_import(_, ids, id) {
             e.imports.insert(id, todo(i, sc));
           }
+          ast::view_item_import_from(mod_path, idents, id) {
+            for ident in idents {
+                e.imports.insert(ident.node.id,
+                                 todo_from(i, ident, sc));
+            }
+          }
           _ { }
         }
     }
@@ -238,11 +246,27 @@ fn map_crate(e: &@env, c: &@ast::crate) {
     }
 }
 
+fn vi_from_to_vi(from_item: &@ast::view_item,
+                 ident: ast::import_ident) -> @ast::view_item {
+    alt from_item.node {
+      ast::view_item_import_from(mod_path, idents, _) {
+        @ast::respan(ident.span,
+                     ast::view_item_import(ident.node.name,
+                                           mod_path + ~[ident.node.name],
+                                           ident.node.id))
+      }
+    }
+}
+
 fn resolve_imports(e: &env) {
     for each it: @{key: ast::node_id, val: import_state} in e.imports.items()
              {
         alt it.val {
           todo(item, sc) { resolve_import(e, item, sc); }
+          todo_from(item, ident, sc) {
+            let vi = vi_from_to_vi(item, ident);
+            resolve_import(e, vi, sc);
+          }
           resolved(_, _, _) { }
         }
     }
@@ -941,6 +965,11 @@ fn lookup_import(e: &env, defid: def_id, ns: namespace) -> option::t<def> {
         resolve_import(e, item, sc);
         ret lookup_import(e, defid, ns);
       }
+      todo_from(item, ident, sc) {
+        let vi = vi_from_to_vi(item, ident);
+        resolve_import(e, vi, sc);
+        ret lookup_import(e, defid, ns);
+      }
       resolving(sp) { e.sess.span_err(sp, "cyclic import"); ret none; }
       resolved(val, typ, md) {
         ret alt ns { ns_value. { val } ns_type. { typ } ns_module. { md } };
@@ -1044,6 +1073,7 @@ fn lookup_in_mie(e: &env, mie: &mod_index_entry, ns: namespace) ->
    option::t<def> {
     alt mie {
       mie_view_item(view_item) { ret found_view_item(e, view_item, ns); }
+      mie_import_ident(id) { ret lookup_import(e, local_def(id), ns); }
       mie_item(item) { ret found_def_item(item, ns); }
       mie_tag_variant(item, variant_idx) {
         alt item.node {
@@ -1070,7 +1100,6 @@ fn lookup_in_mie(e: &env, mie: &mod_index_entry, ns: namespace) ->
           }
         }
       }
-      _ { }
     }
     ret none::<def>;
 }
@@ -1094,6 +1123,13 @@ fn index_mod(md: &ast::_mod) -> mod_index {
             add_to_index(index, ident, mie_view_item(it));
           }
 
+          ast::view_item_import_from(_, idents, _) {
+            for ident in idents {
+                add_to_index(index, ident.node.name,
+                             mie_import_ident(ident.node.id));
+            }
+          }
+
           //globbed imports have to be resolved lazily.
           ast::view_item_import_glob(_, _) | ast::view_item_export(_, _) {
           }
@@ -1128,6 +1164,12 @@ fn index_nmod(md: &ast::native_mod) -> mod_index {
           {
             add_to_index(index, ident, mie_view_item(it));
           }
+          ast::view_item_import_from(_, idents, _) {
+            for ident in idents {
+                add_to_index(index, ident.node.name,
+                             mie_import_ident(ident.node.id));
+            }
+          }
           ast::view_item_import_glob(_, _) | ast::view_item_export(_, _) { }
         }
     }
diff --git a/src/comp/syntax/ast.rs b/src/comp/syntax/ast.rs
index b286fdaf484..066a0b9675b 100644
--- a/src/comp/syntax/ast.rs
+++ b/src/comp/syntax/ast.rs
@@ -564,10 +564,15 @@ type view_item = spanned<view_item_>;
 // 'import ::foo'
 type simple_path = [ident];
 
+type import_ident_ = {name: ident, id: node_id};
+
+type import_ident = spanned<import_ident_>;
+
 tag view_item_ {
     view_item_use(ident, [@meta_item], node_id);
     view_item_import(ident, simple_path, node_id);
     view_item_import_glob(simple_path, node_id);
+    view_item_import_from(simple_path, [import_ident], node_id);
     view_item_export([ident], node_id);
 }
 
diff --git a/src/comp/syntax/parse/parser.rs b/src/comp/syntax/parse/parser.rs
index e6b65444029..f92ab2ca6bd 100644
--- a/src/comp/syntax/parse/parser.rs
+++ b/src/comp/syntax/parse/parser.rs
@@ -2288,11 +2288,17 @@ fn parse_rest_import_name(p: &parser, first: ast::ident,
    ast::view_item_ {
     let identifiers: [ast::ident] = ~[first];
     let glob: bool = false;
+    let from_idents = option::none::<[ast::import_ident]>;
     while true {
         alt p.peek() {
           token::SEMI. { break; }
           token::MOD_SEP. {
-            if glob { p.fatal("cannot path into a glob"); }
+            if glob {
+                p.fatal("cannot path into a glob");
+            }
+            if option::is_some(from_idents) {
+                p.fatal("cannot path into import list");
+            }
             p.bump();
           }
           _ { p.fatal("expecting '::' or ';'"); }
@@ -2305,17 +2311,46 @@ fn parse_rest_import_name(p: &parser, first: ast::ident,
             glob = true;
             p.bump();
           }
+
+          token::LBRACE. {
+            fn parse_import_ident(p: &parser) -> ast::import_ident {
+                let lo = p.get_lo_pos();
+                let ident = parse_ident(p);
+                let hi = p.get_hi_pos();
+                ret spanned(lo, hi, {name: ident,
+                                     id: p.get_id()});
+            }
+            let from_idents_ = parse_seq(token::LBRACE,
+                                         token::RBRACE,
+                                         some(token::COMMA),
+                                         parse_import_ident,
+                                         p).node;
+            if vec::is_empty(from_idents_) {
+                p.fatal("at least one import is required");
+            }
+            from_idents = some(from_idents_);
+          }
+
           _ { p.fatal("expecting an identifier, or '*'"); }
         }
     }
     alt def_ident {
       some(i) {
-        if glob { p.fatal("globbed imports can't be renamed"); }
+        if glob {
+            p.fatal("globbed imports can't be renamed");
+        }
+        if option::is_some(from_idents) {
+            p.fatal("can't rename import list");
+        }
         ret ast::view_item_import(i, identifiers, p.get_id());
       }
       _ {
         if glob {
             ret ast::view_item_import_glob(identifiers, p.get_id());
+        } else if option::is_some(from_idents) {
+            ret ast::view_item_import_from(identifiers,
+                                           option::get(from_idents),
+                                           p.get_id());
         } else {
             let len = vec::len(identifiers);
             ret ast::view_item_import(identifiers.(len - 1u), identifiers,
diff --git a/src/comp/syntax/print/pprust.rs b/src/comp/syntax/print/pprust.rs
index 43ab6c5c823..a8f694e6755 100644
--- a/src/comp/syntax/print/pprust.rs
+++ b/src/comp/syntax/print/pprust.rs
@@ -1267,6 +1267,19 @@ fn print_view_item(s: &ps, item: &@ast::view_item) {
             word(s.s, elt);
         }
       }
+      ast::view_item_import_from(mod_path, idents, _) {
+        head(s, "import");
+        for elt: str in mod_path {
+            word(s.s, elt);
+            word(s.s, "::");
+        }
+        word(s.s, "{");
+        commasep(s, inconsistent, idents,
+                 fn(s: &ps, w: &ast::import_ident) {
+                     word(s.s, w.node.name)
+                 });
+        word(s.s, "}");
+      }
       ast::view_item_import_glob(ids, _) {
         head(s, "import");
         let first = true;
diff --git a/src/test/compile-fail/import-from-missing.rs b/src/test/compile-fail/import-from-missing.rs
new file mode 100644
index 00000000000..1e0b3869053
--- /dev/null
+++ b/src/test/compile-fail/import-from-missing.rs
@@ -0,0 +1,11 @@
+// error-pattern:unresolved import: eggs
+import spam::{ham, eggs};
+
+mod spam {
+    fn ham() {}
+}
+
+fn main() {
+    ham();
+    eggs();
+}
\ No newline at end of file
diff --git a/src/test/compile-fail/import-from-none.rs b/src/test/compile-fail/import-from-none.rs
new file mode 100644
index 00000000000..d80aa4f7ade
--- /dev/null
+++ b/src/test/compile-fail/import-from-none.rs
@@ -0,0 +1,8 @@
+// error-pattern:at least one import is required
+import spam::{};
+
+mod spam {
+}
+
+fn main() {
+}
\ No newline at end of file
diff --git a/src/test/compile-fail/import-from-path.rs b/src/test/compile-fail/import-from-path.rs
new file mode 100644
index 00000000000..91ea6efdf2a
--- /dev/null
+++ b/src/test/compile-fail/import-from-path.rs
@@ -0,0 +1,2 @@
+// error-pattern:cannot path into import list
+import foo::{bar}::baz
\ No newline at end of file
diff --git a/src/test/compile-fail/import-from-rename.rs b/src/test/compile-fail/import-from-rename.rs
new file mode 100644
index 00000000000..e4aa78f6320
--- /dev/null
+++ b/src/test/compile-fail/import-from-rename.rs
@@ -0,0 +1,10 @@
+// error-pattern:can't rename import list
+
+import baz = foo::{bar};
+
+mod foo {
+    fn bar() {}
+}
+
+fn main() {
+}
\ No newline at end of file
diff --git a/src/test/run-pass/import-from-native.rs b/src/test/run-pass/import-from-native.rs
new file mode 100644
index 00000000000..03c49b2adfe
--- /dev/null
+++ b/src/test/run-pass/import-from-native.rs
@@ -0,0 +1,15 @@
+mod spam {
+    fn ham() {}
+    fn eggs() {}
+}
+
+native "rust" mod rustrt {
+    import spam::{ham, eggs};
+    export ham;
+    export eggs;
+}
+
+fn main() {
+    rustrt::ham();
+    rustrt::eggs();
+}
\ No newline at end of file
diff --git a/src/test/run-pass/import-from.rs b/src/test/run-pass/import-from.rs
new file mode 100644
index 00000000000..b42793d16df
--- /dev/null
+++ b/src/test/run-pass/import-from.rs
@@ -0,0 +1,11 @@
+import spam::{ham, eggs};
+
+mod spam {
+    fn ham() {}
+    fn eggs() {}
+}
+
+fn main() {
+    ham();
+    eggs();
+}
\ No newline at end of file