This commit is contained in:
		
							parent
							
								
									76ea7f82c3
								
							
						
					
					
						commit
						2c1afd1cd6
					
				
					 3 changed files with 355 additions and 86 deletions
				
			
		|  | @ -11,8 +11,8 @@ use syn::{ | |||
|     AngleBracketedGenericArguments, Attribute, ConstParam, Expr, ExprIndex, ExprPath, ExprTuple, | ||||
|     Field, FieldMutability, Fields, FieldsNamed, FieldsUnnamed, GenericArgument, GenericParam, | ||||
|     Generics, Ident, ImplGenerics, Index, ItemStruct, Path, PathArguments, PathSegment, | ||||
|     PredicateType, Token, Turbofish, Type, TypeGenerics, TypeGroup, TypeParam, TypeParen, TypePath, | ||||
|     TypeTuple, Visibility, WhereClause, WherePredicate, | ||||
|     PredicateType, QSelf, Token, Turbofish, Type, TypeGenerics, TypeGroup, TypeParam, TypeParen, | ||||
|     TypePath, TypeTuple, Visibility, WhereClause, WherePredicate, | ||||
| }; | ||||
| 
 | ||||
| crate::options! { | ||||
|  | @ -1236,7 +1236,6 @@ impl ParseTypes<Path> for ParsedType { | |||
|                             parser | ||||
|                                 .errors | ||||
|                                 .error(ident, "constant provided when a type was expected"); | ||||
|                             todo!(); | ||||
|                             return Err(ParseFailed); | ||||
|                         } | ||||
|                     }, | ||||
|  | @ -1524,6 +1523,7 @@ pub(crate) enum UnparsedGenericParam { | |||
|         ident: Ident, | ||||
|         colon_token: Token![:], | ||||
|         bounds: ParsedBounds, | ||||
|         mask_type_bounds: ParsedTypeBounds, | ||||
|     }, | ||||
|     Const { | ||||
|         attrs: Vec<Attribute>, | ||||
|  | @ -1532,6 +1532,7 @@ pub(crate) enum UnparsedGenericParam { | |||
|         ident: Ident, | ||||
|         colon_token: Token![:], | ||||
|         ty: ParsedConstGenericType, | ||||
|         bounds: Option<ParsedConstParamWhereBounds>, | ||||
|     }, | ||||
| } | ||||
| 
 | ||||
