#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum Signedness {
Signed,
Unsigned,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum IntWidth {
W8,
W16,
W32,
W64,
W128,
WSize,
}
impl IntWidth {
pub fn byte_size(self) -> usize {
match self {
Self::W8 => 1,
Self::W16 => 2,
Self::W32 => 4,
Self::W64 | Self::WSize => 8,
Self::W128 => 16,
}
}
pub fn bit_size(self) -> usize {
self.byte_size() * 8
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum FloatWidth {
W32,
W64,
}
impl FloatWidth {
pub fn byte_size(self) -> usize {
use FloatWidth::*;
match self {
W32 => 4,
W64 => 8,
}
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum Mutability {
Shared,
Mutable,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct FunctionSignature {
pub parameters: Vec<Type>,
pub return_type: Box<Type>,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum Type {
Never,
Bool,
Int(IntWidth, Signedness),
Float(FloatWidth),
Pointer(Mutability, Box<Self>),
Array(Box<Self>, usize),
Vector(Box<Self>, usize),
Slice(Mutability, Box<Self>),
Tuple(Vec<Self>),
Enum(Vec<Self>),
Named(String),
Function(FunctionSignature),
}
impl Type {
pub fn unit() -> Self {
Self::Tuple(Vec::new())
}
pub fn is_unit(&self) -> bool {
matches!(self, Self::Tuple(fields) if fields.is_empty())
}
pub fn matches_name(&self, name: &str) -> bool {
match self {
Self::Named(type_name) => type_name == name,
Self::Bool => name == "bool",
Self::Int(IntWidth::W8, Signedness::Signed) => name == "i8",
Self::Int(IntWidth::W16, Signedness::Signed) => name == "i16",
Self::Int(IntWidth::W32, Signedness::Signed) => name == "i32",
Self::Int(IntWidth::W64, Signedness::Signed) => name == "i64",
Self::Int(IntWidth::W128, Signedness::Signed) => name == "i128",
Self::Int(IntWidth::W8, Signedness::Unsigned) => name == "u8",
Self::Int(IntWidth::W16, Signedness::Unsigned) => name == "u16",
Self::Int(IntWidth::W32, Signedness::Unsigned) => name == "u32",
Self::Int(IntWidth::W64, Signedness::Unsigned) => name == "u64",
Self::Int(IntWidth::W128, Signedness::Unsigned) => name == "u128",
Self::Int(IntWidth::WSize, Signedness::Signed) => name == "isize",
Self::Int(IntWidth::WSize, Signedness::Unsigned) => name == "usize",
Self::Float(FloatWidth::W32) => name == "f32",
Self::Float(FloatWidth::W64) => name == "f64",
_ => false,
}
}
}
impl std::fmt::Display for Type {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Never => write!(f, "never"),
Self::Bool => write!(f, "bool"),
Self::Int(IntWidth::W8, Signedness::Signed) => write!(f, "i8"),
Self::Int(IntWidth::W16, Signedness::Signed) => write!(f, "i16"),
Self::Int(IntWidth::W32, Signedness::Signed) => write!(f, "i32"),
Self::Int(IntWidth::W64, Signedness::Signed) => write!(f, "i64"),
Self::Int(IntWidth::W128, Signedness::Signed) => write!(f, "i128"),
Self::Int(IntWidth::WSize, Signedness::Signed) => write!(f, "isize"),
Self::Int(IntWidth::W8, Signedness::Unsigned) => write!(f, "u8"),
Self::Int(IntWidth::W16, Signedness::Unsigned) => write!(f, "u16"),
Self::Int(IntWidth::W32, Signedness::Unsigned) => write!(f, "u32"),
Self::Int(IntWidth::W64, Signedness::Unsigned) => write!(f, "u64"),
Self::Int(IntWidth::W128, Signedness::Unsigned) => write!(f, "u128"),
Self::Int(IntWidth::WSize, Signedness::Unsigned) => write!(f, "usize"),
Self::Float(FloatWidth::W32) => write!(f, "f32"),
Self::Float(FloatWidth::W64) => write!(f, "f64"),
Self::Pointer(Mutability::Shared, inner) => write!(f, "&{inner}"),
Self::Pointer(Mutability::Mutable, inner) => write!(f, "|{inner}"),
Self::Array(inner, length) => write!(f, "[{inner}]{length}"),
Self::Vector(inner, count) => write!(f, "{{{inner}}}{count}"),
Self::Named(name) => write!(f, "{name}"),
Self::Tuple(fields) => {
for (index, field) in fields.iter().enumerate() {
if index > 0 {
write!(f, " & ")?;
}
write!(f, "{field}")?;
}
Ok(())
}
Self::Enum(variants) => {
for (index, variant) in variants.iter().enumerate() {
if index > 0 {
write!(f, " | ")?;
}
write!(f, "{variant}")?;
}
Ok(())
}
Self::Slice(_, inner) => write!(f, "[{inner}]"),
Self::Function(signature) => {
write!(f, "fn(")?;
for (index, parameter) in signature.parameters.iter().enumerate() {
if index > 0 {
write!(f, ", ")?;
}
write!(f, "{parameter}")?;
}
write!(f, ") -> {}", signature.return_type)
}
}
}
}