1
// Tests for lambda list keywords (&rest, &optional, etc.)
2
// These tests verify that the lambda list keyword infrastructure works correctly
3

            
4
use nomiscript::{
5
    Reader, eval_program,
6
    runtime::{SymbolTable, Value},
7
};
8

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

            
15
#[cfg(test)]
16
mod rest_parameter_tests {
17
    use super::*;
18

            
19
    #[test]
20
1
    fn test_lambda_with_rest_basic() {
21
1
        let result = eval_expr("((lambda (x &rest y) y) 1 2 3 4)");
22
1
        match &result {
23
            Err(e) => println!("Error: {e:?}"),
24
1
            Ok(v) => println!("Result: {v:?}"),
25
        }
26
1
        assert!(result.is_ok(), "Lambda with &rest should work");
27
1
    }
28

            
29
    #[test]
30
1
    fn test_lambda_with_rest_no_extra_args() {
31
1
        let result = eval_expr("((lambda (x &rest y) x) 42)");
32
1
        assert!(
33
1
            result.is_ok(),
34
            "Lambda with &rest and no extra args should work"
35
        );
36
1
    }
37

            
38
    #[test]
39
1
    fn test_defun_with_rest() {
40
1
        let code = r"
41
1
        (defun sum-all (first &rest others)
42
1
          first)
43
1
        (sum-all 10 20 30)
44
1
        ";
45
1
        let result = eval_expr(code);
46
1
        assert!(result.is_ok(), "DEFUN with &rest should work");
47
1
    }
48
}
49

            
50
#[cfg(test)]
51
mod optional_parameter_tests {
52
    use super::*;
53

            
54
    #[test]
55
1
    fn test_lambda_with_optional_no_default() {
56
1
        let result = eval_expr("((lambda (x &optional y) x) 42)");
57
1
        assert!(result.is_ok(), "Lambda with &optional should work");
58
1
    }
59

            
60
    #[test]
61
1
    fn test_lambda_with_optional_with_default() {
62
1
        let result = eval_expr("((lambda (x &optional (y 100)) x) 42)");
63
1
        assert!(
64
1
            result.is_ok(),
65
            "Lambda with &optional and default should work"
66
        );
67
1
    }
68

            
69
    #[test]
70
1
    fn test_defun_with_optional() {
71
1
        let code = r#"
72
1
        (defun greet (&optional (name "World"))
73
1
          name)
74
1
        (greet "Alice")
75
1
        "#;
76
1
        let result = eval_expr(code);
77
1
        assert!(result.is_ok(), "DEFUN with &optional should work");
78
1
    }
79
}
80

            
81
#[cfg(test)]
82
mod aux_parameter_tests {
83
    use super::*;
84

            
85
    #[test]
86
1
    fn test_lambda_with_aux() {
87
1
        let result = eval_expr("((lambda (x &aux (temp 42)) x) 10)");
88
1
        assert!(result.is_ok(), "Lambda with &aux should work");
89
1
    }
90

            
91
    #[test]
92
1
    fn test_defun_with_aux() {
93
1
        let code = r"
94
1
        (defun process (data &aux (result nil))
95
1
          data)
96
1
        (process 123)
97
1
        ";
98
1
        let result = eval_expr(code);
99
1
        assert!(result.is_ok(), "DEFUN with &aux should work");
100
1
    }
101
}
102

            
103
#[cfg(test)]
104
mod key_parameter_tests {
105
    use super::*;
106

            
107
    #[test]
108
1
    fn test_lambda_with_key_basic() {
109
1
        let result = eval_expr("((lambda (x &key name) x) 42 :name \"test\")");
110
1
        assert!(result.is_ok(), "Lambda with &key should work");
111
1
    }
112

            
113
    #[test]
114
1
    fn test_lambda_with_key_no_keyword_args() {
115
1
        let result = eval_expr("((lambda (x &key name) x) 42)");
116
1
        assert!(
117
1
            result.is_ok(),
118
            "Lambda with &key and no keyword args should work"
119
        );
120
1
    }
121

            
122
    #[test]
123
1
    fn test_defun_with_key() {
124
1
        let code = r#"
125
1
        (defun greet (person &key (greeting "Hello"))
126
1
          person)
127
1
        (greet "Alice" :greeting "Hi")
128
1
        "#;
129
1
        let result = eval_expr(code);
130
1
        assert!(result.is_ok(), "DEFUN with &key should work");
131
1
    }
132

            
133
    #[test]
134
1
    fn test_defmacro_with_key() {
135
1
        let code = r#"
136
1
        (defmacro test-macro (name &key (type "default"))
137
1
          (quote (+ 1 2)))
138
1
        (test-macro foo :type "custom")
139
1
        "#;
140
1
        let result = eval_expr(code);
141
1
        assert!(result.is_ok(), "DEFMACRO with &key should work");
142
1
    }
143
}