Skip to main content

unlab_gpu/
builtins.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 module of built-in functions.
9use std::cmp;
10use std::f32;
11use std::ffi::OsString;
12use std::fs;
13use std::fs::File;
14use std::fs::create_dir;
15use std::fs::read_dir;
16use std::fs::remove_dir;
17use std::fs::remove_file;
18use std::io::BufWriter;
19use std::io::ErrorKind;
20use std::io::Read;
21use std::io::Write;
22use std::io::stdin;
23use std::io::stdout;
24use std::io::stderr;
25use std::mem::size_of;
26use std::path;
27use std::path::PathBuf;
28use std::process::Command;
29use std::sync::Arc;
30use std::sync::RwLock;
31use std::sync::Weak;
32use opener::open_browser;
33use rand::random;
34use rand::random_range;
35use crate::matrix::Matrix;
36use crate::serde_json;
37use crate::toml;
38use crate::env::*;
39use crate::error::*;
40use crate::getopts::*;
41use crate::interp::*;
42use crate::io::*;
43use crate::mod_node::*;
44use crate::parser::*;
45#[cfg(feature = "plot")]
46use crate::plot::*;
47use crate::utils::*;
48use crate::value::*;
49use crate::version::*;
50
51fn fun1<F>(arg_values: &[Value], f: F) -> Result<Value>
52    where F: FnOnce(&Value) -> Result<Value>
53{
54    if arg_values.len() != 1 {
55        return Err(Error::Interp(String::from("invalid number of arguments")));
56    }
57    match arg_values.get(0) {
58        Some(value) => f(value),
59        None => Err(Error::Interp(String::from("no argument"))),
60    }
61}
62
63fn fun2<F>(arg_values: &[Value], f: F) -> Result<Value>
64    where F: FnOnce(&Value, &Value) -> Result<Value>
65{
66    if arg_values.len() != 2 {
67        return Err(Error::Interp(String::from("invalid number of arguments")));
68    }
69    match (arg_values.get(0), arg_values.get(1)) {
70        (Some(value), Some(value2)) => f(value, value2),
71        (_, _) => Err(Error::Interp(String::from("no argument"))),
72    }
73}
74
75fn fun1_for_f32_and_matrix_with_fun_refs<F, G>(arg_values: &[Value], err_msg: &str, f: &mut F, g: &mut G) -> Result<Value>
76    where F: FnMut(f32) -> f32,
77        G: FnMut(&Matrix) -> Result<Matrix>
78{
79    if arg_values.len() != 1 {
80        return Err(Error::Interp(String::from("invalid number of arguments")));
81    }
82    match arg_values.get(0) {
83        Some(value @ (Value::Int(_) | Value::Float(_))) => Ok(Value::Float(f(value.to_f32()))),
84        Some(Value::Object(object)) => {
85            match &**object {
86                Object::Matrix(a) => Ok(Value::Object(Arc::new(Object::Matrix(g(a)?)))),
87                _ => Err(Error::Interp(String::from(err_msg))),
88            }
89        },
90        Some(value) => value.dot1(err_msg, |a| fun1_for_f32_and_matrix_with_fun_refs(&[a.clone()], err_msg, f, g)),
91        None => Err(Error::Interp(String::from("no argument"))),
92    }
93}
94
95fn fun1_for_f32_and_matrix<F, G>(arg_values: &[Value], err_msg: &str, mut f: F, mut g: G) -> Result<Value>
96    where F: FnMut(f32) -> f32,
97        G: FnMut(&Matrix) -> Result<Matrix>
98{ fun1_for_f32_and_matrix_with_fun_refs(arg_values, err_msg, &mut f, &mut g) }
99
100fn fun2_for_f32_and_matrix_with_fun_refs<F, G, RG, H>(arg_values: &[Value], err_msg: &str, f: &mut F, g: &mut G, rg: &mut RG, h: &mut H) -> Result<Value>
101    where F: FnMut(f32, f32) -> f32,
102        G: FnMut(&Matrix, f32) -> Result<Matrix>,
103        RG: FnMut(&Matrix, f32) -> Result<Matrix>,
104        H: FnMut(&Matrix, &Matrix) -> Result<Matrix>
105{
106    if arg_values.len() != 2 {
107        return Err(Error::Interp(String::from("invalid number of arguments")));
108    }
109    match (arg_values.get(0), arg_values.get(1)) {
110        (Some(value @ (Value::Int(_) | Value::Float(_))), Some(value2 @ (Value::Int(_) | Value::Float(_)))) => Ok(Value::Float(f(value.to_f32(), value2.to_f32()))),
111        (Some(Value::Object(object)), Some(value2 @ (Value::Int(_) | Value::Float(_)))) => {
112            match &**object {
113                Object::Matrix(a) => Ok(Value::Object(Arc::new(Object::Matrix(g(a, value2.to_f32())?)))),
114                _ => Err(Error::Interp(String::from(err_msg))),
115            }
116        },
117        (Some(value @ (Value::Int(_) | Value::Float(_))), Some(Value::Object(object2))) => {
118            match &**object2 {
119                Object::Matrix(b) => Ok(Value::Object(Arc::new(Object::Matrix(rg(b, value.to_f32())?)))),
120                _ => Err(Error::Interp(String::from(err_msg))),
121            }
122        },
123        (Some(Value::Object(object)), Some(Value::Object(object2))) => {
124            match (&**object, &**object2) {
125                (Object::Matrix(a), Object::Matrix(b)) => Ok(Value::Object(Arc::new(Object::Matrix(h(a, b)?)))),
126                _ => Err(Error::Interp(String::from(err_msg))),
127            }
128        },
129        (Some(value @ Value::Ref(_)), Some(value2 @ (Value::Int(_) | Value::Float(_)))) => value.dot1(err_msg, |a| fun2_for_f32_and_matrix_with_fun_refs(&[a.clone(), value2.clone()], err_msg, f, g, rg, h)),
130        (Some(value @ (Value::Int(_) | Value::Float(_))), Some(value2 @ Value::Ref(_))) => value2.dot1(err_msg, |b| fun2_for_f32_and_matrix_with_fun_refs(&[value.clone(), b.clone()], err_msg, f, g, rg, h)),
131        (Some(value), Some(value2)) => value.dot2(value2, err_msg, |a, b| fun2_for_f32_and_matrix_with_fun_refs(&[a.clone(), b.clone()], err_msg, f, g, rg, h)),
132        (_, _) => Err(Error::Interp(String::from("no argument"))),
133    }
134}
135
136fn fun2_for_f32_and_matrix<F, G, RG, H>(arg_values: &[Value], err_msg: &str, mut f: F, mut g: G, mut rg: RG, mut h: H) -> Result<Value>
137    where F: FnMut(f32, f32) -> f32,
138        G: FnMut(&Matrix, f32) -> Result<Matrix>,
139        RG: FnMut(&Matrix, f32) -> Result<Matrix>,
140        H: FnMut(&Matrix, &Matrix) -> Result<Matrix>
141{ fun2_for_f32_and_matrix_with_fun_refs(arg_values, err_msg, &mut f, &mut g, &mut rg, &mut h) }
142
143fn get_first_arg_string(arg_values: &[Value], err_msg: &str) -> Result<String>
144{
145    match arg_values.get(0) {
146        Some(arg_value) => {
147            match arg_value.to_opt_string() {
148                Some(s) => Ok(s),
149                None => Err(Error::Interp(String::from(err_msg))),
150            }
151        },
152        None => Err(Error::Interp(String::from("no argument"))),
153    }
154}
155
156/// A `type` built-in function.
157pub fn typ(_interp: &mut Interp, _env: &mut Env, arg_values: &[Value]) -> Result<Value>
158{
159    if arg_values.len() != 1 {
160        return Err(Error::Interp(String::from("invalid number of arguments")));
161    }
162    match arg_values.get(0) {
163        Some(Value::None) => Ok(Value::Object(Arc::new(Object::String(String::from("none"))))),
164        Some(Value::Bool(_)) => Ok(Value::Object(Arc::new(Object::String(String::from("bool"))))),
165        Some(Value::Int(_)) => Ok(Value::Object(Arc::new(Object::String(String::from("int"))))),
166        Some(Value::Float(_)) => Ok(Value::Object(Arc::new(Object::String(String::from("float"))))),
167        Some(Value::Object(object)) => {
168            match &**object {
169                Object::String(_) => Ok(Value::Object(Arc::new(Object::String(String::from("string"))))),
170                Object::IntRange(_, _, _) => Ok(Value::Object(Arc::new(Object::String(String::from("intrange"))))),
171                Object::FloatRange(_, _, _) => Ok(Value::Object(Arc::new(Object::String(String::from("floatrange"))))),
172                Object::Matrix(_) => Ok(Value::Object(Arc::new(Object::String(String::from("matrix"))))),
173                Object::Fun(_, _, _) | Object::BuiltinFun(_, _) => Ok(Value::Object(Arc::new(Object::String(String::from("function"))))),
174                Object::MatrixArray(_, _, _, _) => Ok(Value::Object(Arc::new(Object::String(String::from("matrixarray"))))),
175                Object::MatrixRowSlice(_, _) => Ok(Value::Object(Arc::new(Object::String(String::from("matrixrowslice"))))),
176                Object::Error(_, _) => Ok(Value::Object(Arc::new(Object::String(String::from("error"))))),
177                Object::WindowId(_) => Ok(Value::Object(Arc::new(Object::String(String::from("windowid"))))),
178            }
179        },
180        Some(Value::Ref(object)) => {
181            let object_g = rw_lock_read(object)?;
182            match &*object_g {
183                MutObject::Array(_) => Ok(Value::Object(Arc::new(Object::String(String::from("array"))))),
184                MutObject::Struct(_) => Ok(Value::Object(Arc::new(Object::String(String::from("struct"))))),
185            }
186        },
187        Some(Value::Weak(_)) => Ok(Value::Object(Arc::new(Object::String(String::from("weak"))))),
188        None => Err(Error::Interp(String::from("no argument"))),
189    }
190}
191
192/// A `clone` built-in function.
193pub fn clone(_interp: &mut Interp, _env: &mut Env, arg_values: &[Value]) -> Result<Value>
194{
195    if arg_values.len() != 1 {
196        return Err(Error::Interp(String::from("invalid number of arguments")));
197    }
198    match arg_values.get(0) {
199        Some(Value::Ref(object)) => {
200            let object_g = rw_lock_read(object)?;
201            Ok(Value::Ref(Arc::new(RwLock::new(object_g.clone()))))
202        },
203        Some(value) => Ok(value.clone()),
204        None => Err(Error::Interp(String::from("no argument"))),
205    }
206}
207
208/// A `bool` built-in function.
209pub fn boolean(_interp: &mut Interp, _env: &mut Env, arg_values: &[Value]) -> Result<Value>
210{ fun1(arg_values, |a| Ok(Value::Bool(a.to_bool()))) }
211
212/// An `int` built-in function.
213pub fn int(_interp: &mut Interp, _env: &mut Env, arg_values: &[Value]) -> Result<Value>
214{ fun1(arg_values, |a| Ok(Value::Int(a.to_i64()))) }
215
216/// A `float` built-in function.
217pub fn float(_interp: &mut Interp, _env: &mut Env, arg_values: &[Value]) -> Result<Value>
218{ fun1(arg_values, |a| Ok(Value::Float(a.to_f32()))) }
219
220/// A `string` built-in function.
221pub fn string(_interp: &mut Interp, _env: &mut Env, arg_values: &[Value]) -> Result<Value>
222{ fun1(arg_values, |a| Ok(Value::Object(Arc::new(Object::String(format!("{}", a)))))) }
223
224fn checked_mul_row_count_and_col_count(row_count: i64, col_count: i64) -> Result<usize>
225{
226    if row_count < 0 {
227        return Err(Error::Interp(String::from("number of rows is negative")));
228    }
229    if col_count < 0 {
230        return Err(Error::Interp(String::from("number of columns is negative")));
231    }
232    if row_count > (isize::MAX as i64) {
233        return Err(Error::Interp(String::from("too large number of rows")));
234    }
235    if col_count > (isize::MAX as i64) {
236        return Err(Error::Interp(String::from("too large number of columns")));
237    }
238    match row_count.checked_mul(col_count) {
239        Some(len) => {
240            if len > (isize::MAX as i64) {
241                return Err(Error::Interp(String::from("too large number of matrix elements")));
242            }
243            match (len as isize).checked_mul(size_of::<f32>() as isize) {
244                Some(_) => Ok(len as usize),
245                None => Err(Error::Interp(String::from("too large number of matrix elements"))),
246            }
247        },
248        None => Err(Error::Interp(String::from("too large number of matrix elements"))),
249    }
250}
251
252/// A `zeros` built-in function.
253pub fn zeros(_interp: &mut Interp, _env: &mut Env, arg_values: &[Value]) -> Result<Value>
254{
255    if arg_values.len() != 2 {
256        return Err(Error::Interp(String::from("invalid number of arguments")));
257    }
258    match (arg_values.get(0), arg_values.get(1)) {
259        (Some(n_value @ (Value::Int(_) | Value::Float(_))), Some(m_value @ (Value::Int(_) | Value::Float(_)))) => {
260            let n = n_value.to_i64();
261            let m = m_value.to_i64();
262            checked_mul_row_count_and_col_count(n, m)?;
263            Ok(Value::Object(Arc::new(Object::Matrix(matrix_create_and_set_zeros(n as usize, m as usize)?))))
264        },
265        (Some(_), Some(_)) => Err(Error::Interp(String::from("unsupported types for function zeros"))),
266        (_, _) => Err(Error::Interp(String::from("no argument"))),
267    }
268}
269
270/// An `ones` built-in function.
271pub fn ones(_interp: &mut Interp, _env: &mut Env, arg_values: &[Value]) -> Result<Value>
272{
273    if arg_values.len() != 2 {
274        return Err(Error::Interp(String::from("invalid number of arguments")));
275    }
276    match (arg_values.get(0), arg_values.get(1)) {
277        (Some(n_value @ (Value::Int(_) | Value::Float(_))), Some(m_value @ (Value::Int(_) | Value::Float(_)))) => {
278            let n = n_value.to_i64();
279            let m = m_value.to_i64();
280            let len = checked_mul_row_count_and_col_count(n, m)?;
281            let xs = vec![1.0f32; len];
282            Ok(Value::Object(Arc::new(Object::Matrix(matrix_create_and_set_elems(n as usize, m as usize, xs.as_slice())?))))
283        },
284        (Some(_), Some(_)) => Err(Error::Interp(String::from("unsupported types for function ones"))),
285        (_, _) => Err(Error::Interp(String::from("no argument"))),
286    }
287}
288
289/// An `eye` built-in function.
290pub fn eye(_interp: &mut Interp, _env: &mut Env, arg_values: &[Value]) -> Result<Value>
291{
292    if arg_values.len() != 1 {
293        return Err(Error::Interp(String::from("invalid number of arguments")));
294    }
295    match arg_values.get(0) {
296        Some(n_value @ (Value::Int(_) | Value::Float(_))) => {
297            let n = n_value.to_i64();
298            let len = checked_mul_row_count_and_col_count(n, n)?;
299            let mut xs = vec![0.0f32; len];
300            for i in 0..(n as usize) {
301                xs[i * (n as usize) + i] = 1.0;
302            }
303            Ok(Value::Object(Arc::new(Object::Matrix(matrix_create_and_set_elems(n as usize, n as usize, xs.as_slice())?))))
304        },
305        Some(_) => Err(Error::Interp(String::from("unsupported type for function eye"))),
306        None => Err(Error::Interp(String::from("no argument"))),
307    }
308}
309
310/// An `init` built-in function.
311pub fn init(interp: &mut Interp, env: &mut Env, arg_values: &[Value]) -> Result<Value>
312{
313    if arg_values.len() != 4 {
314        return Err(Error::Interp(String::from("invalid number of arguments")));
315    }
316    match (arg_values.get(0), arg_values.get(1), arg_values.get(2), arg_values.get(3)) {
317        (Some(n_value @ (Value::Int(_) | Value::Float(_))), Some(m_value @ (Value::Int(_) | Value::Float(_))), Some(data_value), Some(fun_value)) => {
318            let n = n_value.to_i64();
319            let m = m_value.to_i64();
320            let len = checked_mul_row_count_and_col_count(n, m)?;
321            let mut xs = vec![0.0f32; len];
322            for i in 0..(n as usize) {
323                for j in 0..(m as usize) {
324                    match fun_value.apply(interp, env, &[data_value.clone(), Value::Int((i + 1) as i64), Value::Int((j + 1) as i64)])?.to_opt_f32() {
325                        Some(x) => xs[i * (m as usize) + j] = x,
326                        None => return Err(Error::Interp(String::from("can't convert value to floating-point number"))),
327                    }
328                }
329            }
330            Ok(Value::Object(Arc::new(Object::Matrix(matrix_create_and_set_elems(n as usize, m as usize, xs.as_slice())?))))
331        },
332        (Some(_), Some(_), Some(_), Some(_)) => Err(Error::Interp(String::from("unsupported types for function init"))),
333        (_, _, _, _) => Err(Error::Interp(String::from("no argument"))),
334    }
335}
336
337/// An `initdiag` built-in function.
338pub fn initdiag(interp: &mut Interp, env: &mut Env, arg_values: &[Value]) -> Result<Value>
339{
340    if arg_values.len() != 3 {
341        return Err(Error::Interp(String::from("invalid number of arguments")));
342    }
343    match (arg_values.get(0), arg_values.get(1), arg_values.get(2)) {
344        (Some(n_value @ (Value::Int(_) | Value::Float(_))), Some(data_value), Some(fun_value)) => {
345            let n = n_value.to_i64();
346            let len = checked_mul_row_count_and_col_count(n, n)?;
347            let mut xs = vec![0.0f32; len];
348            for i in 0..(n as usize) {
349                match fun_value.apply(interp, env, &[data_value.clone(), Value::Int((i + 1) as i64)])?.to_opt_f32() {
350                    Some(x) => xs[i * (n as usize) + i] = x,
351                    None => return Err(Error::Interp(String::from("can't convert value to floating-point number"))),
352                }
353            }
354            Ok(Value::Object(Arc::new(Object::Matrix(matrix_create_and_set_elems(n as usize, n as usize, xs.as_slice())?))))
355        },
356        (Some(_), Some(_), Some(_)) => Err(Error::Interp(String::from("unsupported types for function init"))),
357        (_, _, _) => Err(Error::Interp(String::from("no argument"))),
358    }
359}
360
361fn to_row_or_column(value: &Value) -> Result<Vec<f32>>
362{
363    match value.iter()? {
364        Some(mut iter) => {
365            let mut xs: Vec<f32> = Vec::new();
366            loop {
367                match iter.next() {
368                    Some(Ok(elem)) => {
369                        match elem.to_opt_f32() {
370                            Some(x) => xs.push(x),
371                            None => return Err(Error::Interp(String::from("can't convert value to floating-point number"))),
372                        }
373                    },
374                    Some(Err(err)) => return Err(err),
375                    None => break,
376                }
377            }
378            Ok(xs)
379        },
380        None => Err(Error::Interp(String::from("value isn't iterable"))),
381    }
382}
383
384/// A `matrix` built-in function.
385pub fn matrix(_interp: &mut Interp, _env: &mut Env, arg_values: &[Value]) -> Result<Value>
386{
387    if arg_values.len() != 1 {
388        return Err(Error::Interp(String::from("invalid number of arguments")));
389    }
390    let value = match arg_values.get(0) {
391        Some(tmp_value @ Value::Object(object)) => {
392            match &**object {
393                Object::Matrix(_) => return Ok(tmp_value.clone()),
394                _ => tmp_value,
395            }
396        },
397        Some(tmp_value) => tmp_value,
398        None => return Err(Error::Interp(String::from("no argument"))),
399    };
400    match value.iter()? {
401        Some(mut iter) => {
402            let mut xs: Vec<f32> = Vec::new();
403            let mut row_count = 0usize;
404            let mut col_count: Option<usize> = None;
405            loop {
406                match iter.next() {
407                    Some(Ok(row_value)) => {
408                        let ys = to_row_or_column(&row_value)?;
409                        if col_count.map(|n| n == ys.len()).unwrap_or(true) {
410                            xs.extend_from_slice(ys.as_slice());
411                            col_count = Some(ys.len());
412                        } else {
413                            return Err(Error::Interp(String::from("numbers of columns of matrix rows aren't equal")));
414                        }
415                        match row_count.checked_add(1) {
416                            Some(new_row_count) => row_count = new_row_count,
417                            None => return Err(Error::Interp(String::from("too many matrix rows"))),
418                        }
419                    },
420                    Some(Err(err)) => return Err(err),
421                    None => break,
422                }
423            }
424            Ok(Value::Object(Arc::new(Object::Matrix(matrix_create_and_set_elems(row_count, col_count.unwrap_or(0), xs.as_slice())?))))
425        },
426        None => Err(Error::Interp(String::from("value isn't iterable"))),
427    }
428}
429
430/// A `rowvector` built-in function.
431pub fn rowvector(_interp: &mut Interp, _env: &mut Env, arg_values: &[Value]) -> Result<Value>
432{
433    if arg_values.len() != 1 {
434        return Err(Error::Interp(String::from("invalid number of arguments")));
435    }
436    let value = match arg_values.get(0) {
437        Some(tmp_value @ Value::Object(object)) => {
438            match &**object {
439                Object::Matrix(a) => {
440                    if a.row_count() == 1 {
441                        return Ok(tmp_value.clone());
442                    } else {
443                        return Err(Error::Interp(String::from("number of rows isn't one")));
444                    }
445                },
446                _ => tmp_value,
447            }
448        },
449        Some(tmp_value) => tmp_value,
450        None => return Err(Error::Interp(String::from("no argument"))),
451    };
452    let xs = to_row_or_column(&value)?;
453    Ok(Value::Object(Arc::new(Object::Matrix(matrix_create_and_set_elems(1, xs.len(), xs.as_slice())?))))
454}
455
456/// A `colvector` built-in function.
457pub fn colvector(_interp: &mut Interp, _env: &mut Env, arg_values: &[Value]) -> Result<Value>
458{
459    if arg_values.len() != 1 {
460        return Err(Error::Interp(String::from("invalid number of arguments")));
461    }
462    let value = match arg_values.get(0) {
463        Some(tmp_value @ Value::Object(object)) => {
464            match &**object {
465                Object::Matrix(a) => {
466                    if a.col_count() == 1 {
467                        return Ok(tmp_value.clone());
468                    } else {
469                        return Err(Error::Interp(String::from("number of columns isn't one")));
470                    }
471                },
472                _ => tmp_value,
473            }
474        },
475        Some(tmp_value) => tmp_value,
476        None => return Err(Error::Interp(String::from("no argument"))),
477    };
478    let xs = to_row_or_column(&value)?;
479    Ok(Value::Object(Arc::new(Object::Matrix(matrix_create_and_set_elems(xs.len(), 1, xs.as_slice())?))))
480}
481
482/// A `matrixarray` built-in function.
483pub fn matrixarray(_interp: &mut Interp, _env: &mut Env, arg_values: &[Value]) -> Result<Value>
484{ fun1(arg_values, Value::to_matrix_array) }
485
486/// An `error` built-in function.
487pub fn error(_interp: &mut Interp, _env: &mut Env, arg_values: &[Value]) -> Result<Value>
488{
489    if arg_values.len() != 2 {
490        return Err(Error::Interp(String::from("invalid number of arguments")));
491    }
492    match (arg_values.get(0), arg_values.get(1)) {
493        (Some(Value::Object(kind_object)), Some(Value::Object(msg_object))) => {
494            match (&**kind_object, &**msg_object) {
495                (Object::String(kind), Object::String(msg)) => Ok(Value::Object(Arc::new(Object::Error(kind.clone(), msg.clone())))),
496                (_, _) => Err(Error::Interp(String::from("unsupported types for function error"))),
497            }
498        },
499        (Some(_), Some(_)) => Err(Error::Interp(String::from("unsupported types for function error"))),
500        (_, _) => Err(Error::Interp(String::from("no argument"))),
501    }
502}
503
504/// An `array` built-in function.
505pub fn array(_interp: &mut Interp, _env: &mut Env, arg_values: &[Value]) -> Result<Value>
506{
507    if arg_values.len() != 1 {
508        return Err(Error::Interp(String::from("invalid number of arguments")));
509    }
510    let value = match arg_values.get(0) {
511        Some(tmp_value @ Value::Ref(object)) => {
512            let object_g = rw_lock_read(object)?;
513            match &*object_g {
514                MutObject::Array(_) => return Ok(tmp_value.clone()),
515                _ => tmp_value,
516            }
517        },
518        Some(tmp_value) => tmp_value,
519        None => return Err(Error::Interp(String::from("no argument"))),
520    };
521    match value.iter()? {
522        Some(mut iter) => {
523            let mut elems: Vec<Value> = Vec::new();
524            loop {
525                match iter.next() {
526                    Some(Ok(elem)) => elems.push(elem),
527                    Some(Err(err)) => return Err(err),
528                    None => break,
529                }
530            }
531            Ok(Value::Ref(Arc::new(RwLock::new(MutObject::Array(elems)))))
532        },
533        None => Err(Error::Interp(String::from("value isn't iterable"))),
534    }
535}
536
537/// A `strong` built-in function.
538pub fn strong(_interp: &mut Interp, _env: &mut Env, arg_values: &[Value]) -> Result<Value>
539{
540    if arg_values.len() != 1 {
541        return Err(Error::Interp(String::from("invalid number of arguments")));
542    }
543    match arg_values.get(0) {
544        Some(value @ Value::Ref(_)) => Ok(value.clone()),
545        Some(Value::Weak(object)) => {
546            match object.upgrade() {
547                Some(object) => Ok(Value::Ref(object)),
548                None => Ok(Value::None),
549            }
550        },
551        Some(_) => Err(Error::Interp(String::from("unsupported types for function strong"))),
552        None => Err(Error::Interp(String::from("no argument"))),
553    }
554}
555
556/// A `weak` built-in function.
557pub fn weak(_interp: &mut Interp, _env: &mut Env, arg_values: &[Value]) -> Result<Value>
558{
559    if arg_values.len() > 1 {
560        return Err(Error::Interp(String::from("invalid number of arguments")));
561    }
562    match arg_values.get(0) {
563        Some(Value::Ref(object)) => Ok(Value::Weak(Arc::downgrade(object))),
564        Some(value @ Value::Weak(_)) => Ok(value.clone()),
565        Some(_) => Err(Error::Interp(String::from("unsupported types for function weak"))),
566        None => Ok(Value::Weak(Weak::new())),
567    }
568}
569
570/// An `isempty` built-in function.
571pub fn isempty(_interp: &mut Interp, _env: &mut Env, arg_values: &[Value]) -> Result<Value>
572{
573    if arg_values.len() != 1 {
574        return Err(Error::Interp(String::from("invalid number of arguments")));
575    }
576    match arg_values.get(0) {
577        Some(Value::Object(object)) => {
578            match &**object {
579                Object::String(s) => Ok(Value::Bool(s.is_empty())),
580                Object::MatrixArray(row_count, _, _, _) => Ok(Value::Bool(*row_count == 0)),
581                Object::MatrixRowSlice(matrix_array, _) => {
582                    match &**matrix_array {
583                        Object::MatrixArray(_, col_count, _, _) => Ok(Value::Bool(*col_count == 0)),
584                        _ => Err(Error::Interp(String::from("invalid matrix array type"))),
585                    }
586                },
587                _ => Err(Error::Interp(String::from("unsupported type for function isempty"))),
588            }
589        },
590        Some(Value::Ref(object)) => {
591            let object_g = rw_lock_read(object)?;
592            match &*object_g {
593                MutObject::Array(elems) => Ok(Value::Bool(elems.is_empty())),
594                _ => Err(Error::Interp(String::from("unsupported type for function isempty"))),
595            }
596        },
597        Some(_) => Err(Error::Interp(String::from("unsupported type for function isempty"))),
598        None => Err(Error::Interp(String::from("no argument"))),
599    }
600}
601
602/// A `length` built-in function.
603pub fn length(_interp: &mut Interp, _env: &mut Env, arg_values: &[Value]) -> Result<Value>
604{
605    if arg_values.len() != 1 {
606        return Err(Error::Interp(String::from("invalid number of arguments")));
607    }
608    match arg_values.get(0) {
609        Some(Value::Object(object)) => {
610            match &**object {
611                Object::String(s) => Ok(Value::Int(s.chars().count() as i64)),
612                Object::MatrixArray(row_count, _, _, _) => Ok(Value::Int(*row_count as i64)),
613                Object::MatrixRowSlice(matrix_array, _) => {
614                    match &**matrix_array {
615                        Object::MatrixArray(_, col_count, _, _) => Ok(Value::Int(*col_count as i64)),
616                        _ => Err(Error::Interp(String::from("invalid matrix array type"))),
617                    }
618                },
619                _ => Err(Error::Interp(String::from("unsupported type for function length"))),
620            }
621        },
622        Some(Value::Ref(object)) => {
623            let object_g = rw_lock_read(object)?;
624            match &*object_g {
625                MutObject::Array(elems) => Ok(Value::Int(elems.len() as i64)),
626                _ => Err(Error::Interp(String::from("unsupported type for function length"))),
627            }
628        },
629        Some(_) => Err(Error::Interp(String::from("unsupported type for function length"))),
630        None => Err(Error::Interp(String::from("no argument"))),
631    }
632}
633
634/// A `rows` built-in function.
635pub fn rows(_interp: &mut Interp, _env: &mut Env, arg_values: &[Value]) -> Result<Value>
636{
637    if arg_values.len() != 1 {
638        return Err(Error::Interp(String::from("invalid number of arguments")));
639    }
640    match arg_values.get(0) {
641        Some(Value::Object(object)) => {
642            match &**object {
643                Object::Matrix(a) => Ok(Value::Int(a.row_count() as i64)),
644                Object::MatrixArray(row_count, _, _, _) => Ok(Value::Int(*row_count as i64)),
645                _ => Err(Error::Interp(String::from("unsupported type for function rows"))),
646            }
647        },
648        Some(_) => Err(Error::Interp(String::from("unsupported type for function rows"))),
649        None => Err(Error::Interp(String::from("no argument"))),
650    }
651}
652
653/// A `columns` built-in function.
654pub fn columns(_interp: &mut Interp, _env: &mut Env, arg_values: &[Value]) -> Result<Value>
655{
656    if arg_values.len() != 1 {
657        return Err(Error::Interp(String::from("invalid number of arguments")));
658    }
659    match arg_values.get(0) {
660        Some(Value::Object(object)) => {
661            match &**object {
662                Object::Matrix(a) => Ok(Value::Int(a.col_count() as i64)),
663                Object::MatrixArray(_, col_count, _, _) => Ok(Value::Int(*col_count as i64)),
664                Object::MatrixRowSlice(matrix_array, _) => {
665                    match &**matrix_array {
666                        Object::MatrixArray(_, col_count, _, _) => Ok(Value::Int(*col_count as i64)),
667                        _ => Err(Error::Interp(String::from("invalid matrix array type"))),
668                    }
669                },
670                _ => Err(Error::Interp(String::from("unsupported type for function columns"))),
671            }
672        },
673        Some(_) => Err(Error::Interp(String::from("unsupported type for function columns"))),
674        None => Err(Error::Interp(String::from("no argument"))),
675    }
676}
677
678/// A `get` built-in function.
679pub fn get(_interp: &mut Interp, _env: &mut Env, arg_values: &[Value]) -> Result<Value>
680{
681    if arg_values.len() < 2 || arg_values.len() > 3 {
682        return Err(Error::Interp(String::from("invalid number of arguments")));
683    }
684    match (arg_values.get(0), arg_values.get(1), arg_values.get(2)) {
685        (Some(Value::Object(object)), Some(i_value @ (Value::Int(_) | Value::Float(_))), None)  => {
686            match &**object {
687                Object::String(s) => {
688                    let i = i_value.to_i64();
689                    if i < 1 || i > (s.chars().count() as i64) {
690                        return Ok(Value::None);
691                    }
692                    match s.chars().nth((i - 1) as usize) {
693                        Some(c) => {
694                            let mut t = String::new();
695                            t.push(c);
696                            Ok(Value::Object(Arc::new(Object::String(t))))
697                        }
698                        None => Ok(Value::None),
699                    }
700                },
701                Object::MatrixArray(row_count, _, _, _) => {
702                    let i = i_value.to_i64();
703                    if i < 1 || i > (*row_count as i64) {
704                        return Ok(Value::None);
705                    }
706                    Ok(Value::Object(Arc::new(Object::MatrixRowSlice(object.clone(), (i - 1) as usize))))
707                },
708                Object::MatrixRowSlice(matrix_array, i) => {
709                    let j = i_value.to_i64();
710                    match &**matrix_array {
711                        Object::MatrixArray(row_count, col_count, transpose_flag, xs) => {
712                            if j < 1 || j > (*col_count as i64) {
713                                return Ok(Value::None);
714                            }
715                            let k = match transpose_flag {
716                                TransposeFlag::NoTranspose => i * (*col_count) + ((j - 1) as usize),
717                                TransposeFlag::Transpose => ((j - 1) as usize) * (*row_count) + i,
718                            };
719                            Ok(xs.get(k).map(|x| Value::Float(*x)).unwrap_or(Value::None))
720                        },
721                        _ => Err(Error::Interp(String::from("invalid matrix array type"))),
722                    }
723                },
724                _ => Err(Error::Interp(String::from("unsupported types for function get"))),
725            }
726        },
727        (Some(Value::Ref(object)), Some(i_value @ (Value::Int(_) | Value::Float(_) | Value::Object(_))), None)  => {
728            let object_g = rw_lock_read(&**object)?;
729            match &*object_g {
730                MutObject::Array(elems) => {
731                    match i_value {
732                        Value::Int(_) | Value::Float(_) => {
733                            let i = i_value.to_i64();
734                            if i < 1 || i > (elems.len() as i64) {
735                                return Ok(Value::None);
736                            }
737                            Ok(elems.get((i - 1) as usize).map(|x| x.clone()).unwrap_or(Value::None))
738                        },
739                        _ => Err(Error::Interp(String::from("unsupported types for function get"))),
740                    }
741                },
742                MutObject::Struct(fields) => {
743                    match i_value {
744                        Value::Object(i_object) => {
745                            match &**i_object {
746                                Object::String(ident) => Ok(fields.get(ident).map(|x| x.clone()).unwrap_or(Value::None)),
747                                _ => Err(Error::Interp(String::from("unsupported types for function get"))),
748                            }
749                        },
750                        _ => Err(Error::Interp(String::from("unsupported types for function get"))),
751                    }
752                },
753            }
754        },
755        (Some(Value::Object(object)), Some(i_value @ (Value::Int(_) | Value::Float(_))), Some(j_value @ (Value::Int(_) | Value::Float(_))))  => {
756            match &**object {
757                Object::MatrixArray(row_count, col_count, transpose_flag, xs) => {
758                    let i = i_value.to_i64();
759                    let j = j_value.to_i64();
760                    if i < 1 || i > (*row_count as i64) {
761                        return Ok(Value::None);
762                    }
763                    if j < 1 || j > (*col_count as i64) {
764                        return Ok(Value::None);
765                    }
766                    let k = match transpose_flag {
767                        TransposeFlag::NoTranspose => ((i - 1) as usize) * (*col_count) + ((j - 1) as usize),
768                        TransposeFlag::Transpose => ((j - 1) as usize) * (*row_count) + ((i - 1) as usize),
769                    };
770                    Ok(xs.get(k).map(|x| Value::Float(*x)).unwrap_or(Value::None))
771                },
772                _ => Err(Error::Interp(String::from("unsupported types for function get"))),
773            }
774        },
775        (Some(_), Some(_), _)  => Err(Error::Interp(String::from("unsupported types for function get"))),
776        (_, _, _) => Err(Error::Interp(String::from("no argument")))
777    }
778}
779
780/// A `getdiag` built-in function.
781pub fn getdiag(_interp: &mut Interp, _env: &mut Env, arg_values: &[Value]) -> Result<Value>
782{
783    if arg_values.len() != 2 {
784        return Err(Error::Interp(String::from("invalid number of arguments")));
785    }
786    match (arg_values.get(0), arg_values.get(1)) {
787        (Some(Value::Object(object)), Some(i_value @ (Value::Int(_) | Value::Float(_))))  => {
788            match &**object {
789                Object::MatrixArray(row_count, col_count, _, xs) => {
790                    if *row_count != *col_count {
791                        return Err(Error::Interp(String::from("number of rows isn't equal to number of columns")));
792                    }
793                    let i = i_value.to_i64();
794                    if i < 1 || i > (*row_count as i64) {
795                        return Ok(Value::None);
796                    }
797                    let k = ((i - 1) as usize) * (*col_count) + ((i - 1) as usize);
798                    Ok(xs.get(k).map(|x| Value::Float(*x)).unwrap_or(Value::None))
799                },
800                _ => Err(Error::Interp(String::from("unsupported type for function getdiag"))),
801            }
802        },
803        (Some(_), Some(_))  => Err(Error::Interp(String::from("unsupported types for function getdiag"))),
804        (_, _) => Err(Error::Interp(String::from("no argument")))
805    }
806}
807
808/// A `split` built-in function.
809pub fn split(_interp: &mut Interp, _env: &mut Env, arg_values: &[Value]) -> Result<Value>
810{
811    if arg_values.len() < 1 || arg_values.len() > 2 {
812        return Err(Error::Interp(String::from("invalid number of arguments")));
813    }
814    match (arg_values.get(0), arg_values.get(1)) {
815        (Some(Value::Object(object)), None) => {
816            match &**object {
817                Object::String(s) => {
818                    let ss = s.split_whitespace();
819                    let elems: Vec<Value> = ss.map(|t| Value::Object(Arc::new(Object::String(String::from(t))))).collect();
820                    Ok(Value::Ref(Arc::new(RwLock::new(MutObject::Array(elems)))))
821                },
822                _ => Err(Error::Interp(String::from("unsupported type for function split"))),
823            }
824        },
825        (Some(Value::Object(object)), Some(Value::Object(object2))) => {
826            match (&**object, &**object2) {
827                (Object::String(s), Object::String(t)) => {
828                    let ss = s.split(t.as_str());
829                    let elems: Vec<Value> = ss.map(|u| Value::Object(Arc::new(Object::String(String::from(u))))).collect();
830                    Ok(Value::Ref(Arc::new(RwLock::new(MutObject::Array(elems)))))
831                },
832                (_, _) => Err(Error::Interp(String::from("unsupported types for function split"))),
833            }
834        },
835        (Some(_), None) => Err(Error::Interp(String::from("unsupported type for function split"))),
836        (Some(_), Some(_)) => Err(Error::Interp(String::from("unsupported types for function split"))),
837        (_, _) => Err(Error::Interp(String::from("no argument"))),
838    }
839}
840
841/// A `trim` built-in function.
842pub fn trim(_interp: &mut Interp, _env: &mut Env, arg_values: &[Value]) -> Result<Value>
843{
844    if arg_values.len() != 1 {
845        return Err(Error::Interp(String::from("invalid number of arguments")));
846    }
847    match arg_values.get(0) {
848        Some(Value::Object(object)) => {
849            match &**object {
850                Object::String(s) => Ok(Value::Object(Arc::new(Object::String(String::from(s.trim()))))),
851                _ => Err(Error::Interp(String::from("unsupported type for function trim"))),
852            }
853        },
854        Some(_) => Err(Error::Interp(String::from("unsupported type for function trim"))),
855        None => Err(Error::Interp(String::from("no argument"))),
856    }
857}
858
859/// A `contains` built-in function.
860pub fn contains(_interp: &mut Interp, _env: &mut Env, arg_values: &[Value]) -> Result<Value>
861{
862    if arg_values.len() != 2 {
863        return Err(Error::Interp(String::from("invalid number of arguments")));
864    }
865    match (arg_values.get(0), arg_values.get(1)) {
866        (Some(Value::Object(object)), Some(Value::Object(object2))) => {
867            match (&**object, &**object2) {
868                (Object::String(s), Object::String(t)) => Ok(Value::Bool(s.contains(t.as_str()))),
869                (_, _) => Err(Error::Interp(String::from("unsupported types for function contains"))),
870            }
871        },
872        (Some(_), Some(_)) => Err(Error::Interp(String::from("unsupported types for function contains"))),
873        (_, _) => Err(Error::Interp(String::from("no argument"))),
874    }
875}
876
877/// A `startswith` built-in function.
878pub fn startswith(_interp: &mut Interp, _env: &mut Env, arg_values: &[Value]) -> Result<Value>
879{
880    if arg_values.len() != 2 {
881        return Err(Error::Interp(String::from("invalid number of arguments")));
882    }
883    match (arg_values.get(0), arg_values.get(1)) {
884        (Some(Value::Object(object)), Some(Value::Object(object2))) => {
885            match (&**object, &**object2) {
886                (Object::String(s), Object::String(t)) => Ok(Value::Bool(s.starts_with(t.as_str()))),
887                (_, _) => Err(Error::Interp(String::from("unsupported types for function startswith"))),
888            }
889        },
890        (Some(_), Some(_)) => Err(Error::Interp(String::from("unsupported types for function startswith"))),
891        (_, _) => Err(Error::Interp(String::from("no argument"))),
892    }
893}
894
895/// An `endswith` built-in function.
896pub fn endswith(_interp: &mut Interp, _env: &mut Env, arg_values: &[Value]) -> Result<Value>
897{
898    if arg_values.len() != 2 {
899        return Err(Error::Interp(String::from("invalid number of arguments")));
900    }
901    match (arg_values.get(0), arg_values.get(1)) {
902        (Some(Value::Object(object)), Some(Value::Object(object2))) => {
903            match (&**object, &**object2) {
904                (Object::String(s), Object::String(t)) => Ok(Value::Bool(s.ends_with(t.as_str()))),
905                (_, _) => Err(Error::Interp(String::from("unsupported types for function endswith"))),
906            }
907        },
908        (Some(_), Some(_)) => Err(Error::Interp(String::from("unsupported types for function endswith"))),
909        (_, _) => Err(Error::Interp(String::from("no argument"))),
910    }
911}
912
913/// A `replace` built-in function.
914pub fn replace(_interp: &mut Interp, _env: &mut Env, arg_values: &[Value]) -> Result<Value>
915{
916    if arg_values.len() != 3 {
917        return Err(Error::Interp(String::from("invalid number of arguments")));
918    }
919    match (arg_values.get(0), arg_values.get(1), arg_values.get(2)) {
920        (Some(Value::Object(object)), Some(Value::Object(object2)), Some(Value::Object(object3))) => {
921            match (&**object, &**object2, &**object3) {
922                (Object::String(s), Object::String(t), Object::String(u)) => Ok(Value::Object(Arc::new(Object::String(s.replace(t.as_str(), u.as_str()))))),
923                (_, _, _) => Err(Error::Interp(String::from("unsupported types for function replace"))),
924            }
925        },
926        (Some(_), Some(_), Some(_)) => Err(Error::Interp(String::from("unsupported types for function replace"))),
927        (_, _, _) => Err(Error::Interp(String::from("no argument"))),
928    }
929}
930
931/// An `upper` built-in function.
932pub fn upper(_interp: &mut Interp, _env: &mut Env, arg_values: &[Value]) -> Result<Value>
933{
934    if arg_values.len() != 1 {
935        return Err(Error::Interp(String::from("invalid number of arguments")));
936    }
937    match arg_values.get(0) {
938        Some(Value::Object(object)) => {
939            match &**object {
940                Object::String(s) => Ok(Value::Object(Arc::new(Object::String(s.to_uppercase())))),
941                _ => Err(Error::Interp(String::from("unsupported type for function upper"))),
942            }
943        },
944        Some(_) => Err(Error::Interp(String::from("unsupported type for function upper"))),
945        None => Err(Error::Interp(String::from("no argument"))),
946    }
947}
948
949/// A `lower` built-in function.
950pub fn lower(_interp: &mut Interp, _env: &mut Env, arg_values: &[Value]) -> Result<Value>
951{
952    if arg_values.len() != 1 {
953        return Err(Error::Interp(String::from("invalid number of arguments")));
954    }
955    match arg_values.get(0) {
956        Some(Value::Object(object)) => {
957            match &**object {
958                Object::String(s) => Ok(Value::Object(Arc::new(Object::String(s.to_lowercase())))),
959                _ => Err(Error::Interp(String::from("unsupported type for function lower"))),
960            }
961        },
962        Some(_) => Err(Error::Interp(String::from("unsupported type for function lower"))),
963        None => Err(Error::Interp(String::from("no argument"))),
964    }
965}
966
967#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
968enum SortType
969{
970    Bool,
971    Number,
972    String,
973    Incomparable,
974}
975
976/// A `sort` built-in function.
977pub fn sort(_interp: &mut Interp, _env: &mut Env, arg_values: &[Value]) -> Result<Value>
978{
979    if arg_values.len() != 1 {
980        return Err(Error::Interp(String::from("invalid number of arguments")));
981    }
982    match arg_values.get(0) {
983        Some(Value::Ref(object)) => {
984            let mut object_g = rw_lock_write(object)?;
985            match &mut *object_g {
986                MutObject::Array(elems) => {
987                    let mut sort_type: Option<SortType> = None;
988                    for elem in &*elems {
989                        let new_sort_type = match elem {
990                            Value::Bool(_) => SortType::Bool,
991                            Value::Int(_) => SortType::Number,
992                            Value::Float(n) => if !n.is_nan() { SortType::Number } else { SortType::Incomparable },
993                            Value::Object(elem_object) => {
994                                match &**elem_object {
995                                    Object::String(_) => SortType::String,
996                                    _ => SortType::Incomparable,
997                                }
998                            },
999                            _ => SortType::Incomparable,
1000                       };
1001                       if sort_type.map(|t| t == new_sort_type).unwrap_or(true) {
1002                           sort_type = Some(new_sort_type);
1003                       } else {
1004                           return Err(Error::Interp(String::from("array has elements which can't be compared")));
1005                       }
1006                    }
1007                    match sort_type {
1008                        Some(SortType::Incomparable) => return Err(Error::Interp(String::from("array has incomparable elements"))),
1009                        _ => (),
1010                    }
1011                    elems.sort_by(|x, y| x.partial_cmp(y).unwrap());
1012                    Ok(Value::None)
1013                },
1014                _ => Err(Error::Interp(String::from("unsupported type for function sort"))),
1015            }
1016        },
1017        Some(_) => Err(Error::Interp(String::from("unsupported type for function sort"))),
1018        None => Err(Error::Interp(String::from("no argument"))),
1019    }
1020}
1021
1022/// A `reverse` built-in function.
1023pub fn reverse(_interp: &mut Interp, _env: &mut Env, arg_values: &[Value]) -> Result<Value>
1024{
1025    if arg_values.len() != 1 {
1026        return Err(Error::Interp(String::from("invalid number of arguments")));
1027    }
1028    match arg_values.get(0) {
1029        Some(Value::Ref(object)) => {
1030            let mut object_g = rw_lock_write(object)?;
1031            match &mut *object_g {
1032                MutObject::Array(elems) => {
1033                    elems.reverse();
1034                    Ok(Value::None)
1035                },
1036                _ => Err(Error::Interp(String::from("unsupported type for function reverse"))),
1037            }
1038        },
1039        Some(_) => Err(Error::Interp(String::from("unsupported type for function reverse"))),
1040        None => Err(Error::Interp(String::from("no argument"))),
1041    }
1042}
1043
1044/// An `any` built-in function.
1045pub fn any(interp: &mut Interp, env: &mut Env, arg_values: &[Value]) -> Result<Value>
1046{
1047    if arg_values.len() != 3 {
1048        return Err(Error::Interp(String::from("invalid number of arguments")));
1049    }
1050    match (arg_values.get(0), arg_values.get(1), arg_values.get(2)) {
1051        (Some(a_value), Some(data_value), Some(fun_value)) => {
1052            match a_value.iter()? {
1053                Some(mut iter) => {
1054                    loop {
1055                        match iter.next() {
1056                            Some(Ok(elem)) => {
1057                                if fun_value.apply(interp, env, &[data_value.clone(), elem])?.to_bool() {
1058                                    return Ok(Value::Bool(true));
1059                                }
1060                            },
1061                            Some(Err(err)) => return Err(err),
1062                            None => break,
1063                        }
1064                    }
1065                    Ok(Value::Bool(false))
1066                },
1067                None => Err(Error::Interp(String::from("value isn't iterable"))),
1068            }
1069        },
1070        (_, _, _) => Err(Error::Interp(String::from("no argument"))),
1071    }
1072}
1073
1074/// An `all` built-in function.
1075pub fn all(interp: &mut Interp, env: &mut Env, arg_values: &[Value]) -> Result<Value>
1076{
1077    if arg_values.len() != 3 {
1078        return Err(Error::Interp(String::from("invalid number of arguments")));
1079    }
1080    match (arg_values.get(0), arg_values.get(1), arg_values.get(2)) {
1081        (Some(a_value), Some(data_value), Some(fun_value)) => {
1082            match a_value.iter()? {
1083                Some(mut iter) => {
1084                    loop {
1085                        match iter.next() {
1086                            Some(Ok(elem)) => {
1087                                if !fun_value.apply(interp, env, &[data_value.clone(), elem])?.to_bool() {
1088                                    return Ok(Value::Bool(false));
1089                                }
1090                            },
1091                            Some(Err(err)) => return Err(err),
1092                            None => break,
1093                        }
1094                    }
1095                    Ok(Value::Bool(true))
1096                },
1097                None => Err(Error::Interp(String::from("value isn't iterable"))),
1098            }
1099        },
1100        (_, _, _) => Err(Error::Interp(String::from("no argument"))),
1101    }
1102}
1103
1104/// A `find` built-in function.
1105pub fn find(interp: &mut Interp, env: &mut Env, arg_values: &[Value]) -> Result<Value>
1106{
1107    if arg_values.len() != 3 {
1108        return Err(Error::Interp(String::from("invalid number of arguments")));
1109    }
1110    match (arg_values.get(0), arg_values.get(1), arg_values.get(2)) {
1111        (Some(a_value), Some(data_value), Some(fun_value)) => {
1112            match a_value.iter()? {
1113                Some(mut iter) => {
1114                    let mut i = 1i64;
1115                    loop {
1116                        match iter.next() {
1117                            Some(Ok(elem)) => {
1118                                if fun_value.apply(interp, env, &[data_value.clone(), elem])?.to_bool() {
1119                                    return Ok(Value::Int(i));
1120                                }
1121                                match i.checked_add(1) {
1122                                    Some(j) => i = j,
1123                                    None => return Err(Error::Interp(String::from("too large index"))),
1124                                }
1125                            },
1126                            Some(Err(err)) => return Err(err),
1127                            None => break,
1128                        }
1129                    }
1130                    Ok(Value::None)
1131                },
1132                None => Err(Error::Interp(String::from("value isn't iterable"))),
1133            }
1134        },
1135        (_, _, _) => Err(Error::Interp(String::from("no argument"))),
1136    }
1137}
1138
1139/// A `filter` built-in function.
1140pub fn filter(interp: &mut Interp, env: &mut Env, arg_values: &[Value]) -> Result<Value>
1141{
1142    if arg_values.len() != 3 {
1143        return Err(Error::Interp(String::from("invalid number of arguments")));
1144    }
1145    match (arg_values.get(0), arg_values.get(1), arg_values.get(2)) {
1146        (Some(a_value), Some(data_value), Some(fun_value)) => {
1147            match a_value.iter()? {
1148                Some(mut iter) => {
1149                    let mut i_values: Vec<Value> = Vec::new();
1150                    let mut i = 1i64;
1151                    loop {
1152                        match iter.next() {
1153                            Some(Ok(elem)) => {
1154                                if fun_value.apply(interp, env, &[data_value.clone(), elem])?.to_bool() {
1155                                    i_values.push(Value::Int(i));
1156                                }
1157                                match i.checked_add(1) {
1158                                    Some(j) => i = j,
1159                                    None => return Err(Error::Interp(String::from("too large index"))),
1160                                }
1161                            },
1162                            Some(Err(err)) => return Err(err),
1163                            None => break,
1164                        }
1165                    }
1166                    Ok(Value::Ref(Arc::new(RwLock::new(MutObject::Array(i_values)))))
1167                },
1168                None => Err(Error::Interp(String::from("value isn't iterable"))),
1169            }
1170        },
1171        (_, _, _) => Err(Error::Interp(String::from("no argument"))),
1172    }
1173}
1174
1175/// A `max` built-in function.
1176pub fn max(interp: &mut Interp, env: &mut Env, arg_values: &[Value]) -> Result<Value>
1177{
1178    if arg_values.len() < 1 || arg_values.len() > 2 {
1179        return Err(Error::Interp(String::from("invalid number of arguments")));
1180    }
1181    match (arg_values.get(0), arg_values.get(1)) {
1182        (Some(value), None) => {
1183            match value.iter()? {
1184                Some(mut iter) => {
1185                    let mut max_elem = Value::None;
1186                    loop {
1187                        match iter.next() {
1188                            Some(Ok(elem)) => {
1189                                match max_elem {
1190                                    Value::None => max_elem = elem,
1191                                    _ => {
1192                                        if elem > max_elem {
1193                                            max_elem = elem;
1194                                        }
1195                                    },
1196                                }
1197                            },
1198                            Some(Err(err)) => return Err(err),
1199                            None => break,
1200                        }
1201                    }
1202                    Ok(max_elem)
1203                },
1204                None => Err(Error::Interp(String::from("value isn't iterable"))),
1205            }
1206        },
1207        (Some(Value::Int(a)), Some(Value::Int(b))) => Ok(Value::Int((*a).max(*b))),
1208        (Some(value @ (Value::Int(_) | Value::Float(_))), Some(value2 @ (Value::Int(_) | Value::Float(_)))) => Ok(Value::Float(value.to_f32().max(value2.to_f32()))),
1209        (Some(Value::Object(object)), Some(value2 @ (Value::Int(_) | Value::Float(_)))) => {
1210            match &**object {
1211                Object::Matrix(a) => Ok(Value::Object(Arc::new(Object::Matrix(matrix_max_for_scalar(a, value2.to_f32())?)))),
1212                _ => Err(Error::Interp(String::from("unsupported types for function max"))),
1213            }
1214        },
1215        (Some(value @ (Value::Int(_) | Value::Float(_))), Some(Value::Object(object2))) => {
1216            match &**object2 {
1217                Object::Matrix(b) => Ok(Value::Object(Arc::new(Object::Matrix(matrix_max_for_scalar(b, value.to_f32())?)))),
1218                _ => Err(Error::Interp(String::from("unsupported types for function max"))),
1219            }
1220        },
1221        (Some(Value::Object(object)), Some(Value::Object(object2))) => {
1222            match (&**object, &**object2) {
1223                (Object::Matrix(a), Object::Matrix(b)) => Ok(Value::Object(Arc::new(Object::Matrix(matrix_max(a, b)?)))),
1224                _ => Err(Error::Interp(String::from("unsupported types for function max"))),
1225            }
1226        },
1227        (Some(value @ Value::Ref(_)), Some(value2 @ (Value::Int(_) | Value::Float(_)))) => value.dot1("unsupported types for function max", |a| max(interp, env, &[a.clone(), value2.clone()])),
1228        (Some(value @ (Value::Int(_) | Value::Float(_))), Some(value2 @ Value::Ref(_))) => value2.dot1("unsupported types for function max", |b| max(interp, env, &[value.clone(), b.clone()])),
1229        (Some(value), Some(value2)) => value.dot2(value2, "unsupported types for function max", |a, b| max(interp, env, &[a.clone(), b.clone()])),
1230        (_, _) => Err(Error::Interp(String::from("no argument"))),
1231    }
1232}
1233
1234/// A `min` built-in function.
1235pub fn min(interp: &mut Interp, env: &mut Env, arg_values: &[Value]) -> Result<Value>
1236{
1237    if arg_values.len() < 1 || arg_values.len() > 2 {
1238        return Err(Error::Interp(String::from("invalid number of arguments")));
1239    }
1240    match (arg_values.get(0), arg_values.get(1)) {
1241        (Some(value), None) => {
1242            match value.iter()? {
1243                Some(mut iter) => {
1244                    let mut min_elem = Value::None;
1245                    loop {
1246                        match iter.next() {
1247                            Some(Ok(elem)) => {
1248                                match min_elem {
1249                                    Value::None => min_elem = elem,
1250                                    _ => {
1251                                        if elem < min_elem {
1252                                            min_elem = elem;
1253                                        }
1254                                    },
1255                                }
1256                            },
1257                            Some(Err(err)) => return Err(err),
1258                            None => break,
1259                        }
1260                    }
1261                    Ok(min_elem)
1262                },
1263                None => Err(Error::Interp(String::from("value isn't iterable"))),
1264            }
1265        },
1266        (Some(Value::Int(a)), Some(Value::Int(b))) => Ok(Value::Int((*a).min(*b))),
1267        (Some(value @ (Value::Int(_) | Value::Float(_))), Some(value2 @ (Value::Int(_) | Value::Float(_)))) => Ok(Value::Float(value.to_f32().min(value2.to_f32()))),
1268        (Some(Value::Object(object)), Some(value2 @ (Value::Int(_) | Value::Float(_)))) => {
1269            match &**object {
1270                Object::Matrix(a) => Ok(Value::Object(Arc::new(Object::Matrix(matrix_min_for_scalar(a, value2.to_f32())?)))),
1271                _ => Err(Error::Interp(String::from("unsupported types for function min"))),
1272            }
1273        },
1274        (Some(value @ (Value::Int(_) | Value::Float(_))), Some(Value::Object(object2))) => {
1275            match &**object2 {
1276                Object::Matrix(b) => Ok(Value::Object(Arc::new(Object::Matrix(matrix_min_for_scalar(b, value.to_f32())?)))),
1277                _ => Err(Error::Interp(String::from("unsupported types for function min"))),
1278            }
1279        },
1280        (Some(Value::Object(object)), Some(Value::Object(object2))) => {
1281            match (&**object, &**object2) {
1282                (Object::Matrix(a), Object::Matrix(b)) => Ok(Value::Object(Arc::new(Object::Matrix(matrix_min(a, b)?)))),
1283                _ => Err(Error::Interp(String::from("unsupported types for function min"))),
1284            }
1285        },
1286        (Some(value @ Value::Ref(_)), Some(value2 @ (Value::Int(_) | Value::Float(_)))) => value.dot1("unsupported types for function min", |a| min(interp, env, &[a.clone(), value2.clone()])),
1287        (Some(value @ (Value::Int(_) | Value::Float(_))), Some(value2 @ Value::Ref(_))) => value2.dot1("unsupported types for function min", |b| min(interp, env, &[value.clone(), b.clone()])),
1288        (Some(value), Some(value2)) => value.dot2(value2, "unsupported types for function min", |a, b| min(interp, env, &[a.clone(), b.clone()])),
1289        (_, _) => Err(Error::Interp(String::from("no argument"))),
1290    }
1291}
1292
1293/// An `imax` built-in function.
1294pub fn imax(_interp: &mut Interp, _env: &mut Env, arg_values: &[Value]) -> Result<Value>
1295{
1296    if arg_values.len() != 1 {
1297        return Err(Error::Interp(String::from("invalid number of arguments")));
1298    }
1299    match arg_values.get(0) {
1300        Some(value) => {
1301            match value.iter()? {
1302                Some(mut iter) => {
1303                    let mut max_elem = Value::None;
1304                    let mut i: Option<i64> = None;
1305                    let mut j = 1i64;
1306                    loop {
1307                        match iter.next() {
1308                            Some(Ok(elem)) => {
1309                                match max_elem {
1310                                    Value::None => {
1311                                        max_elem = elem;
1312                                        i = Some(j);
1313                                    },
1314                                    _ => {
1315                                        if elem > max_elem {
1316                                            max_elem = elem;
1317                                            i = Some(j);
1318                                        }
1319                                    },
1320                                }
1321                                match j.checked_add(1) {
1322                                    Some(k) => j = k,
1323                                    None => return Err(Error::Interp(String::from("too large index"))),
1324                                }
1325                            },
1326                            Some(Err(err)) => return Err(err),
1327                            None => break,
1328                        }
1329                    }
1330                    Ok(i.map(|i| Value::Int(i)).unwrap_or(Value::None))
1331                },
1332                None => Err(Error::Interp(String::from("value isn't iterable"))),
1333            }
1334        },
1335        None => Err(Error::Interp(String::from("no argument"))),
1336    }
1337}
1338
1339/// An `imin` built-in function.
1340pub fn imin(_interp: &mut Interp, _env: &mut Env, arg_values: &[Value]) -> Result<Value>
1341{
1342    if arg_values.len() != 1 {
1343        return Err(Error::Interp(String::from("invalid number of arguments")));
1344    }
1345    match arg_values.get(0) {
1346        Some(value) => {
1347            match value.iter()? {
1348                Some(mut iter) => {
1349                    let mut min_elem = Value::None;
1350                    let mut i: Option<i64> = None;
1351                    let mut j = 1i64;
1352                    loop {
1353                        match iter.next() {
1354                            Some(Ok(elem)) => {
1355                                match min_elem {
1356                                    Value::None => {
1357                                        min_elem = elem;
1358                                        i = Some(j);
1359                                    },
1360                                    _ => {
1361                                        if elem < min_elem {
1362                                            min_elem = elem;
1363                                            i = Some(j);
1364                                        }
1365                                    },
1366                                }
1367                                match j.checked_add(1) {
1368                                    Some(k) => j = k,
1369                                    None => return Err(Error::Interp(String::from("too large index"))),
1370                                }
1371                            },
1372                            Some(Err(err)) => return Err(err),
1373                            None => break,
1374                        }
1375                    }
1376                    Ok(i.map(|i| Value::Int(i)).unwrap_or(Value::None))
1377                },
1378                None => Err(Error::Interp(String::from("value isn't iterable"))),
1379            }
1380        },
1381        None => Err(Error::Interp(String::from("no argument"))),
1382    }
1383}
1384
1385/// A `push` built-in function.
1386pub fn push(_interp: &mut Interp, _env: &mut Env, arg_values: &[Value]) -> Result<Value>
1387{
1388    if arg_values.len() != 2 {
1389        return Err(Error::Interp(String::from("invalid number of arguments")));
1390    }
1391    match (arg_values.get(0), arg_values.get(1)) {
1392        (Some(Value::Ref(a_object)), Some(value)) => {
1393            let mut a_object_g = rw_lock_write(a_object)?;
1394            match &mut *a_object_g {
1395                MutObject::Array(elems) => {
1396                    elems.push(value.clone());
1397                    Ok(Value::None)
1398                },
1399                _ => Err(Error::Interp(String::from("unsupported types for function push"))),
1400            }
1401        },
1402        (Some(_), Some(_)) => Err(Error::Interp(String::from("unsupported types for function push"))),
1403        (_, _) => Err(Error::Interp(String::from("no argument"))),
1404    }
1405}
1406
1407/// A `pop` built-in function.
1408pub fn pop(_interp: &mut Interp, _env: &mut Env, arg_values: &[Value]) -> Result<Value>
1409{
1410    if arg_values.len() != 1 {
1411        return Err(Error::Interp(String::from("invalid number of arguments")));
1412    }
1413    match arg_values.get(0) {
1414        Some(Value::Ref(a_object)) => {
1415            let mut a_object_g = rw_lock_write(a_object)?;
1416            match &mut *a_object_g {
1417                MutObject::Array(elems) => {
1418                    match elems.pop() {
1419                        Some(value) => Ok(value),
1420                        None => Ok(Value::None),
1421                    }
1422                },
1423                _ => Err(Error::Interp(String::from("unsupported type for function pop"))),
1424            }
1425        },
1426        Some(_) => Err(Error::Interp(String::from("unsupported type for function pop"))),
1427        None => Err(Error::Interp(String::from("no argument"))),
1428    }
1429}
1430
1431/// An `append` built-in function.
1432pub fn append(_interp: &mut Interp, _env: &mut Env, arg_values: &[Value]) -> Result<Value>
1433{
1434    if arg_values.len() != 2 {
1435        return Err(Error::Interp(String::from("invalid number of arguments")));
1436    }
1437    match (arg_values.get(0), arg_values.get(1)) {
1438        (Some(Value::Ref(a_object)), Some(Value::Ref(b_object))) => {
1439            if !Arc::ptr_eq(a_object, b_object) {
1440                let mut a_object_g = rw_lock_write(a_object)?;
1441                let b_object_g = rw_lock_read(b_object)?;
1442                match (&mut *a_object_g, &*b_object_g) {
1443                    (MutObject::Array(elems), MutObject::Array(elems2)) => {
1444                        elems.extend_from_slice(elems2.as_slice());
1445                        Ok(Value::None)
1446                    },
1447                    (MutObject::Struct(fields), MutObject::Struct(fields2)) => {
1448                        for (ident2, field2) in fields2 {
1449                            fields.insert(ident2.clone(), field2.clone());
1450                        }
1451                        Ok(Value::None)
1452                    },
1453                    (_, _) => Err(Error::Interp(String::from("unsupported types for function append"))),
1454                }
1455            } else {
1456                let mut a_object_g = rw_lock_write(a_object)?;
1457                match &mut *a_object_g {
1458                    MutObject::Array(elems) => {
1459                        let elems2 = elems.clone();
1460                        elems.extend_from_slice(elems2.as_slice());
1461                        Ok(Value::None)
1462                    },
1463                    MutObject::Struct(_) => Ok(Value::None),
1464                }
1465            }
1466        },
1467        (Some(_), Some(_)) => Err(Error::Interp(String::from("unsupported types for function append"))),
1468        (_, _) => Err(Error::Interp(String::from("no argument"))),
1469    }
1470}
1471
1472/// An `insert` built-in function.
1473pub fn insert(_interp: &mut Interp, _env: &mut Env, arg_values: &[Value]) -> Result<Value>
1474{
1475    if arg_values.len() != 3 {
1476        return Err(Error::Interp(String::from("invalid number of arguments")));
1477    }
1478    match (arg_values.get(0), arg_values.get(1), arg_values.get(2)) {
1479        (Some(Value::Ref(a_object)), Some(i_value @ (Value::Int(_) | Value::Float(_) | Value::Object(_))), Some(value)) => {
1480            let mut a_object_g = rw_lock_write(a_object)?;
1481            match &mut *a_object_g {
1482                MutObject::Array(elems) => {
1483                    match i_value {
1484                        Value::Int(_) | Value::Float(_) => {
1485                            let i = i_value.to_i64();
1486                            if i < 1 || i > (elems.len() as i64).saturating_add(1) {
1487                                return Err(Error::Interp(String::from("index out of bounds")));
1488                            }
1489                            elems.insert((i - 1) as usize, value.clone());
1490                            Ok(Value::None)
1491                        },
1492                        _ => Err(Error::Interp(String::from("unsupported types for function insert"))),
1493                    }
1494                },
1495                MutObject::Struct(fields) => {
1496                    match i_value {
1497                        Value::Object(i_object) => {
1498                            match &**i_object {
1499                                Object::String(ident) => Ok(fields.insert(ident.clone(), value.clone()).unwrap_or(Value::None)),
1500                                _ => Err(Error::Interp(String::from("unsupported types for function insert"))),
1501                            }
1502                        },
1503                        _ => Err(Error::Interp(String::from("unsupported types for function insert"))),
1504                    }
1505                },
1506            }
1507        },
1508        (Some(_), Some(_), Some(_)) => Err(Error::Interp(String::from("unsupported types for function insert"))),
1509        (_, _, _) => Err(Error::Interp(String::from("no argument"))),
1510    }
1511}
1512
1513/// A `remove` built-in function.
1514pub fn remove(_interp: &mut Interp, _env: &mut Env, arg_values: &[Value]) -> Result<Value>
1515{
1516    if arg_values.len() != 2 {
1517        return Err(Error::Interp(String::from("invalid number of arguments")));
1518    }
1519    match (arg_values.get(0), arg_values.get(1)) {
1520        (Some(Value::Ref(a_object)), Some(i_value @ (Value::Int(_) | Value::Float(_) | Value::Object(_)))) => {
1521            let mut a_object_g = rw_lock_write(a_object)?;
1522            match &mut *a_object_g {
1523                MutObject::Array(elems) => {
1524                    match i_value {
1525                        Value::Int(_) | Value::Float(_) => {
1526                            let i = i_value.to_i64();
1527                            if i < 1 || i > (elems.len() as i64) {
1528                                return Ok(Value::None);
1529                            }
1530                            Ok(elems.remove((i - 1) as usize))
1531                        },
1532                        _ => Err(Error::Interp(String::from("unsupported types for function remove"))),
1533                    }
1534                },
1535                MutObject::Struct(fields) => {
1536                    match i_value {
1537                        Value::Object(i_object) => {
1538                            match &**i_object {
1539                                Object::String(ident) => Ok(fields.remove(ident).unwrap_or(Value::None)),
1540                                _ => Err(Error::Interp(String::from("unsupported types for function remove"))),
1541                            }
1542                        },
1543                        _ => Err(Error::Interp(String::from("unsupported types for function remove"))),
1544                    }
1545                },
1546            }
1547        },
1548        (Some(_), Some(_)) => Err(Error::Interp(String::from("unsupported types for function remove"))),
1549        (_, _) => Err(Error::Interp(String::from("no argument"))),
1550    }
1551}
1552
1553/// An `errorkind` built-in function.
1554pub fn errorkind(_interp: &mut Interp, _env: &mut Env, arg_values: &[Value]) -> Result<Value>
1555{
1556    if arg_values.len() != 1 {
1557        return Err(Error::Interp(String::from("invalid number of arguments")));
1558    }
1559    match arg_values.get(0) {
1560        Some(Value::Object(object)) => {
1561            match &**object {
1562                Object::Error(kind, _) => Ok(Value::Object(Arc::new(Object::String(kind.clone())))),
1563                _ => Err(Error::Interp(String::from("unsupported type for function errorkind"))),
1564            }
1565        },
1566        Some(_) => Err(Error::Interp(String::from("unsupported type for function errorkind"))),
1567        None => Err(Error::Interp(String::from("no argument"))),
1568    }
1569}
1570
1571/// An `errormsg` built-in function.
1572pub fn errormsg(_interp: &mut Interp, _env: &mut Env, arg_values: &[Value]) -> Result<Value>
1573{
1574    if arg_values.len() != 1 {
1575        return Err(Error::Interp(String::from("invalid number of arguments")));
1576    }
1577    match arg_values.get(0) {
1578        Some(Value::Object(object)) => {
1579            match &**object {
1580                Object::Error(_, msg) => Ok(Value::Object(Arc::new(Object::String(msg.clone())))),
1581                _ => Err(Error::Interp(String::from("unsupported type for function errormsg"))),
1582            }
1583        },
1584        Some(_) => Err(Error::Interp(String::from("unsupported type for function errormsg"))),
1585        None => Err(Error::Interp(String::from("no argument"))),
1586    }
1587}
1588
1589/// An `isequal` built-in function.
1590pub fn isequal(_interp: &mut Interp, _env: &mut Env, arg_values: &[Value]) -> Result<Value>
1591{ fun2(arg_values, |a, b| Ok(Value::Bool(a.eq_without_types(b)?))) }
1592
1593/// An `isnotequal` built-in function.
1594pub fn isnotequal(_interp: &mut Interp, _env: &mut Env, arg_values: &[Value]) -> Result<Value>
1595{ fun2(arg_values, |a, b| Ok(Value::Bool(!a.eq_without_types(b)?))) }
1596
1597/// An `isless` built-in function.
1598pub fn isless(_interp: &mut Interp, _env: &mut Env, arg_values: &[Value]) -> Result<Value>
1599{ fun2(arg_values, |a, b| Ok(Value::Bool(a < b))) }
1600
1601/// An `isgreaterequal` built-in function.
1602pub fn isgreaterequal(_interp: &mut Interp, _env: &mut Env, arg_values: &[Value]) -> Result<Value>
1603{ fun2(arg_values, |a, b| Ok(Value::Bool(a >= b))) }
1604
1605/// An `isgreater` built-in function.
1606pub fn isgreater(_interp: &mut Interp, _env: &mut Env, arg_values: &[Value]) -> Result<Value>
1607{ fun2(arg_values, |a, b| Ok(Value::Bool(a > b))) }
1608
1609/// An `islessequal` built-in function.
1610pub fn islessequal(_interp: &mut Interp, _env: &mut Env, arg_values: &[Value]) -> Result<Value>
1611{ fun2(arg_values, |a, b| Ok(Value::Bool(a <= b))) }
1612
1613/// A `sigmoid` built-in function.
1614pub fn sigmoid(_interp: &mut Interp, _env: &mut Env, arg_values: &[Value]) -> Result<Value>
1615{ fun1_for_f32_and_matrix(arg_values, "unsupported type for function sigmoid", |a| 1.0 / (1.0 + (-a).exp()), matrix_sigmoid) }
1616
1617/// A `tanh` built-in function.
1618pub fn tanh(_interp: &mut Interp, _env: &mut Env, arg_values: &[Value]) -> Result<Value>
1619{ fun1_for_f32_and_matrix(arg_values, "unsupported type for function tanh", f32::tanh, matrix_tanh) }
1620
1621/// A `swish` built-in function.
1622pub fn swish(_interp: &mut Interp, _env: &mut Env, arg_values: &[Value]) -> Result<Value>
1623{ fun1_for_f32_and_matrix(arg_values, "unsupported type for function swish", |a| a / (1.0 + (-a).exp()), matrix_swish) }
1624
1625/// A `softmax` built-in function.
1626pub fn softmax(_interp: &mut Interp, _env: &mut Env, arg_values: &[Value]) -> Result<Value>
1627{
1628    if arg_values.len() != 1 {
1629        return Err(Error::Interp(String::from("invalid number of arguments")));
1630    }
1631    match arg_values.get(0) {
1632        Some(value @ (Value::Int(_) | Value::Float(_))) => Ok(Value::Float(value.to_f32().exp() / value.to_f32().exp())),
1633        Some(Value::Object(object)) => {
1634            match &**object {
1635                Object::Matrix(a) => Ok(Value::Object(Arc::new(Object::Matrix(matrix_softmax(a)?)))),
1636                _ => Err(Error::Interp(String::from("unsupported type for function softmax"))),
1637            }
1638        },
1639        Some(_) => Err(Error::Interp(String::from("unsupported type for function softmax"))),
1640        None => Err(Error::Interp(String::from("no argument"))),
1641    }
1642}
1643
1644/// A `sqrt` built-in function.
1645pub fn sqrt(_interp: &mut Interp, _env: &mut Env, arg_values: &[Value]) -> Result<Value>
1646{ fun1_for_f32_and_matrix(arg_values, "unsupported type for function sqrt", f32::sqrt, matrix_sqrt) }
1647
1648/// A `reallytranspose` built-in function.
1649pub fn reallytranspose(_interp: &mut Interp, _env: &mut Env, arg_values: &[Value]) -> Result<Value>
1650{
1651    if arg_values.len() != 1 {
1652        return Err(Error::Interp(String::from("invalid number of arguments")));
1653    }
1654    match arg_values.get(0) {
1655        Some(value @ (Value::Int(_) | Value::Float(_))) => Ok(value.clone()),
1656        Some(Value::Object(object)) => {
1657            match &**object {
1658                Object::Matrix(a) => Ok(Value::Object(Arc::new(Object::Matrix(matrix_really_transpose(a)?)))),
1659                _ => Err(Error::Interp(String::from("unsupported type for function reallytranspose"))),
1660            }
1661        },
1662        Some(_) => Err(Error::Interp(String::from("unsupported type for function reallytranspose"))),
1663        None => Err(Error::Interp(String::from("no argument"))),
1664    }
1665}
1666
1667/// A `repeat` built-in function.
1668pub fn repeat(_interp: &mut Interp, _env: &mut Env, arg_values: &[Value]) -> Result<Value>
1669{
1670    if arg_values.len() != 2 {
1671        return Err(Error::Interp(String::from("invalid number of arguments")));
1672    }
1673    match (arg_values.get(0), arg_values.get(1)) {
1674        (Some(Value::Object(object)), Some(n_value @ (Value::Int(_) | Value::Float(_)))) => {
1675            match &**object {
1676                Object::Matrix(a) => {
1677                    let n = n_value.to_i64();
1678                    let (m, l) = if a.col_count() == 1 {
1679                        (a.row_count() as i64, n) 
1680                    } else if a.row_count() == 1 {
1681                        (n, a.col_count() as i64)
1682                    } else {
1683                        return Err(Error::Interp(String::from("number of columns or rows isn't one")));
1684                    };
1685                    checked_mul_row_count_and_col_count(m, l)?;
1686                    match matrix_repeat(a, n as usize)? {
1687                        Some(b) => Ok(Value::Object(Arc::new(Object::Matrix(b)))),
1688                        None => return Err(Error::Interp(String::from("number of columns or rows isn't one"))),
1689                    }
1690                },
1691                _ => Err(Error::Interp(String::from("unsupported types for function repeat"))),
1692            }
1693        },
1694        (Some(_), Some(_)) => Err(Error::Interp(String::from("unsupported types for function repeat"))),
1695        (_, _) => Err(Error::Interp(String::from("no argument"))),
1696    }
1697}
1698
1699/// A `mod` built-in function.
1700pub fn modulo(_interp: &mut Interp, _env: &mut Env, arg_values: &[Value]) -> Result<Value>
1701{
1702    if arg_values.len() != 2 {
1703        return Err(Error::Interp(String::from("invalid number of arguments")));
1704    }
1705    match (arg_values.get(0), arg_values.get(1)) {
1706        (Some(Value::Int(a)), Some(Value::Int(b))) => {
1707            match a.checked_rem(*b) {
1708                Some(c) => Ok(Value::Int(c)),
1709                None => {
1710                    if *b == 0 {
1711                        Err(Error::Interp(String::from("division by zero")))
1712                    } else {
1713                        Err(Error::Interp(String::from("overflow in function mod")))
1714                    }
1715                },
1716            }
1717        },
1718        (Some(value @ (Value::Int(_) | Value::Float(_))), Some(value2 @ (Value::Int(_) | Value::Float(_)))) => Ok(Value::Float(value.to_f32() % value2.to_f32())),
1719        (Some(_), Some(_)) => Err(Error::Interp(String::from("unsupported types for function mod"))),
1720        (_, _) => Err(Error::Interp(String::from("no argument"))),
1721    }
1722}
1723
1724/// An `abs` built-in function.
1725pub fn abs(interp: &mut Interp, env: &mut Env, arg_values: &[Value]) -> Result<Value>
1726{
1727    if arg_values.len() != 1 {
1728        return Err(Error::Interp(String::from("invalid number of arguments")));
1729    }
1730    match arg_values.get(0) {
1731        Some(Value::Int(a)) => Ok(Value::Int(a.abs())),
1732        Some(Value::Float(a)) => Ok(Value::Float(a.abs())),
1733        Some(Value::Object(object)) => {
1734            match &**object {
1735                Object::Matrix(a) => Ok(Value::Object(Arc::new(Object::Matrix(matrix_abs(a)?)))),
1736                _ => Err(Error::Interp(String::from("unsupported type for function abs"))),
1737            }
1738        },
1739        Some(value) => value.dot1("unsupported type for function abs", |a| abs(interp, env, &[a.clone()])),
1740        None => Err(Error::Interp(String::from("no argument"))),
1741    }
1742}
1743
1744/// A `pow` built-in function.
1745pub fn pow(_interp: &mut Interp, _env: &mut Env, arg_values: &[Value]) -> Result<Value>
1746{ fun2_for_f32_and_matrix(arg_values, "unsupported types for function pow", f32::powf, matrix_pow_for_scalar, matrix_rpow_for_scalar, matrix_pow) }
1747
1748/// An `exp` built-in function.
1749pub fn exp(_interp: &mut Interp, _env: &mut Env, arg_values: &[Value]) -> Result<Value>
1750{ fun1_for_f32_and_matrix(arg_values, "unsupported type for function exp", f32::exp, matrix_exp) }
1751
1752/// A `log` built-in function.
1753pub fn log(_interp: &mut Interp, _env: &mut Env, arg_values: &[Value]) -> Result<Value>
1754{ fun1_for_f32_and_matrix(arg_values, "unsupported type for function log", f32::ln, matrix_ln) }
1755
1756/// A `log2` built-in function.
1757pub fn log2(_interp: &mut Interp, _env: &mut Env, arg_values: &[Value]) -> Result<Value>
1758{ fun1_for_f32_and_matrix(arg_values, "unsupported type for function log2", f32::log2, matrix_log2) }
1759
1760/// A `log10` built-in function.
1761pub fn log10(_interp: &mut Interp, _env: &mut Env, arg_values: &[Value]) -> Result<Value>
1762{ fun1_for_f32_and_matrix(arg_values, "unsupported type for function log10", f32::log10, matrix_log10) }
1763
1764/// A `sin` built-in function.
1765pub fn sin(_interp: &mut Interp, _env: &mut Env, arg_values: &[Value]) -> Result<Value>
1766{ fun1_for_f32_and_matrix(arg_values, "unsupported type for function sin", f32::sin, matrix_sin) }
1767
1768/// A `cos` built-in function.
1769pub fn cos(_interp: &mut Interp, _env: &mut Env, arg_values: &[Value]) -> Result<Value>
1770{ fun1_for_f32_and_matrix(arg_values, "unsupported type for function cos", f32::cos, matrix_cos) }
1771
1772/// A `tan` built-in function.
1773pub fn tan(_interp: &mut Interp, _env: &mut Env, arg_values: &[Value]) -> Result<Value>
1774{ fun1_for_f32_and_matrix(arg_values, "unsupported type for function tan", f32::tan, matrix_tan) }
1775
1776/// An `asin` built-in function.
1777pub fn asin(_interp: &mut Interp, _env: &mut Env, arg_values: &[Value]) -> Result<Value>
1778{ fun1_for_f32_and_matrix(arg_values, "unsupported type for function asin", f32::asin, matrix_asin) }
1779
1780/// An `acos` built-in function.
1781pub fn acos(_interp: &mut Interp, _env: &mut Env, arg_values: &[Value]) -> Result<Value>
1782{ fun1_for_f32_and_matrix(arg_values, "unsupported type for function acos", f32::acos, matrix_acos) }
1783
1784/// An `atan` built-in function.
1785pub fn atan(_interp: &mut Interp, _env: &mut Env, arg_values: &[Value]) -> Result<Value>
1786{ fun1_for_f32_and_matrix(arg_values, "unsupported type for function atan", f32::atan, matrix_atan) }
1787
1788/// An `atan2` built-in function.
1789pub fn atan2(_interp: &mut Interp, _env: &mut Env, arg_values: &[Value]) -> Result<Value>
1790{ fun2_for_f32_and_matrix(arg_values, "unsupported types for function atan2", f32::atan2, matrix_atan2_for_scalar, matrix_ratan2_for_scalar, matrix_atan2) }
1791
1792/// A `sinh` built-in function.
1793pub fn sinh(_interp: &mut Interp, _env: &mut Env, arg_values: &[Value]) -> Result<Value>
1794{ fun1_for_f32_and_matrix(arg_values, "unsupported type for function sinh", f32::sinh, matrix_sinh) }
1795
1796/// A `cosh` built-in function.
1797pub fn cosh(_interp: &mut Interp, _env: &mut Env, arg_values: &[Value]) -> Result<Value>
1798{ fun1_for_f32_and_matrix(arg_values, "unsupported type for function cosh", f32::cosh, matrix_cosh) }
1799
1800/// An `asinh` built-in function.
1801pub fn asinh(_interp: &mut Interp, _env: &mut Env, arg_values: &[Value]) -> Result<Value>
1802{ fun1_for_f32_and_matrix(arg_values, "unsupported type for function asinh", f32::asinh, matrix_asinh) }
1803
1804/// An `acosh` built-in function.
1805pub fn acosh(_interp: &mut Interp, _env: &mut Env, arg_values: &[Value]) -> Result<Value>
1806{ fun1_for_f32_and_matrix(arg_values, "unsupported type for function acosh", f32::acosh, matrix_acosh) }
1807
1808/// An `atanh` built-in function.
1809pub fn atanh(_interp: &mut Interp, _env: &mut Env, arg_values: &[Value]) -> Result<Value>
1810{ fun1_for_f32_and_matrix(arg_values, "unsupported type for function atanh", f32::atanh, matrix_atanh) }
1811
1812/// A `sign` built-in function.
1813pub fn sign(_interp: &mut Interp, _env: &mut Env, arg_values: &[Value]) -> Result<Value>
1814{ fun1_for_f32_and_matrix(arg_values, "unsupported type for function sign", f32::signum, matrix_signum) }
1815
1816/// A `ceil` built-in function.
1817pub fn ceil(_interp: &mut Interp, _env: &mut Env, arg_values: &[Value]) -> Result<Value>
1818{ fun1_for_f32_and_matrix(arg_values, "unsupported type for function ceil", f32::ceil, matrix_ceil) }
1819
1820/// A `floor` built-in function.
1821pub fn floor(_interp: &mut Interp, _env: &mut Env, arg_values: &[Value]) -> Result<Value>
1822{ fun1_for_f32_and_matrix(arg_values, "unsupported type for function floor", f32::floor, matrix_floor) }
1823
1824/// A `round` built-in function.
1825pub fn round(_interp: &mut Interp, _env: &mut Env, arg_values: &[Value]) -> Result<Value>
1826{ fun1_for_f32_and_matrix(arg_values, "unsupported type for function round", f32::round, matrix_round) }
1827
1828/// A `trunc` built-in function.
1829pub fn trunc(_interp: &mut Interp, _env: &mut Env, arg_values: &[Value]) -> Result<Value>
1830{ fun1_for_f32_and_matrix(arg_values, "unsupported type for function trunc", f32::trunc, matrix_trunc) }
1831
1832/// A `rand` built-in function.
1833pub fn rand(_interp: &mut Interp, _env: &mut Env, arg_values: &[Value]) -> Result<Value>
1834{
1835    if arg_values.len() != 0 {
1836        return Err(Error::Interp(String::from("invalid number of arguments")));
1837    }
1838    Ok(Value::Float(random()))
1839}
1840
1841/// A `randi` built-in function.
1842pub fn randi(_interp: &mut Interp, _env: &mut Env, arg_values: &[Value]) -> Result<Value>
1843{
1844    if arg_values.len() < 1 || arg_values.len() > 2 {
1845        return Err(Error::Interp(String::from("invalid number of arguments")));
1846    }
1847    match (arg_values.get(0), arg_values.get(1)) {
1848        (Some(max_value @ (Value::Int(_) | Value::Float(_))), None) => {
1849            let max = max_value.to_i64();
1850            Ok(Value::Int(random_range(1..=max)))
1851        }
1852        (Some(min_value @ (Value::Int(_) | Value::Float(_))), Some(max_value @ (Value::Int(_) | Value::Float(_)))) => {
1853            let min = min_value.to_i64();
1854            let max = max_value.to_i64();
1855            Ok(Value::Int(random_range(min..=max)))
1856        },
1857        (Some(_), None) => Err(Error::Interp(String::from("unsupported type for function randi"))),
1858        (Some(_), Some(_)) => Err(Error::Interp(String::from("unsupported types for function randi"))),
1859        (_, _) => Err(Error::Interp(String::from("no argument"))),
1860    }
1861}
1862
1863/// A `str2int` built-in function.
1864pub fn str2int(_interp: &mut Interp, _env: &mut Env, arg_values: &[Value]) -> Result<Value>
1865{
1866    if arg_values.len() != 1 {
1867        return Err(Error::Interp(String::from("invalid number of arguments")));
1868    }
1869    match arg_values.get(0) {
1870        Some(Value::Object(object)) => {
1871            match &**object {
1872                Object::String(s) => {
1873                    match s.parse::<i64>() {
1874                        Ok(n) => Ok(Value::Int(n)),
1875                        Err(err) => Ok(Value::Object(Arc::new(Object::Error(String::from("parseint"), format!("{}", err))))),
1876                    }
1877                },
1878                _ => Err(Error::Interp(String::from("unsupported type for function str2int"))),
1879            }
1880        },
1881        Some(_) => Err(Error::Interp(String::from("unsupported type for function str2int"))),
1882        None => Err(Error::Interp(String::from("no argument"))),
1883    }
1884}
1885
1886/// A `str2float` built-in function.
1887pub fn str2float(_interp: &mut Interp, _env: &mut Env, arg_values: &[Value]) -> Result<Value>
1888{
1889    if arg_values.len() != 1 {
1890        return Err(Error::Interp(String::from("invalid number of arguments")));
1891    }
1892    match arg_values.get(0) {
1893        Some(Value::Object(object)) => {
1894            match &**object {
1895                Object::String(s) => {
1896                    match s.parse::<f32>() {
1897                        Ok(n) => Ok(Value::Float(n)),
1898                        Err(err) => Ok(Value::Object(Arc::new(Object::Error(String::from("parsefloat"), format!("{}", err))))),
1899                    }
1900                },
1901                _ => Err(Error::Interp(String::from("unsupported type for function str2float"))),
1902            }
1903        },
1904        Some(_) => Err(Error::Interp(String::from("unsupported type for function str2float"))),
1905        None => Err(Error::Interp(String::from("no argument"))),
1906    }
1907}
1908
1909/// A `hex2dec` built-in function.
1910pub fn hex2dec(_interp: &mut Interp, _env: &mut Env, arg_values: &[Value]) -> Result<Value>
1911{
1912    if arg_values.len() != 1 {
1913        return Err(Error::Interp(String::from("invalid number of arguments")));
1914    }
1915    match arg_values.get(0) {
1916        Some(Value::Object(object)) => {
1917            match &**object {
1918                Object::String(s) => {
1919                    let s2 = if s.starts_with("0X") || s.starts_with("0x") {
1920                        &s[2..]
1921                    } else {
1922                        s
1923                    };
1924                    match i64::from_str_radix(s2, 16) {
1925                        Ok(n) => Ok(Value::Int(n)),
1926                        Err(err) => Ok(Value::Object(Arc::new(Object::Error(String::from("parseint"), format!("{}", err))))),
1927                    }
1928                },
1929                _ => Err(Error::Interp(String::from("unsupported type for function hex2dec"))),
1930            }
1931        },
1932        Some(_) => Err(Error::Interp(String::from("unsupported type for function hex2dec"))),
1933        None => Err(Error::Interp(String::from("no argument"))),
1934    }
1935}
1936
1937/// A `char2code` built-in function.
1938pub fn char2code(_interp: &mut Interp, _env: &mut Env, arg_values: &[Value]) -> Result<Value>
1939{
1940    if arg_values.len() != 1 {
1941        return Err(Error::Interp(String::from("invalid number of arguments")));
1942    }
1943    match arg_values.get(0) {
1944        Some(Value::Object(object)) => {
1945            match &**object {
1946                Object::String(s) => {
1947                    match s.chars().next() {
1948                        Some(c) => Ok(Value::Int((c as u32) as i64)),
1949                        None => Ok(Value::None),
1950                    }
1951                },
1952                _ => Err(Error::Interp(String::from("unsupported type for function char2code"))),
1953            }
1954        },
1955        Some(_) => Err(Error::Interp(String::from("unsupported type for function char2code"))),
1956        None => Err(Error::Interp(String::from("no argument"))),
1957    }
1958}
1959
1960/// A `code2char` built-in function.
1961pub fn code2char(_interp: &mut Interp, _env: &mut Env, arg_values: &[Value]) -> Result<Value>
1962{
1963    if arg_values.len() != 1 {
1964        return Err(Error::Interp(String::from("invalid number of arguments")));
1965    }
1966    match arg_values.get(0) {
1967        Some(value @ (Value::Int(_) | Value::Float(_))) => {
1968            let n = value.to_i64();
1969            if n < 0 || n > (u32::MAX as i64) {
1970                return Ok(Value::None);
1971            }
1972            match char::from_u32(n as u32) {
1973                Some(c) => {
1974                    let mut s = String::new();
1975                    s.push(c);
1976                    Ok(Value::Object(Arc::new(Object::String(s))))
1977                },
1978                None => Ok(Value::None),
1979            }
1980        },
1981        Some(_) => Err(Error::Interp(String::from("unsupported type for function code2char"))),
1982        None => Err(Error::Interp(String::from("no argument"))),
1983    }
1984}
1985
1986/// A `formatmillis` built-in function.
1987pub fn formatmillis(_interp: &mut Interp, _env: &mut Env, arg_values: &[Value]) -> Result<Value>
1988{
1989    if arg_values.len() != 2 {
1990        return Err(Error::Interp(String::from("invalid number of arguments")));
1991    }
1992    match (arg_values.get(0), arg_values.get(1)) {
1993        (Some(Value::Object(object)), Some(millis_value @ (Value::Int(_) | Value::Float(_)))) => {
1994            match &**object {
1995                Object::String(s) => {
1996                    let millis = millis_value.to_i64();
1997                    let secs = millis / 1000;
1998                    if s == &String::from("s") {
1999                        Ok(Value::Object(Arc::new(Object::String(format!("{}.{:03}s", secs, millis % 1000)))))
2000                    } else if s == &String::from("ms") {
2001                        Ok(Value::Object(Arc::new(Object::String(format!("{}m{}.{:03}s", secs / 60, secs % 60, millis % 1000)))))
2002                    } else if s == &String::from("hms") {
2003                        Ok(Value::Object(Arc::new(Object::String(format!("{}h{}m{}.{:03}s", (secs / 60) / 60, (secs / 60) % 60, secs % 60, millis % 1000)))))
2004                    } else {
2005                        Ok(Value::Object(Arc::new(Object::Error(String::from("format"), String::from("invalid format")))))
2006                    }
2007                },
2008                _ => Err(Error::Interp(String::from("unsupported types for function formatmillis"))),
2009            }
2010        },
2011        (Some(_), Some(_)) => Err(Error::Interp(String::from("unsupported types for function formatmillis"))),
2012        (_, _) => Err(Error::Interp(String::from("no argument"))),
2013    }
2014}
2015
2016/// A `withwidth` built-in function.
2017pub fn withwidth(_interp: &mut Interp, _env: &mut Env, arg_values: &[Value]) -> Result<Value>
2018{
2019    if arg_values.len() < 2 || arg_values.len() > 3 {
2020        return Err(Error::Interp(String::from("invalid number of arguments")));
2021    }
2022    match (arg_values.get(0), arg_values.get(1), arg_values.get(2)) {
2023        (Some(value), Some(width_value @ (Value::Int(_) | Value::Float(_))), None) => {
2024            let width = width_value.to_i64();
2025            if width < 0 {
2026                return Ok(Value::Object(Arc::new(Object::Error(String::from("format"), String::from("width is negative")))));
2027            }
2028            if width > (isize::MAX as i64) {
2029                return Ok(Value::Object(Arc::new(Object::Error(String::from("format"), String::from("too large width")))));
2030            }
2031            Ok(Value::Object(Arc::new(Object::String(format!("{:width$}", format!("{}", value), width = width as usize)))))
2032        },
2033        (Some(value), Some(width_value @ (Value::Int(_) | Value::Float(_))), Some(Value::Object(align_object))) => {
2034            match &**align_object {
2035                Object::String(align) => {
2036                    let width = width_value.to_i64();
2037                    if width < 0 {
2038                        return Ok(Value::Object(Arc::new(Object::Error(String::from("format"), String::from("width is negative")))));
2039                    }
2040                    if width > (isize::MAX as i64) {
2041                        return Ok(Value::Object(Arc::new(Object::Error(String::from("format"), String::from("too large width")))));
2042                    }
2043                    if align == &String::from("left") || align == &String::from("l") {
2044                        Ok(Value::Object(Arc::new(Object::String(format!("{:<width$}", format!("{}", value), width = width as usize)))))
2045                    } else if align == &String::from("center") || align == &String::from("c") {
2046                        Ok(Value::Object(Arc::new(Object::String(format!("{:^width$}", format!("{}", value), width = width as usize)))))
2047                    } else if align == &String::from("right") || align == &String::from("r") {
2048                        Ok(Value::Object(Arc::new(Object::String(format!("{:>width$}", format!("{}", value), width = width as usize)))))
2049                    } else {
2050                        Ok(Value::Object(Arc::new(Object::Error(String::from("format"), String::from("invalid alignment")))))
2051                    }
2052                },
2053                _ => Err(Error::Interp(String::from("unsupported types for function withwidth"))),
2054            }
2055        },
2056        (Some(_), Some(_), Some(_)) => Err(Error::Interp(String::from("unsupported types for function withwidth"))),
2057        (_, _, _) => Err(Error::Interp(String::from("no argument"))),
2058    }
2059}
2060
2061/// A `withzeros` built-in function.
2062pub fn withzeros(_interp: &mut Interp, _env: &mut Env, arg_values: &[Value]) -> Result<Value>
2063{
2064    if arg_values.len() != 2 {
2065        return Err(Error::Interp(String::from("invalid number of arguments")));
2066    }
2067    match (arg_values.get(0), arg_values.get(1)) {
2068        (Some(value), Some(width_value @ (Value::Int(_) | Value::Float(_)))) => {
2069            let width = width_value.to_i64();
2070            if width < 0 {
2071                return Ok(Value::Object(Arc::new(Object::Error(String::from("format"), String::from("width is negative")))));
2072            }
2073            if width > (isize::MAX as i64) {
2074                return Ok(Value::Object(Arc::new(Object::Error(String::from("format"), String::from("too large width")))));
2075            }
2076            Ok(Value::Object(Arc::new(Object::String(format!("{:0>width$}", format!("{}", value), width = width as usize)))))
2077        },
2078        (Some(_), Some(_)) => Err(Error::Interp(String::from("unsupported types for function withzeros"))),
2079        (_, _) => Err(Error::Interp(String::from("no argument"))),
2080    }
2081}
2082
2083/// A `readline` built-in function.
2084pub fn readline(_interp: &mut Interp, env: &mut Env, arg_values: &[Value]) -> Result<Value>
2085{
2086    if arg_values.len() != 0 {
2087        return Err(Error::Interp(String::from("invalid number of arguments")));
2088    }
2089    match env.stdin() {
2090        Input::Std => {
2091            let mut line = String::new();
2092            match stdin().read_line(&mut line) {
2093                Ok(_) => Ok(Value::Object(Arc::new(Object::String(line)))),
2094                Err(err) => Ok(Value::Object(Arc::new(Object::Error(String::from("io"), format!("{}", err))))),
2095            }
2096        },
2097        Input::Null => Ok(Value::Object(Arc::new(Object::String(String::new())))),
2098    }
2099}
2100
2101/// A `format` built-in function.
2102pub fn format(_interp: &mut Interp, _env: &mut Env, arg_values: &[Value]) -> Result<Value>
2103{
2104    let mut s = String::new();
2105    for arg_value in arg_values {
2106        s.push_str(format!("{}", arg_value).as_str());
2107    }
2108    Ok(Value::Object(Arc::new(Object::String(s))))
2109}
2110
2111/// A `print` built-in function.
2112pub fn print(_interp: &mut Interp, env: &mut Env, arg_values: &[Value]) -> Result<Value>
2113{
2114    match env.stdout() {
2115        Output::Std => {
2116            for arg_value in arg_values {
2117                print!("{}", arg_value);
2118            }
2119        },
2120        Output::Null => (),
2121        Output::Cursor(cursor) => {
2122            let mut cursor_g = rw_lock_write(cursor)?;
2123            for arg_value in arg_values {
2124                write!(&mut *cursor_g, "{}", arg_value).unwrap();
2125            }
2126        },
2127    }
2128    Ok(Value::None)
2129}
2130
2131/// A `println` built-in function.
2132pub fn println(_interp: &mut Interp, env: &mut Env, arg_values: &[Value]) -> Result<Value>
2133{
2134    match env.stdout() {
2135        Output::Std => {
2136            for arg_value in arg_values {
2137                print!("{}", arg_value);
2138            }
2139            println!("");
2140        },
2141        Output::Null => (),
2142        Output::Cursor(cursor) => {
2143            let mut cursor_g = rw_lock_write(cursor)?;
2144            for arg_value in arg_values {
2145                write!(&mut *cursor_g, "{}", arg_value).unwrap();
2146            }
2147            writeln!(&mut *cursor_g, "").unwrap();
2148        },
2149    }
2150    Ok(Value::None)
2151}
2152
2153/// An `eprint` built-in function.
2154pub fn eprint(_interp: &mut Interp, env: &mut Env, arg_values: &[Value]) -> Result<Value>
2155{
2156    match env.stderr() {
2157        Output::Std => {
2158            for arg_value in arg_values {
2159                eprint!("{}", arg_value);
2160            }
2161        },
2162        Output::Null => (),
2163        Output::Cursor(cursor) => {
2164            let mut cursor_g = rw_lock_write(cursor)?;
2165            for arg_value in arg_values {
2166                write!(&mut *cursor_g, "{}", arg_value).unwrap();
2167            }
2168        },
2169    }
2170    Ok(Value::None)
2171}
2172
2173/// An `eprintln` built-in function.
2174pub fn eprintln(_interp: &mut Interp, env: &mut Env, arg_values: &[Value]) -> Result<Value>
2175{
2176    match env.stderr() {
2177        Output::Std => {
2178            for arg_value in arg_values {
2179                eprint!("{}", arg_value);
2180            }
2181            eprintln!("");
2182        },
2183        Output::Null => (),
2184        Output::Cursor(cursor) => {
2185            let mut cursor_g = rw_lock_write(cursor)?;
2186            for arg_value in arg_values {
2187                write!(&mut *cursor_g, "{}", arg_value).unwrap();
2188            }
2189            writeln!(&mut *cursor_g, "").unwrap();
2190        },
2191    }
2192    Ok(Value::None)
2193}
2194
2195/// A `flush` built-in function.
2196pub fn flush(_interp: &mut Interp, env: &mut Env, arg_values: &[Value]) -> Result<Value>
2197{
2198    if arg_values.len() != 0 {
2199        return Err(Error::Interp(String::from("invalid number of arguments")));
2200    }
2201    match env.stdout() {
2202        Output::Std => {
2203            match stdout().flush() {
2204                Ok(()) => Ok(Value::Bool(true)),
2205                Err(err) => Ok(Value::Object(Arc::new(Object::Error(String::from("io"), format!("{}", err))))),
2206            }
2207        },
2208        _ => Ok(Value::Bool(true)),
2209    }
2210}
2211
2212/// An `eflush` built-in function.
2213pub fn eflush(_interp: &mut Interp, env: &mut Env, arg_values: &[Value]) -> Result<Value>
2214{
2215    if arg_values.len() != 0 {
2216        return Err(Error::Interp(String::from("invalid number of arguments")));
2217    }
2218    match env.stderr() {
2219        Output::Std => {
2220            match stderr().flush() {
2221                Ok(()) => Ok(Value::Bool(true)),
2222                Err(err) => Ok(Value::Object(Arc::new(Object::Error(String::from("io"), format!("{}", err))))),
2223            }
2224        },
2225        _ => Ok(Value::Bool(true)),
2226    }
2227}
2228
2229/// A `cd` built-in function.
2230pub fn cd(_interp: &mut Interp, _env: &mut Env, arg_values: &[Value]) -> Result<Value>
2231{
2232    if arg_values.len() != 1 {
2233        return Err(Error::Interp(String::from("invalid number of arguments")));
2234    }
2235    let new_dir_name = get_first_arg_string(arg_values, "unsupported type for function cd")?;
2236    let old_dir_name = match std::env::current_dir() {
2237        Ok(path) => path.to_string_lossy().into_owned(),
2238        Err(err) => return Ok(Value::Object(Arc::new(Object::Error(String::from("io"), format!("{}", err))))),
2239    };
2240    match std::env::set_current_dir(new_dir_name) {
2241        Ok(()) => Ok(Value::Object(Arc::new(Object::String(old_dir_name)))),
2242        Err(err) => Ok(Value::Object(Arc::new(Object::Error(String::from("io"), format!("{}", err))))),
2243    }
2244}
2245
2246/// A `pwd` built-in function.
2247pub fn pwd(_interp: &mut Interp, _env: &mut Env, arg_values: &[Value]) -> Result<Value>
2248{
2249    if arg_values.len() != 0 {
2250        return Err(Error::Interp(String::from("invalid number of arguments")));
2251    }
2252    match std::env::current_dir() {
2253        Ok(path) => Ok(Value::Object(Arc::new(Object::String(path.to_string_lossy().into_owned())))),
2254        Err(err) => Ok(Value::Object(Arc::new(Object::Error(String::from("io"), format!("{}", err))))),
2255    }
2256}
2257
2258/// An `exist` built-in function.
2259pub fn exist(_interp: &mut Interp, _env: &mut Env, arg_values: &[Value]) -> Result<Value>
2260{
2261    if arg_values.len() != 1 {
2262        return Err(Error::Interp(String::from("invalid number of arguments")));
2263    }
2264    let file_name = get_first_arg_string(arg_values, "unsupported type for function exist")?;
2265    match fs::metadata(file_name.as_str()) {
2266        Ok(_) => Ok(Value::Bool(true)),
2267        Err(err) if err.kind() == ErrorKind::NotFound => Ok(Value::Bool(false)),
2268        Err(err) => Ok(Value::Object(Arc::new(Object::Error(String::from("io"), format!("{}", err))))),
2269    }
2270}
2271
2272/// A `filetype` built-in function.
2273pub fn filetype(_interp: &mut Interp, _env: &mut Env, arg_values: &[Value]) -> Result<Value>
2274{
2275    if arg_values.len() != 1 {
2276        return Err(Error::Interp(String::from("invalid number of arguments")));
2277    }
2278    let file_name = get_first_arg_string(arg_values, "unsupported type for function filetype")?;
2279    match fs::metadata(file_name.as_str()) {
2280        Ok(metadata) => {
2281            if metadata.is_dir() {
2282                Ok(Value::Object(Arc::new(Object::String(String::from("dir")))))
2283            } else {
2284                Ok(Value::Object(Arc::new(Object::String(String::from("file")))))
2285            }
2286        },
2287        Err(err) => Ok(Value::Object(Arc::new(Object::Error(String::from("io"), format!("{}", err))))),
2288    }
2289}
2290
2291/// A `dir` built-in function.
2292pub fn dir(_interp: &mut Interp, _env: &mut Env, arg_values: &[Value]) -> Result<Value>
2293{
2294    if arg_values.len() != 1 {
2295        return Err(Error::Interp(String::from("invalid number of arguments")));
2296    }
2297    let dir_name = get_first_arg_string(arg_values, "unsupported type for function dir")?;
2298    match read_dir(dir_name.as_str()) {
2299        Ok(entries) => {
2300            let mut name_values: Vec<Value> = Vec::new();
2301            for entry in entries {
2302                match entry {
2303                    Ok(entry) => name_values.push(Value::Object(Arc::new(Object::String(entry.file_name().to_string_lossy().into_owned())))),
2304                    Err(err) => return Ok(Value::Object(Arc::new(Object::Error(String::from("io"), format!("{}", err))))),
2305                }
2306            }
2307            Ok(Value::Ref(Arc::new(RwLock::new(MutObject::Array(name_values)))))
2308        },
2309        Err(err) => Ok(Value::Object(Arc::new(Object::Error(String::from("io"), format!("{}", err))))),
2310    }
2311}
2312
2313/// A `mkdir` built-in function.
2314pub fn mkdir(_interp: &mut Interp, _env: &mut Env, arg_values: &[Value]) -> Result<Value>
2315{
2316    if arg_values.len() != 1 {
2317        return Err(Error::Interp(String::from("invalid number of arguments")));
2318    }
2319    let dir_name = get_first_arg_string(arg_values, "unsupported type for function mkdir")?;
2320    match create_dir(dir_name.as_str()) {
2321        Ok(()) => Ok(Value::Bool(true)),
2322        Err(err) => Ok(Value::Object(Arc::new(Object::Error(String::from("io"), format!("{}", err))))),
2323    }
2324}
2325
2326/// A `rmdir` built-in function.
2327pub fn rmdir(_interp: &mut Interp, _env: &mut Env, arg_values: &[Value]) -> Result<Value>
2328{
2329    if arg_values.len() != 1 {
2330        return Err(Error::Interp(String::from("invalid number of arguments")));
2331    }
2332    let dir_name = get_first_arg_string(arg_values, "unsupported type for function rmdir")?;
2333    match remove_dir(dir_name.as_str()) {
2334        Ok(()) => Ok(Value::Bool(true)),
2335        Err(err) => Ok(Value::Object(Arc::new(Object::Error(String::from("io"), format!("{}", err))))),
2336    }
2337}
2338
2339/// A `rmfile` built-in function.
2340pub fn rmfile(_interp: &mut Interp, _env: &mut Env, arg_values: &[Value]) -> Result<Value>
2341{
2342    if arg_values.len() != 1 {
2343        return Err(Error::Interp(String::from("invalid number of arguments")));
2344    }
2345    let file_name = get_first_arg_string(arg_values, "unsupported type for function rmfile")?;
2346    match remove_file(file_name.as_str()) {
2347        Ok(()) => Ok(Value::Bool(true)),
2348        Err(err) => Ok(Value::Object(Arc::new(Object::Error(String::from("io"), format!("{}", err))))),
2349    }
2350}
2351
2352/// A `copy` built-in function.
2353pub fn copy(_interp: &mut Interp, _env: &mut Env, arg_values: &[Value]) -> Result<Value>
2354{
2355    if arg_values.len() != 2 {
2356        return Err(Error::Interp(String::from("invalid number of arguments")));
2357    }
2358    let (src_file_name, dst_file_name) = match (arg_values.get(0), arg_values.get(1)) {
2359        (Some(src_file_name_value), Some(dst_file_name_value)) => {
2360            match (src_file_name_value.to_opt_string(), dst_file_name_value.to_opt_string()) {
2361                (Some(tmp_src_file_name), Some(tmp_dst_file_name)) => (tmp_src_file_name, tmp_dst_file_name),
2362                (_, _) => return Err(Error::Interp(String::from("unsupported types for function copy"))),
2363            }
2364        },
2365        (_, _) => return Err(Error::Interp(String::from("no argument"))),
2366    };
2367    match fs::copy(src_file_name.as_str(), dst_file_name.as_str()) {
2368        Ok(_) => Ok(Value::Bool(true)),
2369        Err(err) => Ok(Value::Object(Arc::new(Object::Error(String::from("io"), format!("{}", err))))),
2370    }
2371}
2372
2373/// A `rename` built-in function.
2374pub fn rename(_interp: &mut Interp, _env: &mut Env, arg_values: &[Value]) -> Result<Value>
2375{
2376    if arg_values.len() != 2 {
2377        return Err(Error::Interp(String::from("invalid number of arguments")));
2378    }
2379    let (src_file_name, dst_file_name) = match (arg_values.get(0), arg_values.get(1)) {
2380        (Some(src_file_name_value), Some(dst_file_name_value)) => {
2381            match (src_file_name_value.to_opt_string(), dst_file_name_value.to_opt_string()) {
2382                (Some(tmp_src_file_name), Some(tmp_dst_file_name)) => (tmp_src_file_name, tmp_dst_file_name),
2383                (_, _) => return Err(Error::Interp(String::from("unsupported types for function rename"))),
2384            }
2385        },
2386        (_, _) => return Err(Error::Interp(String::from("no argument"))),
2387    };
2388    match fs::rename(src_file_name.as_str(), dst_file_name.as_str()) {
2389        Ok(_) => Ok(Value::Bool(true)),
2390        Err(err) => Ok(Value::Object(Arc::new(Object::Error(String::from("io"), format!("{}", err))))),
2391    }
2392}
2393
2394/// A `spawn` built-in function.
2395pub fn spawn(_interp: &mut Interp, _env: &mut Env, arg_values: &[Value]) -> Result<Value>
2396{
2397    if arg_values.len() < 1 {
2398        return Err(Error::Interp(String::from("invalid number of arguments")));
2399    }
2400    let cmd_name = get_first_arg_string(arg_values, "unsupported type for function spawn")?;
2401    let mut cmd_args: Vec<String> = Vec::new();
2402    for arg_value in &arg_values[1..] {
2403        cmd_args.push(format!("{}", arg_value));
2404    }
2405    match Command::new(cmd_name).args(cmd_args).spawn() {
2406        Ok(mut child) => {
2407            match child.wait() {
2408                Ok(exit_status) => {
2409                    match exit_status.code() {
2410                        Some(code) => Ok(Value::Int(code as i64)),
2411                        None => Ok(Value::Object(Arc::new(Object::Error(String::from("exitstatus"), String::from("process terminated by signal"))))),
2412                    }
2413                },
2414                Err(err) => Ok(Value::Object(Arc::new(Object::Error(String::from("io"), format!("{}", err))))),
2415            }
2416        },
2417        Err(err) => Ok(Value::Object(Arc::new(Object::Error(String::from("io"), format!("{}", err))))),
2418    }
2419}
2420
2421/// An `exit` built-in function.
2422pub fn exit(_interp: &mut Interp, _env: &mut Env, arg_values: &[Value]) -> Result<Value>
2423{
2424    if arg_values.len() != 1 {
2425        return Err(Error::Interp(String::from("invalid number of arguments")));
2426    }
2427    match arg_values.get(0) {
2428        Some(value @ (Value::Int(_) | Value::Float(_))) => Err(Error::Stop(Stop::Exit(value.to_i64() as i32))),
2429        Some(_) => Err(Error::Interp(String::from("unsupported type for fuction exit"))),
2430        None => Err(Error::Interp(String::from("no argument"))),
2431    }
2432}
2433
2434/// A `load` built-in function.
2435pub fn load(_interp: &mut Interp, env: &mut Env, arg_values: &[Value]) -> Result<Value>
2436{
2437    if arg_values.len() != 1 {
2438        return Err(Error::Interp(String::from("invalid number of arguments")));
2439    }
2440    let file_name = get_first_arg_string(arg_values, "unsupported type for function load")?;
2441    match load_values(file_name.as_str(), env) {
2442        Ok(values) => Ok(Value::Ref(Arc::new(RwLock::new(MutObject::Array(values))))),
2443        Err(Error::Io(err)) => Ok(Value::Object(Arc::new(Object::Error(String::from("io"), format!("{}", err))))),
2444        Err(err) => Err(err),
2445    }
2446}
2447
2448/// A `save` built-in function.
2449pub fn save(_interp: &mut Interp, _env: &mut Env, arg_values: &[Value]) -> Result<Value>
2450{
2451    if arg_values.len() < 1 {
2452        return Err(Error::Interp(String::from("invalid number of arguments")));
2453    }
2454    let file_name = get_first_arg_string(arg_values, "unsupported type for function save")?;
2455    match save_values(file_name.as_str(), &arg_values[1..]) {
2456        Ok(()) => Ok(Value::Bool(true)),
2457        Err(Error::Io(err)) => Ok(Value::Object(Arc::new(Object::Error(String::from("io"), format!("{}", err))))),
2458        Err(err) => Err(err),
2459    }
2460}
2461
2462/// A `loadstr` built-in function.
2463pub fn loadstr(_interp: &mut Interp, _env: &mut Env, arg_values: &[Value]) -> Result<Value>
2464{
2465    if arg_values.len() != 1 {
2466        return Err(Error::Interp(String::from("invalid number of arguments")));
2467    }
2468    let file_name = get_first_arg_string(arg_values, "unsupported type for function loadstr")?;
2469    match File::open(file_name.as_str()) {
2470        Ok(mut file) => {
2471            let mut s = String::new();
2472            match file.read_to_string(&mut s) {
2473                Ok(_) => Ok(Value::Object(Arc::new(Object::String(s)))),
2474                Err(err) => Ok(Value::Object(Arc::new(Object::Error(String::from("io"), format!("{}", err))))),
2475            }
2476        },
2477        Err(err) => Ok(Value::Object(Arc::new(Object::Error(String::from("io"), format!("{}", err))))),
2478    }
2479}
2480
2481/// A `savestr` built-in function.
2482pub fn savestr(_interp: &mut Interp, _env: &mut Env, arg_values: &[Value]) -> Result<Value>
2483{
2484    if arg_values.len() != 2 {
2485        return Err(Error::Interp(String::from("invalid number of arguments")));
2486    }
2487    let (file_name, str_value) = match (arg_values.get(0), arg_values.get(1)) {
2488        (Some(file_name_value), Some(str_value)) => {
2489            match file_name_value.to_opt_string() {
2490                Some(tmp_file_name) => (tmp_file_name, str_value.clone()),
2491                None => return Err(Error::Interp(String::from("unsupported type for function savestr"))),
2492            }
2493        },
2494        (_, _) => return Err(Error::Interp(String::from("no argument"))),
2495    };
2496    match File::create(file_name.as_str()) {
2497        Ok(file) => {
2498            let mut w = BufWriter::new(file);
2499            match write!(&mut w, "{}", str_value) {
2500                Ok(()) => Ok(Value::Bool(true)),
2501                Err(err) => Ok(Value::Object(Arc::new(Object::Error(String::from("io"), format!("{}", err))))),
2502            }
2503        },
2504        Err(err) => Ok(Value::Object(Arc::new(Object::Error(String::from("io"), format!("{}", err))))),
2505    }
2506}
2507
2508/// A `loadtoml` built-in function.
2509pub fn loadtoml(_interp: &mut Interp, _env: &mut Env, arg_values: &[Value]) -> Result<Value>
2510{
2511    if arg_values.len() != 1 {
2512        return Err(Error::Interp(String::from("invalid number of arguments")));
2513    }
2514    let file_name = get_first_arg_string(arg_values, "unsupported type for function loadtoml")?;
2515    match File::open(file_name.as_str()) {
2516        Ok(mut file) => {
2517            let mut s = String::new();
2518            match file.read_to_string(&mut s) {
2519                Ok(_) => {
2520                    match toml::from_str(s.as_str()) {
2521                        Ok(value) => Ok(value),
2522                        Err(err) => Ok(Value::Object(Arc::new(Object::Error(String::from("toml"), format!("{}", err))))),
2523                    }
2524                },
2525                Err(err) => Ok(Value::Object(Arc::new(Object::Error(String::from("io"), format!("{}", err))))),
2526            }
2527        },
2528        Err(err) => Ok(Value::Object(Arc::new(Object::Error(String::from("io"), format!("{}", err))))),
2529    }
2530}
2531
2532/// A `savetoml` built-in function.
2533pub fn savetoml(_interp: &mut Interp, _env: &mut Env, arg_values: &[Value]) -> Result<Value>
2534{
2535    if arg_values.len() != 2 {
2536        return Err(Error::Interp(String::from("invalid number of arguments")));
2537    }
2538    let (file_name, value) = match (arg_values.get(0), arg_values.get(1)) {
2539        (Some(file_name_value), Some(value)) => {
2540            match file_name_value.to_opt_string() {
2541                Some(tmp_file_name) => (tmp_file_name, value),
2542                None => return Err(Error::Interp(String::from("unsupported type for function savetoml"))),
2543            }
2544        },
2545        (_, _) => return Err(Error::Interp(String::from("no argument"))),
2546    };
2547    match toml::to_string(&value) {
2548        Ok(s) => {
2549            match File::create(file_name.as_str()) {
2550                Ok(file) => {
2551                    let mut w = BufWriter::new(file);
2552                    match write!(&mut w, "{}", s) {
2553                        Ok(()) => Ok(Value::Bool(true)),
2554                        Err(err) => Ok(Value::Object(Arc::new(Object::Error(String::from("io"), format!("{}", err))))),
2555                    }
2556                },
2557                Err(err) => Ok(Value::Object(Arc::new(Object::Error(String::from("io"), format!("{}", err))))),
2558            }
2559        },
2560        Err(err) => Ok(Value::Object(Arc::new(Object::Error(String::from("toml"), format!("{}", err))))),
2561    }
2562}
2563
2564/// A `loadjson` built-in function.
2565pub fn loadjson(_interp: &mut Interp, _env: &mut Env, arg_values: &[Value]) -> Result<Value>
2566{
2567    if arg_values.len() != 1 {
2568        return Err(Error::Interp(String::from("invalid number of arguments")));
2569    }
2570    let file_name = get_first_arg_string(arg_values, "unsupported type for function loadjson")?;
2571    match File::open(file_name.as_str()) {
2572        Ok(mut file) => {
2573            let mut s = String::new();
2574            match file.read_to_string(&mut s) {
2575                Ok(_) => {
2576                    match serde_json::from_str(s.as_str()) {
2577                        Ok(value) => Ok(value),
2578                        Err(err) => Ok(Value::Object(Arc::new(Object::Error(String::from("json"), format!("{}", err))))),
2579                    }
2580                },
2581                Err(err) => Ok(Value::Object(Arc::new(Object::Error(String::from("io"), format!("{}", err))))),
2582            }
2583        },
2584        Err(err) => Ok(Value::Object(Arc::new(Object::Error(String::from("io"), format!("{}", err))))),
2585    }
2586}
2587
2588/// A `savejson` built-in function.
2589pub fn savejson(_interp: &mut Interp, _env: &mut Env, arg_values: &[Value]) -> Result<Value>
2590{
2591    if arg_values.len() != 2 {
2592        return Err(Error::Interp(String::from("invalid number of arguments")));
2593    }
2594    let (file_name, value) = match (arg_values.get(0), arg_values.get(1)) {
2595        (Some(file_name_value), Some(value)) => {
2596            match file_name_value.to_opt_string() {
2597                Some(tmp_file_name) => (tmp_file_name, value),
2598                None => return Err(Error::Interp(String::from("unsupported type for function savejson"))),
2599            }
2600        },
2601        (_, _) => return Err(Error::Interp(String::from("no argument"))),
2602    };
2603    match serde_json::to_string(&value) {
2604        Ok(s) => {
2605            match File::create(file_name.as_str()) {
2606                Ok(file) => {
2607                    let mut w = BufWriter::new(file);
2608                    match write!(&mut w, "{}", s) {
2609                        Ok(()) => Ok(Value::Bool(true)),
2610                        Err(err) => Ok(Value::Object(Arc::new(Object::Error(String::from("io"), format!("{}", err))))),
2611                    }
2612                },
2613                Err(err) => Ok(Value::Object(Arc::new(Object::Error(String::from("io"), format!("{}", err))))),
2614            }
2615        },
2616        Err(err) => Ok(Value::Object(Arc::new(Object::Error(String::from("json"), format!("{}", err))))),
2617    }
2618}
2619
2620/// An `args` built-in function.
2621pub fn args(_interp: &mut Interp, env: &mut Env, arg_values: &[Value]) -> Result<Value>
2622{
2623    if arg_values.len() != 0 {
2624        return Err(Error::Interp(String::from("invalid number of arguments")));
2625    }
2626    let shared_env_g = rw_lock_read(env.shared_env())?;
2627    Ok(Value::Ref(Arc::new(RwLock::new(MutObject::Array(shared_env_g.args().iter().map(|s| Value::Object(Arc::new(Object::String(s.clone())))).collect())))))
2628}
2629
2630/// An `env` built-in function.
2631pub fn env(_interp: &mut Interp, _env: &mut Env, arg_values: &[Value]) -> Result<Value>
2632{
2633    if arg_values.len() != 0 {
2634        return Err(Error::Interp(String::from("invalid number of arguments")));
2635    }
2636    Ok(Value::Ref(Arc::new(RwLock::new(MutObject::Array(std::env::vars_os().map(|p| Value::Object(Arc::new(Object::String(format!("{}={}", p.0.to_string_lossy().into_owned(), p.1.to_string_lossy().into_owned()))))).collect())))))
2637}
2638
2639/// A `scriptdir` built-in function.
2640pub fn scriptdir(_interp: &mut Interp, env: &mut Env, arg_values: &[Value]) -> Result<Value>
2641{
2642    if arg_values.len() != 0 {
2643        return Err(Error::Interp(String::from("invalid number of arguments")));
2644    }
2645    Ok(Value::Object(Arc::new(Object::String(env.script_dir().to_string_lossy().into_owned()))))
2646}
2647
2648/// A `libpath` built-in function.
2649pub fn libpath(_interp: &mut Interp, env: &mut Env, arg_values: &[Value]) -> Result<Value>
2650{
2651    if arg_values.len() != 0 {
2652        return Err(Error::Interp(String::from("invalid number of arguments")));
2653    }
2654    let shared_env_g = rw_lock_read(env.shared_env())?;
2655    Ok(Value::Object(Arc::new(Object::String(shared_env_g.lib_path().to_string_lossy().into_owned()))))
2656}
2657
2658/// A `domain` built-in function.
2659pub fn domain(_interp: &mut Interp, env: &mut Env, arg_values: &[Value]) -> Result<Value>
2660{
2661    if arg_values.len() != 0 {
2662        return Err(Error::Interp(String::from("invalid number of arguments")));
2663    }
2664    match env.domain() {
2665        Some(domain) => Ok(Value::Object(Arc::new(Object::String(String::from(domain))))),
2666        None => Ok(Value::None),
2667    }
2668}
2669
2670fn name_with_domain(name: &str, env: &Env) -> Result<String>
2671{
2672    if name.contains('/') {
2673        Ok(String::from(name))
2674    } else {
2675        match env.domain() {
2676            Some(domain) => {
2677                let mut new_name = String::from(domain);
2678                new_name.push('/');
2679                new_name.push_str(name);
2680                Ok(new_name)
2681            },
2682            None => Err(Error::Interp(String::from("name library without domain"))),
2683        }
2684    }
2685}
2686
2687fn domain_from_name(name: &str) -> Result<String>
2688{
2689    match name.split_once('/') {
2690        Some((domain, _)) => Ok(String::from(domain)),
2691        None => Err(Error::Interp(String::from("name library without domain"))),
2692    }
2693}
2694
2695fn use_lib(interp: &mut Interp, env: &mut Env, lib_name: &str) -> Result<()>
2696{
2697    let domain = domain_from_name(lib_name)?;
2698    let lib_path = {
2699        let shared_env_g = rw_lock_read(env.shared_env())?;
2700        OsString::from(shared_env_g.lib_path())
2701    };
2702    let mut res: Result<()> = Ok(());
2703    for dir in std::env::split_paths(lib_path.as_os_str()) {
2704        let mut script_dir = dir.clone();
2705        script_dir.push(lib_name.replace('/', path::MAIN_SEPARATOR_STR));
2706        let mut path = script_dir.clone();
2707        path.push("lib.un");
2708        match parse(path) {
2709            Ok(tree) => {
2710                let mut new_env = Env::new_with_script_dir_and_domain_and_shared_env(env.root_mod().clone(), script_dir.clone(), Some(domain), env.shared_env().clone());
2711                new_env.set_stdin(*env.stdin());
2712                new_env.set_stdout(env.stdout().clone());
2713                new_env.set_stderr(env.stderr().clone());
2714                interp.interpret(&mut new_env, &tree)?;
2715                {
2716                    let mut shared_env_g = rw_lock_write(env.shared_env())?;
2717                    shared_env_g.add_used_lib(String::from(lib_name));
2718                }
2719                return Ok(());
2720            },
2721            Err(Error::ParserIo(path, err)) if err.kind() == ErrorKind::NotFound => res = Err(Error::ParserIo(path, err)),
2722            Err(err) => return Err(err),
2723        }
2724    }
2725    res
2726}
2727
2728/// An `uselib` built-in function.
2729pub fn uselib(interp: &mut Interp, env: &mut Env, arg_values: &[Value]) -> Result<Value>
2730{
2731    if arg_values.len() != 1 {
2732        return Err(Error::Interp(String::from("invalid number of arguments")));
2733    }
2734    let lib_name = get_first_arg_string(arg_values, "unsupported type for function uselib")?;
2735    let lib_name = name_with_domain(lib_name.as_str(), env)?;
2736    let is_used_lib = {
2737        let shared_env_g = rw_lock_read(env.shared_env())?;
2738        shared_env_g.has_used_lib(&lib_name)
2739    };
2740    if !is_used_lib {
2741        use_lib(interp, env, lib_name.as_str())?;
2742    }
2743    Ok(Value::None)
2744}
2745
2746/// A `reuselib` built-in function.
2747pub fn reuselib(interp: &mut Interp, env: &mut Env, arg_values: &[Value]) -> Result<Value>
2748{
2749    if arg_values.len() != 1 {
2750        return Err(Error::Interp(String::from("invalid number of arguments")));
2751    }
2752    let lib_name = get_first_arg_string(arg_values, "unsupported type for function reuselib")?;
2753    let lib_name = name_with_domain(lib_name.as_str(), env)?;
2754    use_lib(interp, env, lib_name.as_str())?;
2755    Ok(Value::None)
2756}
2757
2758/// A `run` built-in function.
2759pub fn run(interp: &mut Interp, env: &mut Env, arg_values: &[Value]) -> Result<Value>
2760{
2761    if arg_values.len() != 1 {
2762        return Err(Error::Interp(String::from("invalid number of arguments")));
2763    }
2764    let script_name = get_first_arg_string(arg_values, "unsupported type for function run")?;
2765    let mut path_buf = PathBuf::from(env.script_dir());
2766    path_buf.push(script_name.replace('/', path::MAIN_SEPARATOR_STR).as_str());
2767    let tree = parse(path_buf)?;
2768    let mut new_env = env.clone_without_stack();
2769    interp.interpret(&mut new_env, &tree)?;
2770    Ok(Value::None)
2771}
2772
2773/// A `clock` built-in function.
2774pub fn clock(_interp: &mut Interp, env: &mut Env, arg_values: &[Value]) -> Result<Value>
2775{
2776    if arg_values.len() != 0 {
2777        return Err(Error::Interp(String::from("invalid number of arguments")));
2778    }
2779    let shared_env_g = rw_lock_read(env.shared_env())?;
2780    Ok(Value::Int(shared_env_g.instant().elapsed().as_millis() as i64))
2781}
2782
2783fn mod_pair_for_name(env: &Env, name: &str, is_var: bool) -> Result<(Arc<RwLock<ModNode<Value, ()>>>, Vec<String>)>
2784{
2785    let name_without_first_colons = if name.starts_with("::") {
2786        &name[2..]
2787    } else {
2788        name
2789    };
2790    let idents: Vec<String> = name_without_first_colons.split("::").map(String::from).collect();
2791    let end = if is_var {
2792        idents.len().saturating_sub(1)
2793    } else {
2794        idents.len()
2795    };
2796    match idents.first() {
2797        Some(ident) if ident == &String::from("root") => {
2798            match ModNode::mod_from(env.root_mod(), &idents[1..cmp::max(end, 1)], false)? {
2799                Some(mod1) => Ok((mod1, (&idents[1..]).to_vec())),
2800                None => Err(Error::Interp(String::from("undefined module"))),
2801            }
2802        },
2803        _ => {
2804            match ModNode::mod_from(env.current_mod(), &idents[0..end], true)? {
2805                Some(mod1) => Ok((mod1, idents)),
2806                None => {
2807                    match ModNode::mod_from(env.root_mod(), &idents[0..end], false)? {
2808                        Some(mod1) => Ok((mod1, idents)),
2809                        None => Err(Error::Interp(String::from("undefined module"))),
2810                    }
2811                },
2812            }
2813        },
2814    }
2815}
2816
2817/// An `usemod` built-in function.
2818pub fn usemod(_interp: &mut Interp, env: &mut Env, arg_values: &[Value]) -> Result<Value>
2819{
2820    if arg_values.len() < 1 || arg_values.len() > 2 {
2821        return Err(Error::Interp(String::from("invalid number of arguments")));
2822    }
2823    match arg_values.get(0) {
2824        Some(Value::Object(object)) => {
2825            match &**object {
2826                Object::String(name) => {
2827                    let (used_mod, idents) = mod_pair_for_name(env, name, false)?;
2828                    let ident = match arg_values.get(1) {
2829                        Some(Value::Object(object)) => {
2830                            match &**object {
2831                                Object::String(tmp_ident) => tmp_ident.clone(),
2832                                _ => return Err(Error::Interp(String::from("unsupported types for function usemod"))),
2833                            }
2834                        },
2835                        Some(_) =>  return Err(Error::Interp(String::from("unsupported types for function usemod"))),
2836                        None => {
2837                            match idents.last() {
2838                                Some(tmp_ident) => tmp_ident.clone(),
2839                                None => return Err(Error::Interp(String::from("no last identifier"))),
2840                            }
2841                        },
2842                    };
2843                    ModNode::add_used_mod(env.current_mod(), ident, used_mod)?;
2844                    Ok(Value::None)
2845                },
2846                _ => Err(Error::Interp(String::from("unsupported types for function usemod"))),
2847            }
2848        },
2849        Some(_) => Err(Error::Interp(String::from("unsupported types for function usemod"))),
2850        None => Err(Error::Interp(String::from("no argument"))),
2851    }
2852}
2853
2854/// An `usemods` built-in function.
2855pub fn usemods(_interp: &mut Interp, env: &mut Env, arg_values: &[Value]) -> Result<Value>
2856{
2857    if arg_values.len() != 1 {
2858        return Err(Error::Interp(String::from("invalid number of arguments")));
2859    }
2860    match arg_values.get(0) {
2861        Some(Value::Object(object)) => {
2862            match &**object {
2863                Object::String(name) => {
2864                    let mod1 = mod_pair_for_name(env, name, false)?.0;
2865                    let used_mods: Vec<(String, Arc<RwLock<ModNode<Value, ()>>>)> = {
2866                        let mod_g = rw_lock_read(&mod1)?;
2867                        mod_g.mods().iter().map(|p| (p.0.clone(), p.1.clone())).collect()
2868                    };
2869                    for (ident, used_mod) in &used_mods {
2870                        ModNode::add_used_mod(env.current_mod(), ident.clone(), used_mod.clone())?;
2871                    }
2872                    Ok(Value::None)
2873                },
2874                _ => Err(Error::Interp(String::from("unsupported type for function usemods"))),
2875            }
2876        },
2877        Some(_) => Err(Error::Interp(String::from("unsupported type for function usemods"))),
2878        None => Err(Error::Interp(String::from("no argument"))),
2879    }
2880}
2881
2882/// An `usevar` built-in function.
2883pub fn usevar(_interp: &mut Interp, env: &mut Env, arg_values: &[Value]) -> Result<Value>
2884{
2885    if arg_values.len() < 1 || arg_values.len() > 2 {
2886        return Err(Error::Interp(String::from("invalid number of arguments")));
2887    }
2888    match arg_values.get(0) {
2889        Some(Value::Object(object)) => {
2890            match &**object {
2891                Object::String(name) => {
2892                    let (used_var_mod, idents) = mod_pair_for_name(env, name, true)?;
2893                    let (ident, used_var_ident) = match arg_values.get(1) {
2894                        Some(Value::Object(object)) => {
2895                            match &**object {
2896                                Object::String(tmp_ident) => {
2897                                    match idents.last() {
2898                                        Some(tmp_used_var_ident) => (tmp_ident.clone(), tmp_used_var_ident.clone()),
2899                                        None => return Err(Error::Interp(String::from("no last identifier"))),
2900                                    }
2901                                },
2902                                _ => return Err(Error::Interp(String::from("unsupported types for function usevar"))),
2903                            }
2904                        },
2905                        Some(_) =>  return Err(Error::Interp(String::from("unsupported types for function usevar"))),
2906                        None => {
2907                            match idents.last() {
2908                                Some(tmp_used_var_ident) => (tmp_used_var_ident.clone(), tmp_used_var_ident.clone()),
2909                                None => return Err(Error::Interp(String::from("no last identifier"))),
2910                            }
2911                        },
2912                    };
2913                    {
2914                        let used_var_mod_g = rw_lock_read(&used_var_mod)?;
2915                        if !used_var_mod_g.has_var(&used_var_ident) {
2916                            return Err(Error::Interp(String::from("undefined variable")));
2917                        }
2918                    }
2919                    ModNode::add_used_var(env.current_mod(), ident.clone(), used_var_mod, used_var_ident)?;
2920                    Ok(Value::None)
2921                },
2922                _ => Err(Error::Interp(String::from("unsupported types for function usevar"))),
2923            }
2924        },
2925        Some(_) => Err(Error::Interp(String::from("unsupported types for function usevar"))),
2926        None => Err(Error::Interp(String::from("no argument"))),
2927    }
2928}
2929
2930/// An `usevars` built-in function.
2931pub fn usevars(_interp: &mut Interp, env: &mut Env, arg_values: &[Value]) -> Result<Value>
2932{
2933    if arg_values.len() != 1 {
2934        return Err(Error::Interp(String::from("invalid number of arguments")));
2935    }
2936    match arg_values.get(0) {
2937        Some(Value::Object(object)) => {
2938            match &**object {
2939                Object::String(name) => {
2940                    let used_var_mod = mod_pair_for_name(env, name, false)?.0;
2941                    let used_var_idents: Vec<String> = {
2942                        let used_var_mod_g = rw_lock_read(&used_var_mod)?;
2943                        used_var_mod_g.vars().keys().map(|s| s.clone()).collect()
2944                    };
2945                    for used_var_ident in &used_var_idents {
2946                        ModNode::add_used_var(env.current_mod(), used_var_ident.clone(), used_var_mod.clone(), used_var_ident.clone())?;
2947                    }
2948                    Ok(Value::None)
2949                },
2950                _ => Err(Error::Interp(String::from("unsupported type for function usevars"))),
2951            }
2952        },
2953        Some(_) => Err(Error::Interp(String::from("unsupported type for function usevars"))),
2954        None => Err(Error::Interp(String::from("no argument"))),
2955    }
2956}
2957
2958/// A `removeusemod` built-in function.
2959pub fn removeusemod(_interp: &mut Interp, env: &mut Env, arg_values: &[Value]) -> Result<Value>
2960{
2961    if arg_values.len() != 1 {
2962        return Err(Error::Interp(String::from("invalid number of arguments")));
2963    }
2964    match arg_values.get(0) {
2965        Some(Value::Object(object)) => {
2966            match &**object {
2967                Object::String(ident) => {
2968                    let mut current_mod_g = rw_lock_write(env.current_mod())?;
2969                    current_mod_g.remove_used_mod(ident);
2970                    Ok(Value::None)
2971                },
2972                _ => Err(Error::Interp(String::from("unsupported type for function removeusemod"))),
2973            }
2974        },
2975        Some(_) => Err(Error::Interp(String::from("unsupported type for function removeusemod"))),
2976        None => Err(Error::Interp(String::from("no argument"))),
2977    }
2978}
2979
2980/// A `removeusevar` built-in function.
2981pub fn removeusevar(_interp: &mut Interp, env: &mut Env, arg_values: &[Value]) -> Result<Value>
2982{
2983    if arg_values.len() != 1 {
2984        return Err(Error::Interp(String::from("invalid number of arguments")));
2985    }
2986    match arg_values.get(0) {
2987        Some(Value::Object(object)) => {
2988            match &**object {
2989                Object::String(ident) => {
2990                    let mut current_mod_g = rw_lock_write(env.current_mod())?;
2991                    current_mod_g.remove_used_var(ident);
2992                    Ok(Value::None)
2993                },
2994                _ => Err(Error::Interp(String::from("unsupported type for function removeusevar"))),
2995            }
2996        },
2997        Some(_) => Err(Error::Interp(String::from("unsupported type for function removeusevar"))),
2998        None => Err(Error::Interp(String::from("no argument"))),
2999    }
3000}
3001
3002/// A `removemod` built-in function.
3003pub fn removemod(_interp: &mut Interp, env: &mut Env, arg_values: &[Value]) -> Result<Value>
3004{
3005    if arg_values.len() != 1 {
3006        return Err(Error::Interp(String::from("invalid number of arguments")));
3007    }
3008    match arg_values.get(0) {
3009        Some(Value::Object(object)) => {
3010            match &**object {
3011                Object::String(ident) => {
3012                    let mut current_mod_g = rw_lock_write(env.current_mod())?;
3013                    current_mod_g.remove_mod(ident)?;
3014                    Ok(Value::None)
3015                },
3016                _ => Err(Error::Interp(String::from("unsupported type for function removemod"))),
3017            }
3018        },
3019        Some(_) => Err(Error::Interp(String::from("unsupported type for function removemod"))),
3020        None => Err(Error::Interp(String::from("no argument"))),
3021    }
3022}
3023
3024/// A `removevar` built-in function.
3025pub fn removevar(_interp: &mut Interp, env: &mut Env, arg_values: &[Value]) -> Result<Value>
3026{
3027    if arg_values.len() != 1 {
3028        return Err(Error::Interp(String::from("invalid number of arguments")));
3029    }
3030    match arg_values.get(0) {
3031        Some(Value::Object(object)) => {
3032            match &**object {
3033                Object::String(ident) => {
3034                    let mut current_mod_g = rw_lock_write(env.current_mod())?;
3035                    current_mod_g.remove_var(ident);
3036                    Ok(Value::None)
3037                },
3038                _ => Err(Error::Interp(String::from("unsupported type for function removevar"))),
3039            }
3040        },
3041        Some(_) => Err(Error::Interp(String::from("unsupported type for function removevar"))),
3042        None => Err(Error::Interp(String::from("no argument"))),
3043    }
3044}
3045
3046/// A `removelocalvar` built-in function.
3047pub fn removelocalvar(_interp: &mut Interp, env: &mut Env, arg_values: &[Value]) -> Result<Value>
3048{
3049    if arg_values.len() != 1 {
3050        return Err(Error::Interp(String::from("invalid number of arguments")));
3051    }
3052    match arg_values.get(0) {
3053        Some(Value::Object(object)) => {
3054            match &**object {
3055                Object::String(ident) => Ok(Value::Bool(env.remove_local_var(ident))),
3056                _ => Err(Error::Interp(String::from("unsupported type for function removelocalvar"))),
3057            }
3058        },
3059        Some(_) => Err(Error::Interp(String::from("unsupported type for function removelocalvar"))),
3060        None => Err(Error::Interp(String::from("no argument"))),
3061    }
3062}
3063
3064/// A `checkintr` built-in function.
3065pub fn checkintr(_interp: &mut Interp, env: &mut Env, arg_values: &[Value]) -> Result<Value>
3066{
3067    if arg_values.len() != 0 {
3068        return Err(Error::Interp(String::from("invalid number of arguments")));
3069    }
3070    let intr_checker = {
3071        let shared_env_g = rw_lock_read(env.shared_env())?;
3072        shared_env_g.intr_checker().clone()
3073    };
3074    intr_checker.check()?;
3075    Ok(Value::None)
3076}
3077
3078/// A `backend` built-in function.
3079pub fn backend(_interp: &mut Interp, _env: &mut Env, arg_values: &[Value]) -> Result<Value>
3080{
3081    if arg_values.len() != 0 {
3082        return Err(Error::Interp(String::from("invalid number of arguments")));
3083    }
3084    Ok(Value::Object(Arc::new(Object::String(String::from(matrix_backend_name()?)))))
3085}
3086
3087/// A `version` built-in function.
3088pub fn version(_interp: &mut Interp, _env: &mut Env, arg_values: &[Value]) -> Result<Value>
3089{
3090    if arg_values.len() != 0 {
3091        return Err(Error::Interp(String::from("invalid number of arguments")));
3092    }
3093    Ok(Value::Object(Arc::new(Object::String(String::from(env!("CARGO_PKG_VERSION"))))))
3094}
3095
3096/// A `reqver` built-in function.
3097pub fn reqver(_interp: &mut Interp, _env: &mut Env, arg_values: &[Value]) -> Result<Value>
3098{
3099    if arg_values.len() != 1 {
3100        return Err(Error::Interp(String::from("invalid number of arguments")));
3101    }
3102    match arg_values.get(0) {
3103        Some(Value::Object(object)) => {
3104            match &**object {
3105                Object::String(s) => {
3106                    let version = Version::parse(env!("CARGO_PKG_VERSION"))?;
3107                    let version_req = VersionReq::parse(s.as_str())?;
3108                    if version_req.matches(&version) {
3109                        Ok(Value::None)
3110                    } else {
3111                        Err(Error::Interp(format!("unlab-gpu version {} isn't matched to version requirement {}", version, version_req)))
3112                    }
3113                },
3114                _ => Err(Error::Interp(String::from("unsupported type for function reqver"))),
3115            }
3116        },
3117        Some(_) => Err(Error::Interp(String::from("unsupported type for function reqver"))),
3118        None => Err(Error::Interp(String::from("no argument"))),
3119    }
3120}
3121
3122
3123/// A `docpath` built-in function.
3124pub fn docpath(_interp: &mut Interp, env: &mut Env, arg_values: &[Value]) -> Result<Value>
3125{
3126    if arg_values.len() != 0 {
3127        return Err(Error::Interp(String::from("invalid number of arguments")));
3128    }
3129    let shared_env_g = rw_lock_read(env.shared_env())?;
3130    Ok(Value::Object(Arc::new(Object::String(shared_env_g.doc_path().to_string_lossy().into_owned()))))
3131}
3132
3133/// A `doc` built-in function.
3134pub fn doc(_interp: &mut Interp, env: &mut Env, arg_values: &[Value]) -> Result<Value>
3135{
3136    if arg_values.len() > 2 {
3137        return Err(Error::Interp(String::from("invalid number of arguments")));
3138    }
3139    let lib_name = match arg_values.get(0) {
3140        Some(arg_value) => {
3141            match arg_value.to_opt_string() {
3142                Some(tmp_lib_name) => tmp_lib_name,
3143                None => return Err(Error::Interp(String::from("unsupported types for function doc"))),
3144            }
3145        },
3146        None => String::from("std/root"),
3147    };
3148    let idents = match arg_values.get(1) {
3149        Some(arg_value) => {
3150            match arg_value.to_opt_string() {
3151                Some(name) => {
3152                    let name_without_first_colons = if name.starts_with("::") {
3153                        &name[2..]
3154                    } else {
3155                        name.as_str()
3156                    };
3157                    let tmp_idents: Vec<String> = name_without_first_colons.split("::").map(String::from).collect();
3158                    match tmp_idents.first() {
3159                        Some(tmp_ident) if tmp_ident == &String::from("root") => Some((&tmp_idents[1..]).to_vec()),
3160                        Some(_) => Some(tmp_idents),
3161                        None => Some(Vec::new()),
3162                    }
3163                },
3164                None => return Err(Error::Interp(String::from("unsupported types for function doc"))),
3165            }
3166        },
3167        None => None,
3168    };
3169    let doc_path = {
3170        let shared_env_g = rw_lock_read(env.shared_env())?;
3171        OsString::from(shared_env_g.doc_path())
3172    };
3173    let mut res: Result<Value> = Ok(Value::None);
3174    for dir in std::env::split_paths(doc_path.as_os_str()) {
3175        let mut path = dir.clone();
3176        path.push(lib_name.replace('/', path::MAIN_SEPARATOR_STR));
3177        match &idents {
3178            Some(idents) => {
3179                path.push("root");
3180                for ident in idents {
3181                    path.push(ident);
3182                }
3183                path.set_extension("html");
3184            },
3185            None => path.push("index.html"),
3186        }
3187        match fs::metadata(path.as_path()) {
3188            Ok(_) => {
3189                let canon_path = match path.canonicalize() {
3190                    Ok(tmp_canon_path) => tmp_canon_path,
3191                    Err(err) => return Err(Error::Io(err)),
3192                };
3193                match open_browser(canon_path) {
3194                    Ok(()) => return Ok(Value::None),
3195                    Err(err) => return Err(Error::Opener(Box::new(err))),
3196                }
3197            },
3198            Err(err) if err.kind() == ErrorKind::NotFound => res = Err(Error::Io(err)),
3199            Err(err) => return Err(Error::Io(err)),
3200        }
3201    }
3202    res
3203}
3204
3205fn assert_op<F>(arg_values: &[Value], default_msg: Option<&str>, pair: Option<(Value, Value)>, f: F) -> Result<Value>
3206    where F: FnOnce() -> Result<bool>
3207{
3208    if !f()? {
3209        let msg = if !arg_values.is_empty() {
3210            let mut s = String::new();
3211            for arg_value in arg_values {
3212                s.push_str(format!("{}", arg_value).as_str());
3213            }
3214            Some(s)
3215        } else {
3216            match default_msg {
3217                Some(s) => Some(String::from(s)),
3218                None => None,
3219            }
3220        };
3221        return Err(Error::Assert(msg, pair));
3222    }
3223    Ok(Value::None)
3224}
3225
3226/// An `assert` built-in function.
3227pub fn assert(_interp: &mut Interp, _env: &mut Env, arg_values: &[Value]) -> Result<Value>
3228{
3229    if arg_values.len() < 1 {
3230        return Err(Error::Interp(String::from("invalid number of arguments")));
3231    }
3232    match arg_values.get(0) {
3233        Some(Value::Bool(b)) => assert_op(&arg_values[1..], None, None, || Ok(*b)),
3234        Some(_) => Err(Error::Interp(String::from("unsupported type for fuction assert"))),
3235        None => Err(Error::Interp(String::from("no argument"))),
3236    }                                    
3237}
3238
3239/// An `asserteq` built-in function.
3240pub fn asserteq(_interp: &mut Interp, _env: &mut Env, arg_values: &[Value]) -> Result<Value>
3241{
3242    if arg_values.len() < 2 {
3243        return Err(Error::Interp(String::from("invalid number of arguments")));
3244    }
3245    match (arg_values.get(0), arg_values.get(1)) {
3246        (Some(value), Some(value2)) => assert_op(&arg_values[2..], Some("left isn't equal to right"), Some((value.clone(), value2.clone())), || value.eq_without_types(&value2)),
3247        _ => Err(Error::Interp(String::from("no argument"))),
3248    }
3249}
3250
3251/// An `assertne` built-in function.
3252pub fn assertne(_interp: &mut Interp, _env: &mut Env, arg_values: &[Value]) -> Result<Value>
3253{
3254    if arg_values.len() < 2 {
3255        return Err(Error::Interp(String::from("invalid number of arguments")));
3256    }
3257    match (arg_values.get(0), arg_values.get(1)) {
3258        (Some(value), Some(value2)) => assert_op(&arg_values[2..], Some("left is equal to right"), Some((value.clone(), value2.clone())), || Ok(!value.eq_without_types(&value2)?)),
3259        _ => Err(Error::Interp(String::from("no argument"))),
3260    }
3261}
3262
3263/// An `assertnearlyeq` built-in function.
3264pub fn assertnearlyeq(_interp: &mut Interp, _env: &mut Env, arg_values: &[Value]) -> Result<Value>
3265{
3266    if arg_values.len() < 3 {
3267        return Err(Error::Interp(String::from("invalid number of arguments")));
3268    }
3269    match (arg_values.get(0), arg_values.get(1), arg_values.get(2)) {
3270        (Some(value), Some(value2), Some(eps_value @ (Value::Int(_) | Value::Float(_)))) => {
3271            let eps = eps_value.to_f32();
3272            assert_op(&arg_values[3..], Some("left isn't nearly equal to right"), Some((value.clone(), value2.clone())), || value.nearly_eq_without_types(&value2, eps))
3273        },
3274        (Some(_), Some(_), Some(_)) => Err(Error::Interp(String::from("unsupported types for fuction assertnearlyeq"))),
3275        _ => Err(Error::Interp(String::from("no argument"))),
3276    }
3277}
3278
3279/// An `assertnearlyne` built-in function.
3280pub fn assertnearlyne(_interp: &mut Interp, _env: &mut Env, arg_values: &[Value]) -> Result<Value>
3281{
3282    if arg_values.len() < 3 {
3283        return Err(Error::Interp(String::from("invalid number of arguments")));
3284    }
3285    match (arg_values.get(0), arg_values.get(1), arg_values.get(2)) {
3286        (Some(value), Some(value2), Some(eps_value @ (Value::Int(_) | Value::Float(_)))) => {
3287            let eps = eps_value.to_f32();
3288            assert_op(&arg_values[3..], Some("left is nearly equal to right"), Some((value.clone(), value2.clone())), || Ok(!value.nearly_eq_without_types(&value2, eps)?))
3289        },
3290        (Some(_), Some(_), Some(_)) => Err(Error::Interp(String::from("unsupported types for fuction assertnearlyne"))),
3291        _ => Err(Error::Interp(String::from("no argument"))),
3292    }
3293}
3294
3295/// A `tests` built-in function.
3296pub fn tests(_interp: &mut Interp, env: &mut Env, arg_values: &[Value]) -> Result<Value>
3297{
3298    if arg_values.len() != 0 {
3299        return Err(Error::Interp(String::from("invalid number of arguments")));
3300    }
3301    let mut shared_env_g = rw_lock_write(env.shared_env())?;
3302    shared_env_g.add_test_suite(env.mod_idents().to_vec());
3303    Ok(Value::None)
3304}
3305
3306/// Adds the built-in function to the root module.
3307pub fn add_builtin_fun(root_mod: &mut ModNode<Value, ()>, ident: String, f: fn(&mut Interp, &mut Env, &[Value]) -> Result<Value>)
3308{ root_mod.add_var(ident.clone(), Value::Object(Arc::new(Object::BuiltinFun(ident, f)))) }
3309
3310/// Adds the alias to the root module.
3311pub fn add_alias(root_mod: &mut ModNode<Value, ()>, new_ident: String, old_ident: &String)
3312{
3313    match root_mod.var(old_ident) {
3314        Some(value) => root_mod.add_var(new_ident, value.clone()),
3315        None => (),
3316    }
3317}
3318
3319/// Adds standard built-in functions to the root module.
3320pub fn add_std_builtin_funs(root_mod: &mut ModNode<Value, ()>)
3321{
3322    root_mod.add_var(String::from("pi"), Value::Float(f32::consts::PI));
3323    root_mod.add_var(String::from("e"), Value::Float(f32::consts::E));
3324    root_mod.add_var(String::from("eps"), Value::Float(f32::EPSILON));
3325    root_mod.add_var(String::from("pathsep"), Value::Object(Arc::new(Object::String(format!("{}", path::MAIN_SEPARATOR)))));
3326    add_builtin_fun(root_mod, String::from("type"), typ);
3327    add_builtin_fun(root_mod, String::from("clone"), clone);
3328    add_builtin_fun(root_mod, String::from("bool"), boolean);
3329    add_builtin_fun(root_mod, String::from("int"), int);
3330    add_builtin_fun(root_mod, String::from("float"), float);
3331    add_builtin_fun(root_mod, String::from("string"), string);
3332    add_builtin_fun(root_mod, String::from("zeros"), zeros);
3333    add_builtin_fun(root_mod, String::from("ones"), ones);
3334    add_builtin_fun(root_mod, String::from("eye"), eye);
3335    add_builtin_fun(root_mod, String::from("init"), init);
3336    add_builtin_fun(root_mod, String::from("initdiag"), initdiag);
3337    add_builtin_fun(root_mod, String::from("matrix"), matrix);
3338    add_builtin_fun(root_mod, String::from("rowvector"), rowvector);
3339    add_builtin_fun(root_mod, String::from("colvector"), colvector);
3340    add_builtin_fun(root_mod, String::from("matrixarray"), matrixarray);
3341    add_builtin_fun(root_mod, String::from("error"), error);
3342    add_builtin_fun(root_mod, String::from("array"), array);
3343    add_builtin_fun(root_mod, String::from("strong"), strong);
3344    add_builtin_fun(root_mod, String::from("weak"), weak);
3345    add_builtin_fun(root_mod, String::from("isempty"), isempty);
3346    add_builtin_fun(root_mod, String::from("length"), length);
3347    add_builtin_fun(root_mod, String::from("rows"), rows);
3348    add_builtin_fun(root_mod, String::from("columns"), columns);
3349    add_builtin_fun(root_mod, String::from("get"), get);
3350    add_builtin_fun(root_mod, String::from("getdiag"), getdiag);
3351    add_builtin_fun(root_mod, String::from("split"), split);
3352    add_builtin_fun(root_mod, String::from("trim"), trim);
3353    add_builtin_fun(root_mod, String::from("contains"), contains);
3354    add_builtin_fun(root_mod, String::from("startswith"), startswith);
3355    add_builtin_fun(root_mod, String::from("endswith"), endswith);
3356    add_builtin_fun(root_mod, String::from("replace"), replace);
3357    add_builtin_fun(root_mod, String::from("upper"), upper);
3358    add_builtin_fun(root_mod, String::from("lower"), lower);
3359    add_builtin_fun(root_mod, String::from("sort"), sort);
3360    add_builtin_fun(root_mod, String::from("reverse"), reverse);
3361    add_builtin_fun(root_mod, String::from("any"), any);
3362    add_builtin_fun(root_mod, String::from("all"), all);
3363    add_builtin_fun(root_mod, String::from("find"), find);
3364    add_builtin_fun(root_mod, String::from("filter"), filter);
3365    add_builtin_fun(root_mod, String::from("max"), max);
3366    add_builtin_fun(root_mod, String::from("min"), min);
3367    add_builtin_fun(root_mod, String::from("imax"), imax);
3368    add_builtin_fun(root_mod, String::from("imin"), imin);
3369    add_builtin_fun(root_mod, String::from("push"), push);
3370    add_builtin_fun(root_mod, String::from("pop"), pop);
3371    add_builtin_fun(root_mod, String::from("append"), append);
3372    add_builtin_fun(root_mod, String::from("insert"), insert);
3373    add_builtin_fun(root_mod, String::from("remove"), remove);
3374    add_builtin_fun(root_mod, String::from("errorkind"), errorkind);
3375    add_builtin_fun(root_mod, String::from("errormsg"), errormsg);
3376    add_builtin_fun(root_mod, String::from("isequal"), isequal);
3377    add_builtin_fun(root_mod, String::from("isnotequal"), isnotequal);
3378    add_builtin_fun(root_mod, String::from("isless"), isless);
3379    add_builtin_fun(root_mod, String::from("isgreaterequal"), isgreaterequal);
3380    add_builtin_fun(root_mod, String::from("isgreater"), isgreater);
3381    add_builtin_fun(root_mod, String::from("islessequal"), islessequal);
3382    add_builtin_fun(root_mod, String::from("sigmoid"), sigmoid);
3383    add_builtin_fun(root_mod, String::from("tanh"), tanh);
3384    add_builtin_fun(root_mod, String::from("swish"), swish);
3385    add_builtin_fun(root_mod, String::from("softmax"), softmax);
3386    add_builtin_fun(root_mod, String::from("sqrt"), sqrt);
3387    add_builtin_fun(root_mod, String::from("reallytranspose"), reallytranspose);
3388    add_alias(root_mod, String::from("rt"), &String::from("reallytranspose"));
3389    add_builtin_fun(root_mod, String::from("repeat"), repeat);
3390    add_builtin_fun(root_mod, String::from("mod"), modulo);
3391    add_builtin_fun(root_mod, String::from("abs"), abs);
3392    add_builtin_fun(root_mod, String::from("pow"), pow);
3393    add_builtin_fun(root_mod, String::from("exp"), exp);
3394    add_builtin_fun(root_mod, String::from("log"), log);
3395    add_builtin_fun(root_mod, String::from("log2"), log2);
3396    add_builtin_fun(root_mod, String::from("log10"), log10);
3397    add_builtin_fun(root_mod, String::from("sin"), sin);
3398    add_builtin_fun(root_mod, String::from("cos"), cos);
3399    add_builtin_fun(root_mod, String::from("tan"), tan);
3400    add_builtin_fun(root_mod, String::from("asin"), asin);
3401    add_builtin_fun(root_mod, String::from("acos"), acos);
3402    add_builtin_fun(root_mod, String::from("atan"), atan);
3403    add_builtin_fun(root_mod, String::from("atan2"), atan2);
3404    add_builtin_fun(root_mod, String::from("sinh"), sinh);
3405    add_builtin_fun(root_mod, String::from("cosh"), cosh);
3406    add_builtin_fun(root_mod, String::from("asinh"), asinh);
3407    add_builtin_fun(root_mod, String::from("acosh"), acosh);
3408    add_builtin_fun(root_mod, String::from("atanh"), atanh);
3409    add_builtin_fun(root_mod, String::from("sign"), sign);
3410    add_builtin_fun(root_mod, String::from("ceil"), ceil);
3411    add_builtin_fun(root_mod, String::from("floor"), floor);
3412    add_builtin_fun(root_mod, String::from("round"), round);
3413    add_builtin_fun(root_mod, String::from("trunc"), trunc);
3414    add_builtin_fun(root_mod, String::from("rand"), rand);
3415    add_builtin_fun(root_mod, String::from("randi"), randi);
3416    add_builtin_fun(root_mod, String::from("str2int"), str2int);
3417    add_builtin_fun(root_mod, String::from("str2float"), str2float);
3418    add_builtin_fun(root_mod, String::from("hex2dec"), hex2dec);
3419    add_builtin_fun(root_mod, String::from("char2code"), char2code);
3420    add_builtin_fun(root_mod, String::from("code2char"), code2char);
3421    add_builtin_fun(root_mod, String::from("formatmillis"), formatmillis);
3422    add_builtin_fun(root_mod, String::from("withwidth"), withwidth);
3423    add_builtin_fun(root_mod, String::from("withzeros"), withzeros);
3424    add_builtin_fun(root_mod, String::from("readline"), readline);
3425    add_builtin_fun(root_mod, String::from("format"), format);
3426    add_builtin_fun(root_mod, String::from("print"), print);
3427    add_builtin_fun(root_mod, String::from("println"), println);
3428    add_builtin_fun(root_mod, String::from("eprint"), eprint);
3429    add_builtin_fun(root_mod, String::from("eprintln"), eprintln);
3430    add_builtin_fun(root_mod, String::from("flush"), flush);
3431    add_builtin_fun(root_mod, String::from("eflush"), eflush);
3432    add_builtin_fun(root_mod, String::from("cd"), cd);
3433    add_builtin_fun(root_mod, String::from("pwd"), pwd);
3434    add_builtin_fun(root_mod, String::from("exist"), exist);
3435    add_builtin_fun(root_mod, String::from("filetype"), filetype);
3436    add_builtin_fun(root_mod, String::from("dir"), dir);
3437    add_alias(root_mod, String::from("ls"), &String::from("dir"));
3438    add_builtin_fun(root_mod, String::from("mkdir"), mkdir);
3439    add_builtin_fun(root_mod, String::from("rmdir"), rmdir);
3440    add_builtin_fun(root_mod, String::from("rmfile"), rmfile);
3441    add_builtin_fun(root_mod, String::from("copy"), copy);
3442    add_builtin_fun(root_mod, String::from("rename"), rename);
3443    add_builtin_fun(root_mod, String::from("spawn"), spawn);
3444    add_builtin_fun(root_mod, String::from("exit"), exit);
3445    add_builtin_fun(root_mod, String::from("load"), load);
3446    add_builtin_fun(root_mod, String::from("save"), save);
3447    add_builtin_fun(root_mod, String::from("loadstr"), loadstr);
3448    add_builtin_fun(root_mod, String::from("savestr"), savestr);
3449    add_builtin_fun(root_mod, String::from("loadtoml"), loadtoml);
3450    add_builtin_fun(root_mod, String::from("savetoml"), savetoml);
3451    add_builtin_fun(root_mod, String::from("loadjson"), loadjson);
3452    add_builtin_fun(root_mod, String::from("savejson"), savejson);
3453    add_builtin_fun(root_mod, String::from("args"), args);
3454    add_builtin_fun(root_mod, String::from("env"), env);
3455    add_builtin_fun(root_mod, String::from("scriptdir"), scriptdir);
3456    add_builtin_fun(root_mod, String::from("libpath"), libpath);
3457    add_builtin_fun(root_mod, String::from("domain"), domain);
3458    add_builtin_fun(root_mod, String::from("uselib"), uselib);
3459    add_builtin_fun(root_mod, String::from("reuselib"), reuselib);
3460    add_builtin_fun(root_mod, String::from("run"), run);
3461    add_alias(root_mod, String::from("runwithdoc"), &String::from("run"));
3462    add_builtin_fun(root_mod, String::from("clock"), clock);
3463    add_builtin_fun(root_mod, String::from("usemod"), usemod);
3464    add_builtin_fun(root_mod, String::from("usemods"), usemods);
3465    add_builtin_fun(root_mod, String::from("usevar"), usevar);
3466    add_builtin_fun(root_mod, String::from("usevars"), usevars);
3467    add_builtin_fun(root_mod, String::from("removeusemod"), removeusemod);
3468    add_builtin_fun(root_mod, String::from("removeusevar"), removeusevar);
3469    add_builtin_fun(root_mod, String::from("removemod"), removemod);
3470    add_builtin_fun(root_mod, String::from("removevar"), removevar);
3471    add_builtin_fun(root_mod, String::from("removelocalvar"), removelocalvar);
3472    add_builtin_fun(root_mod, String::from("checkintr"), checkintr);
3473    add_builtin_fun(root_mod, String::from("backend"), backend);
3474    add_builtin_fun(root_mod, String::from("version"), version);
3475    add_builtin_fun(root_mod, String::from("reqver"), reqver);
3476    add_builtin_fun(root_mod, String::from("docpath"), docpath);
3477    add_builtin_fun(root_mod, String::from("doc"), doc);
3478    add_alias(root_mod, String::from("help"), &String::from("doc"));
3479    add_builtin_fun(root_mod, String::from("assert"), assert);
3480    add_builtin_fun(root_mod, String::from("asserteq"), asserteq);
3481    add_builtin_fun(root_mod, String::from("assertne"), assertne);
3482    add_builtin_fun(root_mod, String::from("assertnearlyeq"), assertnearlyeq);
3483    add_builtin_fun(root_mod, String::from("assertnearlyne"), assertnearlyne);
3484    add_builtin_fun(root_mod, String::from("tests"), tests);
3485    add_builtin_fun(root_mod, String::from("getopts"), getopts);
3486    add_builtin_fun(root_mod, String::from("getoptsusage"), getoptsusage);
3487    #[cfg(feature = "plot")]
3488    add_builtin_fun(root_mod, String::from("plot"), plot);
3489    #[cfg(feature = "plot")]
3490    add_builtin_fun(root_mod, String::from("plot3"), plot3);
3491    #[cfg(feature = "plot")]
3492    add_builtin_fun(root_mod, String::from("histogram"), histogram);
3493    #[cfg(feature = "plot")]
3494    add_alias(root_mod, String::from("hist"), &String::from("histogram"));
3495}
3496
3497#[cfg(test)]
3498mod tests;