use crate::{
expr::{Expr, ToExpr},
int::Bool,
source_location::SourceLocation,
ty::{impl_match_variant_as_self, CanonicalType, StaticType, Type, TypeProperties},
};
mod sealed {
pub trait ResetTypeSealed {}
}
pub trait ResetType: StaticType<MaskType = Bool> + sealed::ResetTypeSealed {}
macro_rules! reset_type {
($name:ident, $Trait:ident::$trait_fn:ident, $is_castable_from_bits:literal) => {
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, Default)]
pub struct $name;
impl Type for $name {
type BaseType = $name;
type MaskType = Bool;
impl_match_variant_as_self!();
fn mask_type(&self) -> Self::MaskType {
Bool
}
fn canonical(&self) -> CanonicalType {
CanonicalType::$name(*self)
}
fn source_location() -> SourceLocation {
SourceLocation::builtin()
}
fn from_canonical(canonical_type: CanonicalType) -> Self {
let CanonicalType::$name(retval) = canonical_type else {
panic!("expected {}", stringify!($name));
};
retval
}
}
impl $name {
pub fn type_properties(self) -> TypeProperties {
Self::TYPE_PROPERTIES
}
pub fn can_connect(self, _rhs: Self) -> bool {
true
}
}
impl StaticType for $name {
const TYPE: Self = Self;
const MASK_TYPE: Self::MaskType = Bool;
const TYPE_PROPERTIES: TypeProperties = TypeProperties {
is_passive: true,
is_storable: false,
is_castable_from_bits: $is_castable_from_bits,
bit_width: 1,
};
const MASK_TYPE_PROPERTIES: TypeProperties = Bool::TYPE_PROPERTIES;
}
impl sealed::ResetTypeSealed for $name {}
impl ResetType for $name {}
pub trait $Trait {
fn $trait_fn(&self) -> Expr<$name>;
}
impl<T: ?Sized + $Trait> $Trait for &'_ T {
fn $trait_fn(&self) -> Expr<$name> {
(**self).$trait_fn()
}
}
impl<T: ?Sized + $Trait> $Trait for &'_ mut T {
fn $trait_fn(&self) -> Expr<$name> {
(**self).$trait_fn()
}
}
impl<T: ?Sized + $Trait> $Trait for Box<T> {
fn $trait_fn(&self) -> Expr<$name> {
(**self).$trait_fn()
}
}
impl $Trait for Expr<$name> {
fn $trait_fn(&self) -> Expr<$name> {
*self
}
}
};
}
reset_type!(AsyncReset, ToAsyncReset::to_async_reset, true);
reset_type!(SyncReset, ToSyncReset::to_sync_reset, true);
reset_type!(
Reset,
ToReset::to_reset,
false );
impl ToSyncReset for bool {
fn to_sync_reset(&self) -> Expr<SyncReset> {
self.to_expr().to_sync_reset()
}
}
impl ToAsyncReset for bool {
fn to_async_reset(&self) -> Expr<AsyncReset> {
self.to_expr().to_async_reset()
}
}