diff options
author | John Hodge <tpg@mutabah.net> | 2016-08-19 10:27:38 +0800 |
---|---|---|
committer | John Hodge <tpg@mutabah.net> | 2016-08-19 10:27:38 +0800 |
commit | a3e8257c4f77f197c9be2dbae7aaddb81257abb2 (patch) | |
tree | 598c815b4e42041966e3a0834a118b9a7c56411f | |
parent | 64c957b03ede8b0af825b50e6e551c61444a3275 (diff) | |
download | mrust-a3e8257c4f77f197c9be2dbae7aaddb81257abb2.tar.gz |
Patterns - Support tuples with .. (fully)
-rw-r--r-- | src/ast/pattern.cpp | 17 | ||||
-rw-r--r-- | src/ast/pattern.hpp | 22 | ||||
-rw-r--r-- | src/dump_as_rust.cpp | 32 | ||||
-rw-r--r-- | src/expand/mod.cpp | 8 | ||||
-rw-r--r-- | src/hir/from_ast.cpp | 133 | ||||
-rw-r--r-- | src/hir/pattern.cpp | 20 | ||||
-rw-r--r-- | src/hir/pattern.hpp | 6 | ||||
-rw-r--r-- | src/hir/visitor.cpp | 6 | ||||
-rw-r--r-- | src/hir_expand/closures.cpp | 8 | ||||
-rw-r--r-- | src/hir_typeck/expr_cs.cpp | 52 | ||||
-rw-r--r-- | src/mir/from_hir.cpp | 4 | ||||
-rw-r--r-- | src/mir/from_hir_match.cpp | 1 | ||||
-rw-r--r-- | src/parse/expr.cpp | 2 | ||||
-rw-r--r-- | src/parse/pattern.cpp | 63 | ||||
-rw-r--r-- | src/resolve/absolute.cpp | 8 |
15 files changed, 206 insertions, 176 deletions
diff --git a/src/ast/pattern.cpp b/src/ast/pattern.cpp index bc961e63..06b96b48 100644 --- a/src/ast/pattern.cpp +++ b/src/ast/pattern.cpp @@ -59,12 +59,16 @@ namespace AST { } ::std::ostream& operator<<(::std::ostream& os, const Pattern::TuplePat& val) { - if( val.glob_pos == Pattern::TupleGlob::Start ) { + if( val.has_wildcard ) + { + os << val.start; os << ".., "; + os << val.end; } - os << val.sub_patterns; - if( val.glob_pos == Pattern::TupleGlob::End ) { - os << ".., "; + else + { + os << val.start; + assert(val.end.size() == 0); } return os; } @@ -169,8 +173,9 @@ AST::Pattern AST::Pattern::clone() const } static TuplePat clone_tup(const TuplePat& p) { return TuplePat { - p.glob_pos, - H::clone_list(p.sub_patterns) + H::clone_list(p.start), + p.has_wildcard, + H::clone_list(p.end) }; } static AST::Pattern::Value clone_val(const AST::Pattern::Value& v) { diff --git a/src/ast/pattern.hpp b/src/ast/pattern.hpp index 4db20fd5..687d1e34 100644 --- a/src/ast/pattern.hpp +++ b/src/ast/pattern.hpp @@ -60,14 +60,10 @@ 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; + ::std::vector<Pattern> start; + bool has_wildcard; + ::std::vector<Pattern> end; }; TAGGED_UNION(Data, Any, @@ -136,18 +132,18 @@ public: } struct TagTuple {}; - 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) } ) ) + m_data( Data::make_Tuple( TuplePat { mv$(pats), false, {} } ) ) + {} + Pattern(TagTuple, TuplePat pat): + m_data( Data::make_Tuple( mv$(pat) ) ) {} struct TagNamedTuple {}; Pattern(TagNamedTuple, Path path, ::std::vector<Pattern> pats): - m_data( Data::make_StructTuple( { ::std::move(path), TuplePat { TupleGlob::None, ::std::move(pats) } } ) ) + m_data( Data::make_StructTuple( { mv$(path), TuplePat { mv$(pats), false, {} } } ) ) {} - Pattern(TagNamedTuple, Path path, TuplePat pat = TuplePat { TupleGlob::Start, {} }): + Pattern(TagNamedTuple, Path path, TuplePat pat = TuplePat { {}, false, {} }): m_data( Data::make_StructTuple( { ::std::move(path), ::std::move(pat) } ) ) {} diff --git a/src/dump_as_rust.cpp b/src/dump_as_rust.cpp index 1f51f317..3c3a215d 100644 --- a/src/dump_as_rust.cpp +++ b/src/dump_as_rust.cpp @@ -535,6 +535,7 @@ private: void print_params(const AST::GenericParams& params); void print_bounds(const AST::GenericParams& params); + void print_pattern_tuple(const AST::Pattern::TuplePat& v); void print_pattern(const AST::Pattern& p, bool is_refutable); void print_type(const TypeRef& t); @@ -772,6 +773,15 @@ void RustPrinter::print_bounds(const AST::GenericParams& params) } } +void RustPrinter::print_pattern_tuple(const AST::Pattern::TuplePat& v) +{ + m_os << v.start; + if( v.has_wildcard ) + { + m_os << ".., "; + m_os << v.end; + } +} void RustPrinter::print_pattern(const AST::Pattern& p, bool is_refutable) { if( p.binding().is_valid() ) { @@ -814,16 +824,7 @@ void RustPrinter::print_pattern(const AST::Pattern& p, bool is_refutable) ), (StructTuple, m_os << v.path << "("; - 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 << " .."; - } + this->print_pattern_tuple(v.tup_pat); m_os << ")"; ), (Struct, { @@ -838,16 +839,7 @@ void RustPrinter::print_pattern(const AST::Pattern& p, bool is_refutable) }), (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 << " .."; - } + this->print_pattern_tuple(v); m_os << ")"; ), (Slice, diff --git a/src/expand/mod.cpp b/src/expand/mod.cpp index 6a7d81ee..01342ea5 100644 --- a/src/expand/mod.cpp +++ b/src/expand/mod.cpp @@ -158,11 +158,15 @@ void Expand_Pattern(bool is_early, ::AST::Crate& crate, LList<const AST::Module* //Expand_Expr(is_early, crate, modstack, e.end); ), (Tuple, - for(auto& sp : e.sub_patterns) + for(auto& sp : e.start) + Expand_Pattern(is_early, crate, modstack, mod, sp); + for(auto& sp : e.end) Expand_Pattern(is_early, crate, modstack, mod, sp); ), (StructTuple, - for(auto& sp : e.tup_pat.sub_patterns) + for(auto& sp : e.tup_pat.start) + Expand_Pattern(is_early, crate, modstack, mod, sp); + for(auto& sp : e.tup_pat.end) Expand_Pattern(is_early, crate, modstack, mod, sp); ), (Struct, diff --git a/src/hir/from_ast.cpp b/src/hir/from_ast.cpp index 1bf63ac3..5c84b8f1 100644 --- a/src/hir/from_ast.cpp +++ b/src/hir/from_ast.cpp @@ -132,18 +132,6 @@ const ::HIR::SimplePath path_Sized = ::HIR::SimplePath("", {"marker", "Sized"}); 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), @@ -177,54 +165,67 @@ const ::HIR::SimplePath path_Sized = ::HIR::SimplePath("", {"marker", "Sized"}); }; ), (Tuple, - auto glob_pos = H::lowerhir_globpos( e.glob_pos ); - auto sub_patterns = H::lowerhir_patternvec( e.sub_patterns ); + auto leading = H::lowerhir_patternvec( e.start ); + auto trailing = H::lowerhir_patternvec( e.end ); - return ::HIR::Pattern { - mv$(binding), - ::HIR::Pattern::Data::make_Tuple({ - glob_pos, mv$(sub_patterns) - }) - }; + if( e.has_wildcard ) + { + return ::HIR::Pattern { + mv$(binding), + ::HIR::Pattern::Data::make_SplitTuple({ + mv$(leading), mv$(trailing) + }) + }; + } + else + { + assert( trailing.size() == 0 ); + return ::HIR::Pattern { + mv$(binding), + ::HIR::Pattern::Data::make_Tuple({ + mv$(leading) + }) + }; + } ), (StructTuple, - auto sub_patterns = H::lowerhir_patternvec( e.tup_pat.sub_patterns ); - + unsigned int leading_count = e.tup_pat.start.size(); + unsigned int trailing_count = e.tup_pat.end .size(); 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()); + unsigned int field_count = var.as_Tuple().m_sub_types.size(); + ::std::vector<HIR::Pattern> sub_patterns; + + if( e.tup_pat.has_wildcard ) { + sub_patterns.reserve( field_count ); + if( leading_count + trailing_count > field_count ) { + ERROR(pat.span(), E0000, "Enum variant pattern has too many fields - " << field_count << " max, got " << leading_count + trailing_count); } - 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()); + unsigned int padding_count = field_count - leading_count - trailing_count; + for(const auto& subpat : e.tup_pat.start) { + sub_patterns.push_back( LowerHIR_Pattern(subpat) ); } - while( sub_patterns.size() < var_tup_tys.size() ) { - sub_patterns.insert( sub_patterns.begin(), ::HIR::Pattern() ); + for(unsigned int i = 0; i < padding_count; i ++) { + sub_patterns.push_back( ::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()); + for(const auto& subpat : e.tup_pat.end) { + sub_patterns.push_back( LowerHIR_Pattern(subpat) ); } - while( sub_patterns.size() < var_tup_tys.size() ) { - sub_patterns.insert( sub_patterns.end(), ::HIR::Pattern() ); + } + else { + assert( trailing_count == 0 ); + + if( leading_count != field_count ) { + ERROR(pat.span(), E0000, "Enum variant pattern has a mismatched field count - " << field_count << " exp, got " << leading_count); } - break; + sub_patterns = H::lowerhir_patternvec( e.tup_pat.start ); } + return ::HIR::Pattern { mv$(binding), ::HIR::Pattern::Data::make_EnumTuple({ @@ -235,34 +236,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()); + unsigned int field_count = pb.struct_->m_data.as_Tuple().ents.size(); + ::std::vector<HIR::Pattern> sub_patterns; + + if( e.tup_pat.has_wildcard ) { + sub_patterns.reserve( field_count ); + if( leading_count + trailing_count > field_count ) { + ERROR(pat.span(), E0000, "Struct pattern has too many fields - " << field_count << " max, got " << leading_count + trailing_count); } - 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()); + unsigned int padding_count = field_count - leading_count - trailing_count; + for(const auto& subpat : e.tup_pat.start) { + sub_patterns.push_back( LowerHIR_Pattern(subpat) ); } - while( sub_patterns.size() < tys.size() ) { - sub_patterns.insert( sub_patterns.begin(), ::HIR::Pattern() ); + for(unsigned int i = 0; i < padding_count; i ++) { + sub_patterns.push_back( ::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()); + for(const auto& subpat : e.tup_pat.end) { + sub_patterns.push_back( LowerHIR_Pattern(subpat) ); } - while( sub_patterns.size() < tys.size() ) { - sub_patterns.insert( sub_patterns.end(), ::HIR::Pattern() ); + } + else { + assert( trailing_count == 0 ); + + if( leading_count != field_count ) { + ERROR(pat.span(), E0000, "Struct pattern has a mismatched field count - " << field_count << " exp, got " << leading_count); } - break; + sub_patterns = H::lowerhir_patternvec( e.tup_pat.start ); } + return ::HIR::Pattern { mv$(binding), ::HIR::Pattern::Data::make_StructTuple({ diff --git a/src/hir/pattern.cpp b/src/hir/pattern.cpp index d6715f0c..c5c2ef93 100644 --- a/src/hir/pattern.cpp +++ b/src/hir/pattern.cpp @@ -47,12 +47,17 @@ 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 << ")"; + ), + (SplitTuple, + os << "("; + for(const auto& s : e.leading) + os << s << ", "; + os << ".., "; + for(const auto& s : e.trailing) + os << s << ", "; os << ")"; ), (StructValue, @@ -171,10 +176,15 @@ namespace { ), (Tuple, return Pattern(m_binding, Data::make_Tuple({ - e.glob_pos, clone_pat_vec(e.sub_patterns) })); ), + (SplitTuple, + return Pattern(m_binding, Data::make_SplitTuple({ + clone_pat_vec(e.leading), + clone_pat_vec(e.trailing) + })); + ), (StructValue, return Pattern(m_binding, Data::make_StructValue({ e.path.clone(), e.binding diff --git a/src/hir/pattern.hpp b/src/hir/pattern.hpp index 13877dbc..205acfcb 100644 --- a/src/hir/pattern.hpp +++ b/src/hir/pattern.hpp @@ -70,10 +70,12 @@ struct Pattern (Box, struct { ::std::unique_ptr<Pattern> sub; }), (Ref, struct { ::HIR::BorrowType type; ::std::unique_ptr<Pattern> sub; } ), (Tuple, struct { - // NOTE: Has the glob still because the tuple isn't yet known - GlobPos glob_pos; ::std::vector<Pattern> sub_patterns; }), + (SplitTuple, struct { + ::std::vector<Pattern> leading; + ::std::vector<Pattern> trailing; + }), (StructValue, struct { GenericPath path; const Struct* binding; diff --git a/src/hir/visitor.cpp b/src/hir/visitor.cpp index cadf3722..2471bfa2 100644 --- a/src/hir/visitor.cpp +++ b/src/hir/visitor.cpp @@ -330,6 +330,12 @@ void ::HIR::Visitor::visit_pattern(::HIR::Pattern& pat) for(auto& sp : e.sub_patterns) this->visit_pattern(sp); ), + (SplitTuple, + for(auto& sp : e.leading) + this->visit_pattern(sp); + for(auto& sp : e.trailing) + this->visit_pattern(sp); + ), (StructValue, this->visit_generic_path(e.path, ::HIR::Visitor::PathContext::TYPE); ), diff --git a/src/hir_expand/closures.cpp b/src/hir_expand/closures.cpp index 52ef1629..74255849 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({ ::HIR::Pattern::GlobPos::None, mv$(args_pat_inner) }) }; + ::HIR::Pattern args_pat { {}, ::HIR::Pattern::Data::make_Tuple({ 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); @@ -609,6 +609,12 @@ namespace { for( const auto& subpat : e.sub_patterns ) add_closure_def_from_pattern(sp, subpat); ), + (SplitTuple, + for( const auto& subpat : e.leading ) + add_closure_def_from_pattern(sp, subpat); + for( const auto& subpat : e.trailing ) + add_closure_def_from_pattern(sp, subpat); + ), (Slice, for(const auto& sub : e.sub_patterns) add_closure_def_from_pattern(sp, sub); diff --git a/src/hir_typeck/expr_cs.cpp b/src/hir_typeck/expr_cs.cpp index 9585b8c5..159209fb 100644 --- a/src/hir_typeck/expr_cs.cpp +++ b/src/hir_typeck/expr_cs.cpp @@ -2427,6 +2427,7 @@ void Context::equate_types(const Span& sp, const ::HIR::TypeRef& li, const ::HIR } } } +// NOTE: Mutates the pattern to add ivars to contained paths void Context::add_binding(const Span& sp, ::HIR::Pattern& pat, const ::HIR::TypeRef& type) { TRACE_FUNCTION_F("pat = " << pat << ", type = " << type); @@ -2503,36 +2504,14 @@ void Context::add_binding(const Span& sp, ::HIR::Pattern& pat, const ::HIR::Type const auto& ty = this->get_type(type); TU_IFLET(::HIR::TypeRef::Data, ty.m_data, Tuple, te, - 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; + 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); } for(unsigned int i = 0; i < e.sub_patterns.size(); i ++ ) - this->add_binding(sp, e.sub_patterns[i], te[field_ofs+i] ); + this->add_binding(sp, e.sub_patterns[i], te[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 ++ ) { @@ -2542,6 +2521,29 @@ void Context::add_binding(const Span& sp, ::HIR::Pattern& pat, const ::HIR::Type this->equate_types(sp, ty, ::HIR::TypeRef( mv$(sub_types) )); } ), + (SplitTuple, + const auto& ty = this->get_type(type); + TU_IFLET(::HIR::TypeRef::Data, ty.m_data, Tuple, te, + // - Should have been checked in AST resolve + ASSERT_BUG(sp, e.leading.size() + e.trailing.size() <= te.size(), "Invalid field count for split tuple pattern"); + + unsigned int tup_idx = 0; + for(auto& subpat : e.leading) { + this->add_binding(sp, subpat, te[tup_idx++]); + } + tup_idx = te.size() - e.trailing.size(); + for(auto& subpat : e.leading) { + this->add_binding(sp, subpat, te[tup_idx++]); + } + ) + else { + if( !ty.m_data.is_Infer() ) { + ERROR(sp, E0000, "Tuple pattern on non-tuple"); + } + + TODO(sp, "Handle split tuple patterns when type isn't known in starting pass"); + } + ), (Slice, const auto& ty = this->get_type(type); TU_IFLET(::HIR::TypeRef::Data, ty.m_data, Slice, te, diff --git a/src/mir/from_hir.cpp b/src/mir/from_hir.cpp index 55ce6cb1..800398b7 100644 --- a/src/mir/from_hir.cpp +++ b/src/mir/from_hir.cpp @@ -81,12 +81,14 @@ 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); } ), + (SplitTuple, + BUG(sp, "Tuple .. should be eliminated"); + ), (StructValue, // Nothing. ), diff --git a/src/mir/from_hir_match.cpp b/src/mir/from_hir_match.cpp index a2d786d8..5fb4e263 100644 --- a/src/mir/from_hir_match.cpp +++ b/src/mir/from_hir_match.cpp @@ -949,7 +949,6 @@ 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]); diff --git a/src/parse/expr.cpp b/src/parse/expr.cpp index 44f0b35d..682d641c 100644 --- a/src/parse/expr.cpp +++ b/src/parse/expr.cpp @@ -730,7 +730,7 @@ LEFTASSOC(Parse_Expr10, Parse_Expr11, // 11: Cast
LEFTASSOC(Parse_Expr11, Parse_Expr12,
case TOK_RWORD_AS:
- rv = NEWNODE( AST::ExprNode_Cast, ::std::move(rv), Parse_Type(lex) );
+ rv = NEWNODE( AST::ExprNode_Cast, ::std::move(rv), Parse_Type(lex, false) );
break;
)
// 12: Type Ascription
diff --git a/src/parse/pattern.cpp b/src/parse/pattern.cpp index a2b5afb8..ded81103 100644 --- a/src/parse/pattern.cpp +++ b/src/parse/pattern.cpp @@ -15,7 +15,7 @@ using AST::ExprNode; -::AST::Pattern::TuplePat Parse_PatternList(TokenStream& lex, bool is_refutable); +::AST::Pattern::TuplePat Parse_PatternTuple(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); @@ -231,7 +231,7 @@ AST::Pattern Parse_PatternReal1(TokenStream& lex, bool is_refutable) // TODO: Differentiate byte and UTF-8 strings return AST::Pattern( AST::Pattern::TagValue(), AST::Pattern::Value::make_String( mv$(tok.str()) ) ); case TOK_PAREN_OPEN: - return AST::Pattern( AST::Pattern::TagTuple(), Parse_PatternList(lex, is_refutable) ); + return AST::Pattern( AST::Pattern::TagTuple(), Parse_PatternTuple(lex, is_refutable) ); case TOK_SQUARE_OPEN: return Parse_PatternReal_Slice(lex, is_refutable); default: @@ -245,7 +245,7 @@ AST::Pattern Parse_PatternReal_Path(TokenStream& lex, AST::Path path, bool is_re switch( GET_TOK(tok, lex) ) { case TOK_PAREN_OPEN: - return AST::Pattern( AST::Pattern::TagNamedTuple(), mv$(path), Parse_PatternList(lex, is_refutable) ); + return AST::Pattern( AST::Pattern::TagNamedTuple(), mv$(path), Parse_PatternTuple(lex, is_refutable) ); case TOK_BRACE_OPEN: return Parse_PatternStruct(lex, mv$(path), is_refutable); default: @@ -310,48 +310,49 @@ AST::Pattern Parse_PatternReal_Slice(TokenStream& lex, bool is_refutable) return rv; } -::AST::Pattern::TuplePat Parse_PatternList(TokenStream& lex, bool is_refutable) +::AST::Pattern::TuplePat Parse_PatternTuple(TokenStream& lex, bool is_refutable) { TRACE_FUNCTION; auto sp = lex.start_span(); Token tok; - 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; + ::std::vector<AST::Pattern> leading; + while( LOOK_AHEAD(lex) != TOK_PAREN_CLOSE && LOOK_AHEAD(lex) != TOK_DOUBLE_DOT ) + { + leading.push_back( Parse_Pattern(lex, is_refutable) ); + if( GET_TOK(tok, lex) != TOK_COMMA ) { - CHECK_TOK(tok, end); - return ::AST::Pattern::TuplePat { glob_pos, {} }; + CHECK_TOK(tok, TOK_PAREN_CLOSE); + return AST::Pattern::TuplePat { mv$(leading), false, {} }; } } - // 2. Body - ::std::vector<AST::Pattern> child_pats; - do { - if( GET_TOK(tok, lex) == end || tok.type() == TOK_DOUBLE_DOT ) - break; - else - PUTBACK(tok, lex); + if( LOOK_AHEAD(lex) != TOK_DOUBLE_DOT ) + { + GET_TOK(tok, lex); - AST::Pattern pat = Parse_Pattern(lex, is_refutable); - DEBUG("pat = " << pat); - child_pats.push_back( ::std::move(pat) ); - } while( GET_TOK(tok, lex) == TOK_COMMA ); + CHECK_TOK(tok, TOK_PAREN_CLOSE); + return AST::Pattern::TuplePat { mv$(leading), false, {} }; + } + GET_CHECK_TOK(tok, lex, TOK_DOUBLE_DOT); - // 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"); + ::std::vector<AST::Pattern> trailing; + if( GET_TOK(tok, lex) == TOK_COMMA ) + { + while( LOOK_AHEAD(lex) != TOK_PAREN_CLOSE ) + { + trailing.push_back( Parse_Pattern(lex, is_refutable) ); + + if( GET_TOK(tok, lex) != TOK_COMMA ) { + PUTBACK(tok, lex); + break; + } } - glob_pos = ::AST::Pattern::TupleGlob::End; GET_TOK(tok, lex); } - CHECK_TOK(tok, end); - return ::AST::Pattern::TuplePat { glob_pos, mv$(child_pats) }; + + CHECK_TOK(tok, TOK_PAREN_CLOSE); + return ::AST::Pattern::TuplePat { mv$(leading), true, mv$(trailing) }; } 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 1aec18b0..8938fbb1 100644 --- a/src/resolve/absolute.cpp +++ b/src/resolve/absolute.cpp @@ -1191,12 +1191,16 @@ void Resolve_Absolute_Pattern(Context& context, bool allow_refutable, ::AST::Pa Resolve_Absolute_PatternValue(context, pat.span(), e.end); ), (Tuple, - for(auto& sp : e.sub_patterns) + for(auto& sp : e.start) + Resolve_Absolute_Pattern(context, allow_refutable, sp); + for(auto& sp : e.end) Resolve_Absolute_Pattern(context, allow_refutable, sp); ), (StructTuple, Resolve_Absolute_Path(context, pat.span(), Context::LookupMode::Pattern, e.path); - for(auto& sp : e.tup_pat.sub_patterns) + for(auto& sp : e.tup_pat.start) + Resolve_Absolute_Pattern(context, allow_refutable, sp); + for(auto& sp : e.tup_pat.end) Resolve_Absolute_Pattern(context, allow_refutable, sp); ), (Struct, |