From 75205189d5e33a33193fa76a29f7518a9797299d Mon Sep 17 00:00:00 2001 From: John Hodge Date: Sat, 21 Mar 2015 15:41:00 +0800 Subject: Move wildcard use to Path::resolve, add 'bool' type --- src/ast/path.cpp | 65 ++++++++++++++++++++++++++++++++++++---------- src/ast/path.hpp | 11 +++++--- src/convert/resolve.cpp | 69 ++++++++++++++++++++----------------------------- src/coretypes.hpp | 1 + src/parse/types.cpp | 1 + src/types.cpp | 18 +++++++++++++ 6 files changed, 108 insertions(+), 57 deletions(-) diff --git a/src/ast/path.cpp b/src/ast/path.cpp index 4f83ae34..338a0b15 100644 --- a/src/ast/path.cpp +++ b/src/ast/path.cpp @@ -56,9 +56,10 @@ typename ::std::vector >::const_iterator find_named(const ::std::vector< }); } +/// Resolve a path into a canonical form, and bind it to the target value void Path::resolve(const Crate& root_crate) { - DEBUG("*this = " << *this); + TRACE_FUNCTION_F("*this = "<< *this); if(m_class != ABSOLUTE) throw ParseError::BugCheck("Calling Path::resolve on non-absolute path"); DEBUG("m_crate = '" << m_crate << "'"); @@ -102,18 +103,7 @@ void Path::resolve(const Crate& root_crate) continue; } } - - // Start searching for: - // - Re-exports - { - auto& imp = mod->imports(); - auto it = find_named(imp, node.name()); - if( it != imp.end() ) - { - DEBUG("Re-exported path " << it->data); - throw ParseError::Todo("Path::resolve() re-export"); - } - } + // Type Aliases { auto& items = mod->type_aliases(); @@ -232,6 +222,55 @@ void Path::resolve(const Crate& root_crate) } } + // - Re-exports + // > Comes last, as it's a potentially expensive operation + { + for( const auto& imp : mod->imports() ) + { + if( !imp.is_pub ) + { + // not public, ignore + } + else if( imp.name == node.name() ) + { + // replace nodes 0:i with the source path + DEBUG("Re-exported path " << imp.data); + AST::Path newpath = imp.data; + for( unsigned int j = i+1; j < m_nodes.size(); j ++ ) + { + newpath.m_nodes.push_back( m_nodes[j] ); + } + DEBUG("- newpath = " << newpath); + // TODO: This should check for recursion somehow + newpath.resolve(root_crate); + + *this = newpath; + DEBUG("Alias resolved, *this = " << *this); + return ; + } + else if( imp.name == "" ) + { + // Loop avoidance, don't check this + if( &imp.data == this ) + continue ; + + if( !imp.data.is_bound() ) + { + // not yet bound, so run resolution (recursion) + DEBUG("Recursively resolving pub wildcard use " << imp.data); + //imp.data.resolve(root_crate); + throw ParseError::Todo("Path::resolve() wildcard re-export call resolve"); + } + + throw ParseError::Todo("Path::resolve() wildcard re-export"); + } + else + { + // Can't match, ignore + } + } + } + throw ParseError::Generic("Unable to find component '" + node.name() + "'"); } diff --git a/src/ast/path.hpp b/src/ast/path.hpp index 51dd70f5..00a1b439 100644 --- a/src/ast/path.hpp +++ b/src/ast/path.hpp @@ -128,13 +128,18 @@ public: } } + /// Add the all nodes except the first from 'b' to 'a' and return static Path add_tailing(const Path& a, const Path& b) { Path ret(a); - ret[ret.size()-1].args() = b[0].args(); - for(unsigned int i = 1; i < b.m_nodes.size(); i ++) - ret.m_nodes.push_back(b.m_nodes[i]); + ret.add_tailing(b); return ret; } + /// Grab the args from the first node of b, and add the rest to the end of the path + void add_tailing(const Path& b) { + m_nodes.back().args() = b[0].args(); + for(unsigned int i = 1; i < b.m_nodes.size(); i ++) + m_nodes.push_back(b.m_nodes[i]); + } Path operator+(PathNode&& pn) const { Path tmp; tmp.append( ::std::move(pn) ); diff --git a/src/convert/resolve.cpp b/src/convert/resolve.cpp index 49c2e2a9..1e320e6f 100644 --- a/src/convert/resolve.cpp +++ b/src/convert/resolve.cpp @@ -381,68 +381,55 @@ void CPathResolver::handle_module(AST::Path path, AST::Module& mod) void ResolvePaths_HandleModule_Use(const AST::Crate& crate, const AST::Path& modpath, AST::Module& mod) { - DEBUG("modpath = " << modpath); + TRACE_FUNCTION_F("modpath = " << modpath); ::std::vector new_imports; for( auto& imp : mod.imports() ) { // TODO: Handle 'super' and 'self' imports // - Any other type of import will be absolute + if( !imp.data.is_absolute() ) + { + if( imp.data[0].name() == "super" ) { + if( modpath.size() < 1 ) + throw ParseError::Generic("Encountered 'super' at crate root"); + auto newpath = modpath; + newpath.nodes().pop_back(); + newpath.add_tailing(imp.data); + DEBUG("Absolutised path " << imp.data << " into " << newpath); + imp.data = ::std::move(newpath); + } + else { + auto newpath = modpath + imp.data; + DEBUG("Absolutised path " << imp.data << " into " << newpath); + imp.data = ::std::move(newpath); + } + } + + // Run resolution on import + imp.data.resolve(crate); + DEBUG("Resolved import : " << imp.data); + // If wildcard, make sure it's sane if( imp.name == "" ) { - DEBUG("Wildcard of " << imp.data); - if( imp.is_pub ) { - throw ParseError::Generic("Wildcard uses can't be public"); - } - - // Wildcard import - AST::Path& basepath = imp.data; - basepath.resolve(crate); - DEBUG("basepath = " << basepath); - switch(basepath.binding_type()) + switch(imp.data.binding_type()) { case AST::Path::UNBOUND: throw ParseError::BugCheck("path unbound after calling .resolve()"); case AST::Path::MODULE: - for( auto& submod : basepath.bound_module().submods() ) - { - if( submod.second == true ) - { - new_imports.push_back( basepath + AST::PathNode(submod.first.name(), {}) ); - } - } - for(const auto& imp : basepath.bound_module().imports() ) - { - if( imp.is_pub ) - { - DEBUG("Re-export " << imp.data); - if(imp.name == "") - throw ParseError::Generic("Wilcard uses can't be public"); - AST::Path path = imp.data; - path.resolve(crate); - DEBUG("Re-export (resolved) " << path); - new_imports.push_back( ::std::move(path) ); - } - } - //throw ParseError::Todo("ResolvePaths_HandleModule - wildcard use on module"); break; - case AST::Path::ALIAS: - throw ParseError::Todo("ResolvePaths_HandleModule_Use - ALIAS"); case AST::Path::ENUM: - throw ParseError::Todo("ResolvePaths_HandleModule_Use - ENUM"); + break; + + case AST::Path::ALIAS: case AST::Path::ENUM_VAR: - throw ParseError::Todo("ResolvePaths_HandleModule_Use - ENUM_VAR"); case AST::Path::STRUCT: - throw ParseError::Todo("ResolvePaths_HandleModule_Use - STRUCT"); case AST::Path::STRUCT_METHOD: - throw ParseError::Todo("ResolvePaths_HandleModule_Use - STRUCT_METHOD"); case AST::Path::TRAIT: - throw ParseError::Todo("ResolvePaths_HandleModule_Use - TRAIT"); case AST::Path::FUNCTION: - throw ParseError::Todo("ResolvePaths_HandleModule_Use - FUNCTION"); case AST::Path::STATIC: - throw ParseError::Todo("ResolvePaths_HandleModule_Use - STATIC"); + throw ParseError::Generic("Wildcard imports are only allowed on modules and enums"); } } } diff --git a/src/coretypes.hpp b/src/coretypes.hpp index 2982d42f..2fc11412 100644 --- a/src/coretypes.hpp +++ b/src/coretypes.hpp @@ -8,6 +8,7 @@ enum eCoreType { CORETYPE_INVAL, CORETYPE_ANY, + CORETYPE_BOOL, CORETYPE_CHAR, CORETYPE_UINT, CORETYPE_INT, CORETYPE_U8, CORETYPE_I8, diff --git a/src/parse/types.cpp b/src/parse/types.cpp index 3752dc85..23101dba 100644 --- a/src/parse/types.cpp +++ b/src/parse/types.cpp @@ -15,6 +15,7 @@ static const struct { const char* name; enum eCoreType type; } CORETYPES[] = { + {"bool", CORETYPE_BOOL}, {"char", CORETYPE_CHAR}, {"f32", CORETYPE_F32}, {"f64", CORETYPE_F64}, diff --git a/src/types.cpp b/src/types.cpp index abf6b2da..4082bc96 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -16,6 +16,7 @@ const char* coretype_name(const eCoreType ct ) { case CORETYPE_INVAL:return "-"; case CORETYPE_ANY: return "_"; case CORETYPE_CHAR: return "char"; + case CORETYPE_BOOL: return "bool"; case CORETYPE_UINT: return "usize"; case CORETYPE_INT: return "isize"; case CORETYPE_U8: return "u8"; @@ -38,6 +39,8 @@ bool TypeRef::deref(bool is_implicit) { switch(m_class) { + case TypeRef::NONE: + throw ::std::runtime_error("Dereferencing ! - bugcheck"); case TypeRef::ANY: // TODO: Check if the _ is bounded by Deref, if so use that throw ::std::runtime_error("Dereferencing _"); @@ -103,6 +106,7 @@ void TypeRef::merge_with(const TypeRef& other) switch(m_class) { + case TypeRef::NONE: case TypeRef::ANY: case TypeRef::UNIT: case TypeRef::PRIMITIVE: @@ -148,6 +152,8 @@ void TypeRef::resolve_args(::std::function fcn) DEBUG("" << *this); switch(m_class) { + case TypeRef::NONE: + throw ::std::runtime_error("TypeRef::resolve_args on !"); case TypeRef::ANY: // TODO: Is resolving args on an ANY an erorr? break; @@ -204,6 +210,8 @@ void TypeRef::match_args(const TypeRef& other, ::std::function>(::Deserialiser& d, TypeRef::Class& c) { d.item(n); #define _(x) if(n == #x) c = TypeRef::x; /**/ _(ANY) + else _(NONE) else _(UNIT) else _(PRIMITIVE) else _(FUNCTION) -- cgit v1.2.3