1use crate::gc::{Finalize, Trace};
2use crate::runtime::*;
3use crate::util::*;
4use crate::{
5 collections::*, gc, value_eq, FromRantyArgs, IntoRanty, RantySelectorHandle, TryFromRanty,
6};
7use crate::{lang::Slice, util, RantyFunction, RantyString};
8use cast::*;
9use std::cmp::Ordering;
10use std::error::Error;
11use std::ops::Deref;
12use std::{
13 fmt::{Debug, Display},
14 ops::{Add, Div, Mul, Neg, Not, Rem, Sub},
15};
16
17pub const TYPENAME_STRING: &str = "string";
18pub const TYPENAME_INT: &str = "int";
19pub const TYPENAME_FLOAT: &str = "float";
20pub const TYPENAME_BOOL: &str = "bool";
21pub const TYPENAME_TUPLE: &str = "tuple";
22pub const TYPENAME_LIST: &str = "list";
23pub const TYPENAME_MAP: &str = "map";
24pub const TYPENAME_FUNCTION: &str = "function";
25pub const TYPENAME_SELECTOR: &str = "selector";
26pub const TYPENAME_RANGE: &str = "range";
27pub const TYPENAME_NOTHING: &str = "nothing";
28
29const MAX_DISPLAY_STRING_DEPTH: usize = 4;
30
31macro_rules! impl_error_default {
33 ($t:ty) => {
34 impl Error for $t {
35 fn source(&self) -> Option<&(dyn Error + 'static)> {
36 None
37 }
38
39 fn cause(&self) -> Option<&dyn Error> {
40 self.source()
41 }
42 }
43 };
44}
45
46macro_rules! impl_into_runtime_result {
48 ($src_result_type:ty, $ok_type:ty, $err_type_variant:ident) => {
49 impl IntoRuntimeResult<$ok_type> for $src_result_type {
50 #[inline]
51 fn into_runtime_result(self) -> RuntimeResult<$ok_type> {
52 self.map_err(|err| RuntimeError {
53 error_type: RuntimeErrorType::$err_type_variant(err),
54 description: None,
55 stack_trace: None,
56 })
57 }
58 }
59 };
60}
61
62pub type ValueResult<T> = Result<T, ValueError>;
64pub type ValueIndexResult = Result<RantyValue, IndexError>;
66pub type ValueKeyResult = Result<RantyValue, KeyError>;
68pub type ValueIndexSetResult = Result<(), IndexError>;
70pub type ValueKeySetResult = Result<(), KeyError>;
72pub type ValueSliceResult = Result<RantyValue, SliceError>;
74pub type ValueSliceSetResult = Result<(), SliceError>;
76
77pub type RantyFunctionHandle = gc::Cc<RantyFunction>;
79
80pub struct RantyNothing;
82
83#[derive(Copy, Clone, Debug, PartialEq)]
85#[repr(u8)]
86pub enum RantyValueType {
87 String,
89 Float,
91 Int,
93 Boolean,
95 Function,
97 List,
99 Tuple,
101 Map,
103 Selector,
105 Range,
107 Nothing,
109}
110
111impl RantyValueType {
112 pub fn name(&self) -> &'static str {
114 match self {
115 Self::String => TYPENAME_STRING,
116 Self::Float => TYPENAME_FLOAT,
117 Self::Int => TYPENAME_INT,
118 Self::Boolean => TYPENAME_BOOL,
119 Self::Function => TYPENAME_FUNCTION,
120 Self::List => TYPENAME_LIST,
121 Self::Tuple => TYPENAME_TUPLE,
122 Self::Map => TYPENAME_MAP,
123 Self::Selector => TYPENAME_SELECTOR,
124 Self::Range => TYPENAME_RANGE,
125 Self::Nothing => TYPENAME_NOTHING,
126 }
127 }
128}
129
130impl Display for RantyValueType {
131 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
132 write!(f, "{}", self.name())
133 }
134}
135
136#[derive(Clone, Trace, Finalize)]
144#[rust_cc(unsafe_no_drop)]
145pub enum RantyValue {
146 String(RantyString),
148 Float(f64),
150 Int(i64),
152 Boolean(bool),
154 Function(RantyFunctionHandle),
156 List(RantyListHandle),
158 Tuple(RantyTupleHandle),
160 Map(RantyMapHandle),
162 Range(RantyRange),
164 Selector(RantySelectorHandle),
166 Nothing,
168}
169
170impl RantyValue {
171 pub const NAN: Self = Self::Float(f64::NAN);
173 pub const INFINITY: Self = Self::Float(f64::INFINITY);
175 pub const NEG_INFINITY: Self = Self::Float(f64::NEG_INFINITY);
177 pub const MIN_FLOAT: Self = Self::Float(f64::MIN);
179 pub const MAX_FLOAT: Self = Self::Float(f64::MAX);
181 pub const EPSILON: Self = Self::Float(f64::EPSILON);
183 pub const MIN_INT: Self = Self::Int(i64::MIN);
185 pub const MAX_INT: Self = Self::Int(i64::MAX);
187
188 #[inline]
190 pub fn is_nothing(&self) -> bool {
191 matches!(self, RantyValue::Nothing)
192 }
193
194 #[inline]
196 pub fn is_nan(&self) -> bool {
197 if let Self::Float(f) = self {
198 f64::is_nan(*f)
199 } else {
200 false
201 }
202 }
203
204 #[inline]
206 pub fn is_callable(&self) -> bool {
207 matches!(self, Self::Function(..))
208 }
209}
210
211#[allow(clippy::len_without_is_empty)]
212impl RantyValue {
213 #[inline]
214 pub fn from_func<P: FromRantyArgs>(func: fn(&mut VM, P) -> Result<(), RuntimeError>) -> Self {
215 Self::Function(gc::alloc(RantyFunction::from_native(func)))
216 }
217
218 #[inline]
219 pub fn from_captured_func<P: FromRantyArgs>(
220 captures: Vec<RantyValue>,
221 func: fn(&mut VM, P, &[RantyValue]) -> Result<(), RuntimeError>,
222 ) -> Self {
223 Self::Function(gc::alloc(RantyFunction::from_captured_native(
224 captures, func,
225 )))
226 }
227
228 #[inline]
238 pub fn to_bool(&self) -> bool {
239 match self {
240 Self::Boolean(b) => *b,
241 Self::String(s) => !s.is_empty(),
242 Self::Float(n) => !n.is_nan() && *n != 0.0,
243 Self::Int(n) => *n != 0,
244 Self::Function(_) => true,
245 Self::List(l) => !l.borrow().is_empty(),
246 Self::Tuple(_) => true,
247 Self::Map(m) => !m.borrow().is_empty(),
248 Self::Range(r) => !r.is_empty(),
249 Self::Selector(_) => true,
250 Self::Nothing => false,
251 }
252 }
253
254 #[inline]
256 pub fn into_bool_value(self) -> Self {
257 Self::Boolean(self.to_bool())
258 }
259
260 #[inline]
262 pub fn into_int_value(self) -> Self {
263 match self {
264 Self::Int(_) => self,
265 Self::Float(n) => Self::Int(n as i64),
266 Self::String(s) => match s.as_str().parse() {
267 Ok(n) => Self::Int(n),
268 Err(_) => Self::Nothing,
269 },
270 Self::Boolean(b) => Self::Int(bi64(b)),
271 _ => Self::Nothing,
272 }
273 }
274
275 #[inline]
277 pub fn into_float_value(self) -> Self {
278 match self {
279 Self::Float(_) => self,
280 Self::Int(n) => Self::Float(n as f64),
281 Self::String(s) => match s.as_str().parse() {
282 Ok(n) => Self::Float(n),
283 Err(_) => Self::Nothing,
284 },
285 Self::Boolean(b) => Self::Float(bf64(b)),
286 _ => Self::Nothing,
287 }
288 }
289
290 #[inline]
292 pub fn into_string_value(self) -> Self {
293 match self {
294 Self::String(_) => self,
295 _ => Self::String(self.to_string().into()),
296 }
297 }
298
299 #[inline]
301 pub fn into_list_value(self) -> Self {
302 Self::List(
303 match self {
304 Self::Tuple(tuple) => tuple.to_ranty_list(),
305 Self::String(s) => s.to_ranty_list(),
306 Self::Range(range) => range.to_ranty_list(),
307 list @ Self::List(_) => return list,
308 _ => return RantyValue::Nothing,
309 }
310 .into_handle(),
311 )
312 }
313
314 #[inline]
316 pub fn into_tuple_value(self) -> Self {
317 Self::Tuple(
318 match self {
319 Self::String(s) => s.to_ranty_tuple(),
320 Self::List(list) => list.borrow().to_ranty_tuple(),
321 Self::Range(range) => range.to_ranty_tuple(),
322 tuple @ RantyValue::Tuple(_) => return tuple,
323 _ => return RantyValue::Nothing,
324 }
325 .into_handle(),
326 )
327 }
328
329 #[inline]
331 pub fn len(&self) -> usize {
332 match self {
333 Self::String(s) => s.len(),
335 Self::List(lst) => lst.borrow().len(),
337 Self::Range(range) => range.len(),
339 Self::Map(map) => map.borrow().raw_len(),
341 Self::Tuple(tuple) => tuple.len(),
343 _ => 1,
345 }
346 }
347
348 #[inline]
350 pub fn is_empty(&self) -> bool {
351 self.len() == 0
352 }
353
354 #[inline]
355 pub fn reversed(&self) -> Self {
356 match self {
357 Self::String(s) => RantyValue::String(s.reversed()),
358 Self::Tuple(tuple) => {
359 RantyValue::Tuple(tuple.iter().rev().collect::<RantyTuple>().into_handle())
360 }
361 Self::List(list) => RantyValue::List(
362 list.borrow()
363 .iter()
364 .rev()
365 .cloned()
366 .collect::<RantyList>()
367 .into_handle(),
368 ),
369 Self::Range(range) => RantyValue::Range(range.reversed()),
370 _ => self.clone(),
371 }
372 }
373
374 #[inline]
376 pub fn shallow_copy(&self) -> Self {
377 match self {
378 Self::List(list) => RantyValue::List(list.cloned()),
379 Self::Map(map) => RantyValue::Map(map.cloned()),
380 Self::Tuple(tuple) => RantyValue::Tuple(tuple.cloned()),
381 Self::Selector(special) => RantyValue::Selector(special.clone()),
382 _ => self.clone(),
383 }
384 }
385
386 #[inline]
388 pub fn get_type(&self) -> RantyValueType {
389 match self {
390 Self::String(_) => RantyValueType::String,
391 Self::Float(_) => RantyValueType::Float,
392 Self::Int(_) => RantyValueType::Int,
393 Self::Boolean(_) => RantyValueType::Boolean,
394 Self::Function(_) => RantyValueType::Function,
395 Self::List(_) => RantyValueType::List,
396 Self::Tuple(_) => RantyValueType::Tuple,
397 Self::Map(_) => RantyValueType::Map,
398 Self::Range(_) => RantyValueType::Range,
399 Self::Selector(_) => RantyValueType::Selector,
400 Self::Nothing => RantyValueType::Nothing,
401 }
402 }
403
404 #[inline]
406 pub fn type_name(&self) -> &'static str {
407 self.get_type().name()
408 }
409
410 #[inline]
411 fn get_uindex(&self, index: i64) -> Option<usize> {
412 let uindex = if index < 0 {
413 self.len() as i64 + index
414 } else {
415 index
416 };
417
418 if uindex < 0 || uindex >= self.len() as i64 {
419 None
420 } else {
421 Some(uindex as usize)
422 }
423 }
424
425 #[inline]
426 fn get_ubound(&self, index: i64) -> Option<usize> {
427 let uindex = if index < 0 {
428 self.len() as i64 + index
429 } else {
430 index
431 };
432
433 if uindex < 0 || uindex > self.len() as i64 {
434 None
435 } else {
436 Some(uindex as usize)
437 }
438 }
439
440 #[inline]
441 fn get_uslice(&self, slice: &Slice) -> Option<(Option<usize>, Option<usize>)> {
442 match slice {
443 Slice::Full => Some((None, None)),
444 Slice::From(i) => Some((Some(self.get_ubound(*i)?), None)),
445 Slice::To(i) => Some((None, Some(self.get_ubound(*i)?))),
446 Slice::Between(l, r) => Some((Some(self.get_ubound(*l)?), Some(self.get_ubound(*r)?))),
447 }
448 }
449
450 pub fn slice_get(&self, slice: &Slice) -> ValueSliceResult {
451 let (slice_from, slice_to) = self.get_uslice(slice).ok_or(SliceError::OutOfRange)?;
452
453 match self {
454 Self::String(s) => Ok(Self::String(
455 s.to_slice(slice_from, slice_to)
456 .ok_or(SliceError::OutOfRange)?,
457 )),
458 Self::Range(range) => Ok(Self::Range(range.sliced(slice_from, slice_to).unwrap())),
459 Self::List(list) => {
460 let list = list.borrow();
461 match (slice_from, slice_to) {
462 (None, None) => Ok(self.shallow_copy()),
463 (None, Some(to)) => Ok(Self::List(
464 (&list[..to])
465 .iter()
466 .cloned()
467 .collect::<RantyList>()
468 .into_handle(),
469 )),
470 (Some(from), None) => Ok(Self::List(
471 (&list[from..])
472 .iter()
473 .cloned()
474 .collect::<RantyList>()
475 .into_handle(),
476 )),
477 (Some(from), Some(to)) => {
478 let (from, to) = util::minmax(from, to);
479 Ok(Self::List(
480 (&list[from..to])
481 .iter()
482 .cloned()
483 .collect::<RantyList>()
484 .into_handle(),
485 ))
486 }
487 }
488 }
489 Self::Tuple(tuple) => match (slice_from, slice_to) {
490 (None, None) => Ok(self.shallow_copy()),
491 (None, Some(to)) => Ok(Self::Tuple(
492 (&tuple[..to])
493 .iter()
494 .cloned()
495 .collect::<RantyTuple>()
496 .into_handle(),
497 )),
498 (Some(from), None) => Ok(Self::Tuple(
499 (&tuple[from..])
500 .iter()
501 .cloned()
502 .collect::<RantyTuple>()
503 .into_handle(),
504 )),
505 (Some(from), Some(to)) => {
506 let (from, to) = util::minmax(from, to);
507 Ok(Self::Tuple(
508 (&tuple[from..to])
509 .iter()
510 .cloned()
511 .collect::<RantyTuple>()
512 .into_handle(),
513 ))
514 }
515 },
516 other => Err(SliceError::CannotSliceType(other.get_type())),
517 }
518 }
519
520 pub fn slice_set(&mut self, slice: &Slice, val: RantyValue) -> ValueSliceSetResult {
521 let (slice_from, slice_to) = self.get_uslice(slice).ok_or(SliceError::OutOfRange)?;
522
523 match (self, &val) {
524 (Self::List(dst_list), Self::List(src_list)) => {
525 let src_list = src_list.borrow();
526 let mut dst_list = dst_list.borrow_mut();
527 let src = src_list.iter().cloned();
528 match (slice_from, slice_to) {
529 (None, None) => {
530 dst_list.splice(.., src);
531 }
532 (None, Some(to)) => {
533 dst_list.splice(..to, src);
534 }
535 (Some(from), None) => {
536 dst_list.splice(from.., src);
537 }
538 (Some(from), Some(to)) => {
539 let (from, to) = util::minmax(from, to);
540 dst_list.splice(from..to, src);
541 }
542 }
543 Ok(())
544 }
545 (Self::List(dst_list), Self::Tuple(src_tuple)) => {
546 let mut dst_list = dst_list.borrow_mut();
547 let src = src_tuple.iter().cloned();
548 match (slice_from, slice_to) {
549 (None, None) => {
550 dst_list.splice(.., src);
551 }
552 (None, Some(to)) => {
553 dst_list.splice(..to, src);
554 }
555 (Some(from), None) => {
556 dst_list.splice(from.., src);
557 }
558 (Some(from), Some(to)) => {
559 let (from, to) = util::minmax(from, to);
560 dst_list.splice(from..to, src);
561 }
562 }
563 Ok(())
564 }
565 (Self::List(_), other) => Err(SliceError::UnsupportedSpliceSource {
566 src: RantyValueType::List,
567 dst: other.get_type(),
568 }),
569 (dst, _src) => Err(SliceError::CannotSetSliceOnType(dst.get_type())),
570 }
571 }
572
573 #[inline]
575 pub fn is_indexable(&self) -> bool {
576 matches!(
577 self,
578 Self::String(_) | Self::List(_) | Self::Range(_) | Self::Tuple(_)
579 )
580 }
581
582 pub fn index_get(&self, index: i64) -> ValueIndexResult {
584 let uindex = self.get_uindex(index).ok_or(IndexError::OutOfRange)?;
585
586 match self {
587 Self::String(s) => {
588 if let Some(s) = s.grapheme_at(uindex) {
589 Ok(Self::String(s))
590 } else {
591 Err(IndexError::OutOfRange)
592 }
593 }
594 Self::List(list) => {
595 let list = list.borrow();
596 if uindex < list.len() {
597 Ok(list[uindex].clone())
598 } else {
599 Err(IndexError::OutOfRange)
600 }
601 }
602 Self::Range(range) => {
603 if let Some(item) = range.get(uindex) {
604 Ok(Self::Int(item))
605 } else {
606 Err(IndexError::OutOfRange)
607 }
608 }
609 Self::Tuple(tuple) => {
610 if uindex < tuple.len() {
611 Ok(tuple[uindex].clone())
612 } else {
613 Err(IndexError::OutOfRange)
614 }
615 }
616 _ => Err(IndexError::CannotIndexType(self.get_type())),
617 }
618 }
619
620 pub fn index_set(&mut self, index: i64, val: RantyValue) -> ValueIndexSetResult {
622 let uindex = self.get_uindex(index).ok_or(IndexError::OutOfRange)?;
623
624 match self {
625 Self::List(list) => {
626 let mut list = list.borrow_mut();
627
628 if uindex < list.len() {
629 list[uindex] = val;
630 Ok(())
631 } else {
632 Err(IndexError::OutOfRange)
633 }
634 }
635 Self::Map(map) => {
636 let mut map = map.borrow_mut();
637 map.raw_set(uindex.to_string().as_str(), val);
638 Ok(())
639 }
640 _ => Err(IndexError::CannotSetIndexOnType(self.get_type())),
641 }
642 }
643
644 pub fn key_get(&self, key: &str) -> ValueKeyResult {
646 match self {
647 Self::Map(map) => {
648 let map = map.borrow();
649 if let Some(val) = map.get(key) {
650 Ok(val.into_owned())
651 } else {
652 Err(KeyError::KeyNotFound(key.to_owned()))
653 }
654 }
655 _ => Err(KeyError::CannotKeyType(self.get_type())),
656 }
657 }
658
659 pub fn key_set(&mut self, key: &str, val: RantyValue) -> ValueKeySetResult {
661 match self {
662 Self::Map(map) => {
663 let mut map = map.borrow_mut();
664 map.raw_set(key, val);
665 Ok(())
666 }
667 _ => Err(KeyError::CannotKeyType(self.get_type())),
668 }
669 }
670}
671
672impl Default for RantyValue {
673 fn default() -> Self {
675 Self::Nothing
676 }
677}
678
679#[derive(Debug)]
681pub enum ValueError {
682 InvalidConversion {
684 from: &'static str,
685 to: &'static str,
686 message: Option<String>,
687 },
688 DivideByZero,
690 Overflow,
692}
693
694impl_error_default!(ValueError);
695
696impl Display for ValueError {
697 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
698 match self {
699 ValueError::InvalidConversion { from, to, message } => {
700 if let Some(message) = message {
701 write!(f, "unable to convert from {} to {}: {}", from, to, message)
702 } else {
703 write!(f, "unable to convert from {} to {}", from, to)
704 }
705 }
706 ValueError::DivideByZero => write!(f, "attempted to divide by zero"),
707 ValueError::Overflow => write!(f, "arithmetic overflow"),
708 }
709 }
710}
711
712impl<T> IntoRuntimeResult<T> for Result<T, ValueError> {
713 #[inline]
714 fn into_runtime_result(self) -> RuntimeResult<T> {
715 self.map_err(|err| RuntimeError {
716 error_type: RuntimeErrorType::ValueError(err),
717 description: None,
718 stack_trace: None,
719 })
720 }
721}
722
723#[derive(Debug)]
725pub enum IndexError {
726 OutOfRange,
728 CannotIndexType(RantyValueType),
730 CannotSetIndexOnType(RantyValueType),
732}
733
734impl_error_default!(IndexError);
735impl_into_runtime_result!(ValueIndexResult, RantyValue, IndexError);
736impl_into_runtime_result!(ValueIndexSetResult, (), IndexError);
737
738impl Display for IndexError {
739 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
740 match self {
741 IndexError::OutOfRange => write!(f, "value index is out of range"),
742 IndexError::CannotIndexType(t) => {
743 write!(f, "cannot read index on value of type '{}'", t)
744 }
745 IndexError::CannotSetIndexOnType(t) => {
746 write!(f, "cannot write index on value of type '{}'", t)
747 }
748 }
749 }
750}
751
752#[derive(Debug)]
754pub enum KeyError {
755 KeyNotFound(String),
757 CannotKeyType(RantyValueType),
759}
760
761impl_error_default!(KeyError);
762impl_into_runtime_result!(ValueKeyResult, RantyValue, KeyError);
763impl_into_runtime_result!(ValueKeySetResult, (), KeyError);
764
765impl Display for KeyError {
766 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
767 match self {
768 KeyError::KeyNotFound(k) => write!(f, "key not found: '{}'", k),
769 KeyError::CannotKeyType(t) => write!(f, "cannot key value of type '{}'", t),
770 }
771 }
772}
773
774#[derive(Debug)]
776pub enum SliceError {
777 OutOfRange,
779 UnsupportedSliceBoundType(RantyValueType),
781 CannotSliceType(RantyValueType),
783 CannotSetSliceOnType(RantyValueType),
785 UnsupportedSpliceSource {
787 src: RantyValueType,
788 dst: RantyValueType,
789 },
790}
791
792impl_error_default!(SliceError);
793impl_into_runtime_result!(ValueSliceResult, RantyValue, SliceError);
794impl_into_runtime_result!(ValueSliceSetResult, (), SliceError);
795
796impl Display for SliceError {
797 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
798 match self {
799 SliceError::OutOfRange => write!(f, "slice is out of range"),
800 SliceError::UnsupportedSliceBoundType(t) => {
801 write!(f, "cannot use '{}' value as slice bound", t)
802 }
803 SliceError::CannotSliceType(t) => write!(f, "cannot slice '{}' value", t),
804 SliceError::CannotSetSliceOnType(t) => write!(f, "cannot set slice on '{}' value", t),
805 SliceError::UnsupportedSpliceSource { src, dst } => {
806 write!(f, "cannot splice {} into {}", dst, src)
807 }
808 }
809 }
810}
811
812#[derive(Debug, Copy, Clone, PartialEq, PartialOrd)]
817pub enum RantyNumber {
818 Int(i64),
820 Float(f64),
822}
823
824impl TryFromRanty for RantyNumber {
825 fn try_from_ranty(val: RantyValue) -> Result<Self, ValueError> {
826 match val {
827 RantyValue::Int(i) => Ok(RantyNumber::Int(i)),
828 RantyValue::Float(f) => Ok(RantyNumber::Float(f)),
829 other => Err(ValueError::InvalidConversion {
830 from: other.type_name(),
831 to: "[number]",
832 message: None,
833 }),
834 }
835 }
836
837 fn is_optional_param_type() -> bool {
838 false
839 }
840}
841
842#[derive(Debug, Clone, PartialEq, PartialOrd)]
846pub struct RantyOrderedCollection(RantyValue);
847
848impl Deref for RantyOrderedCollection {
849 type Target = RantyValue;
850
851 fn deref(&self) -> &Self::Target {
852 &self.0
853 }
854}
855
856impl TryFromRanty for RantyOrderedCollection {
857 fn try_from_ranty(val: RantyValue) -> Result<Self, ValueError> {
858 if val.is_indexable() {
859 Ok(Self(val))
860 } else {
861 Err(ValueError::InvalidConversion {
862 from: val.type_name(),
863 to: "[ordered collection]",
864 message: Some(format!(
865 "type '{}' is not an ordered collection type",
866 val.type_name()
867 )),
868 })
869 }
870 }
871}
872
873impl Debug for RantyValue {
874 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
875 match self {
876 Self::String(s) => write!(f, "{}", s),
877 Self::Float(n) => write!(f, "{}", n),
878 Self::Int(n) => write!(f, "{}", n),
879 Self::Boolean(b) => write!(f, "{}", if *b { "@true" } else { "@false" }),
880 Self::Function(func) => write!(f, "[function({:?})]", func.body),
881 Self::List(l) => write!(f, "[list({})]", l.borrow().len()),
882 Self::Tuple(t) => write!(f, "[tuple({})]", t.len()),
883 Self::Map(m) => write!(f, "[map({})]", m.borrow().raw_len()),
884 Self::Range(range) => write!(f, "{}", range),
885 Self::Selector(special) => write!(f, "[special({:?})]", special),
886 Self::Nothing => write!(f, "[empty]"),
887 }
888 }
889}
890
891fn get_display_string(value: &RantyValue, max_depth: usize) -> String {
892 match value {
893 RantyValue::String(s) => s.to_string(),
894 RantyValue::Float(f) => format!("{}", f),
895 RantyValue::Int(i) => format!("{}", i),
896 RantyValue::Boolean(b) => (if *b { "@true" } else { "@false" }).to_string(),
897 RantyValue::Function(f) => format!("[function({:?})]", f.body),
898 RantyValue::List(list) => {
899 let mut buf = String::new();
900 let mut is_first = true;
901 buf.push_str("(:");
902 if !list.borrow().is_empty() {
903 buf.push(' ');
904 }
905 if max_depth > 0 {
906 for val in list.borrow().iter() {
907 if is_first {
908 is_first = false;
909 } else {
910 buf.push_str("; ");
911 }
912 buf.push_str(&get_display_string(val, max_depth - 1));
913 }
914 } else {
915 buf.push_str("...");
916 }
917 buf.push(')');
918 buf
919 }
920 RantyValue::Tuple(tuple) => {
921 let mut buf = String::new();
922 let mut is_first = true;
923 buf.push('(');
924 if max_depth > 0 {
925 for val in tuple.iter() {
926 if is_first {
927 is_first = false;
928 } else {
929 buf.push_str("; ");
930 }
931 buf.push_str(&get_display_string(val, max_depth - 1));
932 }
933 } else {
934 buf.push_str("...");
935 }
936 if tuple.len() == 1 {
937 buf.push(';');
938 }
939 buf.push(')');
940 buf
941 }
942 RantyValue::Map(map) => {
943 let mut buf = String::new();
944 let mut is_first = true;
945 buf.push_str("(::");
946 if !map.borrow().is_empty() {
947 buf.push(' ');
948 }
949 if max_depth > 0 {
950 let map = map.borrow();
951 for key in map.raw_keys() {
952 let key_string = key.to_string();
953 if let Some(val) = map.raw_get(&key_string) {
954 if is_first {
955 is_first = false;
956 } else {
957 buf.push_str("; ");
958 }
959 buf.push_str(&format!(
960 "{} = {}",
961 key_string,
962 get_display_string(val, max_depth - 1)
963 ));
964 }
965 }
966 } else {
967 buf.push_str("...");
968 }
969 buf.push(')');
970 buf
971 }
972 RantyValue::Selector(_) => "[special]".to_owned(),
973 RantyValue::Range(range) => range.to_string(),
974 RantyValue::Nothing => (if max_depth < MAX_DISPLAY_STRING_DEPTH {
975 "<>"
976 } else {
977 ""
978 })
979 .to_owned(),
980 }
981}
982
983impl Display for RantyValue {
984 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
985 write!(f, "{}", get_display_string(self, MAX_DISPLAY_STRING_DEPTH))
986 }
987}
988
989impl PartialEq for RantyValue {
990 fn eq(&self, other: &Self) -> bool {
991 value_eq::values_equal(self, other)
992 }
993}
994
995impl Eq for RantyValue {}
996
997impl PartialOrd for RantyValue {
998 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
999 match (self, other) {
1000 (Self::Nothing, _) | (_, Self::Nothing) => None,
1001 (Self::Int(a), Self::Int(b)) => a.partial_cmp(b),
1002 (Self::Float(a), Self::Float(b)) => a.partial_cmp(b),
1003 (Self::Float(a), Self::Int(b)) => a.partial_cmp(&(*b as f64)),
1004 (Self::Int(a), Self::Float(b)) => (&(*a as f64)).partial_cmp(b),
1005 (Self::String(a), Self::String(b)) => a.partial_cmp(b),
1006 (a, b) => {
1007 if a == b {
1008 Some(Ordering::Equal)
1009 } else {
1010 None
1011 }
1012 }
1013 }
1014 }
1015}
1016
1017impl Not for RantyValue {
1018 type Output = Self;
1019 fn not(self) -> Self::Output {
1020 RantyValue::Boolean(!self.to_bool())
1021 }
1022}
1023
1024impl Neg for RantyValue {
1025 type Output = Self;
1026 fn neg(self) -> Self::Output {
1027 match self {
1028 Self::Int(a) => Self::Int(a.saturating_neg()),
1029 Self::Float(a) => Self::Float(-a),
1030 Self::Boolean(a) => Self::Int(-bi64(a)),
1031 _ => self,
1032 }
1033 }
1034}
1035
1036impl Add for RantyValue {
1037 type Output = Self;
1038 fn add(self, rhs: Self) -> Self::Output {
1039 match (self, rhs) {
1040 (Self::Nothing, Self::Nothing) => Self::Nothing,
1041 (lhs, Self::Nothing) => lhs,
1042 (Self::Nothing, rhs) => rhs,
1043 (Self::Int(a), Self::Int(b)) => Self::Int(a.saturating_add(b)),
1044 (Self::Int(a), Self::Float(b)) => Self::Float(f64(a) + b),
1045 (Self::Int(a), Self::Boolean(b)) => Self::Int(a.saturating_add(bi64(b))),
1046 (Self::Float(a), Self::Float(b)) => Self::Float(a + b),
1047 (Self::Float(a), Self::Int(b)) => Self::Float(a + f64(b)),
1048 (Self::Float(a), Self::Boolean(b)) => Self::Float(a + bf64(b)),
1049 (Self::String(a), Self::String(b)) => Self::String(a + b),
1050 (Self::String(a), rhs) => Self::String(a + rhs.to_string().into()),
1051 (Self::Boolean(a), Self::Boolean(b)) => Self::Int(bi64(a) + bi64(b)),
1052 (Self::Boolean(a), Self::Int(b)) => Self::Int(bi64(a).saturating_add(b)),
1053 (Self::Boolean(a), Self::Float(b)) => Self::Float(bf64(a) + b),
1054 (Self::Tuple(a), Self::Tuple(b)) => (a + b).into_ranty(),
1055 (Self::Tuple(a), Self::List(b)) => (a + b).into_ranty(),
1056 (Self::List(a), Self::List(b)) => (a + b).into_ranty(),
1057 (Self::List(a), Self::Tuple(b)) => (a + b).into_ranty(),
1058 (Self::Map(a), Self::Map(b)) => {
1059 let mut map = RantyMap::new();
1060 for (k, v) in a.borrow().raw_pairs_internal() {
1061 map.raw_set(k, v.clone());
1062 }
1063 for (k, v) in b.borrow().raw_pairs_internal() {
1064 map.raw_set(k, v.clone());
1065 }
1066 map.into_ranty()
1067 }
1068 (lhs, rhs) => Self::String(RantyString::from(format!("{}{}", lhs, rhs))),
1069 }
1070 }
1071}
1072
1073impl Sub for RantyValue {
1074 type Output = Self;
1075 fn sub(self, rhs: Self) -> Self::Output {
1076 match (self, rhs) {
1077 (Self::Nothing, Self::Nothing) => Self::Nothing,
1078 (lhs, Self::Nothing) => lhs,
1079 (Self::Nothing, rhs) => -rhs,
1080 (Self::Int(a), Self::Int(b)) => Self::Int(a.saturating_sub(b)),
1081 (Self::Int(a), Self::Float(b)) => Self::Float((a as f64) - b),
1082 (Self::Int(a), Self::Boolean(b)) => Self::Int(a - bi64(b)),
1083 (Self::Float(a), Self::Float(b)) => Self::Float(a - b),
1084 (Self::Float(a), Self::Int(b)) => Self::Float(a - (b as f64)),
1085 (Self::Float(a), Self::Boolean(b)) => Self::Float(a - bf64(b)),
1086 (Self::Boolean(a), Self::Boolean(b)) => Self::Int(bi64(a) - bi64(b)),
1087 (Self::Boolean(a), Self::Int(b)) => Self::Int(bi64(a).saturating_sub(b)),
1088 (Self::Boolean(a), Self::Float(b)) => Self::Float(bf64(a) - b),
1089 _ => Self::NAN,
1090 }
1091 }
1092}
1093
1094impl Mul for RantyValue {
1095 type Output = Self;
1096 fn mul(self, rhs: Self) -> Self::Output {
1097 match (self, rhs) {
1098 (Self::Nothing, _) | (_, Self::Nothing) => Self::Nothing,
1099 (Self::Int(a), Self::Int(b)) => Self::Int(a.saturating_mul(b)),
1100 (Self::Int(a), Self::Float(b)) => Self::Float((a as f64) * b),
1101 (Self::Int(a), Self::Boolean(b)) => Self::Int(a * bi64(b)),
1102 (Self::Float(a), Self::Float(b)) => Self::Float(a * b),
1103 (Self::Float(a), Self::Int(b)) => Self::Float(a * (b as f64)),
1104 (Self::Float(a), Self::Boolean(b)) => Self::Float(a * bf64(b)),
1105 (Self::Boolean(a), Self::Boolean(b)) => Self::Int(bi64(a) * bi64(b)),
1106 (Self::Boolean(a), Self::Int(b)) => Self::Int(bi64(a) * b),
1107 (Self::Boolean(a), Self::Float(b)) => Self::Float(bf64(a) * b),
1108 (Self::String(a), Self::Int(b)) => {
1109 Self::String(a.as_str().repeat(clamp(b, 0, i64::MAX) as usize).into())
1110 }
1111 _ => Self::NAN,
1112 }
1113 }
1114}
1115
1116impl Div for RantyValue {
1117 type Output = ValueResult<Self>;
1118 fn div(self, rhs: Self) -> Self::Output {
1119 Ok(match (self, rhs) {
1120 (Self::Nothing, _) | (_, Self::Nothing) => Self::Nothing,
1121 (_, Self::Int(0)) | (_, Self::Boolean(false)) => return Err(ValueError::DivideByZero),
1122 (Self::Int(a), Self::Int(b)) => Self::Int(a / b),
1123 (Self::Int(a), Self::Float(b)) => Self::Float((a as f64) / b),
1124 (Self::Int(a), Self::Boolean(b)) => Self::Int(a / bi64(b)),
1125 (Self::Float(a), Self::Float(b)) => Self::Float(a / b),
1126 (Self::Float(a), Self::Int(b)) => Self::Float(a / (b as f64)),
1127 (Self::Float(a), Self::Boolean(b)) => Self::Float(a / bf64(b)),
1128 (Self::Boolean(a), Self::Boolean(b)) => Self::Int(bi64(a) / bi64(b)),
1129 (Self::Boolean(a), Self::Int(b)) => Self::Int(bi64(a) / b),
1130 (Self::Boolean(a), Self::Float(b)) => Self::Float(bf64(a) / b),
1131 _ => Self::NAN,
1132 })
1133 }
1134}
1135
1136impl Rem for RantyValue {
1137 type Output = ValueResult<Self>;
1138 fn rem(self, rhs: Self) -> Self::Output {
1139 Ok(match (self, rhs) {
1140 (Self::Nothing, _) | (_, Self::Nothing) => Self::Nothing,
1141 (_, Self::Int(0)) | (_, Self::Boolean(false)) => return Err(ValueError::DivideByZero),
1142 (Self::Int(a), Self::Int(b)) => Self::Int(a % b),
1143 (Self::Int(a), Self::Float(b)) => Self::Float((a as f64) % b),
1144 (Self::Int(a), Self::Boolean(b)) => Self::Int(a % bi64(b)),
1145 _ => Self::NAN,
1146 })
1147 }
1148}
1149
1150impl RantyValue {
1151 #[inline]
1153 pub fn pow(self, exponent: Self) -> ValueResult<Self> {
1154 match (self, exponent) {
1155 (Self::Int(lhs), Self::Int(rhs)) => {
1156 if rhs >= 0 {
1157 cast::u32(rhs)
1158 .map_err(|_| ValueError::Overflow)
1159 .and_then(|rhs| lhs.checked_pow(rhs).ok_or(ValueError::Overflow))
1160 .map(Self::Int)
1161 } else {
1162 Ok(Self::Float((lhs as f64).powf(rhs as f64)))
1163 }
1164 }
1165 (Self::Int(lhs), Self::Float(rhs)) => Ok(Self::Float((lhs as f64).powf(rhs))),
1166 (Self::Float(lhs), Self::Int(rhs)) => Ok(Self::Float(lhs.powf(rhs as f64))),
1167 (Self::Float(lhs), Self::Float(rhs)) => Ok(Self::Float(lhs.powf(rhs))),
1168 _ => Ok(Self::Nothing),
1169 }
1170 }
1171
1172 #[inline]
1174 pub fn abs(self) -> ValueResult<Self> {
1175 match self {
1176 Self::Int(i) => i.checked_abs().map(Self::Int).ok_or(ValueError::Overflow),
1177 Self::Float(f) => Ok(Self::Float(f.abs())),
1178 _ => Ok(self),
1179 }
1180 }
1181
1182 #[inline]
1184 pub fn and(self, rhs: RantyValue) -> Self {
1185 let truth_lhs = self.to_bool();
1186 if !truth_lhs {
1187 self
1188 } else {
1189 rhs
1190 }
1191 }
1192
1193 #[inline]
1195 pub fn or(self, rhs: RantyValue) -> Self {
1196 let truth_lhs = self.to_bool();
1197 if truth_lhs {
1198 self
1199 } else {
1200 rhs
1201 }
1202 }
1203
1204 #[inline]
1206 pub fn xor(self, rhs: RantyValue) -> Self {
1207 let truth_lhs = self.to_bool();
1208 let truth_rhs = rhs.to_bool();
1209 RantyValue::Boolean(truth_lhs ^ truth_rhs)
1210 }
1211}