1#[derive(Clone, Copy, Debug, PartialEq, Eq)]
5pub enum DType {
6 Bool,
7 I64,
8 Ext,
10 Rat,
12 F64,
13 Complex,
15 Char,
16 Symbol,
19 Box,
21}
22
23impl DType {
24 pub fn name(self) -> &'static str {
25 match self {
26 DType::Bool => "boolean",
27 DType::I64 => "integer",
28 DType::Ext => "extended",
29 DType::Rat => "rational",
30 DType::F64 => "float",
31 DType::Complex => "complex",
32 DType::Char => "character",
33 DType::Symbol => "symbol",
34 DType::Box => "boxed",
35 }
36 }
37
38 pub fn is_numeric(self) -> bool {
39 matches!(
40 self,
41 DType::Bool | DType::I64 | DType::Ext | DType::Rat | DType::F64 | DType::Complex
42 )
43 }
44
45 pub fn is_exact(self) -> bool {
47 matches!(self, DType::Ext | DType::Rat)
48 }
49
50 pub fn promote(a: DType, b: DType) -> Option<DType> {
56 use DType::*;
57 match (a, b) {
58 (Box, Box) => Some(Box),
59 (Box, _) | (_, Box) => None,
60 (Char, Char) => Some(Char),
61 (Char, _) | (_, Char) => None,
62 (Symbol, Symbol) => Some(Symbol),
63 (Symbol, _) | (_, Symbol) => None,
64 (Complex, _) | (_, Complex) => Some(Complex),
65 (F64, _) | (_, F64) => Some(F64),
66 (Rat, _) | (_, Rat) => Some(Rat),
67 (Ext, _) | (_, Ext) => Some(Ext),
68 (I64, _) | (_, I64) => Some(I64),
69 (Bool, Bool) => Some(Bool),
70 }
71 }
72}
73
74#[cfg(test)]
75mod tests {
76 use super::DType::*;
77
78 #[test]
79 fn the_numeric_tower_climbs_bool_integer_extended_rational_float_complex() {
80 let tower = [Bool, I64, Ext, Rat, F64, Complex];
81 for (i, &a) in tower.iter().enumerate() {
82 for (j, &b) in tower.iter().enumerate() {
83 let want = tower[i.max(j)];
84 assert_eq!(super::DType::promote(a, b), Some(want), "{a:?} with {b:?}");
86 }
87 }
88 }
89
90 #[test]
91 fn characters_and_boxes_mix_with_nothing() {
92 assert_eq!(super::DType::promote(Char, Ext), None);
93 assert_eq!(super::DType::promote(Box, Rat), None);
94 assert_eq!(super::DType::promote(Symbol, Char), None);
95 assert_eq!(super::DType::promote(Symbol, I64), None);
96 assert_eq!(super::DType::promote(Symbol, Symbol), Some(Symbol));
97 }
98}