duskphantom_middle/ir/
value_type.rs1use anyhow::{anyhow, Context, Result};
18
19use crate::context;
20
21use super::Constant;
22
23#[derive(Clone, PartialEq, Eq, Hash)]
25pub enum ValueType {
26 Void,
27 SignedChar,
28 Int,
29 Float,
30 Bool,
31 Array(Box<ValueType>, usize),
32 Pointer(Box<ValueType>),
33}
34
35impl std::fmt::Display for ValueType {
36 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
37 match self {
38 ValueType::Void => write!(f, "void"),
39 ValueType::SignedChar => write!(f, "i8"),
40 ValueType::Int => write!(f, "i32"),
41 ValueType::Float => write!(f, "float"),
42 ValueType::Bool => write!(f, "i1"),
43 ValueType::Array(one_type, size) => write!(f, "[{} x {}]", size, one_type),
44 ValueType::Pointer(pointer) => write!(f, "{}*", pointer),
45 }
46 }
47}
48
49impl std::fmt::Debug for ValueType {
50 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
51 write!(f, "{}", self)
52 }
53}
54
55impl ValueType {
56 pub fn is_basic_type(&self) -> bool {
57 matches!(
58 self,
59 ValueType::Void | ValueType::Int | ValueType::Float | ValueType::Bool
60 )
61 }
62
63 pub fn is_num(&self) -> bool {
64 matches!(self, ValueType::Bool | ValueType::Int | ValueType::Float)
65 }
66
67 pub fn is_pointer(&self) -> bool {
68 matches!(self, ValueType::Pointer(_))
69 }
70
71 pub fn is_array(&self) -> bool {
72 matches!(self, ValueType::Array(_, _))
73 }
74
75 pub fn size(&self) -> usize {
77 match self {
78 ValueType::Array(element_type, dim) => *dim * element_type.size(),
79 _ => 1,
80 }
81 }
82
83 pub fn get_sub_type(&self) -> Option<&ValueType> {
86 match self {
87 ValueType::Array(sub_type, _) => Some(sub_type.as_ref()),
88 ValueType::Pointer(sub_type) => Some(sub_type.as_ref()),
89 _ => None,
90 }
91 }
92
93 pub fn get_base_type(&self) -> ValueType {
96 match self {
97 ValueType::Array(sub_type, _) => sub_type.get_base_type(),
98 ValueType::Pointer(sub_type) => sub_type.get_base_type(),
99 _ => self.clone(),
100 }
101 }
102
103 pub fn default_initializer(&self) -> Result<Constant> {
105 match self {
106 ValueType::Void => {
107 Err(anyhow!("Cannot convert void type to constant")).with_context(|| context!())
108 }
109 ValueType::Int => Ok(Constant::Int(0)),
110 ValueType::SignedChar => Ok(Constant::SignedChar(0)),
111 ValueType::Float => Ok(Constant::Float(0.0)),
112 ValueType::Bool => Ok(Constant::Bool(false)),
113 ValueType::Pointer(_) => {
114 Err(anyhow!("Cannot convert pointer type to constant")).with_context(|| context!())
115 }
116 ValueType::Array(ty, _) => Ok(Constant::Zero(*ty.clone())),
117 }
118 }
119
120 pub fn to_precision_level(&self) -> i32 {
123 match self {
124 ValueType::Bool => 1,
126 ValueType::Int => 1,
127 ValueType::Float => 2,
128 _ => 0,
129 }
130 }
131
132 pub fn from_precision_level(level: i32) -> Self {
134 match level {
135 1 => ValueType::Int,
136 2 => ValueType::Float,
137 _ => ValueType::Void,
138 }
139 }
140
141 pub fn max_with(&self, b: &Self) -> Self {
144 if self.is_num() && b.is_num() {
145 let a_lv = self.to_precision_level();
146 let b_lv = b.to_precision_level();
147 let max_lv = if a_lv > b_lv { a_lv } else { b_lv };
148 ValueType::from_precision_level(max_lv)
149 } else {
150 ValueType::Void
151 }
152 }
153}