forked from libre-chip/fayalite
WIP: use HdlOption[the_type_var] or UInt[123 + n] for creating types
This commit is contained in:
parent
cd99dbc849
commit
5835b995a9
63 changed files with 13500 additions and 13210 deletions
|
@ -13,15 +13,15 @@ use syn::{
|
|||
};
|
||||
|
||||
mod fold;
|
||||
mod hdl_bundle;
|
||||
mod hdl_enum;
|
||||
mod hdl_type_common;
|
||||
mod module;
|
||||
mod value_derive_common;
|
||||
mod value_derive_enum;
|
||||
mod value_derive_struct;
|
||||
//mod value_derive_common;
|
||||
//mod value_derive_struct;
|
||||
|
||||
mod kw {
|
||||
pub(crate) use syn::token::{
|
||||
Enum as enum_, Extern as extern_, Static as static_, Struct as struct_, Where as where_,
|
||||
};
|
||||
pub(crate) use syn::token::Extern as extern_;
|
||||
|
||||
macro_rules! custom_keyword {
|
||||
($kw:ident) => {
|
||||
|
@ -43,6 +43,7 @@ mod kw {
|
|||
|
||||
custom_keyword!(clock_domain);
|
||||
custom_keyword!(connect_inexact);
|
||||
custom_keyword!(custom_bounds);
|
||||
custom_keyword!(flip);
|
||||
custom_keyword!(hdl);
|
||||
custom_keyword!(input);
|
||||
|
@ -52,6 +53,8 @@ mod kw {
|
|||
custom_keyword!(memory_array);
|
||||
custom_keyword!(memory_with_init);
|
||||
custom_keyword!(no_reset);
|
||||
custom_keyword!(no_runtime_generics);
|
||||
custom_keyword!(no_static);
|
||||
custom_keyword!(outline_generated);
|
||||
custom_keyword!(output);
|
||||
custom_keyword!(reg_builder);
|
||||
|
@ -519,6 +522,26 @@ macro_rules! impl_extra_traits_for_options {
|
|||
) => {
|
||||
impl Copy for $option_enum_name {}
|
||||
|
||||
impl PartialEq for $option_enum_name {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.cmp(other).is_eq()
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for $option_enum_name {}
|
||||
|
||||
impl PartialOrd for $option_enum_name {
|
||||
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
|
||||
Some(self.cmp(other))
|
||||
}
|
||||
}
|
||||
|
||||
impl Ord for $option_enum_name {
|
||||
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
|
||||
self.variant().cmp(&other.variant())
|
||||
}
|
||||
}
|
||||
|
||||
impl quote::IdentFragment for $option_enum_name {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
let _ = f;
|
||||
|
@ -554,6 +577,66 @@ pub(crate) use impl_extra_traits_for_options;
|
|||
macro_rules! options {
|
||||
(
|
||||
#[options = $options_name:ident]
|
||||
$($tt:tt)*
|
||||
) => {
|
||||
crate::options! {
|
||||
#[options = $options_name, punct = syn::Token![,], allow_duplicates = false]
|
||||
$($tt)*
|
||||
}
|
||||
};
|
||||
(
|
||||
#[options = $options_name:ident, punct = $Punct:ty, allow_duplicates = true]
|
||||
$(#[$($enum_meta:tt)*])*
|
||||
$enum_vis:vis enum $option_enum_name:ident {
|
||||
$($Variant:ident($key:ident $(, $value:ty)?),)*
|
||||
}
|
||||
) => {
|
||||
crate::options! {
|
||||
#[options = $options_name, punct = $Punct, allow_duplicates = (true)]
|
||||
$(#[$($enum_meta)*])*
|
||||
$enum_vis enum $option_enum_name {
|
||||
$($Variant($key $(, $value)?),)*
|
||||
}
|
||||
}
|
||||
|
||||
impl Extend<$option_enum_name> for $options_name {
|
||||
fn extend<T: IntoIterator<Item = $option_enum_name>>(&mut self, iter: T) {
|
||||
iter.into_iter().for_each(|v| match v {
|
||||
$($option_enum_name::$Variant(v) => {
|
||||
self.$key = Some(v);
|
||||
})*
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
impl FromIterator<$option_enum_name> for $options_name {
|
||||
fn from_iter<T: IntoIterator<Item = $option_enum_name>>(iter: T) -> Self {
|
||||
let mut retval = Self::default();
|
||||
retval.extend(iter);
|
||||
retval
|
||||
}
|
||||
}
|
||||
|
||||
impl Extend<$options_name> for $options_name {
|
||||
fn extend<T: IntoIterator<Item = $options_name>>(&mut self, iter: T) {
|
||||
iter.into_iter().for_each(|v| {
|
||||
$(if let Some(v) = v.$key {
|
||||
self.$key = Some(v);
|
||||
})*
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
impl FromIterator<$options_name> for $options_name {
|
||||
fn from_iter<T: IntoIterator<Item = $options_name>>(iter: T) -> Self {
|
||||
let mut retval = Self::default();
|
||||
retval.extend(iter);
|
||||
retval
|
||||
}
|
||||
}
|
||||
};
|
||||
(
|
||||
#[options = $options_name:ident, punct = $Punct:ty, allow_duplicates = $allow_duplicates:expr]
|
||||
$(#[$($enum_meta:tt)*])*
|
||||
$enum_vis:vis enum $option_enum_name:ident {
|
||||
$($Variant:ident($key:ident $(, $value:ty)?),)*
|
||||
|
@ -567,8 +650,11 @@ macro_rules! options {
|
|||
}
|
||||
|
||||
#[derive(Clone, Debug, Default)]
|
||||
#[allow(non_snake_case)]
|
||||
$enum_vis struct $options_name {
|
||||
$($enum_vis $key: Option<(crate::kw::$key, $(syn::token::Paren, $value)?)>,)*
|
||||
$(
|
||||
$enum_vis $key: Option<(crate::kw::$key, $(syn::token::Paren, $value)?)>,
|
||||
)*
|
||||
}
|
||||
|
||||
crate::fold::impl_fold! {
|
||||
|
@ -577,6 +663,43 @@ macro_rules! options {
|
|||
}
|
||||
}
|
||||
|
||||
const _: () = {
|
||||
#[derive(Clone, Debug)]
|
||||
$enum_vis struct Iter($enum_vis $options_name);
|
||||
|
||||
impl IntoIterator for $options_name {
|
||||
type Item = $option_enum_name;
|
||||
type IntoIter = Iter;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
Iter(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl Iterator for Iter {
|
||||
type Item = $option_enum_name;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
$(
|
||||
if let Some(value) = self.0.$key.take() {
|
||||
return Some($option_enum_name::$Variant(value));
|
||||
}
|
||||
)*
|
||||
None
|
||||
}
|
||||
|
||||
#[allow(unused_mut, unused_variables)]
|
||||
fn fold<B, F: FnMut(B, Self::Item) -> B>(mut self, mut init: B, mut f: F) -> B {
|
||||
$(
|
||||
if let Some(value) = self.0.$key.take() {
|
||||
init = f(init, $option_enum_name::$Variant(value));
|
||||
}
|
||||
)*
|
||||
init
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
impl syn::parse::Parse for $options_name {
|
||||
fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
|
||||
#![allow(unused_mut, unused_variables, unreachable_code)]
|
||||
|
@ -585,7 +708,7 @@ macro_rules! options {
|
|||
let old_input = input.fork();
|
||||
match input.parse::<$option_enum_name>()? {
|
||||
$($option_enum_name::$Variant(v) => {
|
||||
if retval.$key.replace(v).is_some() {
|
||||
if retval.$key.replace(v).is_some() && !$allow_duplicates {
|
||||
return Err(old_input.error(concat!("duplicate ", stringify!($key), " option")));
|
||||
}
|
||||
})*
|
||||
|
@ -593,7 +716,7 @@ macro_rules! options {
|
|||
if input.is_empty() {
|
||||
break;
|
||||
}
|
||||
input.parse::<syn::Token![,]>()?;
|
||||
input.parse::<$Punct>()?;
|
||||
}
|
||||
Ok(retval)
|
||||
}
|
||||
|
@ -602,7 +725,7 @@ macro_rules! options {
|
|||
impl quote::ToTokens for $options_name {
|
||||
#[allow(unused_mut, unused_variables, unused_assignments)]
|
||||
fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
|
||||
let mut separator: Option<syn::Token![,]> = None;
|
||||
let mut separator: Option<$Punct> = None;
|
||||
$(if let Some(v) = &self.$key {
|
||||
separator.to_tokens(tokens);
|
||||
separator = Some(Default::default());
|
||||
|
@ -673,6 +796,20 @@ macro_rules! options {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl $option_enum_name {
|
||||
#[allow(dead_code)]
|
||||
fn variant(&self) -> usize {
|
||||
#[repr(usize)]
|
||||
enum Variant {
|
||||
$($Variant,)*
|
||||
__Last, // so it doesn't complain about zero-variant enums
|
||||
}
|
||||
match *self {
|
||||
$(Self::$Variant(..) => Variant::$Variant as usize,)*
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -686,6 +823,15 @@ pub(crate) fn outline_generated(contents: TokenStream, prefix: &str) -> TokenStr
|
|||
.suffix(".tmp.rs")
|
||||
.tempfile_in(out_dir)
|
||||
.unwrap();
|
||||
struct PrintOnPanic<'a>(&'a TokenStream);
|
||||
impl Drop for PrintOnPanic<'_> {
|
||||
fn drop(&mut self) {
|
||||
if std::thread::panicking() {
|
||||
println!("{}", self.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
let _print_on_panic = PrintOnPanic(&contents);
|
||||
let contents = prettyplease::unparse(&parse_quote! { #contents });
|
||||
let hash = <sha2::Sha256 as sha2::Digest>::digest(&contents);
|
||||
let hash = base16ct::HexDisplay(&hash[..5]);
|
||||
|
@ -706,7 +852,7 @@ pub(crate) fn outline_generated(contents: TokenStream, prefix: &str) -> TokenStr
|
|||
}
|
||||
}
|
||||
|
||||
pub fn module(attr: TokenStream, item: TokenStream) -> syn::Result<TokenStream> {
|
||||
pub fn hdl_module(attr: TokenStream, item: TokenStream) -> syn::Result<TokenStream> {
|
||||
let options = syn::parse2::<module::ConfigOptions>(attr)?;
|
||||
let options = HdlAttr::from(options);
|
||||
let func = syn::parse2::<module::ModuleFn>(quote! { #options #item })?;
|
||||
|
@ -717,14 +863,14 @@ pub fn module(attr: TokenStream, item: TokenStream) -> syn::Result<TokenStream>
|
|||
Ok(contents)
|
||||
}
|
||||
|
||||
pub fn value_derive(item: TokenStream) -> syn::Result<TokenStream> {
|
||||
let item = syn::parse2::<Item>(item)?;
|
||||
pub fn hdl_attr(attr: TokenStream, item: TokenStream) -> syn::Result<TokenStream> {
|
||||
let item = syn::parse2::<Item>(quote! { #[hdl(#attr)] #item })?;
|
||||
match item {
|
||||
Item::Enum(item) => value_derive_enum::value_derive_enum(item),
|
||||
Item::Struct(item) => value_derive_struct::value_derive_struct(item),
|
||||
Item::Enum(item) => hdl_enum::hdl_enum(item),
|
||||
Item::Struct(item) => hdl_bundle::hdl_bundle(item),
|
||||
_ => Err(syn::Error::new(
|
||||
Span::call_site(),
|
||||
"derive(Value) can only be used on structs or enums",
|
||||
"top-level #[hdl] can only be used on structs or enums",
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue