diff --git a/crates/fayalite-proc-macros-impl/src/hdl_bundle.rs b/crates/fayalite-proc-macros-impl/src/hdl_bundle.rs index 7f7d626..f29f43a 100644 --- a/crates/fayalite-proc-macros-impl/src/hdl_bundle.rs +++ b/crates/fayalite-proc-macros-impl/src/hdl_bundle.rs @@ -19,13 +19,13 @@ use syn::{ #[derive(Clone, Debug)] pub(crate) struct ParsedBundle { pub(crate) attrs: Vec, - pub(crate) options: HdlAttr, + pub(crate) options: HdlAttr, pub(crate) vis: Visibility, pub(crate) struct_token: Token![struct], pub(crate) ident: Ident, pub(crate) generics: MaybeParsed, pub(crate) fields: MaybeParsed, - pub(crate) field_flips: Vec>>, + pub(crate) field_flips: Vec>>, pub(crate) mask_type_ident: Ident, pub(crate) mask_type_match_variant_ident: Ident, pub(crate) match_variant_ident: Ident, @@ -38,7 +38,7 @@ impl ParsedBundle { errors: &mut Errors, field: &mut Field, index: usize, - ) -> Option> { + ) -> Option> { let Field { attrs, vis: _, @@ -71,9 +71,7 @@ impl ParsedBundle { } = item; let mut errors = Errors::new(); let mut options = errors - .unwrap_or_default(HdlAttr::::parse_and_take_attr( - &mut attrs, - )) + .unwrap_or_default(HdlAttr::::parse_and_take_attr(&mut attrs)) .unwrap_or_default(); errors.ok(options.body.validate()); let ItemOptions { diff --git a/crates/fayalite-proc-macros-impl/src/hdl_enum.rs b/crates/fayalite-proc-macros-impl/src/hdl_enum.rs index d7e5b61..1e0b66b 100644 --- a/crates/fayalite-proc-macros-impl/src/hdl_enum.rs +++ b/crates/fayalite-proc-macros-impl/src/hdl_enum.rs @@ -3,7 +3,7 @@ use crate::{ common_derives, get_target, ItemOptions, MakeHdlTypeExpr, MaybeParsed, ParsedGenerics, ParsedType, SplitForImpl, TypesParser, WrappedInConst, }, - kw, Errors, HdlAttr, PairsIterExt, + Errors, HdlAttr, PairsIterExt, }; use proc_macro2::TokenStream; use quote::{format_ident, quote_spanned, ToTokens}; @@ -29,7 +29,7 @@ crate::options! { pub(crate) struct ParsedVariantField { pub(crate) paren_token: Paren, pub(crate) attrs: Vec, - pub(crate) options: HdlAttr, + pub(crate) options: HdlAttr, pub(crate) ty: MaybeParsed, pub(crate) comma_token: Option, } @@ -37,7 +37,7 @@ pub(crate) struct ParsedVariantField { #[derive(Clone, Debug)] pub(crate) struct ParsedVariant { pub(crate) attrs: Vec, - pub(crate) options: HdlAttr, + pub(crate) options: HdlAttr, pub(crate) ident: Ident, pub(crate) field: Option, } @@ -119,7 +119,7 @@ impl ParsedVariant { #[derive(Clone, Debug)] pub(crate) struct ParsedEnum { pub(crate) attrs: Vec, - pub(crate) options: HdlAttr, + pub(crate) options: HdlAttr, pub(crate) vis: Visibility, pub(crate) enum_token: Token![enum], pub(crate) ident: Ident, @@ -142,9 +142,7 @@ impl ParsedEnum { } = item; let mut errors = Errors::new(); let mut options = errors - .unwrap_or_default(HdlAttr::::parse_and_take_attr( - &mut attrs, - )) + .unwrap_or_default(HdlAttr::::parse_and_take_attr(&mut attrs)) .unwrap_or_default(); errors.ok(options.body.validate()); let ItemOptions { diff --git a/crates/fayalite-proc-macros-impl/src/hdl_type_common.rs b/crates/fayalite-proc-macros-impl/src/hdl_type_common.rs index e33d0e0..88da9a7 100644 --- a/crates/fayalite-proc-macros-impl/src/hdl_type_common.rs +++ b/crates/fayalite-proc-macros-impl/src/hdl_type_common.rs @@ -1745,7 +1745,7 @@ impl, I, P: Clone> ParseTypes> for Punctuated< pub(crate) enum UnparsedGenericParam { Type { attrs: Vec, - options: HdlAttr, + options: HdlAttr, ident: Ident, colon_token: Token![:], bounds: ParsedBounds, @@ -1753,7 +1753,7 @@ pub(crate) enum UnparsedGenericParam { }, Const { attrs: Vec, - options: HdlAttr, + options: HdlAttr, const_token: Token![const], ident: Ident, colon_token: Token![:], @@ -2278,7 +2278,7 @@ impl ParsedBound { #[derive(Debug, Clone)] pub(crate) struct ParsedTypeParam { pub(crate) attrs: Vec, - pub(crate) options: HdlAttr, + pub(crate) options: HdlAttr, pub(crate) ident: Ident, pub(crate) colon_token: Token![:], pub(crate) bounds: ParsedTypeBounds, @@ -2312,7 +2312,7 @@ impl ToTokens for ParsedTypeParam { #[derive(Debug, Clone)] pub(crate) struct ParsedSizeTypeParam { pub(crate) attrs: Vec, - pub(crate) options: HdlAttr, + pub(crate) options: HdlAttr, pub(crate) ident: Ident, pub(crate) colon_token: Token![:], pub(crate) bounds: ParsedSizeTypeBounds, @@ -2356,7 +2356,7 @@ pub(crate) struct ParsedConstParamWhereBounds { #[derive(Debug, Clone)] pub(crate) struct ParsedConstParam { pub(crate) attrs: Vec, - pub(crate) options: HdlAttr, + pub(crate) options: HdlAttr, pub(crate) const_token: Token![const], pub(crate) ident: Ident, pub(crate) colon_token: Token![:], @@ -2413,7 +2413,7 @@ impl ParsedGenericParam { } } -#[derive(Debug, Clone, Default)] +#[derive(Debug, Clone)] pub(crate) struct ParsedGenerics { pub(crate) lt_token: Option, pub(crate) params: Punctuated, @@ -2863,11 +2863,9 @@ impl ParsedGenerics { let (input_param, punct) = input_param.into_tuple(); let (unparsed_param, late_parsed_param) = match input_param { GenericParam::Lifetime(param) => { - errors.unwrap_or_default( - HdlAttr::::parse_and_take_attr( - &mut param.attrs, - ), - ); + errors.unwrap_or_default(HdlAttr::::parse_and_take_attr( + &mut param.attrs, + )); errors.error(param, "lifetime generics are not supported by #[hdl]"); continue; } @@ -2881,9 +2879,7 @@ impl ParsedGenerics { }) => { let span = ident.span(); let options = errors - .unwrap_or_default( - HdlAttr::::parse_and_take_attr(attrs), - ) + .unwrap_or_default(HdlAttr::::parse_and_take_attr(attrs)) .unwrap_or_default(); let colon_token = colon_token.unwrap_or_else(|| Token![:](span)); if !bounds.is_empty() { @@ -2921,9 +2917,7 @@ impl ParsedGenerics { default, }) => { let options = errors - .unwrap_or_default( - HdlAttr::::parse_and_take_attr(attrs), - ) + .unwrap_or_default(HdlAttr::::parse_and_take_attr(attrs)) .unwrap_or_default(); if let Some(default) = default { let _ = eq_token; diff --git a/crates/fayalite-proc-macros-impl/src/lib.rs b/crates/fayalite-proc-macros-impl/src/lib.rs index 903983f..94fb040 100644 --- a/crates/fayalite-proc-macros-impl/src/lib.rs +++ b/crates/fayalite-proc-macros-impl/src/lib.rs @@ -9,8 +9,7 @@ use syn::{ parse::{Parse, ParseStream, Parser}, parse_quote, punctuated::Pair, - spanned::Spanned, - AttrStyle, Attribute, Error, Item, ItemFn, Token, + AttrStyle, Attribute, Error, Item, Token, }; mod fold; @@ -18,20 +17,8 @@ mod hdl_bundle; mod hdl_enum; mod hdl_type_common; mod module; - -pub(crate) trait CustomToken: - Copy - + Spanned - + ToTokens - + std::fmt::Debug - + Eq - + std::hash::Hash - + Default - + quote::IdentFragment - + Parse -{ - const IDENT_STR: &'static str; -} +//mod value_derive_common; +//mod value_derive_struct; mod kw { pub(crate) use syn::token::Extern as extern_; @@ -51,10 +38,6 @@ mod 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!(flip); custom_keyword!(hdl); - custom_keyword!(hdl_module); custom_keyword!(input); - custom_keyword!(incomplete_wire); custom_keyword!(instance); custom_keyword!(m); custom_keyword!(memory); @@ -87,34 +68,34 @@ mod kw { type Pound = Token![#]; // work around https://github.com/rust-lang/rust/issues/50676 #[derive(Clone, Debug)] -pub(crate) struct HdlAttr { +pub(crate) struct HdlAttr { pub(crate) pound_token: Pound, pub(crate) style: AttrStyle, pub(crate) bracket_token: syn::token::Bracket, - pub(crate) kw: KW, + pub(crate) hdl: kw::hdl, pub(crate) paren_token: Option, pub(crate) body: T, } crate::fold::impl_fold! { - struct HdlAttr { + struct HdlAttr { pound_token: Pound, style: AttrStyle, bracket_token: syn::token::Bracket, - kw: KW, + hdl: kw::hdl, paren_token: Option, body: T, } } #[allow(dead_code)] -impl HdlAttr { - pub(crate) fn split_body(self) -> (HdlAttr<(), KW>, T) { +impl HdlAttr { + pub(crate) fn split_body(self) -> (HdlAttr<()>, T) { let Self { pound_token, style, bracket_token, - kw, + hdl, paren_token, body, } = self; @@ -123,19 +104,19 @@ impl HdlAttr { pound_token, style, bracket_token, - kw, + hdl, paren_token, body: (), }, body, ) } - pub(crate) fn replace_body(self, body: T2) -> HdlAttr { + pub(crate) fn replace_body(self, body: T2) -> HdlAttr { let Self { pound_token, style, bracket_token, - kw, + hdl, paren_token, body: _, } = self; @@ -143,20 +124,17 @@ impl HdlAttr { pound_token, style, bracket_token, - kw, + hdl, paren_token, body, } } - pub(crate) fn as_ref(&self) -> HdlAttr<&T, KW> - where - KW: Clone, - { + pub(crate) fn as_ref(&self) -> HdlAttr<&T> { let Self { pound_token, style, bracket_token, - ref kw, + hdl, paren_token, ref body, } = *self; @@ -164,20 +142,17 @@ impl HdlAttr { pound_token, style, bracket_token, - kw: kw.clone(), + hdl, paren_token, body, } } - pub(crate) fn try_map Result>( - self, - f: F, - ) -> Result, E> { + pub(crate) fn try_map Result>(self, f: F) -> Result, E> { let Self { pound_token, style, bracket_token, - kw, + hdl, paren_token, body, } = self; @@ -185,17 +160,17 @@ impl HdlAttr { pound_token, style, bracket_token, - kw, + hdl, paren_token, body: f(body)?, }) } - pub(crate) fn map R>(self, f: F) -> HdlAttr { + pub(crate) fn map R>(self, f: F) -> HdlAttr { let Self { pound_token, style, bracket_token, - kw, + hdl, paren_token, body, } = self; @@ -203,7 +178,7 @@ impl HdlAttr { pound_token, style, bracket_token, - kw, + hdl, paren_token, body: f(body), } @@ -211,32 +186,31 @@ impl HdlAttr { fn to_attr(&self) -> Attribute where T: ToTokens, - KW: ToTokens, { parse_quote! { #self } } } -impl Default for HdlAttr { +impl Default for HdlAttr { fn default() -> Self { T::default().into() } } -impl From for HdlAttr { +impl From for HdlAttr { fn from(body: T) -> Self { HdlAttr { pound_token: Default::default(), style: AttrStyle::Outer, bracket_token: Default::default(), - kw: Default::default(), + hdl: Default::default(), paren_token: Default::default(), body, } } } -impl ToTokens for HdlAttr { +impl ToTokens for HdlAttr { fn to_tokens(&self, tokens: &mut TokenStream) { self.pound_token.to_tokens(tokens); match self.style { @@ -244,7 +218,7 @@ impl ToTokens for HdlAttr { AttrStyle::Outer => {} }; self.bracket_token.surround(tokens, |tokens| { - self.kw.to_tokens(tokens); + self.hdl.to_tokens(tokens); match self.paren_token { Some(paren_token) => { paren_token.surround(tokens, |tokens| self.body.to_tokens(tokens)) @@ -252,7 +226,7 @@ impl ToTokens for HdlAttr { None => { let body = self.body.to_token_stream(); if !body.is_empty() { - syn::token::Paren(self.kw.span()) + syn::token::Paren(self.hdl.span) .surround(tokens, |tokens| tokens.extend([body])); } } @@ -261,24 +235,18 @@ impl ToTokens for HdlAttr { } } -fn is_hdl_attr(attr: &Attribute) -> bool { - attr.path().is_ident(KW::IDENT_STR) +fn is_hdl_attr(attr: &Attribute) -> bool { + attr.path().is_ident("hdl") } -impl HdlAttr { - fn parse_and_take_attr(attrs: &mut Vec) -> syn::Result> - where - KW: ToTokens, - { +impl HdlAttr { + fn parse_and_take_attr(attrs: &mut Vec) -> syn::Result> { let mut retval = None; let mut errors = Errors::new(); attrs.retain(|attr| { - if let Ok(kw) = syn::parse2::(attr.path().to_token_stream()) { + if is_hdl_attr(attr) { if retval.is_some() { - errors.push(Error::new_spanned( - attr, - format_args!("more than one #[{}] attribute", kw.to_token_stream()), - )); + errors.push(Error::new_spanned(attr, "more than one #[hdl] attribute")); } errors.unwrap_or_default(Self::parse_attr(attr).map(|v| retval = Some(v))); false @@ -289,19 +257,13 @@ impl HdlAttr { errors.finish()?; Ok(retval) } - fn parse_and_leave_attr(attrs: &[Attribute]) -> syn::Result> - where - KW: ToTokens, - { + fn parse_and_leave_attr(attrs: &[Attribute]) -> syn::Result> { let mut retval = None; let mut errors = Errors::new(); for attr in attrs { - if let Ok(kw) = syn::parse2::(attr.path().to_token_stream()) { + if is_hdl_attr(attr) { if retval.is_some() { - errors.push(Error::new_spanned( - attr, - format_args!("more than one #[{}] attribute", kw.to_token_stream()), - )); + errors.push(Error::new_spanned(attr, "more than one #[hdl] attribute")); } errors.unwrap_or_default(Self::parse_attr(attr).map(|v| retval = Some(v))); } @@ -322,7 +284,7 @@ impl HdlAttr { ) -> syn::Result { let bracket_content; let bracket_token = bracketed!(bracket_content in input); - let kw = bracket_content.parse()?; + let hdl = bracket_content.parse()?; let paren_content; let body; let paren_token; @@ -343,7 +305,7 @@ impl HdlAttr { pound_token, style, bracket_token, - kw, + hdl, paren_token, body, }) @@ -890,31 +852,25 @@ pub(crate) fn outline_generated(contents: TokenStream, prefix: &str) -> TokenStr } } -fn hdl_module_impl(item: ItemFn) -> syn::Result { - let func = module::ModuleFn::parse_from_fn(item)?; - let options = func.config_options(); +pub fn hdl_module(attr: TokenStream, item: TokenStream) -> syn::Result { + let options = syn::parse2::(attr)?; + let options = HdlAttr::from(options); + let func = syn::parse2::(quote! { #options #item })?; let mut contents = func.generate(); - if options.outline_generated.is_some() { + if options.body.outline_generated.is_some() { contents = outline_generated(contents, "module-"); } Ok(contents) } -pub fn hdl_module(attr: TokenStream, item: TokenStream) -> syn::Result { - 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 { - let kw = kw::hdl::default(); - let item = syn::parse2::(quote! { #[#kw(#attr)] #item })?; + let item = syn::parse2::(quote! { #[hdl(#attr)] #item })?; match item { Item::Enum(item) => hdl_enum::hdl_enum(item), Item::Struct(item) => hdl_bundle::hdl_bundle(item), - Item::Fn(item) => hdl_module_impl(item), _ => Err(syn::Error::new( 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", )), } } diff --git a/crates/fayalite-proc-macros-impl/src/module.rs b/crates/fayalite-proc-macros-impl/src/module.rs index 6363bb3..0945abb 100644 --- a/crates/fayalite-proc-macros-impl/src/module.rs +++ b/crates/fayalite-proc-macros-impl/src/module.rs @@ -2,7 +2,6 @@ // See Notices.txt for copyright information use crate::{ hdl_type_common::{ParsedGenerics, SplitForImpl}, - kw, module::transform_body::{HdlLet, HdlLetKindIO}, options, Errors, HdlAttr, PairsIterExt, }; @@ -10,6 +9,7 @@ use proc_macro2::TokenStream; use quote::{format_ident, quote, quote_spanned, ToTokens}; use std::collections::HashSet; use syn::{ + parse::{Parse, ParseStream}, parse_quote, visit::{visit_pat, Visit}, Attribute, Block, ConstParam, Error, FnArg, GenericParam, Generics, Ident, ItemFn, ItemStruct, @@ -59,9 +59,9 @@ impl Visit<'_> for CheckNameConflictsWithModuleBuilderVisitor<'_> { pub(crate) type ModuleIO = HdlLet; -struct ModuleFnModule { +pub(crate) struct ModuleFn { attrs: Vec, - config_options: HdlAttr, + config_options: HdlAttr, module_kind: ModuleKind, vis: Visibility, sig: Signature, @@ -70,26 +70,6 @@ struct ModuleFnModule { the_struct: TokenStream, } -enum ModuleFnImpl { - Module(ModuleFnModule), - Fn { - attrs: Vec, - config_options: HdlAttr, - vis: Visibility, - sig: Signature, - block: Box, - }, -} - -options! { - pub(crate) enum HdlOrHdlModule { - Hdl(hdl), - HdlModule(hdl_module), - } -} - -pub(crate) struct ModuleFn(ModuleFnImpl); - #[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)] pub(crate) enum ModuleKind { Extern, @@ -109,25 +89,14 @@ impl Visit<'_> for ContainsSkippedIdent<'_> { } } -impl ModuleFn { - pub(crate) fn config_options(&self) -> ConfigOptions { - 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 { +impl Parse for ModuleFn { + fn parse(input: ParseStream) -> syn::Result { let ItemFn { mut attrs, vis, mut sig, block, - } = item; + } = input.parse()?; let Signature { ref constness, ref asyncness, @@ -142,60 +111,43 @@ impl ModuleFn { ref output, } = sig; let mut errors = Errors::new(); - let Some(mut config_options) = - errors.unwrap_or_default( - HdlAttr::::parse_and_take_attr(&mut attrs), - ) - else { - errors.error(sig.ident, "missing #[hdl] or #[hdl_module] attribute"); - errors.finish()?; - unreachable!(); - }; + let config_options = errors + .unwrap_or_default(HdlAttr::parse_and_take_attr(&mut attrs)) + .unwrap_or_default(); let ConfigOptions { outline_generated: _, extern_, } = config_options.body; - let module_kind = match (config_options.kw, extern_) { - (HdlOrHdlModule::Hdl(_), None) => None, - (HdlOrHdlModule::Hdl(_), Some(extern2)) => { - 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), + let module_kind = match extern_ { + Some(_) => ModuleKind::Extern, + None => ModuleKind::Normal, }; - if let HdlOrHdlModule::HdlModule(_) = config_options.kw { - for fn_arg in inputs { - match fn_arg { - FnArg::Receiver(_) => { - errors.push(syn::Error::new_spanned(fn_arg, "self not allowed here")); - } - FnArg::Typed(fn_arg) => { - visit_pat( - &mut CheckNameConflictsWithModuleBuilderVisitor { - errors: &mut errors, - }, - &fn_arg.pat, - ); - } + for fn_arg in inputs { + match fn_arg { + FnArg::Receiver(_) => { + errors.push(syn::Error::new_spanned(fn_arg, "self not allowed here")); + } + FnArg::Typed(fn_arg) => { + visit_pat( + &mut CheckNameConflictsWithModuleBuilderVisitor { + errors: &mut errors, + }, + &fn_arg.pat, + ); } } - if let Some(constness) = constness { - errors.push(syn::Error::new_spanned(constness, "const not allowed here")); - } - if let Some(asyncness) = asyncness { - errors.push(syn::Error::new_spanned(asyncness, "async not allowed here")); - } - if let Some(unsafety) = unsafety { - errors.push(syn::Error::new_spanned(unsafety, "unsafe not allowed here")); - } - if let Some(abi) = abi { - errors.push(syn::Error::new_spanned(abi, "extern not allowed here")); - } + } + if let Some(constness) = constness { + errors.push(syn::Error::new_spanned(constness, "const not allowed here")); + } + if let Some(asyncness) = asyncness { + errors.push(syn::Error::new_spanned(asyncness, "async not allowed here")); + } + if let Some(unsafety) = unsafety { + errors.push(syn::Error::new_spanned(unsafety, "unsafe not allowed here")); + } + if let Some(abi) = abi { + errors.push(syn::Error::new_spanned(abi, "extern not allowed here")); } let mut skipped_idents = HashSet::new(); let struct_generic_params = generics @@ -203,17 +155,14 @@ impl ModuleFn { .pairs_mut() .filter_map_pair_value_mut(|v| match v { GenericParam::Lifetime(LifetimeParam { attrs, .. }) => { - errors.unwrap_or_default( - HdlAttr::::parse_and_take_attr(attrs), - ); + errors + .unwrap_or_default(HdlAttr::::parse_and_take_attr(attrs)); None } GenericParam::Type(TypeParam { attrs, ident, .. }) | GenericParam::Const(ConstParam { attrs, ident, .. }) => { if errors - .unwrap_or_default( - HdlAttr::::parse_and_take_attr(attrs), - ) + .unwrap_or_default(HdlAttr::::parse_and_take_attr(attrs)) .is_some() { skipped_idents.insert(ident.clone()); @@ -227,7 +176,6 @@ impl ModuleFn { let struct_where_clause = generics .where_clause .as_mut() - .filter(|_| matches!(config_options.kw, HdlOrHdlModule::HdlModule(_))) .map(|where_clause| WhereClause { where_token: where_clause.where_token, predicates: where_clause @@ -250,26 +198,22 @@ impl ModuleFn { }) .collect(), }); - let struct_generics = if let HdlOrHdlModule::HdlModule(_) = config_options.kw { - let mut struct_generics = Generics { - lt_token: generics.lt_token, - params: struct_generic_params, - gt_token: generics.gt_token, - where_clause: struct_where_clause, - }; - if let Some(variadic) = variadic { - errors.push(syn::Error::new_spanned(variadic, "... not allowed here")); - } - if !matches!(output, ReturnType::Default) { - errors.push(syn::Error::new_spanned( - output, - "return type not allowed here", - )); - } - errors.ok(ParsedGenerics::parse(&mut struct_generics)) - } else { - Some(ParsedGenerics::default()) + let struct_generics = Generics { + lt_token: generics.lt_token, + params: struct_generic_params, + gt_token: generics.gt_token, + where_clause: struct_where_clause, }; + if let Some(variadic) = variadic { + errors.push(syn::Error::new_spanned(variadic, "... not allowed here")); + } + if !matches!(output, ReturnType::Default) { + errors.push(syn::Error::new_spanned( + output, + "return type not allowed here", + )); + } + let struct_generics = errors.ok(ParsedGenerics::parse(&mut { struct_generics })); let body_results = struct_generics.as_ref().and_then(|struct_generics| { errors.ok(transform_body::transform_body( module_kind, @@ -280,47 +224,6 @@ impl ModuleFn { errors.finish()?; let struct_generics = struct_generics.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) = struct_generics.split_for_impl(); let struct_where_clause: Option = parse_quote! { #struct_where_clause }; @@ -356,22 +259,7 @@ impl ModuleFn { } }; let the_struct = crate::hdl_bundle::hdl_bundle(the_struct)?; - Ok(Self(ModuleFnImpl::Module(ModuleFnModule { - 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 { + Ok(Self { attrs, config_options, module_kind, @@ -380,28 +268,22 @@ impl ModuleFn { block, struct_generics, the_struct, - } = match self.0 { - ModuleFnImpl::Module(v) => v, - ModuleFnImpl::Fn { - attrs, - config_options, - vis, - sig, - block, - } => { - let ConfigOptions { - outline_generated: _, - extern_: _, - } = config_options.body; - return ItemFn { - attrs, - vis, - sig, - block, - } - .into_token_stream(); - } - }; + }) + } +} + +impl ModuleFn { + pub(crate) fn generate(self) -> TokenStream { + let Self { + attrs, + config_options, + module_kind, + vis, + sig, + block, + struct_generics, + the_struct, + } = self; let ConfigOptions { outline_generated: _, extern_: _, diff --git a/crates/fayalite-proc-macros-impl/src/module/transform_body.rs b/crates/fayalite-proc-macros-impl/src/module/transform_body.rs index 1f9565a..76e1d69 100644 --- a/crates/fayalite-proc-macros-impl/src/module/transform_body.rs +++ b/crates/fayalite-proc-macros-impl/src/module/transform_body.rs @@ -34,7 +34,6 @@ options! { Instance(instance), RegBuilder(reg_builder), Wire(wire), - IncompleteWire(incomplete_wire), Memory(memory), MemoryArray(memory_array), 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 for HdlLetKindIncomplete { - fn parse_types(input: &mut Self, _parser: &mut TypesParser<'_>) -> Result { - 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! { pub(crate) enum MemoryFnName { Memory(memory), @@ -733,7 +697,6 @@ impl HdlLetKindMemory { #[derive(Clone, Debug)] pub(crate) enum HdlLetKind { IO(HdlLetKindIO), - Incomplete(HdlLetKindIncomplete), Instance(HdlLetKindInstance), RegBuilder(HdlLetKindRegBuilder), Wire(HdlLetKindWire), @@ -743,7 +706,6 @@ pub(crate) enum HdlLetKind { impl_fold! { enum HdlLetKind { IO(HdlLetKindIO), - Incomplete(HdlLetKindIncomplete), Instance(HdlLetKindInstance), RegBuilder(HdlLetKindRegBuilder), Wire(HdlLetKindWire), @@ -758,9 +720,6 @@ impl, I> ParseTypes> for HdlLetKind { ) -> Result { match input { 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) => { ParseTypes::parse_types(input, parser).map(HdlLetKind::Instance) } @@ -912,20 +871,6 @@ impl HdlLetKindParse for HdlLetKind { 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( input, parsed_ty, @@ -958,7 +903,6 @@ impl HdlLetKindToTokens for HdlLetKind { fn ty_to_tokens(&self, tokens: &mut TokenStream) { match self { 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::RegBuilder(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) { match self { 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::RegBuilder(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)] pub(crate) struct HdlLet { pub(crate) attrs: Vec, - pub(crate) hdl_attr: HdlAttr, + pub(crate) hdl_attr: HdlAttr, pub(crate) let_token: Token![let], pub(crate) mut_token: Option, pub(crate) name: Ident, @@ -1169,7 +1112,7 @@ impl ToTokens for ImplicitName { } struct Visitor<'a> { - module_kind: Option, + module_kind: ModuleKind, errors: Errors, io: Vec, block_depth: usize, @@ -1177,33 +1120,22 @@ struct Visitor<'a> { } impl Visitor<'_> { - fn take_hdl_attr( - &mut self, - attrs: &mut Vec, - ) -> Option> { + fn take_hdl_attr(&mut self, attrs: &mut Vec) -> Option> { self.errors.unwrap_or( HdlAttr::parse_and_take_attr(attrs), Some(syn::parse2::(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 { - Some(ModuleKind::Extern) => { + ModuleKind::Extern => { self.errors .error(spanned, "not allowed in #[hdl_module(extern)]"); } - Some(ModuleKind::Normal) | None => {} + ModuleKind::Normal => {} } } - fn require_module(&mut self, spanned: impl ToTokens) { - match self.module_kind { - None => { - self.errors.error(spanned, "not allowed in #[hdl] fn"); - } - Some(_) => {} - } - } - fn process_hdl_if(&mut self, hdl_attr: HdlAttr, expr_if: ExprIf) -> Expr { + fn process_hdl_if(&mut self, hdl_attr: HdlAttr, expr_if: ExprIf) -> Expr { let ExprIf { attrs, if_token, @@ -1211,7 +1143,7 @@ impl Visitor<'_> { then_branch, else_branch, } = 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 { Expr::If(expr_if) => self.process_hdl_if(hdl_attr.clone(), expr_if), expr => expr, @@ -1276,12 +1208,11 @@ impl Visitor<'_> { .to_tokens(expr); }); let mut attrs = hdl_let.attrs.clone(); - self.require_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)] }), - Some(ModuleKind::Normal) | None => {} + ModuleKind::Normal => {} } let let_stmt = Local { attrs, @@ -1318,7 +1249,7 @@ impl Visitor<'_> { }, semi_token, } = hdl_let; - self.require_normal_module_or_fn(instance); + self.require_normal_module(instance); let mut expr = instance.to_token_stream(); paren.surround(&mut expr, |expr| { let name_str = ImplicitName { @@ -1345,7 +1276,7 @@ impl Visitor<'_> { fn process_hdl_let_reg_builder(&mut self, hdl_let: HdlLet) -> Local { let name = &hdl_let.name; 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(); hdl_let.kind.reg_builder_paren.surround(&mut expr, |expr| { let name_str = ImplicitName { @@ -1396,7 +1327,7 @@ impl Visitor<'_> { fn process_hdl_let_wire(&mut self, hdl_let: HdlLet) -> Local { let name = &hdl_let.name; 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 mut expr = wire.to_token_stream(); hdl_let.kind.paren.surround(&mut expr, |expr| { @@ -1426,36 +1357,11 @@ impl Visitor<'_> { semi_token: hdl_let.semi_token, } } - fn process_hdl_let_incomplete(&mut self, hdl_let: HdlLet) -> 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) -> Local { let name = &hdl_let.name; let memory_fn = hdl_let.kind.memory_fn; 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 (paren, arg) = match memory_fn { MemoryFn::Memory { @@ -1520,7 +1426,6 @@ impl Visitor<'_> { } the_match! { IO => process_hdl_let_io, - Incomplete => process_hdl_let_incomplete, Instance => process_hdl_let_instance, RegBuilder => process_hdl_let_reg_builder, Wire => process_hdl_let_wire, @@ -1638,7 +1543,7 @@ impl Fold for Visitor<'_> { } fn fold_attribute(&mut self, attr: Attribute) -> Attribute { - if is_hdl_attr::(&attr) { + if is_hdl_attr(&attr) { self.errors .error(&attr, "#[hdl] attribute not supported here"); } @@ -1705,9 +1610,8 @@ impl Fold for Visitor<'_> { fn fold_local(&mut self, let_stmt: Local) -> Local { match self .errors - .ok(HdlAttr::::parse_and_leave_attr( - &let_stmt.attrs, - )) { + .ok(HdlAttr::::parse_and_leave_attr(&let_stmt.attrs)) + { None => return empty_let(), Some(None) => return fold_local(self, let_stmt), Some(Some(HdlAttr { .. })) => {} @@ -1742,7 +1646,7 @@ impl Fold for Visitor<'_> { } pub(crate) fn transform_body( - module_kind: Option, + module_kind: ModuleKind, mut body: Box, parsed_generics: &ParsedGenerics, ) -> syn::Result<(Box, Vec)> { diff --git a/crates/fayalite-proc-macros-impl/src/module/transform_body/expand_aggregate_literals.rs b/crates/fayalite-proc-macros-impl/src/module/transform_body/expand_aggregate_literals.rs index b5a0ad3..00ee706 100644 --- a/crates/fayalite-proc-macros-impl/src/module/transform_body/expand_aggregate_literals.rs +++ b/crates/fayalite-proc-macros-impl/src/module/transform_body/expand_aggregate_literals.rs @@ -1,6 +1,6 @@ // SPDX-License-Identifier: LGPL-3.0-or-later // 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 syn::{ parse::Nothing, parse_quote, parse_quote_spanned, spanned::Spanned, Expr, ExprArray, ExprPath, @@ -10,10 +10,10 @@ use syn::{ impl Visitor<'_> { pub(crate) fn process_hdl_array( &mut self, - hdl_attr: HdlAttr, + hdl_attr: HdlAttr, mut expr_array: ExprArray, ) -> Expr { - self.require_normal_module_or_fn(hdl_attr); + self.require_normal_module(hdl_attr); for elem in &mut expr_array.elems { *elem = parse_quote_spanned! {elem.span()=> ::fayalite::expr::ToExpr::to_expr(&(#elem)) @@ -23,10 +23,10 @@ impl Visitor<'_> { } pub(crate) fn process_hdl_repeat( &mut self, - hdl_attr: HdlAttr, + hdl_attr: HdlAttr, mut expr_repeat: ExprRepeat, ) -> Expr { - self.require_normal_module_or_fn(hdl_attr); + self.require_normal_module(hdl_attr); let repeated_value = &expr_repeat.expr; *expr_repeat.expr = parse_quote_spanned! {repeated_value.span()=> ::fayalite::expr::ToExpr::to_expr(&(#repeated_value)) @@ -35,10 +35,10 @@ impl Visitor<'_> { } pub(crate) fn process_hdl_struct( &mut self, - hdl_attr: HdlAttr, + hdl_attr: HdlAttr, expr_struct: ExprStruct, ) -> 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 builder_ident = format_ident!("__builder", span = name_span); let empty_builder = if expr_struct.qself.is_some() @@ -91,10 +91,10 @@ impl Visitor<'_> { } pub(crate) fn process_hdl_tuple( &mut self, - hdl_attr: HdlAttr, + hdl_attr: HdlAttr, expr_tuple: ExprTuple, ) -> Expr { - self.require_normal_module_or_fn(hdl_attr); + self.require_normal_module(hdl_attr); parse_quote_spanned! {expr_tuple.span()=> ::fayalite::expr::ToExpr::to_expr(&#expr_tuple) } diff --git a/crates/fayalite-proc-macros-impl/src/module/transform_body/expand_match.rs b/crates/fayalite-proc-macros-impl/src/module/transform_body/expand_match.rs index 1d53104..ae21a73 100644 --- a/crates/fayalite-proc-macros-impl/src/module/transform_body/expand_match.rs +++ b/crates/fayalite-proc-macros-impl/src/module/transform_body/expand_match.rs @@ -2,7 +2,6 @@ // See Notices.txt for copyright information use crate::{ fold::{impl_fold, DoFold}, - kw, module::transform_body::{with_debug_clone_and_fold, Visitor}, Errors, HdlAttr, PairsIterExt, }; @@ -750,7 +749,7 @@ struct HdlMatchParseState<'a> { impl Visitor<'_> { pub(crate) fn process_hdl_match( &mut self, - _hdl_attr: HdlAttr, + _hdl_attr: HdlAttr, expr_match: ExprMatch, ) -> Expr { let span = expr_match.match_token.span(); @@ -762,7 +761,7 @@ impl Visitor<'_> { brace_token: _, arms, } = expr_match; - self.require_normal_module_or_fn(match_token); + self.require_normal_module(match_token); let mut state = HdlMatchParseState { match_span: span, errors: &mut self.errors, diff --git a/crates/fayalite/src/enum_.rs b/crates/fayalite/src/enum_.rs index 13724ef..384414c 100644 --- a/crates/fayalite/src/enum_.rs +++ b/crates/fayalite/src/enum_.rs @@ -7,14 +7,14 @@ use crate::{ int::Bool, intern::{Intern, Interned}, module::{ - connect, enum_match_variants_helper, incomplete_wire, wire, - EnumMatchVariantAndInactiveScopeImpl, EnumMatchVariantsIterImpl, Scope, + enum_match_variants_helper, EnumMatchVariantAndInactiveScopeImpl, + EnumMatchVariantsIterImpl, Scope, }, source_location::SourceLocation, ty::{CanonicalType, MatchVariantAndInactiveScope, StaticType, Type, TypeProperties}, }; use hashbrown::HashMap; -use std::{convert::Infallible, fmt, iter::FusedIterator}; +use std::{fmt, iter::FusedIterator}; #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] pub struct EnumVariant { @@ -364,308 +364,3 @@ pub fn HdlSome(value: impl ToExpr) -> Expr> { let value = value.to_expr(); HdlOption[Expr::ty(value)].HdlSome(value) } - -impl HdlOption { - #[track_caller] - pub fn try_map( - expr: Expr, - f: impl FnOnce(Expr) -> Result, E>, - ) -> Result>, E> { - Self::try_and_then(expr, |v| Ok(HdlSome(f(v)?))) - } - #[track_caller] - pub fn map( - expr: Expr, - f: impl FnOnce(Expr) -> Expr, - ) -> Expr> { - Self::and_then(expr, |v| HdlSome(f(v))) - } - #[hdl] - #[track_caller] - pub fn try_and_then( - expr: Expr, - f: impl FnOnce(Expr) -> Result>, E>, - ) -> Result>, E> { - // manually run match steps so we can extract the return type to construct HdlNone - type Wrap = 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::<::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::<::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( - expr: Expr, - f: impl FnOnce(Expr) -> Expr>, - ) -> Expr> { - match Self::try_and_then(expr, |v| Ok::<_, Infallible>(f(v))) { - Ok(v) => v, - Err(e) => match e {}, - } - } - #[hdl] - #[track_caller] - pub fn and(expr: Expr, opt_b: Expr>) -> Expr> { - #[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( - expr: Expr, - f: impl FnOnce(Expr) -> Result, E>, - ) -> Result, 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, f: impl FnOnce(Expr) -> Expr) -> Expr { - match Self::try_filter(expr, |v| Ok::<_, Infallible>(f(v))) { - Ok(v) => v, - Err(e) => match e {}, - } - } - #[hdl] - #[track_caller] - pub fn try_inspect( - expr: Expr, - f: impl FnOnce(Expr) -> Result<(), E>, - ) -> Result, 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, f: impl FnOnce(Expr)) -> Expr { - 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) -> Expr { - #[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) -> Expr { - #[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( - expr: Expr, - default: Expr, - f: impl FnOnce(Expr) -> Expr, - ) -> Expr { - #[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( - expr: Expr, - default: impl FnOnce() -> Expr, - f: impl FnOnce(Expr) -> Expr, - ) -> Expr { - #[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, opt_b: Expr) -> Expr { - #[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, f: impl FnOnce() -> Expr) -> Expr { - #[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, default: Expr) -> Expr { - #[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, f: impl FnOnce() -> Expr) -> Expr { - #[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, opt_b: Expr) -> Expr { - #[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(expr: Expr, other: Expr>) -> Expr> { - #[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 HdlOption> { - #[hdl] - #[track_caller] - pub fn flatten(expr: Expr) -> Expr> { - #[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 HdlOption<(T, U)> { - #[hdl] - #[track_caller] - pub fn unzip(expr: Expr) -> Expr<(HdlOption, HdlOption)> { - 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 - } -} diff --git a/crates/fayalite/src/module.rs b/crates/fayalite/src/module.rs index 3a17343..cb57758 100644 --- a/crates/fayalite/src/module.rs +++ b/crates/fayalite/src/module.rs @@ -22,7 +22,7 @@ use crate::{ source_location::SourceLocation, ty::{CanonicalType, Type}, util::ScopedRef, - wire::{IncompleteWire, Wire}, + wire::Wire, }; use hashbrown::{hash_map::Entry, HashMap, HashSet}; use num_bigint::BigInt; @@ -118,35 +118,9 @@ pub trait BlockRef: 'static + Send + Sync + Copy + Eq + Hash + fmt::Debug {} impl BlockRef for BlockId {} -pub(crate) enum IncompleteDeclaration { - Incomplete { - name: ScopedNameId, - source_location: SourceLocation, - }, - Complete(StmtDeclaration), - 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)] pub struct BuilderBlock { memories: Vec>>, - incomplete_declarations: Vec>>, stmts: Vec>, } @@ -857,34 +831,13 @@ impl From> for NormalModuleBody { annotations_map: &mut HashMap, Vec>, block_id: BlockId, ) -> Block { - let BuilderBlock { - memories, - incomplete_declarations, - stmts, - } = &mut blocks[block_id.as_usize()]; + let BuilderBlock { memories, stmts } = &mut blocks[block_id.as_usize()]; let memories = Interned::from_iter( memories .drain(..) .filter_map(|memory| memory.borrow().make_memory()), ); - let stmts = Vec::from_iter( - 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 = std::mem::take(stmts); let stmts = Interned::from_iter(stmts.into_iter().map(|stmt| { match stmt { Stmt::Connect(stmt) => stmt.into(), @@ -955,7 +908,6 @@ impl NormalModuleBody { let index = self.body.blocks.len(); self.body.blocks.push(BuilderBlock { memories: vec![], - incomplete_declarations: vec![], stmts: vec![], }); BlockId(index) @@ -1991,7 +1943,6 @@ impl ModuleBuilder { body: BuilderModuleBody { blocks: vec![BuilderBlock { memories: vec![], - incomplete_declarations: vec![], stmts: vec![], }], annotations_map: HashMap::new(), @@ -2205,42 +2156,6 @@ pub fn wire(implicit_name: ImplicitName<'_>, ty: T) -> Expr { wire_with_loc(implicit_name.0, SourceLocation::caller(), ty) } -#[track_caller] -fn incomplete_declaration( - name: &str, - source_location: SourceLocation, -) -> Rc> { - 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] pub fn reg_builder_with_loc(name: &str, source_location: SourceLocation) -> RegBuilder<(), (), ()> { ModuleBuilder::with(|m| { diff --git a/crates/fayalite/src/prelude.rs b/crates/fayalite/src/prelude.rs index bedece2..14c3aa7 100644 --- a/crates/fayalite/src/prelude.rs +++ b/crates/fayalite/src/prelude.rs @@ -9,8 +9,8 @@ pub use crate::{ int::{Bool, DynSize, IntCmp, KnownSize, SInt, SIntType, Size, UInt, UIntType}, memory::{Mem, MemBuilder, ReadUnderWrite}, module::{ - annotate, connect, connect_any, incomplete_wire, instance, memory, memory_array, - memory_with_init, reg_builder, wire, Instance, Module, ModuleBuilder, + annotate, connect, connect_any, instance, memory, memory_array, memory_with_init, + reg_builder, wire, Instance, Module, ModuleBuilder, }, reg::Reg, reset::{AsyncReset, Reset, SyncReset, ToAsyncReset, ToReset, ToSyncReset}, diff --git a/crates/fayalite/src/util.rs b/crates/fayalite/src/util.rs index 5b97e3b..fc5daf4 100644 --- a/crates/fayalite/src/util.rs +++ b/crates/fayalite/src/util.rs @@ -25,5 +25,3 @@ pub use scoped_ref::ScopedRef; pub use misc::{ interned_bit, iter_eq_by, BitSliceWriteWithBase, DebugAsDisplay, DebugAsRawString, MakeMutSlice, }; - -pub mod ready_valid; diff --git a/crates/fayalite/src/util/ready_valid.rs b/crates/fayalite/src/util/ready_valid.rs deleted file mode 100644 index a5893cf..0000000 --- a/crates/fayalite/src/util/ready_valid.rs +++ /dev/null @@ -1,34 +0,0 @@ -use crate::prelude::*; - -#[hdl] -pub struct ReadyValid { - pub data: HdlOption, - #[hdl(flip)] - pub ready: Bool, -} - -impl ReadyValid { - #[hdl] - pub fn fire(expr: Expr) -> Expr { - #[hdl] - let fire: Bool = wire(); - #[hdl] - match expr.data { - HdlNone => connect(fire, false), - HdlSome(_) => connect(fire, expr.ready), - } - fire - } - #[hdl] - pub fn map( - expr: Expr, - f: impl FnOnce(Expr) -> Expr, - ) -> Expr> { - 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 - } -} diff --git a/crates/fayalite/src/wire.rs b/crates/fayalite/src/wire.rs index 85ab342..b84d6ae 100644 --- a/crates/fayalite/src/wire.rs +++ b/crates/fayalite/src/wire.rs @@ -1,13 +1,13 @@ // SPDX-License-Identifier: LGPL-3.0-or-later // See Notices.txt for copyright information use crate::{ - expr::{Expr, Flow, ToExpr}, + expr::Flow, intern::Interned, - module::{IncompleteDeclaration, NameId, ScopedNameId, StmtDeclaration, StmtWire}, + module::{NameId, ScopedNameId}, source_location::SourceLocation, ty::{CanonicalType, Type}, }; -use std::{cell::RefCell, fmt, rc::Rc}; +use std::fmt; #[derive(Copy, Clone, Eq, PartialEq, Hash)] pub struct Wire { @@ -76,57 +76,3 @@ impl Wire { true } } - -#[derive(Clone)] -pub struct IncompleteWire { - pub(crate) declaration: Rc>, -} - -impl IncompleteWire { - #[track_caller] - pub fn complete(&mut self, ty: T) -> Expr { - 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!() - } - } - } -} diff --git a/crates/fayalite/tests/ui/hdl_types.stderr b/crates/fayalite/tests/ui/hdl_types.stderr index a65d796..e01b04f 100644 --- a/crates/fayalite/tests/ui/hdl_types.stderr +++ b/crates/fayalite/tests/ui/hdl_types.stderr @@ -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 | 5 | #[hdl]