fix handling of const and size type generics when generating Index impls

This commit is contained in:
Jacob Lifshay 2024-09-19 18:45:04 -07:00
parent 2c1afd1cd6
commit 9887d70f41
Signed by: programmerjake
SSH key fingerprint: SHA256:B1iRVvUJkvd7upMIiMqn6OyxvD2SgJkAH3ZnUOj6z+c
5 changed files with 519 additions and 212 deletions

View file

@ -3,7 +3,7 @@
use crate::{
expr::{ops::ArrayIndex, Expr, ToExpr},
int::{DynSize, KnownSize, Size},
int::{DynSize, KnownSize, Size, SizeType, DYN_SIZE},
intern::{Intern, Interned, LazyInterned},
module::transform::visit::{Fold, Folder, Visit, Visitor},
source_location::SourceLocation,
@ -27,10 +27,7 @@ impl<T: Type, Len: Size> std::fmt::Debug for ArrayType<T, Len> {
}
}
pub type Array<
T = CanonicalType,
const LEN: usize = { <DynSize as crate::util::GenericConstUsize>::VALUE },
> = ArrayType<T, ConstUsize<LEN>>;
pub type Array<T = CanonicalType, const LEN: usize = DYN_SIZE> = ArrayType<T, ConstUsize<LEN>>;
#[allow(non_upper_case_globals)]
pub const Array: ArrayWithoutGenerics = ArrayWithoutGenerics;
@ -214,21 +211,10 @@ pub struct ArrayWithoutLen<T: Type> {
element: T,
}
impl<T: Type> Index<usize> for ArrayWithoutLen<T> {
type Output = Array<T>;
impl<T: Type, L: SizeType> Index<L> for ArrayWithoutLen<T> {
type Output = ArrayType<T, L::Size>;
fn index(&self, len: usize) -> &Self::Output {
Interned::<_>::into_inner(Intern::intern_sized(Array::new_dyn(self.element, len)))
}
}
impl<T: Type, const LEN: usize> Index<ConstUsize<LEN>> for ArrayWithoutLen<T>
where
ConstUsize<LEN>: KnownSize,
{
type Output = Array<T, LEN>;
fn index(&self, len: ConstUsize<LEN>) -> &Self::Output {
Interned::<_>::into_inner(Intern::intern_sized(Array::new(self.element, len)))
fn index(&self, len: L) -> &Self::Output {
Interned::<_>::into_inner(Intern::intern_sized(ArrayType::new(self.element, len)))
}
}

View file

@ -25,6 +25,7 @@ use std::{
mod sealed {
pub trait BoolOrIntTypeSealed {}
pub trait SizeSealed {}
pub trait SizeTypeSealed {}
}
pub const DYN_SIZE: usize = !0;
@ -59,6 +60,12 @@ macro_rules! known_widths {
known_widths!([2 2 2 2 2 2 2 2 2]);
pub trait SizeType:
sealed::SizeTypeSealed + Copy + Ord + std::hash::Hash + std::fmt::Debug + Send + Sync + 'static
{
type Size: Size<SizeType = Self>;
}
pub trait Size:
sealed::SizeSealed + Copy + Ord + std::hash::Hash + std::fmt::Debug + Send + Sync + 'static
{
@ -76,7 +83,14 @@ pub trait Size:
+ TryFrom<Vec<Expr<Element>>>
+ Into<Vec<Expr<Element>>>;
const KNOWN_VALUE: Option<usize>;
type SizeType: Copy + Ord + std::hash::Hash + std::fmt::Debug + Send + Sync + 'static;
type SizeType: SizeType<Size = Self>
+ Copy
+ Ord
+ std::hash::Hash
+ std::fmt::Debug
+ Send
+ Sync
+ 'static;
fn as_usize(size_type: Self::SizeType) -> usize;
fn try_from_usize(v: usize) -> Option<Self::SizeType>;
#[track_caller]
@ -85,6 +99,12 @@ pub trait Size:
}
}
impl sealed::SizeTypeSealed for usize {}
impl SizeType for usize {
type Size = DynSize;
}
impl Size for DynSize {
type ArrayMatch<Element: Type> = Box<[Expr<Element>]>;
const KNOWN_VALUE: Option<usize> = None;
@ -101,6 +121,15 @@ impl Size for DynSize {
impl<const VALUE: usize> sealed::SizeSealed for ConstUsize<VALUE> {}
impl<const VALUE: usize> sealed::SizeTypeSealed for ConstUsize<VALUE> {}
impl<const VALUE: usize> SizeType for ConstUsize<VALUE>
where
ConstUsize<VALUE>: KnownSize,
{
type Size = ConstUsize<VALUE>;
}
impl<const VALUE: usize> Size for ConstUsize<VALUE>
where
ConstUsize<VALUE>: KnownSize,
@ -138,9 +167,7 @@ macro_rules! impl_int {
}
}
pub type $pretty_name<
const WIDTH: usize = { <DynSize as crate::util::GenericConstUsize>::VALUE },
> = $name<ConstUsize<WIDTH>>;
pub type $pretty_name<const WIDTH: usize = DYN_SIZE> = $name<ConstUsize<WIDTH>>;
#[allow(non_upper_case_globals)]
pub const $pretty_name: $generic_name = $generic_name;
@ -269,21 +296,10 @@ macro_rules! impl_int {
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, Default)]
pub struct $generic_name;
impl Index<usize> for $generic_name {
type Output = $name;
impl<Width: SizeType> Index<Width> for $generic_name {
type Output = $name<Width::Size>;
fn index(&self, width: usize) -> &Self::Output {
Interned::<_>::into_inner(Intern::intern_sized($name::new_dyn(width)))
}
}
impl<const WIDTH: usize> Index<ConstUsize<WIDTH>> for $generic_name
where
ConstUsize<WIDTH>: KnownSize,
{
type Output = $pretty_name<WIDTH>;
fn index(&self, width: ConstUsize<WIDTH>) -> &Self::Output {
fn index(&self, width: Width) -> &Self::Output {
Interned::<_>::into_inner(Intern::intern_sized($name::new(width)))
}
}

View file

@ -1,16 +1,22 @@
// SPDX-License-Identifier: LGPL-3.0-or-later
// See Notices.txt for copyright information
use fayalite::{
array::ArrayType,
hdl,
int::{IntType, Size, UInt},
};
use fayalite::prelude::*;
#[hdl(outline_generated)]
pub struct S<T: IntType, Len: Size> {
pub struct S<T, Len: Size, T2> {
pub a: T,
b: UInt<3>,
pub(crate) c: ArrayType<UInt<1>, Len>,
pub d: T2,
}
//#[cfg(todo)]
#[hdl(outline_generated)]
pub struct S3<const LEN: usize, T> {
pub a: T,
b: UInt<3>,
pub(crate) c: Array<UInt<1>, LEN>,
pub d: S<T, ConstUsize<LEN>, ()>,
}
#[hdl(outline_generated)]