use super::BitSize; use crate::intermediate_representation::Variable as IrVariable; use crate::prelude::*; use serde::{Deserialize, Serialize}; #[derive(Serialize, Deserialize, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone)] pub struct Variable { pub name: String, pub type_: Type, pub is_temp: bool, } #[derive(Serialize, Deserialize, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy)] pub enum Type { Immediate(BitSize), Memory { addr_size: BitSize, elem_size: BitSize, }, Unknown, } impl Type { pub fn bitsize(&self) -> Result<BitSize, Error> { if let Type::Immediate(bitsize) = self { Ok(*bitsize) } else { Err(anyhow!("Not a register type")) } } } impl Variable { pub fn bitsize(&self) -> Result<BitSize, Error> { self.type_.bitsize() } } impl From<Variable> for IrVariable { fn from(var: Variable) -> IrVariable { let size = if let Type::Immediate(bitsize) = var.type_ { bitsize.into() } else { panic!() }; IrVariable { name: var.name, size, is_temp: var.is_temp, } } } #[cfg(test)] mod tests { use super::*; #[test] fn type_deserialization() { let typ = Type::Immediate(64); let string = serde_json::to_string_pretty(&typ).expect("Serialization failed"); println!("{}", &string); let _: Type = serde_json::from_str(&string).expect("Deserialization failed"); let typ = Type::Memory { addr_size: 64, elem_size: 8, }; let string = serde_json::to_string_pretty(&typ).expect("Serialization failed"); println!("{}", &string); let _: Type = serde_json::from_str(&string).expect("Deserialization failed"); let typ = Type::Unknown; let string = serde_json::to_string_pretty(&typ).expect("Serialization failed"); println!("{}", &string); let _: Type = serde_json::from_str(&string).expect("Deserialization failed"); } #[test] fn var_type_from_ocaml() { let json_string = "{\"Memory\":{\"addr_size\":64,\"elem_size\":8}}"; let typ = Type::Memory { addr_size: 64, elem_size: 8, }; assert_eq!(typ, serde_json::from_str(json_string).unwrap()) } #[test] fn var_from_ocaml() { let json_string = "{\"is_temp\":false,\"name\":\"RAX\",\"type_\":{\"Memory\":{\"addr_size\":64,\"elem_size\":8}}}"; let var = Variable { name: "RAX".to_string(), type_: Type::Memory { addr_size: 64, elem_size: 8, }, is_temp: false, }; assert_eq!(var, serde_json::from_str(json_string).unwrap()) } }