summaryrefslogtreecommitdiff
path: root/src/hir/from_ast.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/hir/from_ast.cpp')
-rw-r--r--src/hir/from_ast.cpp164
1 files changed, 130 insertions, 34 deletions
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) );