summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Hodge <tpg@mutabah.net>2016-05-29 22:30:28 +0800
committerJohn Hodge <tpg@mutabah.net>2016-05-29 22:30:28 +0800
commit7890a6dba8fcdb9454b2e58ea1363f270d2da2c5 (patch)
treefa51d39712f552c78b390d61d19793c737d5238a
parent73bcd2fb0bda8f939a6c1385b419a67ad8eeef2c (diff)
downloadmrust-7890a6dba8fcdb9454b2e58ea1363f270d2da2c5.tar.gz
Parse/AST/HIR - Support Enum::Var(..) and Struct { .. } patters properly
-rw-r--r--src/ast/pattern.cpp12
-rw-r--r--src/ast/pattern.hpp10
-rw-r--r--src/dump_as_rust.cpp8
-rw-r--r--src/expand/mod.cpp2
-rw-r--r--src/hir/from_ast.cpp33
-rw-r--r--src/hir/pattern.hpp11
-rw-r--r--src/hir/visitor.cpp6
-rw-r--r--src/hir_conv/bind.cpp30
-rw-r--r--src/hir_typeck/expr.cpp52
-rw-r--r--src/parse/pattern.cpp13
-rw-r--r--src/resolve/absolute.cpp4
11 files changed, 168 insertions, 13 deletions
diff --git a/src/ast/pattern.cpp b/src/ast/pattern.cpp
index ca5378e1..9e17abcf 100644
--- a/src/ast/pattern.cpp
+++ b/src/ast/pattern.cpp
@@ -70,6 +70,9 @@ namespace AST {
(Tuple,
os << "(" << ent.sub_patterns << ")";
),
+ (WildcardStructTuple,
+ os << ent.path << " (..)";
+ ),
(StructTuple,
os << ent.path << " (" << ent.sub_patterns << ")";
),
@@ -220,6 +223,9 @@ AST::Pattern AST::Pattern::clone() const
(Tuple,
rv.m_data = Data::make_Tuple({ H::clone_list(e.sub_patterns) });
),
+ (WildcardStructTuple,
+ rv.m_data = Data::make_WildcardStructTuple({ ::AST::Path(e.path) });
+ ),
(StructTuple,
rv.m_data = Data::make_StructTuple({ ::AST::Path(e.path), H::clone_list(e.sub_patterns) });
),
@@ -263,6 +269,9 @@ SERIALISE_TYPE(Pattern::, "Pattern", {
(Tuple,
s << e.sub_patterns;
),
+ (WildcardStructTuple,
+ s << e.path;
+ ),
(StructTuple,
s << e.path;
s << e.sub_patterns;
@@ -304,6 +313,9 @@ SERIALISE_TYPE(Pattern::, "Pattern", {
_D(Tuple,
s.item( ent.sub_patterns );
)
+ _D(WildcardStructTuple,
+ s.item( ent.path );
+ )
_D(StructTuple,
s.item( ent.path );
s.item( ent.sub_patterns );
diff --git a/src/ast/pattern.hpp b/src/ast/pattern.hpp
index 79d349c2..699ed466 100644
--- a/src/ast/pattern.hpp
+++ b/src/ast/pattern.hpp
@@ -40,8 +40,9 @@ public:
(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; } ),
- (Struct, struct { Path path; ::std::vector< ::std::pair< ::std::string, Pattern> > sub_patterns; } ),
+ (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; } )
);
private:
@@ -110,13 +111,16 @@ public:
{}
struct TagEnumVariant {};
+ Pattern(TagEnumVariant, Path path):
+ m_data( Data::make_WildcardStructTuple( { ::std::move(path) } ) )
+ {}
Pattern(TagEnumVariant, Path path, ::std::vector<Pattern> sub_patterns):
m_data( Data::make_StructTuple( { ::std::move(path), ::std::move(sub_patterns) } ) )
{}
struct TagStruct {};
- Pattern(TagStruct, Path path, ::std::vector< ::std::pair< ::std::string,Pattern> > sub_patterns):
- m_data( Data::make_Struct( { ::std::move(path), ::std::move(sub_patterns) } ) )
+ Pattern(TagStruct, Path path, ::std::vector< ::std::pair< ::std::string,Pattern> > sub_patterns, bool is_exhaustive):
+ m_data( Data::make_Struct( { ::std::move(path), ::std::move(sub_patterns), is_exhaustive } ) )
{}
struct TagSlice {};
diff --git a/src/dump_as_rust.cpp b/src/dump_as_rust.cpp
index 4091842a..2d079223 100644
--- a/src/dump_as_rust.cpp
+++ b/src/dump_as_rust.cpp
@@ -808,15 +808,17 @@ void RustPrinter::print_pattern(const AST::Pattern& p, bool is_refutable)
m_os << " ... " << v.end;
}
),
- (StructTuple, {
- const auto& v = p.data().as_StructTuple();
+ (WildcardStructTuple,
+ m_os << v.path << "(..)";
+ ),
+ (StructTuple,
m_os << v.path << "(";
for(const auto& sp : v.sub_patterns) {
print_pattern(sp, is_refutable);
m_os << ",";
}
m_os << ")";
- }),
+ ),
(Struct, {
const auto& v = p.data().as_Struct();
m_os << v.path << "(";
diff --git a/src/expand/mod.cpp b/src/expand/mod.cpp
index c46c7d84..62425f86 100644
--- a/src/expand/mod.cpp
+++ b/src/expand/mod.cpp
@@ -161,6 +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)
Expand_Pattern(is_early, crate, modstack, mod, sp);
diff --git a/src/hir/from_ast.cpp b/src/hir/from_ast.cpp
index a3584663..8681a078 100644
--- a/src/hir/from_ast.cpp
+++ b/src/hir/from_ast.cpp
@@ -88,6 +88,8 @@
::HIR::Pattern LowerHIR_Pattern(const ::AST::Pattern& pat)
{
+ TRACE_FUNCTION_F("@" << pat.span().filename << ":" << pat.span().start_line << " pat = " << pat);
+
::HIR::PatternBinding binding;
if( pat.binding() != "" )
{
@@ -144,6 +146,31 @@
};
),
+ (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)
@@ -191,7 +218,8 @@
::HIR::Pattern::Data::make_EnumStruct({
LowerHIR_GenericPath(pat.span(), e.path),
nullptr, 0,
- mv$(sub_patterns)
+ mv$(sub_patterns),
+ e.is_exhaustive
})
};
),
@@ -201,7 +229,8 @@
::HIR::Pattern::Data::make_Struct({
LowerHIR_GenericPath(pat.span(), e.path),
nullptr,
- mv$(sub_patterns)
+ mv$(sub_patterns),
+ e.is_exhaustive
})
};
)
diff --git a/src/hir/pattern.hpp b/src/hir/pattern.hpp
index fc763f54..c7b0fe7d 100644
--- a/src/hir/pattern.hpp
+++ b/src/hir/pattern.hpp
@@ -65,10 +65,15 @@ struct Pattern
const Struct* binding;
::std::vector<Pattern> sub_patterns;
} ),
+ (StructTupleWildcard, struct {
+ GenericPath path;
+ const Struct* binding;
+ }),
(Struct, struct {
GenericPath path;
const Struct* binding;
::std::vector< ::std::pair< ::std::string, Pattern> > sub_patterns;
+ bool is_exhaustive;
} ),
// Refutable
(Value, struct { Value val; } ),
@@ -79,11 +84,17 @@ 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;
unsigned binding_idx;
::std::vector< ::std::pair< ::std::string, Pattern> > sub_patterns;
+ bool is_exhaustive;
} ),
(Slice, struct {
::std::vector<Pattern> sub_patterns;
diff --git a/src/hir/visitor.cpp b/src/hir/visitor.cpp
index 33ac6505..23acf4e4 100644
--- a/src/hir/visitor.cpp
+++ b/src/hir/visitor.cpp
@@ -300,6 +300,9 @@ void ::HIR::Visitor::visit_pattern(::HIR::Pattern& pat)
for(auto& sp : e.sub_patterns)
this->visit_pattern(sp);
),
+ (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)
@@ -318,6 +321,9 @@ void ::HIR::Visitor::visit_pattern(::HIR::Pattern& pat)
this->visit_pattern_val(e.start);
this->visit_pattern_val(e.end);
),
+ (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 948a3d75..97f52cc9 100644
--- a/src/hir_conv/bind.cpp
+++ b/src/hir_conv/bind.cpp
@@ -125,6 +125,18 @@ namespace {
fix_type_params(sp, str.m_params, e.path.m_params);
e.binding = &str;
),
+ (StructTupleWildcard,
+ const auto& str = *reinterpret_cast< const ::HIR::Struct*>( get_type_pointer(sp, m_crate, e.path.m_path, Target::Struct) );
+ TU_IFLET(::HIR::Struct::Data, str.m_data, Tuple, _,
+ // All good
+ )
+ else {
+ ERROR(sp, E0000, "Struct tuple pattern on non-tuple struct " << e.path);
+ }
+
+ fix_type_params(sp, str.m_params, e.path.m_params);
+ e.binding = &str;
+ ),
(Struct,
const auto& str = *reinterpret_cast< const ::HIR::Struct*>( get_type_pointer(sp, m_crate, e.path.m_path, Target::Struct) );
TU_IFLET(::HIR::Struct::Data, str.m_data, Named, _,
@@ -154,6 +166,24 @@ namespace {
e.binding_ptr = &enm;
e.binding_idx = idx;
),
+ (EnumTupleWildcard,
+ const auto& enm = *reinterpret_cast< const ::HIR::Enum*>( get_type_pointer(sp, m_crate, e.path.m_path, Target::EnumVariant) );
+ const auto& des_name = e.path.m_path.m_components.back();
+ unsigned int idx = ::std::find_if( enm.m_variants.begin(), enm.m_variants.end(), [&](const auto& x) { return x.first == des_name; }) - enm.m_variants.begin();
+ if( idx == enm.m_variants.size() ) {
+ ERROR(sp, E0000, "Couldn't find enum variant " << e.path);
+ }
+ const auto& var = enm.m_variants[idx].second;
+ TU_IFLET(::HIR::Enum::Variant, var, Tuple, _,
+ // All good
+ )
+ else {
+ ERROR(sp, E0000, "Enum tuple pattern on non-tuple variant " << e.path);
+ }
+ fix_type_params(sp, enm.m_params, e.path.m_params);
+ e.binding_ptr = &enm;
+ e.binding_idx = idx;
+ ),
(EnumStruct,
const auto& enm = *reinterpret_cast< const ::HIR::Enum*>( get_type_pointer(sp, m_crate, e.path.m_path, Target::EnumVariant) );
const auto& des_name = e.path.m_path.m_components.back();
diff --git a/src/hir_typeck/expr.cpp b/src/hir_typeck/expr.cpp
index 18937155..e77c27a6 100644
--- a/src/hir_typeck/expr.cpp
+++ b/src/hir_typeck/expr.cpp
@@ -378,6 +378,28 @@ namespace {
)
)
),
+ (StructTupleWildcard,
+ this->add_ivars_params( e.path.m_params );
+ if( type.m_data.is_Infer() ) {
+ type.m_data = ::HIR::TypeRef::Data::make_Path( {e.path.clone(), ::HIR::TypeRef::TypePathBinding(e.binding)} );
+ }
+ 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, (type.m_data), (te),
+ (
+ // TODO: Type mismatch
+ ),
+ (Infer, throw ""; ),
+ (Path,
+ if( ! te.binding.is_Struct() || te.binding.as_Struct() != &str ) {
+ ERROR(sp, E0000, "Type mismatch in struct pattern - " << type << " is not " << e.path);
+ }
+ )
+ )
+ ),
(Struct,
this->add_ivars_params( e.path.m_params );
if( type.m_data.is_Infer() ) {
@@ -453,13 +475,37 @@ namespace {
this->add_binding(e.sub_patterns[i], var_ty);
}
else {
- // SAFE: Can't have _ as monomorphise_type_needed checks for that
+ // SAFE: Can't have a _ (monomorphise_type_needed checks for that)
this->add_binding(e.sub_patterns[i], const_cast< ::HIR::TypeRef&>(tup_var[i]));
}
}
)
)
),
+ (EnumTupleWildcard,
+ 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();
+ type.m_data = ::HIR::TypeRef::Data::make_Path( {mv$(path), ::HIR::TypeRef::TypePathBinding(e.binding_ptr)} );
+ }
+ assert(e.binding_ptr);
+ const auto& enm = *e.binding_ptr;
+ const auto& var = enm.m_variants[e.binding_idx].second;
+ assert(var.is_Tuple());
+
+ TU_MATCH_DEF(::HIR::TypeRef::Data, (type.m_data), (te),
+ (
+ // TODO: Type mismatch
+ ),
+ (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);
+ }
+ )
+ )
+ ),
(EnumStruct,
this->add_ivars_params( e.path.m_params );
if( type.m_data.is_Infer() ) {
@@ -619,6 +665,8 @@ namespace {
)
)
),
+ (StructTupleWildcard,
+ ),
(Struct,
if( ty.m_data.is_Infer() ) {
//TODO: Does this lead to issues with generic parameters?
@@ -651,6 +699,8 @@ namespace {
)
)
),
+ (EnumTupleWildcard,
+ ),
(EnumStruct,
if( ty.m_data.is_Infer() ) {
TODO(sp, "EnumStruct - infer");
diff --git a/src/parse/pattern.cpp b/src/parse/pattern.cpp
index e67647bd..5d13cba6 100644
--- a/src/parse/pattern.cpp
+++ b/src/parse/pattern.cpp
@@ -171,8 +171,8 @@ AST::Pattern Parse_PatternReal1(TokenStream& lex, bool is_refutable)
{
case TOK_UNDERSCORE:
return AST::Pattern( );
- case TOK_DOUBLE_DOT:
- return AST::Pattern( AST::Pattern::TagWildcard() );
+ //case TOK_DOUBLE_DOT:
+ // return AST::Pattern( AST::Pattern::TagWildcard() );
case TOK_RWORD_BOX:
return AST::Pattern( AST::Pattern::TagBox(), Parse_Pattern(lex, is_refutable) );
case TOK_DOUBLE_AMP:
@@ -240,6 +240,11 @@ 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) );
case TOK_BRACE_OPEN:
return Parse_PatternStruct(lex, ::std::move(path), is_refutable);
@@ -331,6 +336,7 @@ AST::Pattern Parse_PatternStruct(TokenStream& lex, AST::Path path, bool is_refut
TRACE_FUNCTION;
Token tok;
+ bool is_exhaustive = true;
::std::vector< ::std::pair< ::std::string, AST::Pattern> > subpats;
do {
GET_TOK(tok, lex);
@@ -338,6 +344,7 @@ AST::Pattern Parse_PatternStruct(TokenStream& lex, AST::Path path, bool is_refut
if( tok.type() == TOK_BRACE_CLOSE )
break;
if( tok.type() == TOK_DOUBLE_DOT ) {
+ is_exhaustive = false;
GET_TOK(tok, lex);
break;
}
@@ -391,6 +398,6 @@ AST::Pattern Parse_PatternStruct(TokenStream& lex, AST::Path path, bool is_refut
} while( GET_TOK(tok, lex) == TOK_COMMA );
CHECK_TOK(tok, TOK_BRACE_CLOSE);
- return AST::Pattern(AST::Pattern::TagStruct(), ::std::move(path), ::std::move(subpats));
+ return AST::Pattern(AST::Pattern::TagStruct(), ::std::move(path), ::std::move(subpats), is_exhaustive);
}
diff --git a/src/resolve/absolute.cpp b/src/resolve/absolute.cpp
index 5137aca6..05fa7523 100644
--- a/src/resolve/absolute.cpp
+++ b/src/resolve/absolute.cpp
@@ -1082,8 +1082,10 @@ 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,
- // TODO: This isn't a type lookup, it's a pattern lookup (allowing imported enum variants, e.g. `Some(_)` to work)
Resolve_Absolute_Path(context, pat.span(), Context::LookupMode::Pattern, e.path);
for(auto& sp : e.sub_patterns)
Resolve_Absolute_Pattern(context, allow_refutable, sp);