|  | @ -1595,6 +1596,20 @@ pub(crate) mod known_items { | |||
|                         Err(path) | ||||
|                     } | ||||
|                 } | ||||
|                 #[allow(dead_code)] | ||||
|                 pub(crate) fn parse_path_with_arguments(mut path: Path) -> Result<(Self, PathArguments), Path> { | ||||
|                     let Some(last_segment) = path.segments.last_mut() else { | ||||
|                         return Err(path); | ||||
|                     }; | ||||
|                     let arguments = std::mem::replace(&mut last_segment.arguments, PathArguments::None); | ||||
|                     match Self::parse_path(path) { | ||||
|                         Ok(retval) => Ok((retval, arguments)), | ||||
|                         Err(mut path) => { | ||||
|                             path.segments.last_mut().unwrap().arguments = arguments; | ||||
|                             Err(path) | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             impl Parse for $known_item { | ||||
|  | @ -1664,6 +1679,7 @@ pub(crate) mod known_items { | |||
|     impl_known_item!(::fayalite::ty::CanonicalType); | ||||
|     impl_known_item!(::fayalite::ty::StaticType); | ||||
|     impl_known_item!(::fayalite::ty::Type); | ||||
|     impl_known_item!(::fayalite::ty::Type::MaskType); | ||||
|     impl_known_item!(::fayalite::util::ConstUsize); | ||||
|     impl_known_item!(::fayalite::__std::primitive::usize); | ||||
| } | ||||
|  | @ -1822,6 +1838,19 @@ macro_rules! impl_bounds { | |||
|                 Ok(retval) | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         impl $struct_type { | ||||
|             #[allow(dead_code)] | ||||
|             $vis fn add_implied_bounds(&mut self) { | ||||
|                 let orig_bounds = self.clone(); | ||||
|                 self.extend( | ||||
|                     self.clone() | ||||
|                         .into_iter() | ||||
|                         .map($enum_type::implied_bounds), | ||||
|                 ); | ||||
|                 self.extend([orig_bounds]); // keep spans of explicitly provided bounds
 | ||||
|             } | ||||
|         } | ||||
|     }; | ||||
| } | ||||
| 
 | ||||
|  | @ -1849,6 +1878,64 @@ impl_bounds! { | |||
|     } | ||||
| } | ||||
| 
 | ||||
| impl From<ParsedTypeBound> for ParsedBound { | ||||
|     fn from(value: ParsedTypeBound) -> Self { | ||||
|         match value { | ||||
|             ParsedTypeBound::BundleType(v) => ParsedBound::BundleType(v), | ||||
|             ParsedTypeBound::EnumType(v) => ParsedBound::EnumType(v), | ||||
|             ParsedTypeBound::IntType(v) => ParsedBound::IntType(v), | ||||
|             ParsedTypeBound::StaticType(v) => ParsedBound::StaticType(v), | ||||
|             ParsedTypeBound::Type(v) => ParsedBound::Type(v), | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl From<ParsedTypeBounds> for ParsedBounds { | ||||
|     fn from(value: ParsedTypeBounds) -> Self { | ||||
|         let ParsedTypeBounds { | ||||
|             BundleType, | ||||
|             EnumType, | ||||
|             IntType, | ||||
|             StaticType, | ||||
|             Type, | ||||
|         } = value; | ||||
|         Self { | ||||
|             BundleType, | ||||
|             EnumType, | ||||
|             IntType, | ||||
|             KnownSize: None, | ||||
|             Size: None, | ||||
|             StaticType, | ||||
|             Type, | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl ParsedTypeBound { | ||||
|     fn implied_bounds(self) -> ParsedTypeBounds { | ||||
|         let span = self.span(); | ||||
|         match self { | ||||
|             Self::BundleType(v) => ParsedTypeBounds::from_iter([ | ||||
|                 ParsedTypeBound::from(v), | ||||
|                 ParsedTypeBound::Type(known_items::Type(span)), | ||||
|             ]), | ||||
|             Self::EnumType(v) => ParsedTypeBounds::from_iter([ | ||||
|                 ParsedTypeBound::from(v), | ||||
|                 ParsedTypeBound::Type(known_items::Type(span)), | ||||
|             ]), | ||||
|             Self::IntType(v) => ParsedTypeBounds::from_iter([ | ||||
|                 ParsedTypeBound::from(v), | ||||
|                 ParsedTypeBound::Type(known_items::Type(span)), | ||||
|             ]), | ||||
|             Self::StaticType(v) => ParsedTypeBounds::from_iter([ | ||||
|                 ParsedTypeBound::from(v), | ||||
|                 ParsedTypeBound::Type(known_items::Type(span)), | ||||
|             ]), | ||||
|             Self::Type(v) => ParsedTypeBounds::from_iter([ParsedTypeBound::from(v)]), | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl_bounds! { | ||||
|     #[struct = ParsedSizeTypeBounds] | ||||
|     pub(crate) enum ParsedSizeTypeBound { | ||||
|  | @ -1857,6 +1944,43 @@ impl_bounds! { | |||
|     } | ||||
| } | ||||
| 
 | ||||
| impl From<ParsedSizeTypeBound> for ParsedBound { | ||||
|     fn from(value: ParsedSizeTypeBound) -> Self { | ||||
|         match value { | ||||
|             ParsedSizeTypeBound::KnownSize(v) => ParsedBound::KnownSize(v), | ||||
|             ParsedSizeTypeBound::Size(v) => ParsedBound::Size(v), | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl From<ParsedSizeTypeBounds> for ParsedBounds { | ||||
|     fn from(value: ParsedSizeTypeBounds) -> Self { | ||||
|         let ParsedSizeTypeBounds { KnownSize, Size } = value; | ||||
|         Self { | ||||
|             BundleType: None, | ||||
|             EnumType: None, | ||||
|             IntType: None, | ||||
|             KnownSize, | ||||
|             Size, | ||||
|             StaticType: None, | ||||
|             Type: None, | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl ParsedSizeTypeBound { | ||||
|     fn implied_bounds(self) -> ParsedSizeTypeBounds { | ||||
|         let span = self.span(); | ||||
|         match self { | ||||
|             Self::KnownSize(v) => ParsedSizeTypeBounds::from_iter([ | ||||
|                 ParsedSizeTypeBound::from(v), | ||||
|                 ParsedSizeTypeBound::Size(known_items::Size(span)), | ||||
|             ]), | ||||
|             Self::Size(v) => ParsedSizeTypeBounds::from_iter([ParsedSizeTypeBound::from(v)]), | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #[derive(Clone, Debug)] | ||||
| pub(crate) enum ParsedBoundsCategory { | ||||
|     Type(ParsedTypeBounds), | ||||
|  | @ -1918,42 +2042,13 @@ impl ParsedBound { | |||
|         } | ||||
|     } | ||||
|     fn implied_bounds(self) -> ParsedBounds { | ||||
|         let span = self.span(); | ||||
|         match self { | ||||
|             Self::BundleType(v) => ParsedBounds::from_iter([ | ||||
|                 ParsedBound::from(v), | ||||
|                 ParsedBound::Type(known_items::Type(span)), | ||||
|             ]), | ||||
|             Self::EnumType(v) => ParsedBounds::from_iter([ | ||||
|                 ParsedBound::from(v), | ||||
|                 ParsedBound::Type(known_items::Type(span)), | ||||
|             ]), | ||||
|             Self::IntType(v) => ParsedBounds::from_iter([ | ||||
|                 ParsedBound::from(v), | ||||
|                 ParsedBound::Type(known_items::Type(span)), | ||||
|             ]), | ||||
|             Self::KnownSize(v) => ParsedBounds::from_iter([ | ||||
|                 ParsedBound::from(v), | ||||
|                 ParsedBound::Size(known_items::Size(span)), | ||||
|             ]), | ||||
|             Self::Size(v) => ParsedBounds::from_iter([ParsedBound::from(v)]), | ||||
|             Self::StaticType(v) => ParsedBounds::from_iter([ | ||||
|                 ParsedBound::from(v), | ||||
|                 ParsedBound::Type(known_items::Type(span)), | ||||
|             ]), | ||||
|             Self::Type(v) => ParsedBounds::from_iter([ParsedBound::from(v)]), | ||||
|         match self.categorize() { | ||||
|             ParsedBoundCategory::Type(v) => v.implied_bounds().into(), | ||||
|             ParsedBoundCategory::SizeType(v) => v.implied_bounds().into(), | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl ParsedBounds { | ||||
|     fn add_implied_bounds(&mut self) { | ||||
|         let orig_bounds = self.clone(); | ||||
|         self.extend(self.clone().into_iter().map(ParsedBound::implied_bounds)); | ||||
|         self.extend([orig_bounds]); // keep spans of explicitly provided bounds
 | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #[derive(Debug, Clone)] | ||||
| pub(crate) struct ParsedTypeParam { | ||||
|     pub(crate) attrs: Vec<Attribute>, | ||||
|  | @ -2116,6 +2211,7 @@ impl ParsedGenerics { | |||
|                 } | ||||
|                 ParsedGenericParam::Const(ParsedConstParam { ident, bounds, .. }) => { | ||||
|                     bounds | ||||
|                         .bounds | ||||
|                         .KnownSize | ||||
|                         .get_or_insert_with(|| known_items::KnownSize(ident.span())); | ||||
|                 } | ||||
|  | @ -2527,6 +2623,7 @@ impl ParsedGenerics { | |||
|                             ident: ident.clone(), | ||||
|                             colon_token, | ||||
|                             bounds: ParsedBounds::default(), | ||||
|                             mask_type_bounds: ParsedTypeBounds::default(), | ||||
|                         }, | ||||
|                         LateParsedParam { | ||||
|                             default: default | ||||
|  | @ -2563,6 +2660,7 @@ impl ParsedGenerics { | |||
|                             ident: ident.clone(), | ||||
|                             colon_token: *colon_token, | ||||
|                             ty: ParsedConstGenericType::Usize(known_items::usize(ident.span())), | ||||
|                             bounds: None, | ||||
|                         }, | ||||
|                         LateParsedParam { | ||||
|                             default: None, | ||||
|  | @ -2591,20 +2689,139 @@ impl ParsedGenerics { | |||
|                 lifetimes: None, | ||||
|                 bounded_ty: | ||||
|                     Type::Path(TypePath { | ||||
|                         qself: None, | ||||
|                         qself, | ||||
|                         path: bounded_ty, | ||||
|                     }), | ||||
|                 colon_token: _, | ||||
|                 colon_token, | ||||
|                 bounds: unparsed_bounds, | ||||
|             }) = predicate | ||||
|             else { | ||||
|                 errors.error(predicate, "unsupported where predicate kind"); | ||||
|                 continue; | ||||
|             }; | ||||
|             ParsedTypeNamed { | ||||
|                 path: todo!(), | ||||
|                 args: todo!(), | ||||
|             }; | ||||
|             if let Some(qself) = &qself { | ||||
|                 if let QSelf { | ||||
|                     lt_token: _, | ||||
|                     ty: base_ty, | ||||
|                     position: 3, | ||||
|                     as_token: Some(_), | ||||
|                     gt_token: _, | ||||
|                 } = qself | ||||
|                 { | ||||
|                     if bounded_ty.segments.len() == 4 && unparsed_bounds.len() == 1 { | ||||
|                         if let ( | ||||
|                             Ok(_), | ||||
|                             Type::Path(TypePath { | ||||
|                                 qself: None, | ||||
|                                 path: base_ty, | ||||
|                             }), | ||||
|                         ) = ( | ||||
|                             known_items::MaskType::parse_path(bounded_ty.clone()), | ||||
|                             &**base_ty, | ||||
|                         ) { | ||||
|                             let Some(&index) = base_ty | ||||
|                                 .get_ident() | ||||
|                                 .and_then(|base_ty| param_name_to_index_map.get(base_ty)) | ||||
|                             else { | ||||
|                                 errors.error( | ||||
|                                     TypePath { | ||||
|                                         qself: Some(qself.clone()), | ||||
|                                         path: bounded_ty, | ||||
|                                     }, | ||||
|                                     "unsupported where predicate kind", | ||||
|                                 ); | ||||
|                                 continue; | ||||
|                             }; | ||||
|                             let parsed_bounds = match &mut unparsed_params[index] { | ||||
|                                 UnparsedGenericParam::Type { | ||||
|                                     mask_type_bounds, .. | ||||
|                                 } => mask_type_bounds, | ||||
|                                 UnparsedGenericParam::Const { ident, .. } => { | ||||
|                                     errors.error( | ||||
|                                         bounded_ty, | ||||
|                                         format_args!( | ||||
|                                             "expected type, found const parameter `{ident}`" | ||||
|                                         ), | ||||
|                                     ); | ||||
|                                     continue; | ||||
|                                 } | ||||
|                             }; | ||||
|                             parsed_bounds.extend(errors.ok(syn::parse2::<ParsedTypeBounds>( | ||||
|                                 unparsed_bounds.to_token_stream(), | ||||
|                             ))); | ||||
|                             continue; | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|                 errors.error( | ||||
|                     TypePath { | ||||
|                         qself: Some(qself.clone()), | ||||
|                         path: bounded_ty, | ||||
|                     }, | ||||
|                     "unsupported where predicate kind", | ||||
|                 ); | ||||
|                 continue; | ||||
|             } | ||||
|             if let Ok(( | ||||
|                 const_usize, | ||||
|                 PathArguments::AngleBracketed(AngleBracketedGenericArguments { | ||||
|                     colon2_token: _, | ||||
|                     lt_token, | ||||
|                     args, | ||||
|                     gt_token, | ||||
|                 }), | ||||
|             )) = known_items::ConstUsize::parse_path_with_arguments(bounded_ty.clone()) | ||||
|             { | ||||
|                 if args.len() != 1 { | ||||
|                     errors.error(const_usize, "ConstUsize must have one argument"); | ||||
|                     continue; | ||||
|                 } | ||||
|                 let GenericArgument::Type(Type::Path(TypePath { | ||||
|                     qself: None, | ||||
|                     path: arg, | ||||
|                 })) = &args[0] | ||||
|                 else { | ||||
|                     errors.error( | ||||
|                         const_usize, | ||||
|                         "the only supported ConstUsize argument is a const generic parameter", | ||||
|                     ); | ||||
|                     continue; | ||||
|                 }; | ||||
|                 let arg = arg.get_ident(); | ||||
|                 let Some((arg, &index)) = | ||||
|                     arg.and_then(|arg| Some((arg, param_name_to_index_map.get(arg)?))) | ||||
|                 else { | ||||
|                     errors.error( | ||||
|                         const_usize, | ||||
|                         "the only supported ConstUsize argument is a const generic parameter", | ||||
|                     ); | ||||
|                     continue; | ||||
|                 }; | ||||
|                 let parsed_bounds = match &mut unparsed_params[index] { | ||||
|                     UnparsedGenericParam::Const { bounds, .. } => bounds, | ||||
|                     UnparsedGenericParam::Type { ident, .. } => { | ||||
|                         errors.error( | ||||
|                             bounded_ty, | ||||
|                             format_args!("expected const generic parameter, found type `{ident}`"), | ||||
|                         ); | ||||
|                         continue; | ||||
|                     } | ||||
|                 }; | ||||
|                 parsed_bounds | ||||
|                     .get_or_insert_with(|| ParsedConstParamWhereBounds { | ||||
|                         const_usize, | ||||
|                         lt_token, | ||||
|                         ident: arg.clone(), | ||||
|                         gt_token, | ||||
|                         colon_token, | ||||
|                         bounds: ParsedSizeTypeBounds::default(), | ||||
|                     }) | ||||
|                     .bounds | ||||
|                     .extend(errors.ok(syn::parse2::<ParsedSizeTypeBounds>( | ||||
|                         unparsed_bounds.to_token_stream(), | ||||
|                     ))); | ||||
|                 continue; | ||||
|             } | ||||
|             let Some(&index) = bounded_ty | ||||
|                 .get_ident() | ||||
|                 .and_then(|bounded_ty| param_name_to_index_map.get(bounded_ty)) | ||||
|  | @ -2639,7 +2856,26 @@ impl ParsedGenerics { | |||
|                         ident, | ||||
|                         colon_token, | ||||
|                         mut bounds, | ||||
|                         mask_type_bounds, | ||||
|                     } => { | ||||
|                         for bound in mask_type_bounds { | ||||
|                             bounds | ||||
|                                 .Type | ||||
|                                 .get_or_insert_with(|| known_items::Type(bound.span())); | ||||
|                             match bound { | ||||
|                                 ParsedTypeBound::BundleType(_) | ||||
|                                 | ParsedTypeBound::EnumType(_) | ||||
|                                 | ParsedTypeBound::IntType(_) => { | ||||
|                                     errors.error(bound, "bound on mask type not implemented"); | ||||
|                                 } | ||||
|                                 ParsedTypeBound::StaticType(bound) => { | ||||
|                                     if bounds.StaticType.is_none() { | ||||
|                                         errors.error(bound, "StaticType bound on mask type without corresponding StaticType bound on original type is not implemented"); | ||||
|                                     } | ||||
|                                 }, | ||||
|                                 ParsedTypeBound::Type(_) => {} | ||||
|                             } | ||||
|                         } | ||||
|                         bounds.add_implied_bounds(); | ||||
|                         match bounds.categorize(&mut errors, ident.span()) { | ||||
|                             ParsedBoundsCategory::Type(bounds) => { | ||||
|  | @ -2671,18 +2907,35 @@ impl ParsedGenerics { | |||
|                         ident, | ||||
|                         colon_token, | ||||
|                         ty, | ||||
|                     } => ParsedGenericParam::Const(ParsedConstParam { | ||||
|                         bounds: ParsedSizeTypeBounds { | ||||
|                             KnownSize: None, | ||||
|                             Size: Some(known_items::Size(ident.span())), | ||||
|                         }, | ||||
|                         attrs, | ||||
|                         options, | ||||
|                         const_token, | ||||
|                         ident, | ||||
|                         colon_token, | ||||
|                         ty, | ||||
|                     }), | ||||
|                         bounds, | ||||
|                     } => { | ||||
|                         let span = ident.span(); | ||||
|                         let mut bounds = bounds.unwrap_or_else(|| ParsedConstParamWhereBounds { | ||||
|                             const_usize: known_items::ConstUsize(span), | ||||
|                             lt_token: Token, | ||||
|                             ident: ident.clone(), | ||||
|                             gt_token: Token, | ||||
|                             colon_token: Token, | ||||
|                             bounds: ParsedSizeTypeBounds { | ||||
|                                 KnownSize: None, | ||||
|                                 Size: Some(known_items::Size(span)), | ||||
|                             }, | ||||
|                         }); | ||||
|                         bounds | ||||
|                             .bounds | ||||
|                             .Size | ||||
|                             .get_or_insert_with(|| known_items::Size(span)); | ||||
|                         bounds.bounds.add_implied_bounds(); | ||||
|                         ParsedGenericParam::Const(ParsedConstParam { | ||||
|                             bounds, | ||||
|                             attrs, | ||||
|                             options, | ||||
|                             const_token, | ||||
|                             ident, | ||||
|                             colon_token, | ||||
|                             ty, | ||||
|                         }) | ||||
|                     } | ||||
|                 }, | ||||
|             )); | ||||
|         let mut retval = Self { | ||||
|  |  | |||
|  | @ -66,8 +66,8 @@ pub(crate) struct ModuleFn { | |||
|     vis: Visibility, | ||||
|     sig: Signature, | ||||
|     block: Box<Block>, | ||||
|     io: Vec<ModuleIO>, | ||||
|     struct_generics: ParsedGenerics, | ||||
|     the_struct: TokenStream, | ||||
| } | ||||
| 
 | ||||
| #[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)] | ||||
|  | @ -224,6 +224,41 @@ impl Parse for ModuleFn { | |||
|         errors.finish()?; | ||||
|         let struct_generics = struct_generics.unwrap(); | ||||
|         let (block, io) = body_results.unwrap(); | ||||
|         let (_struct_impl_generics, _struct_type_generics, struct_where_clause) = | ||||
|             struct_generics.split_for_impl(); | ||||
|         let struct_where_clause: Option<WhereClause> = parse_quote! { #struct_where_clause }; | ||||
|         if let Some(struct_where_clause) = &struct_where_clause { | ||||
|             sig.generics | ||||
|                 .where_clause | ||||
|                 .get_or_insert_with(|| WhereClause { | ||||
|                     where_token: struct_where_clause.where_token, | ||||
|                     predicates: Default::default(), | ||||
|                 }) | ||||
|                 .predicates | ||||
|                 .extend(struct_where_clause.predicates.clone()); | ||||
|         } | ||||
|         let fn_name = &sig.ident; | ||||
|         let io_flips = io | ||||
|             .iter() | ||||
|             .map(|io| match io.kind.kind { | ||||
|                 ModuleIOKind::Input((input,)) => quote_spanned! {input.span=> | ||||
|                     #[hdl(flip)] | ||||
|                 }, | ||||
|                 ModuleIOKind::Output(_) => quote! {}, | ||||
|             }) | ||||
|             .collect::<Vec<_>>(); | ||||
|         let io_types = io.iter().map(|io| &io.kind.ty).collect::<Vec<_>>(); | ||||
|         let io_names = io.iter().map(|io| &io.name).collect::<Vec<_>>(); | ||||
|         let the_struct: ItemStruct = parse_quote! { | ||||
|             #[allow(non_camel_case_types)] | ||||
|             #[hdl(no_runtime_generics, no_static)] | ||||
|             #vis struct #fn_name #struct_generics #struct_where_clause { | ||||
|                 #( | ||||
|                 #io_flips | ||||
|                 #vis #io_names: #io_types,)* | ||||
|             } | ||||
|         }; | ||||
|         let the_struct = crate::hdl_bundle::hdl_bundle(the_struct)?; | ||||
|         Ok(Self { | ||||
|             attrs, | ||||
|             config_options, | ||||
|  | @ -231,8 +266,8 @@ impl Parse for ModuleFn { | |||
|             vis, | ||||
|             sig, | ||||
|             block, | ||||
|             io, | ||||
|             struct_generics, | ||||
|             the_struct, | ||||
|         }) | ||||
|     } | ||||
| } | ||||
|  | @ -246,8 +281,8 @@ impl ModuleFn { | |||
|             vis, | ||||
|             sig, | ||||
|             block, | ||||
|             io, | ||||
|             struct_generics, | ||||
|             the_struct, | ||||
|         } = self; | ||||
|         let ConfigOptions { | ||||
|             outline_generated: _, | ||||
|  | @ -279,7 +314,7 @@ impl ModuleFn { | |||
|             ModuleKind::Normal => quote! { ::fayalite::module::ModuleKind::Normal }, | ||||
|         }; | ||||
|         let fn_name = &outer_sig.ident; | ||||
|         let (_struct_impl_generics, struct_type_generics, struct_where_clause) = | ||||
|         let (_struct_impl_generics, struct_type_generics, _struct_where_clause) = | ||||
|             struct_generics.split_for_impl(); | ||||
|         let struct_ty = quote! {#fn_name #struct_type_generics}; | ||||
|         body_sig.ident = parse_quote! {__body}; | ||||
|  | @ -294,17 +329,6 @@ impl ModuleFn { | |||
|         }; | ||||
|         outer_sig.output = | ||||
|             parse_quote! {-> ::fayalite::intern::Interned<::fayalite::module::Module<#struct_ty>>}; | ||||
|         let io_flips = io | ||||
|             .iter() | ||||
|             .map(|io| match io.kind.kind { | ||||
|                 ModuleIOKind::Input((input,)) => quote_spanned! {input.span=> | ||||
|                     #[hdl(flip)] | ||||
|                 }, | ||||
|                 ModuleIOKind::Output(_) => quote! {}, | ||||
|             }) | ||||
|             .collect::<Vec<_>>(); | ||||
|         let io_types = io.iter().map(|io| &io.kind.ty).collect::<Vec<_>>(); | ||||
|         let io_names = io.iter().map(|io| &io.name).collect::<Vec<_>>(); | ||||
|         let fn_name_str = fn_name.to_string(); | ||||
|         let (_, body_type_generics, _) = body_fn.sig.generics.split_for_impl(); | ||||
|         let body_turbofish_type_generics = body_type_generics.as_turbofish(); | ||||
|  | @ -316,15 +340,6 @@ impl ModuleFn { | |||
|                 |m| __body #body_turbofish_type_generics(m, #(#param_names,)*), | ||||
|             ) | ||||
|         }}; | ||||
|         let the_struct: ItemStruct = parse_quote! { | ||||
|             #[allow(non_camel_case_types)] | ||||
|             #[hdl(no_runtime_generics, no_static)] | ||||
|             #vis struct #fn_name #struct_generics #struct_where_clause { | ||||
|                 #( | ||||
|                 #io_flips | ||||
|                 #vis #io_names: #io_types,)* | ||||
|             } | ||||
|         }; | ||||
|         let outer_fn = ItemFn { | ||||
|             attrs, | ||||
|             vis, | ||||
|  | @ -332,7 +347,7 @@ impl ModuleFn { | |||
|             block, | ||||
|         }; | ||||
|         let mut retval = outer_fn.into_token_stream(); | ||||
|         retval.extend(crate::hdl_bundle::hdl_bundle(the_struct).unwrap()); | ||||
|         retval.extend(the_struct); | ||||
|         retval | ||||
|     } | ||||
| } | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue