add support for custom debug/display formatting of #[hdl] structs/enums
also cleans up default debug formatting to use the struct/enum name (or MaskType<StructName>) instead of the implementation detail type name.
This commit is contained in:
parent
402f457c68
commit
8e4eeef723
18 changed files with 773 additions and 63 deletions
|
|
@ -3,8 +3,9 @@
|
|||
use crate::{
|
||||
Errors, HdlAttr, PairsIterExt,
|
||||
hdl_type_common::{
|
||||
ItemOptions, MakeHdlTypeExpr, MaybeParsed, ParsedField, ParsedFieldsNamed, ParsedGenerics,
|
||||
SplitForImpl, TypesParser, WrappedInConst, common_derives, get_target,
|
||||
CustomDebugOptions, CustomDebugTrait, ItemOptions, MakeHdlTypeExpr, MaybeParsed,
|
||||
ParsedField, ParsedFieldsNamed, ParsedGenerics, SplitForImpl, TypesParser, WrappedInConst,
|
||||
common_derives, create_struct_debug_impl, get_target,
|
||||
},
|
||||
kw,
|
||||
};
|
||||
|
|
@ -30,6 +31,7 @@ pub(crate) struct ParsedBundle {
|
|||
pub(crate) fields: MaybeParsed<ParsedFieldsNamed, FieldsNamed>,
|
||||
pub(crate) field_flips: Vec<Option<HdlAttr<kw::flip, kw::hdl>>>,
|
||||
pub(crate) mask_type_ident: Ident,
|
||||
pub(crate) mask_type_name: String,
|
||||
pub(crate) mask_type_match_variant_ident: Ident,
|
||||
pub(crate) mask_type_sim_value_ident: Ident,
|
||||
pub(crate) match_variant_ident: Ident,
|
||||
|
|
@ -88,6 +90,8 @@ impl ParsedBundle {
|
|||
no_runtime_generics: _,
|
||||
cmp_eq: _,
|
||||
ref get,
|
||||
custom_debug: _,
|
||||
custom_sim_display: _,
|
||||
} = options.body;
|
||||
if let Some((get, ..)) = get {
|
||||
errors.error(get, "#[hdl(get(...))] is not allowed on structs");
|
||||
|
|
@ -131,6 +135,7 @@ impl ParsedBundle {
|
|||
fields,
|
||||
field_flips,
|
||||
mask_type_ident: format_ident!("__{}__MaskType", ident),
|
||||
mask_type_name: format!("MaskType<{}>", ident),
|
||||
mask_type_match_variant_ident: format_ident!("__{}__MaskType__MatchVariant", ident),
|
||||
mask_type_sim_value_ident: format_ident!("__{}__MaskType__SimValue", ident),
|
||||
match_variant_ident: format_ident!("__{}__MatchVariant", ident),
|
||||
|
|
@ -448,6 +453,7 @@ impl ToTokens for ParsedBundle {
|
|||
fields,
|
||||
field_flips,
|
||||
mask_type_ident,
|
||||
mask_type_name,
|
||||
mask_type_match_variant_ident,
|
||||
mask_type_sim_value_ident,
|
||||
match_variant_ident,
|
||||
|
|
@ -464,11 +470,20 @@ impl ToTokens for ParsedBundle {
|
|||
no_runtime_generics,
|
||||
cmp_eq,
|
||||
get: _,
|
||||
custom_debug: _,
|
||||
custom_sim_display,
|
||||
} = &options.body;
|
||||
let CustomDebugOptions {
|
||||
type_: custom_debug_type,
|
||||
sim: custom_debug_sim,
|
||||
mask_type: custom_debug_mask_type,
|
||||
mask_sim: custom_debug_mask_sim,
|
||||
} = options.body.custom_debug();
|
||||
let target = get_target(target, ident);
|
||||
let struct_name = ident.to_string();
|
||||
let mut item_attrs = attrs.clone();
|
||||
item_attrs.push(common_derives(span));
|
||||
ItemStruct {
|
||||
item_attrs.push(common_derives(span, false));
|
||||
let type_struct = ItemStruct {
|
||||
attrs: item_attrs,
|
||||
vis: vis.clone(),
|
||||
struct_token: *struct_token,
|
||||
|
|
@ -476,8 +491,8 @@ impl ToTokens for ParsedBundle {
|
|||
generics: generics.into(),
|
||||
fields: Fields::Named(fields.clone().into()),
|
||||
semi_token: None,
|
||||
}
|
||||
.to_tokens(tokens);
|
||||
};
|
||||
type_struct.to_tokens(tokens);
|
||||
let (impl_generics, type_generics, where_clause) = generics.split_for_impl();
|
||||
if let (MaybeParsed::Parsed(generics), MaybeParsed::Parsed(fields), None) =
|
||||
(generics, fields, no_runtime_generics)
|
||||
|
|
@ -503,6 +518,9 @@ impl ToTokens for ParsedBundle {
|
|||
}
|
||||
let mut wrapped_in_const = WrappedInConst::new(tokens, span);
|
||||
let tokens = wrapped_in_const.inner();
|
||||
if custom_debug_type.is_none() {
|
||||
create_struct_debug_impl(&type_struct, &struct_name, None).to_tokens(tokens);
|
||||
}
|
||||
let builder = Builder {
|
||||
vis: vis.clone(),
|
||||
struct_token: *struct_token,
|
||||
|
|
@ -530,9 +548,9 @@ impl ToTokens for ParsedBundle {
|
|||
mask_type_builder.to_tokens(tokens);
|
||||
let unfilled_mask_type_builder_ty =
|
||||
mask_type_builder.builder_struct_ty(|_| BuilderFieldState::Unfilled);
|
||||
ItemStruct {
|
||||
let mask_type_struct = ItemStruct {
|
||||
attrs: vec![
|
||||
common_derives(span),
|
||||
common_derives(span, false),
|
||||
parse_quote_spanned! {span=>
|
||||
#[allow(non_camel_case_types, dead_code)]
|
||||
},
|
||||
|
|
@ -543,17 +561,20 @@ impl ToTokens for ParsedBundle {
|
|||
generics: generics.into(),
|
||||
fields: Fields::Named(mask_type_fields.clone()),
|
||||
semi_token: None,
|
||||
};
|
||||
mask_type_struct.to_tokens(tokens);
|
||||
if custom_debug_mask_type.is_none() {
|
||||
create_struct_debug_impl(&mask_type_struct, mask_type_name, None).to_tokens(tokens);
|
||||
}
|
||||
.to_tokens(tokens);
|
||||
let mut mask_type_match_variant_fields = mask_type_fields.clone();
|
||||
for Field { ty, .. } in &mut mask_type_match_variant_fields.named {
|
||||
*ty = parse_quote_spanned! {span=>
|
||||
::fayalite::expr::Expr<#ty>
|
||||
};
|
||||
}
|
||||
ItemStruct {
|
||||
let mask_type_match_variant_struct = ItemStruct {
|
||||
attrs: vec![
|
||||
common_derives(span),
|
||||
common_derives(span, false),
|
||||
parse_quote_spanned! {span=>
|
||||
#[allow(non_camel_case_types, dead_code)]
|
||||
},
|
||||
|
|
@ -564,17 +585,19 @@ impl ToTokens for ParsedBundle {
|
|||
generics: generics.into(),
|
||||
fields: Fields::Named(mask_type_match_variant_fields),
|
||||
semi_token: None,
|
||||
}
|
||||
.to_tokens(tokens);
|
||||
};
|
||||
mask_type_match_variant_struct.to_tokens(tokens);
|
||||
create_struct_debug_impl(&mask_type_match_variant_struct, mask_type_name, None)
|
||||
.to_tokens(tokens);
|
||||
let mut match_variant_fields = FieldsNamed::from(fields.clone());
|
||||
for Field { ty, .. } in &mut match_variant_fields.named {
|
||||
*ty = parse_quote_spanned! {span=>
|
||||
::fayalite::expr::Expr<#ty>
|
||||
};
|
||||
}
|
||||
ItemStruct {
|
||||
let match_variant_struct = ItemStruct {
|
||||
attrs: vec![
|
||||
common_derives(span),
|
||||
common_derives(span, false),
|
||||
parse_quote_spanned! {span=>
|
||||
#[allow(non_camel_case_types, dead_code)]
|
||||
},
|
||||
|
|
@ -585,19 +608,19 @@ impl ToTokens for ParsedBundle {
|
|||
generics: generics.into(),
|
||||
fields: Fields::Named(match_variant_fields),
|
||||
semi_token: None,
|
||||
}
|
||||
.to_tokens(tokens);
|
||||
};
|
||||
match_variant_struct.to_tokens(tokens);
|
||||
create_struct_debug_impl(&match_variant_struct, &struct_name, None).to_tokens(tokens);
|
||||
let mut mask_type_sim_value_fields = mask_type_fields;
|
||||
for Field { ty, .. } in &mut mask_type_sim_value_fields.named {
|
||||
*ty = parse_quote_spanned! {span=>
|
||||
::fayalite::sim::value::SimValue<#ty>
|
||||
};
|
||||
}
|
||||
ItemStruct {
|
||||
let mask_type_sim_value_struct = ItemStruct {
|
||||
attrs: vec![
|
||||
parse_quote_spanned! {span=>
|
||||
#[::fayalite::__std::prelude::v1::derive(
|
||||
::fayalite::__std::fmt::Debug,
|
||||
::fayalite::__std::clone::Clone,
|
||||
)]
|
||||
},
|
||||
|
|
@ -611,19 +634,34 @@ impl ToTokens for ParsedBundle {
|
|||
generics: generics.into(),
|
||||
fields: Fields::Named(mask_type_sim_value_fields),
|
||||
semi_token: None,
|
||||
};
|
||||
mask_type_sim_value_struct.to_tokens(tokens);
|
||||
if custom_debug_mask_sim.is_none() {
|
||||
create_struct_debug_impl(
|
||||
&mask_type_struct,
|
||||
mask_type_name,
|
||||
Some(CustomDebugTrait {
|
||||
trait_path: &parse_quote_spanned! {span=>
|
||||
::fayalite::ty::SimValueDebug
|
||||
},
|
||||
fn_name: &format_ident!("sim_value_debug", span = span),
|
||||
this_arg: &parse_quote_spanned! {span=>
|
||||
value: &<Self as ::fayalite::ty::Type>::SimValue
|
||||
},
|
||||
}),
|
||||
)
|
||||
.to_tokens(tokens);
|
||||
}
|
||||
.to_tokens(tokens);
|
||||
let mut sim_value_fields = FieldsNamed::from(fields.clone());
|
||||
for Field { ty, .. } in &mut sim_value_fields.named {
|
||||
*ty = parse_quote_spanned! {span=>
|
||||
::fayalite::sim::value::SimValue<#ty>
|
||||
};
|
||||
}
|
||||
ItemStruct {
|
||||
let sim_value_struct = ItemStruct {
|
||||
attrs: vec![
|
||||
parse_quote_spanned! {span=>
|
||||
#[::fayalite::__std::prelude::v1::derive(
|
||||
::fayalite::__std::fmt::Debug,
|
||||
::fayalite::__std::clone::Clone,
|
||||
)]
|
||||
},
|
||||
|
|
@ -637,8 +675,36 @@ impl ToTokens for ParsedBundle {
|
|||
generics: generics.into(),
|
||||
fields: Fields::Named(sim_value_fields),
|
||||
semi_token: None,
|
||||
};
|
||||
sim_value_struct.to_tokens(tokens);
|
||||
if custom_debug_sim.is_none() {
|
||||
create_struct_debug_impl(
|
||||
&type_struct,
|
||||
&struct_name,
|
||||
Some(CustomDebugTrait {
|
||||
trait_path: &parse_quote_spanned! {span=>
|
||||
::fayalite::ty::SimValueDebug
|
||||
},
|
||||
fn_name: &format_ident!("sim_value_debug", span = span),
|
||||
this_arg: &parse_quote_spanned! {span=>
|
||||
value: &<Self as ::fayalite::ty::Type>::SimValue
|
||||
},
|
||||
}),
|
||||
)
|
||||
.to_tokens(tokens);
|
||||
}
|
||||
if custom_sim_display.is_some() {
|
||||
quote_spanned! {span=>
|
||||
#[automatically_derived]
|
||||
impl #impl_generics ::fayalite::__std::fmt::Display for #sim_value_ident #type_generics
|
||||
#where_clause
|
||||
{
|
||||
fn fmt(&self, f: &mut ::fayalite::__std::fmt::Formatter<'_>) -> ::fayalite::__std::fmt::Result {
|
||||
<#target #type_generics as ::fayalite::ty::SimValueDisplay>::sim_value_display(self, f)
|
||||
}
|
||||
}
|
||||
}.to_tokens(tokens);
|
||||
}
|
||||
.to_tokens(tokens);
|
||||
let this_token = Ident::new("__this", span);
|
||||
let fields_token = Ident::new("__fields", span);
|
||||
let self_token = Token;
|
||||
|
|
@ -820,6 +886,14 @@ impl ToTokens for ParsedBundle {
|
|||
}
|
||||
}
|
||||
#[automatically_derived]
|
||||
impl #impl_generics ::fayalite::__std::fmt::Debug for #mask_type_sim_value_ident #type_generics
|
||||
#where_clause
|
||||
{
|
||||
fn fmt(&self, f: &mut ::fayalite::__std::fmt::Formatter<'_>) -> ::fayalite::__std::fmt::Result {
|
||||
<#mask_type_ident #type_generics as ::fayalite::ty::SimValueDebug>::sim_value_debug(self, f)
|
||||
}
|
||||
}
|
||||
#[automatically_derived]
|
||||
impl #impl_generics ::fayalite::expr::ValueType for #mask_type_sim_value_ident #type_generics
|
||||
#where_clause
|
||||
{
|
||||
|
|
@ -980,6 +1054,14 @@ impl ToTokens for ParsedBundle {
|
|||
}
|
||||
}
|
||||
#[automatically_derived]
|
||||
impl #impl_generics ::fayalite::__std::fmt::Debug for #sim_value_ident #type_generics
|
||||
#where_clause
|
||||
{
|
||||
fn fmt(&self, f: &mut ::fayalite::__std::fmt::Formatter<'_>) -> ::fayalite::__std::fmt::Result {
|
||||
<#target #type_generics as ::fayalite::ty::SimValueDebug>::sim_value_debug(self, f)
|
||||
}
|
||||
}
|
||||
#[automatically_derived]
|
||||
impl #impl_generics ::fayalite::expr::ValueType for #sim_value_ident #type_generics
|
||||
#where_clause
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue