use crate::facet::Facets;
use crate::node::annotation::AnnotationDefNode;
use crate::node::constant::ConstExprNode;
use crate::node::interface::{InterfaceNode, OperationNode};
use crate::node::member::{BitValueNode, BitfieldNode, CaseNode, EnumeratorNode, MemberNode};
use crate::node::module::ModuleNode;
use alloc::string::String;
use alloc::vec::Vec;
use zerodds_ast_core::{Id, NodeId, Ref};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub enum PrimitiveKind {
Boolean,
Octet,
Char,
WChar,
Int8,
UInt8,
Int16,
UInt16,
Int32,
UInt32,
Int64,
UInt64,
Float32,
Float64,
Float128,
}
impl PrimitiveKind {
pub const ALL: [Self; 15] = [
Self::Boolean,
Self::Octet,
Self::Char,
Self::WChar,
Self::Int8,
Self::UInt8,
Self::Int16,
Self::UInt16,
Self::Int32,
Self::UInt32,
Self::Int64,
Self::UInt64,
Self::Float32,
Self::Float64,
Self::Float128,
];
#[must_use]
pub const fn as_str(self) -> &'static str {
match self {
Self::Boolean => "boolean",
Self::Octet => "octet",
Self::Char => "char",
Self::WChar => "wchar",
Self::Int8 => "int8",
Self::UInt8 => "uint8",
Self::Int16 => "short",
Self::UInt16 => "unsigned short",
Self::Int32 => "long",
Self::UInt32 => "unsigned long",
Self::Int64 => "long long",
Self::UInt64 => "unsigned long long",
Self::Float32 => "float",
Self::Float64 => "double",
Self::Float128 => "long double",
}
}
#[must_use]
pub const fn is_integral(self) -> bool {
matches!(
self,
Self::Octet
| Self::Int8
| Self::UInt8
| Self::Int16
| Self::UInt16
| Self::Int32
| Self::UInt32
| Self::Int64
| Self::UInt64
)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum CharWidth {
Char,
WChar,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Bound {
Unbounded,
Const(Id<ConstExprNode>),
}
impl Bound {
#[must_use]
pub const fn expr(self) -> Option<Id<ConstExprNode>> {
match self {
Self::Unbounded => None,
Self::Const(id) => Some(id),
}
}
#[must_use]
pub const fn is_bounded(self) -> bool {
matches!(self, Self::Const(_))
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum ValuetypeKind {
Regular,
Abstract,
Custom,
Truncatable,
}
impl ValuetypeKind {
pub const ALL: [Self; 4] = [
Self::Regular,
Self::Abstract,
Self::Custom,
Self::Truncatable,
];
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Completeness {
Forward,
Complete,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum TypeKind {
Primitive(PrimitiveKind),
Fixed {
digits: u8,
scale: u8,
},
String {
width: CharWidth,
bound: Bound,
},
Sequence {
element: Ref<TypeNode>,
bound: Bound,
},
Array {
element: Ref<TypeNode>,
dims: Vec<Id<ConstExprNode>>,
},
Map {
key: Ref<TypeNode>,
value: Ref<TypeNode>,
bound: Bound,
},
Structure {
base: Option<Ref<TypeNode>>,
members: Vec<Id<MemberNode>>,
},
Union {
discriminator: Ref<TypeNode>,
cases: Vec<Id<CaseNode>>,
default_case: Option<Id<CaseNode>>,
},
Enumeration {
enumerators: Vec<Id<EnumeratorNode>>,
},
Bitmask {
bits: Vec<Id<BitValueNode>>,
},
Bitset {
base: Option<Ref<TypeNode>>,
fields: Vec<Id<BitfieldNode>>,
},
Alias {
aliased: Ref<TypeNode>,
},
Valuetype {
kind: ValuetypeKind,
bases: Vec<Ref<TypeNode>>,
state: Vec<Id<MemberNode>>,
initializers: Vec<Id<OperationNode>>,
supported: Vec<Ref<InterfaceNode>>,
},
ValueBox {
boxed: Ref<TypeNode>,
},
Native,
ValueBase,
Any,
ObjectRef {
interface: Option<Ref<InterfaceNode>>,
},
AnnotationType {
definition: Id<AnnotationDefNode>,
},
}
impl TypeKind {
#[must_use]
pub const fn as_str(&self) -> &'static str {
match self {
Self::Primitive(_) => "primitive",
Self::Fixed { .. } => "fixed",
Self::String { .. } => "string",
Self::Sequence { .. } => "sequence",
Self::Array { .. } => "array",
Self::Map { .. } => "map",
Self::Structure { .. } => "struct",
Self::Union { .. } => "union",
Self::Enumeration { .. } => "enum",
Self::Bitmask { .. } => "bitmask",
Self::Bitset { .. } => "bitset",
Self::Alias { .. } => "typedef",
Self::Valuetype { .. } => "valuetype",
Self::ValueBox { .. } => "value box",
Self::Native => "native",
Self::Any => "any",
Self::ValueBase => "ValueBase",
Self::ObjectRef { .. } => "object reference",
Self::AnnotationType { .. } => "annotation type",
}
}
#[must_use]
pub const fn is_member_aggregate(&self) -> bool {
matches!(self, Self::Structure { .. } | Self::Valuetype { .. })
}
#[must_use]
pub fn members(&self) -> &[Id<MemberNode>] {
match self {
Self::Structure { members, .. } => members,
Self::Valuetype { state, .. } => state,
_ => &[],
}
}
#[must_use]
pub fn type_refs(&self) -> Vec<&Ref<TypeNode>> {
match self {
Self::Sequence { element, .. } | Self::Array { element, .. } => {
alloc::vec![element]
}
Self::Map { key, value, .. } => alloc::vec![key, value],
Self::Alias { aliased } => alloc::vec![aliased],
Self::ValueBox { boxed } => alloc::vec![boxed],
Self::Union { discriminator, .. } => alloc::vec![discriminator],
Self::Structure { base, .. } | Self::Bitset { base, .. } => {
base.as_ref().map_or_else(Vec::new, |b| alloc::vec![b])
}
Self::Valuetype { bases, .. } => bases.iter().collect(),
_ => Vec::new(),
}
}
pub fn type_refs_mut(&mut self) -> Vec<&mut Ref<TypeNode>> {
match self {
Self::Sequence { element, .. } | Self::Array { element, .. } => {
alloc::vec![element]
}
Self::Map { key, value, .. } => alloc::vec![key, value],
Self::Alias { aliased } => alloc::vec![aliased],
Self::ValueBox { boxed } => alloc::vec![boxed],
Self::Union { discriminator, .. } => alloc::vec![discriminator],
Self::Structure { base, .. } | Self::Bitset { base, .. } => {
base.as_mut().map_or_else(Vec::new, |b| alloc::vec![b])
}
Self::Valuetype { bases, .. } => bases.iter_mut().collect(),
_ => Vec::new(),
}
}
}
impl TypeNode {
#[must_use]
pub const fn facets_ref(&self) -> &Facets {
&self.facets
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct TypeNode {
pub node_id: NodeId,
pub name: String,
pub module: Id<ModuleNode>,
pub scope: Option<String>,
pub kind: TypeKind,
pub completeness: Completeness,
pub facets: Facets,
}