forked from libre-chip/fayalite
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
|
|
@ -257,5 +257,6 @@ no_op_fold!(syn::Token![let]);
|
|||
no_op_fold!(syn::Token![mut]);
|
||||
no_op_fold!(syn::Token![static]);
|
||||
no_op_fold!(syn::Token![struct]);
|
||||
no_op_fold!(syn::Token![type]);
|
||||
no_op_fold!(syn::Token![where]);
|
||||
no_op_fold!(usize);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
{
|
||||
|
|
|
|||
|
|
@ -3,8 +3,9 @@
|
|||
use crate::{
|
||||
Errors, HdlAttr, PairsIterExt,
|
||||
hdl_type_common::{
|
||||
ItemOptions, MakeHdlTypeExpr, MaybeParsed, ParsedGenerics, ParsedType, SplitForImpl,
|
||||
TypesParser, WrappedInConst, common_derives, get_target,
|
||||
CustomDebugOptions, ItemOptions, MakeHdlTypeExpr, MaybeParsed, ParsedGenerics, ParsedType,
|
||||
SplitForImpl, TypesParser, WrappedInConst, common_derives, create_struct_debug_impl,
|
||||
get_target,
|
||||
},
|
||||
kw,
|
||||
};
|
||||
|
|
@ -160,6 +161,8 @@ impl ParsedEnum {
|
|||
no_runtime_generics: _,
|
||||
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");
|
||||
|
|
@ -167,6 +170,24 @@ impl ParsedEnum {
|
|||
if let Some((get, ..)) = get {
|
||||
errors.error(get, "#[hdl(get(...))] is not allowed on enums");
|
||||
}
|
||||
let CustomDebugOptions {
|
||||
type_: _,
|
||||
sim: _,
|
||||
mask_type,
|
||||
mask_sim,
|
||||
} = options.body.custom_debug();
|
||||
if let Some((mask_type,)) = mask_type {
|
||||
errors.error(
|
||||
mask_type,
|
||||
"#[hdl(custom_debug(mask_type)] is not allowed on enums",
|
||||
);
|
||||
}
|
||||
if let Some((mask_sim,)) = mask_sim {
|
||||
errors.error(
|
||||
mask_sim,
|
||||
"#[hdl(custom_debug(mask_sim)] is not allowed on enums",
|
||||
);
|
||||
}
|
||||
attrs.retain(|attr| {
|
||||
if attr.path().is_ident("repr") {
|
||||
errors.error(attr, "#[repr] is not supported on #[hdl] enums");
|
||||
|
|
@ -230,10 +251,19 @@ impl ToTokens for ParsedEnum {
|
|||
no_runtime_generics,
|
||||
cmp_eq: _, // TODO: implement cmp_eq for enums
|
||||
get: _,
|
||||
custom_debug: _,
|
||||
custom_sim_display,
|
||||
} = &options.body;
|
||||
let CustomDebugOptions {
|
||||
type_: custom_debug_type,
|
||||
sim: custom_debug_sim,
|
||||
mask_type: _,
|
||||
mask_sim: _,
|
||||
} = options.body.custom_debug();
|
||||
let target = get_target(target, ident);
|
||||
let enum_name = ident.to_string();
|
||||
let mut struct_attrs = attrs.clone();
|
||||
struct_attrs.push(common_derives(span));
|
||||
struct_attrs.push(common_derives(span, false));
|
||||
struct_attrs.push(parse_quote_spanned! {span=>
|
||||
#[allow(non_snake_case)]
|
||||
});
|
||||
|
|
@ -273,7 +303,7 @@ impl ToTokens for ParsedEnum {
|
|||
}
|
||||
},
|
||||
));
|
||||
ItemStruct {
|
||||
let type_struct = ItemStruct {
|
||||
attrs: struct_attrs,
|
||||
vis: vis.clone(),
|
||||
struct_token: Token,
|
||||
|
|
@ -288,8 +318,8 @@ impl ToTokens for ParsedEnum {
|
|||
})
|
||||
},
|
||||
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), None) = (generics, no_runtime_generics) {
|
||||
generics.make_runtime_generics(tokens, vis, ident, &target, |context| {
|
||||
|
|
@ -373,6 +403,9 @@ impl ToTokens for ParsedEnum {
|
|||
}
|
||||
.to_tokens(tokens);
|
||||
}
|
||||
if custom_debug_type.is_none() {
|
||||
create_struct_debug_impl(&type_struct, &enum_name, None).to_tokens(tokens);
|
||||
}
|
||||
let mut enum_attrs = attrs.clone();
|
||||
enum_attrs.push(parse_quote_spanned! {span=>
|
||||
#[allow(dead_code, non_camel_case_types)]
|
||||
|
|
@ -453,7 +486,6 @@ impl ToTokens for ParsedEnum {
|
|||
let mut enum_attrs = attrs.clone();
|
||||
enum_attrs.push(parse_quote_spanned! {span=>
|
||||
#[::fayalite::__std::prelude::v1::derive(
|
||||
::fayalite::__std::fmt::Debug,
|
||||
::fayalite::__std::clone::Clone,
|
||||
)]
|
||||
});
|
||||
|
|
@ -838,6 +870,74 @@ impl ToTokens for ParsedEnum {
|
|||
},
|
||||
)),
|
||||
);
|
||||
if custom_debug_sim.is_none() {
|
||||
let debug_match_arms = Vec::from_iter(
|
||||
variants
|
||||
.iter()
|
||||
.map(
|
||||
|ParsedVariant {
|
||||
attrs: _,
|
||||
options: _,
|
||||
ident,
|
||||
field,
|
||||
}| {
|
||||
let variant_name = ident.to_string();
|
||||
if let Some(_) = field {
|
||||
quote_spanned! {span=>
|
||||
#sim_value_ident::#ident(field, _) => {
|
||||
f.debug_tuple(#variant_name).field(field).finish()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
quote_spanned! {span=>
|
||||
#sim_value_ident::#ident(_) => {
|
||||
f.write_str(#variant_name)
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
.chain(sim_value_unknown_variant_name.as_ref().map(
|
||||
|sim_value_unknown_variant_name| {
|
||||
let sim_value_unknown_variant_name_str =
|
||||
sim_value_unknown_variant_name.to_string();
|
||||
quote_spanned! {span=>
|
||||
#sim_value_ident::#sim_value_unknown_variant_name(_) => {
|
||||
f.write_str(#sim_value_unknown_variant_name_str)
|
||||
}
|
||||
}
|
||||
},
|
||||
)),
|
||||
);
|
||||
quote_spanned! {span=>
|
||||
#[automatically_derived]
|
||||
impl #impl_generics ::fayalite::ty::SimValueDebug for #target #type_generics
|
||||
#where_clause
|
||||
{
|
||||
fn sim_value_debug(
|
||||
value: &<Self as ::fayalite::ty::Type>::SimValue,
|
||||
f: &mut ::fayalite::__std::fmt::Formatter<'_>,
|
||||
) -> ::fayalite::__std::fmt::Result {
|
||||
match value {
|
||||
#(#debug_match_arms)*
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.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);
|
||||
}
|
||||
let variants_len = variants.len();
|
||||
quote_spanned! {span=>
|
||||
#[automatically_derived]
|
||||
|
|
@ -934,6 +1034,14 @@ impl ToTokens for ParsedEnum {
|
|||
}
|
||||
}
|
||||
#[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::sim::value::ToSimValueWithType<#target #type_generics>
|
||||
for #sim_value_ident #type_generics
|
||||
#where_clause
|
||||
|
|
|
|||
|
|
@ -215,6 +215,8 @@ impl ParsedTypeAlias {
|
|||
no_runtime_generics,
|
||||
cmp_eq,
|
||||
get: _,
|
||||
ref custom_debug,
|
||||
custom_sim_display,
|
||||
} = options.body;
|
||||
if let Some((no_static,)) = no_static {
|
||||
errors.error(no_static, "no_static is not valid on type aliases");
|
||||
|
|
@ -234,6 +236,15 @@ impl ParsedTypeAlias {
|
|||
if let Some((cmp_eq,)) = cmp_eq {
|
||||
errors.error(cmp_eq, "cmp_eq is not valid on type aliases");
|
||||
}
|
||||
if let Some((custom_debug, _, _)) = custom_debug {
|
||||
errors.error(custom_debug, "custom_debug is not valid on type aliases");
|
||||
}
|
||||
if let Some((custom_sim_display,)) = custom_sim_display {
|
||||
errors.error(
|
||||
custom_sim_display,
|
||||
"custom_sim_display is not valid on type aliases",
|
||||
);
|
||||
}
|
||||
if let Some((custom_bounds,)) = custom_bounds {
|
||||
errors.error(
|
||||
custom_bounds,
|
||||
|
|
@ -287,6 +298,8 @@ impl ParsedTypeAlias {
|
|||
no_runtime_generics: _,
|
||||
cmp_eq,
|
||||
ref mut get,
|
||||
ref custom_debug,
|
||||
custom_sim_display,
|
||||
} = options.body;
|
||||
if let Some(get) = get.take() {
|
||||
return Self::parse_phantom_const_accessor(
|
||||
|
|
@ -311,6 +324,15 @@ impl ParsedTypeAlias {
|
|||
if let Some((cmp_eq,)) = cmp_eq {
|
||||
errors.error(cmp_eq, "cmp_eq is not valid on type aliases");
|
||||
}
|
||||
if let Some((custom_debug, _, _)) = custom_debug {
|
||||
errors.error(custom_debug, "custom_debug is not valid on type aliases");
|
||||
}
|
||||
if let Some((custom_sim_display,)) = custom_sim_display {
|
||||
errors.error(
|
||||
custom_sim_display,
|
||||
"custom_sim_display is not valid on type aliases",
|
||||
);
|
||||
}
|
||||
let generics = if custom_bounds.is_some() {
|
||||
MaybeParsed::Unrecognized(generics)
|
||||
} else if let Some(generics) = errors.ok(ParsedGenerics::parse(&mut generics)) {
|
||||
|
|
@ -356,6 +378,8 @@ impl ToTokens for ParsedTypeAlias {
|
|||
no_runtime_generics,
|
||||
cmp_eq: _,
|
||||
get: _,
|
||||
custom_debug: _,
|
||||
custom_sim_display: _,
|
||||
} = &options.body;
|
||||
let target = get_target(target, ident);
|
||||
let mut type_attrs = attrs.clone();
|
||||
|
|
@ -402,6 +426,8 @@ impl ToTokens for ParsedTypeAlias {
|
|||
no_runtime_generics: _,
|
||||
cmp_eq: _,
|
||||
get: _,
|
||||
custom_debug: _,
|
||||
custom_sim_display: _,
|
||||
} = &options.body;
|
||||
let span = ident.span();
|
||||
let mut type_attrs = attrs.clone();
|
||||
|
|
@ -427,7 +453,7 @@ impl ToTokens for ParsedTypeAlias {
|
|||
format_ident!("__{}__GenericsAccumulation", ident);
|
||||
ItemStruct {
|
||||
attrs: vec![
|
||||
common_derives(span),
|
||||
common_derives(span, true),
|
||||
parse_quote_spanned! {span=>
|
||||
#[allow(non_camel_case_types)]
|
||||
},
|
||||
|
|
|
|||
|
|
@ -7,10 +7,10 @@ use std::{collections::HashMap, fmt, mem};
|
|||
use syn::{
|
||||
AngleBracketedGenericArguments, Attribute, Block, ConstParam, Expr, ExprBlock, ExprGroup,
|
||||
ExprIndex, ExprParen, ExprPath, ExprTuple, Field, FieldMutability, Fields, FieldsNamed,
|
||||
FieldsUnnamed, GenericArgument, GenericParam, Generics, Ident, ImplGenerics, Index, ItemStruct,
|
||||
Path, PathArguments, PathSegment, PredicateType, QSelf, Stmt, Token, TraitBound, Turbofish,
|
||||
Type, TypeGenerics, TypeGroup, TypeParam, TypeParamBound, TypeParen, TypePath, TypeTuple,
|
||||
Visibility, WhereClause, WherePredicate,
|
||||
FieldsUnnamed, FnArg, GenericArgument, GenericParam, Generics, Ident, ImplGenerics, Index,
|
||||
ItemStruct, Path, PathArguments, PathSegment, PredicateType, QSelf, Stmt, Token, TraitBound,
|
||||
Turbofish, Type, TypeGenerics, TypeGroup, TypeParam, TypeParamBound, TypeParen, TypePath,
|
||||
TypeTuple, Visibility, WhereClause, WherePredicate,
|
||||
parse::{Parse, ParseStream},
|
||||
parse_quote, parse_quote_spanned,
|
||||
punctuated::{Pair, Punctuated},
|
||||
|
|
@ -18,6 +18,17 @@ use syn::{
|
|||
token::{Brace, Bracket, Paren},
|
||||
};
|
||||
|
||||
crate::options! {
|
||||
#[options = CustomDebugOptions]
|
||||
#[no_ident_fragment]
|
||||
pub(crate) enum CustomDebugOption {
|
||||
Type(type_),
|
||||
Sim(sim),
|
||||
MaskType(mask_type),
|
||||
MaskSim(mask_sim),
|
||||
}
|
||||
}
|
||||
|
||||
crate::options! {
|
||||
#[options = ItemOptions]
|
||||
pub(crate) enum ItemOption {
|
||||
|
|
@ -28,6 +39,8 @@ crate::options! {
|
|||
NoRuntimeGenerics(no_runtime_generics),
|
||||
CmpEq(cmp_eq),
|
||||
Get(get, Expr),
|
||||
CustomDebug(custom_debug, CustomDebugOptions),
|
||||
CustomSimDisplay(custom_sim_display),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -41,8 +54,36 @@ impl ItemOptions {
|
|||
{
|
||||
self.no_static = Some((kw::no_static(custom_bounds.span),));
|
||||
}
|
||||
if let Some((kw, _, custom_debug)) = &mut self.custom_debug {
|
||||
if let CustomDebugOptions {
|
||||
type_: None,
|
||||
sim: None,
|
||||
mask_type: None,
|
||||
mask_sim: None,
|
||||
} = custom_debug
|
||||
{
|
||||
*custom_debug = CustomDebugOptions {
|
||||
type_: Some((kw::type_(kw.span),)),
|
||||
sim: Some((kw::sim(kw.span),)),
|
||||
mask_type: None,
|
||||
mask_sim: None,
|
||||
};
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
pub(crate) fn custom_debug(&self) -> &CustomDebugOptions {
|
||||
self.custom_debug.as_ref().map(|v| &v.2).unwrap_or(
|
||||
const {
|
||||
&CustomDebugOptions {
|
||||
type_: None,
|
||||
sim: None,
|
||||
mask_type: None,
|
||||
mask_sim: None,
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct WrappedInConst<'a> {
|
||||
|
|
@ -84,10 +125,17 @@ pub(crate) fn get_target(target: &Option<(kw::target, Paren, Path)>, item_ident:
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn common_derives(span: Span) -> Attribute {
|
||||
pub(crate) fn common_derives(span: Span, include_debug: bool) -> Attribute {
|
||||
let debug = include_debug
|
||||
.then(|| {
|
||||
quote_spanned! {span=>
|
||||
::fayalite::__std::fmt::Debug
|
||||
}
|
||||
})
|
||||
.into_iter();
|
||||
parse_quote_spanned! {span=>
|
||||
#[::fayalite::__std::prelude::v1::derive(
|
||||
::fayalite::__std::fmt::Debug,
|
||||
#(#debug,)*
|
||||
::fayalite::__std::cmp::Eq,
|
||||
::fayalite::__std::cmp::PartialEq,
|
||||
::fayalite::__std::hash::Hash,
|
||||
|
|
@ -2975,7 +3023,7 @@ impl ParsedGenerics {
|
|||
let span = ident.span();
|
||||
ItemStruct {
|
||||
attrs: vec![
|
||||
common_derives(span),
|
||||
common_derives(span, true),
|
||||
parse_quote_spanned! {span=>
|
||||
#[allow(non_camel_case_types)]
|
||||
},
|
||||
|
|
@ -4733,3 +4781,109 @@ impl ParsedVisibility {
|
|||
.map(|ord| if ord.is_lt() { self } else { other })
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct CustomDebugTrait<'a> {
|
||||
pub(crate) trait_path: &'a Path,
|
||||
pub(crate) fn_name: &'a Ident,
|
||||
pub(crate) this_arg: &'a FnArg,
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub(crate) fn create_struct_debug_impl(
|
||||
item_struct: &ItemStruct,
|
||||
debug_struct_name: &str,
|
||||
custom_debug_trait: Option<CustomDebugTrait<'_>>,
|
||||
) -> TokenStream {
|
||||
let ident = &item_struct.ident;
|
||||
let span = ident.span();
|
||||
let (impl_generics, type_generics, where_clause) = item_struct.generics.split_for_impl();
|
||||
let trait_path;
|
||||
let fn_name;
|
||||
let this_arg;
|
||||
let CustomDebugTrait {
|
||||
trait_path,
|
||||
fn_name,
|
||||
this_arg,
|
||||
} = match custom_debug_trait {
|
||||
Some(v) => v,
|
||||
None => {
|
||||
trait_path = parse_quote_spanned! {span=>
|
||||
::fayalite::__std::fmt::Debug
|
||||
};
|
||||
fn_name = parse_quote_spanned! {span=>
|
||||
fmt
|
||||
};
|
||||
this_arg = parse_quote_spanned! {span=>
|
||||
&self
|
||||
};
|
||||
CustomDebugTrait {
|
||||
trait_path: &trait_path,
|
||||
fn_name: &fn_name,
|
||||
this_arg: &this_arg,
|
||||
}
|
||||
}
|
||||
};
|
||||
let this_arg_name = match this_arg {
|
||||
FnArg::Receiver(this_arg) => this_arg.self_token.to_token_stream(),
|
||||
FnArg::Typed(this_arg) => match &*this_arg.pat {
|
||||
syn::Pat::Ident(pat_ident) => pat_ident.ident.to_token_stream(),
|
||||
_ => unreachable!(),
|
||||
},
|
||||
};
|
||||
match &item_struct.fields {
|
||||
Fields::Named(fields) => {
|
||||
let field_idents = fields
|
||||
.named
|
||||
.iter()
|
||||
.map(|v| v.ident.as_ref().expect("known to have field name"));
|
||||
let field_names = field_idents.clone().map(|v| v.to_string());
|
||||
quote_spanned! {span=>
|
||||
#[automatically_derived]
|
||||
impl #impl_generics #trait_path for #ident #type_generics
|
||||
#where_clause
|
||||
{
|
||||
fn #fn_name(#this_arg, f: &mut ::fayalite::__std::fmt::Formatter<'_>) -> ::fayalite::__std::fmt::Result {
|
||||
let _ = #this_arg_name;
|
||||
f.debug_struct(#debug_struct_name)
|
||||
#(.field(#field_names, &#this_arg_name.#field_idents))*
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Fields::Unnamed(fields) => {
|
||||
let field_members = fields
|
||||
.unnamed
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(index, _)| syn::Index {
|
||||
index: index as _,
|
||||
span,
|
||||
});
|
||||
quote_spanned! {span=>
|
||||
#[automatically_derived]
|
||||
impl #impl_generics #trait_path for #ident #type_generics
|
||||
#where_clause
|
||||
{
|
||||
fn #fn_name(#this_arg, f: &mut ::fayalite::__std::fmt::Formatter<'_>) -> ::fayalite::__std::fmt::Result {
|
||||
let _ = #this_arg_name;
|
||||
f.debug_tuple(#debug_struct_name)
|
||||
#(.field(&#this_arg_name.#field_members))*
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Fields::Unit => quote_spanned! {ident.span()=>
|
||||
#[automatically_derived]
|
||||
impl #impl_generics #trait_path for #ident #type_generics
|
||||
#where_clause
|
||||
{
|
||||
fn #fn_name(#this_arg, f: &mut ::fayalite::__std::fmt::Formatter<'_>) -> ::fayalite::__std::fmt::Result {
|
||||
let _ = #this_arg_name;
|
||||
f.write_str(#debug_struct_name)
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ pub(crate) trait CustomToken:
|
|||
|
||||
mod kw {
|
||||
pub(crate) use syn::token::Extern as extern_;
|
||||
pub(crate) use syn::token::Type as type_;
|
||||
|
||||
macro_rules! custom_keyword {
|
||||
($kw:ident) => {
|
||||
|
|
@ -75,6 +76,8 @@ mod kw {
|
|||
custom_keyword!(cmp_eq);
|
||||
custom_keyword!(connect_inexact);
|
||||
custom_keyword!(custom_bounds);
|
||||
custom_keyword!(custom_debug);
|
||||
custom_keyword!(custom_sim_display);
|
||||
custom_keyword!(flip);
|
||||
custom_keyword!(get);
|
||||
custom_keyword!(hdl);
|
||||
|
|
@ -83,6 +86,8 @@ mod kw {
|
|||
custom_keyword!(input);
|
||||
custom_keyword!(instance);
|
||||
custom_keyword!(m);
|
||||
custom_keyword!(mask_sim);
|
||||
custom_keyword!(mask_type);
|
||||
custom_keyword!(memory);
|
||||
custom_keyword!(memory_array);
|
||||
custom_keyword!(memory_with_init);
|
||||
|
|
|
|||
|
|
@ -13,13 +13,13 @@ use crate::{
|
|||
source_location::SourceLocation,
|
||||
ty::{
|
||||
CanonicalType, MatchVariantWithoutScope, OpaqueSimValueSlice, OpaqueSimValueWriter,
|
||||
OpaqueSimValueWritten, StaticType, Type, TypeProperties, TypeWithDeref,
|
||||
OpaqueSimValueWritten, SimValueDebug, StaticType, Type, TypeProperties, TypeWithDeref,
|
||||
serde_impls::SerdeCanonicalType,
|
||||
},
|
||||
util::ConstUsize,
|
||||
};
|
||||
use serde::{Deserialize, Deserializer, Serialize, Serializer, de::Error};
|
||||
use std::{borrow::Cow, iter::FusedIterator, ops::Index};
|
||||
use std::{borrow::Cow, fmt, iter::FusedIterator, ops::Index};
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct ArrayType<T: Type = CanonicalType, Len: Size = DynSize> {
|
||||
|
|
@ -28,8 +28,8 @@ pub struct ArrayType<T: Type = CanonicalType, Len: Size = DynSize> {
|
|||
type_properties: TypeProperties,
|
||||
}
|
||||
|
||||
impl<T: Type, Len: Size> std::fmt::Debug for ArrayType<T, Len> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
impl<T: Type, Len: Size> fmt::Debug for ArrayType<T, Len> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "Array<{:?}, {}>", self.element, self.len())
|
||||
}
|
||||
}
|
||||
|
|
@ -182,6 +182,15 @@ impl<T: Type + Visit<State>, Len: Size, State: Visitor + ?Sized> Visit<State>
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: Type, Len: Size> SimValueDebug for ArrayType<T, Len> {
|
||||
fn sim_value_debug(
|
||||
value: &<Self as Type>::SimValue,
|
||||
f: &mut fmt::Formatter<'_>,
|
||||
) -> fmt::Result {
|
||||
fmt::Debug::fmt(value, f)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Type, Len: Size> Type for ArrayType<T, Len> {
|
||||
type BaseType = Array;
|
||||
type MaskType = ArrayType<T::MaskType, Len>;
|
||||
|
|
|
|||
|
|
@ -14,8 +14,8 @@ use crate::{
|
|||
source_location::SourceLocation,
|
||||
ty::{
|
||||
CanonicalType, MatchVariantWithoutScope, OpaqueSimValue, OpaqueSimValueSize,
|
||||
OpaqueSimValueSlice, OpaqueSimValueWriter, OpaqueSimValueWritten, StaticType, Type,
|
||||
TypeProperties, TypeWithDeref, impl_match_variant_as_self,
|
||||
OpaqueSimValueSlice, OpaqueSimValueWriter, OpaqueSimValueWritten, SimValueDebug,
|
||||
StaticType, Type, TypeProperties, TypeWithDeref, impl_match_variant_as_self,
|
||||
},
|
||||
util::HashMap,
|
||||
};
|
||||
|
|
@ -271,6 +271,15 @@ impl Type for Bundle {
|
|||
}
|
||||
}
|
||||
|
||||
impl SimValueDebug for Bundle {
|
||||
fn sim_value_debug(
|
||||
value: &<Self as Type>::SimValue,
|
||||
f: &mut fmt::Formatter<'_>,
|
||||
) -> fmt::Result {
|
||||
fmt::Debug::fmt(value, f)
|
||||
}
|
||||
}
|
||||
|
||||
pub trait BundleType: Type<BaseType = Bundle> {
|
||||
type Builder: Default;
|
||||
fn fields(&self) -> Interned<[BundleField]>;
|
||||
|
|
@ -471,6 +480,14 @@ macro_rules! impl_tuples {
|
|||
#[var($var)]
|
||||
})*]
|
||||
}
|
||||
impl<$($T: Type,)*> SimValueDebug for ($($T,)*) {
|
||||
fn sim_value_debug(
|
||||
value: &<Self as Type>::SimValue,
|
||||
f: &mut fmt::Formatter<'_>,
|
||||
) -> fmt::Result {
|
||||
fmt::Debug::fmt(value, f)
|
||||
}
|
||||
}
|
||||
impl<$($T: Type,)*> Type for ($($T,)*) {
|
||||
type BaseType = Bundle;
|
||||
type MaskType = ($($T::MaskType,)*);
|
||||
|
|
@ -773,6 +790,15 @@ impl_tuples! {
|
|||
]
|
||||
}
|
||||
|
||||
impl<T: ?Sized + Send + Sync + 'static> SimValueDebug for PhantomData<T> {
|
||||
fn sim_value_debug(
|
||||
value: &<Self as Type>::SimValue,
|
||||
f: &mut fmt::Formatter<'_>,
|
||||
) -> fmt::Result {
|
||||
fmt::Debug::fmt(value, f)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ?Sized + Send + Sync + 'static> Type for PhantomData<T> {
|
||||
type BaseType = Bundle;
|
||||
type MaskType = ();
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
// See Notices.txt for copyright information
|
||||
|
||||
use crate::{
|
||||
expr::{Expr, ValueType},
|
||||
hdl,
|
||||
|
|
@ -9,10 +10,12 @@ use crate::{
|
|||
source_location::SourceLocation,
|
||||
ty::{
|
||||
CanonicalType, OpaqueSimValueSize, OpaqueSimValueSlice, OpaqueSimValueWriter,
|
||||
OpaqueSimValueWritten, StaticType, Type, TypeProperties, impl_match_variant_as_self,
|
||||
OpaqueSimValueWritten, SimValueDebug, StaticType, Type, TypeProperties,
|
||||
impl_match_variant_as_self,
|
||||
},
|
||||
};
|
||||
use bitvec::{bits, order::Lsb0};
|
||||
use std::fmt;
|
||||
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, Default)]
|
||||
pub struct Clock;
|
||||
|
|
@ -69,6 +72,15 @@ impl Type for Clock {
|
|||
}
|
||||
}
|
||||
|
||||
impl SimValueDebug for Clock {
|
||||
fn sim_value_debug(
|
||||
value: &<Self as Type>::SimValue,
|
||||
f: &mut fmt::Formatter<'_>,
|
||||
) -> fmt::Result {
|
||||
fmt::Debug::fmt(value, f)
|
||||
}
|
||||
}
|
||||
|
||||
impl Clock {
|
||||
pub fn type_properties(self) -> TypeProperties {
|
||||
Self::TYPE_PROPERTIES
|
||||
|
|
|
|||
|
|
@ -14,8 +14,8 @@ use crate::{
|
|||
source_location::SourceLocation,
|
||||
ty::{
|
||||
CanonicalType, MatchVariantAndInactiveScope, OpaqueSimValue, OpaqueSimValueSize,
|
||||
OpaqueSimValueSlice, OpaqueSimValueWriter, OpaqueSimValueWritten, StaticType, Type,
|
||||
TypeProperties,
|
||||
OpaqueSimValueSlice, OpaqueSimValueWriter, OpaqueSimValueWritten, SimValueDebug,
|
||||
StaticType, Type, TypeProperties,
|
||||
},
|
||||
util::HashMap,
|
||||
};
|
||||
|
|
@ -410,6 +410,15 @@ impl Type for Enum {
|
|||
}
|
||||
}
|
||||
|
||||
impl SimValueDebug for Enum {
|
||||
fn sim_value_debug(
|
||||
value: &<Self as Type>::SimValue,
|
||||
f: &mut fmt::Formatter<'_>,
|
||||
) -> fmt::Result {
|
||||
fmt::Debug::fmt(value, f)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Hash, Debug, Default)]
|
||||
pub struct EnumPaddingSimValue {
|
||||
bits: Option<UIntValue>,
|
||||
|
|
|
|||
|
|
@ -15,8 +15,8 @@ use crate::{
|
|||
source_location::SourceLocation,
|
||||
ty::{
|
||||
CanonicalType, FillInDefaultedGenerics, OpaqueSimValueSize, OpaqueSimValueSlice,
|
||||
OpaqueSimValueWriter, OpaqueSimValueWritten, StaticType, Type, TypeProperties,
|
||||
impl_match_variant_as_self,
|
||||
OpaqueSimValueWriter, OpaqueSimValueWritten, SimValueDebug, SimValueDisplay, StaticType,
|
||||
Type, TypeProperties, impl_match_variant_as_self,
|
||||
},
|
||||
util::{ConstBool, ConstUsize, GenericConstBool, GenericConstUsize, interned_bit, slice_range},
|
||||
};
|
||||
|
|
@ -1019,6 +1019,24 @@ macro_rules! impl_int {
|
|||
}
|
||||
}
|
||||
|
||||
impl<Width: Size> SimValueDebug for $name<Width> {
|
||||
fn sim_value_debug(
|
||||
value: &<Self as Type>::SimValue,
|
||||
f: &mut fmt::Formatter<'_>,
|
||||
) -> fmt::Result {
|
||||
fmt::Debug::fmt(value, f)
|
||||
}
|
||||
}
|
||||
|
||||
impl<Width: Size> SimValueDisplay for $name<Width> {
|
||||
fn sim_value_display(
|
||||
value: &<Self as Type>::SimValue,
|
||||
f: &mut fmt::Formatter<'_>,
|
||||
) -> fmt::Result {
|
||||
fmt::Display::fmt(value, f)
|
||||
}
|
||||
}
|
||||
|
||||
impl<Width: KnownSize> Default for $name<Width> {
|
||||
fn default() -> Self {
|
||||
Self::TYPE
|
||||
|
|
@ -1899,6 +1917,15 @@ impl Type for Bool {
|
|||
}
|
||||
}
|
||||
|
||||
impl SimValueDebug for Bool {
|
||||
fn sim_value_debug(
|
||||
value: &<Self as Type>::SimValue,
|
||||
f: &mut fmt::Formatter<'_>,
|
||||
) -> fmt::Result {
|
||||
fmt::Debug::fmt(value, f)
|
||||
}
|
||||
}
|
||||
|
||||
impl StaticType for Bool {
|
||||
const TYPE: Self = Bool;
|
||||
const MASK_TYPE: Self::MaskType = Bool;
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ use crate::{
|
|||
source_location::SourceLocation,
|
||||
ty::{
|
||||
CanonicalType, OpaqueSimValueSlice, OpaqueSimValueWriter, OpaqueSimValueWritten,
|
||||
StaticType, Type, TypeProperties, impl_match_variant_as_self,
|
||||
SimValueDebug, StaticType, Type, TypeProperties, impl_match_variant_as_self,
|
||||
},
|
||||
};
|
||||
use bitvec::{order::Lsb0, view::BitView};
|
||||
|
|
@ -94,6 +94,15 @@ impl Type for UIntInRangeMaskType {
|
|||
}
|
||||
}
|
||||
|
||||
impl SimValueDebug for UIntInRangeMaskType {
|
||||
fn sim_value_debug(
|
||||
value: &<Self as Type>::SimValue,
|
||||
f: &mut fmt::Formatter<'_>,
|
||||
) -> fmt::Result {
|
||||
fmt::Debug::fmt(value, f)
|
||||
}
|
||||
}
|
||||
|
||||
impl BundleType for UIntInRangeMaskType {
|
||||
type Builder = NoBuilder;
|
||||
|
||||
|
|
@ -339,6 +348,15 @@ macro_rules! define_uint_in_range_type {
|
|||
}
|
||||
}
|
||||
|
||||
impl<Start: Size, End: Size> SimValueDebug for $UIntInRangeType<Start, End> {
|
||||
fn sim_value_debug(
|
||||
value: &<Self as Type>::SimValue,
|
||||
f: &mut fmt::Formatter<'_>,
|
||||
) -> fmt::Result {
|
||||
fmt::Debug::fmt(value, f)
|
||||
}
|
||||
}
|
||||
|
||||
impl<Start: Size, End: Size> fmt::Debug for $UIntInRangeType<Start, End> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let Self { value, range } = self;
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ use crate::{
|
|||
source_location::SourceLocation,
|
||||
ty::{
|
||||
CanonicalType, OpaqueSimValueSlice, OpaqueSimValueWriter, OpaqueSimValueWritten,
|
||||
StaticType, Type, TypeProperties, impl_match_variant_as_self,
|
||||
SimValueDebug, StaticType, Type, TypeProperties, impl_match_variant_as_self,
|
||||
serde_impls::{SerdeCanonicalType, SerdePhantomConst},
|
||||
},
|
||||
};
|
||||
|
|
@ -327,6 +327,15 @@ impl<T: ?Sized + PhantomConstValue> Type for PhantomConst<T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: ?Sized + PhantomConstValue> SimValueDebug for PhantomConst<T> {
|
||||
fn sim_value_debug(
|
||||
value: &<Self as Type>::SimValue,
|
||||
f: &mut fmt::Formatter<'_>,
|
||||
) -> fmt::Result {
|
||||
fmt::Debug::fmt(value, f)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ?Sized + PhantomConstValue> Default for PhantomConst<T>
|
||||
where
|
||||
Interned<T>: Default,
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
// See Notices.txt for copyright information
|
||||
|
||||
use crate::{
|
||||
clock::Clock,
|
||||
expr::{CastToImpl, Expr, ValueType},
|
||||
|
|
@ -8,11 +9,13 @@ use crate::{
|
|||
source_location::SourceLocation,
|
||||
ty::{
|
||||
CanonicalType, OpaqueSimValueSize, OpaqueSimValueSlice, OpaqueSimValueWriter,
|
||||
OpaqueSimValueWritten, StaticType, Type, TypeProperties, impl_match_variant_as_self,
|
||||
OpaqueSimValueWritten, SimValueDebug, StaticType, Type, TypeProperties,
|
||||
impl_match_variant_as_self,
|
||||
},
|
||||
util::ConstUsize,
|
||||
};
|
||||
use bitvec::{bits, order::Lsb0};
|
||||
use std::fmt;
|
||||
|
||||
mod sealed {
|
||||
pub trait ResetTypeSealed {}
|
||||
|
|
@ -100,6 +103,15 @@ macro_rules! reset_type {
|
|||
}
|
||||
}
|
||||
|
||||
impl SimValueDebug for $name {
|
||||
fn sim_value_debug(
|
||||
value: &<Self as Type>::SimValue,
|
||||
f: &mut fmt::Formatter<'_>,
|
||||
) -> fmt::Result {
|
||||
fmt::Debug::fmt(value, f)
|
||||
}
|
||||
}
|
||||
|
||||
impl $name {
|
||||
pub fn type_properties(self) -> TypeProperties {
|
||||
Self::TYPE_PROPERTIES
|
||||
|
|
|
|||
|
|
@ -15,7 +15,8 @@ use crate::{
|
|||
source_location::SourceLocation,
|
||||
ty::{
|
||||
CanonicalType, OpaqueSimValue, OpaqueSimValueSize, OpaqueSimValueSlice,
|
||||
OpaqueSimValueWriter, StaticType, Type, TypeProperties, impl_match_variant_as_self,
|
||||
OpaqueSimValueWriter, SimValueDebug, StaticType, Type, TypeProperties,
|
||||
impl_match_variant_as_self,
|
||||
},
|
||||
util::{
|
||||
ConstUsize, HashMap,
|
||||
|
|
@ -1394,6 +1395,15 @@ impl Type for DynSimOnly {
|
|||
}
|
||||
}
|
||||
|
||||
impl SimValueDebug for DynSimOnly {
|
||||
fn sim_value_debug(
|
||||
value: &<Self as Type>::SimValue,
|
||||
f: &mut fmt::Formatter<'_>,
|
||||
) -> fmt::Result {
|
||||
fmt::Debug::fmt(value, f)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: SimOnlyValueTrait> Type for SimOnly<T> {
|
||||
type BaseType = DynSimOnly;
|
||||
type MaskType = Bool;
|
||||
|
|
@ -1459,6 +1469,15 @@ impl<T: SimOnlyValueTrait> Type for SimOnly<T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: SimOnlyValueTrait> SimValueDebug for SimOnly<T> {
|
||||
fn sim_value_debug(
|
||||
value: &<Self as Type>::SimValue,
|
||||
f: &mut fmt::Formatter<'_>,
|
||||
) -> fmt::Result {
|
||||
fmt::Debug::fmt(value, f)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: SimOnlyValueTrait> StaticType for SimOnly<T> {
|
||||
const TYPE: Self = Self::new();
|
||||
|
||||
|
|
|
|||
|
|
@ -367,7 +367,15 @@ impl<D: Type> TypeOrDefault<D> for crate::__ {
|
|||
}
|
||||
|
||||
pub trait Type:
|
||||
Copy + Hash + Eq + fmt::Debug + Send + Sync + 'static + FillInDefaultedGenerics<Type = Self>
|
||||
Copy
|
||||
+ Hash
|
||||
+ Eq
|
||||
+ fmt::Debug
|
||||
+ Send
|
||||
+ Sync
|
||||
+ 'static
|
||||
+ FillInDefaultedGenerics<Type = Self>
|
||||
+ SimValueDebug
|
||||
{
|
||||
type BaseType: BaseType;
|
||||
type MaskType: Type<MaskType = Self::MaskType>;
|
||||
|
|
@ -402,6 +410,16 @@ pub trait Type:
|
|||
) -> OpaqueSimValueWritten<'w>;
|
||||
}
|
||||
|
||||
pub trait SimValueDebug {
|
||||
fn sim_value_debug(value: &<Self as Type>::SimValue, f: &mut fmt::Formatter<'_>) -> fmt::Result
|
||||
where
|
||||
Self: Type;
|
||||
}
|
||||
|
||||
pub trait SimValueDisplay: Type {
|
||||
fn sim_value_display(value: &Self::SimValue, f: &mut fmt::Formatter<'_>) -> fmt::Result;
|
||||
}
|
||||
|
||||
pub trait BaseType:
|
||||
Type<
|
||||
BaseType = Self,
|
||||
|
|
@ -490,6 +508,15 @@ impl Type for CanonicalType {
|
|||
}
|
||||
}
|
||||
|
||||
impl SimValueDebug for CanonicalType {
|
||||
fn sim_value_debug(
|
||||
value: &<Self as Type>::SimValue,
|
||||
f: &mut fmt::Formatter<'_>,
|
||||
) -> fmt::Result {
|
||||
fmt::Debug::fmt(value, f)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Hash, Debug, Serialize, Deserialize, Default)]
|
||||
#[non_exhaustive]
|
||||
pub struct OpaqueSimValueSizeRange {
|
||||
|
|
|
|||
166
crates/fayalite/tests/hdl_types_fmt.rs
Normal file
166
crates/fayalite/tests/hdl_types_fmt.rs
Normal file
|
|
@ -0,0 +1,166 @@
|
|||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
// See Notices.txt for copyright information
|
||||
use fayalite::{prelude::*, ty::SimValueDebug};
|
||||
use std::fmt;
|
||||
|
||||
#[hdl(outline_generated)]
|
||||
struct MyStruct0<T, S: Size> {
|
||||
v: T,
|
||||
a: ArrayType<UInt<8>, S>,
|
||||
}
|
||||
|
||||
#[hdl]
|
||||
#[test]
|
||||
fn check_my_struct0() {
|
||||
let ty = MyStruct0[UInt[8]][3];
|
||||
assert_eq!(
|
||||
format!("{ty:?}"),
|
||||
"MyStruct0 { v: UInt<8>, a: Array<UInt<8>, 3> }",
|
||||
);
|
||||
assert_eq!(
|
||||
format!("{:?}", ty.mask_type()),
|
||||
"MaskType<MyStruct0> { v: Bool, a: Array<Bool, 3> }",
|
||||
);
|
||||
let v = #[hdl(sim)]
|
||||
MyStruct0::<_, _> {
|
||||
v: 0x23u8,
|
||||
a: [1u8, 2, 3],
|
||||
};
|
||||
assert_eq!(
|
||||
format!("{v:?}"),
|
||||
"MyStruct0 { v: 0x23_u8, a: [0x1_u8, 0x2_u8, 0x3_u8] }",
|
||||
);
|
||||
}
|
||||
|
||||
#[hdl(outline_generated, custom_debug())]
|
||||
struct MyStruct1<T, S: Size> {
|
||||
v: T,
|
||||
a: ArrayType<UInt<8>, S>,
|
||||
}
|
||||
|
||||
impl<T: Type, S: Size> fmt::Debug for MyStruct1<T, S> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let Self { v, a } = self;
|
||||
f.debug_struct("Custom<MyStruct1>")
|
||||
.field("v", v)
|
||||
.field("a", a)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Type, S: Size> SimValueDebug for MyStruct1<T, S> {
|
||||
#[hdl]
|
||||
fn sim_value_debug(
|
||||
value: &<Self as Type>::SimValue,
|
||||
f: &mut fmt::Formatter<'_>,
|
||||
) -> fmt::Result {
|
||||
#[hdl(sim)]
|
||||
let Self { v, a } = value;
|
||||
f.debug_struct("Custom<MyStruct1>")
|
||||
.field("v", &v)
|
||||
.field("a", &a)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
#[hdl]
|
||||
#[test]
|
||||
fn check_my_struct1() {
|
||||
let ty = MyStruct1[UInt[8]][3];
|
||||
assert_eq!(
|
||||
format!("{ty:?}"),
|
||||
"Custom<MyStruct1> { v: UInt<8>, a: Array<UInt<8>, 3> }",
|
||||
);
|
||||
assert_eq!(
|
||||
format!("{:?}", ty.mask_type()),
|
||||
"MaskType<MyStruct1> { v: Bool, a: Array<Bool, 3> }",
|
||||
);
|
||||
let v = #[hdl(sim)]
|
||||
MyStruct1::<_, _> {
|
||||
v: 0x23u8,
|
||||
a: [1u8, 2, 3],
|
||||
};
|
||||
assert_eq!(
|
||||
format!("{v:?}"),
|
||||
"Custom<MyStruct1> { v: 0x23_u8, a: [0x1_u8, 0x2_u8, 0x3_u8] }",
|
||||
);
|
||||
}
|
||||
|
||||
#[hdl(outline_generated)]
|
||||
enum MyEnum0<T, S: Size> {
|
||||
Unit,
|
||||
V(T),
|
||||
A(ArrayType<UInt<8>, S>),
|
||||
}
|
||||
|
||||
#[hdl]
|
||||
#[test]
|
||||
fn check_my_enum0() {
|
||||
let ty = MyEnum0[UInt[8]][3];
|
||||
assert_eq!(
|
||||
format!("{ty:?}"),
|
||||
"MyEnum0 { Unit: (), V: UInt<8>, A: Array<UInt<8>, 3> }",
|
||||
);
|
||||
let v = #[hdl(sim)]
|
||||
ty.Unit();
|
||||
assert_eq!(format!("{v:?}"), "Unit");
|
||||
let v = #[hdl(sim)]
|
||||
ty.V(0x23u8);
|
||||
assert_eq!(format!("{v:?}"), "V(0x23_u8)");
|
||||
let v = #[hdl(sim)]
|
||||
ty.A([1u8, 2, 3]);
|
||||
assert_eq!(format!("{v:?}"), "A([0x1_u8, 0x2_u8, 0x3_u8])");
|
||||
}
|
||||
|
||||
#[hdl(outline_generated, custom_debug())]
|
||||
enum MyEnum1<T, S: Size> {
|
||||
Unit,
|
||||
V(T),
|
||||
A(ArrayType<UInt<8>, S>),
|
||||
}
|
||||
|
||||
impl<T: Type, S: Size> fmt::Debug for MyEnum1<T, S> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let Self { Unit, V, A } = self;
|
||||
f.debug_struct("Custom<MyEnum1>")
|
||||
.field("Unit", Unit)
|
||||
.field("V", V)
|
||||
.field("A", A)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Type, S: Size> SimValueDebug for MyEnum1<T, S> {
|
||||
#[hdl]
|
||||
fn sim_value_debug(
|
||||
value: &<Self as Type>::SimValue,
|
||||
f: &mut fmt::Formatter<'_>,
|
||||
) -> fmt::Result {
|
||||
type SimValueT<T> = <T as Type>::SimValue;
|
||||
match value {
|
||||
SimValueT::<Self>::Unit(_) => f.write_str("MyEnum1::Unit"),
|
||||
SimValueT::<Self>::V(v, _) => f.debug_tuple("MyEnum1::V").field(v).finish(),
|
||||
SimValueT::<Self>::A(a, _) => f.debug_tuple("MyEnum1::A").field(a).finish(),
|
||||
SimValueT::<Self>::Unknown(_) => f.write_str("MyEnum1::Unknown"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[hdl]
|
||||
#[test]
|
||||
fn check_my_enum1() {
|
||||
let ty = MyEnum1[UInt[8]][3];
|
||||
assert_eq!(
|
||||
format!("{ty:?}"),
|
||||
"Custom<MyEnum1> { Unit: (), V: UInt<8>, A: Array<UInt<8>, 3> }",
|
||||
);
|
||||
let v = #[hdl(sim)]
|
||||
ty.Unit();
|
||||
assert_eq!(format!("{v:?}"), "MyEnum1::Unit");
|
||||
let v = #[hdl(sim)]
|
||||
ty.V(0x23u8);
|
||||
assert_eq!(format!("{v:?}"), "MyEnum1::V(0x23_u8)");
|
||||
let v = #[hdl(sim)]
|
||||
ty.A([1u8, 2, 3]);
|
||||
assert_eq!(format!("{v:?}"), "MyEnum1::A([0x1_u8, 0x2_u8, 0x3_u8])");
|
||||
}
|
||||
|
|
@ -75,12 +75,12 @@ note: required because it appears within the type `Vec<DynSimOnlyValue>`
|
|||
note: required because it appears within the type `OpaqueSimValue`
|
||||
--> src/ty.rs
|
||||
|
|
||||
734 | pub struct OpaqueSimValue {
|
||||
761 | pub struct OpaqueSimValue {
|
||||
| ^^^^^^^^^^^^^^
|
||||
note: required because it appears within the type `value::SimValueInner<()>`
|
||||
--> src/sim/value.rs
|
||||
|
|
||||
51 | struct SimValueInner<T: Type> {
|
||||
52 | struct SimValueInner<T: Type> {
|
||||
| ^^^^^^^^^^^^^
|
||||
note: required because it appears within the type `UnsafeCell<value::SimValueInner<()>>`
|
||||
--> $RUST/core/src/cell.rs
|
||||
|
|
@ -95,7 +95,7 @@ note: required because it appears within the type `util::alternating_cell::Alter
|
|||
note: required because it appears within the type `fayalite::prelude::SimValue<()>`
|
||||
--> src/sim/value.rs
|
||||
|
|
||||
160 | pub struct SimValue<T: Type> {
|
||||
161 | pub struct SimValue<T: Type> {
|
||||
| ^^^^^^^^
|
||||
note: required by a bound in `fayalite::intern::Interned`
|
||||
--> src/intern.rs
|
||||
|
|
@ -214,12 +214,12 @@ note: required because it appears within the type `Vec<DynSimOnlyValue>`
|
|||
note: required because it appears within the type `OpaqueSimValue`
|
||||
--> src/ty.rs
|
||||
|
|
||||
734 | pub struct OpaqueSimValue {
|
||||
761 | pub struct OpaqueSimValue {
|
||||
| ^^^^^^^^^^^^^^
|
||||
note: required because it appears within the type `value::SimValueInner<()>`
|
||||
--> src/sim/value.rs
|
||||
|
|
||||
51 | struct SimValueInner<T: Type> {
|
||||
52 | struct SimValueInner<T: Type> {
|
||||
| ^^^^^^^^^^^^^
|
||||
note: required because it appears within the type `UnsafeCell<value::SimValueInner<()>>`
|
||||
--> $RUST/core/src/cell.rs
|
||||
|
|
@ -234,7 +234,7 @@ note: required because it appears within the type `util::alternating_cell::Alter
|
|||
note: required because it appears within the type `fayalite::prelude::SimValue<()>`
|
||||
--> src/sim/value.rs
|
||||
|
|
||||
160 | pub struct SimValue<T: Type> {
|
||||
161 | pub struct SimValue<T: Type> {
|
||||
| ^^^^^^^^
|
||||
note: required by a bound in `intern_sized`
|
||||
--> src/intern.rs
|
||||
|
|
@ -326,12 +326,12 @@ note: required because it appears within the type `Vec<DynSimOnlyValue>`
|
|||
note: required because it appears within the type `OpaqueSimValue`
|
||||
--> src/ty.rs
|
||||
|
|
||||
734 | pub struct OpaqueSimValue {
|
||||
761 | pub struct OpaqueSimValue {
|
||||
| ^^^^^^^^^^^^^^
|
||||
note: required because it appears within the type `value::SimValueInner<()>`
|
||||
--> src/sim/value.rs
|
||||
|
|
||||
51 | struct SimValueInner<T: Type> {
|
||||
52 | struct SimValueInner<T: Type> {
|
||||
| ^^^^^^^^^^^^^
|
||||
note: required because it appears within the type `UnsafeCell<value::SimValueInner<()>>`
|
||||
--> $RUST/core/src/cell.rs
|
||||
|
|
@ -346,7 +346,7 @@ note: required because it appears within the type `util::alternating_cell::Alter
|
|||
note: required because it appears within the type `fayalite::prelude::SimValue<()>`
|
||||
--> src/sim/value.rs
|
||||
|
|
||||
160 | pub struct SimValue<T: Type> {
|
||||
161 | pub struct SimValue<T: Type> {
|
||||
| ^^^^^^^^
|
||||
note: required by a bound in `fayalite::intern::Interned`
|
||||
--> src/intern.rs
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue