1use bincode::{Decode, Encode};
16use serde::{Deserialize, Serialize};
17use std::fmt::Display;
18
19#[derive(
20 Hash, Eq, Debug, Clone, PartialEq, Ord, PartialOrd, Serialize, Deserialize, Encode, Decode,
21)]
22pub enum VariableId {
23 Global(String),
24 Local(String, Option<Id>),
25 MatchIdentifier(MatchIdentifier),
26 ListComprehension(ListComprehensionIdentifier),
27 ListReduce(ListAggregationIdentifier),
28}
29
30impl VariableId {
31 pub fn as_instance_variable(&self) -> VariableId {
32 let variable_string = match self {
33 VariableId::Global(name) => name.clone(),
34 VariableId::Local(name, identifier) => {
35 if let Some(id) = identifier {
36 format!("{}-{}", name, id.0)
37 } else {
38 name.clone()
39 }
40 }
41 VariableId::MatchIdentifier(m) => format!("{}-{}", m.name, m.match_arm_index),
42 VariableId::ListComprehension(l) => l.name.clone(),
43 VariableId::ListReduce(r) => r.name.clone(),
44 };
45
46 VariableId::global(format!("__instance_{variable_string}"))
47 }
48 pub fn list_comprehension_identifier(name: impl AsRef<str>) -> VariableId {
49 VariableId::ListComprehension(ListComprehensionIdentifier {
50 name: name.as_ref().to_string(),
51 })
52 }
53
54 pub fn list_reduce_identifier(name: impl AsRef<str>) -> VariableId {
55 VariableId::ListReduce(ListAggregationIdentifier {
56 name: name.as_ref().to_string(),
57 })
58 }
59
60 pub fn match_identifier(name: String, match_arm_index: usize) -> VariableId {
61 VariableId::MatchIdentifier(MatchIdentifier {
62 name,
63 match_arm_index,
64 })
65 }
66
67 pub fn name(&self) -> String {
68 match self {
69 VariableId::Global(name) => name.clone(),
70 VariableId::Local(name, _) => name.clone(),
71 VariableId::MatchIdentifier(m) => m.name.clone(),
72 VariableId::ListComprehension(l) => l.name.clone(),
73 VariableId::ListReduce(r) => r.name.clone(),
74 }
75 }
76
77 pub fn is_global(&self) -> bool {
78 match self {
79 VariableId::Global(_) => true,
80 VariableId::Local(_, _) => false,
81 VariableId::MatchIdentifier(_) => false,
82 VariableId::ListComprehension(_) => false,
83 VariableId::ListReduce(_) => false,
84 }
85 }
86
87 pub fn is_local(&self) -> bool {
88 match self {
89 VariableId::Global(_) => false,
90 VariableId::Local(_, _) => true,
91 VariableId::MatchIdentifier(_) => false,
92 VariableId::ListComprehension(_) => false,
93 VariableId::ListReduce(_) => false,
94 }
95 }
96
97 pub fn is_match_binding(&self) -> bool {
98 match self {
99 VariableId::Global(_) => false,
100 VariableId::Local(_, _) => false,
101 VariableId::MatchIdentifier(_) => true,
102 VariableId::ListComprehension(_) => false,
103 VariableId::ListReduce(_) => false,
104 }
105 }
106
107 pub fn global(variable_name: String) -> VariableId {
110 VariableId::Global(variable_name)
111 }
112
113 pub fn local(variable_name: &str, id: u32) -> VariableId {
114 VariableId::Local(variable_name.to_string(), Some(Id(id)))
115 }
116
117 pub fn local_with_no_id(name: &str) -> VariableId {
121 VariableId::Local(name.to_string(), None)
122 }
123
124 pub fn increment_local_variable_id(&mut self) -> VariableId {
125 match self {
126 VariableId::Global(name) => VariableId::Local(name.clone(), Some(Id(0))),
127 VariableId::Local(name, id) => {
128 let new_id = id.clone().map_or(Some(Id(0)), |x| Some(Id(x.0 + 1)));
129 *id = new_id.clone();
130 VariableId::Local(name.to_string(), new_id)
131 }
132 VariableId::MatchIdentifier(m) => VariableId::MatchIdentifier(m.clone()),
133 VariableId::ListComprehension(l) => VariableId::ListComprehension(l.clone()),
134 VariableId::ListReduce(l) => VariableId::ListReduce(l.clone()),
135 }
136 }
137}
138
139#[derive(
140 Hash, Eq, Debug, Clone, PartialEq, Serialize, Deserialize, Encode, Decode, Ord, PartialOrd,
141)]
142pub struct ListComprehensionIdentifier {
143 pub name: String,
144}
145
146#[derive(
147 Hash, Eq, Debug, Clone, PartialEq, Serialize, Deserialize, Encode, Decode, Ord, PartialOrd,
148)]
149pub struct ListAggregationIdentifier {
150 pub name: String,
151}
152
153#[derive(
154 Hash, Eq, Debug, Clone, PartialEq, Serialize, Deserialize, Encode, Decode, Ord, PartialOrd,
155)]
156pub struct MatchIdentifier {
157 pub name: String,
158 pub match_arm_index: usize, }
160
161impl MatchIdentifier {
162 pub fn new(name: String, match_arm_index: usize) -> MatchIdentifier {
163 MatchIdentifier {
164 name,
165 match_arm_index,
166 }
167 }
168}
169
170impl Display for VariableId {
171 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
172 match self {
173 VariableId::Global(name) => write!(f, "{name}"),
174 VariableId::Local(name, _) => write!(f, "{name}"),
175 VariableId::MatchIdentifier(m) => write!(f, "{}", m.name),
176 VariableId::ListComprehension(l) => write!(f, "{}", l.name),
177 VariableId::ListReduce(r) => write!(f, "{}", r.name),
178 }
179 }
180}
181#[derive(
182 Hash, Eq, Debug, Clone, PartialEq, Serialize, Deserialize, Encode, Decode, Ord, PartialOrd,
183)]
184pub struct Id(pub(crate) u32);
185
186#[cfg(feature = "protobuf")]
187mod protobuf {
188 use crate::{Id, VariableId};
189 use golem_api_grpc::proto::golem::rib::VariableId as ProtoVariableId;
190
191 impl TryFrom<ProtoVariableId> for VariableId {
192 type Error = String;
193
194 fn try_from(value: ProtoVariableId) -> Result<Self, Self::Error> {
195 let variable_id = value.variable_id.ok_or("Missing variable_id".to_string())?;
196
197 match variable_id {
198 golem_api_grpc::proto::golem::rib::variable_id::VariableId::Global(global) => {
199 Ok(VariableId::Global(global.name))
200 }
201 golem_api_grpc::proto::golem::rib::variable_id::VariableId::Local(local) => Ok(
202 VariableId::Local(local.name, local.id.map(|x| Id(x as u32))),
203 ),
204 golem_api_grpc::proto::golem::rib::variable_id::VariableId::MatchIdentifier(
205 match_identifier,
206 ) => Ok(VariableId::MatchIdentifier(crate::MatchIdentifier {
207 name: match_identifier.name,
208 match_arm_index: match_identifier.match_arm_index as usize
209 })),
210 golem_api_grpc::proto::golem::rib::variable_id::VariableId::ListComprehensionIdentifier(
211 list_comprehension,
212 ) => Ok(VariableId::ListComprehension(
213 crate::ListComprehensionIdentifier {
214 name: list_comprehension.name,
215 },
216 )),
217 golem_api_grpc::proto::golem::rib::variable_id::VariableId::ListAggregationIdentifier(
218 list_aggregation,
219 ) => Ok(VariableId::ListReduce(
220 crate::ListAggregationIdentifier {
221 name: list_aggregation.name,
222 },
223 )),
224 }
225 }
226 }
227
228 impl From<VariableId> for ProtoVariableId {
229 fn from(value: VariableId) -> Self {
230 match value {
231 VariableId::Global(name) => ProtoVariableId {
232 variable_id: Some(
233 golem_api_grpc::proto::golem::rib::variable_id::VariableId::Global(
234 golem_api_grpc::proto::golem::rib::Global { name },
235 ),
236 ),
237 },
238 VariableId::MatchIdentifier(m) => ProtoVariableId {
239 variable_id: Some(
240 golem_api_grpc::proto::golem::rib::variable_id::VariableId::MatchIdentifier(
241 golem_api_grpc::proto::golem::rib::MatchIdentifier {
242 name: m.name,
243 match_arm_index: m.match_arm_index as u32,
244 },
245 ),
246 ),
247 },
248 VariableId::Local(name, id) => ProtoVariableId {
249 variable_id: Some(
250 golem_api_grpc::proto::golem::rib::variable_id::VariableId::Local(
251 golem_api_grpc::proto::golem::rib::Local {
252 name,
253 id: id.map(|x| x.0 as u64),
254 },
255 ),
256 ),
257 },
258 VariableId::ListComprehension(l) => ProtoVariableId {
259 variable_id: Some(
260 golem_api_grpc::proto::golem::rib::variable_id::VariableId::ListComprehensionIdentifier(
261 golem_api_grpc::proto::golem::rib::ListComprehensionIdentifier {
262 name: l.name,
263 },
264 ),
265 ),
266 },
267 VariableId::ListReduce(r) => ProtoVariableId {
268 variable_id: Some(
269 golem_api_grpc::proto::golem::rib::variable_id::VariableId::ListAggregationIdentifier(
270 golem_api_grpc::proto::golem::rib::ListAggregationIdentifier {
271 name: r.name,
272 },
273 ),
274 ),
275 },
276 }
277 }
278 }
279}