mech_core/
value.rs

1use crate::*;
2use crate::nodes::Matrix as Mat;
3#[cfg(feature = "matrix")]
4use crate::matrix::Matrix;
5#[cfg(feature = "complex")]
6use crate::types::complex_numbers::C64;
7#[cfg(feature = "rational")]
8use num_rational::Rational64;
9
10#[cfg(feature = "no_std")]
11use core::mem;
12#[cfg(not(feature = "no_std"))]
13use std::mem;
14
15#[cfg(feature = "matrix")]
16use nalgebra::DVector;
17
18macro_rules! impl_as_type {
19  ($target_type:ty) => {
20    paste!{
21      pub fn [<as_ $target_type>](&self) -> Option<Ref<$target_type>> {
22        match self {
23          #[cfg(feature = "u8")]
24          Value::U8(v) => Some(Ref::new(*v.borrow() as $target_type)),
25          #[cfg(feature = "u16")]
26          Value::U16(v) => Some(Ref::new(*v.borrow() as $target_type)),
27          #[cfg(feature = "u32")]
28          Value::U32(v) => Some(Ref::new(*v.borrow() as $target_type)),
29          #[cfg(feature = "u64")]
30          Value::U64(v) => Some(Ref::new(*v.borrow() as $target_type)),
31          #[cfg(feature = "u128")]
32          Value::U128(v) => Some(Ref::new(*v.borrow() as $target_type)),
33          #[cfg(feature = "i8")]
34          Value::I8(v) => Some(Ref::new(*v.borrow() as $target_type)),
35          #[cfg(feature = "i16")]
36          Value::I16(v) => Some(Ref::new(*v.borrow() as $target_type)),
37          #[cfg(feature = "i32")]
38          Value::I32(v) => Some(Ref::new(*v.borrow() as $target_type)),
39          #[cfg(feature = "i64")]
40          Value::I64(v) => Some(Ref::new(*v.borrow() as $target_type)),
41          #[cfg(feature = "i128")]
42          Value::I128(v) => Some(Ref::new(*v.borrow() as $target_type)),
43          #[cfg(feature = "f32")]
44          Value::F32(v) => Some(Ref::new((*v.borrow()).0 as $target_type)),
45          #[cfg(feature = "f64")]
46          Value::F64(v) => Some(Ref::new((*v.borrow()).0 as $target_type)),
47          Value::Id(v) => Some(Ref::new(*v as $target_type)),
48          Value::MutableReference(val) => val.borrow().[<as_ $target_type>](),
49          _ => None,
50        }
51      }
52    }
53  };
54}
55
56// Value Kind
57// ----------------------------------------------------------------------------
58
59#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
60#[derive(Clone, Debug, Eq, PartialEq, Hash)]
61pub enum ValueKind {
62  U8, U16, U32, U64, U128, I8, I16, I32, I64, I128, F32, F64, C64, R64,
63  String, Bool, Id, Index, Empty, Any, 
64  Matrix(Box<ValueKind>,Vec<usize>),  Enum(u64),                  Record(Vec<(String,ValueKind)>),
65  Map(Box<ValueKind>,Box<ValueKind>), Atom(u64),                  Table(Vec<(String,ValueKind)>, usize), 
66  Tuple(Vec<ValueKind>),              Reference(Box<ValueKind>),  Set(Box<ValueKind>, Option<usize>), 
67  Option(Box<ValueKind>),
68}
69
70impl Display for ValueKind {
71  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
72    match self {
73      ValueKind::R64 => write!(f, "r64"),
74      ValueKind::C64 => write!(f, "c64"),
75      ValueKind::U8 => write!(f, "u8"),
76      ValueKind::U16 => write!(f, "u16"),
77      ValueKind::U32 => write!(f, "u32"),
78      ValueKind::U64 => write!(f, "u64"),
79      ValueKind::U128 => write!(f, "u128"),
80      ValueKind::I8 => write!(f, "i8"),
81      ValueKind::I16 => write!(f, "i16"),
82      ValueKind::I32 => write!(f, "i32"),
83      ValueKind::I64 => write!(f, "i64"),
84      ValueKind::I128 => write!(f, "i128"),
85      ValueKind::F32 => write!(f, "f32"),
86      ValueKind::F64 => write!(f, "f64"),
87      ValueKind::String => write!(f, "string"),
88      ValueKind::Bool => write!(f, "bool"),
89      ValueKind::Matrix(x,s) => write!(f, "[{}]:{}", x, s.iter().map(|s| s.to_string()).collect::<Vec<String>>().join(",")),
90      ValueKind::Enum(x) => write!(f, "{}",x),
91      ValueKind::Set(x,el) => write!(f, "{{{}}}{}", x, el.map_or("".to_string(), |e| format!(":{}", e))),
92      ValueKind::Map(x,y) => write!(f, "{{{}:{}}}",x,y),
93      ValueKind::Record(x) => write!(f, "{{{}}}",x.iter().map(|(i,k)| format!("{}<{}>",i.to_string(),k)).collect::<Vec<String>>().join(" ")),
94      ValueKind::Table(x,y) => {
95        let size_str = if y > &0 { format!(":{}", y) } else { "".to_string() };
96        write!(f, "|{}|{}",x.iter().map(|(i,k)| format!("{}<{}>",i.to_string(),k)).collect::<Vec<String>>().join(" "),size_str)
97      }
98      ValueKind::Tuple(x) => write!(f, "({})",x.iter().map(|x| format!("{}",x)).collect::<Vec<String>>().join(",")),
99      ValueKind::Id => write!(f, "id"),
100      ValueKind::Index => write!(f, "ix"),
101      ValueKind::Reference(x) => write!(f, "{}",x),
102      ValueKind::Atom(x) => write!(f, "`{}",x),
103      ValueKind::Empty => write!(f, "_"),
104      ValueKind::Any => write!(f, "*"),
105      ValueKind::Option(x) => write!(f, "{}?", x),
106    }
107  }
108}
109
110impl ValueKind {
111
112  #[cfg(feature = "compiler")]
113  pub fn to_feature_kind(&self) -> FeatureKind {
114    match self {
115      #[cfg(feature = "i8")]
116      ValueKind::I8 => FeatureKind::I8,
117      #[cfg(feature = "i16")]
118      ValueKind::I16 => FeatureKind::I16,
119      #[cfg(feature = "i32")]
120      ValueKind::I32 => FeatureKind::I32,
121      #[cfg(feature = "i64")]
122      ValueKind::I64 => FeatureKind::I64,
123      #[cfg(feature = "i128")]
124      ValueKind::I128 => FeatureKind::I128,
125      #[cfg(feature = "u8")] 
126      ValueKind::U8 => FeatureKind::U8,
127      #[cfg(feature = "u16")]
128      ValueKind::U16 => FeatureKind::U16,
129      #[cfg(feature = "u32")]
130      ValueKind::U32 => FeatureKind::U32,
131      #[cfg(feature = "u64")]
132      ValueKind::U64 => FeatureKind::U64,
133      #[cfg(feature = "u128")]
134      ValueKind::U128 => FeatureKind::U128,
135      #[cfg(feature = "f32")]
136      ValueKind::F32 => FeatureKind::F32, 
137      #[cfg(feature = "f64")]
138      ValueKind::F64 => FeatureKind::F64,
139      #[cfg(feature = "string")]
140      ValueKind::String => FeatureKind::String,
141      #[cfg(feature = "bool")]
142      ValueKind::Bool => FeatureKind::Bool,
143      #[cfg(feature = "table")]
144      ValueKind::Table(_,_) => FeatureKind::Table,
145      #[cfg(feature = "set")]
146      ValueKind::Set(_,_) => FeatureKind::Set,
147      #[cfg(feature = "map")]
148      ValueKind::Map(_,_) => FeatureKind::Map,
149      #[cfg(feature = "record")]
150      ValueKind::Record(_) => FeatureKind::Record,
151      #[cfg(feature = "tuple")] 
152      ValueKind::Tuple(_) => FeatureKind::Tuple,
153      #[cfg(feature = "enum")]
154      ValueKind::Enum(_) => FeatureKind::Enum,
155      #[cfg(feature = "matrix")]
156      ValueKind::Matrix(_,shape) => {
157        match shape[..] {
158          #[cfg(feature = "matrix1")]
159          [1,1] => FeatureKind::Matrix1,
160          #[cfg(feature = "matrix2")]
161          [2,2] => FeatureKind::Matrix2,
162          #[cfg(feature = "matrix3")]
163          [3,3] => FeatureKind::Matrix3,
164          #[cfg(feature = "matrix4")]
165          [4,4] => FeatureKind::Matrix4,
166          #[cfg(feature = "matrix2x3")]
167          [2,3] => FeatureKind::Matrix2x3,
168          #[cfg(feature = "matrix3x2")]
169          [3,2] => FeatureKind::Matrix3x2,
170          #[cfg(feature = "row_vector2")]
171          [1,2] => FeatureKind::RowVector2,
172          #[cfg(feature = "row_vector3")]
173          [1,3] => FeatureKind::RowVector3,
174          #[cfg(feature = "row_vector4")]
175          [1,4] => FeatureKind::RowVector4,
176          #[cfg(feature = "vector2")]
177          [2,1] => FeatureKind::Vector2,
178          #[cfg(feature = "vector3")]
179          [3,1] => FeatureKind::Vector3,
180          #[cfg(feature = "vector4")]
181          [4,1] => FeatureKind::Vector4,
182          #[cfg(feature = "row_vectord")]
183          [1,n] => FeatureKind::RowVectorD,
184          #[cfg(feature = "vectord")]
185          [n,1] => FeatureKind::VectorD,
186          #[cfg(feature = "matrixd")]
187          [n,m] => FeatureKind::MatrixD,
188          _ => panic!("Unsupported matrix shape for feature kind: {}", self),
189        }
190      }
191      #[cfg(feature = "complex")]
192      ValueKind::C64 => FeatureKind::C64,
193      #[cfg(feature = "rational")]
194      ValueKind::R64 => FeatureKind::R64,
195      ValueKind::Atom(_) => FeatureKind::Atom,
196      ValueKind::Index => FeatureKind::Index,
197      _ => panic!("Unsupported feature kind for value kind: {}", self),
198    }
199  }
200
201  pub fn collection_kind(&self) -> Option<ValueKind> {
202    match self {
203      ValueKind::Matrix(x,_) => Some(*x.clone()),
204      ValueKind::Set(x,_) => Some(*x.clone()),
205      _ => None,
206    }
207  }
208
209  pub fn deref_kind(&self) -> ValueKind {
210    match self {
211      ValueKind::Reference(x) => *x.clone(),
212      _ => self.clone(),
213    }
214  }
215
216  pub fn is_convertible_to(&self, other: &ValueKind) -> bool {
217    use ValueKind::*;
218    match (self, other) {
219      // Unsigned widening
220      (U8, U16) | (U8, U32) | (U8, U64) | (U8, U128) |
221      (U16, U32) | (U16, U64) | (U16, U128) |
222      (U32, U64) | (U32, U128) |
223      (U64, U128) => true,
224
225      // Signed widening
226      (I8, I16) | (I8, I32) | (I8, I64) | (I8, I128) |
227      (I16, I32) | (I16, I64) | (I16, I128) |
228      (I32, I64) | (I32, I128) |
229      (I64, I128) => true,
230
231      // Unsigned -> signed widening
232      (U8, I16) | (U8, I32) | (U8, I64) | (U8, I128) |
233      (U16, I32) | (U16, I64) | (U16, I128) |
234      (U32, I64) | (U32, I128) |
235      (U64, I128) => true,
236
237      // Signed -> unsigned widening (runtime safety not enforced here)
238      (I8, U16) | (I8, U32) | (I8, U64) | (I8, U128) |
239      (I16, U32) | (I16, U64) | (I16, U128) |
240      (I32, U64) | (I32, U128) |
241      (I64, U128) => true,
242
243      // Integer -> float
244      (U8, F32) | (U8, F64) |
245      (U16, F32) | (U16, F64) |
246      (U32, F32) | (U32, F64) |
247      (U64, F32) | (U64, F64) |
248      (U128, F32) | (U128, F64) |
249      (I8, F32) | (I8, F64) |
250      (I16, F32) | (I16, F64) |
251      (I32, F32) | (I32, F64) |
252      (I64, F32) | (I64, F64) |
253      (I128, F32) | (I128, F64) => true,
254
255      // Float widening + narrowing
256      (F32, F64) | (F64, F32) => true,
257
258      // Float -> integer (allowed, but lossy)
259      (F32, I8) | (F32, I16) | (F32, I32) | (F32, I64) | (F32, I128) |
260      (F32, U8) | (F32, U16) | (F32, U32) | (F32, U64) | (F32, U128) |
261      (F64, I8) | (F64, I16) | (F64, I32) | (F64, I64) | (F64, I128) |
262      (F64, U8) | (F64, U16) | (F64, U32) | (F64, U64) | (F64, U128) => true,
263
264      // Index conversions (both ways)
265      (Index, U8) | (Index, U16) | (Index, U32) | (Index, U64) | (Index, U128) |
266      (Index, I8) | (Index, I16) | (Index, I32) | (Index, I64) | (Index, I128) |
267      (Index, F32) | (Index, F64) |
268      (U8, Index) | (U16, Index) | (U32, Index) | (U64, Index) | (U128, Index) |
269      (I8, Index) | (I16, Index) | (I32, Index) | (I64, Index) | (I128, Index) => true,
270
271      // Matrix: element type convertible and shape matches
272      (Matrix(box a, ashape), Matrix(box b, bshape)) if ashape.into_iter().product::<usize>() == bshape.into_iter().product::<usize>() && a.is_convertible_to(b) => true,
273
274      // Option conversions
275      (Option(box a), Option(box b)) if a.is_convertible_to(b) => true,
276
277      // Reference conversions
278      (Reference(box a), Reference(box b)) if a.is_convertible_to(b) => true,
279
280      // Tuple conversions (element-wise)
281      (Tuple(a), Tuple(b)) if a.len() == b.len() && a.iter().zip(b.iter()).all(|(x, y)| x.is_convertible_to(y)) => true,
282
283      // Set conversions
284      (Set(box a, _), Set(box b, _)) if a.is_convertible_to(b) => true,
285
286      // Map conversions
287      (Map(box ak, box av), Map(box bk, box bv)) if ak.is_convertible_to(bk) && av.is_convertible_to(bv) => true,
288
289      // Table conversions: allow source to have extra columns
290      (Table(acols, _), Table(bcols, _)) if bcols.iter().all(|(bk, bv)| 
291        acols.iter().any(|(ak, av)| ak == bk && av.is_convertible_to(bv))
292      ) => true,
293
294      // Record conversions: allow source to have extra fields
295      (Record(afields), Record(bfields)) if bfields.iter().all(|(bk, bv)| 
296        afields.iter().any(|(ak, av)| ak == bk && av.is_convertible_to(bv))
297      ) => true,
298
299      // Direct match
300      _ => self == other,
301    }
302  }
303
304  pub fn is_compatible(k1: ValueKind, k2: ValueKind) -> bool {
305    match k1 {
306      ValueKind::Reference(x) => {
307        ValueKind::is_compatible(*x,k2)
308      }
309      ValueKind::Matrix(x,_) => {
310        *x == k2
311      }
312      x => x == k2,
313    }
314  }
315
316  pub fn align(&self) -> usize {
317    // pointer alignment (platform word size) for pointer-like kinds
318    let ptr_align = mem::align_of::<usize>();
319
320    match self {
321      // unsigned integers
322      ValueKind::U8   => 1,
323      ValueKind::U16  => 2,
324      ValueKind::U32  => 4,
325      ValueKind::U64  => 8,
326      ValueKind::U128 => 16,
327
328      // signed integers
329      ValueKind::I8   => 1,
330      ValueKind::I16  => 2,
331      ValueKind::I32  => 4,
332      ValueKind::I64  => 8,
333      ValueKind::I128 => 16,
334
335      // floats
336      ValueKind::F32  => 4,
337      ValueKind::F64  => 8,
338
339      // complex / rational (assume composed of f64 parts)
340      ValueKind::C64 => 8,
341      ValueKind::R64 => 8,
342
343      // small simple payloads
344      ValueKind::Bool => 1,
345      ValueKind::String => 1, // strings are length+bytes; bytes are packed
346      ValueKind::Id | ValueKind::Index => 8, // id/index -> likely machine word (u64)
347      ValueKind::Empty => 1,
348      ValueKind::Any => ptr_align,
349
350      // compound types
351      ValueKind::Matrix(elem_ty, _dims) => {
352        // matrix alignment = alignment of element type
353        elem_ty.align()
354      }
355
356      ValueKind::Enum(_space) => 8, // enum tag stored in u64
357      ValueKind::Atom(_id) => 8,
358
359      ValueKind::Record(fields) => {
360        // record alignment = max alignment of fields (or 1 if empty)
361        fields.iter()
362            .map(|(_, ty)| ty.align())
363            .max()
364            .unwrap_or(1)
365      }
366
367      ValueKind::Map(_, _) => ptr_align,   // typically pointer-based representation
368      ValueKind::Table(cols, _pk) => {
369        // table: use max column alignment or pointer-align if empty
370        cols.iter()
371            .map(|(_, ty)| ty.align())
372            .max()
373            .unwrap_or(ptr_align)
374      }
375
376      ValueKind::Tuple(elems) => {
377        elems.iter().map(|ty| ty.align()).max().unwrap_or(1)
378      }
379
380      ValueKind::Reference(inner) => ptr_align, // references are pointers at runtime
381
382      ValueKind::Set(elem, _) => {
383        // set alignment equals element alignment (or ptr_align fallback)
384        match elem.as_ref() {
385          v => v.align()
386        }
387      }
388      ValueKind::Option(inner) => inner.align(),
389    }
390  }
391}
392
393pub trait AsNaKind {
394  fn as_na_kind() -> String;
395}
396
397macro_rules! impl_as_na_kind {
398  ($type:ty, $kind:expr) => {
399    impl<T> AsNaKind for $type {
400      fn as_na_kind() -> String { $kind.to_string() }
401    }
402  };
403}
404
405#[cfg(feature = "row_vector2")]
406impl_as_na_kind!(RowVector2<T>, "RowVector2");
407#[cfg(feature = "row_vector3")]
408impl_as_na_kind!(RowVector3<T>, "RowVector3");
409#[cfg(feature = "row_vector4")]
410impl_as_na_kind!(RowVector4<T>, "RowVector4");
411#[cfg(feature = "row_vectord")]
412impl_as_na_kind!(RowDVector<T>, "RowDVector");
413#[cfg(feature = "vector2")]
414impl_as_na_kind!(Vector2<T>, "Vector2");
415#[cfg(feature = "vector3")]
416impl_as_na_kind!(Vector3<T>, "Vector3");
417#[cfg(feature = "vector4")]
418impl_as_na_kind!(Vector4<T>, "Vector4");
419#[cfg(feature = "vectord")]
420impl_as_na_kind!(DVector<T>, "DVector");
421#[cfg(feature = "matrix1")]
422impl_as_na_kind!(Matrix1<T>, "Matrix1");
423#[cfg(feature = "matrix2")]
424impl_as_na_kind!(Matrix2<T>, "Matrix2");
425#[cfg(feature = "matrix3")]
426impl_as_na_kind!(Matrix3<T>, "Matrix3");
427#[cfg(feature = "matrix4")]
428impl_as_na_kind!(Matrix4<T>, "Matrix4");
429#[cfg(feature = "matrix2x3")]
430impl_as_na_kind!(Matrix2x3<T>, "Matrix2x3");
431#[cfg(feature = "matrix3x2")]
432impl_as_na_kind!(Matrix3x2<T>, "Matrix3x2");
433#[cfg(feature = "matrixd")]
434impl_as_na_kind!(DMatrix<T>, "DMatrix");
435
436pub trait AsValueKind {
437  fn as_value_kind() -> ValueKind;
438}
439
440macro_rules! impl_as_value_kind {
441  ($type:ty, $value_kind:expr) => {
442    impl AsValueKind for $type {
443      fn as_value_kind() -> ValueKind { $value_kind }
444    }
445  };
446}
447
448impl_as_value_kind!(usize, ValueKind::Index);
449
450#[cfg(feature = "i8")]
451impl_as_value_kind!(i8, ValueKind::I8);
452#[cfg(feature = "i16")]
453impl_as_value_kind!(i16, ValueKind::I16);
454#[cfg(feature = "i32")]
455impl_as_value_kind!(i32, ValueKind::I32);
456#[cfg(feature = "i64")]
457impl_as_value_kind!(i64, ValueKind::I64);
458#[cfg(feature = "i128")]
459impl_as_value_kind!(i128, ValueKind::I128);
460#[cfg(feature = "u8")]
461impl_as_value_kind!(u8, ValueKind::U8);
462#[cfg(feature = "u16")]
463impl_as_value_kind!(u16, ValueKind::U16);
464#[cfg(feature = "u32")]
465impl_as_value_kind!(u32, ValueKind::U32);
466#[cfg(feature = "u64")]
467impl_as_value_kind!(u64, ValueKind::U64);
468#[cfg(feature = "u128")]
469impl_as_value_kind!(u128, ValueKind::U128);
470#[cfg(feature = "f32")]
471impl_as_value_kind!(F32, ValueKind::F32);
472#[cfg(feature = "f64")]
473impl_as_value_kind!(F64, ValueKind::F64);
474#[cfg(feature = "bool")]
475impl_as_value_kind!(bool, ValueKind::Bool);
476#[cfg(feature = "string")]
477impl_as_value_kind!(String, ValueKind::String);
478#[cfg(feature = "rational")]
479impl_as_value_kind!(R64, ValueKind::R64);
480#[cfg(feature = "complex")]
481impl_as_value_kind!(C64, ValueKind::C64);
482
483
484macro_rules! impl_as_value_kind_for_matrix {
485  ($type:ty, $dims:expr) => {
486    impl<T: AsValueKind> AsValueKind for $type {
487      fn as_value_kind() -> ValueKind {
488        ValueKind::Matrix(Box::new(T::as_value_kind()), $dims)
489      }
490    }
491  };
492}
493
494#[cfg(feature = "row_vectord")]
495impl_as_value_kind_for_matrix!(RowDVector<T>, vec![1, 0]);
496#[cfg(feature = "row_vector2")]
497impl_as_value_kind_for_matrix!(RowVector2<T>, vec![1, 2]);
498#[cfg(feature = "row_vector3")]
499impl_as_value_kind_for_matrix!(RowVector3<T>, vec![1, 3]);
500#[cfg(feature = "row_vector4")]
501impl_as_value_kind_for_matrix!(RowVector4<T>, vec![1, 4]);
502#[cfg(feature = "vectord")]
503impl_as_value_kind_for_matrix!(DVector<T>, vec![0, 1]);
504#[cfg(feature = "vector2")]
505impl_as_value_kind_for_matrix!(Vector2<T>, vec![2, 1]);
506#[cfg(feature = "vector3")]
507impl_as_value_kind_for_matrix!(Vector3<T>, vec![3, 1]);
508#[cfg(feature = "vector4")]
509impl_as_value_kind_for_matrix!(Vector4<T>, vec![4, 1]);
510#[cfg(feature = "matrix1")]
511impl_as_value_kind_for_matrix!(Matrix1<T>, vec![1, 1]);
512#[cfg(feature = "matrix2")]
513impl_as_value_kind_for_matrix!(Matrix2<T>, vec![2, 2]);
514#[cfg(feature = "matrix3")]
515impl_as_value_kind_for_matrix!(Matrix3<T>, vec![3, 3]);
516#[cfg(feature = "matrix4")]
517impl_as_value_kind_for_matrix!(Matrix4<T>, vec![4, 4]);
518#[cfg(feature = "matrix2x3")]
519impl_as_value_kind_for_matrix!(Matrix2x3<T>, vec![2, 3]);
520#[cfg(feature = "matrix3x2")]
521impl_as_value_kind_for_matrix!(Matrix3x2<T>, vec![3, 2]);
522#[cfg(feature = "matrixd")]
523impl_as_value_kind_for_matrix!(DMatrix<T>, vec![0, 0]);
524
525impl AsValueKind for Value {
526  fn as_value_kind() -> ValueKind {
527    ValueKind::Any
528  }
529}
530
531
532// Value
533// ----------------------------------------------------------------------------
534
535#[derive(Clone, Debug, PartialEq, Eq)]
536pub enum Value {
537  #[cfg(feature = "u8")]
538  U8(Ref<u8>),
539  #[cfg(feature = "u16")]
540  U16(Ref<u16>),
541  #[cfg(feature = "u32")]
542  U32(Ref<u32>),
543  #[cfg(feature = "u64")]
544  U64(Ref<u64>),
545  #[cfg(feature = "u128")]
546  U128(Ref<u128>),
547  #[cfg(feature = "i8")]
548  I8(Ref<i8>),
549  #[cfg(feature = "i16")]
550  I16(Ref<i16>),
551  #[cfg(feature = "i32")]
552  I32(Ref<i32>),
553  #[cfg(feature = "i64")]
554  I64(Ref<i64>),
555  #[cfg(feature = "i128")]
556  I128(Ref<i128>),
557  #[cfg(feature = "f32")]
558  F32(Ref<F32>),
559  #[cfg(feature = "f64")]
560  F64(Ref<F64>),
561  #[cfg(feature = "string")]
562  String(Ref<String>),
563  #[cfg(feature = "bool")]
564  Bool(Ref<bool>),
565  #[cfg(feature = "atom")]
566  Atom(Ref<MechAtom>),
567  #[cfg(feature = "matrix")]
568  MatrixIndex(Matrix<usize>),
569  #[cfg(all(feature = "matrix", feature = "bool"))]
570  MatrixBool(Matrix<bool>),
571  #[cfg(all(feature = "matrix", feature = "u8"))]
572  MatrixU8(Matrix<u8>),
573  #[cfg(all(feature = "matrix", feature = "u16"))]
574  MatrixU16(Matrix<u16>),
575  #[cfg(all(feature = "matrix", feature = "u32"))]
576  MatrixU32(Matrix<u32>),
577  #[cfg(all(feature = "matrix", feature = "u64"))]
578  MatrixU64(Matrix<u64>),
579  #[cfg(all(feature = "matrix", feature = "u128"))]
580  MatrixU128(Matrix<u128>),
581  #[cfg(all(feature = "matrix", feature = "i8"))]
582  MatrixI8(Matrix<i8>),
583  #[cfg(all(feature = "matrix", feature = "i16"))]
584  MatrixI16(Matrix<i16>),
585  #[cfg(all(feature = "matrix", feature = "i32"))]
586  MatrixI32(Matrix<i32>),
587  #[cfg(all(feature = "matrix", feature = "i64"))]
588  MatrixI64(Matrix<i64>),
589  #[cfg(all(feature = "matrix", feature = "i128"))]
590  MatrixI128(Matrix<i128>),
591  #[cfg(all(feature = "matrix", feature = "f32"))]
592  MatrixF32(Matrix<F32>),
593  #[cfg(all(feature = "matrix", feature = "f64"))]
594  MatrixF64(Matrix<F64>),
595  #[cfg(all(feature = "matrix", feature = "string"))]
596  MatrixString(Matrix<String>),
597  #[cfg(all(feature = "matrix", feature = "rational"))]
598  MatrixR64(Matrix<R64>),
599  #[cfg(all(feature = "matrix", feature = "complex"))]
600  MatrixC64(Matrix<C64>),
601  #[cfg(feature = "matrix")]
602  MatrixValue(Matrix<Value>),
603  #[cfg(feature = "complex")]
604  C64(Ref<C64>),
605  #[cfg(feature = "rational")]
606  R64(Ref<R64>),
607  #[cfg(feature = "set")]
608  Set(Ref<MechSet>),
609  #[cfg(feature = "map")]
610  Map(Ref<MechMap>),
611  #[cfg(feature = "record")]
612  Record(Ref<MechRecord>),
613  #[cfg(feature = "table")]
614  Table(Ref<MechTable>),
615  #[cfg(feature = "tuple")]
616  Tuple(Ref<MechTuple>),
617  #[cfg(feature = "enum")]
618  Enum(Ref<MechEnum>),
619  Id(u64),
620  Index(Ref<usize>),
621  MutableReference(MutableReference),
622  Kind(ValueKind),
623  IndexAll,
624  Empty
625}
626
627impl fmt::Display for Value {
628  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
629    if cfg!(feature = "pretty_print") {
630      #[cfg(feature = "pretty_print")]
631      return fmt::Display::fmt(&self.pretty_print(), f);
632      fmt::Display::fmt(&"".to_string(), f) // kind of a hack to assuage the compiler
633    } else {
634      write!(f, "{:?}", self)
635    }
636  }
637}
638
639impl Hash for Value {
640  fn hash<H: Hasher>(&self, state: &mut H) {
641    match self {
642      #[cfg(feature = "rational")]
643      Value::R64(x) => x.borrow().hash(state),
644      #[cfg(feature = "u8")]
645      Value::U8(x)   => x.borrow().hash(state),
646      #[cfg(feature = "u16")]
647      Value::U16(x)  => x.borrow().hash(state),
648      #[cfg(feature = "u32")]
649      Value::U32(x)  => x.borrow().hash(state),
650      #[cfg(feature = "u64")]
651      Value::U64(x)  => x.borrow().hash(state),
652      #[cfg(feature = "u128")]
653      Value::U128(x) => x.borrow().hash(state),
654      #[cfg(feature = "i8")]
655      Value::I8(x)   => x.borrow().hash(state),
656      #[cfg(feature = "i16")]
657      Value::I16(x)  => x.borrow().hash(state),
658      #[cfg(feature = "i32")]
659      Value::I32(x)  => x.borrow().hash(state),
660      #[cfg(feature = "i64")]
661      Value::I64(x)  => x.borrow().hash(state),
662      #[cfg(feature = "i128")]
663      Value::I128(x) => x.borrow().hash(state),
664      #[cfg(feature = "f32")]
665      Value::F32(x)  => x.borrow().hash(state),
666      #[cfg(feature = "f64")]
667      Value::F64(x)  => x.borrow().hash(state),
668      #[cfg(feature = "complex")]
669      Value::C64(x) => x.borrow().hash(state),
670      #[cfg(feature = "bool")]
671      Value::Bool(x) => x.borrow().hash(state),
672      #[cfg(feature = "atom")]
673      Value::Atom(x) => x.borrow().hash(state),
674      #[cfg(feature = "set")]
675      Value::Set(x)  => x.borrow().hash(state),
676      #[cfg(feature = "map")]
677      Value::Map(x)  => x.borrow().hash(state),
678      #[cfg(feature = "table")]
679      Value::Table(x) => x.borrow().hash(state),
680      #[cfg(feature = "tuple")]
681      Value::Tuple(x) => x.borrow().hash(state),
682      #[cfg(feature = "record")]
683      Value::Record(x) => x.borrow().hash(state),
684      #[cfg(feature = "enum")]
685      Value::Enum(x) => x.borrow().hash(state),
686      #[cfg(feature = "string")]
687      Value::String(x) => x.borrow().hash(state),
688      #[cfg(all(feature = "matrix", feature = "bool"))]
689      Value::MatrixBool(x) => x.hash(state),
690      #[cfg(feature = "matrix")]
691      Value::MatrixIndex(x) => x.hash(state),
692      #[cfg(all(feature = "matrix", feature = "u8"))]
693      Value::MatrixU8(x)   => x.hash(state),
694      #[cfg(all(feature = "matrix", feature = "u16"))]
695      Value::MatrixU16(x)  => x.hash(state),
696      #[cfg(all(feature = "matrix", feature = "u32"))]
697      Value::MatrixU32(x)  => x.hash(state),
698      #[cfg(all(feature = "matrix", feature = "u64"))]
699      Value::MatrixU64(x)  => x.hash(state),
700      #[cfg(all(feature = "matrix", feature = "u128"))]
701      Value::MatrixU128(x) => x.hash(state),
702      #[cfg(all(feature = "matrix", feature = "i8"))]
703      Value::MatrixI8(x)   => x.hash(state),
704      #[cfg(all(feature = "matrix", feature = "i16"))]
705      Value::MatrixI16(x)  => x.hash(state),
706      #[cfg(all(feature = "matrix", feature = "i32"))]
707      Value::MatrixI32(x)  => x.hash(state),
708      #[cfg(all(feature = "matrix", feature = "i64"))]
709      Value::MatrixI64(x)  => x.hash(state),
710      #[cfg(all(feature = "matrix", feature = "i128"))]
711      Value::MatrixI128(x) => x.hash(state),
712      #[cfg(all(feature = "matrix", feature = "f32"))]
713      Value::MatrixF32(x)  => x.hash(state),
714      #[cfg(all(feature = "matrix", feature = "f64"))]
715      Value::MatrixF64(x)  => x.hash(state),
716      #[cfg(all(feature = "matrix", feature = "string"))]
717      Value::MatrixString(x) => x.hash(state),
718      #[cfg(feature = "matrix")]
719      Value::MatrixValue(x)  => x.hash(state),
720      #[cfg(all(feature = "matrix", feature = "rational"))]
721      Value::MatrixR64(x) => x.hash(state),
722      #[cfg(all(feature = "matrix", feature = "complex"))]
723      Value::MatrixC64(x) => x.hash(state),
724      Value::Id(x)   => x.hash(state),
725      Value::Kind(x) => x.hash(state),
726      Value::Index(x)=> x.borrow().hash(state),
727      Value::MutableReference(x) => x.borrow().hash(state),
728      Value::Empty => Value::Empty.hash(state),
729      Value::IndexAll => Value::IndexAll.hash(state),
730    }
731  }
732}
733impl Value {
734
735  #[cfg(feature = "matrix")]
736  pub unsafe fn get_copyable_matrix_unchecked<T>(&self) -> Box<dyn CopyMat<T>> 
737  where T: AsValueKind + 'static
738  {
739    match (T::as_value_kind(), self) {
740      #[cfg(all(feature = "matrix", feature = "bool"))]
741      (ValueKind::Bool, Value::MatrixBool(m)) => {
742        let b: Box<dyn CopyMat<bool>> = m.get_copyable_matrix();
743        std::mem::transmute::<Box<dyn CopyMat<bool>>, Box<dyn CopyMat<T>>>(b)
744      }
745      #[cfg(all(feature = "matrix", feature = "u8"))]
746      (ValueKind::U8, Value::MatrixU8(m)) => {
747        let b: Box<dyn CopyMat<u8>> = m.get_copyable_matrix();
748        std::mem::transmute::<Box<dyn CopyMat<u8>>, Box<dyn CopyMat<T>>>(b)
749      }
750      #[cfg(all(feature = "matrix", feature = "u16"))]
751      (ValueKind::U16, Value::MatrixU16(m)) => {
752        let b: Box<dyn CopyMat<u16>> = m.get_copyable_matrix();
753        std::mem::transmute::<Box<dyn CopyMat<u16>>, Box<dyn CopyMat<T>>>(b)
754      }
755      #[cfg(all(feature = "matrix", feature = "u32"))]
756      (ValueKind::U32, Value::MatrixU32(m)) => {
757        let b: Box<dyn CopyMat<u32>> = m.get_copyable_matrix();
758        std::mem::transmute::<Box<dyn CopyMat<u32>>, Box<dyn CopyMat<T>>>(b)
759      }
760      #[cfg(all(feature = "matrix", feature = "u64"))]
761      (ValueKind::U64, Value::MatrixU64(m)) => {
762        let b: Box<dyn CopyMat<u64>> = m.get_copyable_matrix();
763        std::mem::transmute::<Box<dyn CopyMat<u64>>, Box<dyn CopyMat<T>>>(b)
764      }
765      #[cfg(all(feature = "matrix", feature = "u128"))]
766      (ValueKind::U128, Value::MatrixU128(m)) => {
767        let b: Box<dyn CopyMat<u128>> = m.get_copyable_matrix();
768        std::mem::transmute::<Box<dyn CopyMat<u128>>, Box<dyn CopyMat<T>>>(b)
769      }
770      #[cfg(all(feature = "matrix", feature = "i8"))]
771      (ValueKind::I8, Value::MatrixI8(m)) => {
772        let b: Box<dyn CopyMat<i8>> = m.get_copyable_matrix();
773        std::mem::transmute::<Box<dyn CopyMat<i8>>, Box<dyn CopyMat<T>>>(b)
774      }
775      #[cfg(all(feature = "matrix", feature = "i16"))]
776      (ValueKind::I16, Value::MatrixI16(m)) => {
777        let b: Box<dyn CopyMat<i16>> = m.get_copyable_matrix();
778        std::mem::transmute::<Box<dyn CopyMat<i16>>, Box<dyn CopyMat<T>>>(b)
779      }
780      #[cfg(all(feature = "matrix", feature = "i32"))]
781      (ValueKind::I32, Value::MatrixI32(m)) => {
782        let b: Box<dyn CopyMat<i32>> = m.get_copyable_matrix();
783        std::mem::transmute::<Box<dyn CopyMat<i32>>, Box<dyn CopyMat<T>>>(b)
784      }
785      #[cfg(all(feature = "matrix", feature = "i64"))]
786      (ValueKind::I64, Value::MatrixI64(m)) => {
787        let b: Box<dyn CopyMat<i64>> = m.get_copyable_matrix();
788        std::mem::transmute::<Box<dyn CopyMat<i64>>, Box<dyn CopyMat<T>>>(b)
789      }
790      #[cfg(all(feature = "matrix", feature = "i128"))]
791      (ValueKind::I128, Value::MatrixI128(m)) => {
792        let b: Box<dyn CopyMat<i128>> = m.get_copyable_matrix();
793        std::mem::transmute::<Box<dyn CopyMat<i128>>, Box<dyn CopyMat<T>>>(b)
794      }
795      #[cfg(all(feature = "matrix", feature = "f32"))]
796      (ValueKind::F32, Value::MatrixF32(m)) => {
797        let b: Box<dyn CopyMat<F32>> = m.get_copyable_matrix();
798        std::mem::transmute::<Box<dyn CopyMat<F32>>, Box<dyn CopyMat<T>>>(b)
799      }
800      #[cfg(all(feature = "matrix", feature = "f64"))]
801      (ValueKind::F64, Value::MatrixF64(m)) => {
802        let b: Box<dyn CopyMat<F64>> = m.get_copyable_matrix();
803        std::mem::transmute::<Box<dyn CopyMat<F64>>, Box<dyn CopyMat<T>>>(b)
804      }
805      #[cfg(all(feature = "matrix", feature = "string"))]
806      (ValueKind::String, Value::MatrixString(m)) => {
807        let b: Box<dyn CopyMat<String>> = m.get_copyable_matrix();
808        std::mem::transmute::<Box<dyn CopyMat<String>>, Box<dyn CopyMat<T>>>(b)
809      }
810      _ => panic!("Unsupported type for get_copyable_matrix_unchecked"),
811    }
812  }
813
814  pub unsafe fn as_unchecked<T>(&self) -> &Ref<T> {
815    match self {
816      #[cfg(feature = "u8")]
817      Value::U8(r) => &*(r as *const Ref<u8> as *const Ref<T>),
818      #[cfg(feature = "u16")]
819      Value::U16(r) => &*(r as *const Ref<u16> as *const Ref<T>),
820      #[cfg(feature = "u32")]
821      Value::U32(r) => &*(r as *const Ref<u32> as *const Ref<T>),
822      #[cfg(feature = "u64")]
823      Value::U64(r) => &*(r as *const Ref<u64> as *const Ref<T>),
824      #[cfg(feature = "u128")]
825      Value::U128(r) => &*(r as *const Ref<u128> as *const Ref<T>),
826      #[cfg(feature = "i8")]
827      Value::I8(r) => &*(r as *const Ref<i8> as *const Ref<T>),
828      #[cfg(feature = "i16")]
829      Value::I16(r) => &*(r as *const Ref<i16> as *const Ref<T>),
830      #[cfg(feature = "i32")]
831      Value::I32(r) => &*(r as *const Ref<i32> as *const Ref<T>),
832      #[cfg(feature = "i64")]
833      Value::I64(r) => &*(r as *const Ref<i64> as *const Ref<T>),
834      #[cfg(feature = "i128")]
835      Value::I128(r) => &*(r as *const Ref<i128> as *const Ref<T>),
836      #[cfg(feature = "f32")]
837      Value::F32(r) => &*(r as *const Ref<F32> as *const Ref<T>),
838      #[cfg(feature = "f64")]
839      Value::F64(r) => &*(r as *const Ref<F64> as *const Ref<T>),
840      #[cfg(feature = "string")]
841      Value::String(r) => &*(r as *const Ref<String> as *const Ref<T>),
842      #[cfg(feature = "bool")]
843      Value::Bool(r) => &*(r as *const Ref<bool> as *const Ref<T>),
844      #[cfg(feature = "rational")]
845      Value::R64(r) => &*(r as *const Ref<R64> as *const Ref<T>),
846      #[cfg(feature = "complex")]
847      Value::C64(r) => &*(r as *const Ref<C64> as *const Ref<T>),
848      #[cfg(all(feature = "f64", feature = "matrix"))]
849      Value::MatrixF64(r) => r.as_unchecked(),
850      #[cfg(all(feature = "f32", feature = "matrix"))]
851      Value::MatrixF32(r) => r.as_unchecked(),
852      #[cfg(all(feature = "i8", feature = "matrix"))]
853      Value::MatrixI8(r) => r.as_unchecked(),
854      #[cfg(all(feature = "i16", feature = "matrix"))]
855      Value::MatrixI16(r) => r.as_unchecked(),
856      #[cfg(all(feature = "i32", feature = "matrix"))]
857      Value::MatrixI32(r) => r.as_unchecked(),
858      #[cfg(all(feature = "i64", feature = "matrix"))]
859      Value::MatrixI64(r) => r.as_unchecked(),
860      #[cfg(all(feature = "i128", feature = "matrix"))]
861      Value::MatrixI128(r) => r.as_unchecked(),
862      #[cfg(all(feature = "u8", feature = "matrix"))]
863      Value::MatrixU8(r) => r.as_unchecked(),
864      #[cfg(all(feature = "u16", feature = "matrix"))]
865      Value::MatrixU16(r) => r.as_unchecked(),
866      #[cfg(all(feature = "u32", feature = "matrix"))]
867      Value::MatrixU32(r) => r.as_unchecked(),
868      #[cfg(all(feature = "u64", feature = "matrix"))]
869      Value::MatrixU64(r) => r.as_unchecked(),
870      #[cfg(all(feature = "u128", feature = "matrix"))]
871      Value::MatrixU128(r) => r.as_unchecked(),
872      #[cfg(all(feature = "bool", feature = "matrix"))]
873      Value::MatrixBool(r) => r.as_unchecked(),
874      #[cfg(all(feature = "string", feature = "matrix"))]
875      Value::MatrixString(r) => r.as_unchecked(),
876      #[cfg(all(feature = "rational", feature = "matrix"))]
877      Value::MatrixR64(r) => r.as_unchecked(),
878      #[cfg(all(feature = "complex", feature = "matrix"))]
879      Value::MatrixC64(r) => r.as_unchecked(),
880      #[cfg(feature = "matrix")]
881      Value::MatrixIndex(r) => r.as_unchecked(),
882      Value::Index(r) => &*(r as *const Ref<usize> as *const Ref<T>),
883      #[cfg(feature = "enum")]
884      Value::Enum(r) => &*(r as *const Ref<MechEnum> as *const Ref<T>),
885      _ => panic!("Unsupported type for as_unchecked"),
886    }
887  }
888
889  pub fn addr(&self) -> usize {
890    match self {
891      #[cfg(feature = "u8")]
892      Value::U8(v) => v.addr(),
893      #[cfg(feature = "u16")]
894      Value::U16(v) => v.addr(),
895      #[cfg(feature = "u32")]
896      Value::U32(v) => v.addr(),
897      #[cfg(feature = "u64")]
898      Value::U64(v) => v.addr(),
899      #[cfg(feature = "u128")]
900      Value::U128(v) => v.addr(),
901      #[cfg(feature = "i8")]
902      Value::I8(v) => v.addr(),
903      #[cfg(feature = "i16")]
904      Value::I16(v) => v.addr(),
905      #[cfg(feature = "i32")]
906      Value::I32(v) => v.addr(),
907      #[cfg(feature = "i64")]
908      Value::I64(v) => v.addr(),
909      #[cfg(feature = "i128")]
910      Value::I128(v) => v.addr(),
911      #[cfg(feature = "f32")]
912      Value::F32(v) => v.addr(),
913      #[cfg(feature = "f64")]
914      Value::F64(v) => v.addr(),
915      #[cfg(feature = "string")]
916      Value::String(v) => v.addr(),
917      #[cfg(feature = "bool")]
918      Value::Bool(v) => v.addr(),
919      #[cfg(feature = "complex")]
920      Value::C64(v) => v.addr(),
921      #[cfg(feature = "rational")]
922      Value::R64(v) => v.addr(),
923      #[cfg(feature = "record")]
924      Value::Record(v) => v.addr(),
925      #[cfg(feature = "table")]
926      Value::Table(v) => v.addr(),
927      #[cfg(feature = "map")]
928      Value::Map(v) => v.addr(),
929      #[cfg(feature = "tuple")]
930      Value::Tuple(v) => v.addr(),
931      #[cfg(feature = "set")]
932      Value::Set(v) => v.addr(),
933      #[cfg(feature = "enum")]
934      Value::Enum(v) => v.addr(),
935      #[cfg(feature = "atom")]
936      Value::Atom(v) => v.addr(),
937      #[cfg(feature = "matrix")]
938      Value::MatrixIndex(v) => v.addr(),
939      Value::Index(v) => v.addr(),
940      Value::MutableReference(v) => v.addr(),
941      _ => todo!(),
942    }
943  }
944
945  pub fn convert_to(&self, other: &ValueKind) -> Option<Value> {
946
947    if self.kind() == *other {
948        return Some(self.clone());
949    }
950
951    if !self.kind().is_convertible_to(other) {
952        return None;
953    }
954
955    match (self, other) {
956    // ==== Unsigned widening and narrowing ====
957    #[cfg(all(feature = "u8", feature = "u16"))]
958    (Value::U8(v), ValueKind::U16) => Some(Value::U16(Ref::new((*v.borrow()) as u16))),
959    #[cfg(all(feature = "u8", feature = "u32"))]
960    (Value::U8(v), ValueKind::U32) => Some(Value::U32(Ref::new((*v.borrow()) as u32))),
961    #[cfg(all(feature = "u8", feature = "u64"))]
962    (Value::U8(v), ValueKind::U64) => Some(Value::U64(Ref::new((*v.borrow()) as u64))),
963    #[cfg(all(feature = "u8", feature = "u128"))]
964    (Value::U8(v), ValueKind::U128) => Some(Value::U128(Ref::new((*v.borrow()) as u128))),
965    #[cfg(all(feature = "u8", feature = "i16"))]
966    (Value::U8(v), ValueKind::I16) => Some(Value::I16(Ref::new((*v.borrow()) as i16))),
967    #[cfg(all(feature = "u8", feature = "i32"))]
968    (Value::U8(v), ValueKind::I32) => Some(Value::I32(Ref::new((*v.borrow()) as i32))),
969    #[cfg(all(feature = "u8", feature = "i64"))]
970    (Value::U8(v), ValueKind::I64) => Some(Value::I64(Ref::new((*v.borrow()) as i64))),
971    #[cfg(all(feature = "u8", feature = "i128"))]
972    (Value::U8(v), ValueKind::I128) => Some(Value::I128(Ref::new((*v.borrow()) as i128))),
973    #[cfg(all(feature = "u8", feature = "f32"))]
974    (Value::U8(v), ValueKind::F32) => Some(Value::F32(Ref::new(F32::new(*v.borrow() as f32)))),
975    #[cfg(all(feature = "u8", feature = "f64"))]
976    (Value::U8(v), ValueKind::F64) => Some(Value::F64(Ref::new(F64::new(*v.borrow() as f64)))),
977
978    #[cfg(all(feature = "u16", feature = "u8"))]
979    (Value::U16(v), ValueKind::U8) => Some(Value::U8(Ref::new((*v.borrow()) as u8))),
980    #[cfg(all(feature = "u16", feature = "u32"))]
981    (Value::U16(v), ValueKind::U32) => Some(Value::U32(Ref::new((*v.borrow()) as u32))),
982    #[cfg(all(feature = "u16", feature = "u64"))]
983    (Value::U16(v), ValueKind::U64) => Some(Value::U64(Ref::new((*v.borrow()) as u64))),
984    #[cfg(all(feature = "u16", feature = "u128"))]
985    (Value::U16(v), ValueKind::U128) => Some(Value::U128(Ref::new((*v.borrow()) as u128))),
986    #[cfg(all(feature = "u16", feature = "i8"))]
987    (Value::U16(v), ValueKind::I8) => Some(Value::I8(Ref::new((*v.borrow()) as i8))),
988    #[cfg(all(feature = "u16", feature = "i32"))]
989    (Value::U16(v), ValueKind::I32) => Some(Value::I32(Ref::new((*v.borrow()) as i32))),
990    #[cfg(all(feature = "u16", feature = "i64"))]
991    (Value::U16(v), ValueKind::I64) => Some(Value::I64(Ref::new((*v.borrow()) as i64))),
992    #[cfg(all(feature = "u16", feature = "i128"))]
993    (Value::U16(v), ValueKind::I128) => Some(Value::I128(Ref::new((*v.borrow()) as i128))),
994    #[cfg(all(feature = "u16", feature = "f32"))]
995    (Value::U16(v), ValueKind::F32) => Some(Value::F32(Ref::new(F32::new(*v.borrow() as f32)))),
996    #[cfg(all(feature = "u16", feature = "f64"))]
997    (Value::U16(v), ValueKind::F64) => Some(Value::F64(Ref::new(F64::new(*v.borrow() as f64)))),
998
999    #[cfg(all(feature = "u32", feature = "u8"))]
1000    (Value::U32(v), ValueKind::U8) => Some(Value::U8(Ref::new((*v.borrow()) as u8))),
1001    #[cfg(all(feature = "u32", feature = "u16"))]
1002    (Value::U32(v), ValueKind::U16) => Some(Value::U16(Ref::new((*v.borrow()) as u16))),
1003    #[cfg(all(feature = "u32", feature = "u64"))]
1004    (Value::U32(v), ValueKind::U64) => Some(Value::U64(Ref::new((*v.borrow()) as u64))),
1005    #[cfg(all(feature = "u32", feature = "u128"))]
1006    (Value::U32(v), ValueKind::U128) => Some(Value::U128(Ref::new((*v.borrow()) as u128))),
1007    #[cfg(all(feature = "u32", feature = "i8"))]
1008    (Value::U32(v), ValueKind::I8) => Some(Value::I8(Ref::new((*v.borrow()) as i8))),
1009    #[cfg(all(feature = "u32", feature = "i16"))]
1010    (Value::U32(v), ValueKind::I16) => Some(Value::I16(Ref::new((*v.borrow()) as i16))),
1011    #[cfg(all(feature = "u32", feature = "i64"))]
1012    (Value::U32(v), ValueKind::I64) => Some(Value::I64(Ref::new((*v.borrow()) as i64))),
1013    #[cfg(all(feature = "u32", feature = "i128"))]
1014    (Value::U32(v), ValueKind::I128) => Some(Value::I128(Ref::new((*v.borrow()) as i128))),
1015    #[cfg(all(feature = "u32", feature = "f32"))]
1016    (Value::U32(v), ValueKind::F32) => Some(Value::F32(Ref::new(F32::new(*v.borrow() as f32)))),
1017    #[cfg(all(feature = "u32", feature = "f64"))]
1018    (Value::U32(v), ValueKind::F64) => Some(Value::F64(Ref::new(F64::new(*v.borrow() as f64)))),
1019
1020    #[cfg(all(feature = "u64", feature = "u8"))]
1021    (Value::U64(v), ValueKind::U8) => Some(Value::U8(Ref::new((*v.borrow()) as u8))),
1022    #[cfg(all(feature = "u64", feature = "u16"))]
1023    (Value::U64(v), ValueKind::U16) => Some(Value::U16(Ref::new((*v.borrow()) as u16))),
1024    #[cfg(all(feature = "u64", feature = "u32"))]
1025    (Value::U64(v), ValueKind::U32) => Some(Value::U32(Ref::new((*v.borrow()) as u32))),
1026    #[cfg(all(feature = "u64", feature = "u128"))]
1027    (Value::U64(v), ValueKind::U128) => Some(Value::U128(Ref::new((*v.borrow()) as u128))),
1028    #[cfg(all(feature = "u64", feature = "i8"))]
1029    (Value::U64(v), ValueKind::I8) => Some(Value::I8(Ref::new((*v.borrow()) as i8))),
1030    #[cfg(all(feature = "u64", feature = "i16"))]
1031    (Value::U64(v), ValueKind::I16) => Some(Value::I16(Ref::new((*v.borrow()) as i16))),
1032    #[cfg(all(feature = "u64", feature = "i32"))]
1033    (Value::U64(v), ValueKind::I32) => Some(Value::I32(Ref::new((*v.borrow()) as i32))),
1034    #[cfg(all(feature = "u64", feature = "i128"))]
1035    (Value::U64(v), ValueKind::I128) => Some(Value::I128(Ref::new((*v.borrow()) as i128))),
1036    #[cfg(all(feature = "u64", feature = "f32"))]
1037    (Value::U64(v), ValueKind::F32) => Some(Value::F32(Ref::new(F32::new(*v.borrow() as f32)))),
1038    #[cfg(all(feature = "u64", feature = "f64"))]
1039    (Value::U64(v), ValueKind::F64) => Some(Value::F64(Ref::new(F64::new(*v.borrow() as f64)))),
1040
1041    #[cfg(all(feature = "u128", feature = "u8"))]
1042    (Value::U128(v), ValueKind::U8) => Some(Value::U8(Ref::new((*v.borrow()) as u8))),
1043    #[cfg(all(feature = "u128", feature = "u16"))]
1044    (Value::U128(v), ValueKind::U16) => Some(Value::U16(Ref::new((*v.borrow()) as u16))),
1045    #[cfg(all(feature = "u128", feature = "u32"))]
1046    (Value::U128(v), ValueKind::U32) => Some(Value::U32(Ref::new((*v.borrow()) as u32))),
1047    #[cfg(all(feature = "u128", feature = "u64"))]
1048    (Value::U128(v), ValueKind::U64) => Some(Value::U64(Ref::new((*v.borrow()) as u64))),
1049    #[cfg(all(feature = "u128", feature = "i8"))]
1050    (Value::U128(v), ValueKind::I8) => Some(Value::I8(Ref::new((*v.borrow()) as i8))),
1051    #[cfg(all(feature = "u128", feature = "i16"))]
1052    (Value::U128(v), ValueKind::I16) => Some(Value::I16(Ref::new((*v.borrow()) as i16))),
1053    #[cfg(all(feature = "u128", feature = "i32"))]
1054    (Value::U128(v), ValueKind::I32) => Some(Value::I32(Ref::new((*v.borrow()) as i32))),
1055    #[cfg(all(feature = "u128", feature = "i64"))]
1056    (Value::U128(v), ValueKind::I64) => Some(Value::I64(Ref::new((*v.borrow()) as i64))),
1057    #[cfg(all(feature = "u128", feature = "f32"))]
1058    (Value::U128(v), ValueKind::F32) => Some(Value::F32(Ref::new(F32::new(*v.borrow() as f32)))),
1059    #[cfg(all(feature = "u128", feature = "f64"))]
1060    (Value::U128(v), ValueKind::F64) => Some(Value::F64(Ref::new(F64::new(*v.borrow() as f64)))),
1061
1062    // ==== Signed widening and narrowing ====
1063    #[cfg(all(feature = "i8", feature = "i16"))]
1064    (Value::I8(v), ValueKind::I16) => Some(Value::I16(Ref::new((*v.borrow()) as i16))),
1065    #[cfg(all(feature = "i8", feature = "i32"))]
1066    (Value::I8(v), ValueKind::I32) => Some(Value::I32(Ref::new((*v.borrow()) as i32))),
1067    #[cfg(all(feature = "i8", feature = "i64"))]
1068    (Value::I8(v), ValueKind::I64) => Some(Value::I64(Ref::new((*v.borrow()) as i64))),
1069    #[cfg(all(feature = "i8", feature = "i128"))]
1070    (Value::I8(v), ValueKind::I128) => Some(Value::I128(Ref::new((*v.borrow()) as i128))),
1071    #[cfg(all(feature = "i8", feature = "u16"))]
1072    (Value::I8(v), ValueKind::U16) => Some(Value::U16(Ref::new((*v.borrow()) as u16))),
1073    #[cfg(all(feature = "i8", feature = "u32"))]
1074    (Value::I8(v), ValueKind::U32) => Some(Value::U32(Ref::new((*v.borrow()) as u32))),
1075    #[cfg(all(feature = "i8", feature = "u64"))]
1076    (Value::I8(v), ValueKind::U64) => Some(Value::U64(Ref::new((*v.borrow()) as u64))),
1077    #[cfg(all(feature = "i8", feature = "u128"))]
1078    (Value::I8(v), ValueKind::U128) => Some(Value::U128(Ref::new((*v.borrow()) as u128))),
1079    #[cfg(all(feature = "i8", feature = "f32"))]
1080    (Value::I8(v), ValueKind::F32) => Some(Value::F32(Ref::new(F32::new(*v.borrow() as f32)))),
1081    #[cfg(all(feature = "i8", feature = "f64"))]
1082    (Value::I8(v), ValueKind::F64) => Some(Value::F64(Ref::new(F64::new(*v.borrow() as f64)))),
1083
1084    #[cfg(all(feature = "i16", feature = "i8"))]
1085    (Value::I16(v), ValueKind::I8) => Some(Value::I8(Ref::new((*v.borrow()) as i8))),
1086    #[cfg(all(feature = "i16", feature = "i32"))]
1087    (Value::I16(v), ValueKind::I32) => Some(Value::I32(Ref::new((*v.borrow()) as i32))),
1088    #[cfg(all(feature = "i16", feature = "i64"))]
1089    (Value::I16(v), ValueKind::I64) => Some(Value::I64(Ref::new((*v.borrow()) as i64))),
1090    #[cfg(all(feature = "i16", feature = "i128"))]
1091    (Value::I16(v), ValueKind::I128) => Some(Value::I128(Ref::new((*v.borrow()) as i128))),
1092    #[cfg(all(feature = "i16", feature = "u8"))]
1093    (Value::I16(v), ValueKind::U8) => Some(Value::U8(Ref::new((*v.borrow()) as u8))),
1094    #[cfg(all(feature = "i16", feature = "u32"))]
1095    (Value::I16(v), ValueKind::U32) => Some(Value::U32(Ref::new((*v.borrow()) as u32))),
1096    #[cfg(all(feature = "i16", feature = "u64"))]
1097    (Value::I16(v), ValueKind::U64) => Some(Value::U64(Ref::new((*v.borrow()) as u64))),
1098    #[cfg(all(feature = "i16", feature = "u128"))]
1099    (Value::I16(v), ValueKind::U128) => Some(Value::U128(Ref::new((*v.borrow()) as u128))),
1100    #[cfg(all(feature = "i16", feature = "f32"))]
1101    (Value::I16(v), ValueKind::F32) => Some(Value::F32(Ref::new(F32::new(*v.borrow() as f32)))),
1102    #[cfg(all(feature = "i16", feature = "f64"))]
1103    (Value::I16(v), ValueKind::F64) => Some(Value::F64(Ref::new(F64::new(*v.borrow() as f64)))),
1104
1105    #[cfg(all(feature = "i32", feature = "i8"))]
1106    (Value::I32(v), ValueKind::I8) => Some(Value::I8(Ref::new((*v.borrow()) as i8))),
1107    #[cfg(all(feature = "i32", feature = "i16"))]
1108    (Value::I32(v), ValueKind::I16) => Some(Value::I16(Ref::new((*v.borrow()) as i16))),
1109    #[cfg(all(feature = "i32", feature = "i64"))]
1110    (Value::I32(v), ValueKind::I64) => Some(Value::I64(Ref::new((*v.borrow()) as i64))),
1111    #[cfg(all(feature = "i32", feature = "i128"))]
1112    (Value::I32(v), ValueKind::I128) => Some(Value::I128(Ref::new((*v.borrow()) as i128))),
1113    #[cfg(all(feature = "i32", feature = "u8"))]
1114    (Value::I32(v), ValueKind::U8) => Some(Value::U8(Ref::new((*v.borrow()) as u8))),
1115    #[cfg(all(feature = "i32", feature = "u16"))]
1116    (Value::I32(v), ValueKind::U16) => Some(Value::U16(Ref::new((*v.borrow()) as u16))),
1117    #[cfg(all(feature = "i32", feature = "u64"))]
1118    (Value::I32(v), ValueKind::U64) => Some(Value::U64(Ref::new((*v.borrow()) as u64))),
1119    #[cfg(all(feature = "i32", feature = "u128"))]
1120    (Value::I32(v), ValueKind::U128) => Some(Value::U128(Ref::new((*v.borrow()) as u128))),
1121    #[cfg(all(feature = "i32", feature = "f32"))]
1122    (Value::I32(v), ValueKind::F32) => Some(Value::F32(Ref::new(F32::new(*v.borrow() as f32)))),
1123    #[cfg(all(feature = "i32", feature = "f64"))]
1124    (Value::I32(v), ValueKind::F64) => Some(Value::F64(Ref::new(F64::new(*v.borrow() as f64)))),
1125
1126    #[cfg(all(feature = "i64", feature = "i8"))]
1127    (Value::I64(v), ValueKind::I8) => Some(Value::I8(Ref::new((*v.borrow()) as i8))),
1128    #[cfg(all(feature = "i64", feature = "i16"))]
1129    (Value::I64(v), ValueKind::I16) => Some(Value::I16(Ref::new((*v.borrow()) as i16))),
1130    #[cfg(all(feature = "i64", feature = "i32"))]
1131    (Value::I64(v), ValueKind::I32) => Some(Value::I32(Ref::new((*v.borrow()) as i32))),
1132    #[cfg(all(feature = "i64", feature = "i128"))]
1133    (Value::I64(v), ValueKind::I128) => Some(Value::I128(Ref::new((*v.borrow()) as i128))),
1134    #[cfg(all(feature = "i64", feature = "u8"))]
1135    (Value::I64(v), ValueKind::U8) => Some(Value::U8(Ref::new((*v.borrow()) as u8))),
1136    #[cfg(all(feature = "i64", feature = "u16"))]
1137    (Value::I64(v), ValueKind::U16) => Some(Value::U16(Ref::new((*v.borrow()) as u16))),
1138    #[cfg(all(feature = "i64", feature = "u32"))]
1139    (Value::I64(v), ValueKind::U32) => Some(Value::U32(Ref::new((*v.borrow()) as u32))),
1140    #[cfg(all(feature = "i64", feature = "u128"))]
1141    (Value::I64(v), ValueKind::U128) => Some(Value::U128(Ref::new((*v.borrow()) as u128))),
1142    #[cfg(all(feature = "i64", feature = "f32"))]
1143    (Value::I64(v), ValueKind::F32) => Some(Value::F32(Ref::new(F32::new(*v.borrow() as f32)))),
1144    #[cfg(all(feature = "i64", feature = "f64"))]
1145    (Value::I64(v), ValueKind::F64) => Some(Value::F64(Ref::new(F64::new(*v.borrow() as f64)))),
1146
1147    #[cfg(all(feature = "i128", feature = "i8"))]
1148    (Value::I128(v), ValueKind::I8) => Some(Value::I8(Ref::new((*v.borrow()) as i8))),
1149    #[cfg(all(feature = "i128", feature = "i16"))]
1150    (Value::I128(v), ValueKind::I16) => Some(Value::I16(Ref::new((*v.borrow()) as i16))),
1151    #[cfg(all(feature = "i128", feature = "i32"))]
1152    (Value::I128(v), ValueKind::I32) => Some(Value::I32(Ref::new((*v.borrow()) as i32))),
1153    #[cfg(all(feature = "i128", feature = "i64"))]
1154    (Value::I128(v), ValueKind::I64) => Some(Value::I64(Ref::new((*v.borrow()) as i64))),
1155    #[cfg(all(feature = "i128", feature = "u8"))]
1156    (Value::I128(v), ValueKind::U8) => Some(Value::U8(Ref::new((*v.borrow()) as u8))),
1157    #[cfg(all(feature = "i128", feature = "u16"))]
1158    (Value::I128(v), ValueKind::U16) => Some(Value::U16(Ref::new((*v.borrow()) as u16))),
1159    #[cfg(all(feature = "i128", feature = "u32"))]
1160    (Value::I128(v), ValueKind::U32) => Some(Value::U32(Ref::new((*v.borrow()) as u32))),
1161    #[cfg(all(feature = "i128", feature = "u64"))]
1162    (Value::I128(v), ValueKind::U64) => Some(Value::U64(Ref::new((*v.borrow()) as u64))),
1163    #[cfg(all(feature = "i128", feature = "f32"))]
1164    (Value::I128(v), ValueKind::F32) => Some(Value::F32(Ref::new(F32::new(*v.borrow() as f32)))),
1165    #[cfg(all(feature = "i128", feature = "f64"))]
1166    (Value::I128(v), ValueKind::F64) => Some(Value::F64(Ref::new(F64::new(*v.borrow() as f64)))),
1167
1168    // ==== Float widening and narrowing ====
1169    #[cfg(all(feature = "f32", feature = "f64"))]
1170    (Value::F32(v), ValueKind::F64) => Some(Value::F64(Ref::new(F64::new(v.borrow().0 as f64)))),
1171    #[cfg(all(feature = "f32", feature = "f64"))]
1172    (Value::F64(v), ValueKind::F32) => Some(Value::F32(Ref::new(F32::new(v.borrow().0 as f32)))),
1173
1174    // ==== Float to integer conversions (truncate) ====
1175    #[cfg(all(feature = "f32", feature = "i8"))]
1176    (Value::F32(v), ValueKind::I8) => Some(Value::I8(Ref::new(v.borrow().0 as i8))),
1177    #[cfg(all(feature = "f32", feature = "i16"))]
1178    (Value::F32(v), ValueKind::I16) => Some(Value::I16(Ref::new(v.borrow().0 as i16))),
1179    #[cfg(all(feature = "f32", feature = "i32"))]
1180    (Value::F32(v), ValueKind::I32) => Some(Value::I32(Ref::new(v.borrow().0 as i32))),
1181    #[cfg(all(feature = "f32", feature = "i64"))]
1182    (Value::F32(v), ValueKind::I64) => Some(Value::I64(Ref::new(v.borrow().0 as i64))),
1183    #[cfg(all(feature = "f32", feature = "i128"))]
1184    (Value::F32(v), ValueKind::I128) => Some(Value::I128(Ref::new(v.borrow().0 as i128))),
1185    #[cfg(all(feature = "f32", feature = "u8"))]
1186    (Value::F32(v), ValueKind::U8) => Some(Value::U8(Ref::new(v.borrow().0 as u8))),
1187    #[cfg(all(feature = "f32", feature = "u16"))]
1188    (Value::F32(v), ValueKind::U16) => Some(Value::U16(Ref::new(v.borrow().0 as u16))),
1189    #[cfg(all(feature = "f32", feature = "u32"))]
1190    (Value::F32(v), ValueKind::U32) => Some(Value::U32(Ref::new(v.borrow().0 as u32))),
1191    #[cfg(all(feature = "f32", feature = "u64"))]
1192    (Value::F32(v), ValueKind::U64) => Some(Value::U64(Ref::new(v.borrow().0 as u64))),
1193    #[cfg(all(feature = "f32", feature = "u128"))]
1194    (Value::F32(v), ValueKind::U128) => Some(Value::U128(Ref::new(v.borrow().0 as u128))),
1195
1196    #[cfg(all(feature = "f64", feature = "i8"))]
1197    (Value::F64(v), ValueKind::I8) => Some(Value::I8(Ref::new(v.borrow().0 as i8))),
1198    #[cfg(all(feature = "f64", feature = "i16"))]
1199    (Value::F64(v), ValueKind::I16) => Some(Value::I16(Ref::new(v.borrow().0 as i16))),
1200    #[cfg(all(feature = "f64", feature = "i32"))]
1201    (Value::F64(v), ValueKind::I32) => Some(Value::I32(Ref::new(v.borrow().0 as i32))),
1202    #[cfg(all(feature = "f64", feature = "i64"))]
1203    (Value::F64(v), ValueKind::I64) => Some(Value::I64(Ref::new(v.borrow().0 as i64))),
1204    #[cfg(all(feature = "f64", feature = "i128"))]
1205    (Value::F64(v), ValueKind::I128) => Some(Value::I128(Ref::new(v.borrow().0 as i128))),
1206    #[cfg(all(feature = "f64", feature = "u8"))]
1207    (Value::F64(v), ValueKind::U8) => Some(Value::U8(Ref::new(v.borrow().0 as u8))),
1208    #[cfg(all(feature = "f64", feature = "u16"))]
1209    (Value::F64(v), ValueKind::U16) => Some(Value::U16(Ref::new(v.borrow().0 as u16))),
1210    #[cfg(all(feature = "f64", feature = "u32"))]
1211    (Value::F64(v), ValueKind::U32) => Some(Value::U32(Ref::new(v.borrow().0 as u32))),
1212    #[cfg(all(feature = "f64", feature = "u64"))]
1213    (Value::F64(v), ValueKind::U64) => Some(Value::U64(Ref::new(v.borrow().0 as u64))),
1214    #[cfg(all(feature = "f64", feature = "u128"))]
1215    (Value::F64(v), ValueKind::U128) => Some(Value::U128(Ref::new(v.borrow().0 as u128))),
1216
1217      /*
1218      // ==== INDEX conversions ====
1219      (Value::Index(i), U32) => Some(Value::U32(Ref::new((*i.borrow()) as u32))),
1220      (Value::U32(v), Index) => Some(Value::Index(Ref::new((*v.borrow()) as usize))),
1221
1222
1223      // ==== MATRIX conversions (element-wise) ====
1224      (Value::MatrixU8(m), MatrixU16) => Some(Value::MatrixU16(m.map(|x| *x as u16))),
1225      (Value::MatrixI32(m), MatrixF64) => Some(Value::MatrixF64(m.map(|x| (*x) as f64))),
1226      // You can expand other matrix conversions similarly...
1227
1228      // ==== COMPLEX TYPES (stubs) ====
1229      (Value::Set(set), Set(_)) => Some(Value::Set(set.clone())), // TODO: element-wise convert
1230      (Value::Map(map), Map(_)) => Some(Value::Map(map.clone())), // TODO: key/value convert
1231      (Value::Record(r), Record(_)) => Some(Value::Record(r.clone())), // TODO: field convert
1232      (Value::Table(t), Table(_)) => Some(Value::Table(t.clone())), // TODO: column convert
1233
1234      // ==== ENUM, KIND ====
1235      (Value::Enum(e), Enum(_)) => Some(Value::Enum(e.clone())),
1236      (Value::Kind(k), Kind(_)) => Some(Value::Kind(k.clone())),
1237
1238      // ==== SPECIAL CASES ====
1239      (Value::IndexAll, IndexAll) => Some(Value::IndexAll),
1240      (Value::Empty, Empty) => Some(Value::Empty),
1241      */
1242      // ==== FALLBACK ====
1243      _ => None,
1244    }
1245  }
1246
1247  pub fn size_of(&self) -> usize {
1248    match self {
1249      #[cfg(feature = "rational")]
1250      Value::R64(x) => 16,
1251      #[cfg(feature = "u8")]
1252      Value::U8(x) => 1,
1253      #[cfg(feature = "u16")]
1254      Value::U16(x) => 2,
1255      #[cfg(feature = "u32")]
1256      Value::U32(x) => 4,
1257      #[cfg(feature = "u64")]
1258      Value::U64(x) => 8,
1259      #[cfg(feature = "u128")]
1260      Value::U128(x) => 16,
1261      #[cfg(feature = "i8")]
1262      Value::I8(x) => 1,
1263      #[cfg(feature = "i16")]
1264      Value::I16(x) => 2,
1265      #[cfg(feature = "i32")]
1266      Value::I32(x) => 4,
1267      #[cfg(feature = "i64")]
1268      Value::I64(x) => 8,
1269      #[cfg(feature = "i128")]
1270      Value::I128(x) => 16,
1271      #[cfg(feature = "f32")]
1272      Value::F32(x) => 4,
1273      #[cfg(feature = "f64")]
1274      Value::F64(x) => 8,
1275      #[cfg(feature = "bool")]
1276      Value::Bool(x) => 1,
1277      #[cfg(feature = "complex")]
1278      Value::C64(x) => 16,
1279      #[cfg(all(feature = "matrix"))]
1280      Value::MatrixIndex(x) => x.size_of(),
1281      #[cfg(all(feature = "matrix", feature = "bool"))]
1282      Value::MatrixBool(x) => x.size_of(),
1283      #[cfg(all(feature = "matrix", feature = "u8"))]
1284      Value::MatrixU8(x)   => x.size_of(),
1285      #[cfg(all(feature = "matrix", feature = "u16"))]
1286      Value::MatrixU16(x)  => x.size_of(),
1287      #[cfg(all(feature = "matrix", feature = "u32"))]
1288      Value::MatrixU32(x)  => x.size_of(),
1289      #[cfg(all(feature = "matrix", feature = "u64"))]
1290      Value::MatrixU64(x)  => x.size_of(),
1291      #[cfg(all(feature = "matrix", feature = "u128"))]
1292      Value::MatrixU128(x) => x.size_of(),
1293      #[cfg(all(feature = "matrix", feature = "i8"))]
1294      Value::MatrixI8(x)   => x.size_of(),
1295      #[cfg(all(feature = "matrix", feature = "i16"))]
1296      Value::MatrixI16(x)  => x.size_of(),
1297      #[cfg(all(feature = "matrix", feature = "i32"))]
1298      Value::MatrixI32(x)  => x.size_of(),
1299      #[cfg(all(feature = "matrix", feature = "i64"))]
1300      Value::MatrixI64(x)  => x.size_of(),
1301      #[cfg(all(feature = "matrix", feature = "i128"))]
1302      Value::MatrixI128(x) => x.size_of(),
1303      #[cfg(all(feature = "matrix", feature = "f32"))]
1304      Value::MatrixF32(x)  => x.size_of(),
1305      #[cfg(all(feature = "matrix", feature = "f64"))]
1306      Value::MatrixF64(x)  => x.size_of(),
1307      #[cfg(feature = "matrix")]
1308      Value::MatrixValue(x)  => x.size_of(),
1309      #[cfg(all(feature = "matrix", feature = "string"))]
1310      Value::MatrixString(x) => x.size_of(),
1311      #[cfg(all(feature = "matrix", feature = "rational"))]
1312      Value::MatrixR64(x) => x.size_of(),
1313      #[cfg(all(feature = "matrix", feature = "complex"))]
1314      Value::MatrixC64(x) => x.size_of(),
1315      #[cfg(feature = "string")]
1316      Value::String(x) => x.borrow().len(),
1317      #[cfg(feature = "atom")]
1318      Value::Atom(x) => 8,
1319      #[cfg(feature = "set")]
1320      Value::Set(x) => x.borrow().size_of(),
1321      #[cfg(feature = "map")]
1322      Value::Map(x) => x.borrow().size_of(),
1323      #[cfg(feature = "table")]
1324      Value::Table(x) => x.borrow().size_of(),
1325      #[cfg(feature = "record")]
1326      Value::Record(x) => x.borrow().size_of(),
1327      #[cfg(feature = "tuple")]
1328      Value::Tuple(x) => x.borrow().size_of(),
1329      #[cfg(feature = "enum")]
1330      Value::Enum(x) => x.borrow().size_of(),
1331      Value::MutableReference(x) => x.borrow().size_of(),
1332      Value::Id(_) => 8,
1333      Value::Index(x) => 8,
1334      Value::Kind(_) => 0, // Kind is not a value, so it has no size
1335      Value::Empty => 0,
1336      Value::IndexAll => 0, // IndexAll is a special value, so it has no size
1337    }
1338  }
1339
1340  #[cfg(feature = "pretty_print")]
1341  pub fn to_html(&self) -> String {
1342    match self {
1343      #[cfg(feature = "u8")]
1344      Value::U8(n) => format!("<span class='mech-number'>{}</span>", n.borrow()),
1345      #[cfg(feature = "u16")]
1346      Value::U16(n) => format!("<span class='mech-number'>{}</span>", n.borrow()),
1347      #[cfg(feature = "u32")]
1348      Value::U32(n) => format!("<span class='mech-number'>{}</span>", n.borrow()),
1349      #[cfg(feature = "u64")]
1350      Value::U64(n) => format!("<span class='mech-number'>{}</span>", n.borrow()),
1351      #[cfg(feature = "i8")]
1352      Value::I8(n) => format!("<span class='mech-number'>{}</span>", n.borrow()),
1353      #[cfg(feature = "i128")]
1354      Value::I128(n) => format!("<span class='mech-number'>{}</span>", n.borrow()),
1355      #[cfg(feature = "i16")]
1356      Value::I16(n) => format!("<span class='mech-number'>{}</span>", n.borrow()),
1357      #[cfg(feature = "i32")]
1358      Value::I32(n) => format!("<span class='mech-number'>{}</span>", n.borrow()),
1359      #[cfg(feature = "i64")]
1360      Value::I64(n) => format!("<span class='mech-number'>{}</span>", n.borrow()),
1361      #[cfg(feature = "i128")]
1362      Value::I128(n) => format!("<span class='mech-number'>{}</span>", n.borrow()),
1363      #[cfg(feature = "f32")]
1364      Value::F32(n) => format!("<span class='mech-number'>{}</span>", n.borrow()),
1365      #[cfg(feature = "f64")]
1366      Value::F64(n) => format!("<span class='mech-number'>{}</span>", n.borrow()),
1367      #[cfg(feature = "string")]
1368      Value::String(s) => format!("<span class='mech-string'>\"{}\"</span>", s.borrow()),
1369      #[cfg(feature = "bool")]
1370      Value::Bool(b) => format!("<span class='mech-boolean'>{}</span>", b.borrow()),
1371      #[cfg(feature = "complex")]
1372      Value::C64(c) => c.borrow().to_html(),
1373      #[cfg(all(feature = "matrix", feature = "u8"))]
1374      Value::MatrixU8(m) => m.to_html(),
1375      #[cfg(all(feature = "matrix", feature = "u16"))]
1376      Value::MatrixU16(m) => m.to_html(),
1377      #[cfg(all(feature = "matrix", feature = "u32"))]
1378      Value::MatrixU32(m) => m.to_html(),
1379      #[cfg(all(feature = "matrix", feature = "u64"))]
1380      Value::MatrixU64(m) => m.to_html(),
1381      #[cfg(all(feature = "matrix", feature = "u128"))]
1382      Value::MatrixU128(m) => m.to_html(),
1383      #[cfg(all(feature = "matrix", feature = "i8"))]
1384      Value::MatrixI8(m) => m.to_html(),
1385      #[cfg(all(feature = "matrix", feature = "i16"))]
1386      Value::MatrixI16(m) => m.to_html(),
1387      #[cfg(all(feature = "matrix", feature = "i32"))]
1388      Value::MatrixI32(m) => m.to_html(),
1389      #[cfg(all(feature = "matrix", feature = "i64"))]
1390      Value::MatrixI64(m) => m.to_html(),
1391      #[cfg(all(feature = "matrix", feature = "i128"))]
1392      Value::MatrixI128(m) => m.to_html(),
1393      #[cfg(all(feature = "matrix", feature = "f64"))]
1394      Value::MatrixF64(m) => m.to_html(),
1395      #[cfg(all(feature = "matrix", feature = "f32"))]
1396      Value::MatrixF32(m) => m.to_html(),
1397      #[cfg(feature = "matrix")]
1398      Value::MatrixIndex(m) => m.to_html(),
1399      #[cfg(all(feature = "matrix", feature = "bool"))]
1400      Value::MatrixBool(m) => m.to_html(),
1401      #[cfg(all(feature = "matrix", feature = "string"))]
1402      Value::MatrixString(m) => m.to_html(),
1403      #[cfg(feature = "matrix")]
1404      Value::MatrixValue(m) => m.to_html(),
1405      #[cfg(all(feature = "matrix", feature = "rational"))]
1406      Value::MatrixR64(m) => m.to_html(),
1407      #[cfg(all(feature = "matrix", feature = "complex"))]
1408      Value::MatrixC64(m) => m.to_html(),
1409      #[cfg(feature = "atom")]
1410      Value::Atom(a) => format!("<span class=\"mech-atom\"><span class=\"mech-atom-grave\">`</span><span class=\"mech-atom-name\">{}</span></span>",a.borrow()),
1411      #[cfg(feature = "set")]
1412      Value::Set(s) => s.borrow().to_html(),
1413      #[cfg(feature = "map")]
1414      Value::Map(m) => m.borrow().to_html(),
1415      #[cfg(feature = "table")]
1416      Value::Table(t) => t.borrow().to_html(),
1417      #[cfg(feature = "record")]
1418      Value::Record(r) => r.borrow().to_html(),
1419      #[cfg(feature = "tuple")]
1420      Value::Tuple(t) => t.borrow().to_html(),
1421      #[cfg(feature = "enum")]
1422      Value::Enum(e) => e.borrow().to_html(),
1423      Value::MutableReference(m) => {
1424        let inner = m.borrow();
1425        format!("<span class='mech-reference'>{}</span>", inner.to_html())
1426      },
1427      _ => "???".to_string(),
1428    }
1429  }
1430
1431  pub fn shape(&self) -> Vec<usize> {
1432    match self {
1433      #[cfg(feature = "rational")]
1434      Value::R64(x) => vec![1,1],
1435      #[cfg(feature = "complex")]
1436      Value::C64(x) => vec![1,1],
1437      #[cfg(feature = "u8")]
1438      Value::U8(x) => vec![1,1],
1439      #[cfg(feature = "u16")]
1440      Value::U16(x) => vec![1,1],
1441      #[cfg(feature = "u32")]
1442      Value::U32(x) => vec![1,1],
1443      #[cfg(feature = "u64")]
1444      Value::U64(x) => vec![1,1],
1445      #[cfg(feature = "u128")]
1446      Value::U128(x) => vec![1,1],
1447      #[cfg(feature = "i8")]
1448      Value::I8(x) => vec![1,1],
1449      #[cfg(feature = "i16")]
1450      Value::I16(x) => vec![1,1],
1451      #[cfg(feature = "i32")]
1452      Value::I32(x) => vec![1,1],
1453      #[cfg(feature = "i64")]
1454      Value::I64(x) => vec![1,1],
1455      #[cfg(feature = "i128")]
1456      Value::I128(x) => vec![1,1],
1457      #[cfg(feature = "f32")]
1458      Value::F32(x) => vec![1,1],
1459      #[cfg(feature = "f64")]
1460      Value::F64(x) => vec![1,1],
1461      #[cfg(feature = "string")]
1462      Value::String(x) => vec![1,1],
1463      #[cfg(feature = "bool")]
1464      Value::Bool(x) => vec![1,1],
1465      #[cfg(feature = "atom")]
1466      Value::Atom(x) => vec![1,1],
1467      #[cfg(feature = "matrix")]
1468      Value::MatrixIndex(x) => x.shape(),
1469      #[cfg(all(feature = "matrix", feature = "bool"))]
1470      Value::MatrixBool(x) => x.shape(),
1471      #[cfg(all(feature = "matrix", feature = "u8"))]
1472      Value::MatrixU8(x) => x.shape(),
1473      #[cfg(all(feature = "matrix", feature = "u16"))]
1474      Value::MatrixU16(x) => x.shape(),
1475      #[cfg(all(feature = "matrix", feature = "u32"))]
1476      Value::MatrixU32(x) => x.shape(),
1477      #[cfg(all(feature = "matrix", feature = "u64"))]
1478      Value::MatrixU64(x) => x.shape(),
1479      #[cfg(all(feature = "matrix", feature = "u128"))]
1480      Value::MatrixU128(x) => x.shape(),
1481      #[cfg(all(feature = "matrix", feature = "i8"))]
1482      Value::MatrixI8(x) => x.shape(),
1483      #[cfg(all(feature = "matrix", feature = "i16"))]
1484      Value::MatrixI16(x) => x.shape(),
1485      #[cfg(all(feature = "matrix", feature = "i32"))]
1486      Value::MatrixI32(x) => x.shape(),
1487      #[cfg(all(feature = "matrix", feature = "i64"))]
1488      Value::MatrixI64(x) => x.shape(),
1489      #[cfg(all(feature = "matrix", feature = "i128"))]
1490      Value::MatrixI128(x) => x.shape(),
1491      #[cfg(all(feature = "matrix", feature = "f32"))]
1492      Value::MatrixF32(x) => x.shape(),
1493      #[cfg(all(feature = "matrix", feature = "f64"))]
1494      Value::MatrixF64(x) => x.shape(),
1495      #[cfg(all(feature = "matrix", feature = "string"))]
1496      Value::MatrixString(x) => x.shape(),
1497      #[cfg(feature = "matrix")]
1498      Value::MatrixValue(x) => x.shape(),
1499      #[cfg(all(feature = "matrix", feature = "rational"))]
1500      Value::MatrixR64(x) => x.shape(),
1501      #[cfg(all(feature = "matrix", feature = "complex"))]
1502      Value::MatrixC64(x) => x.shape(),
1503      #[cfg(feature = "enum")]
1504      Value::Enum(x) => vec![1,1],
1505      #[cfg(feature = "table")]
1506      Value::Table(x) => x.borrow().shape(),
1507      #[cfg(feature = "set")]
1508      Value::Set(x) => vec![1,x.borrow().set.len()],
1509      #[cfg(feature = "map")]
1510      Value::Map(x) => vec![1,x.borrow().map.len()],
1511      #[cfg(feature = "record")]
1512      Value::Record(x) => x.borrow().shape(),
1513      #[cfg(feature = "tuple")]
1514      Value::Tuple(x) => vec![1,x.borrow().size()],
1515      Value::Index(x) => vec![1,1],
1516      Value::MutableReference(x) => x.borrow().shape(),
1517      Value::Empty => vec![0,0],
1518      Value::IndexAll => vec![0,0],
1519      Value::Kind(_) => vec![0,0],
1520      Value::Id(x) => vec![0,0],
1521    }
1522  }
1523
1524  pub fn deref_kind(&self) -> ValueKind {
1525    match self {
1526      Value::MutableReference(x) => x.borrow().kind(),
1527      x => x.kind(),
1528    }
1529  }
1530
1531  pub fn kind(&self) -> ValueKind {
1532    match self {
1533      #[cfg(feature = "complex")]
1534      Value::C64(_) => ValueKind::C64,
1535      #[cfg(feature = "rational")]
1536      Value::R64(_) => ValueKind::R64,
1537      #[cfg(feature = "u8")]
1538      Value::U8(_) => ValueKind::U8,
1539      #[cfg(feature = "u16")]
1540      Value::U16(_) => ValueKind::U16,
1541      #[cfg(feature = "u32")]
1542      Value::U32(_) => ValueKind::U32,
1543      #[cfg(feature = "u64")]
1544      Value::U64(_) => ValueKind::U64,
1545      #[cfg(feature = "u128")]
1546      Value::U128(_) => ValueKind::U128,
1547      #[cfg(feature = "i8")]
1548      Value::I8(_) => ValueKind::I8,
1549      #[cfg(feature = "i16")]
1550      Value::I16(_) => ValueKind::I16,
1551      #[cfg(feature = "i32")]
1552      Value::I32(_) => ValueKind::I32,
1553      #[cfg(feature = "i64")]
1554      Value::I64(_) => ValueKind::I64,
1555      #[cfg(feature = "i128")]
1556      Value::I128(_) => ValueKind::I128,
1557      #[cfg(feature = "f32")]
1558      Value::F32(_) => ValueKind::F32,
1559      #[cfg(feature = "f64")]
1560      Value::F64(_) => ValueKind::F64,
1561      #[cfg(feature = "string")]
1562      Value::String(_) => ValueKind::String,
1563      #[cfg(feature = "bool")]
1564      Value::Bool(_) => ValueKind::Bool,
1565      #[cfg(feature = "atom")]
1566      Value::Atom(x) => ValueKind::Atom((x.borrow().0)),
1567      #[cfg(feature = "matrix")]
1568      Value::MatrixValue(x) => ValueKind::Matrix(Box::new(ValueKind::Any),x.shape()),
1569      #[cfg(feature = "matrix")]
1570      Value::MatrixIndex(x) => ValueKind::Matrix(Box::new(ValueKind::Index),x.shape()),
1571      #[cfg(all(feature = "matrix", feature = "bool"))]
1572      Value::MatrixBool(x) => ValueKind::Matrix(Box::new(ValueKind::Bool), x.shape()),
1573      #[cfg(all(feature = "matrix", feature = "u8"))]
1574      Value::MatrixU8(x) => ValueKind::Matrix(Box::new(ValueKind::U8), x.shape()),
1575      #[cfg(all(feature = "matrix", feature = "u16"))]
1576      Value::MatrixU16(x) => ValueKind::Matrix(Box::new(ValueKind::U16), x.shape()),
1577      #[cfg(all(feature = "matrix", feature = "u32"))]
1578      Value::MatrixU32(x) => ValueKind::Matrix(Box::new(ValueKind::U32), x.shape()),
1579      #[cfg(all(feature = "matrix", feature = "u64"))]
1580      Value::MatrixU64(x) => ValueKind::Matrix(Box::new(ValueKind::U64), x.shape()),
1581      #[cfg(all(feature = "matrix", feature = "u128"))]
1582      Value::MatrixU128(x) => ValueKind::Matrix(Box::new(ValueKind::U128), x.shape()),
1583      #[cfg(all(feature = "matrix", feature = "i8"))]
1584      Value::MatrixI8(x) => ValueKind::Matrix(Box::new(ValueKind::I8), x.shape()),
1585      #[cfg(all(feature = "matrix", feature = "i16"))]
1586      Value::MatrixI16(x) => ValueKind::Matrix(Box::new(ValueKind::I16), x.shape()),
1587      #[cfg(all(feature = "matrix", feature = "i32"))]
1588      Value::MatrixI32(x) => ValueKind::Matrix(Box::new(ValueKind::I32), x.shape()),
1589      #[cfg(all(feature = "matrix", feature = "i64"))]
1590      Value::MatrixI64(x) => ValueKind::Matrix(Box::new(ValueKind::I64), x.shape()),
1591      #[cfg(all(feature = "matrix", feature = "i128"))]
1592      Value::MatrixI128(x) => ValueKind::Matrix(Box::new(ValueKind::I128), x.shape()),
1593      #[cfg(all(feature = "matrix", feature = "f32"))]
1594      Value::MatrixF32(x) => ValueKind::Matrix(Box::new(ValueKind::F32), x.shape()),
1595      #[cfg(all(feature = "matrix", feature = "f64"))]
1596      Value::MatrixF64(x) => ValueKind::Matrix(Box::new(ValueKind::F64), x.shape()),
1597      #[cfg(all(feature = "matrix", feature = "string"))]
1598      Value::MatrixString(x) => ValueKind::Matrix(Box::new(ValueKind::String), x.shape()),
1599      #[cfg(all(feature = "matrix", feature = "rational"))]
1600      Value::MatrixR64(x) => ValueKind::Matrix(Box::new(ValueKind::R64), x.shape()),
1601      #[cfg(all(feature = "matrix", feature = "complex"))]
1602      Value::MatrixC64(x) => ValueKind::Matrix(Box::new(ValueKind::C64), x.shape()),
1603      #[cfg(feature = "table")]
1604      Value::Table(x) => x.borrow().kind(),
1605      #[cfg(feature = "set")]
1606      Value::Set(x) => x.borrow().kind(),
1607      #[cfg(feature = "map")]
1608      Value::Map(x) => x.borrow().kind(),
1609      #[cfg(feature = "record")]
1610      Value::Record(x) => x.borrow().kind(),
1611      #[cfg(feature = "tuple")]
1612      Value::Tuple(x) => x.borrow().kind(),
1613      #[cfg(feature = "enum")]
1614      Value::Enum(x) => x.borrow().kind(),
1615      Value::MutableReference(x) => ValueKind::Reference(Box::new(x.borrow().kind())),
1616      Value::Empty => ValueKind::Empty,
1617      Value::IndexAll => ValueKind::Empty,
1618      Value::Id(x) => ValueKind::Id,
1619      Value::Index(x) => ValueKind::Index,
1620      Value::Kind(x) => x.clone(),
1621    }
1622  }
1623
1624  #[cfg(feature = "matrix")]
1625  pub fn is_matrix(&self) -> bool {
1626    match self {
1627      #[cfg(feature = "matrix")]
1628      Value::MatrixIndex(_) => true,
1629      #[cfg(all(feature = "matrix", feature = "bool"))]
1630      Value::MatrixBool(_) => true,
1631      #[cfg(all(feature = "matrix", feature = "u8"))]
1632      Value::MatrixU8(_) => true,
1633      #[cfg(all(feature = "matrix", feature = "u16"))]
1634      Value::MatrixU16(_) => true,
1635      #[cfg(all(feature = "matrix", feature = "u32"))]
1636      Value::MatrixU32(_) => true,
1637      #[cfg(all(feature = "matrix", feature = "u64"))]
1638      Value::MatrixU64(_) => true,
1639      #[cfg(all(feature = "matrix", feature = "u128"))]
1640      Value::MatrixU128(_) => true,
1641      #[cfg(all(feature = "matrix", feature = "i8"))]
1642      Value::MatrixI8(_) => true,
1643      #[cfg(all(feature = "matrix", feature = "i16"))]
1644      Value::MatrixI16(_) => true,
1645      #[cfg(all(feature = "matrix", feature = "i32"))]
1646      Value::MatrixI32(_) => true,
1647      #[cfg(all(feature = "matrix", feature = "i64"))]
1648      Value::MatrixI64(_) => true,
1649      #[cfg(all(feature = "matrix", feature = "i128"))]
1650      Value::MatrixI128(_) => true,
1651      #[cfg(all(feature = "matrix", feature = "f32"))]
1652      Value::MatrixF32(_) => true,
1653      #[cfg(all(feature = "matrix", feature = "f64"))]
1654      Value::MatrixF64(_) => true,
1655      #[cfg(all(feature = "matrix", feature = "string"))]
1656      Value::MatrixString(_) => true,
1657      #[cfg(all(feature = "matrix", feature = "rational"))]
1658      Value::MatrixR64(_) => true,
1659      #[cfg(all(feature = "matrix", feature = "complex"))]
1660      Value::MatrixC64(_) => true,
1661      #[cfg(feature = "matrix")]
1662      Value::MatrixValue(_) => true,
1663      _ => false,
1664    }
1665  }
1666
1667  pub fn is_scalar(&self) -> bool {
1668    match self {
1669      #[cfg(feature = "u8")]
1670      Value::U8(_) => true,
1671      #[cfg(feature = "u16")]
1672      Value::U16(_) => true,
1673      #[cfg(feature = "u32")]
1674      Value::U32(_) => true,
1675      #[cfg(feature = "u64")]
1676      Value::U64(_) => true,
1677      #[cfg(feature = "u128")]
1678      Value::U128(_) => true,
1679      #[cfg(feature = "i8")]
1680      Value::I8(_) => true,
1681      #[cfg(feature = "i16")]
1682      Value::I16(_) => true,
1683      #[cfg(feature = "i32")]
1684      Value::I32(_) => true,
1685      #[cfg(feature = "i64")]
1686      Value::I64(_) => true,
1687      #[cfg(feature = "i128")]
1688      Value::I128(_) => true,
1689      #[cfg(feature = "f32")]
1690      Value::F32(_) => true,
1691      #[cfg(feature = "f64")]
1692      Value::F64(_) => true,
1693      #[cfg(feature = "bool")]
1694      Value::Bool(_) => true,
1695      #[cfg(feature = "string")]
1696      Value::String(_) => true,
1697      #[cfg(feature = "atom")]
1698      Value::Atom(_) => true,
1699      Value::Index(_) => true,
1700      _ => false,
1701    }
1702  }
1703
1704  #[cfg(feature = "bool")]
1705  pub fn as_bool(&self) -> Option<Ref<bool>> {if let Value::Bool(v) = self { Some(v.clone()) } else if let Value::MutableReference(val) = self { val.borrow().as_bool() } else { None }}
1706  
1707  impl_as_type!(i8);
1708  impl_as_type!(i16);
1709  impl_as_type!(i32);
1710  impl_as_type!(i64);
1711  impl_as_type!(i128);
1712  impl_as_type!(u8);
1713  impl_as_type!(u16);
1714  impl_as_type!(u32);
1715  impl_as_type!(u64);
1716  impl_as_type!(u128);
1717
1718  #[cfg(feature = "string")]
1719  pub fn as_string(&self) -> Option<Ref<String>> {
1720    match self {
1721      #[cfg(feature = "string")]
1722      Value::String(v) => Some(v.clone()),
1723      #[cfg(feature = "u8")]
1724      Value::U8(v) => Some(Ref::new(v.borrow().to_string())),
1725      #[cfg(feature = "u16")]
1726      Value::U16(v) => Some(Ref::new(v.borrow().to_string())),
1727      #[cfg(feature = "u32")]
1728      Value::U32(v) => Some(Ref::new(v.borrow().to_string())),
1729      #[cfg(feature = "u64")]
1730      Value::U64(v) => Some(Ref::new(v.borrow().to_string())),
1731      #[cfg(feature = "u128")]
1732      Value::U128(v) => Some(Ref::new(v.borrow().to_string())),
1733      #[cfg(feature = "i8")]
1734      Value::I8(v) => Some(Ref::new(v.borrow().to_string())),
1735      #[cfg(feature = "i16")]
1736      Value::I16(v) => Some(Ref::new(v.borrow().to_string())),
1737      #[cfg(feature = "i32")]
1738      Value::I32(v) => Some(Ref::new(v.borrow().to_string())),
1739      #[cfg(feature = "i64")]
1740      Value::I64(v) => Some(Ref::new(v.borrow().to_string())),
1741      #[cfg(feature = "i128")]
1742      Value::I128(v) => Some(Ref::new(v.borrow().to_string())),
1743      #[cfg(feature = "f32")]
1744      Value::F32(v) => Some(Ref::new(format!("{}", v.borrow().0))),
1745      #[cfg(feature = "f64")]
1746      Value::F64(v) => Some(Ref::new(format!("{}", v.borrow().0))),
1747      #[cfg(feature = "bool")]
1748      Value::Bool(v) => Some(Ref::new(format!("{}", v.borrow()))),
1749      #[cfg(feature = "rational")]
1750      Value::R64(v) => Some(Ref::new(v.borrow().to_string())),
1751      #[cfg(feature = "complex")]
1752      Value::C64(v) => Some(Ref::new(v.borrow().to_string())),
1753      Value::MutableReference(val) => val.borrow().as_string(),
1754      _ => None,
1755    }
1756  }
1757
1758  #[cfg(feature = "rational")]
1759  pub fn as_r64(&self) -> Option<Ref<R64>> {
1760    match self {
1761      Value::R64(v) => Some(v.clone()),
1762      #[cfg(feature = "f32")]
1763      Value::F32(v) => Some(Ref::new(R64::new(v.borrow().0 as i64, 1))),
1764      #[cfg(feature = "f64")]
1765      Value::F64(v) => Some(Ref::new(R64::new(v.borrow().0 as i64, 1))),
1766      #[cfg(feature = "u8")]
1767      Value::U8(v) => Some(Ref::new(R64::new(*v.borrow() as i64, 1))),
1768      #[cfg(feature = "u16")]
1769      Value::U16(v) => Some(Ref::new(R64::new(*v.borrow() as i64, 1))),
1770      #[cfg(feature = "u32")]
1771      Value::U32(v) => Some(Ref::new(R64::new(*v.borrow() as i64, 1))),
1772      #[cfg(feature = "u64")]
1773      Value::U64(v) => Some(Ref::new(R64::new(*v.borrow() as i64, 1))),
1774      #[cfg(feature = "u128")]
1775      Value::U128(v) => Some(Ref::new(R64::new(*v.borrow() as i64, 1))),
1776      #[cfg(feature = "i8")]
1777      Value::I8(v) => Some(Ref::new(R64::new(*v.borrow() as i64, 1))),
1778      #[cfg(feature = "i16")]
1779      Value::I16(v) => Some(Ref::new(R64::new(*v.borrow() as i64, 1))),
1780      #[cfg(feature = "i32")]
1781      Value::I32(v) => Some(Ref::new(R64::new(*v.borrow() as i64, 1))),
1782      #[cfg(feature = "i64")]
1783      Value::I64(v) => Some(Ref::new(R64::new(*v.borrow() as i64, 1))),
1784      #[cfg(feature = "i128")]
1785      Value::I128(v) => Some(Ref::new(R64::new(*v.borrow() as i64, 1))),
1786      Value::MutableReference(val) => val.borrow().as_r64(),
1787      _ => None,
1788    }
1789  }
1790
1791  #[cfg(feature = "complex")]
1792  pub fn as_c64(&self) -> Option<Ref<C64>> {
1793    match self {
1794      Value::C64(v) => Some(v.clone()),
1795      #[cfg(feature = "f32")]
1796      Value::F32(v) =>  Some(Ref::new(C64::new(v.borrow().0 as f64, 0.0))),
1797      #[cfg(feature = "f64")]
1798      Value::F64(v) =>  Some(Ref::new(C64::new(v.borrow().0, 0.0))),
1799      #[cfg(feature = "u8")]
1800      Value::U8(v) =>   Some(Ref::new(C64::new(*v.borrow() as f64, 0.0))),
1801      #[cfg(feature = "u16")]
1802      Value::U16(v) =>  Some(Ref::new(C64::new(*v.borrow() as f64, 0.0))),
1803      #[cfg(feature = "u32")]
1804      Value::U32(v) =>  Some(Ref::new(C64::new(*v.borrow() as f64, 0.0))),
1805      #[cfg(feature = "u64")]
1806      Value::U64(v) =>  Some(Ref::new(C64::new(*v.borrow() as f64, 0.0))),
1807      #[cfg(feature = "u128")]
1808      Value::U128(v) => Some(Ref::new(C64::new(*v.borrow() as f64, 0.0))),
1809      #[cfg(feature = "i8")]
1810      Value::I8(v) =>   Some(Ref::new(C64::new(*v.borrow() as f64, 0.0))),
1811      #[cfg(feature = "i16")]
1812      Value::I16(v) =>  Some(Ref::new(C64::new(*v.borrow() as f64, 0.0))),
1813      #[cfg(feature = "i32")]
1814      Value::I32(v) =>  Some(Ref::new(C64::new(*v.borrow() as f64, 0.0))),
1815      #[cfg(feature = "i64")]
1816      Value::I64(v) =>  Some(Ref::new(C64::new(*v.borrow() as f64, 0.0))),
1817      #[cfg(feature = "i128")]
1818      Value::I128(v) => Some(Ref::new(C64::new(*v.borrow() as f64, 0.0))),
1819      Value::MutableReference(val) => val.borrow().as_c64(),
1820      _ => None,
1821    }
1822  }
1823
1824  #[cfg(feature = "f32")]
1825  pub fn as_f32(&self) -> Option<Ref<F32>> {
1826    match self {
1827      #[cfg(feature = "u8")]
1828      Value::U8(v) => Some(Ref::new(F32::new(*v.borrow() as f32))),
1829      #[cfg(feature = "u16")]
1830      Value::U16(v) => Some(Ref::new(F32::new(*v.borrow() as f32))),
1831      #[cfg(feature = "u32")]
1832      Value::U32(v) => Some(Ref::new(F32::new(*v.borrow() as f32))),
1833      #[cfg(feature = "u64")]
1834      Value::U64(v) => Some(Ref::new(F32::new(*v.borrow() as f32))),
1835      #[cfg(feature = "u128")]
1836      Value::U128(v) => Some(Ref::new(F32::new(*v.borrow() as f32))),
1837      #[cfg(feature = "i8")]
1838      Value::I8(v) => Some(Ref::new(F32::new(*v.borrow() as f32))),
1839      #[cfg(feature = "i16")]
1840      Value::I16(v) => Some(Ref::new(F32::new(*v.borrow() as f32))),
1841      #[cfg(feature = "i32")]
1842      Value::I32(v) => Some(Ref::new(F32::new(*v.borrow() as f32))),
1843      #[cfg(feature = "i64")]
1844      Value::I64(v) => Some(Ref::new(F32::new(*v.borrow() as f32))),
1845      #[cfg(feature = "i128")]
1846      Value::I128(v) => Some(Ref::new(F32::new(*v.borrow() as f32))),
1847      #[cfg(feature = "f32")]
1848      Value::F32(v) => Some(v.clone()),
1849      #[cfg(feature = "f64")]
1850      Value::F64(v) => Some(Ref::new(F32::new((*v.borrow()).0 as f32))),
1851      Value::MutableReference(val) => val.borrow().as_f32(),
1852      _ => None,
1853    }
1854  }
1855
1856  #[cfg(feature = "f64")]
1857  pub fn as_f64(&self) -> Option<Ref<F64>> {
1858    match self {
1859      #[cfg(feature = "u8")]
1860      Value::U8(v) => Some(Ref::new(F64::new(*v.borrow() as f64))),
1861      #[cfg(feature = "u16")]
1862      Value::U16(v) => Some(Ref::new(F64::new(*v.borrow() as f64))),
1863      #[cfg(feature = "u32")]
1864      Value::U32(v) => Some(Ref::new(F64::new(*v.borrow() as f64))),
1865      #[cfg(feature = "u64")]
1866      Value::U64(v) => Some(Ref::new(F64::new(*v.borrow() as f64))),
1867      #[cfg(feature = "u128")]
1868      Value::U128(v) => Some(Ref::new(F64::new(*v.borrow() as f64))),
1869      #[cfg(feature = "i8")]
1870      Value::I8(v) => Some(Ref::new(F64::new(*v.borrow() as f64))),
1871      #[cfg(feature = "i16")]
1872      Value::I16(v) => Some(Ref::new(F64::new(*v.borrow() as f64))),
1873      #[cfg(feature = "i32")]
1874      Value::I32(v) => Some(Ref::new(F64::new(*v.borrow() as f64))),
1875      #[cfg(feature = "i64")]
1876      Value::I64(v) => Some(Ref::new(F64::new(*v.borrow() as f64))),
1877      #[cfg(feature = "i128")]
1878      Value::I128(v) => Some(Ref::new(F64::new(*v.borrow() as f64))),
1879      Value::F64(v) => Some(v.clone()),
1880      Value::MutableReference(val) => val.borrow().as_f64(),
1881      _ => None,
1882    }
1883  }
1884
1885  #[cfg(all(feature = "matrix", feature = "bool"))]
1886  pub fn as_vecbool(&self) -> Option<Vec<bool>> {if let Value::MatrixBool(v)  = self { Some(v.as_vec()) } else if let Value::Bool(v) = self { Some(vec![v.borrow().clone()]) } else if let Value::MutableReference(val) = self { val.borrow().as_vecbool()  } else { None }}
1887  
1888  #[cfg(all(feature = "matrix", feature = "f64"))]
1889  pub fn as_vecf64(&self) -> Option<Vec<F64>> { if let Value::MatrixF64(v) = self { Some(v.as_vec()) } else if let Value::F64(v) = self { Some(vec![v.borrow().clone()]) } else if let Value::MutableReference(val) = self { val.borrow().as_vecf64() } else if let Some(v) = self.as_f64() { Some(vec![v.borrow().clone()]) } else { None } }
1890  #[cfg(all(feature = "matrix", feature = "f32"))]
1891  pub fn as_vecf32(&self) -> Option<Vec<F32>> { if let Value::MatrixF32(v) = self { Some(v.as_vec()) } else if let Value::F32(v) = self { Some(vec![v.borrow().clone()]) } else if let Value::MutableReference(val) = self { val.borrow().as_vecf32() } else if let Some(v) = self.as_f32() { Some(vec![v.borrow().clone()]) } else { None } }
1892
1893  #[cfg(all(feature = "matrix", feature = "u8"))]
1894  pub fn as_vecu8(&self) -> Option<Vec<u8>> { if let Value::MatrixU8(v) = self { Some(v.as_vec()) } else if let Value::U8(v) = self { Some(vec![v.borrow().clone()]) } else if let Value::MutableReference(val) = self { val.borrow().as_vecu8() } else if let Some(v) = self.as_u8() { Some(vec![v.borrow().clone()]) } else { None } }
1895  #[cfg(all(feature = "matrix", feature = "u16"))]
1896  pub fn as_vecu16(&self) -> Option<Vec<u16>> { if let Value::MatrixU16(v) = self { Some(v.as_vec()) } else if let Value::U16(v) = self { Some(vec![v.borrow().clone()]) } else if let Value::MutableReference(val) = self { val.borrow().as_vecu16() } else if let Some(v) = self.as_u16() { Some(vec![v.borrow().clone()]) } else { None } }
1897  #[cfg(all(feature = "matrix", feature = "u32"))]
1898  pub fn as_vecu32(&self) -> Option<Vec<u32>> { if let Value::MatrixU32(v) = self { Some(v.as_vec()) } else if let Value::U32(v) = self { Some(vec![v.borrow().clone()]) } else if let Value::MutableReference(val) = self { val.borrow().as_vecu32() } else if let Some(v) = self.as_u32() { Some(vec![v.borrow().clone()]) } else { None } }
1899  #[cfg(all(feature = "matrix", feature = "u64"))]
1900  pub fn as_vecu64(&self) -> Option<Vec<u64>> { if let Value::MatrixU64(v) = self { Some(v.as_vec()) } else if let Value::U64(v) = self { Some(vec![v.borrow().clone()]) } else if let Value::MutableReference(val) = self { val.borrow().as_vecu64() } else if let Some(v) = self.as_u64() { Some(vec![v.borrow().clone()]) } else { None } }
1901  #[cfg(all(feature = "matrix", feature = "u128"))]
1902  pub fn as_vecu128(&self) -> Option<Vec<u128>> { if let Value::MatrixU128(v) = self { Some(v.as_vec()) } else if let Value::U128(v) = self { Some(vec![v.borrow().clone()]) } else if let Value::MutableReference(val) = self { val.borrow().as_vecu128() } else if let Some(v) = self.as_u128() { Some(vec![v.borrow().clone()]) } else { None } }
1903
1904  #[cfg(all(feature = "matrix", feature = "i8"))]
1905  pub fn as_veci8(&self) -> Option<Vec<i8>> { if let Value::MatrixI8(v) = self { Some(v.as_vec()) } else if let Value::I8(v) = self { Some(vec![v.borrow().clone()]) } else if let Value::MutableReference(val) = self { val.borrow().as_veci8() } else if let Some(v) = self.as_i8() { Some(vec![v.borrow().clone()]) } else { None } }
1906  #[cfg(all(feature = "matrix", feature = "i16"))]
1907  pub fn as_veci16(&self) -> Option<Vec<i16>> { if let Value::MatrixI16(v) = self { Some(v.as_vec()) } else if let Value::I16(v) = self { Some(vec![v.borrow().clone()]) } else if let Value::MutableReference(val) = self { val.borrow().as_veci16() } else if let Some(v) = self.as_i16() { Some(vec![v.borrow().clone()]) } else { None } }
1908  #[cfg(all(feature = "matrix", feature = "i32"))]
1909  pub fn as_veci32(&self) -> Option<Vec<i32>> { if let Value::MatrixI32(v) = self { Some(v.as_vec()) } else if let Value::I32(v) = self { Some(vec![v.borrow().clone()]) } else if let Value::MutableReference(val) = self { val.borrow().as_veci32() } else if let Some(v) = self.as_i32() { Some(vec![v.borrow().clone()]) } else { None } }
1910  #[cfg(all(feature = "matrix", feature = "i64"))]
1911  pub fn as_veci64(&self) -> Option<Vec<i64>> { if let Value::MatrixI64(v) = self { Some(v.as_vec()) } else if let Value::I64(v) = self { Some(vec![v.borrow().clone()]) } else if let Value::MutableReference(val) = self { val.borrow().as_veci64() } else if let Some(v) = self.as_i64() { Some(vec![v.borrow().clone()]) } else { None } }
1912  #[cfg(all(feature = "matrix", feature = "i128"))]
1913  pub fn as_veci128(&self) -> Option<Vec<i128>> { if let Value::MatrixI128(v) = self { Some(v.as_vec()) } else if let Value::I128(v) = self { Some(vec![v.borrow().clone()]) } else if let Value::MutableReference(val) = self { val.borrow().as_veci128() } else if let Some(v) = self.as_i128() { Some(vec![v.borrow().clone()]) } else { None } }
1914
1915  #[cfg(all(feature = "matrix", feature = "string"))]
1916  pub fn as_vecstring(&self) -> Option<Vec<String>> {if let Value::MatrixString(v)  = self { Some(v.as_vec()) } else if let Value::String(v) = self { Some(vec![v.borrow().clone()]) } else if let Value::MutableReference(val) = self { val.borrow().as_vecstring()  } else { None }}
1917
1918  #[cfg(all(feature = "matrix", feature = "rational"))]
1919  pub fn as_vecr64(&self) -> Option<Vec<R64>> {if let Value::MatrixR64(v)  = self { Some(v.as_vec()) } else if let Value::R64(v) = self { Some(vec![v.borrow().clone()]) } else if let Value::MutableReference(val) = self { val.borrow().as_vecr64()  } else { None }}
1920  #[cfg(all(feature = "matrix", feature = "complex"))]
1921  pub fn as_vecc64(&self) -> Option<Vec<C64>> {if let Value::MatrixC64(v)  = self { Some(v.as_vec()) } else if let Value::C64(v) = self { Some(vec![v.borrow().clone()]) } else if let Value::MutableReference(val) = self { val.borrow().as_vecc64()  } else { None }}
1922
1923  pub fn as_vecusize(&self) -> Option<Vec<usize>> {
1924    match self {
1925      #[cfg(feature = "u8")]
1926      Value::U8(v) => Some(vec![*v.borrow() as usize]),
1927      #[cfg(feature = "u16")]
1928      Value::U16(v) => Some(vec![*v.borrow() as usize]),
1929      #[cfg(feature = "u32")]
1930      Value::U32(v) => Some(vec![*v.borrow() as usize]),
1931      #[cfg(feature = "u64")]
1932      Value::U64(v) => Some(vec![*v.borrow() as usize]),
1933      #[cfg(feature = "u128")]
1934      Value::U128(v) => Some(vec![*v.borrow() as usize]),
1935      #[cfg(feature = "i8")]
1936      Value::I8(v) => Some(vec![*v.borrow() as usize]),
1937      #[cfg(feature = "i16")]
1938      Value::I16(v) => Some(vec![*v.borrow() as usize]),
1939      #[cfg(feature = "i32")]
1940      Value::I32(v) => Some(vec![*v.borrow() as usize]),
1941      #[cfg(feature = "i64")]
1942      Value::I64(v) => Some(vec![*v.borrow() as usize]),
1943      #[cfg(feature = "i128")]
1944      Value::I128(v) => Some(vec![*v.borrow() as usize]),
1945      #[cfg(feature = "f32")]
1946      Value::F32(v) => Some(vec![(*v.borrow()).0 as usize]),
1947      #[cfg(feature = "f64")]
1948      Value::F64(v) => Some(vec![(*v.borrow()).0 as usize]),
1949      #[cfg(feature = "matrix")]
1950      Value::MatrixIndex(v) => Some(v.as_vec()),
1951      #[cfg(all(feature = "matrix", feature = "f64"))]
1952      Value::MatrixF64(v) => Some(v.as_vec().iter().map(|x| (*x).0 as usize).collect::<Vec<usize>>()),
1953      #[cfg(all(feature = "matrix", feature = "f32"))]
1954      Value::MatrixF32(v) => Some(v.as_vec().iter().map(|x| (*x).0 as usize).collect::<Vec<usize>>()),
1955      #[cfg(all(feature = "matrix", feature = "u8"))]
1956      Value::MatrixU8(v) => Some(v.as_vec().iter().map(|x| *x as usize).collect::<Vec<usize>>()),
1957      #[cfg(all(feature = "matrix", feature = "u16"))]  
1958      Value::MatrixU16(v) => Some(v.as_vec().iter().map(|x| *x as usize).collect::<Vec<usize>>()),
1959      #[cfg(all(feature = "matrix", feature = "u32"))]
1960      Value::MatrixU32(v) => Some(v.as_vec().iter().map(|x| *x as usize).collect::<Vec<usize>>()),
1961      #[cfg(all(feature = "matrix", feature = "u64"))]
1962      Value::MatrixU64(v) => Some(v.as_vec().iter().map(|x| *x as usize).collect::<Vec<usize>>()),
1963      #[cfg(all(feature = "matrix", feature = "u128"))]
1964      Value::MatrixU128(v) => Some(v.as_vec().iter().map(|x| *x as usize).collect::<Vec<usize>>()),
1965      #[cfg(all(feature = "matrix", feature = "i8"))]
1966      Value::MatrixI8(v) => Some(v.as_vec().iter().map(|x| *x as usize).collect::<Vec<usize>>()),
1967      #[cfg(all(feature = "matrix", feature = "i16"))]
1968      Value::MatrixI16(v) => Some(v.as_vec().iter().map(|x| *x as usize).collect::<Vec<usize>>()),
1969      #[cfg(all(feature = "matrix", feature = "i32"))]
1970      Value::MatrixI32(v) => Some(v.as_vec().iter().map(|x| *x as usize).collect::<Vec<usize>>()),
1971      #[cfg(all(feature = "matrix", feature = "i128"))]
1972      Value::MatrixI128(v) => Some(v.as_vec().iter().map(|x| *x as usize).collect::<Vec<usize>>()),
1973      #[cfg(all(feature = "matrix", feature = "i64"))]
1974      Value::MatrixI64(v) => Some(v.as_vec().iter().map(|x| *x as usize).collect::<Vec<usize>>()),
1975      #[cfg(all(feature = "matrix", feature = "bool"))]
1976      Value::MatrixBool(_) => None,
1977      #[cfg(feature = "bool")]
1978      Value::Bool(_) => None,
1979      Value::MutableReference(x) => x.borrow().as_vecusize(),
1980      _ => todo!(),
1981    }
1982  }
1983
1984  pub fn as_index(&self) -> MResult<Value> {
1985    match self.as_usize() {      
1986      Some(ix) => Ok(Value::Index(Ref::new(ix))),
1987      #[cfg(feature = "matrix")]
1988      None => match self.as_vecusize() {
1989        #[cfg(feature = "matrix")]
1990        Some(x) => {
1991          let shape = self.shape();
1992          let out = Value::MatrixIndex(usize::to_matrix(x, shape[0] * shape[1],1 ));
1993          Ok(out)
1994        },
1995        #[cfg(all(feature = "matrix", feature = "bool"))]
1996        None => match self.as_vecbool() {
1997          Some(x) => {
1998            let shape = self.shape();
1999            let out = match (shape[0], shape[1]) {
2000              (1,1) => Value::Bool(Ref::new(x[0])),
2001              #[cfg(all(feature = "vectord", feature = "bool"))]
2002              (1,n) => Value::MatrixBool(Matrix::DVector(Ref::new(DVector::from_vec(x)))),
2003              #[cfg(all(feature = "vectord", feature = "bool"))]
2004              (m,1) => Value::MatrixBool(Matrix::DVector(Ref::new(DVector::from_vec(x)))),
2005              #[cfg(all(feature = "vectord", feature = "bool"))]
2006              (m,n) => Value::MatrixBool(Matrix::DVector(Ref::new(DVector::from_vec(x)))),
2007              _ => todo!(),
2008            };
2009            Ok(out)
2010          }
2011          None => match self.as_bool() {
2012            Some(x) => Ok(Value::Bool(x)),
2013            None => Err(MechError{file: file!().to_string(), tokens: vec![], msg: "".to_string(), id: line!(), kind: MechErrorKind::UnhandledIndexKind}),
2014          }
2015        }
2016        x => Err(MechError{file: file!().to_string(), tokens: vec![], msg: "".to_string(), id: line!(), kind: MechErrorKind::None}),
2017      }
2018      _ => todo!(),
2019    }
2020  }
2021
2022  pub fn as_usize(&self) -> Option<usize> {
2023    match self {      
2024      Value::Index(v) => Some(*v.borrow()),
2025      #[cfg(feature = "u8")]
2026      Value::U8(v) => Some(*v.borrow() as usize),
2027      #[cfg(feature = "u16")]
2028      Value::U16(v) => Some(*v.borrow() as usize),
2029      #[cfg(feature = "u32")]
2030      Value::U32(v) => Some(*v.borrow() as usize),
2031      #[cfg(feature = "u64")]
2032      Value::U64(v) => Some(*v.borrow() as usize),
2033      #[cfg(feature = "u128")]
2034      Value::U128(v) => Some(*v.borrow() as usize),
2035      #[cfg(feature = "i8")]
2036      Value::I8(v) => Some(*v.borrow() as usize),
2037      #[cfg(feature = "i16")]
2038      Value::I16(v) => Some(*v.borrow() as usize),
2039      #[cfg(feature = "i32")]
2040      Value::I32(v) => Some(*v.borrow() as usize),
2041      #[cfg(feature = "i64")]
2042      Value::I64(v) => Some(*v.borrow() as usize),
2043      #[cfg(feature = "i128")]
2044      Value::I128(v) => Some(*v.borrow() as usize),
2045      #[cfg(feature = "f32")]
2046      Value::F32(v) => Some((*v.borrow()).0 as usize),
2047      #[cfg(feature = "f64")]
2048      Value::F64(v) => Some((*v.borrow()).0 as usize),
2049      Value::MutableReference(v) => v.borrow().as_usize(),
2050      _ => None,
2051    }
2052  }
2053
2054  #[cfg(feature = "u8")]
2055  pub fn expect_u8(&self) -> MResult<Ref<u8>> {
2056    match self {
2057      Value::U8(v) => Ok(v.clone()),
2058      Value::MutableReference(v) => v.borrow().expect_u8(),
2059      _ => Err(MechError{file: file!().to_string(), tokens: vec![], msg: "".to_string(), id: line!(), kind: MechErrorKind::None}),
2060    }
2061  }
2062
2063  #[cfg(feature = "f64")]
2064  pub fn expect_f64(&self) -> MResult<Ref<F64>> {
2065    match self {
2066      Value::F64(v) => Ok(v.clone()),
2067      Value::MutableReference(v) => v.borrow().expect_f64(),
2068      _ => Err(MechError{file: file!().to_string(), tokens: vec![], msg: "".to_string(), id: line!(), kind: MechErrorKind::None}),
2069    }
2070  }
2071
2072}
2073
2074#[cfg(feature = "pretty_print")]
2075impl PrettyPrint for Value {
2076  fn pretty_print(&self) -> String {
2077    let mut builder = Builder::default();
2078    match self {
2079      #[cfg(feature = "u8")]
2080      Value::U8(x)   => {builder.push_record(vec![format!("{}",x.borrow())]);},
2081      #[cfg(feature = "u16")]
2082      Value::U16(x)  => {builder.push_record(vec![format!("{}",x.borrow())]);},
2083      #[cfg(feature = "u32")]
2084      Value::U32(x)  => {builder.push_record(vec![format!("{}",x.borrow())]);},
2085      #[cfg(feature = "u64")]
2086      Value::U64(x)  => {builder.push_record(vec![format!("{}",x.borrow())]);},
2087      #[cfg(feature = "u128")]
2088      Value::U128(x) => {builder.push_record(vec![format!("{}",x.borrow())]);},
2089      #[cfg(feature = "i8")]
2090      Value::I8(x)   => {builder.push_record(vec![format!("{}",x.borrow())]);},
2091      #[cfg(feature = "i16")]
2092      Value::I16(x)  => {builder.push_record(vec![format!("{}",x.borrow())]);},
2093      #[cfg(feature = "i32")]
2094      Value::I32(x)  => {builder.push_record(vec![format!("{}",x.borrow())]);},
2095      #[cfg(feature = "i64")]
2096      Value::I64(x)  => {builder.push_record(vec![format!("{}",x.borrow())]);},
2097      #[cfg(feature = "i128")]
2098      Value::I128(x) => {builder.push_record(vec![format!("{}",x.borrow())]);},
2099      #[cfg(feature = "f32")]
2100      Value::F32(x)  => {builder.push_record(vec![format!("{}",x.borrow().0)]);},
2101      #[cfg(feature = "f64")]
2102      Value::F64(x)  => {builder.push_record(vec![format!("{}",x.borrow().0)]);},
2103      #[cfg(feature = "bool")]
2104      Value::Bool(x) => {builder.push_record(vec![format!("{}",x.borrow())]);},
2105      #[cfg(feature = "complex")]
2106      Value::C64(x) => {builder.push_record(vec![x.borrow().pretty_print()]);},
2107      #[cfg(feature = "rational")]
2108      Value::R64(x) => {builder.push_record(vec![format!("{}",x.borrow().pretty_print())]);},
2109      #[cfg(feature = "atom")]
2110      Value::Atom(x) => {builder.push_record(vec![format!("{}",x.borrow())]);},
2111      #[cfg(feature = "set")]
2112      Value::Set(x)  => {return x.borrow().pretty_print();}
2113      #[cfg(feature = "map")]
2114      Value::Map(x)  => {return x.borrow().pretty_print();}
2115      #[cfg(feature = "string")]
2116      Value::String(x) => {return format!("\"{}\"",x.borrow().clone());},
2117      #[cfg(feature = "table")]
2118      Value::Table(x)  => {return x.borrow().pretty_print();},
2119      #[cfg(feature = "tuple")]
2120      Value::Tuple(x)  => {return x.borrow().pretty_print();},
2121      #[cfg(feature = "record")]
2122      Value::Record(x) => {return x.borrow().pretty_print();},
2123      #[cfg(feature = "enum")]
2124      Value::Enum(x) => {return x.borrow().pretty_print();},
2125      #[cfg(feature = "matrix")]
2126      Value::MatrixIndex(x) => {return x.pretty_print();},
2127      #[cfg(all(feature = "matrix", feature = "bool"))]
2128      Value::MatrixBool(x) => {return x.pretty_print();},
2129      #[cfg(all(feature = "matrix", feature = "u8"))]
2130      Value::MatrixU8(x)   => {return x.pretty_print();},
2131      #[cfg(all(feature = "matrix", feature = "u16"))]
2132      Value::MatrixU16(x)  => {return x.pretty_print();},
2133      #[cfg(all(feature = "matrix", feature = "u32"))]
2134      Value::MatrixU32(x)  => {return x.pretty_print();},
2135      #[cfg(all(feature = "matrix", feature = "u64"))]
2136      Value::MatrixU64(x)  => {return x.pretty_print();},
2137      #[cfg(all(feature = "matrix", feature = "u128"))]
2138      Value::MatrixU128(x) => {return x.pretty_print();},
2139      #[cfg(all(feature = "matrix", feature = "i8"))]
2140      Value::MatrixI8(x)   => {return x.pretty_print();},
2141      #[cfg(all(feature = "matrix", feature = "i16"))]
2142      Value::MatrixI16(x)  => {return x.pretty_print();},
2143      #[cfg(all(feature = "matrix", feature = "i32"))]
2144      Value::MatrixI32(x)  => {return x.pretty_print();},
2145      #[cfg(all(feature = "matrix", feature = "i64"))]
2146      Value::MatrixI64(x)  => {return x.pretty_print();},
2147      #[cfg(all(feature = "matrix", feature = "i128"))]
2148      Value::MatrixI128(x) => {return x.pretty_print();},
2149      #[cfg(all(feature = "matrix", feature = "f32"))]
2150      Value::MatrixF32(x)  => {return x.pretty_print();},
2151      #[cfg(all(feature = "matrix", feature = "f64"))]
2152      Value::MatrixF64(x)  => {return x.pretty_print();},
2153      #[cfg(all(feature = "matrix", feature = "any"))]
2154      Value::MatrixValue(x)  => {return x.pretty_print();},
2155      #[cfg(all(feature = "matrix", feature = "string"))]
2156      Value::MatrixString(x)  => {return x.pretty_print();},
2157      #[cfg(all(feature = "matrix", feature = "rational"))]
2158      Value::MatrixR64(x) => {return x.pretty_print();},
2159      #[cfg(all(feature = "matrix", feature = "complex"))]
2160      Value::MatrixC64(x) => {return x.pretty_print();},
2161      Value::Index(x)  => {builder.push_record(vec![format!("{}",x.borrow())]);},
2162      Value::MutableReference(x) => {return x.borrow().pretty_print();},
2163      Value::Empty => builder.push_record(vec!["_"]),
2164      Value::IndexAll => builder.push_record(vec![":"]),
2165      Value::Id(x) => builder.push_record(vec![format!("{}",humanize(x))]),
2166      Value::Kind(x) => builder.push_record(vec![format!("{}",x)]),
2167      x => {
2168        todo!("{x:#?}");
2169      },
2170    };
2171    let value_style = Style::empty()
2172      .top(' ')
2173      .left(' ')
2174      .right(' ')
2175      .bottom(' ')
2176      .vertical(' ')
2177      .intersection_bottom(' ')
2178      .corner_top_left(' ')
2179      .corner_top_right(' ')
2180      .corner_bottom_left(' ')
2181      .corner_bottom_right(' ');
2182    let mut table = builder.build();
2183    table.with(value_style);
2184    format!("{table}")
2185  }
2186}
2187
2188
2189pub trait ToIndex {
2190  fn to_index(&self) -> Value;
2191}
2192
2193#[cfg(feature = "matrix")]
2194impl ToIndex for Ref<Vec<i64>> { fn to_index(&self) -> Value { (*self.borrow()).iter().map(|x| *x as usize).collect::<Vec<usize>>().to_value() } }
2195
2196pub trait ToValue {
2197  fn to_value(&self) -> Value;
2198}
2199
2200#[cfg(feature = "matrix")]
2201impl ToValue for Vec<usize> {
2202  fn to_value(&self) -> Value {
2203    match self.len() {
2204      1 => Value::Index(Ref::new(self[0].clone())),
2205      #[cfg(feature = "vector2")]
2206      2 => Value::MatrixIndex(Matrix::Vector2(Ref::new(Vector2::from_vec(self.clone())))),
2207      #[cfg(feature = "vector3")]
2208      3 => Value::MatrixIndex(Matrix::Vector3(Ref::new(Vector3::from_vec(self.clone())))),
2209      #[cfg(feature = "vector4")]
2210      4 => Value::MatrixIndex(Matrix::Vector4(Ref::new(Vector4::from_vec(self.clone())))),
2211      #[cfg(feature = "vectord")]
2212      n => Value::MatrixIndex(Matrix::DVector(Ref::new(DVector::from_vec(self.clone())))),
2213      _ => todo!(),
2214    }
2215  }
2216}
2217
2218impl ToValue for Ref<usize>  { fn to_value(&self) -> Value { Value::Index(self.clone())  } }
2219#[cfg(feature = "u8")]
2220impl ToValue for Ref<u8>     { fn to_value(&self) -> Value { Value::U8(self.clone())     } }
2221#[cfg(feature = "u16")]
2222impl ToValue for Ref<u16>    { fn to_value(&self) -> Value { Value::U16(self.clone())    } }
2223#[cfg(feature = "u32")]
2224impl ToValue for Ref<u32>    { fn to_value(&self) -> Value { Value::U32(self.clone())    } }
2225#[cfg(feature = "u64")]
2226impl ToValue for Ref<u64>    { fn to_value(&self) -> Value { Value::U64(self.clone())    } }
2227#[cfg(feature = "u128")]
2228impl ToValue for Ref<u128>   { fn to_value(&self) -> Value { Value::U128(self.clone())   } }
2229#[cfg(feature = "i8")]
2230impl ToValue for Ref<i8>     { fn to_value(&self) -> Value { Value::I8(self.clone())     } }
2231#[cfg(feature = "i16")]
2232impl ToValue for Ref<i16>    { fn to_value(&self) -> Value { Value::I16(self.clone())    } }
2233#[cfg(feature = "i32")]
2234impl ToValue for Ref<i32>    { fn to_value(&self) -> Value { Value::I32(self.clone())    } }
2235#[cfg(feature = "i64")]
2236impl ToValue for Ref<i64>    { fn to_value(&self) -> Value { Value::I64(self.clone())    } }
2237#[cfg(feature = "i128")]
2238impl ToValue for Ref<i128>   { fn to_value(&self) -> Value { Value::I128(self.clone())   } }
2239#[cfg(feature = "f32")]
2240impl ToValue for Ref<F32>    { fn to_value(&self) -> Value { Value::F32(self.clone())    } }
2241#[cfg(feature = "f64")]
2242impl ToValue for Ref<F64>    { fn to_value(&self) -> Value { Value::F64(self.clone())    } }
2243#[cfg(feature = "bool")]
2244impl ToValue for Ref<bool>   { fn to_value(&self) -> Value { Value::Bool(self.clone())   } }
2245#[cfg(feature = "string")]
2246impl ToValue for Ref<String> { fn to_value(&self) -> Value { Value::String(self.clone()) } }
2247#[cfg(feature = "rational")]
2248impl ToValue for Ref<R64> { fn to_value(&self) -> Value { Value::R64(self.clone()) } }
2249#[cfg(feature = "complex")]
2250impl ToValue for Ref<C64> { fn to_value(&self) -> Value { Value::C64(self.clone()) } }
2251
2252#[cfg(feature = "u8")]
2253impl From<u8> for Value {
2254  fn from(val: u8) -> Self {
2255    Value::U8(Ref::new(val))
2256  }
2257}
2258
2259#[cfg(feature = "u16")]
2260impl From<u16> for Value {
2261  fn from(val: u16) -> Self {
2262    Value::U16(Ref::new(val))
2263  }
2264}
2265
2266#[cfg(feature = "u32")]
2267impl From<u32> for Value {
2268  fn from(val: u32) -> Self {
2269    Value::U32(Ref::new(val))
2270  }
2271}
2272
2273#[cfg(feature = "u64")]
2274impl From<u64> for Value {
2275  fn from(val: u64) -> Self {
2276    Value::U64(Ref::new(val))
2277  }
2278}
2279
2280#[cfg(feature = "u128")]
2281impl From<u128> for Value {
2282  fn from(val: u128) -> Self {
2283    Value::U128(Ref::new(val))
2284  }
2285}
2286
2287#[cfg(feature = "i8")]
2288impl From<i8> for Value {
2289  fn from(val: i8) -> Self {
2290    Value::I8(Ref::new(val))
2291  }
2292}
2293
2294#[cfg(feature = "i16")]
2295impl From<i16> for Value {
2296  fn from(val: i16) -> Self {
2297    Value::I16(Ref::new(val))
2298  }
2299}
2300
2301#[cfg(feature = "i32")]
2302impl From<i32> for Value {
2303  fn from(val: i32) -> Self {
2304    Value::I32(Ref::new(val))
2305  }
2306}
2307
2308#[cfg(feature = "i64")]
2309impl From<i64> for Value {
2310  fn from(val: i64) -> Self {
2311    Value::I64(Ref::new(val))
2312  }
2313}
2314
2315#[cfg(feature = "i128")]
2316impl From<i128> for Value {
2317  fn from(val: i128) -> Self {
2318    Value::I128(Ref::new(val))
2319  }
2320}
2321
2322#[cfg(feature = "bool")]
2323impl From<bool> for Value {
2324  fn from(val: bool) -> Self {
2325    Value::Bool(Ref::new(val))
2326  }
2327}
2328
2329#[cfg(feature = "string")]
2330impl From<String> for Value {
2331  fn from(val: String) -> Self {
2332    Value::String(Ref::new(val))
2333  }
2334}
2335
2336#[cfg(feature = "rational")]
2337impl From<R64> for Value {
2338  fn from(val: R64) -> Self {
2339    Value::R64(Ref::new(val))
2340  }
2341}
2342
2343
2344pub trait ToUsize {
2345  fn to_usize(&self) -> usize;
2346}
2347
2348macro_rules! impl_to_usize_for {
2349  ($t:ty) => {
2350    impl ToUsize for $t {
2351      fn to_usize(&self) -> usize {
2352        #[allow(unused_comparisons)]
2353        if *self < 0 as $t {
2354          panic!("Cannot convert negative number to usize");
2355        }
2356        *self as usize
2357      }
2358    }
2359  };
2360}
2361
2362#[cfg(feature = "u8")]
2363impl_to_usize_for!(u8);
2364#[cfg(feature = "u16")]
2365impl_to_usize_for!(u16);
2366#[cfg(feature = "u32")]
2367impl_to_usize_for!(u32);
2368#[cfg(feature = "u64")]
2369impl_to_usize_for!(u64);
2370#[cfg(feature = "u128")]
2371impl_to_usize_for!(u128);
2372impl_to_usize_for!(usize);
2373
2374#[cfg(feature = "i8")]
2375impl_to_usize_for!(i8);
2376#[cfg(feature = "i16")]
2377impl_to_usize_for!(i16);
2378#[cfg(feature = "i32")]
2379impl_to_usize_for!(i32);
2380#[cfg(feature = "i64")]
2381impl_to_usize_for!(i64);
2382#[cfg(feature = "i128")]
2383impl_to_usize_for!(i128);
2384