use serde::{Deserialize, Serialize};
use std::fmt::Display;
#[derive(Hash, Eq, Debug, Clone, PartialEq, Ord, PartialOrd, Serialize, Deserialize)]
pub enum VariableId {
Global(String),
Local(String, Option<Id>),
MatchIdentifier(MatchIdentifier),
ListComprehension(ListComprehensionIdentifier),
ListReduce(ListAggregationIdentifier),
}
impl VariableId {
pub fn as_instance_variable(&self) -> VariableId {
let variable_string = match self {
VariableId::Global(name) => name.clone(),
VariableId::Local(name, identifier) => {
if let Some(id) = identifier {
format!("{}-{}", name, id.0)
} else {
name.clone()
}
}
VariableId::MatchIdentifier(m) => format!("{}-{}", m.name, m.match_arm_index),
VariableId::ListComprehension(l) => l.name.clone(),
VariableId::ListReduce(r) => r.name.clone(),
};
VariableId::global(format!("__instance_{variable_string}"))
}
pub fn list_comprehension_identifier(name: impl AsRef<str>) -> VariableId {
VariableId::ListComprehension(ListComprehensionIdentifier {
name: name.as_ref().to_string(),
})
}
pub fn list_reduce_identifier(name: impl AsRef<str>) -> VariableId {
VariableId::ListReduce(ListAggregationIdentifier {
name: name.as_ref().to_string(),
})
}
pub fn match_identifier(name: String, match_arm_index: usize) -> VariableId {
VariableId::MatchIdentifier(MatchIdentifier {
name,
match_arm_index,
})
}
pub fn name(&self) -> String {
match self {
VariableId::Global(name) => name.clone(),
VariableId::Local(name, _) => name.clone(),
VariableId::MatchIdentifier(m) => m.name.clone(),
VariableId::ListComprehension(l) => l.name.clone(),
VariableId::ListReduce(r) => r.name.clone(),
}
}
pub fn is_global(&self) -> bool {
match self {
VariableId::Global(_) => true,
VariableId::Local(_, _) => false,
VariableId::MatchIdentifier(_) => false,
VariableId::ListComprehension(_) => false,
VariableId::ListReduce(_) => false,
}
}
pub fn is_local(&self) -> bool {
match self {
VariableId::Global(_) => false,
VariableId::Local(_, _) => true,
VariableId::MatchIdentifier(_) => false,
VariableId::ListComprehension(_) => false,
VariableId::ListReduce(_) => false,
}
}
pub fn is_match_binding(&self) -> bool {
match self {
VariableId::Global(_) => false,
VariableId::Local(_, _) => false,
VariableId::MatchIdentifier(_) => true,
VariableId::ListComprehension(_) => false,
VariableId::ListReduce(_) => false,
}
}
pub fn global(variable_name: String) -> VariableId {
VariableId::Global(variable_name)
}
pub fn local(variable_name: &str, id: u32) -> VariableId {
VariableId::Local(variable_name.to_string(), Some(Id(id)))
}
pub fn local_with_no_id(name: &str) -> VariableId {
VariableId::Local(name.to_string(), None)
}
pub fn increment_local_variable_id(&mut self) -> VariableId {
match self {
VariableId::Global(name) => VariableId::Local(name.clone(), Some(Id(0))),
VariableId::Local(name, id) => {
let new_id = id.clone().map_or(Some(Id(0)), |x| Some(Id(x.0 + 1)));
*id = new_id.clone();
VariableId::Local(name.to_string(), new_id)
}
VariableId::MatchIdentifier(m) => VariableId::MatchIdentifier(m.clone()),
VariableId::ListComprehension(l) => VariableId::ListComprehension(l.clone()),
VariableId::ListReduce(l) => VariableId::ListReduce(l.clone()),
}
}
}
#[derive(Hash, Eq, Debug, Clone, PartialEq, Serialize, Deserialize, Ord, PartialOrd)]
pub struct ListComprehensionIdentifier {
pub name: String,
}
#[derive(Hash, Eq, Debug, Clone, PartialEq, Serialize, Deserialize, Ord, PartialOrd)]
pub struct ListAggregationIdentifier {
pub name: String,
}
#[derive(Hash, Eq, Debug, Clone, PartialEq, Serialize, Deserialize, Ord, PartialOrd)]
pub struct MatchIdentifier {
pub name: String,
pub match_arm_index: usize, }
impl MatchIdentifier {
pub fn new(name: String, match_arm_index: usize) -> MatchIdentifier {
MatchIdentifier {
name,
match_arm_index,
}
}
}
impl Display for VariableId {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
VariableId::Global(name) => write!(f, "{name}"),
VariableId::Local(name, _) => write!(f, "{name}"),
VariableId::MatchIdentifier(m) => write!(f, "{}", m.name),
VariableId::ListComprehension(l) => write!(f, "{}", l.name),
VariableId::ListReduce(r) => write!(f, "{}", r.name),
}
}
}
#[derive(Hash, Eq, Debug, Clone, PartialEq, Serialize, Deserialize, Ord, PartialOrd)]
pub struct Id(pub(crate) u32);