use crate::{SourceCodeSpan, SourceSpan, source_code_span_impl};
use super::expr::Expr;
use super::item::Path;
use super::punct::Punctuated;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum FundamentalKind {
Void,
Bool,
Char,
Char8,
Char16,
Char32,
Wchar,
Short,
Int,
Long,
LongLong,
Float,
Double,
LongDouble,
SignedChar,
UnsignedChar,
UnsignedShort,
UnsignedInt,
UnsignedLong,
UnsignedLongLong,
}
#[derive(Debug, Clone, Copy, PartialEq, Default)]
pub struct CvQualifiers {
pub const_token: bool,
pub volatile_token: bool,
}
#[derive(Debug, Clone, PartialEq)]
pub enum Type<'de> {
Fundamental(TypeFundamental<'de>),
Path(TypePath<'de>),
Ptr(TypePtr<'de>),
Reference(TypeReference<'de>),
RvalueReference(TypeRvalueReference<'de>),
Array(TypeArray<'de>),
FnPtr(TypeFnPtr<'de>),
Auto(TypeAuto<'de>),
Decltype(TypeDecltype<'de>),
TemplateInst(TypeTemplateInst<'de>),
Qualified(TypeQualified<'de>),
}
impl<'de> Type<'de> {
pub fn is_auto(&self) -> bool {
match self {
Type::Auto(_) => true,
Type::Qualified(q) => q.ty.is_auto(),
_ => false,
}
}
pub fn remove_ref(&mut self) {
match self {
Type::Reference(r) => {
*self = *r.referent.clone();
}
Type::RvalueReference(r) => {
*self = *r.referent.clone();
}
Type::Qualified(q) => q.ty.remove_ref(),
_ => {}
}
}
}
impl<'de> SourceCodeSpan<'de> for Type<'de> {
fn span(&self) -> Option<SourceSpan<'de>> {
match self {
Type::Fundamental(f) => Some(f.span),
Type::Path(p) => p.span(),
Type::Auto(a) => Some(a.span),
Type::Decltype(d) => d.span(),
Type::Ptr(p) => p.span(),
Type::Reference(r) => r.span(),
Type::RvalueReference(r) => r.span(),
Type::Array(a) => a.span(),
Type::FnPtr(f) => f.span(),
Type::Qualified(q) => q.span(),
Type::TemplateInst(t) => t.span(),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct TypeFundamental<'de> {
pub span: SourceSpan<'de>,
pub kind: FundamentalKind,
}
source_code_span_impl!(TypeFundamental, Some, span);
#[derive(Debug, Clone, PartialEq)]
pub struct TypePath<'de> {
pub path: Path<'de>,
}
source_code_span_impl!(TypePath, path);
#[derive(Debug, Clone, PartialEq)]
pub struct TypePtr<'de> {
pub cv: CvQualifiers,
pub pointee: Box<Type<'de>>,
}
source_code_span_impl!(TypePtr, pointee);
#[derive(Debug, Clone, PartialEq)]
pub struct TypeReference<'de> {
pub cv: CvQualifiers,
pub referent: Box<Type<'de>>,
}
source_code_span_impl!(TypeReference, referent);
#[derive(Debug, Clone, PartialEq)]
pub struct TypeRvalueReference<'de> {
pub referent: Box<Type<'de>>,
}
source_code_span_impl!(TypeRvalueReference, referent);
#[derive(Debug, Clone, PartialEq)]
pub struct TypeArray<'de> {
pub element: Box<Type<'de>>,
pub size: Option<Expr<'de>>,
}
source_code_span_impl!(TypeArray, and_then, size, element);
#[derive(Debug, Clone, PartialEq)]
pub struct TypeFnPtr<'de> {
pub return_type: Box<Type<'de>>,
pub params: Punctuated<'de, Type<'de>>,
}
source_code_span_impl!(TypeFnPtr, return_type, params);
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct TypeAuto<'de> {
pub span: SourceSpan<'de>,
}
source_code_span_impl!(TypeAuto, Some, span);
#[derive(Debug, Clone, PartialEq)]
pub struct TypeDecltype<'de> {
pub expr: Expr<'de>,
}
source_code_span_impl!(TypeDecltype, expr);
#[derive(Debug, Clone, PartialEq)]
pub struct TypeTemplateInst<'de> {
pub path: Path<'de>,
pub args: Vec<TemplateArg<'de>>,
}
source_code_span_impl!(TypeTemplateInst, path, args);
#[derive(Debug, Clone, PartialEq)]
pub enum TemplateArg<'de> {
Type(Type<'de>),
Expr(Expr<'de>),
}
impl<'de> SourceCodeSpan<'de> for TemplateArg<'de> {
fn span(&self) -> Option<SourceSpan<'de>> {
match &self {
TemplateArg::Type(ty) => ty.span(),
TemplateArg::Expr(expr) => expr.span(),
}
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct TypeQualified<'de> {
pub cv: CvQualifiers,
pub ty: Box<Type<'de>>,
}
source_code_span_impl!(TypeQualified, ty);
#[derive(Debug, Clone, PartialEq)]
pub struct AngleBracketedArgs<'de> {
pub args: Vec<TemplateArg<'de>>,
}
source_code_span_impl!(AngleBracketedArgs, args);