diff --git a/crates/fayalite-proc-macros-impl/src/hdl_type_common.rs b/crates/fayalite-proc-macros-impl/src/hdl_type_common.rs index bc0b074..57b1034 100644 --- a/crates/fayalite-proc-macros-impl/src/hdl_type_common.rs +++ b/crates/fayalite-proc-macros-impl/src/hdl_type_common.rs @@ -5,14 +5,14 @@ use std::{collections::HashMap, fmt, mem}; use syn::{ parse::{Parse, ParseStream}, parse_quote, parse_quote_spanned, - punctuated::{Pair, Punctuated}, + punctuated::Punctuated, spanned::Spanned, token::{Brace, Bracket, Paren}, AngleBracketedGenericArguments, Attribute, ConstParam, Expr, ExprIndex, ExprPath, ExprTuple, Field, FieldMutability, Fields, FieldsNamed, FieldsUnnamed, GenericArgument, GenericParam, Generics, Ident, ImplGenerics, Index, ItemStruct, Path, PathArguments, PathSegment, - PredicateType, QSelf, Token, Turbofish, Type, TypeGenerics, TypeGroup, TypeParam, TypeParen, - TypePath, TypeTuple, Visibility, WhereClause, WherePredicate, + PredicateType, Token, Turbofish, Type, TypeGenerics, TypeGroup, TypeParam, TypeParen, TypePath, + TypeTuple, Visibility, WhereClause, WherePredicate, }; crate::options! { @@ -239,34 +239,7 @@ impl ParseTypes for ParsedGenericArgument { parser: &mut TypesParser<'_>, ) -> Result { match arg { - GenericArgument::Type(ty) => { - { - let mut ty = &*ty; - while let Type::Group(TypeGroup { elem, .. }) = ty { - ty = &**elem; - } - if let Type::Path(TypePath { qself: None, path }) = ty { - if let Some(ident) = path.get_ident() { - if let Some(¶m_index) = - parser.generics.param_name_to_index_map.get(ident) - { - match parser.generics.params[param_index] { - ParsedGenericParam::Type(_) - | ParsedGenericParam::SizeType(_) => {} - ParsedGenericParam::Const(_) => { - return Ok(Self::Const(Expr::Path(ExprPath { - attrs: vec![], - qself: None, - path: path.clone(), - }))); - } - } - } - } - } - } - Ok(Self::Type(parser.parse(ty)?)) - } + GenericArgument::Type(ty) => Ok(Self::Type(parser.parse(ty)?)), GenericArgument::Const(expr) => Ok(Self::Const(expr.clone())), _ => parse_failed!(parser, arg, "expected type or const generic argument"), } @@ -1232,12 +1205,6 @@ impl ParseTypes for ParsedType { param_index, }) } - ParsedGenericParam::Const(ParsedConstParam { ref ident, .. }) => { - parser - .errors - .error(ident, "constant provided when a type was expected"); - return Err(ParseFailed); - } }, )); } @@ -1324,120 +1291,6 @@ impl ParseTypes for ParsedType { } } -#[derive(Debug, Clone)] -pub(crate) enum ParsedConstGenericType { - Usize(known_items::usize), -} - -impl_fold! { - enum ParsedConstGenericType<> { - Usize(known_items::usize), - } -} - -impl From for Type { - fn from(value: ParsedConstGenericType) -> Self { - match value { - ParsedConstGenericType::Usize(v) => parse_quote! { #v }, - } - } -} - -impl From> for Type { - fn from(value: MaybeParsed) -> Self { - match value { - MaybeParsed::Unrecognized(value) => value, - MaybeParsed::Parsed(value) => value.into(), - } - } -} - -impl From> for Type { - fn from(value: Box) -> Self { - (*value).into() - } -} - -impl ToTokens for ParsedConstGenericType { - fn to_tokens(&self, tokens: &mut TokenStream) { - match self { - ParsedConstGenericType::Usize(ty) => ty.to_tokens(tokens), - } - } -} - -impl ParseTypes for ParsedConstGenericType { - fn parse_types(path: &mut Path, parser: &mut TypesParser<'_>) -> Result { - let Path { - leading_colon, - ref mut segments, - } = *path; - if segments.is_empty() { - parse_failed!(parser, path, "path must not be empty"); - } - let mut args = None; - let segments = Punctuated::from_iter(segments.pairs_mut().map_pair_value_mut(|segment| { - let PathSegment { ident, arguments } = segment; - if let Some(_) = args { - parser - .errors() - .error(&ident, "associated types/consts are not yet implemented"); - } - args = match arguments { - PathArguments::None => None, - PathArguments::AngleBracketed(args) => parser.parse(args).ok(), - PathArguments::Parenthesized(_) => { - parser - .errors() - .error(&segment, "function traits are not allowed"); - None - } - }; - PathSegment::from(segment.ident.clone()) - })); - let named = ParsedTypeNamed { - path: Path { - leading_colon, - segments, - }, - args, - }; - let named = match known_items::usize::try_from_named(named, parser)? { - Ok(v) => return Ok(Self::Usize(v)), - Err(named) => named, - }; - parser.errors.error( - named, - "const parameter types other than `usize` are not yet implemented", - ); - Err(ParseFailed) - } -} - -impl ParseTypes for ParsedConstGenericType { - fn parse_types(ty: &mut TypePath, parser: &mut TypesParser<'_>) -> Result { - let TypePath { qself, path } = ty; - if let Some(_qself) = qself { - parse_failed!( - parser, - ty, - "associated types/consts are not yet implemented" - ); - } else { - parser.parse(path) - } - } -} - -impl ParseTypes for ParsedConstGenericType { - fn parse_types(ty: &mut Type, parser: &mut TypesParser<'_>) -> Result { - Ok(match ty { - Type::Path(ty) => parser.parse(ty)?, - _ => parse_failed!(parser, ty, "unsupported const generic type"), - }) - } -} - pub(crate) struct ParseFailed; impl fmt::Display for ParseFailed { @@ -1523,16 +1376,6 @@ pub(crate) enum UnparsedGenericParam { ident: Ident, colon_token: Token![:], bounds: ParsedBounds, - mask_type_bounds: ParsedTypeBounds, - }, - Const { - attrs: Vec, - options: HdlAttr, - const_token: Token![const], - ident: Ident, - colon_token: Token![:], - ty: ParsedConstGenericType, - bounds: Option, }, } @@ -1547,7 +1390,7 @@ pub(crate) mod known_items { macro_rules! impl_known_item_body { ($known_item:ident) => { #[derive(Clone, Debug)] - #[allow(dead_code, non_camel_case_types)] + #[allow(dead_code)] pub(crate) struct $known_item { pub(crate) path: Path, pub(crate) span: Span, @@ -1596,20 +1439,6 @@ 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 { @@ -1679,9 +1508,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); } macro_rules! impl_bounds { @@ -1838,19 +1665,6 @@ 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 - } - } }; } @@ -1878,64 +1692,6 @@ impl_bounds! { } } -impl From 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 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 { @@ -1944,43 +1700,6 @@ impl_bounds! { } } -impl From for ParsedBound { - fn from(value: ParsedSizeTypeBound) -> Self { - match value { - ParsedSizeTypeBound::KnownSize(v) => ParsedBound::KnownSize(v), - ParsedSizeTypeBound::Size(v) => ParsedBound::Size(v), - } - } -} - -impl From 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), @@ -2042,13 +1761,42 @@ impl ParsedBound { } } fn implied_bounds(self) -> ParsedBounds { - match self.categorize() { - ParsedBoundCategory::Type(v) => v.implied_bounds().into(), - ParsedBoundCategory::SizeType(v) => v.implied_bounds().into(), + 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)]), } } } +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, @@ -2117,54 +1865,10 @@ impl ToTokens for ParsedSizeTypeParam { } } -#[derive(Debug, Clone)] -pub(crate) struct ParsedConstParamWhereBounds { - pub(crate) const_usize: known_items::ConstUsize, - pub(crate) lt_token: Token![<], - pub(crate) ident: Ident, - pub(crate) gt_token: Token![>], - pub(crate) colon_token: Token![:], - pub(crate) bounds: ParsedSizeTypeBounds, -} - -#[derive(Debug, Clone)] -pub(crate) struct ParsedConstParam { - pub(crate) attrs: Vec, - pub(crate) options: HdlAttr, - pub(crate) const_token: Token![const], - pub(crate) ident: Ident, - pub(crate) colon_token: Token![:], - pub(crate) ty: ParsedConstGenericType, - pub(crate) bounds: ParsedConstParamWhereBounds, -} - -impl ToTokens for ParsedConstParam { - fn to_tokens(&self, tokens: &mut TokenStream) { - let Self { - attrs, - options, - const_token, - ident, - colon_token, - ty, - bounds: _, - } = self; - let ConstParamOptions {} = options.body; - for attr in attrs { - attr.to_tokens(tokens); - } - const_token.to_tokens(tokens); - ident.to_tokens(tokens); - colon_token.to_tokens(tokens); - ty.to_tokens(tokens); - } -} - #[derive(Debug, Clone)] pub(crate) enum ParsedGenericParam { Type(ParsedTypeParam), SizeType(ParsedSizeTypeParam), - Const(ParsedConstParam), } impl ToTokens for ParsedGenericParam { @@ -2172,7 +1876,6 @@ impl ToTokens for ParsedGenericParam { match self { ParsedGenericParam::Type(v) => v.to_tokens(tokens), ParsedGenericParam::SizeType(v) => v.to_tokens(tokens), - ParsedGenericParam::Const(v) => v.to_tokens(tokens), } } } @@ -2182,7 +1885,6 @@ impl ParsedGenericParam { match self { ParsedGenericParam::Type(v) => &v.ident, ParsedGenericParam::SizeType(v) => &v.ident, - ParsedGenericParam::Const(v) => &v.ident, } } } @@ -2209,12 +1911,6 @@ impl ParsedGenerics { .KnownSize .get_or_insert_with(|| known_items::KnownSize(ident.span())); } - ParsedGenericParam::Const(ParsedConstParam { ident, bounds, .. }) => { - bounds - .bounds - .KnownSize - .get_or_insert_with(|| known_items::KnownSize(ident.span())); - } } } self @@ -2286,13 +1982,6 @@ impl ParsedGenerics { <#ident as ::fayalite::int::Size>::SizeType } } - ParsedGenericParam::Const(param) => { - let ident = ¶m.ident; - parse_quote_spanned! {span=> - <::fayalite::util::ConstUsize<#ident> - as ::fayalite::int::Size>::SizeType - } - } }) .collect(), } @@ -2565,119 +2254,98 @@ impl ParsedGenerics { todo!(); } } - ParsedGenericParam::Const(_) => todo!(), }; } } - pub(crate) fn parse<'a>(generics: &'a mut Generics) -> syn::Result { + pub(crate) fn parse(generics: &mut Generics) -> syn::Result { let Generics { lt_token, - params: input_params, + params, gt_token, where_clause, } = generics; let mut errors = Errors::new(); - let mut predicates: Vec = Vec::with_capacity(input_params.len()); - struct LateParsedParam<'a> { - default: Option<(Token![=], &'a mut Type)>, - const_param_type: Option<&'a mut Type>, - } - let mut late_parsed_params: Vec> = - Vec::with_capacity(input_params.len()); - let mut unparsed_params: Punctuated = Punctuated::new(); - for input_param in input_params.pairs_mut() { - let (input_param, punct) = input_param.into_tuple(); - let (unparsed_param, late_parsed_param) = match input_param { - GenericParam::Lifetime(param) => { - errors.unwrap_or_default(HdlAttr::::parse_and_take_attr( - &mut param.attrs, - )); - errors.error(param, "lifetime generics are not supported by #[hdl]"); - continue; - } - GenericParam::Type(TypeParam { - attrs, - ident, - colon_token, - bounds, - eq_token, - default, - }) => { - let span = ident.span(); - let options = errors - .unwrap_or_default(HdlAttr::::parse_and_take_attr(attrs)) - .unwrap_or_default(); - let colon_token = colon_token.unwrap_or_else(|| Token![:](span)); - if !bounds.is_empty() { - predicates.push(WherePredicate::Type(PredicateType { - lifetimes: None, - bounded_ty: parse_quote! { #ident }, - colon_token, - bounds: bounds.clone(), - })); - } - ( - UnparsedGenericParam::Type { - attrs: attrs.clone(), - options, - ident: ident.clone(), - colon_token, - bounds: ParsedBounds::default(), - mask_type_bounds: ParsedTypeBounds::default(), - }, - LateParsedParam { - default: default - .as_mut() - .map(|v| (eq_token.unwrap_or_else(|| Token![=](span)), v)), - const_param_type: None, - }, - ) - } - GenericParam::Const(ConstParam { - attrs, - const_token, - ident, - colon_token, - ty, - eq_token, - default, - }) => { - let options = errors - .unwrap_or_default(HdlAttr::::parse_and_take_attr(attrs)) - .unwrap_or_default(); - if let Some(default) = default { - let _ = eq_token; - errors.error( - default, - "const generics' default values are not yet implemented", + let mut predicates: Vec = Vec::with_capacity(params.len()); + let mut defaults = Vec::with_capacity(params.len()); + let mut params = Punctuated::::from_iter( + params.pairs_mut().filter_map_pair_value_mut(|param| { + let (param, default) = match param { + GenericParam::Lifetime(param) => { + errors.unwrap_or_default( + HdlAttr::::parse_and_take_attr(&mut param.attrs), ); + errors.error(param, "lifetime generics are not supported by #[hdl]"); + return None; } - ( - UnparsedGenericParam::Const { - attrs: attrs.clone(), - options, - const_token: *const_token, - ident: ident.clone(), - colon_token: *colon_token, - ty: ParsedConstGenericType::Usize(known_items::usize(ident.span())), - bounds: None, - }, - LateParsedParam { - default: None, - const_param_type: Some(ty), - }, - ) - } - }; - late_parsed_params.push(late_parsed_param); - unparsed_params.extend([Pair::new(unparsed_param, punct.cloned())]); - } - let param_name_to_index_map: HashMap = unparsed_params + GenericParam::Type(TypeParam { + attrs, + ident, + colon_token, + bounds, + eq_token, + default, + }) => { + let span = ident.span(); + let options = errors + .unwrap_or_default(HdlAttr::::parse_and_take_attr( + attrs, + )) + .unwrap_or_default(); + let colon_token = colon_token.unwrap_or_else(|| Token![:](span)); + if !bounds.is_empty() { + predicates.push(WherePredicate::Type(PredicateType { + lifetimes: None, + bounded_ty: parse_quote! { #ident }, + colon_token, + bounds: bounds.clone(), + })); + } + ( + UnparsedGenericParam::Type { + attrs: attrs.clone(), + options, + ident: ident.clone(), + colon_token, + bounds: ParsedBounds::default(), + }, + default + .clone() + .map(|v| (eq_token.unwrap_or_else(|| Token![=](span)), v)), + ) + } + GenericParam::Const(ConstParam { + attrs, + const_token, + ident, + colon_token, + ty, + eq_token, + default, + }) => { + let options = errors + .unwrap_or_default(HdlAttr::::parse_and_take_attr( + attrs, + )) + .unwrap_or_default(); + let _ = const_token; + let _ = ident; + let _ = colon_token; + let _ = ty; + let _ = eq_token; + let _ = default; + let _ = options; + todo!() + } + }; + defaults.push(default); + Some(param) + }), + ); + let param_name_to_index_map: HashMap = params .iter() .enumerate() .map(|(index, param)| { - let (UnparsedGenericParam::Type { ident, .. } - | UnparsedGenericParam::Const { ident, .. }) = param; + let UnparsedGenericParam::Type { ident, .. } = param; (ident.clone(), index) }) .collect(); @@ -2689,296 +2357,90 @@ impl ParsedGenerics { lifetimes: None, bounded_ty: Type::Path(TypePath { - qself, + qself: None, path: bounded_ty, }), - colon_token, + colon_token: _, bounds: unparsed_bounds, }) = predicate else { errors.error(predicate, "unsupported where predicate kind"); continue; }; - 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::( - 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::( - 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)) else { errors.error( bounded_ty, - "where predicate bounded type must be one of the generic type \ - parameters or `ConstUsize`", + "where predicate bounded type must be one of the generic parameters", ); continue; }; - let parsed_bounds = match &mut unparsed_params[index] { - UnparsedGenericParam::Type { bounds, .. } => bounds, - UnparsedGenericParam::Const { ident, .. } => { - errors.error( - bounded_ty, - format_args!("expected type, found const parameter `{ident}`"), - ); - continue; - } - }; + let UnparsedGenericParam::Type { + bounds: parsed_bounds, + .. + } = &mut params[index]; parsed_bounds.extend(errors.ok(syn::parse2::( unparsed_bounds.to_token_stream(), ))); } let params = - Punctuated::from_iter(unparsed_params.into_pairs().map_pair_value( - |param| match param { - UnparsedGenericParam::Type { - attrs, - options, - 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(_) => {} - } + Punctuated::from_iter(params.into_pairs().map_pair_value(|param| match param { + UnparsedGenericParam::Type { + attrs, + options, + ident, + colon_token, + mut bounds, + } => { + bounds.add_implied_bounds(); + match bounds.categorize(&mut errors, ident.span()) { + ParsedBoundsCategory::Type(bounds) => { + ParsedGenericParam::Type(ParsedTypeParam { + attrs, + options, + ident, + colon_token, + bounds, + default: None, + }) } - bounds.add_implied_bounds(); - match bounds.categorize(&mut errors, ident.span()) { - ParsedBoundsCategory::Type(bounds) => { - ParsedGenericParam::Type(ParsedTypeParam { - attrs, - options, - ident, - colon_token, - bounds, - default: None, - }) - } - ParsedBoundsCategory::SizeType(bounds) => { - ParsedGenericParam::SizeType(ParsedSizeTypeParam { - attrs, - options, - ident, - colon_token, - bounds, - default: None, - }) - } + ParsedBoundsCategory::SizeType(bounds) => { + ParsedGenericParam::SizeType(ParsedSizeTypeParam { + attrs, + options, + ident, + colon_token, + bounds, + default: None, + }) } } - UnparsedGenericParam::Const { - 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![<](span), - ident: ident.clone(), - gt_token: Token![>](span), - colon_token: Token![:](span), - 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 { lt_token: *lt_token, params, gt_token: *gt_token, param_name_to_index_map, }; - for ( - cur_param_index, - LateParsedParam { - default, - const_param_type, - }, - ) in late_parsed_params.into_iter().enumerate() - { - let mut parser = TypesParser { + for (cur_param_index, default) in defaults.into_iter().enumerate() { + let Some((eq, mut ty)) = default else { + continue; + }; + let Ok(ty) = TypesParser { generics: &retval, cur_param_index: Some(cur_param_index), errors: &mut errors, + } + .parse(&mut ty) else { + continue; }; - let parsed_default = default.and_then(|(eq, ty)| { - let ty = parser.parse(ty).ok()?; - Some((eq, ty)) - }); - let parsed_const_param_type = const_param_type.and_then(|ty| parser.parse(ty).ok()); match &mut retval.params[cur_param_index] { ParsedGenericParam::Type(ParsedTypeParam { default, .. }) | ParsedGenericParam::SizeType(ParsedSizeTypeParam { default, .. }) => { - *default = parsed_default; - } - ParsedGenericParam::Const(ParsedConstParam { - attrs: _, - options: _, - const_token: _, - ident: _, - colon_token: _, - ty, - bounds: _, - }) => { - if let Some(parsed_const_param_type) = parsed_const_param_type { - *ty = parsed_const_param_type; - } + *default = Some((eq, ty)) } } } @@ -3055,21 +2517,6 @@ impl ToTokens for ParsedGenericsImplGenerics<'_> { colon_token.to_tokens(tokens); bounds.to_tokens(tokens); } - ParsedGenericParam::Const(ParsedConstParam { - attrs: _, - options, - const_token, - ident, - colon_token, - ty, - bounds: _, - }) => { - let ConstParamOptions {} = options.body; - const_token.to_tokens(tokens); - ident.to_tokens(tokens); - colon_token.to_tokens(tokens); - ty.to_tokens(tokens); - } } punct.to_tokens(tokens); } @@ -3162,27 +2609,6 @@ impl ToTokens for ParsedGenericsWhereClause<'_> { } } ParsedGenericParam::SizeType(_) => {} - ParsedGenericParam::Const(ParsedConstParam { - ident: _, - bounds: - ParsedConstParamWhereBounds { - const_usize, - lt_token, - ident, - gt_token, - colon_token, - bounds, - }, - .. - }) => { - where_token(ident.span()).to_tokens(tokens); - const_usize.to_tokens(tokens); - lt_token.to_tokens(tokens); - ident.to_tokens(tokens); - gt_token.to_tokens(tokens); - colon_token.to_tokens(tokens); - bounds.to_tokens(tokens); - } } } } diff --git a/crates/fayalite-proc-macros-impl/src/module.rs b/crates/fayalite-proc-macros-impl/src/module.rs index 0945abb..7d816d3 100644 --- a/crates/fayalite-proc-macros-impl/src/module.rs +++ b/crates/fayalite-proc-macros-impl/src/module.rs @@ -66,8 +66,8 @@ pub(crate) struct ModuleFn { vis: Visibility, sig: Signature, block: Box, + io: Vec, struct_generics: ParsedGenerics, - the_struct: TokenStream, } #[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)] @@ -224,41 +224,6 @@ 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 = 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::>(); - let io_types = io.iter().map(|io| &io.kind.ty).collect::>(); - let io_names = io.iter().map(|io| &io.name).collect::>(); - 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, @@ -266,8 +231,8 @@ impl Parse for ModuleFn { vis, sig, block, + io, struct_generics, - the_struct, }) } } @@ -281,8 +246,8 @@ impl ModuleFn { vis, sig, block, + io, struct_generics, - the_struct, } = self; let ConfigOptions { outline_generated: _, @@ -314,7 +279,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}; @@ -329,6 +294,17 @@ 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::>(); + let io_types = io.iter().map(|io| &io.kind.ty).collect::>(); + let io_names = io.iter().map(|io| &io.name).collect::>(); 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(); @@ -340,6 +316,15 @@ 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, @@ -347,7 +332,7 @@ impl ModuleFn { block, }; let mut retval = outer_fn.into_token_stream(); - retval.extend(the_struct); + retval.extend(crate::hdl_bundle::hdl_bundle(the_struct).unwrap()); retval } } diff --git a/crates/fayalite/tests/module.rs b/crates/fayalite/tests/module.rs index f039750..8df3771 100644 --- a/crates/fayalite/tests/module.rs +++ b/crates/fayalite/tests/module.rs @@ -6,7 +6,6 @@ use fayalite::{ intern::Intern, module::transform::simplify_enums::{simplify_enums, SimplifyEnumsKind}, prelude::*, - ty::StaticType, }; use serde_json::json; @@ -134,11 +133,9 @@ circuit my_module: }; } +#[cfg(todo)] #[hdl_module(outline_generated)] -pub fn check_array_repeat() -where - ConstUsize: KnownSize, -{ +pub fn check_array_repeat() { #[hdl] let i: UInt<8> = m.input(); #[hdl] @@ -150,6 +147,7 @@ where ); } +#[cfg(todo)] #[test] fn test_array_repeat() { let _n = SourceLocation::normalize_files_for_tests(); @@ -190,21 +188,21 @@ circuit check_array_repeat_1: }; } +#[cfg(todo)] #[hdl_module(outline_generated)] pub fn check_skipped_generics(v: U) where - T: StaticType, - ConstUsize: KnownSize, + T: StaticValue, U: std::fmt::Display, { dbg!(M); #[hdl] let i: T = m.input(); #[hdl] - let o: Array = m.output(); + let o: Array<[T; N]> = m.output(); let bytes = v.to_string().as_bytes().to_expr(); #[hdl] - let o2: Array> = m.output(Expr::ty(bytes)); + let o2: Array<[UInt<8>]> = m.output(bytes.ty()); connect( o, #[hdl] @@ -213,6 +211,7 @@ where connect(o2, bytes); } +#[cfg(todo)] #[test] fn test_skipped_generics() { let _n = SourceLocation::normalize_files_for_tests();