WIP: use HdlOption[the_type_var] or UInt[123 + n] for creating types
All checks were successful
/ test (push) Successful in 13s
All checks were successful
/ test (push) Successful in 13s
This commit is contained in:
parent
cd99dbc849
commit
5d395a1510
43 changed files with 12842 additions and 12372 deletions
|
@ -2,11 +2,14 @@
|
|||
// See Notices.txt for copyright information
|
||||
use crate::{
|
||||
fold::{impl_fold, DoFold},
|
||||
hdl_type_common::{
|
||||
known_items, ParseFailed, ParseTypes, ParsedGenerics, ParsedType, TypesParser,
|
||||
},
|
||||
is_hdl_attr, kw,
|
||||
module::{check_name_conflicts_with_module_builder, ModuleIO, ModuleIOKind, ModuleKind},
|
||||
options, Errors, HdlAttr,
|
||||
};
|
||||
use num_bigint::{BigInt, Sign};
|
||||
use num_bigint::BigInt;
|
||||
use proc_macro2::{Span, TokenStream};
|
||||
use quote::{quote, quote_spanned, ToTokens};
|
||||
use std::{borrow::Borrow, convert::Infallible};
|
||||
|
@ -87,9 +90,9 @@ macro_rules! with_debug_clone_and_fold {
|
|||
pub(crate) use with_debug_clone_and_fold;
|
||||
|
||||
with_debug_clone_and_fold! {
|
||||
pub(crate) struct HdlLetKindIO<Kind = ModuleIOKind> {
|
||||
pub(crate) struct HdlLetKindIO<Kind = ModuleIOKind, Ty = ParsedType> {
|
||||
pub(crate) colon_token: Token![:],
|
||||
pub(crate) ty: Box<Type>,
|
||||
pub(crate) ty: Box<Ty>,
|
||||
pub(crate) m: kw::m,
|
||||
pub(crate) dot_token: Token![.],
|
||||
pub(crate) kind: Kind,
|
||||
|
@ -98,6 +101,32 @@ with_debug_clone_and_fold! {
|
|||
}
|
||||
}
|
||||
|
||||
impl<Kind: Clone, T: ParseTypes<I>, I> ParseTypes<HdlLetKindIO<Kind, I>> for HdlLetKindIO<Kind, T> {
|
||||
fn parse_types(
|
||||
input: &mut HdlLetKindIO<Kind, I>,
|
||||
parser: &mut TypesParser<'_>,
|
||||
) -> Result<Self, ParseFailed> {
|
||||
let HdlLetKindIO {
|
||||
colon_token,
|
||||
ty,
|
||||
m,
|
||||
dot_token,
|
||||
kind,
|
||||
paren,
|
||||
ty_expr,
|
||||
} = input;
|
||||
Ok(Self {
|
||||
colon_token: *colon_token,
|
||||
ty: ParseTypes::parse_types(ty, parser)?,
|
||||
m: *m,
|
||||
dot_token: *dot_token,
|
||||
kind: kind.clone(),
|
||||
paren: *paren,
|
||||
ty_expr: ty_expr.clone(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn parse_single_fn_arg(input: ParseStream) -> syn::Result<Box<Expr>> {
|
||||
let retval = input.parse()?;
|
||||
let _: Option<Token![,]> = input.parse()?;
|
||||
|
@ -145,17 +174,19 @@ impl<Kind: ToTokens> HdlLetKindToTokens for HdlLetKindIO<Kind> {
|
|||
|
||||
#[derive(Clone, Debug)]
|
||||
pub(crate) struct HdlLetKindInstance {
|
||||
pub(crate) m: kw::m,
|
||||
pub(crate) dot_token: Token![.],
|
||||
pub(crate) instance: kw::instance,
|
||||
pub(crate) paren: Paren,
|
||||
pub(crate) module: Box<Expr>,
|
||||
}
|
||||
|
||||
impl ParseTypes<Self> for HdlLetKindInstance {
|
||||
fn parse_types(input: &mut Self, _parser: &mut TypesParser<'_>) -> Result<Self, ParseFailed> {
|
||||
Ok(input.clone())
|
||||
}
|
||||
}
|
||||
|
||||
impl_fold! {
|
||||
struct HdlLetKindInstance<> {
|
||||
m: kw::m,
|
||||
dot_token: Token![.],
|
||||
instance: kw::instance,
|
||||
paren: Paren,
|
||||
module: Box<Expr>,
|
||||
|
@ -167,14 +198,10 @@ impl HdlLetKindToTokens for HdlLetKindInstance {
|
|||
|
||||
fn expr_to_tokens(&self, tokens: &mut TokenStream) {
|
||||
let Self {
|
||||
m,
|
||||
dot_token,
|
||||
instance,
|
||||
paren,
|
||||
module,
|
||||
} = self;
|
||||
m.to_tokens(tokens);
|
||||
dot_token.to_tokens(tokens);
|
||||
instance.to_tokens(tokens);
|
||||
paren.surround(tokens, |tokens| module.to_tokens(tokens));
|
||||
}
|
||||
|
@ -381,19 +408,21 @@ make_builder_method_enum! {
|
|||
#[derive(Clone, Debug)]
|
||||
pub(crate) struct HdlLetKindRegBuilder {
|
||||
pub(crate) ty: Option<(Token![:], Box<Type>)>,
|
||||
pub(crate) m: kw::m,
|
||||
pub(crate) dot_token: Token![.],
|
||||
pub(crate) reg_builder: kw::reg_builder,
|
||||
pub(crate) reg_builder_paren: Paren,
|
||||
pub(crate) clock_domain: Option<RegBuilderClockDomain>,
|
||||
pub(crate) reset: RegBuilderReset,
|
||||
}
|
||||
|
||||
impl ParseTypes<Self> for HdlLetKindRegBuilder {
|
||||
fn parse_types(input: &mut Self, _parser: &mut TypesParser<'_>) -> Result<Self, ParseFailed> {
|
||||
Ok(input.clone())
|
||||
}
|
||||
}
|
||||
|
||||
impl_fold! {
|
||||
struct HdlLetKindRegBuilder<> {
|
||||
ty: Option<(Token![:], Box<Type>)>,
|
||||
m: kw::m,
|
||||
dot_token: Token![.],
|
||||
reg_builder: kw::reg_builder,
|
||||
reg_builder_paren: Paren,
|
||||
clock_domain: Option<RegBuilderClockDomain>,
|
||||
|
@ -406,10 +435,10 @@ impl HdlLetKindRegBuilder {
|
|||
input: ParseStream,
|
||||
parsed_ty: Option<(Token![:], Box<Type>)>,
|
||||
_after_ty: Token![=],
|
||||
m: kw::m,
|
||||
dot_token: Token![.],
|
||||
m_dot: Option<(kw::m, Token![.])>,
|
||||
reg_builder: kw::reg_builder,
|
||||
) -> syn::Result<Self> {
|
||||
check_empty_m_dot(m_dot, reg_builder)?;
|
||||
let _reg_builder_paren_inner;
|
||||
let reg_builder_paren = parenthesized!(_reg_builder_paren_inner in input);
|
||||
let mut clock_domain = None;
|
||||
|
@ -430,8 +459,6 @@ impl HdlLetKindRegBuilder {
|
|||
}
|
||||
Ok(Self {
|
||||
ty: parsed_ty,
|
||||
m,
|
||||
dot_token,
|
||||
reg_builder,
|
||||
reg_builder_paren,
|
||||
clock_domain,
|
||||
|
@ -451,15 +478,11 @@ impl HdlLetKindToTokens for HdlLetKindRegBuilder {
|
|||
fn expr_to_tokens(&self, tokens: &mut TokenStream) {
|
||||
let Self {
|
||||
ty: _,
|
||||
m,
|
||||
dot_token,
|
||||
reg_builder,
|
||||
reg_builder_paren,
|
||||
clock_domain,
|
||||
reset,
|
||||
} = self;
|
||||
m.to_tokens(tokens);
|
||||
dot_token.to_tokens(tokens);
|
||||
reg_builder.to_tokens(tokens);
|
||||
reg_builder_paren.surround(tokens, |_tokens| {});
|
||||
clock_domain.to_tokens(tokens);
|
||||
|
@ -470,18 +493,20 @@ impl HdlLetKindToTokens for HdlLetKindRegBuilder {
|
|||
#[derive(Clone, Debug)]
|
||||
pub(crate) struct HdlLetKindWire {
|
||||
pub(crate) ty: Option<(Token![:], Box<Type>)>,
|
||||
pub(crate) m: kw::m,
|
||||
pub(crate) dot_token: Token![.],
|
||||
pub(crate) wire: kw::wire,
|
||||
pub(crate) paren: Paren,
|
||||
pub(crate) ty_expr: Option<Box<Expr>>,
|
||||
}
|
||||
|
||||
impl ParseTypes<Self> for HdlLetKindWire {
|
||||
fn parse_types(input: &mut Self, _parser: &mut TypesParser<'_>) -> Result<Self, ParseFailed> {
|
||||
Ok(input.clone())
|
||||
}
|
||||
}
|
||||
|
||||
impl_fold! {
|
||||
struct HdlLetKindWire<> {
|
||||
ty: Option<(Token![:], Box<Type>)>,
|
||||
m: kw::m,
|
||||
dot_token: Token![.],
|
||||
wire: kw::wire,
|
||||
paren: Paren,
|
||||
ty_expr: Option<Box<Expr>>,
|
||||
|
@ -499,14 +524,10 @@ impl HdlLetKindToTokens for HdlLetKindWire {
|
|||
fn expr_to_tokens(&self, tokens: &mut TokenStream) {
|
||||
let Self {
|
||||
ty: _,
|
||||
m,
|
||||
dot_token,
|
||||
wire,
|
||||
paren,
|
||||
ty_expr,
|
||||
} = self;
|
||||
m.to_tokens(tokens);
|
||||
dot_token.to_tokens(tokens);
|
||||
wire.to_tokens(tokens);
|
||||
paren.surround(tokens, |tokens| ty_expr.to_tokens(tokens));
|
||||
}
|
||||
|
@ -627,16 +648,18 @@ impl ToTokens for MemoryFn {
|
|||
#[derive(Clone, Debug)]
|
||||
pub(crate) struct HdlLetKindMemory {
|
||||
pub(crate) ty: Option<(Token![:], Box<Type>)>,
|
||||
pub(crate) m: kw::m,
|
||||
pub(crate) dot_token: Token![.],
|
||||
pub(crate) memory_fn: MemoryFn,
|
||||
}
|
||||
|
||||
impl ParseTypes<Self> for HdlLetKindMemory {
|
||||
fn parse_types(input: &mut Self, _parser: &mut TypesParser<'_>) -> Result<Self, ParseFailed> {
|
||||
Ok(input.clone())
|
||||
}
|
||||
}
|
||||
|
||||
impl_fold! {
|
||||
struct HdlLetKindMemory<> {
|
||||
ty: Option<(Token![:], Box<Type>)>,
|
||||
m: kw::m,
|
||||
dot_token: Token![.],
|
||||
memory_fn: MemoryFn,
|
||||
}
|
||||
}
|
||||
|
@ -650,14 +673,7 @@ impl HdlLetKindToTokens for HdlLetKindMemory {
|
|||
}
|
||||
|
||||
fn expr_to_tokens(&self, tokens: &mut TokenStream) {
|
||||
let Self {
|
||||
ty: _,
|
||||
m,
|
||||
dot_token,
|
||||
memory_fn,
|
||||
} = self;
|
||||
m.to_tokens(tokens);
|
||||
dot_token.to_tokens(tokens);
|
||||
let Self { ty: _, memory_fn } = self;
|
||||
memory_fn.to_tokens(tokens);
|
||||
}
|
||||
}
|
||||
|
@ -667,22 +683,20 @@ impl HdlLetKindMemory {
|
|||
input: ParseStream,
|
||||
parsed_ty: Option<(Token![:], Box<Type>)>,
|
||||
_after_ty: Token![=],
|
||||
m: kw::m,
|
||||
dot_token: Token![.],
|
||||
m_dot: Option<(kw::m, Token![.])>,
|
||||
memory_fn_name: MemoryFnName,
|
||||
) -> syn::Result<Self> {
|
||||
check_empty_m_dot(m_dot, memory_fn_name)?;
|
||||
Ok(Self {
|
||||
ty: parsed_ty,
|
||||
m,
|
||||
dot_token,
|
||||
memory_fn: MemoryFn::parse_rest(input, memory_fn_name)?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub(crate) enum HdlLetKind {
|
||||
IO(HdlLetKindIO),
|
||||
pub(crate) enum HdlLetKind<IOType = ParsedType> {
|
||||
IO(HdlLetKindIO<ModuleIOKind, IOType>),
|
||||
Instance(HdlLetKindInstance),
|
||||
RegBuilder(HdlLetKindRegBuilder),
|
||||
Wire(HdlLetKindWire),
|
||||
|
@ -690,8 +704,8 @@ pub(crate) enum HdlLetKind {
|
|||
}
|
||||
|
||||
impl_fold! {
|
||||
enum HdlLetKind<> {
|
||||
IO(HdlLetKindIO),
|
||||
enum HdlLetKind<IOType,> {
|
||||
IO(HdlLetKindIO<ModuleIOKind, IOType>),
|
||||
Instance(HdlLetKindInstance),
|
||||
RegBuilder(HdlLetKindRegBuilder),
|
||||
Wire(HdlLetKindWire),
|
||||
|
@ -699,6 +713,27 @@ impl_fold! {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: ParseTypes<I>, I> ParseTypes<HdlLetKind<I>> for HdlLetKind<T> {
|
||||
fn parse_types(
|
||||
input: &mut HdlLetKind<I>,
|
||||
parser: &mut TypesParser<'_>,
|
||||
) -> Result<Self, ParseFailed> {
|
||||
match input {
|
||||
HdlLetKind::IO(input) => ParseTypes::parse_types(input, parser).map(HdlLetKind::IO),
|
||||
HdlLetKind::Instance(input) => {
|
||||
ParseTypes::parse_types(input, parser).map(HdlLetKind::Instance)
|
||||
}
|
||||
HdlLetKind::RegBuilder(input) => {
|
||||
ParseTypes::parse_types(input, parser).map(HdlLetKind::RegBuilder)
|
||||
}
|
||||
HdlLetKind::Wire(input) => ParseTypes::parse_types(input, parser).map(HdlLetKind::Wire),
|
||||
HdlLetKind::Memory(input) => {
|
||||
ParseTypes::parse_types(input, parser).map(HdlLetKind::Memory)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn parsed_ty_or_err(
|
||||
parsed_ty: Option<(Token![:], Box<Type>)>,
|
||||
after_ty: Token![=],
|
||||
|
@ -710,15 +745,15 @@ fn parsed_ty_or_err(
|
|||
}
|
||||
}
|
||||
|
||||
impl HdlLetKindIO {
|
||||
impl HdlLetKindIO<ModuleIOKind, Type> {
|
||||
fn rest_of_parse(
|
||||
input: ParseStream,
|
||||
parsed_ty: Option<(Token![:], Box<Type>)>,
|
||||
after_ty: Token![=],
|
||||
m: kw::m,
|
||||
dot_token: Token![.],
|
||||
m_dot: Option<(kw::m, Token![.])>,
|
||||
kind: ModuleIOKind,
|
||||
) -> syn::Result<Self> {
|
||||
let (m, dot_token) = unwrap_m_dot(m_dot, kind)?;
|
||||
let (colon_token, ty) = parsed_ty_or_err(parsed_ty, after_ty)?;
|
||||
let paren_contents;
|
||||
Ok(Self {
|
||||
|
@ -733,7 +768,36 @@ impl HdlLetKindIO {
|
|||
}
|
||||
}
|
||||
|
||||
impl HdlLetKindParse for HdlLetKind {
|
||||
fn check_empty_m_dot(m_dot: Option<(kw::m, Token![.])>, kind: impl ToTokens) -> syn::Result<()> {
|
||||
if let Some((m, dot_token)) = m_dot {
|
||||
Err(Error::new_spanned(
|
||||
quote! {#m #dot_token #kind},
|
||||
format_args!(
|
||||
"{} is a free function, not a method of ModuleBuilder: try removing the `m.`",
|
||||
kind.to_token_stream()
|
||||
),
|
||||
))
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
fn unwrap_m_dot(
|
||||
m_dot: Option<(kw::m, Token![.])>,
|
||||
kind: impl ToTokens,
|
||||
) -> syn::Result<(kw::m, Token![.])> {
|
||||
m_dot.ok_or_else(|| {
|
||||
Error::new_spanned(
|
||||
&kind,
|
||||
format_args!(
|
||||
"{} is a ModuleBuilder method, not a free function: try prefixing it with `m.`",
|
||||
kind.to_token_stream()
|
||||
),
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
impl HdlLetKindParse for HdlLetKind<Type> {
|
||||
type ParsedTy = Option<(Token![:], Box<Type>)>;
|
||||
|
||||
fn parse_ty(input: ParseStream) -> syn::Result<Self::ParsedTy> {
|
||||
|
@ -753,16 +817,20 @@ impl HdlLetKindParse for HdlLetKind {
|
|||
after_ty: Token![=],
|
||||
input: ParseStream,
|
||||
) -> syn::Result<Self> {
|
||||
let m = input.parse()?;
|
||||
let dot_token = input.parse()?;
|
||||
let m_dot = if input.peek(kw::m) && input.peek2(Token![.]) {
|
||||
let m = input.parse()?;
|
||||
let dot_token = input.parse()?;
|
||||
Some((m, dot_token))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let kind: LetFnKind = input.parse()?;
|
||||
match kind {
|
||||
LetFnKind::Input(input_token) => HdlLetKindIO::rest_of_parse(
|
||||
input,
|
||||
parsed_ty,
|
||||
after_ty,
|
||||
m,
|
||||
dot_token,
|
||||
m_dot,
|
||||
ModuleIOKind::Input(input_token),
|
||||
)
|
||||
.map(Self::IO),
|
||||
|
@ -770,8 +838,7 @@ impl HdlLetKindParse for HdlLetKind {
|
|||
input,
|
||||
parsed_ty,
|
||||
after_ty,
|
||||
m,
|
||||
dot_token,
|
||||
m_dot,
|
||||
ModuleIOKind::Output(output),
|
||||
)
|
||||
.map(Self::IO),
|
||||
|
@ -782,30 +849,23 @@ impl HdlLetKindParse for HdlLetKind {
|
|||
"type annotation not allowed for instance",
|
||||
));
|
||||
}
|
||||
check_empty_m_dot(m_dot, kind)?;
|
||||
let paren_contents;
|
||||
Ok(Self::Instance(HdlLetKindInstance {
|
||||
m,
|
||||
dot_token,
|
||||
instance,
|
||||
paren: parenthesized!(paren_contents in input),
|
||||
module: paren_contents.call(parse_single_fn_arg)?,
|
||||
}))
|
||||
}
|
||||
LetFnKind::RegBuilder((reg_builder,)) => HdlLetKindRegBuilder::rest_of_parse(
|
||||
input,
|
||||
parsed_ty,
|
||||
after_ty,
|
||||
m,
|
||||
dot_token,
|
||||
reg_builder,
|
||||
)
|
||||
.map(Self::RegBuilder),
|
||||
LetFnKind::RegBuilder((reg_builder,)) => {
|
||||
HdlLetKindRegBuilder::rest_of_parse(input, parsed_ty, after_ty, m_dot, reg_builder)
|
||||
.map(Self::RegBuilder)
|
||||
}
|
||||
LetFnKind::Wire((wire,)) => {
|
||||
check_empty_m_dot(m_dot, wire)?;
|
||||
let paren_contents;
|
||||
Ok(Self::Wire(HdlLetKindWire {
|
||||
ty: parsed_ty,
|
||||
m,
|
||||
dot_token,
|
||||
wire,
|
||||
paren: parenthesized!(paren_contents in input),
|
||||
ty_expr: paren_contents.call(parse_optional_fn_arg)?,
|
||||
|
@ -815,8 +875,7 @@ impl HdlLetKindParse for HdlLetKind {
|
|||
input,
|
||||
parsed_ty,
|
||||
after_ty,
|
||||
m,
|
||||
dot_token,
|
||||
m_dot,
|
||||
MemoryFnName::Memory(fn_name),
|
||||
)
|
||||
.map(Self::Memory),
|
||||
|
@ -824,8 +883,7 @@ impl HdlLetKindParse for HdlLetKind {
|
|||
input,
|
||||
parsed_ty,
|
||||
after_ty,
|
||||
m,
|
||||
dot_token,
|
||||
m_dot,
|
||||
MemoryFnName::MemoryArray(fn_name),
|
||||
)
|
||||
.map(Self::Memory),
|
||||
|
@ -833,8 +891,7 @@ impl HdlLetKindParse for HdlLetKind {
|
|||
input,
|
||||
parsed_ty,
|
||||
after_ty,
|
||||
m,
|
||||
dot_token,
|
||||
m_dot,
|
||||
MemoryFnName::MemoryWithInit(fn_name),
|
||||
)
|
||||
.map(Self::Memory),
|
||||
|
@ -878,6 +935,34 @@ with_debug_clone_and_fold! {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: ParseTypes<I>, I> ParseTypes<HdlLet<I>> for HdlLet<T> {
|
||||
fn parse_types(
|
||||
input: &mut HdlLet<I>,
|
||||
parser: &mut TypesParser<'_>,
|
||||
) -> Result<Self, ParseFailed> {
|
||||
let HdlLet {
|
||||
attrs,
|
||||
hdl_attr,
|
||||
let_token,
|
||||
mut_token,
|
||||
name,
|
||||
eq_token,
|
||||
kind,
|
||||
semi_token,
|
||||
} = input;
|
||||
Ok(Self {
|
||||
attrs: attrs.clone(),
|
||||
hdl_attr: hdl_attr.clone(),
|
||||
let_token: *let_token,
|
||||
mut_token: *mut_token,
|
||||
name: name.clone(),
|
||||
eq_token: *eq_token,
|
||||
kind: T::parse_types(kind, parser)?,
|
||||
semi_token: *semi_token,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<Kind> HdlLet<Kind> {
|
||||
pub(crate) fn try_map<Kind2, E>(
|
||||
self,
|
||||
|
@ -1006,7 +1091,7 @@ fn wrap_ty_with_expr(ty: impl ToTokens) -> Type {
|
|||
fn unwrap_or_static_type(expr: Option<impl ToTokens>, span: Span) -> TokenStream {
|
||||
expr.map(ToTokens::into_token_stream).unwrap_or_else(|| {
|
||||
quote_spanned! {span=>
|
||||
::fayalite::ty::StaticType::static_type()
|
||||
::fayalite::ty::StaticType::TYPE
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -1026,14 +1111,15 @@ impl<T: ToString> ToTokens for ImplicitName<T> {
|
|||
}
|
||||
}
|
||||
|
||||
struct Visitor {
|
||||
struct Visitor<'a> {
|
||||
module_kind: ModuleKind,
|
||||
errors: Errors,
|
||||
io: Vec<ModuleIO>,
|
||||
block_depth: usize,
|
||||
parsed_generics: &'a ParsedGenerics,
|
||||
}
|
||||
|
||||
impl Visitor {
|
||||
impl Visitor<'_> {
|
||||
fn take_hdl_attr<T: Parse>(&mut self, attrs: &mut Vec<Attribute>) -> Option<HdlAttr<T>> {
|
||||
self.errors.unwrap_or(
|
||||
HdlAttr::parse_and_take_attr(attrs),
|
||||
|
@ -1086,7 +1172,7 @@ impl Visitor {
|
|||
parse_quote_spanned! {if_token.span=>
|
||||
#(#attrs)*
|
||||
{
|
||||
let mut __scope = m.if_(#cond);
|
||||
let mut __scope = ::fayalite::module::if_(#cond);
|
||||
let _: () = #then_branch;
|
||||
let mut __scope = __scope.else_();
|
||||
let _: () = #else_expr;
|
||||
|
@ -1096,7 +1182,7 @@ impl Visitor {
|
|||
parse_quote_spanned! {if_token.span=>
|
||||
#(#attrs)*
|
||||
{
|
||||
let mut __scope = m.if_(#cond);
|
||||
let mut __scope = ::fayalite::module::if_(#cond);
|
||||
let _: () = #then_branch;
|
||||
}
|
||||
}
|
||||
|
@ -1157,8 +1243,6 @@ impl Visitor {
|
|||
eq_token,
|
||||
kind:
|
||||
HdlLetKindInstance {
|
||||
m,
|
||||
dot_token,
|
||||
instance,
|
||||
paren,
|
||||
module,
|
||||
|
@ -1166,7 +1250,7 @@ impl Visitor {
|
|||
semi_token,
|
||||
} = hdl_let;
|
||||
self.require_normal_module(instance);
|
||||
let mut expr = quote! {#m #dot_token #instance};
|
||||
let mut expr = instance.to_token_stream();
|
||||
paren.surround(&mut expr, |expr| {
|
||||
let name_str = ImplicitName {
|
||||
name: &name,
|
||||
|
@ -1191,11 +1275,9 @@ impl Visitor {
|
|||
}
|
||||
fn process_hdl_let_reg_builder(&mut self, hdl_let: HdlLet<HdlLetKindRegBuilder>) -> Local {
|
||||
let name = &hdl_let.name;
|
||||
let m = hdl_let.kind.m;
|
||||
let dot = hdl_let.kind.dot_token;
|
||||
let reg_builder = hdl_let.kind.reg_builder;
|
||||
self.require_normal_module(reg_builder);
|
||||
let mut expr = quote! {#m #dot #reg_builder};
|
||||
let mut expr = reg_builder.to_token_stream();
|
||||
hdl_let.kind.reg_builder_paren.surround(&mut expr, |expr| {
|
||||
let name_str = ImplicitName {
|
||||
name,
|
||||
|
@ -1244,12 +1326,10 @@ impl Visitor {
|
|||
}
|
||||
fn process_hdl_let_wire(&mut self, hdl_let: HdlLet<HdlLetKindWire>) -> Local {
|
||||
let name = &hdl_let.name;
|
||||
let m = hdl_let.kind.m;
|
||||
let dot = hdl_let.kind.dot_token;
|
||||
let wire = hdl_let.kind.wire;
|
||||
self.require_normal_module(wire);
|
||||
let ty_expr = unwrap_or_static_type(hdl_let.kind.ty_expr.as_ref(), wire.span());
|
||||
let mut expr = quote! {#m #dot #wire};
|
||||
let mut expr = wire.to_token_stream();
|
||||
hdl_let.kind.paren.surround(&mut expr, |expr| {
|
||||
let name_str = ImplicitName {
|
||||
name,
|
||||
|
@ -1279,18 +1359,19 @@ impl Visitor {
|
|||
}
|
||||
fn process_hdl_let_memory(&mut self, hdl_let: HdlLet<HdlLetKindMemory>) -> Local {
|
||||
let name = &hdl_let.name;
|
||||
let m = hdl_let.kind.m;
|
||||
let dot = hdl_let.kind.dot_token;
|
||||
let memory_fn = hdl_let.kind.memory_fn;
|
||||
let memory_fn_name = memory_fn.name();
|
||||
self.require_normal_module(memory_fn_name);
|
||||
let mut expr = quote! {#m #dot #memory_fn_name};
|
||||
let mut expr = memory_fn_name.to_token_stream();
|
||||
let (paren, arg) = match memory_fn {
|
||||
MemoryFn::Memory {
|
||||
memory,
|
||||
paren,
|
||||
ty_expr,
|
||||
} => (paren, unwrap_or_static_type(ty_expr.as_ref(), memory.span())),
|
||||
} => (
|
||||
paren,
|
||||
unwrap_or_static_type(ty_expr.as_ref(), memory.span()),
|
||||
),
|
||||
MemoryFn::MemoryArray {
|
||||
memory_array,
|
||||
paren,
|
||||
|
@ -1377,16 +1458,17 @@ impl Visitor {
|
|||
let value: BigInt = self
|
||||
.errors
|
||||
.ok(base10_digits.parse().map_err(|e| Error::new(span, e)))?;
|
||||
let (negative, bytes) = match value.sign() {
|
||||
Sign::Minus => (true, value.magnitude().to_bytes_le()),
|
||||
Sign::NoSign => (false, vec![]),
|
||||
Sign::Plus => (false, value.magnitude().to_bytes_le()),
|
||||
let bytes = value.to_signed_bytes_le();
|
||||
let path = if signed {
|
||||
known_items::SInt(span).path
|
||||
} else {
|
||||
known_items::UInt(span).path
|
||||
};
|
||||
Some(parse_quote_spanned! {span=>
|
||||
::fayalite::int::make_int_literal::<#signed, #width>(
|
||||
#negative,
|
||||
<#path<#width> as ::fayalite::int::BoolOrIntType>::le_bytes_to_expr_wrapping(
|
||||
&[#(#bytes,)*],
|
||||
).to_int_expr()
|
||||
#width,
|
||||
)
|
||||
})
|
||||
}
|
||||
fn process_literal(&mut self, literal: ExprLit) -> Expr {
|
||||
|
@ -1449,7 +1531,7 @@ fn empty_let() -> Local {
|
|||
}
|
||||
}
|
||||
|
||||
impl Fold for Visitor {
|
||||
impl Fold for Visitor<'_> {
|
||||
fn fold_item(&mut self, item: Item) -> Item {
|
||||
// don't process item interiors
|
||||
item
|
||||
|
@ -1536,11 +1618,16 @@ impl Fold for Visitor {
|
|||
Some(None) => return fold_local(self, let_stmt),
|
||||
Some(Some(HdlAttr { .. })) => {}
|
||||
};
|
||||
let hdl_let = syn::parse2::<HdlLet>(let_stmt.into_token_stream());
|
||||
let hdl_let = syn::parse2::<HdlLet<HdlLetKind<Type>>>(let_stmt.into_token_stream());
|
||||
let Some(hdl_let) = self.errors.ok(hdl_let) else {
|
||||
return empty_let();
|
||||
};
|
||||
let hdl_let = hdl_let.do_fold(self);
|
||||
let mut hdl_let = hdl_let.do_fold(self);
|
||||
let Ok(hdl_let) =
|
||||
TypesParser::run_with_errors(self.parsed_generics, &mut hdl_let, &mut self.errors)
|
||||
else {
|
||||
return empty_let();
|
||||
};
|
||||
self.process_hdl_let(hdl_let)
|
||||
}
|
||||
|
||||
|
@ -1563,12 +1650,14 @@ impl Fold for Visitor {
|
|||
pub(crate) fn transform_body(
|
||||
module_kind: ModuleKind,
|
||||
mut body: Box<Block>,
|
||||
parsed_generics: &ParsedGenerics,
|
||||
) -> syn::Result<(Box<Block>, Vec<ModuleIO>)> {
|
||||
let mut visitor = Visitor {
|
||||
module_kind,
|
||||
errors: Errors::new(),
|
||||
io: vec![],
|
||||
block_depth: 0,
|
||||
parsed_generics,
|
||||
};
|
||||
*body = syn::fold::fold_block(&mut visitor, *body);
|
||||
visitor.errors.finish()?;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
// See Notices.txt for copyright information
|
||||
use crate::{module::transform_body::Visitor, options, Errors, HdlAttr, PairsIterExt};
|
||||
use crate::{module::transform_body::Visitor, Errors, HdlAttr, PairsIterExt};
|
||||
use proc_macro2::{Span, TokenStream};
|
||||
use quote::{format_ident, quote_spanned, ToTokens, TokenStreamExt};
|
||||
use syn::{
|
||||
|
@ -13,15 +13,6 @@ use syn::{
|
|||
FieldValue, Ident, Index, Member, Path, PathArguments, PathSegment, Token, TypePath,
|
||||
};
|
||||
|
||||
options! {
|
||||
#[options = AggregateLiteralOptions]
|
||||
#[no_ident_fragment]
|
||||
pub(crate) enum AggregateLiteralOption {
|
||||
Struct(struct_),
|
||||
Enum(enum_),
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub(crate) struct StructOrEnumPath {
|
||||
pub(crate) ty: TypePath,
|
||||
|
@ -79,11 +70,7 @@ impl StructOrEnumPath {
|
|||
},
|
||||
]
|
||||
};
|
||||
pub(crate) fn new(
|
||||
errors: &mut Errors,
|
||||
path: TypePath,
|
||||
options: &AggregateLiteralOptions,
|
||||
) -> Result<Self, ()> {
|
||||
pub(crate) fn new(errors: &mut Errors, path: TypePath) -> Result<Self, ()> {
|
||||
let Path {
|
||||
leading_colon,
|
||||
segments,
|
||||
|
@ -95,18 +82,6 @@ impl StructOrEnumPath {
|
|||
None
|
||||
};
|
||||
let enum_type = 'guess_enum_type: {
|
||||
if options.enum_.is_some() {
|
||||
if let Some((struct_,)) = options.struct_ {
|
||||
errors.error(
|
||||
struct_,
|
||||
"can't specify both #[hdl(enum)] and #[hdl(struct)]",
|
||||
);
|
||||
}
|
||||
break 'guess_enum_type Some(None);
|
||||
}
|
||||
if options.struct_.is_some() {
|
||||
break 'guess_enum_type None;
|
||||
}
|
||||
if path.qself.is_none() && leading_colon.is_none() && segments.len() == 1 {
|
||||
let PathSegment { ident, arguments } = &segments[0];
|
||||
for &SingleSegmentVariant {
|
||||
|
@ -330,7 +305,7 @@ impl ToTokens for StructOrEnumLiteral {
|
|||
}
|
||||
}
|
||||
|
||||
impl Visitor {
|
||||
impl Visitor<'_> {
|
||||
pub(crate) fn process_hdl_array(
|
||||
&mut self,
|
||||
hdl_attr: HdlAttr<Nothing>,
|
||||
|
@ -358,7 +333,7 @@ impl Visitor {
|
|||
}
|
||||
pub(crate) fn process_struct_enum(
|
||||
&mut self,
|
||||
hdl_attr: HdlAttr<AggregateLiteralOptions>,
|
||||
hdl_attr: HdlAttr<Nothing>,
|
||||
mut literal: StructOrEnumLiteral,
|
||||
) -> Expr {
|
||||
let span = hdl_attr.hdl.span;
|
||||
|
@ -384,7 +359,7 @@ impl Visitor {
|
|||
parse_quote! { #field_var }
|
||||
});
|
||||
let Ok(StructOrEnumPath { ty, variant }) =
|
||||
StructOrEnumPath::new(&mut self.errors, literal.path.clone(), &hdl_attr.body)
|
||||
StructOrEnumPath::new(&mut self.errors, literal.path.clone())
|
||||
else {
|
||||
return parse_quote_spanned! {span=>
|
||||
{}
|
||||
|
@ -445,11 +420,59 @@ impl Visitor {
|
|||
}
|
||||
pub(crate) fn process_hdl_struct(
|
||||
&mut self,
|
||||
hdl_attr: HdlAttr<AggregateLiteralOptions>,
|
||||
hdl_attr: HdlAttr<Nothing>,
|
||||
expr_struct: ExprStruct,
|
||||
) -> Expr {
|
||||
self.require_normal_module(&hdl_attr);
|
||||
self.process_struct_enum(hdl_attr, expr_struct.into())
|
||||
let name_span = expr_struct.path.segments.last().unwrap().ident.span();
|
||||
let builder_ident = format_ident!("__builder", span = name_span);
|
||||
let empty_builder = if expr_struct.qself.is_some()
|
||||
|| expr_struct
|
||||
.path
|
||||
.segments
|
||||
.iter()
|
||||
.any(|seg| !seg.arguments.is_none())
|
||||
{
|
||||
let ty = TypePath {
|
||||
qself: expr_struct.qself,
|
||||
path: expr_struct.path,
|
||||
};
|
||||
let builder_ty = quote_spanned! {name_span=>
|
||||
<#ty as ::fayalite::bundle::BundleType>::Builder
|
||||
};
|
||||
quote_spanned! {name_span=>
|
||||
<#builder_ty as ::fayalite::__std::default::Default>::default()
|
||||
}
|
||||
} else {
|
||||
let path = ExprPath {
|
||||
attrs: vec![],
|
||||
qself: expr_struct.qself,
|
||||
path: expr_struct.path,
|
||||
};
|
||||
quote_spanned! {name_span=>
|
||||
#path::__bundle_builder()
|
||||
}
|
||||
};
|
||||
let field_calls = Vec::from_iter(expr_struct.fields.iter().map(
|
||||
|FieldValue {
|
||||
attrs: _,
|
||||
member,
|
||||
colon_token: _,
|
||||
expr,
|
||||
}| {
|
||||
let field_fn = format_ident!("field_{}", member);
|
||||
quote_spanned! {member.span()=>
|
||||
let #builder_ident = #builder_ident.#field_fn(#expr);
|
||||
}
|
||||
},
|
||||
));
|
||||
parse_quote_spanned! {name_span=>
|
||||
{
|
||||
let #builder_ident = #empty_builder;
|
||||
#(#field_calls)*
|
||||
::fayalite::expr::ToExpr::to_expr(&#builder_ident)
|
||||
}
|
||||
}
|
||||
}
|
||||
pub(crate) fn process_hdl_tuple(
|
||||
&mut self,
|
||||
|
@ -473,7 +496,7 @@ impl Visitor {
|
|||
}
|
||||
pub(crate) fn process_hdl_call(
|
||||
&mut self,
|
||||
hdl_attr: HdlAttr<AggregateLiteralOptions>,
|
||||
hdl_attr: HdlAttr<Nothing>,
|
||||
expr_call: ExprCall,
|
||||
) -> Expr {
|
||||
self.require_normal_module(&hdl_attr);
|
||||
|
|
|
@ -3,8 +3,7 @@
|
|||
use crate::{
|
||||
fold::impl_fold,
|
||||
module::transform_body::{
|
||||
expand_aggregate_literals::{AggregateLiteralOptions, StructOrEnumPath},
|
||||
with_debug_clone_and_fold, Visitor,
|
||||
expand_aggregate_literals::StructOrEnumPath, with_debug_clone_and_fold, Visitor,
|
||||
},
|
||||
Errors, HdlAttr, PairsIterExt,
|
||||
};
|
||||
|
@ -561,8 +560,7 @@ struct HdlMatchParseState<'a> {
|
|||
|
||||
impl HdlMatchParseState<'_> {
|
||||
fn resolve_enum_struct_path(&mut self, path: TypePath) -> Result<Path, ()> {
|
||||
let StructOrEnumPath { ty, variant } =
|
||||
StructOrEnumPath::new(self.errors, path, &AggregateLiteralOptions::default())?;
|
||||
let StructOrEnumPath { ty, variant } = StructOrEnumPath::new(self.errors, path)?;
|
||||
Ok(if let Some((_variant_path, variant_name)) = variant {
|
||||
parse_quote_spanned! {self.span=>
|
||||
__MatchTy::<#ty>::#variant_name
|
||||
|
@ -575,7 +573,7 @@ impl HdlMatchParseState<'_> {
|
|||
}
|
||||
}
|
||||
|
||||
impl Visitor {
|
||||
impl Visitor<'_> {
|
||||
pub(crate) fn process_hdl_match(
|
||||
&mut self,
|
||||
_hdl_attr: HdlAttr<Nothing>,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue