1
use nms::interpreter::Interpreter;
2
use scripting::nomiscript::{Fraction, Value};
3

            
4
// LIST
5

            
6
#[test]
7
1
fn test_eval_list_empty() {
8
1
    let mut interp = Interpreter::new(false).unwrap();
9
1
    let results = interp.eval("(list)").unwrap();
10
1
    assert_eq!(results, vec![Value::String("()".to_string())]);
11
1
}
12

            
13
#[test]
14
1
fn test_eval_list_numbers() {
15
1
    let mut interp = Interpreter::new(false).unwrap();
16
1
    let results = interp.eval("(list 1 2 3)").unwrap();
17
1
    assert_eq!(results, vec![Value::String("(1 2 3)".to_string())]);
18
1
}
19

            
20
#[test]
21
1
fn test_eval_list_mixed() {
22
1
    let mut interp = Interpreter::new(false).unwrap();
23
1
    let results = interp.eval(r#"(list 1 "hello" #t)"#).unwrap();
24
1
    assert_eq!(results, vec![Value::String("(1 hello #T)".to_string())]);
25
1
}
26

            
27
// CONS
28

            
29
#[test]
30
1
fn test_eval_cons_onto_list() {
31
1
    let mut interp = Interpreter::new(false).unwrap();
32
1
    let results = interp.eval("(cons 1 (list 2 3))").unwrap();
33
1
    assert_eq!(results, vec![Value::String("(1 2 3)".to_string())]);
34
1
}
35

            
36
#[test]
37
1
fn test_eval_cons_onto_nil() {
38
1
    let mut interp = Interpreter::new(false).unwrap();
39
1
    let results = interp.eval("(cons 1 nil)").unwrap();
40
1
    assert_eq!(results, vec![Value::String("(1)".to_string())]);
41
1
}
42

            
43
#[test]
44
1
fn test_eval_cons_arity_error() {
45
1
    let mut interp = Interpreter::new(false).unwrap();
46
1
    assert!(interp.eval("(cons 1)").is_err());
47
1
    assert!(interp.eval("(cons 1 2 3)").is_err());
48
1
}
49

            
50
// QUOTE
51

            
52
#[test]
53
1
fn test_eval_quote_number() {
54
1
    let mut interp = Interpreter::new(false).unwrap();
55
1
    let results = interp.eval("(quote 42)").unwrap();
56
1
    assert_eq!(results, vec![Value::Number(Fraction::from_integer(42))]);
57
1
}
58

            
59
#[test]
60
1
fn test_eval_quote_reader_sugar() {
61
1
    let mut interp = Interpreter::new(false).unwrap();
62
1
    let results = interp.eval("'42").unwrap();
63
1
    assert_eq!(results, vec![Value::Number(Fraction::from_integer(42))]);
64
1
}
65

            
66
#[test]
67
1
fn test_eval_quote_string() {
68
1
    let mut interp = Interpreter::new(false).unwrap();
69
1
    let results = interp.eval("(quote \"hello\")").unwrap();
70
1
    assert_eq!(results, vec![Value::String("hello".to_string())]);
71
1
}
72

            
73
// DESCRIBE
74

            
75
#[test]
76
1
fn test_eval_describe_function() {
77
1
    let mut interp = Interpreter::new(false).unwrap();
78
1
    let results = interp
79
1
        .eval(r#"(defun sum (a b) "Adds two numbers" (+ a b)) (describe sum)"#)
80
1
        .unwrap();
81
1
    match &results[0] {
82
1
        Value::String(s) => {
83
1
            assert!(s.contains("SUM is a function"), "got: {s}");
84
1
            assert!(s.contains("Lambda:"), "got: {s}");
85
1
            assert!(s.contains("Adds two numbers"), "got: {s}");
86
        }
87
        _ => panic!("expected string, got {:?}", results[0]),
88
    }
89
1
}
90

            
91
#[test]
92
1
fn test_eval_describe_variable() {
93
1
    let mut interp = Interpreter::new(false).unwrap();
94
1
    let results = interp
95
1
        .eval(r#"(defvar *x* 42 "The answer") (describe *x*)"#)
96
1
        .unwrap();
97
1
    match &results[0] {
98
1
        Value::String(s) => {
99
1
            assert!(s.contains("*X* is a variable"), "got: {s}");
100
1
            assert!(s.contains("Value: 42"), "got: {s}");
101
1
            assert!(s.contains("The answer"), "got: {s}");
102
        }
103
        _ => panic!("expected string, got {:?}", results[0]),
104
    }
105
1
}
106

            
107
// Nested calls
108

            
109
#[test]
110
1
fn test_nested_comparison_with_subtraction() {
111
1
    let mut interp = Interpreter::new(false).unwrap();
112
1
    assert_eq!(
113
1
        interp.eval("(= 1 (- 3 2))").unwrap(),
114
1
        vec![Value::Bool(true)]
115
    );
116
1
}
117

            
118
#[test]
119
1
fn test_nested_addition_with_multiplication() {
120
1
    let mut interp = Interpreter::new(false).unwrap();
121
1
    assert_eq!(
122
1
        interp.eval("(+ 1 (* 2 3))").unwrap(),
123
1
        vec![Value::Number(Fraction::from_integer(7))]
124
    );
125
1
}
126

            
127
#[test]
128
1
fn test_nested_subtraction_multiple_args() {
129
1
    let mut interp = Interpreter::new(false).unwrap();
130
1
    assert_eq!(
131
1
        interp.eval("(- 10 (+ 1 2) (- 5 2))").unwrap(),
132
1
        vec![Value::Number(Fraction::from_integer(4))]
133
    );
134
1
}
135

            
136
#[test]
137
1
fn test_nested_addition_both_sides() {
138
1
    let mut interp = Interpreter::new(false).unwrap();
139
1
    assert_eq!(
140
1
        interp.eval("(+ (+ 1 2) (+ 3 4))").unwrap(),
141
1
        vec![Value::Number(Fraction::from_integer(10))]
142
    );
143
1
}
144

            
145
#[test]
146
1
fn test_deeply_nested_addition() {
147
1
    let mut interp = Interpreter::new(false).unwrap();
148
1
    assert_eq!(
149
1
        interp.eval("(+ 1 (+ 2 (+ 3 4)))").unwrap(),
150
1
        vec![Value::Number(Fraction::from_integer(10))]
151
    );
152
1
}
153

            
154
#[test]
155
1
fn test_nested_calls_with_defun() {
156
1
    let mut interp = Interpreter::new(false).unwrap();
157
1
    assert_eq!(
158
1
        interp
159
1
            .eval("(defun double (x) (* x 2)) (+ (double 3) (double 4))")
160
1
            .unwrap(),
161
1
        vec![Value::Number(Fraction::from_integer(14))]
162
    );
163
1
}
164

            
165
#[test]
166
1
fn test_nested_equal_with_arithmetic() {
167
1
    let mut interp = Interpreter::new(false).unwrap();
168
1
    assert_eq!(
169
1
        interp.eval("(equal (+ 1 1) (- 4 2))").unwrap(),
170
1
        vec![Value::Bool(true)]
171
    );
172
1
}
173

            
174
#[test]
175
1
fn test_nested_funcall_with_arithmetic() {
176
1
    let mut interp = Interpreter::new(false).unwrap();
177
1
    assert_eq!(
178
1
        interp.eval("(funcall + (- 10 3) (* 2 3))").unwrap(),
179
1
        vec![Value::Number(Fraction::from_integer(13))]
180
    );
181
1
}