forked from libre-chip/fayalite
fix #[hdl] to work with unusual identifier hygiene from macros
This commit is contained in:
parent
15a28aa7a7
commit
343805f80b
5 changed files with 202 additions and 112 deletions
|
@ -204,6 +204,7 @@ impl ToTokens for ParsedEnum {
|
|||
variants,
|
||||
match_variant_ident,
|
||||
} = self;
|
||||
let span = ident.span();
|
||||
let ItemOptions {
|
||||
outline_generated: _,
|
||||
target,
|
||||
|
@ -213,8 +214,8 @@ impl ToTokens for ParsedEnum {
|
|||
} = &options.body;
|
||||
let target = get_target(target, ident);
|
||||
let mut struct_attrs = attrs.clone();
|
||||
struct_attrs.push(common_derives(ident.span()));
|
||||
struct_attrs.push(parse_quote_spanned! {ident.span()=>
|
||||
struct_attrs.push(common_derives(span));
|
||||
struct_attrs.push(parse_quote_spanned! {span=>
|
||||
#[allow(non_snake_case)]
|
||||
});
|
||||
let struct_fields = Punctuated::from_iter(variants.pairs().map_pair_value_ref(
|
||||
|
@ -238,8 +239,8 @@ impl ToTokens for ParsedEnum {
|
|||
colon_token = Token);
|
||||
ty.clone().into()
|
||||
} else {
|
||||
colon_token = Token);
|
||||
parse_quote_spanned! {ident.span()=>
|
||||
colon_token = Token;
|
||||
parse_quote_spanned! {span=>
|
||||
()
|
||||
}
|
||||
};
|
||||
|
@ -282,30 +283,30 @@ impl ToTokens for ParsedEnum {
|
|||
}) = field
|
||||
{
|
||||
let expr = ty.make_hdl_type_expr(context);
|
||||
quote_spanned! {ident.span()=>
|
||||
quote_spanned! {span=>
|
||||
#ident: #expr,
|
||||
}
|
||||
} else {
|
||||
quote_spanned! {ident.span()=>
|
||||
quote_spanned! {span=>
|
||||
#ident: (),
|
||||
}
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
parse_quote_spanned! {ident.span()=>
|
||||
parse_quote_spanned! {span=>
|
||||
#target {
|
||||
#(#fields)*
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
let mut wrapped_in_const = WrappedInConst::new(tokens, ident.span());
|
||||
let mut wrapped_in_const = WrappedInConst::new(tokens, span);
|
||||
let tokens = wrapped_in_const.inner();
|
||||
{
|
||||
let mut wrapped_in_const = WrappedInConst::new(tokens, ident.span());
|
||||
let mut wrapped_in_const = WrappedInConst::new(tokens, span);
|
||||
let tokens = wrapped_in_const.inner();
|
||||
let mut enum_attrs = attrs.clone();
|
||||
enum_attrs.push(parse_quote_spanned! {ident.span()=>
|
||||
enum_attrs.push(parse_quote_spanned! {span=>
|
||||
#[allow(dead_code)]
|
||||
});
|
||||
ItemEnum {
|
||||
|
@ -354,7 +355,7 @@ impl ToTokens for ParsedEnum {
|
|||
.to_tokens(tokens);
|
||||
}
|
||||
let mut enum_attrs = attrs.clone();
|
||||
enum_attrs.push(parse_quote_spanned! {ident.span()=>
|
||||
enum_attrs.push(parse_quote_spanned! {span=>
|
||||
#[allow(dead_code, non_camel_case_types)]
|
||||
});
|
||||
ItemEnum {
|
||||
|
@ -389,7 +390,7 @@ impl ToTokens for ParsedEnum {
|
|||
mutability: FieldMutability::None,
|
||||
ident: None,
|
||||
colon_token: None,
|
||||
ty: parse_quote_spanned! {ident.span()=>
|
||||
ty: parse_quote_spanned! {span=>
|
||||
::fayalite::expr::Expr<#ty>
|
||||
},
|
||||
},
|
||||
|
@ -403,21 +404,22 @@ impl ToTokens for ParsedEnum {
|
|||
)),
|
||||
}
|
||||
.to_tokens(tokens);
|
||||
let self_token = Token;
|
||||
for (index, ParsedVariant { ident, field, .. }) in variants.iter().enumerate() {
|
||||
if let Some(ParsedVariantField { ty, .. }) = field {
|
||||
quote_spanned! {ident.span()=>
|
||||
quote_spanned! {span=>
|
||||
#[automatically_derived]
|
||||
impl #impl_generics #target #type_generics
|
||||
#where_clause
|
||||
{
|
||||
#[allow(non_snake_case, dead_code)]
|
||||
#vis fn #ident<__V: ::fayalite::expr::ToExpr<Type = #ty>>(
|
||||
self,
|
||||
#self_token,
|
||||
v: __V,
|
||||
) -> ::fayalite::expr::Expr<Self> {
|
||||
::fayalite::expr::ToExpr::to_expr(
|
||||
&::fayalite::expr::ops::EnumLiteral::new_by_index(
|
||||
self,
|
||||
#self_token,
|
||||
#index,
|
||||
::fayalite::__std::option::Option::Some(
|
||||
::fayalite::expr::Expr::canonical(
|
||||
|
@ -430,16 +432,16 @@ impl ToTokens for ParsedEnum {
|
|||
}
|
||||
}
|
||||
} else {
|
||||
quote_spanned! {ident.span()=>
|
||||
quote_spanned! {span=>
|
||||
#[automatically_derived]
|
||||
impl #impl_generics #target #type_generics
|
||||
#where_clause
|
||||
{
|
||||
#[allow(non_snake_case, dead_code)]
|
||||
#vis fn #ident(self) -> ::fayalite::expr::Expr<Self> {
|
||||
#vis fn #ident(#self_token) -> ::fayalite::expr::Expr<Self> {
|
||||
::fayalite::expr::ToExpr::to_expr(
|
||||
&::fayalite::expr::ops::EnumLiteral::new_by_index(
|
||||
self,
|
||||
#self_token,
|
||||
#index,
|
||||
::fayalite::__std::option::Option::None,
|
||||
),
|
||||
|
@ -450,46 +452,48 @@ impl ToTokens for ParsedEnum {
|
|||
}
|
||||
.to_tokens(tokens);
|
||||
}
|
||||
let variants_token = Ident::new("variants", span);
|
||||
let from_canonical_body_fields = Vec::from_iter(variants.iter().enumerate().map(
|
||||
|(index, ParsedVariant { ident, field, .. })| {
|
||||
let ident_str = ident.to_string();
|
||||
let val = if field.is_some() {
|
||||
let missing_value_msg = format!("expected variant {ident} to have a field");
|
||||
quote_spanned! {ident.span()=>
|
||||
quote_spanned! {span=>
|
||||
::fayalite::ty::Type::from_canonical(ty.expect(#missing_value_msg))
|
||||
}
|
||||
} else {
|
||||
quote_spanned! {ident.span()=>
|
||||
quote_spanned! {span=>
|
||||
::fayalite::__std::assert!(ty.is_none());
|
||||
}
|
||||
};
|
||||
quote_spanned! {ident.span()=>
|
||||
quote_spanned! {span=>
|
||||
#ident: {
|
||||
let ::fayalite::enum_::EnumVariant {
|
||||
name,
|
||||
ty,
|
||||
} = variants[#index];
|
||||
} = #variants_token[#index];
|
||||
::fayalite::__std::assert_eq!(&*name, #ident_str);
|
||||
#val
|
||||
},
|
||||
}
|
||||
},
|
||||
));
|
||||
let variant_access_token = Ident::new("variant_access", span);
|
||||
let match_active_scope_match_arms = Vec::from_iter(variants.iter().enumerate().map(
|
||||
|(index, ParsedVariant { ident, field, .. })| {
|
||||
if field.is_some() {
|
||||
quote_spanned! {ident.span()=>
|
||||
quote_spanned! {span=>
|
||||
#index => #match_variant_ident::#ident(
|
||||
::fayalite::expr::ToExpr::to_expr(
|
||||
&::fayalite::expr::ops::VariantAccess::new_by_index(
|
||||
variant_access.base(),
|
||||
variant_access.variant_index(),
|
||||
#variant_access_token.base(),
|
||||
#variant_access_token.variant_index(),
|
||||
),
|
||||
),
|
||||
),
|
||||
}
|
||||
} else {
|
||||
quote_spanned! {ident.span()=>
|
||||
quote_spanned! {span=>
|
||||
#index => #match_variant_ident::#ident,
|
||||
}
|
||||
}
|
||||
|
@ -507,16 +511,16 @@ impl ToTokens for ParsedEnum {
|
|||
match field {
|
||||
Some(ParsedVariantField { options, .. }) => {
|
||||
let FieldOptions {} = options.body;
|
||||
quote_spanned! {ident.span()=>
|
||||
quote_spanned! {span=>
|
||||
::fayalite::enum_::EnumVariant {
|
||||
name: ::fayalite::intern::Intern::intern(#ident_str),
|
||||
ty: ::fayalite::__std::option::Option::Some(
|
||||
::fayalite::ty::Type::canonical(&self.#ident),
|
||||
::fayalite::ty::Type::canonical(&#self_token.#ident),
|
||||
),
|
||||
},
|
||||
}
|
||||
}
|
||||
None => quote_spanned! {ident.span()=>
|
||||
None => quote_spanned! {span=>
|
||||
::fayalite::enum_::EnumVariant {
|
||||
name: ::fayalite::intern::Intern::intern(#ident_str),
|
||||
ty: ::fayalite::__std::option::Option::None,
|
||||
|
@ -526,7 +530,7 @@ impl ToTokens for ParsedEnum {
|
|||
},
|
||||
));
|
||||
let variants_len = variants.len();
|
||||
quote_spanned! {ident.span()=>
|
||||
quote_spanned! {span=>
|
||||
#[automatically_derived]
|
||||
impl #impl_generics ::fayalite::ty::Type for #target #type_generics
|
||||
#where_clause
|
||||
|
@ -544,11 +548,11 @@ impl ToTokens for ParsedEnum {
|
|||
) -> <Self as ::fayalite::ty::Type>::MatchVariantsIter {
|
||||
::fayalite::module::enum_match_variants_helper(this, source_location)
|
||||
}
|
||||
fn mask_type(&self) -> <Self as ::fayalite::ty::Type>::MaskType {
|
||||
fn mask_type(&#self_token) -> <Self as ::fayalite::ty::Type>::MaskType {
|
||||
::fayalite::int::Bool
|
||||
}
|
||||
fn canonical(&self) -> ::fayalite::ty::CanonicalType {
|
||||
::fayalite::ty::CanonicalType::Enum(::fayalite::enum_::Enum::new(::fayalite::enum_::EnumType::variants(self)))
|
||||
fn canonical(&#self_token) -> ::fayalite::ty::CanonicalType {
|
||||
::fayalite::ty::CanonicalType::Enum(::fayalite::enum_::Enum::new(::fayalite::enum_::EnumType::variants(#self_token)))
|
||||
}
|
||||
#[track_caller]
|
||||
#[allow(non_snake_case)]
|
||||
|
@ -556,8 +560,8 @@ impl ToTokens for ParsedEnum {
|
|||
let ::fayalite::ty::CanonicalType::Enum(enum_) = canonical_type else {
|
||||
::fayalite::__std::panic!("expected enum");
|
||||
};
|
||||
let variants = ::fayalite::enum_::EnumType::variants(&enum_);
|
||||
::fayalite::__std::assert_eq!(variants.len(), #variants_len, "enum has wrong number of variants");
|
||||
let #variants_token = ::fayalite::enum_::EnumType::variants(&enum_);
|
||||
::fayalite::__std::assert_eq!(#variants_token.len(), #variants_len, "enum has wrong number of variants");
|
||||
Self {
|
||||
#(#from_canonical_body_fields)*
|
||||
}
|
||||
|
@ -573,16 +577,16 @@ impl ToTokens for ParsedEnum {
|
|||
fn match_activate_scope(
|
||||
v: <Self as ::fayalite::ty::Type>::MatchVariantAndInactiveScope,
|
||||
) -> (<Self as ::fayalite::ty::Type>::MatchVariant, <Self as ::fayalite::ty::Type>::MatchActiveScope) {
|
||||
let (variant_access, scope) = v.activate();
|
||||
let (#variant_access_token, scope) = v.activate();
|
||||
(
|
||||
match variant_access.variant_index() {
|
||||
match #variant_access_token.variant_index() {
|
||||
#(#match_active_scope_match_arms)*
|
||||
#variants_len.. => ::fayalite::__std::panic!("invalid variant index"),
|
||||
},
|
||||
scope,
|
||||
)
|
||||
}
|
||||
fn variants(&self) -> ::fayalite::intern::Interned<[::fayalite::enum_::EnumVariant]> {
|
||||
fn variants(&#self_token) -> ::fayalite::intern::Interned<[::fayalite::enum_::EnumVariant]> {
|
||||
::fayalite::intern::Intern::intern(&[
|
||||
#(#variants_body_variants)*
|
||||
][..])
|
||||
|
@ -597,34 +601,34 @@ impl ToTokens for ParsedEnum {
|
|||
let static_type_body_variants =
|
||||
Vec::from_iter(variants.iter().map(|ParsedVariant { ident, field, .. }| {
|
||||
if let Some(_) = field {
|
||||
quote_spanned! {ident.span()=>
|
||||
quote_spanned! {span=>
|
||||
#ident: ::fayalite::ty::StaticType::TYPE,
|
||||
}
|
||||
} else {
|
||||
quote_spanned! {ident.span()=>
|
||||
quote_spanned! {span=>
|
||||
#ident: (),
|
||||
}
|
||||
}
|
||||
}));
|
||||
let type_properties = format_ident!("__type_properties", span = ident.span());
|
||||
let type_properties = format_ident!("__type_properties", span = span);
|
||||
let type_properties_variants =
|
||||
Vec::from_iter(variants.iter().map(|ParsedVariant { ident, field, .. }| {
|
||||
Vec::from_iter(variants.iter().map(|ParsedVariant { field, .. }| {
|
||||
let variant = if let Some(ParsedVariantField { ty, .. }) = field {
|
||||
quote_spanned! {ident.span()=>
|
||||
quote_spanned! {span=>
|
||||
::fayalite::__std::option::Option::Some(
|
||||
<#ty as ::fayalite::ty::StaticType>::TYPE_PROPERTIES,
|
||||
)
|
||||
}
|
||||
} else {
|
||||
quote_spanned! {ident.span()=>
|
||||
quote_spanned! {span=>
|
||||
::fayalite::__std::option::Option::None
|
||||
}
|
||||
};
|
||||
quote_spanned! {ident.span()=>
|
||||
quote_spanned! {span=>
|
||||
let #type_properties = #type_properties.variant(#variant);
|
||||
}
|
||||
}));
|
||||
quote_spanned! {ident.span()=>
|
||||
quote_spanned! {span=>
|
||||
#[automatically_derived]
|
||||
impl #static_impl_generics ::fayalite::ty::StaticType
|
||||
for #target #static_type_generics
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue