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.
This commit is contained in:
Brian Anderson
2011-10-29 01:21:43 -07:00
parent 2cebef095e
commit e0f44730e8
11 changed files with 88 additions and 14 deletions

View File

@@ -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};