forked from libre-chip/fayalite
		
	
		
			
				
	
	
		
			1203 lines
		
	
	
	
		
			51 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
			
		
		
	
	
			1203 lines
		
	
	
	
		
			51 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
| // SPDX-License-Identifier: LGPL-3.0-or-later
 | |
| // See Notices.txt for copyright information
 | |
| use crate::{
 | |
|     Errors, HdlAttr, PairsIterExt,
 | |
|     hdl_type_common::{
 | |
|         ItemOptions, MakeHdlTypeExpr, MaybeParsed, ParsedField, ParsedFieldsNamed, ParsedGenerics,
 | |
|         SplitForImpl, TypesParser, WrappedInConst, common_derives, get_target,
 | |
|     },
 | |
|     kw,
 | |
| };
 | |
| use proc_macro2::TokenStream;
 | |
| use quote::{ToTokens, format_ident, quote_spanned};
 | |
| use syn::{
 | |
|     AngleBracketedGenericArguments, Attribute, Field, FieldMutability, Fields, FieldsNamed,
 | |
|     GenericParam, Generics, Ident, ItemStruct, Path, Token, Type, Visibility, parse_quote,
 | |
|     parse_quote_spanned,
 | |
|     punctuated::{Pair, Punctuated},
 | |
|     spanned::Spanned,
 | |
|     token::Brace,
 | |
| };
 | |
| 
 | |
| #[derive(Clone, Debug)]
 | |
| pub(crate) struct ParsedBundle {
 | |
|     pub(crate) attrs: Vec<Attribute>,
 | |
|     pub(crate) options: HdlAttr<ItemOptions, kw::hdl>,
 | |
|     pub(crate) vis: Visibility,
 | |
|     pub(crate) struct_token: Token![struct],
 | |
|     pub(crate) ident: Ident,
 | |
|     pub(crate) generics: MaybeParsed<ParsedGenerics, Generics>,
 | |
|     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_match_variant_ident: Ident,
 | |
|     pub(crate) mask_type_sim_value_ident: Ident,
 | |
|     pub(crate) match_variant_ident: Ident,
 | |
|     pub(crate) sim_value_ident: Ident,
 | |
|     pub(crate) builder_ident: Ident,
 | |
|     pub(crate) mask_type_builder_ident: Ident,
 | |
| }
 | |
| 
 | |
| impl ParsedBundle {
 | |
|     fn parse_field(
 | |
|         errors: &mut Errors,
 | |
|         field: &mut Field,
 | |
|         index: usize,
 | |
|     ) -> Option<HdlAttr<kw::flip, kw::hdl>> {
 | |
|         let Field {
 | |
|             attrs,
 | |
|             vis: _,
 | |
|             mutability,
 | |
|             ident,
 | |
|             colon_token,
 | |
|             ty,
 | |
|         } = field;
 | |
|         let ident = ident.get_or_insert_with(|| format_ident!("_{}", index, span = ty.span()));
 | |
|         if !matches!(mutability, FieldMutability::None) {
 | |
|             // FIXME: use mutability as the spanned tokens,
 | |
|             // blocked on https://github.com/dtolnay/syn/issues/1717
 | |
|             errors.error(&ident, "field mutability is not supported");
 | |
|             *mutability = FieldMutability::None;
 | |
|         }
 | |
|         *mutability = FieldMutability::None;
 | |
|         colon_token.get_or_insert(Token));
 | |
|         errors.unwrap_or_default(HdlAttr::parse_and_take_attr(attrs))
 | |
|     }
 | |
|     fn parse(item: ItemStruct) -> syn::Result<Self> {
 | |
|         let ItemStruct {
 | |
|             mut attrs,
 | |
|             vis,
 | |
|             struct_token,
 | |
|             ident,
 | |
|             mut generics,
 | |
|             fields,
 | |
|             semi_token,
 | |
|         } = item;
 | |
|         let mut errors = Errors::new();
 | |
|         let mut options = errors
 | |
|             .unwrap_or_default(HdlAttr::<ItemOptions, kw::hdl>::parse_and_take_attr(
 | |
|                 &mut attrs,
 | |
|             ))
 | |
|             .unwrap_or_default();
 | |
|         errors.ok(options.body.validate());
 | |
|         let ItemOptions {
 | |
|             outline_generated: _,
 | |
|             target: _,
 | |
|             custom_bounds,
 | |
|             no_static: _,
 | |
|             no_runtime_generics: _,
 | |
|             cmp_eq: _,
 | |
|         } = options.body;
 | |
|         let mut fields = match fields {
 | |
|             syn::Fields::Named(fields) => fields,
 | |
|             syn::Fields::Unnamed(fields) => {
 | |
|                 errors.error(&fields, "#[hdl] struct must use curly braces: {}");
 | |
|                 FieldsNamed {
 | |
|                     brace_token: Brace(fields.paren_token.span),
 | |
|                     named: fields.unnamed,
 | |
|                 }
 | |
|             }
 | |
|             syn::Fields::Unit => {
 | |
|                 errors.error(&fields, "#[hdl] struct must use curly braces: {}");
 | |
|                 FieldsNamed {
 | |
|                     brace_token: Brace(semi_token.unwrap_or_default().span),
 | |
|                     named: Punctuated::default(),
 | |
|                 }
 | |
|             }
 | |
|         };
 | |
|         let mut field_flips = Vec::with_capacity(fields.named.len());
 | |
|         for (index, field) in fields.named.iter_mut().enumerate() {
 | |
|             field_flips.push(Self::parse_field(&mut errors, field, index));
 | |
|         }
 | |
|         let generics = if custom_bounds.is_some() {
 | |
|             MaybeParsed::Unrecognized(generics)
 | |
|         } else if let Some(generics) = errors.ok(ParsedGenerics::parse(&mut generics)) {
 | |
|             MaybeParsed::Parsed(generics)
 | |
|         } else {
 | |
|             MaybeParsed::Unrecognized(generics)
 | |
|         };
 | |
|         let fields = TypesParser::maybe_run(generics.as_ref(), fields, &mut errors);
 | |
|         errors.finish()?;
 | |
|         Ok(Self {
 | |
|             attrs,
 | |
|             options,
 | |
|             vis,
 | |
|             struct_token,
 | |
|             generics,
 | |
|             fields,
 | |
|             field_flips,
 | |
|             mask_type_ident: format_ident!("__{}__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),
 | |
|             sim_value_ident: format_ident!("__{}__SimValue", ident),
 | |
|             mask_type_builder_ident: format_ident!("__{}__MaskType__Builder", ident),
 | |
|             builder_ident: format_ident!("__{}__Builder", ident),
 | |
|             ident,
 | |
|         })
 | |
|     }
 | |
| }
 | |
| 
 | |
| #[derive(Clone, Debug)]
 | |
| struct Builder {
 | |
|     vis: Visibility,
 | |
|     struct_token: Token![struct],
 | |
|     ident: Ident,
 | |
|     target: Path,
 | |
|     generics: Generics,
 | |
|     fields: FieldsNamed,
 | |
| }
 | |
| 
 | |
| #[derive(Copy, Clone, Eq, PartialEq, Debug)]
 | |
| enum BuilderFieldState {
 | |
|     Unfilled,
 | |
|     Generic,
 | |
|     Filled,
 | |
| }
 | |
| 
 | |
