//! This module defines built-in types. //! //! A peculiarity of built-in types is that they are always available and are //! not associated with any particular crate. use std::fmt; use hir_expand::name::{name, AsName, Name}; #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] pub enum Signedness { Signed, Unsigned, } #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] pub enum IntBitness { Xsize, X8, X16, X32, X64, X128, } #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] pub enum FloatBitness { X32, X64, } #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct BuiltinInt { pub signedness: Signedness, pub bitness: IntBitness, } #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct BuiltinFloat { pub bitness: FloatBitness, } #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub enum BuiltinType { Char, Bool, Str, Int(BuiltinInt), Float(BuiltinFloat), } impl BuiltinType { #[rustfmt::skip] pub const ALL: &'static [(Name, BuiltinType)] = &[ (name![char], BuiltinType::Char), (name![bool], BuiltinType::Bool), (name![str], BuiltinType::Str), (name![isize], BuiltinType::Int(BuiltinInt::ISIZE)), (name![i8], BuiltinType::Int(BuiltinInt::I8)), (name![i16], BuiltinType::Int(BuiltinInt::I16)), (name![i32], BuiltinType::Int(BuiltinInt::I32)), (name![i64], BuiltinType::Int(BuiltinInt::I64)), (name![i128], BuiltinType::Int(BuiltinInt::I128)), (name![usize], BuiltinType::Int(BuiltinInt::USIZE)), (name![u8], BuiltinType::Int(BuiltinInt::U8)), (name![u16], BuiltinType::Int(BuiltinInt::U16)), (name![u32], BuiltinType::Int(BuiltinInt::U32)), (name![u64], BuiltinType::Int(BuiltinInt::U64)), (name![u128], BuiltinType::Int(BuiltinInt::U128)), (name![f32], BuiltinType::Float(BuiltinFloat::F32)), (name![f64], BuiltinType::Float(BuiltinFloat::F64)), ]; } impl AsName for BuiltinType { fn as_name(&self) -> Name { match self { BuiltinType::Char => name![char], BuiltinType::Bool => name![bool], BuiltinType::Str => name![str], BuiltinType::Int(BuiltinInt { signedness, bitness }) => match (signedness, bitness) { (Signedness::Signed, IntBitness::Xsize) => name![isize], (Signedness::Signed, IntBitness::X8) => name![i8], (Signedness::Signed, IntBitness::X16) => name![i16], (Signedness::Signed, IntBitness::X32) => name![i32], (Signedness::Signed, IntBitness::X64) => name![i64], (Signedness::Signed, IntBitness::X128) => name![i128], (Signedness::Unsigned, IntBitness::Xsize) => name![usize], (Signedness::Unsigned, IntBitness::X8) => name![u8], (Signedness::Unsigned, IntBitness::X16) => name![u16], (Signedness::Unsigned, IntBitness::X32) => name![u32], (Signedness::Unsigned, IntBitness::X64) => name![u64], (Signedness::Unsigned, IntBitness::X128) => name![u128], }, BuiltinType::Float(BuiltinFloat { bitness }) => match bitness { FloatBitness::X32 => name![f32], FloatBitness::X64 => name![f64], }, } } } impl fmt::Display for BuiltinType { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let type_name = self.as_name(); type_name.fmt(f) } } #[rustfmt::skip] impl BuiltinInt { pub const ISIZE: BuiltinInt = BuiltinInt { signedness: Signedness::Signed, bitness: IntBitness::Xsize }; pub const I8 : BuiltinInt = BuiltinInt { signedness: Signedness::Signed, bitness: IntBitness::X8 }; pub const I16 : BuiltinInt = BuiltinInt { signedness: Signedness::Signed, bitness: IntBitness::X16 }; pub const I32 : BuiltinInt = BuiltinInt { signedness: Signedness::Signed, bitness: IntBitness::X32 }; pub const I64 : BuiltinInt = BuiltinInt { signedness: Signedness::Signed, bitness: IntBitness::X64 }; pub const I128 : BuiltinInt = BuiltinInt { signedness: Signedness::Signed, bitness: IntBitness::X128 }; pub const USIZE: BuiltinInt = BuiltinInt { signedness: Signedness::Unsigned, bitness: IntBitness::Xsize }; pub const U8 : BuiltinInt = BuiltinInt { signedness: Signedness::Unsigned, bitness: IntBitness::X8 }; pub const U16 : BuiltinInt = BuiltinInt { signedness: Signedness::Unsigned, bitness: IntBitness::X16 }; pub const U32 : BuiltinInt = BuiltinInt { signedness: Signedness::Unsigned, bitness: IntBitness::X32 }; pub const U64 : BuiltinInt = BuiltinInt { signedness: Signedness::Unsigned, bitness: IntBitness::X64 }; pub const U128 : BuiltinInt = BuiltinInt { signedness: Signedness::Unsigned, bitness: IntBitness::X128 }; pub fn from_suffix(suffix: &str) -> Option { let res = match suffix { "isize" => Self::ISIZE, "i8" => Self::I8, "i16" => Self::I16, "i32" => Self::I32, "i64" => Self::I64, "i128" => Self::I128, "usize" => Self::USIZE, "u8" => Self::U8, "u16" => Self::U16, "u32" => Self::U32, "u64" => Self::U64, "u128" => Self::U128, _ => return None, }; Some(res) } } #[rustfmt::skip] impl BuiltinFloat { pub const F32: BuiltinFloat = BuiltinFloat { bitness: FloatBitness::X32 }; pub const F64: BuiltinFloat = BuiltinFloat { bitness: FloatBitness::X64 }; pub fn from_suffix(suffix: &str) -> Option { let res = match suffix { "f32" => BuiltinFloat::F32, "f64" => BuiltinFloat::F64, _ => return None, }; Some(res) } }