#[macro_export]
#[doc(hidden)]
macro_rules! _def_circuit_struct {
($name: ident, {
$($fields:tt)*
}
) => {
$crate::circuit::macros::def_circuit_struct!(@parse
struct $name {}
$($fields)*
);
};
(@parse
struct $name:ident { $($out:tt)* }
) => {
#[derive(Debug)]
struct $name { $($out)* }
};
(@parse
struct $name:ident { $($out:tt)* }
$field:ident : [[ $w:ty ; $n:expr ] ; $m:expr ],
$($rest:tt)*
) => {
$crate::circuit::macros::def_circuit_struct!(@parse
struct $name {
$($out)*
$field: [$crate::word::CompositeWord<$w, $n>; $m],
}
$($rest)*
);
};
(@parse
struct $name:ident { $($out:tt)* }
$field:ident : [ $w:ty ; $n:expr ],
$($rest:tt)*
) => {
$crate::circuit::macros::def_circuit_struct!(@parse
struct $name {
$($out)*
$field: $crate::word::CompositeWord<$w, $n>,
}
$($rest)*
);
};
(@parse
struct $name:ident { $($out:tt)* }
$field:ident : $w:ty,
$($rest:tt)*
) => {
$crate::circuit::macros::def_circuit_struct!(@parse
struct $name {
$($out)*
$field: $w,
}
$($rest)*
);
};
(@parse
struct $name:ident { $($out:tt)* }
$field:ident : [[ $w:ty ; $n:expr ] ; $m:expr ]
) => {
#[derive(Debug)]
struct $name {
$($out)*
$field: [CompositeWord<$w, $n>; $m],
}
};
(@parse
struct $name:ident { $($out:tt)* }
$field:ident : [ $w:ty ; $n:expr ]
) => {
#[derive(Debug)]
struct $name {
$($out)*
$field: $crate::word::CompositeWord<$w, $n>,
}
};
(@parse
struct $name:ident { $($out:tt)* }
$field:ident : $w:ty
) => {
#[derive(Debug)]
struct $name {
$($out)*
$field: $w,
}
};
}
pub use _def_circuit_struct as def_circuit_struct;
#[macro_export]
#[doc(hidden)]
macro_rules! _impl_circuit_constructor {
($name:ident, {
$($fields:tt)*
}) => {
$crate::circuit::macros::impl_circuit_constructor!(@parse
impl $name { () () }
$($fields)*
);
};
(@parse
impl $name:ident {
($($params:tt)*)
($($inits:tt)*)
}
) => {
impl $name {
pub fn new($($params)*) -> Self {
Self {
$($inits)*
}
}
}
};
(@parse
impl $name:ident { ($($p:tt)*) ($($i:tt)*) }
$field:ident : [[ $w:ty ; $n:expr ] ; $m:expr ],
$($rest:tt)*
) => {
$crate::circuit::macros::impl_circuit_constructor!(@parse
impl $name {
($($p)* $field: [[ $w ; $n ]; $m],)
($($i)* $field: $field.map(|x| $crate::word::CompositeWord::from_le_words(x)),)
}
$($rest)*
);
};
(@parse
impl $name:ident { ($($p:tt)*) ($($i:tt)*) }
$field:ident : [[ $w:ty ; $n:expr ] ; $m:expr ]
) => {
impl $name {
pub fn new($($p)* $field: [[ $w ; $n ]; $m],) -> Self {
Self {
$($i)*
$field: $field.map(|x| $crate::word::CompositeWord::from_le_words(x)),
}
}
}
};
(@parse
impl $name:ident { ($($p:tt)*) ($($i:tt)*) }
$field:ident : [ $w:ty ; $n:expr ],
$($rest:tt)*
) => {
$crate::circuit::macros::impl_circuit_constructor!(@parse
impl $name {
($($p)* $field: [ $w ; $n ],)
($($i)* $field: $crate::word::CompositeWord::from_le_words($field),)
}
$($rest)*
);
};
(@parse
impl $name:ident { ($($p:tt)*) ($($i:tt)*) }
$field:ident : [ $w:ty ; $n:expr ]
) => {
impl $name {
pub fn new($($p)* $field: [ $w ; $n ],) -> Self {
Self {
$($i)*
$field: $crate::word::CompositeWord::from_le_words($field),
}
}
}
};
(@parse
impl $name:ident { ($($p:tt)*) ($($i:tt)*) }
$field:ident : $w:ty,
$($rest:tt)*
) => {
$crate::circuit::macros::impl_circuit_constructor!(@parse
impl $name {
($($p)* $field: $w,)
($($i)* $field: $field,)
}
$($rest)*
);
};
(@parse
impl $name:ident { ($($p:tt)*) ($($i:tt)*) }
$field:ident : $w:ty
) => {
impl $name {
pub fn new($($p)* $field: $w,) -> Self {
Self {
$($i)*
$field: $field,
}
}
}
};
}
pub use _impl_circuit_constructor as impl_circuit_constructor;
#[macro_export]
#[doc(hidden)]
macro_rules! _impl_circuit_exec {
($name:ident, $fun:expr,
{ frontend, $($in_name:ident : $in_ty:tt),* $(,)? },
{ $($out_name:ident : $out_ty:tt),* $(,)? }
) => {
impl $crate::circuit::Circuit for $name {
fn exec<B: $crate::backend::Backend, F: $crate::backend::Frontend<B>>(&self, frontend: &mut F) {
$crate::circuit::macros::impl_circuit_exec!(@inputs frontend self;
$($in_name : $in_ty),*
);
$crate::circuit::macros::impl_circuit_exec!(@output_declarations;
$($out_name : $out_ty),*
);
($($out_name),*) =
$fun(frontend, $($in_name),*);
$crate::circuit::macros::impl_circuit_exec!(@outputs frontend;
$($out_name : $out_ty),*
);
}
}
};
($name:ident, $fun:expr,
{ $($in_name:ident : $in_ty:tt),* $(,)? },
{ $($out_name:ident : $out_ty:tt),* $(,)? }
) => {
impl $crate::circuit::Circuit for $name {
fn exec<B: $crate::backend::Backend, F: $crate::backend::Frontend<B>>(&self, frontend: &mut F) {
$crate::circuit::macros::impl_circuit_exec!(@inputs frontend self;
$($in_name : $in_ty),*
);
$crate::circuit::macros::impl_circuit_exec!(@output_declarations;
$($out_name : $out_ty),*
);
($($out_name),*) =
$fun($($in_name),*);
$crate::circuit::macros::impl_circuit_exec!(@outputs frontend;
$($out_name : $out_ty),*
);
}
}
};
(@expand_args) => {};
(@expand_args $field:ident : $ty:ty, $($rest:tt)*) => {
$field, $crate::circuit::macros::impl_circuit_exec!(@expand_args $($rest)*)
};
(@expand_args $field:ident : $ty:ty) => {
$field
};
(@out_names $field:ident : $ty:ty, $($rest:tt)*) => {
$field, $crate::circuit::macros::impl_circuit_exec!(@out_names $($rest)*)
};
(@out_names $field:ident : $ty:ty) => {
$field
};
(@inputs $fe:ident $slf:ident;) => {};
(@inputs $fe:ident $slf:ident;
$field:ident : [[ $w:ty ; $n:expr ] ; $m:expr ],
$($rest:tt)*
) => {
let $field: [$crate::backend::WordRef<B, $w, $n>; $m] = $slf.$field.map(|cw| $fe.input(cw));
$crate::circuit::macros::impl_circuit_exec!(@inputs $fe $slf; $($rest)*);
};
(@inputs $fe:ident $slf:ident;
$field:ident : [[ $w:ty ; $n:expr ] ; $m:expr ]
) => {
let $field: [$crate::backend::WordRef<B, $w, $n>; $m] = $slf.$field.map(|cw| $fe.input(cw));
};
(@inputs $fe:ident $slf:ident;
$field:ident : [ $w:ty ; $n:expr ],
$($rest:tt)*
) => {
let $field: $crate::backend::WordRef<B, $w, $n> = $fe.input($slf.$field);
$crate::circuit::macros::impl_circuit_exec!(@inputs $fe $slf; $($rest)*);
};
(@inputs $fe:ident $slf:ident;
$field:ident : [ $w:ty ; $n:expr ]
) => {
let $field: WordRef<B, $w, $n> = $fe.input($slf.$field);
};
(@inputs $fe:ident $slf:ident;
$field:ident : $w:ty,
$($rest:tt)*
) => {
let $field: $crate::backend::WordRef<B, $w> =
$fe.input($crate::word::CompositeWord::<$w, 1>::from_le_words([$slf.$field]));
$crate::circuit::macros::impl_circuit_exec!(@inputs $fe $slf; $($rest)*);
};
(@inputs $fe:ident $slf:ident;
$field:ident : $w:ty
) => {
let $field: WordRef<B, $w> =
$fe.input($crate::word::CompositeWord::<$w, 1>::from_le_words([$slf.$field]));
};
(@output_declarations;) => {};
(@output_declarations;
$field:ident : [[ $w:ty ; $n:expr ] ; $m:expr ],
$($rest:tt)*
) => {
let $field: [$crate::backend::WordRef<B, $w, $n>; $m];
$crate::circuit::macros::impl_circuit_exec!(@output_declarations; $($rest)*);
};
(@output_declarations;
$field:ident : [[ $w:ty ; $n:expr ] ; $m:expr ]
) => {
let $field: [$crate::backend::WordRef<B, $w, $n>; $m];
};
(@output_declarations;
$field:ident : [ $w:ty ; $n:expr ],
$($rest:tt)*
) => {
let $field: $crate::backend::WordRef<B, $w, $n>;
$crate::circuit::macros::impl_circuit_exec!(@output_declarations; $($rest)*);
};
(@output_declarations;
$field:ident : [ $w:ty ; $n:expr ]
) => {
let $field: $crate::backend::WordRef<B, $w, $n>;
};
(@output_declarations;
$field:ident : $w:ty,
$($rest:tt)*
) => {
let $field: $crate::backend::WordRef<B, $w>;
$crate::circuit::macros::impl_circuit_exec!(@output_declarations; $($rest)*);
};
(@output_declarations;
$field:ident : $w:ty
) => {
let $field: $crate::backend::WordRef<B, $w>;
};
(@outputs $fe:ident;) => {};
(@outputs $fe:ident;
$field:ident : $ty:ty,
$($rest:tt)*
) => {
$fe.output($field);
$crate::circuit::macros::impl_circuit_exec!(@outputs $fe; $($rest)*);
};
(@outputs $fe:ident;
$field:ident : $ty:ty
) => {
$fe.output($field);
};
}
pub use _impl_circuit_exec as impl_circuit_exec;
#[macro_export]
#[doc(hidden)]
macro_rules! _circuit {
($name:ident, $fun:expr, { frontend, $($inputs:tt)* }, { $($outputs:tt)* }) => {
$crate::circuit::macros::def_circuit_struct!($name, { $($inputs)* });
$crate::circuit::macros::impl_circuit_constructor!($name, { $($inputs)* });
$crate::circuit::macros::impl_circuit_exec!($name, $fun, { frontend, $($inputs)* }, { $($outputs)* });
};
($name:ident, $fun:expr, { $($inputs:tt)* }, { $($outputs:tt)* }) => {
$crate::circuit::macros::def_circuit_struct!($name, { $($inputs)* });
$crate::circuit::macros::impl_circuit_constructor!($name, { $($inputs)* });
$crate::circuit::macros::impl_circuit_exec!($name, $fun, { $($inputs)* }, { $($outputs)* });
};
}
pub use _circuit as circuit;