use super::types::RegisterType;
#[derive(Debug, Clone)]
pub struct RegisterContext {
pub values: Vec<(String, RegisterType)>,
}
impl RegisterContext {
pub fn new() -> Self {
Self { values: Vec::new() }
}
pub fn from_params(params: &[(String, RegisterType)]) -> Self {
Self {
values: params.to_vec(),
}
}
pub fn push(&mut self, ssa_var: String, ty: RegisterType) {
self.values.push((ssa_var, ty));
}
pub fn pop(&mut self) -> Option<(String, RegisterType)> {
self.values.pop()
}
#[cfg_attr(not(test), allow(dead_code))]
pub fn len(&self) -> usize {
self.values.len()
}
pub fn dup(&mut self) {
if let Some((ssa, ty)) = self.values.last().cloned() {
self.values.push((ssa, ty));
}
}
pub fn drop(&mut self) {
self.values.pop();
}
pub fn swap(&mut self) {
let len = self.values.len();
if len >= 2 {
self.values.swap(len - 1, len - 2);
}
}
pub fn over(&mut self) {
let len = self.values.len();
if len >= 2 {
let a = self.values[len - 2].clone();
self.values.push(a);
}
}
pub fn rot(&mut self) {
let len = self.values.len();
if len >= 3 {
let a = self.values.remove(len - 3);
self.values.push(a);
}
}
}
impl Default for RegisterContext {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_register_context_stack_ops() {
let mut ctx = RegisterContext::new();
ctx.push("a".to_string(), RegisterType::I64);
ctx.push("b".to_string(), RegisterType::I64);
assert_eq!(ctx.len(), 2);
ctx.swap();
assert_eq!(ctx.values[0].0, "b");
assert_eq!(ctx.values[1].0, "a");
ctx.dup();
assert_eq!(ctx.len(), 3);
assert_eq!(ctx.values[2].0, "a");
ctx.drop();
assert_eq!(ctx.len(), 2);
}
}