1use serde::{Deserialize, Serialize};
2use std::fmt::Display;
3
4#[derive(Hash, Eq, Debug, Clone, PartialEq, Ord, PartialOrd, Serialize, Deserialize)]
5pub enum VariableId {
6 Global(String),
7 Local(String, Option<Id>),
8 MatchIdentifier(MatchIdentifier),
9 ListComprehension(ListComprehensionIdentifier),
10 ListReduce(ListAggregationIdentifier),
11}
12
13impl VariableId {
14 pub fn as_instance_variable(&self) -> VariableId {
15 let variable_string = match self {
16 VariableId::Global(name) => name.clone(),
17 VariableId::Local(name, identifier) => {
18 if let Some(id) = identifier {
19 format!("{}-{}", name, id.0)
20 } else {
21 name.clone()
22 }
23 }
24 VariableId::MatchIdentifier(m) => format!("{}-{}", m.name, m.match_arm_index),
25 VariableId::ListComprehension(l) => l.name.clone(),
26 VariableId::ListReduce(r) => r.name.clone(),
27 };
28
29 VariableId::global(format!("__instance_{variable_string}"))
30 }
31 pub fn list_comprehension_identifier(name: impl AsRef<str>) -> VariableId {
32 VariableId::ListComprehension(ListComprehensionIdentifier {
33 name: name.as_ref().to_string(),
34 })
35 }
36
37 pub fn list_reduce_identifier(name: impl AsRef<str>) -> VariableId {
38 VariableId::ListReduce(ListAggregationIdentifier {
39 name: name.as_ref().to_string(),
40 })
41 }
42
43 pub fn match_identifier(name: String, match_arm_index: usize) -> VariableId {
44 VariableId::MatchIdentifier(MatchIdentifier {
45 name,
46 match_arm_index,
47 })
48 }
49
50 pub fn name(&self) -> String {
51 match self {
52 VariableId::Global(name) => name.clone(),
53 VariableId::Local(name, _) => name.clone(),
54 VariableId::MatchIdentifier(m) => m.name.clone(),
55 VariableId::ListComprehension(l) => l.name.clone(),
56 VariableId::ListReduce(r) => r.name.clone(),
57 }
58 }
59
60 pub fn is_global(&self) -> bool {
61 match self {
62 VariableId::Global(_) => true,
63 VariableId::Local(_, _) => false,
64 VariableId::MatchIdentifier(_) => false,
65 VariableId::ListComprehension(_) => false,
66 VariableId::ListReduce(_) => false,
67 }
68 }
69
70 pub fn is_local(&self) -> bool {
71 match self {
72 VariableId::Global(_) => false,
73 VariableId::Local(_, _) => true,
74 VariableId::MatchIdentifier(_) => false,
75 VariableId::ListComprehension(_) => false,
76 VariableId::ListReduce(_) => false,
77 }
78 }
79
80 pub fn is_match_binding(&self) -> bool {
81 match self {
82 VariableId::Global(_) => false,
83 VariableId::Local(_, _) => false,
84 VariableId::MatchIdentifier(_) => true,
85 VariableId::ListComprehension(_) => false,
86 VariableId::ListReduce(_) => false,
87 }
88 }
89
90 pub fn global(variable_name: String) -> VariableId {
93 VariableId::Global(variable_name)
94 }
95
96 pub fn local(variable_name: &str, id: u32) -> VariableId {
97 VariableId::Local(variable_name.to_string(), Some(Id(id)))
98 }
99
100 pub fn local_with_no_id(name: &str) -> VariableId {
104 VariableId::Local(name.to_string(), None)
105 }
106
107 pub fn increment_local_variable_id(&mut self) -> VariableId {
108 match self {
109 VariableId::Global(name) => VariableId::Local(name.clone(), Some(Id(0))),
110 VariableId::Local(name, id) => {
111 let new_id = id.clone().map_or(Some(Id(0)), |x| Some(Id(x.0 + 1)));
112 *id = new_id.clone();
113 VariableId::Local(name.to_string(), new_id)
114 }
115 VariableId::MatchIdentifier(m) => VariableId::MatchIdentifier(m.clone()),
116 VariableId::ListComprehension(l) => VariableId::ListComprehension(l.clone()),
117 VariableId::ListReduce(l) => VariableId::ListReduce(l.clone()),
118 }
119 }
120}
121
122#[derive(Hash, Eq, Debug, Clone, PartialEq, Serialize, Deserialize, Ord, PartialOrd)]
123pub struct ListComprehensionIdentifier {
124 pub name: String,
125}
126
127#[derive(Hash, Eq, Debug, Clone, PartialEq, Serialize, Deserialize, Ord, PartialOrd)]
128pub struct ListAggregationIdentifier {
129 pub name: String,
130}
131
132#[derive(Hash, Eq, Debug, Clone, PartialEq, Serialize, Deserialize, Ord, PartialOrd)]
133pub struct MatchIdentifier {
134 pub name: String,
135 pub match_arm_index: usize, }
137
138impl MatchIdentifier {
139 pub fn new(name: String, match_arm_index: usize) -> MatchIdentifier {
140 MatchIdentifier {
141 name,
142 match_arm_index,
143 }
144 }
145}
146
147impl Display for VariableId {
148 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
149 match self {
150 VariableId::Global(name) => write!(f, "{name}"),
151 VariableId::Local(name, _) => write!(f, "{name}"),
152 VariableId::MatchIdentifier(m) => write!(f, "{}", m.name),
153 VariableId::ListComprehension(l) => write!(f, "{}", l.name),
154 VariableId::ListReduce(r) => write!(f, "{}", r.name),
155 }
156 }
157}
158#[derive(Hash, Eq, Debug, Clone, PartialEq, Serialize, Deserialize, Ord, PartialOrd)]
159pub struct Id(pub(crate) u32);