forked from libre-chip/fayalite
implement #[hdl(cmp_eq)] for enums
This commit is contained in:
parent
8e4eeef723
commit
7516ec3c24
3 changed files with 530 additions and 7 deletions
|
|
@ -1223,7 +1223,7 @@ impl ToTokens for ParsedBundle {
|
|||
valueless_eq_body = quote_spanned! {span=>
|
||||
let __lhs = ::fayalite::expr::ValueType::ty(&__lhs);
|
||||
let __rhs = ::fayalite::expr::ValueType::ty(&__rhs);
|
||||
#(#fields_valueless_eq)|*
|
||||
#(#fields_valueless_eq)&*
|
||||
};
|
||||
valueless_ne_body = quote_spanned! {span=>
|
||||
let __lhs = ::fayalite::expr::ValueType::ty(&__lhs);
|
||||
|
|
|
|||
|
|
@ -159,14 +159,11 @@ impl ParsedEnum {
|
|||
custom_bounds,
|
||||
no_static: _,
|
||||
no_runtime_generics: _,
|
||||
cmp_eq,
|
||||
cmp_eq: _,
|
||||
ref get,
|
||||
custom_debug: _,
|
||||
custom_sim_display: _,
|
||||
} = options.body;
|
||||
if let Some((cmp_eq,)) = cmp_eq {
|
||||
errors.error(cmp_eq, "#[hdl(cmp_eq)] is not yet implemented for enums");
|
||||
}
|
||||
if let Some((get, ..)) = get {
|
||||
errors.error(get, "#[hdl(get(...))] is not allowed on enums");
|
||||
}
|
||||
|
|
@ -249,7 +246,7 @@ impl ToTokens for ParsedEnum {
|
|||
custom_bounds: _,
|
||||
no_static,
|
||||
no_runtime_generics,
|
||||
cmp_eq: _, // TODO: implement cmp_eq for enums
|
||||
cmp_eq,
|
||||
get: _,
|
||||
custom_debug: _,
|
||||
custom_sim_display,
|
||||
|
|
@ -938,6 +935,172 @@ impl ToTokens for ParsedEnum {
|
|||
}
|
||||
}.to_tokens(tokens);
|
||||
}
|
||||
if let Some((cmp_eq,)) = cmp_eq {
|
||||
let mut cmp_eq_where_clause =
|
||||
Generics::from(generics)
|
||||
.where_clause
|
||||
.unwrap_or_else(|| syn::WhereClause {
|
||||
where_token: Token,
|
||||
predicates: Punctuated::new(),
|
||||
});
|
||||
let mut variants_value_eq = vec![];
|
||||
let mut variants_expr_eq = vec![];
|
||||
let mut fields_valueless_eq = vec![];
|
||||
for (
|
||||
variant_index,
|
||||
ParsedVariant {
|
||||
attrs: _,
|
||||
options: variant_options,
|
||||
ident: variant_ident,
|
||||
field,
|
||||
},
|
||||
) in variants.iter().enumerate()
|
||||
{
|
||||
let VariantOptions {} = variant_options.body;
|
||||
if let Some(ParsedVariantField {
|
||||
paren_token: _,
|
||||
attrs: _,
|
||||
options: field_options,
|
||||
ty: field_ty,
|
||||
comma_token: _,
|
||||
}) = field
|
||||
{
|
||||
let FieldOptions {} = field_options.body;
|
||||
cmp_eq_where_clause
|
||||
.predicates
|
||||
.push(parse_quote_spanned! {cmp_eq.span=>
|
||||
#field_ty: ::fayalite::expr::HdlPartialEqImpl<#field_ty>
|
||||
});
|
||||
variants_value_eq.push(quote_spanned! {span=>
|
||||
(#sim_value_ident::#variant_ident(__lhs_field, _), #sim_value_ident::#variant_ident(__rhs_field, _)) => {
|
||||
::fayalite::expr::HdlPartialEqImpl::cmp_value_eq(
|
||||
__lhs.#variant_ident,
|
||||
::fayalite::__std::borrow::Cow::Borrowed(__lhs_field),
|
||||
__rhs.#variant_ident,
|
||||
::fayalite::__std::borrow::Cow::Borrowed(__rhs_field),
|
||||
)
|
||||
}
|
||||
});
|
||||
variants_expr_eq.push(quote_spanned! {span=>
|
||||
{
|
||||
let (#match_variant_ident::#variant_ident(__lhs), __scope) =
|
||||
::fayalite::ty::MatchVariantAndInactiveScope::match_activate_scope(
|
||||
::fayalite::__std::iter::Iterator::next(&mut __lhs_match_variant_iter)
|
||||
.expect("known to have enough variants"),
|
||||
)
|
||||
else {
|
||||
::fayalite::__std::unreachable!();
|
||||
};
|
||||
let (#match_variant_ident::#variant_ident(__rhs), __scope) =
|
||||
::fayalite::ty::MatchVariantAndInactiveScope::match_activate_scope(
|
||||
::fayalite::__std::iter::Iterator::nth(
|
||||
&mut ::fayalite::module::match_(__rhs),
|
||||
#variant_index,
|
||||
)
|
||||
.expect("known to have variant"),
|
||||
)
|
||||
else {
|
||||
::fayalite::__std::unreachable!();
|
||||
};
|
||||
::fayalite::module::connect(__retval, ::fayalite::expr::HdlPartialEqImpl::cmp_expr_eq(__lhs, __rhs));
|
||||
}
|
||||
});
|
||||
fields_valueless_eq.push(quote_spanned! {span=>
|
||||
::fayalite::expr::HdlPartialEqImpl::cmp_valueless_eq(
|
||||
::fayalite::expr::Valueless::new(__lhs.#variant_ident),
|
||||
::fayalite::expr::Valueless::new(__rhs.#variant_ident),
|
||||
)
|
||||
});
|
||||
} else {
|
||||
variants_value_eq.push(quote_spanned! {span=>
|
||||
(#sim_value_ident::#variant_ident(_), #sim_value_ident::#variant_ident(_)) => true,
|
||||
});
|
||||
variants_expr_eq.push(quote_spanned! {span=>
|
||||
{
|
||||
let (#match_variant_ident::#variant_ident, __scope) =
|
||||
::fayalite::ty::MatchVariantAndInactiveScope::match_activate_scope(
|
||||
::fayalite::__std::iter::Iterator::next(&mut __lhs_match_variant_iter)
|
||||
.expect("known to have enough variants"),
|
||||
)
|
||||
else {
|
||||
::fayalite::__std::unreachable!();
|
||||
};
|
||||
let (#match_variant_ident::#variant_ident, __scope) =
|
||||
::fayalite::ty::MatchVariantAndInactiveScope::match_activate_scope(
|
||||
::fayalite::__std::iter::Iterator::nth(
|
||||
&mut ::fayalite::module::match_(__rhs),
|
||||
#variant_index,
|
||||
)
|
||||
.expect("known to have variant"),
|
||||
)
|
||||
else {
|
||||
::fayalite::__std::unreachable!();
|
||||
};
|
||||
::fayalite::module::connect(__retval, true);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
if let Some(sim_value_unknown_variant_name) = &sim_value_unknown_variant_name {
|
||||
variants_value_eq.push(quote_spanned! {span=>
|
||||
(#sim_value_ident::#sim_value_unknown_variant_name(__lhs_unknown), #sim_value_ident::#sim_value_unknown_variant_name(__rhs_unknown)) => {
|
||||
__lhs_unknown == __rhs_unknown
|
||||
}
|
||||
});
|
||||
}
|
||||
let valueless_eq_body = if fields_valueless_eq.is_empty() {
|
||||
quote_spanned! {span=>
|
||||
::fayalite::expr::Valueless::new(::fayalite::int::Bool)
|
||||
}
|
||||
} else {
|
||||
quote_spanned! {span=>
|
||||
let __lhs = ::fayalite::expr::ValueType::ty(&__lhs);
|
||||
let __rhs = ::fayalite::expr::ValueType::ty(&__rhs);
|
||||
#(#fields_valueless_eq)&*
|
||||
}
|
||||
};
|
||||
let cmp_expr_eq_wire_name = format!("{ident}_cmp_eq");
|
||||
quote_spanned! {span=>
|
||||
#[automatically_derived]
|
||||
impl #impl_generics ::fayalite::expr::HdlPartialEqImpl<Self> for #target #type_generics
|
||||
#cmp_eq_where_clause
|
||||
{
|
||||
#[track_caller]
|
||||
fn cmp_value_eq(
|
||||
__lhs: Self,
|
||||
__lhs_value: ::fayalite::__std::borrow::Cow<'_, <Self as ::fayalite::ty::Type>::SimValue>,
|
||||
__rhs: Self,
|
||||
__rhs_value: ::fayalite::__std::borrow::Cow<'_, <Self as ::fayalite::ty::Type>::SimValue>,
|
||||
) -> ::fayalite::__std::primitive::bool {
|
||||
match (&*__lhs_value, &*__rhs_value) {
|
||||
#(#variants_value_eq)*
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
fn cmp_expr_eq(
|
||||
__lhs: ::fayalite::expr::Expr<Self>,
|
||||
__rhs: ::fayalite::expr::Expr<Self>,
|
||||
) -> ::fayalite::expr::Expr<::fayalite::int::Bool> {
|
||||
let __retval = ::fayalite::module::wire(::fayalite::module::ImplicitName(#cmp_expr_eq_wire_name), ::fayalite::int::Bool);
|
||||
::fayalite::module::connect(__retval, false);
|
||||
let mut __lhs_match_variant_iter = ::fayalite::module::match_(__lhs);
|
||||
#(#variants_expr_eq)*
|
||||
__retval
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
fn cmp_valueless_eq(
|
||||
__lhs: ::fayalite::expr::Valueless<Self>,
|
||||
__rhs: ::fayalite::expr::Valueless<Self>,
|
||||
) -> ::fayalite::expr::Valueless<::fayalite::int::Bool> {
|
||||
#valueless_eq_body
|
||||
}
|
||||
}
|
||||
}
|
||||
.to_tokens(tokens);
|
||||
}
|
||||
let variants_len = variants.len();
|
||||
quote_spanned! {span=>
|
||||
#[automatically_derived]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue