summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/mir/from_hir.cpp82
1 files changed, 73 insertions, 9 deletions
diff --git a/src/mir/from_hir.cpp b/src/mir/from_hir.cpp
index 633caf8e..4b60640d 100644
--- a/src/mir/from_hir.cpp
+++ b/src/mir/from_hir.cpp
@@ -151,16 +151,80 @@ namespace {
}
- void destructure_from(const Span& sp, const ::HIR::Pattern& pat, ::MIR::LValue lval)
+ void destructure_from(const Span& sp, const ::HIR::Pattern& pat, ::MIR::LValue lval, int allow_refutable=0) // 1 : yes, 2 : disallow binding
{
if( pat.m_binding.is_valid() ) {
- ASSERT_BUG(sp, pat.m_data.is_Any(), "Destructure patterns can't bind and match");
-
- m_builder.push_stmt_assign( ::MIR::LValue::make_Variable(pat.m_binding.m_slot), mv$(lval) );
- return ;
+ if( allow_refutable == 2 ) {
+ BUG(sp, "Binding when not expected");
+ }
+ else if( allow_refutable == 0 ) {
+ ASSERT_BUG(sp, pat.m_data.is_Any(), "Destructure patterns can't bind and match");
+
+ m_builder.push_stmt_assign( ::MIR::LValue::make_Variable(pat.m_binding.m_slot), mv$(lval) );
+ return;
+ }
+ else {
+ // Refutable and binding allowed
+ m_builder.push_stmt_assign( ::MIR::LValue::make_Variable(pat.m_binding.m_slot), lval.clone() );
+ }
}
- // TODO: Destructure
- TODO(sp, "Destructure using " << pat);
+
+ TU_MATCHA( (pat.m_data), (e),
+ (Any,
+ ),
+ (Box,
+ TODO(sp, "Destructure using " << pat);
+ ),
+ (Ref,
+ destructure_from(sp, *e.sub, ::MIR::LValue::make_Deref({ box$( mv$(lval) ) }));
+ ),
+ (Tuple,
+ for(unsigned int i = 0; i < e.sub_patterns.size(); i ++ )
+ {
+ destructure_from(sp, e.sub_patterns[i], ::MIR::LValue::make_Field({ box$( lval.clone() ), i}));
+ }
+ ),
+ (StructTuple,
+ for(unsigned int i = 0; i < e.sub_patterns.size(); i ++ )
+ {
+ destructure_from(sp, e.sub_patterns[i], ::MIR::LValue::make_Field({ box$( lval.clone() ), i}));
+ }
+ ),
+ (StructTupleWildcard,
+ ),
+ (Struct,
+ TODO(sp, "Destructure using " << pat);
+ ),
+ // Refutable
+ (Value,
+ ASSERT_BUG(sp, allow_refutable, "Refutable pattern not expected");
+ ),
+ (Range,
+ ASSERT_BUG(sp, allow_refutable, "Refutable pattern not expected");
+ ),
+ (EnumValue,
+ ASSERT_BUG(sp, allow_refutable, "Refutable pattern not expected");
+ ),
+ (EnumTuple,
+ ASSERT_BUG(sp, allow_refutable, "Refutable pattern not expected");
+ TODO(sp, "Destructure using " << pat);
+ ),
+ (EnumTupleWildcard,
+ ASSERT_BUG(sp, allow_refutable, "Refutable pattern not expected");
+ ),
+ (EnumStruct,
+ ASSERT_BUG(sp, allow_refutable, "Refutable pattern not expected");
+ TODO(sp, "Destructure using " << pat);
+ ),
+ (Slice,
+ ASSERT_BUG(sp, allow_refutable, "Refutable pattern not expected");
+ TODO(sp, "Destructure using " << pat);
+ ),
+ (SplitSlice,
+ ASSERT_BUG(sp, allow_refutable, "Refutable pattern not expected");
+ TODO(sp, "Destructure using " << pat);
+ )
+ )
}
// -- ExprVisitor
@@ -543,8 +607,8 @@ namespace {
ASSERT_BUG(node.span(), arm.m_patterns.size() == 1, "TODO: Handle multiple patterns on one arm");
const auto& pat = arm.m_patterns[0 /*rule.first.second*/];
- // Assign bindings (drop registration happens in previous loop)
- this->destructure_from( arm.m_code->span(), pat, match_val.clone() );
+ // Assign bindings (drop registration happens in previous loop) - Allow refutable patterns
+ this->destructure_from( arm.m_code->span(), pat, match_val.clone(), 1 );
}
// ## Create descision tree in-memory based off the ruleset