| impl Builder {
 | |
|     fn phantom_field_name(&self) -> Ident {
 | |
|         format_ident!("__phantom", span = self.ident.span())
 | |
|     }
 | |
|     fn phantom_field(&self) -> Field {
 | |
|         let target = &self.target;
 | |
|         let type_generics = self.generics.split_for_impl().1;
 | |
|         Field {
 | |
|             attrs: vec![],
 | |
|             vis: Visibility::Inherited,
 | |
|             mutability: FieldMutability::None,
 | |
|             ident: Some(self.phantom_field_name()),
 | |
|             colon_token: Some(Token)),
 | |
|             ty: parse_quote_spanned! {self.ident.span()=>
 | |
|                 ::fayalite::__std::marker::PhantomData<#target #type_generics>
 | |
|             },
 | |
|         }
 | |
|     }
 | |
|     fn builder_struct_generics(
 | |
|         &self,
 | |
|         mut get_field_state: impl FnMut(usize) -> BuilderFieldState,
 | |
|     ) -> Generics {
 | |
|         let mut retval = self.generics.clone();
 | |
|         for param in retval.params.iter_mut() {
 | |
|             match param {
 | |
|                 GenericParam::Lifetime(_) => {}
 | |
|                 GenericParam::Type(param) => param.default = None,
 | |
|                 GenericParam::Const(param) => param.default = None,
 | |
|             }
 | |
|         }
 | |
|         for (field_index, field) in self.fields.named.iter().enumerate() {
 | |
|             match get_field_state(field_index) {
 | |
|                 BuilderFieldState::Unfilled | BuilderFieldState::Filled => continue,
 | |
|                 BuilderFieldState::Generic => {}
 | |
|             }
 | |
|             if !retval.params.empty_or_trailing() {
 | |
|                 retval.params.push_punct(Token));
 | |
|             }
 | |
|             retval.params.push_value(GenericParam::Type(
 | |
|                 type_var_for_field_name(field.ident.as_ref().unwrap()).into(),
 | |
|             ));
 | |
|         }
 | |
|         retval
 | |
|     }
 | |
|     fn builder_struct_ty(
 | |
|         &self,
 | |
|         mut get_field_state: impl FnMut(usize) -> BuilderFieldState,
 | |
|     ) -> Type {
 | |
|         let mut ty_arguments: AngleBracketedGenericArguments = if self.generics.params.is_empty() {
 | |
|             parse_quote_spanned! {self.ident.span()=>
 | |
|                 <>
 | |
|             }
 | |
|         } else {
 | |
|             let builder_type_generics = self.generics.split_for_impl().1;
 | |
|             parse_quote! { #builder_type_generics }
 | |
|         };
 | |
|         for (field_index, Field { ident, ty, .. }) in self.fields.named.iter().enumerate() {
 | |
|             let ident = ident.as_ref().unwrap();
 | |
|             if !ty_arguments.args.empty_or_trailing() {
 | |
|                 ty_arguments.args.push_punct(Token));
 | |
|             }
 | |
|             ty_arguments
 | |
|                 .args
 | |
|                 .push_value(match get_field_state(field_index) {
 | |
|                     BuilderFieldState::Unfilled => parse_quote_spanned! {self.ident.span()=>
 | |
|                         ::fayalite::bundle::Unfilled<#ty>
 | |
|                     },
 | |
|                     BuilderFieldState::Generic => {
 | |
|                         let type_var = type_var_for_field_name(ident);
 | |
|                         parse_quote_spanned! {self.ident.span()=>
 | |
|                             #type_var
 | |
|                         }
 | |
|                     }
 | |
|                     BuilderFieldState::Filled => parse_quote_spanned! {self.ident.span()=>
 | |
|                         ::fayalite::expr::Expr<#ty>
 | |
|                     },
 | |
|                 });
 | |
|         }
 | |
|         let ident = &self.ident;
 | |
|         parse_quote_spanned! {ident.span()=>
 | |
|             #ident #ty_arguments
 | |
|         }
 | |
|     }
 | |
| }
 | |
| 
 | |
| fn type_var_for_field_name(ident: &Ident) -> Ident {
 | |
|     format_ident!("__T_{}", ident)
 | |
| }
 | |
| 
 | |
| fn field_fn_for_field_name(ident: &Ident) -> Ident {
 | |
|     format_ident!("field_{}", ident)
 | |
| }
 | |
| 
 | |
