summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/ast/pattern.cpp31
-rw-r--r--src/ast/pattern.hpp46
-rw-r--r--src/dump_as_rust.cpp22
-rw-r--r--src/expand/derive.cpp10
-rw-r--r--src/expand/mod.cpp10
-rw-r--r--src/hir/from_ast.cpp116
-rw-r--r--src/hir/pattern.cpp29
-rw-r--r--src/hir/pattern.hpp21
-rw-r--r--src/hir/visitor.cpp6
-rw-r--r--src/hir_conv/bind.cpp20
-rw-r--r--src/hir_expand/closures.cpp6
-rw-r--r--src/hir_typeck/expr_cs.cpp130
-rw-r--r--src/mir/from_hir.cpp7
-rw-r--r--src/mir/from_hir_match.cpp7
-rw-r--r--src/parse/pattern.cpp42
-rw-r--r--src/resolve/absolute.cpp5
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,