1use 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 Void, Null, True, False, #[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), Float(f64), #[cfg_attr(feature = "serde", serde(
43 untagged, serialize_with = "serialize_object",
45 deserialize_with = "deserialize_object"
46 ))]
47 Object(BoxedObject), }
49
50impl Value {
51 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 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 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 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 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#[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#[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#[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}