Skip to content

Commit e0f4473

Browse files
committed
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.
1 parent 2cebef0 commit e0f4473

File tree

11 files changed

+88
-14
lines changed

11 files changed

+88
-14
lines changed

src/comp/syntax/parse/eval.rs

Lines changed: 60 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11

2-
import std::{str, option};
2+
import std::{str, option, result, io, fs};
33
import std::option::{some, none};
44
import syntax::ast;
55
import syntax::parse::token;
@@ -25,11 +25,65 @@ fn eval_crate_directives(cx: ctx, cdirs: [@ast::crate_directive], prefix: str,
2525
}
2626

2727
fn eval_crate_directives_to_mod(cx: ctx, cdirs: [@ast::crate_directive],
28-
prefix: str) -> ast::_mod {
28+
prefix: str, suffix: option::t<str>)
29+
-> (ast::_mod, [ast::attribute]) {
30+
log #fmt("eval crate prefix: %s", prefix);
31+
log #fmt("eval crate suffix: %s",
32+
option::from_maybe("none", suffix));
33+
let (cview_items, citems, cattrs)
34+
= parse_companion_mod(cx, prefix, suffix);
2935
let view_items: [@ast::view_item] = [];
3036
let items: [@ast::item] = [];
3137
eval_crate_directives(cx, cdirs, prefix, view_items, items);
32-
ret {view_items: view_items, items: items};
38+
ret ({view_items: view_items + cview_items,
39+
items: items + citems},
40+
cattrs);
41+
}
42+
43+
/*
44+
The 'companion mod'. So .rc crates and directory mod crate directives define
45+
modules but not a .rs file to fill those mods with stuff. The companion mod is
46+
a convention for location a .rs file to go with them. For .rc files the
47+
companion mod is a .rs file with the same name; for directory mods the
48+
companion mod is a .rs file with the same name as the directory.
49+
50+
We build the path to the companion mod by combining the prefix and the
51+
optional suffix then adding the .rs extension.
52+
*/
53+
fn parse_companion_mod(cx: ctx, prefix: str, suffix: option::t<str>)
54+
-> ([@ast::view_item], [@ast::item], [ast::attribute]) {
55+
56+
fn companion_file(prefix: str, suffix: option::t<str>) -> str {
57+
alt suffix {
58+
option::some(s) { fs::connect(prefix, s) }
59+
option::none. { prefix }
60+
} + ".rs"
61+
}
62+
63+
fn file_exists(path: str) -> bool {
64+
// Crude, but there's no lib function for this and I'm not
65+
// up to writing it just now
66+
alt io::file_reader(path) {
67+
result::ok(_) { true }
68+
result::err(_) { false }
69+
}
70+
}
71+
72+
let modpath = companion_file(prefix, suffix);
73+
log #fmt("looking for companion mod %s", modpath);
74+
if file_exists(modpath) {
75+
log "found companion mod";
76+
let p0 = new_parser_from_file(cx.sess, cx.cfg, modpath,
77+
cx.chpos, cx.byte_pos, SOURCE_FILE);
78+
let inner_attrs = parse_inner_attrs_and_next(p0);
79+
let first_item_outer_attrs = inner_attrs.next;
80+
let m0 = parse_mod_items(p0, token::EOF, first_item_outer_attrs);
81+
cx.chpos = p0.get_chpos();
82+
cx.byte_pos = p0.get_byte_pos();
83+
ret (m0.view_items, m0.items, inner_attrs.inner);
84+
} else {
85+
ret ([], [], []);
86+
}
3387
}
3488

3589
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,
66120
if std::fs::path_is_absolute(path) {
67121
path
68122
} else { prefix + std::fs::path_sep() + path };
69-
let m0 = eval_crate_directives_to_mod(cx, cdirs, full_path);
123+
let (m0, a0) = eval_crate_directives_to_mod(
124+
cx, cdirs, full_path, none);
70125
let i =
71126
@{ident: id,
72-
attrs: attrs,
127+
attrs: attrs + a0,
73128
id: cx.sess.next_id,
74129
node: ast::item_mod(m0),
75130
span: cdir.span};

src/comp/syntax/parse/parser.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11

2-
import std::{io, vec, str, option, either, result};
2+
import std::{io, vec, str, option, either, result, fs};
33
import std::option::{some, none};
44
import std::either::{left, right};
55
import std::map::{hashmap, new_str_hash};
@@ -2599,13 +2599,15 @@ fn parse_crate_from_crate_file(input: str, cfg: ast::crate_cfg,
25992599
mutable chpos: p.get_chpos(),
26002600
mutable byte_pos: p.get_byte_pos(),
26012601
cfg: p.get_cfg()};
2602-
let m = eval::eval_crate_directives_to_mod(cx, cdirs, prefix);
2602+
let (companionmod, _) = fs::splitext(fs::basename(input));
2603+
let (m, attrs) = eval::eval_crate_directives_to_mod(
2604+
cx, cdirs, prefix, option::some(companionmod));
26032605
let hi = p.get_hi_pos();
26042606
expect(p, token::EOF);
26052607
ret @spanned(lo, hi,
26062608
{directives: cdirs,
26072609
module: m,
2608-
attrs: crate_attrs,
2610+
attrs: crate_attrs + attrs,
26092611
config: p.get_cfg()});
26102612
}
26112613

src/compiletest/compiletest.rc

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
use std;
22

3-
mod compiletest;
43
mod procsrv;
54
mod util;
65
mod header;

src/fuzzer/fuzzer.rc

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@
33
use std;
44
use rustc;
55

6-
mod fuzzer;
7-
86
// Local Variables:
97
// fill-column: 78;
108
// indent-tabs-mode: nil

src/fuzzer/fuzzer.rs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
1-
use std;
2-
use rustc;
3-
41
import std::{fs, io, getopts, math, vec, str, int, uint, option, result};
52
import std::getopts::{optopt, opt_present, opt_str};
63
import std::io::stdout;
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
import g = x::f;
2+
export g;
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
fn f() -> str { "ralph" }
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
import g = x::f;
2+
export g;
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
fn f() -> str { "nelson" }

src/test/run-pass/companionmod.rc

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// Test that crates and directory modules can contain code
2+
3+
mod a = "companionmod-src" {
4+
mod b {
5+
mod x;
6+
}
7+
mod c = "d" {
8+
mod x;
9+
}
10+
}

src/test/run-pass/companionmod.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// This isn't really xfailed; it's used by the companionmod.rc test
2+
// xfail-test
3+
4+
fn main() {
5+
assert a::b::g() == "ralph";
6+
assert a::c::g() == "nelson";
7+
}

0 commit comments

Comments
 (0)