diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/ast/pattern.cpp | 31 | ||||
-rw-r--r-- | src/ast/pattern.hpp | 46 | ||||
-rw-r--r-- | src/dump_as_rust.cpp | 22 | ||||
-rw-r--r-- | src/expand/derive.cpp | 10 | ||||
-rw-r--r-- | src/expand/mod.cpp | 10 | ||||
-rw-r--r-- | src/hir/from_ast.cpp | 116 | ||||
-rw-r--r-- | src/hir/pattern.cpp | 29 | ||||
-rw-r--r-- | src/hir/pattern.hpp | 21 | ||||
-rw-r--r-- | src/hir/visitor.cpp | 6 | ||||
-rw-r--r-- | src/hir_conv/bind.cpp | 20 | ||||
-rw-r--r-- | src/hir_expand/closures.cpp | 6 | ||||
-rw-r--r-- | src/hir_typeck/expr_cs.cpp | 130 | ||||
-rw-r--r-- | src/mir/from_hir.cpp | 7 | ||||
-rw-r--r-- | src/mir/from_hir_match.cpp | 7 | ||||
-rw-r--r-- | src/parse/pattern.cpp | 42 | ||||
-rw-r--r-- | src/resolve/absolute.cpp | 5 |
16 files changed, 264 insertions, 244 deletions
diff --git a/src/ast/pattern.cpp b/src/ast/pattern.cpp index 164ba962..bc961e63 100644 --- a/src/ast/pattern.cpp +++ b/src/ast/pattern.cpp @@ -57,6 +57,17 @@ namespace AST { ) return os; } +::std::ostream& operator<<(::std::ostream& os, const Pattern::TuplePat& val) +{ + if( val.glob_pos == Pattern::TupleGlob::Start ) { + os << ".., "; + } + os << val.sub_patterns; + if( val.glob_pos == Pattern::TupleGlob::End ) { + os << ".., "; + } + return os; +} ::std::ostream& operator<<(::std::ostream& os, const Pattern& pat) { os << "Pattern("; @@ -85,13 +96,10 @@ namespace AST { os << " ... " << ent.end; ), (Tuple, - os << "(" << ent.sub_patterns << ")"; - ), - (WildcardStructTuple, - os << ent.path << " (..)"; + os << "(" << ent << ")"; ), (StructTuple, - os << ent.path << " (" << ent.sub_patterns << ")"; + os << ent.path << " (" << ent.tup_pat << ")"; ), (Struct, os << ent.path << " {" << ent.sub_patterns << "}"; @@ -159,6 +167,12 @@ AST::Pattern AST::Pattern::clone() const rv.push_back( p.clone() ); return rv; } + static TuplePat clone_tup(const TuplePat& p) { + return TuplePat { + p.glob_pos, + H::clone_list(p.sub_patterns) + }; + } static AST::Pattern::Value clone_val(const AST::Pattern::Value& v) { TU_MATCH(::AST::Pattern::Value, (v), (e), (Invalid, return Value(e);), @@ -191,13 +205,10 @@ AST::Pattern AST::Pattern::clone() const rv.m_data = Data::make_Value({ H::clone_val(e.start), H::clone_val(e.end) }); ), (Tuple, - rv.m_data = Data::make_Tuple({ H::clone_list(e.sub_patterns) }); - ), - (WildcardStructTuple, - rv.m_data = Data::make_WildcardStructTuple({ ::AST::Path(e.path) }); + rv.m_data = Data::make_Tuple({ H::clone_tup(e) }); ), (StructTuple, - rv.m_data = Data::make_StructTuple({ ::AST::Path(e.path), H::clone_list(e.sub_patterns) }); + rv.m_data = Data::make_StructTuple({ ::AST::Path(e.path), H::clone_tup(e.tup_pat) }); ), (Struct, ::std::vector< ::std::pair< ::std::string, Pattern> > sps; diff --git a/src/ast/pattern.hpp b/src/ast/pattern.hpp index 7df25520..4db20fd5 100644 --- a/src/ast/pattern.hpp +++ b/src/ast/pattern.hpp @@ -60,6 +60,16 @@ public: (Named, Path) ); + enum class TupleGlob { + None, // (a, b) + Start, // (.., a, b) + End, // (a, b, ..) + }; + struct TuplePat { + TupleGlob glob_pos; + ::std::vector<Pattern> sub_patterns; + }; + TAGGED_UNION(Data, Any, (MaybeBind, struct { ::std::string name; } ), (Macro, struct { unique_ptr<::AST::MacroInvocation> inv; } ), @@ -67,9 +77,8 @@ public: (Box, struct { unique_ptr<Pattern> sub; } ), (Ref, struct { bool mut; unique_ptr<Pattern> sub; } ), (Value, struct { Value start; Value end; } ), - (Tuple, struct { ::std::vector<Pattern> sub_patterns; } ), - (WildcardStructTuple, struct { Path path; } ), - (StructTuple, struct { Path path; ::std::vector<Pattern> sub_patterns; } ), + (Tuple, TuplePat ), + (StructTuple, struct { Path path; TuplePat tup_pat; } ), (Struct, struct { Path path; ::std::vector< ::std::pair< ::std::string, Pattern> > sub_patterns; bool is_exhaustive; } ), (Slice, struct { ::std::vector<Pattern> leading; ::std::string extra_bind; ::std::vector<Pattern> trailing; } ) ); @@ -85,6 +94,11 @@ public: {} Pattern(Pattern&&) = default; Pattern& operator=(Pattern&&) = default; + + Pattern(Data dat): + m_binding(), + m_data( mv$(dat) ) + {}; struct TagMaybeBind {}; Pattern(TagMaybeBind, ::std::string name): @@ -97,12 +111,6 @@ public: m_data( Data::make_Macro({mv$(inv)}) ) {} - // Wildcard = '..', distinct from '_' - // TODO: Store wildcard as a different pattern type - struct TagWildcard {}; - Pattern(TagWildcard) - {} - struct TagBind {}; Pattern(TagBind, ::std::string name, PatternBinding::Type ty = PatternBinding::Type::MOVE, bool is_mut=false): m_binding( PatternBinding(name, ty, is_mut) ) @@ -128,16 +136,19 @@ public: } struct TagTuple {}; - Pattern(TagTuple, ::std::vector<Pattern> sub_patterns): - m_data( Data::make_Tuple( { ::std::move(sub_patterns) } ) ) + Pattern(TagTuple, TuplePat pat): + m_data( Data::make_Tuple( ::std::move(pat) ) ) + {} + Pattern(TagTuple, ::std::vector<Pattern> pats): + m_data( Data::make_Tuple( TuplePat { TupleGlob::None, ::std::move(pats) } ) ) {} - struct TagEnumVariant {}; - Pattern(TagEnumVariant, Path path): - m_data( Data::make_WildcardStructTuple( { ::std::move(path) } ) ) + struct TagNamedTuple {}; + Pattern(TagNamedTuple, Path path, ::std::vector<Pattern> pats): + m_data( Data::make_StructTuple( { ::std::move(path), TuplePat { TupleGlob::None, ::std::move(pats) } } ) ) {} - Pattern(TagEnumVariant, Path path, ::std::vector<Pattern> sub_patterns): - m_data( Data::make_StructTuple( { ::std::move(path), ::std::move(sub_patterns) } ) ) + Pattern(TagNamedTuple, Path path, TuplePat pat = TuplePat { TupleGlob::Start, {} }): + m_data( Data::make_StructTuple( { ::std::move(path), ::std::move(pat) } ) ) {} struct TagStruct {}; @@ -179,7 +190,8 @@ public: } }; -::std::ostream& operator<<(::std::ostream& os, const Pattern::Value& val); +extern ::std::ostream& operator<<(::std::ostream& os, const Pattern::Value& val); +extern ::std::ostream& operator<<(::std::ostream& os, const Pattern::TuplePat& val); }; diff --git a/src/dump_as_rust.cpp b/src/dump_as_rust.cpp index 191366fa..1f51f317 100644 --- a/src/dump_as_rust.cpp +++ b/src/dump_as_rust.cpp @@ -812,15 +812,18 @@ void RustPrinter::print_pattern(const AST::Pattern& p, bool is_refutable) m_os << " ... " << v.end; } ), - (WildcardStructTuple, - m_os << v.path << "(..)"; - ), (StructTuple, m_os << v.path << "("; - for(const auto& sp : v.sub_patterns) { + if( v.tup_pat.glob_pos == ::AST::Pattern::TupleGlob::Start ) { + m_os << ".., "; + } + for(const auto& sp : v.tup_pat.sub_patterns) { print_pattern(sp, is_refutable); m_os << ","; } + if( v.tup_pat.glob_pos == ::AST::Pattern::TupleGlob::End ) { + m_os << " .."; + } m_os << ")"; ), (Struct, { @@ -833,15 +836,20 @@ void RustPrinter::print_pattern(const AST::Pattern& p, bool is_refutable) } m_os << ")"; }), - (Tuple, { - const auto& v = p.data().as_Tuple(); + (Tuple, m_os << "("; + if( v.glob_pos == ::AST::Pattern::TupleGlob::Start ) { + m_os << ".., "; + } for(const auto& sp : v.sub_patterns) { print_pattern(sp, is_refutable); m_os << ","; } + if( v.glob_pos == ::AST::Pattern::TupleGlob::End ) { + m_os << " .."; + } m_os << ")"; - }), + ), (Slice, m_os << "["; bool needs_comma = false; diff --git a/src/expand/derive.cpp b/src/expand/derive.cpp index f78a2217..f14e7ae8 100644 --- a/src/expand/derive.cpp +++ b/src/expand/derive.cpp @@ -357,7 +357,7 @@ public: vec$( NEWNODE(String, v.m_name + "(...)") ) ); - pat_a = AST::Pattern(AST::Pattern::TagEnumVariant(), base_path + v.m_name, mv$(pats_a)); + pat_a = AST::Pattern(AST::Pattern::TagNamedTuple(), base_path + v.m_name, mv$(pats_a)); } ), (Struct, @@ -510,8 +510,8 @@ public: } nodes.push_back( NEWNODE(Bool, true) ); - pat_a = AST::Pattern(AST::Pattern::TagEnumVariant(), base_path + v.m_name, mv$(pats_a)); - pat_b = AST::Pattern(AST::Pattern::TagEnumVariant(), base_path + v.m_name, mv$(pats_b)); + pat_a = AST::Pattern(AST::Pattern::TagNamedTuple(), base_path + v.m_name, mv$(pats_a)); + pat_b = AST::Pattern(AST::Pattern::TagNamedTuple(), base_path + v.m_name, mv$(pats_b)); code = NEWNODE(Block, mv$(nodes), nullptr); } ), @@ -673,7 +673,7 @@ public: nodes.push_back( this->assert_is_eq(assert_method_path, NEWNODE(NamedValue, AST::Path(name_a))) ); } - pat_a = AST::Pattern(AST::Pattern::TagEnumVariant(), base_path + v.m_name, mv$(pats_a)); + pat_a = AST::Pattern(AST::Pattern::TagNamedTuple(), base_path + v.m_name, mv$(pats_a)); code = NEWNODE(Block, mv$(nodes), nullptr); } ), @@ -820,7 +820,7 @@ public: nodes.push_back( this->clone_val(NEWNODE(NamedValue, AST::Path(name_a))) ); } - pat_a = AST::Pattern(AST::Pattern::TagEnumVariant(), base_path + v.m_name, mv$(pats_a)); + pat_a = AST::Pattern(AST::Pattern::TagNamedTuple(), base_path + v.m_name, mv$(pats_a)); code = NEWNODE(CallPath, base_path + v.m_name, mv$(nodes)); } ), diff --git a/src/expand/mod.cpp b/src/expand/mod.cpp index 2f9956bc..6a7d81ee 100644 --- a/src/expand/mod.cpp +++ b/src/expand/mod.cpp @@ -161,10 +161,8 @@ void Expand_Pattern(bool is_early, ::AST::Crate& crate, LList<const AST::Module* for(auto& sp : e.sub_patterns) Expand_Pattern(is_early, crate, modstack, mod, sp); ), - (WildcardStructTuple, - ), (StructTuple, - for(auto& sp : e.sub_patterns) + for(auto& sp : e.tup_pat.sub_patterns) Expand_Pattern(is_early, crate, modstack, mod, sp); ), (Struct, @@ -371,7 +369,7 @@ struct CExpandExpr: ::std::vector< ::AST::ExprNode_Match_Arm> arms; // - `Some(pattern ) => code` arms.push_back( ::AST::ExprNode_Match_Arm( - ::make_vec1( ::AST::Pattern(::AST::Pattern::TagEnumVariant(), path_Some, ::make_vec1( mv$(node.m_pattern) ) ) ), + ::make_vec1( ::AST::Pattern(::AST::Pattern::TagNamedTuple(), path_Some, ::make_vec1( mv$(node.m_pattern) ) ) ), nullptr, mv$(node.m_code) ) ); @@ -506,13 +504,13 @@ struct CExpandExpr: ::std::vector< ::AST::ExprNode_Match_Arm> arms; // `Ok(v) => v,` arms.push_back(::AST::ExprNode_Match_Arm( - ::make_vec1( ::AST::Pattern(::AST::Pattern::TagEnumVariant(), path_Ok, ::make_vec1( ::AST::Pattern(::AST::Pattern::TagBind(), "v") )) ), + ::make_vec1( ::AST::Pattern(::AST::Pattern::TagNamedTuple(), path_Ok, ::make_vec1( ::AST::Pattern(::AST::Pattern::TagBind(), "v") )) ), nullptr, ::AST::ExprNodeP( new ::AST::ExprNode_NamedValue( ::AST::Path(::AST::Path::TagLocal(), "v") ) ) )); // `Err(e) => return Err(From::from(e)),` arms.push_back(::AST::ExprNode_Match_Arm( - ::make_vec1( ::AST::Pattern(::AST::Pattern::TagEnumVariant(), path_Err, ::make_vec1( ::AST::Pattern(::AST::Pattern::TagBind(), "e") )) ), + ::make_vec1( ::AST::Pattern(::AST::Pattern::TagNamedTuple(), path_Err, ::make_vec1( ::AST::Pattern(::AST::Pattern::TagBind(), "e") )) ), nullptr, ::AST::ExprNodeP(new ::AST::ExprNode_Flow( ::AST::ExprNode_Flow::RETURN, diff --git a/src/hir/from_ast.cpp b/src/hir/from_ast.cpp index 01917193..1bf63ac3 100644 --- a/src/hir/from_ast.cpp +++ b/src/hir/from_ast.cpp @@ -122,9 +122,30 @@ const ::HIR::SimplePath path_Sized = ::HIR::SimplePath("", {"marker", "Sized"}); case ::AST::PatternBinding::Type::REF: bt = ::HIR::PatternBinding::Type::Ref; break; case ::AST::PatternBinding::Type::MUTREF: bt = ::HIR::PatternBinding::Type::MutRef; break; } - // TODO: Get bound slot binding = ::HIR::PatternBinding(pat.binding().m_mutable, bt, pat.binding().m_name, pat.binding().m_slot); } + + struct H { + static ::std::vector< ::HIR::Pattern> lowerhir_patternvec(const ::std::vector< ::AST::Pattern>& sub_patterns) { + ::std::vector< ::HIR::Pattern> rv; + for(const auto& sp : sub_patterns) + rv.push_back( LowerHIR_Pattern(sp) ); + return rv; + } + static ::HIR::Pattern::GlobPos lowerhir_globpos(::AST::Pattern::TupleGlob pos) { + switch(pos) + { + case ::AST::Pattern::TupleGlob::None: + return ::HIR::Pattern::GlobPos::None; + case ::AST::Pattern::TupleGlob::Start: + return ::HIR::Pattern::GlobPos::Start; + case ::AST::Pattern::TupleGlob::End: + return ::HIR::Pattern::GlobPos::End; + } + throw ""; + } + }; + TU_MATCH(::AST::Pattern::Data, (pat.data()), (e), (MaybeBind, BUG(pat.span(), "Encountered MaybeBind pattern"); @@ -156,53 +177,54 @@ const ::HIR::SimplePath path_Sized = ::HIR::SimplePath("", {"marker", "Sized"}); }; ), (Tuple, - ::std::vector< ::HIR::Pattern> sub_patterns; - for(const auto& sp : e.sub_patterns) - sub_patterns.push_back( LowerHIR_Pattern(sp) ); + auto glob_pos = H::lowerhir_globpos( e.glob_pos ); + auto sub_patterns = H::lowerhir_patternvec( e.sub_patterns ); return ::HIR::Pattern { mv$(binding), ::HIR::Pattern::Data::make_Tuple({ - mv$(sub_patterns) + glob_pos, mv$(sub_patterns) }) }; ), - (WildcardStructTuple, - TU_MATCH_DEF(::AST::PathBinding, (e.path.binding()), (pb), - ( - BUG(pat.span(), "Encountered StructTuple pattern not pointing to a enum variant or a struct - " << e.path); - ), - (EnumVar, - return ::HIR::Pattern { - mv$(binding), - ::HIR::Pattern::Data::make_EnumTupleWildcard({ - LowerHIR_GenericPath(pat.span(), e.path), - nullptr, 0 - }) - }; - ), - (Struct, - return ::HIR::Pattern { - mv$(binding), - ::HIR::Pattern::Data::make_StructTupleWildcard({ - LowerHIR_GenericPath(pat.span(), e.path), - nullptr - }) - }; - ) - ) - ), (StructTuple, - ::std::vector< ::HIR::Pattern> sub_patterns; - for(const auto& sp : e.sub_patterns) - sub_patterns.push_back( LowerHIR_Pattern(sp) ); + auto sub_patterns = H::lowerhir_patternvec( e.tup_pat.sub_patterns ); TU_MATCH_DEF(::AST::PathBinding, (e.path.binding()), (pb), ( BUG(pat.span(), "Encountered StructTuple pattern not pointing to a enum variant or a struct - " << e.path); ), (EnumVar, + const auto& var = pb.enum_->variants()[pb.idx].m_data; + const auto& var_tup_tys = var.as_Tuple().m_sub_types; + switch(e.tup_pat.glob_pos) + { + case ::AST::Pattern::TupleGlob::None: + // Check count + if( var_tup_tys.size() != sub_patterns.size() ) { + ERROR(pat.span(), E0000, "Enum variant pattern has a mismatched field count - " << var_tup_tys.size() << " exp, got " << sub_patterns.size()); + } + break; + case ::AST::Pattern::TupleGlob::Start: + // NOTE == is allowed + if( var_tup_tys.size() < sub_patterns.size() ) { + ERROR(pat.span(), E0000, "Enum variant pattern has too many fields - " << var_tup_tys.size() << " max, got " << sub_patterns.size()); + } + while( sub_patterns.size() < var_tup_tys.size() ) { + sub_patterns.insert( sub_patterns.begin(), ::HIR::Pattern() ); + } + break; + case ::AST::Pattern::TupleGlob::End: + // NOTE == is allowed + if( var_tup_tys.size() < sub_patterns.size() ) { + ERROR(pat.span(), E0000, "Enum variant pattern has too many fields - " << var_tup_tys.size() << " max, got " << sub_patterns.size()); + } + while( sub_patterns.size() < var_tup_tys.size() ) { + sub_patterns.insert( sub_patterns.end(), ::HIR::Pattern() ); + } + break; + } return ::HIR::Pattern { mv$(binding), ::HIR::Pattern::Data::make_EnumTuple({ @@ -213,6 +235,34 @@ const ::HIR::SimplePath path_Sized = ::HIR::SimplePath("", {"marker", "Sized"}); }; ), (Struct, + const auto& tys = pb.struct_->m_data.as_Tuple().ents; + switch(e.tup_pat.glob_pos) + { + case ::AST::Pattern::TupleGlob::None: + // Check count + if( tys.size() != sub_patterns.size() ) { + ERROR(pat.span(), E0000, "Struct pattern has a mismatched field count - " << tys.size() << " exp, got " << sub_patterns.size()); + } + break; + case ::AST::Pattern::TupleGlob::Start: + // NOTE == is allowed + if( sub_patterns.size() > tys.size() ) { + ERROR(pat.span(), E0000, "Struct pattern has too many fields - " << tys.size() << " max, got " << sub_patterns.size()); + } + while( sub_patterns.size() < tys.size() ) { + sub_patterns.insert( sub_patterns.begin(), ::HIR::Pattern() ); + } + break; + case ::AST::Pattern::TupleGlob::End: + // NOTE == is allowed + if( sub_patterns.size() > tys.size() ) { + ERROR(pat.span(), E0000, "Struct pattern has too many fields - " << tys.size() << " max, got " << sub_patterns.size()); + } + while( sub_patterns.size() < tys.size() ) { + sub_patterns.insert( sub_patterns.end(), ::HIR::Pattern() ); + } + break; + } return ::HIR::Pattern { mv$(binding), ::HIR::Pattern::Data::make_StructTuple({ diff --git a/src/hir/pattern.cpp b/src/hir/pattern.cpp index f3ad277e..d6715f0c 100644 --- a/src/hir/pattern.cpp +++ b/src/hir/pattern.cpp @@ -47,8 +47,12 @@ namespace HIR { ), (Tuple, os << "("; + if(e.glob_pos == ::HIR::Pattern::GlobPos::Start) + os << ".., "; for(const auto& s : e.sub_patterns) os << s << ", "; + if(e.glob_pos == ::HIR::Pattern::GlobPos::End) + os << ".., "; os << ")"; ), (StructValue, @@ -61,9 +65,6 @@ namespace HIR { os << s << ", "; os << ")"; ), - (StructTupleWildcard, - os << e.path << "(..)"; - ), (Struct, os << e.path; os << "{ "; @@ -89,9 +90,6 @@ namespace HIR { os << s << ", "; os << ")"; ), - (EnumTupleWildcard, - os << e.path << "(..)"; - ), (EnumStruct, os << e.path; os << "{ "; @@ -173,6 +171,7 @@ namespace { ), (Tuple, return Pattern(m_binding, Data::make_Tuple({ + e.glob_pos, clone_pat_vec(e.sub_patterns) })); ), @@ -188,12 +187,6 @@ namespace { clone_pat_vec(e.sub_patterns) })); ), - (StructTupleWildcard, - return Pattern(m_binding, Data::make_StructTupleWildcard({ - e.path.clone(), - e.binding - })); - ), (Struct, return Pattern(m_binding, Data::make_Struct({ e.path.clone(), @@ -219,13 +212,11 @@ namespace { return Pattern(m_binding, Data::make_EnumValue({ e.path.clone(), e.binding_ptr, e.binding_idx })); ), (EnumTuple, - return Pattern(m_binding, Data::make_EnumTupleWildcard({ - e.path.clone(), e.binding_ptr, e.binding_idx - })); - ), - (EnumTupleWildcard, - return Pattern(m_binding, Data::make_EnumTupleWildcard({ - e.path.clone(), e.binding_ptr, e.binding_idx + return Pattern(m_binding, Data::make_EnumTuple({ + e.path.clone(), + e.binding_ptr, + e.binding_idx, + clone_pat_vec(e.sub_patterns) })); ), (EnumStruct, diff --git a/src/hir/pattern.hpp b/src/hir/pattern.hpp index 2a5ebb2a..13877dbc 100644 --- a/src/hir/pattern.hpp +++ b/src/hir/pattern.hpp @@ -57,13 +57,23 @@ struct Pattern }) ); friend ::std::ostream& operator<<(::std::ostream& os, const Pattern::Value& x); + + enum class GlobPos { + None, + Start, + End, + }; TAGGED_UNION(Data, Any, // Irrefutable / destructuring (Any, struct { } ), (Box, struct { ::std::unique_ptr<Pattern> sub; }), (Ref, struct { ::HIR::BorrowType type; ::std::unique_ptr<Pattern> sub; } ), - (Tuple, struct { ::std::vector<Pattern> sub_patterns; } ), + (Tuple, struct { + // NOTE: Has the glob still because the tuple isn't yet known + GlobPos glob_pos; + ::std::vector<Pattern> sub_patterns; + }), (StructValue, struct { GenericPath path; const Struct* binding; @@ -74,10 +84,6 @@ struct Pattern const Struct* binding; ::std::vector<Pattern> sub_patterns; } ), - (StructTupleWildcard, struct { - GenericPath path; - const Struct* binding; - }), (Struct, struct { GenericPath path; const Struct* binding; @@ -98,11 +104,6 @@ struct Pattern unsigned binding_idx; ::std::vector<Pattern> sub_patterns; } ), - (EnumTupleWildcard, struct { - GenericPath path; - const Enum* binding_ptr; - unsigned binding_idx; - } ), (EnumStruct, struct { GenericPath path; const Enum* binding_ptr; diff --git a/src/hir/visitor.cpp b/src/hir/visitor.cpp index faca63da..cadf3722 100644 --- a/src/hir/visitor.cpp +++ b/src/hir/visitor.cpp @@ -333,9 +333,6 @@ void ::HIR::Visitor::visit_pattern(::HIR::Pattern& pat) (StructValue, this->visit_generic_path(e.path, ::HIR::Visitor::PathContext::TYPE); ), - (StructTupleWildcard, - this->visit_generic_path(e.path, ::HIR::Visitor::PathContext::TYPE); - ), (StructTuple, this->visit_generic_path(e.path, ::HIR::Visitor::PathContext::TYPE); for(auto& sp : e.sub_patterns) @@ -357,9 +354,6 @@ void ::HIR::Visitor::visit_pattern(::HIR::Pattern& pat) (EnumValue, this->visit_generic_path(e.path, ::HIR::Visitor::PathContext::TYPE); ), - (EnumTupleWildcard, - this->visit_generic_path(e.path, ::HIR::Visitor::PathContext::TYPE); - ), (EnumTuple, this->visit_generic_path(e.path, ::HIR::Visitor::PathContext::TYPE); for(auto& sp : e.sub_patterns) diff --git a/src/hir_conv/bind.cpp b/src/hir_conv/bind.cpp index c0e58648..cce11cdf 100644 --- a/src/hir_conv/bind.cpp +++ b/src/hir_conv/bind.cpp @@ -253,15 +253,6 @@ namespace { ERROR(sp, E0000, "Struct tuple pattern on non-tuple struct " << e.path); } ), - (StructTupleWildcard, - const auto& str = get_struct_ptr(sp, m_crate, e.path); - TU_IFLET(::HIR::Struct::Data, str.m_data, Tuple, _, - e.binding = &str; - ) - else { - ERROR(sp, E0000, "Struct tuple pattern on non-tuple struct " << e.path); - } - ), (Struct, const auto& str = get_struct_ptr(sp, m_crate, e.path); TU_IFLET(::HIR::Struct::Data, str.m_data, Named, _, @@ -282,17 +273,6 @@ namespace { ERROR(sp, E0000, "Enum tuple pattern on non-tuple variant " << e.path); } ), - (EnumTupleWildcard, - auto p = get_enum_ptr(sp, m_crate, e.path); - const auto& var = p.first->m_variants[p.second].second; - TU_IFLET(::HIR::Enum::Variant, var, Tuple, _, - e.binding_ptr = p.first; - e.binding_idx = p.second; - ) - else { - ERROR(sp, E0000, "Enum tuple pattern on non-tuple variant " << e.path); - } - ), (EnumStruct, auto p = get_enum_ptr(sp, m_crate, e.path); const auto& var = p.first->m_variants[p.second].second; diff --git a/src/hir_expand/closures.cpp b/src/hir_expand/closures.cpp index 892b6bad..52ef1629 100644 --- a/src/hir_expand/closures.cpp +++ b/src/hir_expand/closures.cpp @@ -407,7 +407,7 @@ namespace { args_ty_inner.push_back( monomorphise_type_with(sp, arg.second, monomorph_cb) ); } ::HIR::TypeRef args_ty { mv$(args_ty_inner) }; - ::HIR::Pattern args_pat { {}, ::HIR::Pattern::Data::make_Tuple({ mv$(args_pat_inner) }) }; + ::HIR::Pattern args_pat { {}, ::HIR::Pattern::Data::make_Tuple({ ::HIR::Pattern::GlobPos::None, mv$(args_pat_inner) }) }; ::HIR::TypeRef ret_type = monomorphise_type_with(sp, node.m_return, monomorph_cb); DEBUG("args_ty = " << args_ty << ", ret_type = " << ret_type); @@ -631,8 +631,6 @@ namespace { add_closure_def_from_pattern(sp, field); } ), - (StructTupleWildcard, - ), (Struct, for( auto& field_pat : e.sub_patterns ) { add_closure_def_from_pattern(sp, field_pat.second); @@ -645,8 +643,6 @@ namespace { add_closure_def_from_pattern(sp, field); } ), - (EnumTupleWildcard, - ), (EnumStruct, for( auto& field_pat : e.sub_patterns ) { add_closure_def_from_pattern(sp, field_pat.second); diff --git a/src/hir_typeck/expr_cs.cpp b/src/hir_typeck/expr_cs.cpp index 04e27bb2..c59abc8b 100644 --- a/src/hir_typeck/expr_cs.cpp +++ b/src/hir_typeck/expr_cs.cpp @@ -2502,13 +2502,38 @@ void Context::add_binding(const Span& sp, ::HIR::Pattern& pat, const ::HIR::Type (Tuple, const auto& ty = this->get_type(type); TU_IFLET(::HIR::TypeRef::Data, ty.m_data, Tuple, te, - if( te.size() != e.sub_patterns.size() ) { - ERROR(sp, E0000, "Pattern-type mismatch, expected " << e.sub_patterns.size() << "-tuple, got " << ty); + + unsigned int field_ofs = 0; + switch(e.glob_pos) + { + case ::HIR::Pattern::GlobPos::None: + if( e.sub_patterns.size() != te.size() ) { + ERROR(sp, E0000, "Tuple pattern with an incorrect number of fields, expected " << e.sub_patterns.size() << "-tuple, got " << ty); + } + break; + case ::HIR::Pattern::GlobPos::End: + field_ofs = te.size() - e.sub_patterns.size(); + case ::HIR::Pattern::GlobPos::Start: + if( e.sub_patterns.size() > te.size() ) { + ERROR(sp, E0000, "Tuple pattern with too many fields"); + } + break; } + for(unsigned int i = 0; i < e.sub_patterns.size(); i ++ ) - this->add_binding(sp, e.sub_patterns[i], te[i] ); + this->add_binding(sp, e.sub_patterns[i], te[field_ofs+i] ); ) else { + switch(e.glob_pos) + { + case ::HIR::Pattern::GlobPos::None: + break; + case ::HIR::Pattern::GlobPos::End: + case ::HIR::Pattern::GlobPos::Start: + TODO(sp, "Create ivar type when wildcard is present"); + break; + } + ::std::vector< ::HIR::TypeRef> sub_types; for(unsigned int i = 0; i < e.sub_patterns.size(); i ++ ) { sub_types.push_back( this->m_ivars.new_ivar_tr() ); @@ -2580,45 +2605,20 @@ void Context::add_binding(const Span& sp, ::HIR::Pattern& pat, const ::HIR::Type assert(e.binding); const auto& params = *params_ptr; - if( e.sub_patterns.size() != sd.size() ) { - ERROR(sp, E0000, "Tuple struct pattern with an incorrect number of fields"); - } for( unsigned int i = 0; i < e.sub_patterns.size(); i ++ ) { + /*const*/ auto& sub_pat = e.sub_patterns[i]; const auto& field_type = sd[i].ent; if( monomorphise_type_needed(field_type) ) { auto var_ty = monomorphise_type(sp, str.m_params, params, field_type); - this->add_binding(sp, e.sub_patterns[i], var_ty); + this->add_binding(sp, sub_pat, var_ty); } else { // SAFE: Can't have _ as monomorphise_type_needed checks for that - this->add_binding(sp, e.sub_patterns[i], const_cast< ::HIR::TypeRef&>(field_type)); + this->add_binding(sp, sub_pat, const_cast< ::HIR::TypeRef&>(field_type)); } } ), - (StructTupleWildcard, - this->add_ivars_params( e.path.m_params ); - if( type.m_data.is_Infer() ) { - this->equate_types( sp, type, ::HIR::TypeRef::new_path(e.path.clone(), ::HIR::TypeRef::TypePathBinding(e.binding)) ); - } - const auto& ty = this->get_type(type); - assert(e.binding); - const auto& str = *e.binding; - // - assert check from earlier pass - assert( str.m_data.is_Tuple() ); - - TU_MATCH_DEF(::HIR::TypeRef::Data, (ty.m_data), (te), - ( - ERROR(sp, E0000, "Type mismatch in struct pattern - " << ty << " is not " << e.path); - ), - (Infer, throw ""; ), - (Path, - if( ! te.binding.is_Struct() || te.binding.as_Struct() != &str ) { - ERROR(sp, E0000, "Type mismatch in struct pattern - " << ty << " is not " << e.path); - } - ) - ) - ), (Struct, this->add_ivars_params( e.path.m_params ); if( type.m_data.is_Infer() ) { @@ -2661,51 +2661,6 @@ void Context::add_binding(const Span& sp, ::HIR::Pattern& pat, const ::HIR::Type ) ) ), - (EnumTuple, - this->add_ivars_params( e.path.m_params ); - if( type.m_data.is_Infer() ) { - auto path = e.path.clone(); - path.m_path.m_components.pop_back(); - - this->equate_types( sp, type, ::HIR::TypeRef::new_path(mv$(path), ::HIR::TypeRef::TypePathBinding(e.binding_ptr)) ); - } - const auto& ty = this->get_type(type); - const auto& type = ty; - - assert(e.binding_ptr); - const auto& enm = *e.binding_ptr; - const auto& var = enm.m_variants[e.binding_idx].second; - assert(var.is_Tuple()); - const auto& tup_var = var.as_Tuple(); - - TU_MATCH_DEF(::HIR::TypeRef::Data, (type.m_data), (te), - ( - ERROR(sp, E0000, "Type mismatch in enum pattern - " << type << " is not " << e.path); - ), - (Infer, throw ""; ), - (Path, - if( ! te.binding.is_Enum() || te.binding.as_Enum() != &enm ) { - ERROR(sp, E0000, "Type mismatch in enum pattern - " << type << " is not " << e.path); - } - // NOTE: Must be Generic for the above to have passed - auto& gp = te.path.m_data.as_Generic(); - if( e.sub_patterns.size() != tup_var.size() ) { - ERROR(sp, E0000, "Enum pattern with an incorrect number of fields - " << e.path << " - expected " << tup_var.size() << ", got " << e.sub_patterns.size()); - } - for( unsigned int i = 0; i < e.sub_patterns.size(); i ++ ) - { - if( monomorphise_type_needed(tup_var[i].ent) ) { - auto var_ty = monomorphise_type(sp, enm.m_params, gp.m_params, tup_var[i].ent); - this->add_binding(sp, e.sub_patterns[i], var_ty); - } - else { - // SAFE: Can't have a _ (monomorphise_type_needed checks for that) - this->add_binding(sp, e.sub_patterns[i], const_cast< ::HIR::TypeRef&>(tup_var[i].ent)); - } - } - ) - ) - ), (EnumValue, this->add_ivars_params( e.path.m_params ); if( type.m_data.is_Infer() ) { @@ -2735,7 +2690,7 @@ void Context::add_binding(const Span& sp, ::HIR::Pattern& pat, const ::HIR::Type ) ) ), - (EnumTupleWildcard, + (EnumTuple, this->add_ivars_params( e.path.m_params ); if( type.m_data.is_Infer() ) { auto path = e.path.clone(); @@ -2745,11 +2700,12 @@ void Context::add_binding(const Span& sp, ::HIR::Pattern& pat, const ::HIR::Type } const auto& ty = this->get_type(type); const auto& type = ty; - + assert(e.binding_ptr); const auto& enm = *e.binding_ptr; const auto& var = enm.m_variants[e.binding_idx].second; assert(var.is_Tuple()); + const auto& tup_var = var.as_Tuple(); TU_MATCH_DEF(::HIR::TypeRef::Data, (type.m_data), (te), ( @@ -2760,6 +2716,24 @@ void Context::add_binding(const Span& sp, ::HIR::Pattern& pat, const ::HIR::Type if( ! te.binding.is_Enum() || te.binding.as_Enum() != &enm ) { ERROR(sp, E0000, "Type mismatch in enum pattern - " << type << " is not " << e.path); } + // NOTE: Must be Generic for the above to have passed + auto& gp = te.path.m_data.as_Generic(); + + ASSERT_BUG(sp, e.sub_patterns.size() != tup_var.size(), + "Enum pattern with an incorrect number of fields - " << e.path << " - expected " << tup_var.size() << ", got " << e.sub_patterns.size() + ); + + for( unsigned int i = 0; i < e.sub_patterns.size(); i ++ ) + { + if( monomorphise_type_needed(tup_var[i].ent) ) { + auto var_ty = monomorphise_type(sp, enm.m_params, gp.m_params, tup_var[i].ent); + this->add_binding(sp, e.sub_patterns[i], var_ty); + } + else { + // SAFE: Can't have a _ (monomorphise_type_needed checks for that) + this->add_binding(sp, e.sub_patterns[i], const_cast< ::HIR::TypeRef&>(tup_var[i].ent)); + } + } ) ) ), diff --git a/src/mir/from_hir.cpp b/src/mir/from_hir.cpp index b8953fec..55ce6cb1 100644 --- a/src/mir/from_hir.cpp +++ b/src/mir/from_hir.cpp @@ -81,6 +81,7 @@ namespace { destructure_from_ex(sp, *e.sub, ::MIR::LValue::make_Deref({ box$( mv$(lval) ) }), allow_refutable); ), (Tuple, + ASSERT_BUG(sp, e.glob_pos == ::HIR::Pattern::GlobPos::None, "Tuple .. should be eliminated"); for(unsigned int i = 0; i < e.sub_patterns.size(); i ++ ) { destructure_from_ex(sp, e.sub_patterns[i], ::MIR::LValue::make_Field({ box$( lval.clone() ), i}), allow_refutable); @@ -95,9 +96,6 @@ namespace { destructure_from_ex(sp, e.sub_patterns[i], ::MIR::LValue::make_Field({ box$( lval.clone() ), i}), allow_refutable); } ), - (StructTupleWildcard, - // Nothing. - ), (Struct, const auto& str = *e.binding; const auto& fields = str.m_data.as_Named(); @@ -125,9 +123,6 @@ namespace { destructure_from_ex(sp, e.sub_patterns[i], ::MIR::LValue::make_Field({ box$( lval_var.clone() ), i}), allow_refutable); } ), - (EnumTupleWildcard, - ASSERT_BUG(sp, allow_refutable, "Refutable pattern not expected - " << pat); - ), (EnumStruct, ASSERT_BUG(sp, allow_refutable, "Refutable pattern not expected - " << pat); const auto& enm = *e.binding_ptr; diff --git a/src/mir/from_hir_match.cpp b/src/mir/from_hir_match.cpp index 3ea61cf9..a2d786d8 100644 --- a/src/mir/from_hir_match.cpp +++ b/src/mir/from_hir_match.cpp @@ -949,6 +949,7 @@ void PatternRulesetBuilder::append_from(const Span& sp, const ::HIR::Pattern& pa } ), (Tuple, + ASSERT_BUG(sp, pe.glob_pos == ::HIR::Pattern::GlobPos::None, "Tuple .. should be eliminated"); assert(e.size() == pe.sub_patterns.size()); for(unsigned int i = 0; i < e.size(); i ++) { this->append_from(sp, pe.sub_patterns[i], e[i]); @@ -996,9 +997,6 @@ void PatternRulesetBuilder::append_from(const Span& sp, const ::HIR::Pattern& pa ), (StructTuple, TODO(sp, "Match over struct - Tuple + StructTuple"); - ), - (StructTupleWildcard, - TODO(sp, "Match over struct - Tuple + StructTupleWildcard"); ) ) ), @@ -1053,9 +1051,6 @@ void PatternRulesetBuilder::append_from(const Span& sp, const ::HIR::Pattern& pa } this->push_rule( PatternRule::make_Variant({ pe.binding_idx, mv$(sub_builder.m_rules) }) ); ), - (EnumTupleWildcard, - this->push_rule( PatternRule::make_Variant({ pe.binding_idx, {} }) ); - ), (EnumStruct, const auto& var_def = pe.binding_ptr->m_variants.at(pe.binding_idx); const auto& fields_def = var_def.second.as_Struct(); diff --git a/src/parse/pattern.cpp b/src/parse/pattern.cpp index 87f08d31..a2b5afb8 100644 --- a/src/parse/pattern.cpp +++ b/src/parse/pattern.cpp @@ -15,7 +15,7 @@ using AST::ExprNode; -::std::vector<AST::Pattern> Parse_PatternList(TokenStream& lex, bool is_refutable); +::AST::Pattern::TuplePat Parse_PatternList(TokenStream& lex, bool is_refutable); AST::Pattern Parse_PatternReal_Slice(TokenStream& lex, bool is_refutable); AST::Pattern Parse_PatternReal_Path(TokenStream& lex, AST::Path path, bool is_refutable); AST::Pattern Parse_PatternReal(TokenStream& lex, bool is_refutable); @@ -245,14 +245,9 @@ AST::Pattern Parse_PatternReal_Path(TokenStream& lex, AST::Path path, bool is_re switch( GET_TOK(tok, lex) ) { case TOK_PAREN_OPEN: - if( LOOK_AHEAD(lex) == TOK_DOUBLE_DOT ) { - GET_TOK(tok, lex); - GET_CHECK_TOK(tok, lex, TOK_PAREN_CLOSE); - return AST::Pattern( AST::Pattern::TagEnumVariant(), ::std::move(path) ); - } - return AST::Pattern( AST::Pattern::TagEnumVariant(), ::std::move(path), Parse_PatternList(lex, is_refutable) ); + return AST::Pattern( AST::Pattern::TagNamedTuple(), mv$(path), Parse_PatternList(lex, is_refutable) ); case TOK_BRACE_OPEN: - return Parse_PatternStruct(lex, ::std::move(path), is_refutable); + return Parse_PatternStruct(lex, mv$(path), is_refutable); default: PUTBACK(tok, lex); return AST::Pattern( AST::Pattern::TagValue(), AST::Pattern::Value::make_Named(mv$(path)) ); @@ -315,15 +310,29 @@ AST::Pattern Parse_PatternReal_Slice(TokenStream& lex, bool is_refutable) return rv; } -::std::vector<AST::Pattern> Parse_PatternList(TokenStream& lex, bool is_refutable) +::AST::Pattern::TuplePat Parse_PatternList(TokenStream& lex, bool is_refutable) { TRACE_FUNCTION; + auto sp = lex.start_span(); Token tok; - ::std::vector<AST::Pattern> child_pats; + + auto glob_pos = ::AST::Pattern::TupleGlob::None; auto end = TOK_PAREN_CLOSE; + // 1. Leading `..` + if( LOOK_AHEAD(lex) == TOK_DOUBLE_DOT ) { + GET_TOK(tok, lex); + glob_pos = ::AST::Pattern::TupleGlob::Start; + if( GET_TOK(tok, lex) != TOK_COMMA ) { + CHECK_TOK(tok, end); + return ::AST::Pattern::TuplePat { glob_pos, {} }; + } + } + + // 2. Body + ::std::vector<AST::Pattern> child_pats; do { - if( GET_TOK(tok, lex) == end ) + if( GET_TOK(tok, lex) == end || tok.type() == TOK_DOUBLE_DOT ) break; else PUTBACK(tok, lex); @@ -332,8 +341,17 @@ AST::Pattern Parse_PatternReal_Slice(TokenStream& lex, bool is_refutable) DEBUG("pat = " << pat); child_pats.push_back( ::std::move(pat) ); } while( GET_TOK(tok, lex) == TOK_COMMA ); + + // 3. Trailing `..` + if( tok.type() == TOK_DOUBLE_DOT ) { + if( glob_pos != ::AST::Pattern::TupleGlob::None ) { + ERROR(lex.end_span(sp), E0000, "Multiple instances of .. in pattern"); + } + glob_pos = ::AST::Pattern::TupleGlob::End; + GET_TOK(tok, lex); + } CHECK_TOK(tok, end); - return child_pats; + return ::AST::Pattern::TuplePat { glob_pos, mv$(child_pats) }; } AST::Pattern Parse_PatternStruct(TokenStream& lex, AST::Path path, bool is_refutable) diff --git a/src/resolve/absolute.cpp b/src/resolve/absolute.cpp index f2e58703..1aec18b0 100644 --- a/src/resolve/absolute.cpp +++ b/src/resolve/absolute.cpp @@ -1194,12 +1194,9 @@ void Resolve_Absolute_Pattern(Context& context, bool allow_refutable, ::AST::Pa for(auto& sp : e.sub_patterns) Resolve_Absolute_Pattern(context, allow_refutable, sp); ), - (WildcardStructTuple, - Resolve_Absolute_Path(context, pat.span(), Context::LookupMode::Pattern, e.path); - ), (StructTuple, Resolve_Absolute_Path(context, pat.span(), Context::LookupMode::Pattern, e.path); - for(auto& sp : e.sub_patterns) + for(auto& sp : e.tup_pat.sub_patterns) Resolve_Absolute_Pattern(context, allow_refutable, sp); ), (Struct, |