Skip to main content

rib/
variable_id.rs

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    // Default variable_id could global, but as soon as type inference
91    // identifies them to be local it gets converted to a local with an id
92    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    // A local variable can be directly formed during parsing itself.
101    // For example: all identifiers in the LHS of a pattern-match-arm
102    // don't have a local definition of the variable, yet they are considered to be local
103    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, // Every match arm across the program is identified by a non-sharing index value. Within a match arm the identifier names cannot be reused
136}
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);