Skip to main content

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