| impl ToTokens for Builder {
 | |
|     fn to_tokens(&self, tokens: &mut TokenStream) {
 | |
|         let Self {
 | |
|             vis,
 | |
|             struct_token,
 | |
|             ident,
 | |
|             target,
 | |
|             generics: _,
 | |
|             fields,
 | |
|         } = self;
 | |
|         let phantom_field_name = self.phantom_field_name();
 | |
|         let builder_struct = ItemStruct {
 | |
|             attrs: vec![parse_quote_spanned! {ident.span()=>
 | |
|                 #[allow(non_camel_case_types, dead_code)]
 | |
|             }],
 | |
|             vis: vis.clone(),
 | |
|             struct_token: *struct_token,
 | |
|             ident: ident.clone(),
 | |
|             generics: self.builder_struct_generics(|_| BuilderFieldState::Generic),
 | |
|             fields: Fields::Named(FieldsNamed {
 | |
|                 brace_token: fields.brace_token,
 | |
|                 named: Punctuated::from_iter(
 | |
|                     [Pair::Punctuated(
 | |
|                         self.phantom_field(),
 | |
|                         Token),
 | |
|                     )]
 | |
|                     .into_iter()
 | |
|                     .chain(fields.named.pairs().map_pair_value_ref(|field| {
 | |
|                         let ident = field.ident.as_ref().unwrap();
 | |
|                         let type_var = type_var_for_field_name(ident);
 | |
|                         Field {
 | |
|                             vis: Visibility::Inherited,
 | |
|                             ty: parse_quote_spanned! {ident.span()=>
 | |
|                                 #type_var
 | |
|                             },
 | |
|                             ..field.clone()
 | |
|                         }
 | |
|                     })),
 | |
|                 ),
 | |
|             }),
 | |
|             semi_token: None,
 | |
|         };
 | |
|         builder_struct.to_tokens(tokens);
 | |
|         let field_idents = Vec::from_iter(
 | |
|             self.fields
 | |
|                 .named
 | |
|                 .iter()
 | |
|                 .map(|field| field.ident.as_ref().unwrap()),
 | |
|         );
 | |
|         for (
 | |
|             field_index,
 | |
|             Field {
 | |
|                 vis,
 | |
|                 ident: field_ident,
 | |
|                 ty,
 | |
|                 ..
 | |
|             },
 | |
|         ) in self.fields.named.iter().enumerate()
 | |
|         {
 | |
|             let field_ident = field_ident.as_ref().unwrap();
 | |
|             let fn_ident = field_fn_for_field_name(field_ident);
 | |
|             let fn_generics = self.builder_struct_generics(|i| {
 | |
|                 if i == field_index {
 | |
|                     BuilderFieldState::Unfilled
 | |
|                 } else {
 | |
|                     BuilderFieldState::Generic
 | |
|                 }
 | |
|             });
 | |
|             let (impl_generics, _, where_clause) = fn_generics.split_for_impl();
 | |
|             let unfilled_ty = self.builder_struct_ty(|i| {
 | |
|                 if i == field_index {
 | |
|                     BuilderFieldState::Unfilled
 | |
|                 } else {
 | |
|                     BuilderFieldState::Generic
 | |
|                 }
 | |
|             });
 | |
|             let filled_ty = self.builder_struct_ty(|i| {
 | |
|                 if i == field_index {
 | |
|                     BuilderFieldState::Filled
 | |
|                 } else {
 | |
|                     BuilderFieldState::Generic
 | |
|                 }
 | |
|             });
 | |
|             let pat_fields =
 | |
|                 Vec::from_iter(self.fields.named.iter().enumerate().map(|(i, field)| {
 | |
|                     let field_ident = field.ident.as_ref().unwrap();
 | |
|                     if field_index == i {
 | |
|                         quote_spanned! {self.ident.span()=>
 | |
|                             #field_ident: _,
 | |
|                         }
 | |
|                     } else {
 | |
|                         quote_spanned! {self.ident.span()=>
 | |
|                             #field_ident,
 | |
|                         }
 | |
|                     }
 | |
|                 }));
 | |
|             quote_spanned! {self.ident.span()=>
 | |
|                 #[allow(non_camel_case_types, non_snake_case, dead_code)]
 | |
|                 impl #impl_generics #unfilled_ty
 | |
|                 #where_clause
 | |
|                 {
 | |
|                     #vis fn #fn_ident(
 | |
|                         self,
 | |
|                         #field_ident: impl ::fayalite::expr::ToExpr<Type = #ty>,
 | |
|                     ) -> #filled_ty {
 | |
|                         let Self {
 | |
|                             #phantom_field_name: _,
 | |
|                             #(#pat_fields)*
 | |
|                         } = self;
 | |
|                         let #field_ident = ::fayalite::expr::ToExpr::to_expr(&#field_ident);
 | |
|                         #ident {
 | |
|                             #phantom_field_name: ::fayalite::__std::marker::PhantomData,
 | |
|                             #(#field_idents,)*
 | |
|                         }
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
|             .to_tokens(tokens);
 | |
|         }
 | |
|         let unfilled_generics = self.builder_struct_generics(|_| BuilderFieldState::Unfilled);
 | |
|         let unfilled_ty = self.builder_struct_ty(|_| BuilderFieldState::Unfilled);
 | |
|         let (unfilled_impl_generics, _, unfilled_where_clause) = unfilled_generics.split_for_impl();
 | |
|         quote_spanned! {self.ident.span()=>
 | |
|             #[automatically_derived]
 | |
|             #[allow(non_camel_case_types, dead_code)]
 | |
|             impl #unfilled_impl_generics ::fayalite::__std::default::Default for #unfilled_ty
 | |
|             #unfilled_where_clause
 | |
|             {
 | |
|                 fn default() -> Self {
 | |
|                     #ident {
 | |
|                         #phantom_field_name: ::fayalite::__std::marker::PhantomData,
 | |
|                         #(#field_idents: ::fayalite::__std::default::Default::default(),)*
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|         .to_tokens(tokens);
 | |
|         let filled_generics = self.builder_struct_generics(|_| BuilderFieldState::Filled);
 | |
|         let filled_ty = self.builder_struct_ty(|_| BuilderFieldState::Filled);
 | |
|         let (filled_impl_generics, _, filled_where_clause) = filled_generics.split_for_impl();
 | |
|         let type_generics = self.generics.split_for_impl().1;
 | |
|         quote_spanned! {self.ident.span()=>
 | |
|             #[automatically_derived]
 | |
|             #[allow(non_camel_case_types, dead_code)]
 | |
|             impl #filled_impl_generics ::fayalite::expr::ToExpr for #filled_ty
 | |
|             #filled_where_clause
 | |
|             {
 | |
|                 type Type = #target #type_generics;
 | |
|                 fn to_expr(
 | |
|                     &self,
 | |
|                 ) -> ::fayalite::expr::Expr<<Self as ::fayalite::expr::ToExpr>::Type> {
 | |
|                     let __ty = #target {
 | |
|                         #(#field_idents: ::fayalite::expr::Expr::ty(self.#field_idents),)*
 | |
|                     };
 | |
|                     let __field_values = [
 | |
|                         #(::fayalite::expr::Expr::canonical(self.#field_idents),)*
 | |
|                     ];
 | |
|                     ::fayalite::expr::ToExpr::to_expr(
 | |
|                         &::fayalite::expr::ops::BundleLiteral::new(
 | |
|                             __ty,
 | |
|                             ::fayalite::intern::Intern::intern(&__field_values[..]),
 | |
|                         ),
 | |
|                     )
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|         .to_tokens(tokens);
 | |
|     }
 | |
| }
 | |
| 
 | |
| impl ToTokens for ParsedBundle {
 | |
|     fn to_tokens(&self, tokens: &mut TokenStream) {
 | |
|         let Self {
 | |
|             attrs,
 | |
|             options,
 | |
|             vis,
 | |
|             struct_token,
 | |
|             ident,
 | |
|             generics,
 | |
|             fields,
 | |
|             field_flips,
 | |
|             mask_type_ident,
 | |
|             mask_type_match_variant_ident,
 | |
|             mask_type_sim_value_ident,
 | |
|             match_variant_ident,
 | |
|             sim_value_ident,
 | |
|             builder_ident,
 | |
|             mask_type_builder_ident,
 | |
|         } = self;
 | |
|         let span = ident.span();
 | |
|         let ItemOptions {
 | |
|             outline_generated: _,
 | |
|             target,
 | |
|             custom_bounds: _,
 | |
|             no_static,
 | |
|             no_runtime_generics,
 | |
|             cmp_eq,
 | |
|         } = &options.body;
 | |
|         let target = get_target(target, ident);
 | |
|         let mut item_attrs = attrs.clone();
 | |
|         item_attrs.push(common_derives(span));
 | |
|         ItemStruct {
 | |
|             attrs: item_attrs,
 | |
|             vis: vis.clone(),
 | |
|             struct_token: *struct_token,
 | |
|             ident: ident.clone(),
 | |
|             generics: generics.into(),
 | |
|             fields: Fields::Named(fields.clone().into()),
 | |
|             semi_token: None,
 | |
|         }
 | |
|         .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)
 | |
|         {
 | |
|             generics.make_runtime_generics(tokens, vis, ident, &target, |context| {
 | |
|                 let fields: Vec<_> = fields
 | |
|                     .named
 | |
|                     .iter()
 | |
|                     .map(|ParsedField { ident, ty, .. }| {
 | |
|                         let ident = ident.as_ref().unwrap();
 | |
|                         let expr = ty.make_hdl_type_expr(context);
 | |
|                         quote_spanned! {span=>
 | |
|                             #ident: #expr,
 | |
|                         }
 | |
|                     })
 | |
|                     .collect();
 | |
|                 parse_quote_spanned! {span=>
 | |
|                     #target {
 | |
|                         #(#fields)*
 | |
|                     }
 | |
|                 }
 | |
|             })
 | |
|         }
 | |
|         let mut wrapped_in_const = WrappedInConst::new(tokens, span);
 | |
|         let tokens = wrapped_in_const.inner();
 | |
|         let builder = Builder {
 | |
|             vis: vis.clone(),
 | |
|             struct_token: *struct_token,
 | |
|             ident: builder_ident.clone(),
 | |
|             target: target.clone(),
 | |
|             generics: generics.into(),
 | |
|             fields: fields.clone().into(),
 | |
|         };
 | |
|         builder.to_tokens(tokens);
 | |
|         let unfilled_builder_ty = builder.builder_struct_ty(|_| BuilderFieldState::Unfilled);
 | |
|         let filled_builder_ty = builder.builder_struct_ty(|_| BuilderFieldState::Filled);
 | |
|         let mut mask_type_fields = FieldsNamed::from(fields.clone());
 | |
|         for Field { ty, .. } in &mut mask_type_fields.named {
 | |
|             *ty = parse_quote_spanned! {span=>
 | |
|                 <#ty as ::fayalite::ty::Type>::MaskType
 | |
|             };
 | |
|         }
 | |
|         let mask_type_builder = Builder {
 | |
|             vis: vis.clone(),
 | |
|             struct_token: *struct_token,
 | |
|             ident: mask_type_builder_ident.clone(),
 | |
|             target: mask_type_ident.clone().into(),
 | |
|             generics: generics.into(),
 | |
|             fields: mask_type_fields.clone(),
 | |
|         };
 | |
|         mask_type_builder.to_tokens(tokens);
 | |
|         let unfilled_mask_type_builder_ty =
 | |
|             mask_type_builder.builder_struct_ty(|_| BuilderFieldState::Unfilled);
 | |
|         let filled_mask_type_builder_ty =
 | |
|             mask_type_builder.builder_struct_ty(|_| BuilderFieldState::Filled);
 | |
|         ItemStruct {
 | |
|             attrs: vec![
 | |
|                 common_derives(span),
 | |
|                 parse_quote_spanned! {span=>
 | |
|                     #[allow(non_camel_case_types, dead_code)]
 | |
|                 },
 | |
|             ],
 | |
|             vis: vis.clone(),
 | |
|             struct_token: *struct_token,
 | |
|             ident: mask_type_ident.clone(),
 | |
|             generics: generics.into(),
 | |
|             fields: Fields::Named(mask_type_fields.clone()),
 | |
|             semi_token: None,
 | |
|         }
 | |
|         .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 {
 | |
|             attrs: vec![
 | |
|                 common_derives(span),
 | |
|                 parse_quote_spanned! {span=>
 | |
|                     #[allow(non_camel_case_types, dead_code)]
 | |
|                 },
 | |
|             ],
 | |
|             vis: vis.clone(),
 | |
|             struct_token: *struct_token,
 | |
|             ident: mask_type_match_variant_ident.clone(),
 | |
|             generics: generics.into(),
 | |
|             fields: Fields::Named(mask_type_match_variant_fields),
 | |
|             semi_token: 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 {
 | |
|             attrs: vec![
 | |
|                 common_derives(span),
 | |
|                 parse_quote_spanned! {span=>
 | |
|                     #[allow(non_camel_case_types, dead_code)]
 | |
|                 },
 | |
|             ],
 | |
|             vis: vis.clone(),
 | |
|             struct_token: *struct_token,
 | |
|             ident: match_variant_ident.clone(),
 | |
|             generics: generics.into(),
 | |
|             fields: Fields::Named(match_variant_fields),
 | |
|             semi_token: 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 {
 | |
|             attrs: vec![
 | |
|                 parse_quote_spanned! {span=>
 | |
|                     #[::fayalite::__std::prelude::v1::derive(
 | |
|                         ::fayalite::__std::fmt::Debug,
 | |
|                         ::fayalite::__std::clone::Clone,
 | |
|                     )]
 | |
|                 },
 | |
|                 parse_quote_spanned! {span=>
 | |
|                     #[allow(non_camel_case_types, dead_code)]
 | |
|                 },
 | |
|             ],
 | |
|             vis: vis.clone(),
 | |
|             struct_token: *struct_token,
 | |
|             ident: mask_type_sim_value_ident.clone(),
 | |
|             generics: generics.into(),
 | |
|             fields: Fields::Named(mask_type_sim_value_fields),
 | |
|             semi_token: None,
 | |
|         }
 | |
|         .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 {
 | |
|             attrs: vec![
 | |
|                 parse_quote_spanned! {span=>
 | |
|                     #[::fayalite::__std::prelude::v1::derive(
 | |
|                         ::fayalite::__std::fmt::Debug,
 | |
|                         ::fayalite::__std::clone::Clone,
 | |
|                     )]
 | |
|                 },
 | |
|                 parse_quote_spanned! {span=>
 | |
|                     #[allow(non_camel_case_types, dead_code)]
 | |
|                 },
 | |
|             ],
 | |
|             vis: vis.clone(),
 | |
|             struct_token: *struct_token,
 | |
|             ident: sim_value_ident.clone(),
 | |
|             generics: generics.into(),
 | |
|             fields: Fields::Named(sim_value_fields),
 | |
|             semi_token: None,
 | |
|         }
 | |
|         .to_tokens(tokens);
 | |
|         let this_token = Ident::new("__this", span);
 | |
|         let fields_token = Ident::new("__fields", span);
 | |
|         let self_token = Token;
 | |
|         let match_variant_body_fields = Vec::from_iter(fields.named().into_iter().map(|field| {
 | |
|             let ident: &Ident = field.ident().as_ref().unwrap();
 | |
|             let ident_str = ident.to_string();
 | |
|             quote_spanned! {span=>
 | |
|                 #ident: ::fayalite::expr::Expr::field(#this_token, #ident_str),
 | |
|             }
 | |
|         }));
 | |
|         let mask_type_body_fields = Vec::from_iter(fields.named().into_iter().map(|field| {
 | |
|             let ident: &Ident = field.ident().as_ref().unwrap();
 | |
|             quote_spanned! {span=>
 | |
|                 #ident: ::fayalite::ty::Type::mask_type(&#self_token.#ident),
 | |
|             }
 | |
|         }));
 | |
|         let from_canonical_body_fields =
 | |
|             Vec::from_iter(fields.named().into_iter().enumerate().zip(field_flips).map(
 | |
|                 |((index, field), flip)| {
 | |
|                     let ident: &Ident = field.ident().as_ref().unwrap();
 | |
|                     let ident_str = ident.to_string();
 | |
|                     let not_flipped = flip.is_none().then(|| Token);
 | |
|                     quote_spanned! {span=>
 | |
|                         #ident: {
 | |
|                             let ::fayalite::bundle::BundleField {
 | |
|                                 name: __name,
 | |
|                                 flipped: __flipped,
 | |
|                                 ty: __ty,
 | |
|                             } = #fields_token[#index];
 | |
|                             ::fayalite::__std::assert_eq!(&*__name, #ident_str);
 | |
|                             ::fayalite::__std::assert!(#not_flipped __flipped);
 | |
|                             ::fayalite::ty::Type::from_canonical(__ty)
 | |
|                         },
 | |
|                     }
 | |
|                 },
 | |
|             ));
 | |
|         let fields_body_fields = Vec::from_iter(fields.named().into_iter().zip(field_flips).map(
 | |
|             |(field, flip)| {
 | |
|                 let ident: &Ident = field.ident().as_ref().unwrap();
 | |
|                 let ident_str = ident.to_string();
 | |
|                 let flipped = flip.is_some();
 | |
|                 quote_spanned! {span=>
 | |
|                     ::fayalite::bundle::BundleField {
 | |
|                         name: ::fayalite::intern::Intern::intern(#ident_str),
 | |
|                         flipped: #flipped,
 | |
|                         ty: ::fayalite::ty::Type::canonical(&#self_token.#ident),
 | |
|                     },
 | |
|                 }
 | |
|             },
 | |
|         ));
 | |
|         let sim_value_from_opaque_fields =
 | |
|             Vec::from_iter(fields.named().into_iter().map(|field| {
 | |
|                 let ident: &Ident = field.ident().as_ref().unwrap();
 | |
|                 quote_spanned! {span=>
 | |
|                     #ident: v.field_from_opaque(),
 | |
|                 }
 | |
|             }));
 | |
|         let sim_value_clone_from_opaque_fields =
 | |
|             Vec::from_iter(fields.named().into_iter().map(|field| {
 | |
|                 let ident: &Ident = field.ident().as_ref().unwrap();
 | |
|                 quote_spanned! {span=>
 | |
|                     v.field_clone_from_opaque(&mut value.#ident);
 | |
|                 }
 | |
|             }));
 | |
|         let sim_value_to_opaque_fields = Vec::from_iter(fields.named().into_iter().map(|field| {
 | |
|             let ident: &Ident = field.ident().as_ref().unwrap();
 | |
|             quote_spanned! {span=>
 | |
|                 v.field(&value.#ident);
 | |
|             }
 | |
|         }));
 | |
|         let to_sim_value_fields = Vec::from_iter(fields.named().into_iter().map(|field| {
 | |
|             let ident: &Ident = field.ident().as_ref().unwrap();
 | |
|             quote_spanned! {span=>
 | |
|                 #ident: ::fayalite::sim::value::SimValue::ty(&self.#ident),
 | |
|             }
 | |
|         }));
 | |
|         let fields_len = fields.named().into_iter().len();
 | |
|         quote_spanned! {span=>
 | |
|             #[automatically_derived]
 | |
|             impl #impl_generics ::fayalite::ty::Type for #mask_type_ident #type_generics
 | |
|             #where_clause
 | |
|             {
 | |
|                 type BaseType = ::fayalite::bundle::Bundle;
 | |
|                 type MaskType = #mask_type_ident #type_generics;
 | |
|                 type SimValue = #mask_type_sim_value_ident #type_generics;
 | |
|                 type MatchVariant = #mask_type_match_variant_ident #type_generics;
 | |
|                 type MatchActiveScope = ();
 | |
|                 type MatchVariantAndInactiveScope = ::fayalite::ty::MatchVariantWithoutScope<
 | |
|                     <Self as ::fayalite::ty::Type>::MatchVariant,
 | |
|                 >;
 | |
|                 type MatchVariantsIter = ::fayalite::__std::iter::Once<
 | |
|                     <Self as ::fayalite::ty::Type>::MatchVariantAndInactiveScope,
 | |
|                 >;
 | |
|                 fn match_variants(
 | |
|                     #this_token: ::fayalite::expr::Expr<Self>,
 | |
|                     __source_location: ::fayalite::source_location::SourceLocation,
 | |
|                 ) -> <Self as ::fayalite::ty::Type>::MatchVariantsIter {
 | |
|                     let __retval = #mask_type_match_variant_ident {
 | |
|                         #(#match_variant_body_fields)*
 | |
|                     };
 | |
|                     ::fayalite::__std::iter::once(::fayalite::ty::MatchVariantWithoutScope(__retval))
 | |
|                 }
 | |
|                 fn mask_type(&#self_token) -> <Self as ::fayalite::ty::Type>::MaskType {
 | |
|                     *#self_token
 | |
|                 }
 | |
|                 fn canonical(&#self_token) -> ::fayalite::ty::CanonicalType {
 | |
|                     ::fayalite::ty::Type::canonical(&::fayalite::bundle::Bundle::new(::fayalite::bundle::BundleType::fields(#self_token)))
 | |
|                 }
 | |
|                 #[track_caller]
 | |
|                 fn from_canonical(__canonical_type: ::fayalite::ty::CanonicalType) -> Self {
 | |
|                     let ::fayalite::ty::CanonicalType::Bundle(__bundle) = __canonical_type else {
 | |
|                         ::fayalite::__std::panic!("expected bundle");
 | |
|                     };
 | |
|                     let #fields_token = ::fayalite::bundle::BundleType::fields(&__bundle);
 | |
|                     ::fayalite::__std::assert_eq!(#fields_token.len(), #fields_len, "bundle has wrong number of fields");
 | |
|                     Self {
 | |
|                         #(#from_canonical_body_fields)*
 | |
|                     }
 | |
|                 }
 | |
|                 fn source_location() -> ::fayalite::source_location::SourceLocation {
 | |
|                     ::fayalite::source_location::SourceLocation::caller()
 | |
|                 }
 | |
|                 fn sim_value_from_opaque(
 | |
|                     &self,
 | |
|                     opaque: ::fayalite::ty::OpaqueSimValueSlice<'_>,
 | |
|                 ) -> <Self as ::fayalite::ty::Type>::SimValue {
 | |
|                     #![allow(unused_mut, unused_variables)]
 | |
|                     let mut v = ::fayalite::bundle::BundleSimValueFromOpaque::new(*self, opaque);
 | |
|                     #mask_type_sim_value_ident {
 | |
|                         #(#sim_value_from_opaque_fields)*
 | |
|                     }
 | |
|                 }
 | |
|                 fn sim_value_clone_from_opaque(
 | |
|                     &self,
 | |
|                     value: &mut <Self as ::fayalite::ty::Type>::SimValue,
 | |
|                     opaque: ::fayalite::ty::OpaqueSimValueSlice<'_>,
 | |
|                 ) {
 | |
|                     #![allow(unused_mut, unused_variables)]
 | |
|                     let mut v = ::fayalite::bundle::BundleSimValueFromOpaque::new(*self, opaque);
 | |
|                     #(#sim_value_clone_from_opaque_fields)*
 | |
|                 }
 | |
|                 fn sim_value_to_opaque<'__w>(
 | |
|                     &self,
 | |
|                     value: &<Self as ::fayalite::ty::Type>::SimValue,
 | |
|                     writer: ::fayalite::ty::OpaqueSimValueWriter<'__w>,
 | |
|                 ) -> ::fayalite::ty::OpaqueSimValueWritten<'__w> {
 | |
|                     #![allow(unused_mut, unused_variables)]
 | |
|                     let mut v = ::fayalite::bundle::BundleSimValueToOpaque::new(*self, writer);
 | |
|                     #(#sim_value_to_opaque_fields)*
 | |
|                     v.finish()
 | |
|                 }
 | |
|             }
 | |
|             #[automatically_derived]
 | |
|             impl #impl_generics ::fayalite::bundle::BundleType for #mask_type_ident #type_generics
 | |
|             #where_clause
 | |
|             {
 | |
|                 type Builder = #unfilled_mask_type_builder_ty;
 | |
|                 type FilledBuilder = #filled_mask_type_builder_ty;
 | |
|                 fn fields(&#self_token) -> ::fayalite::intern::Interned<[::fayalite::bundle::BundleField]> {
 | |
|                     ::fayalite::intern::Intern::intern(&[#(#fields_body_fields)*][..])
 | |
|                 }
 | |
|             }
 | |
|             impl #impl_generics #mask_type_ident #type_generics
 | |
|             #where_clause
 | |
|             {
 | |
|                 #vis fn __bundle_builder() -> #unfilled_mask_type_builder_ty {
 | |
|                     ::fayalite::__std::default::Default::default()
 | |
|                 }
 | |
|             }
 | |
|             #[automatically_derived]
 | |
|             impl #impl_generics ::fayalite::ty::TypeWithDeref for #mask_type_ident #type_generics
 | |
|             #where_clause
 | |
|             {
 | |
|                 fn expr_deref(#this_token: &::fayalite::expr::Expr<Self>) -> &<Self as ::fayalite::ty::Type>::MatchVariant {
 | |
|                     let #this_token = *#this_token;
 | |
|                     let __retval = #mask_type_match_variant_ident {
 | |
|                         #(#match_variant_body_fields)*
 | |
|                     };
 | |
|                     ::fayalite::intern::Interned::into_inner(::fayalite::intern::Intern::intern_sized(__retval))
 | |
|                 }
 | |
|             }
 | |
|             #[automatically_derived]
 | |
|             impl #impl_generics ::fayalite::sim::value::ToSimValue for #mask_type_sim_value_ident #type_generics
 | |
|             #where_clause
 | |
|             {
 | |
|                 type Type = #mask_type_ident #type_generics;
 | |
| 
 | |
|                 fn to_sim_value(
 | |
|                     &self,
 | |
|                 ) -> ::fayalite::sim::value::SimValue<
 | |
|                     <Self as ::fayalite::sim::value::ToSimValue>::Type,
 | |
|                 > {
 | |
|                     let ty = #mask_type_ident {
 | |
|                         #(#to_sim_value_fields)*
 | |
|                     };
 | |
|                     ::fayalite::sim::value::SimValue::from_value(ty, ::fayalite::__std::clone::Clone::clone(self))
 | |
|                 }
 | |
|                 fn into_sim_value(
 | |
|                     self,
 | |
|                 ) -> ::fayalite::sim::value::SimValue<
 | |
|                     <Self as ::fayalite::sim::value::ToSimValue>::Type,
 | |
|                 > {
 | |
|                     let ty = #mask_type_ident {
 | |
|                         #(#to_sim_value_fields)*
 | |
|                     };
 | |
|                     ::fayalite::sim::value::SimValue::from_value(ty, self)
 | |
|                 }
 | |
|             }
 | |
|             #[automatically_derived]
 | |
|             impl #impl_generics ::fayalite::sim::value::ToSimValueWithType<#mask_type_ident #type_generics>
 | |
|             for #mask_type_sim_value_ident #type_generics
 | |
|             #where_clause
 | |
|             {
 | |
|                 fn to_sim_value_with_type(
 | |
|                     &self,
 | |
|                     ty: #mask_type_ident #type_generics,
 | |
|                 ) -> ::fayalite::sim::value::SimValue<#mask_type_ident #type_generics> {
 | |
|                     ::fayalite::sim::value::SimValue::from_value(ty, ::fayalite::__std::clone::Clone::clone(self))
 | |
|                 }
 | |
|                 fn into_sim_value_with_type(
 | |
|                     self,
 | |
|                     ty: #mask_type_ident #type_generics,
 | |
|                 ) -> ::fayalite::sim::value::SimValue<#mask_type_ident #type_generics> {
 | |
|                     ::fayalite::sim::value::SimValue::from_value(ty, self)
 | |
|                 }
 | |
|             }
 | |
|             #[automatically_derived]
 | |
|             impl #impl_generics ::fayalite::ty::Type for #target #type_generics
 | |
|             #where_clause
 | |
|             {
 | |
|                 type BaseType = ::fayalite::bundle::Bundle;
 | |
|                 type MaskType = #mask_type_ident #type_generics;
 | |
|                 type SimValue = #sim_value_ident #type_generics;
 | |
|                 type MatchVariant = #match_variant_ident #type_generics;
 | |
|                 type MatchActiveScope = ();
 | |
|                 type MatchVariantAndInactiveScope = ::fayalite::ty::MatchVariantWithoutScope<
 | |
|                     <Self as ::fayalite::ty::Type>::MatchVariant,
 | |
|                 >;
 | |
|                 type MatchVariantsIter = ::fayalite::__std::iter::Once<
 | |
|                     <Self as ::fayalite::ty::Type>::MatchVariantAndInactiveScope,
 | |
|                 >;
 | |
|                 fn match_variants(
 | |
|                     #this_token: ::fayalite::expr::Expr<Self>,
 | |
|                     __source_location: ::fayalite::source_location::SourceLocation,
 | |
|                 ) -> <Self as ::fayalite::ty::Type>::MatchVariantsIter {
 | |
|                     let __retval = #match_variant_ident {
 | |
|                         #(#match_variant_body_fields)*
 | |
|                     };
 | |
|                     ::fayalite::__std::iter::once(::fayalite::ty::MatchVariantWithoutScope(__retval))
 | |
|                 }
 | |
|                 fn mask_type(&#self_token) -> <Self as ::fayalite::ty::Type>::MaskType {
 | |
|                     #mask_type_ident {
 | |
|                         #(#mask_type_body_fields)*
 | |
|                     }
 | |
|                 }
 | |
|                 fn canonical(&#self_token) -> ::fayalite::ty::CanonicalType {
 | |
|                     ::fayalite::ty::Type::canonical(&::fayalite::bundle::Bundle::new(::fayalite::bundle::BundleType::fields(#self_token)))
 | |
|                 }
 | |
|                 #[track_caller]
 | |
|                 fn from_canonical(__canonical_type: ::fayalite::ty::CanonicalType) -> Self {
 | |
|                     let ::fayalite::ty::CanonicalType::Bundle(__bundle) = __canonical_type else {
 | |
|                         ::fayalite::__std::panic!("expected bundle");
 | |
|                     };
 | |
|                     let #fields_token = ::fayalite::bundle::BundleType::fields(&__bundle);
 | |
|                     ::fayalite::__std::assert_eq!(#fields_token.len(), #fields_len, "bundle has wrong number of fields");
 | |
|                     Self {
 | |
|                         #(#from_canonical_body_fields)*
 | |
|                     }
 | |
|                 }
 | |
|                 fn source_location() -> ::fayalite::source_location::SourceLocation {
 | |
|                     ::fayalite::source_location::SourceLocation::caller()
 | |
|                 }
 | |
|                 fn sim_value_from_opaque(
 | |
|                     &self,
 | |
|                     opaque: ::fayalite::ty::OpaqueSimValueSlice<'_>,
 | |
|                 ) -> <Self as ::fayalite::ty::Type>::SimValue {
 | |
|                     #![allow(unused_mut, unused_variables)]
 | |
|                     let mut v = ::fayalite::bundle::BundleSimValueFromOpaque::new(*self, opaque);
 | |
|                     #sim_value_ident {
 | |
|                         #(#sim_value_from_opaque_fields)*
 | |
|                     }
 | |
|                 }
 | |
|                 fn sim_value_clone_from_opaque(
 | |
|                     &self,
 | |
|                     value: &mut <Self as ::fayalite::ty::Type>::SimValue,
 | |
|                     opaque: ::fayalite::ty::OpaqueSimValueSlice<'_>,
 | |
|                 ) {
 | |
|                     #![allow(unused_mut, unused_variables)]
 | |
|                     let mut v = ::fayalite::bundle::BundleSimValueFromOpaque::new(*self, opaque);
 | |
|                     #(#sim_value_clone_from_opaque_fields)*
 | |
|                 }
 | |
|                 fn sim_value_to_opaque<'__w>(
 | |
|                     &self,
 | |
|                     value: &<Self as ::fayalite::ty::Type>::SimValue,
 | |
|                     writer: ::fayalite::ty::OpaqueSimValueWriter<'__w>,
 | |
|                 ) -> ::fayalite::ty::OpaqueSimValueWritten<'__w> {
 | |
|                     #![allow(unused_mut, unused_variables)]
 | |
|                     let mut v = ::fayalite::bundle::BundleSimValueToOpaque::new(*self, writer);
 | |
|                     #(#sim_value_to_opaque_fields)*
 | |
|                     v.finish()
 | |
|                 }
 | |
|             }
 | |
|             #[automatically_derived]
 | |
|             impl #impl_generics ::fayalite::bundle::BundleType for #target #type_generics
 | |
|             #where_clause
 | |
|             {
 | |
|                 type Builder = #unfilled_builder_ty;
 | |
|                 type FilledBuilder = #filled_builder_ty;
 | |
|                 fn fields(&#self_token) -> ::fayalite::intern::Interned<[::fayalite::bundle::BundleField]> {
 | |
|                     ::fayalite::intern::Intern::intern(&[#(#fields_body_fields)*][..])
 | |
|                 }
 | |
|             }
 | |
|             impl #impl_generics #target #type_generics
 | |
|             #where_clause
 | |
|             {
 | |
|                 #vis fn __bundle_builder() -> #unfilled_builder_ty {
 | |
|                     ::fayalite::__std::default::Default::default()
 | |
|                 }
 | |
|             }
 | |
|             #[automatically_derived]
 | |
|             impl #impl_generics ::fayalite::ty::TypeWithDeref for #target #type_generics
 | |
|             #where_clause
 | |
|             {
 | |
|                 fn expr_deref(#this_token: &::fayalite::expr::Expr<Self>) -> &<Self as ::fayalite::ty::Type>::MatchVariant {
 | |
|                     let #this_token = *#this_token;
 | |
|                     let __retval = #match_variant_ident {
 | |
|                         #(#match_variant_body_fields)*
 | |
|                     };
 | |
|                     ::fayalite::intern::Interned::into_inner(::fayalite::intern::Intern::intern_sized(__retval))
 | |
|                 }
 | |
|             }
 | |
|             #[automatically_derived]
 | |
|             impl #impl_generics ::fayalite::sim::value::ToSimValue for #sim_value_ident #type_generics
 | |
|             #where_clause
 | |
|             {
 | |
|                 type Type = #target #type_generics;
 | |
| 
 | |
|                 fn to_sim_value(
 | |
|                     &self,
 | |
|                 ) -> ::fayalite::sim::value::SimValue<
 | |
|                     <Self as ::fayalite::sim::value::ToSimValue>::Type,
 | |
|                 > {
 | |
|                     let ty = #target {
 | |
|                         #(#to_sim_value_fields)*
 | |
|                     };
 | |
|                     ::fayalite::sim::value::SimValue::from_value(ty, ::fayalite::__std::clone::Clone::clone(self))
 | |
|                 }
 | |
|                 fn into_sim_value(
 | |
|                     self,
 | |
|                 ) -> ::fayalite::sim::value::SimValue<
 | |
|                     <Self as ::fayalite::sim::value::ToSimValue>::Type,
 | |
|                 > {
 | |
|                     let ty = #target {
 | |
|                         #(#to_sim_value_fields)*
 | |
|                     };
 | |
|                     ::fayalite::sim::value::SimValue::from_value(ty, self)
 | |
|                 }
 | |
|             }
 | |
|             #[automatically_derived]
 | |
|             impl #impl_generics ::fayalite::sim::value::ToSimValueWithType<#target #type_generics>
 | |
|             for #sim_value_ident #type_generics
 | |
|             #where_clause
 | |
|             {
 | |
|                 fn to_sim_value_with_type(
 | |
|                     &self,
 | |
|                     ty: #target #type_generics,
 | |
|                 ) -> ::fayalite::sim::value::SimValue<#target #type_generics> {
 | |
|                     ::fayalite::sim::value::SimValue::from_value(ty, ::fayalite::__std::clone::Clone::clone(self))
 | |
|                 }
 | |
|                 fn into_sim_value_with_type(
 | |
|                     self,
 | |
|                     ty: #target #type_generics,
 | |
|                 ) -> ::fayalite::sim::value::SimValue<#target #type_generics> {
 | |
|                     ::fayalite::sim::value::SimValue::from_value(ty, self)
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|         .to_tokens(tokens);
 | |
|         if let Some((cmp_eq,)) = cmp_eq {
 | |
|             let mut expr_where_clause =
 | |
|                 Generics::from(generics)
 | |
|                     .where_clause
 | |
|                     .unwrap_or_else(|| syn::WhereClause {
 | |
|                         where_token: Token,
 | |
|                         predicates: Punctuated::new(),
 | |
|                     });
 | |
|             let mut sim_value_where_clause = expr_where_clause.clone();
 | |
|             let mut fields_sim_value_eq = vec![];
 | |
|             let mut fields_cmp_eq = vec![];
 | |
|             let mut fields_cmp_ne = vec![];
 | |
|             for field in fields.named() {
 | |
|                 let field_ident = field.ident();
 | |
|                 let field_ty = field.ty();
 | |
|                 expr_where_clause
 | |
|                     .predicates
 | |
|                     .push(parse_quote_spanned! {cmp_eq.span=>
 | |
|                         #field_ty: ::fayalite::expr::ops::ExprPartialEq<#field_ty>
 | |
|                     });
 | |
|                 sim_value_where_clause
 | |
|                     .predicates
 | |
|                     .push(parse_quote_spanned! {cmp_eq.span=>
 | |
|                         #field_ty: ::fayalite::sim::value::SimValuePartialEq<#field_ty>
 | |
|                     });
 | |
|                 fields_sim_value_eq.push(quote_spanned! {span=>
 | |
|                     ::fayalite::sim::value::SimValuePartialEq::sim_value_eq(&__lhs.#field_ident, &__rhs.#field_ident)
 | |
|                 });
 | |
|                 fields_cmp_eq.push(quote_spanned! {span=>
 | |
|                     ::fayalite::expr::ops::ExprPartialEq::cmp_eq(__lhs.#field_ident, __rhs.#field_ident)
 | |
|                 });
 | |
|                 fields_cmp_ne.push(quote_spanned! {span=>
 | |
|                     ::fayalite::expr::ops::ExprPartialEq::cmp_ne(__lhs.#field_ident, __rhs.#field_ident)
 | |
|                 });
 | |
|             }
 | |
|             let sim_value_eq_body;
 | |
|             let cmp_eq_body;
 | |
|             let cmp_ne_body;
 | |
|             if fields_len == 0 {
 | |
|                 sim_value_eq_body = quote_spanned! {span=>
 | |
|                     true
 | |
|                 };
 | |
|                 cmp_eq_body = quote_spanned! {span=>
 | |
|                     ::fayalite::expr::ToExpr::to_expr(&true)
 | |
|                 };
 | |
|                 cmp_ne_body = quote_spanned! {span=>
 | |
|                     ::fayalite::expr::ToExpr::to_expr(&false)
 | |
|                 };
 | |
|             } else {
 | |
|                 sim_value_eq_body = quote_spanned! {span=>
 | |
|                     #(#fields_sim_value_eq)&&*
 | |
|                 };
 | |
|                 cmp_eq_body = quote_spanned! {span=>
 | |
|                     #(#fields_cmp_eq)&*
 | |
|                 };
 | |
|                 cmp_ne_body = quote_spanned! {span=>
 | |
|                     #(#fields_cmp_ne)|*
 | |
|                 };
 | |
|             };
 | |
|             quote_spanned! {span=>
 | |
|                 #[automatically_derived]
 | |
|                 impl #impl_generics ::fayalite::expr::ops::ExprPartialEq<Self> for #target #type_generics
 | |
|                 #expr_where_clause
 | |
|                 {
 | |
|                     fn cmp_eq(
 | |
|                         __lhs: ::fayalite::expr::Expr<Self>,
 | |
|                         __rhs: ::fayalite::expr::Expr<Self>,
 | |
|                     ) -> ::fayalite::expr::Expr<::fayalite::int::Bool> {
 | |
|                         #cmp_eq_body
 | |
|                     }
 | |
|                     fn cmp_ne(
 | |
|                         __lhs: ::fayalite::expr::Expr<Self>,
 | |
|                         __rhs: ::fayalite::expr::Expr<Self>,
 | |
|                     ) -> ::fayalite::expr::Expr<::fayalite::int::Bool> {
 | |
|                         #cmp_ne_body
 | |
|                     }
 | |
|                 }
 | |
|                 #[automatically_derived]
 | |
|                 impl #impl_generics ::fayalite::sim::value::SimValuePartialEq<Self> for #target #type_generics
 | |
|                 #sim_value_where_clause
 | |
|                 {
 | |
|                     fn sim_value_eq(
 | |
|                         __lhs: &::fayalite::sim::value::SimValue<Self>,
 | |
|                         __rhs: &::fayalite::sim::value::SimValue<Self>,
 | |
|                     ) -> bool {
 | |
|                         #sim_value_eq_body
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
|             .to_tokens(tokens);
 | |
|         }
 | |
|         if let (None, MaybeParsed::Parsed(generics)) = (no_static, &self.generics) {
 | |
|             let static_generics = generics.clone().for_static_type();
 | |
|             let (static_impl_generics, static_type_generics, static_where_clause) =
 | |
|                 static_generics.split_for_impl();
 | |
|             let static_type_body_fields = Vec::from_iter(fields.named().into_iter().map(|field| {
 | |
|                 let ident: &Ident = field.ident().as_ref().unwrap();
 | |
|                 let ty = field.ty();
 | |
|                 quote_spanned! {span=>
 | |
|                     #ident: <#ty as ::fayalite::ty::StaticType>::TYPE,
 | |
|                 }
 | |
|             }));
 | |
|             let static_mask_type_body_fields =
 | |
|                 Vec::from_iter(fields.named().into_iter().map(|field| {
 | |
|                     let ident: &Ident = field.ident().as_ref().unwrap();
 | |
|                     let ty = field.ty();
 | |
|                     quote_spanned! {span=>
 | |
|                         #ident: <#ty as ::fayalite::ty::StaticType>::MASK_TYPE,
 | |
|                     }
 | |
|                 }));
 | |
|             let type_properties = format_ident!("__type_properties", span = span);
 | |
|             let type_properties_fields = Vec::from_iter(fields.named().into_iter().zip(field_flips).map(|(field, field_flip)| {
 | |
|                 let flipped = field_flip.is_some();
 | |
|                 let ty = field.ty();
 | |
|                 quote_spanned! {span=>
 | |
|                     let #type_properties = #type_properties.field(#flipped, <#ty as ::fayalite::ty::StaticType>::TYPE_PROPERTIES);
 | |
|                 }
 | |
|             }));
 | |
|             let type_properties_mask_fields = Vec::from_iter(fields.named().into_iter().zip(field_flips).map(|(field, field_flip)| {
 | |
|                 let flipped = field_flip.is_some();
 | |
|                 let ty = field.ty();
 | |
|                 quote_spanned! {span=>
 | |
|                     let #type_properties = #type_properties.field(#flipped, <#ty as ::fayalite::ty::StaticType>::MASK_TYPE_PROPERTIES);
 | |
|                 }
 | |
|             }));
 | |
|             quote_spanned! {span=>
 | |
|                 #[automatically_derived]
 | |
|                 impl #static_impl_generics ::fayalite::__std::default::Default for #mask_type_ident #static_type_generics
 | |
|                 #static_where_clause
 | |
|                 {
 | |
|                     fn default() -> Self {
 | |
|                         <Self as ::fayalite::ty::StaticType>::TYPE
 | |
|                     }
 | |
|                 }
 | |
|                 #[automatically_derived]
 | |
|                 impl #static_impl_generics ::fayalite::ty::StaticType for #mask_type_ident #static_type_generics
 | |
|                 #static_where_clause
 | |
|                 {
 | |
|                     const TYPE: Self = Self {
 | |
|                         #(#static_mask_type_body_fields)*
 | |
|                     };
 | |
|                     const MASK_TYPE: <Self as ::fayalite::ty::Type>::MaskType = Self {
 | |
|                         #(#static_mask_type_body_fields)*
 | |
|                     };
 | |
|                     const TYPE_PROPERTIES: ::fayalite::ty::TypeProperties = {
 | |
|                         let #type_properties = ::fayalite::bundle::BundleTypePropertiesBuilder::new();
 | |
|                         #(#type_properties_mask_fields)*
 | |
|                         #type_properties.finish()
 | |
|                     };
 | |
|                     const MASK_TYPE_PROPERTIES: ::fayalite::ty::TypeProperties = {
 | |
|                         let #type_properties = ::fayalite::bundle::BundleTypePropertiesBuilder::new();
 | |
|                         #(#type_properties_mask_fields)*
 | |
|                         #type_properties.finish()
 | |
|                     };
 | |
|                 }
 | |
|                 #[automatically_derived]
 | |
|                 impl #static_impl_generics ::fayalite::__std::default::Default
 | |
|                 for #target #static_type_generics
 | |
|                 #static_where_clause
 | |
|                 {
 | |
|                     fn default() -> Self {
 | |
|                         <Self as ::fayalite::ty::StaticType>::TYPE
 | |
|                     }
 | |
|                 }
 | |
|                 #[automatically_derived]
 | |
|                 impl #static_impl_generics ::fayalite::ty::StaticType for #target #static_type_generics
 | |
|                 #static_where_clause
 | |
|                 {
 | |
|                     const TYPE: Self = Self {
 | |
|                         #(#static_type_body_fields)*
 | |
|                     };
 | |
|                     const MASK_TYPE: <Self as ::fayalite::ty::Type>::MaskType = #mask_type_ident {
 | |
|                         #(#static_mask_type_body_fields)*
 | |
|                     };
 | |
|                     const TYPE_PROPERTIES: ::fayalite::ty::TypeProperties = {
 | |
|                         let #type_properties = ::fayalite::bundle::BundleTypePropertiesBuilder::new();
 | |
|                         #(#type_properties_fields)*
 | |
|                         #type_properties.finish()
 | |
|                     };
 | |
|                     const MASK_TYPE_PROPERTIES: ::fayalite::ty::TypeProperties = {
 | |
|                         let #type_properties = ::fayalite::bundle::BundleTypePropertiesBuilder::new();
 | |
|                         #(#type_properties_mask_fields)*
 | |
|                         #type_properties.finish()
 | |
|                     };
 | |
|                 }
 | |
|             }
 | |
|             .to_tokens(tokens);
 | |
|         }
 | |
|     }
 | |
| }
 | |
| 
 | |
| pub(crate) fn hdl_bundle(item: ItemStruct) -> syn::Result<TokenStream> {
 | |
|     let item = ParsedBundle::parse(item)?;
 | |
|     let outline_generated = item.options.body.outline_generated;
 | |
|     let mut contents = item.to_token_stream();
 | |
|     if outline_generated.is_some() {
 | |
|         contents = crate::outline_generated(contents, "hdl-bundle-");
 | |
|     }
 | |
|     Ok(contents)
 | |
| }
 |