use std::ops::Deref;
use arcstr::ArcStr;
use serde::{Deserialize, Serialize};
use crate::{model::{DataRef, Graph, NodeRef, SId}, runtime::{Error, Type, Val, ValRef}};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Variable {
pub val: ValRef<Val>,
pub mutable: bool,
pub vtype: Option<Type>,
}
impl Variable {
pub fn new(graph: &Graph, mutable: bool, val: Val, typed: bool) -> Self {
let mut var = Self {
mutable,
val: ValRef::new(val),
vtype: None,
};
if typed {
var.vtype = Some(var.spec_type(graph));
}
var
}
pub fn val(val: Val) -> Self {
Self {
mutable: true,
val: ValRef::new(val),
vtype: None,
}
}
pub fn refval(val: ValRef<Val>) -> Self {
Self {
mutable: true,
val,
vtype: None,
}
}
pub fn by_ref(&self) -> bool {
self.val.1
}
pub fn set(&mut self, var: &Variable, graph: &mut Graph, context: Option<NodeRef>) -> Result<(), Error> {
if self.mutable {
if var.by_ref() {
self.val = var.val.clone();
if let Some(vtype) = &self.vtype {
if vtype != &var.spec_type(graph) {
if let Err(error) = self.val.write().cast(vtype, graph, context) {
return Err(error);
}
}
} else {
self.vtype = var.vtype.clone();
}
return Ok(());
}
let mut val = var.val.read().clone();
if let Some(vtype) = &self.vtype {
if vtype != &val.spec_type(graph) {
if let Err(error) = val.cast(vtype, graph, context) {
return Err(error);
}
}
}
if self.value_type() && !self.by_ref() {
self.val = ValRef::new(val);
} else {
*self.val.write() = val;
}
Ok(())
} else {
Err(Error::AssignConst)
}
}
pub fn stack_var(&self, by_ref: bool) -> Self {
let mut clone = self.clone();
clone.val = self.val.duplicate(by_ref);
clone
}
#[inline]
pub fn get(&self) -> Val {
self.val.read().clone()
}
#[inline]
pub fn try_obj(&self) -> Option<NodeRef> {
self.val.read().try_obj()
}
#[inline]
pub fn try_data_or_func(&self) -> Option<DataRef> {
self.val.read().try_data_or_func()
}
#[inline]
pub fn try_func(&self) -> Option<DataRef> {
self.val.read().try_func()
}
#[inline]
pub fn try_promise(&self) -> Option<(SId, Type)> {
self.val.read().try_promise()
}
#[inline]
pub fn value_type(&self) -> bool {
self.val.read().val_type()
}
#[inline]
pub fn cast(&self, target: &Type, graph: &mut Graph, context: Option<NodeRef>) -> Result<(), Error> {
self.val.write().cast(target, graph, context)
}
#[inline]
pub fn truthy(&self) -> bool {
self.val.read().truthy()
}
#[inline]
pub fn null(&self) -> bool {
self.val.read().null()
}
#[inline]
pub fn dangling_obj(&self, graph: &Graph) -> bool {
if let Some(obj) = self.try_obj() {
!obj.node_exists(graph)
} else {
false
}
}
#[inline]
pub fn is_data_ref(&self, data: &DataRef) -> bool {
self.val.read().is_data_ref(data)
}
#[inline]
pub fn gen_type(&self) -> Type {
self.val.read().gen_type()
}
#[inline]
pub fn spec_type(&self, graph: &Graph) -> Type {
self.val.read().spec_type(graph)
}
#[inline]
pub fn instance_of(&self, other: &Self, graph: &Graph) -> Result<bool, Error> {
if let Some(oref) = other.try_obj() {
return self.val.read().instance_of(&oref, graph);
}
Ok(false)
}
#[inline]
pub fn lib_name(&self, graph: &Graph) -> ArcStr {
self.val.read().lib_name(graph)
}
#[inline]
pub fn drop_data(self, graph: &mut Graph) {
self.val.read().drop_data(graph);
}
pub fn gt(&self, rhs: &Self, graph: &Graph) -> Result<Self, Error> {
match self.val.read().gt(rhs.val.read().deref(), graph) {
Ok(val) => {
Ok(Self::val(val))
},
Err(e) => Err(e)
}
}
pub fn lt(&self, rhs: &Self, graph: &Graph) -> Result<Self, Error> {
match self.val.read().lt(rhs.val.read().deref(), graph) {
Ok(val) => {
Ok(Self::val(val))
},
Err(e) => Err(e)
}
}
pub fn gte(&self, rhs: &Self, graph: &Graph) -> Result<Self, Error> {
match self.val.read().gte(rhs.val.read().deref(), graph) {
Ok(val) => {
Ok(Self::val(val))
},
Err(e) => Err(e)
}
}
pub fn lte(&self, rhs: &Self, graph: &Graph) -> Result<Self, Error> {
match self.val.read().lte(rhs.val.read().deref(), graph) {
Ok(val) => {
Ok(Self::val(val))
},
Err(e) => Err(e)
}
}
pub fn equal(&self, rhs: &Self) -> Result<Self, Error> {
match self.val.read().equal(rhs.val.read().deref()) {
Ok(val) => {
Ok(Self::val(val))
},
Err(e) => Err(e)
}
}
pub fn not_equal(&self, rhs: &Self) -> Result<Self, Error> {
match self.val.read().not_equal(rhs.val.read().deref()) {
Ok(val) => {
Ok(Self::val(val))
},
Err(e) => Err(e)
}
}
pub fn deep_copy(&self, graph: &mut Graph, context: Option<NodeRef>) -> Self {
let mut clone = self.clone();
let copy = self.val.read().deep_copy(graph, context);
clone.val = ValRef::new(copy);
clone
}
#[inline]
pub fn add(&self, rhs: Self, graph: &mut Graph) -> Result<(), Error> {
self.val.write().add(rhs.val.read().clone(), graph)?;
Ok(())
}
#[inline]
pub fn sub(&self, rhs: Self, graph: &mut Graph) -> Result<(), Error> {
self.val.write().sub(rhs.val.read().clone(), graph)?;
Ok(())
}
#[inline]
pub fn mul(&self, rhs: Self, graph: &mut Graph) -> Result<(), Error> {
self.val.write().mul(rhs.val.read().clone(), graph)?;
Ok(())
}
#[inline]
pub fn div(&self, rhs: Self, graph: &mut Graph) -> Result<(), Error> {
self.val.write().div(rhs.val.read().clone(), graph)?;
Ok(())
}
#[inline]
pub fn rem(&self, rhs: Self, graph: &mut Graph) -> Result<(), Error> {
self.val.write().rem(rhs.val.read().clone(), graph)?;
Ok(())
}
#[inline]
pub fn bit_and(&self, rhs: Self) -> Result<(), Error> {
self.val.write().bit_and(rhs.val.read().clone())?;
Ok(())
}
#[inline]
pub fn bit_or(&self, rhs: Self) -> Result<(), Error> {
self.val.write().bit_or(rhs.val.read().clone())?;
Ok(())
}
#[inline]
pub fn bit_xor(&self, rhs: Self) -> Result<(), Error> {
self.val.write().bit_xor(rhs.val.read().clone())?;
Ok(())
}
#[inline]
pub fn bit_shl(&self, rhs: Self) -> Result<(), Error> {
self.val.write().bit_shl(rhs.val.read().clone())?;
Ok(())
}
#[inline]
pub fn bit_shr(&self, rhs: Self) -> Result<(), Error> {
self.val.write().bit_shr(rhs.val.read().clone())?;
Ok(())
}
}