diff options
| -rw-r--r-- | src/ast/ast.cpp | 28 | ||||
| -rw-r--r-- | src/ast/path.cpp | 192 | ||||
| -rw-r--r-- | src/ast/path.hpp | 38 | ||||
| -rw-r--r-- | src/ast/types.cpp | 381 | ||||
| -rw-r--r-- | src/ast/types.hpp | 17 | ||||
| -rw-r--r-- | src/common.hpp | 50 | ||||
| -rw-r--r-- | src/expand/derive.cpp | 6 | ||||
| -rw-r--r-- | src/expand/lang_item.cpp | 2 | ||||
| -rw-r--r-- | src/hir/from_ast.cpp | 7 | ||||
| -rw-r--r-- | src/hir/from_ast_expr.cpp | 2 | ||||
| -rw-r--r-- | src/include/span.hpp | 2 | ||||
| -rw-r--r-- | src/main.cpp | 4 | ||||
| -rw-r--r-- | src/parse/common.hpp | 2 | ||||
| -rw-r--r-- | src/parse/paths.cpp | 36 | ||||
| -rw-r--r-- | src/resolve/absolute.cpp | 43 | 
15 files changed, 157 insertions, 653 deletions
| diff --git a/src/ast/ast.cpp b/src/ast/ast.cpp index 802bde37..77981a4d 100644 --- a/src/ast/ast.cpp +++ b/src/ast/ast.cpp @@ -495,34 +495,6 @@ SERIALISE_TYPE(Enum::, "AST_Enum", {      s.item(m_variants);
  })
 -TypeRef Struct::get_field_type(const char *name, const ::std::vector<TypeRef>& args)
 -{
 -    if( args.size() != m_params.ty_params().size() )
 -    {
 -        throw ::std::runtime_error("Incorrect parameter count for struct");
 -    }
 -    // TODO: Should the bounds be checked here? Or is the count sufficient?
 -    for(const auto& f : m_data.as_Struct().ents)
 -    {
 -        if( f.m_name == name )
 -        {
 -            // Found it!
 -            if( args.size() )
 -            {
 -                TypeRef res = f.m_type;
 -                res.resolve_args( GenericResolveClosure(m_params, args) );
 -                return res;
 -            }
 -            else
 -            {
 -                return f.m_type;
 -            }
 -        }
 -    }
 -    
 -    throw ::std::runtime_error(FMT("No such field " << name));
 -}
 -
  SERIALISE_TYPE(Struct::, "AST_Struct", {
      s << m_params;
      s << m_data;
 diff --git a/src/ast/path.cpp b/src/ast/path.cpp index be8b5887..bd5ffe1a 100644 --- a/src/ast/path.cpp +++ b/src/ast/path.cpp @@ -52,8 +52,42 @@ PathBinding PathBinding::clone() const      throw "BUG: Fell off the end of PathBinding::clone";  } +::std::ostream& operator<<(::std::ostream& os, const PathParams& x) +{ +    bool needs_comma = false; +    os << "<"; +    for(const auto& v : x.m_lifetimes) { +        if(needs_comma) os << ", "; +        needs_comma = true; +        os << "'" << v; +    } +    for(const auto& v : x.m_types) { +        if(needs_comma) os << ", "; +        needs_comma = true; +        os << v; +    } +    for(const auto& v : x.m_assoc) { +        if(needs_comma) os << ", "; +        needs_comma = true; +        os << v.first << "=" << v.second; +    } +    os << ">"; +    return os; +} +Ordering PathParams::ord(const PathParams& x) const +{ +    Ordering rv; +    rv = ::ord(m_lifetimes, x.m_lifetimes); +    if(rv != OrdEqual)  return rv; +    rv = ::ord(m_types, x.m_types); +    if(rv != OrdEqual)  return rv; +    rv = ::ord(m_assoc, x.m_assoc); +    if(rv != OrdEqual)  return rv; +    return rv; +} +  // --- AST::PathNode -PathNode::PathNode(::std::string name, ::std::vector<TypeRef> args): +PathNode::PathNode(::std::string name, PathParams args):      m_name( mv$(name) ),      m_params( mv$(args) )  { @@ -63,20 +97,18 @@ Ordering PathNode::ord(const PathNode& x) const      Ordering    rv;      rv = ::ord(m_name, x.m_name);      if(rv != OrdEqual)  return rv; -    rv = ::ord(m_params, x.m_params); +    rv = m_params.ord(x.m_params);      if(rv != OrdEqual)  return rv;      return OrdEqual;  }  void PathNode::print_pretty(::std::ostream& os, bool is_type_context) const  {      os << m_name; -    if( m_params.size() ) +    if( ! m_params.is_empty() )      {          if( ! is_type_context )              os << "::"; -        os << "<";          os << m_params; -        os << ">";      }  }  ::std::ostream& operator<<(::std::ostream& os, const PathNode& pn) { @@ -85,10 +117,10 @@ void PathNode::print_pretty(::std::ostream& os, bool is_type_context) const  }  SERIALISE_TYPE(PathNode::, "PathNode", {      s << m_name; -    s << m_params; +    //s << m_params;  },{      s.item(m_name); -    s.item(m_params); +    //s.item(m_params);  })  /// Return an iterator to the named item @@ -260,34 +292,6 @@ void Path::bind_trait(const Trait& ent, const ::std::vector<TypeRef>& /*args*/)      m_binding = PathBinding::make_Trait({&ent});  } -void Path::resolve_args(::std::function<TypeRef(const char*)> fcn) -{ -    TRACE_FUNCTION_F(*this); -     -    TU_MATCH(Path::Class, (m_class), (ent), -    (Invalid), -    (Local,  ), -     -    (Relative, Path::resolve_args_nl(ent.nodes, fcn); ), -    (Absolute, Path::resolve_args_nl(ent.nodes, fcn); ), -    (Self    , Path::resolve_args_nl(ent.nodes, fcn); ), -    (Super   , Path::resolve_args_nl(ent.nodes, fcn); ), -    (UFCS, -        ent.type->resolve_args(fcn); -        ent.trait->resolve_args(fcn); -        Path::resolve_args_nl(ent.nodes, fcn); -        ) -    ) -} -void Path::resolve_args_nl(::std::vector<PathNode>& nodes, ::std::function<TypeRef(const char*)> fcn) -{ -    for(auto& n : nodes) -    { -        for(auto& p : n.args()) -            p.resolve_args(fcn); -    } -} -  Path& Path::operator+=(const Path& other)  {      for(auto& node : other.nodes()) @@ -297,124 +301,6 @@ Path& Path::operator+=(const Path& other)      return *this;  } -/// Match two same-format (i.e. same components) paths together, calling TypeRef::match_args on arguments -void Path::match_args(const Path& other, ::std::function<void(const char*,const TypeRef&)> fcn) const -{ -    // TODO: Ensure that the two paths are of a compatible class (same class?) -    // - This will crash atm if they aren't the same -    TU_MATCH(Path::Class, (m_class, other.m_class), (ent, x_ent), -    (Invalid), -    (Local,  ), -     -    (Relative, Path::match_args_nl(ent.nodes, x_ent.nodes, fcn); ), -    (Absolute, Path::match_args_nl(ent.nodes, x_ent.nodes, fcn); ), -    (Self    , Path::match_args_nl(ent.nodes, x_ent.nodes, fcn); ), -    (Super   , Path::match_args_nl(ent.nodes, x_ent.nodes, fcn); ), -    (UFCS, -        Path::match_args_nl(ent.nodes, x_ent.nodes, fcn); -        throw ::std::runtime_error("TODO: UFCS Path::match_args"); -        ) -    ) -} - -void Path::match_args_nl(const ::std::vector<PathNode>& nodes_a, const ::std::vector<PathNode>& nodes_b, ::std::function<void(const char*,const TypeRef&)> fcn) -{ -    if( nodes_a.size() != nodes_b.size() ) -        throw ::std::runtime_error("Type mismatch (path size)"); -    for( unsigned int i = 0; i < nodes_a.size(); i++ ) -    { -        auto& pn1 = nodes_a[i]; -        auto& pn2 = nodes_b[i]; -        if( pn1.name() != pn2.name() ) -            throw ::std::runtime_error("Type mismatch (path component)"); -        if( pn1.args().size() != pn2.args().size() ) -            throw ::std::runtime_error("Type mismatch (path component param count)"); -         -        for( unsigned int j = 0; j < pn1.args().size(); j ++ ) -        { -            auto& t1 = pn1.args()[j]; -            auto& t2 = pn2.args()[j]; -            t1.match_args( t2, fcn ); -        } -    } -} - -bool Path::is_concrete() const -{ -    for(const auto& n : this->nodes()) -    { -        for(const auto& p : n.args()) -            if( not p.is_concrete() ) -                return false; -    } -    return true; -} - -/// Compare if two paths refer to the same non-generic item -/// -/// - This doesn't handle the (impossible?) case where a generic might -///   cause two different paths to look the same. -int Path::equal_no_generic(const Path& x) const -{ -    if( m_class.is_Invalid() && x.m_class.is_Invalid() ) -        return 0; -    DEBUG("equal_no_generic(this = " << *this << ", x = " << x << ")"); -    if( m_class.tag() != x.m_class.tag() ) -        return -1; -     -    TU_MATCH(Path::Class, (m_class, x.m_class), (ent, x_ent), -    (Invalid, return 0; ), -    (Local,    return (ent.name == x_ent.name ? 0 : 1); ), -     -    (Relative, return Path::node_lists_equal_no_generic(ent.nodes, x_ent.nodes); ), -    (Absolute, -        if( ent.crate != x_ent.crate ) -            return -1; -        return Path::node_lists_equal_no_generic(ent.nodes, x_ent.nodes); -        ), -    (Self    , return Path::node_lists_equal_no_generic(ent.nodes, x_ent.nodes); ), -    (Super   , return Path::node_lists_equal_no_generic(ent.nodes, x_ent.nodes); ), -    (UFCS, -        throw ::std::runtime_error("TODO: UFCS Path::equal_no_generic"); -        return Path::node_lists_equal_no_generic(ent.nodes, x_ent.nodes); -        ) -    ) -    throw ::std::runtime_error("Path::equal_no_generic - fell off"); -} - -int Path::node_lists_equal_no_generic(const ::std::vector<PathNode>& nodes_a, const ::std::vector<PathNode>& nodes_b) -{ -    if( nodes_a.size() != nodes_b.size() ) { -        return -1; -    } -     -    bool conditional_match = false; -    unsigned int i = 0; -    for( const auto &e : nodes_a ) -    { -        const auto& xe = nodes_b[i]; -        if( e.name() != xe.name() ) -            return -1; -         -        if( e.args().size() || xe.args().size() ) -        { -            DEBUG("e = " << e << ", xe = " << xe); -            if( e.args().size() != xe.args().size() ) -                throw CompileError::BugCheck("Generics should be resolved, and hence have the correct argument count"); -            for( unsigned int j = 0; j < e.args().size(); j ++ ) -            { -                int rv = e.args()[j].equal_no_generic( xe.args()[j] ); -                if(rv < 0) return rv; -                if(rv > 0)  conditional_match = true; -            } -        } -         -        i ++; -    } -     -    return (conditional_match ? 1 : 0); -} -  Ordering Path::ord(const Path& x) const  {      Ordering rv; diff --git a/src/ast/path.hpp b/src/ast/path.hpp index 4029f655..4b9cffa4 100644 --- a/src/ast/path.hpp +++ b/src/ast/path.hpp @@ -82,18 +82,33 @@ TAGGED_UNION_EX(PathBinding, (), Unbound, (  extern ::std::ostream& operator<<(::std::ostream& os, const PathBinding& x); +struct PathParams +{ +    ::std::vector< ::std::string >  m_lifetimes; +    ::std::vector< TypeRef >    m_types; +    ::std::vector< ::std::pair< ::std::string, TypeRef> >   m_assoc; +     +    bool is_empty() const { +        return m_lifetimes.empty() && m_types.empty() && m_assoc.empty(); +    } +     +    Ordering ord(const PathParams& x) const; +     +    friend ::std::ostream& operator<<(::std::ostream& os, const PathParams& x); +};  class PathNode:      public ::Serialisable  {      ::std::string   m_name; -    ::std::vector<TypeRef>  m_params; +    PathParams  m_params;  public:      PathNode() {} -    PathNode(::std::string name, ::std::vector<TypeRef> args = {}); +    PathNode(::std::string name, PathParams args = {});      const ::std::string& name() const { return m_name; } -          ::std::vector<TypeRef>& args()       { return m_params; } -    const ::std::vector<TypeRef>& args() const { return m_params; } +     +    const ::AST::PathParams& args() const { return m_params; } +          ::AST::PathParams& args()       { return m_params; }      Ordering ord(const PathNode& x) const;      void print_pretty(::std::ostream& os, bool is_type_context) const; @@ -218,7 +233,7 @@ public:              ;          else if( nodes().size() > 0 )              nodes().back().args() = b[0].args(); -        else if( b[0].args().size() > 0 ) +        else if( ! b[0].args().is_empty() )              throw ::std::runtime_error("add_tail to empty path, but generics in source");          else {          } @@ -247,12 +262,6 @@ public:          nodes().push_back(node);          m_binding = PathBinding();      } - -    /// Resolve generic arguments within the path -    void resolve_args(::std::function<TypeRef(const char*)> fcn); -     -    /// Match args -    void match_args(const Path& other, ::std::function<void(const char*,const TypeRef&)> fcn) const;      bool is_trivial() const {          TU_MATCH_DEF(Class, (m_class), (e), @@ -263,7 +272,7 @@ public:              return true;              ),          (Relative, -            return e.nodes.size() == 1 && e.nodes[0].args().size() == 0; +            return e.nodes.size() == 1 && e.nodes[0].args().is_empty();              )          )      } @@ -311,9 +320,6 @@ public:      PathNode& operator[](int idx) { if(idx>=0) return nodes()[idx]; else return nodes()[size()+idx]; }      const PathNode& operator[](int idx) const { return (*(Path*)this)[idx]; } -    /// Returns 0 if paths are identical, 1 if TypeRef::TagArg is present in one, and -1 if a node differs -    int equal_no_generic(const Path& x) const; -          Ordering ord(const Path& x) const;      bool operator==(const Path& x) const { return ord(x) == OrdEqual; }      bool operator!=(const Path& x) const { return ord(x) != OrdEqual; } @@ -327,8 +333,6 @@ public:      friend void operator>>(Deserialiser& s, Path::Class& pc);  private:      static void resolve_args_nl(::std::vector<PathNode>& nodes, ::std::function<TypeRef(const char*)> fcn); -    static void match_args_nl(const ::std::vector<PathNode>& nodes_a, const ::std::vector<PathNode>& nodes_b, ::std::function<void(const char*,const TypeRef&)> fcn); -    static int node_lists_equal_no_generic(const ::std::vector<PathNode>& nodes_a, const ::std::vector<PathNode>& nodes_b);      void check_param_counts(const GenericParams& params, bool expect_params, PathNode& node);  public: diff --git a/src/ast/types.cpp b/src/ast/types.cpp index 8cc9b4ea..7b1c4cdb 100644 --- a/src/ast/types.cpp +++ b/src/ast/types.cpp @@ -127,387 +127,6 @@ TypeRef::TypeRef(const TypeRef& other)      }  } -/// Replace this type reference with a dereferenced version -bool TypeRef::deref(bool is_implicit) -{ -    #define _(VAR, ...) case TypeData::TAG_##VAR: { auto &ent = m_data.as_##VAR(); (void)&ent; __VA_ARGS__ } break; -    switch(m_data.tag()) -    { -    case TypeData::TAGDEAD: throw ""; -    case TypeData::TAG_None:        throw ::std::runtime_error("Dereferencing ! - bugcheck"); -    case TypeData::TAG_Macro:       throw ::std::runtime_error("Dereferencing unexpanded macro - bugcheck"); -    case TypeData::TAG_Any:         throw ::std::runtime_error("Dereferencing _"); -    case TypeData::TAG_Unit:        throw ::std::runtime_error("Dereferencing ()"); -    case TypeData::TAG_Primitive:   throw ::std::runtime_error("Dereferencing a primtive type"); -    case TypeData::TAG_Function:    throw ::std::runtime_error("Dereferencing a function"); -     -    case TypeData::TAG_Generic: -        // TODO: Check for Deref<Output=?> bound -        throw ::std::runtime_error("TODO: Check for a Deref bound on generic"); -    _(Borrow, -        *this = *ent.inner; -        return true; -        ) -    _(Pointer, -        // raw pointers can't be implicitly dereferenced -        if( is_implicit ) -            return false; -        *this = *ent.inner; -        return true; -        ) -    case TypeData::TAG_Tuple: -    case TypeData::TAG_Array: -    case TypeData::TAG_Path: -        throw ::std::runtime_error("TODO: Search for an impl of Deref"); -    case TypeData::TAG_TraitObject: -        throw ::std::runtime_error("TODO: TypeRef::deref on MULTIDST"); -    } -    #undef _ -    throw ::std::runtime_error("BUGCHECK: Fell off end of TypeRef::deref"); -} - -/// Merge the contents of the passed type with this type -///  -/// \note Both types must be of the same form (i.e. both be tuples) -void TypeRef::merge_with(const TypeRef& other) -{ -    // Ignore if other is wildcard -    //if( other.m_class == TypeRef::ANY ) { -    //    assert(other.m_inner_types.size() == 0 && "TODO: merge_with on bounded _"); -    //    return; -    //} -    -    // If this is a wildcard, then replace with the other type  -    if( m_data.is_Any() ) { -        //if( m_inner_types.size() && m_inner_types.size() != other.m_inner_types.size() ) -        //    throw ::std::runtime_error("TypeRef::merge_with - Handle bounded wildcards"); -        *this = other; -        return; -    } -     -    // If classes don't match, then merge is impossible -    if( m_data.tag() != other.m_data.tag() ) -        throw ::std::runtime_error("TypeRef::merge_with - Types not compatible"); -     -    // If both types are concrete, then they must be the same -    if( is_concrete() && other.is_concrete() ) -    { -        if( *this != other ) -            throw ::std::runtime_error("TypeRef::merge_with - Types not compatible"); -        return; -    } -     -     -    TU_MATCH(TypeData, (m_data, other.m_data), (ent, other_ent), -    (None, -        throw ::std::runtime_error("TypeRef::merge_with - Reached concrete/wildcard"); -        ), -    (Macro, -        throw ::std::runtime_error("TypeRef::merge_with - Reached unexpanded macro"); -        ), -    (Any, -        throw ::std::runtime_error("TypeRef::merge_with - Reached concrete/wildcard"); -        ), -    (Unit, -        throw ::std::runtime_error("TypeRef::merge_with - Reached concrete/wildcard"); -        ), -    (Primitive, -        throw ::std::runtime_error("TypeRef::merge_with - Reached concrete/wildcard"); -        ), -    (Function, -        ent.info.m_rettype->merge_with( *other_ent.info.m_rettype ); -         -        if( ent.info.m_arg_types.size() != other_ent.info.m_arg_types.size() ) -            throw ::std::runtime_error("TypeRef::merge_with - Types not compatible [function sz]"); -        for(unsigned int i = 0; i < ent.info.m_arg_types.size(); i ++) -        { -            ent.info.m_arg_types[i].merge_with( other_ent.info.m_arg_types[i] ); -        } -        ), -    (Tuple, -        // Other is known not to be wildcard, and is also a tuple, so it must be the same size -        if( ent.inner_types.size() != other_ent.inner_types.size() ) -            throw ::std::runtime_error("TypeRef::merge_with - Types not compatible [tuple sz]"); -        for(unsigned int i = 0; i < ent.inner_types.size(); i ++) -        { -            ent.inner_types[i].merge_with( other_ent.inner_types[i] ); -        } -        ), -    (Borrow, -        if( ent.is_mut != other_ent.is_mut ) -            throw ::std::runtime_error("TypeRef::merge_with - Types not compatible [inner mut]"); -        ent.inner->merge_with( *other_ent.inner ); -        ), -    (Pointer, -        if( ent.is_mut != other_ent.is_mut ) -            throw ::std::runtime_error("TypeRef::merge_with - Types not compatible [inner mut]"); -        ent.inner->merge_with( *other_ent.inner ); -        ), -    (Array, -        throw ::std::runtime_error("TODO: TypeRef::merge_with on ARRAY"); -        ), -    (Generic, -        throw ::std::runtime_error("TODO: TypeRef::merge_with on GENERIC"); -        ), -    (Path, -        throw ::std::runtime_error("TODO: TypeRef::merge_with on PATH"); -        ), -    (TraitObject, -        throw ::std::runtime_error("TODO: TypeRef::merge_with on MULTIDST"); -        ) -    ) -} - -/// Resolve all Generic/Argument types to the value returned by the passed closure -///  -/// Replaces every instance of a TypeRef::GENERIC with the value returned from the passed -/// closure. -void TypeRef::resolve_args(::std::function<TypeRef(const char*)> fcn) -{ -    DEBUG("" << *this); -    #define _(VAR, ...) case TypeData::TAG_##VAR: { auto &ent = m_data.as_##VAR(); (void)&ent; __VA_ARGS__ } break; -    switch(m_data.tag()) -    { -    case TypeData::TAGDEAD: throw ""; -    _(None, -        throw ::std::runtime_error("TypeRef::resolve_args on !"); -        ) -    _(Macro, -        throw ::std::runtime_error("TypeRef::resolve_args on unexpanded macro"); -        ) -    // TODO: Is resolving args on an ANY an erorr? -    _(Any) -    _(Unit) -    _(Primitive) -    _(Function, -        ent.info.m_rettype->resolve_args(fcn); -        for( auto& t : ent.info.m_arg_types ) -            t.resolve_args(fcn); -        ) -    _(Tuple, -        for( auto& t : ent.inner_types ) -            t.resolve_args(fcn); -        ) -    _(Borrow, -        ent.inner->resolve_args(fcn); -        ) -    _(Pointer, -        ent.inner->resolve_args(fcn); -        ) -    _(Array, -        ent.inner->resolve_args(fcn); -        ) -    _(Generic, -        *this = fcn(ent.name.c_str()); -        ) -    _(Path, -        ent.path.resolve_args(fcn); -        ) -    _(TraitObject, -        for( auto& p : ent.traits ) -            p.resolve_args(fcn); -        ) -    } -    #undef _ -} - -/// Match this type against another type, calling the provided function for all generics found in this -/// -/// \param other    Type containing (possibly) concrete types -/// \param fcn  Function to call for all generics (called with matching type from \a other) -/// This is used to handle extracting types passsed to methods/enum variants -void TypeRef::match_args(const TypeRef& other, ::std::function<void(const char*,const TypeRef&)> fcn) const -{ -    // If this type is a generic, then call the closure with the other type -    if( m_data.tag() == TypeData::TAG_Generic ) { -        fcn( m_data.as_Generic().name.c_str(), other ); -        return ; -    } -     -    // If the other type is a wildcard, early return -    // - TODO - Might want to restrict the other type to be of the same form as this type -    if( other.m_data.tag() == TypeData::TAG_Any ) -        return; -     -    DEBUG("this = " << *this << ", other = " << other); -     -    // Any other case, it's a "pattern" match -    if( m_data.tag() != other.m_data.tag() ) -        throw ::std::runtime_error("Type mismatch (class)"); -    TU_MATCH(TypeData, (m_data, other.m_data), (ent, other_ent), -    (None, -        throw ::std::runtime_error("TypeRef::match_args on !"); -        ), -    (Macro, -        throw CompileError::BugCheck("TypeRef::match_args - unexpanded macro"); -        ), -    (Any, -        // Wait, isn't this an error? -        throw ::std::runtime_error("Encountered '_' in match_args"); -        ), -    (Unit), -    (Primitive, -        // TODO: Should check if the type matches -        if( ent.core_type != other_ent.core_type ) -            throw ::std::runtime_error("Type mismatch (core)"); -        ), -    (Function, -        if( ent.info.m_abi != other_ent.info.m_abi ) -            throw ::std::runtime_error("Type mismatch (function abi)"); -        ent.info.m_rettype->match_args( *other_ent.info.m_rettype, fcn ); -         -        if( ent.info.m_arg_types.size() != other_ent.info.m_arg_types.size() ) -            throw ::std::runtime_error("Type mismatch (function size)"); -        for(unsigned int i = 0; i < ent.info.m_arg_types.size(); i ++ ) -            ent.info.m_arg_types[i].match_args( other_ent.info.m_arg_types[i], fcn ); -        ), -    (Tuple, -        if( ent.inner_types.size() != other_ent.inner_types.size() ) -            throw ::std::runtime_error("Type mismatch (tuple size)"); -        for(unsigned int i = 0; i < ent.inner_types.size(); i ++ ) -            ent.inner_types[i].match_args( other_ent.inner_types[i], fcn ); -        ), -    (Borrow, -        if( ent.is_mut != other_ent.is_mut ) -            throw ::std::runtime_error("Type mismatch (inner mutable)"); -        ent.inner->match_args( *other_ent.inner, fcn ); -        ), -    (Pointer, -        if( ent.is_mut != other_ent.is_mut ) -            throw ::std::runtime_error("Type mismatch (inner mutable)"); -        ent.inner->match_args( *other_ent.inner, fcn ); -        ), -    (Array, -        ent.inner->match_args( *other_ent.inner, fcn ); -        if(ent.size.get() || other_ent.size.get()) -        { -            throw ::std::runtime_error("TODO: Sized array match_args"); -        } -        ), -    (Generic, -        throw ::std::runtime_error("Encountered GENERIC in match_args"); -        ), -    (Path, -        ent.path.match_args(other_ent.path, fcn); -        ), -    (TraitObject, -        throw ::std::runtime_error("TODO: TypeRef::match_args on MULTIDST"); -        ) -    ) -} - -/// Checks if the type is fully bounded -bool TypeRef::is_concrete() const -{ -    #define _(VAR, ...) case TypeData::VAR: { const auto &ent = m_data.as_##VAR(); (void)&ent; __VA_ARGS__ } break; -    TU_MATCH(TypeData, (m_data), (ent), -    (None, -        throw ::std::runtime_error("TypeRef::is_concrete on !"); -        ), -    (Macro, throw CompileError::BugCheck("TypeRef::is_concrete - unexpanded macro");), -    (Any, return false;), -    (Unit, return true; ), -    (Primitive, return true; ), -    (Function, -        if( not ent.info.m_rettype->is_concrete() ) -            return false; -        for(const auto& t : ent.info.m_arg_types ) -            if( not t.is_concrete() ) -                return false; -        return true; -        ), -    (Tuple, -        for(const auto& t : ent.inner_types) -            if( not t.is_concrete() ) -                return false; -        return true; -        ), -    (Borrow, -        return ent.inner->is_concrete(); -        ), -    (Pointer, -        return ent.inner->is_concrete(); -        ), -    (Array, -        return ent.inner->is_concrete(); -        ), -    (Generic, -        // Well, I guess a generic param is "concrete" -        return true; -        ), -    (Path, -        return ent.path.is_concrete(); -        ), -    (TraitObject, -        for(const auto& p : ent.traits ) -            if( not p.is_concrete() ) -                return false; -        return true; -        ) -    ) -    #undef _ -    throw ::std::runtime_error( FMT("BUGCHECK - Invalid type class on " << *this) ); -} - -int TypeRef::equal_no_generic(const TypeRef& x) const -{ -    //DEBUG(*this << ", " << x); -    if( m_data.tag() == TypeData::TAG_Generic ) //|| x.m_class == TypeRef::GENERIC ) -        return 1; -    if( m_data.tag() != x.m_data.tag() )  return -1; - -    TU_MATCH(TypeData, (m_data, x.m_data), (ent, x_ent), -    (None, return 0;), -    (Macro, throw CompileError::BugCheck("TypeRef::equal_no_generic - unexpanded macro");), -    (Unit, return 0;), -    (Any, return 0;), -    (Primitive, -        if( ent.core_type != x_ent.core_type )  return -1; -        return 0; -        ), -    (Function, -        if( ent.info.m_abi != x_ent.info.m_abi )    return -1; -        throw CompileError::Todo("TypeRef::equal_no_generic - FUNCTION"); -        ), -    (Generic, -        throw CompileError::BugCheck("equal_no_generic - Generic should have been handled above"); -        ), -    (Path, -        return ent.path.equal_no_generic( x_ent.path ); -        ), -    (Borrow, -        if( ent.is_mut != x_ent.is_mut ) -            return -1; -        return ent.inner->equal_no_generic( *x_ent.inner ); -        ), -    (Pointer, -        if( ent.is_mut != x_ent.is_mut ) -            return -1; -        return ent.inner->equal_no_generic( *x_ent.inner ); -        ), -    (Array, -        if( ent.size.get() || x_ent.size.get() ) -            throw CompileError::Todo("TypeRef::equal_no_generic - sized array"); -        return ent.inner->equal_no_generic( *x_ent.inner ); -        ), -    (Tuple, -        bool fuzzy = false; -        if( ent.inner_types.size() != x_ent.inner_types.size() ) -            return -1; -        for( unsigned int i = 0; i < ent.inner_types.size(); i ++ ) -        { -            int rv = ent.inner_types[i].equal_no_generic( x_ent.inner_types[i] ); -            if(rv < 0)  return -1; -            if(rv > 0)  fuzzy = true; -        } -        return (fuzzy ? 1 : 0); -        ), -    (TraitObject, -        throw CompileError::Todo("TypeRef::equal_no_generic - MULTIDST"); -        ) -    ) -    throw CompileError::BugCheck("equal_no_generic - Ran off end"); -}  Ordering TypeRef::ord(const TypeRef& x) const  {      Ordering    rv; diff --git a/src/ast/types.hpp b/src/ast/types.hpp index a79a811d..b3208f8c 100644 --- a/src/ast/types.hpp +++ b/src/ast/types.hpp @@ -220,20 +220,6 @@ public:      const Span& span() const { return m_span; }
 -    /// Dereference the type (return the result of *type_instance)
 -    bool deref(bool is_implicit);
 -    /// Merge with another type (combines known aspects, conflitcs cause an exception)
 -    void merge_with(const TypeRef& other);
 -    /// Replace 'GENERIC' entries with the return value of the closure
 -    void resolve_args(::std::function<TypeRef(const char*)> fcn);
 -    /// Match 'GENERIC' entries with another type, passing matches to a closure
 -    void match_args(const TypeRef& other, ::std::function<void(const char*,const TypeRef&)> fcn) const;
 -    
 -    bool impls_wildcard(const AST::Crate& crate, const AST::Path& trait) const;
 -    
 -    /// Returns true if the type is fully known (all sub-types are not wildcards)
 -    bool is_concrete() const;
 -    
      bool is_valid() const { return ! m_data.is_None(); }
      bool is_unbounded() const { return m_data.is_Any(); }
 @@ -285,9 +271,6 @@ public:      //void add_trait(TypeRef trait) { assert(is_wildcard()); m_inner_types.push_back( ::std::move(trait) ); }
      //const ::std::vector<TypeRef>& traits() const { assert(is_wildcard()); return m_inner_types; }   
 -    /// Returns 0 if types are identical, 1 if TypeRef::TagArg is present in one, and -1 if form differs
 -    int equal_no_generic(const TypeRef& x) const;
 -    
      Ordering ord(const TypeRef& x) const;
      bool operator==(const TypeRef& x) const { return ord(x) == OrdEqual; }
      bool operator!=(const TypeRef& x) const { return ord(x) != OrdEqual; }
 diff --git a/src/common.hpp b/src/common.hpp index 96cfcd96..da2c3898 100644 --- a/src/common.hpp +++ b/src/common.hpp @@ -41,24 +41,6 @@ enum Ordering      OrdEqual,      OrdGreater,  }; -template<typename T> -Ordering ord(const ::std::vector<T>& l, const ::std::vector<T>& r) -{ -    unsigned int i = 0; -    for(const auto& it : l) -    { -        if( i >= r.size() ) -            return OrdGreater; -         -        auto rv = it.ord(r[i]); -        if( rv != OrdEqual ) -            return rv; -         -        i ++; -    } -         -    return OrdEqual; -}  static inline Ordering ord(bool l, bool r)  {      if(l == r) @@ -86,6 +68,38 @@ static inline Ordering ord(const ::std::string& l, const ::std::string& r)      else          return OrdLess;  } +template<typename T> +Ordering ord(const T& l, const T& r) +{ +    return l.ord(r); +} +template<typename T, typename U> +Ordering ord(const ::std::pair<T,U>& l, const ::std::pair<T,U>& r) +{ +    Ordering    rv; +    rv = ::ord(l.first, r.first); +    if(rv != OrdEqual)   return rv; +    rv = ::ord(l.second, r.second); +    return rv; +} +template<typename T> +Ordering ord(const ::std::vector<T>& l, const ::std::vector<T>& r) +{ +    unsigned int i = 0; +    for(const auto& it : l) +    { +        if( i >= r.size() ) +            return OrdGreater; +         +        auto rv = ::ord( it, r[i] ); +        if( rv != OrdEqual ) +            return rv; +         +        i ++; +    } +         +    return OrdEqual; +}  template <typename T> diff --git a/src/expand/derive.cpp b/src/expand/derive.cpp index 06369787..fdb8088b 100644 --- a/src/expand/derive.cpp +++ b/src/expand/derive.cpp @@ -149,8 +149,10 @@ static void derive_item(const Span& sp, AST::Module& mod, const AST::MetaItem& a      const auto& params = item.params();      TypeRef type(sp, path); -    for( const auto& param : params.ty_params() ) -        type.path().nodes().back().args().push_back( TypeRef(TypeRef::TagArg(), param.name()) ); +    auto& types_args = type.path().nodes().back().args(); +    for( const auto& param : params.ty_params() ) { +        types_args.m_types.push_back( TypeRef(TypeRef::TagArg(), param.name()) ); +    }      for( const auto& trait : attr.items() )      { diff --git a/src/expand/lang_item.cpp b/src/expand/lang_item.cpp index d381d17c..c34642db 100644 --- a/src/expand/lang_item.cpp +++ b/src/expand/lang_item.cpp @@ -15,7 +15,7 @@ void handle_lang_item(AST::Crate& crate, const AST::Path& path, const ::std::str  {      if(name == "phantom_fn") {          crate.m_lang_item_PhantomFn = AST::Path(path); -        crate.m_lang_item_PhantomFn.nodes().back().args() = { TypeRef("A"), TypeRef("B") }; +        crate.m_lang_item_PhantomFn.nodes().back().args().m_types = { TypeRef("A"), TypeRef("B") };      }      else if( name == "send" ) {          // Don't care, Send is fully library in mrustc diff --git a/src/hir/from_ast.cpp b/src/hir/from_ast.cpp index 26d7029f..bffafc48 100644 --- a/src/hir/from_ast.cpp +++ b/src/hir/from_ast.cpp @@ -319,7 +319,7 @@          ::HIR::SimplePath   rv( e.crate );          for( const auto& node : e.nodes )          { -            if( node.args().size() > 0 ) +            if( ! node.args().is_empty() )              {                  if( allow_final_generic && &node == &e.nodes.back() ) {                      // Let it pass @@ -342,7 +342,10 @@      TU_IFLET(::AST::Path::Class, path.m_class, Absolute, e,          auto sp = LowerHIR_SimplePath(path, true);          ::HIR::PathParams   params; -        for(const auto& param : e.nodes.back().args()) { +        const auto& src_params = e.nodes.back().args(); +        //for(const auto& param : src_params.m_lifetimes) { +        //} +        for(const auto& param : src_params.m_types) {              params.m_types.push_back( LowerHIR_Type(param) );          }          // TODO: Lifetime params (not encoded in AST::PathNode as yet) diff --git a/src/hir/from_ast_expr.cpp b/src/hir/from_ast_expr.cpp index d9982da9..f5e9b31a 100644 --- a/src/hir/from_ast_expr.cpp +++ b/src/hir/from_ast_expr.cpp @@ -237,7 +237,7 @@ struct LowerHIR_ExprNode_Visitor:          // TODO: Should this be abstracted?          ::HIR::PathParams   params; -        for(const auto& param : v.m_method.args()) +        for(const auto& param : v.m_method.args().m_types)              params.m_types.push_back( LowerHIR_Type(param) );          m_rv.reset( new ::HIR::ExprNode_CallMethod( diff --git a/src/include/span.hpp b/src/include/span.hpp index e7bd2694..86d21514 100644 --- a/src/include/span.hpp +++ b/src/include/span.hpp @@ -67,5 +67,5 @@ Spanned<T> make_spanned(Span sp, T val) {  #define ERROR(span, code, msg)  do { ::Span(span).error(code, [&](::std::ostream& os) { os << msg; }); throw ::std::runtime_error("Error fell through" #code); } while(0)  #define WARNING(span, code, msg)  do { ::Span(span).warning(code, [&](::std::ostream& os) { os << msg; }); } while(0)  #define BUG(span, msg)  do { ::Span(span).bug([&](::std::ostream& os) { os << msg; }); throw ::std::runtime_error("Bug fell through"); } while(0) -#define TODO(span, msg)  do { ::Span(span).bug([&](::std::ostream& os) { os << "TODO: " << msg; }); throw ::std::runtime_error("Bug (todo) fell through"); } while(0) +#define TODO(span, msg)  do { const char* __TODO_func = __func__; ::Span(span).bug([&](::std::ostream& os) { os << "TODO: " << __TODO_func << " - " << msg; }); throw ::std::runtime_error("Bug (todo) fell through"); } while(0) diff --git a/src/main.cpp b/src/main.cpp index d8384184..ffe61468 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -25,9 +25,9 @@ int g_debug_indent_level = 0;  bool debug_enabled()
  {
 -    //return true;
 +    return true;
      //return g_cur_phase != "Parse";
 -    return g_cur_phase != "Parse" && g_cur_phase != "Expand";
 +    //return g_cur_phase != "Parse" && g_cur_phase != "Expand";
      //return g_cur_phase != "Parse" && g_cur_phase != "Expand" && g_cur_phase != "Resolve";
  }
  ::std::ostream& debug_output(int indent, const char* function)
 diff --git a/src/parse/common.hpp b/src/parse/common.hpp index c42889c3..bf1c7448 100644 --- a/src/parse/common.hpp +++ b/src/parse/common.hpp @@ -36,7 +36,7 @@ enum eParsePathGenericMode  extern AST::Path   Parse_Path(TokenStream& lex, eParsePathGenericMode generic_mode);    // Auto-determines
  extern AST::Path   Parse_Path(TokenStream& lex, bool is_abs, eParsePathGenericMode generic_mode);
  extern ::std::vector<AST::PathNode> Parse_PathNodes(TokenStream& lex, eParsePathGenericMode generic_mode);
 -extern ::std::vector<TypeRef>   Parse_Path_GenericList(TokenStream& lex);
 +extern AST::PathParams Parse_Path_GenericList(TokenStream& lex);
  extern AST::MetaItem   Parse_MetaItem(TokenStream& lex);
 diff --git a/src/parse/paths.cpp b/src/parse/paths.cpp index 153f51a0..2c97075e 100644 --- a/src/parse/paths.cpp +++ b/src/parse/paths.cpp @@ -12,7 +12,7 @@  AST::Path   Parse_Path(TokenStream& lex, eParsePathGenericMode generic_mode);  AST::Path   Parse_Path(TokenStream& lex, bool is_abs, eParsePathGenericMode generic_mode);  ::std::vector<AST::PathNode> Parse_PathNodes(TokenStream& lex, eParsePathGenericMode generic_mode); -::std::vector<TypeRef>  Parse_Path_GenericList(TokenStream& lex); +AST::PathParams Parse_Path_GenericList(TokenStream& lex);  AST::Path Parse_Path(TokenStream& lex, eParsePathGenericMode generic_mode)  { @@ -106,7 +106,7 @@ AST::Path Parse_Path(TokenStream& lex, bool is_abs, eParsePathGenericMode generi      tok = lex.getToken();      while(true)      { -        ::std::vector<TypeRef>  params; +        ::AST::PathParams   params;          CHECK_TOK(tok, TOK_IDENT);          ::std::string component = tok.str(); @@ -122,7 +122,7 @@ AST::Path Parse_Path(TokenStream& lex, bool is_abs, eParsePathGenericMode generi                  // Type-mode generics "::path::to::Type<A,B>"                  params = Parse_Path_GenericList(lex); -                tok = lex.getToken(); +                GET_TOK(tok, lex);              }              // HACK - 'Fn*(...) -> ...' notation              else if( tok.type() == TOK_PAREN_OPEN ) @@ -153,7 +153,11 @@ AST::Path Parse_Path(TokenStream& lex, bool is_abs, eParsePathGenericMode generi                  DEBUG("- Fn("<<args<<")->"<<ret_type<<"");                  // Encode into path, by converting Fn(A,B)->C into Fn<(A,B),Ret=C> -                params = ::std::vector<TypeRef> { TypeRef(TypeRef::TagTuple(), lex.end_span(ps), ::std::move(args)) }; +                params = ::AST::PathParams { +                    {}, +                    ::std::vector<TypeRef> { TypeRef(TypeRef::TagTuple(), lex.end_span(ps), ::std::move(args)) }, +                    { ::std::make_pair( (::std::string)"Output", mv$(ret_type) ) } +                    };                  // TODO: Use 'ret_type' as an associated type bound                  GET_TOK(tok, lex); @@ -175,32 +179,30 @@ AST::Path Parse_Path(TokenStream& lex, bool is_abs, eParsePathGenericMode generi              // Expr-mode generics "::path::to::function::<Type1,Type2>(arg1, arg2)"              params = Parse_Path_GenericList(lex); -            tok = lex.getToken(); -            if( tok.type() != TOK_DOUBLE_COLON ) { +            if( GET_TOK(tok, lex) != TOK_DOUBLE_COLON ) {                  ret.push_back( AST::PathNode(component, mv$(params)) ); +                // Break out of loop down to return                  break;              } +            // Match with CHECK_TOK at start of loop              GET_TOK(tok, lex);          }          ret.push_back( AST::PathNode(component, mv$(params)) );      }      PUTBACK(tok, lex); -    //if( path.is_trivial() ) { -    //    path = AST::Path(path[0].name()); -    //}      DEBUG("ret = " << ret);      return ret;  }  /// Parse a list of parameters within a path -::std::vector<TypeRef> Parse_Path_GenericList(TokenStream& lex) +::AST::PathParams Parse_Path_GenericList(TokenStream& lex)  {      TRACE_FUNCTION;      Token   tok;      ::std::vector<TypeRef>  types;      ::std::vector< ::std::string>   lifetimes; -    ::std::map< ::std::string, TypeRef> assoc_bounds; -    //::std::vector<unsigned int> int_args; +    ::std::vector< ::std::pair< ::std::string, TypeRef > > assoc_bounds; +          do {          if( LOOK_AHEAD(lex) == TOK_GT || LOOK_AHEAD(lex) == TOK_DOUBLE_GT || LOOK_AHEAD(lex) == TOK_GTE || LOOK_AHEAD(lex) == TOK_DOUBLE_GT_EQUAL ) {              GET_TOK(tok, lex); @@ -216,7 +218,7 @@ AST::Path Parse_Path(TokenStream& lex, bool is_abs, eParsePathGenericMode generi              {                  ::std::string name = tok.str();                  GET_CHECK_TOK(tok, lex, TOK_EQUAL); -                assoc_bounds.insert( ::std::make_pair( ::std::move(name), Parse_Type(lex) ) ); +                assoc_bounds.push_back( ::std::make_pair( mv$(name), Parse_Type(lex) ) );                  break;              }          default: @@ -240,8 +242,10 @@ AST::Path Parse_Path(TokenStream& lex, bool is_abs, eParsePathGenericMode generi          CHECK_TOK(tok, TOK_GT);      } -    // TODO: Actually use the lifetimes/assoc_bounds -     -    return types; +    return ::AST::PathParams { +        mv$( lifetimes ), +        mv$( types ), +        mv$( assoc_bounds ) +        };  } diff --git a/src/resolve/absolute.cpp b/src/resolve/absolute.cpp index 41eacd46..ca7b0dfc 100644 --- a/src/resolve/absolute.cpp +++ b/src/resolve/absolute.cpp @@ -414,14 +414,23 @@ void Resolve_Absolute_Mod(const ::AST::Crate& crate, ::AST::Module& mod);  void Resolve_Absolute_Mod( Context item_context, ::AST::Module& mod ); +void Resolve_Absolute_PathParams(/*const*/ Context& context, const Span& sp, ::AST::PathParams& args) +{ +    for(auto& arg : args.m_types) +    { +        Resolve_Absolute_Type(context, arg); +    } +    for(auto& arg : args.m_assoc) +    { +        Resolve_Absolute_Type(context, arg.second); +    } +} +  void Resolve_Absolute_PathNodes(/*const*/ Context& context, const Span& sp, ::std::vector< ::AST::PathNode >& nodes)  {      for(auto& node : nodes)      { -        for(auto& arg : node.args()) -        { -            Resolve_Absolute_Type(context, arg); -        } +        Resolve_Absolute_PathParams(context, sp, node.args());      }  } @@ -522,7 +531,7 @@ void Resolve_Absolute_Path_BindAbsolute(Context& context, const Span& sp, Contex          if( n.name()[0] == '#' ) { -            if( n.args().size() > 0 ) { +            if( ! n.args().is_empty() ) {                  ERROR(sp, E0000, "Type parameters were not expected here");              } @@ -553,8 +562,9 @@ void Resolve_Absolute_Path_BindAbsolute(Context& context, const Span& sp, Contex                  ),              (Trait,                  auto trait_path = ::AST::Path(name_ref.path); -                if( n.args().size() ) +                if( !n.args().is_empty() ) {                      trait_path.nodes().back().args() = mv$(n.args()); +                }                  auto new_path = ::AST::Path(::AST::Path::TagUfcs(), ::TypeRef(), mv$(trait_path));                  for( unsigned int j = i+1; j < path_abs.nodes.size(); j ++ )                      new_path.nodes().push_back( mv$(path_abs.nodes[j]) ); @@ -575,7 +585,7 @@ void Resolve_Absolute_Path_BindAbsolute(Context& context, const Span& sp, Contex                                  ERROR(sp, E0000, "Unexpected enum in path " << path);                              }                              // NOTE: Type parameters for enums go after the _variant_ -                            if( n.args().size() ) { +                            if( ! n.args().is_empty() ) {                                  ERROR(sp, E0000, "Type parameters were not expected here (enum params go on the variant)");                              } @@ -585,8 +595,9 @@ void Resolve_Absolute_Path_BindAbsolute(Context& context, const Span& sp, Contex                      }                      auto type_path = ::AST::Path(name_ref.path); -                    if( n.args().size() ) +                    if( !n.args().is_empty() ) {                          type_path.nodes().back().args() = mv$(n.args()); +                    }                      auto new_path = ::AST::Path(::AST::Path::TagUfcs(), ::TypeRef(sp, mv$(type_path)), ::AST::Path());                      for( unsigned int j = i+1; j < path_abs.nodes.size(); j ++ )                          new_path.nodes().push_back( mv$(path_abs.nodes[j]) ); @@ -597,8 +608,9 @@ void Resolve_Absolute_Path_BindAbsolute(Context& context, const Span& sp, Contex                  ),              (Struct,                  auto type_path = ::AST::Path(name_ref.path); -                if( n.args().size() ) +                if( ! n.args().is_empty() ) {                      type_path.nodes().back().args() = mv$(n.args()); +                }                  auto new_path = ::AST::Path(::AST::Path::TagUfcs(), ::TypeRef(sp, mv$(type_path)), ::AST::Path());                  for( unsigned int j = i+1; j < path_abs.nodes.size(); j ++ )                      new_path.nodes().push_back( mv$(path_abs.nodes[j]) ); @@ -627,6 +639,7 @@ void Resolve_Absolute_Path_BindAbsolute(Context& context, const Span& sp, Contex      // Replaces the path with the one returned by `lookup_in_mod`, ensuring that `use` aliases are eliminated      DEBUG("Replace " << path << " with " << tmp); +    tmp.nodes().back().args() = mv$(path.nodes().back().args());      path = mv$(tmp);  } @@ -664,10 +677,10 @@ void Resolve_Absolute_Path(/*const*/ Context& context, const Span& sp, Context::                  if( p.m_class.is_Local() ) {                      p = ::AST::Path( ::AST::Path::TagUfcs(), TypeRef(sp, mv$(p)) );                  } -                if( e.nodes[0].args().size() > 0 ) +                if( ! e.nodes[0].args().is_empty() )                  {                      assert( p.nodes().size() > 0 ); -                    assert( p.nodes().back().args().size() == 0 ); +                    assert( p.nodes().back().args().is_empty() );                      p.nodes().back().args() = mv$( e.nodes[0].args() );                  }                  for( unsigned int i = 1; i < e.nodes.size(); i ++ ) @@ -681,6 +694,10 @@ void Resolve_Absolute_Path(/*const*/ Context& context, const Span& sp, Context::              // Look up value              auto p = context.lookup(sp, e.nodes[0].name(), mode);              DEBUG("Found path " << p << " for " << path); +            if( p.is_absolute() ) { +                assert( !p.nodes().empty() ); +                p.nodes().back().args() = mv$(e.nodes.back().args()); +            }              path = mv$(p);          } @@ -730,6 +747,7 @@ void Resolve_Absolute_Path(/*const*/ Context& context, const Span& sp, Context::          )      ) +    DEBUG("path = " << path);      // TODO: Should this be deferred until the HIR?      // - Doing it here so the HIR lowering has a bit more information      // - Also handles splitting "absolute" paths into UFCS @@ -934,8 +952,7 @@ void Resolve_Absolute_Expr(Context& context,  ::AST::ExprNode& node)          }          void visit(AST::ExprNode_CallMethod& node) override {              DEBUG("ExprNode_CallMethod"); -            for(auto& param : node.m_method.args()) -                Resolve_Absolute_Type(this->context, param); +            Resolve_Absolute_PathParams(this->context, Span(node.get_pos()),  node.m_method.args());              AST::NodeVisitorDef::visit(node);          }          void visit(AST::ExprNode_NamedValue& node) override { | 
