diff options
-rw-r--r-- | src/ast/ast.cpp | 30 | ||||
-rw-r--r-- | src/ast/attrs.hpp | 21 | ||||
-rw-r--r-- | src/ast/dump.cpp | 8 | ||||
-rw-r--r-- | src/ast/generics.hpp | 74 | ||||
-rw-r--r-- | src/ast/path.hpp | 5 | ||||
-rw-r--r-- | src/ast/types.cpp | 33 | ||||
-rw-r--r-- | src/ast/types.hpp | 77 | ||||
-rw-r--r-- | src/expand/derive.cpp | 25 | ||||
-rw-r--r-- | src/expand/mod.cpp | 8 | ||||
-rw-r--r-- | src/expand/proc_macro.cpp | 48 | ||||
-rw-r--r-- | src/hir/from_ast.cpp | 57 | ||||
-rw-r--r-- | src/parse/common.hpp | 2 | ||||
-rw-r--r-- | src/parse/paths.cpp | 4 | ||||
-rw-r--r-- | src/parse/root.cpp | 52 | ||||
-rw-r--r-- | src/parse/tokenstream.cpp | 4 | ||||
-rw-r--r-- | src/parse/types.cpp | 77 | ||||
-rw-r--r-- | src/resolve/absolute.cpp | 16 |
17 files changed, 376 insertions, 165 deletions
diff --git a/src/ast/ast.cpp b/src/ast/ast.cpp index 641bd633..1a19a10f 100644 --- a/src/ast/ast.cpp +++ b/src/ast/ast.cpp @@ -379,10 +379,31 @@ Item Item::clone() const //os << ")"; return os; } +::std::ostream& operator<<(::std::ostream& os, const LifetimeParam& p) +{ + os << "'" << p.m_name; + return os; +} + +::std::ostream& operator<<(::std::ostream& os, const HigherRankedBounds& x) +{ + if( x.m_lifetimes.empty() ) { + return os; + } + os << "for<"; + for(const auto& l : x.m_lifetimes) + os << "'" << l << ","; + os << "> "; + return os; +} + ::std::ostream& operator<<(::std::ostream& os, const GenericBound& x) { TU_MATCH(GenericBound, (x), (ent), + (None, + os << "/*-*/"; + ), (Lifetime, os << "'" << ent.test << ": '" << ent.bound; ), @@ -390,14 +411,7 @@ Item Item::clone() const os << ent.type << ": '" << ent.bound; ), (IsTrait, - if( ! ent.hrls.empty() ) - { - os << "for<"; - for(const auto& l : ent.hrls) - os << "'" << l; - os << ">"; - } - os << ent.type << ": " << ent.trait; + os << ent.outer_hrbs << ent.type << ": " << ent.inner_hrbs << ent.trait; ), (MaybeTrait, os << ent.type << ": ?" << ent.trait; diff --git a/src/ast/attrs.hpp b/src/ast/attrs.hpp index 4afbdbc1..1926e96a 100644 --- a/src/ast/attrs.hpp +++ b/src/ast/attrs.hpp @@ -30,8 +30,8 @@ public: // Move present AttributeList(AttributeList&&) = default; AttributeList& operator=(AttributeList&&) = default; - // No copy - AttributeList(const AttributeList&) = delete; + // No copy assign, but explicit copy + explicit AttributeList(const AttributeList&) = default; AttributeList& operator=(const AttributeList&) = delete; // Explicit clone AttributeList clone() const; @@ -97,7 +97,22 @@ public: { } - Attribute(const Attribute& ) = delete; + explicit Attribute(const Attribute& x): + m_span(x.m_span), + m_name(x.m_name), + m_is_used(x.m_is_used) + { + TU_MATCHA( (x.m_data), (e), + (None, + ), + (String, + m_data = AttributeData::make_String({ e.val }); + ), + (List, + m_data = AttributeData::make_List({ ::std::vector<Attribute>(e.sub_items) }); + ) + ) + } Attribute& operator=(const Attribute&& ) = delete; Attribute(Attribute&& ) = default; Attribute& operator=(Attribute&& ) = default; diff --git a/src/ast/dump.cpp b/src/ast/dump.cpp index b6336a02..73b332c0 100644 --- a/src/ast/dump.cpp +++ b/src/ast/dump.cpp @@ -829,6 +829,9 @@ void RustPrinter::print_bounds(const AST::GenericParams& params) m_os << indent(); TU_MATCH(AST::GenericBound, (b), (ent), + (None, + m_os << "/*-*/"; + ), (Lifetime, m_os << "'" << ent.test << ": '" << ent.bound; ), @@ -836,10 +839,7 @@ void RustPrinter::print_bounds(const AST::GenericParams& params) m_os << ent.type << ": '" << ent.bound; ), (IsTrait, - if( ent.hrls.size() > 0 ) { - m_os << "for<'" << ::join(", '", ent.hrls) << "> "; - } - m_os << ent.type << ": " << ent.trait; + m_os << ent.outer_hrbs << ent.type << ": " << ent.inner_hrbs << ent.trait; ), (MaybeTrait, m_os << ent.type << ": ?" << ent.trait; diff --git a/src/ast/generics.hpp b/src/ast/generics.hpp index bc14202e..c222044c 100644 --- a/src/ast/generics.hpp +++ b/src/ast/generics.hpp @@ -14,49 +14,86 @@ namespace AST { class TypeParam { + ::AST::AttributeList m_attrs; + Span m_span; + // TODO: use an Ident? ::std::string m_name; ::TypeRef m_default; public: TypeParam(TypeParam&& x) = default; TypeParam& operator=(TypeParam&& x) = default; - TypeParam(const TypeParam& x): - m_name(x.m_name), - m_default(x.m_default.clone()) - {} - //TypeParam(): m_name("") {} - TypeParam(::std::string name): + explicit TypeParam(const TypeParam& x): + m_attrs( x.m_attrs ), + m_span( x.m_span ), + m_name( x.m_name ), + m_default( x.m_default.clone() ) + { + } + + TypeParam(Span sp, ::AST::AttributeList attrs, ::std::string name): + m_attrs( ::std::move(attrs) ), + m_span( ::std::move(sp) ), m_name( ::std::move(name) ), - m_default( Span() ) + m_default(m_span) {} + void setDefault(TypeRef type) { assert(m_default.is_wildcard()); m_default = ::std::move(type); } - const ::std::string& name() const { return m_name; } + const ::AST::AttributeList& attrs() const { return m_attrs; } + const Span& span() const { return m_span; } + const ::std::string& name() const { return m_name; } const TypeRef& get_default() const { return m_default; } TypeRef& get_default() { return m_default; } friend ::std::ostream& operator<<(::std::ostream& os, const TypeParam& tp); }; +class LifetimeParam +{ + ::AST::AttributeList m_attrs; + Span m_span; + Ident m_name; +public: + LifetimeParam(Span sp, ::AST::AttributeList attrs, Ident name): + m_attrs( ::std::move(attrs) ), + m_span( ::std::move(sp) ), + m_name( ::std::move(name) ) + { + } + LifetimeParam(LifetimeParam&&) = default; + LifetimeParam& operator=(LifetimeParam&&) = default; + explicit LifetimeParam(const LifetimeParam&) = default; + + const ::AST::AttributeList& attrs() const { return m_attrs; } + const Span& span() const { return m_span; } + const Ident& name() const { return m_name; } + + friend ::std::ostream& operator<<(::std::ostream& os, const LifetimeParam& p); +}; + +// HigherRankedBounds is defined in `types.hpp` -TAGGED_UNION_EX( GenericBound, (), Lifetime, +TAGGED_UNION_EX( GenericBound, (), None, ( + (None, struct{}), // Lifetime bound: 'test must be valid for 'bound (Lifetime, struct { - ::std::string test; - ::std::string bound; + LifetimeRef test; + LifetimeRef bound; }), // Type lifetime bound (TypeLifetime, struct { TypeRef type; - ::std::string bound; + LifetimeRef bound; }), // Standard trait bound: "Type: [for<'a>] Trait" (IsTrait, struct { + HigherRankedBounds outer_hrbs; TypeRef type; - ::std::vector< ::std::string> hrls; // Higher-ranked lifetimes + HigherRankedBounds inner_hrbs; AST::Path trait; }), // Removed trait bound: "Type: ?Trait" @@ -84,9 +121,10 @@ TAGGED_UNION_EX( GenericBound, (), Lifetime, GenericBound clone() const { TU_MATCH(GenericBound, ( (*this) ), (ent), + (None, return make_None({}); ), (Lifetime, return make_Lifetime({ent.test, ent.bound}); ), (TypeLifetime, return make_TypeLifetime({ent.type.clone(), ent.bound}); ), - (IsTrait, return make_IsTrait({ent.type.clone(), ent.hrls, ent.trait}); ), + (IsTrait, return make_IsTrait({ent.outer_hrbs, ent.type.clone(), ent.inner_hrbs, ent.trait}); ), (MaybeTrait, return make_MaybeTrait({ent.type.clone(), ent.trait}); ), (NotTrait, return make_NotTrait({ent.type.clone(), ent.trait}); ), (Equality, return make_Equality({ent.type.clone(), ent.replacement.clone()}); ) @@ -101,7 +139,7 @@ TAGGED_UNION_EX( GenericBound, (), Lifetime, class GenericParams { ::std::vector<TypeParam> m_type_params; - ::std::vector< ::std::string > m_lifetime_params; + ::std::vector<LifetimeParam> m_lifetime_params; ::std::vector<GenericBound> m_bounds; public: GenericParams() {} @@ -112,7 +150,7 @@ public: GenericParams clone() const { GenericParams rv; rv.m_type_params = ::std::vector<TypeParam>( m_type_params ); // Copy-constructable - rv.m_lifetime_params = m_lifetime_params; + rv.m_lifetime_params = ::std::vector<LifetimeParam>(m_lifetime_params); rv.m_bounds.reserve( m_bounds.size() ); for(auto& e: m_bounds) rv.m_bounds.push_back( e.clone() ); @@ -121,12 +159,12 @@ public: const ::std::vector<TypeParam>& ty_params() const { return m_type_params; } ::std::vector<TypeParam>& ty_params() { return m_type_params; } - const ::std::vector< ::std::string>& lft_params() const { return m_lifetime_params; } + const ::std::vector<LifetimeParam>& lft_params() const { return m_lifetime_params; } const ::std::vector<GenericBound>& bounds() const { return m_bounds; } ::std::vector<GenericBound>& bounds() { return m_bounds; } void add_ty_param(TypeParam param) { m_type_params.push_back( ::std::move(param) ); } - void add_lft_param(::std::string name) { m_lifetime_params.push_back( ::std::move(name) ); } + void add_lft_param(LifetimeParam lft) { m_lifetime_params.push_back( ::std::move(lft) ); } void add_bound(GenericBound bound) { m_bounds.push_back( ::std::move(bound) ); } diff --git a/src/ast/path.hpp b/src/ast/path.hpp index 2126e3b2..0470084b 100644 --- a/src/ast/path.hpp +++ b/src/ast/path.hpp @@ -28,6 +28,7 @@ class Static; namespace AST { +class LifetimeRef; class GenericParams; class Crate; class Module; @@ -109,14 +110,14 @@ extern ::std::ostream& operator<<(::std::ostream& os, const PathBinding& x); struct PathParams { - ::std::vector< ::std::string > m_lifetimes; + ::std::vector< LifetimeRef > m_lifetimes; ::std::vector< TypeRef > m_types; ::std::vector< ::std::pair< ::std::string, TypeRef> > m_assoc; PathParams(PathParams&& x) = default; PathParams(const PathParams& x); PathParams() {} - PathParams(::std::vector<::std::string> lfts, ::std::vector<TypeRef> tys, ::std::vector<::std::pair<::std::string,TypeRef>> a): + PathParams(::std::vector<LifetimeRef> lfts, ::std::vector<TypeRef> tys, ::std::vector<::std::pair<::std::string,TypeRef>> a): m_lifetimes(mv$(lfts)), m_types(mv$(tys)), m_assoc(mv$(a)) diff --git a/src/ast/types.cpp b/src/ast/types.cpp index af99f3d7..8065a3ba 100644 --- a/src/ast/types.cpp +++ b/src/ast/types.cpp @@ -141,6 +141,15 @@ TypeRef TypeRef::clone() const throw ""; } +Ordering Type_TraitPath::ord(const Type_TraitPath& x) const +{ + Ordering rv; + + rv = ::ord( this->path, x.path ); + if(rv != OrdEqual) return rv; + + return rv; +} Ordering TypeRef::ord(const TypeRef& x) const { Ordering rv; @@ -277,7 +286,8 @@ void TypeRef::print(::std::ostream& os, bool is_debug/*=false*/) const for( const auto& it : ent.traits ) { if( &it != &ent.traits.front() ) os << "+"; - it.print_pretty(os, true, is_debug); + os << it.hrbs; + it.path.print_pretty(os, true, is_debug); } os << ")"; ) @@ -286,7 +296,8 @@ void TypeRef::print(::std::ostream& os, bool is_debug/*=false*/) const for( const auto& it : ent.traits ) { if( &it != &ent.traits.front() ) os << "+"; - it.print_pretty(os, true, is_debug); + os << it.hrbs; + it.path.print_pretty(os, true, is_debug); } os << ""; ) @@ -303,3 +314,21 @@ void TypeRef::print(::std::ostream& os, bool is_debug/*=false*/) const return os; } +namespace AST { + ::std::ostream& operator<<(::std::ostream& os, const LifetimeRef& x) { + if( x.m_binding == LifetimeRef::BINDING_STATIC ) { + os << "'static"; + } + else if( x.m_binding == LifetimeRef::BINDING_INFER ) { + os << "'_"; + } + else { + os << "'" << x.m_name; + if( x.m_binding != LifetimeRef::BINDING_UNBOUND ) { + os << "/*" << x.m_binding << "*/"; + } + } + return os; + } +} + diff --git a/src/ast/types.hpp b/src/ast/types.hpp index 820bcf27..49cae373 100644 --- a/src/ast/types.hpp +++ b/src/ast/types.hpp @@ -13,6 +13,63 @@ namespace AST { class ExprNode; class Expr; +class LifetimeParam; +} + +namespace AST { + + // Defined here for dependency reasons + class HigherRankedBounds + { + public: + ::std::vector<LifetimeParam> m_lifetimes; + //::std::vector<TypeParam> m_types; + //::std::vector<GenericBound> m_bounds; + + bool empty() const { + return m_lifetimes.empty(); + } + + friend ::std::ostream& operator<<(::std::ostream& os, const HigherRankedBounds& x); + }; + + class LifetimeRef + { + static const uint16_t BINDING_STATIC = 0xFFFF; + static const uint16_t BINDING_UNBOUND = 0xFFFE; + static const uint16_t BINDING_INFER = 0xFFFD; + + Ident m_name; + uint16_t m_binding; + + LifetimeRef(Ident name, uint32_t binding): + m_name( ::std::move(name) ), + m_binding( binding ) + { + } + public: + LifetimeRef(): + LifetimeRef("", BINDING_INFER) + { + } + LifetimeRef(Ident name): + LifetimeRef(::std::move(name), BINDING_UNBOUND) + { + } + static LifetimeRef new_static() { + return LifetimeRef("static", BINDING_STATIC); + } + + void set_binding(uint16_t b) { assert(m_binding == BINDING_UNBOUND); m_binding = b; } + + const Ident& name() const { return m_name; } + Ordering ord(const LifetimeRef& x) const { return ::ord(m_name.name, x.m_name.name); } + bool operator==(const LifetimeRef& x) const { return ord(x) == OrdEqual; } + bool operator!=(const LifetimeRef& x) const { return ord(x) != OrdEqual; } + bool operator<(const LifetimeRef& x) const { return ord(x) == OrdLess; }; + + friend ::std::ostream& operator<<(::std::ostream& os, const LifetimeRef& x); + }; } class PrettyPrintType @@ -57,6 +114,14 @@ struct Type_Function Ordering ord(const Type_Function& x) const; }; +struct Type_TraitPath +{ + AST::HigherRankedBounds hrbs; + AST::Path path; + + Ordering ord(const Type_TraitPath& x) const; +}; + TAGGED_UNION(TypeData, None, (None, struct { }), (Any, struct { }), @@ -94,12 +159,12 @@ TAGGED_UNION(TypeData, None, AST::Path path; }), (TraitObject, struct { - ::std::vector<::std::string> hrls; - ::std::vector<AST::Path> traits; + ::std::vector<Type_TraitPath> traits; + ::std::vector<AST::LifetimeRef> lifetimes; }), (ErasedType, struct { - ::std::vector<::std::string> hrls; - ::std::vector<AST::Path> traits; + ::std::vector<Type_TraitPath> traits; + ::std::vector<AST::LifetimeRef> lifetimes; }) ); @@ -215,9 +280,9 @@ public: TypeRef(TagPath(), mv$(sp), mv$(path)) {} - TypeRef( Span sp, ::std::vector<::std::string> hrls, ::std::vector<AST::Path> traits ): + TypeRef( Span sp, ::std::vector<Type_TraitPath> traits, ::std::vector<AST::LifetimeRef> lifetimes ): m_span(mv$(sp)), - m_data(TypeData::make_TraitObject({ mv$(hrls), ::std::move(traits) })) + m_data(TypeData::make_TraitObject({ ::std::move(traits), mv$(lifetimes) })) {} diff --git a/src/expand/derive.cpp b/src/expand/derive.cpp index 077c4b70..0e28b6da 100644 --- a/src/expand/derive.cpp +++ b/src/expand/derive.cpp @@ -86,7 +86,7 @@ struct Deriver for(const auto& arg : params.ty_params()) { params.add_bound( ::AST::GenericBound::make_IsTrait({ - TypeRef(sp, arg.name(), i), {}, trait_path + {}, TypeRef(sp, arg.name(), i), {}, trait_path }) ); i ++; } @@ -96,7 +96,7 @@ struct Deriver for(auto& ty : additional_bounded_types) { params.add_bound( ::AST::GenericBound::make_IsTrait({ - mv$(ty), {}, trait_path + {}, mv$(ty), {}, trait_path }) ); } @@ -1563,11 +1563,10 @@ class Deriver_Hash: ::std::make_pair( AST::Pattern(AST::Pattern::TagBind(), "state"), TypeRef(TypeRef::TagReference(), sp, true, TypeRef(sp, "H", 0x100|0)) ) ) ); - fcn.params().add_ty_param( AST::TypeParam("H") ); + fcn.params().add_ty_param( AST::TypeParam(sp, {}, "H") ); fcn.params().add_bound( AST::GenericBound::make_IsTrait({ - TypeRef(sp, "H", 0x100|0), - {}, - this->get_trait_path_Hasher(core_name) + {}, TypeRef(sp, "H", 0x100|0), + {}, this->get_trait_path_Hasher(core_name) }) ); fcn.set_code( NEWNODE(Block, vec$(mv$(node))) ); @@ -1717,11 +1716,10 @@ class Deriver_RustcEncodable: ::std::make_pair( AST::Pattern(AST::Pattern::TagBind(), "s"), TypeRef(TypeRef::TagReference(), sp, true, TypeRef(sp, "S", 0x100|0)) ) ) ); - fcn.params().add_ty_param( AST::TypeParam("S") ); + fcn.params().add_ty_param( AST::TypeParam(sp, {}, "S") ); fcn.params().add_bound( AST::GenericBound::make_IsTrait({ - TypeRef(sp, "S", 0x100|0), - {}, - this->get_trait_path_Encoder() + {}, TypeRef(sp, "S", 0x100|0), + {}, this->get_trait_path_Encoder() }) ); fcn.set_code( NEWNODE(Block, vec$(mv$(node))) ); @@ -1951,11 +1949,10 @@ class Deriver_RustcDecodable: ::std::make_pair( AST::Pattern(AST::Pattern::TagBind(), "d"), TypeRef(TypeRef::TagReference(), sp, true, TypeRef(sp, "D", 0x100|0)) ) ) ); - fcn.params().add_ty_param( AST::TypeParam("D") ); + fcn.params().add_ty_param( AST::TypeParam(sp, {}, "D") ); fcn.params().add_bound( AST::GenericBound::make_IsTrait({ - TypeRef(sp, "D", 0x100|0), - {}, - this->get_trait_path_Decoder() + {}, TypeRef(sp, "D", 0x100|0), + {}, this->get_trait_path_Decoder() }) ); fcn.set_code( NEWNODE(Block, vec$(mv$(node))) ); diff --git a/src/expand/mod.cpp b/src/expand/mod.cpp index aa7655e3..4470b2bb 100644 --- a/src/expand/mod.cpp +++ b/src/expand/mod.cpp @@ -272,13 +272,15 @@ void Expand_Type(::AST::Crate& crate, LList<const AST::Module*> modstack, ::AST: (TraitObject, for(auto& p : e.traits) { - Expand_Path(crate, modstack, mod, p); + // TODO: p.hrbs? Not needed until types are in those + Expand_Path(crate, modstack, mod, p.path); } ), (ErasedType, for(auto& p : e.traits) { - Expand_Path(crate, modstack, mod, p); + // TODO: p.hrbs? + Expand_Path(crate, modstack, mod, p.path); } ) ) @@ -859,6 +861,8 @@ void Expand_GenericParams(::AST::Crate& crate, LList<const AST::Module*> modstac for(auto& bound : params.bounds()) { TU_MATCHA( (bound), (be), + (None, + ), (Lifetime, ), (TypeLifetime, diff --git a/src/expand/proc_macro.cpp b/src/expand/proc_macro.cpp index cdd13a42..28d9f613 100644 --- a/src/expand/proc_macro.cpp +++ b/src/expand/proc_macro.cpp @@ -345,45 +345,41 @@ namespace { ), (TraitObject, m_pmi.send_symbol("("); - if( te.hrls.size() > 0 ) - { - m_pmi.send_ident("for"); - m_pmi.send_symbol("<"); - for(const auto& v : te.hrls) - { - m_pmi.send_lifetime(v.c_str()); - m_pmi.send_symbol(","); - } - m_pmi.send_symbol(">"); - } for(const auto& t : te.traits) { - this->visit_path(t); + this->visit_hrbs(t.hrbs); + this->visit_path(t.path); m_pmi.send_symbol("+"); } + // TODO: Lifetimes m_pmi.send_symbol(")"); ), (ErasedType, m_pmi.send_ident("impl"); - if( te.hrls.size() > 0 ) - { - m_pmi.send_ident("for"); - m_pmi.send_symbol("<"); - for(const auto& v : te.hrls) - { - m_pmi.send_lifetime(v.c_str()); - m_pmi.send_symbol(","); - } - m_pmi.send_symbol(">"); - } for(const auto& t : te.traits) { - this->visit_path(t); + this->visit_hrbs(t.hrbs); + this->visit_path(t.path); m_pmi.send_symbol("+"); } + // TODO: Lifetimes ) ) } + void visit_hrbs(const AST::HigherRankedBounds& hrbs) + { + if( !hrbs.empty() ) + { + m_pmi.send_ident("for"); + m_pmi.send_symbol("<"); + for(const auto& v : hrbs.m_lifetimes) + { + m_pmi.send_lifetime(v.name().name.c_str()); + m_pmi.send_symbol(","); + } + m_pmi.send_symbol(">"); + } + } void visit_path(const AST::Path& path, bool is_expr=false) { @@ -445,7 +441,7 @@ namespace { m_pmi.send_symbol("<"); for(const auto& l : e.args().m_lifetimes) { - m_pmi.send_lifetime(l.c_str()); + m_pmi.send_lifetime(l.name().name.c_str()); m_pmi.send_symbol(","); } for(const auto& t : e.args().m_types) @@ -475,7 +471,7 @@ namespace { { if( !is_first ) m_pmi.send_symbol(","); - m_pmi.send_lifetime(p.c_str()); + m_pmi.send_lifetime(p.name().name.c_str()); is_first = false; } // Types diff --git a/src/hir/from_ast.cpp b/src/hir/from_ast.cpp index 1dbfdad2..6353a0ea 100644 --- a/src/hir/from_ast.cpp +++ b/src/hir/from_ast.cpp @@ -28,6 +28,11 @@ ::HIR::Crate* g_crate_ptr = nullptr; // -------------------------------------------------------------------- +::std::string LowerHIR_LifetimeRef(const ::AST::LifetimeRef& r) +{ + return r.name().name; +} + ::HIR::GenericParams LowerHIR_GenericParams(const ::AST::GenericParams& gp, bool* self_is_sized) { ::HIR::GenericParams rv; @@ -41,24 +46,26 @@ } if( gp.lft_params().size() > 0 ) { - for(const auto& lft_name : gp.lft_params()) - rv.m_lifetimes.push_back( lft_name ); + for(const auto& lft_def : gp.lft_params()) + rv.m_lifetimes.push_back( lft_def.name().name ); } if( gp.bounds().size() > 0 ) { for(const auto& bound : gp.bounds()) { TU_MATCH(::AST::GenericBound, (bound), (e), + (None, + ), (Lifetime, rv.m_bounds.push_back(::HIR::GenericBound::make_Lifetime({ - e.test, - e.bound + LowerHIR_LifetimeRef(e.test), + LowerHIR_LifetimeRef(e.bound) })); ), (TypeLifetime, rv.m_bounds.push_back(::HIR::GenericBound::make_TypeLifetime({ LowerHIR_Type(e.type), - e.bound + LowerHIR_LifetimeRef(e.bound) })); ), (IsTrait, @@ -66,8 +73,8 @@ // TODO: Check if this trait is `Sized` and ignore if it is - rv.m_bounds.push_back(::HIR::GenericBound::make_TraitBound({ mv$(type), LowerHIR_TraitPath(bound.span, e.trait) })); - rv.m_bounds.back().as_TraitBound().trait.m_hrls = e.hrls; + rv.m_bounds.push_back(::HIR::GenericBound::make_TraitBound({ /*LowerHIR_HigherRankedBounds(e.outer_hrbs),*/ mv$(type), LowerHIR_TraitPath(bound.span, e.trait) })); + //rv.m_bounds.back().as_TraitBound().trait.m_hrls = LowerHIR_HigherRankedBounds(e.inner_hrbs); ), (MaybeTrait, auto type = LowerHIR_Type(e.type); @@ -755,47 +762,59 @@ } ), (TraitObject, - //if( e.hrls.size() > 0 ) - // TODO(ty.span(), "TraitObjects with HRLS - " << ty); ::HIR::TypeRef::Data::Data_TraitObject v; // TODO: Lifetime for(const auto& t : e.traits) { - DEBUG("t = " << t); - const auto& tb = t.binding().as_Trait(); + DEBUG("t = " << t.path); + const auto& tb = t.path.binding().as_Trait(); assert( tb.trait_ || tb.hir ); - if( (tb.trait_ ? tb.trait_->is_marker() : tb.hir->m_is_marker) ) { + if( (tb.trait_ ? tb.trait_->is_marker() : tb.hir->m_is_marker) ) + { if( tb.hir ) { DEBUG(tb.hir->m_values.size()); } - v.m_markers.push_back( LowerHIR_GenericPath(ty.span(), t) ); + // TODO: If this has HRBs, what? + v.m_markers.push_back( LowerHIR_GenericPath(ty.span(), t.path) ); } else { // TraitPath -> GenericPath -> SimplePath if( v.m_trait.m_path.m_path.m_components.size() > 0 ) { ERROR(ty.span(), E0000, "Multiple data traits in trait object - " << ty); } - v.m_trait = LowerHIR_TraitPath(ty.span(), t); + // TODO: Handle HRBs + v.m_trait = LowerHIR_TraitPath(ty.span(), t.path); } } return ::HIR::TypeRef( ::HIR::TypeRef::Data::make_TraitObject( mv$(v) ) ); ), (ErasedType, - //if( e.hrls.size() > 0 ) - // TODO(ty.span(), "ErasedType with HRLS - " << ty); ASSERT_BUG(ty.span(), e.traits.size() > 0, "ErasedType with no traits"); ::std::vector< ::HIR::TraitPath> traits; for(const auto& t : e.traits) { - DEBUG("t = " << t); - traits.push_back( LowerHIR_TraitPath(ty.span(), t) ); + DEBUG("t = " << t.path); + // TODO: Pass the HRBs down + traits.push_back( LowerHIR_TraitPath(ty.span(), t.path) ); + } + ::HIR::LifetimeRef lft; + if( e.lifetimes.size() == 0 ) + { + } + else if( e.lifetimes.size() == 1 ) + { + // TODO: Convert the lifetime reference + } + else + { + TODO(ty.span(), "Handle multiple lifetime parameters - " << ty); } // Leave `m_origin` until the bind pass return ::HIR::TypeRef( ::HIR::TypeRef::Data::make_ErasedType(::HIR::TypeRef::Data::Data_ErasedType { ::HIR::Path(::HIR::SimplePath()), 0, mv$(traits), - ::HIR::LifetimeRef() // TODO: Lifetime ref + lft } ) ); ), (Function, diff --git a/src/parse/common.hpp b/src/parse/common.hpp index 1ca86128..49499c86 100644 --- a/src/parse/common.hpp +++ b/src/parse/common.hpp @@ -40,7 +40,7 @@ extern ::std::vector<AST::PathNode> Parse_PathNodes(TokenStream& lex, eParsePath extern AST::PathParams Parse_Path_GenericList(TokenStream& lex); -extern ::std::vector< ::std::string> Parse_HRB(TokenStream& lex); +extern AST::HigherRankedBounds Parse_HRB(TokenStream& lex); extern AST::AttributeList Parse_ItemAttrs(TokenStream& lex); extern void Parse_ParentAttrs(TokenStream& lex, AST::AttributeList& out); extern AST::Attribute Parse_MetaItem(TokenStream& lex); diff --git a/src/parse/paths.cpp b/src/parse/paths.cpp index 59b6b939..d103840e 100644 --- a/src/parse/paths.cpp +++ b/src/parse/paths.cpp @@ -203,7 +203,7 @@ AST::Path Parse_Path(TokenStream& lex, bool is_abs, eParsePathGenericMode generi Token tok; ::std::vector<TypeRef> types; - ::std::vector< ::std::string> lifetimes; + ::std::vector<AST::LifetimeRef> lifetimes; ::std::vector< ::std::pair< ::std::string, TypeRef > > assoc_bounds; do { @@ -214,7 +214,7 @@ AST::Path Parse_Path(TokenStream& lex, bool is_abs, eParsePathGenericMode generi switch(GET_TOK(tok, lex)) { case TOK_LIFETIME: - lifetimes.push_back( tok.str() ); + lifetimes.push_back(AST::LifetimeRef(/*lex.point_span(),*/ lex.get_ident(mv$(tok)) )); break; case TOK_IDENT: if( LOOK_AHEAD(lex) == TOK_EQUAL ) diff --git a/src/parse/root.cpp b/src/parse/root.cpp index 35da3a76..2b027bf9 100644 --- a/src/parse/root.cpp +++ b/src/parse/root.cpp @@ -119,12 +119,12 @@ bool Parse_Publicity(TokenStream& lex, bool allow_restricted=true) } } -::std::vector< ::std::string> Parse_HRB(TokenStream& lex) +::AST::HigherRankedBounds Parse_HRB(TokenStream& lex) { TRACE_FUNCTION; Token tok; - ::std::vector< ::std::string> lifetimes; + ::AST::HigherRankedBounds rv; GET_CHECK_TOK(tok, lex, TOK_LT); do { auto attrs = Parse_ItemAttrs(lex); @@ -133,17 +133,25 @@ bool Parse_Publicity(TokenStream& lex, bool allow_restricted=true) switch(GET_TOK(tok, lex)) { case TOK_LIFETIME: - lifetimes.push_back(tok.str()); + rv.m_lifetimes.push_back(::AST::LifetimeParam(lex.point_span(), ::std::move(attrs), Ident(lex.getHygiene(), tok.str()))); break; default: throw ParseError::Unexpected(lex, tok, Token(TOK_LIFETIME)); } } while( GET_TOK(tok, lex) == TOK_COMMA ); CHECK_TOK(tok, TOK_GT); - return lifetimes; + return rv; +} + +namespace { + AST::LifetimeRef get_LifetimeRef(TokenStream& lex, Token tok) + { + CHECK_TOK(tok, TOK_LIFETIME); + return AST::LifetimeRef(/*lex.point_span(), */Ident(lex.getHygiene(), mv$(tok.str()))); + } } /// Parse type parameters in a definition -void Parse_TypeBound(TokenStream& lex, AST::GenericParams& ret, TypeRef checked_type, ::std::vector< ::std::string> lifetimes = {}) +void Parse_TypeBound(TokenStream& lex, AST::GenericParams& ret, TypeRef checked_type, AST::HigherRankedBounds outer_hrbs = {}) { TRACE_FUNCTION; Token tok; @@ -156,10 +164,9 @@ void Parse_TypeBound(TokenStream& lex, AST::GenericParams& ret, TypeRef checked_ // return; //} - ::std::vector< ::std::string> hrls; if(GET_TOK(tok, lex) == TOK_LIFETIME) { ret.add_bound(AST::GenericBound::make_TypeLifetime( { - checked_type.clone(), tok.str() + checked_type.clone(), get_LifetimeRef(lex, mv$(tok)) } )); } else if( tok.type() == TOK_QMARK ) { @@ -168,17 +175,17 @@ void Parse_TypeBound(TokenStream& lex, AST::GenericParams& ret, TypeRef checked_ } )); } else { + ::AST::HigherRankedBounds inner_hrls; if( tok.type() == TOK_RWORD_FOR ) { - hrls = Parse_HRB(lex); + inner_hrls = Parse_HRB(lex); } else { PUTBACK(tok, lex); } - (void)hrls; // TODO: HRLs ret.add_bound( AST::GenericBound::make_IsTrait({ - checked_type.clone(), mv$(lifetimes), Parse_Path(lex, PATH_GENERIC_TYPE) + mv$(outer_hrbs), checked_type.clone(), mv$(inner_hrls), Parse_Path(lex, PATH_GENERIC_TYPE) }) ); } } while( GET_TOK(tok, lex) == TOK_PLUS ); @@ -199,14 +206,12 @@ AST::GenericParams Parse_GenericParams(TokenStream& lex) PUTBACK(tok, lex); auto attrs = Parse_ItemAttrs(lex); - (void)attrs; // TODO: Attributes on generic params GET_TOK(tok, lex); if( tok.type() == TOK_IDENT ) { - // TODO: Hygine ::std::string param_name = mv$(tok.str()); - ret.add_ty_param( AST::TypeParam( param_name ) ); + ret.add_ty_param( AST::TypeParam( lex.point_span(), ::std::move(attrs), param_name ) ); auto param_ty = TypeRef(lex.point_span(), param_name); if( GET_TOK(tok, lex) == TOK_COLON ) @@ -223,14 +228,14 @@ AST::GenericParams Parse_GenericParams(TokenStream& lex) } else if( tok.type() == TOK_LIFETIME ) { - // TODO: Should lifetimes have hygine? - ::std::string param_name = tok.str(); - ret.add_lft_param( param_name ); + auto param_name = tok.str(); + auto ref = get_LifetimeRef(lex, mv$(tok)); + ret.add_lft_param(::AST::LifetimeParam(lex.point_span(), ::std::move(attrs), Ident(lex.getHygiene(), param_name) )); if( GET_TOK(tok, lex) == TOK_COLON ) { do { GET_CHECK_TOK(tok, lex, TOK_LIFETIME); - ret.add_bound(AST::GenericBound::make_Lifetime( {param_name, tok.str()} )); + ret.add_bound(AST::GenericBound::make_Lifetime({ AST::LifetimeRef(ref), get_LifetimeRef(lex, mv$(tok)) })); } while( GET_TOK(tok, lex) == TOK_PLUS ); } } @@ -258,11 +263,11 @@ void Parse_WhereClause(TokenStream& lex, AST::GenericParams& params) if( tok.type() == TOK_LIFETIME ) { - auto lhs = mv$(tok.str()); + auto lhs = get_LifetimeRef(lex, mv$(tok)); GET_CHECK_TOK(tok, lex, TOK_COLON); do { GET_CHECK_TOK(tok, lex, TOK_LIFETIME); - auto rhs = mv$(tok.str()); + auto rhs = get_LifetimeRef(lex, mv$(tok)); params.add_bound( AST::GenericBound::make_Lifetime({lhs, rhs}) ); } while( GET_TOK(tok, lex) == TOK_PLUS ); PUTBACK(tok, lex); @@ -270,11 +275,11 @@ void Parse_WhereClause(TokenStream& lex, AST::GenericParams& params) // Higher-ranked types/lifetimes else if( tok.type() == TOK_RWORD_FOR ) { - ::std::vector< ::std::string> lifetimes = Parse_HRB(lex); + auto hrbs = Parse_HRB(lex); TypeRef type = Parse_Type(lex); GET_CHECK_TOK(tok, lex, TOK_COLON); - Parse_TypeBound(lex,params, mv$(type), mv$(lifetimes)); + Parse_TypeBound(lex,params, mv$(type), mv$(hrbs)); } else { @@ -355,9 +360,9 @@ AST::Function Parse_FunctionDef(TokenStream& lex, ::std::string abi, bool allow_ if( lex.lookahead(ofs) == TOK_RWORD_SELF || (lex.lookahead(ofs) == TOK_RWORD_MUT && lex.lookahead(ofs+1) == TOK_RWORD_SELF) ) { auto ps = lex.start_span(); - ::std::string lifetime; + AST::LifetimeRef lifetime; if( GET_TOK(tok, lex) == TOK_LIFETIME ) { - lifetime = tok.str(); + lifetime = get_LifetimeRef(lex, mv$(tok)); GET_TOK(tok, lex); } auto ty_sp = lex.end_span(ps); @@ -622,6 +627,7 @@ AST::Trait Parse_TraitDef(TokenStream& lex, const AST::AttributeList& meta_items do { if( GET_TOK(tok, lex) == TOK_LIFETIME ) { // TODO: Need a better way of indiciating 'static than just an invalid path + // TODO: Ensure that it's 'static supertraits.push_back( make_spanned( Span(tok.get_pos()), AST::Path() ) ); } else if( tok.type() == TOK_BRACE_OPEN ) { diff --git a/src/parse/tokenstream.cpp b/src/parse/tokenstream.cpp index 625f12db..611df2ff 100644 --- a/src/parse/tokenstream.cpp +++ b/src/parse/tokenstream.cpp @@ -140,6 +140,10 @@ Ident TokenStream::get_ident(Token tok) const if(tok.type() == TOK_IDENT) { return Ident(getHygiene(), tok.str()); } + else if(tok.type() == TOK_LIFETIME) { + // TODO: Maybe only when it's explicitly asked for? + return Ident(getHygiene(), tok.str()); + } else if( tok.type() == TOK_INTERPOLATED_IDENT ) { TODO(getPosition(), "get_ident from TOK_INTERPOLATED_IDENT"); } diff --git a/src/parse/types.cpp b/src/parse/types.cpp index 26785cf7..b0b43426 100644 --- a/src/parse/types.cpp +++ b/src/parse/types.cpp @@ -13,8 +13,8 @@ // === PROTOTYPES === //TypeRef Parse_Type(TokenStream& lex, bool allow_trait_list); TypeRef Parse_Type_Int(TokenStream& lex, bool allow_trait_list); -TypeRef Parse_Type_Fn(TokenStream& lex, ::std::vector<::std::string> hrls = {}); -TypeRef Parse_Type_Path(TokenStream& lex, ::std::vector<::std::string> hrls, bool allow_trait_list); +TypeRef Parse_Type_Fn(TokenStream& lex, AST::HigherRankedBounds hrbs = {}); +TypeRef Parse_Type_Path(TokenStream& lex, AST::HigherRankedBounds hrbs, bool allow_trait_list); TypeRef Parse_Type_ErasedType(TokenStream& lex, bool allow_trait_list); // === CODE === @@ -196,7 +196,7 @@ TypeRef Parse_Type_Int(TokenStream& lex, bool allow_trait_list) throw ParseError::BugCheck("Reached end of Parse_Type"); } -TypeRef Parse_Type_Fn(TokenStream& lex, ::std::vector<::std::string> hrls) +TypeRef Parse_Type_Fn(TokenStream& lex, ::AST::HigherRankedBounds hrbs) { auto ps = lex.start_span(); // TODO: HRLs @@ -262,36 +262,52 @@ TypeRef Parse_Type_Fn(TokenStream& lex, ::std::vector<::std::string> hrls) return TypeRef(TypeRef::TagFunction(), lex.end_span(ps), is_unsafe, mv$(abi), mv$(args), is_variadic, mv$(ret_type)); } -TypeRef Parse_Type_Path(TokenStream& lex, ::std::vector<::std::string> hrls, bool allow_trait_list) +TypeRef Parse_Type_Path(TokenStream& lex, ::AST::HigherRankedBounds hrbs, bool allow_trait_list) { Token tok; auto ps = lex.start_span(); - if( ! allow_trait_list ) + if( hrbs.empty() && !allow_trait_list ) { return TypeRef(TypeRef::TagPath(), lex.end_span(ps), Parse_Path(lex, PATH_GENERIC_TYPE)); } else { - ::std::vector<AST::Path> traits; - ::std::vector< ::std::string> lifetimes; - do { - if( LOOK_AHEAD(lex) == TOK_LIFETIME ) { - GET_TOK(tok, lex); - lifetimes.push_back( tok.str() ); + ::std::vector<Type_TraitPath> traits; + ::std::vector<AST::LifetimeRef> lifetimes; + + traits.push_back(Type_TraitPath { mv$(hrbs), Parse_Path(lex, PATH_GENERIC_TYPE) }); + + if( allow_trait_list ) + { + while( GET_TOK(tok, lex) == TOK_PLUS ) + { + if( LOOK_AHEAD(lex) == TOK_LIFETIME ) { + GET_TOK(tok, lex); + lifetimes.push_back(AST::LifetimeRef( /*lex.point_span(),*/ lex.get_ident(mv$(tok)) )); + } + else + { + if( lex.lookahead(0) == TOK_RWORD_FOR ) + { + hrbs = Parse_HRB(lex); + } + traits.push_back({ mv$(hrbs), Parse_Path(lex, PATH_GENERIC_TYPE) }); + } } - else - traits.push_back( Parse_Path(lex, PATH_GENERIC_TYPE) ); - } while( GET_TOK(tok, lex) == TOK_PLUS ); - PUTBACK(tok, lex); - if( hrls.size() > 0 || traits.size() > 1 || lifetimes.size() > 0 ) { - if( lifetimes.size() ) - DEBUG("TODO: Lifetime bounds on trait objects"); - return TypeRef(lex.end_span(ps), mv$(hrls), ::std::move(traits)); + PUTBACK(tok, lex); } - else { - return TypeRef(TypeRef::TagPath(), lex.end_span(ps), mv$(traits.at(0))); + + if( !traits[0].hrbs.empty() || traits.size() > 1 || lifetimes.size() > 0 ) + { + if( lifetimes.empty()) + lifetimes.push_back(AST::LifetimeRef()); + return TypeRef(lex.end_span(ps), mv$(traits), mv$(lifetimes)); + } + else + { + return TypeRef(TypeRef::TagPath(), lex.end_span(ps), mv$(traits.at(0).path)); } } } @@ -300,20 +316,25 @@ TypeRef Parse_Type_ErasedType(TokenStream& lex, bool allow_trait_list) Token tok; auto ps = lex.start_span(); - ::std::vector<AST::Path> traits; - ::std::vector< ::std::string> lifetimes; + ::std::vector<Type_TraitPath> traits; + ::std::vector<AST::LifetimeRef> lifetimes; do { if( LOOK_AHEAD(lex) == TOK_LIFETIME ) { GET_TOK(tok, lex); - lifetimes.push_back( tok.str() ); + lifetimes.push_back(AST::LifetimeRef( /*lex.point_span(),*/ lex.get_ident(mv$(tok)) )); } else - traits.push_back( Parse_Path(lex, PATH_GENERIC_TYPE) ); + { + AST::HigherRankedBounds hrbs; + if( lex.lookahead(0) == TOK_RWORD_FOR ) + { + hrbs = Parse_HRB(lex); + } + traits.push_back({ mv$(hrbs), Parse_Path(lex, PATH_GENERIC_TYPE) }); + } } while( GET_TOK(tok, lex) == TOK_PLUS ); PUTBACK(tok, lex); - if( lifetimes.size() ) - DEBUG("TODO: Lifetime bounds on erased types"); - return TypeRef(lex.end_span(ps), TypeData::make_ErasedType({ {}, mv$(traits) })); + return TypeRef(lex.end_span(ps), TypeData::make_ErasedType({ mv$(traits), mv$(lifetimes) })); } diff --git a/src/resolve/absolute.cpp b/src/resolve/absolute.cpp index 2c17592c..d05e3bc6 100644 --- a/src/resolve/absolute.cpp +++ b/src/resolve/absolute.cpp @@ -1500,24 +1500,24 @@ void Resolve_Absolute_Type(Context& context, TypeRef& type) ) TU_IFLET(::AST::PathBinding, e.path.binding(), Trait, be, - auto ty = ::TypeRef( type.span(), {}, ::make_vec1(mv$(e.path)) ); + auto ty = ::TypeRef( type.span(), ::make_vec1(Type_TraitPath { {}, mv$(e.path)}), {} ); type = mv$(ty); return ; ) ), (TraitObject, - //context.push_lifetimes( e.hrls ); for(auto& trait : e.traits) { - Resolve_Absolute_Path(context, type.span(), Context::LookupMode::Type, trait); + //context.push_lifetimes( trait.hrbs.m_lifetimes ); + Resolve_Absolute_Path(context, type.span(), Context::LookupMode::Type, trait.path); + //context.pop_lifetimes(); } - //context.pop_lifetimes(); ), (ErasedType, - //context.push_lifetimes( e.hrls ); for(auto& trait : e.traits) { - Resolve_Absolute_Path(context, type.span(), Context::LookupMode::Type, trait); + //context.push_lifetimes( trait.hrbs.m_lifetimes ); + Resolve_Absolute_Path(context, type.span(), Context::LookupMode::Type, trait.path); + //context.pop_lifetimes(); } - //context.pop_lifetimes(); ) ) } @@ -1683,6 +1683,8 @@ void Resolve_Absolute_Generic(Context& context, ::AST::GenericParams& params) for( auto& bound : params.bounds() ) { TU_MATCH(::AST::GenericBound, (bound), (e), + (None, + ), (Lifetime, // TODO: Link lifetime names to params ), |