Skip to main content

unlab_gpu/
value.rs

1//
2// Copyright (c) 2025-2026 Ɓukasz Szpakowski
3//
4// This Source Code Form is subject to the terms of the Mozilla Public
5// License, v. 2.0. If a copy of the MPL was not distributed with this
6// file, You can obtain one at https://mozilla.org/MPL/2.0/.
7//
8//! A value module.
9use std::cmp::Ordering;
10use std::collections::BTreeMap;
11use std::collections::BTreeSet;
12use std::fmt;
13use std::ops::Neg;
14use std::ops::Not;
15use std::ops::Add;
16use std::ops::AddAssign;
17use std::ops::Sub;
18use std::ops::SubAssign;
19use std::ops::Mul;
20use std::ops::MulAssign;
21use std::ops::Div;
22use std::ops::DivAssign;
23use std::result;
24use std::str::Chars;
25use std::sync::Arc;
26use std::sync::RwLock;
27use std::sync::Weak;
28use crate::serde::de;
29use crate::serde::de::MapAccess;
30use crate::serde::de::SeqAccess;
31use crate::serde::de::Visitor;
32use crate::serde::ser;
33use crate::serde::ser::SerializeSeq;
34use crate::serde::ser::SerializeMap;
35use crate::serde::Deserialize;
36use crate::serde::Deserializer;
37use crate::serde::Serialize;
38use crate::serde::Serializer;
39use crate::matrix::Matrix;
40#[cfg(feature = "plot")]
41use crate::winit;
42use crate::env::*;
43use crate::error::*;
44use crate::interp::*;
45use crate::tree::*;
46use crate::utils::*;
47
48/// A type of window identifier.
49#[cfg(feature = "plot")]
50pub type WindowId = winit::window::WindowId;
51
52/// A type of window identifier.
53#[cfg(not(feature = "plot"))]
54#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
55pub struct WindowId(());
56
57fn nearly_eq(a: f32, b: f32, eps: f32) -> bool
58{
59    if a == b {
60        true
61    } else {
62        (a - b).abs() <= eps
63    }
64}
65
66/// A value enumeration.
67///
68/// The value enumeration represents a value of the Unlab scripting language.
69#[derive(Clone, Debug)]
70pub enum Value
71{
72    /// A none value.
73    None,
74    /// A boolean value.
75    Bool(bool),
76    /// An integer number.
77    Int(i64),
78    /// Floating-point number.
79    Float(f32),
80    /// An immutablke object.
81    Object(Arc<Object>),
82    /// A strong reference to a mutable object.
83    Ref(Arc<RwLock<MutObject>>),
84    /// A weak reference to a mutable object.
85    Weak(Weak<RwLock<MutObject>>),
86}
87
88impl Value
89{
90    /// Converts any value to a boolean value.
91    pub fn to_bool(&self) -> bool
92    {
93        match self {
94            Value::None => false,
95            Value::Bool(a) => *a,
96            Value::Int(a) => *a != 0,
97            Value::Float(a) => *a != 0.0,
98            Value::Object(object) => {
99                match &**object {
100                    Object::Error(_, _) => false,
101                    _ => true,
102                }
103            },
104            _ => true,
105        }
106    }
107
108    /// Converts any value to an integer number.
109    pub fn to_i64(&self) -> i64
110    {
111        match self {
112            Value::None => 0,
113            Value::Bool(a) => if *a { 1 } else { 0 },
114            Value::Int(a) => *a,
115            Value::Float(a) => *a as i64,
116            Value::Object(object) => {
117                match &**object {
118                    Object::Error(_, _) => 0,
119                    _ => 1,
120                }
121            },
122            _ => 1,
123        }
124    }
125
126    /// Converts any value to a floating-point number.
127    pub fn to_f32(&self) -> f32
128    {
129        match self {
130            Value::None => 0.0,
131            Value::Bool(a) => if *a { 1.0 } else { 0.0 },
132            Value::Int(a) => *a as f32,
133            Value::Float(a) => *a,
134            Value::Object(object) => {
135                match &**object {
136                    Object::Error(_, _) => 0.0,
137                    _ => 1.0,
138                }
139            },
140            _ => 1.0,
141        }
142    }
143
144    /// Converts the value to a boolean value if the value is a boolean type, otherwise this
145    /// method returns `None`.
146    pub fn to_opt_bool(&self) -> Option<bool>
147    {
148        match self {
149            Value::Bool(a) => Some(*a),
150            _ => None,
151        }
152    }
153
154    /// Converts the value to an integer number if the value is an integer type or floating-point
155    /// type, otherwise this method returns `None`.
156    pub fn to_opt_i64(&self) -> Option<i64>
157    {
158        match self {
159            Value::Int(a) => Some(*a),
160            Value::Float(a) => Some(*a as i64),
161            _ => None,
162        }
163    }
164
165    /// Converts the value to a floating-point number if the value is an integer type or
166    /// floating-point type, otherwise this method returns `None`.
167    pub fn to_opt_f32(&self) -> Option<f32>
168    {
169        match self {
170            Value::Int(a) => Some(*a as f32),
171            Value::Float(a) => Some(*a),
172            _ => None,
173        }
174    }
175
176    /// Converts the value to a string if the value is a string type, otherwise this method
177    /// returns `None`.
178    pub fn to_opt_string(&self) -> Option<String>
179    {
180        match self {
181            Value::Object(object) => {
182                match &**object {
183                    Object::String(s) => Some(s.clone()),
184                    _ => None,
185                }
186            },
187            _ => None,
188        }
189    }
190
191    /// Returns `true` if the value is a function or a built-in function, otherwise `false`.
192    pub fn is_fun(&self) -> bool
193    {
194        match self {
195            Value::Object(object) => {
196                match &**object {
197                    Object::Fun(_, _, _) | Object::BuiltinFun(_, _) => true,
198                    _ => false,
199                }
200            },
201            _ => false,
202        }
203    }
204    
205    /// Returns `true` if two values are equal with types, otherwise `false`.
206    ///
207    /// This method also compares types of two values for integer numbers and floating-point
208    /// numbers. If two values are weak references, this method compares their pointers instead
209    /// values. If two values are matrices, this method doesn't compare two values and returns
210    /// `false`. 
211    pub fn eq_with_types(&self, value: &Value) -> Result<bool>
212    {
213        match (self, value) {
214            (Value::None, Value::None) => Ok(true),
215            (Value::Bool(a), Value::Bool(b)) => Ok(a == b),
216            (Value::Int(a), Value::Int(b)) => Ok(a == b),
217            (Value::Float(a), Value::Float(b)) => Ok(a == b),
218            (Value::Object(object), Value::Object(object2)) => {
219                if Arc::ptr_eq(object, object2) {
220                    return Ok(true);
221                }
222                object.priv_eq(&**object2)
223            },
224            (Value::Ref(object), Value::Ref(object2)) => {
225                if Arc::ptr_eq(object, object2) {
226                    return Ok(true);
227                }
228                let object_g = rw_lock_read(&**object)?;
229                let object2_g = rw_lock_read(&**object2)?;
230                object_g.priv_eq(&*object2_g, Self::eq_with_types)
231            },
232            (Value::Weak(object), Value::Weak(object2)) => {
233                match (object.upgrade(), object2.upgrade()) {
234                    (Some(object), Some(object2)) => Ok(Arc::ptr_eq(&object, &object2)),
235                    (None, None) => Ok(true),
236                    (_, _) => Ok(false),
237                }
238            },
239            (_, _) => Ok(false),
240        }
241    }
242
243    /// Returns `true` if two values are equal without types, otherwise `false`.
244    ///
245    /// This method doesn't compare types of two values for integer numbers and floating-point
246    /// numbers. If two values are weak references, this method compares their pointers instead
247    /// values. If two values are matrices, this method doesn't compare two values and returns
248    /// `false`.
249    pub fn eq_without_types(&self, value: &Value) -> Result<bool>
250    {
251        match (self, value) {
252            (Value::None, Value::None) => Ok(true),
253            (Value::Bool(a), Value::Bool(b)) => Ok(a == b),
254            (Value::Int(a), Value::Int(b)) => Ok(a == b),
255            (Value::Int(_) | Value::Float(_), Value::Int(_) | Value::Float(_)) => Ok(self.to_f32() == value.to_f32()),
256            (Value::Object(object), Value::Object(object2)) => {
257                if Arc::ptr_eq(object, object2) {
258                    return Ok(true);
259                }
260                object.priv_eq(&**object2)
261            },
262            (Value::Ref(object), Value::Ref(object2)) => {
263                if Arc::ptr_eq(object, object2) {
264                    return Ok(true);
265                }
266                let object_g = rw_lock_read(&**object)?;
267                let object2_g = rw_lock_read(&**object2)?;
268                object_g.priv_eq(&*object2_g, Self::eq_without_types)
269            },
270            (Value::Weak(object), Value::Weak(object2)) => {
271                match (object.upgrade(), object2.upgrade()) {
272                    (Some(object), Some(object2)) => Ok(Arc::ptr_eq(&object, &object2)),
273                    (None, None) => Ok(true),
274                    (_, _) => Ok(false),
275                }
276            },
277            (_, _) => Ok(false),
278        }
279    }
280    
281    /// Returns `true` if two values are nearly equal with types, otherwise `false`.
282    ///
283    /// If absolute difference between two numbers is less than or equal to the epsilon, two
284    /// numbers are nearly equal for floating-point numbers, matrix arrays, and matrix row slices.
285    /// Other values are compered as for [`eq_with_types`](Self::eq_with_types). 
286    pub fn nearly_eq_with_types(&self, value: &Value, eps: f32) -> Result<bool>
287    {
288        match (self, value) {
289            (Value::Float(a), Value::Float(b)) => Ok(nearly_eq(*a, *b, eps)),
290            (Value::Object(object), Value::Object(object2)) => {
291                if Arc::ptr_eq(object, object2) {
292                    return Ok(true);
293                }
294                object.priv_nearly_eq(&**object2, eps)
295            },
296            (Value::Ref(object), Value::Ref(object2)) => {
297                if Arc::ptr_eq(object, object2) {
298                    return Ok(true);
299                }
300                let object_g = rw_lock_read(&**object)?;
301                let object2_g = rw_lock_read(&**object2)?;
302                object_g.priv_nearly_eq(&*object2_g, eps, Self::nearly_eq_with_types)
303            },
304            (Value::Weak(object), Value::Weak(object2)) => {
305                match (object.upgrade(), object2.upgrade()) {
306                    (Some(object), Some(object2)) => Ok(Arc::ptr_eq(&object, &object2)),
307                    (None, None) => Ok(true),
308                    (_, _) => Ok(false),
309                }
310            },
311            (_, _) => self.eq_with_types(value),
312        }
313    }
314
315    /// Returns `true` if two values are nearly equal without types, otherwise `false`.
316    ///
317    /// If absolute difference between two numbers is less than or equal to the epsilon, two
318    /// numbers are nearly equal for numbers, matrix arrays, and matrix row slices. Other values
319    /// are compered as for [`eq_without_types`](Self::eq_without_types). 
320    pub fn nearly_eq_without_types(&self, value: &Value, eps: f32) -> Result<bool>
321    {
322        match (self, value) {
323            (Value::Int(a), Value::Int(b)) => Ok(nearly_eq(*a as f32, *b as f32, eps)),
324            (Value::Int(_) | Value::Float(_), Value::Int(_) | Value::Float(_)) => Ok(nearly_eq(self.to_f32(), value.to_f32(), eps)),
325            (Value::Object(object), Value::Object(object2)) => {
326                if Arc::ptr_eq(object, object2) {
327                    return Ok(true);
328                }
329                object.priv_nearly_eq(&**object2, eps)
330            },
331            (Value::Ref(object), Value::Ref(object2)) => {
332                if Arc::ptr_eq(object, object2) {
333                    return Ok(true);
334                }
335                let object_g = rw_lock_read(&**object)?;
336                let object2_g = rw_lock_read(&**object2)?;
337                object_g.priv_nearly_eq(&*object2_g, eps, Self::nearly_eq_without_types)
338            },
339            (Value::Weak(object), Value::Weak(object2)) => {
340                match (object.upgrade(), object2.upgrade()) {
341                    (Some(object), Some(object2)) => Ok(Arc::ptr_eq(&object, &object2)),
342                    (None, None) => Ok(true),
343                    (_, _) => Ok(false),
344                }
345            },
346            (_, _) => self.eq_without_types(value),
347        }
348    }    
349    
350    fn dot1_for_elem_with_fun_ref<F>(&self, err_msg: &str, f: &mut F) -> Result<Value>
351        where F: FnMut(&Value) -> Result<Value>
352    {
353        match self {
354            Value::Float(_) => f(self),
355            Value::Object(object) => {
356                match &**object {
357                    Object::Matrix(_) => f(self),
358                    _ => Ok(self.clone()),
359                }
360            },
361            Value::Ref(_) => self.dot1_with_fun_ref(err_msg, f),
362            _ => Ok(self.clone()),
363        }
364    }
365    
366    fn dot1_with_fun_ref<F>(&self, err_msg: &str, f: &mut F) -> Result<Value>
367        where F: FnMut(&Value) -> Result<Value>
368    {
369        match self {
370            Value::Ref(object) => {
371                let object_g = rw_lock_read(&**object)?;
372                match &*object_g {
373                    MutObject::Array(elems) => {
374                        let mut new_elems: Vec<Value> = Vec::new();
375                        for elem in elems {
376                            new_elems.push(elem.dot1_for_elem_with_fun_ref(err_msg, f)?);
377                        }
378                        Ok(Value::Ref(Arc::new(RwLock::new(MutObject::Array(new_elems)))))
379                    },
380                    MutObject::Struct(fields) => {
381                        let mut new_fields: BTreeMap<String, Value> = BTreeMap::new();
382                        for (ident, field) in fields {
383                            new_fields.insert(ident.clone(), field.dot1_for_elem_with_fun_ref(err_msg, f)?);
384                        }
385                        Ok(Value::Ref(Arc::new(RwLock::new(MutObject::Struct(new_fields)))))
386                    },
387                }
388            },
389            _ => Err(Error::Interp(String::from(err_msg))),
390        }
391    }
392    
393    /// Applies the function with one argument for a dot operation.
394    ///
395    /// If one element of one value or one field of one value is a floating-point number or a
396    /// matrix, this method applies the function to one argument for this element or this field.
397    /// If this element or this field is an array or a structure, this method recursively invokes
398    /// itself for this element or this field. This method ignores this element or this field
399    /// otherwise. This method returns an error with the error message if one value isn't an
400    /// array or an structure.
401    pub fn dot1<F>(&self, err_msg: &str, mut f: F) -> Result<Value>
402        where F: FnMut(&Value) -> Result<Value>
403    { self.dot1_with_fun_ref(err_msg, &mut f) }
404
405    fn dot2_for_elem_with_fun_ref<F>(&self, value: &Value, err_msg: &str, f: &mut F) -> Result<Value>
406        where F: FnMut(&Value, &Value) -> Result<Value>
407    {
408        match (self, value) {
409            (Value::Float(_), Value::Float(_)) => f(self, value),
410            (Value::Object(object), Value::Object(object2)) => {
411                match (&**object, &**object2) {
412                    (Object::Matrix(_), Object::Matrix(_)) => f(self, value),
413                    (_, _) => {
414                        if !self.eq_with_types(value)? {
415                            return Err(Error::Interp(String::from("two values aren't equal")))
416                        }
417                        Ok(self.clone())
418                    },
419                }
420            },
421            (Value::Ref(_), Value::Ref(_)) => self.dot2_with_fun_ref(value, err_msg, f),
422            (Value::Weak(_), Value::Weak(_)) => Err(Error::Interp(String::from("two values are weak references"))),
423            (_, _) => {
424                if !self.eq_with_types(value)? {
425                    return Err(Error::Interp(String::from("two values aren't equal")))
426                }
427                Ok(self.clone())
428            },
429        }
430    }
431    
432    fn dot2_with_fun_ref<F>(&self, value: &Value, err_msg: &str, f: &mut F) -> Result<Value>
433        where F: FnMut(&Value, &Value) -> Result<Value>
434    {
435        match (self, value) {
436            (Value::Ref(object), Value::Ref(object2)) => {
437                let object_g = rw_lock_read(&**object)?;
438                let object2_g = rw_lock_read(&**object2)?;
439                match (&*object_g, &*object2_g) {
440                    (MutObject::Array(elems), MutObject::Array(elems2)) => {
441                        if elems.len() != elems2.len() {
442                            return Err(Error::Interp(String::from("lengths of two arrays aren't equal")));
443                        }
444                        let mut new_elems: Vec<Value> = Vec::new();
445                        for (elem, elem2) in elems.iter().zip(elems2.iter()) {
446                            new_elems.push(elem.dot2_for_elem_with_fun_ref(elem2, err_msg, f)?);
447                        }
448                        Ok(Value::Ref(Arc::new(RwLock::new(MutObject::Array(new_elems)))))
449                    },
450                    (MutObject::Struct(fields), MutObject::Struct(fields2)) => {
451                        let idents: BTreeSet<&String> = fields.keys().collect();
452                        let idents2: BTreeSet<&String> = fields2.keys().collect();
453                        if idents != idents2 {
454                            return Err(Error::Interp(String::from("field names of two structures aren't equal")));
455                        }
456                        let mut new_fields: BTreeMap<String, Value> = BTreeMap::new();
457                        for ident in &idents {
458                            match (fields.get(*ident), fields2.get(*ident)) {
459                                (Some(field), Some(field2)) => {
460                                    new_fields.insert((*ident).clone(), field.dot2_for_elem_with_fun_ref(field2, err_msg, f)?);
461                                },
462                                (_, _) => return Err(Error::Interp(String::from("no field value"))),
463                            }
464                        }
465                        Ok(Value::Ref(Arc::new(RwLock::new(MutObject::Struct(new_fields)))))
466                    },
467                    (_, _) => Err(Error::Interp(String::from("two types aren't equal"))),
468                }
469            },
470            (_, _) => Err(Error::Interp(String::from(err_msg))),
471        }
472    }
473
474    /// Applies the function with two arguments for a dot operation.
475    ///
476    /// If two elements of two values or two fields of two values are floating-point numbers or
477    /// matrices, this method applies the function to two arguments for these elements or these
478    /// fields. If these elements or these fields are arrays or structures, this method
479    /// recursively invokes itself for these elements or these fields. This method compares these
480    /// elements or these fields otherwise. If these elements or these fields aren't equal, this
481    /// method returns an error. This method returns an error with the error message if two
482    /// values aren't arrays or structures.
483    pub fn dot2<F>(&self, value: &Value, err_msg: &str, mut f: F) -> Result<Value>
484        where F: FnMut(&Value, &Value) -> Result<Value>
485    { self.dot2_with_fun_ref(value, err_msg, &mut f) }
486
487    /// Applies the function to the arguments.
488    ///
489    /// See [`Interp::apply_fun`].
490    pub fn apply(&self, interp: &mut Interp, env: &mut Env, arg_values: &[Value]) -> Result<Value>
491    { interp.apply_fun(env, self, arg_values) }
492    
493    /// Returns the element or the field if the value has the element or the field, otherwise
494    /// `None` or an error.
495    ///
496    /// If the value isn't a string, a matrix array, a matrix row slice, or a mutable object,
497    /// this method returns an error.
498    pub fn elem(&self, idx_value: &Value) -> Result<Value>
499    {
500        match self {
501            Value::Object(object) => {
502                match &**object {
503                    Object::String(s) => {
504                        match idx_value {
505                            Value::Int(_) | Value::Float(_) => {
506                                let i = idx_value.to_i64();
507                                if i < 1 || i > (s.chars().count() as i64) {
508                                    return Err(Error::Interp(String::from("index out of bounds")));
509                                }
510                                match s.chars().nth((i - 1) as usize) {
511                                    Some(c) => {
512                                        let mut t = String::new();
513                                        t.push(c);
514                                        Ok(Value::Object(Arc::new(Object::String(t))))
515                                    }
516                                    None => Err(Error::Interp(String::from("no character"))),
517                                }
518                            },
519                            _ => Err(Error::Interp(String::from("unsupported index type for indexing"))),
520                        }
521                    },
522                    Object::MatrixArray(row_count, _, _, _) => {
523                        match idx_value {
524                            Value::Int(_) | Value::Float(_) => {
525                                let i = idx_value.to_i64();
526                                if i < 1 || i > (*row_count as i64) {
527                                    return Err(Error::Interp(String::from("index out of bounds")));
528                                }
529                                Ok(Value::Object(Arc::new(Object::MatrixRowSlice(object.clone(), (i - 1) as usize))))
530                            },
531                            _ => Err(Error::Interp(String::from("unsupported index type for indexing"))),
532                        }
533                    },
534                    Object::MatrixRowSlice(matrix_array, i) => {
535                        match idx_value {
536                            Value::Int(_) | Value::Float(_) => {
537                                let j = idx_value.to_i64();
538                                match &**matrix_array {
539                                    Object::MatrixArray(row_count, col_count, transpose_flag, xs) => {
540                                        if j < 1 || j > (*col_count as i64) {
541                                            return Err(Error::Interp(String::from("index out of bounds")));
542                                        }
543                                        let k = match transpose_flag {
544                                            TransposeFlag::NoTranspose => i * (*col_count) + ((j - 1) as usize),
545                                            TransposeFlag::Transpose => ((j - 1) as usize) * (*row_count) + i,
546                                        };
547                                        match xs.get(k) {
548                                            Some(x) => Ok(Value::Float(*x)),
549                                            None => Err(Error::Interp(String::from("no element"))),
550                                        }
551                                    },
552                                    _ => Err(Error::Interp(String::from("invalid matrix array type"))),
553                                }
554                            },
555                            _ => Err(Error::Interp(String::from("unsupported index type for indexing"))),
556                        }
557                    },
558                    _ => Err(Error::Interp(String::from("unsupported type for indexing"))),
559                }
560            },
561            Value::Ref(object) => {
562                let object_g = rw_lock_read(&**object)?;
563                match &*object_g {
564                    MutObject::Array(elems) => {
565                        match idx_value {
566                            Value::Int(_) | Value::Float(_) => {
567                                let i = idx_value.to_i64();
568                                if i < 1 || i > (elems.len() as i64) {
569                                    return Err(Error::Interp(String::from("index out of bounds")));
570                                }
571                                match elems.get((i - 1) as usize) { 
572                                    Some(elem) => Ok(elem.clone()),
573                                    None => Err(Error::Interp(String::from("no element"))),
574                                }
575                            },
576                            _ => Err(Error::Interp(String::from("unsupported index type for indexing"))),
577                        }
578                    },
579                    MutObject::Struct(fields) => {
580                        match idx_value {
581                            Value::Object(idx_object) => {
582                                match &**idx_object {
583                                    Object::String(ident) => {
584                                        match fields.get(ident) {
585                                            Some(field) => Ok(field.clone()),
586                                            None => Err(Error::Interp(String::from("not found key")))
587                                        }
588                                    },
589                                    _ => Err(Error::Interp(String::from("unsupported index type for indexing"))),
590                                }
591                            },
592                            _ => Err(Error::Interp(String::from("unsupported index type for indexing"))),
593                        }
594                    },
595                }
596            },
597            _ => Err(Error::Interp(String::from("unsupported type for indexing"))),
598        }
599    }
600
601    /// Sets the element or the field for the value.
602    ///
603    /// If the value isn't a mutable object, this method returns an error.
604    pub fn set_elem(&self, idx_value: &Value, value: Value) -> Result<()>
605    {
606        match self {
607            Value::Ref(object) => {
608                let mut object_g = rw_lock_write(&**object)?;
609                match &mut *object_g {
610                    MutObject::Array(elems) => {
611                        match idx_value {
612                            Value::Int(_) | Value::Float(_) => {
613                                let i = idx_value.to_i64();
614                                if i < 1 || i > (elems.len() as i64) {
615                                    return Err(Error::Interp(String::from("index out of bounds")));
616                                }
617                                match elems.get_mut((i - 1) as usize) {
618                                    Some(elem) => {
619                                        *elem = value;
620                                        Ok(())
621                                    }
622                                    None => Err(Error::Interp(String::from("no element"))),
623                                }
624                            },
625                            _ => Err(Error::Interp(String::from("unsupported index type for indexing"))),
626                        }
627                    },
628                    MutObject::Struct(fields) => {
629                        match idx_value {
630                            Value::Object(idx_object) => {
631                                match &**idx_object {
632                                    Object::String(ident) => {
633                                        fields.insert(ident.clone(), value);
634                                        Ok(())
635                                    },
636                                    _ => Err(Error::Interp(String::from("unsupported index type for indexing"))),
637                                }
638                            },
639                            _ => Err(Error::Interp(String::from("unsupported index type for indexing"))),
640                        }
641                    },
642                }
643            },
644            _ => Err(Error::Interp(String::from("unsupported type for indexing"))),
645        }
646    }
647
648    /// Returns the field if the value has the field, otherwise `None` or an error.
649    ///
650    /// If the value isn't a structure, this method returns an error.
651    pub fn field(&self, ident: &String) -> Result<Value>
652    {
653        match self {
654            Value::Ref(object) => {
655                let object_g = rw_lock_read(&**object)?;
656                match &*object_g {
657                    MutObject::Struct(fields) => {
658                        match fields.get(ident) {
659                            Some(field) => Ok(field.clone()),
660                            None => Err(Error::Interp(format!("structure hasn't field {}", ident))),
661                        }
662                    },
663                    _ => Err(Error::Interp(format!("unsupported type for field {}", ident))),
664                }
665            },
666            _ => Err(Error::Interp(format!("unsupported type for field {}", ident))),
667        }
668    }
669
670    /// Sets the field for the value.
671    ///
672    /// If the value isn't a structure, this method returns an error.
673    pub fn set_field(&self, ident: String, value: Value) -> Result<()>
674    {
675        match self {
676            Value::Ref(object) => {
677                let mut object_g = rw_lock_write(&**object)?;
678                match &mut *object_g {
679                    MutObject::Struct(fields) => {
680                        fields.insert(ident.clone(), value);
681                        Ok(())
682                    },
683                    _ => Err(Error::Interp(format!("unsupported type for field {}", ident))),
684                }
685            },
686            _ => Err(Error::Interp(format!("unsupported type for field {}", ident))),
687        }
688    }
689
690    /// Performs an operation on one value for the unary operator.
691    pub fn unary_op(&self, op: UnaryOp) -> Result<Value>
692    {
693        match op {
694            UnaryOp::Neg => {
695                match self {
696                    Value::Int(a) => {
697                        match a.checked_neg() {
698                            Some(b) => Ok(Value::Int(b)),
699                            None => Err(Error::Interp(String::from("overflow in negation"))),
700                        }
701                    },
702                    Value::Float(a) => Ok(Value::Float(-a)),
703                    Value::Object(object) => {
704                        match &**object {
705                            Object::Matrix(a) => Ok(Value::Object(Arc::new(Object::Matrix(matrix_rsub_for_scalar(a, 0.0)?)))),
706                            _ => Err(Error::Interp(String::from("unsupported type for negation"))),
707                        }
708                    },
709                    _ => Err(Error::Interp(String::from("unsupported type for negation"))),
710                }
711            },
712            UnaryOp::DotNeg => {
713                match self {
714                    Value::Int(_) | Value::Float(_) => Ok(Value::Float(-self.to_f32())),
715                    Value::Object(object) => {
716                        match &**object {
717                            Object::Matrix(a) => Ok(Value::Object(Arc::new(Object::Matrix(matrix_rsub_for_scalar(a, 0.0)?)))),
718                            _ => Err(Error::Interp(String::from("unsupported type for dot negation"))),
719                        }
720                    },
721                    _ => self.dot1("unsupported type for dot negation", |v| v.unary_op(op)),
722                }
723            },
724            UnaryOp::Not => Ok(Value::Bool(!self.to_bool())),
725            UnaryOp::Transpose => {
726                match self {
727                    Value::Int(_) | Value::Float(_) => Ok(self.clone()),
728                    Value::Object(object) => {
729                        match &**object {
730                            Object::Matrix(a) => Ok(Value::Object(Arc::new(Object::Matrix(a.transpose())))),
731                            _ => Err(Error::Interp(String::from("unsupported type for transpose"))),
732                        }
733                    },
734                    _ => Err(Error::Interp(String::from("unsupported type for transpose"))),
735                }
736            },
737        }
738    }
739
740    /// Performs an operation on two values for the binary operator.
741    pub fn bin_op(&self, op: BinOp, value: &Value) -> Result<Value>
742    {
743        match op {
744            BinOp::Index => self.elem(value),
745            BinOp::Mul => {
746                match (self, value) {
747                    (Value::Int(a), Value::Int(b)) => {
748                        match a.checked_mul(*b) {
749                            Some(c) => Ok(Value::Int(c)),
750                            None => Err(Error::Interp(String::from("overflow in multiplication"))),
751                        }
752                    },
753                    (Value::Int(_) | Value::Float(_), Value::Int(_) | Value::Float(_)) => Ok(Value::Float(self.to_f32() * value.to_f32())),
754                    (Value::Object(object), Value::Int(_) | Value::Float(_)) => {
755                        match &**object {
756                            Object::Matrix(a) => Ok(Value::Object(Arc::new(Object::Matrix(matrix_mul_for_scalar(a, value.to_f32())?)))),
757                            _ => Err(Error::Interp(String::from("unsupported types for multiplication"))),
758                        }
759                    },
760                    (Value::Int(_) | Value::Float(_), Value::Object(object2)) => {
761                        match &**object2 {
762                            Object::Matrix(b) => Ok(Value::Object(Arc::new(Object::Matrix(matrix_mul_for_scalar(b, self.to_f32())?)))),
763                            _ => Err(Error::Interp(String::from("unsupported types for multiplication"))),
764                        }
765                    },
766                    (Value::Object(object), Value::Object(object2)) => {
767                        match (&**object, &**object2) {
768                            (Object::Matrix(a), Object::Matrix(b)) => Ok(Value::Object(Arc::new(Object::Matrix(matrix_mul(a, b)?)))),
769                            _ => Err(Error::Interp(String::from("unsupported types for multiplication"))),
770                        }
771                    },
772                    _ => Err(Error::Interp(String::from("unsupported types for multiplication"))),
773                }
774            },
775            BinOp::DotMul => {
776                match (self, value) {
777                    (Value::Int(_) | Value::Float(_), Value::Int(_) | Value::Float(_)) => Ok(Value::Float(self.to_f32() * value.to_f32())),
778                    (Value::Object(object), Value::Int(_) | Value::Float(_)) => {
779                        match &**object {
780                            Object::Matrix(a) => Ok(Value::Object(Arc::new(Object::Matrix(matrix_mul_for_scalar(a, value.to_f32())?)))),
781                            _ => Err(Error::Interp(String::from("unsupported types for dot multiplication"))),
782                        }
783                    },
784                    (Value::Int(_) | Value::Float(_), Value::Object(object2)) => {
785                        match &**object2 {
786                            Object::Matrix(b) => Ok(Value::Object(Arc::new(Object::Matrix(matrix_mul_for_scalar(b, self.to_f32())?)))),
787                            _ => Err(Error::Interp(String::from("unsupported types for dot multiplication"))),
788                        }
789                    },
790                    (Value::Object(object), Value::Object(object2)) => {
791                        match (&**object, &**object2) {
792                            (Object::Matrix(a), Object::Matrix(b)) => Ok(Value::Object(Arc::new(Object::Matrix(matrix_mul_elems(a, b)?)))),
793                            _ => Err(Error::Interp(String::from("unsupported types for dot multiplication"))),
794                        }
795                    },
796                    (Value::Ref(_), Value::Int(_) | Value::Float(_)) => self.dot1("unsupported types for dot multiplication", |v| v.bin_op(op, value)),
797                    (Value::Int(_) | Value::Float(_), Value::Ref(_)) => value.dot1("unsupported types for dot multiplication", |v| self.bin_op(op, v)),
798                    _ => self.dot2(value, "unsupported types for dot multiplication", |v, w| v.bin_op(op, w)),
799                }
800            },
801            BinOp::Div => {
802                match (self, value) {
803                    (Value::Int(a), Value::Int(b)) => {
804                        match a.checked_div(*b) {
805                            Some(c) => Ok(Value::Int(c)),
806                            None => {
807                                if *b == 0 {
808                                    Err(Error::Interp(String::from("division by zero")))
809                                } else {
810                                    Err(Error::Interp(String::from("overflow in division")))
811                                }
812                            },
813                        }
814                    },
815                    (Value::Int(_) | Value::Float(_), Value::Int(_) | Value::Float(_)) => Ok(Value::Float(self.to_f32() / value.to_f32())),
816                    (Value::Object(object), Value::Int(_) | Value::Float(_)) => {
817                        match &**object {
818                            Object::Matrix(a) => Ok(Value::Object(Arc::new(Object::Matrix(matrix_div_for_scalar(a, value.to_f32())?)))),
819                            _ => Err(Error::Interp(String::from("unsupported types for division"))),
820                        }
821                    },
822                    (Value::Int(_) | Value::Float(_), Value::Object(object2)) => {
823                        match &**object2 {
824                            Object::Matrix(b) => Ok(Value::Object(Arc::new(Object::Matrix(matrix_rdiv_for_scalar(b, self.to_f32())?)))),
825                            _ => Err(Error::Interp(String::from("unsupported types for division"))),
826                        }
827                    },
828                    (_, _) => Err(Error::Interp(String::from("unsupported types for division"))),
829                }
830            },
831            BinOp::DotDiv => {
832                match (self, value) {
833                    (Value::Int(_) | Value::Float(_), Value::Int(_) | Value::Float(_)) => Ok(Value::Float(self.to_f32() / value.to_f32())),
834                    (Value::Object(object), Value::Int(_) | Value::Float(_)) => {
835                        match &**object {
836                            Object::Matrix(a) => Ok(Value::Object(Arc::new(Object::Matrix(matrix_div_for_scalar(a, value.to_f32())?)))),
837                            _ => Err(Error::Interp(String::from("unsupported types for dot division"))),
838                        }
839                    },
840                    (Value::Int(_) | Value::Float(_), Value::Object(object2)) => {
841                        match &**object2 {
842                            Object::Matrix(b) => Ok(Value::Object(Arc::new(Object::Matrix(matrix_rdiv_for_scalar(b, self.to_f32())?)))),
843                            _ => Err(Error::Interp(String::from("unsupported types for dot division"))),
844                        }
845                    },
846                    (Value::Object(object), Value::Object(object2)) => {
847                        match (&**object, &**object2) {
848                            (Object::Matrix(a), Object::Matrix(b)) => Ok(Value::Object(Arc::new(Object::Matrix(matrix_div_elems(a, b)?)))),
849                            _ => Err(Error::Interp(String::from("unsupported types for dot division"))),
850                        }
851                    },
852                    (Value::Ref(_), Value::Int(_) | Value::Float(_)) => self.dot1("unsupported types for dot division", |v| v.bin_op(op, value)),
853                    (Value::Int(_) | Value::Float(_), Value::Ref(_)) => value.dot1("unsupported types for dot division", |v| self.bin_op(op, v)),
854                    (_, _) => self.dot2(value, "unsupported types for dot division", |v, w| v.bin_op(op, w)),
855                }
856            },
857            BinOp::Add => {
858                match (self, value) {
859                    (Value::Int(a), Value::Int(b)) => {
860                        match a.checked_add(*b) {
861                            Some(c) => Ok(Value::Int(c)),
862                            None => Err(Error::Interp(String::from("overflow in addition"))),
863                        }
864                    },
865                    (Value::Int(_) | Value::Float(_), Value::Int(_) | Value::Float(_)) => Ok(Value::Float(self.to_f32() + value.to_f32())),
866                    (Value::Object(object), Value::Int(_) | Value::Float(_)) => {
867                        match &**object {
868                            Object::Matrix(a) => Ok(Value::Object(Arc::new(Object::Matrix(matrix_add_for_scalar(a, value.to_f32())?)))),
869                            _ => Err(Error::Interp(String::from("unsupported types for addition"))),
870                        }
871                    },
872                    (Value::Int(_) | Value::Float(_), Value::Object(object2)) => {
873                        match &**object2 {
874                            Object::Matrix(b) => Ok(Value::Object(Arc::new(Object::Matrix(matrix_add_for_scalar(b, self.to_f32())?)))),
875                            _ => Err(Error::Interp(String::from("unsupported types for addition"))),
876                        }
877                    },
878                    (Value::Object(object), Value::Object(object2)) => {
879                        match (&**object, &**object2) {
880                            (Object::String(s), Object::String(t)) => Ok(Value::Object(Arc::new(Object::String(s.clone() + t.as_str())))),
881                            (Object::Matrix(a), Object::Matrix(b)) => Ok(Value::Object(Arc::new(Object::Matrix(matrix_add(a, b)?)))),
882                            _ => Err(Error::Interp(String::from("unsupported types for addition"))),
883                        }
884                    },
885                    (Value::Ref(object), Value::Ref(object2)) => {
886                        let object_g = rw_lock_read(&**object)?;
887                        let object2_g = rw_lock_read(&**object2)?;
888                        match (&*object_g, &*object2_g) {
889                            (MutObject::Array(elems), MutObject::Array(elems2)) => {
890                                let mut new_elems = elems.clone();
891                                new_elems.extend_from_slice(elems2.as_slice());
892                                Ok(Value::Ref(Arc::new(RwLock::new(MutObject::Array(new_elems)))))
893                            },
894                            (MutObject::Struct(fields), MutObject::Struct(fields2)) => {
895                                let mut new_fields: BTreeMap<String, Value> = BTreeMap::new();
896                                let idents: BTreeSet<&String> = fields.keys().collect();
897                                let idents2: BTreeSet<&String> = fields2.keys().collect();
898                                let idents3: Vec<&String> = idents.union(&idents2).map(|s| *s).collect();
899                                for ident in &idents3 {
900                                    match fields.get(*ident) {
901                                        Some(field) => {
902                                            new_fields.insert((*ident).clone(), field.clone());
903                                        },
904                                        None => {
905                                            match fields2.get(*ident) {
906                                                Some(field2) => {
907                                                    new_fields.insert((*ident).clone(), field2.clone());
908                                                },
909                                                None => return Err(Error::Interp(String::from("no field"))),
910                                            }
911                                        },
912                                    }
913                                }
914                                Ok(Value::Ref(Arc::new(RwLock::new(MutObject::Struct(new_fields)))))
915                            },
916                            _ => Err(Error::Interp(String::from("unsupported types for addition"))),
917                        }
918                    },
919                    (_, _) => Err(Error::Interp(String::from("unsupported types for addition"))),
920                }
921            },
922            BinOp::DotAdd => {
923                match (self, value) {
924                    (Value::Int(_) | Value::Float(_), Value::Int(_) | Value::Float(_)) => Ok(Value::Float(self.to_f32() + value.to_f32())),
925                    (Value::Object(object), Value::Int(_) | Value::Float(_)) => {
926                        match &**object {
927                            Object::Matrix(a) => Ok(Value::Object(Arc::new(Object::Matrix(matrix_add_for_scalar(a, value.to_f32())?)))),
928                            _ => Err(Error::Interp(String::from("unsupported types for dot addition"))),
929                        }
930                    },
931                    (Value::Int(_) | Value::Float(_), Value::Object(object2)) => {
932                        match &**object2 {
933                            Object::Matrix(b) => Ok(Value::Object(Arc::new(Object::Matrix(matrix_add_for_scalar(b, self.to_f32())?)))),
934                            _ => Err(Error::Interp(String::from("unsupported types for dot addition"))),
935                        }
936                    },
937                    (Value::Object(object), Value::Object(object2)) => {
938                        match (&**object, &**object2) {
939                            (Object::Matrix(a), Object::Matrix(b)) => Ok(Value::Object(Arc::new(Object::Matrix(matrix_add(a, b)?)))),
940                            _ => Err(Error::Interp(String::from("unsupported types for dot addition"))),
941                        }
942                    },
943                    (Value::Ref(_), Value::Int(_) | Value::Float(_)) => self.dot1("unsupported types for dot addition", |v| v.bin_op(op, value)),
944                    (Value::Int(_) | Value::Float(_), Value::Ref(_)) => value.dot1("unsupported types for dot addition", |v| self.bin_op(op, v)),
945                    (_, _) => self.dot2(value, "unsupported types for dot addition", |v, w| v.bin_op(op, w)),
946                }
947            },
948            BinOp::Sub => {
949                match (self, value) {
950                    (Value::Int(a), Value::Int(b)) => {
951                        match a.checked_sub(*b) {
952                            Some(c) => Ok(Value::Int(c)),
953                            None => Err(Error::Interp(String::from("overflow in subtraction"))),
954                        }
955                    },
956                    (Value::Int(_) | Value::Float(_), Value::Int(_) | Value::Float(_)) => Ok(Value::Float(self.to_f32() - value.to_f32())),
957                    (Value::Object(object), Value::Int(_) | Value::Float(_)) => {
958                        match &**object {
959                            Object::Matrix(a) => Ok(Value::Object(Arc::new(Object::Matrix(matrix_sub_for_scalar(a, value.to_f32())?)))),
960                            _ => Err(Error::Interp(String::from("unsupported types for subtraction"))),
961                        }
962                    },
963                    (Value::Int(_) | Value::Float(_), Value::Object(object2)) => {
964                        match &**object2 {
965                            Object::Matrix(b) => Ok(Value::Object(Arc::new(Object::Matrix(matrix_rsub_for_scalar(b, self.to_f32())?)))),
966                            _ => Err(Error::Interp(String::from("unsupported types for subtraction"))),
967                        }
968                    },
969                    (Value::Object(object), Value::Object(object2)) => {
970                        match (&**object, &**object2) {
971                            (Object::Matrix(a), Object::Matrix(b)) => Ok(Value::Object(Arc::new(Object::Matrix(matrix_sub(a, b)?)))),
972                            _ => Err(Error::Interp(String::from("unsupported types for subtraction"))),
973                        }
974                    },
975                    (_, _) => Err(Error::Interp(String::from("unsupported types for subtraction"))),
976                }
977            },
978            BinOp::DotSub => {
979                match (self, value) {
980                    (Value::Int(_) | Value::Float(_), Value::Int(_) | Value::Float(_)) => Ok(Value::Float(self.to_f32() - value.to_f32())),
981                    (Value::Object(object), Value::Int(_) | Value::Float(_)) => {
982                        match &**object {
983                            Object::Matrix(a) => Ok(Value::Object(Arc::new(Object::Matrix(matrix_sub_for_scalar(a, value.to_f32())?)))),
984                            _ => Err(Error::Interp(String::from("unsupported types for dot subtraction"))),
985                        }
986                    },
987                    (Value::Int(_) | Value::Float(_), Value::Object(object2)) => {
988                        match &**object2 {
989                            Object::Matrix(b) => Ok(Value::Object(Arc::new(Object::Matrix(matrix_rsub_for_scalar(b, self.to_f32())?)))),
990                            _ => Err(Error::Interp(String::from("unsupported types for dot subtraction"))),
991                        }
992                    },
993                    (Value::Object(object), Value::Object(object2)) => {
994                        match (&**object, &**object2) {
995                            (Object::Matrix(a), Object::Matrix(b)) => Ok(Value::Object(Arc::new(Object::Matrix(matrix_sub(a, b)?)))),
996                            _ => Err(Error::Interp(String::from("unsupported types for dot subtraction"))),
997                        }
998                    },
999                    (Value::Ref(_), Value::Int(_) | Value::Float(_)) => self.dot1("unsupported types for dot subtraction", |v| v.bin_op(op, value)),
1000                    (Value::Int(_) | Value::Float(_), Value::Ref(_)) => value.dot1("unsupported types for dot subtraction", |v| self.bin_op(op, v)),
1001                    (_, _) => self.dot2(value, "unsupported types for dot subtraction", |v, w| v.bin_op(op, w)),
1002                }
1003            },
1004            BinOp::Lt => {
1005                match (self, value) {
1006                    (Value::Bool(a), Value::Bool(b)) => Ok(Value::Bool(a < b)),
1007                    (Value::Int(a), Value::Int(b)) => Ok(Value::Bool(a < b)),
1008                    (Value::Int(_) | Value::Float(_), Value::Int(_) | Value::Float(_)) => Ok(Value::Bool(self.to_f32() < value.to_f32())),
1009                    (Value::Object(object), Value::Object(object2)) => {
1010                        match (&**object, &**object2) {
1011                            (Object::String(s), Object::String(t)) => Ok(Value::Bool(s < t)),
1012                            (_, _) => Err(Error::Interp(String::from("unsupported types for comparison"))),
1013                        }
1014                    },
1015                    (_, _) => Err(Error::Interp(String::from("unsupported types for comparison"))),
1016                }
1017            },
1018            BinOp::Ge => Ok(Value::Bool(!self.bin_op(BinOp::Lt, value)?.to_bool())),
1019            BinOp::Gt => Ok(Value::Bool(value.bin_op(BinOp::Lt, self)?.to_bool())),
1020            BinOp::Le => Ok(Value::Bool(!value.bin_op(BinOp::Lt, self)?.to_bool())),
1021            BinOp::Eq => Ok(Value::Bool(self.eq_without_types(value)?)),
1022            BinOp::Ne => Ok(Value::Bool(!self.bin_op(BinOp::Eq, value)?.to_bool())),
1023        }
1024    }
1025    
1026    /// Returns an interator if the value is iterable, otherwise `None`.
1027    pub fn iter(&self) -> Result<Option<Iter<'_>>>
1028    {
1029        match self {
1030            Value::Object(object) => {
1031                match &**object {
1032                    Object::String(s) => Ok(Some(Iter::new(IterEnum::String(s.chars())))),
1033                    Object::IntRange(a, b, c) => Ok(Some(Iter::new(IterEnum::IntRange(*a, *b, *c, false)))),
1034                    Object::FloatRange(a, b, c) => Ok(Some(Iter::new(IterEnum::FloatRange(*a, *b, *c, false)))),
1035                    Object::MatrixArray(_, _, _, _) => Ok(Some(Iter::new(IterEnum::MatrixArray(object.clone(), 0, false)))), 
1036                    Object::MatrixRowSlice(matrix_array, i) => Ok(Some(Iter::new(IterEnum::MatrixRowSlice(matrix_array.clone(), *i, 0, false)))),
1037                    _ => Ok(None),
1038                }
1039            },
1040            Value::Ref(object) => {
1041                let object_g = rw_lock_read(&**object)?;
1042                match &*object_g {
1043                    MutObject::Array(_) => Ok(Some(Iter::new(IterEnum::Array(object.clone(), 0, false)))),
1044                    _ => Ok(None),
1045                }
1046            }
1047            _ => Ok(None),
1048        }
1049    }
1050
1051    /// Converts the value to a matrix array.
1052    ///
1053    /// If the value isn't a matrix or a matrix array, this method returns an error.
1054    pub fn to_matrix_array(&self) -> Result<Value>
1055    {
1056        match self {
1057            Value::Object(object) => {
1058                match &**object {
1059                    Object::Matrix(a) => Ok(Value::Object(Arc::new(matrix_to_matrix_array(a)?))),
1060                    Object::MatrixArray(_, _, _, _) => Ok(self.clone()),
1061                    _ => Err(Error::Interp(String::from("unsupported type for conversion to matrix array"))),
1062                }
1063            },
1064            _ => Err(Error::Interp(String::from("unsupported type for conversion to matrix array"))),
1065        }
1066    }
1067
1068    fn fmt_with_indent(&self, f: &mut fmt::Formatter<'_>, indent: usize, is_width: bool) -> fmt::Result
1069    {
1070        let width = if is_width { 11 } else { 0 };
1071        match self {
1072            Value::None => write!(f, "{:>width$}", "none")?,
1073            Value::Bool(false) => write!(f, "{:>width$}", "false")?,
1074            Value::Bool(true) => write!(f, "{:>width$}", "true")?,
1075            Value::Int(a) => write!(f, "{:>width$}", a)?,
1076            Value::Float(a) => {
1077                if a.floor() == *a {
1078                    if format!("{}", a).len() > 11 {
1079                        write!(f, "{:>width$.4e}", a)?;
1080                    } else {
1081                        write!(f, "{:>width$}", a)?;
1082                    }
1083                } else {
1084                    if format!("{:.4}", a).len() > 11 || (a.abs() < 0.0001 && *a != 0.0) {
1085                        write!(f, "{:>width$.4e}", a)?;
1086                    } else {
1087                        write!(f, "{:>width$.4}", a)?;
1088                    }
1089                }
1090            },
1091            Value::Object(object) => {
1092                match &**object {
1093                    Object::String(s) => write!(f, "{}", s)?,
1094                    Object::IntRange(a, b, c) => {
1095                        Value::Int(*a).fmt_with_indent(f, indent, is_width)?;
1096                        write!(f, " to ")?;
1097                        Value::Int(*b).fmt_with_indent(f, indent, is_width)?;
1098                        write!(f, " by ")?;
1099                        Value::Int(*c).fmt_with_indent(f, indent, is_width)?;
1100                    },
1101                    Object::FloatRange(a, b, c) => {
1102                        Value::Float(*a).fmt_with_indent(f, indent, is_width)?;
1103                        write!(f, " to ")?;
1104                        Value::Float(*b).fmt_with_indent(f, indent, is_width)?;
1105                        write!(f, " by ")?;
1106                        Value::Float(*c).fmt_with_indent(f, indent, is_width)?;
1107                    },
1108                    Object::Matrix(_) => self.to_matrix_array().unwrap().fmt_with_indent(f, indent, is_width)?,
1109                    Object::Fun(idents, ident, _) => {
1110                        for ident2 in idents {
1111                            write!(f, "{}::", ident2)?;
1112                        }
1113                        write!(f, "{}", ident)?;
1114                    },
1115                    Object::BuiltinFun(ident, _) => write!(f, "{}", ident)?,
1116                    Object::MatrixArray(row_count, col_count, transpose_flag, xs) => {
1117                        if *row_count > 0 && *col_count > 0 { 
1118                            let new_indent = indent + 4;
1119                            writeln!(f, "[")?;
1120                            for i in 0..*row_count {
1121                                write!(f, "{:new_indent$}", "")?;
1122                                for j in 0..*col_count {
1123                                    let k = match transpose_flag {
1124                                        TransposeFlag::NoTranspose => i * (*col_count) + j,
1125                                        TransposeFlag::Transpose => j * (*row_count) + i,
1126                                    };
1127                                    Value::Float(xs[k]).fmt_with_indent(f, new_indent, true)?;
1128                                    if j + 1 < *col_count {
1129                                        write!(f, " ")?;
1130                                    }
1131                                }
1132                                writeln!(f, "")?;          
1133                            }
1134                            write!(f, "{:indent$}]", "")?;
1135                        } else {
1136                            write!(f, "[]")?;
1137                        }
1138                    },
1139                    Object::MatrixRowSlice(matrix_array, i) => {
1140                        match &**matrix_array {
1141                            Object::MatrixArray(row_count, col_count, transpose_flag, xs) => {
1142                                if *col_count > 0 {
1143                                    let new_indent = indent + 4;
1144                                    write!(f, "[")?;
1145                                    for j in 0..*col_count {
1146                                        let k = match transpose_flag {
1147                                            TransposeFlag::NoTranspose => (*i) * (*col_count) + j,
1148                                            TransposeFlag::Transpose => j * (*row_count) + (*i),
1149                                        };
1150                                        write!(f, " ")?;
1151                                        Value::Float(xs[k]).fmt_with_indent(f, new_indent, is_width)?;
1152                                    }
1153                                    write!(f, " ]")?;
1154                                } else {
1155                                    write!(f, "[]")?;
1156                                }
1157                            },
1158                            _ => write!(f, "[]")?,
1159                        }
1160                    },
1161                    Object::Error(_, msg) => write!(f, "{}", msg)?,
1162                    Object::WindowId(_) => write!(f, "windowid(...)")?,
1163                }
1164            },
1165            Value::Ref(object) => {
1166                let object_g = rw_lock_read(&**object).unwrap();
1167                match &*object_g {
1168                    MutObject::Array(elems) => {
1169                        if !elems.is_empty() {
1170                            let new_indent = indent + 4;
1171                            write!(f, ".[")?;
1172                            for elem in elems {
1173                                write!(f, " ")?;
1174                                elem.fmt_with_indent(f, new_indent, is_width)?;
1175                            }
1176                            write!(f, " .]")?;
1177                        } else {
1178                            write!(f, ".[.]")?;
1179                        }
1180                    },
1181                    MutObject::Struct(fields) => {
1182                        if !fields.is_empty() {
1183                            let new_indent = indent + 4;
1184                            writeln!(f, "{{")?;
1185                            for (ident, field) in fields {
1186                                write!(f, "{:new_indent$}{}: ", "", ident)?;
1187                                field.fmt_with_indent(f, new_indent, is_width)?;
1188                                writeln!(f, "")?;
1189                            }
1190                            write!(f, "{:indent$}}}", "")?;
1191                        } else {
1192                            write!(f, "{{}}")?;
1193                        }
1194                    },
1195                }
1196            },
1197            Value::Weak(object) => {
1198                match object.upgrade() {
1199                    Some(_) => write!(f, "weak(...)")?,
1200                    None => write!(f, "weak()")?,
1201                }
1202            },
1203        }
1204        Ok(())
1205    }
1206}
1207
1208impl Neg for Value
1209{
1210    type Output = Self;
1211    
1212    fn neg(self) -> Self::Output
1213    { self.unary_op(UnaryOp::Neg).unwrap() }
1214}
1215
1216impl Neg for &Value
1217{
1218    type Output = Value;
1219    
1220    fn neg(self) -> Self::Output
1221    { self.unary_op(UnaryOp::Neg).unwrap() }
1222}
1223
1224impl Not for Value
1225{
1226    type Output = Self;
1227    
1228    fn not(self) -> Self::Output
1229    { self.unary_op(UnaryOp::Not).unwrap() }
1230}
1231
1232impl Not for &Value
1233{
1234    type Output = Value;
1235    
1236    fn not(self) -> Self::Output
1237    { self.unary_op(UnaryOp::Not).unwrap() }
1238}
1239
1240impl Add for Value
1241{
1242    type Output = Self;
1243    
1244    fn add(self, rhs: Self) -> Self::Output
1245    { self.bin_op(BinOp::Add, &rhs).unwrap() }
1246}
1247
1248impl Add<&Value> for Value
1249{
1250    type Output = Self;
1251    
1252    fn add(self, rhs: &Value) -> Self::Output
1253    { self.bin_op(BinOp::Add, rhs).unwrap() }
1254}
1255
1256impl Add<Value> for &Value
1257{
1258    type Output = Value;
1259    
1260    fn add(self, rhs: Value) -> Self::Output
1261    { self.bin_op(BinOp::Add, &rhs).unwrap() }
1262}
1263
1264impl Add<&Value> for &Value
1265{
1266    type Output = Value;
1267    
1268    fn add(self, rhs: &Value) -> Self::Output
1269    { self.bin_op(BinOp::Add, rhs).unwrap() }
1270}
1271
1272impl AddAssign for Value
1273{
1274    fn add_assign(&mut self, rhs: Self)
1275    { *self = self.bin_op(BinOp::Add, &rhs).unwrap(); }
1276}
1277
1278impl AddAssign<&Value> for Value
1279{
1280    fn add_assign(&mut self, rhs: &Self)
1281    { *self = self.bin_op(BinOp::Add, rhs).unwrap(); }
1282}
1283
1284impl Sub for Value
1285{
1286    type Output = Self;
1287    
1288    fn sub(self, rhs: Self) -> Self::Output
1289    { self.bin_op(BinOp::Sub, &rhs).unwrap() }
1290}
1291
1292impl Sub<&Value> for Value
1293{
1294    type Output = Self;
1295    
1296    fn sub(self, rhs: &Value) -> Self::Output
1297    { self.bin_op(BinOp::Sub, rhs).unwrap() }
1298}
1299
1300impl Sub<Value> for &Value
1301{
1302    type Output = Value;
1303    
1304    fn sub(self, rhs: Value) -> Self::Output
1305    { self.bin_op(BinOp::Sub, &rhs).unwrap() }
1306}
1307
1308impl Sub<&Value> for &Value
1309{
1310    type Output = Value;
1311    
1312    fn sub(self, rhs: &Value) -> Self::Output
1313    { self.bin_op(BinOp::Sub, rhs).unwrap() }
1314}
1315
1316impl SubAssign for Value
1317{
1318    fn sub_assign(&mut self, rhs: Self)
1319    { *self = self.bin_op(BinOp::Sub, &rhs).unwrap(); }
1320}
1321
1322impl SubAssign<&Value> for Value
1323{
1324    fn sub_assign(&mut self, rhs: &Self)
1325    { *self = self.bin_op(BinOp::Sub, rhs).unwrap(); }
1326}
1327
1328impl Mul for Value
1329{
1330    type Output = Self;
1331    
1332    fn mul(self, rhs: Self) -> Self::Output
1333    { self.bin_op(BinOp::Mul, &rhs).unwrap() }
1334}
1335
1336impl Mul<&Value> for Value
1337{
1338    type Output = Self;
1339    
1340    fn mul(self, rhs: &Value) -> Self::Output
1341    { self.bin_op(BinOp::Mul, rhs).unwrap() }
1342}
1343
1344impl Mul<Value> for &Value
1345{
1346    type Output = Value;
1347    
1348    fn mul(self, rhs: Value) -> Self::Output
1349    { self.bin_op(BinOp::Mul, &rhs).unwrap() }
1350}
1351
1352impl Mul<&Value> for &Value
1353{
1354    type Output = Value;
1355    
1356    fn mul(self, rhs: &Value) -> Self::Output
1357    { self.bin_op(BinOp::Mul, rhs).unwrap() }
1358}
1359
1360impl MulAssign for Value
1361{
1362    fn mul_assign(&mut self, rhs: Self)
1363    { *self = self.bin_op(BinOp::Mul, &rhs).unwrap(); }
1364}
1365
1366impl MulAssign<&Value> for Value
1367{
1368    fn mul_assign(&mut self, rhs: &Self)
1369    { *self = self.bin_op(BinOp::Mul, rhs).unwrap(); }
1370}
1371
1372impl Div for Value
1373{
1374    type Output = Self;
1375    
1376    fn div(self, rhs: Self) -> Self::Output
1377    { self.bin_op(BinOp::Div, &rhs).unwrap() }
1378}
1379
1380impl Div<&Value> for Value
1381{
1382    type Output = Self;
1383    
1384    fn div(self, rhs: &Value) -> Self::Output
1385    { self.bin_op(BinOp::Div, rhs).unwrap() }
1386}
1387
1388impl Div<Value> for &Value
1389{
1390    type Output = Value;
1391    
1392    fn div(self, rhs: Value) -> Self::Output
1393    { self.bin_op(BinOp::Div, &rhs).unwrap() }
1394}
1395
1396impl Div<&Value> for &Value
1397{
1398    type Output = Value;
1399    
1400    fn div(self, rhs: &Value) -> Self::Output
1401    { self.bin_op(BinOp::Div, rhs).unwrap() }
1402}
1403
1404impl DivAssign for Value
1405{
1406    fn div_assign(&mut self, rhs: Self)
1407    { *self = self.bin_op(BinOp::Div, &rhs).unwrap(); }
1408}
1409
1410impl DivAssign<&Value> for Value
1411{
1412    fn div_assign(&mut self, rhs: &Self)
1413    { *self = self.bin_op(BinOp::Div, rhs).unwrap(); }
1414}
1415
1416impl PartialEq for Value
1417{
1418    fn eq(&self, other: &Self) -> bool
1419    { self.bin_op(BinOp::Eq, other).unwrap().to_bool() }
1420}
1421
1422impl PartialOrd for Value
1423{
1424    fn partial_cmp(&self, other: &Self) -> Option<Ordering>
1425    {
1426        match (self, other) {
1427            (Value::Bool(a), Value::Bool(b)) => a.partial_cmp(b),
1428            (Value::Int(a), Value::Int(b)) => a.partial_cmp(b),
1429            (Value::Int(_) | Value::Float(_), Value::Int(_) | Value::Float(_)) => self.to_f32().partial_cmp(&other.to_f32()),
1430            (Value::Object(object), Value::Object(object2)) => {
1431                match (&**object, &**object2) {
1432                    (Object::String(s), Object::String(t)) => s.partial_cmp(t),
1433                    (_, _) => None,
1434                }
1435            },
1436            (_, _) => None,
1437        }
1438    }
1439}
1440
1441impl fmt::Display for Value
1442{
1443    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
1444    { self.fmt_with_indent(f, 0, false) }
1445}
1446
1447impl Serialize for Value
1448{
1449    fn serialize<S>(&self, serializer: S) -> result::Result<S::Ok, S::Error>
1450        where S: Serializer
1451    {
1452        match self {
1453            Value::None => serializer.serialize_unit(),
1454            Value::Bool(a) => serializer.serialize_bool(*a),
1455            Value::Int(a) => serializer.serialize_i64(*a),
1456            Value::Float(a) => serializer.serialize_f32(*a),
1457            Value::Object(object) => {
1458                match &**object {
1459                    Object::String(s) => serializer.serialize_str(s.as_str()),
1460                    _ => Err(ser::Error::custom("unsupported type for serialization")),
1461                }
1462            },
1463            Value::Ref(object) => {
1464                let object_g = match rw_lock_read(&**object) {
1465                    Ok(tmp_object_g) => tmp_object_g,
1466                    Err(err) => return Err(ser::Error::custom(format!("{}", err))),
1467                };
1468                match &*object_g {
1469                    MutObject::Array(elems) => {
1470                        let mut seq = serializer.serialize_seq(Some(elems.len()))?;
1471                        for elem in elems {
1472                            seq.serialize_element(elem)?;
1473                        }
1474                        seq.end()
1475                    },
1476                    MutObject::Struct(fields) => {
1477                        let mut map = serializer.serialize_map(Some(fields.len()))?;
1478                        for (ident, field) in fields {
1479                            map.serialize_entry(ident, field)?;
1480                        }
1481                        map.end()
1482                    },
1483                }
1484            },
1485            _ => Err(ser::Error::custom("unsupported type for serialization")),
1486        }
1487    }
1488}
1489
1490struct ValueVisitor;
1491
1492impl<'de> Visitor<'de> for ValueVisitor
1493{
1494    type Value = Value;
1495
1496    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result
1497    { write!(formatter, "a value") }
1498
1499    fn visit_unit<E>(self) -> result::Result<Self::Value, E>
1500        where E: de::Error
1501    { Ok(Value::None) }
1502
1503    fn visit_bool<E>(self, v: bool) -> result::Result<Self::Value, E>
1504        where E: de::Error
1505    { Ok(Value::Bool(v)) }
1506
1507    fn visit_i64<E>(self, v: i64) -> result::Result<Self::Value, E>
1508        where E: de::Error
1509    { Ok(Value::Int(v)) }
1510
1511    fn visit_u64<E>(self, v: u64) -> result::Result<Self::Value, E>
1512        where E: de::Error
1513    { 
1514        if v <= (i64::MAX as u64) {
1515            Ok(Value::Int(v as i64))
1516        } else {
1517            Err(E::custom(String::from("too large integer number")))
1518        }
1519    }
1520    
1521    fn visit_f32<E>(self, v: f32) -> result::Result<Self::Value, E>
1522        where E: de::Error
1523    { Ok(Value::Float(v)) }
1524
1525    fn visit_f64<E>(self, v: f64) -> result::Result<Self::Value, E>
1526        where E: de::Error
1527    { Ok(Value::Float(v as f32)) }
1528    
1529    fn visit_str<E>(self, v: &str) -> result::Result<Self::Value, E>
1530        where E: de::Error
1531    { Ok(Value::Object(Arc::new(Object::String(String::from(v))))) }
1532    
1533    fn visit_seq<A>(self, mut seq: A) -> result::Result<Self::Value, A::Error>
1534        where A: SeqAccess<'de>
1535    {
1536        let mut elems: Vec<Value> = Vec::new();
1537        loop {
1538            match seq.next_element()? {
1539                Some(elem) => elems.push(elem),
1540                None => break,
1541            }
1542        }
1543        Ok(Value::Ref(Arc::new(RwLock::new(MutObject::Array(elems)))))
1544    }
1545    
1546    fn visit_map<A>(self, mut map: A) -> result::Result<Self::Value, A::Error>
1547        where A: MapAccess<'de>
1548    {
1549        let mut fields: BTreeMap<String, Value> = BTreeMap::new();
1550        loop {
1551            match map.next_key()? {
1552                Some(ident) => {
1553                    fields.insert(ident, map.next_value()?);
1554                },
1555                None => break,
1556            }
1557        }
1558        Ok(Value::Ref(Arc::new(RwLock::new(MutObject::Struct(fields)))))
1559    }
1560}
1561
1562impl<'de> Deserialize<'de> for Value
1563{
1564    fn deserialize<D>(deserializer: D) -> result::Result<Self, D::Error>
1565        where D: Deserializer<'de>
1566    { deserializer.deserialize_any(ValueVisitor) }
1567}
1568
1569/// An enumeration of immutable object.
1570#[derive(Clone, Debug)]
1571pub enum Object
1572{
1573    /// A string.
1574    String(String),
1575    /// An integer number range.
1576    IntRange(i64, i64, i64),
1577    /// A floating-point number range.
1578    FloatRange(f32, f32, f32),
1579    /// A matrix.
1580    Matrix(Matrix),
1581    /// A function.
1582    Fun(Vec<String>, String, Arc<Fun>),
1583    /// A built-in function.
1584    BuiltinFun(String, fn(&mut Interp, &mut Env, &[Value]) -> Result<Value>),
1585    /// A matrix array.
1586    MatrixArray(usize, usize, TransposeFlag, Vec<f32>),
1587    /// A matrix row slice.
1588    MatrixRowSlice(Arc<Object>, usize),
1589    /// An error.
1590    Error(String, String),
1591    /// A window identifier.
1592    WindowId(WindowId),
1593}
1594
1595impl Object
1596{
1597    fn priv_eq(&self, object: &Object) -> Result<bool>
1598    {
1599        match (self, object) {
1600            (Object::String(s), Object::String(t)) => Ok(s == t),
1601            (Object::IntRange(a, b, c), Object::IntRange(d, e, f)) => Ok(a == d && b == e && c == f),
1602            (Object::FloatRange(a, b, c), Object::FloatRange(d, e, f)) => Ok(a == d && b == e && c == f),
1603            (Object::Fun(idents, ident, fun), Object::Fun(idents2, ident2, fun2)) => Ok(idents == idents2 && ident == ident2 && Arc::ptr_eq(fun, fun2)),
1604            (Object::BuiltinFun(ident, f), Object::BuiltinFun(ident2, g)) => Ok(ident == ident2 && f == g),
1605            (Object::MatrixArray(a_row_count, a_col_count, a_transpose_flag, xs), Object::MatrixArray(b_row_count, b_col_count, b_transpose_flag, ys)) => {
1606                if a_row_count != b_row_count || a_col_count != b_col_count {
1607                    return Ok(false);
1608                }
1609                for i in 0..(*a_row_count) {
1610                    for j in 0..(*a_col_count) {
1611                        let ak = match a_transpose_flag {
1612                            TransposeFlag::NoTranspose => i * (*a_col_count) + j,
1613                            TransposeFlag::Transpose => j * (*a_row_count) + i,
1614                        };
1615                        let bk = match b_transpose_flag {
1616                            TransposeFlag::NoTranspose => i * (*b_col_count) + j,
1617                            TransposeFlag::Transpose => j * (*b_row_count) + i,
1618                        };
1619                        match (xs.get(ak), ys.get(bk)) {
1620                            (Some(x), Some(y)) => {
1621                                if x != y {
1622                                    return Ok(false);
1623                                }
1624                            },
1625                            (_, _) => return Err(Error::Interp(String::from("no element"))),
1626                        }
1627                    }
1628                }
1629                Ok(true)
1630            },
1631            (Object::MatrixRowSlice(matrix_array, ai), Object::MatrixRowSlice(matrix_array2, bi)) => {
1632                match (&**matrix_array, &**matrix_array2) {
1633                    (Object::MatrixArray(a_row_count, a_col_count, a_transpose_flag, xs), Object::MatrixArray(b_row_count, b_col_count, b_transpose_flag, ys)) => {
1634                        if a_col_count != b_col_count {
1635                            return Ok(false);
1636                        }
1637                        for j in 0..(*a_col_count) {
1638                            let ak = match a_transpose_flag {
1639                                TransposeFlag::NoTranspose => (*ai) * (*a_col_count) + j,
1640                                TransposeFlag::Transpose => j * (*a_row_count) + (*ai),
1641                            };
1642                            let bk = match b_transpose_flag {
1643                                TransposeFlag::NoTranspose => (*bi) * (*b_col_count) + j,
1644                                TransposeFlag::Transpose => j * (*b_row_count) + (*bi),
1645                            };
1646                            match (xs.get(ak), ys.get(bk)) {
1647                                (Some(x), Some(y)) => {
1648                                    if x != y {
1649                                        return Ok(false);
1650                                    }
1651                                },
1652                                (_, _) => return Err(Error::Interp(String::from("no element"))),
1653                            }
1654                        }
1655                        Ok(true)
1656                    },
1657                    (_, _) => return Err(Error::Interp(String::from("invalid matrix array type")))
1658                }
1659            },
1660            (Object::Error(kind, msg), Object::Error(kind2, msg2)) => Ok(kind == kind2 && msg == msg2),
1661            (Object::WindowId(window_id), Object::WindowId(window_id2)) => Ok(window_id == window_id2),
1662            (_, _) => Ok(false),
1663        }
1664    }
1665
1666    fn priv_nearly_eq(&self, object: &Object, eps: f32) -> Result<bool>
1667    {
1668        match (self, object) {
1669            (Object::MatrixArray(a_row_count, a_col_count, a_transpose_flag, xs), Object::MatrixArray(b_row_count, b_col_count, b_transpose_flag, ys)) => {
1670                if a_row_count != b_row_count || a_col_count != b_col_count {
1671                    return Ok(false);
1672                }
1673                for i in 0..(*a_row_count) {
1674                    for j in 0..(*a_col_count) {
1675                        let ak = match a_transpose_flag {
1676                            TransposeFlag::NoTranspose => i * (*a_col_count) + j,
1677                            TransposeFlag::Transpose => j * (*a_row_count) + i,
1678                        };
1679                        let bk = match b_transpose_flag {
1680                            TransposeFlag::NoTranspose => i * (*b_col_count) + j,
1681                            TransposeFlag::Transpose => j * (*b_row_count) + i,
1682                        };
1683                        match (xs.get(ak), ys.get(bk)) {
1684                            (Some(x), Some(y)) => {
1685                                if !nearly_eq(*x, *y, eps) {
1686                                    return Ok(false);
1687                                }
1688                            },
1689                            (_, _) => return Err(Error::Interp(String::from("no element"))),
1690                        }
1691                    }
1692                }
1693                Ok(true)
1694            },
1695            (Object::MatrixRowSlice(matrix_array, ai), Object::MatrixRowSlice(matrix_array2, bi)) => {
1696                match (&**matrix_array, &**matrix_array2) {
1697                    (Object::MatrixArray(a_row_count, a_col_count, a_transpose_flag, xs), Object::MatrixArray(b_row_count, b_col_count, b_transpose_flag, ys)) => {
1698                        if a_col_count != b_col_count {
1699                            return Ok(false);
1700                        }
1701                        for j in 0..(*a_col_count) {
1702                            let ak = match a_transpose_flag {
1703                                TransposeFlag::NoTranspose => (*ai) * (*a_col_count) + j,
1704                                TransposeFlag::Transpose => j * (*a_row_count) + (*ai),
1705                            };
1706                            let bk = match b_transpose_flag {
1707                                TransposeFlag::NoTranspose => (*bi) * (*b_col_count) + j,
1708                                TransposeFlag::Transpose => j * (*b_row_count) + (*bi),
1709                            };
1710                            match (xs.get(ak), ys.get(bk)) {
1711                                (Some(x), Some(y)) => {
1712                                    if !nearly_eq(*x, *y, eps) {
1713                                        return Ok(false);
1714                                    }
1715                                },
1716                                (_, _) => return Err(Error::Interp(String::from("no element"))),
1717                            }
1718                        }
1719                        Ok(true)
1720                    },
1721                    (_, _) => return Err(Error::Interp(String::from("invalid matrix array type")))
1722                }
1723            },
1724            (_, _) => self.priv_eq(object),
1725        }
1726    }
1727}
1728
1729/// An enumeration of transpose flag.
1730///
1731/// The transpose flag determines whether a matrix array is transposed.
1732#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
1733pub enum TransposeFlag
1734{
1735    /// No transpose, e.i. a matrix array isn't transposed.
1736    NoTranspose,
1737    /// Transpose, e.i. a matrix array is transposed.
1738    Transpose,
1739}
1740
1741/// An enumeration of mutable object.
1742#[derive(Clone, Debug)]
1743pub enum MutObject
1744{
1745    /// An array.
1746    Array(Vec<Value>),
1747    /// A structure.
1748    Struct(BTreeMap<String, Value>),
1749}
1750
1751impl MutObject
1752{
1753    fn priv_eq<F>(&self, object: &MutObject, mut f: F) -> Result<bool>
1754        where F: FnMut(&Value, &Value) -> Result<bool>
1755    {
1756        match (self, object) {
1757            (MutObject::Array(elems), MutObject::Array(elems2)) => {
1758                if elems.len() != elems2.len() {
1759                    return Ok(false);
1760                }
1761                for (elem, elem2) in elems.iter().zip(elems2.iter()) {
1762                    if !f(elem, elem2)? {
1763                        return Ok(false);
1764                    }
1765                }
1766                Ok(true)
1767            },
1768            (MutObject::Struct(fields), MutObject::Struct(fields2)) => {
1769                let idents: BTreeSet<&String> = fields.keys().collect();
1770                let idents2: BTreeSet<&String> = fields2.keys().collect();
1771                if idents != idents2 {
1772                    return Ok(false);
1773                }
1774                for ident in &idents {
1775                    match (fields.get(*ident), fields2.get(*ident)) {
1776                        (Some(field), Some(field2)) => {
1777                            if !f(field, field2)? {
1778                                return Ok(false);
1779                            }
1780                        },
1781                        (_, _) => return Err(Error::Interp(String::from("no field"))),
1782                    }
1783                }
1784                Ok(true)
1785            },
1786            (_, _) => Ok(false),
1787        }
1788    }
1789
1790    fn priv_nearly_eq<F>(&self, object: &MutObject, eps: f32, mut f: F) -> Result<bool>
1791        where F: FnMut(&Value, &Value, f32) -> Result<bool>
1792    {
1793        match (self, object) {
1794            (MutObject::Array(elems), MutObject::Array(elems2)) => {
1795                if elems.len() != elems2.len() {
1796                    return Ok(false);
1797                }
1798                for (elem, elem2) in elems.iter().zip(elems2.iter()) {
1799                    if !f(elem, elem2, eps)? {
1800                        return Ok(false);
1801                    }
1802                }
1803                Ok(true)
1804            },
1805            (MutObject::Struct(fields), MutObject::Struct(fields2)) => {
1806                let idents: BTreeSet<&String> = fields.keys().collect();
1807                let idents2: BTreeSet<&String> = fields2.keys().collect();
1808                if idents != idents2 {
1809                    return Ok(false);
1810                }
1811                for ident in &idents {
1812                    match (fields.get(*ident), fields2.get(*ident)) {
1813                        (Some(field), Some(field2)) => {
1814                            if !f(field, field2, eps)? {
1815                                return Ok(false);
1816                            }
1817                        },
1818                        (_, _) => return Err(Error::Interp(String::from("no field"))),
1819                    }
1820                }
1821                Ok(true)
1822            },
1823            (_, _) => Ok(false),
1824        }
1825    }
1826}
1827
1828/// A structure of iterator of values.
1829#[derive(Clone, Debug)]
1830pub struct Iter<'a>
1831{
1832    iter_enum: IterEnum<'a>,
1833}
1834
1835impl<'a> Iter<'a>
1836{
1837    fn new(iter_enum: IterEnum<'a>) -> Self
1838    { Iter { iter_enum, } }
1839}
1840
1841impl<'a> Iterator for Iter<'a>
1842{
1843    type Item = Result<Value>;
1844    
1845    fn next(&mut self) -> Option<Self::Item>
1846    {
1847        match &mut self.iter_enum {
1848            IterEnum::String(cs) => {
1849                match cs.next() {
1850                    Some(c) => {
1851                        let mut s = String::new();
1852                        s.push(c);
1853                        Some(Ok(Value::Object(Arc::new(Object::String(s)))))
1854                    },
1855                    None => None,
1856                }
1857            },
1858            IterEnum::IntRange(from, to, step, is_stopped) => {
1859                if !*is_stopped {
1860                    let current = if *step > 0 {
1861                        let tmp_current = if *from <= *to {
1862                            Some(*from)
1863                        } else {
1864                            None
1865                        };
1866                        if *from < *to {
1867                            match from.checked_add(*step) {
1868                                Some(tmp_from) => *from = tmp_from,
1869                                None => {
1870                                    *is_stopped = true;
1871                                    return Some(Err(Error::Interp(String::from("overflow in iteration"))));
1872                                },
1873                            }
1874                        } else {
1875                            *is_stopped = true;
1876                        }
1877                        tmp_current
1878                    } else if *step < 0 {
1879                        let tmp_current = if *from >= *to {
1880                            Some(*from)
1881                        } else {
1882                            None
1883                        };
1884                        if *from > *to {
1885                            match from.checked_add(*step) {
1886                                Some(tmp_from) => *from = tmp_from,
1887                                None => {
1888                                    *is_stopped = true;
1889                                    return Some(Err(Error::Interp(String::from("overflow in iteration"))));
1890                                },
1891                            }
1892                        } else {
1893                            *is_stopped = true;
1894                        }
1895                        tmp_current
1896                    } else {
1897                        *is_stopped = true;
1898                        return Some(Err(Error::Interp(String::from("range step is zero"))));
1899                    };
1900                    match current {
1901                        Some(current) => Some(Ok(Value::Int(current))),
1902                        None => None,
1903                    }
1904                } else {
1905                    None
1906                }
1907            },
1908            IterEnum::FloatRange(from, to, step, is_stopped) => {
1909                if !*is_stopped {
1910                    let current = if *step > 0.0 {
1911                        let tmp_current = if *from <= *to {
1912                            Some(*from)
1913                        } else {
1914                            None
1915                        };
1916                        if *from < *to {
1917                            *from += *step;
1918                        } else {
1919                            *is_stopped = true;
1920                        }
1921                        tmp_current
1922                    } else if *step < 0.0 {
1923                        let tmp_current = if *from >= *to {
1924                            Some(*from)
1925                        } else {
1926                            None
1927                        };
1928                        if *from > *to {
1929                            *from += *step;
1930                        } else {
1931                            *is_stopped = true;
1932                        }
1933                        tmp_current
1934                    } else {
1935                        *is_stopped = true;
1936                        return Some(Err(Error::Interp(String::from("range step is zero"))));
1937                    };
1938                    match current {
1939                        Some(current) => Some(Ok(Value::Float(current))),
1940                        None => None,
1941                    }
1942                } else {
1943                    None
1944                }
1945            },
1946            IterEnum::MatrixArray(matrix_array, i, is_stopped) => {
1947                if !*is_stopped {
1948                    match &**matrix_array {
1949                        Object::MatrixArray(row_count, _, _, _) => {
1950                            if *i < *row_count {
1951                                let j = *i;
1952                                *i += 1;
1953                                Some(Ok(Value::Object(Arc::new(Object::MatrixRowSlice(matrix_array.clone(), j)))))
1954                            } else {
1955                                None
1956                            }
1957                        },
1958                        _ => {
1959                            *is_stopped = true;
1960                            Some(Err(Error::Interp(String::from("invalid matrix array type"))))
1961                        },
1962                    }
1963                } else {
1964                    None
1965                }
1966            },
1967            IterEnum::MatrixRowSlice(matrix_array, i, j, is_stopped) => {
1968                if !*is_stopped {
1969                    match &**matrix_array {
1970                        Object::MatrixArray(row_count, col_count, transpose_flag, xs) => {
1971                            if *j < *col_count {
1972                                let k = match transpose_flag {
1973                                    TransposeFlag::NoTranspose => (*i) * (*col_count) + (*j),
1974                                    TransposeFlag::Transpose => (*j) * (*row_count) + (*i),
1975                                };
1976                                *j += 1;
1977                                match xs.get(k) {
1978                                    Some(x) => Some(Ok(Value::Float(*x))),
1979                                    None => {
1980                                        *is_stopped = true;
1981                                        Some(Err(Error::Interp(String::from("invalid index"))))
1982                                    },
1983                                }
1984                            } else {
1985                                None
1986                            }
1987                        },
1988                        _ => {
1989                            *is_stopped = true;
1990                            Some(Err(Error::Interp(String::from("invalid matrix array type"))))
1991                        },
1992                    }
1993                } else {
1994                    None
1995                }
1996            },
1997            IterEnum::Array(array, i, is_stopped) => {
1998                if !*is_stopped {
1999                    match rw_lock_read(&**array) {
2000                        Ok(array_g) => {
2001                            match &*array_g {
2002                                MutObject::Array(elems) => {
2003                                    if *i < elems.len() {
2004                                        let j = *i;
2005                                        *i += 1;
2006                                        match elems.get(j) {
2007                                            Some(elem) => Some(Ok(elem.clone())),
2008                                            None => {
2009                                                *is_stopped = true;
2010                                                Some(Err(Error::Interp(String::from("invalid index"))))
2011                                            },
2012                                        }
2013                                    } else {
2014                                        None
2015                                    }
2016                                },
2017                                _ => {
2018                                    *is_stopped = true;
2019                                    Some(Err(Error::Interp(String::from("invalid array type"))))
2020                                },
2021                            }
2022                        },
2023                        Err(err) => {
2024                            *is_stopped = true;
2025                            Some(Err(err))
2026                        },
2027                    }
2028                } else {
2029                    None
2030                }
2031            },
2032        }
2033    }
2034}
2035
2036#[derive(Clone, Debug)]
2037enum IterEnum<'a>
2038{
2039    String(Chars<'a>),
2040    IntRange(i64, i64, i64, bool),
2041    FloatRange(f32, f32, f32, bool),
2042    MatrixArray(Arc<Object>, usize, bool),
2043    MatrixRowSlice(Arc<Object>, usize, usize, bool),
2044    Array(Arc<RwLock<MutObject>>, usize, bool),
2045}
2046
2047#[cfg(test)]
2048mod tests;