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