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 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 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}