seraphine_core/
lib.rs

1mod common;
2pub mod error;
3pub mod eval;
4pub mod io;
5pub mod parser;
6pub mod tokenizer;
7
8#[cfg(test)]
9mod tests {
10    use std::io::Write;
11
12    use crate::{
13        error::SeraphineError,
14        eval::{Context, Value},
15        io,
16    };
17
18    fn eval_str(s: &str) -> Result<Value, SeraphineError> {
19        Context::new().eval_str(s)
20    }
21
22    fn eval_str_ctx(s: &str, ctx: &mut Context) -> Result<Value, SeraphineError> {
23        ctx.eval_str(s)
24    }
25
26    macro_rules! assert_null {
27        ( $value:expr ) => {
28            match $value {
29                $crate::eval::Value::Null => {}
30                value => {
31                    ::std::panic!("value is not null: {:?}", value);
32                }
33            }
34        };
35    }
36
37    macro_rules! assert_eq_num {
38        ( $left:expr, $right:expr ) => {
39            match ($left, $right) {
40                (value, expected) => {
41                    let $crate::eval::Value::Number(got) = value else {
42                        ::std::panic!("value is not a number");
43                    };
44                    ::std::assert_eq!(got, expected);
45                }
46            }
47        };
48        ( $left:expr, $right:expr, $eps:expr ) => {
49            match ($left, $right) {
50                (value, expected) => {
51                    let $crate::eval::Value::Number(got) = value else {
52                        ::std::panic!("value is not a number");
53                    };
54                    ::std::assert!((got - expected).abs() < $eps);
55                }
56            }
57        };
58    }
59
60    macro_rules! assert_eq_bool {
61        ( $left:expr, $right:expr ) => {
62            match ($left, $right) {
63                (value, expected) => {
64                    let $crate::eval::Value::Bool(got) = value else {
65                        ::std::panic!("value is not a bool");
66                    };
67                    ::std::assert_eq!(got, expected);
68                }
69            }
70        };
71    }
72
73    macro_rules! assert_eq_str {
74        ( $left:expr, $right:expr ) => {
75            match ($left, $right) {
76                (value, expected) => {
77                    let $crate::eval::Value::String(got) = value else {
78                        ::std::panic!("value is not a string");
79                    };
80                    ::std::assert_eq!(got, expected);
81                }
82            }
83        };
84    }
85
86    macro_rules! assert_eq_num_list {
87        ( $left:expr, $right:expr ) => {
88            match ($left, $right) {
89                (value, expected) => {
90                    let $crate::eval::Value::List(got) = value else {
91                        ::std::panic!("value is not a list");
92                    };
93                    let got = got.borrow();
94                    ::std::assert_eq!(got.len(), expected.len(), "length mismatch");
95                    for (i, (got, expected)) in got.iter().zip(expected.iter()).enumerate() {
96                        let $crate::eval::Value::Number(got) = got else {
97                            ::std::panic!("value is not a number");
98                        };
99                        ::std::assert_eq!(*got, *expected, "at index {}", i);
100                    }
101                }
102            }
103        };
104    }
105
106    /// Asserts that the given object has the given keys and values.
107    ///
108    /// Note that the object syntax is different from the one used in the language, since
109    /// `macro_rules` cannot parse it.
110    ///
111    /// Example:
112    /// ```rust
113    /// assert_eq_num_object!(eval_str("{ a: 1, b: 2 }"), { "a" => 1.0, "b" => 2.0 });
114    /// ```
115    macro_rules! assert_eq_num_object {
116        ( $obj:expr, { $( $key:expr => $val:expr ),* } ) => {
117            {
118                let $crate::eval::Value::Object(obj) = $obj else {
119                    ::std::panic!("value is not an object");
120                };
121                #[allow(unused_variables)]
122                let obj = obj.borrow();
123                #[allow(unused_mut)]
124                let mut keys = 0;
125                $(
126                    let got_val = obj.get($key);
127                    ::std::assert!(got_val.is_some(), r#"key "{}" not found in object"#, $key);
128                    let $crate::eval::Value::Number(got) = got_val.unwrap() else {
129                        ::std::panic!("value is not a number");
130                    };
131                    ::std::assert_eq!(*got, $val, "at key {}", $key);
132                    keys += 1;
133                )*
134                ::std::assert_eq!(keys, obj.len(), "length mismatch");
135            }
136        };
137    }
138
139    #[test]
140    fn test_eval_str() {
141        assert!(eval_str("").is_ok());
142        assert!(eval_str("-").is_err());
143        assert!(eval_str("* 2").is_err());
144        assert!(eval_str("2 +").is_err());
145        assert_eq_num!(eval_str("2").unwrap(), 2.0);
146        assert_eq_num!(eval_str("2 - 3").unwrap(), -1.0);
147        assert_eq_num!(eval_str("2-3").unwrap(), -1.0);
148        assert_eq_num!(eval_str("2 + 2 * 2").unwrap(), 6.0);
149        assert_eq_num!(eval_str("3 * 2 * 5 + 10 / 5 - 8").unwrap(), 24.0);
150    }
151
152    #[test]
153    fn test_precedence_bug_fix() {
154        assert_eq_num!(eval_str("1 + 2 ^ 2 * 2").unwrap(), 9.0);
155    }
156
157    #[test]
158    fn test_number_parsing() {
159        assert!(eval_str(".1").is_ok());
160        assert!(eval_str("1.1").is_ok());
161        assert!(eval_str("1.").is_ok());
162        assert!(eval_str("1e9").is_ok());
163        assert!(eval_str(".1e9").is_ok());
164        assert!(eval_str("1e-9").is_ok());
165        assert!(eval_str("42e0").is_ok());
166        assert!(eval_str("8.e2").is_ok());
167
168        assert!(eval_str("2.3.4").is_err());
169        assert!(eval_str("..").is_err());
170        assert!(eval_str("..1").is_err());
171        assert!(eval_str("1..").is_err());
172        assert!(eval_str(".1.").is_err());
173        assert!(eval_str(".e9").is_err());
174        assert!(eval_str(".e").is_err());
175        assert!(eval_str("1e9e4").is_err());
176        assert!(eval_str("1e42.1").is_err());
177    }
178
179    #[test]
180    fn test_unary_minus() {
181        assert_eq_num!(eval_str("-2").unwrap(), -2.0);
182        assert_eq_num!(eval_str("2--2").unwrap(), 4.0);
183        assert_eq_num!(eval_str("2+-2").unwrap(), 0.0);
184        assert_eq_num!(eval_str("-2+-2").unwrap(), -4.0);
185        assert_eq_num!(eval_str("2---2").unwrap(), 0.0);
186        assert!(eval_str("2*+-2").is_err());
187
188        assert!(eval_str("-true").is_err());
189    }
190
191    #[test]
192    fn test_brackets() {
193        assert_eq_num!(eval_str("4 * (5 - 1)").unwrap(), 16.0);
194        assert_eq_num!(eval_str("(2 + 2) * (3 + 3)").unwrap(), 24.0);
195        assert_eq_num!(eval_str("(2 + 2)").unwrap(), 4.0);
196        assert_eq_num!(eval_str("-(2 + 2)").unwrap(), -4.0);
197        assert_eq_num!(eval_str("-((2 + 3) * 4)").unwrap(), -20.0);
198        assert_eq_num!(eval_str("-((2 + -4) * 5) / 2").unwrap(), 5.0);
199        assert_eq_num!(eval_str("(1 + 2) + 3").unwrap(), 6.0);
200        assert!(eval_str("-2 + 2)").is_err());
201        assert!(eval_str("-(2 + 2").is_err());
202        assert!(eval_str("()").is_err());
203    }
204
205    #[test]
206    fn test_power() {
207        assert!(eval_str("4 ^").is_err());
208        assert!(eval_str("^ 3").is_err());
209        assert_eq_num!(eval_str("1 ^ -3").unwrap(), 1.0);
210        assert_eq_num!(eval_str("(-1) ^ -3").unwrap(), -1.0);
211        assert_eq_num!(eval_str("(-1) ^ -4").unwrap(), 1.0);
212        assert_eq_num!(eval_str("2 ^ -3").unwrap(), 0.125);
213        assert_eq_num!(eval_str("2 ^ 0").unwrap(), 1.0);
214        assert_eq_num!(eval_str("3 ^ 5").unwrap(), 243.0);
215        assert_eq_num!(eval_str("-1 ^ 4").unwrap(), 1.0);
216        assert_eq_num!(eval_str("-1 ^ 5").unwrap(), -1.0);
217        assert_eq_num!(eval_str("-1 ^ -5").unwrap(), -1.0);
218        assert_eq_num!(eval_str("(1 + 1) ^ (4 * 2)").unwrap(), 256.0);
219
220        assert!(eval_str("true ^ true").is_err());
221    }
222
223    #[test]
224    fn test_mod() {
225        assert!(eval_str("2 %").is_err());
226        assert!(eval_str("% 3").is_err());
227        assert_eq_bool!(eval_str("is_nan(100 % 0)").unwrap(), true);
228        assert_eq_num!(eval_str("7 % 3").unwrap(), 1.0);
229        assert_eq_num!(eval_str("7 % -3").unwrap(), 1.0);
230        assert_eq_num!(eval_str("-7 % 3").unwrap(), -1.0);
231        assert_eq_num!(eval_str("-9 % -3").unwrap(), 0.0);
232        assert_eq_num!(eval_str("42 % 1337").unwrap(), 42.0);
233        assert_eq_num!(eval_str("2 + 3 * 4 % 5").unwrap(), 4.0);
234
235        assert!(eval_str("true % false").is_err());
236    }
237
238    #[test]
239    fn test_variables() {
240        let mut ctx = Context::new();
241        assert!(eval_str_ctx("a = 2", &mut ctx).is_ok());
242        assert!(eval_str_ctx("b = a + 1", &mut ctx).is_ok());
243        assert!(eval_str_ctx("c = a + b", &mut ctx).is_ok());
244        assert_eq_num!(ctx.get_var("a").unwrap(), 2.0);
245        assert_eq_num!(ctx.get_var("b").unwrap(), 3.0);
246        assert_eq_num!(ctx.get_var("c").unwrap(), 5.0);
247
248        assert!(eval_str("not_defined").is_err());
249
250        let mut ctx = Context::new();
251        assert!(eval_str_ctx("some_longer_name = 2", &mut ctx).is_ok());
252        assert_eq_num!(ctx.get_var("some_longer_name").unwrap(), 2.0);
253
254        assert!(eval_str("a b = 2").is_err());
255        assert!(eval_str("2 = 2").is_err());
256        assert!(eval_str("* = 2").is_err());
257        assert!(eval_str("() = 2").is_err());
258    }
259
260    #[test]
261    fn test_builtin_functions() {
262        use std::f64::consts;
263
264        let eps = 1e-10;
265        assert_eq_num!(eval_str("sin(pi/2)").unwrap(), 1.0, eps);
266        assert_eq_num!(eval_str("cos(pi/2)").unwrap(), 0.0, eps);
267        assert_eq_num!(eval_str("tan(pi/4)").unwrap(), 1.0, eps);
268        assert_eq_num!(eval_str("asin(1)").unwrap(), consts::FRAC_PI_2, eps);
269        assert_eq_num!(eval_str("acos(1)").unwrap(), 0.0, eps);
270        assert_eq_num!(eval_str("atan(1)").unwrap(), consts::FRAC_PI_4, eps);
271        assert_eq_num!(eval_str("sinh(1)").unwrap(), 1_f64.sinh(), eps);
272        assert_eq_num!(eval_str("cosh(1)").unwrap(), 1_f64.cosh(), eps);
273        assert_eq_num!(eval_str("tanh(1)").unwrap(), 1_f64.tanh(), eps);
274
275        assert_eq_num!(eval_str("ln(e)").unwrap(), 1.0, eps);
276        assert_eq_num!(eval_str("log2(1024)").unwrap(), 10.0, eps);
277        assert_eq_num!(eval_str("log10(1000)").unwrap(), 3.0, eps);
278        assert_eq_num!(eval_str("log(27, 3)").unwrap(), 3.0, eps);
279        assert_eq_bool!(eval_str("is_nan(log(42, -21))").unwrap(), true);
280
281        assert_eq_num!(eval_str("abs(-1)").unwrap(), 1.0, eps);
282        assert_eq_num!(eval_str("abs(1)").unwrap(), 1.0, eps);
283        assert_eq_num!(eval_str("min(1, 5)").unwrap(), 1.0, eps);
284        assert_eq_num!(eval_str("max(1, 5)").unwrap(), 5.0, eps);
285        assert_eq_num!(eval_str("floor(1.5)").unwrap(), 1.0, eps);
286        assert_eq_num!(eval_str("ceil(1.5)").unwrap(), 2.0, eps);
287        assert_eq_num!(eval_str("round(1.5)").unwrap(), 2.0, eps);
288        assert_eq_num!(eval_str("round(1.4)").unwrap(), 1.0, eps);
289        assert_eq_num!(eval_str("round(1.6)").unwrap(), 2.0, eps);
290
291        assert_eq_num!(eval_str("sqrt(4)").unwrap(), 2.0, eps);
292        assert_eq_bool!(eval_str("is_nan(sqrt(-1))").unwrap(), true);
293        assert_eq_num!(eval_str("exp(2)").unwrap(), 7.389056099, eps);
294
295        assert!(eval_str("exp(true)").is_err());
296
297        assert_eq_bool!(eval_str("is_nan(nan)").unwrap(), true);
298        assert_eq_bool!(eval_str("is_nan(inf)").unwrap(), false);
299        assert_eq_bool!(eval_str("is_nan(42)").unwrap(), false);
300        assert_eq_bool!(eval_str("is_infinite(nan)").unwrap(), false);
301        assert_eq_bool!(eval_str("is_infinite(inf)").unwrap(), true);
302        assert_eq_bool!(eval_str("is_infinite(42)").unwrap(), false);
303        assert_eq_bool!(eval_str("is_infinite(1/0)").unwrap(), true);
304        assert_eq_bool!(eval_str("is_finite(nan)").unwrap(), false);
305        assert_eq_bool!(eval_str("is_finite(inf)").unwrap(), false);
306        assert_eq_bool!(eval_str("is_finite(42)").unwrap(), true);
307    }
308
309    #[test]
310    fn test_functions() {
311        let mut ctx = Context::new();
312        ctx.add_builtin_function("add", Some(2), |_ctx, _this, args| {
313            let Value::Number(arg1) = args[0] else {
314                unreachable!()
315            };
316            let Value::Number(arg2) = args[1] else {
317                unreachable!()
318            };
319            Ok(Value::Number(arg1 + arg2))
320        });
321
322        assert!(eval_str_ctx("add()", &mut ctx).is_err());
323        assert!(eval_str_ctx("add(1)", &mut ctx).is_err());
324        assert!(eval_str_ctx("add(1,)", &mut ctx).is_err());
325        assert!(eval_str_ctx("add(,1)", &mut ctx).is_err());
326        assert!(eval_str_ctx("add(1 1)", &mut ctx).is_err());
327        assert_eq_num!(eval_str_ctx("add(1, 2)", &mut ctx).unwrap(), 3.0);
328        assert!(eval_str_ctx("add(1, 2, 3)", &mut ctx).is_err());
329        assert_eq_num!(eval_str_ctx("add(1, add(2, 3))", &mut ctx).unwrap(), 6.0);
330    }
331
332    #[test]
333    fn test_multiple_lines() {
334        let mut ctx = Context::new();
335
336        eval_str_ctx(
337            r"a = 2
338            b = 3
339            c = a + b",
340            &mut ctx,
341        )
342        .unwrap();
343
344        assert_eq_num!(ctx.get_var("a").unwrap(), 2.0);
345        assert_eq_num!(ctx.get_var("b").unwrap(), 3.0);
346        assert_eq_num!(ctx.get_var("c").unwrap(), 5.0);
347
348        assert_eq_num!(eval_str("\n42\n").unwrap(), 42.0);
349        assert_eq_num!(eval_str("42\n").unwrap(), 42.0);
350        assert_eq_num!(eval_str("\n42").unwrap(), 42.0);
351        assert_null!(eval_str("\n\n\n").unwrap());
352    }
353
354    #[test]
355    fn test_user_functions() {
356        let code = "\
357            fn add(a, b, c) {\n\
358                a + b + c\n\
359            }\n\
360            \n\
361            fn sub(a, b) {\n\
362                a - b\n\
363            }\n\
364            \n\
365            sub(42, add(1, 2, 3))";
366        assert_eq_num!(eval_str(code).unwrap(), 36.0);
367
368        assert!(eval_str("fn add(a, {b) a + b }").is_err());
369        assert!(eval_str("fn empty_body() {}").is_ok());
370        assert!(eval_str("fn no_args() {\n inspect(1)\n }").is_ok());
371        assert!(eval_str("fn one_liner(a, b) { a + b }").is_ok());
372        assert!(eval_str("fn trailing_comma(a, b,) { a + b }").is_ok());
373        assert!(eval_str("fn leading_comma(, a, b) { a + b }").is_err());
374        assert!(eval_str("fn no_comma(a b) { a + b }").is_err());
375        assert!(eval_str("fn contains_expression(a, b, 1 + 1) { a + b }").is_err());
376        assert!(eval_str("fn duplicate_arg_name(a, a) { a + a }").is_err());
377    }
378
379    #[test]
380    fn test_if_statements() {
381        let code = "\
382            a = 0
383            if (false) {
384                a = 2
385            }
386            a";
387        assert_eq_num!(eval_str(code).unwrap(), 0.0);
388
389        let code = "\
390            a = 0
391            if (true) {
392                a = 2
393            }
394            a";
395        assert_eq_num!(eval_str(code).unwrap(), 2.0);
396
397        let code = "\
398            a = 0
399            if (false) {
400                a = 2
401            } else {
402                a = 3
403            }
404            a";
405        assert_eq_num!(eval_str(code).unwrap(), 3.0);
406
407        let code = "\
408            a = 0
409            if (true) {
410                a = 2
411            } else {
412                a = 3
413            }
414            a";
415        assert_eq_num!(eval_str(code).unwrap(), 2.0);
416
417        let code = "\
418            a = 0
419            if (false) {
420                a = 2
421            } else if (false) {
422                a = 3
423            }
424            a";
425        assert_eq_num!(eval_str(code).unwrap(), 0.0);
426
427        let code = "\
428            a = 0
429            if (false) {
430                a = 2
431            } else if (false) {
432                a = 3
433            } else {
434                a = 4
435            }
436            a";
437        assert_eq_num!(eval_str(code).unwrap(), 4.0);
438
439        let code = "\
440            a = 0
441            if (true) {
442                a = 2
443            } else if (false) {
444                a = 3
445            } else {
446                a = 4
447            }
448            a";
449        assert_eq_num!(eval_str(code).unwrap(), 2.0);
450
451        let code = "\
452            a = 0
453            if (true) {
454                a = 2
455            } else if (true) {
456                a = 3
457            } else {
458                a = 4
459            }
460            a";
461        assert_eq_num!(eval_str(code).unwrap(), 2.0);
462
463        let code = "\
464            a = 0
465            if (false) {
466                a = 2
467            } else if (true) {
468                a = 3
469            } else {
470                a = 4
471            }
472            a";
473        assert_eq_num!(eval_str(code).unwrap(), 3.0);
474
475        let code = "\
476            a = 0
477            if (false) {
478                a = 2
479            } else if (false) {
480                a = 3
481            } else if (true) {
482                a = 4
483            } else {
484                a = 5
485            }
486            a";
487        assert_eq_num!(eval_str(code).unwrap(), 4.0);
488    }
489
490    #[test]
491    fn test_boolean_negate_operator() {
492        assert_eq_bool!(eval_str("!1").unwrap(), false);
493        assert_eq_bool!(eval_str("!0.01").unwrap(), false);
494        assert_eq_bool!(eval_str("!0.00001").unwrap(), false);
495        assert_eq_bool!(eval_str("!42").unwrap(), false);
496        assert_eq_bool!(eval_str("!-42").unwrap(), false);
497        assert_eq_bool!(eval_str("!-1").unwrap(), false);
498        assert_eq_bool!(eval_str("!!42").unwrap(), true);
499
500        assert_eq_bool!(eval_str("!true").unwrap(), false);
501        assert_eq_bool!(eval_str("!!!true").unwrap(), false);
502        assert_eq_bool!(eval_str("!false").unwrap(), true);
503    }
504
505    #[test]
506    fn test_equality_operator() {
507        assert_eq_bool!(eval_str("1 == 0").unwrap(), false);
508        assert_eq_bool!(eval_str("-1 == -2").unwrap(), false);
509        assert_eq_bool!(eval_str("42 == 21").unwrap(), false);
510        assert_eq_bool!(eval_str("0 == 0").unwrap(), true);
511        assert_eq_bool!(eval_str("42 == 42").unwrap(), true);
512        assert_eq_bool!(eval_str("-1 == -1").unwrap(), true);
513        assert_eq_bool!(eval_str("-0 == 0").unwrap(), true);
514
515        assert_eq_bool!(eval_str("true == true").unwrap(), true);
516        assert_eq_bool!(eval_str("false == true").unwrap(), false);
517        assert_eq_bool!(eval_str("1.0 == true").unwrap(), false);
518        assert_eq_bool!(eval_str("false == 0.0").unwrap(), false);
519    }
520
521    #[test]
522    fn test_inequality_operator() {
523        assert_eq_bool!(eval_str("1 != 0").unwrap(), true);
524        assert_eq_bool!(eval_str("-1 != -2").unwrap(), true);
525        assert_eq_bool!(eval_str("42 != 21").unwrap(), true);
526        assert_eq_bool!(eval_str("-42 != 42").unwrap(), true);
527        assert_eq_bool!(eval_str("0 != 0").unwrap(), false);
528        assert_eq_bool!(eval_str("42 != 42").unwrap(), false);
529        assert_eq_bool!(eval_str("-1 != -1").unwrap(), false);
530        assert_eq_bool!(eval_str("-0 != 0").unwrap(), false);
531
532        assert_eq_bool!(eval_str("true != true").unwrap(), false);
533        assert_eq_bool!(eval_str("false != true").unwrap(), true);
534        assert_eq_bool!(eval_str("1.0 != true").unwrap(), true);
535        assert_eq_bool!(eval_str("false != 0.0").unwrap(), true);
536    }
537
538    #[test]
539    fn test_less_than_operator() {
540        assert_eq_bool!(eval_str("0 < 1").unwrap(), true);
541        assert_eq_bool!(eval_str("-2 < -1").unwrap(), true);
542        assert_eq_bool!(eval_str("42 < 21").unwrap(), false);
543        assert_eq_bool!(eval_str("-42 < 42").unwrap(), true);
544        assert_eq_bool!(eval_str("0 < 0").unwrap(), false);
545        assert_eq_bool!(eval_str("42 < 42").unwrap(), false);
546        assert_eq_bool!(eval_str("-1 < -1").unwrap(), false);
547        assert_eq_bool!(eval_str("-0 < 0").unwrap(), false);
548
549        assert!(eval_str("true < 2").is_err());
550        assert!(eval_str("true < false").is_err());
551        assert!(eval_str("7 < false").is_err());
552    }
553
554    #[test]
555    fn test_greater_than_operator() {
556        assert_eq_bool!(eval_str("0 > 1").unwrap(), false);
557        assert_eq_bool!(eval_str("-2 > -1").unwrap(), false);
558        assert_eq_bool!(eval_str("42 > 21").unwrap(), true);
559        assert_eq_bool!(eval_str("-42 > 42").unwrap(), false);
560        assert_eq_bool!(eval_str("0 > 0").unwrap(), false);
561        assert_eq_bool!(eval_str("42 > 42").unwrap(), false);
562        assert_eq_bool!(eval_str("-1 > -1").unwrap(), false);
563        assert_eq_bool!(eval_str("-0 > 0").unwrap(), false);
564
565        assert!(eval_str("true > 2").is_err());
566        assert!(eval_str("true > false").is_err());
567        assert!(eval_str("7 > false").is_err());
568    }
569
570    #[test]
571    fn test_less_than_or_equal_operator() {
572        assert_eq_bool!(eval_str("0 <= 1").unwrap(), true);
573        assert_eq_bool!(eval_str("-2 <= -1").unwrap(), true);
574        assert_eq_bool!(eval_str("42 <= 21").unwrap(), false);
575        assert_eq_bool!(eval_str("-42 <= 42").unwrap(), true);
576        assert_eq_bool!(eval_str("0 <= 0").unwrap(), true);
577        assert_eq_bool!(eval_str("42 <= 42").unwrap(), true);
578        assert_eq_bool!(eval_str("-1 <= -1").unwrap(), true);
579        assert_eq_bool!(eval_str("-0 <= 0").unwrap(), true);
580
581        assert!(eval_str("true <= 2").is_err());
582        assert!(eval_str("true <= false").is_err());
583        assert!(eval_str("7 <= false").is_err());
584    }
585
586    #[test]
587    fn test_greater_than_or_equal_operator() {
588        assert_eq_bool!(eval_str("0 >= 1").unwrap(), false);
589        assert_eq_bool!(eval_str("-2 >= -1").unwrap(), false);
590        assert_eq_bool!(eval_str("42 >= 21").unwrap(), true);
591        assert_eq_bool!(eval_str("-42 >= 42").unwrap(), false);
592        assert_eq_bool!(eval_str("0 >= 0").unwrap(), true);
593        assert_eq_bool!(eval_str("42 >= 42").unwrap(), true);
594        assert_eq_bool!(eval_str("-1 >= -1").unwrap(), true);
595        assert_eq_bool!(eval_str("-0 >= 0").unwrap(), true);
596
597        assert!(eval_str("true >= 2").is_err());
598        assert!(eval_str("true >= false").is_err());
599        assert!(eval_str("7 >= false").is_err());
600    }
601
602    #[test]
603    fn test_and_operator() {
604        assert_eq_bool!(eval_str("0 && 0").unwrap(), false);
605        assert_eq_bool!(eval_str("8 && 0").unwrap(), false);
606        assert_eq_bool!(eval_str("-7 && 0").unwrap(), false);
607        assert_eq_bool!(eval_str("0 && 15").unwrap(), false);
608        assert_eq_bool!(eval_str("0 && -27").unwrap(), false);
609        assert_eq_bool!(eval_str("18 && 1").unwrap(), true);
610        assert_eq_bool!(eval_str("42 && -42").unwrap(), true);
611
612        let code = "\
613            a = 2
614            a > 0 && a > 1";
615        assert_eq_bool!(eval_str(code).unwrap(), true);
616
617        assert_eq_bool!(eval_str("1 + 1 > 1 && 2 + 2 > 2").unwrap(), true);
618
619        assert_eq_bool!(eval_str("false && true").unwrap(), false);
620        assert_eq_bool!(eval_str("false && false").unwrap(), false);
621        assert_eq_bool!(eval_str("true && true").unwrap(), true);
622        assert_eq_bool!(eval_str("1 && true").unwrap(), true);
623    }
624
625    #[test]
626    fn test_and_operator_short_circuit() {
627        let mut ctx = Context::new();
628        let code = "\
629            fn set_a() {
630                _set_internal_side_effect_flag()
631                true
632            }
633            false && set_a()
634        ";
635        eval_str_ctx(code, &mut ctx).unwrap();
636        assert!(!ctx._internal_side_effect_flag);
637
638        let mut ctx = Context::new();
639        let code = "\
640            fn set_a() {
641                _set_internal_side_effect_flag()
642                true
643            }
644            true && set_a()
645        ";
646        eval_str_ctx(code, &mut ctx).unwrap();
647        assert!(ctx._internal_side_effect_flag);
648    }
649
650    #[test]
651    fn test_or_operator() {
652        assert_eq_bool!(eval_str("0 || 0").unwrap(), false);
653        assert_eq_bool!(eval_str("8 || 0").unwrap(), true);
654        assert_eq_bool!(eval_str("-7 || 0").unwrap(), true);
655        assert_eq_bool!(eval_str("0 || 15").unwrap(), true);
656        assert_eq_bool!(eval_str("0 || -27").unwrap(), true);
657        assert_eq_bool!(eval_str("18 || 1").unwrap(), true);
658        assert_eq_bool!(eval_str("42 || -42").unwrap(), true);
659
660        assert_eq_bool!(eval_str("false || true").unwrap(), true);
661        assert_eq_bool!(eval_str("false || false").unwrap(), false);
662        assert_eq_bool!(eval_str("true || true").unwrap(), true);
663        assert_eq_bool!(eval_str("1 || true").unwrap(), true);
664    }
665
666    #[test]
667    fn test_or_operator_short_circuit() {
668        let mut ctx = Context::new();
669        let code = "\
670            fn set_a() {
671                _set_internal_side_effect_flag()
672                true
673            }
674            false || set_a()
675        ";
676        eval_str_ctx(code, &mut ctx).unwrap();
677        assert!(ctx._internal_side_effect_flag);
678
679        let mut ctx = Context::new();
680        let code = "\
681            fn set_a() {
682                _set_internal_side_effect_flag()
683                true
684            }
685            true || set_a()
686        ";
687        eval_str_ctx(code, &mut ctx).unwrap();
688        assert!(!ctx._internal_side_effect_flag);
689    }
690
691    #[test]
692    fn test_while_loop() {
693        let code = "\
694            a = 0
695            while (0) {
696                a = 1
697            }
698            a";
699        assert_eq_num!(eval_str(code).unwrap(), 0.0);
700
701        let code = "\
702            a = 0
703            while (2 * a < 10) {
704                a = a + 1
705            }
706            a";
707        assert_eq_num!(eval_str(code).unwrap(), 5.0);
708    }
709
710    #[test]
711    fn test_continue_statement() {
712        assert!(eval_str("continue").is_err());
713        assert!(eval_str("while (true) { continue 42 }").is_err());
714
715        let code = "\
716            fn my_func() {
717                continue
718            }
719
720            a = 0
721            b = 0
722            while (a == 0) {
723                a = 1
724                my_func()
725                b = 1
726            }
727            b
728        ";
729        assert!(eval_str(code).is_err());
730
731        let code = "\
732            a = 0
733            b = 0
734            while (a < 10) {
735                a = a + 1
736                if (a % 2 == 0) {
737                    continue
738                }
739                b = b + 1
740            }
741            b";
742        assert_eq_num!(eval_str(code).unwrap(), 5.0);
743    }
744
745    #[test]
746    fn test_break_statement() {
747        assert!(eval_str("break").is_err());
748        assert!(eval_str("while (true) { break 42 }").is_err());
749
750        let code = "\
751            fn my_func() {
752                break
753            }
754
755            a = 0
756            b = 0
757            while (a == 0) {
758                a = 1
759                my_func()
760                b = 1
761            }
762            b
763        ";
764        assert!(eval_str(code).is_err());
765
766        let code = "\
767            a = 0
768            b = 0
769            while (a < 10) {
770                a = a + 1
771                if (a % 3 == 0) {
772                    break
773                }
774                b = b + 1
775            }
776            b";
777        assert_eq_num!(eval_str(code).unwrap(), 2.0);
778    }
779
780    #[test]
781    fn test_return_statement() {
782        assert!(eval_str("return").is_err());
783        assert!(eval_str("return 1").is_err());
784        assert!(eval_str("return 1 + 1").is_err());
785
786        let code = "\
787            fn do_nothing() {
788                return
789                1
790            }
791            do_nothing()";
792        assert_null!(eval_str(code).unwrap());
793
794        let code = "\
795            fn do_nothing() { return }
796            do_nothing()";
797        assert_null!(eval_str(code).unwrap());
798
799        let code = "\
800            fn add(a, b) {
801                return a + b
802                a - b
803            }
804            add(1, 2)";
805        assert_eq_num!(eval_str(code).unwrap(), 3.0);
806
807        let mut ctx = Context::new();
808        let code = "\
809            fn my_abs(num) {
810                if (num < 0) {
811                    return -num
812                }
813                num
814            }";
815        assert!(eval_str_ctx(code, &mut ctx).is_ok());
816        assert_eq_num!(eval_str_ctx("my_abs(-1)", &mut ctx).unwrap(), 1.0);
817        assert_eq_num!(eval_str_ctx("my_abs(42)", &mut ctx).unwrap(), 42.0);
818        assert_eq_num!(eval_str_ctx("my_abs(-0.23)", &mut ctx).unwrap(), 0.23);
819
820        let code = "\
821            fn a() {
822                b()
823                return 1
824            }
825
826            fn b() {
827                c()
828                return 2
829            }
830            
831            fn c() {
832                return 3
833            }
834
835            a()";
836        assert_eq_num!(eval_str(code).unwrap(), 1.0);
837    }
838
839    #[test]
840    fn test_errors_on_missing_newline() {
841        assert!(eval_str("1 + 1 2 + 2").is_err());
842        assert!(eval_str("1 2").is_err());
843        assert!(eval_str("(1 * 3) 2").is_err());
844
845        assert!(eval_str("fn add(a, b) { a + b } fn sub(a, b) { a - b }").is_err());
846        assert!(eval_str("if (1){ 1 } if (2){ 2 }").is_err());
847    }
848
849    #[test]
850    fn test_comments() {
851        let code = "\
852            // This function adds to numbers
853            fn add(a, b) {
854                a + b  // <- this is where the magic happens
855            }
856
857            sum = add(1, 2) // <- assignment that requires a newline after it
858            sum// no space before comment
859        ";
860
861        assert_eq_num!(eval_str(code).unwrap(), 3.0);
862    }
863
864    #[test]
865    fn test_boolean_literals() {
866        assert_eq_bool!(eval_str("true").unwrap(), true);
867        assert_eq_bool!(eval_str("false").unwrap(), false);
868    }
869
870    #[test]
871    fn test_string_literals() {
872        assert_eq_str!(eval_str(r#""abc""#).unwrap(), "abc");
873        assert_eq_str!(eval_str(r#""123""#).unwrap(), "123");
874        assert_eq_str!(
875            eval_str(r#""This is a sentence.""#).unwrap(),
876            "This is a sentence."
877        );
878        assert_eq_str!(eval_str(r#""""#).unwrap(), "");
879        assert_eq_str!(eval_str(r#""\"\n\t\r\0\\""#).unwrap(), "\"\n\t\r\0\\");
880
881        assert!(eval_str(r#"""#).is_err());
882        assert!(eval_str(r#""abc"#).is_err());
883        assert!(eval_str(r#"abc""#).is_err());
884
885        let code = r#"\
886            s = "abc
887            "
888        "#;
889        assert!(eval_str(code).is_err());
890
891        let code = r#"\
892            s = "abc
893
894        "#;
895        assert!(eval_str(code).is_err());
896    }
897
898    #[test]
899    fn test_string_boolean_coercion() {
900        assert_eq_bool!(eval_str(r#"!!"abc""#).unwrap(), true);
901        assert_eq_bool!(eval_str(r#"!!"\0""#).unwrap(), true);
902        assert_eq_bool!(eval_str(r#"!!"""#).unwrap(), false);
903    }
904
905    #[test]
906    fn test_string_concatenation() {
907        assert_eq_str!(eval_str(r#""abc" + "def""#).unwrap(), "abcdef");
908
909        let mut ctx = Context::new();
910        let code = r#"
911            a = "abc"
912            b = "def"
913            c = a + b
914        "#;
915        eval_str_ctx(code, &mut ctx).unwrap();
916        assert_eq_str!(ctx.get_var("a").unwrap(), "abc");
917        assert_eq_str!(ctx.get_var("b").unwrap(), "def");
918        assert_eq_str!(ctx.get_var("c").unwrap(), "abcdef");
919        assert_eq_str!(eval_str_ctx(r#"a + "def""#, &mut ctx).unwrap(), "abcdef");
920        assert_eq_str!(eval_str_ctx(r#""abc" + b"#, &mut ctx).unwrap(), "abcdef");
921    }
922
923    #[test]
924    fn test_parse_number() {
925        assert_eq_num!(eval_str(r#"parse_number("1e9")"#).unwrap(), 1e9);
926        assert_eq_num!(eval_str(r#"parse_number("-42.1")"#).unwrap(), -42.1);
927        assert_eq_bool!(eval_str(r#"is_nan(parse_number(""))"#).unwrap(), true);
928        assert_eq_bool!(eval_str(r#"is_nan(parse_number("abc"))"#).unwrap(), true);
929
930        assert!(eval_str("is_nan(parse_number())").is_err());
931        assert!(eval_str("is_nan(parse_number(42))").is_err());
932        assert!(eval_str("is_nan(parse_number(true))").is_err());
933    }
934
935    #[test]
936    fn test_to_string() {
937        assert_eq_str!(eval_str("to_string(123)").unwrap(), "123");
938        assert_eq_str!(eval_str("to_string(true)").unwrap(), "true");
939        assert_eq_str!(eval_str("to_string(123)").unwrap(), "123");
940        assert_eq_str!(eval_str("to_string(nan)").unwrap(), "nan");
941        assert_eq_str!(eval_str("to_string(inf)").unwrap(), "inf");
942        assert_eq_str!(eval_str(r#"to_string("")"#).unwrap(), "");
943        assert_eq_str!(eval_str(r#"to_string("abc")"#).unwrap(), "abc");
944    }
945
946    #[test]
947    fn test_print() {
948        let (mut stdout_reader, stdout_writer) = io::create_channel_reader_writer();
949        let (mut stderr_reader, stderr_writer) = io::create_channel_reader_writer();
950        let mut ctx = Context::builder()
951            .stdout(stdout_writer)
952            .stderr(stderr_writer)
953            .build();
954
955        eval_str_ctx(r#"println()"#, &mut ctx).unwrap();
956        assert_eq!(stdout_reader.read_available_to_string(), "\n");
957        assert_eq!(stderr_reader.read_available_to_string(), "");
958
959        eval_str_ctx(r#"println("Hello, world!")"#, &mut ctx).unwrap();
960        assert_eq!(stdout_reader.read_available_to_string(), "Hello, world!\n");
961        assert_eq!(stderr_reader.read_available_to_string(), "");
962
963        eval_str_ctx(r#"println("Hello", ",", "world", "!")"#, &mut ctx).unwrap();
964        assert_eq!(
965            stdout_reader.read_available_to_string(),
966            "Hello , world !\n"
967        );
968        assert_eq!(stderr_reader.read_available_to_string(), "");
969
970        eval_str_ctx(r#"eprintln()"#, &mut ctx).unwrap();
971        assert_eq!(stdout_reader.read_available_to_string(), "");
972        assert_eq!(stderr_reader.read_available_to_string(), "\n");
973
974        eval_str_ctx(r#"eprintln("Goodbye, world!")"#, &mut ctx).unwrap();
975        assert_eq!(stdout_reader.read_available_to_string(), "");
976        assert_eq!(
977            stderr_reader.read_available_to_string(),
978            "Goodbye, world!\n"
979        );
980
981        eval_str_ctx(r#"eprintln("Goodbye", ",", "world", "!")"#, &mut ctx).unwrap();
982        assert_eq!(stdout_reader.read_available_to_string(), "");
983        assert_eq!(
984            stderr_reader.read_available_to_string(),
985            "Goodbye , world !\n"
986        );
987
988        eval_str_ctx(r#"print()"#, &mut ctx).unwrap();
989        assert_eq!(stdout_reader.read_available_to_string(), "");
990        assert_eq!(stderr_reader.read_available_to_string(), "");
991
992        eval_str_ctx(r#"print(42)"#, &mut ctx).unwrap();
993        assert_eq!(stdout_reader.read_available_to_string(), "42");
994        assert_eq!(stderr_reader.read_available_to_string(), "");
995
996        eval_str_ctx(r#"print(1, 1, 2, 3, 5)"#, &mut ctx).unwrap();
997        assert_eq!(stdout_reader.read_available_to_string(), "1 1 2 3 5");
998        assert_eq!(stderr_reader.read_available_to_string(), "");
999
1000        eval_str_ctx(r#"eprint()"#, &mut ctx).unwrap();
1001        assert_eq!(stdout_reader.read_available_to_string(), "");
1002        assert_eq!(stderr_reader.read_available_to_string(), "");
1003
1004        eval_str_ctx(r#"eprint(false)"#, &mut ctx).unwrap();
1005        assert_eq!(stdout_reader.read_available_to_string(), "");
1006        assert_eq!(stderr_reader.read_available_to_string(), "false");
1007
1008        eval_str_ctx(r#"eprint(2, 3, 5, 7, 11, true)"#, &mut ctx).unwrap();
1009        assert_eq!(stdout_reader.read_available_to_string(), "");
1010        assert_eq!(stderr_reader.read_available_to_string(), "2 3 5 7 11 true");
1011    }
1012
1013    #[test]
1014    fn test_read_line() {
1015        let (reader, mut writer) = io::create_channel_reader_writer();
1016        let mut ctx = Context::builder().stdin(reader).build();
1017
1018        writer.write_all(b"This is some input\n").unwrap();
1019        assert_eq_str!(
1020            eval_str_ctx("read_line()", &mut ctx).unwrap(),
1021            "This is some input"
1022        );
1023
1024        writer.write_all(b"\n").unwrap();
1025        assert_eq_str!(eval_str_ctx("read_line()", &mut ctx).unwrap(), "");
1026
1027        writer.write_all(b"first line\nsecond line\n").unwrap();
1028        assert_eq_str!(eval_str_ctx("read_line()", &mut ctx).unwrap(), "first line");
1029        assert_eq_str!(
1030            eval_str_ctx("read_line()", &mut ctx).unwrap(),
1031            "second line"
1032        );
1033    }
1034
1035    #[test]
1036    fn test_named_functions_are_not_expressions() {
1037        assert!(eval_str("my_func = fn my_func() { }").is_err());
1038        assert!(eval_str("print(fn my_func() { })").is_err());
1039    }
1040
1041    #[test]
1042    fn test_unnamed_functions() {
1043        let code = "\
1044            fn apply_twice(func, val) {
1045                func(func(val))
1046            }
1047
1048            apply_twice(fn (num) { 2 * num }, 7)
1049        ";
1050        assert_eq_num!(eval_str(code).unwrap(), 28.0);
1051
1052        let code = r#"
1053            str_concat = fn (s) {
1054                s + s
1055            }
1056            str_concat("abc")
1057        "#;
1058        assert_eq_str!(eval_str(code).unwrap(), "abcabc");
1059
1060        assert_eq_bool!(
1061            eval_str("fn (a, b) { (a && !b) || (!a && b) }(true, true)").unwrap(),
1062            false
1063        );
1064        assert_eq_bool!(
1065            eval_str("(fn (a, b) { (a && !b) || (!a && b) })(true, true)").unwrap(),
1066            false
1067        );
1068    }
1069
1070    #[test]
1071    fn test_function_values() {
1072        let code = "\
1073            fn add(a, b) {
1074                a + b
1075            }
1076
1077            my_add = add
1078            my_add(2, 3)
1079        ";
1080        assert_eq_num!(eval_str(code).unwrap(), 5.0);
1081
1082        let code = "\
1083            fn apply_both(f1, f2, v) {
1084                f2(f1(v))
1085            }
1086
1087            fn double (num) {
1088                2 * num
1089            }
1090
1091            apply_both(double, fn (num) { num ^ 2 }, 4)
1092        ";
1093
1094        assert_eq_num!(eval_str(code).unwrap(), 64.0);
1095
1096        let code = "\
1097            fn (a, b) {
1098                a + b
1099            }
1100        ";
1101        assert!(eval_str(code).is_ok());
1102    }
1103
1104    #[test]
1105    fn test_function_equality() {
1106        assert_eq_bool!(eval_str("fn () { } == fn () { }").unwrap(), false);
1107
1108        let mut ctx = Context::new();
1109        let code = "\
1110            fn add1(a, b) {
1111                a + b
1112            }
1113
1114            fn add2(a, b) {
1115                a + b
1116            }
1117
1118            add1_2 = add1
1119            add1_3 = add1_2
1120            add2_2 = add2
1121        ";
1122        eval_str_ctx(code, &mut ctx).unwrap();
1123        assert_eq_bool!(eval_str_ctx("add1 == add2", &mut ctx).unwrap(), false);
1124        assert_eq_bool!(eval_str_ctx("add1 == add1", &mut ctx).unwrap(), true);
1125        assert_eq_bool!(eval_str_ctx("add1 == add1_2", &mut ctx).unwrap(), true);
1126        assert_eq_bool!(eval_str_ctx("add1 == add1_3", &mut ctx).unwrap(), true);
1127        assert_eq_bool!(eval_str_ctx("add1_3 == add1_3", &mut ctx).unwrap(), true);
1128        assert_eq_bool!(eval_str_ctx("add1_2 == add1_3", &mut ctx).unwrap(), true);
1129        assert_eq_bool!(eval_str_ctx("add1_2 == add2_2", &mut ctx).unwrap(), false);
1130
1131        let code = "\
1132            o = { answer() { 42 } }
1133            o.answer == o.answer
1134        ";
1135        assert_eq_bool!(eval_str(code).unwrap(), true);
1136
1137        let code = "\
1138            fn answer() { 42 }
1139            o = { answer }
1140            
1141            o.answer == answer
1142        ";
1143        assert_eq_bool!(eval_str(code).unwrap(), false);
1144
1145        let code = "\
1146            fn answer() { 42 }
1147            o1 = { answer }
1148            o2 = { answer }
1149            
1150            o1.answer == o2.answer
1151        ";
1152        assert_eq_bool!(eval_str(code).unwrap(), false);
1153    }
1154
1155    #[test]
1156    fn test_member_access() {
1157        let code = r#"
1158            "Hello, world!".length
1159        "#;
1160        assert_eq_num!(eval_str(code).unwrap(), 13.0);
1161
1162        let code = r#"
1163            s = "Hello, world!"
1164            s.length
1165        "#;
1166        assert_eq_num!(eval_str(code).unwrap(), 13.0);
1167
1168        let code = r#"
1169            "  abc ".trim()
1170        "#;
1171        assert_eq_str!(eval_str(code).unwrap(), "abc");
1172
1173        let code = r#"
1174            s = "  abc "
1175            s.trim()
1176        "#;
1177        assert_eq_str!(eval_str(code).unwrap(), "abc");
1178
1179        let code = r#"
1180            s = "  abc "
1181            t = s.trim
1182            t()
1183        "#;
1184        assert_eq_str!(eval_str(code).unwrap(), "abc");
1185
1186        let code = r#"
1187            "  abc ".trim().trim()
1188        "#;
1189        assert_eq_str!(eval_str(code).unwrap(), "abc");
1190
1191        let code = r#"
1192            "abc".this_does_not_exist()
1193        "#;
1194        assert!(eval_str(code).is_err());
1195    }
1196
1197    #[test]
1198    fn test_list_literals() {
1199        let code = "[]";
1200        assert_eq_num_list!(eval_str(code).unwrap(), []);
1201
1202        let code = "[3.7]";
1203        assert_eq_num_list!(eval_str(code).unwrap(), [3.7]);
1204
1205        let code = "[1, 2, 3]";
1206        assert_eq_num_list!(eval_str(code).unwrap(), [1.0, 2.0, 3.0]);
1207
1208        let code = "\
1209            num = 42
1210            [1, 2, 3, num]
1211        ";
1212        assert_eq_num_list!(eval_str(code).unwrap(), [1.0, 2.0, 3.0, 42.0]);
1213
1214        let code = r#"
1215            ["abc", fn() { }, 42]
1216        "#;
1217        let Ok(Value::List(list)) = eval_str(code) else {
1218            panic!("Expected list");
1219        };
1220        let list = list.borrow();
1221        assert_eq!(list.len(), 3);
1222        assert_eq_str!(&list[0], "abc");
1223        assert!(matches!(list[1], Value::Function(_)));
1224        assert_eq_num!(&list[2], &42.0);
1225    }
1226
1227    #[test]
1228    fn test_list_indexing() {
1229        let code = "[1, 2, 3][0]";
1230        assert_eq_num!(eval_str(code).unwrap(), 1.0);
1231
1232        let code = "\
1233            list = [1, 2, 3]
1234            list[0]
1235        ";
1236        assert_eq_num!(eval_str(code).unwrap(), 1.0);
1237
1238        let code = "\
1239            list = [42, -1, 18.9]
1240            list[2]
1241        ";
1242        assert_eq_num!(eval_str(code).unwrap(), 18.9);
1243
1244        let code = "\
1245            list = [42, -1, 18.9]
1246            list[3]
1247        ";
1248        assert!(eval_str(code).is_err());
1249
1250        // TODO: Add this once negative indexing is either supported or properly rejected
1251        // let code = "\
1252        //     list = [42, -1, 18.9]
1253        //     list[-1]
1254        // ";
1255        // assert!(eval_str(code).is_err());
1256
1257        let code = "\
1258            list = []
1259            list[0]
1260        ";
1261        assert!(eval_str(code).is_err());
1262    }
1263
1264    #[test]
1265    fn test_indexing_assignment() {
1266        let code = "\
1267            list = [1, 2, 3]
1268            list[0] = 42
1269            list
1270        ";
1271        assert_eq_num_list!(eval_str(code).unwrap(), [42.0, 2.0, 3.0]);
1272
1273        let code = "\
1274            list = [1, 2, 3]
1275            list[5] = 42
1276            list
1277        ";
1278        assert!(eval_str(code).is_err());
1279
1280        let code = "\
1281            matrix = [[1, 2], [3, 4]]
1282            matrix[0][0] = 42
1283        ";
1284        let mut ctx = Context::new();
1285        assert!(eval_str_ctx(code, &mut ctx).is_ok());
1286        assert_eq_num_list!(eval_str_ctx("matrix[0]", &mut ctx).unwrap(), [42.0, 2.0]);
1287        assert_eq_num_list!(eval_str_ctx("matrix[1]", &mut ctx).unwrap(), [3.0, 4.0]);
1288
1289        let code = "\
1290            x = 1
1291            y = 1
1292            matrix = [[1, 2], [3, 4]]
1293            matrix[y][x] = 42
1294        ";
1295        let mut ctx = Context::new();
1296        assert!(eval_str_ctx(code, &mut ctx).is_ok());
1297        assert_eq_num_list!(eval_str_ctx("matrix[0]", &mut ctx).unwrap(), [1.0, 2.0]);
1298        assert_eq_num_list!(eval_str_ctx("matrix[1]", &mut ctx).unwrap(), [3.0, 42.0]);
1299
1300        let code = "\
1301            fn get_x() { 0 }
1302            fn get_y() { 1 }
1303            matrix = [[1, 2], [3, 4]]
1304            matrix[get_y()][get_x()] = 42
1305        ";
1306        let mut ctx = Context::new();
1307        assert!(eval_str_ctx(code, &mut ctx).is_ok());
1308        assert_eq_num_list!(eval_str_ctx("matrix[0]", &mut ctx).unwrap(), [1.0, 2.0]);
1309        assert_eq_num_list!(eval_str_ctx("matrix[1]", &mut ctx).unwrap(), [42.0, 4.0]);
1310
1311        let code = "\
1312            fn get_list() { [1, 2, 3] }
1313            get_list()[0] = 42
1314        ";
1315        assert!(eval_str(code).is_ok());
1316    }
1317
1318    #[test]
1319    fn test_object_literals() {
1320        let code = "{}";
1321        assert_eq_num_object!(eval_str(code).unwrap(), {});
1322
1323        let code = "{ a: 1 }";
1324        assert_eq_num_object!(eval_str(code).unwrap(), { "a" => 1.0 });
1325
1326        let code = "{ a: 1, b: 2 }";
1327        assert_eq_num_object!(eval_str(code).unwrap(), { "a" => 1.0, "b" => 2.0 });
1328
1329        let code = "{ a: 1, a: 2 }";
1330        assert_eq_num_object!(eval_str(code).unwrap(), { "a" => 2.0 });
1331
1332        let code = "\
1333            a = 1
1334            b = 2
1335            { a, b }
1336        ";
1337        assert_eq_num_object!(eval_str(code).unwrap(), { "a" => 1.0, "b" => 2.0 });
1338
1339        let code = "\
1340            a = 1
1341            { a, a: 2 }
1342        ";
1343        assert_eq_num_object!(eval_str(code).unwrap(), { "a" => 2.0 });
1344
1345        let code = "{ 1: 1 }";
1346        assert!(eval_str(code).is_err());
1347
1348        let code = "{ a: }";
1349        assert!(eval_str(code).is_err());
1350
1351        let code = "{ a: }";
1352        assert!(eval_str(code).is_err());
1353    }
1354
1355    #[test]
1356    fn test_multiline_obeject_literals() {
1357        let code = "\
1358            {
1359                a: 1,
1360                b: 2,
1361            }
1362        ";
1363        assert_eq_num_object!(eval_str(code).unwrap(), { "a" => 1.0, "b" => 2.0 });
1364
1365        let code = "\
1366            {
1367                a
1368                    :
1369            1
1370            }
1371        ";
1372        assert_eq_num_object!(eval_str(code).unwrap(), { "a" => 1.0 });
1373
1374        let code = "\
1375            o = {
1376                a() {
1377                    1
1378                }
1379            }
1380            o.a()
1381        ";
1382        assert_eq_num!(eval_str(code).unwrap(), 1.0);
1383
1384        let code = "\
1385            {
1386                a() { 1 }
1387                b() { 2 }
1388            }
1389        ";
1390        assert!(eval_str(code).is_err());
1391
1392        let code = "\
1393            o = {
1394                a
1395                    (
1396
1397                    )
1398                    {
1399                        1
1400                    }
1401            }
1402            o.a()
1403        ";
1404        assert_eq_num!(eval_str(code).unwrap(), 1.0);
1405    }
1406
1407    #[test]
1408    fn test_object_get() {
1409        let code = "\
1410            obj = { a: 1, b: 2 }
1411            obj.a
1412        ";
1413        assert_eq_num!(eval_str(code).unwrap(), 1.0);
1414
1415        let code = "\
1416            { a: 1, b: 2 }.a
1417        ";
1418        assert_eq_num!(eval_str(code).unwrap(), 1.0);
1419
1420        let code = "\
1421            obj = { a: 1, b: 2 }
1422            obj.c
1423        ";
1424        assert!(eval_str(code).is_err());
1425
1426        let code = r#"
1427            obj = { a: 1, b: 2 }
1428            obj["a"]
1429        "#;
1430        assert_eq_num!(eval_str(code).unwrap(), 1.0);
1431
1432        let code = r#"
1433            obj = { a: 1, b: 2 }
1434            obj["c"]
1435        "#;
1436        assert!(eval_str(code).is_err());
1437
1438        let code = "\
1439            obj = { a: 1, b: 2 }
1440            obj[1]
1441        ";
1442        assert!(eval_str(code).is_err());
1443
1444        let code = r#"
1445            key = "a"
1446            obj = { a: 1, b: 2 }
1447            obj[key]
1448        "#;
1449        assert_eq_num!(eval_str(code).unwrap(), 1.0);
1450
1451        let code = r#"
1452            fn get_key() { "a" }
1453            obj = { a: 1, b: 2 }
1454            obj[get_key()]
1455        "#;
1456        assert_eq_num!(eval_str(code).unwrap(), 1.0);
1457
1458        let code = "\
1459            obj = { inner: { answer: 42 } }
1460            obj.inner.answer
1461        ";
1462        assert_eq_num!(eval_str(code).unwrap(), 42.0);
1463
1464        let code = r#"
1465            obj = { inner: { answer: 42 } }
1466            obj["inner"].answer
1467        "#;
1468        assert_eq_num!(eval_str(code).unwrap(), 42.0);
1469    }
1470
1471    #[test]
1472    fn test_object_set() {
1473        let code = "\
1474            obj = {}
1475            obj.a = 42
1476            obj
1477        ";
1478        assert_eq_num_object!(eval_str(code).unwrap(), { "a" => 42.0 });
1479
1480        let code = "\
1481            obj = { a: 1, b: 2 }
1482            obj.a = 42
1483            obj
1484        ";
1485        assert_eq_num_object!(eval_str(code).unwrap(), { "a" => 42.0, "b" => 2.0 });
1486
1487        let code = r#"
1488            obj = { a: 1, b: 2 }
1489            obj["a"] = 42
1490            obj
1491        "#;
1492        assert_eq_num_object!(eval_str(code).unwrap(), { "a" => 42.0, "b" => 2.0 });
1493
1494        let code = r#"
1495            key = "a"
1496            obj = { a: 1, b: 2 }
1497            obj[key] = 42
1498            obj
1499        "#;
1500        assert_eq_num_object!(eval_str(code).unwrap(), { "a" => 42.0, "b" => 2.0 });
1501
1502        let code = r#"
1503            key = "a"
1504            obj = { a: 1, b: 2 }
1505            obj[key] = 42
1506            obj
1507        "#;
1508        assert_eq_num_object!(eval_str(code).unwrap(), { "a" => 42.0, "b" => 2.0 });
1509
1510        let code = r#"
1511            fn get_key() { "a" }
1512            obj = { a: 1, b: 2 }
1513            obj[get_key()] = 42
1514            obj
1515        "#;
1516        assert_eq_num_object!(eval_str(code).unwrap(), { "a" => 42.0, "b" => 2.0 });
1517
1518        let code = r#"
1519            obj = { inner: { answer: 21 } }
1520            obj.inner.answer = 42
1521            obj.inner
1522        "#;
1523        assert_eq_num_object!(eval_str(code).unwrap(), { "answer" => 42.0 });
1524    }
1525
1526    #[test]
1527    fn test_object_methods() {
1528        let code = "
1529            obj = { add: fn (a, b) { a + b } }
1530            obj.add(1, 2)
1531        ";
1532        assert_eq_num!(eval_str(code).unwrap(), 3.0);
1533
1534        let code = "
1535            obj = { add(a, b) { a + b } }
1536            obj.add(1, 2)
1537        ";
1538        assert_eq_num!(eval_str(code).unwrap(), 3.0);
1539
1540        let code = "
1541            obj = { num: 0, increment() { this.num = this.num + 1 } }
1542            obj.increment()
1543            obj.num
1544        ";
1545        assert_eq_num!(eval_str(code).unwrap(), 1.0);
1546
1547        let code = "
1548            fn increment() {
1549                this.num = this.num + 1
1550            }
1551
1552            obj = { num: 0, increment }
1553            obj.increment()
1554            obj.num
1555        ";
1556        assert_eq_num!(eval_str(code).unwrap(), 1.0);
1557
1558        let code = "
1559            o1 = { num: 1, get_num() { this.num } }
1560            o2 = { num: 2, get_num: o1.get_num }
1561            o2.get_num()
1562        ";
1563        assert_eq_num!(eval_str(code).unwrap(), 2.0);
1564    }
1565
1566    #[test]
1567    fn test_self_referential_print() {
1568        let (mut stdout_reader, stdout_writer) = io::create_channel_reader_writer();
1569        let mut ctx = Context::builder().stdout(stdout_writer).build();
1570
1571        let code = "\
1572            obj = {}
1573            obj.a = obj
1574            print(obj)
1575        ";
1576        eval_str_ctx(code, &mut ctx).unwrap();
1577        assert_eq!(stdout_reader.read_available_to_string(), "{ a: { ... } }");
1578
1579        let code = "\
1580            lst = []
1581            lst.push(lst)
1582            print(lst)
1583        ";
1584        eval_str_ctx(code, &mut ctx).unwrap();
1585        assert_eq!(stdout_reader.read_available_to_string(), "[[...]]");
1586
1587        let code = "\
1588            lst = []
1589            lst.push({lst})
1590            print(lst)
1591        ";
1592        eval_str_ctx(code, &mut ctx).unwrap();
1593        assert_eq!(stdout_reader.read_available_to_string(), "[{ lst: [...] }]");
1594    }
1595
1596    #[test]
1597    fn test_list_equality() {
1598        assert_eq_bool!(eval_str("[] == []").unwrap(), false);
1599        assert_eq_bool!(eval_str("[1, 2, 3] == [1, 2, 3]").unwrap(), false);
1600
1601        let code = "\
1602            l = []
1603            l == l
1604        ";
1605        assert_eq_bool!(eval_str(code).unwrap(), true);
1606
1607        let code = "\
1608            l1 = []
1609            l2 = []
1610            l1 == l2
1611        ";
1612        assert_eq_bool!(eval_str(code).unwrap(), false);
1613
1614        let code = "\
1615            l = [1, 2, 3]
1616            l == l
1617        ";
1618        assert_eq_bool!(eval_str(code).unwrap(), true);
1619    }
1620
1621    #[test]
1622    fn test_object_equality() {
1623        assert_eq_bool!(eval_str("{} == {}").unwrap(), false);
1624        assert_eq_bool!(eval_str("{a: 1, b: 2} == {a: 1, b: 2}").unwrap(), false);
1625
1626        let code = "\
1627            o = {}
1628            o == o
1629        ";
1630        assert_eq_bool!(eval_str(code).unwrap(), true);
1631
1632        let code = "\
1633            o1 = {}
1634            o2 = {}
1635            o1 == o2
1636        ";
1637        assert_eq_bool!(eval_str(code).unwrap(), false);
1638
1639        let code = "\
1640            o = {a: 1, b: 2}
1641            o == o
1642        ";
1643        assert_eq_bool!(eval_str(code).unwrap(), true);
1644    }
1645
1646    #[test]
1647    fn test_null() {
1648        assert_null!(eval_str("null").unwrap());
1649        assert_eq_bool!(eval_str("null == null").unwrap(), true);
1650    }
1651
1652    #[test]
1653    fn test_multiline_function_definition() {
1654        let code = "\
1655            fn
1656                add
1657                (
1658                a
1659                ,
1660                b,
1661            )
1662                {
1663                a + b
1664            }
1665            add(1, 2)
1666        ";
1667        assert_eq_num!(eval_str(code).unwrap(), 3.0);
1668    }
1669
1670    #[test]
1671    fn test_multiline_function_call() {
1672        let code = "\
1673            fn add(a, b) {
1674                a + b
1675            }
1676            add(
1677                1
1678                ,
1679                2
1680            )
1681        ";
1682        assert_eq_num!(eval_str(code).unwrap(), 3.0);
1683
1684        let code = "\
1685            fn add(a, b) {
1686                a + b
1687            }
1688            add
1689            (
1690                1
1691                ,
1692                2
1693            )
1694        ";
1695        assert!(eval_str(code).is_err());
1696    }
1697
1698    #[test]
1699    fn test_multiline_list_literal() {
1700        let code = "\
1701            [
1702                1
1703                ,
1704                2
1705                ,
1706            ]
1707        ";
1708        assert_eq_num_list!(eval_str(code).unwrap(), [1.0, 2.0]);
1709    }
1710
1711    #[test]
1712    fn test_newline_in_assignment() {
1713        let code = "\
1714            a
1715            =
1716            1
1717            a
1718        ";
1719        assert_eq_num!(eval_str(code).unwrap(), 1.0);
1720
1721        let code = "\
1722            o = {}
1723            o.a
1724            =
1725            1
1726            o.a
1727        ";
1728        assert_eq_num!(eval_str(code).unwrap(), 1.0);
1729
1730        let code = "\
1731            l = [0]
1732            l[0]
1733            =
1734            1
1735            l[0]
1736        ";
1737        assert_eq_num!(eval_str(code).unwrap(), 1.0);
1738    }
1739
1740    #[test]
1741    fn test_newline_in_member_access() {
1742        let code = r#"
1743            "  abc "
1744                .trim()
1745                .slice(1, 2)
1746        "#;
1747        assert_eq_str!(eval_str(code).unwrap(), "b");
1748
1749        let code = "\
1750            o = {
1751                a: 1
1752            }
1753            o
1754            .
1755            a
1756            =
1757            2
1758            o
1759            .
1760            a
1761        ";
1762        assert_eq_num!(eval_str(code).unwrap(), 2.0);
1763    }
1764
1765    #[test]
1766    fn test_newline_in_indexing() {
1767        let code = "\
1768            l = [1, 2]
1769            l[
1770                0
1771            ]
1772            =
1773            3
1774            l[
1775                0
1776            ]
1777        ";
1778        assert_eq_num!(eval_str(code).unwrap(), 3.0);
1779
1780        let code = "\
1781            l = [1, 2]
1782            l
1783            [
1784                0
1785            ]
1786            =
1787            3
1788            l
1789            [
1790                0
1791            ]
1792        ";
1793        assert!(eval_str(code).is_err());
1794    }
1795
1796    #[test]
1797    fn test_newlines_in_expressions() {
1798        let code = "\
1799            a = 1
1800
1801            a
1802            +
1803            (
1804            -
1805            2
1806            +
1807            3
1808            *
1809            4
1810            ^
1811            5
1812            +
1813            6
1814            )
1815        ";
1816        assert_eq_num!(eval_str(code).unwrap(), 3077.0);
1817    }
1818
1819    #[test]
1820    fn test_newlines_in_while_loop() {
1821        let code = "\
1822            i = 0
1823            while
1824                (
1825                    i < 10
1826                )
1827            {
1828                i = i + 1
1829
1830                if (i == 5) {
1831                    break
1832                }
1833            }
1834            i
1835        ";
1836        assert_eq_num!(eval_str(code).unwrap(), 5.0);
1837    }
1838
1839    #[test]
1840    fn test_newlines_in_if_statement() {
1841        let code = "\
1842            a = 0
1843            if
1844                (
1845                    true
1846                )
1847            {
1848                a = 1
1849            }
1850            else if
1851                (
1852                    false
1853                )
1854            {
1855                a = 2
1856            }
1857            else
1858            {
1859                a = 3
1860            }
1861            a
1862        ";
1863        assert_eq_num!(eval_str(code).unwrap(), 1.0);
1864
1865        let code = "\
1866            if (true) { }
1867            else
1868            if (false) { }
1869        ";
1870        assert!(eval_str(code).is_err());
1871    }
1872
1873    #[test]
1874    fn test_for_loops() {
1875        let code = "\
1876            sum = 0
1877            for (i in [1, 2, 3]) {
1878                sum = sum + i
1879            }
1880            sum
1881        ";
1882        assert_eq_num!(eval_str(code).unwrap(), 6.0);
1883
1884        let code = "\
1885            fn get_numbers() {
1886                [1, 2, 3]
1887            }
1888            sum = 0
1889            for (i in get_numbers()) {
1890                sum = sum + i
1891            }
1892            sum
1893        ";
1894        assert_eq_num!(eval_str(code).unwrap(), 6.0);
1895
1896        let code = "\
1897            sum = 0
1898            for (i in [1, 2, 3]) {
1899                if (i == 2) {
1900                    continue
1901                }
1902                sum = sum + i
1903            }
1904            sum
1905        ";
1906        assert_eq_num!(eval_str(code).unwrap(), 4.0);
1907
1908        let code = "\
1909            sum = 0
1910            for (i in [1, 2, 3]) {
1911                if (i == 2) {
1912                    break
1913                }
1914                sum = sum + i
1915            }
1916            sum
1917        ";
1918        assert_eq_num!(eval_str(code).unwrap(), 1.0);
1919
1920        assert!(eval_str("for (i in 1) { }").is_err());
1921
1922        assert!(eval_str("for (i [1, 2, 3]) { }").is_err());
1923        assert!(eval_str("for (in [1, 2, 3]) { }").is_err());
1924        assert!(eval_str("for (i in) { }").is_err());
1925        assert!(eval_str("for (in) { }").is_err());
1926    }
1927
1928    #[test]
1929    fn test_newlines_in_for_loop() {
1930        let code = "\
1931            sum = 0
1932            for
1933                (
1934                    i
1935                    in
1936                    [
1937                        1
1938                        ,
1939                        2
1940                        ,
1941                        3
1942                    ]
1943                )
1944            {
1945                sum = sum + i
1946            }
1947            sum
1948        ";
1949        assert_eq_num!(eval_str(code).unwrap(), 6.0);
1950    }
1951
1952    #[test]
1953    fn test_builtin_range() {
1954        assert_eq_num_list!(eval_str("range(3)").unwrap(), [0.0, 1.0, 2.0]);
1955        assert_eq_num_list!(eval_str("range(1, 3)").unwrap(), [1.0, 2.0]);
1956        assert_eq_num_list!(eval_str("range(3, 3)").unwrap(), []);
1957        assert_eq_num_list!(eval_str("range(10, 3)").unwrap(), []);
1958        assert_eq_num_list!(eval_str("range(1, 10, 3)").unwrap(), [1.0, 4.0, 7.0]);
1959
1960        assert_eq_num_list!(eval_str("range(2, 3, -1)").unwrap(), []);
1961        assert_eq_num_list!(eval_str("range(3, 3, -1)").unwrap(), []);
1962        assert_eq_num_list!(eval_str("range(3, 0, -1)").unwrap(), [3.0, 2.0, 1.0]);
1963        assert_eq_num_list!(eval_str("range(10, 3, -2)").unwrap(), [10.0, 8.0, 6.0, 4.0]);
1964        assert_eq_num_list!(eval_str("range(10, 4, -2)").unwrap(), [10.0, 8.0, 6.0]);
1965
1966        assert!(eval_str("range()").is_err());
1967        assert!(eval_str("range(1, 2, 0)").is_err());
1968        assert!(eval_str("range(1, 2, 3, 4)").is_err());
1969    }
1970}