add PhantomData as a hdl bundle
Some checks failed
/ test (push) Has been cancelled

This commit is contained in:
Jacob Lifshay 2024-10-10 20:48:09 -07:00
parent bf907c3872
commit 59cef3f398
Signed by: programmerjake
SSH key fingerprint: SHA256:B1iRVvUJkvd7upMIiMqn6OyxvD2SgJkAH3ZnUOj6z+c
3 changed files with 255 additions and 22 deletions

View file

@ -1273,6 +1273,130 @@ make_parsed_type_or_const! {
}
}
#[derive(Debug, Clone)]
pub(crate) struct ParsedTypePhantomData {
pub(crate) phantom_data: known_items::PhantomData,
pub(crate) lt_token: Token![<],
pub(crate) ty: Box<ParsedType>,
pub(crate) gt_token: Token![>],
}
impl_fold! {
struct ParsedTypePhantomData<> {
phantom_data: known_items::PhantomData,
lt_token: Token![<],
ty: Box<ParsedType>,
gt_token: Token![>],
}
}
impl ParsedTypePhantomData {
pub(crate) fn try_from_named(
named: ParsedTypeNamed,
parser: &mut TypesParser<'_>,
) -> Result<Result<Self, ParsedTypeNamed>, ParseFailed> {
let ParsedTypeNamed { path, args } = named;
let parsed_path = known_items::PhantomData::parse_path(path);
let phantom_data = match parsed_path {
Ok(phantom_data) => phantom_data,
Err(path) => return Ok(Err(ParsedTypeNamed { path, args })),
};
let Some(ParsedGenericArguments {
colon2_token: _,
lt_token,
args,
gt_token,
}) = args
else {
parser
.errors()
.error(phantom_data, "PhantomData requires generic arguments");
return Err(ParseFailed);
};
let args_len = args.len();
if args_len != 1 {
parser.errors().error(
phantom_data,
format_args!(
"wrong number of generic arguments supplied: got {args_len}, expected 1"
),
);
return Err(ParseFailed);
}
let ty = args.into_iter().next().unwrap();
let ParsedGenericArgument::Type(ty) = ty else {
parser.errors().error(ty, "expected a type");
return Err(ParseFailed);
};
Ok(Ok(Self {
phantom_data,
lt_token,
ty: Box::new(ty),
gt_token,
}))
}
}
impl From<ParsedTypePhantomData> for Type {
fn from(value: ParsedTypePhantomData) -> Type {
let ParsedTypePhantomData {
phantom_data,
lt_token,
ty,
gt_token,
} = value;
let path = phantom_data.path;
let mut args = Punctuated::new();
args.push(GenericArgument::Type(ty.into()));
let args = AngleBracketedGenericArguments {
colon2_token: Some(Token![::](lt_token.span)),
lt_token,
args,
gt_token,
};
let mut segments = path.segments;
segments.last_mut().unwrap().arguments = PathArguments::AngleBracketed(args);
Type::Path(TypePath {
qself: None,
path: Path {
leading_colon: path.leading_colon,
segments,
},
})
}
}
impl MakeHdlTypeExpr for ParsedTypePhantomData {
fn make_hdl_type_expr(&self, _context: &MakeHdlTypeExprContext) -> Expr {
let ParsedTypePhantomData {
phantom_data,
lt_token: _,
ty: _,
gt_token: _,
} = self;
Expr::Path(ExprPath {
attrs: vec![],
qself: None,
path: phantom_data.path.clone(),
})
}
}
impl ToTokens for ParsedTypePhantomData {
fn to_tokens(&self, tokens: &mut TokenStream) {
let Self {
phantom_data,
lt_token,
ty,
gt_token,
} = self;
phantom_data.to_tokens(tokens);
lt_token.to_tokens(tokens);
ty.to_tokens(tokens);
gt_token.to_tokens(tokens);
}
}
#[derive(Debug, Clone)]
pub(crate) enum ParsedType {
Delimited(ParsedTypeDelimited),
@ -1280,6 +1404,7 @@ pub(crate) enum ParsedType {
NamedParam(ParsedTypeNamedParam),
Tuple(ParsedTypeTuple),
ConstUsize(ParsedTypeConstUsize),
PhantomData(ParsedTypePhantomData),
Array(ParsedTypeArray),
UInt(ParsedTypeUInt),
SInt(ParsedTypeSInt),
@ -1294,6 +1419,7 @@ impl_fold! {
NamedParam(ParsedTypeNamedParam),
Tuple(ParsedTypeTuple),
ConstUsize(ParsedTypeConstUsize),
PhantomData(ParsedTypePhantomData),
Array(ParsedTypeArray),
UInt(ParsedTypeUInt),
SInt(ParsedTypeSInt),
@ -1310,6 +1436,7 @@ impl From<ParsedType> for Type {
ParsedType::NamedParam(v) => v.into(),
ParsedType::Tuple(v) => v.into(),
ParsedType::ConstUsize(v) => v.into(),
ParsedType::PhantomData(v) => v.into(),
ParsedType::Array(v) => v.into(),
ParsedType::UInt(v) => v.into(),
ParsedType::SInt(v) => v.into(),
@ -1360,6 +1487,7 @@ impl ToTokens for ParsedType {
ParsedType::Named(ty) => ty.to_tokens(tokens),
ParsedType::Tuple(ty) => ty.to_tokens(tokens),
ParsedType::ConstUsize(ty) => ty.to_tokens(tokens),
ParsedType::PhantomData(ty) => ty.to_tokens(tokens),
ParsedType::Array(ty) => ty.to_tokens(tokens),
ParsedType::UInt(ty) => ty.to_tokens(tokens),
ParsedType::SInt(ty) => ty.to_tokens(tokens),
@ -1467,6 +1595,10 @@ impl ParseTypes<Path> for ParsedType {
Ok(v) => return Ok(Self::ConstUsize(v)),
Err(named) => named,
};
let named = match ParsedTypePhantomData::try_from_named(named, parser)? {
Ok(v) => return Ok(Self::PhantomData(v)),
Err(named) => named,
};
let named = match ParsedTypeUInt::try_from_named(named, parser)? {
Ok(v) => return Ok(Self::UInt(v)),
Err(named) => named,
@ -1784,7 +1916,7 @@ pub(crate) mod known_items {
#[allow(non_snake_case, dead_code)]
pub(crate) fn $known_item(span: Span) -> $known_item {
let segments = $known_item::PATH_SEGMENTS.iter()
let segments = $known_item::PATH_SEGMENTS[0].iter()
.copied()
.map(|seg| PathSegment::from(Ident::new(seg, span)))
.collect();
@ -1810,21 +1942,22 @@ pub(crate) mod known_items {
return Ok(Self { span: ident.span(), path });
}
}
if path.segments.len() == Self::PATH_SEGMENTS.len()
for &path_segments in Self::PATH_SEGMENTS.iter() {
if path.segments.len() == path_segments.len()
&& path
.segments
.iter()
.zip(Self::PATH_SEGMENTS)
.zip(path_segments)
.all(|(seg, expected)| {
matches!(seg.arguments, PathArguments::None)
&& seg.ident == *expected
})
{
Ok(Self { span: path.segments.last().unwrap().ident.span(), path })
} else {
Err(path)
return Ok(Self { span: path.segments.last().unwrap().ident.span(), path });
}
}
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 {
@ -1878,19 +2011,24 @@ pub(crate) mod known_items {
}
macro_rules! impl_known_item {
($([$(::$head:ident)*])? ::$next:ident $(::$tail:ident)+) => {
impl_known_item!([$($(::$head)*)? ::$next] $(::$tail)+);
};
([$(::$seg:ident)+] ::$known_item:ident) => {
($(#[alias = $(::$alias:ident)+])* [$(::$seg:ident)+] ::$known_item:ident) => {
impl_known_item_body!($known_item);
impl $known_item {
pub(crate) const PATH_SEGMENTS: &'static [&'static str] = &[
pub(crate) const PATH_SEGMENTS: &'static [&'static [&'static str]] = &[
&[
$(stringify!($seg),)+
stringify!($known_item),
],
$(&[
$(stringify!($alias),)+
],)*
];
}
};
($(#[alias = $(::$alias:ident)+])* $([$(::$head:ident)*])? ::$next:ident $(::$tail:ident)+) => {
impl_known_item!($(#[alias = $(::$alias)+])* [$($(::$head)*)? ::$next] $(::$tail)+);
};
}
impl_known_item!(::fayalite::array::Array);
@ -1911,7 +2049,16 @@ pub(crate) mod known_items {
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);
impl_known_item!(
#[alias = ::std::primitive::usize]
#[alias = ::core::primitive::usize]
::fayalite::__std::primitive::usize
);
impl_known_item!(
#[alias = ::std::marker::PhantomData]
#[alias = ::core::marker::PhantomData]
::fayalite::__std::marker::PhantomData
);
}
macro_rules! impl_bounds {
@ -3969,6 +4116,7 @@ impl MakeHdlTypeExpr for ParsedType {
Self::NamedParam(v) => v.make_hdl_type_expr(context),
Self::Tuple(v) => v.make_hdl_type_expr(context),
Self::ConstUsize(v) => v.make_hdl_type_expr(context),
Self::PhantomData(v) => v.make_hdl_type_expr(context),
Self::Array(v) => v.make_hdl_type_expr(context),
Self::UInt(v) => v.make_hdl_type_expr(context),
Self::SInt(v) => v.make_hdl_type_expr(context),

View file

@ -446,3 +446,85 @@ impl_tuples! {
{#[num = 11, field = field_11] v11: T11}
]
}
impl<T: ?Sized + Send + Sync + 'static> Type for PhantomData<T> {
type BaseType = Bundle;
type MaskType = ();
type MatchVariant = PhantomData<T>;
type MatchActiveScope = ();
type MatchVariantAndInactiveScope = MatchVariantWithoutScope<Self::MatchVariant>;
type MatchVariantsIter = std::iter::Once<Self::MatchVariantAndInactiveScope>;
fn match_variants(
this: Expr<Self>,
source_location: SourceLocation,
) -> Self::MatchVariantsIter {
let _ = this;
let _ = source_location;
std::iter::once(MatchVariantWithoutScope(PhantomData))
}
fn mask_type(&self) -> Self::MaskType {
()
}
fn canonical(&self) -> CanonicalType {
Bundle::new(self.fields()).canonical()
}
#[track_caller]
fn from_canonical(canonical_type: CanonicalType) -> Self {
let CanonicalType::Bundle(bundle) = canonical_type else {
panic!("expected bundle");
};
assert!(
bundle.fields().is_empty(),
"bundle has wrong number of fields"
);
PhantomData
}
fn source_location() -> SourceLocation {
SourceLocation::builtin()
}
}
pub struct PhantomDataBuilder<T: ?Sized + Send + Sync + 'static>(PhantomData<T>);
impl<T: ?Sized + Send + Sync + 'static> Default for PhantomDataBuilder<T> {
fn default() -> Self {
Self(PhantomData)
}
}
impl<T: ?Sized + Send + Sync + 'static> ToExpr for PhantomDataBuilder<T> {
type Type = PhantomData<T>;
fn to_expr(&self) -> Expr<Self::Type> {
PhantomData.to_expr()
}
}
impl<T: ?Sized + Send + Sync + 'static> BundleType for PhantomData<T> {
type Builder = PhantomDataBuilder<T>;
type FilledBuilder = PhantomDataBuilder<T>;
fn fields(&self) -> Interned<[BundleField]> {
Interned::default()
}
}
impl<T: ?Sized + Send + Sync + 'static> TypeWithDeref for PhantomData<T> {
fn expr_deref(_this: &Expr<Self>) -> &Self::MatchVariant {
&PhantomData
}
}
impl<T: ?Sized + Send + Sync + 'static> StaticType for PhantomData<T> {
const TYPE: Self = PhantomData;
const MASK_TYPE: Self::MaskType = ();
const TYPE_PROPERTIES: TypeProperties = <()>::TYPE_PROPERTIES;
const MASK_TYPE_PROPERTIES: TypeProperties = <()>::TYPE_PROPERTIES;
}
impl<T: ?Sized + Send + Sync + 'static> ToExpr for PhantomData<T> {
type Type = PhantomData<T>;
fn to_expr(&self) -> Expr<Self::Type> {
BundleLiteral::new(PhantomData, Interned::default()).to_expr()
}
}

View file

@ -1,6 +1,7 @@
// SPDX-License-Identifier: LGPL-3.0-or-later
// See Notices.txt for copyright information
use fayalite::prelude::*;
use std::marker::PhantomData;
#[hdl(outline_generated)]
pub struct S<T, Len: Size, T2> {
@ -8,6 +9,8 @@ pub struct S<T, Len: Size, T2> {
b: UInt<3>,
pub(crate) c: ArrayType<UInt<1>, Len>,
pub d: T2,
pub e: PhantomData<T>,
pub f: PhantomData<Len>,
}
#[hdl(outline_generated)]