use std::fmt::Debug;
use std::marker::PhantomData;
use crate::span::{HasSpan, Span};
use crate::{common::SpanId, private::Sealed};
mod other_ty;
mod prim_ty;
mod ptr_ty;
mod sequence_ty;
mod trait_ty;
mod user_ty;
pub use other_ty::*;
pub use prim_ty::*;
pub use ptr_ty::*;
pub use sequence_ty::*;
pub use trait_ty::*;
pub use user_ty::*;
pub trait TyData<'ast>: Debug + HasSpan<'ast> + Sealed {
fn as_kind(&'ast self) -> TyKind<'ast>;
}
#[repr(C)]
#[non_exhaustive]
#[derive(Debug, Copy, Clone)]
pub enum TyKind<'ast> {
Bool(&'ast BoolTy<'ast>),
Num(&'ast NumTy<'ast>),
Text(&'ast TextTy<'ast>),
Never(&'ast NeverTy<'ast>),
Tuple(&'ast TupleTy<'ast>),
Array(&'ast ArrayTy<'ast>),
Slice(&'ast SliceTy<'ast>),
Ref(&'ast RefTy<'ast>),
RawPtr(&'ast RawPtrTy<'ast>),
FnPtr(&'ast FnPtrTy<'ast>),
TraitObj(&'ast TraitObjTy<'ast>),
ImplTrait(&'ast ImplTraitTy<'ast>),
Inferred(&'ast InferredTy<'ast>),
Path(&'ast PathTy<'ast>),
}
impl<'ast> TyKind<'ast> {
#[must_use]
pub fn is_primitive_ty(&self) -> bool {
matches!(self, Self::Bool(..) | Self::Num(..) | Self::Text(..) | Self::Never(..))
}
#[must_use]
pub fn is_sequence_ty(&self) -> bool {
matches!(self, Self::Tuple(..) | Self::Array(..) | Self::Slice(..))
}
#[must_use]
pub fn is_fn(&self) -> bool {
matches!(self, Self::FnPtr(..))
}
#[must_use]
pub fn is_ptr_ty(&self) -> bool {
matches!(self, Self::Ref(..) | Self::RawPtr(..) | Self::FnPtr(..))
}
#[must_use]
pub fn is_trait_ty(&self) -> bool {
matches!(self, Self::TraitObj(..) | Self::ImplTrait(..))
}
#[must_use]
pub fn is_inferred(&self) -> bool {
matches!(self, Self::Inferred(..))
}
#[must_use]
pub fn peel_refs(self) -> Self {
let mut ty = self;
while let Self::Ref(ref_ty) = ty {
ty = ref_ty.inner_ty();
}
ty
}
}
impl<'ast> TyKind<'ast> {
impl_syn_ty_data_fn!(span() -> &Span<'ast>);
}
crate::span::impl_spanned_for!(TyKind<'ast>);
macro_rules! impl_syn_ty_data_fn {
($method:ident () -> $return_ty:ty) => {
impl_syn_ty_data_fn!($method() -> $return_ty,
Bool, Num, Text, Never,
Tuple, Array, Slice,
Ref, RawPtr, FnPtr,
TraitObj, ImplTrait,
Inferred, Path
);
};
($method:ident () -> $return_ty:ty $(, $item:ident)+) => {
pub fn $method(&self) -> $return_ty {
match self {
$(TyKind::$item(data) => data.$method(),)*
}
}
};
}
use impl_syn_ty_data_fn;
#[repr(C)]
#[derive(Debug)]
#[cfg_attr(feature = "driver-api", visibility::make(pub))]
pub(crate) struct CommonSynTyData<'ast> {
_lifetime: PhantomData<&'ast ()>,
span: SpanId,
}
#[cfg(feature = "driver-api")]
impl<'ast> CommonSynTyData<'ast> {
pub fn new_syntactic(span: SpanId) -> Self {
Self {
_lifetime: PhantomData,
span,
}
}
}
macro_rules! impl_ty_data {
($self_ty:ty, $enum_name:ident) => {
impl<'ast> $crate::ast::ty::TyData<'ast> for $self_ty {
fn as_kind(&'ast self) -> $crate::ast::ty::TyKind<'ast> {
self.into()
}
}
$crate::span::impl_has_span_via_field!($self_ty, data.span);
impl<'ast> $crate::private::Sealed for $self_ty {}
impl<'ast> From<&'ast $self_ty> for $crate::ast::ty::TyKind<'ast> {
fn from(from: &'ast $self_ty) -> Self {
$crate::ast::ty::TyKind::$enum_name(from)
}
}
};
}
use impl_ty_data;