1use super::{Interner, Ty, TyFlags, TyKind};
2use solar_ast::{DataLocation, ElementaryType, TypeSize};
3
4pub struct CommonTypes<'gcx> {
6 pub unit: Ty<'gcx>,
8 pub bool: Ty<'gcx>,
10
11 pub address: Ty<'gcx>,
13 pub address_payable: Ty<'gcx>,
15
16 pub string: Ty<'gcx>,
18 pub string_ref: EachDataLoc<Ty<'gcx>>,
20
21 pub bytes: Ty<'gcx>,
23 pub bytes_ref: EachDataLoc<Ty<'gcx>>,
25
26 ints: [Ty<'gcx>; 32],
27 uints: [Ty<'gcx>; 32],
28 fbs: [Ty<'gcx>; 32],
29}
30
31impl<'gcx> CommonTypes<'gcx> {
32 #[instrument(name = "new_common_types", level = "debug", skip_all)]
33 #[inline]
34 pub(super) fn new(interner: &Interner<'gcx>, bump: &'gcx bumpalo::Bump) -> Self {
35 use ElementaryType::*;
36 use TyKind::*;
37 use std::array::from_fn;
38
39 let mk = |kind| interner.intern_ty_with_flags(bump, kind, |_| TyFlags::empty());
43 let mk_refs = |ty| EachDataLoc {
44 storage: mk(Ref(ty, DataLocation::Storage)),
45 transient: mk(Ref(ty, DataLocation::Transient)),
46 memory: mk(Ref(ty, DataLocation::Memory)),
47 calldata: mk(Ref(ty, DataLocation::Calldata)),
48 };
49
50 let string = mk(Elementary(String));
51 let bytes = mk(Elementary(Bytes));
52
53 Self {
54 unit: mk(Tuple(&[])),
55 bool: mk(Elementary(Bool)),
57
58 address: mk(Elementary(Address(false))),
59 address_payable: mk(Elementary(Address(true))),
60
61 string,
62 string_ref: mk_refs(string),
63
64 bytes,
65 bytes_ref: mk_refs(bytes),
66
67 ints: from_fn(|i| mk(Elementary(Int(TypeSize::new(i as u8 + 1).unwrap())))),
68 uints: from_fn(|i| mk(Elementary(UInt(TypeSize::new(i as u8 + 1).unwrap())))),
69 fbs: from_fn(|i| mk(Elementary(FixedBytes(TypeSize::new(i as u8 + 1).unwrap())))),
70 }
71 }
72
73 #[inline]
75 #[track_caller]
76 pub fn int(&self, bits: u16) -> Ty<'gcx> {
77 self.int_(TypeSize::new_int_bits(bits))
78 }
79 pub fn int_(&self, size: TypeSize) -> Ty<'gcx> {
81 self.ints[size.bytes() as usize - 1]
82 }
83
84 #[inline]
86 #[track_caller]
87 pub fn uint(&self, bits: u16) -> Ty<'gcx> {
88 self.uint_(TypeSize::new_int_bits(bits))
89 }
90 pub fn uint_(&self, size: TypeSize) -> Ty<'gcx> {
92 self.uints[size.bytes() as usize - 1]
93 }
94
95 #[inline]
97 #[track_caller]
98 pub fn fixed_bytes(&self, bytes: u8) -> Ty<'gcx> {
99 self.fixed_bytes_(TypeSize::new_fb_bytes(bytes))
100 }
101 pub fn fixed_bytes_(&self, size: TypeSize) -> Ty<'gcx> {
103 self.fbs[size.bytes() as usize - 1]
104 }
105}
106
107pub struct EachDataLoc<T> {
109 pub storage: T,
110 pub transient: T,
111 pub memory: T,
112 pub calldata: T,
113}
114
115impl<T> EachDataLoc<T> {
116 #[inline]
118 pub fn get(&self, loc: DataLocation) -> T
119 where
120 T: Copy,
121 {
122 match loc {
123 DataLocation::Storage => self.storage,
124 DataLocation::Transient => self.transient,
125 DataLocation::Memory => self.memory,
126 DataLocation::Calldata => self.calldata,
127 }
128 }
129
130 #[inline]
132 pub fn get_ref(&self, loc: DataLocation) -> &T {
133 match loc {
134 DataLocation::Storage => &self.storage,
135 DataLocation::Transient => &self.transient,
136 DataLocation::Memory => &self.memory,
137 DataLocation::Calldata => &self.calldata,
138 }
139 }
140
141 #[inline]
143 pub fn get_mut(&mut self, loc: DataLocation) -> &mut T {
144 match loc {
145 DataLocation::Storage => &mut self.storage,
146 DataLocation::Transient => &mut self.transient,
147 DataLocation::Memory => &mut self.memory,
148 DataLocation::Calldata => &mut self.calldata,
149 }
150 }
151}
152
153impl<T> std::ops::Index<DataLocation> for EachDataLoc<T> {
154 type Output = T;
155
156 #[inline]
157 fn index(&self, loc: DataLocation) -> &Self::Output {
158 self.get_ref(loc)
159 }
160}
161
162impl<T> std::ops::IndexMut<DataLocation> for EachDataLoc<T> {
163 #[inline]
164 fn index_mut(&mut self, loc: DataLocation) -> &mut Self::Output {
165 self.get_mut(loc)
166 }
167}