use bincode::{Decode, Encode};
use serde::{Deserialize, Serialize};
use std::fmt::Display;
#[derive(
Hash, Eq, Debug, Clone, PartialEq, Ord, PartialOrd, Serialize, Deserialize, Encode, Decode,
)]
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, Encode, Decode, Ord, PartialOrd,
)]
pub struct ListComprehensionIdentifier {
pub name: String,
}
#[derive(
Hash, Eq, Debug, Clone, PartialEq, Serialize, Deserialize, Encode, Decode, Ord, PartialOrd,
)]
pub struct ListAggregationIdentifier {
pub name: String,
}
#[derive(
Hash, Eq, Debug, Clone, PartialEq, Serialize, Deserialize, Encode, Decode, 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, Encode, Decode, Ord, PartialOrd,
)]
pub struct Id(pub(crate) u32);
#[cfg(feature = "protobuf")]
mod protobuf {
use crate::{Id, VariableId};
use golem_api_grpc::proto::golem::rib::VariableId as ProtoVariableId;
impl TryFrom<ProtoVariableId> for VariableId {
type Error = String;
fn try_from(value: ProtoVariableId) -> Result<Self, Self::Error> {
let variable_id = value.variable_id.ok_or("Missing variable_id".to_string())?;
match variable_id {
golem_api_grpc::proto::golem::rib::variable_id::VariableId::Global(global) => {
Ok(VariableId::Global(global.name))
}
golem_api_grpc::proto::golem::rib::variable_id::VariableId::Local(local) => Ok(
VariableId::Local(local.name, local.id.map(|x| Id(x as u32))),
),
golem_api_grpc::proto::golem::rib::variable_id::VariableId::MatchIdentifier(
match_identifier,
) => Ok(VariableId::MatchIdentifier(crate::MatchIdentifier {
name: match_identifier.name,
match_arm_index: match_identifier.match_arm_index as usize
})),
golem_api_grpc::proto::golem::rib::variable_id::VariableId::ListComprehensionIdentifier(
list_comprehension,
) => Ok(VariableId::ListComprehension(
crate::ListComprehensionIdentifier {
name: list_comprehension.name,
},
)),
golem_api_grpc::proto::golem::rib::variable_id::VariableId::ListAggregationIdentifier(
list_aggregation,
) => Ok(VariableId::ListReduce(
crate::ListAggregationIdentifier {
name: list_aggregation.name,
},
)),
}
}
}
impl From<VariableId> for ProtoVariableId {
fn from(value: VariableId) -> Self {
match value {
VariableId::Global(name) => ProtoVariableId {
variable_id: Some(
golem_api_grpc::proto::golem::rib::variable_id::VariableId::Global(
golem_api_grpc::proto::golem::rib::Global { name },
),
),
},
VariableId::MatchIdentifier(m) => ProtoVariableId {
variable_id: Some(
golem_api_grpc::proto::golem::rib::variable_id::VariableId::MatchIdentifier(
golem_api_grpc::proto::golem::rib::MatchIdentifier {
name: m.name,
match_arm_index: m.match_arm_index as u32,
},
),
),
},
VariableId::Local(name, id) => ProtoVariableId {
variable_id: Some(
golem_api_grpc::proto::golem::rib::variable_id::VariableId::Local(
golem_api_grpc::proto::golem::rib::Local {
name,
id: id.map(|x| x.0 as u64),
},
),
),
},
VariableId::ListComprehension(l) => ProtoVariableId {
variable_id: Some(
golem_api_grpc::proto::golem::rib::variable_id::VariableId::ListComprehensionIdentifier(
golem_api_grpc::proto::golem::rib::ListComprehensionIdentifier {
name: l.name,
},
),
),
},
VariableId::ListReduce(r) => ProtoVariableId {
variable_id: Some(
golem_api_grpc::proto::golem::rib::variable_id::VariableId::ListAggregationIdentifier(
golem_api_grpc::proto::golem::rib::ListAggregationIdentifier {
name: r.name,
},
),
),
},
}
}
}
}