about summary refs log tree commit diff
diff options
context:
space:
mode:
authorBrian Anderson <banderson@mozilla.com>2011-10-29 01:21:43 -0700
committerBrian Anderson <banderson@mozilla.com>2011-10-29 01:40:20 -0700
commite0f44730e8dc75c17dc86fcb48769d62a4dbcaae (patch)
treef11e4626c0fad600fe133c0a2551c1d23ff17d8e
parent2cebef095e61608a3d35710cb5fd3d7de18b68ac (diff)
downloadrust-e0f44730e8dc75c17dc86fcb48769d62a4dbcaae.tar.gz
rust-e0f44730e8dc75c17dc86fcb48769d62a4dbcaae.zip
rustc: Support 'companion mod's for crates and directory mods
Under this scheme when parsing foo.rc the parser will also look for
foo.rs to fill in the crate-level module, and when evaluating a
directory module directive it will look for a .rs file with the
same name as the directory.
-rw-r--r--src/comp/syntax/parse/eval.rs65
-rw-r--r--src/comp/syntax/parse/parser.rs8
-rw-r--r--src/compiletest/compiletest.rc1
-rw-r--r--src/fuzzer/fuzzer.rc2
-rw-r--r--src/fuzzer/fuzzer.rs3
-rw-r--r--src/test/run-pass/companionmod-src/b.rs2
-rw-r--r--src/test/run-pass/companionmod-src/b/x.rs1
-rw-r--r--src/test/run-pass/companionmod-src/d.rs2
-rw-r--r--src/test/run-pass/companionmod-src/d/x.rs1
-rw-r--r--src/test/run-pass/companionmod.rc10
-rw-r--r--src/test/run-pass/companionmod.rs7
11 files changed, 88 insertions, 14 deletions
diff --git a/src/comp/syntax/parse/eval.rs b/src/comp/syntax/parse/eval.rs
index 8a48a8ec2d1..e4b60c4c21e 100644
--- a/src/comp/syntax/parse/eval.rs
+++ b/src/comp/syntax/parse/eval.rs
@@ -1,5 +1,5 @@
 
-import std::{str, option};
+import std::{str, option, result, io, fs};
 import std::option::{some, none};
 import syntax::ast;
 import syntax::parse::token;
@@ -25,11 +25,65 @@ fn eval_crate_directives(cx: ctx, cdirs: [@ast::crate_directive], prefix: str,
 }
 
 fn eval_crate_directives_to_mod(cx: ctx, cdirs: [@ast::crate_directive],
-                                prefix: str) -> ast::_mod {
+                                prefix: str, suffix: option::t<str>)
+    -> (ast::_mod, [ast::attribute]) {
+    log #fmt("eval crate prefix: %s", prefix);
+    log #fmt("eval crate suffix: %s",
+             option::from_maybe("none", suffix));
+    let (cview_items, citems, cattrs)
+        = parse_companion_mod(cx, prefix, suffix);
     let view_items: [@ast::view_item] = [];
     let items: [@ast::item] = [];
     eval_crate_directives(cx, cdirs, prefix, view_items, items);
