Compare commits
No commits in common. "51ce7b079ec1b0ea53c31348be86f5c2fb52c124" and "a8c804ef4adef1879c2e1b3d9433bfe30c1d57cc" have entirely different histories.
51ce7b079e
...
a8c804ef4a
15 changed files with 179 additions and 928 deletions
|
|
@ -19,13 +19,13 @@ use syn::{
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub(crate) struct ParsedBundle {
|
pub(crate) struct ParsedBundle {
|
||||||
pub(crate) attrs: Vec<Attribute>,
|
pub(crate) attrs: Vec<Attribute>,
|
||||||
pub(crate) options: HdlAttr<ItemOptions, kw::hdl>,
|
pub(crate) options: HdlAttr<ItemOptions>,
|
||||||
pub(crate) vis: Visibility,
|
pub(crate) vis: Visibility,
|
||||||
pub(crate) struct_token: Token![struct],
|
pub(crate) struct_token: Token![struct],
|
||||||
pub(crate) ident: Ident,
|
pub(crate) ident: Ident,
|
||||||
pub(crate) generics: MaybeParsed<ParsedGenerics, Generics>,
|
pub(crate) generics: MaybeParsed<ParsedGenerics, Generics>,
|
||||||
pub(crate) fields: MaybeParsed<ParsedFieldsNamed, FieldsNamed>,
|
pub(crate) fields: MaybeParsed<ParsedFieldsNamed, FieldsNamed>,
|
||||||
pub(crate) field_flips: Vec<Option<HdlAttr<kw::flip, kw::hdl>>>,
|
pub(crate) field_flips: Vec<Option<HdlAttr<kw::flip>>>,
|
||||||
pub(crate) mask_type_ident: Ident,
|
pub(crate) mask_type_ident: Ident,
|
||||||
pub(crate) mask_type_match_variant_ident: Ident,
|
pub(crate) mask_type_match_variant_ident: Ident,
|
||||||
pub(crate) match_variant_ident: Ident,
|
pub(crate) match_variant_ident: Ident,
|
||||||
|
|
@ -38,7 +38,7 @@ impl ParsedBundle {
|
||||||
errors: &mut Errors,
|
errors: &mut Errors,
|
||||||
field: &mut Field,
|
field: &mut Field,
|
||||||
index: usize,
|
index: usize,
|
||||||
) -> Option<HdlAttr<kw::flip, kw::hdl>> {
|
) -> Option<HdlAttr<kw::flip>> {
|
||||||
let Field {
|
let Field {
|
||||||
attrs,
|
attrs,
|
||||||
vis: _,
|
vis: _,
|
||||||
|
|
@ -71,9 +71,7 @@ impl ParsedBundle {
|
||||||
} = item;
|
} = item;
|
||||||
let mut errors = Errors::new();
|
let mut errors = Errors::new();
|
||||||
let mut options = errors
|
let mut options = errors
|
||||||
.unwrap_or_default(HdlAttr::<ItemOptions, kw::hdl>::parse_and_take_attr(
|
.unwrap_or_default(HdlAttr::<ItemOptions>::parse_and_take_attr(&mut attrs))
|
||||||
&mut attrs,
|
|
||||||
))
|
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
errors.ok(options.body.validate());
|
errors.ok(options.body.validate());
|
||||||
let ItemOptions {
|
let ItemOptions {
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ use crate::{
|
||||||
common_derives, get_target, ItemOptions, MakeHdlTypeExpr, MaybeParsed, ParsedGenerics,
|
common_derives, get_target, ItemOptions, MakeHdlTypeExpr, MaybeParsed, ParsedGenerics,
|
||||||
ParsedType, SplitForImpl, TypesParser, WrappedInConst,
|
ParsedType, SplitForImpl, TypesParser, WrappedInConst,
|
||||||
},
|
},
|
||||||
kw, Errors, HdlAttr, PairsIterExt,
|
Errors, HdlAttr, PairsIterExt,
|
||||||
};
|
};
|
||||||
use proc_macro2::TokenStream;
|
use proc_macro2::TokenStream;
|
||||||
use quote::{format_ident, quote_spanned, ToTokens};
|
use quote::{format_ident, quote_spanned, ToTokens};
|
||||||
|
|
@ -29,7 +29,7 @@ crate::options! {
|
||||||
pub(crate) struct ParsedVariantField {
|
pub(crate) struct ParsedVariantField {
|
||||||
pub(crate) paren_token: Paren,
|
pub(crate) paren_token: Paren,
|
||||||
pub(crate) attrs: Vec<Attribute>,
|
pub(crate) attrs: Vec<Attribute>,
|
||||||
pub(crate) options: HdlAttr<FieldOptions, kw::hdl>,
|
pub(crate) options: HdlAttr<FieldOptions>,
|
||||||
pub(crate) ty: MaybeParsed<ParsedType, Type>,
|
pub(crate) ty: MaybeParsed<ParsedType, Type>,
|
||||||
pub(crate) comma_token: Option<Token![,]>,
|
pub(crate) comma_token: Option<Token![,]>,
|
||||||
}
|
}
|
||||||
|
|
@ -37,7 +37,7 @@ pub(crate) struct ParsedVariantField {
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub(crate) struct ParsedVariant {
|
pub(crate) struct ParsedVariant {
|
||||||
pub(crate) attrs: Vec<Attribute>,
|
pub(crate) attrs: Vec<Attribute>,
|
||||||
pub(crate) options: HdlAttr<VariantOptions, kw::hdl>,
|
pub(crate) options: HdlAttr<VariantOptions>,
|
||||||
pub(crate) ident: Ident,
|
pub(crate) ident: Ident,
|
||||||
pub(crate) field: Option<ParsedVariantField>,
|
pub(crate) field: Option<ParsedVariantField>,
|
||||||
}
|
}
|
||||||
|
|
@ -119,7 +119,7 @@ impl ParsedVariant {
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub(crate) struct ParsedEnum {
|
pub(crate) struct ParsedEnum {
|
||||||
pub(crate) attrs: Vec<Attribute>,
|
pub(crate) attrs: Vec<Attribute>,
|
||||||
pub(crate) options: HdlAttr<ItemOptions, kw::hdl>,
|
pub(crate) options: HdlAttr<ItemOptions>,
|
||||||
pub(crate) vis: Visibility,
|
pub(crate) vis: Visibility,
|
||||||
pub(crate) enum_token: Token![enum],
|
pub(crate) enum_token: Token![enum],
|
||||||
pub(crate) ident: Ident,
|
pub(crate) ident: Ident,
|
||||||
|
|
@ -142,9 +142,7 @@ impl ParsedEnum {
|
||||||
} = item;
|
} = item;
|
||||||
let mut errors = Errors::new();
|
let mut errors = Errors::new();
|
||||||
let mut options = errors
|
let mut options = errors
|
||||||
.unwrap_or_default(HdlAttr::<ItemOptions, kw::hdl>::parse_and_take_attr(
|
.unwrap_or_default(HdlAttr::<ItemOptions>::parse_and_take_attr(&mut attrs))
|
||||||
&mut attrs,
|
|
||||||
))
|
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
errors.ok(options.body.validate());
|
errors.ok(options.body.validate());
|
||||||
let ItemOptions {
|
let ItemOptions {
|
||||||
|
|
|
||||||
|
|
@ -1745,7 +1745,7 @@ impl<T: ParseTypes<I>, I, P: Clone> ParseTypes<Punctuated<I, P>> for Punctuated<
|
||||||
pub(crate) enum UnparsedGenericParam {
|
pub(crate) enum UnparsedGenericParam {
|
||||||
Type {
|
Type {
|
||||||
attrs: Vec<Attribute>,
|
attrs: Vec<Attribute>,
|
||||||
options: HdlAttr<TypeParamOptions, kw::hdl>,
|
options: HdlAttr<TypeParamOptions>,
|
||||||
ident: Ident,
|
ident: Ident,
|
||||||
colon_token: Token![:],
|
colon_token: Token![:],
|
||||||
bounds: ParsedBounds,
|
bounds: ParsedBounds,
|
||||||
|
|
@ -1753,7 +1753,7 @@ pub(crate) enum UnparsedGenericParam {
|
||||||
},
|
},
|
||||||
Const {
|
Const {
|
||||||
attrs: Vec<Attribute>,
|
attrs: Vec<Attribute>,
|
||||||
options: HdlAttr<ConstParamOptions, kw::hdl>,
|
options: HdlAttr<ConstParamOptions>,
|
||||||
const_token: Token![const],
|
const_token: Token![const],
|
||||||
ident: Ident,
|
ident: Ident,
|
||||||
colon_token: Token![:],
|
colon_token: Token![:],
|
||||||
|
|
@ -2278,7 +2278,7 @@ impl ParsedBound {
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub(crate) struct ParsedTypeParam {
|
pub(crate) struct ParsedTypeParam {
|
||||||
pub(crate) attrs: Vec<Attribute>,
|
pub(crate) attrs: Vec<Attribute>,
|
||||||
pub(crate) options: HdlAttr<TypeParamOptions, kw::hdl>,
|
pub(crate) options: HdlAttr<TypeParamOptions>,
|
||||||
pub(crate) ident: Ident,
|
pub(crate) ident: Ident,
|
||||||
pub(crate) colon_token: Token![:],
|
pub(crate) colon_token: Token![:],
|
||||||
pub(crate) bounds: ParsedTypeBounds,
|
pub(crate) bounds: ParsedTypeBounds,
|
||||||
|
|
@ -2312,7 +2312,7 @@ impl ToTokens for ParsedTypeParam {
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub(crate) struct ParsedSizeTypeParam {
|
pub(crate) struct ParsedSizeTypeParam {
|
||||||
pub(crate) attrs: Vec<Attribute>,
|
pub(crate) attrs: Vec<Attribute>,
|
||||||
pub(crate) options: HdlAttr<TypeParamOptions, kw::hdl>,
|
pub(crate) options: HdlAttr<TypeParamOptions>,
|
||||||
pub(crate) ident: Ident,
|
pub(crate) ident: Ident,
|
||||||
pub(crate) colon_token: Token![:],
|
pub(crate) colon_token: Token![:],
|
||||||
pub(crate) bounds: ParsedSizeTypeBounds,
|
pub(crate) bounds: ParsedSizeTypeBounds,
|
||||||
|
|
@ -2356,7 +2356,7 @@ pub(crate) struct ParsedConstParamWhereBounds {
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub(crate) struct ParsedConstParam {
|
pub(crate) struct ParsedConstParam {
|
||||||
pub(crate) attrs: Vec<Attribute>,
|
pub(crate) attrs: Vec<Attribute>,
|
||||||
pub(crate) options: HdlAttr<ConstParamOptions, kw::hdl>,
|
pub(crate) options: HdlAttr<ConstParamOptions>,
|
||||||
pub(crate) const_token: Token![const],
|
pub(crate) const_token: Token![const],
|
||||||
pub(crate) ident: Ident,
|
pub(crate) ident: Ident,
|
||||||
pub(crate) colon_token: Token![:],
|
pub(crate) colon_token: Token![:],
|
||||||
|
|
@ -2413,7 +2413,7 @@ impl ParsedGenericParam {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Default)]
|
#[derive(Debug, Clone)]
|
||||||
pub(crate) struct ParsedGenerics {
|
pub(crate) struct ParsedGenerics {
|
||||||
pub(crate) lt_token: Option<Token![<]>,
|
pub(crate) lt_token: Option<Token![<]>,
|
||||||
pub(crate) params: Punctuated<ParsedGenericParam, Token![,]>,
|
pub(crate) params: Punctuated<ParsedGenericParam, Token![,]>,
|
||||||
|
|
@ -2863,11 +2863,9 @@ impl ParsedGenerics {
|
||||||
let (input_param, punct) = input_param.into_tuple();
|
let (input_param, punct) = input_param.into_tuple();
|
||||||
let (unparsed_param, late_parsed_param) = match input_param {
|
let (unparsed_param, late_parsed_param) = match input_param {
|
||||||
GenericParam::Lifetime(param) => {
|
GenericParam::Lifetime(param) => {
|
||||||
errors.unwrap_or_default(
|
errors.unwrap_or_default(HdlAttr::<LifetimeParamOptions>::parse_and_take_attr(
|
||||||
HdlAttr::<LifetimeParamOptions, kw::hdl>::parse_and_take_attr(
|
|
||||||
&mut param.attrs,
|
&mut param.attrs,
|
||||||
),
|
));
|
||||||
);
|
|
||||||
errors.error(param, "lifetime generics are not supported by #[hdl]");
|
errors.error(param, "lifetime generics are not supported by #[hdl]");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
@ -2881,9 +2879,7 @@ impl ParsedGenerics {
|
||||||
}) => {
|
}) => {
|
||||||
let span = ident.span();
|
let span = ident.span();
|
||||||
let options = errors
|
let options = errors
|
||||||
.unwrap_or_default(
|
.unwrap_or_default(HdlAttr::<TypeParamOptions>::parse_and_take_attr(attrs))
|
||||||
HdlAttr::<TypeParamOptions, kw::hdl>::parse_and_take_attr(attrs),
|
|
||||||
)
|
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
let colon_token = colon_token.unwrap_or_else(|| Token);
|
let colon_token = colon_token.unwrap_or_else(|| Token);
|
||||||
if !bounds.is_empty() {
|
if !bounds.is_empty() {
|
||||||
|
|
@ -2921,9 +2917,7 @@ impl ParsedGenerics {
|
||||||
default,
|
default,
|
||||||
}) => {
|
}) => {
|
||||||
let options = errors
|
let options = errors
|
||||||
.unwrap_or_default(
|
.unwrap_or_default(HdlAttr::<ConstParamOptions>::parse_and_take_attr(attrs))
|
||||||
HdlAttr::<ConstParamOptions, kw::hdl>::parse_and_take_attr(attrs),
|
|
||||||
)
|
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
if let Some(default) = default {
|
if let Some(default) = default {
|
||||||
let _ = eq_token;
|
let _ = eq_token;
|
||||||
|
|
|
||||||
|
|
@ -9,8 +9,7 @@ use syn::{
|
||||||
parse::{Parse, ParseStream, Parser},
|
parse::{Parse, ParseStream, Parser},
|
||||||
parse_quote,
|
parse_quote,
|
||||||
punctuated::Pair,
|
punctuated::Pair,
|
||||||
spanned::Spanned,
|
AttrStyle, Attribute, Error, Item, Token,
|
||||||
AttrStyle, Attribute, Error, Item, ItemFn, Token,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
mod fold;
|
mod fold;
|
||||||
|
|
@ -18,20 +17,8 @@ mod hdl_bundle;
|
||||||
mod hdl_enum;
|
mod hdl_enum;
|
||||||
mod hdl_type_common;
|
mod hdl_type_common;
|
||||||
mod module;
|
mod module;
|
||||||
|
//mod value_derive_common;
|
||||||
pub(crate) trait CustomToken:
|
//mod value_derive_struct;
|
||||||
Copy
|
|
||||||
+ Spanned
|
|
||||||
+ ToTokens
|
|
||||||
+ std::fmt::Debug
|
|
||||||
+ Eq
|
|
||||||
+ std::hash::Hash
|
|
||||||
+ Default
|
|
||||||
+ quote::IdentFragment
|
|
||||||
+ Parse
|
|
||||||
{
|
|
||||||
const IDENT_STR: &'static str;
|
|
||||||
}
|
|
||||||
|
|
||||||
mod kw {
|
mod kw {
|
||||||
pub(crate) use syn::token::Extern as extern_;
|
pub(crate) use syn::token::Extern as extern_;
|
||||||
|
|
@ -51,10 +38,6 @@ mod kw {
|
||||||
}
|
}
|
||||||
|
|
||||||
crate::fold::no_op_fold!($kw);
|
crate::fold::no_op_fold!($kw);
|
||||||
|
|
||||||
impl crate::CustomToken for $kw {
|
|
||||||
const IDENT_STR: &'static str = stringify!($kw);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -63,9 +46,7 @@ mod kw {
|
||||||
custom_keyword!(custom_bounds);
|
custom_keyword!(custom_bounds);
|
||||||
custom_keyword!(flip);
|
custom_keyword!(flip);
|
||||||
custom_keyword!(hdl);
|
custom_keyword!(hdl);
|
||||||
custom_keyword!(hdl_module);
|
|
||||||
custom_keyword!(input);
|
custom_keyword!(input);
|
||||||
custom_keyword!(incomplete_wire);
|
|
||||||
custom_keyword!(instance);
|
custom_keyword!(instance);
|
||||||
custom_keyword!(m);
|
custom_keyword!(m);
|
||||||
custom_keyword!(memory);
|
custom_keyword!(memory);
|
||||||
|
|
@ -87,34 +68,34 @@ mod kw {
|
||||||
type Pound = Token![#]; // work around https://github.com/rust-lang/rust/issues/50676
|
type Pound = Token![#]; // work around https://github.com/rust-lang/rust/issues/50676
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub(crate) struct HdlAttr<T, KW> {
|
pub(crate) struct HdlAttr<T> {
|
||||||
pub(crate) pound_token: Pound,
|
pub(crate) pound_token: Pound,
|
||||||
pub(crate) style: AttrStyle,
|
pub(crate) style: AttrStyle,
|
||||||
pub(crate) bracket_token: syn::token::Bracket,
|
pub(crate) bracket_token: syn::token::Bracket,
|
||||||
pub(crate) kw: KW,
|
pub(crate) hdl: kw::hdl,
|
||||||
pub(crate) paren_token: Option<syn::token::Paren>,
|
pub(crate) paren_token: Option<syn::token::Paren>,
|
||||||
pub(crate) body: T,
|
pub(crate) body: T,
|
||||||
}
|
}
|
||||||
|
|
||||||
crate::fold::impl_fold! {
|
crate::fold::impl_fold! {
|
||||||
struct HdlAttr<T, KW,> {
|
struct HdlAttr<T,> {
|
||||||
pound_token: Pound,
|
pound_token: Pound,
|
||||||
style: AttrStyle,
|
style: AttrStyle,
|
||||||
bracket_token: syn::token::Bracket,
|
bracket_token: syn::token::Bracket,
|
||||||
kw: KW,
|
hdl: kw::hdl,
|
||||||
paren_token: Option<syn::token::Paren>,
|
paren_token: Option<syn::token::Paren>,
|
||||||
body: T,
|
body: T,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
impl<T, KW> HdlAttr<T, KW> {
|
impl<T> HdlAttr<T> {
|
||||||
pub(crate) fn split_body(self) -> (HdlAttr<(), KW>, T) {
|
pub(crate) fn split_body(self) -> (HdlAttr<()>, T) {
|
||||||
let Self {
|
let Self {
|
||||||
pound_token,
|
pound_token,
|
||||||
style,
|
style,
|
||||||
bracket_token,
|
bracket_token,
|
||||||
kw,
|
hdl,
|
||||||
paren_token,
|
paren_token,
|
||||||
body,
|
body,
|
||||||
} = self;
|
} = self;
|
||||||
|
|
@ -123,19 +104,19 @@ impl<T, KW> HdlAttr<T, KW> {
|
||||||
pound_token,
|
pound_token,
|
||||||
style,
|
style,
|
||||||
bracket_token,
|
bracket_token,
|
||||||
kw,
|
hdl,
|
||||||
paren_token,
|
paren_token,
|
||||||
body: (),
|
body: (),
|
||||||
},
|
},
|
||||||
body,
|
body,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
pub(crate) fn replace_body<T2>(self, body: T2) -> HdlAttr<T2, KW> {
|
pub(crate) fn replace_body<T2>(self, body: T2) -> HdlAttr<T2> {
|
||||||
let Self {
|
let Self {
|
||||||
pound_token,
|
pound_token,
|
||||||
style,
|
style,
|
||||||
bracket_token,
|
bracket_token,
|
||||||
kw,
|
hdl,
|
||||||
paren_token,
|
paren_token,
|
||||||
body: _,
|
body: _,
|
||||||
} = self;
|
} = self;
|
||||||
|
|
@ -143,20 +124,17 @@ impl<T, KW> HdlAttr<T, KW> {
|
||||||
pound_token,
|
pound_token,
|
||||||
style,
|
style,
|
||||||
bracket_token,
|
bracket_token,
|
||||||
kw,
|
hdl,
|
||||||
paren_token,
|
paren_token,
|
||||||
body,
|
body,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub(crate) fn as_ref(&self) -> HdlAttr<&T, KW>
|
pub(crate) fn as_ref(&self) -> HdlAttr<&T> {
|
||||||
where
|
|
||||||
KW: Clone,
|
|
||||||
{
|
|
||||||
let Self {
|
let Self {
|
||||||
pound_token,
|
pound_token,
|
||||||
style,
|
style,
|
||||||
bracket_token,
|
bracket_token,
|
||||||
ref kw,
|
hdl,
|
||||||
paren_token,
|
paren_token,
|
||||||
ref body,
|
ref body,
|
||||||
} = *self;
|
} = *self;
|
||||||
|
|
@ -164,20 +142,17 @@ impl<T, KW> HdlAttr<T, KW> {
|
||||||
pound_token,
|
pound_token,
|
||||||
style,
|
style,
|
||||||
bracket_token,
|
bracket_token,
|
||||||
kw: kw.clone(),
|
hdl,
|
||||||
paren_token,
|
paren_token,
|
||||||
body,
|
body,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub(crate) fn try_map<R, E, F: FnOnce(T) -> Result<R, E>>(
|
pub(crate) fn try_map<R, E, F: FnOnce(T) -> Result<R, E>>(self, f: F) -> Result<HdlAttr<R>, E> {
|
||||||
self,
|
|
||||||
f: F,
|
|
||||||
) -> Result<HdlAttr<R, KW>, E> {
|
|
||||||
let Self {
|
let Self {
|
||||||
pound_token,
|
pound_token,
|
||||||
style,
|
style,
|
||||||
bracket_token,
|
bracket_token,
|
||||||
kw,
|
hdl,
|
||||||
paren_token,
|
paren_token,
|
||||||
body,
|
body,
|
||||||
} = self;
|
} = self;
|
||||||
|
|
@ -185,17 +160,17 @@ impl<T, KW> HdlAttr<T, KW> {
|
||||||
pound_token,
|
pound_token,
|
||||||
style,
|
style,
|
||||||
bracket_token,
|
bracket_token,
|
||||||
kw,
|
hdl,
|
||||||
paren_token,
|
paren_token,
|
||||||
body: f(body)?,
|
body: f(body)?,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
pub(crate) fn map<R, F: FnOnce(T) -> R>(self, f: F) -> HdlAttr<R, KW> {
|
pub(crate) fn map<R, F: FnOnce(T) -> R>(self, f: F) -> HdlAttr<R> {
|
||||||
let Self {
|
let Self {
|
||||||
pound_token,
|
pound_token,
|
||||||
style,
|
style,
|
||||||
bracket_token,
|
bracket_token,
|
||||||
kw,
|
hdl,
|
||||||
paren_token,
|
paren_token,
|
||||||
body,
|
body,
|
||||||
} = self;
|
} = self;
|
||||||
|
|
@ -203,7 +178,7 @@ impl<T, KW> HdlAttr<T, KW> {
|
||||||
pound_token,
|
pound_token,
|
||||||
style,
|
style,
|
||||||
bracket_token,
|
bracket_token,
|
||||||
kw,
|
hdl,
|
||||||
paren_token,
|
paren_token,
|
||||||
body: f(body),
|
body: f(body),
|
||||||
}
|
}
|
||||||
|
|
@ -211,32 +186,31 @@ impl<T, KW> HdlAttr<T, KW> {
|
||||||
fn to_attr(&self) -> Attribute
|
fn to_attr(&self) -> Attribute
|
||||||
where
|
where
|
||||||
T: ToTokens,
|
T: ToTokens,
|
||||||
KW: ToTokens,
|
|
||||||
{
|
{
|
||||||
parse_quote! { #self }
|
parse_quote! { #self }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Default, KW: Default> Default for HdlAttr<T, KW> {
|
impl<T: Default> Default for HdlAttr<T> {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
T::default().into()
|
T::default().into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T, KW: Default> From<T> for HdlAttr<T, KW> {
|
impl<T> From<T> for HdlAttr<T> {
|
||||||
fn from(body: T) -> Self {
|
fn from(body: T) -> Self {
|
||||||
HdlAttr {
|
HdlAttr {
|
||||||
pound_token: Default::default(),
|
pound_token: Default::default(),
|
||||||
style: AttrStyle::Outer,
|
style: AttrStyle::Outer,
|
||||||
bracket_token: Default::default(),
|
bracket_token: Default::default(),
|
||||||
kw: Default::default(),
|
hdl: Default::default(),
|
||||||
paren_token: Default::default(),
|
paren_token: Default::default(),
|
||||||
body,
|
body,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: ToTokens, KW: ToTokens + Spanned> ToTokens for HdlAttr<T, KW> {
|
impl<T: ToTokens> ToTokens for HdlAttr<T> {
|
||||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||||
self.pound_token.to_tokens(tokens);
|
self.pound_token.to_tokens(tokens);
|
||||||
match self.style {
|
match self.style {
|
||||||
|
|
@ -244,7 +218,7 @@ impl<T: ToTokens, KW: ToTokens + Spanned> ToTokens for HdlAttr<T, KW> {
|
||||||
AttrStyle::Outer => {}
|
AttrStyle::Outer => {}
|
||||||
};
|
};
|
||||||
self.bracket_token.surround(tokens, |tokens| {
|
self.bracket_token.surround(tokens, |tokens| {
|
||||||
self.kw.to_tokens(tokens);
|
self.hdl.to_tokens(tokens);
|
||||||
match self.paren_token {
|
match self.paren_token {
|
||||||
Some(paren_token) => {
|
Some(paren_token) => {
|
||||||
paren_token.surround(tokens, |tokens| self.body.to_tokens(tokens))
|
paren_token.surround(tokens, |tokens| self.body.to_tokens(tokens))
|
||||||
|
|
@ -252,7 +226,7 @@ impl<T: ToTokens, KW: ToTokens + Spanned> ToTokens for HdlAttr<T, KW> {
|
||||||
None => {
|
None => {
|
||||||
let body = self.body.to_token_stream();
|
let body = self.body.to_token_stream();
|
||||||
if !body.is_empty() {
|
if !body.is_empty() {
|
||||||
syn::token::Paren(self.kw.span())
|
syn::token::Paren(self.hdl.span)
|
||||||
.surround(tokens, |tokens| tokens.extend([body]));
|
.surround(tokens, |tokens| tokens.extend([body]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -261,24 +235,18 @@ impl<T: ToTokens, KW: ToTokens + Spanned> ToTokens for HdlAttr<T, KW> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_hdl_attr<KW: CustomToken>(attr: &Attribute) -> bool {
|
fn is_hdl_attr(attr: &Attribute) -> bool {
|
||||||
attr.path().is_ident(KW::IDENT_STR)
|
attr.path().is_ident("hdl")
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Parse, KW: Parse> HdlAttr<T, KW> {
|
impl<T: Parse> HdlAttr<T> {
|
||||||
fn parse_and_take_attr(attrs: &mut Vec<Attribute>) -> syn::Result<Option<Self>>
|
fn parse_and_take_attr(attrs: &mut Vec<Attribute>) -> syn::Result<Option<Self>> {
|
||||||
where
|
|
||||||
KW: ToTokens,
|
|
||||||
{
|
|
||||||
let mut retval = None;
|
let mut retval = None;
|
||||||
let mut errors = Errors::new();
|
let mut errors = Errors::new();
|
||||||
attrs.retain(|attr| {
|
attrs.retain(|attr| {
|
||||||
if let Ok(kw) = syn::parse2::<KW>(attr.path().to_token_stream()) {
|
if is_hdl_attr(attr) {
|
||||||
if retval.is_some() {
|
if retval.is_some() {
|
||||||
errors.push(Error::new_spanned(
|
errors.push(Error::new_spanned(attr, "more than one #[hdl] attribute"));
|
||||||
attr,
|
|
||||||
format_args!("more than one #[{}] attribute", kw.to_token_stream()),
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
errors.unwrap_or_default(Self::parse_attr(attr).map(|v| retval = Some(v)));
|
errors.unwrap_or_default(Self::parse_attr(attr).map(|v| retval = Some(v)));
|
||||||
false
|
false
|
||||||
|
|
@ -289,19 +257,13 @@ impl<T: Parse, KW: Parse> HdlAttr<T, KW> {
|
||||||
errors.finish()?;
|
errors.finish()?;
|
||||||
Ok(retval)
|
Ok(retval)
|
||||||
}
|
}
|
||||||
fn parse_and_leave_attr(attrs: &[Attribute]) -> syn::Result<Option<Self>>
|
fn parse_and_leave_attr(attrs: &[Attribute]) -> syn::Result<Option<Self>> {
|
||||||
where
|
|
||||||
KW: ToTokens,
|
|
||||||
{
|
|
||||||
let mut retval = None;
|
let mut retval = None;
|
||||||
let mut errors = Errors::new();
|
let mut errors = Errors::new();
|
||||||
for attr in attrs {
|
for attr in attrs {
|
||||||
if let Ok(kw) = syn::parse2::<KW>(attr.path().to_token_stream()) {
|
if is_hdl_attr(attr) {
|
||||||
if retval.is_some() {
|
if retval.is_some() {
|
||||||
errors.push(Error::new_spanned(
|
errors.push(Error::new_spanned(attr, "more than one #[hdl] attribute"));
|
||||||
attr,
|
|
||||||
format_args!("more than one #[{}] attribute", kw.to_token_stream()),
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
errors.unwrap_or_default(Self::parse_attr(attr).map(|v| retval = Some(v)));
|
errors.unwrap_or_default(Self::parse_attr(attr).map(|v| retval = Some(v)));
|
||||||
}
|
}
|
||||||
|
|
@ -322,7 +284,7 @@ impl<T: Parse, KW: Parse> HdlAttr<T, KW> {
|
||||||
) -> syn::Result<Self> {
|
) -> syn::Result<Self> {
|
||||||
let bracket_content;
|
let bracket_content;
|
||||||
let bracket_token = bracketed!(bracket_content in input);
|
let bracket_token = bracketed!(bracket_content in input);
|
||||||
let kw = bracket_content.parse()?;
|
let hdl = bracket_content.parse()?;
|
||||||
let paren_content;
|
let paren_content;
|
||||||
let body;
|
let body;
|
||||||
let paren_token;
|
let paren_token;
|
||||||
|
|
@ -343,7 +305,7 @@ impl<T: Parse, KW: Parse> HdlAttr<T, KW> {
|
||||||
pound_token,
|
pound_token,
|
||||||
style,
|
style,
|
||||||
bracket_token,
|
bracket_token,
|
||||||
kw,
|
hdl,
|
||||||
paren_token,
|
paren_token,
|
||||||
body,
|
body,
|
||||||
})
|
})
|
||||||
|
|
@ -890,31 +852,25 @@ pub(crate) fn outline_generated(contents: TokenStream, prefix: &str) -> TokenStr
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn hdl_module_impl(item: ItemFn) -> syn::Result<TokenStream> {
|
pub fn hdl_module(attr: TokenStream, item: TokenStream) -> syn::Result<TokenStream> {
|
||||||
let func = module::ModuleFn::parse_from_fn(item)?;
|
let options = syn::parse2::<module::ConfigOptions>(attr)?;
|
||||||
let options = func.config_options();
|
let options = HdlAttr::from(options);
|
||||||
|
let func = syn::parse2::<module::ModuleFn>(quote! { #options #item })?;
|
||||||
let mut contents = func.generate();
|
let mut contents = func.generate();
|
||||||
if options.outline_generated.is_some() {
|
if options.body.outline_generated.is_some() {
|
||||||
contents = outline_generated(contents, "module-");
|
contents = outline_generated(contents, "module-");
|
||||||
}
|
}
|
||||||
Ok(contents)
|
Ok(contents)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn hdl_module(attr: TokenStream, item: TokenStream) -> syn::Result<TokenStream> {
|
|
||||||
let kw = kw::hdl_module::default();
|
|
||||||
hdl_module_impl(syn::parse2(quote! { #[#kw(#attr)] #item })?)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn hdl_attr(attr: TokenStream, item: TokenStream) -> syn::Result<TokenStream> {
|
pub fn hdl_attr(attr: TokenStream, item: TokenStream) -> syn::Result<TokenStream> {
|
||||||
let kw = kw::hdl::default();
|
let item = syn::parse2::<Item>(quote! { #[hdl(#attr)] #item })?;
|
||||||
let item = syn::parse2::<Item>(quote! { #[#kw(#attr)] #item })?;
|
|
||||||
match item {
|
match item {
|
||||||
Item::Enum(item) => hdl_enum::hdl_enum(item),
|
Item::Enum(item) => hdl_enum::hdl_enum(item),
|
||||||
Item::Struct(item) => hdl_bundle::hdl_bundle(item),
|
Item::Struct(item) => hdl_bundle::hdl_bundle(item),
|
||||||
Item::Fn(item) => hdl_module_impl(item),
|
|
||||||
_ => Err(syn::Error::new(
|
_ => Err(syn::Error::new(
|
||||||
Span::call_site(),
|
Span::call_site(),
|
||||||
"top-level #[hdl] can only be used on structs, enums, or functions",
|
"top-level #[hdl] can only be used on structs or enums",
|
||||||
)),
|
)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,6 @@
|
||||||
// See Notices.txt for copyright information
|
// See Notices.txt for copyright information
|
||||||
use crate::{
|
use crate::{
|
||||||
hdl_type_common::{ParsedGenerics, SplitForImpl},
|
hdl_type_common::{ParsedGenerics, SplitForImpl},
|
||||||
kw,
|
|
||||||
module::transform_body::{HdlLet, HdlLetKindIO},
|
module::transform_body::{HdlLet, HdlLetKindIO},
|
||||||
options, Errors, HdlAttr, PairsIterExt,
|
options, Errors, HdlAttr, PairsIterExt,
|
||||||
};
|
};
|
||||||
|
|
@ -10,6 +9,7 @@ use proc_macro2::TokenStream;
|
||||||
use quote::{format_ident, quote, quote_spanned, ToTokens};
|
use quote::{format_ident, quote, quote_spanned, ToTokens};
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
use syn::{
|
use syn::{
|
||||||
|
parse::{Parse, ParseStream},
|
||||||
parse_quote,
|
parse_quote,
|
||||||
visit::{visit_pat, Visit},
|
visit::{visit_pat, Visit},
|
||||||
Attribute, Block, ConstParam, Error, FnArg, GenericParam, Generics, Ident, ItemFn, ItemStruct,
|
Attribute, Block, ConstParam, Error, FnArg, GenericParam, Generics, Ident, ItemFn, ItemStruct,
|
||||||
|
|
@ -59,9 +59,9 @@ impl Visit<'_> for CheckNameConflictsWithModuleBuilderVisitor<'_> {
|
||||||
|
|
||||||
pub(crate) type ModuleIO = HdlLet<HdlLetKindIO>;
|
pub(crate) type ModuleIO = HdlLet<HdlLetKindIO>;
|
||||||
|
|
||||||
struct ModuleFnModule {
|
pub(crate) struct ModuleFn {
|
||||||
attrs: Vec<Attribute>,
|
attrs: Vec<Attribute>,
|
||||||
config_options: HdlAttr<ConfigOptions, kw::hdl_module>,
|
config_options: HdlAttr<ConfigOptions>,
|
||||||
module_kind: ModuleKind,
|
module_kind: ModuleKind,
|
||||||
vis: Visibility,
|
vis: Visibility,
|
||||||
sig: Signature,
|
sig: Signature,
|
||||||
|
|
@ -70,26 +70,6 @@ struct ModuleFnModule {
|
||||||
the_struct: TokenStream,
|
the_struct: TokenStream,
|
||||||
}
|
}
|
||||||
|
|
||||||
enum ModuleFnImpl {
|
|
||||||
Module(ModuleFnModule),
|
|
||||||
Fn {
|
|
||||||
attrs: Vec<Attribute>,
|
|
||||||
config_options: HdlAttr<ConfigOptions, kw::hdl>,
|
|
||||||
vis: Visibility,
|
|
||||||
sig: Signature,
|
|
||||||
block: Box<Block>,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
options! {
|
|
||||||
pub(crate) enum HdlOrHdlModule {
|
|
||||||
Hdl(hdl),
|
|
||||||
HdlModule(hdl_module),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) struct ModuleFn(ModuleFnImpl);
|
|
||||||
|
|
||||||
#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
|
#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
|
||||||
pub(crate) enum ModuleKind {
|
pub(crate) enum ModuleKind {
|
||||||
Extern,
|
Extern,
|
||||||
|
|
@ -109,25 +89,14 @@ impl Visit<'_> for ContainsSkippedIdent<'_> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ModuleFn {
|
impl Parse for ModuleFn {
|
||||||
pub(crate) fn config_options(&self) -> ConfigOptions {
|
fn parse(input: ParseStream) -> syn::Result<Self> {
|
||||||
let (ModuleFnImpl::Module(ModuleFnModule {
|
|
||||||
config_options: HdlAttr { body, .. },
|
|
||||||
..
|
|
||||||
})
|
|
||||||
| ModuleFnImpl::Fn {
|
|
||||||
config_options: HdlAttr { body, .. },
|
|
||||||
..
|
|
||||||
}) = &self.0;
|
|
||||||
body.clone()
|
|
||||||
}
|
|
||||||
pub(crate) fn parse_from_fn(item: ItemFn) -> syn::Result<Self> {
|
|
||||||
let ItemFn {
|
let ItemFn {
|
||||||
mut attrs,
|
mut attrs,
|
||||||
vis,
|
vis,
|
||||||
mut sig,
|
mut sig,
|
||||||
block,
|
block,
|
||||||
} = item;
|
} = input.parse()?;
|
||||||
let Signature {
|
let Signature {
|
||||||
ref constness,
|
ref constness,
|
||||||
ref asyncness,
|
ref asyncness,
|
||||||
|
|
@ -142,33 +111,17 @@ impl ModuleFn {
|
||||||
ref output,
|
ref output,
|
||||||
} = sig;
|
} = sig;
|
||||||
let mut errors = Errors::new();
|
let mut errors = Errors::new();
|
||||||
let Some(mut config_options) =
|
let config_options = errors
|
||||||
errors.unwrap_or_default(
|
.unwrap_or_default(HdlAttr::parse_and_take_attr(&mut attrs))
|
||||||
HdlAttr::<ConfigOptions, HdlOrHdlModule>::parse_and_take_attr(&mut attrs),
|
.unwrap_or_default();
|
||||||
)
|
|
||||||
else {
|
|
||||||
errors.error(sig.ident, "missing #[hdl] or #[hdl_module] attribute");
|
|
||||||
errors.finish()?;
|
|
||||||
unreachable!();
|
|
||||||
};
|
|
||||||
let ConfigOptions {
|
let ConfigOptions {
|
||||||
outline_generated: _,
|
outline_generated: _,
|
||||||
extern_,
|
extern_,
|
||||||
} = config_options.body;
|
} = config_options.body;
|
||||||
let module_kind = match (config_options.kw, extern_) {
|
let module_kind = match extern_ {
|
||||||
(HdlOrHdlModule::Hdl(_), None) => None,
|
Some(_) => ModuleKind::Extern,
|
||||||
(HdlOrHdlModule::Hdl(_), Some(extern2)) => {
|
None => ModuleKind::Normal,
|
||||||
config_options.body.extern_ = None;
|
|
||||||
errors.error(
|
|
||||||
extern2.0,
|
|
||||||
"extern can only be used as #[hdl_module(extern)]",
|
|
||||||
);
|
|
||||||
None
|
|
||||||
}
|
|
||||||
(HdlOrHdlModule::HdlModule(_), None) => Some(ModuleKind::Normal),
|
|
||||||
(HdlOrHdlModule::HdlModule(_), Some(_)) => Some(ModuleKind::Extern),
|
|
||||||
};
|
};
|
||||||
if let HdlOrHdlModule::HdlModule(_) = config_options.kw {
|
|
||||||
for fn_arg in inputs {
|
for fn_arg in inputs {
|
||||||
match fn_arg {
|
match fn_arg {
|
||||||
FnArg::Receiver(_) => {
|
FnArg::Receiver(_) => {
|
||||||
|
|
@ -196,24 +149,20 @@ impl ModuleFn {
|
||||||
if let Some(abi) = abi {
|
if let Some(abi) = abi {
|
||||||
errors.push(syn::Error::new_spanned(abi, "extern not allowed here"));
|
errors.push(syn::Error::new_spanned(abi, "extern not allowed here"));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
let mut skipped_idents = HashSet::new();
|
let mut skipped_idents = HashSet::new();
|
||||||
let struct_generic_params = generics
|
let struct_generic_params = generics
|
||||||
.params
|
.params
|
||||||
.pairs_mut()
|
.pairs_mut()
|
||||||
.filter_map_pair_value_mut(|v| match v {
|
.filter_map_pair_value_mut(|v| match v {
|
||||||
GenericParam::Lifetime(LifetimeParam { attrs, .. }) => {
|
GenericParam::Lifetime(LifetimeParam { attrs, .. }) => {
|
||||||
errors.unwrap_or_default(
|
errors
|
||||||
HdlAttr::<crate::kw::skip, kw::hdl>::parse_and_take_attr(attrs),
|
.unwrap_or_default(HdlAttr::<crate::kw::skip>::parse_and_take_attr(attrs));
|
||||||
);
|
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
GenericParam::Type(TypeParam { attrs, ident, .. })
|
GenericParam::Type(TypeParam { attrs, ident, .. })
|
||||||
| GenericParam::Const(ConstParam { attrs, ident, .. }) => {
|
| GenericParam::Const(ConstParam { attrs, ident, .. }) => {
|
||||||
if errors
|
if errors
|
||||||
.unwrap_or_default(
|
.unwrap_or_default(HdlAttr::<crate::kw::skip>::parse_and_take_attr(attrs))
|
||||||
HdlAttr::<crate::kw::skip, kw::hdl>::parse_and_take_attr(attrs),
|
|
||||||
)
|
|
||||||
.is_some()
|
.is_some()
|
||||||
{
|
{
|
||||||
skipped_idents.insert(ident.clone());
|
skipped_idents.insert(ident.clone());
|
||||||
|
|
@ -227,7 +176,6 @@ impl ModuleFn {
|
||||||
let struct_where_clause = generics
|
let struct_where_clause = generics
|
||||||
.where_clause
|
.where_clause
|
||||||
.as_mut()
|
.as_mut()
|
||||||
.filter(|_| matches!(config_options.kw, HdlOrHdlModule::HdlModule(_)))
|
|
||||||
.map(|where_clause| WhereClause {
|
.map(|where_clause| WhereClause {
|
||||||
where_token: where_clause.where_token,
|
where_token: where_clause.where_token,
|
||||||
predicates: where_clause
|
predicates: where_clause
|
||||||
|
|
@ -250,8 +198,7 @@ impl ModuleFn {
|
||||||
})
|
})
|
||||||
.collect(),
|
.collect(),
|
||||||
});
|
});
|
||||||
let struct_generics = if let HdlOrHdlModule::HdlModule(_) = config_options.kw {
|
let struct_generics = Generics {
|
||||||
let mut struct_generics = Generics {
|
|
||||||
lt_token: generics.lt_token,
|
lt_token: generics.lt_token,
|
||||||
params: struct_generic_params,
|
params: struct_generic_params,
|
||||||
gt_token: generics.gt_token,
|
gt_token: generics.gt_token,
|
||||||
|
|
@ -266,10 +213,7 @@ impl ModuleFn {
|
||||||
"return type not allowed here",
|
"return type not allowed here",
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
errors.ok(ParsedGenerics::parse(&mut struct_generics))
|
let struct_generics = errors.ok(ParsedGenerics::parse(&mut { struct_generics }));
|
||||||
} else {
|
|
||||||
Some(ParsedGenerics::default())
|
|
||||||
};
|
|
||||||
let body_results = struct_generics.as_ref().and_then(|struct_generics| {
|
let body_results = struct_generics.as_ref().and_then(|struct_generics| {
|
||||||
errors.ok(transform_body::transform_body(
|
errors.ok(transform_body::transform_body(
|
||||||
module_kind,
|
module_kind,
|
||||||
|
|
@ -280,47 +224,6 @@ impl ModuleFn {
|
||||||
errors.finish()?;
|
errors.finish()?;
|
||||||
let struct_generics = struct_generics.unwrap();
|
let struct_generics = struct_generics.unwrap();
|
||||||
let (block, io) = body_results.unwrap();
|
let (block, io) = body_results.unwrap();
|
||||||
let config_options = match config_options {
|
|
||||||
HdlAttr {
|
|
||||||
pound_token,
|
|
||||||
style,
|
|
||||||
bracket_token,
|
|
||||||
kw: HdlOrHdlModule::Hdl((kw,)),
|
|
||||||
paren_token,
|
|
||||||
body,
|
|
||||||
} => {
|
|
||||||
debug_assert!(io.is_empty());
|
|
||||||
return Ok(Self(ModuleFnImpl::Fn {
|
|
||||||
attrs,
|
|
||||||
config_options: HdlAttr {
|
|
||||||
pound_token,
|
|
||||||
style,
|
|
||||||
bracket_token,
|
|
||||||
kw,
|
|
||||||
paren_token,
|
|
||||||
body,
|
|
||||||
},
|
|
||||||
vis,
|
|
||||||
sig,
|
|
||||||
block,
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
HdlAttr {
|
|
||||||
pound_token,
|
|
||||||
style,
|
|
||||||
bracket_token,
|
|
||||||
kw: HdlOrHdlModule::HdlModule((kw,)),
|
|
||||||
paren_token,
|
|
||||||
body,
|
|
||||||
} => HdlAttr {
|
|
||||||
pound_token,
|
|
||||||
style,
|
|
||||||
bracket_token,
|
|
||||||
kw,
|
|
||||||
paren_token,
|
|
||||||
body,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
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();
|
struct_generics.split_for_impl();
|
||||||
let struct_where_clause: Option<WhereClause> = parse_quote! { #struct_where_clause };
|
let struct_where_clause: Option<WhereClause> = parse_quote! { #struct_where_clause };
|
||||||
|
|
@ -356,22 +259,7 @@ impl ModuleFn {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let the_struct = crate::hdl_bundle::hdl_bundle(the_struct)?;
|
let the_struct = crate::hdl_bundle::hdl_bundle(the_struct)?;
|
||||||
Ok(Self(ModuleFnImpl::Module(ModuleFnModule {
|
Ok(Self {
|
||||||
attrs,
|
|
||||||
config_options,
|
|
||||||
module_kind: module_kind.unwrap(),
|
|
||||||
vis,
|
|
||||||
sig,
|
|
||||||
block,
|
|
||||||
struct_generics,
|
|
||||||
the_struct,
|
|
||||||
})))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ModuleFn {
|
|
||||||
pub(crate) fn generate(self) -> TokenStream {
|
|
||||||
let ModuleFnModule {
|
|
||||||
attrs,
|
attrs,
|
||||||
config_options,
|
config_options,
|
||||||
module_kind,
|
module_kind,
|
||||||
|
|
@ -380,28 +268,22 @@ impl ModuleFn {
|
||||||
block,
|
block,
|
||||||
struct_generics,
|
struct_generics,
|
||||||
the_struct,
|
the_struct,
|
||||||
} = match self.0 {
|
})
|
||||||
ModuleFnImpl::Module(v) => v,
|
}
|
||||||
ModuleFnImpl::Fn {
|
}
|
||||||
|
|
||||||
|
impl ModuleFn {
|
||||||
|
pub(crate) fn generate(self) -> TokenStream {
|
||||||
|
let Self {
|
||||||
attrs,
|
attrs,
|
||||||
config_options,
|
config_options,
|
||||||
|
module_kind,
|
||||||
vis,
|
vis,
|
||||||
sig,
|
sig,
|
||||||
block,
|
block,
|
||||||
} => {
|
struct_generics,
|
||||||
let ConfigOptions {
|
the_struct,
|
||||||
outline_generated: _,
|
} = self;
|
||||||
extern_: _,
|
|
||||||
} = config_options.body;
|
|
||||||
return ItemFn {
|
|
||||||
attrs,
|
|
||||||
vis,
|
|
||||||
sig,
|
|
||||||
block,
|
|
||||||
}
|
|
||||||
.into_token_stream();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let ConfigOptions {
|
let ConfigOptions {
|
||||||
outline_generated: _,
|
outline_generated: _,
|
||||||
extern_: _,
|
extern_: _,
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,6 @@ options! {
|
||||||
Instance(instance),
|
Instance(instance),
|
||||||
RegBuilder(reg_builder),
|
RegBuilder(reg_builder),
|
||||||
Wire(wire),
|
Wire(wire),
|
||||||
IncompleteWire(incomplete_wire),
|
|
||||||
Memory(memory),
|
Memory(memory),
|
||||||
MemoryArray(memory_array),
|
MemoryArray(memory_array),
|
||||||
MemoryWithInit(memory_with_init),
|
MemoryWithInit(memory_with_init),
|
||||||
|
|
@ -534,41 +533,6 @@ impl HdlLetKindToTokens for HdlLetKindWire {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
options! {
|
|
||||||
pub(crate) enum LetFnKindIncomplete {
|
|
||||||
IncompleteWire(incomplete_wire),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
|
||||||
pub(crate) struct HdlLetKindIncomplete {
|
|
||||||
pub(crate) kind: LetFnKindIncomplete,
|
|
||||||
pub(crate) paren: Paren,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ParseTypes<Self> for HdlLetKindIncomplete {
|
|
||||||
fn parse_types(input: &mut Self, _parser: &mut TypesParser<'_>) -> Result<Self, ParseFailed> {
|
|
||||||
Ok(input.clone())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl_fold! {
|
|
||||||
struct HdlLetKindIncomplete<> {
|
|
||||||
kind: LetFnKindIncomplete,
|
|
||||||
paren: Paren,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl HdlLetKindToTokens for HdlLetKindIncomplete {
|
|
||||||
fn ty_to_tokens(&self, _tokens: &mut TokenStream) {}
|
|
||||||
|
|
||||||
fn expr_to_tokens(&self, tokens: &mut TokenStream) {
|
|
||||||
let Self { kind, paren } = self;
|
|
||||||
kind.to_tokens(tokens);
|
|
||||||
paren.surround(tokens, |_| {});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
options! {
|
options! {
|
||||||
pub(crate) enum MemoryFnName {
|
pub(crate) enum MemoryFnName {
|
||||||
Memory(memory),
|
Memory(memory),
|
||||||
|
|
@ -733,7 +697,6 @@ impl HdlLetKindMemory {
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub(crate) enum HdlLetKind<IOType = ParsedType> {
|
pub(crate) enum HdlLetKind<IOType = ParsedType> {
|
||||||
IO(HdlLetKindIO<ModuleIOKind, IOType>),
|
IO(HdlLetKindIO<ModuleIOKind, IOType>),
|
||||||
Incomplete(HdlLetKindIncomplete),
|
|
||||||
Instance(HdlLetKindInstance),
|
Instance(HdlLetKindInstance),
|
||||||
RegBuilder(HdlLetKindRegBuilder),
|
RegBuilder(HdlLetKindRegBuilder),
|
||||||
Wire(HdlLetKindWire),
|
Wire(HdlLetKindWire),
|
||||||
|
|
@ -743,7 +706,6 @@ pub(crate) enum HdlLetKind<IOType = ParsedType> {
|
||||||
impl_fold! {
|
impl_fold! {
|
||||||
enum HdlLetKind<IOType,> {
|
enum HdlLetKind<IOType,> {
|
||||||
IO(HdlLetKindIO<ModuleIOKind, IOType>),
|
IO(HdlLetKindIO<ModuleIOKind, IOType>),
|
||||||
Incomplete(HdlLetKindIncomplete),
|
|
||||||
Instance(HdlLetKindInstance),
|
Instance(HdlLetKindInstance),
|
||||||
RegBuilder(HdlLetKindRegBuilder),
|
RegBuilder(HdlLetKindRegBuilder),
|
||||||
Wire(HdlLetKindWire),
|
Wire(HdlLetKindWire),
|
||||||
|
|
@ -758,9 +720,6 @@ impl<T: ParseTypes<I>, I> ParseTypes<HdlLetKind<I>> for HdlLetKind<T> {
|
||||||
) -> Result<Self, ParseFailed> {
|
) -> Result<Self, ParseFailed> {
|
||||||
match input {
|
match input {
|
||||||
HdlLetKind::IO(input) => ParseTypes::parse_types(input, parser).map(HdlLetKind::IO),
|
HdlLetKind::IO(input) => ParseTypes::parse_types(input, parser).map(HdlLetKind::IO),
|
||||||
HdlLetKind::Incomplete(input) => {
|
|
||||||
ParseTypes::parse_types(input, parser).map(HdlLetKind::Incomplete)
|
|
||||||
}
|
|
||||||
HdlLetKind::Instance(input) => {
|
HdlLetKind::Instance(input) => {
|
||||||
ParseTypes::parse_types(input, parser).map(HdlLetKind::Instance)
|
ParseTypes::parse_types(input, parser).map(HdlLetKind::Instance)
|
||||||
}
|
}
|
||||||
|
|
@ -912,20 +871,6 @@ impl HdlLetKindParse for HdlLetKind<Type> {
|
||||||
ty_expr: paren_contents.call(parse_optional_fn_arg)?,
|
ty_expr: paren_contents.call(parse_optional_fn_arg)?,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
LetFnKind::IncompleteWire(incomplete_wire) => {
|
|
||||||
if let Some(parsed_ty) = parsed_ty {
|
|
||||||
return Err(Error::new_spanned(
|
|
||||||
parsed_ty.1,
|
|
||||||
"type annotation not allowed for incomplete_wire",
|
|
||||||
));
|
|
||||||
}
|
|
||||||
check_empty_m_dot(m_dot, kind)?;
|
|
||||||
let _paren_contents;
|
|
||||||
Ok(Self::Incomplete(HdlLetKindIncomplete {
|
|
||||||
kind: LetFnKindIncomplete::IncompleteWire(incomplete_wire),
|
|
||||||
paren: parenthesized!(_paren_contents in input),
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
LetFnKind::Memory(fn_name) => HdlLetKindMemory::rest_of_parse(
|
LetFnKind::Memory(fn_name) => HdlLetKindMemory::rest_of_parse(
|
||||||
input,
|
input,
|
||||||
parsed_ty,
|
parsed_ty,
|
||||||
|
|
@ -958,7 +903,6 @@ impl HdlLetKindToTokens for HdlLetKind {
|
||||||
fn ty_to_tokens(&self, tokens: &mut TokenStream) {
|
fn ty_to_tokens(&self, tokens: &mut TokenStream) {
|
||||||
match self {
|
match self {
|
||||||
HdlLetKind::IO(v) => v.ty_to_tokens(tokens),
|
HdlLetKind::IO(v) => v.ty_to_tokens(tokens),
|
||||||
HdlLetKind::Incomplete(v) => v.ty_to_tokens(tokens),
|
|
||||||
HdlLetKind::Instance(v) => v.ty_to_tokens(tokens),
|
HdlLetKind::Instance(v) => v.ty_to_tokens(tokens),
|
||||||
HdlLetKind::RegBuilder(v) => v.ty_to_tokens(tokens),
|
HdlLetKind::RegBuilder(v) => v.ty_to_tokens(tokens),
|
||||||
HdlLetKind::Wire(v) => v.ty_to_tokens(tokens),
|
HdlLetKind::Wire(v) => v.ty_to_tokens(tokens),
|
||||||
|
|
@ -969,7 +913,6 @@ impl HdlLetKindToTokens for HdlLetKind {
|
||||||
fn expr_to_tokens(&self, tokens: &mut TokenStream) {
|
fn expr_to_tokens(&self, tokens: &mut TokenStream) {
|
||||||
match self {
|
match self {
|
||||||
HdlLetKind::IO(v) => v.expr_to_tokens(tokens),
|
HdlLetKind::IO(v) => v.expr_to_tokens(tokens),
|
||||||
HdlLetKind::Incomplete(v) => v.expr_to_tokens(tokens),
|
|
||||||
HdlLetKind::Instance(v) => v.expr_to_tokens(tokens),
|
HdlLetKind::Instance(v) => v.expr_to_tokens(tokens),
|
||||||
HdlLetKind::RegBuilder(v) => v.expr_to_tokens(tokens),
|
HdlLetKind::RegBuilder(v) => v.expr_to_tokens(tokens),
|
||||||
HdlLetKind::Wire(v) => v.expr_to_tokens(tokens),
|
HdlLetKind::Wire(v) => v.expr_to_tokens(tokens),
|
||||||
|
|
@ -982,7 +925,7 @@ with_debug_clone_and_fold! {
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub(crate) struct HdlLet<Kind = HdlLetKind> {
|
pub(crate) struct HdlLet<Kind = HdlLetKind> {
|
||||||
pub(crate) attrs: Vec<Attribute>,
|
pub(crate) attrs: Vec<Attribute>,
|
||||||
pub(crate) hdl_attr: HdlAttr<Nothing, kw::hdl>,
|
pub(crate) hdl_attr: HdlAttr<Nothing>,
|
||||||
pub(crate) let_token: Token![let],
|
pub(crate) let_token: Token![let],
|
||||||
pub(crate) mut_token: Option<Token![mut]>,
|
pub(crate) mut_token: Option<Token![mut]>,
|
||||||
pub(crate) name: Ident,
|
pub(crate) name: Ident,
|
||||||
|
|
@ -1169,7 +1112,7 @@ impl<T: ToString> ToTokens for ImplicitName<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Visitor<'a> {
|
struct Visitor<'a> {
|
||||||
module_kind: Option<ModuleKind>,
|
module_kind: ModuleKind,
|
||||||
errors: Errors,
|
errors: Errors,
|
||||||
io: Vec<ModuleIO>,
|
io: Vec<ModuleIO>,
|
||||||
block_depth: usize,
|
block_depth: usize,
|
||||||
|
|
@ -1177,33 +1120,22 @@ struct Visitor<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Visitor<'_> {
|
impl Visitor<'_> {
|
||||||
fn take_hdl_attr<T: Parse>(
|
fn take_hdl_attr<T: Parse>(&mut self, attrs: &mut Vec<Attribute>) -> Option<HdlAttr<T>> {
|
||||||
&mut self,
|
|
||||||
attrs: &mut Vec<Attribute>,
|
|
||||||
) -> Option<HdlAttr<T, kw::hdl>> {
|
|
||||||
self.errors.unwrap_or(
|
self.errors.unwrap_or(
|
||||||
HdlAttr::parse_and_take_attr(attrs),
|
HdlAttr::parse_and_take_attr(attrs),
|
||||||
Some(syn::parse2::<T>(quote! {}).unwrap().into()),
|
Some(syn::parse2::<T>(quote! {}).unwrap().into()),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
fn require_normal_module_or_fn(&mut self, spanned: impl ToTokens) {
|
fn require_normal_module(&mut self, spanned: impl ToTokens) {
|
||||||
match self.module_kind {
|
match self.module_kind {
|
||||||
Some(ModuleKind::Extern) => {
|
ModuleKind::Extern => {
|
||||||
self.errors
|
self.errors
|
||||||
.error(spanned, "not allowed in #[hdl_module(extern)]");
|
.error(spanned, "not allowed in #[hdl_module(extern)]");
|
||||||
}
|
}
|
||||||
Some(ModuleKind::Normal) | None => {}
|
ModuleKind::Normal => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn require_module(&mut self, spanned: impl ToTokens) {
|
fn process_hdl_if(&mut self, hdl_attr: HdlAttr<Nothing>, expr_if: ExprIf) -> Expr {
|
||||||
match self.module_kind {
|
|
||||||
None => {
|
|
||||||
self.errors.error(spanned, "not allowed in #[hdl] fn");
|
|
||||||
}
|
|
||||||
Some(_) => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn process_hdl_if(&mut self, hdl_attr: HdlAttr<Nothing, kw::hdl>, expr_if: ExprIf) -> Expr {
|
|
||||||
let ExprIf {
|
let ExprIf {
|
||||||
attrs,
|
attrs,
|
||||||
if_token,
|
if_token,
|
||||||
|
|
@ -1211,7 +1143,7 @@ impl Visitor<'_> {
|
||||||
then_branch,
|
then_branch,
|
||||||
else_branch,
|
else_branch,
|
||||||
} = expr_if;
|
} = expr_if;
|
||||||
self.require_normal_module_or_fn(if_token);
|
self.require_normal_module(if_token);
|
||||||
let else_expr = else_branch.unzip().1.map(|else_expr| match *else_expr {
|
let else_expr = else_branch.unzip().1.map(|else_expr| match *else_expr {
|
||||||
Expr::If(expr_if) => self.process_hdl_if(hdl_attr.clone(), expr_if),
|
Expr::If(expr_if) => self.process_hdl_if(hdl_attr.clone(), expr_if),
|
||||||
expr => expr,
|
expr => expr,
|
||||||
|
|
@ -1276,12 +1208,11 @@ impl Visitor<'_> {
|
||||||
.to_tokens(expr);
|
.to_tokens(expr);
|
||||||
});
|
});
|
||||||
let mut attrs = hdl_let.attrs.clone();
|
let mut attrs = hdl_let.attrs.clone();
|
||||||
self.require_module(kind);
|
|
||||||
match self.module_kind {
|
match self.module_kind {
|
||||||
Some(ModuleKind::Extern) => attrs.push(parse_quote_spanned! {hdl_let.let_token.span=>
|
ModuleKind::Extern => attrs.push(parse_quote_spanned! {hdl_let.let_token.span=>
|
||||||
#[allow(unused_variables)]
|
#[allow(unused_variables)]
|
||||||
}),
|
}),
|
||||||
Some(ModuleKind::Normal) | None => {}
|
ModuleKind::Normal => {}
|
||||||
}
|
}
|
||||||
let let_stmt = Local {
|
let let_stmt = Local {
|
||||||
attrs,
|
attrs,
|
||||||
|
|
@ -1318,7 +1249,7 @@ impl Visitor<'_> {
|
||||||
},
|
},
|
||||||
semi_token,
|
semi_token,
|
||||||
} = hdl_let;
|
} = hdl_let;
|
||||||
self.require_normal_module_or_fn(instance);
|
self.require_normal_module(instance);
|
||||||
let mut expr = instance.to_token_stream();
|
let mut expr = instance.to_token_stream();
|
||||||
paren.surround(&mut expr, |expr| {
|
paren.surround(&mut expr, |expr| {
|
||||||
let name_str = ImplicitName {
|
let name_str = ImplicitName {
|
||||||
|
|
@ -1345,7 +1276,7 @@ impl Visitor<'_> {
|
||||||
fn process_hdl_let_reg_builder(&mut self, hdl_let: HdlLet<HdlLetKindRegBuilder>) -> Local {
|
fn process_hdl_let_reg_builder(&mut self, hdl_let: HdlLet<HdlLetKindRegBuilder>) -> Local {
|
||||||
let name = &hdl_let.name;
|
let name = &hdl_let.name;
|
||||||
let reg_builder = hdl_let.kind.reg_builder;
|
let reg_builder = hdl_let.kind.reg_builder;
|
||||||
self.require_normal_module_or_fn(reg_builder);
|
self.require_normal_module(reg_builder);
|
||||||
let mut expr = reg_builder.to_token_stream();
|
let mut expr = reg_builder.to_token_stream();
|
||||||
hdl_let.kind.reg_builder_paren.surround(&mut expr, |expr| {
|
hdl_let.kind.reg_builder_paren.surround(&mut expr, |expr| {
|
||||||
let name_str = ImplicitName {
|
let name_str = ImplicitName {
|
||||||
|
|
@ -1396,7 +1327,7 @@ impl Visitor<'_> {
|
||||||
fn process_hdl_let_wire(&mut self, hdl_let: HdlLet<HdlLetKindWire>) -> Local {
|
fn process_hdl_let_wire(&mut self, hdl_let: HdlLet<HdlLetKindWire>) -> Local {
|
||||||
let name = &hdl_let.name;
|
let name = &hdl_let.name;
|
||||||
let wire = hdl_let.kind.wire;
|
let wire = hdl_let.kind.wire;
|
||||||
self.require_normal_module_or_fn(wire);
|
self.require_normal_module(wire);
|
||||||
let ty_expr = unwrap_or_static_type(hdl_let.kind.ty_expr.as_ref(), wire.span());
|
let ty_expr = unwrap_or_static_type(hdl_let.kind.ty_expr.as_ref(), wire.span());
|
||||||
let mut expr = wire.to_token_stream();
|
let mut expr = wire.to_token_stream();
|
||||||
hdl_let.kind.paren.surround(&mut expr, |expr| {
|
hdl_let.kind.paren.surround(&mut expr, |expr| {
|
||||||
|
|
@ -1426,36 +1357,11 @@ impl Visitor<'_> {
|
||||||
semi_token: hdl_let.semi_token,
|
semi_token: hdl_let.semi_token,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn process_hdl_let_incomplete(&mut self, hdl_let: HdlLet<HdlLetKindIncomplete>) -> Local {
|
|
||||||
let name = &hdl_let.name;
|
|
||||||
let kind = hdl_let.kind.kind;
|
|
||||||
self.require_normal_module_or_fn(kind);
|
|
||||||
let mut expr = kind.to_token_stream();
|
|
||||||
hdl_let.kind.paren.surround(&mut expr, |expr| {
|
|
||||||
ImplicitName {
|
|
||||||
name,
|
|
||||||
span: name.span(),
|
|
||||||
}
|
|
||||||
.to_tokens(expr);
|
|
||||||
});
|
|
||||||
let mut_token = &hdl_let.mut_token;
|
|
||||||
Local {
|
|
||||||
attrs: hdl_let.attrs.clone(),
|
|
||||||
let_token: hdl_let.let_token,
|
|
||||||
pat: parse_quote! { #mut_token #name },
|
|
||||||
init: Some(LocalInit {
|
|
||||||
eq_token: hdl_let.eq_token,
|
|
||||||
expr: parse_quote! { #expr },
|
|
||||||
diverge: None,
|
|
||||||
}),
|
|
||||||
semi_token: hdl_let.semi_token,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn process_hdl_let_memory(&mut self, hdl_let: HdlLet<HdlLetKindMemory>) -> Local {
|
fn process_hdl_let_memory(&mut self, hdl_let: HdlLet<HdlLetKindMemory>) -> Local {
|
||||||
let name = &hdl_let.name;
|
let name = &hdl_let.name;
|
||||||
let memory_fn = hdl_let.kind.memory_fn;
|
let memory_fn = hdl_let.kind.memory_fn;
|
||||||
let memory_fn_name = memory_fn.name();
|
let memory_fn_name = memory_fn.name();
|
||||||
self.require_normal_module_or_fn(memory_fn_name);
|
self.require_normal_module(memory_fn_name);
|
||||||
let mut expr = memory_fn_name.to_token_stream();
|
let mut expr = memory_fn_name.to_token_stream();
|
||||||
let (paren, arg) = match memory_fn {
|
let (paren, arg) = match memory_fn {
|
||||||
MemoryFn::Memory {
|
MemoryFn::Memory {
|
||||||
|
|
@ -1520,7 +1426,6 @@ impl Visitor<'_> {
|
||||||
}
|
}
|
||||||
the_match! {
|
the_match! {
|
||||||
IO => process_hdl_let_io,
|
IO => process_hdl_let_io,
|
||||||
Incomplete => process_hdl_let_incomplete,
|
|
||||||
Instance => process_hdl_let_instance,
|
Instance => process_hdl_let_instance,
|
||||||
RegBuilder => process_hdl_let_reg_builder,
|
RegBuilder => process_hdl_let_reg_builder,
|
||||||
Wire => process_hdl_let_wire,
|
Wire => process_hdl_let_wire,
|
||||||
|
|
@ -1638,7 +1543,7 @@ impl Fold for Visitor<'_> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fold_attribute(&mut self, attr: Attribute) -> Attribute {
|
fn fold_attribute(&mut self, attr: Attribute) -> Attribute {
|
||||||
if is_hdl_attr::<kw::hdl>(&attr) {
|
if is_hdl_attr(&attr) {
|
||||||
self.errors
|
self.errors
|
||||||
.error(&attr, "#[hdl] attribute not supported here");
|
.error(&attr, "#[hdl] attribute not supported here");
|
||||||
}
|
}
|
||||||
|
|
@ -1705,9 +1610,8 @@ impl Fold for Visitor<'_> {
|
||||||
fn fold_local(&mut self, let_stmt: Local) -> Local {
|
fn fold_local(&mut self, let_stmt: Local) -> Local {
|
||||||
match self
|
match self
|
||||||
.errors
|
.errors
|
||||||
.ok(HdlAttr::<Nothing, kw::hdl>::parse_and_leave_attr(
|
.ok(HdlAttr::<Nothing>::parse_and_leave_attr(&let_stmt.attrs))
|
||||||
&let_stmt.attrs,
|
{
|
||||||
)) {
|
|
||||||
None => return empty_let(),
|
None => return empty_let(),
|
||||||
Some(None) => return fold_local(self, let_stmt),
|
Some(None) => return fold_local(self, let_stmt),
|
||||||
Some(Some(HdlAttr { .. })) => {}
|
Some(Some(HdlAttr { .. })) => {}
|
||||||
|
|
@ -1742,7 +1646,7 @@ impl Fold for Visitor<'_> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn transform_body(
|
pub(crate) fn transform_body(
|
||||||
module_kind: Option<ModuleKind>,
|
module_kind: ModuleKind,
|
||||||
mut body: Box<Block>,
|
mut body: Box<Block>,
|
||||||
parsed_generics: &ParsedGenerics,
|
parsed_generics: &ParsedGenerics,
|
||||||
) -> syn::Result<(Box<Block>, Vec<ModuleIO>)> {
|
) -> syn::Result<(Box<Block>, Vec<ModuleIO>)> {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
// 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 crate::{kw, module::transform_body::Visitor, HdlAttr};
|
use crate::{module::transform_body::Visitor, HdlAttr};
|
||||||
use quote::{format_ident, quote_spanned};
|
use quote::{format_ident, quote_spanned};
|
||||||
use syn::{
|
use syn::{
|
||||||
parse::Nothing, parse_quote, parse_quote_spanned, spanned::Spanned, Expr, ExprArray, ExprPath,
|
parse::Nothing, parse_quote, parse_quote_spanned, spanned::Spanned, Expr, ExprArray, ExprPath,
|
||||||
|
|
@ -10,10 +10,10 @@ use syn::{
|
||||||
impl Visitor<'_> {
|
impl Visitor<'_> {
|
||||||
pub(crate) fn process_hdl_array(
|
pub(crate) fn process_hdl_array(
|
||||||
&mut self,
|
&mut self,
|
||||||
hdl_attr: HdlAttr<Nothing, kw::hdl>,
|
hdl_attr: HdlAttr<Nothing>,
|
||||||
mut expr_array: ExprArray,
|
mut expr_array: ExprArray,
|
||||||
) -> Expr {
|
) -> Expr {
|
||||||
self.require_normal_module_or_fn(hdl_attr);
|
self.require_normal_module(hdl_attr);
|
||||||
for elem in &mut expr_array.elems {
|
for elem in &mut expr_array.elems {
|
||||||
*elem = parse_quote_spanned! {elem.span()=>
|
*elem = parse_quote_spanned! {elem.span()=>
|
||||||
::fayalite::expr::ToExpr::to_expr(&(#elem))
|
::fayalite::expr::ToExpr::to_expr(&(#elem))
|
||||||
|
|
@ -23,10 +23,10 @@ impl Visitor<'_> {
|
||||||
}
|
}
|
||||||
pub(crate) fn process_hdl_repeat(
|
pub(crate) fn process_hdl_repeat(
|
||||||
&mut self,
|
&mut self,
|
||||||
hdl_attr: HdlAttr<Nothing, kw::hdl>,
|
hdl_attr: HdlAttr<Nothing>,
|
||||||
mut expr_repeat: ExprRepeat,
|
mut expr_repeat: ExprRepeat,
|
||||||
) -> Expr {
|
) -> Expr {
|
||||||
self.require_normal_module_or_fn(hdl_attr);
|
self.require_normal_module(hdl_attr);
|
||||||
let repeated_value = &expr_repeat.expr;
|
let repeated_value = &expr_repeat.expr;
|
||||||
*expr_repeat.expr = parse_quote_spanned! {repeated_value.span()=>
|
*expr_repeat.expr = parse_quote_spanned! {repeated_value.span()=>
|
||||||
::fayalite::expr::ToExpr::to_expr(&(#repeated_value))
|
::fayalite::expr::ToExpr::to_expr(&(#repeated_value))
|
||||||
|
|
@ -35,10 +35,10 @@ impl Visitor<'_> {
|
||||||
}
|
}
|
||||||
pub(crate) fn process_hdl_struct(
|
pub(crate) fn process_hdl_struct(
|
||||||
&mut self,
|
&mut self,
|
||||||
hdl_attr: HdlAttr<Nothing, kw::hdl>,
|
hdl_attr: HdlAttr<Nothing>,
|
||||||
expr_struct: ExprStruct,
|
expr_struct: ExprStruct,
|
||||||
) -> Expr {
|
) -> Expr {
|
||||||
self.require_normal_module_or_fn(&hdl_attr);
|
self.require_normal_module(&hdl_attr);
|
||||||
let name_span = expr_struct.path.segments.last().unwrap().ident.span();
|
let name_span = expr_struct.path.segments.last().unwrap().ident.span();
|
||||||
let builder_ident = format_ident!("__builder", span = name_span);
|
let builder_ident = format_ident!("__builder", span = name_span);
|
||||||
let empty_builder = if expr_struct.qself.is_some()
|
let empty_builder = if expr_struct.qself.is_some()
|
||||||
|
|
@ -91,10 +91,10 @@ impl Visitor<'_> {
|
||||||
}
|
}
|
||||||
pub(crate) fn process_hdl_tuple(
|
pub(crate) fn process_hdl_tuple(
|
||||||
&mut self,
|
&mut self,
|
||||||
hdl_attr: HdlAttr<Nothing, kw::hdl>,
|
hdl_attr: HdlAttr<Nothing>,
|
||||||
expr_tuple: ExprTuple,
|
expr_tuple: ExprTuple,
|
||||||
) -> Expr {
|
) -> Expr {
|
||||||
self.require_normal_module_or_fn(hdl_attr);
|
self.require_normal_module(hdl_attr);
|
||||||
parse_quote_spanned! {expr_tuple.span()=>
|
parse_quote_spanned! {expr_tuple.span()=>
|
||||||
::fayalite::expr::ToExpr::to_expr(&#expr_tuple)
|
::fayalite::expr::ToExpr::to_expr(&#expr_tuple)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,6 @@
|
||||||
// See Notices.txt for copyright information
|
// See Notices.txt for copyright information
|
||||||
use crate::{
|
use crate::{
|
||||||
fold::{impl_fold, DoFold},
|
fold::{impl_fold, DoFold},
|
||||||
kw,
|
|
||||||
module::transform_body::{with_debug_clone_and_fold, Visitor},
|
module::transform_body::{with_debug_clone_and_fold, Visitor},
|
||||||
Errors, HdlAttr, PairsIterExt,
|
Errors, HdlAttr, PairsIterExt,
|
||||||
};
|
};
|
||||||
|
|
@ -750,7 +749,7 @@ struct HdlMatchParseState<'a> {
|
||||||
impl Visitor<'_> {
|
impl Visitor<'_> {
|
||||||
pub(crate) fn process_hdl_match(
|
pub(crate) fn process_hdl_match(
|
||||||
&mut self,
|
&mut self,
|
||||||
_hdl_attr: HdlAttr<Nothing, kw::hdl>,
|
_hdl_attr: HdlAttr<Nothing>,
|
||||||
expr_match: ExprMatch,
|
expr_match: ExprMatch,
|
||||||
) -> Expr {
|
) -> Expr {
|
||||||
let span = expr_match.match_token.span();
|
let span = expr_match.match_token.span();
|
||||||
|
|
@ -762,7 +761,7 @@ impl Visitor<'_> {
|
||||||
brace_token: _,
|
brace_token: _,
|
||||||
arms,
|
arms,
|
||||||
} = expr_match;
|
} = expr_match;
|
||||||
self.require_normal_module_or_fn(match_token);
|
self.require_normal_module(match_token);
|
||||||
let mut state = HdlMatchParseState {
|
let mut state = HdlMatchParseState {
|
||||||
match_span: span,
|
match_span: span,
|
||||||
errors: &mut self.errors,
|
errors: &mut self.errors,
|
||||||
|
|
|
||||||
|
|
@ -7,14 +7,14 @@ use crate::{
|
||||||
int::Bool,
|
int::Bool,
|
||||||
intern::{Intern, Interned},
|
intern::{Intern, Interned},
|
||||||
module::{
|
module::{
|
||||||
connect, enum_match_variants_helper, incomplete_wire, wire,
|
enum_match_variants_helper, EnumMatchVariantAndInactiveScopeImpl,
|
||||||
EnumMatchVariantAndInactiveScopeImpl, EnumMatchVariantsIterImpl, Scope,
|
EnumMatchVariantsIterImpl, Scope,
|
||||||
},
|
},
|
||||||
source_location::SourceLocation,
|
source_location::SourceLocation,
|
||||||
ty::{CanonicalType, MatchVariantAndInactiveScope, StaticType, Type, TypeProperties},
|
ty::{CanonicalType, MatchVariantAndInactiveScope, StaticType, Type, TypeProperties},
|
||||||
};
|
};
|
||||||
use hashbrown::HashMap;
|
use hashbrown::HashMap;
|
||||||
use std::{convert::Infallible, fmt, iter::FusedIterator};
|
use std::{fmt, iter::FusedIterator};
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
|
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
|
||||||
pub struct EnumVariant {
|
pub struct EnumVariant {
|
||||||
|
|
@ -364,308 +364,3 @@ pub fn HdlSome<T: Type>(value: impl ToExpr<Type = T>) -> Expr<HdlOption<T>> {
|
||||||
let value = value.to_expr();
|
let value = value.to_expr();
|
||||||
HdlOption[Expr::ty(value)].HdlSome(value)
|
HdlOption[Expr::ty(value)].HdlSome(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Type> HdlOption<T> {
|
|
||||||
#[track_caller]
|
|
||||||
pub fn try_map<R: Type, E>(
|
|
||||||
expr: Expr<Self>,
|
|
||||||
f: impl FnOnce(Expr<T>) -> Result<Expr<R>, E>,
|
|
||||||
) -> Result<Expr<HdlOption<R>>, E> {
|
|
||||||
Self::try_and_then(expr, |v| Ok(HdlSome(f(v)?)))
|
|
||||||
}
|
|
||||||
#[track_caller]
|
|
||||||
pub fn map<R: Type>(
|
|
||||||
expr: Expr<Self>,
|
|
||||||
f: impl FnOnce(Expr<T>) -> Expr<R>,
|
|
||||||
) -> Expr<HdlOption<R>> {
|
|
||||||
Self::and_then(expr, |v| HdlSome(f(v)))
|
|
||||||
}
|
|
||||||
#[hdl]
|
|
||||||
#[track_caller]
|
|
||||||
pub fn try_and_then<R: Type, E>(
|
|
||||||
expr: Expr<Self>,
|
|
||||||
f: impl FnOnce(Expr<T>) -> Result<Expr<HdlOption<R>>, E>,
|
|
||||||
) -> Result<Expr<HdlOption<R>>, E> {
|
|
||||||
// manually run match steps so we can extract the return type to construct HdlNone
|
|
||||||
type Wrap<T> = T;
|
|
||||||
#[hdl]
|
|
||||||
let mut and_then_out = incomplete_wire();
|
|
||||||
let mut iter = Self::match_variants(expr, SourceLocation::caller());
|
|
||||||
let none = iter.next().unwrap();
|
|
||||||
let some = iter.next().unwrap();
|
|
||||||
assert!(iter.next().is_none());
|
|
||||||
let (Wrap::<<Self as Type>::MatchVariant>::HdlSome(value), some_scope) =
|
|
||||||
Self::match_activate_scope(some)
|
|
||||||
else {
|
|
||||||
unreachable!();
|
|
||||||
};
|
|
||||||
let value = f(value).map_err(|e| {
|
|
||||||
and_then_out.complete(()); // avoid error
|
|
||||||
e
|
|
||||||
})?;
|
|
||||||
let and_then_out = and_then_out.complete(Expr::ty(value));
|
|
||||||
connect(and_then_out, value);
|
|
||||||
drop(some_scope);
|
|
||||||
let (Wrap::<<Self as Type>::MatchVariant>::HdlNone, none_scope) =
|
|
||||||
Self::match_activate_scope(none)
|
|
||||||
else {
|
|
||||||
unreachable!();
|
|
||||||
};
|
|
||||||
connect(and_then_out, Expr::ty(and_then_out).HdlNone());
|
|
||||||
drop(none_scope);
|
|
||||||
Ok(and_then_out)
|
|
||||||
}
|
|
||||||
#[track_caller]
|
|
||||||
pub fn and_then<R: Type>(
|
|
||||||
expr: Expr<Self>,
|
|
||||||
f: impl FnOnce(Expr<T>) -> Expr<HdlOption<R>>,
|
|
||||||
) -> Expr<HdlOption<R>> {
|
|
||||||
match Self::try_and_then(expr, |v| Ok::<_, Infallible>(f(v))) {
|
|
||||||
Ok(v) => v,
|
|
||||||
Err(e) => match e {},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[hdl]
|
|
||||||
#[track_caller]
|
|
||||||
pub fn and<U: Type>(expr: Expr<Self>, opt_b: Expr<HdlOption<U>>) -> Expr<HdlOption<U>> {
|
|
||||||
#[hdl]
|
|
||||||
let and_out = wire(Expr::ty(opt_b));
|
|
||||||
connect(and_out, Expr::ty(opt_b).HdlNone());
|
|
||||||
#[hdl]
|
|
||||||
if let HdlSome(_) = expr {
|
|
||||||
connect(and_out, opt_b);
|
|
||||||
}
|
|
||||||
and_out
|
|
||||||
}
|
|
||||||
#[hdl]
|
|
||||||
#[track_caller]
|
|
||||||
pub fn try_filter<E>(
|
|
||||||
expr: Expr<Self>,
|
|
||||||
f: impl FnOnce(Expr<T>) -> Result<Expr<Bool>, E>,
|
|
||||||
) -> Result<Expr<Self>, E> {
|
|
||||||
#[hdl]
|
|
||||||
let filtered = wire(Expr::ty(expr));
|
|
||||||
connect(filtered, Expr::ty(expr).HdlNone());
|
|
||||||
let mut f = Some(f);
|
|
||||||
#[hdl]
|
|
||||||
if let HdlSome(v) = expr {
|
|
||||||
#[hdl]
|
|
||||||
if f.take().unwrap()(v)? {
|
|
||||||
connect(filtered, HdlSome(v));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(filtered)
|
|
||||||
}
|
|
||||||
#[hdl]
|
|
||||||
#[track_caller]
|
|
||||||
pub fn filter(expr: Expr<Self>, f: impl FnOnce(Expr<T>) -> Expr<Bool>) -> Expr<Self> {
|
|
||||||
match Self::try_filter(expr, |v| Ok::<_, Infallible>(f(v))) {
|
|
||||||
Ok(v) => v,
|
|
||||||
Err(e) => match e {},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[hdl]
|
|
||||||
#[track_caller]
|
|
||||||
pub fn try_inspect<E>(
|
|
||||||
expr: Expr<Self>,
|
|
||||||
f: impl FnOnce(Expr<T>) -> Result<(), E>,
|
|
||||||
) -> Result<Expr<Self>, E> {
|
|
||||||
let mut f = Some(f);
|
|
||||||
#[hdl]
|
|
||||||
if let HdlSome(v) = expr {
|
|
||||||
f.take().unwrap()(v)?;
|
|
||||||
}
|
|
||||||
Ok(expr)
|
|
||||||
}
|
|
||||||
#[hdl]
|
|
||||||
#[track_caller]
|
|
||||||
pub fn inspect(expr: Expr<Self>, f: impl FnOnce(Expr<T>)) -> Expr<Self> {
|
|
||||||
let mut f = Some(f);
|
|
||||||
#[hdl]
|
|
||||||
if let HdlSome(v) = expr {
|
|
||||||
f.take().unwrap()(v);
|
|
||||||
}
|
|
||||||
expr
|
|
||||||
}
|
|
||||||
#[hdl]
|
|
||||||
#[track_caller]
|
|
||||||
pub fn is_none(expr: Expr<Self>) -> Expr<Bool> {
|
|
||||||
#[hdl]
|
|
||||||
let is_none_out: Bool = wire();
|
|
||||||
connect(is_none_out, false);
|
|
||||||
#[hdl]
|
|
||||||
if let HdlNone = expr {
|
|
||||||
connect(is_none_out, true);
|
|
||||||
}
|
|
||||||
is_none_out
|
|
||||||
}
|
|
||||||
#[hdl]
|
|
||||||
#[track_caller]
|
|
||||||
pub fn is_some(expr: Expr<Self>) -> Expr<Bool> {
|
|
||||||
#[hdl]
|
|
||||||
let is_some_out: Bool = wire();
|
|
||||||
connect(is_some_out, false);
|
|
||||||
#[hdl]
|
|
||||||
if let HdlSome(_) = expr {
|
|
||||||
connect(is_some_out, true);
|
|
||||||
}
|
|
||||||
is_some_out
|
|
||||||
}
|
|
||||||
#[hdl]
|
|
||||||
#[track_caller]
|
|
||||||
pub fn map_or<R: Type>(
|
|
||||||
expr: Expr<Self>,
|
|
||||||
default: Expr<R>,
|
|
||||||
f: impl FnOnce(Expr<T>) -> Expr<R>,
|
|
||||||
) -> Expr<R> {
|
|
||||||
#[hdl]
|
|
||||||
let mapped = wire(Expr::ty(default));
|
|
||||||
let mut f = Some(f);
|
|
||||||
#[hdl]
|
|
||||||
match expr {
|
|
||||||
HdlSome(v) => connect(mapped, f.take().unwrap()(v)),
|
|
||||||
HdlNone => connect(mapped, default),
|
|
||||||
}
|
|
||||||
mapped
|
|
||||||
}
|
|
||||||
#[hdl]
|
|
||||||
#[track_caller]
|
|
||||||
pub fn map_or_else<R: Type>(
|
|
||||||
expr: Expr<Self>,
|
|
||||||
default: impl FnOnce() -> Expr<R>,
|
|
||||||
f: impl FnOnce(Expr<T>) -> Expr<R>,
|
|
||||||
) -> Expr<R> {
|
|
||||||
#[hdl]
|
|
||||||
let mut mapped = incomplete_wire();
|
|
||||||
let mut default = Some(default);
|
|
||||||
let mut f = Some(f);
|
|
||||||
let mut retval = None;
|
|
||||||
#[hdl]
|
|
||||||
match expr {
|
|
||||||
HdlSome(v) => {
|
|
||||||
let v = f.take().unwrap()(v);
|
|
||||||
let mapped = *retval.get_or_insert_with(|| mapped.complete(Expr::ty(v)));
|
|
||||||
connect(mapped, v);
|
|
||||||
}
|
|
||||||
HdlNone => {
|
|
||||||
let v = default.take().unwrap()();
|
|
||||||
let mapped = *retval.get_or_insert_with(|| mapped.complete(Expr::ty(v)));
|
|
||||||
connect(mapped, v);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
retval.unwrap()
|
|
||||||
}
|
|
||||||
#[hdl]
|
|
||||||
#[track_caller]
|
|
||||||
pub fn or(expr: Expr<Self>, opt_b: Expr<Self>) -> Expr<Self> {
|
|
||||||
#[hdl]
|
|
||||||
let or_out = wire(Expr::ty(expr));
|
|
||||||
connect(or_out, opt_b);
|
|
||||||
#[hdl]
|
|
||||||
if let HdlSome(_) = expr {
|
|
||||||
connect(or_out, expr);
|
|
||||||
}
|
|
||||||
or_out
|
|
||||||
}
|
|
||||||
#[hdl]
|
|
||||||
#[track_caller]
|
|
||||||
pub fn or_else(expr: Expr<Self>, f: impl FnOnce() -> Expr<Self>) -> Expr<Self> {
|
|
||||||
#[hdl]
|
|
||||||
let or_else_out = wire(Expr::ty(expr));
|
|
||||||
connect(or_else_out, f());
|
|
||||||
#[hdl]
|
|
||||||
if let HdlSome(_) = expr {
|
|
||||||
connect(or_else_out, expr);
|
|
||||||
}
|
|
||||||
or_else_out
|
|
||||||
}
|
|
||||||
#[hdl]
|
|
||||||
#[track_caller]
|
|
||||||
pub fn unwrap_or(expr: Expr<Self>, default: Expr<T>) -> Expr<T> {
|
|
||||||
#[hdl]
|
|
||||||
let unwrap_or_else_out = wire(Expr::ty(default));
|
|
||||||
connect(unwrap_or_else_out, default);
|
|
||||||
#[hdl]
|
|
||||||
if let HdlSome(v) = expr {
|
|
||||||
connect(unwrap_or_else_out, v);
|
|
||||||
}
|
|
||||||
unwrap_or_else_out
|
|
||||||
}
|
|
||||||
#[hdl]
|
|
||||||
#[track_caller]
|
|
||||||
pub fn unwrap_or_else(expr: Expr<Self>, f: impl FnOnce() -> Expr<T>) -> Expr<T> {
|
|
||||||
#[hdl]
|
|
||||||
let unwrap_or_else_out = wire(Expr::ty(expr).HdlSome);
|
|
||||||
connect(unwrap_or_else_out, f());
|
|
||||||
#[hdl]
|
|
||||||
if let HdlSome(v) = expr {
|
|
||||||
connect(unwrap_or_else_out, v);
|
|
||||||
}
|
|
||||||
unwrap_or_else_out
|
|
||||||
}
|
|
||||||
#[hdl]
|
|
||||||
#[track_caller]
|
|
||||||
pub fn xor(expr: Expr<Self>, opt_b: Expr<Self>) -> Expr<Self> {
|
|
||||||
#[hdl]
|
|
||||||
let xor_out = wire(Expr::ty(expr));
|
|
||||||
#[hdl]
|
|
||||||
if let HdlSome(_) = expr {
|
|
||||||
#[hdl]
|
|
||||||
if let HdlNone = opt_b {
|
|
||||||
connect(xor_out, expr);
|
|
||||||
} else {
|
|
||||||
connect(xor_out, Expr::ty(expr).HdlNone());
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
connect(xor_out, opt_b);
|
|
||||||
}
|
|
||||||
xor_out
|
|
||||||
}
|
|
||||||
#[hdl]
|
|
||||||
#[track_caller]
|
|
||||||
pub fn zip<U: Type>(expr: Expr<Self>, other: Expr<HdlOption<U>>) -> Expr<HdlOption<(T, U)>> {
|
|
||||||
#[hdl]
|
|
||||||
let zip_out = wire(HdlOption[(Expr::ty(expr).HdlSome, Expr::ty(other).HdlSome)]);
|
|
||||||
connect(zip_out, Expr::ty(zip_out).HdlNone());
|
|
||||||
#[hdl]
|
|
||||||
if let HdlSome(l) = expr {
|
|
||||||
#[hdl]
|
|
||||||
if let HdlSome(r) = other {
|
|
||||||
connect(zip_out, HdlSome((l, r)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
zip_out
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: Type> HdlOption<HdlOption<T>> {
|
|
||||||
#[hdl]
|
|
||||||
#[track_caller]
|
|
||||||
pub fn flatten(expr: Expr<Self>) -> Expr<HdlOption<T>> {
|
|
||||||
#[hdl]
|
|
||||||
let flattened = wire(Expr::ty(expr).HdlSome);
|
|
||||||
#[hdl]
|
|
||||||
match expr {
|
|
||||||
HdlSome(v) => connect(flattened, v),
|
|
||||||
HdlNone => connect(flattened, Expr::ty(expr).HdlSome.HdlNone()),
|
|
||||||
}
|
|
||||||
flattened
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: Type, U: Type> HdlOption<(T, U)> {
|
|
||||||
#[hdl]
|
|
||||||
#[track_caller]
|
|
||||||
pub fn unzip(expr: Expr<Self>) -> Expr<(HdlOption<T>, HdlOption<U>)> {
|
|
||||||
let (t, u) = Expr::ty(expr).HdlSome;
|
|
||||||
#[hdl]
|
|
||||||
let unzipped = wire((HdlOption[t], HdlOption[u]));
|
|
||||||
connect(unzipped, (HdlOption[t].HdlNone(), HdlOption[u].HdlNone()));
|
|
||||||
#[hdl]
|
|
||||||
if let HdlSome(v) = expr {
|
|
||||||
connect(unzipped.0, HdlSome(v.0));
|
|
||||||
connect(unzipped.1, HdlSome(v.1));
|
|
||||||
}
|
|
||||||
unzipped
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ use crate::{
|
||||||
source_location::SourceLocation,
|
source_location::SourceLocation,
|
||||||
ty::{CanonicalType, Type},
|
ty::{CanonicalType, Type},
|
||||||
util::ScopedRef,
|
util::ScopedRef,
|
||||||
wire::{IncompleteWire, Wire},
|
wire::Wire,
|
||||||
};
|
};
|
||||||
use hashbrown::{hash_map::Entry, HashMap, HashSet};
|
use hashbrown::{hash_map::Entry, HashMap, HashSet};
|
||||||
use num_bigint::BigInt;
|
use num_bigint::BigInt;
|
||||||
|
|
@ -118,35 +118,9 @@ pub trait BlockRef: 'static + Send + Sync + Copy + Eq + Hash + fmt::Debug {}
|
||||||
|
|
||||||
impl BlockRef for BlockId {}
|
impl BlockRef for BlockId {}
|
||||||
|
|
||||||
pub(crate) enum IncompleteDeclaration {
|
|
||||||
Incomplete {
|
|
||||||
name: ScopedNameId,
|
|
||||||
source_location: SourceLocation,
|
|
||||||
},
|
|
||||||
Complete(StmtDeclaration<ModuleBuilding>),
|
|
||||||
Taken,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Debug for IncompleteDeclaration {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
||||||
match self {
|
|
||||||
Self::Incomplete {
|
|
||||||
name,
|
|
||||||
source_location: _,
|
|
||||||
} => f
|
|
||||||
.debug_struct("Incomplete")
|
|
||||||
.field("name", name)
|
|
||||||
.finish_non_exhaustive(),
|
|
||||||
Self::Complete(v) => v.fmt(f),
|
|
||||||
Self::Taken => f.write_str("Taken"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct BuilderBlock {
|
pub struct BuilderBlock {
|
||||||
memories: Vec<Rc<RefCell<MemBuilderTarget>>>,
|
memories: Vec<Rc<RefCell<MemBuilderTarget>>>,
|
||||||
incomplete_declarations: Vec<Rc<RefCell<IncompleteDeclaration>>>,
|
|
||||||
stmts: Vec<Stmt<ModuleBuilding>>,
|
stmts: Vec<Stmt<ModuleBuilding>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -857,34 +831,13 @@ impl From<NormalModuleBody<ModuleBuilding>> for NormalModuleBody {
|
||||||
annotations_map: &mut HashMap<StmtDeclaration<ModuleBuilding>, Vec<TargetedAnnotation>>,
|
annotations_map: &mut HashMap<StmtDeclaration<ModuleBuilding>, Vec<TargetedAnnotation>>,
|
||||||
block_id: BlockId,
|
block_id: BlockId,
|
||||||
) -> Block {
|
) -> Block {
|
||||||
let BuilderBlock {
|
let BuilderBlock { memories, stmts } = &mut blocks[block_id.as_usize()];
|
||||||
memories,
|
|
||||||
incomplete_declarations,
|
|
||||||
stmts,
|
|
||||||
} = &mut blocks[block_id.as_usize()];
|
|
||||||
let memories = Interned::from_iter(
|
let memories = Interned::from_iter(
|
||||||
memories
|
memories
|
||||||
.drain(..)
|
.drain(..)
|
||||||
.filter_map(|memory| memory.borrow().make_memory()),
|
.filter_map(|memory| memory.borrow().make_memory()),
|
||||||
);
|
);
|
||||||
let stmts = Vec::from_iter(
|
let stmts = std::mem::take(stmts);
|
||||||
incomplete_declarations
|
|
||||||
.drain(..)
|
|
||||||
.map(|decl| {
|
|
||||||
match std::mem::replace(
|
|
||||||
&mut *decl.borrow_mut(),
|
|
||||||
IncompleteDeclaration::Taken,
|
|
||||||
) {
|
|
||||||
IncompleteDeclaration::Incomplete {
|
|
||||||
name,
|
|
||||||
source_location,
|
|
||||||
} => panic!("incomplete declaration: {name:?}\nat: {source_location}"),
|
|
||||||
IncompleteDeclaration::Complete(v) => Stmt::Declaration(v),
|
|
||||||
IncompleteDeclaration::Taken => unreachable!(),
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.chain(stmts.drain(..)),
|
|
||||||
);
|
|
||||||
let stmts = Interned::from_iter(stmts.into_iter().map(|stmt| {
|
let stmts = Interned::from_iter(stmts.into_iter().map(|stmt| {
|
||||||
match stmt {
|
match stmt {
|
||||||
Stmt::Connect(stmt) => stmt.into(),
|
Stmt::Connect(stmt) => stmt.into(),
|
||||||
|
|
@ -955,7 +908,6 @@ impl NormalModuleBody<ModuleBuilding> {
|
||||||
let index = self.body.blocks.len();
|
let index = self.body.blocks.len();
|
||||||
self.body.blocks.push(BuilderBlock {
|
self.body.blocks.push(BuilderBlock {
|
||||||
memories: vec![],
|
memories: vec![],
|
||||||
incomplete_declarations: vec![],
|
|
||||||
stmts: vec![],
|
stmts: vec![],
|
||||||
});
|
});
|
||||||
BlockId(index)
|
BlockId(index)
|
||||||
|
|
@ -1991,7 +1943,6 @@ impl ModuleBuilder {
|
||||||
body: BuilderModuleBody {
|
body: BuilderModuleBody {
|
||||||
blocks: vec![BuilderBlock {
|
blocks: vec![BuilderBlock {
|
||||||
memories: vec![],
|
memories: vec![],
|
||||||
incomplete_declarations: vec![],
|
|
||||||
stmts: vec![],
|
stmts: vec![],
|
||||||
}],
|
}],
|
||||||
annotations_map: HashMap::new(),
|
annotations_map: HashMap::new(),
|
||||||
|
|
@ -2205,42 +2156,6 @@ pub fn wire<T: Type>(implicit_name: ImplicitName<'_>, ty: T) -> Expr<T> {
|
||||||
wire_with_loc(implicit_name.0, SourceLocation::caller(), ty)
|
wire_with_loc(implicit_name.0, SourceLocation::caller(), ty)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[track_caller]
|
|
||||||
fn incomplete_declaration(
|
|
||||||
name: &str,
|
|
||||||
source_location: SourceLocation,
|
|
||||||
) -> Rc<RefCell<IncompleteDeclaration>> {
|
|
||||||
ModuleBuilder::with(|m| {
|
|
||||||
let mut impl_ = m.impl_.borrow_mut();
|
|
||||||
let scoped_name = ScopedNameId(m.name, impl_.name_id_gen.gen(name.intern()));
|
|
||||||
drop(impl_);
|
|
||||||
let retval = Rc::new(RefCell::new(IncompleteDeclaration::Incomplete {
|
|
||||||
name: scoped_name,
|
|
||||||
source_location,
|
|
||||||
}));
|
|
||||||
let mut impl_ = m.impl_.borrow_mut();
|
|
||||||
impl_
|
|
||||||
.body
|
|
||||||
.builder_normal_body()
|
|
||||||
.block(m.block_stack.top())
|
|
||||||
.incomplete_declarations
|
|
||||||
.push(retval.clone());
|
|
||||||
retval
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
#[track_caller]
|
|
||||||
pub fn incomplete_wire_with_loc(name: &str, source_location: SourceLocation) -> IncompleteWire {
|
|
||||||
IncompleteWire {
|
|
||||||
declaration: incomplete_declaration(name, source_location),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[track_caller]
|
|
||||||
pub fn incomplete_wire(implicit_name: ImplicitName<'_>) -> IncompleteWire {
|
|
||||||
incomplete_wire_with_loc(implicit_name.0, SourceLocation::caller())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
pub fn reg_builder_with_loc(name: &str, source_location: SourceLocation) -> RegBuilder<(), (), ()> {
|
pub fn reg_builder_with_loc(name: &str, source_location: SourceLocation) -> RegBuilder<(), (), ()> {
|
||||||
ModuleBuilder::with(|m| {
|
ModuleBuilder::with(|m| {
|
||||||
|
|
|
||||||
|
|
@ -9,8 +9,8 @@ pub use crate::{
|
||||||
int::{Bool, DynSize, IntCmp, KnownSize, SInt, SIntType, Size, UInt, UIntType},
|
int::{Bool, DynSize, IntCmp, KnownSize, SInt, SIntType, Size, UInt, UIntType},
|
||||||
memory::{Mem, MemBuilder, ReadUnderWrite},
|
memory::{Mem, MemBuilder, ReadUnderWrite},
|
||||||
module::{
|
module::{
|
||||||
annotate, connect, connect_any, incomplete_wire, instance, memory, memory_array,
|
annotate, connect, connect_any, instance, memory, memory_array, memory_with_init,
|
||||||
memory_with_init, reg_builder, wire, Instance, Module, ModuleBuilder,
|
reg_builder, wire, Instance, Module, ModuleBuilder,
|
||||||
},
|
},
|
||||||
reg::Reg,
|
reg::Reg,
|
||||||
reset::{AsyncReset, Reset, SyncReset, ToAsyncReset, ToReset, ToSyncReset},
|
reset::{AsyncReset, Reset, SyncReset, ToAsyncReset, ToReset, ToSyncReset},
|
||||||
|
|
|
||||||
|
|
@ -25,5 +25,3 @@ pub use scoped_ref::ScopedRef;
|
||||||
pub use misc::{
|
pub use misc::{
|
||||||
interned_bit, iter_eq_by, BitSliceWriteWithBase, DebugAsDisplay, DebugAsRawString, MakeMutSlice,
|
interned_bit, iter_eq_by, BitSliceWriteWithBase, DebugAsDisplay, DebugAsRawString, MakeMutSlice,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub mod ready_valid;
|
|
||||||
|
|
|
||||||
|
|
@ -1,34 +0,0 @@
|
||||||
use crate::prelude::*;
|
|
||||||
|
|
||||||
#[hdl]
|
|
||||||
pub struct ReadyValid<T> {
|
|
||||||
pub data: HdlOption<T>,
|
|
||||||
#[hdl(flip)]
|
|
||||||
pub ready: Bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: Type> ReadyValid<T> {
|
|
||||||
#[hdl]
|
|
||||||
pub fn fire(expr: Expr<Self>) -> Expr<Bool> {
|
|
||||||
#[hdl]
|
|
||||||
let fire: Bool = wire();
|
|
||||||
#[hdl]
|
|
||||||
match expr.data {
|
|
||||||
HdlNone => connect(fire, false),
|
|
||||||
HdlSome(_) => connect(fire, expr.ready),
|
|
||||||
}
|
|
||||||
fire
|
|
||||||
}
|
|
||||||
#[hdl]
|
|
||||||
pub fn map<R: Type>(
|
|
||||||
expr: Expr<Self>,
|
|
||||||
f: impl FnOnce(Expr<T>) -> Expr<R>,
|
|
||||||
) -> Expr<ReadyValid<R>> {
|
|
||||||
let data = HdlOption::map(expr.data, f);
|
|
||||||
#[hdl]
|
|
||||||
let mapped = wire(ReadyValid[Expr::ty(data).HdlSome]);
|
|
||||||
connect(mapped.data, data);
|
|
||||||
connect(expr.ready, mapped.ready);
|
|
||||||
mapped
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,13 +1,13 @@
|
||||||
// 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 crate::{
|
use crate::{
|
||||||
expr::{Expr, Flow, ToExpr},
|
expr::Flow,
|
||||||
intern::Interned,
|
intern::Interned,
|
||||||
module::{IncompleteDeclaration, NameId, ScopedNameId, StmtDeclaration, StmtWire},
|
module::{NameId, ScopedNameId},
|
||||||
source_location::SourceLocation,
|
source_location::SourceLocation,
|
||||||
ty::{CanonicalType, Type},
|
ty::{CanonicalType, Type},
|
||||||
};
|
};
|
||||||
use std::{cell::RefCell, fmt, rc::Rc};
|
use std::fmt;
|
||||||
|
|
||||||
#[derive(Copy, Clone, Eq, PartialEq, Hash)]
|
#[derive(Copy, Clone, Eq, PartialEq, Hash)]
|
||||||
pub struct Wire<T: Type> {
|
pub struct Wire<T: Type> {
|
||||||
|
|
@ -76,57 +76,3 @@ impl<T: Type> Wire<T> {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
pub struct IncompleteWire {
|
|
||||||
pub(crate) declaration: Rc<RefCell<IncompleteDeclaration>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl IncompleteWire {
|
|
||||||
#[track_caller]
|
|
||||||
pub fn complete<T: Type>(&mut self, ty: T) -> Expr<T> {
|
|
||||||
let canonical_type = ty.canonical();
|
|
||||||
let mut declaration = self.declaration.borrow_mut();
|
|
||||||
if let IncompleteDeclaration::Incomplete {
|
|
||||||
name,
|
|
||||||
source_location,
|
|
||||||
} = *declaration
|
|
||||||
{
|
|
||||||
*declaration = IncompleteDeclaration::Complete(
|
|
||||||
StmtWire {
|
|
||||||
annotations: (),
|
|
||||||
wire: Wire {
|
|
||||||
name,
|
|
||||||
source_location,
|
|
||||||
ty: canonical_type,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
.into(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
match *declaration {
|
|
||||||
IncompleteDeclaration::Complete(StmtDeclaration::Wire(StmtWire {
|
|
||||||
wire:
|
|
||||||
Wire {
|
|
||||||
name,
|
|
||||||
source_location,
|
|
||||||
ty: wire_ty,
|
|
||||||
},
|
|
||||||
..
|
|
||||||
})) => {
|
|
||||||
drop(declaration);
|
|
||||||
assert_eq!(wire_ty, canonical_type, "type mismatch");
|
|
||||||
Wire {
|
|
||||||
name,
|
|
||||||
source_location,
|
|
||||||
ty,
|
|
||||||
}
|
|
||||||
.to_expr()
|
|
||||||
}
|
|
||||||
IncompleteDeclaration::Taken => panic!("can't use wire outside of containing module"),
|
|
||||||
IncompleteDeclaration::Complete(_) | IncompleteDeclaration::Incomplete { .. } => {
|
|
||||||
unreachable!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
error: top-level #[hdl] can only be used on structs, enums, or functions
|
error: top-level #[hdl] can only be used on structs or enums
|
||||||
--> tests/ui/hdl_types.rs:5:1
|
--> tests/ui/hdl_types.rs:5:1
|
||||||
|
|
|
|
||||||
5 | #[hdl]
|
5 | #[hdl]
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue