1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
use rustc_hash::FxHashMap;
use mun_abi::{self as abi, Guid};
use crate::r#type::{HasStaticType, Type};
#[derive(Clone)]
pub struct TypeTable {
concrete: FxHashMap<Guid, Type>,
type_name_to_type_info: FxHashMap<String, Type>,
}
impl TypeTable {
pub fn find_type_info_by_name<S: AsRef<str>>(&self, name: S) -> Option<Type> {
self.type_name_to_type_info.get(name.as_ref()).cloned()
}
pub fn find_type_info_by_id<'abi>(&self, type_id: &'abi abi::TypeId<'abi>) -> Option<Type> {
match type_id {
abi::TypeId::Concrete(guid) => self.concrete.get(guid).cloned(),
abi::TypeId::Pointer(p) => self
.find_type_info_by_id(p.pointee)
.map(|ty| ty.pointer_type(p.mutable)),
abi::TypeId::Array(a) => self
.find_type_info_by_id(a.element)
.map(|ty| ty.array_type()),
}
}
fn insert_static_type<T: HasStaticType>(&mut self) -> Option<Type> {
self.insert_type(T::type_info().clone())
}
pub fn insert_type(&mut self, type_info: Type) -> Option<Type> {
match type_info.as_concrete() {
None => panic!("can only insert concrete types"),
Some(guid) => self.insert_concrete_type(*guid, type_info),
}
}
pub fn insert_concrete_type(&mut self, guid: Guid, ty: Type) -> Option<Type> {
self.type_name_to_type_info
.insert(ty.name().to_owned(), ty.clone());
self.concrete.insert(guid, ty)
}
pub fn remove_type(&mut self, ty: &Type) -> Option<Type> {
match ty.as_concrete() {
None => panic!("can only remove concrete types"),
Some(guid) => {
self.type_name_to_type_info.remove(ty.name());
self.concrete.remove(guid)
}
}
}
pub fn remove_type_by_type_info<'abi>(
&mut self,
type_info: &'abi abi::TypeDefinition<'abi>,
) -> Option<Type> {
let ty = self.concrete.remove(type_info.as_concrete())?;
self.type_name_to_type_info.remove(ty.name())
}
pub fn remove_type_by_name<S: AsRef<str>>(&mut self, name: S) -> Option<Type> {
if let Some(type_info) = self.type_name_to_type_info.remove(name.as_ref()) {
self.remove_type(&type_info)
} else {
None
}
}
}
impl Default for TypeTable {
fn default() -> Self {
let mut type_table = Self {
concrete: Default::default(),
type_name_to_type_info: Default::default(),
};
type_table.insert_static_type::<i8>();
type_table.insert_static_type::<i16>();
type_table.insert_static_type::<i32>();
type_table.insert_static_type::<i64>();
type_table.insert_static_type::<i128>();
type_table.insert_static_type::<u8>();
type_table.insert_static_type::<u16>();
type_table.insert_static_type::<u32>();
type_table.insert_static_type::<u64>();
type_table.insert_static_type::<u128>();
type_table.insert_static_type::<f32>();
type_table.insert_static_type::<f64>();
type_table.insert_static_type::<bool>();
type_table.insert_static_type::<()>();
type_table.insert_static_type::<std::ffi::c_void>();
type_table
}
}