summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Hodge <tpg@mutabah.net>2016-08-19 10:27:38 +0800
committerJohn Hodge <tpg@mutabah.net>2016-08-19 10:27:38 +0800
commita3e8257c4f77f197c9be2dbae7aaddb81257abb2 (patch)
tree598c815b4e42041966e3a0834a118b9a7c56411f
parent64c957b03ede8b0af825b50e6e551c61444a3275 (diff)
downloadmrust-a3e8257c4f77f197c9be2dbae7aaddb81257abb2.tar.gz
Patterns - Support tuples with .. (fully)
-rw-r--r--src/ast/pattern.cpp17
-rw-r--r--src/ast/pattern.hpp22
-rw-r--r--src/dump_as_rust.cpp32
-rw-r--r--src/expand/mod.cpp8
-rw-r--r--src/hir/from_ast.cpp133
-rw-r--r--src/hir/pattern.cpp20
-rw-r--r--src/hir/pattern.hpp6
-rw-r--r--src/hir/visitor.cpp6
-rw-r--r--src/hir_expand/closures.cpp8
-rw-r--r--src/hir_typeck/expr_cs.cpp52
-rw-r--r--src/mir/from_hir.cpp4
-rw-r--r--src/mir/from_hir_match.cpp1
-rw-r--r--src/parse/expr.cpp2
-rw-r--r--src/parse/pattern.cpp63
-rw-r--r--src/resolve/absolute.cpp8
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,