summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJohn Hodge <tpg@mutabah.net>2019-01-01 11:32:39 +0800
committerJohn Hodge <tpg@mutabah.net>2019-01-01 11:32:39 +0800
commit2f0ddfaf240c0269087d307b6df6bc00817e6806 (patch)
tree4810960698dfdbe9ac43a7d0f3abf915002e2122 /src
parentbe34ee650255d6bd5bb2b853c9dbdea5126672ab (diff)
downloadmrust-2f0ddfaf240c0269087d307b6df6bc00817e6806.tar.gz
Parse - Module Loading - Hopefully fix libcore without breaking other crates
Diffstat (limited to 'src')
-rw-r--r--src/ast/ast.hpp4
-rw-r--r--src/parse/root.cpp128
2 files changed, 117 insertions, 15 deletions
diff --git a/src/ast/ast.hpp b/src/ast/ast.hpp
index b80b5fb7..493b397c 100644
--- a/src/ast/ast.hpp
+++ b/src/ast/ast.hpp
@@ -517,7 +517,11 @@ public:
struct FileInfo
{
bool controls_dir = false;
+ bool force_no_load = false;
+ // Path to this module
::std::string path = "!";
+ // Directory controlled by this module
+ ::std::string dir = "";
};
FileInfo m_file_info;
diff --git a/src/parse/root.cpp b/src/parse/root.cpp
index 9ab84c78..d457d197 100644
--- a/src/parse/root.cpp
+++ b/src/parse/root.cpp
@@ -1513,6 +1513,102 @@ bool Parse_MacroInvocation_Opt(TokenStream& lex, AST::MacroInvocation& out_inv)
return true;
}
+#if 0
+namespace {
+ ::AST::Module::FileInfo get_submod_file(
+ Span sp, const ::AST::Module::FileInfo& parent_fileinfo, const ::std::string& new_mod_name, const ::std::string& path_attr,
+ bool is_extern_file, bool is_cfg_disabled
+ )
+ {
+ ::AST::Module::FileInfo rv;
+ TRACE_FUNCTION_F(new_mod_name << ", " << path_attr << ", " << is_extern_file);
+ ::std::string sub_path;
+ bool sub_file_controls_dir = true;
+
+ // 1. Determine the base path for the module
+ if( parent_fileinfo.path == "-" ) {
+ if( path_attr.size() ) {
+ ERROR(lex.point_span(), E0000, "Cannot load module from file when reading stdin");
+ }
+ sub_path = "-";
+ }
+ else if( path_attr.size() > 0 )
+ {
+ // #[path] present, add to the parent path
+ sub_path = dirname(parent_fileinfo.path) + path_attr;
+ }
+ else if( mod_fileinfo.controls_dir )
+ {
+ // The parent module is either the crate root, or a `mod.rs` (or otherwise a controller)
+ sub_path = parent_fileinfo.dir + name;
+ }
+ else
+ {
+ sub_path = parent_fileinfo.path;
+ sub_file_controls_dir = false;
+ }
+ DEBUG("Mod '" << name << "', sub_path = " << sub_path);
+
+ rv.path = sub_path;
+ rv.controls_dir = sub_file_controls_dir;
+
+ if( is_cfg_disabled || parent_fileinfo.force_no_load )
+ {
+ rv.force_no_load = true;
+ }
+ if( ! is_extern_file )
+ {
+ // If this is an inline module, set the path to just a directory
+ if( sub_path != "-" ) {
+ rv.path = sub_path + "/";
+ rv.dir = sub_path + "/";
+ }
+ else {
+ rv.path = "-";
+ }
+ }
+ else
+ {
+ if( sub_path == "-" )
+ {
+ ERROR(lex.point_span(), E0000, "Cannot load module from file when reading stdin");
+ }
+ else
+ {
+ ::std::string newpath_dir = sub_path + "/";
+ ::std::string newpath_file = path_attr.size() > 0 ? sub_path : sub_path + ".rs";
+ DEBUG("newpath_dir = '" << newpath_dir << "', newpath_file = '" << newpath_file << "'");
+ ::std::ifstream ifs_dir (newpath_dir + "mod.rs");
+ ::std::ifstream ifs_file(newpath_file);
+ if( ifs_dir.is_open() && ifs_file.is_open() )
+ {
+ // Collision
+ ERROR(lex.point_span(), E0000, "Both modname.rs and modname/mod.rs exist");
+ }
+ else if( ifs_dir.is_open() )
+ {
+ // Load from dir
+ rv.path = newpath_dir + "mod.rs";
+ rv.dir = newpath_dir;
+ }
+ else if( ifs_file.is_open() )
+ {
+ rv.path = newpath_file;
+ rv.dir = newpath_dir;
+ rv.controls_dir = false;
+ }
+ else
+ {
+ // Can't find file
+ ERROR(sp, E0000, "Can't find file for '" << name << "' in '" << parent_fileinfo.dir << "'");
+ }
+ }
+ }
+ return rv;
+ }
+}
+#endif
+
::AST::Named<::AST::Item> Parse_Mod_Item_S(TokenStream& lex, const AST::Module::FileInfo& mod_fileinfo, const ::AST::Path& mod_path, AST::AttributeList meta_items)
{
TRACE_FUNCTION_F("mod_path="<<mod_path<<", meta_items="<<meta_items);
@@ -1828,6 +1924,19 @@ bool Parse_MacroInvocation_Opt(TokenStream& lex, AST::MacroInvocation& out_inv)
DEBUG("Sub module '" << name << "'");
AST::Module submod( mod_path + name );
+ // Check #[cfg] and don't load if it fails
+ struct H {
+ static bool check_item_cfg(const ::AST::AttributeList& attrs)
+ {
+ for(const auto& at : attrs.m_items) {
+ if( at.name() == "cfg" && !check_cfg(at.span(), at) ) {
+ return false;
+ }
+ }
+ return true;
+ }
+ };
+
// Rules for external files (/ path handling):
// - IF using stdin (path='-') - Disallow and propagate '-' as path
// - IF a #[path] attribute was passed, allow
@@ -1835,7 +1944,7 @@ bool Parse_MacroInvocation_Opt(TokenStream& lex, AST::MacroInvocation& out_inv)
// - else, disallow and set flag
::std::string path_attr = (meta_items.has("path") ? meta_items.get("path")->string() : "");
- //submod.m_file_info = get_submod_file(lex.end_span(ps), mod_fileinfo, name, path_attr, LOOK_AHEAD(lex) == TOK_SEMICOLON);
+ //submod.m_file_info = get_submod_file(lex.end_span(ps), mod_fileinfo, name, path_attr, LOOK_AHEAD(lex) == TOK_SEMICOLON, H::check_item_cfg(meta_items));
::std::string sub_path;
bool sub_file_controls_dir = true;
@@ -1863,23 +1972,12 @@ bool Parse_MacroInvocation_Opt(TokenStream& lex, AST::MacroInvocation& out_inv)
submod.m_file_info.path = sub_path;
submod.m_file_info.controls_dir = sub_file_controls_dir;
- // Check #[cfg] and don't load if it fails
- struct H {
- static bool check_item_cfg(const ::AST::AttributeList& attrs)
- {
- for(const auto& at : attrs.m_items) {
- if( at.name() == "cfg" && !check_cfg(at.span(), at) ) {
- return false;
- }
- }
- return true;
- }
- };
-
switch( GET_TOK(tok, lex) )
{
case TOK_BRACE_OPEN:
submod.m_file_info.path = sub_path + "/";
+ // TODO: If cfg fails, just eat the TT until a matching #[cfg]?
+ // - Or, mark the file infor as not being valid (so child modules don't try to load)
Parse_ModRoot(lex, submod, meta_items);
GET_CHECK_TOK(tok, lex, TOK_BRACE_CLOSE);
break;
@@ -1934,7 +2032,7 @@ bool Parse_MacroInvocation_Opt(TokenStream& lex, AST::MacroInvocation& out_inv)
else if( ifs_file.is_open() )
{
submod.m_file_info.path = newpath_file;
- submod.m_file_info.controls_dir = false;
+ //submod.m_file_info.controls_dir = false;
}
// TODO: If this is not a controlling file, look in `modname/` for the new module
else