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