use std::borrow::Cow;
use crate::gml::Instruction;
use crate::gml::instruction::CodeVariable;
use crate::gml::instruction::DataType;
use crate::prelude::GMRef;
use crate::wad::elements::function::GMFunction;
#[derive(Debug, Clone, PartialEq)]
pub enum PushValue {
Int16(i16),
Int32(i32),
Int64(i64),
Double(f64),
Boolean(bool),
String(String),
Function(GMRef<GMFunction>),
Variable(CodeVariable),
}
impl PushValue {
#[must_use]
pub const fn data_type(&self) -> DataType {
match self {
Self::Int16(_) => DataType::Int16,
Self::Int32(_) | Self::Function(_) => DataType::Int32,
Self::Variable(var) if var.is_int32 => DataType::Int32,
Self::Int64(_) => DataType::Int64,
Self::Double(_) => DataType::Double,
Self::Boolean(_) => DataType::Boolean,
Self::String(_) => DataType::String,
Self::Variable(_) => DataType::Variable,
}
}
#[must_use]
pub const fn as_bool(&self) -> Option<bool> {
match self {
&Self::Int16(int) => Some(int > 0),
&Self::Int32(int) => Some(int > 0),
&Self::Int64(int) => Some(int > 0),
&Self::Double(float) => Some(float > 0.5),
&Self::Boolean(bool) => Some(bool),
Self::String(_) | Self::Function(_) | Self::Variable(_) => None,
}
}
}
impl Instruction {
#[must_use]
pub(crate) fn push_value(&'_ self) -> Option<Cow<'_, PushValue>> {
Some(match self {
Self::Push { value } => Cow::Borrowed(value),
Self::PushLocal { variable }
| Self::PushGlobal { variable }
| Self::PushBuiltin { variable } => Cow::Owned(PushValue::Variable(variable.clone())),
&Self::PushImmediate { integer } => Cow::Owned(PushValue::Int16(integer)),
_ => return None,
})
}
}