shulkerscript-lang/src/transpile/variables.rs

135 lines
3.1 KiB
Rust

#![expect(unused)]
use std::{
collections::HashMap,
sync::{Arc, OnceLock, RwLock},
};
use strum::EnumIs;
use super::{FunctionData, Transpiler};
#[derive(Debug, Clone, EnumIs)]
pub enum VariableType {
Function {
function_data: FunctionData,
path: OnceLock<String>,
},
FunctionArgument {
index: usize,
},
Scoreboard {
objective: String,
},
ScoreboardValue {
objective: String,
target: String,
},
ScoreboardArray {
objective: String,
targets: Vec<String>,
},
Tag {
tag_name: String,
},
BooleanStorage {
storage_name: String,
path: String,
},
BooleanStorageArray {
storage_name: String,
paths: Vec<String>,
},
}
#[derive(Debug, Default)]
pub struct Scope<'a> {
parent: Option<&'a Arc<Self>>,
variables: RwLock<HashMap<String, Arc<VariableType>>>,
}
impl<'a> Scope<'a> {
pub fn new() -> Arc<Self> {
Arc::new(Self::default())
}
pub fn with_parent(parent: &'a Arc<Self>) -> Arc<Self> {
Arc::new(Self {
parent: Some(parent),
..Default::default()
})
}
pub fn get_variable(&self, name: &str) -> Option<Arc<VariableType>> {
let var = self.variables.read().unwrap().get(name).cloned();
if var.is_some() {
var
} else {
self.parent
.as_ref()
.and_then(|parent| parent.get_variable(name))
}
}
pub fn set_variable(&self, name: &str, var: VariableType) {
self.variables
.write()
.unwrap()
.insert(name.to_string(), Arc::new(var));
}
pub fn get_variables(&self) -> &RwLock<HashMap<String, Arc<VariableType>>> {
&self.variables
}
pub fn get_parent(&self) -> Option<Arc<Self>> {
self.parent.cloned()
}
}
impl Transpiler {}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_scope() {
let scope = Scope::new();
scope.set_variable(
"test",
VariableType::Scoreboard {
objective: "test".to_string(),
},
);
if let Some(var) = scope.get_variable("test") {
match var.as_ref() {
VariableType::Scoreboard { objective } => assert_eq!(objective, "test"),
_ => panic!("Incorrect Variable"),
}
} else {
panic!("Variable missing")
}
}
#[test]
fn test_parent() {
let scope = Scope::new();
scope.set_variable(
"test",
VariableType::Scoreboard {
objective: "test".to_string(),
},
);
let child = Scope::with_parent(&scope);
if let Some(var) = child.get_variable("test") {
match var.as_ref() {
VariableType::Scoreboard { objective } => assert_eq!(objective, "test"),
_ => panic!("Incorrect Variable"),
}
} else {
panic!("Variable missing")
}
}
}