1
// Tests for CAR and CDR native functions
2
// These tests verify that the CAR and CDR functions work correctly
3
// through the nomiscript evaluation system.
4

            
5
use nomiscript::{
6
    Reader, eval_program,
7
    runtime::{SymbolTable, Value},
8
};
9
use num_rational::Ratio;
10

            
11
13
fn eval_expr(code: &str) -> Result<Value, nomiscript::Error> {
12
13
    let program = Reader::parse(code)?;
13
13
    let mut symbols = SymbolTable::with_builtins();
14
13
    eval_program(&mut symbols, &program)
15
13
}
16

            
17
2
fn num(n: i64) -> Value {
18
2
    Value::Number(Ratio::from_integer(n))
19
2
}
20

            
21
#[cfg(test)]
22
mod car_cdr_basic_tests {
23
    use super::*;
24

            
25
    #[test]
26
1
    fn test_car_basic() {
27
1
        let result = eval_expr("(car '(1 2 3))").unwrap();
28
1
        assert_eq!(result, num(1));
29
1
    }
30

            
31
    #[test]
32
1
    fn test_cdr_basic() {
33
        // CDR should return something, but the exact structure might depend on implementation
34
1
        let result = eval_expr("(cdr '(1 2 3))");
35
1
        assert!(result.is_ok(), "CDR should work with a basic list");
36
1
    }
37

            
38
    #[test]
39
1
    fn test_car_with_nil() {
40
1
        let result = eval_expr("(car nil)").unwrap();
41
1
        assert_eq!(result, Value::Nil);
42
1
    }
43

            
44
    #[test]
45
1
    fn test_cdr_with_nil() {
46
1
        let result = eval_expr("(cdr nil)").unwrap();
47
1
        assert_eq!(result, Value::Nil);
48
1
    }
49

            
50
    #[test]
51
1
    fn test_car_with_empty_list() {
52
1
        let result = eval_expr("(car '())").unwrap();
53
1
        assert_eq!(result, Value::Nil);
54
1
    }
55

            
56
    #[test]
57
1
    fn test_cdr_with_empty_list() {
58
1
        let result = eval_expr("(cdr '())").unwrap();
59
1
        assert_eq!(result, Value::Nil);
60
1
    }
61

            
62
    #[test]
63
1
    fn test_car_wrong_arity() {
64
1
        let result = eval_expr("(car 1 2)");
65
1
        assert!(
66
1
            result.is_err(),
67
            "CAR should reject wrong number of arguments"
68
        );
69
1
    }
70

            
71
    #[test]
72
1
    fn test_cdr_wrong_arity() {
73
1
        let result = eval_expr("(cdr)");
74
1
        assert!(
75
1
            result.is_err(),
76
            "CDR should reject wrong number of arguments"
77
        );
78
1
    }
79

            
80
    #[test]
81
1
    fn test_car_with_non_list() {
82
1
        let result = eval_expr("(car 42)");
83
1
        assert!(result.is_err(), "CAR should reject non-list arguments");
84
1
    }
85

            
86
    #[test]
87
1
    fn test_cdr_with_non_list() {
88
1
        let result = eval_expr("(cdr \"hello\")");
89
1
        assert!(result.is_err(), "CDR should reject non-list arguments");
90
1
    }
91

            
92
    #[test]
93
1
    fn test_car_with_string_element() {
94
1
        let result = eval_expr("(car '(\"hello\" \"world\"))").unwrap();
95
1
        assert_eq!(result, Value::String("hello".into()));
96
1
    }
97

            
98
    #[test]
99
1
    fn test_car_cdr_case_insensitivity() {
100
        // nomiscript should handle case-insensitive function names
101
1
        let result1 = eval_expr("(CAR '(1 2))").unwrap();
102
1
        let result2 = eval_expr("(car '(1 2))").unwrap();
103
1
        assert_eq!(result1, result2);
104
1
        assert_eq!(result1, num(1));
105
1
    }
106
}