forked from libre-chip/fayalite
fix handling of const and size type generics when generating Index impls
This commit is contained in:
parent
2c1afd1cd6
commit
9887d70f41
|
@ -230,6 +230,7 @@ forward_fold!(syn::Path => fold_path);
|
||||||
forward_fold!(syn::Type => fold_type);
|
forward_fold!(syn::Type => fold_type);
|
||||||
forward_fold!(syn::TypePath => fold_type_path);
|
forward_fold!(syn::TypePath => fold_type_path);
|
||||||
forward_fold!(syn::WherePredicate => fold_where_predicate);
|
forward_fold!(syn::WherePredicate => fold_where_predicate);
|
||||||
|
no_op_fold!(proc_macro2::Span);
|
||||||
no_op_fold!(syn::parse::Nothing);
|
no_op_fold!(syn::parse::Nothing);
|
||||||
no_op_fold!(syn::token::Brace);
|
no_op_fold!(syn::token::Brace);
|
||||||
no_op_fold!(syn::token::Bracket);
|
no_op_fold!(syn::token::Bracket);
|
||||||
|
|
|
@ -8,11 +8,12 @@ use syn::{
|
||||||
punctuated::{Pair, Punctuated},
|
punctuated::{Pair, Punctuated},
|
||||||
spanned::Spanned,
|
spanned::Spanned,
|
||||||
token::{Brace, Bracket, Paren},
|
token::{Brace, Bracket, Paren},
|
||||||
AngleBracketedGenericArguments, Attribute, ConstParam, Expr, ExprIndex, ExprPath, ExprTuple,
|
AngleBracketedGenericArguments, Attribute, Block, ConstParam, Expr, ExprBlock, ExprGroup,
|
||||||
Field, FieldMutability, Fields, FieldsNamed, FieldsUnnamed, GenericArgument, GenericParam,
|
ExprIndex, ExprParen, ExprPath, ExprTuple, Field, FieldMutability, Fields, FieldsNamed,
|
||||||
Generics, Ident, ImplGenerics, Index, ItemStruct, Path, PathArguments, PathSegment,
|
FieldsUnnamed, GenericArgument, GenericParam, Generics, Ident, ImplGenerics, Index, ItemStruct,
|
||||||
PredicateType, QSelf, Token, Turbofish, Type, TypeGenerics, TypeGroup, TypeParam, TypeParen,
|
Path, PathArguments, PathSegment, PredicateType, QSelf, Stmt, Token, Turbofish, Type,
|
||||||
TypePath, TypeTuple, Visibility, WhereClause, WherePredicate,
|
TypeGenerics, TypeGroup, TypeParam, TypeParen, TypePath, TypeTuple, Visibility, WhereClause,
|
||||||
|
WherePredicate,
|
||||||
};
|
};
|
||||||
|
|
||||||
crate::options! {
|
crate::options! {
|
||||||
|
@ -113,6 +114,230 @@ macro_rules! parse_failed {
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug)]
|
||||||
|
pub(crate) enum ExprDelimiter {
|
||||||
|
Group(syn::token::Group),
|
||||||
|
Brace(Brace),
|
||||||
|
Paren(Paren),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl_fold! {
|
||||||
|
enum ExprDelimiter<> {
|
||||||
|
Group(syn::token::Group),
|
||||||
|
Brace(Brace),
|
||||||
|
Paren(Paren),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ExprDelimiter {
|
||||||
|
pub(crate) fn surround<F: FnOnce(&mut TokenStream)>(self, tokens: &mut TokenStream, f: F) {
|
||||||
|
match self {
|
||||||
|
ExprDelimiter::Group(v) => v.surround(tokens, f),
|
||||||
|
ExprDelimiter::Brace(v) => v.surround(tokens, f),
|
||||||
|
ExprDelimiter::Paren(v) => v.surround(tokens, f),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub(crate) struct ParsedExprDelimited {
|
||||||
|
pub(crate) delim: ExprDelimiter,
|
||||||
|
pub(crate) expr: Box<ParsedExpr>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl_fold! {
|
||||||
|
struct ParsedExprDelimited<> {
|
||||||
|
delim: ExprDelimiter,
|
||||||
|
expr: Box<ParsedExpr>,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<ParsedExprDelimited> for Expr {
|
||||||
|
fn from(value: ParsedExprDelimited) -> Self {
|
||||||
|
let ParsedExprDelimited { delim, expr } = value;
|
||||||
|
let expr = expr.into();
|
||||||
|
match delim {
|
||||||
|
ExprDelimiter::Group(group_token) => Expr::Group(ExprGroup {
|
||||||
|
attrs: vec![],
|
||||||
|
group_token,
|
||||||
|
expr: Box::new(expr),
|
||||||
|
}),
|
||||||
|
ExprDelimiter::Brace(brace_token) => Expr::Block(ExprBlock {
|
||||||
|
attrs: vec![],
|
||||||
|
label: None,
|
||||||
|
block: Block {
|
||||||
|
brace_token,
|
||||||
|
stmts: vec![Stmt::Expr(expr, None)],
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
ExprDelimiter::Paren(paren_token) => Expr::Paren(ExprParen {
|
||||||
|
attrs: vec![],
|
||||||
|
paren_token,
|
||||||
|
expr: Box::new(expr),
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ToTokens for ParsedExprDelimited {
|
||||||
|
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||||
|
let Self { delim, expr } = self;
|
||||||
|
delim.surround(tokens, |tokens| expr.to_tokens(tokens));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub(crate) struct ParsedExprNamedParamConst {
|
||||||
|
pub(crate) ident: Ident,
|
||||||
|
pub(crate) param_index: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl_fold! {
|
||||||
|
struct ParsedExprNamedParamConst<> {
|
||||||
|
ident: Ident,
|
||||||
|
param_index: usize,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ToTokens for ParsedExprNamedParamConst {
|
||||||
|
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||||
|
let Self {
|
||||||
|
ident,
|
||||||
|
param_index: _,
|
||||||
|
} = self;
|
||||||
|
ident.to_tokens(tokens);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<ParsedExprNamedParamConst> for Expr {
|
||||||
|
fn from(value: ParsedExprNamedParamConst) -> Self {
|
||||||
|
Expr::Path(ExprPath {
|
||||||
|
attrs: vec![],
|
||||||
|
qself: None,
|
||||||
|
path: value.ident.into(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub(crate) enum ParsedExpr {
|
||||||
|
Delimited(ParsedExprDelimited),
|
||||||
|
NamedParamConst(ParsedExprNamedParamConst),
|
||||||
|
Other(Box<Expr>),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ParsedExpr {
|
||||||
|
pub(crate) fn named_param_const(mut self: &Self) -> Option<&ParsedExprNamedParamConst> {
|
||||||
|
loop {
|
||||||
|
match self {
|
||||||
|
ParsedExpr::Delimited(ParsedExprDelimited { expr, .. }) => self = &**expr,
|
||||||
|
ParsedExpr::NamedParamConst(retval) => return Some(retval),
|
||||||
|
ParsedExpr::Other(_) => return None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl_fold! {
|
||||||
|
enum ParsedExpr<> {
|
||||||
|
Delimited(ParsedExprDelimited),
|
||||||
|
NamedParamConst(ParsedExprNamedParamConst),
|
||||||
|
Other(Box<Expr>),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ToTokens for ParsedExpr {
|
||||||
|
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||||
|
match self {
|
||||||
|
ParsedExpr::Delimited(v) => v.to_tokens(tokens),
|
||||||
|
ParsedExpr::NamedParamConst(v) => v.to_tokens(tokens),
|
||||||
|
ParsedExpr::Other(v) => v.to_tokens(tokens),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<ParsedExpr> for Expr {
|
||||||
|
fn from(value: ParsedExpr) -> Self {
|
||||||
|
match value {
|
||||||
|
ParsedExpr::Delimited(expr) => expr.into(),
|
||||||
|
ParsedExpr::NamedParamConst(expr) => expr.into(),
|
||||||
|
ParsedExpr::Other(expr) => *expr,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Box<ParsedExpr>> for Expr {
|
||||||
|
fn from(value: Box<ParsedExpr>) -> Self {
|
||||||
|
(*value).into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ParseTypes<Expr> for ParsedExpr {
|
||||||
|
fn parse_types(input: &mut Expr, parser: &mut TypesParser<'_>) -> Result<Self, ParseFailed> {
|
||||||
|
match input {
|
||||||
|
Expr::Block(ExprBlock {
|
||||||
|
attrs,
|
||||||
|
label: None,
|
||||||
|
block: Block { brace_token, stmts },
|
||||||
|
}) if attrs.is_empty() && stmts.len() == 1 => {
|
||||||
|
if let Stmt::Expr(expr, None) = &mut stmts[0] {
|
||||||
|
return Ok(ParsedExpr::Delimited(ParsedExprDelimited {
|
||||||
|
delim: ExprDelimiter::Brace(*brace_token),
|
||||||
|
expr: Box::new(parser.parse(expr)?),
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Expr::Group(ExprGroup {
|
||||||
|
attrs,
|
||||||
|
group_token,
|
||||||
|
expr,
|
||||||
|
}) if attrs.is_empty() => {
|
||||||
|
return Ok(ParsedExpr::Delimited(ParsedExprDelimited {
|
||||||
|
delim: ExprDelimiter::Group(*group_token),
|
||||||
|
expr: parser.parse(expr)?,
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
Expr::Paren(ExprParen {
|
||||||
|
attrs,
|
||||||
|
paren_token,
|
||||||
|
expr,
|
||||||
|
}) if attrs.is_empty() => {
|
||||||
|
return Ok(ParsedExpr::Delimited(ParsedExprDelimited {
|
||||||
|
delim: ExprDelimiter::Paren(*paren_token),
|
||||||
|
expr: parser.parse(expr)?,
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
Expr::Path(ExprPath {
|
||||||
|
attrs,
|
||||||
|
qself: None,
|
||||||
|
path,
|
||||||
|
}) if attrs.is_empty() => {
|
||||||
|
if let Some((param_index, ident)) = parser.get_named_param(path) {
|
||||||
|
return Ok(Self::NamedParamConst(
|
||||||
|
match parser.generics().params[param_index] {
|
||||||
|
ParsedGenericParam::Const(_) => ParsedExprNamedParamConst {
|
||||||
|
ident: ident.clone(),
|
||||||
|
param_index,
|
||||||
|
},
|
||||||
|
ParsedGenericParam::Type(ParsedTypeParam { ref ident, .. })
|
||||||
|
| ParsedGenericParam::SizeType(ParsedSizeTypeParam {
|
||||||
|
ref ident, ..
|
||||||
|
}) => {
|
||||||
|
parser
|
||||||
|
.errors
|
||||||
|
.error(ident, "type provided when a constant was expected");
|
||||||
|
return Err(ParseFailed);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
Ok(ParsedExpr::Other(Box::new(input.clone())))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
pub(crate) enum TypeDelimiter {
|
pub(crate) enum TypeDelimiter {
|
||||||
Group(syn::token::Group),
|
Group(syn::token::Group),
|
||||||
|
@ -214,13 +439,13 @@ impl ParseTypes<TypeTuple> for ParsedTypeTuple {
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub(crate) enum ParsedGenericArgument {
|
pub(crate) enum ParsedGenericArgument {
|
||||||
Type(ParsedType),
|
Type(ParsedType),
|
||||||
Const(Expr),
|
Const(ParsedExpr),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_fold! {
|
impl_fold! {
|
||||||
enum ParsedGenericArgument<> {
|
enum ParsedGenericArgument<> {
|
||||||
Type(ParsedType),
|
Type(ParsedType),
|
||||||
Const(Expr),
|
Const(ParsedExpr),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -246,20 +471,16 @@ impl ParseTypes<GenericArgument> for ParsedGenericArgument {
|
||||||
ty = &**elem;
|
ty = &**elem;
|
||||||
}
|
}
|
||||||
if let Type::Path(TypePath { qself: None, path }) = ty {
|
if let Type::Path(TypePath { qself: None, path }) = ty {
|
||||||
if let Some(ident) = path.get_ident() {
|
if let Some((param_index, ident)) = parser.get_named_param(path) {
|
||||||
if let Some(¶m_index) =
|
|
||||||
parser.generics.param_name_to_index_map.get(ident)
|
|
||||||
{
|
|
||||||
match parser.generics.params[param_index] {
|
match parser.generics.params[param_index] {
|
||||||
ParsedGenericParam::Type(_)
|
ParsedGenericParam::Type(_) | ParsedGenericParam::SizeType(_) => {}
|
||||||
| ParsedGenericParam::SizeType(_) => {}
|
|
||||||
ParsedGenericParam::Const(_) => {
|
ParsedGenericParam::Const(_) => {
|
||||||
return Ok(Self::Const(Expr::Path(ExprPath {
|
return Ok(Self::Const(ParsedExpr::NamedParamConst(
|
||||||
attrs: vec![],
|
ParsedExprNamedParamConst {
|
||||||
qself: None,
|
ident: ident.clone(),
|
||||||
path: path.clone(),
|
param_index,
|
||||||
})));
|
},
|
||||||
}
|
)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -267,7 +488,7 @@ impl ParseTypes<GenericArgument> for ParsedGenericArgument {
|
||||||
}
|
}
|
||||||
Ok(Self::Type(parser.parse(ty)?))
|
Ok(Self::Type(parser.parse(ty)?))
|
||||||
}
|
}
|
||||||
GenericArgument::Const(expr) => Ok(Self::Const(expr.clone())),
|
GenericArgument::Const(expr) => Ok(Self::Const(parser.parse(expr)?)),
|
||||||
_ => parse_failed!(parser, arg, "expected type or const generic argument"),
|
_ => parse_failed!(parser, arg, "expected type or const generic argument"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -277,7 +498,7 @@ impl From<ParsedGenericArgument> for GenericArgument {
|
||||||
fn from(value: ParsedGenericArgument) -> Self {
|
fn from(value: ParsedGenericArgument) -> Self {
|
||||||
match value {
|
match value {
|
||||||
ParsedGenericArgument::Type(ty) => Self::Type(ty.into()),
|
ParsedGenericArgument::Type(ty) => Self::Type(ty.into()),
|
||||||
ParsedGenericArgument::Const(expr) => Self::Const(expr),
|
ParsedGenericArgument::Const(expr) => Self::Const(expr.into()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -496,7 +717,7 @@ impl ToTokens for ParsedTypeNamedParam {
|
||||||
pub(crate) struct ParsedTypeConstUsize {
|
pub(crate) struct ParsedTypeConstUsize {
|
||||||
pub(crate) const_usize: known_items::ConstUsize,
|
pub(crate) const_usize: known_items::ConstUsize,
|
||||||
pub(crate) lt_token: Token![<],
|
pub(crate) lt_token: Token![<],
|
||||||
pub(crate) value: Box<Expr>,
|
pub(crate) value: ParsedExpr,
|
||||||
pub(crate) gt_token: Token![>],
|
pub(crate) gt_token: Token![>],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -504,7 +725,7 @@ impl_fold! {
|
||||||
struct ParsedTypeConstUsize<> {
|
struct ParsedTypeConstUsize<> {
|
||||||
const_usize: known_items::ConstUsize,
|
const_usize: known_items::ConstUsize,
|
||||||
lt_token: Token![<],
|
lt_token: Token![<],
|
||||||
value: Box<Expr>,
|
value: ParsedExpr,
|
||||||
gt_token: Token![>],
|
gt_token: Token![>],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -518,7 +739,7 @@ impl From<ParsedTypeConstUsize> for Path {
|
||||||
gt_token,
|
gt_token,
|
||||||
} = value;
|
} = value;
|
||||||
let path = const_usize.path;
|
let path = const_usize.path;
|
||||||
let args = Punctuated::from_iter([GenericArgument::Const(*value)]);
|
let args = Punctuated::from_iter([GenericArgument::Const(value.into())]);
|
||||||
let args = AngleBracketedGenericArguments {
|
let args = AngleBracketedGenericArguments {
|
||||||
colon2_token: Some(Token![::](lt_token.span)),
|
colon2_token: Some(Token![::](lt_token.span)),
|
||||||
lt_token,
|
lt_token,
|
||||||
|
@ -544,13 +765,17 @@ impl From<ParsedTypeConstUsize> for Type {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MakeHdlTypeExpr for ParsedTypeConstUsize {
|
impl MakeHdlTypeExpr for ParsedTypeConstUsize {
|
||||||
fn make_hdl_type_expr(&self, _context: &MakeHdlTypeExprContext) -> Expr {
|
fn make_hdl_type_expr(&self, context: &MakeHdlTypeExprContext) -> Expr {
|
||||||
|
if let Some(named_param_const) = self.value.named_param_const() {
|
||||||
|
named_param_const.make_hdl_type_expr(context)
|
||||||
|
} else {
|
||||||
Expr::Path(ExprPath {
|
Expr::Path(ExprPath {
|
||||||
attrs: vec![],
|
attrs: vec![],
|
||||||
qself: None,
|
qself: None,
|
||||||
path: self.clone().into(),
|
path: self.clone().into(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToTokens for ParsedTypeConstUsize {
|
impl ToTokens for ParsedTypeConstUsize {
|
||||||
|
@ -606,7 +831,7 @@ impl ParsedTypeConstUsize {
|
||||||
Ok(Ok(Self {
|
Ok(Ok(Self {
|
||||||
const_usize,
|
const_usize,
|
||||||
lt_token,
|
lt_token,
|
||||||
value: Box::new(value),
|
value,
|
||||||
gt_token,
|
gt_token,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
@ -694,7 +919,7 @@ macro_rules! make_parsed_type_or_const {
|
||||||
let $type_arg = Box::new(ParsedType::ConstUsize(ParsedTypeConstUsize {
|
let $type_arg = Box::new(ParsedType::ConstUsize(ParsedTypeConstUsize {
|
||||||
const_usize: known_items::ConstUsize($span),
|
const_usize: known_items::ConstUsize($span),
|
||||||
lt_token: Token![<]($span),
|
lt_token: Token![<]($span),
|
||||||
value: Box::new($const_arg.clone()),
|
value: $const_arg.clone(),
|
||||||
gt_token: Token![>]($span),
|
gt_token: Token![>]($span),
|
||||||
}));
|
}));
|
||||||
($type_arg, Some(Box::new($const_arg)))
|
($type_arg, Some(Box::new($const_arg)))
|
||||||
|
@ -887,7 +1112,7 @@ macro_rules! make_parsed_type_or_const {
|
||||||
let mut args = Punctuated::new();
|
let mut args = Punctuated::new();
|
||||||
$(
|
$(
|
||||||
args.push((
|
args.push((
|
||||||
($(|| GenericArgument::Const(*$const_arg),)?
|
($(|| GenericArgument::Const($const_arg.into()),)?
|
||||||
|| GenericArgument::Type($type_arg.into()),
|
|| GenericArgument::Type($type_arg.into()),
|
||||||
).0)());
|
).0)());
|
||||||
$(args.push_punct($separator);)?
|
$(args.push_punct($separator);)?
|
||||||
|
@ -1010,7 +1235,7 @@ make_parsed_type_or_const! {
|
||||||
#[separator]
|
#[separator]
|
||||||
comma_token: Token![,],
|
comma_token: Token![,],
|
||||||
#[const]
|
#[const]
|
||||||
const_len: Option<Box<Expr>>,
|
const_len: Option<Box<ParsedExpr>>,
|
||||||
#[type(default = |span| ParsedType::DynSize(known_items::DynSize(span)))]
|
#[type(default = |span| ParsedType::DynSize(known_items::DynSize(span)))]
|
||||||
type_len: Box<ParsedType>,
|
type_len: Box<ParsedType>,
|
||||||
gt_token: Token![>],
|
gt_token: Token![>],
|
||||||
|
@ -1024,7 +1249,7 @@ make_parsed_type_or_const! {
|
||||||
uint_type: known_items::UIntType,
|
uint_type: known_items::UIntType,
|
||||||
lt_token: Token![<],
|
lt_token: Token![<],
|
||||||
#[const]
|
#[const]
|
||||||
const_width: Option<Box<Expr>>,
|
const_width: Option<Box<ParsedExpr>>,
|
||||||
#[type(default = |span| ParsedType::DynSize(known_items::DynSize(span)))]
|
#[type(default = |span| ParsedType::DynSize(known_items::DynSize(span)))]
|
||||||
type_width: Box<ParsedType>,
|
type_width: Box<ParsedType>,
|
||||||
gt_token: Token![>],
|
gt_token: Token![>],
|
||||||
|
@ -1038,7 +1263,7 @@ make_parsed_type_or_const! {
|
||||||
uint_type: known_items::SIntType,
|
uint_type: known_items::SIntType,
|
||||||
lt_token: Token![<],
|
lt_token: Token![<],
|
||||||
#[const]
|
#[const]
|
||||||
const_width: Option<Box<Expr>>,
|
const_width: Option<Box<ParsedExpr>>,
|
||||||
#[type(default = |span| ParsedType::DynSize(known_items::DynSize(span)))]
|
#[type(default = |span| ParsedType::DynSize(known_items::DynSize(span)))]
|
||||||
type_width: Box<ParsedType>,
|
type_width: Box<ParsedType>,
|
||||||
gt_token: Token![>],
|
gt_token: Token![>],
|
||||||
|
@ -1207,17 +1432,7 @@ impl ParseTypes<Path> for ParsedType {
|
||||||
},
|
},
|
||||||
args,
|
args,
|
||||||
};
|
};
|
||||||
if let Some(ident) = named.path.get_ident() {
|
if let Some((param_index, ident)) = parser.get_named_param(&named.path) {
|
||||||
if let Some(¶m_index) = parser.generics().param_name_to_index_map.get(ident) {
|
|
||||||
if parser
|
|
||||||
.cur_param_index
|
|
||||||
.is_some_and(|cur_param_index| param_index >= cur_param_index)
|
|
||||||
{
|
|
||||||
parser.errors.error(
|
|
||||||
parser.generics().params[param_index].ident(),
|
|
||||||
"cannot use forward declared identifier in generic parameter defaults",
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return Ok(Self::NamedParam(
|
return Ok(Self::NamedParam(
|
||||||
match parser.generics().params[param_index] {
|
match parser.generics().params[param_index] {
|
||||||
ParsedGenericParam::Type(_) => {
|
ParsedGenericParam::Type(_) => {
|
||||||
|
@ -1241,7 +1456,6 @@ impl ParseTypes<Path> for ParsedType {
|
||||||
},
|
},
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
let named = match ParsedTypeArray::try_from_named(named, parser)? {
|
let named = match ParsedTypeArray::try_from_named(named, parser)? {
|
||||||
Ok(v) => return Ok(Self::Array(v)),
|
Ok(v) => return Ok(Self::Array(v)),
|
||||||
Err(named) => named,
|
Err(named) => named,
|
||||||
|
@ -1489,6 +1703,18 @@ impl<'a> TypesParser<'a> {
|
||||||
pub(crate) fn parse<T: ParseTypes<I>, I>(&mut self, input: &mut I) -> Result<T, ParseFailed> {
|
pub(crate) fn parse<T: ParseTypes<I>, I>(&mut self, input: &mut I) -> Result<T, ParseFailed> {
|
||||||
T::parse_types(input, self)
|
T::parse_types(input, self)
|
||||||
}
|
}
|
||||||
|
pub(crate) fn get_named_param<'b>(&mut self, path: &'b Path) -> Option<(usize, &'b Ident)> {
|
||||||
|
let ident = path.get_ident()?;
|
||||||
|
let param_index = *self.generics().param_name_to_index_map.get(ident)?;
|
||||||
|
if self
|
||||||
|
.cur_param_index
|
||||||
|
.is_some_and(|cur_param_index| param_index >= cur_param_index)
|
||||||
|
{
|
||||||
|
self.errors
|
||||||
|
.error(path, "cannot use forward declared identifier here");
|
||||||
|
}
|
||||||
|
Some((param_index, ident))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) trait ParseTypes<I>: Sized {
|
pub(crate) trait ParseTypes<I>: Sized {
|
||||||
|
@ -2311,7 +2537,7 @@ impl ParsedGenerics {
|
||||||
) {
|
) {
|
||||||
if self.params.is_empty() {
|
if self.params.is_empty() {
|
||||||
let target_expr = target_expr(&MakeHdlTypeExprContext {
|
let target_expr = target_expr(&MakeHdlTypeExprContext {
|
||||||
type_arg_values: vec![],
|
named_param_values: vec![],
|
||||||
is_const: true,
|
is_const: true,
|
||||||
});
|
});
|
||||||
quote_spanned! {ident.span()=>
|
quote_spanned! {ident.span()=>
|
||||||
|
@ -2364,36 +2590,40 @@ impl ParsedGenerics {
|
||||||
.clone()
|
.clone()
|
||||||
.into()
|
.into()
|
||||||
};
|
};
|
||||||
let next_generics = if is_last {
|
let make_next_target_args = |next_arg: Option<GenericArgument>| {
|
||||||
|
let generics = if is_last {
|
||||||
&final_generics
|
&final_generics
|
||||||
} else {
|
} else {
|
||||||
&generics_accumulation_types[next_param_count].generics
|
&generics_accumulation_types[next_param_count].generics
|
||||||
};
|
};
|
||||||
|
let type_generics = generics.split_for_impl().1;
|
||||||
|
let turbofish = type_generics.as_turbofish();
|
||||||
|
let mut retval: AngleBracketedGenericArguments = parse_quote! { #turbofish };
|
||||||
|
if let Some(next_arg) = next_arg {
|
||||||
|
*retval.args.last_mut().unwrap() = next_arg;
|
||||||
|
}
|
||||||
|
retval
|
||||||
|
};
|
||||||
let (cur_impl_generics, cur_type_generics, cur_where_clause) =
|
let (cur_impl_generics, cur_type_generics, cur_where_clause) =
|
||||||
cur_generics.split_for_impl();
|
cur_generics.split_for_impl();
|
||||||
let (_next_impl_generics, next_type_generics, _next_where_clause) =
|
|
||||||
next_generics.split_for_impl();
|
|
||||||
let next_turbofish = next_type_generics.as_turbofish();
|
|
||||||
let mut next_target_expr = |context: &MakeHdlTypeExprContext| -> Expr {
|
|
||||||
if is_last {
|
|
||||||
target_expr(context)
|
|
||||||
} else {
|
|
||||||
let args = &context.type_arg_values[..next_param_count];
|
|
||||||
parse_quote_spanned! {ident.span()=>
|
|
||||||
#next_target #next_turbofish(#(#args),*)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
match next_param {
|
match next_param {
|
||||||
ParsedGenericParam::Type(ParsedTypeParam {
|
ParsedGenericParam::Type(ParsedTypeParam {
|
||||||
ident: param_ident,
|
ident: param_ident,
|
||||||
default,
|
default,
|
||||||
..
|
..
|
||||||
}) => {
|
}) => {
|
||||||
let mut generics = next_generics.clone();
|
let next_generics = if is_last {
|
||||||
|
&final_generics
|
||||||
|
} else {
|
||||||
|
&generics_accumulation_types[next_param_count].generics
|
||||||
|
};
|
||||||
|
let (_next_impl_generics, next_type_generics, _next_where_clause) =
|
||||||
|
next_generics.split_for_impl();
|
||||||
|
let next_turbofish = next_type_generics.as_turbofish();
|
||||||
let mut param: Expr = parse_quote_spanned! {ident.span()=>
|
let mut param: Expr = parse_quote_spanned! {ident.span()=>
|
||||||
__param
|
__param
|
||||||
};
|
};
|
||||||
|
let mut generics = next_generics.clone();
|
||||||
let mut index_type = param_ident.clone();
|
let mut index_type = param_ident.clone();
|
||||||
if let Some((_, default)) = default {
|
if let Some((_, default)) = default {
|
||||||
index_type = format_ident!("__Param", span = ident.span());
|
index_type = format_ident!("__Param", span = ident.span());
|
||||||
|
@ -2402,24 +2632,34 @@ impl ParsedGenerics {
|
||||||
#index_type: ::fayalite::ty::TypeOrDefault<#default, Type = #param_ident>
|
#index_type: ::fayalite::ty::TypeOrDefault<#default, Type = #param_ident>
|
||||||
});
|
});
|
||||||
let default_expr = default.make_hdl_type_expr(&MakeHdlTypeExprContext {
|
let default_expr = default.make_hdl_type_expr(&MakeHdlTypeExprContext {
|
||||||
type_arg_values: self_members[..param_count].to_vec(),
|
named_param_values: self_members[..param_count].to_vec(),
|
||||||
is_const: false,
|
is_const: false,
|
||||||
});
|
});
|
||||||
param = parse_quote_spanned! {ident.span()=>
|
param = parse_quote_spanned! {ident.span()=>
|
||||||
::fayalite::ty::TypeOrDefault::get(__param, || #default_expr)
|
::fayalite::ty::TypeOrDefault::get(__param, || #default_expr)
|
||||||
};
|
};
|
||||||
let output_expr = next_target_expr(&MakeHdlTypeExprContext {
|
let context = MakeHdlTypeExprContext {
|
||||||
type_arg_values: self_members[..param_count]
|
named_param_values: self_members[..param_count]
|
||||||
.iter()
|
.iter()
|
||||||
.cloned()
|
.cloned()
|
||||||
.chain([default_expr])
|
.chain([default_expr])
|
||||||
.collect(),
|
.collect(),
|
||||||
is_const: false,
|
is_const: false,
|
||||||
});
|
};
|
||||||
let mut next_target_args: AngleBracketedGenericArguments =
|
let output_expr = {
|
||||||
parse_quote! { #next_type_generics };
|
let next_turbofish = next_type_generics.as_turbofish();
|
||||||
*next_target_args.args.last_mut().unwrap() =
|
if is_last {
|
||||||
GenericArgument::Type(default.clone().into());
|
target_expr(&context)
|
||||||
|
} else {
|
||||||
|
let args = &context.named_param_values[..next_param_count];
|
||||||
|
parse_quote_spanned! {ident.span()=>
|
||||||
|
#next_target #next_turbofish(#(#args),*)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let next_target_args = make_next_target_args(Some(GenericArgument::Type(
|
||||||
|
default.clone().into(),
|
||||||
|
)));
|
||||||
quote_spanned! {ident.span()=>
|
quote_spanned! {ident.span()=>
|
||||||
impl #cur_impl_generics ::fayalite::ty::FillInDefaultedGenerics
|
impl #cur_impl_generics ::fayalite::ty::FillInDefaultedGenerics
|
||||||
for #cur_target #cur_type_generics
|
for #cur_target #cur_type_generics
|
||||||
|
@ -2436,14 +2676,22 @@ impl ParsedGenerics {
|
||||||
.to_tokens(tokens);
|
.to_tokens(tokens);
|
||||||
}
|
}
|
||||||
let (impl_generics, _type_generics, where_clause) = generics.split_for_impl();
|
let (impl_generics, _type_generics, where_clause) = generics.split_for_impl();
|
||||||
let output_expr = next_target_expr(&MakeHdlTypeExprContext {
|
let context = MakeHdlTypeExprContext {
|
||||||
type_arg_values: self_members[..param_count]
|
named_param_values: self_members[..param_count]
|
||||||
.iter()
|
.iter()
|
||||||
.cloned()
|
.cloned()
|
||||||
.chain([param])
|
.chain([param])
|
||||||
.collect(),
|
.collect(),
|
||||||
is_const: false,
|
is_const: false,
|
||||||
});
|
};
|
||||||
|
let output_expr = if is_last {
|
||||||
|
target_expr(&context)
|
||||||
|
} else {
|
||||||
|
let args = &context.named_param_values[..next_param_count];
|
||||||
|
parse_quote_spanned! {ident.span()=>
|
||||||
|
#next_target #next_turbofish(#(#args),*)
|
||||||
|
}
|
||||||
|
};
|
||||||
quote_spanned! {ident.span()=>
|
quote_spanned! {ident.span()=>
|
||||||
#[allow(non_upper_case_globals)]
|
#[allow(non_upper_case_globals)]
|
||||||
#[automatically_derived]
|
#[automatically_derived]
|
||||||
|
@ -2468,9 +2716,9 @@ impl ParsedGenerics {
|
||||||
default,
|
default,
|
||||||
..
|
..
|
||||||
}) => {
|
}) => {
|
||||||
if bounds.KnownSize.is_none() {
|
{
|
||||||
let output_expr = next_target_expr(&MakeHdlTypeExprContext {
|
let context = MakeHdlTypeExprContext {
|
||||||
type_arg_values: self_members[..param_count]
|
named_param_values: self_members[..param_count]
|
||||||
.iter()
|
.iter()
|
||||||
.cloned()
|
.cloned()
|
||||||
.chain([parse_quote_spanned! {ident.span()=>
|
.chain([parse_quote_spanned! {ident.span()=>
|
||||||
|
@ -2478,80 +2726,42 @@ impl ParsedGenerics {
|
||||||
}])
|
}])
|
||||||
.collect(),
|
.collect(),
|
||||||
is_const: false,
|
is_const: false,
|
||||||
});
|
|
||||||
let mut next_target_args: AngleBracketedGenericArguments =
|
|
||||||
parse_quote! { #next_type_generics };
|
|
||||||
*next_target_args.args.last_mut().unwrap() = parse_quote_spanned! {ident.span()=>
|
|
||||||
::fayalite::int::DynSize
|
|
||||||
};
|
};
|
||||||
quote_spanned! {ident.span()=>
|
let next_target_args =
|
||||||
#[allow(non_upper_case_globals)]
|
make_next_target_args(Some(parse_quote_spanned! {ident.span()=>
|
||||||
#[automatically_derived]
|
<#param_ident as ::fayalite::int::SizeType>::Size
|
||||||
impl #cur_impl_generics ::fayalite::__std::ops::Index<::fayalite::__std::primitive::usize>
|
}));
|
||||||
for #cur_target #cur_type_generics
|
let output_expr = if is_last {
|
||||||
#cur_where_clause
|
target_expr(&context)
|
||||||
{
|
} else {
|
||||||
type Output = #next_target #next_target_args;
|
let args = &context.named_param_values[..next_param_count];
|
||||||
|
parse_quote_spanned! {ident.span()=>
|
||||||
fn index(
|
#next_target #next_target_args(#(#args),*)
|
||||||
&self,
|
|
||||||
__param: ::fayalite::__std::primitive::usize,
|
|
||||||
) -> &Self::Output {
|
|
||||||
::fayalite::intern::Interned::<_>::into_inner(
|
|
||||||
::fayalite::intern::Intern::intern_sized(#output_expr),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
}
|
|
||||||
.to_tokens(tokens);
|
|
||||||
}
|
|
||||||
{
|
|
||||||
let output_expr = next_target_expr(&MakeHdlTypeExprContext {
|
|
||||||
type_arg_values: self_members[..param_count]
|
|
||||||
.iter()
|
|
||||||
.cloned()
|
|
||||||
.chain([parse_quote_spanned! {ident.span()=>
|
|
||||||
__param
|
|
||||||
}])
|
|
||||||
.collect(),
|
|
||||||
is_const: false,
|
|
||||||
});
|
|
||||||
let mut next_generics = cur_generics.clone();
|
let mut next_generics = cur_generics.clone();
|
||||||
next_generics
|
next_generics
|
||||||
.params
|
.params
|
||||||
.push(parse_quote_spanned! {ident.span()=>
|
.push(parse_quote_spanned! {ident.span()=>
|
||||||
const #param_ident: ::fayalite::__std::primitive::usize
|
#param_ident: ::fayalite::int::SizeType
|
||||||
});
|
});
|
||||||
let known_size = bounds
|
|
||||||
.KnownSize
|
|
||||||
.clone()
|
|
||||||
.unwrap_or_else(|| known_items::KnownSize(ident.span()));
|
|
||||||
next_generics.make_where_clause().predicates.push(
|
next_generics.make_where_clause().predicates.push(
|
||||||
parse_quote_spanned! {ident.span()=>
|
parse_quote_spanned! {ident.span()=>
|
||||||
::fayalite::util::ConstUsize<#param_ident>: #known_size
|
<#param_ident as ::fayalite::int::SizeType>::Size: #bounds
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
let (next_impl_generics, next_type_generics, next_where_clause) =
|
let (next_impl_generics, _next_type_generics, next_where_clause) =
|
||||||
next_generics.split_for_impl();
|
next_generics.split_for_impl();
|
||||||
let mut next_target_args: AngleBracketedGenericArguments =
|
|
||||||
parse_quote! { #next_type_generics };
|
|
||||||
*next_target_args.args.last_mut().unwrap() = parse_quote_spanned! {ident.span()=>
|
|
||||||
::fayalite::util::ConstUsize<#param_ident>
|
|
||||||
};
|
|
||||||
quote_spanned! {ident.span()=>
|
quote_spanned! {ident.span()=>
|
||||||
#[allow(non_upper_case_globals)]
|
#[allow(non_upper_case_globals)]
|
||||||
#[automatically_derived]
|
#[automatically_derived]
|
||||||
impl #next_impl_generics ::fayalite::__std::ops::Index<
|
impl #next_impl_generics ::fayalite::__std::ops::Index<#param_ident>
|
||||||
::fayalite::util::ConstUsize<#param_ident>,
|
for #cur_target #cur_type_generics
|
||||||
> for #cur_target #cur_type_generics
|
|
||||||
#next_where_clause
|
#next_where_clause
|
||||||
{
|
{
|
||||||
type Output = #next_target #next_target_args;
|
type Output = #next_target #next_target_args;
|
||||||
|
|
||||||
fn index(
|
fn index(&self, __param: #param_ident) -> &Self::Output {
|
||||||
&self,
|
|
||||||
__param: ::fayalite::util::ConstUsize<#param_ident>,
|
|
||||||
) -> &Self::Output {
|
|
||||||
::fayalite::intern::Interned::<_>::into_inner(
|
::fayalite::intern::Interned::<_>::into_inner(
|
||||||
::fayalite::intern::Intern::intern_sized(#output_expr),
|
::fayalite::intern::Intern::intern_sized(#output_expr),
|
||||||
)
|
)
|
||||||
|
@ -2565,7 +2775,71 @@ impl ParsedGenerics {
|
||||||
todo!();
|
todo!();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ParsedGenericParam::Const(_) => todo!(),
|
ParsedGenericParam::Const(ParsedConstParam {
|
||||||
|
attrs: _,
|
||||||
|
options: _,
|
||||||
|
const_token,
|
||||||
|
ident: param_ident,
|
||||||
|
colon_token,
|
||||||
|
ty: ParsedConstGenericType::Usize(ty),
|
||||||
|
bounds: ParsedConstParamWhereBounds { bounds, .. },
|
||||||
|
}) => {
|
||||||
|
let context = MakeHdlTypeExprContext {
|
||||||
|
named_param_values: self_members[..param_count]
|
||||||
|
.iter()
|
||||||
|
.cloned()
|
||||||
|
.chain([parse_quote_spanned! {ident.span()=>
|
||||||
|
__param
|
||||||
|
}])
|
||||||
|
.collect(),
|
||||||
|
is_const: false,
|
||||||
|
};
|
||||||
|
let next_target_args =
|
||||||
|
make_next_target_args(Some(parse_quote! { #param_ident }));
|
||||||
|
let output_expr = if is_last {
|
||||||
|
target_expr(&context)
|
||||||
|
} else {
|
||||||
|
let args = &context.named_param_values[..next_param_count];
|
||||||
|
parse_quote_spanned! {ident.span()=>
|
||||||
|
#next_target #next_target_args(#(#args),*)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let mut next_generics = cur_generics.clone();
|
||||||
|
next_generics
|
||||||
|
.params
|
||||||
|
.push(parse_quote! { #const_token #param_ident #colon_token #ty });
|
||||||
|
next_generics
|
||||||
|
.params
|
||||||
|
.push(parse_quote_spanned! {ident.span()=>
|
||||||
|
__Param: ::fayalite::int::SizeType<
|
||||||
|
Size = ::fayalite::util::ConstUsize<#param_ident>,
|
||||||
|
>
|
||||||
|
});
|
||||||
|
next_generics.make_where_clause().predicates.push(
|
||||||
|
parse_quote_spanned! {ident.span()=>
|
||||||
|
::fayalite::util::ConstUsize<#param_ident>: ::fayalite::int::Size<SizeType = __Param> + #bounds
|
||||||
|
},
|
||||||
|
);
|
||||||
|
let (next_impl_generics, _next_type_generics, next_where_clause) =
|
||||||
|
next_generics.split_for_impl();
|
||||||
|
quote_spanned! {ident.span()=>
|
||||||
|
#[allow(non_upper_case_globals)]
|
||||||
|
#[automatically_derived]
|
||||||
|
impl #next_impl_generics ::fayalite::__std::ops::Index<__Param>
|
||||||
|
for #cur_target #cur_type_generics
|
||||||
|
#next_where_clause
|
||||||
|
{
|
||||||
|
type Output = #next_target #next_target_args;
|
||||||
|
|
||||||
|
fn index(&self, __param: __Param) -> &Self::Output {
|
||||||
|
::fayalite::intern::Interned::<_>::into_inner(
|
||||||
|
::fayalite::intern::Intern::intern_sized(#output_expr),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.to_tokens(tokens);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3145,7 +3419,8 @@ impl ToTokens for ParsedGenericsWhereClause<'_> {
|
||||||
let mut where_token = |span: Span| -> Option<Token![where]> {
|
let mut where_token = |span: Span| -> Option<Token![where]> {
|
||||||
mem::replace(&mut need_where_token, false).then(|| Token![where](span))
|
mem::replace(&mut need_where_token, false).then(|| Token![where](span))
|
||||||
};
|
};
|
||||||
for param in self.generics.params.iter().take(self.param_count) {
|
for param in self.generics.params.pairs().take(self.param_count) {
|
||||||
|
let (param, comma_token) = param.into_tuple();
|
||||||
match param {
|
match param {
|
||||||
ParsedGenericParam::Type(ParsedTypeParam {
|
ParsedGenericParam::Type(ParsedTypeParam {
|
||||||
ident,
|
ident,
|
||||||
|
@ -3156,7 +3431,7 @@ impl ToTokens for ParsedGenericsWhereClause<'_> {
|
||||||
if let Some(static_type) = &bounds.StaticType {
|
if let Some(static_type) = &bounds.StaticType {
|
||||||
where_token(static_type.span).to_tokens(tokens);
|
where_token(static_type.span).to_tokens(tokens);
|
||||||
quote_spanned! {static_type.span=>
|
quote_spanned! {static_type.span=>
|
||||||
<#ident as ::fayalite::ty::Type>::MaskType #colon_token #static_type,
|
<#ident as ::fayalite::ty::Type>::MaskType #colon_token #static_type #comma_token
|
||||||
}
|
}
|
||||||
.to_tokens(tokens);
|
.to_tokens(tokens);
|
||||||
}
|
}
|
||||||
|
@ -3182,6 +3457,7 @@ impl ToTokens for ParsedGenericsWhereClause<'_> {
|
||||||
gt_token.to_tokens(tokens);
|
gt_token.to_tokens(tokens);
|
||||||
colon_token.to_tokens(tokens);
|
colon_token.to_tokens(tokens);
|
||||||
bounds.to_tokens(tokens);
|
bounds.to_tokens(tokens);
|
||||||
|
comma_token.to_tokens(tokens);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3649,7 +3925,7 @@ impl From<MaybeParsed<ParsedFieldsNamed, FieldsNamed>> for FieldsNamed {
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub(crate) struct MakeHdlTypeExprContext {
|
pub(crate) struct MakeHdlTypeExprContext {
|
||||||
pub(crate) type_arg_values: Vec<Expr>,
|
pub(crate) named_param_values: Vec<Expr>,
|
||||||
pub(crate) is_const: bool,
|
pub(crate) is_const: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3694,6 +3970,28 @@ impl MakeHdlTypeExpr for known_items::DynSize {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl MakeHdlTypeExpr for ParsedExprDelimited {
|
||||||
|
fn make_hdl_type_expr(&self, context: &MakeHdlTypeExprContext) -> Expr {
|
||||||
|
self.expr.make_hdl_type_expr(context)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MakeHdlTypeExpr for ParsedExprNamedParamConst {
|
||||||
|
fn make_hdl_type_expr(&self, context: &MakeHdlTypeExprContext) -> Expr {
|
||||||
|
context.named_param_values[self.param_index].clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MakeHdlTypeExpr for ParsedExpr {
|
||||||
|
fn make_hdl_type_expr(&self, context: &MakeHdlTypeExprContext) -> Expr {
|
||||||
|
match self {
|
||||||
|
ParsedExpr::Delimited(expr) => expr.make_hdl_type_expr(context),
|
||||||
|
ParsedExpr::NamedParamConst(expr) => expr.make_hdl_type_expr(context),
|
||||||
|
ParsedExpr::Other(expr) => (**expr).clone(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl MakeHdlTypeExpr for ParsedTypeDelimited {
|
impl MakeHdlTypeExpr for ParsedTypeDelimited {
|
||||||
fn make_hdl_type_expr(&self, context: &MakeHdlTypeExprContext) -> Expr {
|
fn make_hdl_type_expr(&self, context: &MakeHdlTypeExprContext) -> Expr {
|
||||||
self.elem.make_hdl_type_expr(context)
|
self.elem.make_hdl_type_expr(context)
|
||||||
|
@ -3743,7 +4041,7 @@ impl MakeHdlTypeExpr for ParsedGenericArgument {
|
||||||
fn make_hdl_type_expr(&self, context: &MakeHdlTypeExprContext) -> Expr {
|
fn make_hdl_type_expr(&self, context: &MakeHdlTypeExprContext) -> Expr {
|
||||||
match self {
|
match self {
|
||||||
ParsedGenericArgument::Type(v) => v.make_hdl_type_expr(context),
|
ParsedGenericArgument::Type(v) => v.make_hdl_type_expr(context),
|
||||||
ParsedGenericArgument::Const(v) => v.clone(),
|
ParsedGenericArgument::Const(v) => v.make_hdl_type_expr(context),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3759,13 +4057,13 @@ impl MakeHdlTypeExpr for ParsedTypeNamedParam {
|
||||||
|
|
||||||
impl MakeHdlTypeExpr for ParsedTypeNamedParamType {
|
impl MakeHdlTypeExpr for ParsedTypeNamedParamType {
|
||||||
fn make_hdl_type_expr(&self, context: &MakeHdlTypeExprContext) -> Expr {
|
fn make_hdl_type_expr(&self, context: &MakeHdlTypeExprContext) -> Expr {
|
||||||
context.type_arg_values[self.param_index].clone()
|
context.named_param_values[self.param_index].clone()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MakeHdlTypeExpr for ParsedTypeNamedParamSizeType {
|
impl MakeHdlTypeExpr for ParsedTypeNamedParamSizeType {
|
||||||
fn make_hdl_type_expr(&self, context: &MakeHdlTypeExprContext) -> Expr {
|
fn make_hdl_type_expr(&self, context: &MakeHdlTypeExprContext) -> Expr {
|
||||||
context.type_arg_values[self.param_index].clone()
|
context.named_param_values[self.param_index].clone()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
expr::{ops::ArrayIndex, Expr, ToExpr},
|
expr::{ops::ArrayIndex, Expr, ToExpr},
|
||||||
int::{DynSize, KnownSize, Size},
|
int::{DynSize, KnownSize, Size, SizeType, DYN_SIZE},
|
||||||
intern::{Intern, Interned, LazyInterned},
|
intern::{Intern, Interned, LazyInterned},
|
||||||
module::transform::visit::{Fold, Folder, Visit, Visitor},
|
module::transform::visit::{Fold, Folder, Visit, Visitor},
|
||||||
source_location::SourceLocation,
|
source_location::SourceLocation,
|
||||||
|
@ -27,10 +27,7 @@ impl<T: Type, Len: Size> std::fmt::Debug for ArrayType<T, Len> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type Array<
|
pub type Array<T = CanonicalType, const LEN: usize = DYN_SIZE> = ArrayType<T, ConstUsize<LEN>>;
|
||||||
T = CanonicalType,
|
|
||||||
const LEN: usize = { <DynSize as crate::util::GenericConstUsize>::VALUE },
|
|
||||||
> = ArrayType<T, ConstUsize<LEN>>;
|
|
||||||
|
|
||||||
#[allow(non_upper_case_globals)]
|
#[allow(non_upper_case_globals)]
|
||||||
pub const Array: ArrayWithoutGenerics = ArrayWithoutGenerics;
|
pub const Array: ArrayWithoutGenerics = ArrayWithoutGenerics;
|
||||||
|
@ -214,21 +211,10 @@ pub struct ArrayWithoutLen<T: Type> {
|
||||||
element: T,
|
element: T,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Type> Index<usize> for ArrayWithoutLen<T> {
|
impl<T: Type, L: SizeType> Index<L> for ArrayWithoutLen<T> {
|
||||||
type Output = Array<T>;
|
type Output = ArrayType<T, L::Size>;
|
||||||
|
|
||||||
fn index(&self, len: usize) -> &Self::Output {
|
fn index(&self, len: L) -> &Self::Output {
|
||||||
Interned::<_>::into_inner(Intern::intern_sized(Array::new_dyn(self.element, len)))
|
Interned::<_>::into_inner(Intern::intern_sized(ArrayType::new(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)))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,7 @@ use std::{
|
||||||
mod sealed {
|
mod sealed {
|
||||||
pub trait BoolOrIntTypeSealed {}
|
pub trait BoolOrIntTypeSealed {}
|
||||||
pub trait SizeSealed {}
|
pub trait SizeSealed {}
|
||||||
|
pub trait SizeTypeSealed {}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const DYN_SIZE: usize = !0;
|
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]);
|
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:
|
pub trait Size:
|
||||||
sealed::SizeSealed + Copy + Ord + std::hash::Hash + std::fmt::Debug + Send + Sync + 'static
|
sealed::SizeSealed + Copy + Ord + std::hash::Hash + std::fmt::Debug + Send + Sync + 'static
|
||||||
{
|
{
|
||||||
|
@ -76,7 +83,14 @@ pub trait Size:
|
||||||
+ TryFrom<Vec<Expr<Element>>>
|
+ TryFrom<Vec<Expr<Element>>>
|
||||||
+ Into<Vec<Expr<Element>>>;
|
+ Into<Vec<Expr<Element>>>;
|
||||||
const KNOWN_VALUE: Option<usize>;
|
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 as_usize(size_type: Self::SizeType) -> usize;
|
||||||
fn try_from_usize(v: usize) -> Option<Self::SizeType>;
|
fn try_from_usize(v: usize) -> Option<Self::SizeType>;
|
||||||
#[track_caller]
|
#[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 {
|
impl Size for DynSize {
|
||||||
type ArrayMatch<Element: Type> = Box<[Expr<Element>]>;
|
type ArrayMatch<Element: Type> = Box<[Expr<Element>]>;
|
||||||
const KNOWN_VALUE: Option<usize> = None;
|
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::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>
|
impl<const VALUE: usize> Size for ConstUsize<VALUE>
|
||||||
where
|
where
|
||||||
ConstUsize<VALUE>: KnownSize,
|
ConstUsize<VALUE>: KnownSize,
|
||||||
|
@ -138,9 +167,7 @@ macro_rules! impl_int {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type $pretty_name<
|
pub type $pretty_name<const WIDTH: usize = DYN_SIZE> = $name<ConstUsize<WIDTH>>;
|
||||||
const WIDTH: usize = { <DynSize as crate::util::GenericConstUsize>::VALUE },
|
|
||||||
> = $name<ConstUsize<WIDTH>>;
|
|
||||||
|
|
||||||
#[allow(non_upper_case_globals)]
|
#[allow(non_upper_case_globals)]
|
||||||
pub const $pretty_name: $generic_name = $generic_name;
|
pub const $pretty_name: $generic_name = $generic_name;
|
||||||
|
@ -269,21 +296,10 @@ macro_rules! impl_int {
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, Default)]
|
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, Default)]
|
||||||
pub struct $generic_name;
|
pub struct $generic_name;
|
||||||
|
|
||||||
impl Index<usize> for $generic_name {
|
impl<Width: SizeType> Index<Width> for $generic_name {
|
||||||
type Output = $name;
|
type Output = $name<Width::Size>;
|
||||||
|
|
||||||
fn index(&self, width: usize) -> &Self::Output {
|
fn index(&self, width: Width) -> &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 {
|
|
||||||
Interned::<_>::into_inner(Intern::intern_sized($name::new(width)))
|
Interned::<_>::into_inner(Intern::intern_sized($name::new(width)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,16 +1,22 @@
|
||||||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||||
// See Notices.txt for copyright information
|
// See Notices.txt for copyright information
|
||||||
use fayalite::{
|
use fayalite::prelude::*;
|
||||||
array::ArrayType,
|
|
||||||
hdl,
|
|
||||||
int::{IntType, Size, UInt},
|
|
||||||
};
|
|
||||||
|
|
||||||
#[hdl(outline_generated)]
|
#[hdl(outline_generated)]
|
||||||
pub struct S<T: IntType, Len: Size> {
|
pub struct S<T, Len: Size, T2> {
|
||||||
pub a: T,
|
pub a: T,
|
||||||
b: UInt<3>,
|
b: UInt<3>,
|
||||||
pub(crate) c: ArrayType<UInt<1>, Len>,
|
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)]
|
#[hdl(outline_generated)]
|
||||||
|
|
Loading…
Reference in a new issue