diff options
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),
 | 
