Skip to main content

rusty_javac/ty/
types.rs

1use std::fmt;
2use ustr::Ustr;
3
4#[derive(Debug, Clone, PartialEq, Eq, Hash)]
5pub enum Ty {
6    Void,
7    Boolean,
8    Byte,
9    Char,
10    Short,
11    Int,
12    Long,
13    Float,
14    Double,
15    Class(Ustr),
16    Array(Box<Ty>),
17    TypeVar(Ustr),
18    Wildcard(Option<Box<Ty>>),
19    Intersection(Vec<Ty>),
20}
21
22impl Ty {
23    pub fn object() -> Self {
24        Ty::Class(Ustr::from("java/lang/Object"))
25    }
26
27    pub fn string() -> Self {
28        Ty::Class(Ustr::from("java/lang/String"))
29    }
30
31    pub fn class(internal_name: impl AsRef<str>) -> Self {
32        Ty::Class(Ustr::from(internal_name.as_ref()))
33    }
34
35    pub fn is_string(&self) -> bool {
36        matches!(self.erasure(), Ty::Class(name) if name.as_str() == "java/lang/String")
37    }
38
39    pub fn descriptor(&self) -> String {
40        match self {
41            Ty::Void => "V".to_string(),
42            Ty::Boolean => "Z".to_string(),
43            Ty::Byte => "B".to_string(),
44            Ty::Char => "C".to_string(),
45            Ty::Short => "S".to_string(),
46            Ty::Int => "I".to_string(),
47            Ty::Long => "J".to_string(),
48            Ty::Float => "F".to_string(),
49            Ty::Double => "D".to_string(),
50            Ty::Class(name) => format!("L{};", name.as_str().replace('.', "/")),
51            Ty::Array(elem) => format!("[{}", elem.descriptor()),
52            Ty::TypeVar(_) => "Ljava/lang/Object;".to_string(),
53            Ty::Wildcard(_) => "Ljava/lang/Object;".to_string(),
54            Ty::Intersection(_) => "Ljava/lang/Object;".to_string(),
55        }
56    }
57
58    pub fn erasure(&self) -> Ty {
59        match self {
60            Ty::TypeVar(_) => Ty::object(),
61            Ty::Wildcard(Some(bound)) => bound.erasure(),
62            Ty::Wildcard(None) => Ty::object(),
63            Ty::Intersection(types) => types
64                .first()
65                .map(|t| t.erasure())
66                .unwrap_or_else(Ty::object),
67            other => other.clone(),
68        }
69    }
70
71    pub fn is_primitive(&self) -> bool {
72        matches!(
73            self,
74            Ty::Boolean
75                | Ty::Byte
76                | Ty::Char
77                | Ty::Short
78                | Ty::Int
79                | Ty::Long
80                | Ty::Float
81                | Ty::Double
82        )
83    }
84
85    pub fn is_numeric(&self) -> bool {
86        matches!(
87            self,
88            Ty::Byte | Ty::Short | Ty::Int | Ty::Long | Ty::Float | Ty::Double | Ty::Char
89        )
90    }
91
92    pub fn is_integral(&self) -> bool {
93        matches!(self, Ty::Byte | Ty::Short | Ty::Int | Ty::Long | Ty::Char)
94    }
95
96    pub fn is_floating(&self) -> bool {
97        matches!(self, Ty::Float | Ty::Double)
98    }
99
100    pub fn size(&self) -> usize {
101        match self {
102            Ty::Long | Ty::Double => 2,
103            Ty::Void => 0,
104            _ => 1,
105        }
106    }
107
108    pub fn internal_name(&self) -> String {
109        match self {
110            Ty::Class(name) => name.as_str().to_string(),
111            Ty::Array(elem) => elem.descriptor(),
112            _ => self.erasure().internal_name(),
113        }
114    }
115}
116
117#[derive(Debug, Clone, PartialEq, Eq, Hash)]
118pub struct TypeParam {
119    pub name: Ustr,
120    pub bounds: Vec<Ty>,
121}
122
123impl fmt::Display for Ty {
124    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
125        match self {
126            Ty::Void => write!(f, "void"),
127            Ty::Boolean => write!(f, "boolean"),
128            Ty::Byte => write!(f, "byte"),
129            Ty::Char => write!(f, "char"),
130            Ty::Short => write!(f, "short"),
131            Ty::Int => write!(f, "int"),
132            Ty::Long => write!(f, "long"),
133            Ty::Float => write!(f, "float"),
134            Ty::Double => write!(f, "double"),
135            Ty::Class(name) => write!(f, "{}", name.as_str().replace('/', ".")),
136            Ty::Array(elem) => write!(f, "{}[]", elem),
137            Ty::TypeVar(name) => write!(f, "{}", name.as_str()),
138            Ty::Wildcard(Some(bound)) => write!(f, "? extends {}", bound),
139            Ty::Wildcard(None) => write!(f, "?"),
140            Ty::Intersection(types) => {
141                let parts: Vec<String> = types.iter().map(|t| t.to_string()).collect();
142                write!(f, "{}", parts.join(" & "))
143            }
144        }
145    }
146}