forked from libre-chip/fayalite
		
	const generics on hdl_module work!
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
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,6 +6,7 @@ use fayalite::{
 | 
			
		|||
    intern::Intern,
 | 
			
		||||
    module::transform::simplify_enums::{simplify_enums, SimplifyEnumsKind},
 | 
			
		||||
    prelude::*,
 | 
			
		||||
    ty::StaticType,
 | 
			
		||||
};
 | 
			
		||||
use serde_json::json;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -133,9 +134,11 @@ circuit my_module:
 | 
			
		|||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[cfg(todo)]
 | 
			
		||||
#[hdl_module(outline_generated)]
 | 
			
		||||
pub fn check_array_repeat<const N: usize>() {
 | 
			
		||||
pub fn check_array_repeat<const N: usize>()
 | 
			
		||||
where
 | 
			
		||||
    ConstUsize<N>: KnownSize,
 | 
			
		||||
{
 | 
			
		||||
    #[hdl]
 | 
			
		||||
    let i: UInt<8> = m.input();
 | 
			
		||||
    #[hdl]
 | 
			
		||||
| 
						 | 
				
			
			@ -147,7 +150,6 @@ pub fn check_array_repeat<const N: usize>() {
 | 
			
		|||
    );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[cfg(todo)]
 | 
			
		||||
#[test]
 | 
			
		||||
fn test_array_repeat() {
 | 
			
		||||
    let _n = SourceLocation::normalize_files_for_tests();
 | 
			
		||||
| 
						 | 
				
			
			@ -188,21 +190,21 @@ circuit check_array_repeat_1:
 | 
			
		|||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[cfg(todo)]
 | 
			
		||||
#[hdl_module(outline_generated)]
 | 
			
		||||
pub fn check_skipped_generics<T, #[hdl(skip)] U, const N: usize, #[hdl(skip)] const M: usize>(v: U)
 | 
			
		||||
where
 | 
			
		||||
    T: StaticValue,
 | 
			
		||||
    T: StaticType,
 | 
			
		||||
    ConstUsize<N>: KnownSize,
 | 
			
		||||
    U: std::fmt::Display,
 | 
			
		||||
{
 | 
			
		||||
    dbg!(M);
 | 
			
		||||
    #[hdl]
 | 
			
		||||
    let i: T = m.input();
 | 
			
		||||
    #[hdl]
 | 
			
		||||
    let o: Array<[T; N]> = m.output();
 | 
			
		||||
    let o: Array<T, N> = m.output();
 | 
			
		||||
    let bytes = v.to_string().as_bytes().to_expr();
 | 
			
		||||
    #[hdl]
 | 
			
		||||
    let o2: Array<[UInt<8>]> = m.output(bytes.ty());
 | 
			
		||||
    let o2: Array<UInt<8>> = m.output(Expr::ty(bytes));
 | 
			
		||||
    connect(
 | 
			
		||||
        o,
 | 
			
		||||
        #[hdl]
 | 
			
		||||
| 
						 | 
				
			
			@ -211,7 +213,6 @@ where
 | 
			
		|||
    connect(o2, bytes);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[cfg(todo)]
 | 
			
		||||
#[test]
 | 
			
		||||
fn test_skipped_generics() {
 | 
			
		||||
    let _n = SourceLocation::normalize_files_for_tests();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue