diff options
author | John Hodge <tpg@mutabah.net> | 2019-01-01 11:32:39 +0800 |
---|---|---|
committer | John Hodge <tpg@mutabah.net> | 2019-01-01 11:32:39 +0800 |
commit | 2f0ddfaf240c0269087d307b6df6bc00817e6806 (patch) | |
tree | 4810960698dfdbe9ac43a7d0f3abf915002e2122 /src | |
parent | be34ee650255d6bd5bb2b853c9dbdea5126672ab (diff) | |
download | mrust-2f0ddfaf240c0269087d307b6df6bc00817e6806.tar.gz |
Parse - Module Loading - Hopefully fix libcore without breaking other crates
Diffstat (limited to 'src')
-rw-r--r-- | src/ast/ast.hpp | 4 | ||||
-rw-r--r-- | src/parse/root.cpp | 128 |
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 |