144 lines
5.1 KiB
Rust
Raw Normal View History

import parser::{parser, SOURCE_FILE};
2012-05-24 13:44:42 -07:00
import attr::parser_attr;
export eval_crate_directives_to_mod;
type ctx =
@{sess: parse::parse_sess,
2011-07-27 14:19:39 +02:00
cfg: ast::crate_cfg};
fn eval_crate_directives(cx: ctx,
cdirs: ~[@ast::crate_directive],
prefix: ~str,
&view_items: ~[@ast::view_item],
&items: ~[@ast::item]) {
2012-06-30 16:19:07 -07:00
for cdirs.each |sub_cdir| {
eval_crate_directive(cx, sub_cdir, prefix, view_items, items);
}
}
fn eval_crate_directives_to_mod(cx: ctx, cdirs: ~[@ast::crate_directive],
prefix: ~str, suffix: option<~str>)
-> (ast::_mod, ~[ast::attribute]) {
debug!{"eval crate prefix: %s", prefix};
debug!{"eval crate suffix: %s",
option::get_default(suffix, ~"none")};
let (cview_items, citems, cattrs)
= parse_companion_mod(cx, prefix, suffix);
let mut view_items: ~[@ast::view_item] = ~[];
let mut items: ~[@ast::item] = ~[];
eval_crate_directives(cx, cdirs, prefix, view_items, items);
2012-08-01 17:30:05 -07:00
return ({view_items: vec::append(view_items, cview_items),
2012-06-27 23:09:51 -07:00
items: vec::append(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<~str>)
-> (~[@ast::view_item], ~[@ast::item], ~[ast::attribute]) {
fn companion_file(+prefix: ~str, suffix: option<~str>) -> ~str {
2012-08-06 12:34:08 -07:00
return match suffix {
2012-08-03 19:59:04 -07:00
option::some(s) => path::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
2012-08-06 12:34:08 -07:00
match io::file_reader(path) {
2012-08-03 19:59:04 -07:00
result::ok(_) => true,
result::err(_) => false
}
}
let modpath = companion_file(prefix, suffix);
debug!{"looking for companion mod %s", modpath};
if file_exists(modpath) {
debug!{"found companion mod"};
2012-05-30 11:36:30 -07:00
let (p0, r0) = new_parser_etc_from_file(cx.sess, cx.cfg,
modpath, SOURCE_FILE);
2012-05-24 13:44:42 -07:00
let inner_attrs = p0.parse_inner_attrs_and_next();
2012-06-07 21:53:47 -07:00
let m0 = p0.parse_mod_items(token::EOF, inner_attrs.next);
2012-06-15 09:32:17 -07:00
cx.sess.chpos = r0.chpos;
2012-05-30 11:36:30 -07:00
cx.sess.byte_pos = cx.sess.byte_pos + r0.pos;
2012-08-01 17:30:05 -07:00
return (m0.view_items, m0.items, inner_attrs.inner);
} else {
2012-08-01 17:30:05 -07:00
return (~[], ~[], ~[]);
}
}
fn cdir_path_opt(id: ast::ident, attrs: ~[ast::attribute]) -> @~str {
2012-08-06 12:34:08 -07:00
match ::attr::first_attr_value_str_by_name(attrs, ~"path") {
2012-08-03 19:59:04 -07:00
some(d) => return d,
none => return id
}
}
fn eval_crate_directive(cx: ctx, cdir: @ast::crate_directive, prefix: ~str,
&view_items: ~[@ast::view_item],
&items: ~[@ast::item]) {
2012-08-06 12:34:08 -07:00
match cdir.node {
2012-08-03 19:59:04 -07:00
ast::cdir_src_mod(id, attrs) => {
let file_path = cdir_path_opt(@(*id + ~".rs"), attrs);
2011-09-02 15:34:58 -07:00
let full_path =
2012-06-10 00:49:59 -07:00
if path::path_is_absolute(*file_path) {
*file_path
} else { prefix + path::path_sep() + *file_path };
2012-05-30 11:36:30 -07:00
let (p0, r0) =
new_parser_etc_from_file(cx.sess, cx.cfg, full_path, SOURCE_FILE);
2012-05-24 13:44:42 -07:00
let inner_attrs = p0.parse_inner_attrs_and_next();
2012-06-27 23:09:51 -07:00
let mod_attrs = vec::append(attrs, inner_attrs.inner);
2011-07-27 14:19:39 +02:00
let first_item_outer_attrs = inner_attrs.next;
let m0 = p0.parse_mod_items(token::EOF, first_item_outer_attrs);
2012-06-07 21:53:47 -07:00
let i = p0.mk_item(cdir.span.lo, cdir.span.hi,
/* FIXME (#2543) */ copy id,
ast::item_mod(m0), ast::public, mod_attrs);
2011-07-27 14:19:39 +02:00
// Thread defids, chpos and byte_pos through the parsers
2012-06-15 09:32:17 -07:00
cx.sess.chpos = r0.chpos;
2012-05-30 11:36:30 -07:00
cx.sess.byte_pos = cx.sess.byte_pos + r0.pos;
2012-06-27 23:09:51 -07:00
vec::push(items, i);
2011-07-27 14:19:39 +02:00
}
2012-08-03 19:59:04 -07:00
ast::cdir_dir_mod(id, cdirs, attrs) => {
let path = cdir_path_opt(id, attrs);
2011-07-27 14:19:39 +02:00
let full_path =
2012-06-10 00:49:59 -07:00
if path::path_is_absolute(*path) {
*path
} else { prefix + path::path_sep() + *path };
let (m0, a0) = eval_crate_directives_to_mod(
cx, cdirs, full_path, none);
2011-07-27 14:19:39 +02:00
let i =
@{ident: /* FIXME (#2543) */ copy id,
2012-06-27 23:09:51 -07:00
attrs: vec::append(attrs, a0),
2011-07-27 14:19:39 +02:00
id: cx.sess.next_id,
node: ast::item_mod(m0),
vis: ast::public,
2011-07-27 14:19:39 +02:00
span: cdir.span};
cx.sess.next_id += 1;
2012-06-27 23:09:51 -07:00
vec::push(items, i);
2011-07-27 14:19:39 +02:00
}
2012-08-03 19:59:04 -07:00
ast::cdir_view_item(vi) => vec::push(view_items, vi),
ast::cdir_syntax(pth) => ()
}
}
//
// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:
//