diff options
author | John Hodge <tpg@mutabah.net> | 2016-11-05 15:44:46 +0800 |
---|---|---|
committer | John Hodge <tpg@mutabah.net> | 2016-11-05 15:44:46 +0800 |
commit | d9dc2ca34c281859791c0f8e767eb0c8fdc70eb4 (patch) | |
tree | 1633955d267678a2fbaf945bcf56992f62f42240 | |
parent | 85425660cc655b9b71966c5131e692739c04c159 (diff) | |
download | mrust-d9dc2ca34c281859791c0f8e767eb0c8fdc70eb4.tar.gz |
MIR Gen Match - Refactor simple match to operate straight off the ruleset
-rw-r--r-- | src/mir/from_hir_match.cpp | 637 |
1 files changed, 268 insertions, 369 deletions
diff --git a/src/mir/from_hir_match.cpp b/src/mir/from_hir_match.cpp index 1c4a3486..f02a7a00 100644 --- a/src/mir/from_hir_match.cpp +++ b/src/mir/from_hir_match.cpp @@ -1069,10 +1069,130 @@ void PatternRulesetBuilder::append_from(const Span& sp, const ::HIR::Pattern& pa ) } +namespace { + void get_ty_and_val( + const Span& sp, + const ::HIR::TypeRef& top_ty, const ::MIR::LValue& top_val, + const PatternRule::field_path_t& field_path, unsigned int field_path_ofs, + /*Out ->*/ ::HIR::TypeRef& out_ty, ::MIR::LValue& out_val + ) + { + ::MIR::LValue lval = top_val.clone(); + ::HIR::TypeRef tmp_ty; + const ::HIR::TypeRef* cur_ty = &top_ty; + + // TODO: Cache the correspondance of path->type (lval can be inferred) + ASSERT_BUG(sp, field_path_ofs <= field_path.size(), "Field path offset " << field_path_ofs << " is larger than the path [" << field_path << "]"); + for(unsigned int i = field_path_ofs; i < field_path.size(); i ++ ) + { + auto idx = field_path[i]; + + TU_MATCHA( (cur_ty->m_data), (e), + (Infer, BUG(sp, "Ivar for in match type"); ), + (Diverge, BUG(sp, "Diverge in match type"); ), + (Primitive, + BUG(sp, "Destructuring a primitive"); + ), + (Tuple, + ASSERT_BUG(sp, idx < e.size(), "Tuple index out of range"); + lval = ::MIR::LValue::make_Field({ box$(lval), idx }); + cur_ty = &e[idx]; + ), + (Path, + TU_MATCHA( (e.binding), (pbe), + (Unbound, + BUG(sp, "Encounterd unbound path - " << e.path); + ), + (Opaque, + BUG(sp, "Destructuring an opaque type - " << *cur_ty); + ), + (Struct, + // TODO: Should this do a call to expand_associated_types? + auto monomorph = [&](const auto& ty) { return monomorphise_type(sp, pbe->m_params, e.path.m_data.as_Generic().m_params, ty); }; + TU_MATCHA( (pbe->m_data), (fields), + (Unit, + BUG(sp, "Destructuring an unit-like tuple - " << *cur_ty); + ), + (Tuple, + assert( idx < fields.size() ); + const auto& fld = fields[idx]; + if( monomorphise_type_needed(fld.ent) ) { + tmp_ty = monomorph(fld.ent); + cur_ty = &tmp_ty; + } + else { + cur_ty = &fld.ent; + } + lval = ::MIR::LValue::make_Field({ box$(lval), idx }); + ), + (Named, + assert( idx < fields.size() ); + const auto& fld = fields[idx].second; + if( monomorphise_type_needed(fld.ent) ) { + tmp_ty = monomorph(fld.ent); + cur_ty = &tmp_ty; + } + else { + cur_ty = &fld.ent; + } + lval = ::MIR::LValue::make_Field({ box$(lval), idx }); + ) + ) + ), + (Enum, + BUG(sp, "Destructuring an enum - " << *cur_ty); + ) + ) + ), + (Generic, + BUG(sp, "Destructuring a generic - " << *cur_ty); + ), + (TraitObject, + BUG(sp, "Destructuring a trait object - " << *cur_ty); + ), + (ErasedType, + BUG(sp, "Destructuring an erased type - " << *cur_ty); + ), + (Array, + assert(idx < e.size_val); + cur_ty = &*e.inner; + lval = ::MIR::LValue::make_Field({ box$(lval), idx }); + ), + (Slice, + cur_ty = &*e.inner; + lval = ::MIR::LValue::make_Field({ box$(lval), idx }); + ), + (Borrow, + ASSERT_BUG(sp, idx == FIELD_DEREF, "Destructure of borrow doesn't correspond to a deref in the path"); + if( cur_ty == &tmp_ty ) { + tmp_ty = mv$(*tmp_ty.m_data.as_Borrow().inner); + } + else { + cur_ty = &*e.inner; + } + lval = ::MIR::LValue::make_Deref({ box$(lval) }); + ), + (Pointer, + ERROR(sp, E0000, "Attempting to match over a pointer"); + ), + (Function, + ERROR(sp, E0000, "Attempting to match over a functon pointer"); + ), + (Closure, + ERROR(sp, E0000, "Attempting to match over a closure"); + ) + ) + } + + out_ty = (cur_ty == &tmp_ty ? mv$(tmp_ty) : cur_ty->clone()); + out_val = mv$(lval); + } +} + // -------------------------------------------------------------------- // Dumb and Simple // -------------------------------------------------------------------- -int MIR_LowerHIR_Match_Simple__GeneratePattern(MirBuilder& builder, const Span& sp, const PatternRule* rules, unsigned int num_rules, const ::HIR::TypeRef& ty, const ::MIR::LValue& match_val, ::MIR::BasicBlockId fail_bb); +int MIR_LowerHIR_Match_Simple__GeneratePattern(MirBuilder& builder, const Span& sp, const PatternRule* rules, unsigned int num_rules, const ::HIR::TypeRef& ty, const ::MIR::LValue& val, unsigned int field_path_offset, ::MIR::BasicBlockId fail_bb); void MIR_LowerHIR_Match_Simple( MirBuilder& builder, MirConverter& conv, ::HIR::ExprNode_Match& node, ::MIR::LValue match_val, t_arm_rules arm_rules, ::std::vector<ArmCode> arms_code, ::MIR::BasicBlockId first_cmp_block ) { @@ -1101,7 +1221,7 @@ void MIR_LowerHIR_Match_Simple( MirBuilder& builder, MirConverter& conv, ::HIR:: // - If the ruleset is empty, this is a _ arm over a value if( pat_rule.m_rules.size() > 0 ) { - MIR_LowerHIR_Match_Simple__GeneratePattern(builder, arm.m_code->span(), pat_rule.m_rules.data(), pat_rule.m_rules.size(), node.m_value->m_res_type, match_val, next_pattern_bb); + MIR_LowerHIR_Match_Simple__GeneratePattern(builder, arm.m_code->span(), pat_rule.m_rules.data(), pat_rule.m_rules.size(), node.m_value->m_res_type, match_val, 0, next_pattern_bb); } builder.end_block( ::MIR::Terminator::make_Goto(arm_code.destructures[i]) ); builder.set_cur_block( arm_code.destructures[i] ); @@ -1134,20 +1254,33 @@ void MIR_LowerHIR_Match_Simple( MirBuilder& builder, MirConverter& conv, ::HIR:: builder.end_block( ::MIR::Terminator::make_Diverge({}) ); } -int MIR_LowerHIR_Match_Simple__GeneratePattern(MirBuilder& builder, const Span& sp, const PatternRule* rules, unsigned int num_rules, const ::HIR::TypeRef& ty, const ::MIR::LValue& match_val, ::MIR::BasicBlockId fail_bb) +int MIR_LowerHIR_Match_Simple__GeneratePattern(MirBuilder& builder, const Span& sp, const PatternRule* rules, unsigned int num_rules, const ::HIR::TypeRef& top_ty, const ::MIR::LValue& top_val, unsigned int field_path_ofs, ::MIR::BasicBlockId fail_bb) { - TRACE_FUNCTION_F("ty = " << ty); - assert( num_rules > 0 ); - const auto& rule = *rules; - TU_MATCHA( (ty.m_data), (te), - (Infer, - BUG(sp, "Hit _ in type - " << ty); - ), - (Diverge, - BUG(sp, "Matching over !"); - ), - (Primitive, - if( !rule.is_Any() ) { + TRACE_FUNCTION_F("top_ty = " << top_ty << ", rules = [" << FMT_CB(os, for(const auto* r = rules; r != rules+num_rules; r++) os << *r << ","; )); + for(unsigned int rule_idx = 0; rule_idx < num_rules; rule_idx ++) + { + const auto& rule = rules[rule_idx]; + DEBUG("rule = " << rule); + + // Don't care. + if( rule.is_Any() ) + continue ; + + ::MIR::LValue val; + ::HIR::TypeRef ity; + + get_ty_and_val(sp, top_ty, top_val, rule.field_path, field_path_ofs, ity, val); + DEBUG("ty = " << ity << ", val = " << val); + + const auto& ty = ity; + TU_MATCHA( (ty.m_data), (te), + (Infer, + BUG(sp, "Hit _ in type - " << ty); + ), + (Diverge, + BUG(sp, "Matching over !"); + ), + (Primitive, switch(te) { case ::HIR::CoreType::Bool: { @@ -1157,10 +1290,10 @@ int MIR_LowerHIR_Match_Simple__GeneratePattern(MirBuilder& builder, const Span& auto succ_bb = builder.new_bb_unlinked(); if( test_val ) { - builder.end_block( ::MIR::Terminator::make_If({ match_val.clone(), succ_bb, fail_bb }) ); + builder.end_block( ::MIR::Terminator::make_If({ val.clone(), succ_bb, fail_bb }) ); } else { - builder.end_block( ::MIR::Terminator::make_If({ match_val.clone(), fail_bb, succ_bb }) ); + builder.end_block( ::MIR::Terminator::make_If({ val.clone(), fail_bb, succ_bb }) ); } builder.set_cur_block(succ_bb); } break; @@ -1177,7 +1310,7 @@ int MIR_LowerHIR_Match_Simple__GeneratePattern(MirBuilder& builder, const Span& auto succ_bb = builder.new_bb_unlinked(); auto test_lval = builder.lvalue_or_temp(sp, te, ::MIR::Constant(re.as_Uint())); - auto cmp_lval = builder.lvalue_or_temp(sp, ::HIR::CoreType::Bool, ::MIR::RValue::make_BinOp({ match_val.clone(), ::MIR::eBinOp::EQ, mv$(test_lval) })); + auto cmp_lval = builder.lvalue_or_temp(sp, ::HIR::CoreType::Bool, ::MIR::RValue::make_BinOp({ val.clone(), ::MIR::eBinOp::EQ, mv$(test_lval) })); builder.end_block( ::MIR::Terminator::make_If({ mv$(cmp_lval), succ_bb, fail_bb }) ); builder.set_cur_block(succ_bb); ), @@ -1199,7 +1332,7 @@ int MIR_LowerHIR_Match_Simple__GeneratePattern(MirBuilder& builder, const Span& auto succ_bb = builder.new_bb_unlinked(); auto test_lval = builder.lvalue_or_temp(sp, te, ::MIR::Constant(re.as_Int())); - auto cmp_lval = builder.lvalue_or_temp(sp, ::HIR::CoreType::Bool, ::MIR::RValue::make_BinOp({ match_val.clone(), ::MIR::eBinOp::EQ, mv$(test_lval) })); + auto cmp_lval = builder.lvalue_or_temp(sp, ::HIR::CoreType::Bool, ::MIR::RValue::make_BinOp({ val.clone(), ::MIR::eBinOp::EQ, mv$(test_lval) })); builder.end_block( ::MIR::Terminator::make_If({ mv$(cmp_lval), succ_bb, fail_bb }) ); builder.set_cur_block(succ_bb); ), @@ -1217,7 +1350,7 @@ int MIR_LowerHIR_Match_Simple__GeneratePattern(MirBuilder& builder, const Span& auto succ_bb = builder.new_bb_unlinked(); auto test_lval = builder.lvalue_or_temp(sp, te, ::MIR::Constant(re.as_Uint())); - auto cmp_lval = builder.lvalue_or_temp(sp, ::HIR::CoreType::Bool, ::MIR::RValue::make_BinOp({ match_val.clone(), ::MIR::eBinOp::EQ, mv$(test_lval) })); + auto cmp_lval = builder.lvalue_or_temp(sp, ::HIR::CoreType::Bool, ::MIR::RValue::make_BinOp({ val.clone(), ::MIR::eBinOp::EQ, mv$(test_lval) })); builder.end_block( ::MIR::Terminator::make_If({ mv$(cmp_lval), succ_bb, fail_bb }) ); builder.set_cur_block(succ_bb); ), @@ -1225,16 +1358,16 @@ int MIR_LowerHIR_Match_Simple__GeneratePattern(MirBuilder& builder, const Span& auto succ_bb = builder.new_bb_unlinked(); auto test_bb_2 = builder.new_bb_unlinked(); - // IF `match_val` < `first` : fail_bb + // IF `val` < `first` : fail_bb auto test_lt_lval = builder.lvalue_or_temp(sp, te, ::MIR::Constant(re.first.as_Uint())); - auto cmp_lt_lval = builder.lvalue_or_temp(sp, ::HIR::CoreType::Bool, ::MIR::RValue::make_BinOp({ match_val.clone(), ::MIR::eBinOp::LT, mv$(test_lt_lval) })); + auto cmp_lt_lval = builder.lvalue_or_temp(sp, ::HIR::CoreType::Bool, ::MIR::RValue::make_BinOp({ val.clone(), ::MIR::eBinOp::LT, mv$(test_lt_lval) })); builder.end_block( ::MIR::Terminator::make_If({ mv$(cmp_lt_lval), fail_bb, test_bb_2 }) ); builder.set_cur_block(test_bb_2); - // IF `match_val` > `last` : fail_bb + // IF `val` > `last` : fail_bb auto test_gt_lval = builder.lvalue_or_temp(sp, te, ::MIR::Constant(re.last.as_Uint())); - auto cmp_gt_lval = builder.lvalue_or_temp(sp, ::HIR::CoreType::Bool, ::MIR::RValue::make_BinOp({ match_val.clone(), ::MIR::eBinOp::GT, mv$(test_gt_lval) })); + auto cmp_gt_lval = builder.lvalue_or_temp(sp, ::HIR::CoreType::Bool, ::MIR::RValue::make_BinOp({ val.clone(), ::MIR::eBinOp::GT, mv$(test_gt_lval) })); builder.end_block( ::MIR::Terminator::make_If({ mv$(cmp_gt_lval), fail_bb, succ_bb }) ); builder.set_cur_block(succ_bb); @@ -1245,85 +1378,43 @@ int MIR_LowerHIR_Match_Simple__GeneratePattern(MirBuilder& builder, const Span& case ::HIR::CoreType::F64: TODO(sp, "Simple match over float - " << ty); break; - case ::HIR::CoreType::Str: - BUG(sp, "Match on str shouldn't hit this code"); - break; - } - } - return 1; - ), - (Path, - TU_MATCHA( (te.binding), (pbe), - (Unbound, - BUG(sp, "Encounterd unbound path - " << te.path); - ), - (Opaque, - if( !rule.is_Any() ) { - BUG(sp, "Attempting to match over opaque type - " << ty); + case ::HIR::CoreType::Str: { + ASSERT_BUG(sp, rule.is_Value() && rule.as_Value().is_StaticString(), ""); + const auto& v = rule.as_Value(); + + auto succ_bb = builder.new_bb_unlinked(); + + auto test_lval = builder.lvalue_or_temp(sp, ty.clone(), ::MIR::RValue(::MIR::Constant( v.as_StaticString() ))); + auto cmp_lval = builder.lvalue_or_temp(sp, ::HIR::CoreType::Bool, ::MIR::RValue::make_BinOp({ val.clone(), ::MIR::eBinOp::EQ, mv$(test_lval) })); + builder.end_block( ::MIR::Terminator::make_If({ mv$(cmp_lval), succ_bb, fail_bb }) ); + builder.set_cur_block(succ_bb); + } break; } - return 1; ), - (Struct, - auto monomorph = [&](const auto& ty) { return monomorphise_type(sp, pbe->m_params, te.path.m_data.as_Generic().m_params, ty); }; - const auto& str_data = pbe->m_data; - TU_MATCHA( (str_data), (sd), - (Unit, - if( !rule.is_Any() ) { - BUG(sp, "Attempting to match over unit type - " << ty); - } - return 1; + (Path, + TU_MATCHA( (te.binding), (pbe), + (Unbound, + BUG(sp, "Encounterd unbound path - " << te.path); ), - (Tuple, - if( !rule.is_Any() ) { - unsigned int total = 0; - unsigned int i = 0; - for( const auto& fld : sd ) { - ::HIR::TypeRef ent_ty_tmp; - const auto& ent_ty = (monomorphise_type_needed(fld.ent) ? ent_ty_tmp = monomorph(fld.ent) : fld.ent); - unsigned int cnt = MIR_LowerHIR_Match_Simple__GeneratePattern( - builder, sp, - rules, num_rules, ent_ty, - ::MIR::LValue::make_Field({ box$(match_val.clone()), i }), - fail_bb - ); - total += cnt; - rules += cnt; - num_rules -= cnt; - i += 1; - } - return total; - } - return 1; + (Opaque, + BUG(sp, "Attempting to match over opaque type - " << ty); ), - (Named, - if( !rule.is_Any() ) { - unsigned int total = 0; - unsigned int i = 0; - for( const auto& fld : sd ) { - ::HIR::TypeRef ent_ty_tmp; - const auto& ent_ty = (monomorphise_type_needed(fld.second.ent) ? ent_ty_tmp = monomorph(fld.second.ent) : fld.second.ent); - unsigned int cnt = MIR_LowerHIR_Match_Simple__GeneratePattern( - builder, sp, - rules, num_rules, ent_ty, - ::MIR::LValue::make_Field({ box$(match_val.clone()), i }), - fail_bb - ); - total += cnt; - rules += cnt; - num_rules -= cnt; - i += 1; - } - return total; - } - else { - return 1; - } + (Struct, + const auto& str_data = pbe->m_data; + TU_MATCHA( (str_data), (sd), + (Unit, + BUG(sp, "Attempting to match over unit type - " << ty); + ), + (Tuple, + TODO(sp, "Matching on tuple-like struct?"); + ), + (Named, + TODO(sp, "Matching on struct?"); + ) ) - ) - ), - (Enum, - auto monomorph = [&](const auto& ty) { return monomorphise_type(sp, pbe->m_params, te.path.m_data.as_Generic().m_params, ty); }; - if( !rule.is_Any() ) { + ), + (Enum, + auto monomorph = [&](const auto& ty) { return monomorphise_type(sp, pbe->m_params, te.path.m_data.as_Generic().m_params, ty); }; ASSERT_BUG(sp, rule.is_Variant(), "Rule for enum isn't Any or Variant"); const auto& re = rule.as_Variant(); unsigned int var_idx = re.idx; @@ -1334,94 +1425,71 @@ int MIR_LowerHIR_Match_Simple__GeneratePattern(MirBuilder& builder, const Span& // Generate a switch with only one option different. ::std::vector< ::MIR::BasicBlockId> arms(var_count, fail_bb); arms[var_idx] = next_bb; - builder.end_block( ::MIR::Terminator::make_Switch({ match_val.clone(), mv$(arms) }) ); + builder.end_block( ::MIR::Terminator::make_Switch({ val.clone(), mv$(arms) }) ); builder.set_cur_block(next_bb); - const auto& var_data = pbe->m_variants.at(re.idx).second; - TU_MATCHA( (var_data), (ve), - (Unit, - // Nothing to recurse - ), - (Value, - // Nothing to recurse - ), - (Tuple, - auto lval_var = ::MIR::LValue::make_Downcast({ box$(match_val.clone()), var_idx }); - const auto* subrules = re.sub_rules.data(); - unsigned int subrule_count = re.sub_rules.size(); - - for(unsigned int i = 0; i < ve.size(); i ++) - { - if( subrule_count == 0 ) - break ; + if( re.sub_rules.size() > 0 ) + { + const auto& var_data = pbe->m_variants.at(re.idx).second; + TU_MATCHA( (var_data), (ve), + (Unit, + // Nothing to recurse + ), + (Value, + // Nothing to recurse + ), + (Tuple, + // Create a dummy tuple to contain the inner types. + ::std::vector< ::HIR::TypeRef> fake_ty_ents; + fake_ty_ents.reserve( ve.size() ); + for(unsigned int i = 0; i < ve.size(); i ++) + { + fake_ty_ents.push_back( monomorph(ve[i].ent) ); + } + ::HIR::TypeRef fake_tup = ::HIR::TypeRef( mv$(fake_ty_ents) ); - ::HIR::TypeRef ent_ty_tmp; - const auto& ent_ty = (monomorphise_type_needed(ve[i].ent) ? ent_ty_tmp = monomorph(ve[i].ent) : ve[i].ent); - unsigned int cnt = MIR_LowerHIR_Match_Simple__GeneratePattern( - builder, sp, - subrules, subrule_count, ent_ty, - ::MIR::LValue::make_Field({ box$(lval_var.clone()), i }), + // Recurse with the new ruleset + MIR_LowerHIR_Match_Simple__GeneratePattern(builder, sp, + re.sub_rules.data(), re.sub_rules.size(), + fake_tup, ::MIR::LValue::make_Downcast({ box$(val.clone()), var_idx }), rule.field_path.size(), fail_bb ); - subrules += cnt; - subrule_count -= cnt; - } - ), - (Struct, - auto lval_var = ::MIR::LValue::make_Downcast({ box$(match_val.clone()), var_idx }); - const auto* subrules = re.sub_rules.data(); - unsigned int subrule_count = re.sub_rules.size(); - - for(unsigned int i = 0; i < ve.size(); i ++) - { - if( subrule_count == 0 ) - break ; + ), + (Struct, + // Create a dummy tuple to contain the inner types. + ::std::vector< ::HIR::TypeRef> fake_ty_ents; + fake_ty_ents.reserve( ve.size() ); + for(unsigned int i = 0; i < ve.size(); i ++) + { + fake_ty_ents.push_back( monomorph(ve[i].second.ent) ); + } + ::HIR::TypeRef fake_tup = ::HIR::TypeRef( mv$(fake_ty_ents) ); - const auto& tpl_ty = ve[i].second.ent; - ::HIR::TypeRef ent_ty_tmp; - const auto& ent_ty = (monomorphise_type_needed(tpl_ty) ? ent_ty_tmp = monomorph(tpl_ty) : tpl_ty); - unsigned int cnt = MIR_LowerHIR_Match_Simple__GeneratePattern( - builder, sp, - subrules, subrule_count, ent_ty, - ::MIR::LValue::make_Field({ box$(lval_var.clone()), i }), + // Recurse with the new ruleset + MIR_LowerHIR_Match_Simple__GeneratePattern(builder, sp, + re.sub_rules.data(), re.sub_rules.size(), + fake_tup, ::MIR::LValue::make_Downcast({ box$(val.clone()), var_idx }), rule.field_path.size(), fail_bb ); - subrules += cnt; - subrule_count -= cnt; - } + ) ) - ) - // NOTE: All enum variant patterns take one slot - return 1; - } - else { - return 1; - } + } + ) // TypePathBinding::Enum ) - ) - ), - (Generic, - // Nothing needed - if( !rule.is_Any() ) { + ), // Type::Data::Path + (Generic, BUG(sp, "Attempting to match a generic"); - } - return 1; - ), - (TraitObject, - if( !rule.is_Any() ) { + ), + (TraitObject, BUG(sp, "Attempting to match a trait object"); - } - return 1; - ), - (ErasedType, - if( !rule.is_Any() ) { + ), + (ErasedType, BUG(sp, "Attempting to match an erased type"); - } - return 1; - ), - (Array, - if( !rule.is_Any() ) { + ), + (Array, + TODO(sp, "Match directly on array?"); + #if 0 unsigned int total = 0; for( unsigned int i = 0; i < te.size_val; i ++ ) { unsigned int cnt = MIR_LowerHIR_Match_Simple__GeneratePattern( @@ -1436,87 +1504,43 @@ int MIR_LowerHIR_Match_Simple__GeneratePattern(MirBuilder& builder, const Span& if( num_rules == 0 ) return total; } - return total; - } - return 1; - ), - (Slice, - if( !rule.is_Any() ) { - TODO(sp, "Match over Slice - " << rule); - } - return 1; - ), - (Tuple, - if( !rule.is_Any() ) { - unsigned int total = 0; - for( unsigned int i = 0; i < te.size(); i ++ ) { - unsigned int cnt = MIR_LowerHIR_Match_Simple__GeneratePattern( - builder, sp, - rules, num_rules, te[i], - ::MIR::LValue::make_Field({ box$(match_val.clone()), i }), - fail_bb - ); - total += cnt; - rules += cnt; - num_rules -= cnt; - if( num_rules == 0 ) - return total; - } - return total; - } - return 1; - ), - (Borrow, - if( rule.is_Value() ) { - const auto& v = rule.as_Value(); - if( v.is_StaticString() || v.is_Bytes() ) - { - ::MIR::Constant cloned_val; - if( v.is_StaticString() ) { - ASSERT_BUG(sp, *te.inner == ::HIR::TypeRef(::HIR::CoreType::Str), "StaticString pattern on non &str"); - cloned_val = ::MIR::Constant( v.as_StaticString() ); - } - else { - ASSERT_BUG(sp, *te.inner == ::HIR::TypeRef::new_slice(::HIR::CoreType::U8), "Bytes pattern on non-&[u8]"); - cloned_val = ::MIR::Constant( v.as_Bytes() ); - } + #endif + ), + (Slice, + ASSERT_BUG(sp, rule.is_Slice() || (rule.is_Value() && rule.as_Value().is_Bytes()), "Can only match slice with Bytes or Slice rules - " << rule); + if( rule.is_Value() ) { + ASSERT_BUG(sp, *te.inner == ::HIR::CoreType::U8, "Bytes pattern on non-&[u8]"); + auto cloned_val = ::MIR::Constant( rule.as_Value().as_Bytes() ); auto succ_bb = builder.new_bb_unlinked(); auto test_lval = builder.lvalue_or_temp(sp, ty.clone(), ::MIR::RValue(mv$(cloned_val))); - auto cmp_lval = builder.lvalue_or_temp(sp, ::HIR::CoreType::Bool, ::MIR::RValue::make_BinOp({ match_val.clone(), ::MIR::eBinOp::EQ, mv$(test_lval) })); + auto cmp_lval = builder.lvalue_or_temp(sp, ::HIR::CoreType::Bool, ::MIR::RValue::make_BinOp({ val.clone(), ::MIR::eBinOp::EQ, mv$(test_lval) })); builder.end_block( ::MIR::Terminator::make_If({ mv$(cmp_lval), succ_bb, fail_bb }) ); builder.set_cur_block(succ_bb); - return 1; } - } - - if( !rule.is_Any() ) { - return MIR_LowerHIR_Match_Simple__GeneratePattern(builder, sp, rules, num_rules, *te.inner, match_val, fail_bb); - } - return 1; - ), - (Pointer, - if( !rule.is_Any() ) { - BUG(sp, "Attempting to match a pointer"); - } - return 1; - ), - (Function, - if( !rule.is_Any() ) { - BUG(sp, "Attempting to match a function pointer"); - } - return 1; - ), - (Closure, - if( !rule.is_Any() ) { + else { + TODO(sp, "Match over Slice - " << rule); + } + ), + (Tuple, + TODO(sp, "Match directly on tuple?"); + ), + (Borrow, + TODO(sp, "Match directly on borrow?"); + ), // Type::Data::Borrow + (Pointer, + BUG(sp, "Attempting to match a pointer - " << rule << " against " << ty); + ), + (Function, + BUG(sp, "Attempting to match a function pointer - " << rule << " against " << ty); + ), + (Closure, BUG(sp, "Attempting to match a closure"); - } - return 1; + ) ) - ) - - throw ""; + } + return 0; } // -------------------------------------------------------------------- @@ -1682,13 +1706,6 @@ struct DecisionTreeGen return m_rule_blocks.at( rule_index ); } - void get_ty_and_val( - const Span& sp, - const ::HIR::TypeRef& top_ty, const ::MIR::LValue& top_val, - const PatternRule::field_path_t& field_path, unsigned int field_path_ofs, - /*Out ->*/ ::HIR::TypeRef& out_ty, ::MIR::LValue& out_val - ); - void generate_tree_code(const Span& sp, const DecisionTreeNode& node, const ::HIR::TypeRef& ty, const ::MIR::LValue& val) { generate_tree_code(sp, node, ty, 0, val, [&](const auto& n){ DEBUG("node = " << n); @@ -2724,124 +2741,6 @@ void DecisionTreeNode::unify_from(const Branch& b) // DecisionTreeGen // ---------------------------- -void DecisionTreeGen::get_ty_and_val( - const Span& sp, - const ::HIR::TypeRef& top_ty, const ::MIR::LValue& top_val, - const PatternRule::field_path_t& field_path, unsigned int field_path_ofs, - /*Out ->*/ ::HIR::TypeRef& out_ty, ::MIR::LValue& out_val - ) -{ - ::MIR::LValue lval = top_val.clone(); - ::HIR::TypeRef tmp_ty; - const ::HIR::TypeRef* cur_ty = &top_ty; - - // TODO: Cache the correspondance of path->type (lval can be inferred) - ASSERT_BUG(sp, field_path_ofs <= field_path.size(), "Field path offset " << field_path_ofs << " is larger than the path [" << field_path << "]"); - for(unsigned int i = field_path_ofs; i < field_path.size(); i ++ ) - { - auto idx = field_path[i]; - - TU_MATCHA( (cur_ty->m_data), (e), - (Infer, BUG(sp, "Ivar for in match type"); ), - (Diverge, BUG(sp, "Diverge in match type"); ), - (Primitive, - BUG(sp, "Destructuring a primitive"); - ), - (Tuple, - ASSERT_BUG(sp, idx < e.size(), "Tuple index out of range"); - lval = ::MIR::LValue::make_Field({ box$(lval), idx }); - cur_ty = &e[idx]; - ), - (Path, - TU_MATCHA( (e.binding), (pbe), - (Unbound, - BUG(sp, "Encounterd unbound path - " << e.path); - ), - (Opaque, - BUG(sp, "Destructuring an opaque type - " << *cur_ty); - ), - (Struct, - // TODO: Should this do a call to expand_associated_types? - auto monomorph = [&](const auto& ty) { return monomorphise_type(sp, pbe->m_params, e.path.m_data.as_Generic().m_params, ty); }; - TU_MATCHA( (pbe->m_data), (fields), - (Unit, - BUG(sp, "Destructuring an unit-like tuple - " << *cur_ty); - ), - (Tuple, - assert( idx < fields.size() ); - const auto& fld = fields[idx]; - if( monomorphise_type_needed(fld.ent) ) { - tmp_ty = monomorph(fld.ent); - cur_ty = &tmp_ty; - } - else { - cur_ty = &fld.ent; - } - lval = ::MIR::LValue::make_Field({ box$(lval), idx }); - ), - (Named, - assert( idx < fields.size() ); - const auto& fld = fields[idx].second; - if( monomorphise_type_needed(fld.ent) ) { - tmp_ty = monomorph(fld.ent); - cur_ty = &tmp_ty; - } - else { - cur_ty = &fld.ent; - } - lval = ::MIR::LValue::make_Field({ box$(lval), idx }); - ) - ) - ), - (Enum, - BUG(sp, "Destructuring an enum - " << *cur_ty); - ) - ) - ), - (Generic, - BUG(sp, "Destructuring a generic - " << *cur_ty); - ), - (TraitObject, - BUG(sp, "Destructuring a trait object - " << *cur_ty); - ), - (ErasedType, - BUG(sp, "Destructuring an erased type - " << *cur_ty); - ), - (Array, - assert(idx < e.size_val); - cur_ty = &*e.inner; - lval = ::MIR::LValue::make_Field({ box$(lval), idx }); - ), - (Slice, - cur_ty = &*e.inner; - lval = ::MIR::LValue::make_Field({ box$(lval), idx }); - ), - (Borrow, - ASSERT_BUG(sp, idx == FIELD_DEREF, "Destructure of borrow doesn't correspond to a deref in the path"); - if( cur_ty == &tmp_ty ) { - tmp_ty = mv$(*tmp_ty.m_data.as_Borrow().inner); - } - else { - cur_ty = &*e.inner; - } - lval = ::MIR::LValue::make_Deref({ box$(lval) }); - ), - (Pointer, - ERROR(sp, E0000, "Attempting to match over a pointer"); - ), - (Function, - ERROR(sp, E0000, "Attempting to match over a functon pointer"); - ), - (Closure, - ERROR(sp, E0000, "Attempting to match over a closure"); - ) - ) - } - - out_ty = (cur_ty == &tmp_ty ? mv$(tmp_ty) : cur_ty->clone()); - out_val = mv$(lval); -} - void DecisionTreeGen::generate_tree_code( const Span& sp, const DecisionTreeNode& node, |