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