diff options
author | John Hodge <tpg@mutabah.net> | 2016-08-10 11:45:41 +0800 |
---|---|---|
committer | John Hodge <tpg@mutabah.net> | 2016-08-10 11:45:41 +0800 |
commit | 8f3fa5853e80590f666e4852f4f373c7b7826d3b (patch) | |
tree | 8283e7bdbc40e6061d8091da79f256d7bb73d38d | |
parent | 2f362de81877b09a568a02d1786e138dfd0c7710 (diff) | |
download | mrust-8f3fa5853e80590f666e4852f4f373c7b7826d3b.tar.gz |
MIR - Match generation being fleshed out
-rw-r--r-- | src/mir/from_hir.cpp | 90 |
1 files changed, 78 insertions, 12 deletions
diff --git a/src/mir/from_hir.cpp b/src/mir/from_hir.cpp index dcbeff0a..04dfff3f 100644 --- a/src/mir/from_hir.cpp +++ b/src/mir/from_hir.cpp @@ -12,6 +12,7 @@ #include <hir/expr.hpp> #include <hir/hir.hpp> #include <hir/visitor.hpp> +#include <hir_typeck/helpers.hpp> // monomorphise_type #include "main_bindings.hpp" namespace { @@ -239,15 +240,17 @@ namespace { { TRACE_FUNCTION_F("_Match"); this->visit_node_ptr(node.m_value); - //auto match_val = this->get_result(); + auto match_val = this->lvalue_or_temp(node.m_value->m_res_type, this->get_result(node.m_value->span())); if( node.m_arms.size() == 0 ) { // Nothing TODO(node.span(), "Handle zero-arm match"); } - else if( node.m_arms.size() == 1 ) { + else if( node.m_arms.size() == 1 && node.m_arms[0].m_patterns.size() == 1 && ! node.m_arms[0].m_cond ) { // - Shortcut: Single-arm match - TODO(node.span(), "Convert single-arm match"); + // TODO: Drop scope + this->destructure_from(node.span(), node.m_arms[0].m_patterns[0], mv$(match_val)); + this->visit_node_ptr(node.m_arms[0].m_code); } else { // TODO: Convert patterns into sequence of switches and comparisons. @@ -255,8 +258,9 @@ namespace { // Build up a sorted vector of MIR pattern rules TAGGED_UNION(PatternRule, Any, (Any, struct {}), - (EnumVariant, unsigned int), - (Value, ::MIR::Constant) + (Variant, unsigned int), + (Value, ::MIR::Constant), + (Optional, ::std::vector< PatternRule>) ); struct PatternRuleset { ::std::vector<PatternRule> m_rules; @@ -322,12 +326,67 @@ namespace { ) ), (Path, - // TODO: This is either a destructure or an enum - TODO(sp, "Match over path"); + // This is either a struct destructure or an enum + TU_MATCHA( (e.binding), (pbe), + (Unbound, + BUG(sp, "Encounterd unbound path - " << e.path); + ), + (Opaque, + TU_MATCH_DEF( ::HIR::Pattern::Data, (pat.m_data), (pe), + ( throw ""; ), + (Any, + m_rules.push_back( PatternRule::make_Any({}) ); + ) + ) + ), + (Struct, + TODO(sp, "Match over struct - " << e.path); + ), + (Enum, + TU_MATCH_DEF( ::HIR::Pattern::Data, (pat.m_data), (pe), + ( BUG(sp, "Match not allowed, " << ty << " with " << pat); ), + (Any, + m_rules.push_back( PatternRule::make_Any({}) ); + m_rules.push_back( PatternRule::make_Optional({}) ); + ), + (Value, + ASSERT_BUG(sp, pe.val.is_Named(), "Value pattern for enum isn't _Named"); + TODO(sp, "Enum Value"); + ), + (EnumTuple, + m_rules.push_back( PatternRule::make_Variant(pe.binding_idx) ); + const auto& fields_def = pe.binding_ptr->m_variants[pe.binding_idx].second.as_Tuple(); + PatternRulesetBuilder sub_builder; + for( unsigned int i = 0; i < pe.sub_patterns.size(); i ++ ) + { + const auto& subpat = pe.sub_patterns[i]; + auto subty = monomorphise_type(sp, pe.binding_ptr->m_params, e.path.m_data.as_Generic().m_params, fields_def[i].ent); + sub_builder.append_from( sp, subpat, subty ); + } + m_rules.push_back( PatternRule::make_Optional( mv$(sub_builder.m_rules) ) ); + ), + (EnumTupleWildcard, + m_rules.push_back( PatternRule::make_Variant(pe.binding_idx) ); + m_rules.push_back( PatternRule::make_Optional({}) ); + ), + (EnumStruct, + m_rules.push_back( PatternRule::make_Variant(pe.binding_idx) ); + PatternRulesetBuilder sub_builder; + TODO(sp, "Convert EnumStruct patterns"); + m_rules.push_back( PatternRule::make_Optional( mv$(sub_builder.m_rules) ) ); + ) + ) + ) + ) ), (Generic, - // TODO: Is this possible? - Single arm has already been handled - ERROR(sp, E0000, "Attempting to match over a generic"); + // Generics don't destructure, so the only valid pattern is `_` + TU_MATCH_DEF( ::HIR::Pattern::Data, (pat.m_data), (pe), + ( BUG(sp, "Match not allowed, " << ty << " with " << pat); ), + (Any, + m_rules.push_back( PatternRule::make_Any({}) ); + ) + ) ), (TraitObject, ERROR(sp, E0000, "Attempting to match over a trait object"); @@ -340,8 +399,15 @@ namespace { BUG(sp, "Hit match over `[T]` - must be `&[T]`"); ), (Borrow, - // TODO: Sub-match - TODO(sp, "Match over borrow"); + TU_MATCH_DEF( ::HIR::Pattern::Data, (pat.m_data), (pe), + ( throw ""; ), + (Any, + this->append_from( sp, pat, *e.inner ); + ), + (Ref, + this->append_from( sp, *pe.sub, *e.inner ); + ) + ) ), (Pointer, ERROR(sp, E0000, "Attempting to match over a pointer"); @@ -400,7 +466,7 @@ namespace { this->set_cur_block(true_branch); this->visit_node_ptr(node.m_true); - this->push_stmt_assign( ::MIR::LValue::make_Temporary({result_val.as_Temporary().idx}), this->get_result(node.m_true->span()) ); + this->push_stmt_assign( result_val.clone(), this->get_result(node.m_true->span()) ); this->end_block( ::MIR::Terminator::make_Goto(next_block) ); this->set_cur_block(false_branch); |