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 = "i8")]
1418      Value::I8(n) => format!("<span class='mech-number'>{}</span>", n.borrow()),
1419      #[cfg(feature = "i128")]
1420      Value::I128(n) => format!("<span class='mech-number'>{}</span>", n.borrow()),
1421      #[cfg(feature = "i16")]
1422      Value::I16(n) => format!("<span class='mech-number'>{}</span>", n.borrow()),
1423      #[cfg(feature = "i32")]
1424      Value::I32(n) => format!("<span class='mech-number'>{}</span>", n.borrow()),
1425      #[cfg(feature = "i64")]
1426      Value::I64(n) => format!("<span class='mech-number'>{}</span>", n.borrow()),
1427      #[cfg(feature = "i128")]
1428      Value::I128(n) => format!("<span class='mech-number'>{}</span>", n.borrow()),
1429      #[cfg(feature = "f32")]
1430      Value::F32(n) => format!("<span class='mech-number'>{}</span>", n.borrow()),
1431      #[cfg(feature = "f64")]
1432      Value::F64(n) => format!("<span class='mech-number'>{}</span>", n.borrow()),
1433      #[cfg(any(feature = "string", feature = "variable_define"))]
1434      Value::String(s) => format!("<span class='mech-string'>\"{}\"</span>", s.borrow()),
1435      #[cfg(any(feature = "bool", feature = "variable_define"))]
1436      Value::Bool(b) => format!("<span class='mech-boolean'>{}</span>", b.borrow()),
1437      #[cfg(feature = "complex")]
1438      Value::C64(c) => c.borrow().to_html(),
1439      #[cfg(feature = "rational")]
1440      Value::R64(r) => r.borrow().to_html(),
1441      #[cfg(all(feature = "matrix", feature = "u8"))]
1442      Value::MatrixU8(m) => m.to_html(),
1443      #[cfg(all(feature = "matrix", feature = "u16"))]
1444      Value::MatrixU16(m) => m.to_html(),
1445      #[cfg(all(feature = "matrix", feature = "u32"))]
1446      Value::MatrixU32(m) => m.to_html(),
1447      #[cfg(all(feature = "matrix", feature = "u64"))]
1448      Value::MatrixU64(m) => m.to_html(),
1449      #[cfg(all(feature = "matrix", feature = "u128"))]
1450      Value::MatrixU128(m) => m.to_html(),
1451      #[cfg(all(feature = "matrix", feature = "i8"))]
1452      Value::MatrixI8(m) => m.to_html(),
1453      #[cfg(all(feature = "matrix", feature = "i16"))]
1454      Value::MatrixI16(m) => m.to_html(),
1455      #[cfg(all(feature = "matrix", feature = "i32"))]
1456      Value::MatrixI32(m) => m.to_html(),
1457      #[cfg(all(feature = "matrix", feature = "i64"))]
1458      Value::MatrixI64(m) => m.to_html(),
1459      #[cfg(all(feature = "matrix", feature = "i128"))]
1460      Value::MatrixI128(m) => m.to_html(),
1461      #[cfg(all(feature = "matrix", feature = "f64"))]
1462      Value::MatrixF64(m) => m.to_html(),
1463      #[cfg(all(feature = "matrix", feature = "f32"))]
1464      Value::MatrixF32(m) => m.to_html(),
1465      #[cfg(feature = "matrix")]
1466      Value::MatrixIndex(m) => m.to_html(),
1467      #[cfg(all(feature = "matrix", feature = "bool"))]
1468      Value::MatrixBool(m) => m.to_html(),
1469      #[cfg(all(feature = "matrix", feature = "string"))]
1470      Value::MatrixString(m) => m.to_html(),
1471      #[cfg(feature = "matrix")]
1472      Value::MatrixValue(m) => m.to_html(),
1473      #[cfg(all(feature = "matrix", feature = "rational"))]
1474      Value::MatrixR64(m) => m.to_html(),
1475      #[cfg(all(feature = "matrix", feature = "complex"))]
1476      Value::MatrixC64(m) => m.to_html(),
1477      #[cfg(feature = "atom")]
1478      Value::Atom(a) => a.borrow().to_html(),
1479      #[cfg(feature = "set")]
1480      Value::Set(s) => s.borrow().to_html(),
1481      #[cfg(feature = "map")]
1482      Value::Map(m) => m.borrow().to_html(),
1483      #[cfg(feature = "table")]
1484      Value::Table(t) => t.borrow().to_html(),
1485      #[cfg(feature = "record")]
1486      Value::Record(r) => r.borrow().to_html(),
1487      #[cfg(feature = "tuple")]
1488      Value::Tuple(t) => t.borrow().to_html(),
1489      #[cfg(feature = "enum")]
1490      Value::Enum(e) => e.borrow().to_html(),
1491      Value::Empty | Value::EmptyKind(_) => "<span class='mech-empty'>_</span>".to_string(),
1492      Value::MutableReference(m) => {
1493        let inner = m.borrow();
1494        format!("<span class='mech-reference'>{}</span>", inner.to_html())
1495      },
1496      Value::Typed(value, _) => value.to_html(),
1497      _ => "???".to_string(),
1498    }
1499  }
1500
1501  pub fn format_value_inline(&self) -> String {
1502    match self {
1503      #[cfg(feature = "u8")]
1504      Value::U8(n) => format!("{}", n.borrow()),
1505      #[cfg(feature = "u16")]
1506      Value::U16(n) => format!("{}", n.borrow()),
1507      #[cfg(feature = "u32")]
1508      Value::U32(n) => format!("{}", n.borrow()),
1509      #[cfg(feature = "u64")]
1510      Value::U64(n) => format!("{}", n.borrow()),
1511      #[cfg(feature = "u128")]
1512      Value::U128(n) => format!("{}", n.borrow()),
1513      #[cfg(feature = "i8")]
1514      Value::I8(n) => format!("{}", n.borrow()),
1515      #[cfg(feature = "i16")]
1516      Value::I16(n) => format!("{}", n.borrow()),
1517      #[cfg(feature = "i32")]
1518      Value::I32(n) => format!("{}", n.borrow()),
1519      #[cfg(feature = "i64")]
1520      Value::I64(n) => format!("{}", n.borrow()),
1521      #[cfg(feature = "i128")]
1522      Value::I128(n) => format!("{}", n.borrow()),
1523      #[cfg(feature = "f32")]
1524      Value::F32(n) => format!("{}", n.borrow()),
1525      #[cfg(feature = "f64")]
1526      Value::F64(n) => format!("{}", n.borrow()),
1527      #[cfg(any(feature = "string", feature = "variable_define"))]
1528      Value::String(s) => format!("\"{}\"", s.borrow()),
1529      #[cfg(any(feature = "bool", feature = "variable_define"))]
1530      Value::Bool(b) => format!("{}", b.borrow()),
1531      #[cfg(feature = "complex")]
1532      Value::C64(c) => format!("{}", c.borrow()),
1533      #[cfg(feature = "rational")]
1534      Value::R64(r) => format!("{}", r.borrow()),
1535      #[cfg(feature = "matrix")]
1536      Value::MatrixIndex(m) => Self::format_matrix_inline(m),
1537      #[cfg(all(feature = "matrix", feature = "bool"))]
1538      Value::MatrixBool(m) => Self::format_matrix_inline(m),
1539      #[cfg(all(feature = "matrix", feature = "u8"))]
1540      Value::MatrixU8(m) => Self::format_matrix_inline(m),
1541      #[cfg(all(feature = "matrix", feature = "u16"))]
1542      Value::MatrixU16(m) => Self::format_matrix_inline(m),
1543      #[cfg(all(feature = "matrix", feature = "u32"))]
1544      Value::MatrixU32(m) => Self::format_matrix_inline(m),
1545      #[cfg(all(feature = "matrix", feature = "u64"))]
1546      Value::MatrixU64(m) => Self::format_matrix_inline(m),
1547      #[cfg(all(feature = "matrix", feature = "u128"))]
1548      Value::MatrixU128(m) => Self::format_matrix_inline(m),
1549      #[cfg(all(feature = "matrix", feature = "i8"))]
1550      Value::MatrixI8(m) => Self::format_matrix_inline(m),
1551      #[cfg(all(feature = "matrix", feature = "i16"))]
1552      Value::MatrixI16(m) => Self::format_matrix_inline(m),
1553      #[cfg(all(feature = "matrix", feature = "i32"))]
1554      Value::MatrixI32(m) => Self::format_matrix_inline(m),
1555      #[cfg(all(feature = "matrix", feature = "i64"))]
1556      Value::MatrixI64(m) => Self::format_matrix_inline(m),
1557      #[cfg(all(feature = "matrix", feature = "i128"))]
1558      Value::MatrixI128(m) => Self::format_matrix_inline(m),
1559      #[cfg(all(feature = "matrix", feature = "f32"))]
1560      Value::MatrixF32(m) => Self::format_matrix_inline(m),
1561      #[cfg(all(feature = "matrix", feature = "f64"))]
1562      Value::MatrixF64(m) => Self::format_matrix_inline(m),
1563      #[cfg(all(feature = "matrix", feature = "string"))]
1564      Value::MatrixString(m) => Self::format_matrix_inline(m),
1565      #[cfg(all(feature = "matrix", feature = "rational"))]
1566      Value::MatrixR64(m) => Self::format_matrix_inline(m),
1567      #[cfg(all(feature = "matrix", feature = "complex"))]
1568      Value::MatrixC64(m) => Self::format_matrix_inline(m),
1569      #[cfg(feature = "matrix")]
1570      Value::MatrixValue(m) => Self::format_matrix_inline(m),
1571      #[cfg(feature = "atom")]
1572      Value::Atom(a) => format!("{}", a.borrow()),
1573      #[cfg(feature = "set")]
1574      Value::Set(s) => {
1575        let vals = s.borrow().set.iter().map(|v| v.format_value_inline()).collect::<Vec<_>>();
1576        format!("{{{}}}", vals.join(", "))
1577      }
1578      #[cfg(feature = "map")]
1579      Value::Map(m) => {
1580        let vals = m.borrow().map.iter().map(|(k,v)| format!("{}: {}", k.format_value_inline(), v.format_value_inline())).collect::<Vec<_>>();
1581        format!("{{{}}}", vals.join(", "))
1582      }
1583      #[cfg(feature = "record")]
1584      Value::Record(r) => {
1585        let record = r.borrow();
1586        let vals = record.data.iter().map(|(k,v)| {
1587          let name = record.field_names.get(k).cloned().unwrap_or_else(|| format!("{}", k));
1588          format!("{}: {}", name, v.format_value_inline())
1589        }).collect::<Vec<_>>();
1590        format!("{{{}}}", vals.join(", "))
1591      }
1592      #[cfg(feature = "tuple")]
1593      Value::Tuple(t) => {
1594        let vals = t.borrow().elements.iter().map(|v| v.format_value_inline()).collect::<Vec<_>>();
1595        format!("({})", vals.join(", "))
1596      }
1597      #[cfg(feature = "enum")]
1598      Value::Enum(e) => {
1599        let enm = e.borrow();
1600        let dict = enm.names.borrow();
1601        let name = dict.get(&enm.id).cloned().unwrap_or_else(|| format!("{}", enm.id));
1602        let vals = enm.variants.iter().map(|(id, v)| {
1603          let variant_name = dict.get(id).cloned().unwrap_or_else(|| format!("{}", id));
1604          match v {
1605            Some(value) => format!("{}: {}", variant_name, value.format_value_inline()),
1606            None => variant_name,
1607          }
1608        }).collect::<Vec<_>>();
1609        format!(":{}{{{}}}", name, vals.join(" | "))
1610      }
1611      #[cfg(feature = "table")]
1612      Value::Table(t) => {
1613        let table = t.borrow();
1614        let headers = table.data.iter().map(|(k, (kind, _))| {
1615          let name = table.col_names.get(k).cloned().unwrap_or_else(|| format!("{}", k));
1616          format!("{}<{}>", name, kind)
1617        }).collect::<Vec<_>>().join(" ");
1618        let rows = (0..table.rows).map(|r| {
1619          table.data.iter().map(|(_, (_, col))| col.index2d(r + 1, 1).format_value_inline()).collect::<Vec<_>>().join(" ")
1620        }).collect::<Vec<_>>().join("; ");
1621        format!("|{}| {}", headers, rows)
1622      }
1623      Value::Id(x) => format!("{}", humanize(x)),
1624      Value::Index(x) => format!("{}", x.borrow()),
1625      Value::Kind(k) => format!("<{}>", k),
1626      Value::Typed(value, _) => value.format_value_inline(),
1627      Value::MutableReference(m) => m.borrow().format_value_inline(),
1628      Value::IndexAll => ":".to_string(),
1629      Value::EmptyKind(_) => "_".to_string(),
1630      Value::Empty => "_".to_string(),
1631    }
1632  }
1633
1634  #[cfg(feature = "matrix")]
1635  fn format_matrix_inline<T>(matrix: &Matrix<T>) -> String
1636  where T: Clone + std::fmt::Display + std::fmt::Debug + PartialEq + 'static {
1637    let shape = matrix.shape();
1638    let rows = shape[0];
1639    let cols = shape[1];
1640    let elements = matrix.as_vec();
1641    let row_strings = (0..rows)
1642      .map(|r| {
1643        let start = r * cols;
1644        let end = start + cols;
1645        elements[start..end].iter().map(|v| format!("{}", v)).collect::<Vec<_>>().join(" ")
1646      })
1647      .collect::<Vec<_>>();
1648    format!("[{}]", row_strings.join("; "))
1649  }
1650
1651  pub fn shape(&self) -> Vec<usize> {
1652    match self {
1653      #[cfg(feature = "rational")]
1654      Value::R64(x) => vec![1,1],
1655      #[cfg(feature = "complex")]
1656      Value::C64(x) => vec![1,1],
1657      #[cfg(feature = "u8")]
1658      Value::U8(x) => vec![1,1],
1659      #[cfg(feature = "u16")]
1660      Value::U16(x) => vec![1,1],
1661      #[cfg(feature = "u32")]
1662      Value::U32(x) => vec![1,1],
1663      #[cfg(feature = "u64")]
1664      Value::U64(x) => vec![1,1],
1665      #[cfg(feature = "u128")]
1666      Value::U128(x) => vec![1,1],
1667      #[cfg(feature = "i8")]
1668      Value::I8(x) => vec![1,1],
1669      #[cfg(feature = "i16")]
1670      Value::I16(x) => vec![1,1],
1671      #[cfg(feature = "i32")]
1672      Value::I32(x) => vec![1,1],
1673      #[cfg(feature = "i64")]
1674      Value::I64(x) => vec![1,1],
1675      #[cfg(feature = "i128")]
1676      Value::I128(x) => vec![1,1],
1677      #[cfg(feature = "f32")]
1678      Value::F32(x) => vec![1,1],
1679      #[cfg(feature = "f64")]
1680      Value::F64(x) => vec![1,1],
1681      #[cfg(any(feature = "string", feature = "variable_define"))]
1682      Value::String(x) => vec![1,1],
1683      #[cfg(any(feature = "bool", feature = "variable_define"))]
1684      Value::Bool(x) => vec![1,1],
1685      #[cfg(feature = "atom")]
1686      Value::Atom(x) => vec![1,1],
1687      #[cfg(feature = "matrix")]
1688      Value::MatrixIndex(x) => x.shape(),
1689      #[cfg(all(feature = "matrix", feature = "bool"))]
1690      Value::MatrixBool(x) => x.shape(),
1691      #[cfg(all(feature = "matrix", feature = "u8"))]
1692      Value::MatrixU8(x) => x.shape(),
1693      #[cfg(all(feature = "matrix", feature = "u16"))]
1694      Value::MatrixU16(x) => x.shape(),
1695      #[cfg(all(feature = "matrix", feature = "u32"))]
1696      Value::MatrixU32(x) => x.shape(),
1697      #[cfg(all(feature = "matrix", feature = "u64"))]
1698      Value::MatrixU64(x) => x.shape(),
1699      #[cfg(all(feature = "matrix", feature = "u128"))]
1700      Value::MatrixU128(x) => x.shape(),
1701      #[cfg(all(feature = "matrix", feature = "i8"))]
1702      Value::MatrixI8(x) => x.shape(),
1703      #[cfg(all(feature = "matrix", feature = "i16"))]
1704      Value::MatrixI16(x) => x.shape(),
1705      #[cfg(all(feature = "matrix", feature = "i32"))]
1706      Value::MatrixI32(x) => x.shape(),
1707      #[cfg(all(feature = "matrix", feature = "i64"))]
1708      Value::MatrixI64(x) => x.shape(),
1709      #[cfg(all(feature = "matrix", feature = "i128"))]
1710      Value::MatrixI128(x) => x.shape(),
1711      #[cfg(all(feature = "matrix", feature = "f32"))]
1712      Value::MatrixF32(x) => x.shape(),
1713      #[cfg(all(feature = "matrix", feature = "f64"))]
1714      Value::MatrixF64(x) => x.shape(),
1715      #[cfg(all(feature = "matrix", feature = "string"))]
1716      Value::MatrixString(x) => x.shape(),
1717      #[cfg(feature = "matrix")]
1718      Value::MatrixValue(x) => x.shape(),
1719      #[cfg(all(feature = "matrix", feature = "rational"))]
1720      Value::MatrixR64(x) => x.shape(),
1721      #[cfg(all(feature = "matrix", feature = "complex"))]
1722      Value::MatrixC64(x) => x.shape(),
1723      #[cfg(feature = "enum")]
1724      Value::Enum(x) => vec![1,1],
1725      #[cfg(feature = "table")]
1726      Value::Table(x) => x.borrow().shape(),
1727      #[cfg(feature = "set")]
1728      Value::Set(x) => vec![1,x.borrow().set.len()],
1729      #[cfg(feature = "map")]
1730      Value::Map(x) => vec![1,x.borrow().map.len()],
1731      #[cfg(feature = "record")]
1732      Value::Record(x) => x.borrow().shape(),
1733      #[cfg(feature = "tuple")]
1734      Value::Tuple(x) => vec![1,x.borrow().size()],
1735      Value::Index(x) => vec![1,1],
1736      Value::MutableReference(x) => x.borrow().shape(),
1737      Value::Typed(x, _) => x.shape(),
1738      Value::Empty | Value::EmptyKind(_) => vec![0,0],
1739      Value::IndexAll => vec![0,0],
1740      Value::Kind(_) => vec![0,0],
1741      Value::Id(x) => vec![0,0],
1742    }
1743  }
1744
1745  pub fn deref_kind(&self) -> ValueKind {
1746    match self {
1747      Value::MutableReference(x) => x.borrow().kind(),
1748      x => x.kind(),
1749    }
1750  }
1751
1752  pub fn kind(&self) -> ValueKind {
1753    match self {
1754      #[cfg(feature = "complex")]
1755      Value::C64(_) => ValueKind::C64,
1756      #[cfg(feature = "rational")]
1757      Value::R64(_) => ValueKind::R64,
1758      #[cfg(feature = "u8")]
1759      Value::U8(_) => ValueKind::U8,
1760      #[cfg(feature = "u16")]
1761      Value::U16(_) => ValueKind::U16,
1762      #[cfg(feature = "u32")]
1763      Value::U32(_) => ValueKind::U32,
1764      #[cfg(feature = "u64")]
1765      Value::U64(_) => ValueKind::U64,
1766      #[cfg(feature = "u128")]
1767      Value::U128(_) => ValueKind::U128,
1768      #[cfg(feature = "i8")]
1769      Value::I8(_) => ValueKind::I8,
1770      #[cfg(feature = "i16")]
1771      Value::I16(_) => ValueKind::I16,
1772      #[cfg(feature = "i32")]
1773      Value::I32(_) => ValueKind::I32,
1774      #[cfg(feature = "i64")]
1775      Value::I64(_) => ValueKind::I64,
1776      #[cfg(feature = "i128")]
1777      Value::I128(_) => ValueKind::I128,
1778      #[cfg(feature = "f32")]
1779      Value::F32(_) => ValueKind::F32,
1780      #[cfg(feature = "f64")]
1781      Value::F64(_) => ValueKind::F64,
1782      #[cfg(any(feature = "string", feature = "variable_define"))]
1783      Value::String(_) => ValueKind::String,
1784      #[cfg(any(feature = "bool", feature = "variable_define"))]
1785      Value::Bool(_) => ValueKind::Bool,
1786      #[cfg(feature = "atom")]
1787      Value::Atom(x) => ValueKind::Atom(x.borrow().id(), x.borrow().name().clone()),
1788      #[cfg(feature = "matrix")]
1789      Value::MatrixValue(x) => ValueKind::Matrix(Box::new(Self::infer_matrix_value_kind(x)),x.shape()),
1790      #[cfg(feature = "matrix")]
1791      Value::MatrixIndex(x) => ValueKind::Matrix(Box::new(ValueKind::Index),x.shape()),
1792      #[cfg(all(feature = "matrix", feature = "bool"))]
1793      Value::MatrixBool(x) => ValueKind::Matrix(Box::new(ValueKind::Bool), x.shape()),
1794      #[cfg(all(feature = "matrix", feature = "u8"))]
1795      Value::MatrixU8(x) => ValueKind::Matrix(Box::new(ValueKind::U8), x.shape()),
1796      #[cfg(all(feature = "matrix", feature = "u16"))]
1797      Value::MatrixU16(x) => ValueKind::Matrix(Box::new(ValueKind::U16), x.shape()),
1798      #[cfg(all(feature = "matrix", feature = "u32"))]
1799      Value::MatrixU32(x) => ValueKind::Matrix(Box::new(ValueKind::U32), x.shape()),
1800      #[cfg(all(feature = "matrix", feature = "u64"))]
1801      Value::MatrixU64(x) => ValueKind::Matrix(Box::new(ValueKind::U64), x.shape()),
1802      #[cfg(all(feature = "matrix", feature = "u128"))]
1803      Value::MatrixU128(x) => ValueKind::Matrix(Box::new(ValueKind::U128), x.shape()),
1804      #[cfg(all(feature = "matrix", feature = "i8"))]
1805      Value::MatrixI8(x) => ValueKind::Matrix(Box::new(ValueKind::I8), x.shape()),
1806      #[cfg(all(feature = "matrix", feature = "i16"))]
1807      Value::MatrixI16(x) => ValueKind::Matrix(Box::new(ValueKind::I16), x.shape()),
1808      #[cfg(all(feature = "matrix", feature = "i32"))]
1809      Value::MatrixI32(x) => ValueKind::Matrix(Box::new(ValueKind::I32), x.shape()),
1810      #[cfg(all(feature = "matrix", feature = "i64"))]
1811      Value::MatrixI64(x) => ValueKind::Matrix(Box::new(ValueKind::I64), x.shape()),
1812      #[cfg(all(feature = "matrix", feature = "i128"))]
1813      Value::MatrixI128(x) => ValueKind::Matrix(Box::new(ValueKind::I128), x.shape()),
1814      #[cfg(all(feature = "matrix", feature = "f32"))]
1815      Value::MatrixF32(x) => ValueKind::Matrix(Box::new(ValueKind::F32), x.shape()),
1816      #[cfg(all(feature = "matrix", feature = "f64"))]
1817      Value::MatrixF64(x) => ValueKind::Matrix(Box::new(ValueKind::F64), x.shape()),
1818      #[cfg(all(feature = "matrix", feature = "string"))]
1819      Value::MatrixString(x) => ValueKind::Matrix(Box::new(ValueKind::String), x.shape()),
1820      #[cfg(all(feature = "matrix", feature = "rational"))]
1821      Value::MatrixR64(x) => ValueKind::Matrix(Box::new(ValueKind::R64), x.shape()),
1822      #[cfg(all(feature = "matrix", feature = "complex"))]
1823      Value::MatrixC64(x) => ValueKind::Matrix(Box::new(ValueKind::C64), x.shape()),
1824      #[cfg(feature = "table")]
1825      Value::Table(x) => x.borrow().kind(),
1826      #[cfg(feature = "set")]
1827      Value::Set(x) => x.borrow().kind(),
1828      #[cfg(feature = "map")]
1829      Value::Map(x) => x.borrow().kind(),
1830      #[cfg(feature = "record")]
1831      Value::Record(x) => x.borrow().kind(),
1832      #[cfg(feature = "tuple")]
1833      Value::Tuple(x) => x.borrow().kind(),
1834      #[cfg(feature = "enum")]
1835      Value::Enum(x) => x.borrow().kind(),
1836      Value::MutableReference(x) => ValueKind::Reference(Box::new(x.borrow().kind())),
1837      Value::Typed(_, kind) => kind.clone(),
1838      Value::EmptyKind(k) => k.clone(),
1839      Value::Empty => ValueKind::Empty,
1840      Value::IndexAll => ValueKind::Empty,
1841      Value::Id(x) => ValueKind::Id,
1842      Value::Index(x) => ValueKind::Index,
1843      Value::Kind(x) => x.clone(),
1844    }
1845  }
1846
1847  #[cfg(feature = "matrix")]
1848  pub fn is_matrix(&self) -> bool {
1849    match self {
1850      #[cfg(feature = "matrix")]
1851      Value::MatrixIndex(_) => true,
1852      #[cfg(all(feature = "matrix", feature = "bool"))]
1853      Value::MatrixBool(_) => true,
1854      #[cfg(all(feature = "matrix", feature = "u8"))]
1855      Value::MatrixU8(_) => true,
1856      #[cfg(all(feature = "matrix", feature = "u16"))]
1857      Value::MatrixU16(_) => true,
1858      #[cfg(all(feature = "matrix", feature = "u32"))]
1859      Value::MatrixU32(_) => true,
1860      #[cfg(all(feature = "matrix", feature = "u64"))]
1861      Value::MatrixU64(_) => true,
1862      #[cfg(all(feature = "matrix", feature = "u128"))]
1863      Value::MatrixU128(_) => true,
1864      #[cfg(all(feature = "matrix", feature = "i8"))]
1865      Value::MatrixI8(_) => true,
1866      #[cfg(all(feature = "matrix", feature = "i16"))]
1867      Value::MatrixI16(_) => true,
1868      #[cfg(all(feature = "matrix", feature = "i32"))]
1869      Value::MatrixI32(_) => true,
1870      #[cfg(all(feature = "matrix", feature = "i64"))]
1871      Value::MatrixI64(_) => true,
1872      #[cfg(all(feature = "matrix", feature = "i128"))]
1873      Value::MatrixI128(_) => true,
1874      #[cfg(all(feature = "matrix", feature = "f32"))]
1875      Value::MatrixF32(_) => true,
1876      #[cfg(all(feature = "matrix", feature = "f64"))]
1877      Value::MatrixF64(_) => true,
1878      #[cfg(all(feature = "matrix", feature = "string"))]
1879      Value::MatrixString(_) => true,
1880      #[cfg(all(feature = "matrix", feature = "rational"))]
1881      Value::MatrixR64(_) => true,
1882      #[cfg(all(feature = "matrix", feature = "complex"))]
1883      Value::MatrixC64(_) => true,
1884      #[cfg(feature = "matrix")]
1885      Value::MatrixValue(_) => true,
1886      _ => false,
1887    }
1888  }
1889
1890  pub fn is_scalar(&self) -> bool {
1891    match self {
1892      #[cfg(feature = "u8")]
1893      Value::U8(_) => true,
1894      #[cfg(feature = "u16")]
1895      Value::U16(_) => true,
1896      #[cfg(feature = "u32")]
1897      Value::U32(_) => true,
1898      #[cfg(feature = "u64")]
1899      Value::U64(_) => true,
1900      #[cfg(feature = "u128")]
1901      Value::U128(_) => true,
1902      #[cfg(feature = "i8")]
1903      Value::I8(_) => true,
1904      #[cfg(feature = "i16")]
1905      Value::I16(_) => true,
1906      #[cfg(feature = "i32")]
1907      Value::I32(_) => true,
1908      #[cfg(feature = "i64")]
1909      Value::I64(_) => true,
1910      #[cfg(feature = "i128")]
1911      Value::I128(_) => true,
1912      #[cfg(feature = "f32")]
1913      Value::F32(_) => true,
1914      #[cfg(feature = "f64")]
1915      Value::F64(_) => true,
1916      #[cfg(any(feature = "bool", feature = "variable_define"))]
1917      Value::Bool(_) => true,
1918      #[cfg(any(feature = "string", feature = "variable_define"))]
1919      Value::String(_) => true,
1920      #[cfg(feature = "atom")]
1921      Value::Atom(_) => true,
1922      Value::Index(_) => true,
1923      _ => false,
1924    }
1925  }
1926
1927  #[cfg(any(feature = "bool", feature = "variable_define"))]
1928  pub fn as_bool(&self) -> MResult<Ref<bool>> {
1929    if let Value::Bool(v) = self {
1930      Ok(v.clone())
1931    } else if let Value::MutableReference(val) = self {
1932      val.borrow().as_bool()
1933    } else {
1934      Err(MechError::new(
1935        UnhandledFunctionArgumentKindError,
1936        None
1937      ).with_compiler_loc())
1938    }
1939  }
1940
1941  impl_as_type!(i8);
1942  impl_as_type!(i16);
1943  impl_as_type!(i32);
1944  impl_as_type!(i64);
1945  impl_as_type!(i128);
1946  impl_as_type!(u8);
1947  impl_as_type!(u16);
1948  impl_as_type!(u32);
1949  impl_as_type!(u64);
1950  impl_as_type!(u128);
1951
1952  pub fn is_string(&self) -> bool {
1953    match self {
1954      #[cfg(feature = "string")]
1955      Value::String(_) => true,
1956      #[cfg(feature = "string")]
1957      Value::MatrixString(_) => true,
1958      Value::MutableReference(val) => val.borrow().is_string(),
1959      _ => false,
1960    }
1961  }
1962
1963  #[cfg(any(feature = "string", feature = "variable_define"))]
1964  pub fn as_string(&self) -> MResult<Ref<String>> {
1965    match self {
1966      Value::String(v) => Ok(v.clone()),
1967      #[cfg(feature = "u8")]
1968      Value::U8(v) => Ok(Ref::new(v.borrow().to_string())),
1969      #[cfg(feature = "u16")]
1970      Value::U16(v) => Ok(Ref::new(v.borrow().to_string())),
1971      #[cfg(feature = "u32")]
1972      Value::U32(v) => Ok(Ref::new(v.borrow().to_string())),
1973      #[cfg(feature = "u64")]
1974      Value::U64(v) => Ok(Ref::new(v.borrow().to_string())),
1975      #[cfg(feature = "u128")]
1976      Value::U128(v) => Ok(Ref::new(v.borrow().to_string())),
1977      #[cfg(feature = "i8")]
1978      Value::I8(v) => Ok(Ref::new(v.borrow().to_string())),
1979      #[cfg(feature = "i16")]
1980      Value::I16(v) => Ok(Ref::new(v.borrow().to_string())),
1981      #[cfg(feature = "i32")]
1982      Value::I32(v) => Ok(Ref::new(v.borrow().to_string())),
1983      #[cfg(feature = "i64")]
1984      Value::I64(v) => Ok(Ref::new(v.borrow().to_string())),
1985      #[cfg(feature = "i128")]
1986      Value::I128(v) => Ok(Ref::new(v.borrow().to_string())),
1987      #[cfg(feature = "f32")]
1988      Value::F32(v) => Ok(Ref::new(format!("{}", v.borrow()))),
1989      #[cfg(feature = "f64")]
1990      Value::F64(v) => Ok(Ref::new(format!("{}", v.borrow()))),
1991      #[cfg(any(feature = "bool", feature = "variable_define"))]
1992      Value::Bool(v) => Ok(Ref::new(format!("{}", v.borrow()))),
1993      #[cfg(feature = "rational")]
1994      Value::R64(v) => Ok(Ref::new(v.borrow().to_string())),
1995      #[cfg(feature = "complex")]
1996      Value::C64(v) => Ok(Ref::new(v.borrow().to_string())),
1997      Value::MutableReference(val) => val.borrow().as_string(),
1998      _ => Err(
1999        MechError::new(
2000          CannotConvertToTypeError { 
2001            target_type: "string",
2002          },
2003          None
2004        ).with_compiler_loc()
2005      ),
2006    }
2007  }
2008
2009  #[cfg(feature = "r64")]
2010  pub fn as_r64(&self) -> MResult<Ref<R64>> {
2011    match self {
2012      Value::R64(v) => Ok(v.clone()),
2013      #[cfg(feature = "f32")]
2014      Value::F32(v) => Ok(Ref::new(R64::new(*v.borrow() as i64, 1))),
2015      #[cfg(feature = "f64")]
2016      Value::F64(v) => Ok(Ref::new(R64::new(*v.borrow() as i64, 1))),
2017      #[cfg(feature = "u8")]
2018      Value::U8(v) => Ok(Ref::new(R64::new(*v.borrow() as i64, 1))),
2019      #[cfg(feature = "u16")]
2020      Value::U16(v) => Ok(Ref::new(R64::new(*v.borrow() as i64, 1))),
2021      #[cfg(feature = "u32")]
2022      Value::U32(v) => Ok(Ref::new(R64::new(*v.borrow() as i64, 1))),
2023      #[cfg(feature = "u64")]
2024      Value::U64(v) => Ok(Ref::new(R64::new(*v.borrow() as i64, 1))),
2025      #[cfg(feature = "u128")]
2026      Value::U128(v) => Ok(Ref::new(R64::new(*v.borrow() as i64, 1))),
2027      #[cfg(feature = "i8")]
2028      Value::I8(v) => Ok(Ref::new(R64::new(*v.borrow() as i64, 1))),
2029      #[cfg(feature = "i16")]
2030      Value::I16(v) => Ok(Ref::new(R64::new(*v.borrow() as i64, 1))),
2031      #[cfg(feature = "i32")]
2032      Value::I32(v) => Ok(Ref::new(R64::new(*v.borrow() as i64, 1))),
2033      #[cfg(feature = "i64")]
2034      Value::I64(v) => Ok(Ref::new(R64::new(*v.borrow() as i64, 1))),
2035      #[cfg(feature = "i128")]
2036      Value::I128(v) => Ok(Ref::new(R64::new(*v.borrow() as i64, 1))),
2037      Value::MutableReference(val) => val.borrow().as_r64(),
2038      _ => Err(
2039        MechError::new(
2040          CannotConvertToTypeError { 
2041            target_type: "r64",
2042          },
2043          None
2044        ).with_compiler_loc()
2045      ),
2046    }
2047  }
2048
2049  #[cfg(feature = "c64")]
2050  pub fn as_c64(&self) -> MResult<Ref<C64>> {
2051    match self {
2052      Value::C64(v) => Ok(v.clone()),
2053      #[cfg(feature = "f32")]
2054      Value::F32(v) => Ok(Ref::new(C64::new(*v.borrow() as f64, 0.0))),
2055      #[cfg(feature = "f64")]
2056      Value::F64(v) => Ok(Ref::new(C64::new(*v.borrow(), 0.0))),
2057      #[cfg(feature = "u8")]
2058      Value::U8(v) => Ok(Ref::new(C64::new(*v.borrow() as f64, 0.0))),
2059      #[cfg(feature = "u16")]
2060      Value::U16(v) => Ok(Ref::new(C64::new(*v.borrow() as f64, 0.0))),
2061      #[cfg(feature = "u32")]
2062      Value::U32(v) => Ok(Ref::new(C64::new(*v.borrow() as f64, 0.0))),
2063      #[cfg(feature = "u64")]
2064      Value::U64(v) => Ok(Ref::new(C64::new(*v.borrow() as f64, 0.0))),
2065      #[cfg(feature = "u128")]
2066      Value::U128(v) => Ok(Ref::new(C64::new(*v.borrow() as f64, 0.0))),
2067      #[cfg(feature = "i8")]
2068      Value::I8(v) => Ok(Ref::new(C64::new(*v.borrow() as f64, 0.0))),
2069      #[cfg(feature = "i16")]
2070      Value::I16(v) => Ok(Ref::new(C64::new(*v.borrow() as f64, 0.0))),
2071      #[cfg(feature = "i32")]
2072      Value::I32(v) => Ok(Ref::new(C64::new(*v.borrow() as f64, 0.0))),
2073      #[cfg(feature = "i64")]
2074      Value::I64(v) => Ok(Ref::new(C64::new(*v.borrow() as f64, 0.0))),
2075      #[cfg(feature = "i128")]
2076      Value::I128(v) => Ok(Ref::new(C64::new(*v.borrow() as f64, 0.0))),
2077      Value::MutableReference(val) => val.borrow().as_c64(),
2078      _ => Err(
2079        MechError::new(
2080          CannotConvertToTypeError { 
2081            target_type: "c64",
2082          },
2083          None
2084        ).with_compiler_loc()
2085      ),
2086    }
2087  }
2088
2089  #[cfg(feature = "f32")]
2090  pub fn as_f32(&self) -> MResult<Ref<f32>> {
2091    match self {
2092      #[cfg(feature = "u8")]
2093      Value::U8(v) => Ok(Ref::new(*v.borrow() as f32)),
2094      #[cfg(feature = "u16")]
2095      Value::U16(v) => Ok(Ref::new(*v.borrow() as f32)),
2096      #[cfg(feature = "u32")]
2097      Value::U32(v) => Ok(Ref::new(*v.borrow() as f32)),
2098      #[cfg(feature = "u64")]
2099      Value::U64(v) => Ok(Ref::new(*v.borrow() as f32)),
2100      #[cfg(feature = "u128")]
2101      Value::U128(v) => Ok(Ref::new(*v.borrow() as f32)),
2102      #[cfg(feature = "i8")]
2103      Value::I8(v) => Ok(Ref::new(*v.borrow() as f32)),
2104      #[cfg(feature = "i16")]
2105      Value::I16(v) => Ok(Ref::new(*v.borrow() as f32)),
2106      #[cfg(feature = "i32")]
2107      Value::I32(v) => Ok(Ref::new(*v.borrow() as f32)),
2108      #[cfg(feature = "i64")]
2109      Value::I64(v) => Ok(Ref::new(*v.borrow() as f32)),
2110      #[cfg(feature = "i128")]
2111      Value::I128(v) => Ok(Ref::new(*v.borrow() as f32)),
2112      Value::F32(v) => Ok(v.clone()),
2113      #[cfg(feature = "f64")]
2114      Value::F64(v) => Ok(Ref::new((*v.borrow()) as f32)),
2115      Value::MutableReference(val) => val.borrow().as_f32(),
2116      _ => Err(
2117        MechError::new(
2118          CannotConvertToTypeError { 
2119            target_type: "f32",
2120          },
2121          None
2122        ).with_compiler_loc()
2123      ),
2124    }
2125  }
2126
2127  #[cfg(feature = "f64")]
2128  pub fn as_f64(&self) -> MResult<Ref<f64>> {
2129    match self {
2130      #[cfg(feature = "u8")]
2131      Value::U8(v) => Ok(Ref::new(*v.borrow() as f64)),
2132      #[cfg(feature = "u16")]
2133      Value::U16(v) => Ok(Ref::new(*v.borrow() as f64)),
2134      #[cfg(feature = "u32")]
2135      Value::U32(v) => Ok(Ref::new(*v.borrow() as f64)),
2136      #[cfg(feature = "u64")]
2137      Value::U64(v) => Ok(Ref::new(*v.borrow() as f64)),
2138      #[cfg(feature = "u128")]
2139      Value::U128(v) => Ok(Ref::new(*v.borrow() as f64)),
2140      #[cfg(feature = "i8")]
2141      Value::I8(v) => Ok(Ref::new(*v.borrow() as f64)),
2142      #[cfg(feature = "i16")]
2143      Value::I16(v) => Ok(Ref::new(*v.borrow() as f64)),
2144      #[cfg(feature = "i32")]
2145      Value::I32(v) => Ok(Ref::new(*v.borrow() as f64)),
2146      #[cfg(feature = "i64")]
2147      Value::I64(v) => Ok(Ref::new(*v.borrow() as f64)),
2148      #[cfg(feature = "i128")]
2149      Value::I128(v) => Ok(Ref::new(*v.borrow() as f64)),
2150      #[cfg(feature = "f32")]
2151      Value::F32(v) => Ok(Ref::new((*v.borrow()) as f64)),
2152      Value::F64(v) => Ok(v.clone()),
2153      Value::MutableReference(val) => val.borrow().as_f64(),
2154      _ => Err(
2155        MechError::new(
2156          CannotConvertToTypeError { 
2157            target_type: "f64",
2158          },
2159          None
2160        ).with_compiler_loc()
2161      ),
2162    }
2163  }
2164
2165  #[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()) } }
2166  #[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()) } }
2167  #[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()) } }
2168  #[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()) } }
2169  #[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()) } }
2170  #[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()) } }
2171  #[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()) } }
2172  #[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()) } }
2173  #[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()) } }
2174  #[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()) } }
2175  #[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()) } }
2176  #[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()) } }
2177  #[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()) } }
2178  #[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()) } }
2179  #[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()) } }
2180  #[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()) } }
2181
2182  pub fn as_vecusize(&self) -> MResult<Vec<usize>> {
2183    match self {
2184      #[cfg(feature = "u8")]
2185      Value::U8(v) => Ok(vec![*v.borrow() as usize]),
2186      #[cfg(feature = "u16")]
2187      Value::U16(v) => Ok(vec![*v.borrow() as usize]),
2188      #[cfg(feature = "u32")]
2189      Value::U32(v) => Ok(vec![*v.borrow() as usize]),
2190      #[cfg(feature = "u64")]
2191      Value::U64(v) => Ok(vec![*v.borrow() as usize]),
2192      #[cfg(feature = "u128")]
2193      Value::U128(v) => Ok(vec![*v.borrow() as usize]),
2194      #[cfg(feature = "i8")]
2195      Value::I8(v) => Ok(vec![*v.borrow() as usize]),
2196      #[cfg(feature = "i16")]
2197      Value::I16(v) => Ok(vec![*v.borrow() as usize]),
2198      #[cfg(feature = "i32")]
2199      Value::I32(v) => Ok(vec![*v.borrow() as usize]),
2200      #[cfg(feature = "i64")]
2201      Value::I64(v) => Ok(vec![*v.borrow() as usize]),
2202      #[cfg(feature = "i128")]
2203      Value::I128(v) => Ok(vec![*v.borrow() as usize]),
2204      #[cfg(feature = "f32")]
2205      Value::F32(v) => Ok(vec![(*v.borrow()) as usize]),
2206      #[cfg(feature = "f64")]
2207      Value::F64(v) => Ok(vec![(*v.borrow()) as usize]),
2208      #[cfg(feature = "matrix")]
2209      Value::MatrixIndex(v) => Ok(v.as_vec()),
2210      #[cfg(all(feature = "matrix", feature = "f64"))]
2211      Value::MatrixF64(v) => Ok(v.as_vec().iter().map(|x| (*x) as usize).collect::<Vec<usize>>()),
2212      #[cfg(all(feature = "matrix", feature = "f32"))]
2213      Value::MatrixF32(v) => Ok(v.as_vec().iter().map(|x| (*x) as usize).collect::<Vec<usize>>()),
2214      #[cfg(all(feature = "matrix", feature = "u8"))]
2215      Value::MatrixU8(v) => Ok(v.as_vec().iter().map(|x| *x as usize).collect::<Vec<usize>>()),
2216      #[cfg(all(feature = "matrix", feature = "u16"))]  
2217      Value::MatrixU16(v) => Ok(v.as_vec().iter().map(|x| *x as usize).collect::<Vec<usize>>()),
2218      #[cfg(all(feature = "matrix", feature = "u32"))]
2219      Value::MatrixU32(v) => Ok(v.as_vec().iter().map(|x| *x as usize).collect::<Vec<usize>>()),
2220      #[cfg(all(feature = "matrix", feature = "u64"))]
2221      Value::MatrixU64(v) => Ok(v.as_vec().iter().map(|x| *x as usize).collect::<Vec<usize>>()),
2222      #[cfg(all(feature = "matrix", feature = "u128"))]
2223      Value::MatrixU128(v) => Ok(v.as_vec().iter().map(|x| *x as usize).collect::<Vec<usize>>()),
2224      #[cfg(all(feature = "matrix", feature = "i8"))]
2225      Value::MatrixI8(v) => Ok(v.as_vec().iter().map(|x| *x as usize).collect::<Vec<usize>>()),
2226      #[cfg(all(feature = "matrix", feature = "i16"))]
2227      Value::MatrixI16(v) => Ok(v.as_vec().iter().map(|x| *x as usize).collect::<Vec<usize>>()),
2228      #[cfg(all(feature = "matrix", feature = "i32"))]
2229      Value::MatrixI32(v) => Ok(v.as_vec().iter().map(|x| *x as usize).collect::<Vec<usize>>()),
2230      #[cfg(all(feature = "matrix", feature = "i128"))]
2231      Value::MatrixI128(v) => Ok(v.as_vec().iter().map(|x| *x as usize).collect::<Vec<usize>>()),
2232      #[cfg(all(feature = "matrix", feature = "i64"))]
2233      Value::MatrixI64(v) => Ok(v.as_vec().iter().map(|x| *x as usize).collect::<Vec<usize>>()),
2234      #[cfg(all(feature = "matrix", feature = "bool"))]
2235      Value::MatrixBool(_) =>
2236        Err(MechError::new(
2237          CannotConvertToTypeError { target_type: "[usize]" },
2238          None
2239        ).with_compiler_loc()),
2240      #[cfg(any(feature = "bool", feature = "[usize]"))]
2241      Value::Bool(_) =>
2242        Err(MechError::new(
2243          CannotConvertToTypeError { target_type: "[usize]" },
2244          None
2245        ).with_compiler_loc()),
2246      Value::MutableReference(x) => x.borrow().as_vecusize(),
2247      _ =>
2248        Err(MechError::new(
2249          CannotConvertToTypeError { target_type: "[usize]" },
2250          None
2251        ).with_compiler_loc()),
2252    }
2253  }
2254
2255
2256    pub fn as_index(&self) -> MResult<Value> {
2257    match self.as_usize() {      
2258      Ok(ix) => Ok(Value::Index(Ref::new(ix))),
2259      #[cfg(feature = "matrix")]
2260      Err(_) => match self.as_vecusize() {
2261        #[cfg(feature = "matrix")]
2262        Ok(x) => {
2263          let shape = self.shape();
2264          let out = Value::MatrixIndex(usize::to_matrix(x, shape[0] * shape[1],1 ));
2265          Ok(out)
2266        },
2267        #[cfg(all(feature = "matrix", feature = "bool"))]
2268        Err(_) => match self.as_vecbool() {
2269          Ok(x) => {
2270            let shape = self.shape();
2271            let out = match (shape[0], shape[1]) {
2272              (1,1) => Value::Bool(Ref::new(x[0])),
2273              #[cfg(all(feature = "vectord", feature = "bool"))]
2274              (1,n) => Value::MatrixBool(Matrix::DVector(Ref::new(DVector::from_vec(x)))),
2275              #[cfg(all(feature = "vectord", feature = "bool"))]
2276              (m,1) => Value::MatrixBool(Matrix::DVector(Ref::new(DVector::from_vec(x)))),
2277              #[cfg(all(feature = "vectord", feature = "bool"))]
2278              (m,n) => Value::MatrixBool(Matrix::DVector(Ref::new(DVector::from_vec(x)))),
2279              _ => todo!(),
2280            };
2281            Ok(out)
2282          }
2283          Err(_) => match self.as_bool() {
2284            Ok(x) => Ok(Value::Bool(x)),
2285            Err(_) => Err(MechError::new(
2286              CannotConvertToTypeError { target_type: "ix" },
2287              None
2288            ).with_compiler_loc()),
2289          }
2290        }
2291        x => Err(MechError::new(
2292          CannotConvertToTypeError { target_type: "ix" },
2293          None
2294        ).with_compiler_loc()),
2295      }
2296      _ => todo!(),
2297    }
2298  }
2299
2300  pub fn as_usize(&self) -> MResult<usize> {
2301    match self {      
2302      Value::Index(v) => Ok(*v.borrow()),
2303      #[cfg(feature = "u8")]
2304      Value::U8(v) => Ok(*v.borrow() as usize),
2305      #[cfg(feature = "u16")]
2306      Value::U16(v) => Ok(*v.borrow() as usize),
2307      #[cfg(feature = "u32")]
2308      Value::U32(v) => Ok(*v.borrow() as usize),
2309      #[cfg(feature = "u64")]
2310      Value::U64(v) => Ok(*v.borrow() as usize),
2311      #[cfg(feature = "u128")]
2312      Value::U128(v) => Ok(*v.borrow() as usize),
2313      #[cfg(feature = "i8")]
2314      Value::I8(v) => Ok(*v.borrow() as usize),
2315      #[cfg(feature = "i16")]
2316      Value::I16(v) => Ok(*v.borrow() as usize),
2317      #[cfg(feature = "i32")]
2318      Value::I32(v) => Ok(*v.borrow() as usize),
2319      #[cfg(feature = "i64")]
2320      Value::I64(v) => Ok(*v.borrow() as usize),
2321      #[cfg(feature = "i128")]
2322      Value::I128(v) => Ok(*v.borrow() as usize),
2323      #[cfg(feature = "f32")]
2324      Value::F32(v) => Ok((*v.borrow()) as usize),
2325      #[cfg(feature = "f64")]
2326      Value::F64(v) => Ok((*v.borrow()) as usize),
2327      Value::MutableReference(v) => v.borrow().as_usize(),
2328      _ =>
2329        Err(
2330          MechError::new(
2331            CannotConvertToTypeError { target_type: "usize" },
2332            None
2333          ).with_compiler_loc()
2334        ),
2335    }
2336  }
2337
2338  #[cfg(feature = "u8")]
2339  pub fn expect_u8(&self) -> MResult<Ref<u8>> {
2340    match self {
2341      Value::U8(v) => Ok(v.clone()),
2342      Value::MutableReference(v) => v.borrow().expect_u8(),
2343      _ =>
2344        Err(
2345          MechError::new(
2346            CannotConvertToTypeError { target_type: "u8" },
2347            None
2348          ).with_compiler_loc()
2349        ),
2350    }
2351  }
2352
2353  #[cfg(feature = "f64")]
2354  pub fn expect_f64(&self) -> MResult<Ref<f64>> {
2355    match self {
2356      Value::F64(v) => Ok(v.clone()),
2357      Value::MutableReference(v) => v.borrow().expect_f64(),
2358      _ =>
2359        Err(
2360          MechError::new(
2361            CannotConvertToTypeError { target_type: "f64" },
2362            None
2363          ).with_compiler_loc()
2364        ),
2365    }
2366  }
2367
2368}
2369
2370#[cfg(feature = "pretty_print")]
2371impl PrettyPrint for Value {
2372  fn pretty_print(&self) -> String {
2373    let mut builder = Builder::default();
2374    match self {
2375      #[cfg(feature = "u8")]
2376      Value::U8(x)   => {builder.push_record(vec![format!("{}",x.borrow())]);},
2377      #[cfg(feature = "u16")]
2378      Value::U16(x)  => {builder.push_record(vec![format!("{}",x.borrow())]);},
2379      #[cfg(feature = "u32")]
2380      Value::U32(x)  => {builder.push_record(vec![format!("{}",x.borrow())]);},
2381      #[cfg(feature = "u64")]
2382      Value::U64(x)  => {builder.push_record(vec![format!("{}",x.borrow())]);},
2383      #[cfg(feature = "u128")]
2384      Value::U128(x) => {builder.push_record(vec![format!("{}",x.borrow())]);},
2385      #[cfg(feature = "i8")]
2386      Value::I8(x)   => {builder.push_record(vec![format!("{}",x.borrow())]);},
2387      #[cfg(feature = "i16")]
2388      Value::I16(x)  => {builder.push_record(vec![format!("{}",x.borrow())]);},
2389      #[cfg(feature = "i32")]
2390      Value::I32(x)  => {builder.push_record(vec![format!("{}",x.borrow())]);},
2391      #[cfg(feature = "i64")]
2392      Value::I64(x)  => {builder.push_record(vec![format!("{}",x.borrow())]);},
2393      #[cfg(feature = "i128")]
2394      Value::I128(x) => {builder.push_record(vec![format!("{}",x.borrow())]);},
2395      #[cfg(feature = "f32")]
2396      Value::F32(x)  => {builder.push_record(vec![format!("{}",x.borrow())]);},
2397      #[cfg(feature = "f64")]
2398      Value::F64(x)  => {builder.push_record(vec![format!("{}",x.borrow())]);},
2399      #[cfg(any(feature = "bool", feature = "variable_define"))]
2400      Value::Bool(x) => {builder.push_record(vec![format!("{}",x.borrow())]);},
2401      #[cfg(feature = "complex")]
2402      Value::C64(x) => {builder.push_record(vec![x.borrow().pretty_print()]);},
2403      #[cfg(feature = "rational")]
2404      Value::R64(x) => {builder.push_record(vec![format!("{}",x.borrow().pretty_print())]);},
2405      #[cfg(feature = "atom")]
2406      Value::Atom(x) => {builder.push_record(vec![format!("{}",x.borrow())]);},
2407      #[cfg(feature = "set")]
2408      Value::Set(x)  => {return x.borrow().pretty_print();}
2409      #[cfg(feature = "map")]
2410      Value::Map(x)  => {return x.borrow().pretty_print();}
2411      #[cfg(any(feature = "string", feature = "variable_define"))]
2412      Value::String(x) => {return format!("\"{}\"",x.borrow().clone());},
2413      #[cfg(feature = "table")]
2414      Value::Table(x)  => {return x.borrow().pretty_print();},
2415      #[cfg(feature = "tuple")]
2416      Value::Tuple(x)  => {return x.borrow().pretty_print();},
2417      #[cfg(feature = "record")]
2418      Value::Record(x) => {return x.borrow().pretty_print();},
2419      #[cfg(feature = "enum")]
2420      Value::Enum(x) => {return x.borrow().pretty_print();},
2421      #[cfg(feature = "matrix")]
2422      Value::MatrixIndex(x) => {return x.pretty_print();},
2423      #[cfg(all(feature = "matrix", feature = "bool"))]
2424      Value::MatrixBool(x) => {return x.pretty_print();},
2425      #[cfg(all(feature = "matrix", feature = "u8"))]
2426      Value::MatrixU8(x)   => {return x.pretty_print();},
2427      #[cfg(all(feature = "matrix", feature = "u16"))]
2428      Value::MatrixU16(x)  => {return x.pretty_print();},
2429      #[cfg(all(feature = "matrix", feature = "u32"))]
2430      Value::MatrixU32(x)  => {return x.pretty_print();},
2431      #[cfg(all(feature = "matrix", feature = "u64"))]
2432      Value::MatrixU64(x)  => {return x.pretty_print();},
2433      #[cfg(all(feature = "matrix", feature = "u128"))]
2434      Value::MatrixU128(x) => {return x.pretty_print();},
2435      #[cfg(all(feature = "matrix", feature = "i8"))]
2436      Value::MatrixI8(x)   => {return x.pretty_print();},
2437      #[cfg(all(feature = "matrix", feature = "i16"))]
2438      Value::MatrixI16(x)  => {return x.pretty_print();},
2439      #[cfg(all(feature = "matrix", feature = "i32"))]
2440      Value::MatrixI32(x)  => {return x.pretty_print();},
2441      #[cfg(all(feature = "matrix", feature = "i64"))]
2442      Value::MatrixI64(x)  => {return x.pretty_print();},
2443      #[cfg(all(feature = "matrix", feature = "i128"))]
2444      Value::MatrixI128(x) => {return x.pretty_print();},
2445      #[cfg(all(feature = "matrix", feature = "f32"))]
2446      Value::MatrixF32(x)  => {return x.pretty_print();},
2447      #[cfg(all(feature = "matrix", feature = "f64"))]
2448      Value::MatrixF64(x)  => {return x.pretty_print();},
2449      #[cfg(all(feature = "matrix", feature = "any"))]
2450      Value::MatrixValue(x)  => {return x.pretty_print();},
2451      #[cfg(all(feature = "matrix", feature = "string"))]
2452      Value::MatrixString(x)  => {return x.pretty_print();},
2453      #[cfg(all(feature = "matrix", feature = "rational"))]
2454      Value::MatrixR64(x) => {return x.pretty_print();},
2455      #[cfg(all(feature = "matrix", feature = "complex"))]
2456      Value::MatrixC64(x) => {return x.pretty_print();},
2457      Value::MatrixValue(x) => {return x.pretty_print();},
2458      Value::Index(x)  => {builder.push_record(vec![format!("{}",x.borrow())]);},
2459      Value::MutableReference(x) => {return x.borrow().pretty_print();},
2460      Value::Typed(x, _) => { return x.pretty_print(); },
2461      Value::Empty | Value::EmptyKind(_) => builder.push_record(vec!["_"]),
2462      Value::IndexAll => builder.push_record(vec![":"]),
2463      Value::Id(x) => builder.push_record(vec![format!("{}",humanize(x))]),
2464      Value::Kind(x) => builder.push_record(vec![format!("<{}>",x)]),
2465      x => {
2466        todo!("{x:#?}");
2467      },
2468    };
2469    let value_style = Style::empty()
2470      .top(' ')
2471      .left(' ')
2472      .right(' ')
2473      .bottom(' ')
2474      .vertical(' ')
2475      .intersection_bottom(' ')
2476      .corner_top_left(' ')
2477      .corner_top_right(' ')
2478      .corner_bottom_left(' ')
2479      .corner_bottom_right(' ');
2480    let mut table = builder.build();
2481    table.with(value_style);
2482    format!("{table}")
2483  }
2484}
2485
2486
2487pub trait ToIndex {
2488  fn to_index(&self) -> Value;
2489}
2490
2491#[cfg(feature = "matrix")]
2492impl ToIndex for Ref<Vec<i64>> { fn to_index(&self) -> Value { (*self.borrow()).iter().map(|x| *x as usize).collect::<Vec<usize>>().to_value() } }
2493
2494pub trait ToValue {
2495  fn to_value(&self) -> Value;
2496}
2497
2498#[cfg(feature = "matrix")]
2499impl ToValue for Vec<usize> {
2500  fn to_value(&self) -> Value {
2501    match self.len() {
2502      1 => Value::Index(Ref::new(self[0].clone())),
2503      #[cfg(feature = "vector2")]
2504      2 => Value::MatrixIndex(Matrix::Vector2(Ref::new(Vector2::from_vec(self.clone())))),
2505      #[cfg(feature = "vector3")]
2506      3 => Value::MatrixIndex(Matrix::Vector3(Ref::new(Vector3::from_vec(self.clone())))),
2507      #[cfg(feature = "vector4")]
2508      4 => Value::MatrixIndex(Matrix::Vector4(Ref::new(Vector4::from_vec(self.clone())))),
2509      #[cfg(feature = "vectord")]
2510      n => Value::MatrixIndex(Matrix::DVector(Ref::new(DVector::from_vec(self.clone())))),
2511      _ => todo!(),
2512    }
2513  }
2514}
2515
2516impl ToValue for Ref<usize>  { fn to_value(&self) -> Value { Value::Index(self.clone())  } }
2517#[cfg(feature = "u8")]
2518impl ToValue for Ref<u8>     { fn to_value(&self) -> Value { Value::U8(self.clone())     } }
2519#[cfg(feature = "u16")]
2520impl ToValue for Ref<u16>    { fn to_value(&self) -> Value { Value::U16(self.clone())    } }
2521#[cfg(feature = "u32")]
2522impl ToValue for Ref<u32>    { fn to_value(&self) -> Value { Value::U32(self.clone())    } }
2523#[cfg(feature = "u64")]
2524impl ToValue for Ref<u64>    { fn to_value(&self) -> Value { Value::U64(self.clone())    } }
2525#[cfg(feature = "u128")]
2526impl ToValue for Ref<u128>   { fn to_value(&self) -> Value { Value::U128(self.clone())   } }
2527#[cfg(feature = "i8")]
2528impl ToValue for Ref<i8>     { fn to_value(&self) -> Value { Value::I8(self.clone())     } }
2529#[cfg(feature = "i16")]
2530impl ToValue for Ref<i16>    { fn to_value(&self) -> Value { Value::I16(self.clone())    } }
2531#[cfg(feature = "i32")]
2532impl ToValue for Ref<i32>    { fn to_value(&self) -> Value { Value::I32(self.clone())    } }
2533#[cfg(feature = "i64")]
2534impl ToValue for Ref<i64>    { fn to_value(&self) -> Value { Value::I64(self.clone())    } }
2535#[cfg(feature = "i128")]
2536impl ToValue for Ref<i128>   { fn to_value(&self) -> Value { Value::I128(self.clone())   } }
2537#[cfg(feature = "f32")]
2538impl ToValue for Ref<f32>    { fn to_value(&self) -> Value { Value::F32(self.clone())    } }
2539#[cfg(feature = "f64")]
2540impl ToValue for Ref<f64>    { fn to_value(&self) -> Value { Value::F64(self.clone())    } }
2541#[cfg(any(feature = "bool", feature = "variable_define"))]
2542impl ToValue for Ref<bool>   { fn to_value(&self) -> Value { Value::Bool(self.clone())   } }
2543#[cfg(any(feature = "string", feature = "variable_define"))]
2544impl ToValue for Ref<String> { fn to_value(&self) -> Value { Value::String(self.clone()) } }
2545#[cfg(feature = "rational")]
2546impl ToValue for Ref<R64> { fn to_value(&self) -> Value { Value::R64(self.clone()) } }
2547#[cfg(feature = "complex")]
2548impl ToValue for Ref<C64> { fn to_value(&self) -> Value { Value::C64(self.clone()) } }
2549#[cfg(feature = "atom")]
2550impl ToValue for Ref<MechAtom> { fn to_value(&self) -> Value { Value::Atom(self.clone()) } }
2551
2552impl ToValue for Ref<Value> { fn to_value(&self) -> Value { (*self.borrow()).clone() } }
2553
2554#[cfg(feature = "u8")]
2555impl From<u8> for Value {
2556  fn from(val: u8) -> Self {
2557    Value::U8(Ref::new(val))
2558  }
2559}
2560
2561#[cfg(feature = "u16")]
2562impl From<u16> for Value {
2563  fn from(val: u16) -> Self {
2564    Value::U16(Ref::new(val))
2565  }
2566}
2567
2568#[cfg(feature = "u32")]
2569impl From<u32> for Value {
2570  fn from(val: u32) -> Self {
2571    Value::U32(Ref::new(val))
2572  }
2573}
2574
2575#[cfg(feature = "u64")]
2576impl From<u64> for Value {
2577  fn from(val: u64) -> Self {
2578    Value::U64(Ref::new(val))
2579  }
2580}
2581
2582#[cfg(feature = "u128")]
2583impl From<u128> for Value {
2584  fn from(val: u128) -> Self {
2585    Value::U128(Ref::new(val))
2586  }
2587}
2588
2589#[cfg(feature = "i8")]
2590impl From<i8> for Value {
2591  fn from(val: i8) -> Self {
2592    Value::I8(Ref::new(val))
2593  }
2594}
2595
2596#[cfg(feature = "i16")]
2597impl From<i16> for Value {
2598  fn from(val: i16) -> Self {
2599    Value::I16(Ref::new(val))
2600  }
2601}
2602
2603#[cfg(feature = "i32")]
2604impl From<i32> for Value {
2605  fn from(val: i32) -> Self {
2606    Value::I32(Ref::new(val))
2607  }
2608}
2609
2610#[cfg(feature = "i64")]
2611impl From<i64> for Value {
2612  fn from(val: i64) -> Self {
2613    Value::I64(Ref::new(val))
2614  }
2615}
2616
2617#[cfg(feature = "i128")]
2618impl From<i128> for Value {
2619  fn from(val: i128) -> Self {
2620    Value::I128(Ref::new(val))
2621  }
2622}
2623
2624#[cfg(feature = "f32")]
2625impl From<f32> for Value {
2626  fn from(val: f32) -> Self {
2627    Value::F32(Ref::new(val))
2628  }
2629}
2630
2631#[cfg(feature = "f64")]
2632impl From<f64> for Value {
2633  fn from(val: f64) -> Self {
2634    Value::F64(Ref::new(val))
2635  }
2636}
2637
2638#[cfg(any(feature = "bool", feature = "variable_define"))]
2639impl From<bool> for Value {
2640  fn from(val: bool) -> Self {
2641    Value::Bool(Ref::new(val))
2642  }
2643}
2644
2645#[cfg(any(feature = "string", feature = "variable_define"))]
2646impl From<String> for Value {
2647  fn from(val: String) -> Self {
2648    Value::String(Ref::new(val))
2649  }
2650}
2651
2652#[cfg(feature = "rational")]
2653impl From<R64> for Value {
2654  fn from(val: R64) -> Self {
2655    Value::R64(Ref::new(val))
2656  }
2657}
2658
2659
2660pub trait ToUsize {
2661  fn to_usize(&self) -> usize;
2662}
2663
2664macro_rules! impl_to_usize_for {
2665  ($t:ty) => {
2666    impl ToUsize for $t {
2667      fn to_usize(&self) -> usize {
2668        #[allow(unused_comparisons)]
2669        if *self < 0 as $t {
2670          panic!("Cannot convert negative number to usize");
2671        }
2672        *self as usize
2673      }
2674    }
2675  };
2676}
2677
2678#[cfg(feature = "u8")]
2679impl_to_usize_for!(u8);
2680#[cfg(feature = "u16")]
2681impl_to_usize_for!(u16);
2682#[cfg(feature = "u32")]
2683impl_to_usize_for!(u32);
2684#[cfg(feature = "u64")]
2685impl_to_usize_for!(u64);
2686#[cfg(feature = "u128")]
2687impl_to_usize_for!(u128);
2688impl_to_usize_for!(usize);
2689
2690#[cfg(feature = "i8")]
2691impl_to_usize_for!(i8);
2692#[cfg(feature = "i16")]
2693impl_to_usize_for!(i16);
2694#[cfg(feature = "i32")]
2695impl_to_usize_for!(i32);
2696#[cfg(feature = "i64")]
2697impl_to_usize_for!(i64);
2698#[cfg(feature = "i128")]
2699impl_to_usize_for!(i128);
2700
2701#[cfg(feature = "f64")]
2702impl_to_usize_for!(f64);
2703#[cfg(feature = "f32")]
2704impl_to_usize_for!(f32);
2705
2706#[cfg(feature = "table")]
2707impl ToValue for Ref<MechTable> {
2708  fn to_value(&self) -> Value {
2709    Value::Table(self.clone())
2710  }
2711}
2712
2713#[cfg(feature = "set")]
2714impl ToValue for Ref<MechSet> {
2715  fn to_value(&self) -> Value {
2716    Value::Set(self.clone())
2717  }
2718}
2719
2720#[cfg(feature = "map")]
2721impl ToValue for Ref<MechMap> {
2722  fn to_value(&self) -> Value {
2723    Value::Map(self.clone())
2724  }
2725}
2726
2727#[cfg(feature = "tuple")]
2728impl ToValue for Ref<MechTuple> {
2729  fn to_value(&self) -> Value {
2730    Value::Tuple(self.clone())
2731  }
2732}
2733
2734#[cfg(feature = "record")]
2735impl ToValue for Ref<MechRecord> {
2736  fn to_value(&self) -> Value {
2737    Value::Record(self.clone())
2738  }
2739}
2740
2741// Errors
2742
2743#[derive(Debug, Clone)]
2744pub struct UnhandledFunctionArgumentKindError;
2745
2746impl MechErrorKind for UnhandledFunctionArgumentKindError {
2747  fn name(&self) -> &str { "UnhandledFunctionArgumentKind" }
2748  fn message(&self) -> String {
2749    "Value kind is not valid for this function.".to_string()
2750  }
2751}
2752
2753#[derive(Debug, Clone)]
2754pub struct CannotConvertToTypeError {
2755  pub target_type: &'static str,
2756}
2757
2758impl MechErrorKind for CannotConvertToTypeError {
2759  fn name(&self) -> &str { "CannotConvertToType" }
2760  fn message(&self) -> String {
2761    format!("Cannot convert to {}", self.target_type)
2762  }
2763}