datex_core/values/
value.rs

1use crate::dif::update::{DIFKey, DIFUpdateData};
2use crate::dif::value::DIFValueContainer;
3use crate::libs::core::CoreLibPointerId;
4use crate::references::mutations::DIFUpdateDataOrMemory;
5use crate::references::observers::TransceiverId;
6use crate::references::reference::AccessError;
7use crate::references::type_reference::TypeReference;
8use crate::runtime::execution::ExecutionError;
9use crate::stdlib::boxed::Box;
10use crate::stdlib::format;
11use crate::stdlib::string::String;
12use crate::stdlib::string::ToString;
13use crate::traits::apply::Apply;
14use crate::traits::structural_eq::StructuralEq;
15use crate::traits::value_eq::ValueEq;
16use crate::types::definition::TypeDefinition;
17use crate::values::core_value::CoreValue;
18use crate::values::core_values::callable::{
19    Callable, CallableBody, CallableSignature,
20};
21use crate::values::core_values::integer::typed_integer::TypedInteger;
22use crate::values::value_container::{ValueContainer, ValueError, ValueKey};
23use core::fmt::{Display, Formatter};
24use core::ops::{Add, AddAssign, Deref, Neg, Not, Sub};
25use core::prelude::rust_2024::*;
26use core::result::Result;
27use log::error;
28
29#[derive(Clone, Debug, Eq, PartialEq, Hash)]
30pub struct Value {
31    pub inner: CoreValue,
32    pub actual_type: Box<TypeDefinition>,
33}
34
35/// Two values are structurally equal, if their inner values are structurally equal, regardless
36/// of the actual_type of the values
37impl StructuralEq for Value {
38    fn structural_eq(&self, other: &Self) -> bool {
39        self.inner.structural_eq(&other.inner)
40    }
41}
42
43/// Value equality corresponds to partial equality:
44/// Both type and inner value are the same
45impl ValueEq for Value {
46    fn value_eq(&self, other: &Self) -> bool {
47        self == other
48    }
49}
50
51impl Deref for Value {
52    type Target = CoreValue;
53
54    fn deref(&self) -> &Self::Target {
55        &self.inner
56    }
57}
58
59impl Apply for Value {
60    fn apply(
61        &self,
62        args: &[ValueContainer],
63    ) -> Result<Option<ValueContainer>, ExecutionError> {
64        match self.inner {
65            CoreValue::Callable(ref callable) => callable.apply(args),
66            _ => Err(ExecutionError::InvalidApply),
67        }
68    }
69    fn apply_single(
70        &self,
71        arg: &ValueContainer,
72    ) -> Result<Option<ValueContainer>, ExecutionError> {
73        match self.inner {
74            CoreValue::Callable(ref callable) => callable.apply_single(arg),
75            _ => Err(ExecutionError::InvalidApply),
76        }
77    }
78}
79
80impl<T: Into<CoreValue>> From<T> for Value {
81    fn from(inner: T) -> Self {
82        let inner = inner.into();
83        let new_type = inner.default_type_definition();
84        Value {
85            inner,
86            actual_type: Box::new(new_type),
87        }
88    }
89}
90impl Value {
91    pub fn null() -> Self {
92        CoreValue::Null.into()
93    }
94}
95
96impl Value {
97    pub fn callable(
98        name: Option<String>,
99        signature: CallableSignature,
100        body: CallableBody,
101    ) -> Self {
102        Value {
103            inner: CoreValue::Callable(Callable {
104                name,
105                signature: signature.clone(),
106                body,
107            }),
108            actual_type: Box::new(TypeDefinition::callable(signature)),
109        }
110    }
111
112    pub fn is_type(&self) -> bool {
113        core::matches!(self.inner, CoreValue::Type(_))
114    }
115    pub fn is_null(&self) -> bool {
116        core::matches!(self.inner, CoreValue::Null)
117    }
118    pub fn is_text(&self) -> bool {
119        core::matches!(self.inner, CoreValue::Text(_))
120    }
121    pub fn is_integer_i8(&self) -> bool {
122        core::matches!(
123            &self.inner,
124            CoreValue::TypedInteger(TypedInteger::I8(_))
125        )
126    }
127    pub fn is_bool(&self) -> bool {
128        core::matches!(self.inner, CoreValue::Boolean(_))
129    }
130    pub fn is_map(&self) -> bool {
131        core::matches!(self.inner, CoreValue::Map(_))
132    }
133    pub fn is_list(&self) -> bool {
134        core::matches!(self.inner, CoreValue::List(_))
135    }
136    pub fn actual_type(&self) -> &TypeDefinition {
137        self.actual_type.as_ref()
138    }
139
140    /// Returns true if the current Value's actual type is the same as its default type
141    /// E.g. if the type is integer for an Integer value, or integer/u8 for a typed integer value
142    /// This will return false for an integer value if the actual type is one of the following:
143    /// * an ImplType<integer, x>
144    /// * a new nominal type containing an integer
145    /// TODO #604: this does not match all cases of default types from the point of view of the compiler -
146    /// integer variants (despite bigint) can be distinguished based on the instruction code, but for text variants,
147    /// the variant must be included in the compiler output - so we need to handle theses cases as well.
148    /// Generally speaking, all variants except the few integer variants should never be considered default types.
149    pub fn has_default_type(&self) -> bool {
150        if let TypeDefinition::Reference(type_reference) =
151            self.actual_type.as_ref()
152            && let TypeReference {
153                pointer_address: Some(pointer_address),
154                ..
155            } = &*type_reference.borrow()
156            && let Ok(actual_type_core_ptr_id) =
157                CoreLibPointerId::try_from(pointer_address)
158        {
159            // actual_type has core type pointer id which is equal to the default core type pointer id of self.inner
160            let self_default_type_ptr_id = CoreLibPointerId::from(&self.inner);
161            self_default_type_ptr_id == actual_type_core_ptr_id
162        } else {
163            false
164        }
165    }
166
167    /// Gets a property on the value if applicable (e.g. for map and structs)
168    pub fn try_get_property<'a>(
169        &self,
170        key: impl Into<ValueKey<'a>>,
171    ) -> Result<ValueContainer, AccessError> {
172        match self.inner {
173            CoreValue::Map(ref map) => {
174                // If the value is a map, get the property
175                Ok(map.get(key)?.clone())
176            }
177            CoreValue::List(ref list) => {
178                if let Some(index) = key.into().try_as_index() {
179                    Ok(list.get(index)?.clone())
180                } else {
181                    Err(AccessError::InvalidIndexKey)
182                }
183            }
184            CoreValue::Text(ref text) => {
185                if let Some(index) = key.into().try_as_index() {
186                    let char = text.char_at(index)?;
187                    Ok(ValueContainer::from(char.to_string()))
188                } else {
189                    Err(AccessError::InvalidIndexKey)
190                }
191            }
192            _ => {
193                // If the value is not an map, we cannot get a property
194                Err(AccessError::InvalidOperation(
195                    "Cannot get property".to_string(),
196                ))
197            }
198        }
199    }
200
201    /// Sets a property on the value if applicable (e.g. for maps)
202    pub fn try_set_property<'a>(
203        &mut self,
204        key: impl Into<ValueKey<'a>>,
205        val: ValueContainer,
206    ) -> Result<(), AccessError> {
207        let key = key.into();
208
209        match self.inner {
210            CoreValue::Map(ref mut map) => {
211                // If the value is an map, set the property
212                map.try_set(key, val)?;
213            }
214            CoreValue::List(ref mut list) => {
215                if let Some(index) = key.try_as_index() {
216                    list.set(index, val)
217                        .map_err(|err| AccessError::IndexOutOfBounds(err))?;
218                } else {
219                    return Err(AccessError::InvalidIndexKey);
220                }
221            }
222            CoreValue::Text(ref mut text) => {
223                if let Some(index) = key.try_as_index() {
224                    if let ValueContainer::Value(v) = &val
225                        && let CoreValue::Text(new_char) = &v.inner
226                        && new_char.0.len() == 1
227                    {
228                        let char = new_char.0.chars().next().unwrap_or('\0');
229                        text.set_char_at(index, char).map_err(|err| {
230                            AccessError::IndexOutOfBounds(err)
231                        })?;
232                    } else {
233                        return Err(AccessError::InvalidOperation(
234                            "Can only set char character in text".to_string(),
235                        ));
236                    }
237                } else {
238                    return Err(AccessError::InvalidIndexKey);
239                }
240            }
241            _ => {
242                // If the value is not an map, we cannot set a property
243                return Err(AccessError::InvalidOperation(format!(
244                    "Cannot set property '{}' on non-map value: {:?}",
245                    key, self
246                )));
247            }
248        }
249
250        Ok(())
251    }
252}
253
254impl Add for Value {
255    type Output = Result<Value, ValueError>;
256    fn add(self, rhs: Value) -> Self::Output {
257        Ok((&self.inner + &rhs.inner)?.into())
258    }
259}
260
261impl Add for &Value {
262    type Output = Result<Value, ValueError>;
263    fn add(self, rhs: &Value) -> Self::Output {
264        Value::add(self.clone(), rhs.clone())
265    }
266}
267
268impl Sub for Value {
269    type Output = Result<Value, ValueError>;
270    fn sub(self, rhs: Value) -> Self::Output {
271        Ok((&self.inner - &rhs.inner)?.into())
272    }
273}
274
275impl Sub for &Value {
276    type Output = Result<Value, ValueError>;
277    fn sub(self, rhs: &Value) -> Self::Output {
278        Value::sub(self.clone(), rhs.clone())
279    }
280}
281
282impl Neg for Value {
283    type Output = Result<Value, ValueError>;
284
285    fn neg(self) -> Self::Output {
286        (-self.inner).map(Value::from)
287    }
288}
289
290impl Not for Value {
291    type Output = Option<Value>;
292
293    fn not(self) -> Self::Output {
294        (!self.inner).map(Value::from)
295    }
296}
297
298// TODO #119: crate a TryAddAssign trait etc.
299impl<T> AddAssign<T> for Value
300where
301    Value: From<T>,
302{
303    fn add_assign(&mut self, rhs: T) {
304        let rhs: Value = rhs.into();
305        let res = self.inner.clone() + rhs.inner;
306        if let Ok(res) = res {
307            self.inner = res;
308        } else {
309            error!("Failed to add value: {res:?}");
310        }
311    }
312}
313
314impl Display for Value {
315    fn fmt(&self, f: &mut Formatter) -> core::fmt::Result {
316        core::write!(f, "{}", self.inner)
317    }
318}
319
320impl<T> From<Option<T>> for Value
321where
322    T: Into<Value>,
323{
324    fn from(opt: Option<T>) -> Self {
325        match opt {
326            Some(v) => v.into(),
327            None => Value::null(),
328        }
329    }
330}
331
332#[cfg(test)]
333/// Tests for the Value struct and its methods.
334/// This module contains unit tests for the Value struct, including its methods and operations.
335/// The value is a holder for a combination of a CoreValue representation and its actual type.
336mod tests {
337    use super::*;
338    use crate::libs::core::{get_core_lib_type, get_core_lib_type_reference};
339    use crate::{
340        assert_structural_eq, datex_list,
341        logger::init_logger_debug,
342        values::core_values::{
343            endpoint::Endpoint,
344            integer::{Integer, typed_integer::TypedInteger},
345            list::List,
346        },
347    };
348    use core::str::FromStr;
349    use log::info;
350
351    #[test]
352    fn endpoint() {
353        init_logger_debug();
354        let endpoint = Value::from(Endpoint::from_str("@test").unwrap());
355        assert_eq!(endpoint.to_string(), "@test");
356    }
357
358    #[test]
359    fn new_addition_assignments() {
360        let mut x = Value::from(42i8);
361        let y = Value::from(27i8);
362
363        x += y.clone();
364        assert_eq!(x, Value::from(69i8));
365    }
366
367    #[test]
368    fn new_additions() {
369        let x = Value::from(42i8);
370        let y = Value::from(27i8);
371
372        let z = (x.clone() + y.clone()).unwrap();
373        assert_eq!(z, Value::from(69i8));
374    }
375
376    #[test]
377    fn list() {
378        init_logger_debug();
379        let mut a = List::from(vec![
380            Value::from("42"),
381            Value::from(42),
382            Value::from(true),
383        ]);
384
385        a.push(Value::from(42));
386        a.push(4);
387
388        assert_eq!(a.len(), 5);
389
390        let b = List::from(vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
391        assert_eq!(b.len(), 11);
392
393        let c = datex_list![1, "test", 3, true, false];
394        assert_eq!(c.len(), 5);
395        assert_eq!(c[0], 1.into());
396        assert_eq!(c[1], "test".into());
397        assert_eq!(c[2], 3.into());
398    }
399
400    #[test]
401    fn boolean() {
402        init_logger_debug();
403        let a = Value::from(true);
404        let b = Value::from(false);
405        let c = Value::from(false);
406        assert_ne!(a, b);
407        assert_eq!(b, c);
408
409        let d = (!b.clone()).unwrap();
410        assert_eq!(a, d);
411
412        // We can't add two booleans together, so this should return None
413        let a_plus_b = a.clone() + b.clone();
414        assert!(a_plus_b.is_err());
415    }
416
417    #[test]
418    fn equality_same_type() {
419        init_logger_debug();
420        let a = Value::from(42i8);
421        let b = Value::from(42i8);
422        let c = Value::from(27i8);
423
424        assert_eq!(a, b);
425        assert_ne!(a, c);
426        assert_ne!(b, c);
427
428        info!("{} === {}", a.clone(), b.clone());
429        info!("{} !== {}", a.clone(), c.clone());
430    }
431
432    #[test]
433    fn decimal() {
434        init_logger_debug();
435        let a = Value::from(42.1f32);
436        let b = Value::from(27f32);
437
438        let a_plus_b = (a.clone() + b.clone()).unwrap();
439        assert_eq!(a_plus_b, Value::from(69.1f32));
440        info!("{} + {} = {}", a.clone(), b.clone(), a_plus_b);
441    }
442
443    #[test]
444    fn null() {
445        init_logger_debug();
446
447        let null_value = Value::null();
448        assert_eq!(null_value.to_string(), "null");
449
450        let maybe_value: Option<i8> = None;
451        let null_value = Value::from(maybe_value);
452        assert_eq!(null_value.to_string(), "null");
453        assert!(null_value.is_null());
454    }
455
456    #[test]
457    fn addition() {
458        init_logger_debug();
459        let a = Value::from(42i8);
460        let b = Value::from(27i8);
461
462        let a_plus_b = (a.clone() + b.clone()).unwrap();
463        assert_eq!(a_plus_b, Value::from(69i8));
464        info!("{} + {} = {}", a.clone(), b.clone(), a_plus_b);
465    }
466
467    #[test]
468    fn string_concatenation() {
469        init_logger_debug();
470        let a = Value::from("Hello ");
471        let b = Value::from(42i8);
472
473        assert!(a.is_text());
474        assert!(b.is_integer_i8());
475
476        let a_plus_b = (a.clone() + b.clone()).unwrap();
477        let b_plus_a = (b.clone() + a.clone()).unwrap();
478
479        assert!(a_plus_b.is_text());
480        assert!(b_plus_a.is_text());
481
482        assert_eq!(a_plus_b, Value::from("Hello 42"));
483        assert_eq!(b_plus_a, Value::from("42Hello "));
484
485        info!("{} + {} = {}", a.clone(), b.clone(), a_plus_b);
486        info!("{} + {} = {}", b.clone(), a.clone(), b_plus_a);
487    }
488
489    #[test]
490    fn structural_equality() {
491        let a = Value::from(42_i8);
492        let b = Value::from(42_i32);
493        assert!(a.is_integer_i8());
494
495        assert_structural_eq!(a, b);
496
497        assert_structural_eq!(
498            Value::from(TypedInteger::I8(42)),
499            Value::from(TypedInteger::U32(42)),
500        );
501
502        assert_structural_eq!(
503            Value::from(42_i8),
504            Value::from(Integer::from(42_i8))
505        );
506    }
507
508    #[test]
509    fn default_types() {
510        let val = Value::from(Integer::from(42));
511        assert!(val.has_default_type());
512
513        let val = Value::from(42i8);
514        assert!(val.has_default_type());
515
516        let val = Value {
517            inner: CoreValue::Integer(Integer::from(42)),
518            actual_type: Box::new(TypeDefinition::ImplType(
519                Box::new(get_core_lib_type(CoreLibPointerId::Integer(None))),
520                vec![],
521            )),
522        };
523
524        assert!(!val.has_default_type());
525    }
526}