use crate::ir::*; use serde::{Deserialize, Serialize}; use std::fmt; #[derive(Clone, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)] pub enum RValue { Value(V), Reference(Reference), } impl RValue { pub fn value(&self) -> Option<&V> { match self { RValue::Value(value) => Some(value), _ => None, } } pub fn reference(&self) -> Option<&Reference> { match self { RValue::Reference(reference) => Some(reference), _ => None, } } /// A stack pointer is a `Reference` that wraps a `StackVariable` pub fn stack_pointer(&self) -> Option<&StackVariable> { self.reference() .and_then(|reference| reference.expression().variable()) .and_then(|variable| variable.stack_variable()) } pub fn bits(&self) -> usize { match self { RValue::Value(value) => value.bits(), RValue::Reference(reference) => reference.bits(), } } } impl From> for Expression { fn from(rvalue: RValue) -> Expression { Expression::RValue(Box::new(rvalue)) } } impl From for RValue { fn from(constant: Constant) -> RValue { RValue::Value(constant) } } impl fmt::Display for RValue { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { RValue::Value(value) => fmt::Display::fmt(&value, f), RValue::Reference(reference) => reference.fmt(f), } } }