1use std::{borrow::Cow, fmt::Display, marker::PhantomData};
8
9use jstd::Identifier;
10
11use crate::value::{ModuleView, QCodeView, Value, ValueId, util::named::Named};
12
13#[derive(Identifier)]
15pub struct LocalTempSpaceId(usize);
16
17crate::composite_id!(TempSpaceId, LocalTempSpaceId);
18
19#[derive(Identifier)]
21pub struct LocalTempId(usize);
22
23crate::composite_id!(TempId, LocalTempId);
24
25#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
27pub struct TempSpace {
28 pub(crate) name: Option<Box<str>>,
29 pub(crate) word_size: usize,
30 pub(crate) addr_size: usize,
31}
32
33impl TempSpace {
34 pub fn new(name: Option<&str>, word_size: usize, addr_size: usize) -> Self {
35 Self {
36 name: name.map(Box::from),
37 word_size,
38 addr_size,
39 }
40 }
41
42 pub fn name(&self) -> Option<&str> {
43 self.name.as_deref()
44 }
45
46 pub fn word_size(&self) -> usize {
47 self.word_size
48 }
49
50 pub fn addr_size(&self) -> usize {
51 self.addr_size
52 }
53}
54
55#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
57pub struct Temp<'str> {
58 pub(crate) name: Option<Cow<'str, str>>,
59 pub(crate) label: Option<u32>,
60 pub(crate) address: i64,
61 pub(crate) size: usize,
62 pub(crate) space: LocalTempSpaceId,
63}
64
65impl<'str> Temp<'str> {
66 pub fn new(address: i64, size: usize, space: LocalTempSpaceId) -> Self {
67 Self {
68 name: None,
69 label: None,
70 address,
71 size,
72 space,
73 }
74 }
75
76 pub fn with_name(mut self, name: Cow<'str, str>) -> Self {
79 self.name = Some(name);
80 self
81 }
82}
83
84#[derive(Clone, Copy)]
86pub struct TempSpaceRef<'str, 'ctx, R = ModuleView<'ctx, 'str>> {
87 pub id: TempSpaceId,
88 view: R,
89 marker: PhantomData<&'ctx &'str ()>,
90}
91
92impl<'str, 'ctx, R> TempSpaceRef<'str, 'ctx, R> {
93 pub fn new(view: R, id: TempSpaceId) -> Self {
94 Self {
95 id,
96 view,
97 marker: PhantomData,
98 }
99 }
100}
101
102impl<'str: 'ctx, 'ctx, R> TempSpaceRef<'str, 'ctx, R>
103where
104 R: QCodeView<'ctx, 'str>,
105{
106 fn inner(self) -> &'ctx TempSpace {
107 self.view.temp_space(self.id)
108 }
109
110 pub fn name(self) -> Option<&'ctx str> {
111 self.inner().name.as_deref()
112 }
113
114 pub fn word_size(self) -> usize {
115 self.inner().word_size
116 }
117
118 pub fn addr_size(self) -> usize {
119 self.inner().addr_size
120 }
121}
122
123impl<'str: 'ctx, 'ctx, R> Display for TempSpaceRef<'str, 'ctx, R>
124where
125 R: QCodeView<'ctx, 'str>,
126{
127 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
128 f.write_str(self.name().unwrap_or("temp"))
129 }
130}
131
132#[derive(Clone, Copy)]
134pub struct TempRef<'str, 'ctx, R = ModuleView<'ctx, 'str>> {
135 pub id: TempId,
136 pub(in crate::value) view: R,
137 marker: PhantomData<&'ctx &'str ()>,
138}
139
140impl<'str, 'ctx, R> TempRef<'str, 'ctx, R> {
141 pub fn new(view: R, id: TempId) -> Self {
142 Self {
143 id,
144 view,
145 marker: PhantomData,
146 }
147 }
148}
149
150impl<'str: 'ctx, 'ctx, R> TempRef<'str, 'ctx, R>
151where
152 R: QCodeView<'ctx, 'str>,
153{
154 fn inner(self) -> &'ctx Temp<'str> {
155 self.view.temp(self.id)
156 }
157
158 pub fn name(self) -> Option<&'ctx str> {
159 self.inner().name.as_deref()
160 }
161
162 pub fn label(self) -> Option<u32> {
163 self.inner().label
164 }
165
166 pub fn address(self) -> i64 {
167 self.inner().address
168 }
169
170 pub fn size(self) -> usize {
171 self.inner().size
172 }
173
174 pub fn space(self) -> TempSpaceRef<'str, 'ctx, R> {
175 TempSpaceRef::new(
176 self.view,
177 TempSpaceId::new(self.id.func, self.inner().space),
178 )
179 }
180
181 pub fn memory_space(self) -> crate::space::MemorySpaceId {
182 crate::space::MemorySpaceId::Temp(self.space().id)
183 }
184}
185
186impl<'str: 'ctx, 'ctx, R> Display for TempRef<'str, 'ctx, R>
187where
188 R: QCodeView<'ctx, 'str>,
189{
190 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
191 if let Some(name) = self.name() {
192 f.write_str(name)
193 } else if let Some(label) = self.label() {
194 write!(f, "v{label}")
195 } else {
196 write!(f, "[{}]:{} {}", self.space(), self.size(), self.address())
197 }
198 }
199}
200
201impl<'str: 'ctx, 'ctx, R> Named for TempRef<'str, 'ctx, R>
202where
203 R: QCodeView<'ctx, 'str>,
204{
205 fn name(&self) -> Option<&str> {
206 TempRef::name(*self)
207 }
208}
209
210impl<'str: 'ctx, 'ctx, R> Value<'str, 'ctx> for TempRef<'str, 'ctx, R>
211where
212 R: QCodeView<'ctx, 'str>,
213{
214 fn id(&self) -> ValueId {
215 ValueId::Temp(self.id)
216 }
217
218 fn size(&self) -> usize {
219 TempRef::size(*self)
220 }
221}