diff options
author | John Hodge <tpg@ucc.asn.au> | 2017-11-01 20:46:36 +0800 |
---|---|---|
committer | John Hodge <tpg@ucc.asn.au> | 2017-11-01 20:46:36 +0800 |
commit | cb271f8ea98d1a5c65a5e636a0e73a85710027b4 (patch) | |
tree | 9694427c074c0e0d581cde6e01b6167016e0f844 /src/mir | |
parent | 8306f43ccdf0414b48891aa5eb04d8901899c052 (diff) | |
download | mrust-cb271f8ea98d1a5c65a5e636a0e73a85710027b4.tar.gz |
HIR - Refactor enums to only embed a single field (and give variants types)
Diffstat (limited to 'src/mir')
-rw-r--r-- | src/mir/cleanup.cpp | 46 | ||||
-rw-r--r-- | src/mir/from_hir.cpp | 203 | ||||
-rw-r--r-- | src/mir/from_hir_match.cpp | 153 | ||||
-rw-r--r-- | src/mir/helpers.cpp | 36 | ||||
-rw-r--r-- | src/mir/mir.cpp | 6 | ||||
-rw-r--r-- | src/mir/mir.hpp | 3 | ||||
-rw-r--r-- | src/mir/mir_builder.cpp | 43 | ||||
-rw-r--r-- | src/mir/optimise.cpp | 2 | ||||
-rw-r--r-- | src/mir/visit_crate_mir.cpp | 17 |
9 files changed, 227 insertions, 282 deletions
diff --git a/src/mir/cleanup.cpp b/src/mir/cleanup.cpp index 9718f046..455eef43 100644 --- a/src/mir/cleanup.cpp +++ b/src/mir/cleanup.cpp @@ -289,7 +289,7 @@ const ::HIR::Literal* MIR_Cleanup_GetConstant(const Span& sp, const StaticTraitR } ) ) - return ::MIR::RValue::make_Struct({ te.path.m_data.as_Generic().clone(), ~0u, mv$(lvals) }); + return ::MIR::RValue::make_Struct({ te.path.m_data.as_Generic().clone(), mv$(lvals) }); } else if( te.binding.is_Enum() ) { @@ -298,33 +298,19 @@ const ::HIR::Literal* MIR_Cleanup_GetConstant(const Span& sp, const StaticTraitR auto monomorph = [&](const auto& tpl) { return monomorphise_type(state.sp, enm.m_params, te.path.m_data.as_Generic().m_params, tpl); }; - ::std::vector< ::MIR::Param> lvals; - MIR_ASSERT(state, lit_var.idx < enm.m_variants.size(), "Variant index out of range"); - TU_MATCHA( (enm.m_variants[lit_var.idx].second), (ve), - (Unit, - ), - (Value, - ), - (Tuple, - MIR_ASSERT(state, lit_var.vals.size() == ve.size(), "Value count mismatch in literal for " << ty << " #" << lit_var.idx << " - exp " << ve.size() << ", " << lit); - for(unsigned int i = 0; i < ve.size(); i ++) - { - auto ent_ty = monomorph(ve[i].ent); - auto rval = MIR_Cleanup_LiteralToRValue(state, mutator, lit_var.vals[i], ent_ty.clone(), ::HIR::GenericPath()); - lvals.push_back( mutator.in_temporary(mv$(ent_ty), mv$(rval)) ); - } - ), - (Struct, - MIR_ASSERT(state, lit_var.vals.size() == ve.size(), "Value count mismatch in literal for " << ty << " #" << lit_var.idx << " - exp " << ve.size() << ", " << lit); - for(unsigned int i = 0; i < ve.size(); i ++) - { - auto ent_ty = monomorph(ve[i].second.ent); - auto rval = MIR_Cleanup_LiteralToRValue(state, mutator, lit_var.vals[i], ent_ty.clone(), ::HIR::GenericPath()); - lvals.push_back( mutator.in_temporary(mv$(ent_ty), mv$(rval)) ); - } - ) - ) - return ::MIR::RValue::make_Struct({ te.path.m_data.as_Generic().clone(), lit_var.idx, mv$(lvals) }); + MIR_ASSERT(state, lit_var.idx < enm.num_variants(), "Variant index out of range"); + ::MIR::Param p; + if( const auto* e = enm.m_data.opt_Data() ) + { + auto ty = monomorph( e->at(lit_var.idx).type ); + auto rval = MIR_Cleanup_LiteralToRValue(state, mutator, *lit_var.val, ty.clone(), ::HIR::GenericPath()); + p = mutator.in_temporary(mv$(ty), mv$(rval)); + } + else + { + p = mutator.in_temporary(::HIR::TypeRef::new_unit(), ::MIR::RValue::make_Tuple({})); + } + return ::MIR::RValue::make_Variant({ te.path.m_data.as_Generic().clone(), lit_var.idx, mv$(p) }); } else { @@ -540,7 +526,7 @@ const ::HIR::Literal* MIR_Cleanup_GetConstant(const Span& sp, const StaticTraitR ) auto new_path = ty_path.clone(); - return mutator.in_temporary( mv$(ty), ::MIR::RValue::make_Struct({ mv$(new_path), ~0u, mv$(vals) }) ); + return mutator.in_temporary( mv$(ty), ::MIR::RValue::make_Struct({ mv$(new_path), mv$(vals) }) ); } else if( ty.m_data.is_Pointer() ) { @@ -820,7 +806,7 @@ bool MIR_Cleanup_Unsize_GetMetadata(const ::MIR::TypeResolve& state, MirMutator& } ) ) - return ::MIR::RValue::make_Struct({ dte.path.m_data.as_Generic().clone(), ~0u, mv$(ents) }); + return ::MIR::RValue::make_Struct({ dte.path.m_data.as_Generic().clone(), mv$(ents) }); } if( dst_ty.m_data.is_Borrow() ) diff --git a/src/mir/from_hir.cpp b/src/mir/from_hir.cpp index 2a02b166..06a70d49 100644 --- a/src/mir/from_hir.cpp +++ b/src/mir/from_hir.cpp @@ -261,14 +261,14 @@ namespace { ), (EnumValue, const auto& enm = *e.binding_ptr; - if( enm.m_variants.size() > 1 ) + if( enm.num_variants() > 1 ) { ASSERT_BUG(sp, allow_refutable, "Refutable pattern not expected - " << pat); } ), (EnumTuple, const auto& enm = *e.binding_ptr; - ASSERT_BUG(sp, enm.m_variants.size() == 1 || allow_refutable, "Refutable pattern not expected - " << pat); + ASSERT_BUG(sp, enm.num_variants() == 1 || allow_refutable, "Refutable pattern not expected - " << pat); auto lval_var = ::MIR::LValue::make_Downcast({ box$(mv$(lval)), e.binding_idx }); for(unsigned int i = 0; i < e.sub_patterns.size(); i ++ ) { @@ -277,8 +277,11 @@ namespace { ), (EnumStruct, const auto& enm = *e.binding_ptr; - ASSERT_BUG(sp, enm.m_variants.size() == 1 || allow_refutable, "Refutable pattern not expected - " << pat); - const auto& fields = enm.m_variants[e.binding_idx].second.as_Struct(); + ASSERT_BUG(sp, enm.num_variants() == 1 || allow_refutable, "Refutable pattern not expected - " << pat); + ASSERT_BUG(sp, enm.m_data.is_Data(), "Expected struct variant - " << pat); + const auto& var = enm.m_data.as_Data()[e.binding_idx];; + const auto& str = *var.type.m_data.as_Path().binding.as_Struct(); + const auto& fields = str.m_data.as_Named(); auto lval_var = ::MIR::LValue::make_Downcast({ box$(mv$(lval)), e.binding_idx }); for(const auto& fld_pat : e.sub_patterns) { @@ -1691,25 +1694,47 @@ namespace { values.push_back( m_builder.get_result_in_param(arg->span(), arg->m_res_type) ); } - unsigned int variant_index = ~0u; - if( !node.m_is_struct ) + if( node.m_is_struct ) + { + m_builder.set_result( node.span(), ::MIR::RValue::make_Struct({ + node.m_path.clone(), + mv$(values) + }) ); + } + else { // Get the variant index from the enum. auto enum_path = node.m_path.m_path; enum_path.m_components.pop_back(); const auto& var_name = node.m_path.m_path.m_components.back(); const auto& enm = m_builder.crate().get_enum_by_path(sp, enum_path); - auto var_it = ::std::find_if(enm.m_variants.begin(), enm.m_variants.end(), [&](const auto& x){ return x.first == var_name; }); - ASSERT_BUG(sp, var_it != enm.m_variants.end(), "Variant " << node.m_path.m_path << " isn't present"); - variant_index = var_it - enm.m_variants.begin(); - } + size_t idx = enm.find_variant(var_name); + ASSERT_BUG(sp, idx != SIZE_MAX, "Variant " << node.m_path.m_path << " isn't present"); - m_builder.set_result( node.span(), ::MIR::RValue::make_Struct({ - node.m_path.clone(), - variant_index, - mv$(values) - }) ); + // TODO: Validation? + ASSERT_BUG(sp, enm.m_data.is_Data(), "TupleVariant on non-data enum - " << node.m_path.m_path); + const auto& var_ty = enm.m_data.as_Data()[idx].type; + + // Take advantage of the identical generics to cheaply clone/monomorph the path. + const auto& str = *var_ty.m_data.as_Path().binding.as_Struct(); + ::HIR::GenericPath struct_path = node.m_path.clone(); + struct_path.m_path = var_ty.m_data.as_Path().path.m_data.as_Generic().m_path; + + // Create struct instance + m_builder.set_result( node.span(), ::MIR::RValue::make_Struct({ + struct_path.clone(), + mv$(values) + }) ); + + auto ty = ::HIR::TypeRef::new_path( mv$(struct_path), &str ); + auto v = m_builder.get_result_in_param(node.span(), ty); + m_builder.set_result(node.span(), ::MIR::RValue::make_Variant({ + mv$(enum_path), + static_cast<unsigned>(idx), + mv$(v) + }) ); + } } ::std::vector< ::MIR::Param> get_args(/*const*/ ::std::vector<::HIR::ExprNodeP>& args) @@ -1949,24 +1974,40 @@ namespace { { const Span& sp = node.span(); TRACE_FUNCTION_F("_UnitVariant"); - unsigned int variant_index = ~0u; if( !node.m_is_struct ) { // Get the variant index from the enum. auto enum_path = node.m_path.m_path; enum_path.m_components.pop_back(); const auto& var_name = node.m_path.m_path.m_components.back(); + const auto& enm = m_builder.crate().get_enum_by_path(sp, enum_path); - auto var_it = ::std::find_if(enm.m_variants.begin(), enm.m_variants.end(), [&](const auto& x){ return x.first == var_name; }); - ASSERT_BUG(sp, var_it != enm.m_variants.end(), "Variant " << node.m_path.m_path << " isn't present"); - variant_index = var_it - enm.m_variants.begin(); + auto idx = enm.find_variant(var_name); + ASSERT_BUG(sp, idx != SIZE_MAX, "Variant " << node.m_path.m_path << " isn't present"); + + // VALIDATION + if( const auto* e = enm.m_data.opt_Data() ) + { + const auto& var = (*e)[idx]; + ASSERT_BUG(sp, !var.is_struct, "Variant " << node.m_path.m_path << " isn't a unit variant"); + } + + m_builder.set_result( node.span(), ::MIR::RValue::make_Tuple({}) ); + auto v = m_builder.get_result_in_param(node.span(), ::HIR::TypeRef::new_unit()); + m_builder.set_result( node.span(), ::MIR::RValue::make_Variant({ + mv$(enum_path), + static_cast<unsigned>(idx), + mv$(v) + }) ); + } + else + { + m_builder.set_result( node.span(), ::MIR::RValue::make_Struct({ + node.m_path.clone(), + {} + }) ); } - m_builder.set_result( node.span(), ::MIR::RValue::make_Struct({ - node.m_path.clone(), - variant_index, - {} - }) ); } void visit(::HIR::ExprNode_PathValue& node) override { @@ -1974,18 +2015,23 @@ namespace { TRACE_FUNCTION_F("_PathValue - " << node.m_path); TU_MATCH( ::HIR::Path::Data, (node.m_path.m_data), (pe), (Generic, + // Enum variant constructor. if( node.m_target == ::HIR::ExprNode_PathValue::ENUM_VAR_CONSTR ) { auto enum_path = pe.m_path; enum_path.m_components.pop_back(); const auto& var_name = pe.m_path.m_components.back(); + // Validation only. const auto& enm = m_builder.crate().get_enum_by_path(sp, enum_path); - auto var_it = ::std::find_if(enm.m_variants.begin(), enm.m_variants.end(), [&](const auto& x){ return x.first == var_name; }); - ASSERT_BUG(sp, var_it != enm.m_variants.end(), "Variant " << pe.m_path << " isn't present"); - const auto& var = var_it->second; - ASSERT_BUG(sp, var.is_Tuple(), "Variant " << pe.m_path << " isn't a tuple variant"); - - // TODO: Ideally, the creation of the wrapper function would happen somewhere before this? + ASSERT_BUG(sp, enm.m_data.is_Data(), "Getting variant constructor of value varianta"); + size_t idx = enm.find_variant(var_name); + ASSERT_BUG(sp, idx != SIZE_MAX, "Variant " << pe.m_path << " isn't present"); + const auto& var = enm.m_data.as_Data()[idx]; + ASSERT_BUG(sp, var.type.m_data.is_Path(), "Variant " << pe.m_path << " isn't a tuple"); + const auto& str = *var.type.m_data.as_Path().binding.as_Struct(); + ASSERT_BUG(sp, str.m_data.is_Tuple(), "Variant " << pe.m_path << " isn't a tuple"); + + // TODO: Ideally, the creation of the wrapper function would happen somewhere before trans? auto tmp = m_builder.new_temporary( node.m_res_type ); m_builder.push_stmt_assign( sp, tmp.clone(), ::MIR::Constant::make_ItemAddr(node.m_path.clone()) ); m_builder.set_result( sp, mv$(tmp) ); @@ -2008,7 +2054,6 @@ namespace { // TODO: Why is this still a PathValue? m_builder.set_result( node.span(), ::MIR::RValue::make_Struct({ pe.clone(), - ~0u, {} }) ); ), @@ -2115,9 +2160,13 @@ namespace { m_builder.set_result( node.span(), m_builder.get_variable(node.span(), node.m_slot) ); } - void visit(::HIR::ExprNode_StructLiteral& node) override + void visit_sl_inner(::HIR::ExprNode_StructLiteral& node, const ::HIR::Struct& str, const ::HIR::GenericPath& path) { - TRACE_FUNCTION_F("_StructLiteral"); + const Span& sp = node.span(); + + ASSERT_BUG(sp, str.m_data.is_Named(), ""); + const ::HIR::t_struct_fields& fields = str.m_data.as_Named(); + ::MIR::LValue base_val; if( node.m_base_value ) { @@ -2126,37 +2175,6 @@ namespace { base_val = m_builder.get_result_in_lvalue(node.m_base_value->span(), node.m_base_value->m_res_type); } - unsigned int variant_index = ~0u; - const ::HIR::t_struct_fields* fields_ptr = nullptr; - TU_MATCH(::HIR::TypeRef::TypePathBinding, (node.m_res_type.m_data.as_Path().binding), (e), - (Unbound, ), - (Opaque, ), - (Enum, - const auto& var_name = node.m_path.m_path.m_components.back(); - const auto& enm = *e; - auto it = ::std::find_if(enm.m_variants.begin(), enm.m_variants.end(), [&](const auto&v)->auto{ return v.first == var_name; }); - assert(it != enm.m_variants.end()); - variant_index = it - enm.m_variants.begin(); - fields_ptr = &it->second.as_Struct(); - ), - (Union, - BUG(node.span(), "_StructLiteral Union"); - ), - (Struct, - if(e->m_data.is_Unit()) { - m_builder.set_result( node.span(), ::MIR::RValue::make_Struct({ - node.m_path.clone(), - variant_index, - {} - }) ); - return ; - } - fields_ptr = &e->m_data.as_Named(); - ) - ) - assert(fields_ptr); - const ::HIR::t_struct_fields& fields = *fields_ptr; - ::std::vector<bool> values_set; ::std::vector< ::MIR::Param> values; values.resize( fields.size() ); @@ -2198,11 +2216,63 @@ namespace { } m_builder.set_result( node.span(), ::MIR::RValue::make_Struct({ - node.m_path.clone(), - variant_index, + path.clone(), mv$(values) }) ); } + + void visit(::HIR::ExprNode_StructLiteral& node) override + { + TRACE_FUNCTION_F("_StructLiteral"); + + TU_MATCH(::HIR::TypeRef::TypePathBinding, (node.m_res_type.m_data.as_Path().binding), (e), + (Unbound, ), + (Opaque, ), + (Enum, + auto enum_path = node.m_path.m_path; + enum_path.m_components.pop_back(); + const auto& var_name = node.m_path.m_path.m_components.back(); + + const auto& enm = *e; + size_t idx = enm.find_variant(var_name); + ASSERT_BUG(node.span(), idx != SIZE_MAX, ""); + ASSERT_BUG(node.span(), enm.m_data.is_Data(), ""); + const auto& var_ty = enm.m_data.as_Data()[idx].type; + const auto& str = *var_ty.m_data.as_Path().binding.as_Struct(); + + // Take advantage of the identical generics to cheaply clone/monomorph the path. + ::HIR::GenericPath struct_path = node.m_path.clone(); + struct_path.m_path = var_ty.m_data.as_Path().path.m_data.as_Generic().m_path; + + this->visit_sl_inner(node, str, struct_path); + + // Create type of result from the above path + auto ty = ::HIR::TypeRef::new_path( mv$(struct_path), &str ); + // Obtain in a param + auto v = m_builder.get_result_in_param(node.span(), ty); + // And create Variant + m_builder.set_result( node.span(), ::MIR::RValue::make_Variant({ + mv$(enum_path), + static_cast<unsigned>(idx), + mv$(v) + }) ); + ), + (Union, + BUG(node.span(), "_StructLiteral Union isn't valid?"); + ), + (Struct, + if(e->m_data.is_Unit()) { + m_builder.set_result( node.span(), ::MIR::RValue::make_Struct({ + node.m_path.clone(), + {} + }) ); + return ; + } + + this->visit_sl_inner(node, *e, node.m_path); + ) + ) + } void visit(::HIR::ExprNode_UnionLiteral& node) override { TRACE_FUNCTION_F("_UnionLiteral " << node.m_path); @@ -2281,7 +2351,6 @@ namespace { m_builder.set_result( node.span(), ::MIR::RValue::make_Struct({ node.m_obj_path.clone(), - ~0u, mv$(vals) }) ); } diff --git a/src/mir/from_hir_match.cpp b/src/mir/from_hir_match.cpp index 55d7377e..61548fd2 100644 --- a/src/mir/from_hir_match.cpp +++ b/src/mir/from_hir_match.cpp @@ -806,57 +806,24 @@ void PatternRulesetBuilder::append_from_lit(const Span& sp, const ::HIR::Literal (Enum, ASSERT_BUG(sp, lit.is_Variant(), "Matching enum non-variant literal - " << lit); auto var_idx = lit.as_Variant().idx; - const auto& list = lit.as_Variant().vals; + const auto& subval = *lit.as_Variant().val; auto monomorph = [&](const auto& ty) { auto rv = monomorphise_type(sp, pbe->m_params, e.path.m_data.as_Generic().m_params, ty); this->m_resolve.expand_associated_types(sp, rv); return rv; }; - ASSERT_BUG(sp, var_idx < pbe->m_variants.size(), "Literal refers to a variant out of range"); - const auto& var_def = pbe->m_variants.at(var_idx); - + ASSERT_BUG(sp, var_idx < pbe->num_variants(), "Literal refers to a variant out of range"); PatternRulesetBuilder sub_builder { this->m_resolve }; - sub_builder.m_field_path = m_field_path; - sub_builder.m_field_path.push_back(var_idx); - sub_builder.m_field_path.push_back(0); - - TU_MATCH( ::HIR::Enum::Variant, (var_def.second), (fields_def), - (Unit, - ), - (Value, - ), - (Tuple, - ASSERT_BUG(sp, fields_def.size() == list.size(), ""); - - for( unsigned int i = 0; i < list.size(); i ++ ) - { - sub_builder.m_field_path.back() = i; - const auto& val = list[i]; - const auto& ty_tpl = fields_def[i].ent; - - ::HIR::TypeRef tmp; - const auto& subty = (monomorphise_type_needed(ty_tpl) ? tmp = monomorph(ty_tpl) : ty_tpl); - - sub_builder.append_from_lit( sp, val, subty ); - } - ), - (Struct, - ASSERT_BUG(sp, fields_def.size() == list.size(), ""); - - for( unsigned int i = 0; i < list.size(); i ++ ) - { - sub_builder.m_field_path.back() = i; - const auto& val = list[i]; - const auto& ty_tpl = fields_def[i].second.ent; + if( const auto* e = pbe->m_data.opt_Data() ) + { + const auto& var_def = e->at(var_idx); - ::HIR::TypeRef tmp; - const auto& subty = (monomorphise_type_needed(ty_tpl) ? tmp = monomorph(ty_tpl) : ty_tpl); + sub_builder.m_field_path = m_field_path; + sub_builder.m_field_path.push_back(var_idx); - sub_builder.append_from_lit( sp, val, subty ); - } - ) - ) + sub_builder.append_from_lit(sp, subval, monomorph(var_def.type)); + } this->push_rule( PatternRule::make_Variant({ var_idx, mv$(sub_builder.m_rules) }) ); ) @@ -1253,9 +1220,12 @@ void PatternRulesetBuilder::append_from(const Span& sp, const ::HIR::Pattern& pa this->push_rule( PatternRule::make_Variant( {pe.binding_idx, {} } ) ); ), (EnumTuple, - const auto& var_def = pe.binding_ptr->m_variants.at(pe.binding_idx); + const auto& variants = pe.binding_ptr->m_data.as_Data(); + const auto& var_def = variants.at(pe.binding_idx); + const auto& str = *var_def.type.m_data.as_Path().binding.as_Struct(); + const auto& fields_def = str.m_data.as_Tuple(); - const auto& fields_def = var_def.second.as_Tuple(); + // TODO: Unify with the struct pattern code? PatternRulesetBuilder sub_builder { this->m_resolve }; sub_builder.m_field_path = m_field_path; sub_builder.m_field_path.push_back(pe.binding_idx); @@ -1276,8 +1246,11 @@ void PatternRulesetBuilder::append_from(const Span& sp, const ::HIR::Pattern& pa this->push_rule( PatternRule::make_Variant({ pe.binding_idx, mv$(sub_builder.m_rules) }) ); ), (EnumStruct, - const auto& var_def = pe.binding_ptr->m_variants.at(pe.binding_idx); - const auto& fields_def = var_def.second.as_Struct(); + const auto& variants = pe.binding_ptr->m_data.as_Data(); + const auto& var_def = variants.at(pe.binding_idx); + const auto& str = *var_def.type.m_data.as_Path().binding.as_Struct(); + const auto& fields_def = str.m_data.as_Named(); + // 1. Create a vector of pattern indexes for each field in the variant. ::std::vector<unsigned int> tmp; tmp.resize( fields_def.size(), ~0u ); @@ -1807,32 +1780,13 @@ namespace { return &ty; } }; - ASSERT_BUG(sp, idx < pbe->m_variants.size(), "Variant index (" << idx << ") out of range (" << pbe->m_variants.size() << ") for enum " << *cur_ty); - const auto& var = pbe->m_variants[idx]; - - i++; - assert(i < field_path.data.size()); - unsigned fld_idx = field_path.data[i]; + ASSERT_BUG(sp, pbe->m_data.is_Data(), "Value enum being destructured - " << *cur_ty); + const auto& variants = pbe->m_data.as_Data(); + ASSERT_BUG(sp, idx < variants.size(), "Variant index (" << idx << ") out of range (" << variants.size() << ") for enum " << *cur_ty); + const auto& var = variants[idx]; - TU_MATCHA( (var.second), (e), - (Unit, - BUG(sp, "Unit variant being destructured"); - ), - (Value, - BUG(sp, "Value variant being destructured"); - ), - (Tuple, - ASSERT_BUG(sp, fld_idx < e.size(), "Variant field index (" << fld_idx << ") out of range (" << e.size() << ") for enum " << *cur_ty << "::" << var.first); - cur_ty = monomorph_to_ptr(e[fld_idx].ent); - ), - (Struct, - ASSERT_BUG(sp, fld_idx < e.size(), "Variant field index (" << fld_idx << ") out of range (" << e.size() << ") for enum " << *cur_ty << "::" << var.first); - cur_ty = monomorph_to_ptr(e[fld_idx].second.ent); - ) - ) - DEBUG("*cur_ty = " << *cur_ty); + cur_ty = monomorph_to_ptr(var.type); lval = ::MIR::LValue::make_Downcast({ box$(lval), idx }); - lval = ::MIR::LValue::make_Field({ box$(lval), fld_idx }); ) ) ), @@ -2206,7 +2160,7 @@ int MIR_LowerHIR_Match_Simple__GeneratePattern(MirBuilder& builder, const Span& unsigned int var_idx = re.idx; auto next_bb = builder.new_bb_unlinked(); - auto var_count = pbe->m_variants.size(); + auto var_count = pbe->num_variants(); // Generate a switch with only one option different. ::std::vector< ::MIR::BasicBlockId> arms(var_count, fail_bb); @@ -2217,49 +2171,18 @@ int MIR_LowerHIR_Match_Simple__GeneratePattern(MirBuilder& builder, const Span& 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) ); - - // 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()+1, - fail_bb - ); - ), - (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) ); - - // 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()+1, - fail_bb - ); - ) - ) + ASSERT_BUG(sp, pbe->m_data.is_Data(), "Sub-rules present for non-data enum"); + const auto& variants = pbe->m_data.as_Data(); + const auto& var_ty = variants.at(re.idx).type; + ::HIR::TypeRef tmp; + const auto& var_ty_m = (monomorphise_type_needed(var_ty) ? tmp = monomorph(var_ty) : var_ty); + + // Recurse with the new ruleset + MIR_LowerHIR_Match_Simple__GeneratePattern(builder, sp, + re.sub_rules.data(), re.sub_rules.size(), + var_ty_m, ::MIR::LValue::make_Downcast({ box$(val.clone()), var_idx }), rule.field_path.size()+1, + fail_bb + ); } ) // TypePathBinding::Enum ) @@ -3098,7 +3021,7 @@ void MatchGenGrouped::gen_dispatch__enum(::HIR::TypeRef ty, ::MIR::LValue val, c auto decison_arm = m_builder.pause_cur_block(); - auto var_count = pbe->m_variants.size(); + auto var_count = pbe->num_variants(); ::std::vector< ::MIR::BasicBlockId> arms(var_count, def_blk); size_t arm_idx = 0; for(size_t i = 0; i < rules.size(); i ++) diff --git a/src/mir/helpers.cpp b/src/mir/helpers.cpp index ddab9317..1e43e361 100644 --- a/src/mir/helpers.cpp +++ b/src/mir/helpers.cpp @@ -200,34 +200,20 @@ const ::HIR::TypeRef& ::MIR::TypeResolve::get_lvalue_type(::HIR::TypeRef& tmp, c if( te.binding.is_Enum() ) { const auto& enm = *te.binding.as_Enum(); - const auto& variants = enm.m_variants; - MIR_ASSERT(*this, e.variant_index < variants.size(), "Variant index out of range"); + MIR_ASSERT(*this, enm.m_data.is_Data(), "Downcast on non-data enum - " << ty); + const auto& variants = enm.m_data.as_Data(); + MIR_ASSERT(*this, e.variant_index < variants.size(), "Variant index out of range for " << ty); const auto& variant = variants[e.variant_index]; - // TODO: Make data variants refer to associated types (unify enum and struct handling) - TU_MATCHA( (variant.second), (ve), - (Value, - ), - (Unit, - ), - (Tuple, - // HACK! Create tuple. - ::std::vector< ::HIR::TypeRef> tys; - for(const auto& fld : ve) - tys.push_back( monomorphise_type(sp, enm.m_params, te.path.m_data.as_Generic().m_params, fld.ent) ); - tmp = ::HIR::TypeRef( mv$(tys) ); - m_resolve.expand_associated_types(sp, tmp); - return tmp; - ), - (Struct, - // HACK! Create tuple. - ::std::vector< ::HIR::TypeRef> tys; - for(const auto& fld : ve) - tys.push_back( monomorphise_type(sp, enm.m_params, te.path.m_data.as_Generic().m_params, fld.second.ent) ); - tmp = ::HIR::TypeRef( mv$(tys) ); + + const auto& var_ty = variant.type; + if( monomorphise_type_needed(var_ty) ) { + tmp = monomorphise_type(sp, enm.m_params, te.path.m_data.as_Generic().m_params, var_ty); m_resolve.expand_associated_types(sp, tmp); return tmp; - ) - ) + } + else { + return var_ty; + } } else { diff --git a/src/mir/mir.cpp b/src/mir/mir.cpp index 6af64001..18557304 100644 --- a/src/mir/mir.cpp +++ b/src/mir/mir.cpp @@ -384,8 +384,6 @@ namespace MIR { (Struct, if( are.path != bre.path ) return false; - if( are.variant_idx != bre.variant_idx ) - return false; return are.vals == bre.vals; ) ) @@ -610,13 +608,13 @@ namespace MIR { (Variant, return ::MIR::RValue::make_Variant({ e.path.clone(), e.index, e.val.clone() }); ), - // Create a new instance of a struct (or enum) + // Create a new instance of a struct (Struct, decltype(e.vals) ret; ret.reserve(e.vals.size()); for(const auto& v : e.vals) ret.push_back( v.clone() ); - return ::MIR::RValue::make_Struct({ e.path.clone(), e.variant_idx, mv$(ret) }); + return ::MIR::RValue::make_Struct({ e.path.clone(), mv$(ret) }); ) ) throw ""; diff --git a/src/mir/mir.hpp b/src/mir/mir.hpp index 987e0498..3ce115b8 100644 --- a/src/mir/mir.hpp +++ b/src/mir/mir.hpp @@ -187,10 +187,9 @@ TAGGED_UNION_EX(RValue, (), Use, ( unsigned int index; Param val; }), - // Create a new instance of a struct (or enum) + // Create a new instance of a struct (Struct, struct { ::HIR::GenericPath path; - unsigned int variant_idx; // if ~0, it's a struct ::std::vector<Param> vals; }) ), (),(), ( diff --git a/src/mir/mir_builder.cpp b/src/mir/mir_builder.cpp index 1e72282a..5776ebcf 100644 --- a/src/mir/mir_builder.cpp +++ b/src/mir/mir_builder.cpp @@ -1722,41 +1722,22 @@ void MirBuilder::with_val_type(const Span& sp, const ::MIR::LValue& val, ::std:: BUG(sp, "Downcast on unexpected type - " << ty); ), (Path, - // TODO: Union? if( const auto* pbe = te.binding.opt_Enum() ) { const auto& enm = **pbe; - const auto& variants = enm.m_variants; + ASSERT_BUG(sp, enm.m_data.is_Data(), "Downcast on non-data enum"); + const auto& variants = enm.m_data.as_Data(); ASSERT_BUG(sp, e.variant_index < variants.size(), "Variant index out of range"); const auto& variant = variants[e.variant_index]; - // TODO: Make data variants refer to associated types (unify enum and struct handling) - TU_MATCHA( (variant.second), (ve), - (Value, - DEBUG(""); - cb(::HIR::TypeRef::new_unit()); - ), - (Unit, - cb(::HIR::TypeRef::new_unit()); - ), - (Tuple, - // HACK! Create tuple. - ::std::vector< ::HIR::TypeRef> tys; - for(const auto& fld : ve) - tys.push_back( monomorphise_type(sp, enm.m_params, te.path.m_data.as_Generic().m_params, fld.ent) ); - ::HIR::TypeRef tup( mv$(tys) ); - m_resolve.expand_associated_types(sp, tup); - cb(tup); - ), - (Struct, - // HACK! Create tuple. - ::std::vector< ::HIR::TypeRef> tys; - for(const auto& fld : ve) - tys.push_back( monomorphise_type(sp, enm.m_params, te.path.m_data.as_Generic().m_params, fld.second.ent) ); - ::HIR::TypeRef tup( mv$(tys) ); - m_resolve.expand_associated_types(sp, tup); - cb(tup); - ) - ) + + if( monomorphise_type_needed(variant.type) ) { + auto tmp = monomorphise_type(sp, enm.m_params, te.path.m_data.as_Generic().m_params, variant.type); + m_resolve.expand_associated_types(sp, tmp); + cb(tmp); + } + else { + cb(variant.type); + } } else if( const auto* pbe = te.binding.opt_Union() ) { @@ -2070,7 +2051,7 @@ VarState& MirBuilder::get_val_state_mut(const Span& sp, const ::MIR::LValue& lv) if( pb.is_Enum() ) { const auto& enm = *pb.as_Enum(); - var_count = enm.m_variants.size(); + var_count = enm.num_variants(); } else if( const auto* pbe = pb.opt_Union() ) { diff --git a/src/mir/optimise.cpp b/src/mir/optimise.cpp index 9ed889d9..dc3967b4 100644 --- a/src/mir/optimise.cpp +++ b/src/mir/optimise.cpp @@ -1120,7 +1120,7 @@ bool MIR_Optimise_Inlining(::MIR::TypeResolve& state, ::MIR::Function& fcn, bool return ::MIR::RValue::make_Variant({ this->monomorph(se.path), se.index, this->clone_param(se.val) }); ), (Struct, - return ::MIR::RValue::make_Struct({ this->monomorph(se.path), se.variant_idx, this->clone_param_vec(se.vals) }); + return ::MIR::RValue::make_Struct({ this->monomorph(se.path), this->clone_param_vec(se.vals) }); ) ) throw ""; diff --git a/src/mir/visit_crate_mir.cpp b/src/mir/visit_crate_mir.cpp index 93d5f6ea..79d2e32a 100644 --- a/src/mir/visit_crate_mir.cpp +++ b/src/mir/visit_crate_mir.cpp @@ -72,14 +72,17 @@ void MIR::OuterVisitor::visit_enum(::HIR::ItemPath p, ::HIR::Enum& item) { auto _ = this->m_resolve.set_item_generics(item.m_params); - // TODO: Use a different type depding on repr() - auto enum_type = ::HIR::TypeRef(::HIR::CoreType::Isize); - - for(auto& var : item.m_variants) + if( auto* e = item.m_data.opt_Value() ) { - TU_IFLET(::HIR::Enum::Variant, var.second, Value, e, - m_cb(m_resolve, p + var.first, e.expr, {}, enum_type); - ) + // TODO: Use a different type depding on repr() + auto enum_type = ::HIR::TypeRef(::HIR::CoreType::Isize); + + for(auto& var : e->variants) + { + if( var.expr ) { + m_cb(m_resolve, p + var.name, var.expr, {}, enum_type); + } + } } } |