summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Hodge <tpg@ucc.asn.au>2017-11-01 20:46:36 +0800
committerJohn Hodge <tpg@ucc.asn.au>2017-11-01 20:46:36 +0800
commitcb271f8ea98d1a5c65a5e636a0e73a85710027b4 (patch)
tree9694427c074c0e0d581cde6e01b6167016e0f844
parent8306f43ccdf0414b48891aa5eb04d8901899c052 (diff)
downloadmrust-cb271f8ea98d1a5c65a5e636a0e73a85710027b4.tar.gz
HIR - Refactor enums to only embed a single field (and give variants types)
-rw-r--r--src/hir/deserialise.cpp63
-rw-r--r--src/hir/dump.cpp45
-rw-r--r--src/hir/expr_ptr.hpp9
-rw-r--r--src/hir/from_ast.cpp164
-rw-r--r--src/hir/from_ast_expr.cpp17
-rw-r--r--src/hir/hir.cpp58
-rw-r--r--src/hir/hir.hpp38
-rw-r--r--src/hir/serialise.cpp32
-rw-r--r--src/hir/visitor.cpp32
-rw-r--r--src/hir_conv/bind.cpp37
-rw-r--r--src/hir_conv/constant_evaluation.cpp39
-rw-r--r--src/hir_expand/annotate_value_usage.cpp31
-rw-r--r--src/hir_expand/closures.cpp19
-rw-r--r--src/hir_expand/const_eval_full.cpp36
-rw-r--r--src/hir_expand/reborrow.cpp16
-rw-r--r--src/hir_expand/ufcs_everything.cpp16
-rw-r--r--src/hir_typeck/expr_check.cpp51
-rw-r--r--src/hir_typeck/expr_cs.cpp52
-rw-r--r--src/hir_typeck/expr_visit.cpp23
-rw-r--r--src/hir_typeck/helpers.cpp39
-rw-r--r--src/hir_typeck/static.cpp66
-rw-r--r--src/mir/cleanup.cpp46
-rw-r--r--src/mir/from_hir.cpp203
-rw-r--r--src/mir/from_hir_match.cpp153
-rw-r--r--src/mir/helpers.cpp36
-rw-r--r--src/mir/mir.cpp6
-rw-r--r--src/mir/mir.hpp3
-rw-r--r--src/mir/mir_builder.cpp43
-rw-r--r--src/mir/optimise.cpp2
-rw-r--r--src/mir/visit_crate_mir.cpp17
-rw-r--r--src/resolve/absolute.cpp33
-rw-r--r--src/resolve/index.cpp39
-rw-r--r--src/resolve/use.cpp25
-rw-r--r--src/trans/codegen.cpp3
-rw-r--r--src/trans/codegen_c.cpp331
-rw-r--r--src/trans/enumerate.cpp55
-rw-r--r--src/trans/monomorphise.cpp1
37 files changed, 917 insertions, 962 deletions
diff --git a/src/hir/deserialise.cpp b/src/hir/deserialise.cpp
index b9d87bfa..968cf8d3 100644
--- a/src/hir/deserialise.cpp
+++ b/src/hir/deserialise.cpp
@@ -424,7 +424,6 @@ namespace {
})
_(Struct, {
deserialise_genericpath(),
- static_cast<unsigned int>( m_in.read_count() ),
deserialise_vec< ::MIR::Param>()
})
#undef _
@@ -619,7 +618,8 @@ namespace {
::HIR::Enum deserialise_enum();
- ::HIR::Enum::Variant deserialise_enumvariant();
+ ::HIR::Enum::DataVariant deserialise_enumdatavariant();
+ ::HIR::Enum::ValueVariant deserialise_enumvaluevariant();
::HIR::Struct deserialise_struct();
::HIR::Union deserialise_union();
@@ -685,7 +685,8 @@ namespace {
template<> DEF_D( ::HIR::ValueItem, return d.deserialise_valueitem(); )
template<> DEF_D( ::HIR::TypeItem, return d.deserialise_typeitem(); )
- template<> DEF_D( ::HIR::Enum::Variant, return d.deserialise_enumvariant(); )
+ template<> DEF_D( ::HIR::Enum::ValueVariant, return d.deserialise_enumvaluevariant(); )
+ template<> DEF_D( ::HIR::Enum::DataVariant, return d.deserialise_enumdatavariant(); )
template<> DEF_D( ::HIR::Literal, return d.deserialise_literal(); )
template<> DEF_D( ::HIR::AssociatedType, return d.deserialise_associatedtype(); )
@@ -878,31 +879,47 @@ namespace {
::HIR::Enum HirDeserialiser::deserialise_enum()
{
TRACE_FUNCTION;
+ struct H {
+ static ::HIR::Enum::Class deserialise_enumclass(HirDeserialiser& des) {
+ switch( des.m_in.read_tag() )
+ {
+ case ::HIR::Enum::Class::TAG_Data:
+ return ::HIR::Enum::Class::make_Data( des.deserialise_vec<::HIR::Enum::DataVariant>() );
+ case ::HIR::Enum::Class::TAG_Value:
+ return ::HIR::Enum::Class::make_Value({
+ static_cast< ::HIR::Enum::Repr>(des.m_in.read_tag()),
+ des.deserialise_vec<::HIR::Enum::ValueVariant>()
+ });
+ default:
+ throw "";
+ }
+ }
+ };
return ::HIR::Enum {
deserialise_genericparams(),
- static_cast< ::HIR::Enum::Repr>(m_in.read_tag()),
- deserialise_vec< ::std::pair< ::std::string, ::HIR::Enum::Variant> >(),
+ H::deserialise_enumclass(*this),
deserialise_markings()
};
}
- ::HIR::Enum::Variant HirDeserialiser::deserialise_enumvariant()
+ ::HIR::Enum::DataVariant HirDeserialiser::deserialise_enumdatavariant()
{
- switch( m_in.read_tag() )
- {
- case ::HIR::Enum::Variant::TAG_Unit:
- return ::HIR::Enum::Variant::make_Unit({});
- case ::HIR::Enum::Variant::TAG_Value:
- return ::HIR::Enum::Variant::make_Value({
- ::HIR::ExprPtr {},
- deserialise_literal()
- });
- case ::HIR::Enum::Variant::TAG_Tuple:
- return ::HIR::Enum::Variant( deserialise_vec< ::HIR::VisEnt< ::HIR::TypeRef> >() );
- case ::HIR::Enum::Variant::TAG_Struct:
- return ::HIR::Enum::Variant( deserialise_vec< ::std::pair< ::std::string, ::HIR::VisEnt< ::HIR::TypeRef> > >() );
- default:
- throw "";
- }
+ auto name = m_in.read_string();
+ DEBUG("Enum::DataVariant " << name);
+ return ::HIR::Enum::DataVariant {
+ mv$(name),
+ m_in.read_bool(),
+ deserialise_type()
+ };
+ }
+ ::HIR::Enum::ValueVariant HirDeserialiser::deserialise_enumvaluevariant()
+ {
+ auto name = m_in.read_string();
+ DEBUG("Enum::ValueVariant " << name);
+ return ::HIR::Enum::ValueVariant {
+ mv$(name),
+ ::HIR::ExprPtr {},
+ m_in.read_u64()
+ };
}
::HIR::Union HirDeserialiser::deserialise_union()
{
@@ -975,7 +992,7 @@ namespace {
_(List, deserialise_vec< ::HIR::Literal>() )
_(Variant, {
static_cast<unsigned int>(m_in.read_count()),
- deserialise_vec< ::HIR::Literal>()
+ box$( deserialise_literal() )
})
_(Integer, m_in.read_u64() )
_(Float, m_in.read_double() )
diff --git a/src/hir/dump.cpp b/src/hir/dump.cpp
index 75dde59f..3bbbdd95 100644
--- a/src/hir/dump.cpp
+++ b/src/hir/dump.cpp
@@ -158,38 +158,27 @@ namespace {
}
m_os << indent() << "{\n";
inc_indent();
- for(const auto& var : item.m_variants)
+ if(const auto* e = item.m_data.opt_Value())
{
- m_os << indent() << var.first;
- TU_MATCHA( (var.second), (e),
- (Unit,
- ),
- (Value,
- m_os << " = ";
- if( e.val.is_Invalid() ) {
- m_os << "?";
- }
- else {
- m_os << e.val;
+ for(const auto& var : e->variants)
+ {
+ m_os << indent() << var.name;
+ }
+ }
+ else
+ {
+ for(const auto& var : item.m_data.as_Data())
+ {
+ m_os << indent() << var.name;
+ if( var.type == ::HIR::TypeRef::new_unit() )
+ {
+
}
- ),
- (Tuple,
- m_os << "(";
- for(const auto& fld : e)
- m_os << fld.ent << ", ";
- m_os << ")";
- ),
- (Struct,
- m_os << "{\n";
- inc_indent();
- for(const auto& fld : e)
+ else
{
- m_os << indent() << fld.first << ": " << fld.second.ent << ",\n";
+ m_os << " " << var.type << (var.is_struct ? "/*struct*/" : "");
}
- m_os << indent() << "}";
- dec_indent();
- )
- )
+ }
m_os << ",\n";
}
dec_indent();
diff --git a/src/hir/expr_ptr.hpp b/src/hir/expr_ptr.hpp
index 5bedd1da..97991bf2 100644
--- a/src/hir/expr_ptr.hpp
+++ b/src/hir/expr_ptr.hpp
@@ -8,6 +8,7 @@
#pragma once
#include <memory>
#include <vector>
+#include <cassert>
#include <mir/mir_ptr.hpp>
@@ -47,10 +48,10 @@ public:
this->ptr = p;
}
- ::HIR::ExprNode& operator*() { return *ptr; }
- const ::HIR::ExprNode& operator*() const { return *ptr; }
- ::HIR::ExprNode* operator->() { return ptr; }
- const ::HIR::ExprNode* operator->() const { return ptr; }
+ ::HIR::ExprNode& operator*() { assert(ptr); return *ptr; }
+ const ::HIR::ExprNode& operator*() const { assert(ptr); return *ptr; }
+ ::HIR::ExprNode* operator->() { assert(ptr); return ptr; }
+ const ::HIR::ExprNode* operator->() const { assert(ptr); return ptr; }
};
class ExprPtr
diff --git a/src/hir/from_ast.cpp b/src/hir/from_ast.cpp
index 0f29f9b5..8c072cc5 100644
--- a/src/hir/from_ast.cpp
+++ b/src/hir/from_ast.cpp
@@ -217,8 +217,12 @@
field_count = var.as_Tuple().m_sub_types.size();
}
else {
- const auto& var = pb.hir->m_variants.at(pb.idx).second;
- field_count = var.as_Tuple().size();
+ const auto& var = pb.hir->m_data.as_Data().at(pb.idx);
+ // Need to be able to look up the type's actual definition
+ // - Either a name lookup, or have binding be done before this pass.
+ const auto& str = g_crate_ptr->get_struct_by_path(pat.span(), var.type.m_data.as_Path().path.m_data.as_Generic().m_path);
+ field_count = str.m_data.as_Tuple().size();
+ //field_count = var.type.m_data.as_Path().binding.as_Struct()->m_data.as_Tuple().size();
}
::std::vector<HIR::Pattern> sub_patterns;
@@ -862,48 +866,139 @@ namespace {
};
}
-::HIR::Enum LowerHIR_Enum(::HIR::ItemPath path, const ::AST::Enum& f)
+::HIR::Enum LowerHIR_Enum(::HIR::ItemPath path, const ::AST::Enum& ent, const ::AST::MetaItems& attrs, ::std::function<void(::std::string, ::HIR::Struct)> push_struct)
{
- ::std::vector< ::std::pair< ::std::string, ::HIR::Enum::Variant> > variants;
- for(const auto& var : f.variants())
+ // 1. Figure out what sort of enum this is (value or data)
+ bool has_value = false;
+ bool has_data = false;
+ for(const auto& var : ent.variants())
{
- TU_MATCH(::AST::EnumVariantData, (var.m_data), (e),
- (Value,
- if( e.m_value.is_valid() )
+ if( TU_TEST1(var.m_data, Value, .m_value.is_valid()) )
+ {
+ has_value = true;
+ }
+ else if( var.m_data.is_Tuple() || var.m_data.is_Struct() )
+ {
+ has_data = true;
+ }
+ else
+ {
+ // Unit-like
+ assert(var.m_data.is_Value());
+ }
+ }
+
+ if( has_value && has_data )
+ {
+ ERROR(Span(), E0000, "Enum " << path << " has both value and data variants");
+ }
+
+ ::HIR::Enum::Class data;
+ if( ent.variants().size() > 0 && !has_data )
+ {
+ ::std::vector<::HIR::Enum::ValueVariant> variants;
+ for(const auto& var : ent.variants())
+ {
+ const auto& ve = var.m_data.as_Value();
+ // TODO: Quick consteval on the expression?
+ variants.push_back({
+ var.m_name, LowerHIR_Expr(ve.m_value), 0
+ });
+ }
+
+ auto repr = ::HIR::Enum::Repr::Rust;
+ if( const auto* attr_repr = attrs.get("repr") )
+ {
+ ASSERT_BUG(Span(), attr_repr->has_sub_items(), "#[repr] attribute malformed, " << *attr_repr);
+ ASSERT_BUG(Span(), attr_repr->items().size() == 1, "#[repr] attribute malformed, " << *attr_repr);
+ ASSERT_BUG(Span(), attr_repr->items()[0].has_noarg(), "#[repr] attribute malformed, " << *attr_repr);
+ const auto& repr_str = attr_repr->items()[0].name();
+ if( repr_str == "C" ) {
+ repr = ::HIR::Enum::Repr::C;
+ }
+ else {
+ // TODO: Other repr types
+ }
+ }
+ data = ::HIR::Enum::Class::make_Value({ repr, mv$(variants) });
+ }
+ // NOTE: empty enums are encoded as empty Data enums
+ else
+ {
+ ::std::vector<::HIR::Enum::DataVariant> variants;
+ for(const auto& var : ent.variants())
+ {
+ if( var.m_data.is_Value() )
{
- variants.push_back( ::std::make_pair(var.m_name, ::HIR::Enum::Variant::make_Value({
- LowerHIR_Expr(e.m_value),
- ::HIR::Literal {}
- }) ) );
+ // TODO: Should this make its own unit-like struct?
+ variants.push_back({ var.m_name, false, ::HIR::TypeRef::new_unit() });
}
+ //else if( TU_TEST1(var.m_data, Tuple, m_sub_types.size() == 0) )
+ //{
+ // variants.push_back({ var.m_name, false, ::HIR::TypeRef::new_unit() });
+ //}
+ //else if( TU_TEST1(var.m_data, Tuple, m_sub_types.size() == 1) )
+ //{
+ // const auto& ty = var.m_data.as_Tuple().m_sub_types[0];
+ // variants.push_back({ var.m_name, false, LowerHIR_Type(ty) });
+ //}
else
{
- variants.push_back( ::std::make_pair(var.m_name, ::HIR::Enum::Variant::make_Unit({})) );
+ ::HIR::Struct::Data data;
+ if( const auto* ve = var.m_data.opt_Tuple() )
+ {
+ ::HIR::Struct::Data::Data_Tuple fields;
+ for(const auto& field : ve->m_sub_types)
+ fields.push_back( new_visent(true, LowerHIR_Type(field)) );
+ data = ::HIR::Struct::Data::make_Tuple( mv$(fields) );
+ }
+ else if( const auto* ve = var.m_data.opt_Struct() )
+ {
+ ::HIR::Struct::Data::Data_Named fields;
+ for(const auto& field : ve->m_fields)
+ fields.push_back( ::std::make_pair( field.m_name, new_visent(true, LowerHIR_Type(field.m_type)) ) );
+ data = ::HIR::Struct::Data::make_Named( mv$(fields) );
+ }
+ else
+ {
+ throw "";
+ }
+
+ auto ty_name = FMT(path.name << "#" << var.m_name);
+ push_struct(
+ ty_name,
+ ::HIR::Struct {
+ LowerHIR_GenericParams(ent.params(), nullptr),
+ ::HIR::Struct::Repr::Rust,
+ mv$(data)
+ }
+ );
+ auto ty_ipath = path;
+ ty_ipath.name = ty_name.c_str();
+ auto ty_path = ty_ipath.get_full_path();
+ // Add type params
+ {
+ auto& params = ty_path.m_data.as_Generic().m_params;
+ unsigned int i = 0;
+ for(const auto& typ : ent.params().ty_params())
+ params.m_types.push_back( ::HIR::TypeRef/*::new_generic*/(typ.name(), i++) );
+ }
+ variants.push_back({ var.m_name, var.m_data.is_Struct(), ::HIR::TypeRef::new_path( mv$(ty_path), {} ) });
}
- ),
- (Tuple,
- ::HIR::Enum::Variant::Data_Tuple types;
- for(const auto& st : e.m_sub_types)
- types.push_back( new_visent(true, LowerHIR_Type(st)) );
- variants.push_back( ::std::make_pair(var.m_name, ::HIR::Enum::Variant::make_Tuple(mv$(types))) );
- ),
- (Struct,
- ::HIR::Enum::Variant::Data_Struct ents;
- for( const auto& ent : e.m_fields )
- ents.push_back( ::std::make_pair( ent.m_name, new_visent(true, LowerHIR_Type(ent.m_type)) ) );
- variants.push_back( ::std::make_pair(var.m_name, ::HIR::Enum::Variant::make_Struct(mv$(ents))) );
- )
- )
- }
+ }
- auto repr = ::HIR::Enum::Repr::Rust;
- // TODO: Get repr from attributes
+ if( /*const auto* attr_repr =*/ attrs.get("repr") )
+ {
+ // NOTE: librustc_llvm has `#[repr(C)] enum AttributePlace { Argument(u32), Function }`
+ //ERROR(Span(), E0000, "#[repr] not allowed on enums with data");
+ }
+ data = ::HIR::Enum::Class::make_Data( mv$(variants) );
+ }
return ::HIR::Enum {
- LowerHIR_GenericParams(f.params(), nullptr),
- repr,
- mv$(variants)
+ LowerHIR_GenericParams(ent.params(), nullptr),
+ mv$(data)
};
}
::HIR::Union LowerHIR_Union(::HIR::ItemPath path, const ::AST::Union& f, const ::AST::MetaItems& attrs)
@@ -1252,7 +1347,8 @@ void _add_mod_val_item(::HIR::Module& mod, ::std::string name, bool is_pub, ::H
_add_mod_ns_item( mod, item.name, item.is_pub, LowerHIR_Struct(item_path, e) );
),
(Enum,
- _add_mod_ns_item( mod, item.name, item.is_pub, LowerHIR_Enum(item_path, e) );
+ auto enm = LowerHIR_Enum(item_path, e, item.data.attrs, [&](auto name, auto str){ _add_mod_ns_item(mod, name, item.is_pub, mv$(str)); });
+ _add_mod_ns_item( mod, item.name, item.is_pub, mv$(enm) );
),
(Union,
_add_mod_ns_item( mod, item.name, item.is_pub, LowerHIR_Union(item_path, e, item.data.attrs) );
diff --git a/src/hir/from_ast_expr.cpp b/src/hir/from_ast_expr.cpp
index a98140d7..ef20f08d 100644
--- a/src/hir/from_ast_expr.cpp
+++ b/src/hir/from_ast_expr.cpp
@@ -629,14 +629,19 @@ struct LowerHIR_ExprNode_Visitor:
else
{
const auto& enm = *e.hir;
- auto it = ::std::find_if(enm.m_variants.begin(), enm.m_variants.end(), [&](const auto& x){ return x.first == var_name; });
- assert(it != enm.m_variants.end());
+ auto idx = enm.find_variant(var_name);
+ assert(idx != SIZE_MAX);
- var_idx = static_cast<unsigned int>(it - enm.m_variants.begin());
- if( it->second.is_Struct() ) {
- ERROR(v.span(), E0000, "Named value referring to an enum that isn't tuple-like or unit-like - " << v.m_path);
+ var_idx = idx;
+ if( const auto* ee = enm.m_data.opt_Data() )
+ {
+ if( ee->at(idx).type == ::HIR::TypeRef::new_unit() ) {
+ }
+ // TODO: Assert that it's not a struct-like
+ else {
+ is_tuple_constructor = true;
+ }
}
- is_tuple_constructor = it->second.is_Tuple();
}
(void)var_idx; // TODO: Save time later by saving this.
if( is_tuple_constructor ) {
diff --git a/src/hir/hir.cpp b/src/hir/hir.cpp
index ed6230d5..99fac517 100644
--- a/src/hir/hir.cpp
+++ b/src/hir/hir.cpp
@@ -25,10 +25,7 @@ namespace HIR {
os << " ]";
),
(Variant,
- os << "#" << e.idx << ":[";
- for(const auto& val : e.vals)
- os << " " << val << ",";
- os << " ]";
+ os << "#" << e.idx << ":" << *e.val;
),
(Integer,
os << e;
@@ -66,11 +63,7 @@ namespace HIR {
(Variant,
if( le.idx != re.idx )
return false;
- if( le.vals.size() != re.vals.size() )
- return false;
- for(unsigned int i = 0; i < le.vals.size(); i ++)
- if( le.vals[i] != re.vals[i] )
- return false;
+ return *le.val == *re.val;
),
(Integer,
return le == re;
@@ -92,36 +85,43 @@ namespace HIR {
}
}
-const ::HIR::Enum::Variant* ::HIR::Enum::get_variant(const ::std::string& name) const
+size_t ::HIR::Enum::find_variant(const ::std::string& name) const
{
- auto it = ::std::find_if(m_variants.begin(), m_variants.end(), [&](const auto& x){ return x.first == name; });
- if( it == m_variants.end() )
- return nullptr;
- return &it->second;
+ if( m_data.is_Value() )
+ {
+ const auto& e = m_data.as_Value();
+ auto it = ::std::find_if(e.variants.begin(), e.variants.end(), [&](const auto& x){ return x.name == name; });
+ if( it == e.variants.end() )
+ return SIZE_MAX;
+ return it - e.variants.begin();
+ }
+ else
+ {
+ const auto& e = m_data.as_Data();
+
+ auto it = ::std::find_if(e.begin(), e.end(), [&](const auto& x){ return x.name == name; });
+ if( it == e.end() )
+ return SIZE_MAX;
+ return it - e.begin();
+ }
}
bool HIR::Enum::is_value() const
{
- return this->m_repr != ::HIR::Enum::Repr::Rust || ::std::all_of(m_variants.begin(), m_variants.end(), [](const auto& x){return x.second.is_Unit() || x.second.is_Value();});
+ return this->m_data.is_Value();
}
uint32_t HIR::Enum::get_value(size_t idx) const
{
- assert(idx < m_variants.size());
-
- if( const auto* e = m_variants[idx].second.opt_Value() )
+ if( m_data.is_Value() )
{
- return e->val.as_Integer();
- }
+ const auto& e = m_data.as_Value();
+ assert(idx < e.variants.size());
- uint32_t val = 0;
- for(size_t i = 0; i < idx; i ++)
+ return e.variants[idx].val;
+ }
+ else
{
- if( const auto* e = m_variants[i].second.opt_Value() )
- {
- val = e->val.as_Integer();
- }
- val ++;
+ assert(!"TODO: Enum::get_value on non-value enum?");
}
- return val;
}
namespace {
@@ -1214,7 +1214,7 @@ const ::HIR::Function& ::HIR::Crate::get_function_by_path(const Span& sp, const
return e;
)
else {
- BUG(sp, "Enum path " << path << " didn't point to an enum");
+ BUG(sp, "Function path " << path << " didn't point to an function");
}
}
diff --git a/src/hir/hir.hpp b/src/hir/hir.hpp
index cc34c227..f13b1860 100644
--- a/src/hir/hir.hpp
+++ b/src/hir/hir.hpp
@@ -54,7 +54,7 @@ TAGGED_UNION(Literal, Invalid,
// Variant = Enum variant
(Variant, struct {
unsigned int idx;
- ::std::vector<Literal> vals;
+ ::std::unique_ptr<Literal> val;
}),
// Literal values
(Integer, uint64_t),
@@ -213,33 +213,43 @@ struct StructMarkings
class Enum
{
public:
- TAGGED_UNION(Variant, Unit,
- (Unit, struct{}),
- (Value, struct {
- ::HIR::ExprPtr expr;
- Literal val;
- }),
- (Tuple, t_tuple_fields),
- (Struct, t_struct_fields)
- );
+ struct DataVariant {
+ ::std::string name;
+ bool is_struct; // Indicates that the variant does not show up in the value namespace
+ ::HIR::TypeRef type;
+ };
enum class Repr
{
Rust,
C,
U8, U16, U32,
};
+ struct ValueVariant {
+ ::std::string name;
+ ::HIR::ExprPtr expr;
+ uint64_t val;
+ };
+ TAGGED_UNION(Class, Data,
+ (Data, ::std::vector<DataVariant>),
+ (Value, struct {
+ Repr repr;
+ ::std::vector<ValueVariant> variants;
+ })
+ );
GenericParams m_params;
- Repr m_repr;
- ::std::vector< ::std::pair< ::std::string, Variant > > m_variants;
+ Class m_data;
TraitMarkings m_markings;
- const Variant* get_variant(const ::std::string& ) const;
+ size_t num_variants() const {
+ return (m_data.is_Data() ? m_data.as_Data().size() : m_data.as_Value().variants.size());
+ }
+ size_t find_variant(const ::std::string& ) const;
/// Returns true if this enum is a C-like enum (has values only)
bool is_value() const;
- /// Returns the value for the given variant
+ /// Returns the value for the given variant (onlu for value enums)
uint32_t get_value(size_t variant) const;
};
class Struct
diff --git a/src/hir/serialise.cpp b/src/hir/serialise.cpp
index cac6b3c9..e200a39e 100644
--- a/src/hir/serialise.cpp
+++ b/src/hir/serialise.cpp
@@ -436,7 +436,7 @@ namespace {
),
(Variant,
m_out.write_count(e.idx);
- serialise_vec(e.vals);
+ serialise(*e.val);
),
(Integer,
m_out.write_u64(e);
@@ -685,7 +685,6 @@ namespace {
),
(Struct,
serialise_genericpath(e.path);
- m_out.write_count(e.variant_idx);
serialise_vec(e.vals);
)
)
@@ -852,30 +851,35 @@ namespace {
void serialise(const ::HIR::Enum& item)
{
serialise_generics(item.m_params);
- m_out.write_tag( static_cast<int>(item.m_repr) );
-
- serialise_vec( item.m_variants );
+ serialise( item.m_data );
serialise(item.m_markings);
}
- void serialise(const ::HIR::Enum::Variant& v)
+ void serialise(const ::HIR::Enum::Class& v)
{
m_out.write_tag( v.tag() );
TU_MATCHA( (v), (e),
- (Unit,
- ),
(Value,
- // NOTE: e.expr skipped as it's not needed anymore
- serialise(e.val);
- ),
- (Tuple,
- serialise_vec(e);
+ m_out.write_tag( static_cast<int>(e.repr) );
+ serialise_vec(e.variants);
),
- (Struct,
+ (Data,
serialise_vec(e);
)
)
}
+ void serialise(const ::HIR::Enum::ValueVariant& v)
+ {
+ m_out.write_string(v.name);
+ // NOTE: No expr, no longer needed
+ m_out.write_u64(v.val);
+ }
+ void serialise(const ::HIR::Enum::DataVariant& v)
+ {
+ m_out.write_string(v.name);
+ m_out.write_bool(v.is_struct);
+ serialise(v.type);
+ }
void serialise(const ::HIR::TraitMarkings& m)
{
diff --git a/src/hir/visitor.cpp b/src/hir/visitor.cpp
index ed448cb4..2e03990a 100644
--- a/src/hir/visitor.cpp
+++ b/src/hir/visitor.cpp
@@ -213,26 +213,20 @@ void ::HIR::Visitor::visit_struct(::HIR::ItemPath p, ::HIR::Struct& item)
void ::HIR::Visitor::visit_enum(::HIR::ItemPath p, ::HIR::Enum& item)
{
this->visit_params(item.m_params);
- for(auto& var : item.m_variants)
- {
- TU_MATCH(::HIR::Enum::Variant, (var.second), (v),
- (Unit,
- ),
- (Value,
- this->visit_expr(v.expr);
- ),
- (Tuple,
- for(auto& ty : v) {
- this->visit_type(ty.ent);
- }
- ),
- (Struct,
- for(auto& field : v) {
- this->visit_type(field.second.ent);
- }
- )
+ TU_MATCHA( (item.m_data), (e),
+ (Value,
+ for(auto& var : e.variants)
+ {
+ this->visit_expr(var.expr);
+ }
+ ),
+ (Data,
+ for(auto& var : e)
+ {
+ this->visit_type(var.type);
+ }
)
- }
+ )
}
void ::HIR::Visitor::visit_union(::HIR::ItemPath p, ::HIR::Union& item)
{
diff --git a/src/hir_conv/bind.cpp b/src/hir_conv/bind.cpp
index 2deaac9d..11a6ac1c 100644
--- a/src/hir_conv/bind.cpp
+++ b/src/hir_conv/bind.cpp
@@ -80,8 +80,8 @@ namespace {
::std::pair< const ::HIR::Enum*, unsigned int> get_enum_ptr(const Span& sp, const ::HIR::Crate& crate, ::HIR::GenericPath& path) {
const auto& enm = *reinterpret_cast< const ::HIR::Enum*>( get_type_pointer(sp, crate, path.m_path, Target::EnumVariant) );
const auto& des_name = 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() ) {
+ auto idx = enm.find_variant(des_name);
+ if( idx == SIZE_MAX ) {
ERROR(sp, E0000, "Couldn't find enum variant " << path);
}
@@ -119,9 +119,7 @@ namespace {
}
),
(Variant,
- for(auto& val : e.vals) {
- visit_literal(sp, val);
- }
+ visit_literal(sp, *e.val);
),
(Integer,
),
@@ -161,17 +159,16 @@ namespace {
}
// Enum variant
- auto it = ::std::find_if( enm->m_variants.begin(), enm->m_variants.end(), [&](const auto&v){ return v.first == pc; });
- if( it == enm->m_variants.end() ) {
+ auto idx = enm->find_variant(pc);
+ if( idx == SIZE_MAX ) {
BUG(sp, "'" << pc << "' isn't a variant in path " << path);
}
- unsigned int index = it - enm->m_variants.begin();
auto path = mv$(pe);
fix_type_params(sp, enm->m_params, path.m_params);
pat.m_data = ::HIR::Pattern::Data::make_EnumValue({
mv$(path),
enm,
- index
+ static_cast<unsigned>(idx)
});
}
else if( (mod = ti.opt_Module()) )
@@ -263,27 +260,21 @@ namespace {
),
(EnumTuple,
auto p = get_enum_ptr(sp, m_crate, e.path);
- const auto& var = p.first->m_variants[p.second].second;
- if( var.is_Tuple() ) {
- }
- else {
+ if( !p.first->m_data.is_Data() )
+ ERROR(sp, E0000, "Enum tuple pattern on non-tuple variant " << e.path);
+ const auto& var = p.first->m_data.as_Data()[p.second];
+ if( var.is_struct )
ERROR(sp, E0000, "Enum tuple pattern on non-tuple variant " << e.path);
- }
e.binding_ptr = p.first;
e.binding_idx = p.second;
),
(EnumStruct,
auto p = get_enum_ptr(sp, m_crate, e.path);
- const auto& var = p.first->m_variants[p.second].second;
- if( var.is_Struct() ) {
- }
- else if( var.is_Unit() && e.sub_patterns.empty() ) {
- }
- else if( var.is_Tuple() && var.as_Tuple().empty() && e.sub_patterns.empty() ) {
- }
- else {
+ if( !p.first->m_data.is_Data() )
+ ERROR(sp, E0000, "Enum struct pattern `" << pat << "` on non-struct variant " << e.path);
+ const auto& var = p.first->m_data.as_Data()[p.second];
+ if( !var.is_struct )
ERROR(sp, E0000, "Enum struct pattern `" << pat << "` on non-struct variant " << e.path);
- }
e.binding_ptr = p.first;
e.binding_idx = p.second;
)
diff --git a/src/hir_conv/constant_evaluation.cpp b/src/hir_conv/constant_evaluation.cpp
index 0b54331c..f23d8e65 100644
--- a/src/hir_conv/constant_evaluation.cpp
+++ b/src/hir_conv/constant_evaluation.cpp
@@ -63,11 +63,7 @@ namespace {
return ::HIR::Literal( mv$(vals) );
),
(Variant,
- ::std::vector< ::HIR::Literal> vals;
- for(const auto& val : e.vals) {
- vals.push_back( clone_literal(val) );
- }
- return ::HIR::Literal::make_Variant({ e.idx, mv$(vals) });
+ return ::HIR::Literal::make_Variant({ e.idx, box$(clone_literal(*e.val)) });
),
(Integer,
return ::HIR::Literal(e);
@@ -595,11 +591,11 @@ namespace {
ASSERT_BUG(node.span(), ent.is_Enum(), "_TupleVariant with m_is_struct clear pointing to " << ent.tag_str());
const auto& enm = ent.as_Enum();
- auto it = ::std::find_if( enm.m_variants.begin(), enm.m_variants.end(), [&](const auto&x){ return x.first == varname; } );
- ASSERT_BUG(node.span(), it != enm.m_variants.end(), "_TupleVariant points to unknown variant - " << node.m_path);
- unsigned int var_idx = it - enm.m_variants.begin();
+ auto var_idx = enm.find_variant(varname);
+ ASSERT_BUG(node.span(), var_idx != SIZE_MAX, "_TupleVariant points to unknown variant - " << node.m_path);
- m_rv = ::HIR::Literal::make_Variant({var_idx, mv$(vals)});
+ auto inner = box$( ::HIR::Literal::make_List(mv$(vals)) );
+ m_rv = ::HIR::Literal::make_Variant({ static_cast<unsigned>(var_idx), mv$(inner) });
m_rv_type = ::HIR::TypeRef::new_path( mv$(tmp_path), ::HIR::TypeRef::TypePathBinding(&enm) );
}
}
@@ -766,11 +762,10 @@ namespace {
ASSERT_BUG(node.span(), ent.is_Enum(), "_UnitVariant with m_is_struct clear pointing to " << ent.tag_str());
const auto& enm = ent.as_Enum();
- auto it = ::std::find_if( enm.m_variants.begin(), enm.m_variants.end(), [&](const auto&x){ return x.first == varname; } );
- ASSERT_BUG(node.span(), it != enm.m_variants.end(), "_UnitVariant points to unknown variant - " << node.m_path);
- unsigned int var_idx = it - enm.m_variants.begin();
+ auto var_idx = enm.find_variant(varname);
+ ASSERT_BUG(node.span(), var_idx != SIZE_MAX, "_UnitVariant points to unknown variant - " << node.m_path);
- m_rv = ::HIR::Literal::make_Variant({var_idx, {}});
+ m_rv = ::HIR::Literal::make_Variant({ static_cast<unsigned>(var_idx), box$(::HIR::Literal::make_List({})) });
m_rv_type = ::HIR::TypeRef::new_path( mv$(tmp_path), ::HIR::TypeRef::TypePathBinding(&enm) );
}
}
@@ -1604,12 +1599,20 @@ namespace {
}
}
void visit_enum(::HIR::ItemPath p, ::HIR::Enum& item) override {
- for(auto& var : item.m_variants)
+ if( auto* e = item.m_data.opt_Value() )
{
- TU_IFLET(::HIR::Enum::Variant, var.second, Value, e,
- e.val = evaluate_constant(e.expr->span(), m_crate, NewvalState { m_new_values, *m_mod_path, FMT(p.get_name() << "$" << var.first << "$") }, e.expr, {});
- DEBUG("enum variant: " << p << "::" << var.first << " = " << e.val);
- )
+ uint64_t i = 0;
+ for(auto& var : e->variants)
+ {
+ if( var.expr )
+ {
+ auto val = evaluate_constant(var.expr->span(), m_crate, NewvalState { m_new_values, *m_mod_path, FMT(p.get_name() << "$" << var.name << "$") }, var.expr, {});
+ DEBUG("enum variant: " << p << "::" << var.name << " = " << val);
+ i = val.as_Integer();
+ }
+ var.val = i;
+ i ++;
+ }
}
::HIR::Visitor::visit_enum(p, item);
}
diff --git a/src/hir_expand/annotate_value_usage.cpp b/src/hir_expand/annotate_value_usage.cpp
index dbcd6b13..805eac4e 100644
--- a/src/hir_expand/annotate_value_usage.cpp
+++ b/src/hir_expand/annotate_value_usage.cpp
@@ -354,19 +354,24 @@ namespace {
void visit(::HIR::ExprNode_StructLiteral& node) override
{
+ const auto& sp = node.span();
if( node.m_base_value ) {
bool is_moved = false;
const auto& tpb = node.m_base_value->m_res_type.m_data.as_Path().binding;
- const ::HIR::t_struct_fields* fields_ptr;
+ const ::HIR::Struct* str;
if( tpb.is_Enum() ) {
- const auto* var = tpb.as_Enum()->get_variant( node.m_path.m_path.m_components.back() );
- ASSERT_BUG(node.span(), var, "");
- fields_ptr = &var->as_Struct();
+ const auto& enm = *tpb.as_Enum();
+ auto idx = enm.find_variant(node.m_path.m_path.m_components.back());
+ ASSERT_BUG(sp, idx != SIZE_MAX, "");
+ const auto& var_ty = enm.m_data.as_Data()[idx].type;
+ str = var_ty.m_data.as_Path().binding.as_Struct();
}
else {
- fields_ptr = &tpb.as_Struct()->m_data.as_Named();
+ str = tpb.as_Struct();
}
- const auto& fields = *fields_ptr;
+ ASSERT_BUG(sp, str->m_data.is_Named(), "");
+ const auto& fields = str->m_data.as_Named();
+
::std::vector<bool> provided_mask( fields.size() );
for( const auto& fld : node.m_values ) {
unsigned idx = ::std::find_if( fields.begin(), fields.end(), [&](const auto& x){ return x.first == fld.first; }) - fields.begin();
@@ -529,8 +534,11 @@ namespace {
),
(EnumTuple,
const auto& enm = *pe.binding_ptr;
- const auto& var = enm.m_variants.at(pe.binding_idx);
- const auto& flds = var.second.as_Tuple();
+ ASSERT_BUG(sp, enm.m_data.is_Data(), "");
+ const auto& var = enm.m_data.as_Data().at(pe.binding_idx);
+ const auto& str = *var.type.m_data.as_Path().binding.as_Struct();
+ ASSERT_BUG(sp, str.m_data.is_Tuple(), "");
+ const auto& flds = str.m_data.as_Tuple();
assert(pe.sub_patterns.size() == flds.size());
auto monomorph_cb = monomorphise_type_get_cb(sp, nullptr, &pe.path.m_params, nullptr);
@@ -543,8 +551,11 @@ namespace {
),
(EnumStruct,
const auto& enm = *pe.binding_ptr;
- const auto& var = enm.m_variants.at(pe.binding_idx);
- const auto& flds = var.second.as_Struct();
+ ASSERT_BUG(sp, enm.m_data.is_Data(), "");
+ const auto& var = enm.m_data.as_Data().at(pe.binding_idx);
+ const auto& str = *var.type.m_data.as_Path().binding.as_Struct();
+ ASSERT_BUG(sp, str.m_data.is_Named(), "");
+ const auto& flds = str.m_data.as_Named();
auto monomorph_cb = monomorphise_type_get_cb(sp, nullptr, &pe.path.m_params, nullptr);
auto rv = ::HIR::ValueUsage::Borrow;
diff --git a/src/hir_expand/closures.cpp b/src/hir_expand/closures.cpp
index 3b0fb6a4..8a90c037 100644
--- a/src/hir_expand/closures.cpp
+++ b/src/hir_expand/closures.cpp
@@ -1121,16 +1121,19 @@ namespace {
void visit_enum(::HIR::ItemPath p, ::HIR::Enum& item) override {
//auto _ = this->m_ms.set_item_generics(item.m_params);
- //auto enum_type = ::HIR::TypeRef(::HIR::CoreType::Isize);
- for(auto& var : item.m_variants)
+ /*
+ if(const auto* e = item.m_data.opt_Value())
{
- TU_IFLET(::HIR::Enum::Variant, var.second, Value, e,
- //DEBUG("Enum value " << p << " - " << var.first);
- //::std::vector< ::HIR::TypeRef> tmp;
- //ExprVisitor_Extract ev(m_resolve, tmp, m_new_trait_impls);
- //ev.visit_root(*e);
- )
+ auto enum_type = ::HIR::TypeRef(::HIR::CoreType::Isize);
+ for(auto& var : e->variants)
+ {
+ DEBUG("Enum value " << p << " - " << var.name);
+ ::std::vector< ::HIR::TypeRef> tmp;
+ ExprVisitor_Extract ev(m_resolve, tmp, m_new_trait_impls);
+ ev.visit_root(var.expr);
+ }
}
+ */
}
void visit_trait(::HIR::ItemPath p, ::HIR::Trait& item) override
diff --git a/src/hir_expand/const_eval_full.cpp b/src/hir_expand/const_eval_full.cpp
index 619bc9a2..749f043a 100644
--- a/src/hir_expand/const_eval_full.cpp
+++ b/src/hir_expand/const_eval_full.cpp
@@ -66,11 +66,7 @@ namespace {
return ::HIR::Literal( mv$(vals) );
),
(Variant,
- ::std::vector< ::HIR::Literal> vals;
- for(const auto& val : e.vals) {
- vals.push_back( clone_literal(val) );
- }
- return ::HIR::Literal::make_Variant({ e.idx, mv$(vals) });
+ return ::HIR::Literal::make_Variant({ e.idx, box$(clone_literal(*e.val)) });
),
(Integer,
return ::HIR::Literal(e);
@@ -102,9 +98,7 @@ namespace {
}
),
(Variant,
- for(auto& val : e.vals) {
- monomorph_literal_inplace(sp, val, ms);
- }
+ monomorph_literal_inplace(sp, *e.val, ms);
),
(Integer,
),
@@ -722,17 +716,15 @@ namespace {
val = ::HIR::Literal::make_List( mv$(vals) );
),
(Variant,
- TODO(sp, "MIR _Variant");
+ auto ival = read_param(e.val);
+ val = ::HIR::Literal::make_Variant({ e.index, box$(ival) });
),
(Struct,
::std::vector< ::HIR::Literal> vals;
vals.reserve( e.vals.size() );
for(const auto& v : e.vals)
vals.push_back( read_param(v) );
- if( e.variant_idx == ~0u )
- val = ::HIR::Literal::make_List( mv$(vals) );
- else
- val = ::HIR::Literal::make_Variant({ e.variant_idx, mv$(vals) });
+ val = ::HIR::Literal::make_List( mv$(vals) );
)
)
@@ -932,13 +924,19 @@ namespace {
}
}
void visit_enum(::HIR::ItemPath p, ::HIR::Enum& item) override {
- for(auto& var : item.m_variants)
+ if(auto* e = item.m_data.opt_Value())
{
- TU_IFLET(::HIR::Enum::Variant, var.second, Value, e,
- auto nvs = NewvalState { m_new_values, *m_mod_path, FMT(p.get_name() << "$" << var.first << "$") };
- e.val = evaluate_constant(e.expr->span(), m_resolve, mv$(nvs), FMT_CB(ss, ss << p;), e.expr, {}, {});
- DEBUG("enum variant: " << p << "::" << var.first << " = " << e.val);
- )
+ for(auto& var : e->variants)
+ {
+ if( var.expr )
+ {
+ auto nvs = NewvalState { m_new_values, *m_mod_path, FMT(p.get_name() << "$" << var.name << "$") };
+ auto val = evaluate_constant(var.expr->span(), m_resolve, mv$(nvs), FMT_CB(ss, ss << p;), var.expr, {}, {});
+ DEBUG("Enum value " << p << " - " << var.name << " = " << val);
+ // TODO: Save this value? Or just do the above to
+ // validate?
+ }
+ }
}
::HIR::Visitor::visit_enum(p, item);
}
diff --git a/src/hir_expand/reborrow.cpp b/src/hir_expand/reborrow.cpp
index d1b08f54..d276f57d 100644
--- a/src/hir_expand/reborrow.cpp
+++ b/src/hir_expand/reborrow.cpp
@@ -209,14 +209,18 @@ namespace {
}
}
void visit_enum(::HIR::ItemPath p, ::HIR::Enum& item) override {
- for(auto& var : item.m_variants)
+ if(auto* e = item.m_data.opt_Value())
{
- TU_IFLET(::HIR::Enum::Variant, var.second, Value, e,
- DEBUG("Enum value " << p << " - " << var.first);
+ for(auto& var : e->variants)
+ {
+ DEBUG("Enum value " << p << " - " << var.name);
- ExprVisitor_Mutate ev(m_crate);
- ev.visit_node_ptr(e.expr);
- )
+ if( var.expr )
+ {
+ ExprVisitor_Mutate ev(m_crate);
+ ev.visit_node_ptr(var.expr);
+ }
+ }
}
}
};
diff --git a/src/hir_expand/ufcs_everything.cpp b/src/hir_expand/ufcs_everything.cpp
index adae855c..629dd284 100644
--- a/src/hir_expand/ufcs_everything.cpp
+++ b/src/hir_expand/ufcs_everything.cpp
@@ -795,14 +795,18 @@ namespace {
}
}
void visit_enum(::HIR::ItemPath p, ::HIR::Enum& item) override {
- for(auto& var : item.m_variants)
+ if(auto* e = item.m_data.opt_Value())
{
- TU_IFLET(::HIR::Enum::Variant, var.second, Value, e,
- DEBUG("Enum value " << p << " - " << var.first);
+ for(auto& var : e->variants)
+ {
+ DEBUG("Enum value " << p << " - " << var.name);
- ExprVisitor_Mutate ev(m_crate);
- ev.visit_node_ptr(e.expr);
- )
+ if( var.expr )
+ {
+ ExprVisitor_Mutate ev(m_crate);
+ ev.visit_node_ptr(var.expr);
+ }
+ }
}
}
};
diff --git a/src/hir_typeck/expr_check.cpp b/src/hir_typeck/expr_check.cpp
index d9cbc957..febe8190 100644
--- a/src/hir_typeck/expr_check.cpp
+++ b/src/hir_typeck/expr_check.cpp
@@ -426,10 +426,11 @@ namespace {
(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());
- ASSERT_BUG(sp, it->second.is_Tuple(), "Pointed variant of TupleVariant (" << node.m_path << ") isn't a Tuple");
- fields_ptr = &it->second.as_Tuple();
+ size_t idx = enm.find_variant(var_name);
+ const auto& var_ty = enm.m_data.as_Data()[idx].type;
+ const auto& str = *var_ty.m_data.as_Path().binding.as_Struct();
+ ASSERT_BUG(sp, str.m_data.is_Tuple(), "Pointed variant of TupleVariant (" << node.m_path << ") isn't a Tuple");
+ fields_ptr = &str.m_data.as_Tuple();
),
(Union,
BUG(sp, "Union in TupleVariant");
@@ -480,9 +481,14 @@ namespace {
(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());
- fields_ptr = &it->second.as_Struct();
+ auto idx = enm.find_variant(var_name);
+ ASSERT_BUG(sp, idx != SIZE_MAX, "");
+ ASSERT_BUG(sp, enm.m_data.is_Data(), "");
+ const auto& var = enm.m_data.as_Data()[idx];
+
+ const auto& str = *var.type.m_data.as_Path().binding.as_Struct();
+ ASSERT_BUG(sp, var.is_struct, "Struct literal for enum on non-struct variant");
+ fields_ptr = &str.m_data.as_Named();
),
(Union,
TODO(sp, "Union in StructLiteral");
@@ -566,9 +572,12 @@ namespace {
(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());
- assert( it->second.is_Unit() || it->second.is_Value() );
+ if(const auto* e = enm.m_data.opt_Data())
+ {
+ auto idx = enm.find_variant(var_name);
+ ASSERT_BUG(sp, idx != SIZE_MAX, "");
+ ASSERT_BUG(sp, (*e)[idx].type == ::HIR::TypeRef::new_unit(), "");
+ }
),
(Union,
BUG(sp, "Union with _UnitVariant");
@@ -1133,18 +1142,22 @@ namespace {
}
void visit_enum(::HIR::ItemPath p, ::HIR::Enum& item) override {
//auto _ = this->m_ms.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,
- DEBUG("Enum value " << p << " - " << var.first);
+ // TODO: Use a different type depding on repr()
+ auto enum_type = ::HIR::TypeRef(::HIR::CoreType::Isize);
+ for(auto& var : e->variants)
+ {
+ DEBUG("Enum value " << p << " - " << var.name);
- t_args tmp;
- ExprVisitor_Validate ev(m_resolve, tmp, enum_type);
- ev.visit_root(e.expr);
- )
+ if( var.expr )
+ {
+ t_args tmp;
+ ExprVisitor_Validate ev(m_resolve, tmp, enum_type);
+ ev.visit_root(var.expr);
+ }
+ }
}
}
diff --git a/src/hir_typeck/expr_cs.cpp b/src/hir_typeck/expr_cs.cpp
index c6f060f5..47b83356 100644
--- a/src/hir_typeck/expr_cs.cpp
+++ b/src/hir_typeck/expr_cs.cpp
@@ -1088,10 +1088,11 @@ namespace {
(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());
- ASSERT_BUG(sp, it->second.is_Tuple(), "Pointed variant of TupleVariant (" << node.m_path << ") isn't a Tuple");
- fields_ptr = &it->second.as_Tuple();
+ size_t idx = enm.find_variant(var_name);
+ const auto& var_ty = enm.m_data.as_Data()[idx].type;
+ const auto& str = *var_ty.m_data.as_Path().binding.as_Struct();
+ ASSERT_BUG(sp, str.m_data.is_Tuple(), "Pointed variant of TupleVariant (" << node.m_path << ") isn't a Tuple");
+ fields_ptr = &str.m_data.as_Tuple();
),
(Struct,
ASSERT_BUG(sp, e->m_data.is_Tuple(), "Pointed struct in TupleVariant (" << node.m_path << ") isn't a Tuple");
@@ -1146,6 +1147,7 @@ namespace {
}
void visit(::HIR::ExprNode_StructLiteral& node) override
{
+ const auto& sp = node.span();
TRACE_FUNCTION_F(&node << " " << node.m_path << "{...} [" << (node.m_is_struct ? "struct" : "enum") << "]");
this->add_ivars_generic_path(node.span(), node.m_path);
for( auto& val : node.m_values ) {
@@ -1170,15 +1172,22 @@ namespace {
(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());
- if( it->second.is_Unit() || it->second.is_Value() || it->second.is_Tuple() ) {
+ auto idx = enm.find_variant(var_name);
+ ASSERT_BUG(sp, idx != SIZE_MAX, "");
+ ASSERT_BUG(sp, enm.m_data.is_Data(), "");
+ const auto& var = enm.m_data.as_Data()[idx];
+ if( var.type == ::HIR::TypeRef::new_unit() ) {
ASSERT_BUG(node.span(), node.m_values.size() == 0, "Values provided for unit-like variant");
ASSERT_BUG(node.span(), ! node.m_base_value, "Values provided for unit-like variant");
return ;
}
- ASSERT_BUG(node.span(), it->second.is_Struct(), "_StructLiteral for non-struct variant - " << node.m_path);
- fields_ptr = &it->second.as_Struct();
+ const auto& str = *var.type.m_data.as_Path().binding.as_Struct();
+ /*
+ if( it->second.is_Unit() || it->second.is_Value() || it->second.is_Tuple() ) {
+ }
+ */
+ ASSERT_BUG(sp, var.is_struct, "Struct literal for enum on non-struct variant");
+ fields_ptr = &str.m_data.as_Named();
generics = &enm.m_params;
),
(Union,
@@ -1612,8 +1621,12 @@ namespace {
enum_path.m_components.pop_back();
const auto& enm = this->context.m_crate.get_enum_by_path(sp, enum_path);
fix_param_count(sp, this->context, ::HIR::TypeRef(), false, e, enm.m_params, e.m_params);
- const auto& var = *::std::find_if(enm.m_variants.begin(), enm.m_variants.end(), [&](const auto&x){ return x.first == var_name; });
- const auto& var_data = var.second.as_Tuple();
+ size_t idx = enm.find_variant(var_name);
+ ASSERT_BUG(sp, idx != SIZE_MAX, "Missing variant - " << e.m_path);
+ ASSERT_BUG(sp, enm.m_data.is_Data(), "Enum " << enum_path << " isn't a data-holding enum");
+ const auto& var_ty = enm.m_data.as_Data()[idx].type;
+ const auto& str = *var_ty.m_data.as_Path().binding.as_Struct();
+ const auto& var_data = str.m_data.as_Tuple();
::HIR::FunctionType ft {
false,
@@ -3879,8 +3892,11 @@ void Context::add_binding(const Span& sp, ::HIR::Pattern& pat, const ::HIR::Type
assert(e.binding_ptr);
const auto& enm = *e.binding_ptr;
- const auto& var = enm.m_variants[e.binding_idx].second;
- assert(var.is_Value() || var.is_Unit());
+ if( enm.m_data.is_Data() )
+ {
+ //const auto& var = enm.m_data.as_Data()[e.binding_idx];
+ //assert(var.is_Value() || var.is_Unit());
+ }
),
(EnumTuple,
this->add_ivars_params( e.path.m_params );
@@ -3892,9 +3908,8 @@ void Context::add_binding(const Span& sp, ::HIR::Pattern& pat, const ::HIR::Type
}
assert(e.binding_ptr);
const auto& enm = *e.binding_ptr;
- const auto& var = enm.m_variants[e.binding_idx].second;
- assert(var.is_Tuple());
- const auto& tup_var = var.as_Tuple();
+ const auto& str = *enm.m_data.as_Data()[e.binding_idx].type.m_data.as_Path().binding.as_Struct();
+ const auto& tup_var = str.m_data.as_Tuple();
const auto& params = e.path.m_params;
@@ -3927,9 +3942,8 @@ void Context::add_binding(const Span& sp, ::HIR::Pattern& pat, const ::HIR::Type
assert(e.binding_ptr);
const auto& enm = *e.binding_ptr;
- const auto& var = enm.m_variants[e.binding_idx].second;
- assert(var.is_Struct());
- const auto& tup_var = var.as_Struct();
+ const auto& str = *enm.m_data.as_Data()[e.binding_idx].type.m_data.as_Path().binding.as_Struct();
+ const auto& tup_var = str.m_data.as_Named();
const auto& params = e.path.m_params;
for( auto& field_pat : e.sub_patterns )
diff --git a/src/hir_typeck/expr_visit.cpp b/src/hir_typeck/expr_visit.cpp
index 95e0c29c..b82e8f23 100644
--- a/src/hir_typeck/expr_visit.cpp
+++ b/src/hir_typeck/expr_visit.cpp
@@ -125,17 +125,20 @@ namespace {
void visit_enum(::HIR::ItemPath p, ::HIR::Enum& item) override {
auto _ = this->m_ms.set_item_generics(item.m_params);
- // TODO: Use a different type depding on repr()
- auto enum_type = ::HIR::TypeRef(::HIR::CoreType::Isize);
-
- // TODO: Check types too?
- for(auto& var : item.m_variants)
+ if( auto* e = item.m_data.opt_Value() )
{
- TU_IFLET(::HIR::Enum::Variant, var.second, Value, e,
- DEBUG("Enum value " << p << " - " << var.first);
- t_args tmp;
- Typecheck_Code(m_ms, tmp, enum_type, e.expr);
- )
+ // TODO: Use a different type depding on repr()
+ auto enum_type = ::HIR::TypeRef(::HIR::CoreType::Isize);
+
+ for(auto& var : e->variants)
+ {
+ DEBUG("Enum value " << p << " - " << var.name);
+ if( var.expr )
+ {
+ t_args tmp;
+ Typecheck_Code(m_ms, tmp, enum_type, var.expr);
+ }
+ }
}
}
};
diff --git a/src/hir_typeck/helpers.cpp b/src/hir_typeck/helpers.cpp
index d340514b..9f72483b 100644
--- a/src/hir_typeck/helpers.cpp
+++ b/src/hir_typeck/helpers.cpp
@@ -2599,37 +2599,16 @@ bool TraitResolution::find_trait_impls_crate(const Span& sp,
)
),
(Enum,
- const auto& enm = *tpb;
-
- for(const auto& var : enm.m_variants)
+ if( const auto* e = tpb->m_data.opt_Data() )
{
- TU_MATCH(::HIR::Enum::Variant, (var.second), (ve),
- (Unit,
- ),
- (Value,
- ),
- (Tuple,
- for(const auto& fld : ve)
- {
- const auto& fld_ty_mono = monomorph_get(fld.ent);
- DEBUG("Enum '" << var.first << "'::Tuple " << fld_ty_mono);
- res &= type_impls_trait(fld_ty_mono);
- if( res == ::HIR::Compare::Unequal )
- return ::HIR::Compare::Unequal;
- }
- ),
- (Struct,
- for(const auto& fld : ve)
- {
- const auto& fld_ty_mono = monomorph_get(fld.second.ent);
- DEBUG("Enum '" << var.first << "'::Struct '" << fld.first << "' " << fld_ty_mono);
-
- res &= type_impls_trait(fld_ty_mono);
- if( res == ::HIR::Compare::Unequal )
- return ::HIR::Compare::Unequal;
- }
- )
- )
+ for(const auto& var : *e)
+ {
+ const auto& fld_ty_mono = monomorph_get(var.type);
+ DEBUG("Enum '" << var.name << "'" << fld_ty_mono);
+ res &= type_impls_trait(fld_ty_mono);
+ if( res == ::HIR::Compare::Unequal )
+ return ::HIR::Compare::Unequal;
+ }
}
),
(Union,
diff --git a/src/hir_typeck/static.cpp b/src/hir_typeck/static.cpp
index 8d6ff052..3629c6e4 100644
--- a/src/hir_typeck/static.cpp
+++ b/src/hir_typeck/static.cpp
@@ -785,37 +785,16 @@ bool StaticTraitResolve::find_impl__check_crate(
)
),
(Enum,
- const auto& enm = *tpb;
-
- for(const auto& var : enm.m_variants)
+ if( const auto* e = tpb->m_data.opt_Data() )
{
- TU_MATCH(::HIR::Enum::Variant, (var.second), (ve),
- (Unit,
- ),
- (Value,
- ),
- (Tuple,
- for(const auto& fld : ve)
- {
- const auto& fld_ty_mono = monomorph_get(fld.ent);
- DEBUG("Enum '" << var.first << "'::Tuple " << fld_ty_mono);
- res &= type_impls_trait(fld_ty_mono);
- if( res == ::HIR::Compare::Unequal )
- return ::HIR::Compare::Unequal;
- }
- ),
- (Struct,
- for(const auto& fld : ve)
- {
- const auto& fld_ty_mono = monomorph_get(fld.second.ent);
- DEBUG("Enum '" << var.first << "'::Struct '" << fld.first << "' " << fld_ty_mono);
-
- res &= type_impls_trait(fld_ty_mono);
- if( res == ::HIR::Compare::Unequal )
- return ::HIR::Compare::Unequal;
- }
- )
- )
+ for(const auto& var : *e )
+ {
+ const auto& fld_ty_mono = monomorph_get(var.type);
+ DEBUG("Enum '" << var.name << "' " << fld_ty_mono);
+ res &= type_impls_trait(fld_ty_mono);
+ if( res == ::HIR::Compare::Unequal )
+ return ::HIR::Compare::Unequal;
+ }
}
),
(Union,
@@ -1804,28 +1783,13 @@ bool StaticTraitResolve::type_needs_drop_glue(const Span& sp, const ::HIR::TypeR
return false;
),
(Enum,
- for(const auto& e : pbe->m_variants)
+ if(const auto* e = pbe->m_data.opt_Data())
{
- TU_MATCHA( (e.second), (ve),
- (Unit,
- ),
- (Value,
- ),
- (Tuple,
- for(const auto& e : ve)
- {
- if( type_needs_drop_glue(sp, monomorph(e.ent)) )
- return true;
- }
- ),
- (Struct,
- for(const auto& e : ve)
- {
- if( type_needs_drop_glue(sp, monomorph(e.second.ent)) )
- return true;
- }
- )
- )
+ for(const auto& var : *e)
+ {
+ if( type_needs_drop_glue(sp, monomorph(var.type)) )
+ return true;
+ }
}
return false;
),
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);
+ }
+ }
}
}
diff --git a/src/resolve/absolute.cpp b/src/resolve/absolute.cpp
index e9cf274e..18412c27 100644
--- a/src/resolve/absolute.cpp
+++ b/src/resolve/absolute.cpp
@@ -702,10 +702,9 @@ namespace {
ERROR(sp, E0000, "Enum as path component in unexpected location - " << p);
}
const auto& varname = p.m_components.back();
- auto it = ::std::find_if( e.m_variants.begin(), e.m_variants.end(), [&](const auto&x){return x.first == varname;} );
- ASSERT_BUG(sp, it != e.m_variants.end(), "Extern crate import path points to non-present variant - " << p);
- unsigned int var_idx = it - e.m_variants.begin();
- auto pb = ::AST::PathBinding::make_EnumVar({nullptr, var_idx, &e});
+ auto var_idx = e.find_variant(varname);
+ ASSERT_BUG(sp, var_idx != SIZE_MAX, "Extern crate import path points to non-present variant - " << p);
+ auto pb = ::AST::PathBinding::make_EnumVar({nullptr, static_cast<unsigned>(var_idx), &e});
// Construct output path (with same set of parameters)
AST::Path rv( p.m_crate_name, {} );
@@ -901,22 +900,20 @@ namespace {
(Enum,
const auto& last_node = path_abs.nodes.back();
// If this refers to an enum variant, return the full path
- for( const auto& var : e.m_variants )
+ auto idx = e.find_variant(last_node.name());
+ if( idx != SIZE_MAX )
{
- if( var.first == last_node.name() ) {
-
- if( i != path_abs.nodes.size() - 2 ) {
- ERROR(sp, E0000, "Unexpected enum in path " << path);
- }
- // NOTE: Type parameters for enums go after the _variant_
- if( ! n.args().is_empty() ) {
- ERROR(sp, E0000, "Type parameters were not expected here (enum params go on the variant)");
- }
-
- path.bind( ::AST::PathBinding::make_EnumVar({nullptr, static_cast<unsigned int>(&var - &*e.m_variants.begin()), &e}) );
- path = split_into_crate(sp, mv$(path), start, crate.m_name);
- return;
+ if( i != path_abs.nodes.size() - 2 ) {
+ ERROR(sp, E0000, "Unexpected enum in path " << path);
+ }
+ // NOTE: Type parameters for enums go after the _variant_
+ if( ! n.args().is_empty() ) {
+ ERROR(sp, E0000, "Type parameters were not expected here (enum params go on the variant)");
}
+
+ path.bind( ::AST::PathBinding::make_EnumVar({nullptr, static_cast<unsigned int>(idx), &e}) );
+ path = split_into_crate(sp, mv$(path), start, crate.m_name);
+ return;
}
path = split_into_crate(sp, mv$(path), start, crate.m_name);
path = split_into_ufcs_ty(sp, mv$(path), i-start);
diff --git a/src/resolve/index.cpp b/src/resolve/index.cpp
index 2f4ece59..458aed5e 100644
--- a/src/resolve/index.cpp
+++ b/src/resolve/index.cpp
@@ -223,8 +223,8 @@ void Resolve_Index_Module_Base(const AST::Crate& crate, AST::Module& mod)
is_struct = e.enum_->variants().at(e.idx).m_data.is_Struct();
}
else {
- ASSERT_BUG(sp, e.idx < e.hir->m_variants.size(), "Variant out of range for " << i_data.path);
- is_struct = e.hir->m_variants.at(e.idx).second.is_Struct();
+ //ASSERT_BUG(sp, e.idx < e.hir->m_variants.size(), "Variant out of range for " << i_data.path);
+ is_struct = TU_TEST1(e.hir->m_data, Data, .at(e.idx).is_struct);
}
if( is_struct )
_add_item_type(sp, mod, i.name, i.is_pub, i_data.path, !allow_collide);
@@ -457,19 +457,36 @@ void Resolve_Index_Module_Wildcard__use_stmt(AST::Crate& crate, AST::Module& dst
{
DEBUG("Glob enum " << i_data.path << " (HIR)");
unsigned int idx = 0;
- for( const auto& ev : e.hir->m_variants )
+ if( e.hir->m_data.is_Value() )
{
- ::AST::Path p = i_data.path + ev.first;
- p.bind( ::AST::PathBinding::make_EnumVar({nullptr, idx, e.hir}) );
+ const auto* de = e.hir->m_data.opt_Value();
+ for(const auto& ev : de->variants)
+ {
+ ::AST::Path p = i_data.path + ev.name;
+ p.bind( ::AST::PathBinding::make_EnumVar({nullptr, idx, e.hir}) );
- if( ev.second.is_Struct() ) {
- _add_item_type ( sp, dst_mod, ev.first, is_pub, mv$(p), false );
- }
- else {
- _add_item_value( sp, dst_mod, ev.first, is_pub, mv$(p), false );
+ _add_item_value( sp, dst_mod, ev.name, is_pub, mv$(p), false );
+
+ idx += 1;
}
+ }
+ else
+ {
+ const auto* de = &e.hir->m_data.as_Data();
+ for(const auto& ev : *de)
+ {
+ ::AST::Path p = i_data.path + ev.name;
+ p.bind( ::AST::PathBinding::make_EnumVar({nullptr, idx, e.hir}) );
- idx += 1;
+ if( ev.is_struct ) {
+ _add_item_type ( sp, dst_mod, ev.name, is_pub, mv$(p), false );
+ }
+ else {
+ _add_item_value( sp, dst_mod, ev.name, is_pub, mv$(p), false );
+ }
+
+ idx += 1;
+ }
}
}
)
diff --git a/src/resolve/use.cpp b/src/resolve/use.cpp
index 01a5d22c..e36e40a0 100644
--- a/src/resolve/use.cpp
+++ b/src/resolve/use.cpp
@@ -463,13 +463,10 @@ void Resolve_Use_Mod(const ::AST::Crate& crate, ::AST::Module& mod, ::AST::Path
}
else {
const auto& enm = *e.hir;
- unsigned int i = 0;
- for(const auto& var : enm.m_variants)
+ auto idx = enm.find_variant(des_item_name);
+ if( idx != SIZE_MAX )
{
- if( var.first == des_item_name ) {
- return ::AST::PathBinding::make_EnumVar({ nullptr, i, &enm });
- }
- i ++;
+ return ::AST::PathBinding::make_EnumVar({ nullptr, static_cast<unsigned>(idx), &enm });
}
}
)
@@ -564,11 +561,11 @@ namespace {
}
const auto& name = nodes[i].name();
- auto it2 = ::std::find_if( enm.m_variants.begin(), enm.m_variants.end(), [&](const auto& x){ return x.first == name; } );
- if( it2 == enm.m_variants.end() ) {
+ auto idx = enm.find_variant(name);
+ if( idx == SIZE_MAX ) {
ERROR(span, E0000, "Unable to find variant " << path);
}
- return ::AST::PathBinding::make_EnumVar({ nullptr, static_cast<unsigned int>(it2 - enm.m_variants.begin()), &enm });
+ return ::AST::PathBinding::make_EnumVar({ nullptr, static_cast<unsigned int>(idx), &enm });
}
else {
hmod = reinterpret_cast<const ::HIR::Module*>(ptr);
@@ -584,11 +581,11 @@ namespace {
}
const auto& name = nodes[i].name();
- auto it2 = ::std::find_if( e.m_variants.begin(), e.m_variants.end(), [&](const auto& x){ return x.first == name; } );
- if( it2 == e.m_variants.end() ) {
+ auto idx = e.find_variant(name);
+ if(idx == SIZE_MAX) {
ERROR(span, E0000, "Unable to find variant " << path);
}
- return ::AST::PathBinding::make_EnumVar({ nullptr, static_cast<unsigned int>(it2 - e.m_variants.begin()), &e });
+ return ::AST::PathBinding::make_EnumVar({ nullptr, static_cast<unsigned int>(idx), &e });
)
)
}
@@ -606,7 +603,7 @@ namespace {
auto p = e.path;
p.m_components.pop_back();
const auto& enm = ec.m_hir->get_typeitem_by_path(span, p, true).as_Enum();
- assert(e.idx < enm.m_variants.size());
+ assert(e.idx < enm.num_variants());
return ::AST::PathBinding::make_EnumVar({ nullptr, e.idx, &enm });
}
if( e.path.m_components.empty() )
@@ -653,7 +650,7 @@ namespace {
auto p = e.path;
p.m_components.pop_back();
const auto& enm = ec.m_hir->get_typeitem_by_path(span, p, true).as_Enum();
- assert(e.idx < enm.m_variants.size());
+ assert(e.idx < enm.num_variants());
return ::AST::PathBinding::make_EnumVar({ nullptr, e.idx, &enm });
}
item_ptr = &ec.m_hir->get_valitem_by_path(span, e.path, true); // ignore_crate_name=true
diff --git a/src/trans/codegen.cpp b/src/trans/codegen.cpp
index e7cea40d..e95ff08e 100644
--- a/src/trans/codegen.cpp
+++ b/src/trans/codegen.cpp
@@ -65,8 +65,7 @@ void Trans_Codegen(const ::std::string& outfile, const TransOptions& opt, const
const auto& nse = crate.get_typeitem_by_path(sp, path.m_path, false, true);
if(const auto* e = nse.opt_Enum())
{
- auto it = ::std::find_if(e->m_variants.begin(), e->m_variants.end(), [&](const auto& x){ return x.first == path.m_path.m_components.back(); });
- auto var_idx = it - e->m_variants.begin();
+ auto var_idx = e->find_variant(path.m_path.m_components.back());
codegen->emit_constructor_enum(sp, path, *e, var_idx);
continue ;
}
diff --git a/src/trans/codegen_c.cpp b/src/trans/codegen_c.cpp
index b751a933..f338f502 100644
--- a/src/trans/codegen_c.cpp
+++ b/src/trans/codegen_c.cpp
@@ -982,6 +982,49 @@ namespace {
(
return false;
),
+ (Path,
+ if( te.binding.is_Struct() )
+ {
+ const auto& str = *te.binding.as_Struct();
+ const auto& p = te.path.m_data.as_Generic();
+ ::HIR::TypeRef tmp;
+ auto monomorph = [&](const auto& ty)->const auto& {
+ if( monomorphise_type_needed(ty) ) {
+ tmp = monomorphise_type(sp, str.m_params, p.m_params, ty);
+ m_resolve.expand_associated_types(sp, tmp);
+ return tmp;
+ }
+ else {
+ return ty;
+ }
+ };
+ TU_MATCHA( (str.m_data), (se),
+ (Unit,
+ ),
+ (Tuple,
+ for(size_t i = 0; i < se.size(); i ++)
+ {
+ if( get_nonzero_path(sp, monomorph(se[i].ent), out) )
+ {
+ out.push_back(i);
+ return true;
+ }
+ }
+ ),
+ (Named,
+ for(size_t i = 0; i < se.size(); i ++)
+ {
+ if( get_nonzero_path(sp, monomorph(se[i].second.ent), out) )
+ {
+ out.push_back(i);
+ return true;
+ }
+ }
+ )
+ )
+ }
+ return false;
+ ),
(Borrow,
if( metadata_type(*te.inner) != MetadataType::None )
{
@@ -1031,21 +1074,22 @@ namespace {
::std::vector<unsigned> nonzero_path;
{
// Detect Option (and similar enums)
- if( item.m_variants.size() == 2 && item.m_variants[0].second.is_Unit() && item.m_variants[1].second.is_Tuple() )
+ // - Matches two-variant enums where the first variant is unit-like, and the second is not
+ if( item.m_data.is_Data() && item.m_data.as_Data().size() == 2
+ && item.m_data.as_Data()[0].type == ::HIR::TypeRef::new_unit()
+ && item.m_data.as_Data()[1].type != ::HIR::TypeRef::new_unit()
+ )
{
- const auto& data_ents = item.m_variants[1].second.as_Tuple();
- if( data_ents.size() == 1 )
+ const auto& data_type = monomorph(item.m_data.as_Data()[1].type);
+ if( get_nonzero_path(sp, data_type, nonzero_path) )
{
- const auto& data_type = monomorph(data_ents[0].ent);
- if( get_nonzero_path(sp, data_type, nonzero_path) )
- {
- nonzero_path.push_back(0);
- ::std::reverse( nonzero_path.begin(), nonzero_path.end() );
- }
- else
- {
- assert(nonzero_path.size() == 0);
- }
+ ::std::reverse( nonzero_path.begin(), nonzero_path.end() );
+ DEBUG("Correct format for NonZero to apply, and field found at " << nonzero_path);
+ }
+ else
+ {
+ DEBUG("Correct format for NonZero to apply, but no field");
+ assert(nonzero_path.size() == 0);
}
}
}
@@ -1053,21 +1097,20 @@ namespace {
m_of << "// enum " << p << "\n";
if( nonzero_path.size() > 0 )
{
- MIR_ASSERT(*m_mir_res, nonzero_path[0] == 0, "");
- MIR_ASSERT(*m_mir_res, item.m_variants.size() == 2, "");
- MIR_ASSERT(*m_mir_res, item.m_variants[0].second.is_Unit(), "");
- const auto& data_var = item.m_variants[1];
- MIR_ASSERT(*m_mir_res, data_var.second.is_Tuple(), "");
- MIR_ASSERT(*m_mir_res, data_var.second.as_Tuple().size() == 1, "");
- const auto& data_type = monomorph(data_var.second.as_Tuple()[0].ent);
+ //MIR_ASSERT(*m_mir_res, item.num_variants() == 2, "");
+ //MIR_ASSERT(*m_mir_res, item.m_variants[0].second.is_Unit(), "");
+ //const auto& data_var = item.m_variants[1];
+ //MIR_ASSERT(*m_mir_res, data_var.second.is_Tuple(), "");
+ //MIR_ASSERT(*m_mir_res, data_var.second.as_Tuple().size() == 1, "");
+ const auto& data_type = monomorph(item.m_data.as_Data()[1].type);
m_of << "struct e_" << Trans_Mangle(p) << " {\n";
- m_of << "\t"; emit_ctype(data_type, FMT_CB(s, s << "_0";)); m_of << ";\n";
+ m_of << "\t"; emit_ctype(data_type, FMT_CB(s, s << "_1";)); m_of << ";\n";
m_of << "};\n";
}
- else if( item.m_repr != ::HIR::Enum::Repr::Rust || ::std::all_of(item.m_variants.begin(), item.m_variants.end(), [](const auto& x){return x.second.is_Unit() || x.second.is_Value();}) )
+ else if( item.m_data.is_Value() )
{
m_of << "struct e_" << Trans_Mangle(p) << " {\n";
- switch(item.m_repr)
+ switch(item.m_data.as_Value().repr)
{
case ::HIR::Enum::Repr::Rust:
case ::HIR::Enum::Repr::C:
@@ -1087,41 +1130,15 @@ namespace {
}
else
{
+ const auto& variants = item.m_data.as_Data();
m_of << "struct e_" << Trans_Mangle(p) << " {\n";
m_of << "\tunsigned int TAG;\n";
m_of << "\tunion {\n";
- for(unsigned int i = 0; i < item.m_variants.size(); i ++)
+ for(unsigned int i = 0; i < variants.size(); i ++)
{
- TU_MATCHA( (item.m_variants[i].second), (e),
- (Unit,
- //m_of << "\t\tstruct {} var_" << i << ";\n";
- ),
- (Value,
- //m_of << "\t\tstruct {} var_" << i << ";\n";
- ),
- (Tuple,
- m_of << "\t\tstruct {\n";
- for(unsigned int i = 0; i < e.size(); i ++)
- {
- const auto& fld = e[i];
- m_of << "\t\t\t";
- emit_ctype( monomorph(fld.ent) );
- m_of << " _" << i << ";\n";
- }
- m_of << "\t\t} var_" << i << ";\n";
- ),
- (Struct,
- m_of << "\t\tstruct {\n";
- for(unsigned int i = 0; i < e.size(); i ++)
- {
- const auto& fld = e[i];
- m_of << "\t\t\t";
- emit_ctype( monomorph(fld.second.ent) );
- m_of << " _" << i << ";\n";
- }
- m_of << "\t\t} var_" << i << ";\n";
- )
- )
+ m_of << "\t\t";
+ emit_ctype( monomorph(variants[i].type) );
+ m_of << " var_" << i << ";\n";
}
m_of << "\t} DATA;\n";
m_of << "};\n";
@@ -1153,60 +1170,30 @@ namespace {
if( nonzero_path.size() > 0 )
{
- auto fld_lv = ::MIR::LValue::make_Field({ box$(self), 0 });
// TODO: Fat pointers?
- m_of << "\tif( ! (*rv)"; emit_nonzero_path(nonzero_path); m_of << " ) {\n";
- for(const auto& fld : item.m_variants[1].second.as_Tuple())
- {
- emit_destructor_call(fld_lv, monomorph(fld.ent), false, 2);
- fld_lv.as_Field().field_index ++;
- }
+ m_of << "\tif( (*rv)._1"; emit_nonzero_path(nonzero_path); m_of << " ) {\n";
+ emit_destructor_call( ::MIR::LValue::make_Field({ box$(self), 1 }), monomorph(item.m_data.as_Data()[1].type), false, 2 );
m_of << "\t}\n";
}
- else if( item.m_repr != ::HIR::Enum::Repr::Rust || ::std::all_of(item.m_variants.begin(), item.m_variants.end(), [](const auto& x){return x.second.is_Unit() || x.second.is_Value();}) )
- {
- // Glue does nothing (except call the destructor, if there is one)
- }
- else
+ else if( const auto* e = item.m_data.opt_Data() )
{
- auto fld_lv = ::MIR::LValue::make_Field({ box$(::MIR::LValue::make_Downcast({ box$(self), 0 })), 0 });
+ auto var_lv =::MIR::LValue::make_Downcast({ box$(self), 0 });
m_of << "\tswitch(rv->TAG) {\n";
- for(unsigned int var_idx = 0; var_idx < item.m_variants.size(); var_idx ++)
+ for(unsigned int var_idx = 0; var_idx < e->size(); var_idx ++)
{
- fld_lv.as_Field().val->as_Downcast().variant_index = var_idx;
- TU_MATCHA( (item.m_variants[var_idx].second), (e),
- (Unit,
- m_of << "\tcase " << var_idx << ": break;\n";
- ),
- (Value,
- m_of << "\tcase " << var_idx << ": break;\n";
- ),
- (Tuple,
- m_of << "\tcase " << var_idx << ":\n";
- for(unsigned int i = 0; i < e.size(); i ++)
- {
- fld_lv.as_Field().field_index = i;
- const auto& fld = e[i];
-
- emit_destructor_call(fld_lv, monomorph(fld.ent), false, 2);
- }
- m_of << "\tbreak;\n";
- ),
- (Struct,
- m_of << "\tcase " << var_idx << ":\n";
- for(unsigned int i = 0; i < e.size(); i ++)
- {
- fld_lv.as_Field().field_index = i;
- const auto& fld = e[i];
- emit_destructor_call(fld_lv, monomorph(fld.second.ent), false, 2);
- }
- m_of << "\tbreak;\n";
- )
- )
+ var_lv.as_Downcast().variant_index = var_idx;
+ m_of << "\tcase " << var_idx << ":\n";
+ emit_destructor_call(var_lv, monomorph( (*e)[var_idx].type ), false, 2);
+ m_of << "\tbreak;\n";
}
m_of << "\t}\n";
}
+ else
+ {
+ // Value enum
+ // Glue does nothing (except call the destructor, if there is one)
+ }
m_of << "}\n";
m_mir_res = nullptr;
@@ -1233,9 +1220,13 @@ namespace {
auto p = path.clone();
p.m_path.m_components.pop_back();
- const auto& var = item.m_variants[var_idx];
- ASSERT_BUG(sp, var.second.is_Tuple(), "");
- const auto& e = var.second.as_Tuple();
+
+ ASSERT_BUG(sp, item.m_data.is_Data(), "");
+ const auto& var = item.m_data.as_Data().at(var_idx);
+ ASSERT_BUG(sp, var.type.m_data.is_Path(), "");
+ const auto& str = *var.type.m_data.as_Path().binding.as_Struct();
+ ASSERT_BUG(sp, str.m_data.is_Tuple(), "");
+ const auto& e = str.m_data.as_Tuple();
m_of << "struct e_" << Trans_Mangle(p) << " " << Trans_Mangle(path) << "(";
@@ -1249,7 +1240,7 @@ namespace {
auto it = m_enum_repr_cache.find(p);
if( it != m_enum_repr_cache.end() )
{
- m_of << "\tstruct e_" << Trans_Mangle(p) << " rv = { ._0 = _0 };\n";
+ m_of << "\tstruct e_" << Trans_Mangle(p) << " rv = { _0 };\n";
}
else
{
@@ -1435,21 +1426,9 @@ namespace {
MIR_TODO(*m_mir_res, "Union literals");
),
(Enum,
- const auto& evar = pbe->m_variants.at(var);
- TU_MATCHA( (evar.second), (se),
- (Unit,
- MIR_BUG(*m_mir_res, "Unit enum var " << ty << " #" << var << " - fld " << idx);
- ),
- (Value,
- MIR_BUG(*m_mir_res, "Value enum var " << ty << " #" << var << " - fld " << idx);
- ),
- (Tuple,
- return monomorph_with(pp, se.at(idx).ent);
- ),
- (Struct,
- return monomorph_with(pp, se.at(idx).second.ent);
- )
- )
+ MIR_ASSERT(*m_mir_res, pbe->m_data.is_Data(), "");
+ const auto& evar = pbe->m_data.as_Data().at(var);
+ return monomorph_with(pp, evar.type);
)
)
throw "";
@@ -1489,36 +1468,20 @@ namespace {
m_of << "{0}";
}
else {
- m_of << "{";
- emit_literal(get_inner_type(e.idx, 0), e.vals[0], params);
- m_of << "}";
+ emit_literal(get_inner_type(e.idx, 0), *e.val, params);
}
}
else if( enm.is_value() )
{
- MIR_ASSERT(*m_mir_res, e.vals.empty(), "Value-only enum with fields");
+ MIR_ASSERT(*m_mir_res, TU_TEST1((*e.val), List, .empty()), "Value-only enum with fields");
m_of << "{" << enm.get_value(e.idx) << "}";
}
else
{
m_of << "{" << e.idx;
- if( e.vals.empty() )
- {
- if( m_options.disallow_empty_structs && !enm.m_variants.at(e.idx).second.is_Unit() )
- {
- m_of << ", { .var_" << e.idx << " = {0} }";
- }
- }
- else
- {
- m_of << ", { .var_" << e.idx << " = {";
- for(unsigned int i = 0; i < e.vals.size(); i ++) {
- if(i != 0) m_of << ",";
- m_of << " ";
- emit_literal(get_inner_type(e.idx, i), e.vals[i], params);
- }
- m_of << "} }";
- }
+ m_of << ", { .var_" << e.idx << " = ";
+ emit_literal(get_inner_type(e.idx, 0), *e.val, params);
+ m_of << " }";
m_of << "}";
}
),
@@ -2017,7 +1980,7 @@ namespace {
if( it != m_enum_repr_cache.end() )
{
MIR_ASSERT(mir_res, e.targets.size() == 2, "Non-zero optimised type a variant count that isn't 2");
- m_of << "\tif("; emit_lvalue(e.val); emit_nonzero_path(it->second); m_of << ")\n";
+ m_of << "\tif("; emit_lvalue(e.val); m_of << "._1"; emit_nonzero_path(it->second); m_of << ")\n";
m_of << "\t\tgoto bb" << e.targets[1] << ";\n";
m_of << "\telse\n";
m_of << "\t\tgoto bb" << e.targets[0] << ";\n";
@@ -2537,42 +2500,20 @@ namespace {
}
else if( const auto* enm_p = tyi.opt_Enum() )
{
- MIR_TODO(mir_res, "Construct enum with RValue::Variant");
- if( enm_p->is_value() )
- {
- emit_lvalue(e.dst); m_of << ".TAG = " << enm_p->get_value(ve.index) << "";
- }
- else
- {
- emit_lvalue(e.dst); m_of << ".TAG = " << ve.index << ";\n\t";
- emit_lvalue(e.dst); m_of << ".DATA";
- m_of << ".var_" << ve.index << " = "; emit_param(ve.val);
- }
- }
- else
- {
- BUG(mir_res.sp, "Unexpected type in Variant");
- }
- ),
- (Struct,
- bool is_val_enum = false;
- if(ve.variant_idx != ~0u)
- {
::HIR::TypeRef tmp;
const auto& ty = mir_res.get_lvalue_type(tmp, e.dst);
- const auto* enm_p = ty.m_data.as_Path().binding.as_Enum();
auto it = m_enum_repr_cache.find(ty.m_data.as_Path().path.m_data.as_Generic());
if( it != m_enum_repr_cache.end() )
{
- if( ve.variant_idx == 0 ) {
+ if( ve.index == 0 ) {
// TODO: Use nonzero_path
m_of << "memset(&"; emit_lvalue(e.dst); m_of << ", 0, sizeof("; emit_ctype(ty); m_of << "))";
}
- else if( ve.variant_idx == 1 ) {
+ else if( ve.index == 1 ) {
emit_lvalue(e.dst);
- m_of << "._0 = ";
- emit_param(ve.vals[0]);
+ m_of << "._1 = ";
+ emit_param(ve.val);
}
else {
}
@@ -2580,30 +2521,28 @@ namespace {
}
else if( enm_p->is_value() )
{
- is_val_enum = true;
- emit_lvalue(e.dst);
- m_of << ".TAG = " << enm_p->get_value(ve.variant_idx);
- assert(ve.vals.size() == 0);
+ emit_lvalue(e.dst); m_of << ".TAG = " << enm_p->get_value(ve.index) << "";
}
else
{
- is_val_enum = enm_p->m_variants.at(ve.variant_idx).second.is_Unit();
- emit_lvalue(e.dst);
- m_of << ".TAG = " << ve.variant_idx;
+ emit_lvalue(e.dst); m_of << ".TAG = " << ve.index << ";\n\t";
+ emit_lvalue(e.dst); m_of << ".DATA";
+ m_of << ".var_" << ve.index << " = "; emit_param(ve.val);
}
- if(ve.vals.size() > 0)
- m_of << ";\n" << indent;
}
+ else
+ {
+ BUG(mir_res.sp, "Unexpected type in Variant");
+ }
+ ),
+ (Struct,
+ bool is_val_enum = false;
if( ve.vals.empty() )
{
if( m_options.disallow_empty_structs && !is_val_enum)
{
- if(ve.variant_idx != ~0u)
- m_of << ";\n" << indent;
emit_lvalue(e.dst);
- if(ve.variant_idx != ~0u)
- m_of << ".DATA.var_" << ve.variant_idx;
m_of << "._d = 0";
}
}
@@ -2618,8 +2557,6 @@ namespace {
if( j != 0 ) m_of << ";\n" << indent;
emit_lvalue(e.dst);
- if(ve.variant_idx != ~0u)
- m_of << ".DATA.var_" << ve.variant_idx;
m_of << "._" << j << " = ";
emit_param(ve.vals[j]);
}
@@ -2804,7 +2741,7 @@ namespace {
{
//MIR_ASSERT(mir_res, e.targets.size() == 2, "NonZero optimised representation for an enum without two variants");
MIR_ASSERT(mir_res, n_arms == 2, "NonZero optimised switch without two arms");
- m_of << indent << "if("; emit_lvalue(val); emit_nonzero_path(it->second); m_of << ")\n";
+ m_of << indent << "if("; emit_lvalue(val); m_of << "._1"; emit_nonzero_path(it->second); m_of << ")\n";
m_of << indent;
cb(1);
m_of << "\n";
@@ -3523,7 +3460,7 @@ namespace {
auto it = m_enum_repr_cache.find( ty.m_data.as_Path().path.m_data.as_Generic() );
if( it != m_enum_repr_cache.end() )
{
- emit_param(e.args.at(0)); emit_nonzero_path(it->second); m_of << " != 0";
+ emit_param(e.args.at(0)); m_of << "->_1"; emit_nonzero_path(it->second); m_of << " != 0";
}
else
{
@@ -4073,21 +4010,9 @@ namespace {
MIR_TODO(*m_mir_res, "Union literals");
),
(Enum,
- const auto& evar = pbe->m_variants.at(var);
- TU_MATCHA( (evar.second), (se),
- (Unit,
- MIR_BUG(*m_mir_res, "Unit enum var " << ty << " #" << var << " - fld " << idx);
- ),
- (Value,
- MIR_BUG(*m_mir_res, "Value enum var " << ty << " #" << var << " - fld " << idx);
- ),
- (Tuple,
- return monomorph_with(pp, se.at(idx).ent);
- ),
- (Struct,
- return monomorph_with(pp, se.at(idx).second.ent);
- )
- )
+ MIR_ASSERT(*m_mir_res, pbe->m_data.is_Data(), "");
+ const auto& evar = pbe->m_data.as_Data().at(var);
+ return monomorph_with(pp, evar.type);
)
)
throw "";
@@ -4131,21 +4056,19 @@ namespace {
m_of << " = 0";
}
else {
- assign_from_literal([&](){ emit_dst(); m_of << "._0"; }, get_inner_type(e.idx, 0), e.vals[0]);
+ assign_from_literal([&](){ emit_dst(); }, get_inner_type(e.idx, 0), *e.val);
}
}
else if( enm.is_value() )
{
- MIR_ASSERT(*m_mir_res, e.vals.empty(), "Value-only enum with fields");
+ MIR_ASSERT(*m_mir_res, TU_TEST1((*e.val), List, .empty()), "Value-only enum with fields");
emit_dst(); m_of << ".TAG = " << enm.get_value(e.idx);
}
else
{
emit_dst(); m_of << ".TAG = " << e.idx;
- for(unsigned int i = 0; i < e.vals.size(); i ++) {
- m_of << ";\n\t";
- assign_from_literal([&](){ emit_dst(); m_of << ".DATA.var_" << e.idx << "._" << i; }, get_inner_type(e.idx, i), e.vals[i]);
- }
+ m_of << ";\n\t";
+ assign_from_literal([&](){ emit_dst(); m_of << ".DATA.var_" << e.idx; }, get_inner_type(e.idx, 0), *e.val);
}
),
(Integer,
@@ -4313,7 +4236,7 @@ namespace {
{
MIR_ASSERT(*m_mir_res, e.variant_index == 1, "");
// NOTE: Downcast returns a magic tuple
- //m_of << "._0";
+ m_of << "._1";
break ;
}
else
diff --git a/src/trans/enumerate.cpp b/src/trans/enumerate.cpp
index 283617f2..757b368d 100644
--- a/src/trans/enumerate.cpp
+++ b/src/trans/enumerate.cpp
@@ -424,22 +424,12 @@ namespace {
return x;
}
};
- for(const auto& variant : item.m_variants)
+ if( const auto* e = item.m_data.opt_Data() )
{
- TU_MATCHA( (variant.second), (e),
- (Unit,
- ),
- (Value,
- ),
- (Tuple,
- for(const auto& ty : e)
- visit_type( monomorph(ty.ent) );
- ),
- (Struct,
- for(const auto& fld : e)
- visit_type( monomorph(fld.second.ent) );
- )
- )
+ for(const auto& variant : *e)
+ {
+ visit_type( monomorph(variant.type) );
+ }
}
}
@@ -810,30 +800,16 @@ void Trans_Enumerate_Types(EnumState& state)
tv.m_resolve.expand_associated_types(sp, rv);
return rv;
};
- const auto& variants = enm.m_variants;
+ ASSERT_BUG(Span(), enm.m_data.is_Data(), "");
+ const auto& variants = enm.m_data.as_Data();
ASSERT_BUG(Span(), 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,
- ),
- (Unit,
- ),
- (Tuple,
- // HACK! Create tuple.
- ::std::vector< ::HIR::TypeRef> tys;
- for(const auto& fld : ve)
- tys.push_back( monomorph(fld.ent) );
- return *tmp_ty_ptr = ::HIR::TypeRef( mv$(tys) );
- ),
- (Struct,
- // HACK! Create tuple.
- ::std::vector< ::HIR::TypeRef> tys;
- for(const auto& fld : ve)
- tys.push_back( monomorph(fld.second.ent) );
- return *tmp_ty_ptr = ::HIR::TypeRef( mv$(tys) );
- )
- )
+ const auto& raw_ty = variants[e.variant_index].type;
+ if( monomorphise_type_needed(raw_ty) ) {
+ return *tmp_ty_ptr = monomorph(raw_ty);
+ }
+ else {
+ return raw_ty;
+ }
}
else
{
@@ -1553,8 +1529,7 @@ void Trans_Enumerate_FillFrom_Literal(EnumState& state, const ::HIR::Literal& li
Trans_Enumerate_FillFrom_Literal(state, v, pp);
),
(Variant,
- for(const auto& v : e.vals)
- Trans_Enumerate_FillFrom_Literal(state, v, pp);
+ Trans_Enumerate_FillFrom_Literal(state, *e.val, pp);
),
(Integer,
),
diff --git a/src/trans/monomorphise.cpp b/src/trans/monomorphise.cpp
index b752a5bc..fd05c85b 100644
--- a/src/trans/monomorphise.cpp
+++ b/src/trans/monomorphise.cpp
@@ -234,7 +234,6 @@ namespace {
(Struct,
rval = ::MIR::RValue::make_Struct({
params.monomorph(resolve, se.path),
- se.variant_idx,
monomorph_Param_list(resolve, params, se.vals)
});
)