summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJohn Hodge <tpg@mutabah.net>2016-11-20 09:26:13 +0800
committerJohn Hodge <tpg@mutabah.net>2016-11-20 09:26:13 +0800
commita6aae2e4413789e548a30fd9cb421cc2f6964b14 (patch)
treea6872cea76eaea7fe24e4c11ac5eb9b42482a3c4 /src
parentad7c16cd3664a79c09e00a76ae4e081aadd88493 (diff)
downloadmrust-a6aae2e4413789e548a30fd9cb421cc2f6964b14.tar.gz
MIR - Union support hacked up
Diffstat (limited to 'src')
-rw-r--r--src/hir/deserialise.cpp19
-rw-r--r--src/hir/serialise.cpp5
-rw-r--r--src/hir_conv/constant_evaluation.cpp3
-rw-r--r--src/mir/check.cpp80
-rw-r--r--src/mir/dump.cpp5
-rw-r--r--src/mir/from_hir.cpp13
-rw-r--r--src/mir/mir.cpp3
-rw-r--r--src/mir/mir.hpp19
-rw-r--r--src/mir/mir_builder.cpp3
9 files changed, 114 insertions, 36 deletions
diff --git a/src/hir/deserialise.cpp b/src/hir/deserialise.cpp
index 5eeffdb9..e1939d6d 100644
--- a/src/hir/deserialise.cpp
+++ b/src/hir/deserialise.cpp
@@ -368,6 +368,11 @@ namespace {
_(Array, {
deserialise_vec_c< ::MIR::LValue>([&](){ return deserialise_mir_lvalue(); })
})
+ _(Variant, {
+ deserialise_genericpath(),
+ static_cast<unsigned int>( m_in.read_count() ),
+ deserialise_mir_lvalue()
+ })
_(Struct, {
deserialise_genericpath(),
deserialise_vec_c< ::MIR::LValue>([&](){ return deserialise_mir_lvalue(); })
@@ -419,6 +424,8 @@ namespace {
return ::HIR::TypeItem( deserialise_struct() );
case 5:
return ::HIR::TypeItem( deserialise_trait() );
+ case 6:
+ return ::HIR::TypeItem( deserialise_union() );
default:
throw "";
}
@@ -506,6 +513,7 @@ namespace {
::HIR::Enum::Variant deserialise_enumvariant();
::HIR::Struct deserialise_struct();
+ ::HIR::Union deserialise_union();
::HIR::Trait deserialise_trait();
::HIR::TraitValueItem deserialise_traitvalueitem()
@@ -765,6 +773,17 @@ namespace {
throw "";
}
}
+ ::HIR::Union HirDeserialiser::deserialise_union()
+ {
+ TRACE_FUNCTION;
+ auto params = deserialise_genericparams();
+ auto repr = static_cast< ::HIR::Union::Repr>( m_in.read_tag() );
+
+ return ::HIR::Union {
+ mv$(params), repr,
+ deserialise_vec< ::std::pair< ::std::string, ::HIR::VisEnt< ::HIR::TypeRef> > >()
+ };
+ }
::HIR::Struct HirDeserialiser::deserialise_struct()
{
TRACE_FUNCTION;
diff --git a/src/hir/serialise.cpp b/src/hir/serialise.cpp
index 4cb2771a..ea4dfabf 100644
--- a/src/hir/serialise.cpp
+++ b/src/hir/serialise.cpp
@@ -572,6 +572,11 @@ namespace {
(Array,
serialise_vec(e.vals);
),
+ (Variant,
+ serialise_genericpath(e.path);
+ m_out.write_count(e.index);
+ serialise(e.val);
+ ),
(Struct,
serialise_genericpath(e.path);
serialise_vec(e.vals);
diff --git a/src/hir_conv/constant_evaluation.cpp b/src/hir_conv/constant_evaluation.cpp
index 8d93ced1..bd1e740a 100644
--- a/src/hir_conv/constant_evaluation.cpp
+++ b/src/hir_conv/constant_evaluation.cpp
@@ -1136,6 +1136,9 @@ namespace {
vals.push_back( read_lval(v) );
val = ::HIR::Literal::make_List( mv$(vals) );
),
+ (Variant,
+ TODO(sp, "MIR _Variant");
+ ),
(Struct,
::std::vector< ::HIR::Literal> vals;
vals.reserve( e.vals.size() );
diff --git a/src/mir/check.cpp b/src/mir/check.cpp
index 8833df09..80909902 100644
--- a/src/mir/check.cpp
+++ b/src/mir/check.cpp
@@ -208,36 +208,55 @@ namespace {
MIR_BUG(*this, "Downcast on unexpected type - " << ty);
),
(Path,
- MIR_ASSERT(*this, te.binding.is_Enum(), "Downcast on non-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");
- 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) );
- this->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) );
- this->resolve.expand_associated_types(sp, tmp);
- return tmp;
+ MIR_ASSERT(*this, te.binding.is_Enum() || te.binding.is_Union(), "Downcast on non-Enum");
+ 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");
+ 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) );
+ this->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) );
+ this->resolve.expand_associated_types(sp, tmp);
+ return tmp;
+ )
)
- )
+ }
+ else
+ {
+ const auto& unm = *te.binding.as_Union();
+ MIR_ASSERT(*this, e.variant_index < unm.m_variants.size(), "Variant index out of range");
+ const auto& variant = unm.m_variants[e.variant_index];
+ const auto& var_ty = variant.second.ent;
+
+ if( monomorphise_type_needed(var_ty) ) {
+ tmp = monomorphise_type(sp, unm.m_params, te.path.m_data.as_Generic().m_params, variant.second.ent);
+ this->resolve.expand_associated_types(sp, tmp);
+ return tmp;
+ }
+ else {
+ return var_ty;
+ }
+ }
)
)
)
@@ -505,6 +524,9 @@ void MIR_Validate(const StaticTraitResolve& resolve, const ::HIR::ItemPath& path
(Array,
// TODO: Check return type
),
+ (Variant,
+ // TODO: Check return type
+ ),
(Struct,
// TODO: Check return type
)
diff --git a/src/mir/dump.cpp b/src/mir/dump.cpp
index fe1e16f1..967bc98d 100644
--- a/src/mir/dump.cpp
+++ b/src/mir/dump.cpp
@@ -376,6 +376,11 @@ namespace {
}
os << "]";
),
+ (Variant,
+ os << e.path << " #" << e.index << " (";
+ fmt_val(os, e.val);
+ os << ")";
+ ),
(Struct,
os << e.path << " { ";
for(const auto& v : e.vals) {
diff --git a/src/mir/from_hir.cpp b/src/mir/from_hir.cpp
index 0dda293b..bccbdb13 100644
--- a/src/mir/from_hir.cpp
+++ b/src/mir/from_hir.cpp
@@ -1721,12 +1721,21 @@ namespace {
}
void visit(::HIR::ExprNode_UnionLiteral& node) override
{
+ TRACE_FUNCTION_F("_UnionLiteral " << node.m_path);
this->visit_node_ptr(node.m_value);
auto val = m_builder.get_result_in_lvalue(node.m_value->span(), node.m_value->m_res_type);
- // TODO: Need a way of initialising just this "variant"
- TODO(node.span(), "_UnionLiteral");
+ const auto& unm = *node.m_res_type.m_data.as_Path().binding.as_Union();
+ auto it = ::std::find_if(unm.m_variants.begin(), unm.m_variants.end(), [&](const auto&v)->auto{ return v.first == node.m_variant_name; });
+ assert(it != unm.m_variants.end());
+ unsigned int idx = it - unm.m_variants.begin();
+
+ m_builder.set_result( node.span(), ::MIR::RValue::make_Variant({
+ node.m_path.clone(),
+ idx,
+ mv$(val)
+ }) );
}
void visit(::HIR::ExprNode_Tuple& node) override
diff --git a/src/mir/mir.cpp b/src/mir/mir.cpp
index f65c7616..0517111a 100644
--- a/src/mir/mir.cpp
+++ b/src/mir/mir.cpp
@@ -114,6 +114,9 @@ namespace MIR {
(Array,
os << "Array(" << e.vals << ")";
),
+ (Variant,
+ os << "Variant(" << e.path << " #" << e.index << ", " << e.val << ")";
+ ),
(Struct,
os << "Struct(" << e.path << ", {" << e.vals << "})";
)
diff --git a/src/mir/mir.hpp b/src/mir/mir.hpp
index c0c94807..c0ee0d21 100644
--- a/src/mir/mir.hpp
+++ b/src/mir/mir.hpp
@@ -109,22 +109,28 @@ TAGGED_UNION(RValue, Use,
::HIR::BorrowType type;
LValue val;
}),
+ // Cast on primitives
(Cast, struct {
LValue val;
::HIR::TypeRef type;
}),
+ // Binary operation on primitives
(BinOp, struct {
LValue val_l;
eBinOp op;
LValue val_r;
}),
+ // Unary operation on primitives
(UniOp, struct {
LValue val;
eUniOp op;
}),
+ // Extract the metadata from a DST pointer
+ // NOTE: If used on an array, this yields the array size (for generics)
(DstMeta, struct {
LValue val;
}),
+ // Construct a DST pointer from a thin pointer and metadata
(MakeDst, struct {
LValue ptr_val;
LValue meta_val;
@@ -132,14 +138,17 @@ TAGGED_UNION(RValue, Use,
(Tuple, struct {
::std::vector<LValue> vals;
}),
+ // Array literal
(Array, struct {
::std::vector<LValue> vals;
}),
- //(Variant, struct {
- // ::HIR::GenericPath path;
- // unsigned int index;
- // LValue val;
- // }),
+ // Create a new instance of a union (and eventually enum)
+ (Variant, struct {
+ ::HIR::GenericPath path;
+ unsigned int index;
+ LValue val;
+ }),
+ // Create a new instance of a struct (or enum)
(Struct, struct {
::HIR::GenericPath path;
::std::vector<LValue> vals;
diff --git a/src/mir/mir_builder.cpp b/src/mir/mir_builder.cpp
index a64867b1..73867918 100644
--- a/src/mir/mir_builder.cpp
+++ b/src/mir/mir_builder.cpp
@@ -238,6 +238,9 @@ void MirBuilder::push_stmt_assign(const Span& sp, ::MIR::LValue dst, ::MIR::RVal
for(const auto& val : e.vals)
this->moved_lvalue(sp, val);
),
+ (Variant,
+ this->moved_lvalue(sp, e.val);
+ ),
(Struct,
for(const auto& val : e.vals)
this->moved_lvalue(sp, val);