diff options
author | John Hodge <tpg@mutabah.net> | 2015-03-22 18:37:20 +0800 |
---|---|---|
committer | John Hodge <tpg@mutabah.net> | 2015-03-22 18:37:20 +0800 |
commit | 5c61e0955197adb58fdf7911ccf7e05c13f2263d (patch) | |
tree | ec216818778c9351f850bb4044a58c0cc6e691a4 /src | |
parent | fc9a04403eb5b694d37f77baa0de2f8e363f46f1 (diff) | |
download | mrust-5c61e0955197adb58fdf7911ccf7e05c13f2263d.tar.gz |
Clean up local path resolution, add internal 'str' type
Diffstat (limited to 'src')
-rw-r--r-- | src/ast/ast.hpp | 17 | ||||
-rw-r--r-- | src/ast/path.cpp | 25 | ||||
-rw-r--r-- | src/ast/path.hpp | 4 | ||||
-rw-r--r-- | src/ast/provided_module.cpp | 14 | ||||
-rw-r--r-- | src/convert/resolve.cpp | 228 | ||||
-rw-r--r-- | src/main.cpp | 2 | ||||
-rw-r--r-- | src/parse/types.cpp | 5 | ||||
-rw-r--r-- | src/types.hpp | 5 |
8 files changed, 198 insertions, 102 deletions
diff --git a/src/ast/ast.hpp b/src/ast/ast.hpp index 6ef0d85a..ece9704f 100644 --- a/src/ast/ast.hpp +++ b/src/ast/ast.hpp @@ -7,6 +7,7 @@ #include "../coretypes.hpp"
#include <memory>
#include <map>
+#include <algorithm>
#include "../parse/tokentree.hpp"
#include "../types.hpp"
@@ -520,6 +521,7 @@ class Module: itemlist_use_t m_imports;
::std::vector<Item<TypeAlias> > m_type_aliases;
itemlist_ext_t m_extern_crates;
+ ::std::vector<Module*> m_anon_modules; // TODO: Should this be serialisable?
itemlist_macros_t m_macros;
macro_imports_t m_macro_imports; // module => macro
@@ -583,6 +585,13 @@ public: void add_attr(MetaItem item) {
m_attrs.push_back(item);
}
+ unsigned int add_anon_module(Module* mod_ptr) {
+ auto it = ::std::find(m_anon_modules.begin(), m_anon_modules.end(), mod_ptr);
+ if( it != m_anon_modules.end() )
+ return it - m_anon_modules.begin();
+ m_anon_modules.push_back(mod_ptr);
+ return m_anon_modules.size()-1;
+ }
void iterate_functions(fcn_visitor_t* visitor, const Crate& crate);
@@ -599,6 +608,7 @@ public: ItemList<Trait>& traits() { return m_traits; }
itemlist_enum_t& enums () { return m_enums; }
itemlist_struct_t& structs() { return m_structs; }
+ ::std::vector<Module*>& anon_mods() { return m_anon_modules; }
const ::std::vector<MetaItem>& attrs() const { return m_attrs; }
const itemlist_fcn_t& functions() const { return m_functions; }
@@ -611,10 +621,13 @@ public: const ItemList<Trait>& traits() const { return m_traits; }
const itemlist_enum_t& enums () const { return m_enums; }
const itemlist_struct_t& structs() const { return m_structs; }
+ const ::std::vector<Module*>& anon_mods() const { return m_anon_modules; }
+
const itemlist_macros_t& macros() const { return m_macros; }
const macro_imports_t& macro_imports() const { return m_macro_imports; }
const ::std::vector<ItemNS<const MacroRules*> > macro_imports_res() const { return m_macro_import_res; }
+
SERIALISABLE_PROTOTYPES();
private:
void resolve_macro_import(const Crate& crate, const ::std::string& modname, const ::std::string& macro_name);
@@ -694,4 +707,8 @@ public: }
+extern AST::Module g_compiler_module;
+extern void AST_InitProvidedModule();
+
+
#endif // AST_HPP_INCLUDED
diff --git a/src/ast/path.cpp b/src/ast/path.cpp index fae2642e..8e73c095 100644 --- a/src/ast/path.cpp +++ b/src/ast/path.cpp @@ -79,6 +79,26 @@ void Path::resolve(const Crate& root_crate) const bool is_sec_last = (i+2 == m_nodes.size()); const PathNode& node = m_nodes[i]; + if( node.name()[0] == '#' ) + { + // HACK - Compiler-provided functions/types live in the special '#' module + if( node.name() == "#" ) { + if( i != 0 ) + throw ParseError::BugCheck("# module not at path root"); + mod = &g_compiler_module; + continue ; + } + + // Hacky special case - Anon modules are indexed + // - Darn you C++ and no string views + unsigned int index = ::std::strtoul(node.name().c_str()+1, nullptr, 10); // Parse the number at +1 + DEBUG(" index = " << index); + if( index >= mod->anon_mods().size() ) + throw ParseError::Generic("Anon module index out of range"); + mod = mod->anon_mods().at(index); + continue ; + } + // Sub-modules { auto& sms = mod->submods(); @@ -389,6 +409,11 @@ void Path::print_pretty(::std::ostream& os) const ::std::ostream& operator<<(::std::ostream& os, const Path& path) { + if( path.m_nodes.size() == 0 ) + { + os << "/* null path */"; + return os; + } #if PRETTY_PATH_PRINT switch(path.m_class) { diff --git a/src/ast/path.hpp b/src/ast/path.hpp index 4701b03a..fdf788a5 100644 --- a/src/ast/path.hpp +++ b/src/ast/path.hpp @@ -146,6 +146,10 @@ public: DEBUG("crate set to " << m_crate); } } + void set_local() { + assert(m_class == RELATIVE); + m_class = LOCAL; + } /// Add the all nodes except the first from 'b' to 'a' and return static Path add_tailing(const Path& a, const Path& b) { diff --git a/src/ast/provided_module.cpp b/src/ast/provided_module.cpp new file mode 100644 index 00000000..ea323172 --- /dev/null +++ b/src/ast/provided_module.cpp @@ -0,0 +1,14 @@ +/* + */ +#include "ast.hpp" + +AST::Module g_compiler_module; + +void AST_InitProvidedModule() +{ + // "struct str([u8])" + g_compiler_module.add_struct(true, "str", AST::TypeParams(), ::std::vector<AST::StructItem> { + AST::StructItem("", TypeRef(TypeRef::TagUnsizedArray(), TypeRef(CORETYPE_U8)), false), + }); +} + diff --git a/src/convert/resolve.cpp b/src/convert/resolve.cpp index e519d485..f28e9d45 100644 --- a/src/convert/resolve.cpp +++ b/src/convert/resolve.cpp @@ -35,11 +35,11 @@ class CPathResolver: {}
};
const AST::Crate& m_crate;
- const AST::Module* m_module;
+ AST::Module* m_module;
AST::Path m_module_path;
::std::vector< LocalItem > m_locals;
// TODO: Maintain a stack of variable scopes
- ::std::vector<const AST::Module*> m_module_stack;
+ ::std::vector< ::std::pair<unsigned int,AST::Module*> > m_module_stack;
friend class CResolvePaths_NodeVisitor;
@@ -62,10 +62,6 @@ public: }
virtual void end_scope() override;
- void add_local_use(::std::string name, AST::Path path) {
- throw ParseError::Todo("CPathResolver::add_local_use - Determine type of path (type or value)");
- m_locals.push_back( LocalItem(LocalItem::VAR, ::std::move(name), path) );
- }
::rust::option<const AST::Path&> lookup_local(LocalItem::Type type, const ::std::string& name) const;
// TODO: Handle a block and obtain the local module (if any)
@@ -103,9 +99,17 @@ public: }
void visit(AST::ExprNode_Block& node) {
- if( node.m_inner_mod.get() )
- m_res.m_module_stack.push_back( node.m_inner_mod.get() );
+ // If there's an inner module on this node
+ if( node.m_inner_mod.get() ) {
+ // Add a reference to it to the parent node (add_anon_module will do dedup)
+ AST::Module& parent_mod = *( (m_res.m_module_stack.size() > 0) ? m_res.m_module_stack.back().second : m_res.m_module );
+ auto idx = parent_mod.add_anon_module( node.m_inner_mod.get() );
+ // Increment the module path to include it? (No - Instead handle that when tracing the stack)
+ // And add to the list of modules to use in lookup
+ m_res.m_module_stack.push_back( ::std::make_pair(idx, node.m_inner_mod.get()) );
+ }
AST::NodeVisitorDef::visit(node);
+ // Once done, pop the module
if( node.m_inner_mod.get() )
m_res.m_module_stack.pop_back();
}
@@ -158,6 +162,7 @@ void CPathResolver::end_scope() }
m_locals.clear();
}
+// Returns the bound path for the local item
::rust::option<const AST::Path&> CPathResolver::lookup_local(LocalItem::Type type, const ::std::string& name) const
{
for( auto it = m_locals.end(); it -- != m_locals.begin(); )
@@ -169,6 +174,90 @@ void CPathResolver::end_scope() return ::rust::option<const AST::Path&>();
}
+// Search relative to current module
+// > Search local use definitions (function-level)
+// - TODO: Local use statements (scoped)
+// > Search module-level definitions
+bool lookup_path_in_module(const AST::Crate& crate, const AST::Module& module, const AST::Path& mod_path, AST::Path& path)
+{
+ for( const auto& item_mod : module.submods() )
+ {
+ if( item_mod.first.name() == path[0].name() ) {
+ // Check name down?
+ // Add current module path
+ path = mod_path + path;
+ path.resolve( crate );
+ return true;
+ }
+ }
+ for( const auto& import : module.imports() )
+ {
+ const ::std::string& bind_name = import.name;
+ const AST::Path& bind_path = import.data;
+ if( bind_name == "" ) {
+ throw ParseError::Todo("Handle lookup_path_in_module for wildcard imports");
+ }
+ else if( bind_name == path[0].name() ) {
+ path = AST::Path::add_tailing(bind_path, path);
+ path.resolve( crate );
+ return true;
+ }
+ }
+
+ // Types
+ for( const auto& item : module.structs() )
+ {
+ if( item.name == path[0].name() ) {
+ path = mod_path + path;
+ path.resolve( crate );
+ return true;
+ }
+ }
+ for( const auto& item : module.enums() )
+ {
+ if( item.name == path[0].name() ) {
+ path = mod_path + path;
+ path.resolve( crate );
+ return true;
+ }
+ }
+ for( const auto& item : module.traits() )
+ {
+ if( item.name == path[0].name() ) {
+ path = mod_path + path;
+ path.resolve( crate );
+ return true;
+ }
+ }
+ for( const auto& item : module.type_aliases() )
+ {
+ if( item.name == path[0].name() ) {
+ path = mod_path + path;
+ path.resolve( crate );
+ return true;
+ }
+ }
+
+ // Values / Functions
+ for( const auto& item_fcn : module.functions() )
+ {
+ if( item_fcn.name == path[0].name() ) {
+ path = mod_path + path;
+ path.resolve( crate );
+ return true;
+ }
+ }
+ for( const auto& item : module.statics() )
+ {
+ if( item.name == path[0].name() ) {
+ path = mod_path + path;
+ path.resolve( crate );
+ return true;
+ }
+ }
+
+ return false;
+}
void CPathResolver::handle_path(AST::Path& path, CASTIterator::PathMode mode)
{
DEBUG("path = " << path);
@@ -200,7 +289,7 @@ void CPathResolver::handle_path(AST::Path& path, CASTIterator::PathMode mode) // If there's a single node, and we're in expresion mode, look for a variable
// Otherwise, search for a type
- bool is_trivial_path = path.size() == 1 && path[0].args().size() == 0;
+ bool is_trivial_path = (path.size() == 1 && path[0].args().size() == 0);
LocalItem::Type search_type = (is_trivial_path && mode == MODE_EXPR ? LocalItem::VAR : LocalItem::TYPE);
auto local = lookup_local( search_type, path[0].name() );
@@ -209,29 +298,23 @@ void CPathResolver::handle_path(AST::Path& path, CASTIterator::PathMode mode) auto rpath = local.unwrap();
DEBUG("Local hit: " << path[0].name() << " = " << rpath);
- // Local import?
- if( rpath.size() > 0 )
+ switch(mode)
{
- path = AST::Path::add_tailing(rpath, path);
- path.resolve( m_crate );
- return ;
- }
-
// Local variable?
// - TODO: What would happen if MODE_EXPR but path isn't a single ident?
- if( mode == MODE_EXPR && is_trivial_path )
- {
- DEBUG("Local variable " << path[0].name());
- path = AST::Path(AST::Path::TagLocal(), path[0].name());
- return ;
- }
-
- // Type parameter, return verbatim?
- // - TODO: Are extra params/entries valid here?
- if( mode == MODE_TYPE )
- {
- DEBUG("Local type " << path[0].name());
- throw ParseError::BugCheck("Local types should be handled in handle_type");
+ case MODE_EXPR:
+ if( is_trivial_path )
+ {
+ DEBUG("Local variable " << path[0].name());
+ path = AST::Path(AST::Path::TagLocal(), path[0].name());
+ return ;
+ }
+ throw ParseError::Todo("TODO: MODE_EXPR, but not a single identifer, what do?");
+ // Type parameter
+ case MODE_TYPE:
+ DEBUG("Local type " << path);
+ // - Switch the path to be a "LOCAL"
+ path.set_local();
return ;
}
@@ -239,83 +322,24 @@ void CPathResolver::handle_path(AST::Path& path, CASTIterator::PathMode mode) // - Invalid afaik, instead Trait::method() is used
}
- // Search relative to current module
- // > Search local use definitions (function-level)
- // - TODO: Local use statements (scoped)
- // > Search module-level definitions
- for( const auto& item_mod : m_module->submods() )
- {
- if( item_mod.first.name() == path[0].name() ) {
- // Check name down?
- // Add current module path
- path = m_module_path + path;
- path.resolve( m_crate );
- return ;
- }
- }
- for( const auto& import : m_module->imports() )
- {
- const ::std::string& bind_name = import.name;
- const AST::Path& bind_path = import.data;
- if( bind_name == "" ) {
- }
- else if( bind_name == path[0].name() ) {
- path = AST::Path::add_tailing(bind_path, path);
- path.resolve( m_crate );
- return ;
- }
- }
-
- // Types
- for( const auto& item : m_module->structs() )
- {
- if( item.name == path[0].name() ) {
- path = m_module_path + path;
- path.resolve( m_crate );
- return ;
- }
- }
- for( const auto& item : m_module->enums() )
- {
- if( item.name == path[0].name() ) {
- path = m_module_path + path;
- path.resolve( m_crate );
- return ;
- }
- }
- for( const auto& item : m_module->traits() )
- {
- if( item.name == path[0].name() ) {
- path = m_module_path + path;
- path.resolve( m_crate );
- return ;
- }
- }
- for( const auto& item : m_module->type_aliases() )
- {
- if( item.name == path[0].name() ) {
- path = m_module_path + path;
- path.resolve( m_crate );
- return ;
- }
- }
-
- // Values / Functions
- for( const auto& item_fcn : m_module->functions() )
+ if( m_module_stack.size() )
{
- if( item_fcn.name == path[0].name() ) {
- path = m_module_path + path;
- path.resolve( m_crate );
- return ;
+ AST::Path local_path = m_module_path;
+ for(unsigned int i = 0; i < m_module_stack.size(); i ++)
+ local_path.nodes().push_back( AST::PathNode( FMT("#"<<i), {} ) );
+
+ for(unsigned int i = m_module_stack.size(); i--; )
+ {
+ if( lookup_path_in_module(m_crate, *m_module_stack[i].second, local_path, path) ) {
+ // Success!
+ return ;
+ }
+ local_path.nodes().pop_back();
}
}
- for( const auto& item : m_module->statics() )
+ if( lookup_path_in_module(m_crate, *m_module, m_module_path, path) )
{
- if( item.name == path[0].name() ) {
- path = m_module_path + path;
- path.resolve( m_crate );
- return ;
- }
+ return;
}
DEBUG("no matches found for path = " << path);
diff --git a/src/main.cpp b/src/main.cpp index 760f8566..f7748b14 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -26,6 +26,8 @@ bool debug_enabled() /// main!
int main(int argc, char *argv[])
{
+ AST_InitProvidedModule();
+
const char *infile = NULL;
::std::string outfile;
const char *crate_path = ".";
diff --git a/src/parse/types.cpp b/src/parse/types.cpp index 57c1bad8..bbbdd4f8 100644 --- a/src/parse/types.cpp +++ b/src/parse/types.cpp @@ -87,6 +87,11 @@ TypeRef Parse_Type(TokenStream& lex) if( tok.str() == CORETYPES[i].name ) return TypeRef(TypeRef::TagPrimitive(), CORETYPES[i].type); } + if( tok.str() == "str" ) + { + // TODO: Create an internal newtype for 'str' + return TypeRef(TypeRef::TagPath(), AST::Path({ AST::PathNode("#",{}), AST::PathNode("str",{}) })); + } // - Fall through to path handling // '::' - Absolute path case TOK_DOUBLE_COLON: { diff --git a/src/types.hpp b/src/types.hpp index 86733ad1..ab4c5250 100644 --- a/src/types.hpp +++ b/src/types.hpp @@ -92,6 +92,11 @@ public: m_class(PRIMITIVE),
m_core_type(type)
{}
+ TypeRef(enum eCoreType type):
+ m_class(PRIMITIVE),
+ m_core_type(type)
+ {}
+
struct TagTuple {};
TypeRef(TagTuple _, ::std::vector<TypeRef> inner_types):
m_class(TUPLE),
|