-    ret {view_items: view_items, items: items};
+    ret ({view_items: view_items + cview_items,
+          items: items + citems},
+         cattrs);
+}
+
+/*
+The 'companion mod'. So .rc crates and directory mod crate directives define
+modules but not a .rs file to fill those mods with stuff. The companion mod is
+a convention for location a .rs file to go with them.  For .rc files the
+companion mod is a .rs file with the same name; for directory mods the
+companion mod is a .rs file with the same name as the directory.
+
+We build the path to the companion mod by combining the prefix and the
+optional suffix then adding the .rs extension.
+*/
+fn parse_companion_mod(cx: ctx, prefix: str, suffix: option::t<str>)
+    -> ([@ast::view_item], [@ast::item], [ast::attribute]) {
+
+    fn companion_file(prefix: str, suffix: option::t<str>) -> str {
+        alt suffix {
+          option::some(s) { fs::connect(prefix, s) }
+          option::none. { prefix }
+        } + ".rs"
+    }
+
+    fn file_exists(path: str) -> bool {
+        // Crude, but there's no lib function for this and I'm not
+        // up to writing it just now
+        alt io::file_reader(path) {
+          result::ok(_) { true }
+          result::err(_) { false }
+        }
+    }
+
+    let modpath = companion_file(prefix, suffix);
+    log #fmt("looking for companion mod %s", modpath);
+    if file_exists(modpath) {
+        log "found companion mod";
+        let p0 = new_parser_from_file(cx.sess, cx.cfg, modpath,
+                                     cx.chpos, cx.byte_pos, SOURCE_FILE);
+        let inner_attrs = parse_inner_attrs_and_next(p0);
+        let first_item_outer_attrs = inner_attrs.next;
+        let m0 = parse_mod_items(p0, token::EOF, first_item_outer_attrs);
+        cx.chpos = p0.get_chpos();
+        cx.byte_pos = p0.get_byte_pos();
+        ret (m0.view_items, m0.items, inner_attrs.inner);
+    } else {
+        ret ([], [], []);
+    }
 }
 
 fn eval_crate_directive(cx: ctx, cdir: @ast::crate_directive, prefix: str,
@@ -66,10 +120,11 @@ fn eval_crate_directive(cx: ctx, cdir: @ast::crate_directive, prefix: str,
             if std::fs::path_is_absolute(path) {
                 path
             } else { prefix + std::fs::path_sep() + path };
-        let m0 = eval_crate_directives_to_mod(cx, cdirs, full_path);
+        let (m0, a0) = eval_crate_directives_to_mod(
+            cx, cdirs, full_path, none);
         let i =
             @{ident: id,
-              attrs: attrs,
+              attrs: attrs + a0,
               id: cx.sess.next_id,
               node: ast::item_mod(m0),
               span: cdir.span};
diff --git a/src/comp/syntax/parse/parser.rs b/src/comp/syntax/parse/parser.rs
index f605a2fb699..98dcb141192 100644
--- a/src/comp/syntax/parse/parser.rs
+++ b/src/comp/syntax/parse/parser.rs
@@ -1,5 +1,5 @@
 
-import std::{io, vec, str, option, either, result};
+import std::{io, vec, str, option, either, result, fs};
 import std::option::{some, none};
 import std::either::{left, right};
 import std::map::{hashmap, new_str_hash};
@@ -2599,13 +2599,15 @@ fn parse_crate_from_crate_file(input: str, cfg: ast::crate_cfg,
           mutable chpos: p.get_chpos(),
           mutable byte_pos: p.get_byte_pos(),
           cfg: p.get_cfg()};
-    let m = eval::eval_crate_directives_to_mod(cx, cdirs, prefix);
+    let (companionmod, _) = fs::splitext(fs::basename(input));
+    let (m, attrs) = eval::eval_crate_directives_to_mod(
+        cx, cdirs, prefix, option::some(companionmod));
     let hi = p.get_hi_pos();
     expect(p, token::EOF);
     ret @spanned(lo, hi,
                  {directives: cdirs,
                   module: m,
-                  attrs: crate_attrs,
+                  attrs: crate_attrs + attrs,
                   config: p.get_cfg()});
 }
 
diff --git a/src/compiletest/compiletest.rc b/src/compiletest/compiletest.rc
index 2f9ffe50f81..703862076a5 100644
--- a/src/compiletest/compiletest.rc
+++ b/src/compiletest/compiletest.rc
@@ -1,6 +1,5 @@
 use std;
 
-mod compiletest;
 mod procsrv;
 mod util;
 mod header;
diff --git a/src/fuzzer/fuzzer.rc b/src/fuzzer/fuzzer.rc
index 473a7b20615..9793b9d21c7 100644
--- a/src/fuzzer/fuzzer.rc
+++ b/src/fuzzer/fuzzer.rc
@@ -3,8 +3,6 @@
 use std;
 use rustc;
 
-mod fuzzer;
-
 // Local Variables:
 // fill-column: 78;
 // indent-tabs-mode: nil
diff --git a/src/fuzzer/fuzzer.rs b/src/fuzzer/fuzzer.rs
index 4a96877dfc1..480b45ae6b4 100644
--- a/src/fuzzer/fuzzer.rs
+++ b/src/fuzzer/fuzzer.rs
@@ -1,6 +1,3 @@
-use std;
-use rustc;
-
 import std::{fs, io, getopts, math, vec, str, int, uint, option, result};
 import std::getopts::{optopt, opt_present, opt_str};
 import std::io::stdout;
diff --git a/src/test/run-pass/companionmod-src/b.rs b/src/test/run-pass/companionmod-src/b.rs
new file mode 100644
index 00000000000..e867ff713cd
--- /dev/null
+++ b/src/test/run-pass/companionmod-src/b.rs
@@ -0,0 +1,2 @@
+import g = x::f;
+export g;
\ No newline at end of file
diff --git a/src/test/run-pass/companionmod-src/b/x.rs b/src/test/run-pass/companionmod-src/b/x.rs
new file mode 100644
index 00000000000..413b834fb11
--- /dev/null
+++ b/src/test/run-pass/companionmod-src/b/x.rs
@@ -0,0 +1 @@
+fn f() -> str { "ralph" }
\ No newline at end of file
diff --git a/src/test/run-pass/companionmod-src/d.rs b/src/test/run-pass/companionmod-src/d.rs
new file mode 100644
index 00000000000..e867ff713cd
--- /dev/null
+++ b/src/test/run-pass/companionmod-src/d.rs
@@ -0,0 +1,2 @@
+import g = x::f;
+export g;
\ No newline at end of file
diff --git a/src/test/run-pass/companionmod-src/d/x.rs b/src/test/run-pass/companionmod-src/d/x.rs
new file mode 100644
index 00000000000..94f006f9a1f
--- /dev/null
+++ b/src/test/run-pass/companionmod-src/d/x.rs
@@ -0,0 +1 @@
+fn f() -> str { "nelson" }
\ No newline at end of file
diff --git a/src/test/run-pass/companionmod.rc b/src/test/run-pass/companionmod.rc
new file mode 100644
index 00000000000..405e5efc846
--- /dev/null
+++ b/src/test/run-pass/companionmod.rc
@@ -0,0 +1,10 @@
+// Test that crates and directory modules can contain code
+
+mod a = "companionmod-src" {
+    mod b {
+        mod x;
+    }
+    mod c = "d" {
+        mod x;
+    }
+}
\ No newline at end of file
diff --git a/src/test/run-pass/companionmod.rs b/src/test/run-pass/companionmod.rs
new file mode 100644
index 00000000000..9b9d1a00f0f
--- /dev/null
+++ b/src/test/run-pass/companionmod.rs
@@ -0,0 +1,7 @@
+// This isn't really xfailed; it's used by the companionmod.rc test
+// xfail-test
+
+fn main() {
+    assert a::b::g() == "ralph";
+    assert a::c::g() == "nelson";
+}
\ No newline at end of file