tokay/value/
value.rs

1//! Tokay value
2use super::{BoxedObject, Dict, Object, RefValue};
3
4use crate::{Accept, Context, Error, Reject};
5use tokay_macros::tokay_method;
6extern crate self as tokay;
7use num::{ToPrimitive, Zero};
8use num_bigint::BigInt;
9use std::any::Any;
10use std::cmp::Ordering;
11
12#[cfg(feature = "serde")]
13use super::{List, ParseletRef, Str, Token};
14#[cfg(feature = "serde")]
15use crate::builtin::BuiltinRef;
16#[cfg(feature = "serde")]
17use serde::{self, Deserialize, Serialize, ser::SerializeMap};
18
19#[derive(Debug, Clone, PartialEq)]
20#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
21#[cfg_attr(feature = "serde", serde(rename_all = "lowercase"))]
22pub enum Value {
23    // Atomics
24    Void,  // void
25    Null,  // null
26    True,  // true
27    False, // false
28
29    // Numerics
30    #[cfg_attr(
31        feature = "serde",
32        serde(
33            serialize_with = "serialize_int_to_i64",
34            deserialize_with = "deserialize_int_from_i64"
35        )
36    )]
37    Int(BigInt), // int
38
39    Float(f64), // float
40
41    // Objects
42    #[cfg_attr(feature = "serde", serde(
43        untagged,  // https://play.rust-lang.org/?version=stable&mode=debug&edition=2024&gist=bf4276c00019146d787ffb5b710e31fb
44        serialize_with = "serialize_object",
45        deserialize_with = "deserialize_object"
46    ))]
47    Object(BoxedObject), // object
48}
49
50impl Value {
51    /// Return reference to object of type T.
52    pub fn object<T: Any>(&self) -> Option<&T> {
53        if let Self::Object(o) = self {
54            return o.as_any().downcast_ref::<T>();
55        }
56
57        None
58    }
59
60    /// Return mutable reference to object of type T.
61    pub fn object_mut<T: Any>(&mut self) -> Option<&mut T> {
62        if let Self::Object(o) = self {
63            return o.as_any_mut().downcast_mut::<T>();
64        }
65
66        None
67    }
68
69    /// Extract object of type T from Val.
70    pub fn into_object<T: Any>(self) -> Option<T> {
71        if let Self::Object(o) = self {
72            if let Ok(inner) = o.into_any().downcast::<T>() {
73                return Some(*inner);
74            }
75        }
76
77        None
78    }
79
80    // Constructors
81    tokay_method!("bool : @value", Ok(RefValue::from(value.is_true())));
82    tokay_method!("int : @value", {
83        if let Ok(value) = value.to_bigint() {
84            Ok(RefValue::from(value))
85        } else {
86            Err(Error::from(format!(
87                "`{}` cannot be converted to int",
88                value.name()
89            )))
90        }
91    });
92    tokay_method!("float : @value", {
93        if let Ok(value) = value.to_f64() {
94            Ok(RefValue::from(value))
95        } else {
96            Err(Error::from(format!(
97                "`{}` cannot be converted to float",
98                value.name()
99            )))
100        }
101    });
102
103    // float methods
104    tokay_method!(
105        "float_ceil : @float",
106        Ok(RefValue::from(float.to_f64()?.ceil()))
107    );
108    tokay_method!(
109        "float_trunc : @float",
110        Ok(RefValue::from(float.to_f64()?.trunc()))
111    );
112    tokay_method!(
113        "float_fract : @float",
114        Ok(RefValue::from(float.to_f64()?.fract()))
115    );
116}
117
118impl Object for Value {
119    fn severity(&self) -> u8 {
120        match self {
121            Self::Int(_) => 1,
122            Self::Float(_) => 2,
123            Self::Object(o) => o.severity(),
124            _ => 0,
125        }
126    }
127
128    fn name(&self) -> &'static str {
129        match self {
130            Self::Void => "void",
131            Self::Null => "null",
132            Self::True | Self::False => "bool",
133            Self::Int(_) => "int",
134            Self::Float(_) => "float",
135            Self::Object(o) => o.name(),
136        }
137    }
138
139    fn repr(&self) -> String {
140        match self {
141            Self::True => "true".to_string(),
142            Self::False => "false".to_string(),
143            Self::Int(i) => format!("{}", i),
144            Self::Float(f) => {
145                if f.fract() == 0.0 {
146                    format!("{}.0", f)
147                } else {
148                    format!("{}", f)
149                }
150            }
151            Self::Object(o) => o.repr(),
152            _ => self.name().to_string(),
153        }
154    }
155
156    fn is_void(&self) -> bool {
157        matches!(self, Value::Void)
158    }
159
160    fn is_true(&self) -> bool {
161        match self {
162            Self::True => true,
163            Self::Int(i) => !i.is_zero(),
164            Self::Float(f) => *f != 0.0,
165            Self::Object(o) => o.is_true(),
166            _ => false,
167        }
168    }
169
170    fn to_i64(&self) -> Result<i64, String> {
171        match self {
172            Self::True => Ok(1),
173            Self::Int(i) => Ok(i.to_i64().or(Some(0)).unwrap()),
174            Self::Float(f) => Ok(*f as i64),
175            Self::Object(o) => o.to_i64(),
176            _ => Ok(0),
177        }
178    }
179
180    fn to_f64(&self) -> Result<f64, String> {
181        match self {
182            Self::True => Ok(1.0),
183            Self::Int(i) => Ok(i.to_f64().or(Some(0.0)).unwrap()),
184            Self::Float(f) => Ok(*f),
185            Self::Object(o) => o.to_f64(),
186            _ => Ok(0.0),
187        }
188    }
189
190    fn to_usize(&self) -> Result<usize, String> {
191        match self {
192            Self::True => Ok(1),
193            Self::Int(i) => i
194                .to_usize()
195                .ok_or("Cannot convert BigInt to usize".to_string()),
196            Self::Float(f) => Ok(*f as usize),
197            Self::Object(o) => o.to_usize(),
198            _ => Ok(0),
199        }
200    }
201
202    fn to_string(&self) -> String {
203        match self {
204            Self::Void => "".to_string(),
205            Self::Float(f) => format!("{}", f),
206            Self::Object(o) => o.to_string(),
207            _ => self.repr(),
208        }
209    }
210
211    fn to_bigint(&self) -> Result<BigInt, String> {
212        match self {
213            Self::True => Ok(BigInt::from(1)),
214            Self::Int(i) => Ok(i.clone()),
215            Self::Float(f) => Ok(BigInt::from(*f as i64)),
216            Self::Object(o) => o.to_bigint(),
217            _ => Ok(BigInt::from(0)),
218        }
219    }
220
221    fn is_callable(&self, without_arguments: bool) -> bool {
222        if let Self::Object(object) = self {
223            object.is_callable(without_arguments)
224        } else {
225            false
226        }
227    }
228
229    fn is_consuming(&self) -> bool {
230        if let Self::Object(object) = self {
231            object.is_consuming()
232        } else {
233            false
234        }
235    }
236
237    fn is_nullable(&self) -> bool {
238        if let Self::Object(object) = self {
239            object.is_nullable()
240        } else {
241            false
242        }
243    }
244
245    fn is_mutable(&self) -> bool {
246        if let Self::Object(object) = self {
247            object.is_mutable()
248        } else {
249            false
250        }
251    }
252
253    fn is_hashable(&self) -> bool {
254        match self {
255            Self::Void => false,
256            Self::Object(object) => object.is_hashable(),
257            _ => true,
258        }
259    }
260
261    fn call(
262        &self,
263        context: Option<&mut Context>,
264        args: Vec<RefValue>,
265        nargs: Option<Dict>,
266    ) -> Result<Accept, Reject> {
267        if let Value::Object(object) = self {
268            object.call(context, args, nargs)
269        } else {
270            Err(format!("'{}' is not callable", self.name()).into())
271        }
272    }
273
274    fn call_direct(
275        &self,
276        context: &mut Context,
277        args: usize,
278        nargs: Option<Dict>,
279    ) -> Result<Accept, Reject> {
280        if let Value::Object(object) = self {
281            object.call_direct(context, args, nargs)
282        } else {
283            Err(format!("'{}' is not callable", self.name()).into())
284        }
285    }
286}
287
288impl Eq for Value {}
289
290impl PartialOrd for Value {
291    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
292        match (self, other) {
293            (Self::Object(i), Self::Object(j)) => i.partial_cmp(j),
294            (Self::Object(_), _) => Some(Ordering::Greater),
295            (_, Self::Object(_)) => Some(Ordering::Less),
296
297            (Self::Float(i), j) => i.partial_cmp(&j.to_f64().ok()?),
298            (i, Self::Float(j)) => i.to_f64().ok()?.partial_cmp(j),
299
300            (Self::Int(i), j) => i.partial_cmp(&j.to_bigint().ok()?),
301            (i, j) => i.to_bigint().ok()?.partial_cmp(&j.to_bigint().ok()?),
302        }
303    }
304}
305
306impl Ord for Value {
307    fn cmp(&self, other: &Self) -> Ordering {
308        match self.partial_cmp(other) {
309            Some(ordering) => ordering,
310            None => self.id().cmp(&other.id()),
311        }
312    }
313}
314
315// Serialization for Int
316#[cfg(feature = "serde")]
317fn serialize_int_to_i64<S>(value: &BigInt, serializer: S) -> Result<S::Ok, S::Error>
318where
319    S: serde::Serializer,
320{
321    let i = value
322        .to_i64()
323        .ok_or_else(|| serde::ser::Error::custom("BigInt too big"))?;
324    i.serialize(serializer)
325}
326
327#[cfg(feature = "serde")]
328fn deserialize_int_from_i64<'de, D>(deserializer: D) -> Result<BigInt, D::Error>
329where
330    D: serde::Deserializer<'de>,
331{
332    Ok(BigInt::from(i64::deserialize(deserializer)?))
333}
334
335// Serialization for Object
336#[cfg(feature = "serde")]
337fn serialize_object<S>(value: &BoxedObject, serializer: S) -> Result<S::Ok, S::Error>
338where
339    S: serde::Serializer,
340{
341    macro_rules! downcast_serializer_to_type {
342        () => {
343            unimplemented!("Serializer for '{}' not specified", value.name())
344        };
345
346        ($type:ty $(, $rest:ty)*) => {
347            if let Some(object) = value.as_any().downcast_ref::<$type>() {
348                let mut map = serializer.serialize_map(Some(1))?;
349                map.serialize_entry(object.name(), object)?;
350                map.end()
351            }
352            else {
353                downcast_serializer_to_type!($($rest),*)
354            }
355        };
356    }
357
358    downcast_serializer_to_type!(Str, List, Dict, ParseletRef, BuiltinRef, Token)
359}
360
361// Deserialization for Object
362#[cfg(feature = "serde")]
363fn deserialize_object<'de, D>(deserializer: D) -> Result<BoxedObject, D::Error>
364where
365    D: serde::Deserializer<'de>,
366{
367    struct ObjectVisitor;
368
369    impl<'de> serde::de::Visitor<'de> for ObjectVisitor {
370        type Value = BoxedObject;
371
372        fn expecting(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
373            f.write_str("map with one key")
374        }
375
376        fn visit_map<V>(self, mut map: V) -> Result<BoxedObject, V::Error>
377        where
378            V: serde::de::MapAccess<'de>,
379        {
380            match map.next_key::<&str>()? {
381                Some("str") => Ok(Box::new(map.next_value::<Str>()?)),
382                Some("list") => Ok(Box::new(map.next_value::<List>()?)),
383                Some("dict") => Ok(Box::new(map.next_value::<Dict>()?)),
384                Some("parselet") => Ok(Box::new(map.next_value::<ParseletRef>()?)),
385                Some("builtin") => Ok(Box::new(map.next_value::<BuiltinRef>()?)),
386                Some("token") => Ok(Box::new(map.next_value::<Token>()?)),
387                Some(k) => Err(serde::de::Error::unknown_field(
388                    k,
389                    &["str", "list", "dict", "parselet", "builtin", "token"],
390                )),
391                None => Err(serde::de::Error::custom("expected a single-key map")),
392            }
393        }
394    }
395
396    deserializer.deserialize_map(ObjectVisitor)
397}
398
399impl From<bool> for RefValue {
400    fn from(value: bool) -> Self {
401        RefValue::from(if value { Value::True } else { Value::False })
402    }
403}
404
405impl From<BigInt> for RefValue {
406    fn from(int: BigInt) -> Self {
407        RefValue::from(Value::Int(int))
408    }
409}
410
411impl From<i64> for RefValue {
412    fn from(int: i64) -> Self {
413        RefValue::from(Value::Int(BigInt::from(int)))
414    }
415}
416
417impl From<u64> for RefValue {
418    fn from(int: u64) -> Self {
419        RefValue::from(Value::Int(BigInt::from(int)))
420    }
421}
422
423impl From<i32> for RefValue {
424    fn from(int: i32) -> Self {
425        RefValue::from(Value::Int(BigInt::from(int)))
426    }
427}
428
429impl From<u32> for RefValue {
430    fn from(int: u32) -> Self {
431        RefValue::from(Value::Int(BigInt::from(int)))
432    }
433}
434
435impl From<usize> for RefValue {
436    fn from(addr: usize) -> Self {
437        RefValue::from(Value::Int(BigInt::from(addr)))
438    }
439}
440
441impl From<f64> for RefValue {
442    fn from(float: f64) -> Self {
443        RefValue::from(Value::Float(float))
444    }
445}
446
447impl From<f32> for RefValue {
448    fn from(float: f32) -> Self {
449        RefValue::from(float as f64)
450    }
451}