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 Box,
18}
19
20impl DType {
21 pub fn name(self) -> &'static str {
22 match self {
23 DType::Bool => "boolean",
24 DType::I64 => "integer",
25 DType::Ext => "extended",
26 DType::Rat => "rational",
27 DType::F64 => "float",
28 DType::Complex => "complex",
29 DType::Char => "character",
30 DType::Box => "boxed",
31 }
32 }
33
34 pub fn is_numeric(self) -> bool {
35 matches!(
36 self,
37 DType::Bool | DType::I64 | DType::Ext | DType::Rat | DType::F64 | DType::Complex
38 )
39 }
40
41 pub fn is_exact(self) -> bool {
43 matches!(self, DType::Ext | DType::Rat)
44 }
45
46 pub fn promote(a: DType, b: DType) -> Option<DType> {
52 use DType::*;
53 match (a, b) {
54 (Box, Box) => Some(Box),
55 (Box, _) | (_, Box) => None,
56 (Char, Char) => Some(Char),
57 (Char, _) | (_, Char) => None,
58 (Complex, _) | (_, Complex) => Some(Complex),
59 (F64, _) | (_, F64) => Some(F64),
60 (Rat, _) | (_, Rat) => Some(Rat),
61 (Ext, _) | (_, Ext) => Some(Ext),
62 (I64, _) | (_, I64) => Some(I64),
63 (Bool, Bool) => Some(Bool),
64 }
65 }
66}
67
68#[cfg(test)]
69mod tests {
70 use super::DType::*;
71
72 #[test]
73 fn the_numeric_tower_climbs_bool_integer_extended_rational_float_complex() {
74 let tower = [Bool, I64, Ext, Rat, F64, Complex];
75 for (i, &a) in tower.iter().enumerate() {
76 for (j, &b) in tower.iter().enumerate() {
77 let want = tower[i.max(j)];
78 assert_eq!(super::DType::promote(a, b), Some(want), "{a:?} with {b:?}");
80 }
81 }
82 }
83
84 #[test]
85 fn characters_and_boxes_mix_with_nothing() {
86 assert_eq!(super::DType::promote(Char, Ext), None);
87 assert_eq!(super::DType::promote(Box, Rat), None);
88 }
89}