diff options
author | John Hodge <tpg@mutabah.net> | 2016-05-29 08:50:39 +0800 |
---|---|---|
committer | John Hodge <tpg@mutabah.net> | 2016-05-29 08:50:39 +0800 |
commit | a8d2de3db9d9f92013d0ac6e52319b55590efea4 (patch) | |
tree | 1f85c37a21df5379518f2567a34eb3f174cb790f | |
parent | 727e254fe58274741036ca31f4c3eae2f3e1695a (diff) | |
download | mrust-a8d2de3db9d9f92013d0ac6e52319b55590efea4.tar.gz |
AST - Remove dead code, add lifetime params, fix param clobber
-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 { |