diff options
-rw-r--r-- | src/ast/pattern.cpp | 12 | ||||
-rw-r--r-- | src/ast/pattern.hpp | 10 | ||||
-rw-r--r-- | src/dump_as_rust.cpp | 8 | ||||
-rw-r--r-- | src/expand/mod.cpp | 2 | ||||
-rw-r--r-- | src/hir/from_ast.cpp | 33 | ||||
-rw-r--r-- | src/hir/pattern.hpp | 11 | ||||
-rw-r--r-- | src/hir/visitor.cpp | 6 | ||||
-rw-r--r-- | src/hir_conv/bind.cpp | 30 | ||||
-rw-r--r-- | src/hir_typeck/expr.cpp | 52 | ||||
-rw-r--r-- | src/parse/pattern.cpp | 13 | ||||
-rw-r--r-- | src/resolve/absolute.cpp | 4 |
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); |