mech_core/
value.rs

1use crate::matrix::Matrix;
2use crate::*;
3use crate::nodes::Matrix as Mat;
4use crate::types::ComplexNumber;
5use crate::{MechError, MechErrorKind, hash_str, nodes::Kind as NodeKind, nodes::*, humanize};
6use std::collections::HashMap;
7
8use na::{Vector3, DVector, Vector2, Vector4, RowDVector, Matrix1, Matrix3, Matrix4, RowVector3, RowVector4, RowVector2, DMatrix, Rotation3, Matrix2x3, Matrix3x2, Matrix6, Matrix2};
9use std::hash::{Hash, Hasher};
10use indexmap::set::IndexSet;
11use indexmap::map::*;
12use tabled::{
13  builder::Builder,
14  settings::{object::Rows,Panel, Span, Alignment, Modify, Style},
15  Tabled,
16};
17use paste::paste;
18use serde::ser::{Serialize, Serializer, SerializeStruct};
19use serde::de::{self, Deserialize, SeqAccess, Deserializer, MapAccess, Visitor};
20use std::fmt;
21use std::cell::RefCell;
22use std::rc::Rc;
23use num_rational::Rational64;
24
25macro_rules! impl_as_type {
26  ($target_type:ty) => {
27    paste!{
28      pub fn [<as_ $target_type>](&self) -> Option<Ref<$target_type>> {
29        match self {
30          Value::U8(v) => Some(new_ref(*v.borrow() as $target_type)),
31          Value::U16(v) => Some(new_ref(*v.borrow() as $target_type)),
32          Value::U32(v) => Some(new_ref(*v.borrow() as $target_type)),
33          Value::U64(v) => Some(new_ref(*v.borrow() as $target_type)),
34          Value::U128(v) => Some(new_ref(*v.borrow() as $target_type)),
35          Value::I8(v) => Some(new_ref(*v.borrow() as $target_type)),
36          Value::I16(v) => Some(new_ref(*v.borrow() as $target_type)),
37          Value::I32(v) => Some(new_ref(*v.borrow() as $target_type)),
38          Value::I64(v) => Some(new_ref(*v.borrow() as $target_type)),
39          Value::I128(v) => Some(new_ref(*v.borrow() as $target_type)),
40          Value::F32(v) => Some(new_ref((*v.borrow()).0 as $target_type)),
41          Value::F64(v) => Some(new_ref((*v.borrow()).0 as $target_type)),
42          Value::Id(v) => Some(new_ref(*v as $target_type)),
43          Value::MutableReference(val) => val.borrow().[<as_ $target_type>](),
44          _ => None,
45        }
46      }
47    }
48  };
49}
50
51// Value ----------------------------------------------------------------------
52
53#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
54pub enum ValueKind {
55  U8, U16, U32, U64, U128, I8, I16, I32, I64, I128, F32, F64, ComplexNumber, RationalNumber,
56  String, Bool, Id, Index, Empty, Any, 
57  Matrix(Box<ValueKind>,Vec<usize>),  Enum(u64),                  Record(Vec<(String,ValueKind)>),
58  Map(Box<ValueKind>,Box<ValueKind>), Atom(u64),                  Table(Vec<(String,ValueKind)>, usize), 
59  Tuple(Vec<ValueKind>),              Reference(Box<ValueKind>),  Set(Box<ValueKind>, Option<usize>), 
60  Option(Box<ValueKind>),
61}
62
63impl std::fmt::Display for ValueKind {
64  fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
65    match self {
66      ValueKind::RationalNumber => write!(f, "r64"),
67      ValueKind::ComplexNumber => write!(f, "c64"),
68      ValueKind::U8 => write!(f, "u8"),
69      ValueKind::U16 => write!(f, "u16"),
70      ValueKind::U32 => write!(f, "u32"),
71      ValueKind::U64 => write!(f, "u64"),
72      ValueKind::U128 => write!(f, "u128"),
73      ValueKind::I8 => write!(f, "i8"),
74      ValueKind::I16 => write!(f, "i16"),
75      ValueKind::I32 => write!(f, "i32"),
76      ValueKind::I64 => write!(f, "i64"),
77      ValueKind::I128 => write!(f, "i128"),
78      ValueKind::F32 => write!(f, "f32"),
79      ValueKind::F64 => write!(f, "f64"),
80      ValueKind::String => write!(f, "string"),
81      ValueKind::Bool => write!(f, "bool"),
82      ValueKind::Matrix(x,s) => write!(f, "[{}]:{}", x, s.iter().map(|s| s.to_string()).collect::<Vec<String>>().join(",")),
83      ValueKind::Enum(x) => write!(f, "{}",x),
84      ValueKind::Set(x,el) => write!(f, "{{{}}}{}", x, el.map_or("".to_string(), |e| format!(":{}", e))),
85      ValueKind::Map(x,y) => write!(f, "{{{}:{}}}",x,y),
86      ValueKind::Record(x) => write!(f, "{{{}}}",x.iter().map(|(i,k)| format!("{}<{}>",i.to_string(),k)).collect::<Vec<String>>().join(" ")),
87      ValueKind::Table(x,y) => {
88        let size_str = if y > &0 { format!(":{}", y) } else { "".to_string() };
89        write!(f, "|{}|{}",x.iter().map(|(i,k)| format!("{}<{}>",i.to_string(),k)).collect::<Vec<String>>().join(" "),size_str)
90      }
91      ValueKind::Tuple(x) => write!(f, "({})",x.iter().map(|x| format!("{}",x)).collect::<Vec<String>>().join(",")),
92      ValueKind::Id => write!(f, "id"),
93      ValueKind::Index => write!(f, "ix"),
94      ValueKind::Reference(x) => write!(f, "{}",x),
95      ValueKind::Atom(x) => write!(f, "`{}",x),
96      ValueKind::Empty => write!(f, "_"),
97      ValueKind::Any => write!(f, "_"),
98      ValueKind::Option(x) => write!(f, "{}?", x),
99    }
100  }
101}
102
103impl ValueKind {
104
105  pub fn collection_kind(&self) -> Option<ValueKind> {
106    match self {
107      ValueKind::Matrix(x,_) => Some(*x.clone()),
108      ValueKind::Set(x,_) => Some(*x.clone()),
109      _ => None,
110    }
111  }
112
113  pub fn deref_kind(&self) -> ValueKind {
114    match self {
115      ValueKind::Reference(x) => *x.clone(),
116      _ => self.clone(),
117    }
118  }
119
120  pub fn is_convertible_to(&self, other: &ValueKind) -> bool {
121    use ValueKind::*;
122    match (self, other) {
123      // Unsigned widening
124      (U8, U16) | (U8, U32) | (U8, U64) | (U8, U128) |
125      (U16, U32) | (U16, U64) | (U16, U128) |
126      (U32, U64) | (U32, U128) |
127      (U64, U128) => true,
128
129      // Signed widening
130      (I8, I16) | (I8, I32) | (I8, I64) | (I8, I128) |
131      (I16, I32) | (I16, I64) | (I16, I128) |
132      (I32, I64) | (I32, I128) |
133      (I64, I128) => true,
134
135      // Unsigned -> signed widening
136      (U8, I16) | (U8, I32) | (U8, I64) | (U8, I128) |
137      (U16, I32) | (U16, I64) | (U16, I128) |
138      (U32, I64) | (U32, I128) |
139      (U64, I128) => true,
140
141      // Signed -> unsigned widening (runtime safety not enforced here)
142      (I8, U16) | (I8, U32) | (I8, U64) | (I8, U128) |
143      (I16, U32) | (I16, U64) | (I16, U128) |
144      (I32, U64) | (I32, U128) |
145      (I64, U128) => true,
146
147      // Integer -> float
148      (U8, F32) | (U8, F64) |
149      (U16, F32) | (U16, F64) |
150      (U32, F32) | (U32, F64) |
151      (U64, F32) | (U64, F64) |
152      (U128, F32) | (U128, F64) |
153      (I8, F32) | (I8, F64) |
154      (I16, F32) | (I16, F64) |
155      (I32, F32) | (I32, F64) |
156      (I64, F32) | (I64, F64) |
157      (I128, F32) | (I128, F64) => true,
158
159      // Float widening + narrowing
160      (F32, F64) | (F64, F32) => true,
161
162      // Float -> integer (allowed, but lossy)
163      (F32, I8) | (F32, I16) | (F32, I32) | (F32, I64) | (F32, I128) |
164      (F32, U8) | (F32, U16) | (F32, U32) | (F32, U64) | (F32, U128) |
165      (F64, I8) | (F64, I16) | (F64, I32) | (F64, I64) | (F64, I128) |
166      (F64, U8) | (F64, U16) | (F64, U32) | (F64, U64) | (F64, U128) => true,
167
168      // Index conversions (both ways)
169      (Index, U8) | (Index, U16) | (Index, U32) | (Index, U64) | (Index, U128) |
170      (Index, I8) | (Index, I16) | (Index, I32) | (Index, I64) | (Index, I128) |
171      (Index, F32) | (Index, F64) |
172      (U8, Index) | (U16, Index) | (U32, Index) | (U64, Index) | (U128, Index) |
173      (I8, Index) | (I16, Index) | (I32, Index) | (I64, Index) | (I128, Index) => true,
174
175      // Matrix: element type convertible and shape matches
176      (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,
177
178      // Option conversions
179      (Option(box a), Option(box b)) if a.is_convertible_to(b) => true,
180
181      // Reference conversions
182      (Reference(box a), Reference(box b)) if a.is_convertible_to(b) => true,
183
184      // Tuple conversions (element-wise)
185      (Tuple(a), Tuple(b)) if a.len() == b.len() && a.iter().zip(b.iter()).all(|(x, y)| x.is_convertible_to(y)) => true,
186
187      // Set conversions
188      (Set(box a, _), Set(box b, _)) if a.is_convertible_to(b) => true,
189
190      // Map conversions
191      (Map(box ak, box av), Map(box bk, box bv)) if ak.is_convertible_to(bk) && av.is_convertible_to(bv) => true,
192
193      // Table conversions: allow source to have extra columns
194      (Table(acols, _), Table(bcols, _)) if bcols.iter().all(|(bk, bv)| 
195        acols.iter().any(|(ak, av)| ak == bk && av.is_convertible_to(bv))
196      ) => true,
197
198      // Record conversions: allow source to have extra fields
199      (Record(afields), Record(bfields)) if bfields.iter().all(|(bk, bv)| 
200        afields.iter().any(|(ak, av)| ak == bk && av.is_convertible_to(bv))
201      ) => true,
202
203      // Direct match
204      _ => self == other,
205    }
206  }
207
208  pub fn is_compatible(k1: ValueKind, k2: ValueKind) -> bool {
209    match k1 {
210      ValueKind::Reference(x) => {
211        ValueKind::is_compatible(*x,k2)
212      }
213      ValueKind::Matrix(x,_) => {
214        *x == k2
215      }
216      x => x == k2,
217    }
218  }
219}
220
221#[derive(Clone, Debug, PartialEq, Eq)]
222pub enum Value {
223  U8(Ref<u8>),
224  U16(Ref<u16>),
225  U32(Ref<u32>),
226  U64(Ref<u64>),
227  U128(Ref<u128>),
228  I8(Ref<i8>),
229  I16(Ref<i16>),
230  I32(Ref<i32>),
231  I64(Ref<i64>),
232  I128(Ref<i128>),
233  F32(Ref<F32>),
234  F64(Ref<F64>),
235  String(Ref<String>),
236  Bool(Ref<bool>),
237  Atom(u64),
238  MatrixIndex(Matrix<usize>),
239  MatrixBool(Matrix<bool>),
240  MatrixU8(Matrix<u8>),
241  MatrixU16(Matrix<u16>),
242  MatrixU32(Matrix<u32>),
243  MatrixU64(Matrix<u64>),
244  MatrixU128(Matrix<u128>),
245  MatrixI8(Matrix<i8>),
246  MatrixI16(Matrix<i16>),
247  MatrixI32(Matrix<i32>),
248  MatrixI64(Matrix<i64>),
249  MatrixI128(Matrix<i128>),
250  MatrixF32(Matrix<F32>),
251  MatrixF64(Matrix<F64>),
252  MatrixString(Matrix<String>),
253  MatrixRationalNumber(Matrix<RationalNumber>),
254  MatrixComplexNumber(Matrix<ComplexNumber>),
255  MatrixValue(Matrix<Value>),
256  ComplexNumber(Ref<ComplexNumber>),
257  RationalNumber(Ref<RationalNumber>),
258  Set(MechSet),
259  Map(MechMap),
260  Record(Ref<MechRecord>),
261  Table(Ref<MechTable>),
262  Tuple(MechTuple),
263  Enum(Box<MechEnum>),
264  Id(u64),
265  Index(Ref<usize>),
266  MutableReference(MutableReference),
267  Kind(ValueKind),
268  IndexAll,
269  Empty
270}
271
272impl fmt::Display for Value {
273  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
274    self.pretty_print().fmt(f)
275  }
276}
277
278impl Hash for Value {
279  fn hash<H: Hasher>(&self, state: &mut H) {
280    match self {
281      Value::RationalNumber(x) => x.borrow().hash(state),
282      Value::Id(x)   => x.hash(state),
283      Value::Kind(x) => x.hash(state),
284      Value::U8(x)   => x.borrow().hash(state),
285      Value::U16(x)  => x.borrow().hash(state),
286      Value::U32(x)  => x.borrow().hash(state),
287      Value::U64(x)  => x.borrow().hash(state),
288      Value::U128(x) => x.borrow().hash(state),
289      Value::I8(x)   => x.borrow().hash(state),
290      Value::I16(x)  => x.borrow().hash(state),
291      Value::I32(x)  => x.borrow().hash(state),
292      Value::I64(x)  => x.borrow().hash(state),
293      Value::I128(x) => x.borrow().hash(state),
294      Value::F32(x)  => x.borrow().hash(state),
295      Value::F64(x)  => x.borrow().hash(state),
296      Value::ComplexNumber(x) => x.borrow().hash(state),
297      Value::Index(x)=> x.borrow().hash(state),
298      Value::Bool(x) => x.borrow().hash(state),
299      Value::Atom(x) => x.hash(state),
300      Value::Set(x)  => x.hash(state),
301      Value::Map(x)  => x.hash(state),
302      Value::Table(x) => x.borrow().hash(state),
303      Value::Tuple(x) => x.hash(state),
304      Value::Record(x) => x.borrow().hash(state),
305      Value::Enum(x) => x.hash(state),
306      Value::String(x) => x.borrow().hash(state),
307      Value::MatrixBool(x) => x.hash(state),
308      Value::MatrixIndex(x) => x.hash(state),
309      Value::MatrixU8(x)   => x.hash(state),
310      Value::MatrixU16(x)  => x.hash(state),
311      Value::MatrixU32(x)  => x.hash(state),
312      Value::MatrixU64(x)  => x.hash(state),
313      Value::MatrixU128(x) => x.hash(state),
314      Value::MatrixI8(x)   => x.hash(state),
315      Value::MatrixI16(x)  => x.hash(state),
316      Value::MatrixI32(x)  => x.hash(state),
317      Value::MatrixI64(x)  => x.hash(state),
318      Value::MatrixI128(x) => x.hash(state),
319      Value::MatrixF32(x)  => x.hash(state),
320      Value::MatrixF64(x)  => x.hash(state),
321      Value::MatrixString(x) => x.hash(state),
322      Value::MatrixValue(x)  => x.hash(state),
323      Value::MatrixRationalNumber(x) => x.hash(state),
324      Value::MatrixComplexNumber(x) => x.hash(state),
325      Value::MutableReference(x) => x.borrow().hash(state),
326      Value::Empty => Value::Empty.hash(state),
327      Value::IndexAll => Value::IndexAll.hash(state),
328    }
329  }
330}
331
332impl Value {
333
334  pub fn convert_to(&self, other: &ValueKind) -> Option<Value> {
335
336    if self.kind() == *other {
337        return Some(self.clone());
338    }
339
340    if !self.kind().is_convertible_to(other) {
341        return None;
342    }
343
344    match (self, other) {
345    // ==== Unsigned widening and narrowing ====
346    (Value::U8(v), ValueKind::U16) => Some(Value::U16(new_ref((*v.borrow()) as u16))),
347    (Value::U8(v), ValueKind::U32) => Some(Value::U32(new_ref((*v.borrow()) as u32))),
348    (Value::U8(v), ValueKind::U64) => Some(Value::U64(new_ref((*v.borrow()) as u64))),
349    (Value::U8(v), ValueKind::U128) => Some(Value::U128(new_ref((*v.borrow()) as u128))),
350    (Value::U8(v), ValueKind::I16) => Some(Value::I16(new_ref((*v.borrow()) as i16))),
351    (Value::U8(v), ValueKind::I32) => Some(Value::I32(new_ref((*v.borrow()) as i32))),
352    (Value::U8(v), ValueKind::I64) => Some(Value::I64(new_ref((*v.borrow()) as i64))),
353    (Value::U8(v), ValueKind::I128) => Some(Value::I128(new_ref((*v.borrow()) as i128))),
354    (Value::U8(v), ValueKind::F32) => Some(Value::F32(new_ref(F32::new(*v.borrow() as f32)))),
355    (Value::U8(v), ValueKind::F64) => Some(Value::F64(new_ref(F64::new(*v.borrow() as f64)))),
356
357    (Value::U16(v), ValueKind::U8) => Some(Value::U8(new_ref((*v.borrow()) as u8))),
358    (Value::U16(v), ValueKind::U32) => Some(Value::U32(new_ref((*v.borrow()) as u32))),
359    (Value::U16(v), ValueKind::U64) => Some(Value::U64(new_ref((*v.borrow()) as u64))),
360    (Value::U16(v), ValueKind::U128) => Some(Value::U128(new_ref((*v.borrow()) as u128))),
361    (Value::U16(v), ValueKind::I8) => Some(Value::I8(new_ref((*v.borrow()) as i8))),
362    (Value::U16(v), ValueKind::I32) => Some(Value::I32(new_ref((*v.borrow()) as i32))),
363    (Value::U16(v), ValueKind::I64) => Some(Value::I64(new_ref((*v.borrow()) as i64))),
364    (Value::U16(v), ValueKind::I128) => Some(Value::I128(new_ref((*v.borrow()) as i128))),
365    (Value::U16(v), ValueKind::F32) => Some(Value::F32(new_ref(F32::new(*v.borrow() as f32)))),
366    (Value::U16(v), ValueKind::F64) => Some(Value::F64(new_ref(F64::new(*v.borrow() as f64)))),
367
368    (Value::U32(v), ValueKind::U8) => Some(Value::U8(new_ref((*v.borrow()) as u8))),
369    (Value::U32(v), ValueKind::U16) => Some(Value::U16(new_ref((*v.borrow()) as u16))),
370    (Value::U32(v), ValueKind::U64) => Some(Value::U64(new_ref((*v.borrow()) as u64))),
371    (Value::U32(v), ValueKind::U128) => Some(Value::U128(new_ref((*v.borrow()) as u128))),
372    (Value::U32(v), ValueKind::I8) => Some(Value::I8(new_ref((*v.borrow()) as i8))),
373    (Value::U32(v), ValueKind::I16) => Some(Value::I16(new_ref((*v.borrow()) as i16))),
374    (Value::U32(v), ValueKind::I64) => Some(Value::I64(new_ref((*v.borrow()) as i64))),
375    (Value::U32(v), ValueKind::I128) => Some(Value::I128(new_ref((*v.borrow()) as i128))),
376    (Value::U32(v), ValueKind::F32) => Some(Value::F32(new_ref(F32::new(*v.borrow() as f32)))),
377    (Value::U32(v), ValueKind::F64) => Some(Value::F64(new_ref(F64::new(*v.borrow() as f64)))),
378
379    (Value::U64(v), ValueKind::U8) => Some(Value::U8(new_ref((*v.borrow()) as u8))),
380    (Value::U64(v), ValueKind::U16) => Some(Value::U16(new_ref((*v.borrow()) as u16))),
381    (Value::U64(v), ValueKind::U32) => Some(Value::U32(new_ref((*v.borrow()) as u32))),
382    (Value::U64(v), ValueKind::U128) => Some(Value::U128(new_ref((*v.borrow()) as u128))),
383    (Value::U64(v), ValueKind::I8) => Some(Value::I8(new_ref((*v.borrow()) as i8))),
384    (Value::U64(v), ValueKind::I16) => Some(Value::I16(new_ref((*v.borrow()) as i16))),
385    (Value::U64(v), ValueKind::I32) => Some(Value::I32(new_ref((*v.borrow()) as i32))),
386    (Value::U64(v), ValueKind::I128) => Some(Value::I128(new_ref((*v.borrow()) as i128))),
387    (Value::U64(v), ValueKind::F32) => Some(Value::F32(new_ref(F32::new(*v.borrow() as f32)))),
388    (Value::U64(v), ValueKind::F64) => Some(Value::F64(new_ref(F64::new(*v.borrow() as f64)))),
389
390    (Value::U128(v), ValueKind::U8) => Some(Value::U8(new_ref((*v.borrow()) as u8))),
391    (Value::U128(v), ValueKind::U16) => Some(Value::U16(new_ref((*v.borrow()) as u16))),
392    (Value::U128(v), ValueKind::U32) => Some(Value::U32(new_ref((*v.borrow()) as u32))),
393    (Value::U128(v), ValueKind::U64) => Some(Value::U64(new_ref((*v.borrow()) as u64))),
394    (Value::U128(v), ValueKind::I8) => Some(Value::I8(new_ref((*v.borrow()) as i8))),
395    (Value::U128(v), ValueKind::I16) => Some(Value::I16(new_ref((*v.borrow()) as i16))),
396    (Value::U128(v), ValueKind::I32) => Some(Value::I32(new_ref((*v.borrow()) as i32))),
397    (Value::U128(v), ValueKind::I64) => Some(Value::I64(new_ref((*v.borrow()) as i64))),
398    (Value::U128(v), ValueKind::F32) => Some(Value::F32(new_ref(F32::new(*v.borrow() as f32)))),
399    (Value::U128(v), ValueKind::F64) => Some(Value::F64(new_ref(F64::new(*v.borrow() as f64)))),
400
401    // ==== Signed widening and narrowing ====
402    (Value::I8(v), ValueKind::I16) => Some(Value::I16(new_ref((*v.borrow()) as i16))),
403    (Value::I8(v), ValueKind::I32) => Some(Value::I32(new_ref((*v.borrow()) as i32))),
404    (Value::I8(v), ValueKind::I64) => Some(Value::I64(new_ref((*v.borrow()) as i64))),
405    (Value::I8(v), ValueKind::I128) => Some(Value::I128(new_ref((*v.borrow()) as i128))),
406    (Value::I8(v), ValueKind::U16) => Some(Value::U16(new_ref((*v.borrow()) as u16))),
407    (Value::I8(v), ValueKind::U32) => Some(Value::U32(new_ref((*v.borrow()) as u32))),
408    (Value::I8(v), ValueKind::U64) => Some(Value::U64(new_ref((*v.borrow()) as u64))),
409    (Value::I8(v), ValueKind::U128) => Some(Value::U128(new_ref((*v.borrow()) as u128))),
410    (Value::I8(v), ValueKind::F32) => Some(Value::F32(new_ref(F32::new(*v.borrow() as f32)))),
411    (Value::I8(v), ValueKind::F64) => Some(Value::F64(new_ref(F64::new(*v.borrow() as f64)))),
412
413    (Value::I16(v), ValueKind::I8) => Some(Value::I8(new_ref((*v.borrow()) as i8))),
414    (Value::I16(v), ValueKind::I32) => Some(Value::I32(new_ref((*v.borrow()) as i32))),
415    (Value::I16(v), ValueKind::I64) => Some(Value::I64(new_ref((*v.borrow()) as i64))),
416    (Value::I16(v), ValueKind::I128) => Some(Value::I128(new_ref((*v.borrow()) as i128))),
417    (Value::I16(v), ValueKind::U8) => Some(Value::U8(new_ref((*v.borrow()) as u8))),
418    (Value::I16(v), ValueKind::U32) => Some(Value::U32(new_ref((*v.borrow()) as u32))),
419    (Value::I16(v), ValueKind::U64) => Some(Value::U64(new_ref((*v.borrow()) as u64))),
420    (Value::I16(v), ValueKind::U128) => Some(Value::U128(new_ref((*v.borrow()) as u128))),
421    (Value::I16(v), ValueKind::F32) => Some(Value::F32(new_ref(F32::new(*v.borrow() as f32)))),
422    (Value::I16(v), ValueKind::F64) => Some(Value::F64(new_ref(F64::new(*v.borrow() as f64)))),
423
424    (Value::I32(v), ValueKind::I8) => Some(Value::I8(new_ref((*v.borrow()) as i8))),
425    (Value::I32(v), ValueKind::I16) => Some(Value::I16(new_ref((*v.borrow()) as i16))),
426    (Value::I32(v), ValueKind::I64) => Some(Value::I64(new_ref((*v.borrow()) as i64))),
427    (Value::I32(v), ValueKind::I128) => Some(Value::I128(new_ref((*v.borrow()) as i128))),
428    (Value::I32(v), ValueKind::U8) => Some(Value::U8(new_ref((*v.borrow()) as u8))),
429    (Value::I32(v), ValueKind::U16) => Some(Value::U16(new_ref((*v.borrow()) as u16))),
430    (Value::I32(v), ValueKind::U64) => Some(Value::U64(new_ref((*v.borrow()) as u64))),
431    (Value::I32(v), ValueKind::U128) => Some(Value::U128(new_ref((*v.borrow()) as u128))),
432    (Value::I32(v), ValueKind::F32) => Some(Value::F32(new_ref(F32::new(*v.borrow() as f32)))),
433    (Value::I32(v), ValueKind::F64) => Some(Value::F64(new_ref(F64::new(*v.borrow() as f64)))),
434
435    (Value::I64(v), ValueKind::I8) => Some(Value::I8(new_ref((*v.borrow()) as i8))),
436    (Value::I64(v), ValueKind::I16) => Some(Value::I16(new_ref((*v.borrow()) as i16))),
437    (Value::I64(v), ValueKind::I32) => Some(Value::I32(new_ref((*v.borrow()) as i32))),
438    (Value::I64(v), ValueKind::I128) => Some(Value::I128(new_ref((*v.borrow()) as i128))),
439    (Value::I64(v), ValueKind::U8) => Some(Value::U8(new_ref((*v.borrow()) as u8))),
440    (Value::I64(v), ValueKind::U16) => Some(Value::U16(new_ref((*v.borrow()) as u16))),
441    (Value::I64(v), ValueKind::U32) => Some(Value::U32(new_ref((*v.borrow()) as u32))),
442    (Value::I64(v), ValueKind::U128) => Some(Value::U128(new_ref((*v.borrow()) as u128))),
443    (Value::I64(v), ValueKind::F32) => Some(Value::F32(new_ref(F32::new(*v.borrow() as f32)))),
444    (Value::I64(v), ValueKind::F64) => Some(Value::F64(new_ref(F64::new(*v.borrow() as f64)))),
445
446    (Value::I128(v), ValueKind::I8) => Some(Value::I8(new_ref((*v.borrow()) as i8))),
447    (Value::I128(v), ValueKind::I16) => Some(Value::I16(new_ref((*v.borrow()) as i16))),
448    (Value::I128(v), ValueKind::I32) => Some(Value::I32(new_ref((*v.borrow()) as i32))),
449    (Value::I128(v), ValueKind::I64) => Some(Value::I64(new_ref((*v.borrow()) as i64))),
450    (Value::I128(v), ValueKind::U8) => Some(Value::U8(new_ref((*v.borrow()) as u8))),
451    (Value::I128(v), ValueKind::U16) => Some(Value::U16(new_ref((*v.borrow()) as u16))),
452    (Value::I128(v), ValueKind::U32) => Some(Value::U32(new_ref((*v.borrow()) as u32))),
453    (Value::I128(v), ValueKind::U64) => Some(Value::U64(new_ref((*v.borrow()) as u64))),
454    (Value::I128(v), ValueKind::F32) => Some(Value::F32(new_ref(F32::new(*v.borrow() as f32)))),
455    (Value::I128(v), ValueKind::F64) => Some(Value::F64(new_ref(F64::new(*v.borrow() as f64)))),
456
457    // ==== Float widening and narrowing ====
458    (Value::F32(v), ValueKind::F64) => Some(Value::F64(new_ref(F64::new(v.borrow().0 as f64)))),
459    (Value::F64(v), ValueKind::F32) => Some(Value::F32(new_ref(F32::new(v.borrow().0 as f32)))),
460
461    // ==== Float to integer conversions (truncate) ====
462    (Value::F32(v), ValueKind::I8) => Some(Value::I8(new_ref(v.borrow().0 as i8))),
463    (Value::F32(v), ValueKind::I16) => Some(Value::I16(new_ref(v.borrow().0 as i16))),
464    (Value::F32(v), ValueKind::I32) => Some(Value::I32(new_ref(v.borrow().0 as i32))),
465    (Value::F32(v), ValueKind::I64) => Some(Value::I64(new_ref(v.borrow().0 as i64))),
466    (Value::F32(v), ValueKind::I128) => Some(Value::I128(new_ref(v.borrow().0 as i128))),
467    (Value::F32(v), ValueKind::U8) => Some(Value::U8(new_ref(v.borrow().0 as u8))),
468    (Value::F32(v), ValueKind::U16) => Some(Value::U16(new_ref(v.borrow().0 as u16))),
469    (Value::F32(v), ValueKind::U32) => Some(Value::U32(new_ref(v.borrow().0 as u32))),
470    (Value::F32(v), ValueKind::U64) => Some(Value::U64(new_ref(v.borrow().0 as u64))),
471    (Value::F32(v), ValueKind::U128) => Some(Value::U128(new_ref(v.borrow().0 as u128))),
472
473    (Value::F64(v), ValueKind::I8) => Some(Value::I8(new_ref(v.borrow().0 as i8))),
474    (Value::F64(v), ValueKind::I16) => Some(Value::I16(new_ref(v.borrow().0 as i16))),
475    (Value::F64(v), ValueKind::I32) => Some(Value::I32(new_ref(v.borrow().0 as i32))),
476    (Value::F64(v), ValueKind::I64) => Some(Value::I64(new_ref(v.borrow().0 as i64))),
477    (Value::F64(v), ValueKind::I128) => Some(Value::I128(new_ref(v.borrow().0 as i128))),
478    (Value::F64(v), ValueKind::U8) => Some(Value::U8(new_ref(v.borrow().0 as u8))),
479    (Value::F64(v), ValueKind::U16) => Some(Value::U16(new_ref(v.borrow().0 as u16))),
480    (Value::F64(v), ValueKind::U32) => Some(Value::U32(new_ref(v.borrow().0 as u32))),
481    (Value::F64(v), ValueKind::U64) => Some(Value::U64(new_ref(v.borrow().0 as u64))),
482    (Value::F64(v), ValueKind::U128) => Some(Value::U128(new_ref(v.borrow().0 as u128))),
483
484      /*
485      // ==== INDEX conversions ====
486      (Value::Index(i), U32) => Some(Value::U32(new_ref((*i.borrow()) as u32))),
487      (Value::U32(v), Index) => Some(Value::Index(new_ref((*v.borrow()) as usize))),
488
489
490      // ==== MATRIX conversions (element-wise) ====
491      (Value::MatrixU8(m), MatrixU16) => Some(Value::MatrixU16(m.map(|x| *x as u16))),
492      (Value::MatrixI32(m), MatrixF64) => Some(Value::MatrixF64(m.map(|x| (*x) as f64))),
493      // You can expand other matrix conversions similarly...
494
495      // ==== COMPLEX TYPES (stubs) ====
496      (Value::Set(set), Set(_)) => Some(Value::Set(set.clone())), // TODO: element-wise convert
497      (Value::Map(map), Map(_)) => Some(Value::Map(map.clone())), // TODO: key/value convert
498      (Value::Record(r), Record(_)) => Some(Value::Record(r.clone())), // TODO: field convert
499      (Value::Table(t), Table(_)) => Some(Value::Table(t.clone())), // TODO: column convert
500
501      // ==== ENUM, KIND ====
502      (Value::Enum(e), Enum(_)) => Some(Value::Enum(e.clone())),
503      (Value::Kind(k), Kind(_)) => Some(Value::Kind(k.clone())),
504
505      // ==== SPECIAL CASES ====
506      (Value::IndexAll, IndexAll) => Some(Value::IndexAll),
507      (Value::Empty, Empty) => Some(Value::Empty),
508      */
509      // ==== FALLBACK ====
510      _ => None,
511    }
512  }
513
514  pub fn size_of(&self) -> usize {
515    match self {
516      Value::RationalNumber(x) => 16,
517      Value::U8(x) => 1,
518      Value::U16(x) => 2,
519      Value::U32(x) => 4,
520      Value::U64(x) => 8,
521      Value::U128(x) => 16,
522      Value::I8(x) => 1,
523      Value::I16(x) => 2,
524      Value::I32(x) => 4,
525      Value::I64(x) => 8,
526      Value::I128(x) => 16,
527      Value::F32(x) => 4,
528      Value::F64(x) => 8,
529      Value::Bool(x) => 1,
530      Value::ComplexNumber(x) => 16,
531      Value::MatrixIndex(x) =>x.size_of(),
532      Value::MatrixBool(x) =>x.size_of(),
533      Value::MatrixU8(x)   => x.size_of(),
534      Value::MatrixU16(x)  => x.size_of(),
535      Value::MatrixU32(x)  => x.size_of(),
536      Value::MatrixU64(x)  => x.size_of(),
537      Value::MatrixU128(x) => x.size_of(),
538      Value::MatrixI8(x)   => x.size_of(),
539      Value::MatrixI16(x)  => x.size_of(),
540      Value::MatrixI32(x)  => x.size_of(),
541      Value::MatrixI64(x)  => x.size_of(),
542      Value::MatrixI128(x) => x.size_of(),
543      Value::MatrixF32(x)  => x.size_of(),
544      Value::MatrixF64(x)  => x.size_of(),
545      Value::MatrixValue(x)  => x.size_of(),
546      Value::MatrixString(x) => x.size_of(),
547      Value::MatrixRationalNumber(x) => x.size_of(),
548      Value::MatrixComplexNumber(x) => x.size_of(),
549      Value::String(x) => x.borrow().len(),
550      Value::Atom(x) => 8,
551      Value::Set(x) => x.size_of(),
552      Value::Map(x) => x.size_of(),
553      Value::Table(x) => x.borrow().size_of(),
554      Value::Record(x) => x.borrow().size_of(),
555      Value::Tuple(x) => x.size_of(),
556      Value::Enum(x) => x.size_of(),
557      Value::MutableReference(x) => x.borrow().size_of(),
558      Value::Id(_) => 8,
559      Value::Index(x) => 8,
560      Value::Kind(_) => 0, // Kind is not a value, so it has no size
561      Value::Empty => 0,
562      Value::IndexAll => 0, // IndexAll is a special value, so it has no size
563    }
564  }
565
566  pub fn to_html(&self) -> String {
567    match self {
568      Value::U8(n) => format!("<span class='mech-number'>{}</span>", n.borrow()),
569      Value::U16(n) => format!("<span class='mech-number'>{}</span>", n.borrow()),
570      Value::U32(n) => format!("<span class='mech-number'>{}</span>", n.borrow()),
571      Value::U64(n) => format!("<span class='mech-number'>{}</span>", n.borrow()),
572      Value::I8(n) => format!("<span class='mech-number'>{}</span>", n.borrow()),
573      Value::I128(n) => format!("<span class='mech-number'>{}</span>", n.borrow()),
574      Value::I16(n) => format!("<span class='mech-number'>{}</span>", n.borrow()),
575      Value::I32(n) => format!("<span class='mech-number'>{}</span>", n.borrow()),
576      Value::I64(n) => format!("<span class='mech-number'>{}</span>", n.borrow()),
577      Value::I128(n) => format!("<span class='mech-number'>{}</span>", n.borrow()),
578      Value::F32(n) => format!("<span class='mech-number'>{}</span>", n.borrow()),
579      Value::F64(n) => format!("<span class='mech-number'>{}</span>", n.borrow()),
580      Value::String(s) => format!("<span class='mech-string'>\"{}\"</span>", s.borrow()),
581      Value::Bool(b) => format!("<span class='mech-boolean'>{}</span>", b.borrow()),
582      Value::ComplexNumber(c) => c.borrow().to_html(),
583      Value::MatrixU8(m) => m.to_html(),
584      Value::MatrixU16(m) => m.to_html(),
585      Value::MatrixU32(m) => m.to_html(),
586      Value::MatrixU64(m) => m.to_html(),
587      Value::MatrixU128(m) => m.to_html(),
588      Value::MatrixI8(m) => m.to_html(),
589      Value::MatrixI16(m) => m.to_html(),
590      Value::MatrixI32(m) => m.to_html(),
591      Value::MatrixI64(m) => m.to_html(),
592      Value::MatrixI128(m) => m.to_html(),
593      Value::MatrixF64(m) => m.to_html(),
594      Value::MatrixF32(m) => m.to_html(),
595      Value::MatrixIndex(m) => m.to_html(),
596      Value::MatrixBool(m) => m.to_html(),
597      Value::MatrixString(m) => m.to_html(),
598      Value::MatrixValue(m) => m.to_html(),
599      Value::MatrixRationalNumber(m) => m.to_html(),
600      Value::MatrixComplexNumber(m) => m.to_html(),
601      Value::MutableReference(m) => {
602        let inner = m.borrow();
603        format!("<span class='mech-reference'>{}</span>", inner.to_html())
604      },
605      Value::Atom(a) => format!("<span class=\"mech-atom\"><span class=\"mech-atom-grave\">`</span><span class=\"mech-atom-name\">{}</span></span>",a),
606      Value::Set(s) => s.to_html(),
607      Value::Map(m) => m.to_html(),
608      Value::Table(t) => t.borrow().to_html(),
609      Value::Record(r) => r.borrow().to_html(),
610      Value::Tuple(t) => t.to_html(),
611      Value::Enum(e) => e.to_html(),
612      _ => "".to_string(),
613    }
614  }
615
616  pub fn pretty_print(&self) -> String {
617    let mut builder = Builder::default();
618    match self {
619      Value::U8(x)   => {builder.push_record(vec![format!("{}",x.borrow())]);},
620      Value::U16(x)  => {builder.push_record(vec![format!("{}",x.borrow())]);},
621      Value::U32(x)  => {builder.push_record(vec![format!("{}",x.borrow())]);},
622      Value::U64(x)  => {builder.push_record(vec![format!("{}",x.borrow())]);},
623      Value::U128(x) => {builder.push_record(vec![format!("{}",x.borrow())]);},
624      Value::I8(x)   => {builder.push_record(vec![format!("{}",x.borrow())]);},
625      Value::I16(x)  => {builder.push_record(vec![format!("{}",x.borrow())]);},
626      Value::I32(x)  => {builder.push_record(vec![format!("{}",x.borrow())]);},
627      Value::I64(x)  => {builder.push_record(vec![format!("{}",x.borrow())]);},
628      Value::I128(x) => {builder.push_record(vec![format!("{}",x.borrow())]);},
629      Value::F32(x)  => {builder.push_record(vec![format!("{}",x.borrow().0)]);},
630      Value::F64(x)  => {builder.push_record(vec![format!("{}",x.borrow().0)]);},
631      Value::Bool(x) => {builder.push_record(vec![format!("{}",x.borrow())]);},
632      Value::Index(x)  => {builder.push_record(vec![format!("{}",x.borrow())]);},
633      Value::ComplexNumber(x) => {builder.push_record(vec![x.borrow().pretty_print()]);},
634      Value::RationalNumber(x) => {builder.push_record(vec![format!("{}",x.borrow().pretty_print())]);},
635      Value::Atom(x) => {builder.push_record(vec![format!("{}",x)]);},
636      Value::Set(x)  => {return x.pretty_print();}
637      Value::Map(x)  => {return x.pretty_print();}
638      Value::String(x) => {return format!("\"{}\"",x.borrow().clone());},
639      Value::Table(x)  => {return x.borrow().pretty_print();},
640      Value::Tuple(x)  => {return x.pretty_print();},
641      Value::Record(x) => {return x.borrow().pretty_print();},
642      Value::Enum(x) => {return x.pretty_print();},
643      Value::MatrixIndex(x) => {return x.pretty_print();}
644      Value::MatrixBool(x) => {return x.pretty_print();}
645      Value::MatrixU8(x)   => {return x.pretty_print();},
646      Value::MatrixU16(x)  => {return x.pretty_print();},
647      Value::MatrixU32(x)  => {return x.pretty_print();},
648      Value::MatrixU64(x)  => {return x.pretty_print();},
649      Value::MatrixU128(x) => {return x.pretty_print();},
650      Value::MatrixI8(x)   => {return x.pretty_print();},
651      Value::MatrixI16(x)  => {return x.pretty_print();},
652      Value::MatrixI32(x)  => {return x.pretty_print();},
653      Value::MatrixI64(x)  => {return x.pretty_print();},
654      Value::MatrixI128(x) => {return x.pretty_print();},
655      Value::MatrixF32(x)  => {return x.pretty_print();},
656      Value::MatrixF64(x)  => {return x.pretty_print();},
657      Value::MatrixValue(x)  => {return x.pretty_print();},
658      Value::MatrixString(x)  => {return x.pretty_print();},
659      Value::MatrixRationalNumber(x) => {return x.pretty_print();},
660      Value::MatrixComplexNumber(x) => {return x.pretty_print();},
661      Value::MutableReference(x) => {return x.borrow().pretty_print();},
662      Value::Empty => builder.push_record(vec!["_"]),
663      Value::IndexAll => builder.push_record(vec![":"]),
664      Value::Id(x) => builder.push_record(vec![format!("{}",humanize(x))]),
665      Value::Kind(x) => builder.push_record(vec![format!("{}",x)]),
666    };
667    let value_style = Style::empty()
668      .top(' ')
669      .left(' ')
670      .right(' ')
671      .bottom(' ')
672      .vertical(' ')
673      .intersection_bottom(' ')
674      .corner_top_left(' ')
675      .corner_top_right(' ')
676      .corner_bottom_left(' ')
677      .corner_bottom_right(' ');
678    let mut table = builder.build();
679    table.with(value_style);
680    format!("{table}")
681  }
682
683  pub fn shape(&self) -> Vec<usize> {
684    match self {
685      Value::RationalNumber(x) => vec![1,1],
686      Value::ComplexNumber(x) => vec![1,1],
687      Value::U8(x) => vec![1,1],
688      Value::U16(x) => vec![1,1],
689      Value::U32(x) => vec![1,1],
690      Value::U64(x) => vec![1,1],
691      Value::U128(x) => vec![1,1],
692      Value::I8(x) => vec![1,1],
693      Value::I16(x) => vec![1,1],
694      Value::I32(x) => vec![1,1],
695      Value::I64(x) => vec![1,1],
696      Value::I128(x) => vec![1,1],
697      Value::F32(x) => vec![1,1],
698      Value::F64(x) => vec![1,1],
699      Value::Index(x) => vec![1,1],
700      Value::String(x) => vec![1,1],
701      Value::Bool(x) => vec![1,1],
702      Value::Atom(x) => vec![1,1],
703      Value::MatrixIndex(x) => x.shape(),
704      Value::MatrixBool(x) => x.shape(),
705      Value::MatrixU8(x) => x.shape(),
706      Value::MatrixU16(x) => x.shape(),
707      Value::MatrixU32(x) => x.shape(),
708      Value::MatrixU64(x) => x.shape(),
709      Value::MatrixU128(x) => x.shape(),
710      Value::MatrixI8(x) => x.shape(),
711      Value::MatrixI16(x) => x.shape(),
712      Value::MatrixI32(x) => x.shape(),
713      Value::MatrixI64(x) => x.shape(),
714      Value::MatrixI128(x) => x.shape(),
715      Value::MatrixF32(x) => x.shape(),
716      Value::MatrixF64(x) => x.shape(),
717      Value::MatrixString(x) => x.shape(),
718      Value::MatrixValue(x) => x.shape(),
719      Value::MatrixRationalNumber(x) => x.shape(),
720      Value::MatrixComplexNumber(x) => x.shape(),
721      Value::Enum(x) => vec![1,1],
722      Value::Table(x) => x.borrow().shape(),
723      Value::Set(x) => vec![1,x.set.len()],
724      Value::Map(x) => vec![1,x.map.len()],
725      Value::Record(x) => x.borrow().shape(),
726      Value::Tuple(x) => vec![1,x.size()],
727      Value::MutableReference(x) => x.borrow().shape(),
728      Value::Empty => vec![0,0],
729      Value::IndexAll => vec![0,0],
730      Value::Kind(_) => vec![0,0],
731      Value::Id(x) => vec![0,0],
732    }
733  }
734
735  pub fn deref_kind(&self) -> ValueKind {
736    match self {
737      Value::MutableReference(x) => x.borrow().kind(),
738      x => x.kind(),
739    }
740  }
741
742  pub fn kind(&self) -> ValueKind {
743    match self {
744      Value::ComplexNumber(_) => ValueKind::ComplexNumber,
745      Value::RationalNumber(_) => ValueKind::RationalNumber,
746      Value::U8(_) => ValueKind::U8,
747      Value::U16(_) => ValueKind::U16,
748      Value::U32(_) => ValueKind::U32,
749      Value::U64(_) => ValueKind::U64,
750      Value::U128(_) => ValueKind::U128,
751      Value::I8(_) => ValueKind::I8,
752      Value::I16(_) => ValueKind::I16,
753      Value::I32(_) => ValueKind::I32,
754      Value::I64(_) => ValueKind::I64,
755      Value::I128(_) => ValueKind::I128,
756      Value::F32(_) => ValueKind::F32,
757      Value::F64(_) => ValueKind::F64,
758      Value::String(_) => ValueKind::String,
759      Value::Bool(_) => ValueKind::Bool,
760      Value::Atom(x) => ValueKind::Atom(*x),
761      Value::MatrixIndex(x) => ValueKind::Matrix(Box::new(ValueKind::Index),x.shape()),
762      Value::MatrixBool(x) => ValueKind::Matrix(Box::new(ValueKind::Bool),x.shape()),
763      Value::MatrixU8(x) => ValueKind::Matrix(Box::new(ValueKind::U8),x.shape()),
764      Value::MatrixU16(x) => ValueKind::Matrix(Box::new(ValueKind::U16),x.shape()),
765      Value::MatrixU32(x) => ValueKind::Matrix(Box::new(ValueKind::U32),x.shape()),
766      Value::MatrixU64(x) => ValueKind::Matrix(Box::new(ValueKind::U64),x.shape()),
767      Value::MatrixU128(x) => ValueKind::Matrix(Box::new(ValueKind::U128),x.shape()),
768      Value::MatrixI8(x) => ValueKind::Matrix(Box::new(ValueKind::I8),x.shape()),
769      Value::MatrixI16(x) => ValueKind::Matrix(Box::new(ValueKind::I16),x.shape()),
770      Value::MatrixI32(x) => ValueKind::Matrix(Box::new(ValueKind::I32),x.shape()),
771      Value::MatrixI64(x) => ValueKind::Matrix(Box::new(ValueKind::I64),x.shape()),
772      Value::MatrixI128(x) => ValueKind::Matrix(Box::new(ValueKind::U128,),x.shape()),
773      Value::MatrixF32(x) => ValueKind::Matrix(Box::new(ValueKind::F32),x.shape()),
774      Value::MatrixF64(x) => ValueKind::Matrix(Box::new(ValueKind::F64),x.shape()),
775      Value::MatrixString(x) => ValueKind::Matrix(Box::new(ValueKind::String),x.shape()),
776      Value::MatrixValue(x) => ValueKind::Matrix(Box::new(ValueKind::Any),x.shape()),
777      Value::MatrixRationalNumber(x) => ValueKind::Matrix(Box::new(ValueKind::RationalNumber),x.shape()),
778      Value::MatrixComplexNumber(x) => ValueKind::Matrix(Box::new(ValueKind::ComplexNumber),x.shape()),
779      Value::Table(x) => x.borrow().kind(),
780      Value::Set(x) => x.kind(),
781      Value::Map(x) => x.kind(),
782      Value::Record(x) => x.borrow().kind(),
783      Value::Tuple(x) => x.kind(),
784      Value::Enum(x) => x.kind(),
785      Value::MutableReference(x) => ValueKind::Reference(Box::new(x.borrow().kind())),
786      Value::Empty => ValueKind::Empty,
787      Value::IndexAll => ValueKind::Empty,
788      Value::Id(x) => ValueKind::Id,
789      Value::Index(x) => ValueKind::Index,
790      Value::Kind(x) => x.clone(),
791    }
792  }
793
794  pub fn is_matrix(&self) -> bool {
795    match self {
796      Value::MatrixIndex(_) | Value::MatrixBool(_) | Value::MatrixU8(_) | 
797      Value::MatrixU16(_) | Value::MatrixU32(_) | Value::MatrixU64(_) | 
798      Value::MatrixU128(_) | Value::MatrixI8(_) | Value::MatrixI16(_) | 
799      Value::MatrixI32(_) | Value::MatrixI64(_) | Value::MatrixI128(_) | 
800      Value::MatrixF32(_) | Value::MatrixF64(_) | Value::MatrixString(_) |
801      Value::MatrixValue(_) => true,
802      _ => false,
803    }
804  }
805
806  pub fn is_scalar(&self) -> bool {
807    match self {
808      Value::U8(_) | Value::U16(_) | Value::U32(_) | 
809      Value::U64(_) | Value::U128(_) | Value::I8(_) | 
810      Value::I16(_) | Value::I32(_) | Value::I64(_) | 
811      Value::I128(_) | Value::F32(_) | Value::F64(_) | 
812      Value::Bool(_) | Value::String(_) | 
813      Value::Atom(_) | Value::Index(_) => true,
814      _ => false,
815    }
816  }
817
818  pub fn as_bool(&self) -> Option<Ref<bool>> {if let Value::Bool(v) = self { Some(v.clone()) } else if let Value::MutableReference(val) = self { val.borrow().as_bool() } else { None }}
819  
820  impl_as_type!(i8);
821  impl_as_type!(i16);
822  impl_as_type!(i32);
823  impl_as_type!(i64);
824  impl_as_type!(i128);
825  impl_as_type!(u8);
826  impl_as_type!(u16);
827  impl_as_type!(u32);
828  impl_as_type!(u64);
829  impl_as_type!(u128);
830
831  pub fn as_string(&self) -> Option<Ref<String>> {
832    match self {
833      Value::String(v) => Some(v.clone()),
834      Value::U8(v) => Some(new_ref(v.borrow().to_string())),
835      Value::U16(v) => Some(new_ref(v.borrow().to_string())),
836      Value::U32(v) => Some(new_ref(v.borrow().to_string())),
837      Value::U64(v) => Some(new_ref(v.borrow().to_string())),
838      Value::U128(v) => Some(new_ref(v.borrow().to_string())),
839      Value::I8(v) => Some(new_ref(v.borrow().to_string())),
840      Value::I16(v) => Some(new_ref(v.borrow().to_string())),
841      Value::I32(v) => Some(new_ref(v.borrow().to_string())),
842      Value::I64(v) => Some(new_ref(v.borrow().to_string())),
843      Value::I128(v) => Some(new_ref(v.borrow().to_string())),
844      Value::F32(v) => Some(new_ref(format!("{}", v.borrow().0))),
845      Value::F64(v) => Some(new_ref(format!("{}", v.borrow().0))),
846      Value::Bool(v) => Some(new_ref(format!("{}", v.borrow()))),
847      Value::MutableReference(val) => val.borrow().as_string(),
848      _ => None,
849    }
850  }
851
852  pub fn as_rationalnumber(&self) -> Option<Ref<RationalNumber>> {
853    match self {
854      Value::RationalNumber(v) => Some(v.clone()),
855      Value::F32(v) => Some(new_ref(RationalNumber::new(v.borrow().0 as i64, 1))),
856      Value::F64(v) => Some(new_ref(RationalNumber::new(v.borrow().0 as i64, 1))),
857      Value::U8(v) => Some(new_ref(RationalNumber::new(*v.borrow() as i64, 1))),
858      Value::U16(v) => Some(new_ref(RationalNumber::new(*v.borrow() as i64, 1))),
859      Value::U32(v) => Some(new_ref(RationalNumber::new(*v.borrow() as i64, 1))),
860      Value::U64(v) => Some(new_ref(RationalNumber::new(*v.borrow() as i64, 1))),
861      Value::U128(v) => Some(new_ref(RationalNumber::new(*v.borrow() as i64, 1))),
862      Value::I8(v) => Some(new_ref(RationalNumber::new(*v.borrow() as i64, 1))),
863      Value::I16(v) => Some(new_ref(RationalNumber::new(*v.borrow() as i64, 1))),
864      Value::I32(v) => Some(new_ref(RationalNumber::new(*v.borrow() as i64, 1))),
865      Value::I64(v) => Some(new_ref(RationalNumber::new(*v.borrow() as i64, 1))),
866      Value::I128(v) => Some(new_ref(RationalNumber::new(*v.borrow() as i64, 1))),
867      Value::MutableReference(val) => val.borrow().as_rationalnumber(),
868      _ => None,
869    }
870  }
871
872  pub fn as_complexnumber(&self) -> Option<Ref<ComplexNumber>> {
873    match self {
874      Value::ComplexNumber(v) => Some(v.clone()),
875      Value::F32(v) =>  Some(new_ref(ComplexNumber::new(v.borrow().0 as f64, 0.0))),
876      Value::F64(v) =>  Some(new_ref(ComplexNumber::new(v.borrow().0, 0.0))),
877      Value::U8(v) =>   Some(new_ref(ComplexNumber::new(*v.borrow() as f64, 0.0))),
878      Value::U16(v) =>  Some(new_ref(ComplexNumber::new(*v.borrow() as f64, 0.0))),
879      Value::U32(v) =>  Some(new_ref(ComplexNumber::new(*v.borrow() as f64, 0.0))),
880      Value::U64(v) =>  Some(new_ref(ComplexNumber::new(*v.borrow() as f64, 0.0))),
881      Value::U128(v) => Some(new_ref(ComplexNumber::new(*v.borrow() as f64, 0.0))),
882      Value::I8(v) =>   Some(new_ref(ComplexNumber::new(*v.borrow() as f64, 0.0))),
883      Value::I16(v) =>  Some(new_ref(ComplexNumber::new(*v.borrow() as f64, 0.0))),
884      Value::I32(v) =>  Some(new_ref(ComplexNumber::new(*v.borrow() as f64, 0.0))),
885      Value::I64(v) =>  Some(new_ref(ComplexNumber::new(*v.borrow() as f64, 0.0))),
886      Value::I128(v) => Some(new_ref(ComplexNumber::new(*v.borrow() as f64, 0.0))),
887      Value::MutableReference(val) => val.borrow().as_complexnumber(),
888      _ => None,
889    }
890  }
891
892  pub fn as_f32(&self) -> Option<Ref<F32>> {
893    match self {
894      Value::U8(v) => Some(new_ref(F32::new(*v.borrow() as f32))),
895      Value::U16(v) => Some(new_ref(F32::new(*v.borrow() as f32))),
896      Value::U32(v) => Some(new_ref(F32::new(*v.borrow() as f32))),
897      Value::U64(v) => Some(new_ref(F32::new(*v.borrow() as f32))),
898      Value::U128(v) => Some(new_ref(F32::new(*v.borrow() as f32))),
899      Value::I8(v) => Some(new_ref(F32::new(*v.borrow() as f32))),
900      Value::I16(v) => Some(new_ref(F32::new(*v.borrow() as f32))),
901      Value::I32(v) => Some(new_ref(F32::new(*v.borrow() as f32))),
902      Value::I64(v) => Some(new_ref(F32::new(*v.borrow() as f32))),
903      Value::I128(v) => Some(new_ref(F32::new(*v.borrow() as f32))),
904      Value::F32(v) => Some(new_ref(F32::new((*v.borrow()).0 as f32))),
905      Value::F64(v) => Some(new_ref(F32::new((*v.borrow()).0 as f32))),
906      Value::MutableReference(val) => val.borrow().as_f32(),
907      _ => None,
908    }
909  }
910
911  pub fn as_f64(&self) -> Option<Ref<F64>> {
912    match self {
913      Value::U8(v) => Some(new_ref(F64::new(*v.borrow() as f64))),
914      Value::U16(v) => Some(new_ref(F64::new(*v.borrow() as f64))),
915      Value::U32(v) => Some(new_ref(F64::new(*v.borrow() as f64))),
916      Value::U64(v) => Some(new_ref(F64::new(*v.borrow() as f64))),
917      Value::U128(v) => Some(new_ref(F64::new(*v.borrow() as f64))),
918      Value::I8(v) => Some(new_ref(F64::new(*v.borrow() as f64))),
919      Value::I16(v) => Some(new_ref(F64::new(*v.borrow() as f64))),
920      Value::I32(v) => Some(new_ref(F64::new(*v.borrow() as f64))),
921      Value::I64(v) => Some(new_ref(F64::new(*v.borrow() as f64))),
922      Value::I128(v) => Some(new_ref(F64::new(*v.borrow() as f64))),
923      Value::F64(v) => Some(new_ref(F64::new((*v.borrow()).0 as f64))),
924      Value::F64(v) => Some(new_ref(F64::new((*v.borrow()).0 as f64))),
925      Value::MutableReference(val) => val.borrow().as_f64(),
926      _ => None,
927    }
928  }
929
930  pub fn as_vecbool(&self) -> Option<Vec<bool>> {if let Value::MatrixBool(v)  = self { Some(v.as_vec()) } else if let Value::Bool(v) = self { Some(vec![v.borrow().clone()]) } else if let Value::MutableReference(val) = self { val.borrow().as_vecbool()  } else { None }}
931  
932  pub fn as_vecf64(&self) -> Option<Vec<F64>> { if let Value::MatrixF64(v) = self { Some(v.as_vec()) } else if let Value::F64(v) = self { Some(vec![v.borrow().clone()]) } else if let Value::MutableReference(val) = self { val.borrow().as_vecf64() } else if let Some(v) = self.as_f64() { Some(vec![v.borrow().clone()]) } else { None } }
933  pub fn as_vecf32(&self) -> Option<Vec<F32>> { if let Value::MatrixF32(v) = self { Some(v.as_vec()) } else if let Value::F32(v) = self { Some(vec![v.borrow().clone()]) } else if let Value::MutableReference(val) = self { val.borrow().as_vecf32() } else if let Some(v) = self.as_f32() { Some(vec![v.borrow().clone()]) } else { None } }
934
935  pub fn as_vecu8(&self) -> Option<Vec<u8>> { if let Value::MatrixU8(v) = self { Some(v.as_vec()) } else if let Value::U8(v) = self { Some(vec![v.borrow().clone()]) } else if let Value::MutableReference(val) = self { val.borrow().as_vecu8() } else if let Some(v) = self.as_u8() { Some(vec![v.borrow().clone()]) } else { None } }
936  pub fn as_vecu16(&self) -> Option<Vec<u16>> { if let Value::MatrixU16(v) = self { Some(v.as_vec()) } else if let Value::U16(v) = self { Some(vec![v.borrow().clone()]) } else if let Value::MutableReference(val) = self { val.borrow().as_vecu16() } else if let Some(v) = self.as_u16() { Some(vec![v.borrow().clone()]) } else { None } }
937  pub fn as_vecu32(&self) -> Option<Vec<u32>> { if let Value::MatrixU32(v) = self { Some(v.as_vec()) } else if let Value::U32(v) = self { Some(vec![v.borrow().clone()]) } else if let Value::MutableReference(val) = self { val.borrow().as_vecu32() } else if let Some(v) = self.as_u32() { Some(vec![v.borrow().clone()]) } else { None } }
938  pub fn as_vecu64(&self) -> Option<Vec<u64>> { if let Value::MatrixU64(v) = self { Some(v.as_vec()) } else if let Value::U64(v) = self { Some(vec![v.borrow().clone()]) } else if let Value::MutableReference(val) = self { val.borrow().as_vecu64() } else if let Some(v) = self.as_u64() { Some(vec![v.borrow().clone()]) } else { None } }
939  pub fn as_vecu128(&self) -> Option<Vec<u128>> { if let Value::MatrixU128(v) = self { Some(v.as_vec()) } else if let Value::U128(v) = self { Some(vec![v.borrow().clone()]) } else if let Value::MutableReference(val) = self { val.borrow().as_vecu128() } else if let Some(v) = self.as_u128() { Some(vec![v.borrow().clone()]) } else { None } }
940
941  pub fn as_veci8(&self) -> Option<Vec<i8>> { if let Value::MatrixI8(v) = self { Some(v.as_vec()) } else if let Value::I8(v) = self { Some(vec![v.borrow().clone()]) } else if let Value::MutableReference(val) = self { val.borrow().as_veci8() } else if let Some(v) = self.as_i8() { Some(vec![v.borrow().clone()]) } else { None } }
942  pub fn as_veci16(&self) -> Option<Vec<i16>> { if let Value::MatrixI16(v) = self { Some(v.as_vec()) } else if let Value::I16(v) = self { Some(vec![v.borrow().clone()]) } else if let Value::MutableReference(val) = self { val.borrow().as_veci16() } else if let Some(v) = self.as_i16() { Some(vec![v.borrow().clone()]) } else { None } }
943  pub fn as_veci32(&self) -> Option<Vec<i32>> { if let Value::MatrixI32(v) = self { Some(v.as_vec()) } else if let Value::I32(v) = self { Some(vec![v.borrow().clone()]) } else if let Value::MutableReference(val) = self { val.borrow().as_veci32() } else if let Some(v) = self.as_i32() { Some(vec![v.borrow().clone()]) } else { None } }
944  pub fn as_veci64(&self) -> Option<Vec<i64>> { if let Value::MatrixI64(v) = self { Some(v.as_vec()) } else if let Value::I64(v) = self { Some(vec![v.borrow().clone()]) } else if let Value::MutableReference(val) = self { val.borrow().as_veci64() } else if let Some(v) = self.as_i64() { Some(vec![v.borrow().clone()]) } else { None } }
945  pub fn as_veci128(&self) -> Option<Vec<i128>> { if let Value::MatrixI128(v) = self { Some(v.as_vec()) } else if let Value::I128(v) = self { Some(vec![v.borrow().clone()]) } else if let Value::MutableReference(val) = self { val.borrow().as_veci128() } else if let Some(v) = self.as_i128() { Some(vec![v.borrow().clone()]) } else { None } }
946
947  pub fn as_vecstring(&self) -> Option<Vec<String>> {if let Value::MatrixString(v)  = self { Some(v.as_vec()) } else if let Value::String(v) = self { Some(vec![v.borrow().clone()]) } else if let Value::MutableReference(val) = self { val.borrow().as_vecstring()  } else { None }}
948
949  pub fn as_vecrationalnumber(&self) -> Option<Vec<RationalNumber>> {if let Value::MatrixRationalNumber(v)  = self { Some(v.as_vec()) } else if let Value::RationalNumber(v) = self { Some(vec![v.borrow().clone()]) } else if let Value::MutableReference(val) = self { val.borrow().as_vecrationalnumber()  } else { None }}
950  pub fn as_veccomplexnumber(&self) -> Option<Vec<ComplexNumber>> {if let Value::MatrixComplexNumber(v)  = self { Some(v.as_vec()) } else if let Value::ComplexNumber(v) = self { Some(vec![v.borrow().clone()]) } else if let Value::MutableReference(val) = self { val.borrow().as_veccomplexnumber()  } else { None }}
951
952  pub fn as_vecusize(&self) -> Option<Vec<usize>> {
953    match self {
954      Value::MatrixIndex(v) => Some(v.as_vec()),
955      Value::MatrixI64(v) => Some(v.as_vec().iter().map(|x| *x as usize).collect::<Vec<usize>>()),
956      Value::MatrixF64(v) => Some(v.as_vec().iter().map(|x| (*x).0 as usize).collect::<Vec<usize>>()),
957      Value::MutableReference(x) => x.borrow().as_vecusize(),
958      Value::MatrixBool(_) => None,
959      Value::Bool(_) => None,
960      _ => todo!(),
961    }
962  }
963
964  pub fn as_index(&self) -> MResult<Value> {
965    match self.as_usize() {      
966      Some(ix) => Ok(Value::Index(new_ref(ix))),
967      None => match self.as_vecusize() {
968        Some(x) => {
969          let shape = self.shape();
970          let out = Value::MatrixIndex(usize::to_matrix(x, shape[0] * shape[1],1 ));
971          Ok(out)
972        },
973        None => match self.as_vecbool() {
974          Some(x) => {
975            let shape = self.shape();
976            let out = match (shape[0], shape[1]) {
977              (1,1) => Value::Bool(new_ref(x[0])),
978              (1,n) => Value::MatrixBool(Matrix::DVector(new_ref(DVector::from_vec(x)))),
979              (m,1) => Value::MatrixBool(Matrix::DVector(new_ref(DVector::from_vec(x)))),
980              (m,n) => Value::MatrixBool(Matrix::DVector(new_ref(DVector::from_vec(x)))),
981            };
982            Ok(out)
983          }
984          None => match self.as_bool() {
985            Some(x) => Ok(Value::Bool(x)),
986            None => Err(MechError{file: file!().to_string(), tokens: vec![], msg: "".to_string(), id: line!(), kind: MechErrorKind::UnhandledIndexKind}),
987          }
988        }
989      }
990    }
991  }
992
993  pub fn as_usize(&self) -> Option<usize> {
994    match self {      
995      Value::Index(v) => Some(*v.borrow()),
996      Value::U8(v) => Some(*v.borrow() as usize),
997      Value::U16(v) => Some(*v.borrow() as usize),
998      Value::U32(v) => Some(*v.borrow() as usize),
999      Value::U64(v) => Some(*v.borrow() as usize),
1000      Value::U128(v) => Some(*v.borrow() as usize),
1001      Value::I8(v) => Some(*v.borrow() as usize),
1002      Value::I16(v) => Some(*v.borrow() as usize),
1003      Value::I32(v) => Some(*v.borrow() as usize),
1004      Value::I64(v) => Some(*v.borrow() as usize),
1005      Value::I128(v) => Some(*v.borrow() as usize),
1006      Value::F32(v) => Some((*v.borrow()).0 as usize),
1007      Value::F64(v) => Some((*v.borrow()).0 as usize),
1008      Value::MutableReference(v) => v.borrow().as_usize(),
1009      _ => None,
1010    }
1011  }
1012
1013}
1014
1015pub trait ToIndex {
1016  fn to_index(&self) -> Value;
1017}
1018
1019impl ToIndex for Ref<Vec<i64>> { fn to_index(&self) -> Value { (*self.borrow()).iter().map(|x| *x as usize).collect::<Vec<usize>>().to_value() } }
1020
1021pub trait ToValue {
1022  fn to_value(&self) -> Value;
1023}
1024
1025impl ToValue for Vec<usize> {
1026  fn to_value(&self) -> Value {
1027    match self.len() {
1028      1 => Value::Index(new_ref(self[0].clone())),
1029      //2 => Value::MatrixIndex(Matrix::RowVector2(new_ref(RowVector2::from_vec(self.clone())))),
1030      //3 => Value::MatrixIndex(Matrix::RowVector3(new_ref(RowVector3::from_vec(self.clone())))),
1031      //4 => Value::MatrixIndex(Matrix::RowVector4(new_ref(RowVector4::from_vec(self.clone())))),
1032      n => Value::MatrixIndex(Matrix::DVector(new_ref(DVector::from_vec(self.clone())))),
1033    }
1034  }
1035}
1036
1037impl ToValue for Ref<usize>  { fn to_value(&self) -> Value { Value::Index(self.clone())  } }
1038impl ToValue for Ref<u8>     { fn to_value(&self) -> Value { Value::U8(self.clone())     } }
1039impl ToValue for Ref<u16>    { fn to_value(&self) -> Value { Value::U16(self.clone())    } }
1040impl ToValue for Ref<u32>    { fn to_value(&self) -> Value { Value::U32(self.clone())    } }
1041impl ToValue for Ref<u64>    { fn to_value(&self) -> Value { Value::U64(self.clone())    } }
1042impl ToValue for Ref<u128>   { fn to_value(&self) -> Value { Value::U128(self.clone())   } }
1043impl ToValue for Ref<i8>     { fn to_value(&self) -> Value { Value::I8(self.clone())     } }
1044impl ToValue for Ref<i16>    { fn to_value(&self) -> Value { Value::I16(self.clone())    } }
1045impl ToValue for Ref<i32>    { fn to_value(&self) -> Value { Value::I32(self.clone())    } }
1046impl ToValue for Ref<i64>    { fn to_value(&self) -> Value { Value::I64(self.clone())    } }
1047impl ToValue for Ref<i128>   { fn to_value(&self) -> Value { Value::I128(self.clone())   } }
1048impl ToValue for Ref<F32>    { fn to_value(&self) -> Value { Value::F32(self.clone())    } }
1049impl ToValue for Ref<F64>    { fn to_value(&self) -> Value { Value::F64(self.clone())    } }
1050impl ToValue for Ref<bool>   { fn to_value(&self) -> Value { Value::Bool(self.clone())   } }
1051impl ToValue for Ref<String> { fn to_value(&self) -> Value { Value::String(self.clone()) } }
1052impl ToValue for Ref<RationalNumber> { fn to_value(&self) -> Value { Value::RationalNumber(self.clone()) } }
1053impl ToValue for Ref<ComplexNumber> { fn to_value(&self) -> Value { Value::ComplexNumber(self.clone()) } }
1054
1055macro_rules! to_value_ndmatrix {
1056  ($($nd_matrix_kind:ident, $matrix_kind:ident, $base_type:ty),+ $(,)?) => {
1057    $(
1058      impl ToValue for Ref<$nd_matrix_kind<$base_type>> {
1059        fn to_value(&self) -> Value {
1060          Value::$matrix_kind(Matrix::<$base_type>::$nd_matrix_kind(self.clone()))
1061        }
1062      }
1063    )+
1064  };}
1065
1066macro_rules! impl_to_value_matrix {
1067  ($matrix_kind:ident) => {
1068    to_value_ndmatrix!(
1069      $matrix_kind, MatrixIndex,  usize,
1070      $matrix_kind, MatrixBool,   bool,
1071      $matrix_kind, MatrixI8,     i8,
1072      $matrix_kind, MatrixI16,    i16,
1073      $matrix_kind, MatrixI32,    i32,
1074      $matrix_kind, MatrixI64,    i64,
1075      $matrix_kind, MatrixI128,   i128,
1076      $matrix_kind, MatrixU8,     u8,
1077      $matrix_kind, MatrixU16,    u16,
1078      $matrix_kind, MatrixU32,    u32,
1079      $matrix_kind, MatrixU64,    u64,
1080      $matrix_kind, MatrixU128,   u128,
1081      $matrix_kind, MatrixF32,    F32,
1082      $matrix_kind, MatrixF64,    F64,
1083      $matrix_kind, MatrixString, String,
1084      $matrix_kind, MatrixRationalNumber, RationalNumber,
1085      $matrix_kind, MatrixComplexNumber, ComplexNumber,
1086    );
1087  }
1088}
1089
1090impl_to_value_matrix!(Matrix2x3);
1091impl_to_value_matrix!(Matrix3x2);
1092impl_to_value_matrix!(Matrix1);
1093impl_to_value_matrix!(Matrix2);
1094impl_to_value_matrix!(Matrix3);
1095impl_to_value_matrix!(Matrix4);
1096impl_to_value_matrix!(Vector2);
1097impl_to_value_matrix!(Vector3);
1098impl_to_value_matrix!(Vector4);
1099impl_to_value_matrix!(RowVector2);
1100impl_to_value_matrix!(RowVector3);
1101impl_to_value_matrix!(RowVector4);
1102impl_to_value_matrix!(RowDVector);
1103impl_to_value_matrix!(DVector);
1104impl_to_value_matrix!(DMatrix);
1105
1106impl From<u8> for Value {
1107  fn from(val: u8) -> Self {
1108    Value::U8(new_ref(val))
1109  }
1110}
1111
1112impl From<u16> for Value {
1113  fn from(val: u16) -> Self {
1114    Value::U16(new_ref(val))
1115  }
1116}
1117
1118impl From<u32> for Value {
1119  fn from(val: u32) -> Self {
1120    Value::U32(new_ref(val))
1121  }
1122}
1123
1124impl From<u64> for Value {
1125  fn from(val: u64) -> Self {
1126    Value::U64(new_ref(val))
1127  }
1128}
1129
1130impl From<u128> for Value {
1131  fn from(val: u128) -> Self {
1132    Value::U128(new_ref(val))
1133  }
1134}
1135
1136impl From<i8> for Value {
1137  fn from(val: i8) -> Self {
1138    Value::I8(new_ref(val))
1139  }
1140}
1141
1142impl From<i16> for Value {
1143  fn from(val: i16) -> Self {
1144    Value::I16(new_ref(val))
1145  }
1146}
1147
1148impl From<i32> for Value {
1149  fn from(val: i32) -> Self {
1150    Value::I32(new_ref(val))
1151  }
1152}
1153
1154impl From<i64> for Value {
1155  fn from(val: i64) -> Self {
1156    Value::I64(new_ref(val))
1157  }
1158}
1159
1160impl From<i128> for Value {
1161  fn from(val: i128) -> Self {
1162    Value::I128(new_ref(val))
1163  }
1164}
1165
1166impl From<bool> for Value {
1167  fn from(val: bool) -> Self {
1168    Value::Bool(new_ref(val))
1169  }
1170}
1171
1172impl From<String> for Value {
1173  fn from(val: String) -> Self {
1174    Value::String(new_ref(val))
1175  }
1176}
1177
1178impl From<RationalNumber> for Value {
1179  fn from(val: RationalNumber) -> Self {
1180    Value::RationalNumber(new_ref(val))
1181  }
1182}
1183