diff options
Diffstat (limited to 'src/rustc/syntax/parse/eval.rs')
| -rw-r--r-- | src/rustc/syntax/parse/eval.rs | 150 |
1 files changed, 150 insertions, 0 deletions
diff --git a/src/rustc/syntax/parse/eval.rs b/src/rustc/syntax/parse/eval.rs new file mode 100644 index 00000000000..06f26905550 --- /dev/null +++ b/src/rustc/syntax/parse/eval.rs @@ -0,0 +1,150 @@ + +import front::attr; +import std::{io, fs}; +import syntax::ast; +import syntax::parse::token; +import syntax::parse::parser::{parser, new_parser_from_file, + parse_inner_attrs_and_next, + parse_mod_items, SOURCE_FILE}; + +export eval_crate_directives_to_mod; + +type ctx = + @{p: parser, + sess: parser::parse_sess, + cfg: ast::crate_cfg}; + +fn eval_crate_directives(cx: ctx, cdirs: [@ast::crate_directive], prefix: str, + &view_items: [@ast::view_item], + &items: [@ast::item]) { + for sub_cdir: @ast::crate_directive in cdirs { + 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::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 + 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<str>) + -> ([@ast::view_item], [@ast::item], [ast::attribute]) { + + fn companion_file(prefix: str, suffix: option<str>) -> str { + ret 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); + #debug("looking for companion mod %s", modpath); + if file_exists(modpath) { + #debug("found companion mod"); + let p0 = new_parser_from_file(cx.sess, cx.cfg, modpath, + 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.sess.chpos = p0.reader.chpos; + cx.sess.byte_pos = cx.sess.byte_pos + p0.reader.pos; + ret (m0.view_items, m0.items, inner_attrs.inner); + } else { + ret ([], [], []); + } +} + +fn cdir_path_opt(id: str, attrs: [ast::attribute]) -> str { + alt attr::get_meta_item_value_str_by_name(attrs, "path") { + some(d) { + ret d; + } + none { ret id; } + } +} + +fn eval_crate_directive(cx: ctx, cdir: @ast::crate_directive, prefix: str, + &view_items: [@ast::view_item], + &items: [@ast::item]) { + alt cdir.node { + ast::cdir_src_mod(id, attrs) { + let file_path = cdir_path_opt(id + ".rs", attrs); + let full_path = + if std::fs::path_is_absolute(file_path) { + file_path + } else { prefix + std::fs::path_sep() + file_path }; + let p0 = + new_parser_from_file(cx.sess, cx.cfg, full_path, SOURCE_FILE); + let inner_attrs = parse_inner_attrs_and_next(p0); + let mod_attrs = attrs + inner_attrs.inner; + let first_item_outer_attrs = inner_attrs.next; + let m0 = parse_mod_items(p0, token::EOF, first_item_outer_attrs); + + let i = + syntax::parse::parser::mk_item(p0, cdir.span.lo, cdir.span.hi, id, + ast::item_mod(m0), mod_attrs); + // Thread defids, chpos and byte_pos through the parsers + cx.sess.chpos = p0.reader.chpos; + cx.sess.byte_pos = cx.sess.byte_pos + p0.reader.pos; + items += [i]; + } + ast::cdir_dir_mod(id, cdirs, attrs) { + let path = cdir_path_opt(id, attrs); + let full_path = + if std::fs::path_is_absolute(path) { + path + } else { prefix + std::fs::path_sep() + path }; + let (m0, a0) = eval_crate_directives_to_mod( + cx, cdirs, full_path, none); + let i = + @{ident: id, + attrs: attrs + a0, + id: cx.sess.next_id, + node: ast::item_mod(m0), + span: cdir.span}; + cx.sess.next_id += 1; + items += [i]; + } + ast::cdir_view_item(vi) { 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: +// |
