aboutsummaryrefslogtreecommitdiff
path: root/src/eval/test.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/eval/test.rs')
-rw-r--r--src/eval/test.rs371
1 files changed, 371 insertions, 0 deletions
diff --git a/src/eval/test.rs b/src/eval/test.rs
new file mode 100644
index 0000000..83749e0
--- /dev/null
+++ b/src/eval/test.rs
@@ -0,0 +1,371 @@
1use super::*;
2use crate::ast::*;
3use std::io::Write;
4use expect_test::{expect, Expect};
5
6fn gen_test(file: &str, program: &str, expected: Expect) {
7 let language = tree_sitter_python::language();
8 let mut parser = tree_sitter::Parser::new();
9 let _ = parser.set_language(&language);
10 let tree = parser.parse(file, None).unwrap();
11 let program = ast::Program::new().with_file(program).unwrap();
12
13 let mut output = Vec::new();
14 let result;
15
16 {
17 let mut ctx = Context::new(language)
18 .with_input(file.to_owned())
19 .with_tree(tree)
20 .with_program(program)
21 .with_output_stream(Box::new(&mut output) as Box<dyn io::Write>);
22
23 result = ctx.eval();
24 }
25
26 if let Err(e) = result {
27 writeln!(output, "{e:?}").unwrap();
28 }
29 expected.assert_eq(&String::from_utf8(output).unwrap())
30}
31
32#[test]
33fn bin() {
34 let language = tree_sitter_python::language();
35 let mut ctx = Context::new(language).with_program(Program::new());
36 assert_eq!(
37 ctx.eval_expr(&Expr::bin(Expr::int(5), "+", Expr::int(10),)),
38 Ok(Value::Integer(15))
39 );
40 assert_eq!(
41 ctx.eval_expr(&Expr::bin(Expr::int(5), "==", Expr::int(10),)),
42 Ok(Value::Boolean(false))
43 );
44 assert_eq!(
45 ctx.eval_expr(&Expr::bin(Expr::int(5), "<", Expr::int(10),)),
46 Ok(Value::Boolean(true))
47 );
48 assert_eq!(
49 ctx.eval_expr(&Expr::bin(
50 Expr::bin(Expr::int(5), "<", Expr::int(10),),
51 "&&",
52 Expr::false_(),
53 )),
54 Ok(Value::Boolean(false))
55 );
56}
57
58#[test]
59fn test_evaluate_blocks() {
60 let language = tree_sitter_python::language();
61 let mut ctx = Context::new(language).with_program(Program::new());
62 assert_eq!(
63 ctx.eval_block(&Block {
64 body: vec![
65 Statement::Declaration(Declaration {
66 ty: Type::Integer,
67 name: "a".to_owned(),
68 init: None,
69 }),
70 Statement::Bare(Expr::bin(Expr::ident("a"), "+=", Expr::int(5),)),
71 ]
72 }),
73 Ok(Value::Unit)
74 );
75 assert_eq!(
76 ctx.lookup(&String::from("a")).unwrap().clone(),
77 Variable {
78 ty: Type::Integer,
79 name: "a".to_owned(),
80 value: Value::Integer(5)
81 }
82 );
83}
84
85#[test]
86fn test_evaluate_if() {
87 let language = tree_sitter_python::language();
88 let mut ctx = Context::new(language).with_program(Program::new());
89 assert_eq!(
90 ctx.eval_block(&Block {
91 body: vec![
92 Statement::Declaration(Declaration {
93 ty: Type::Integer,
94 name: "a".to_owned(),
95 init: Some(Expr::int(1).boxed()),
96 }),
97 Statement::Bare(Expr::If(IfExpr {
98 condition: Expr::true_().boxed(),
99 then: Block {
100 body: vec![Statement::Bare(Expr::bin(
101 Expr::Ident("a".to_owned()),
102 "+=",
103 Expr::int(5),
104 ))]
105 },
106 else_: Block {
107 body: vec![Statement::Bare(Expr::bin(
108 Expr::ident("a"),
109 "+=",
110 Expr::int(10),
111 ))]
112 }
113 }))
114 ]
115 }),
116 Ok(Value::Unit)
117 );
118 assert_eq!(
119 ctx.lookup(&String::from("a")).unwrap().clone(),
120 Variable {
121 ty: Type::Integer,
122 name: "a".to_owned(),
123 value: Value::Integer(6)
124 }
125 );
126}
127
128#[test]
129fn test_substring() {
130 let language = tree_sitter_python::language();
131 let mut ctx = Context::new(language).with_program(Program::new());
132 assert_eq!(
133 ctx.eval_block(&Block {
134 body: vec![
135 Statement::Declaration(Declaration {
136 ty: Type::String,
137 name: "a".to_owned(),
138 init: Some(Expr::str("foobar").boxed()),
139 }),
140 Statement::Declaration(Declaration {
141 ty: Type::String,
142 name: "b".to_owned(),
143 init: Some(
144 Expr::call(
145 "substr",
146 [Expr::Ident("a".to_owned()), Expr::int(0), Expr::int(3),]
147 )
148 .boxed()
149 ),
150 }),
151 ]
152 }),
153 Ok(Value::Unit)
154 );
155 assert_eq!(
156 ctx.lookup(&String::from("b")).unwrap().clone(),
157 Variable {
158 ty: Type::String,
159 name: "b".to_owned(),
160 value: "foo".into()
161 }
162 );
163}
164
165#[test]
166fn test_list() {
167 let language = tree_sitter_python::language();
168 let mut ctx = Context::new(language).with_program(Program::new());
169 assert_eq!(
170 ctx.eval_block(&Block {
171 body: vec![Statement::Declaration(Declaration {
172 ty: Type::List,
173 name: "a".to_owned(),
174 init: Some(
175 Expr::List(List {
176 items: vec![Expr::int(5)]
177 })
178 .boxed()
179 ),
180 }),]
181 }),
182 Ok(Value::Unit)
183 );
184 assert_eq!(
185 ctx.lookup(&String::from("a")).unwrap().clone(),
186 Variable {
187 ty: Type::List,
188 name: "a".to_owned(),
189 value: vec![5usize.into()].into(),
190 }
191 );
192}
193
194#[test]
195fn list_1() {
196 gen_test(
197 "",
198 "BEGIN {
199 list a = [5];
200 print(a);
201 }
202 ",
203 expect!["[5]"],
204 );
205}
206
207#[test]
208fn list_2() {
209 gen_test(
210 "",
211 "BEGIN {
212 list a = [5, 4, 3];
213 print(length(a));
214 }
215 ",
216 expect!["3"],
217 );
218}
219
220#[test]
221fn list_3() {
222 gen_test(
223 "",
224 r#"BEGIN {
225 list a = [5, 4, 3];
226 print(member(a, 3));
227 print(", ");
228 print(member(a, 6));
229 }
230 "#,
231 expect!["true, false"],
232 );
233}
234
235#[test]
236fn list_4() {
237 gen_test(
238 "",
239 r#"BEGIN {
240 list a = [5];
241 println(a);
242 push(a, 4);
243 println(a);
244 push(a, 3);
245 println(a);
246 pop(a);
247 println(a);
248 pop(a);
249 println(a);
250 }
251 "#,
252 expect![[r#"
253 [5]
254 [5, 4]
255 [5, 4, 3]
256 [5, 4]
257 [5]
258 "#]],
259 );
260}
261
262#[test]
263fn list_5() {
264 gen_test(
265 "",
266 r#"BEGIN {
267 list a = [5];
268 println(isempty(a));
269 pop(a);
270 println(isempty(a));
271 }
272 "#,
273 expect![[r#"
274 false
275 true
276 "#]],
277 );
278}
279
280#[test]
281fn string_1() {
282 gen_test(
283 "",
284 r#"BEGIN {
285 string a = "Foo";
286 println(toupper(a));
287 println(tolower(a));
288 }
289 "#,
290 expect![[r#"
291 FOO
292 foo
293 "#]],
294 );
295}
296
297#[test]
298fn string_2() {
299 gen_test(
300 "",
301 r#"BEGIN {
302 string a = "foo";
303 println(a, " is upper? ", isupper(a));
304 println(a, " is lower? ", islower(a));
305
306 string b = "Foo";
307 println(b, " is upper? ", isupper(b));
308 println(b, " is lower? ", islower(b));
309
310 string c = "FOO";
311 println(c, " is upper? ", isupper(c));
312 println(c, " is lower? ", islower(c));
313 }
314 "#,
315 expect![[r#"
316 foo is upper? false
317 foo is lower? true
318 Foo is upper? false
319 Foo is lower? false
320 FOO is upper? true
321 FOO is lower? false
322 "#]],
323 );
324}
325
326#[test]
327fn string_3() {
328 gen_test(
329 "",
330 r#"BEGIN {
331 string a = "foo bar baz";
332 println("a[3:5]: `", substr(a, 3, 5), "`");
333 println("a[2:9]: `", substr(a, 2, 9), "`");
334 }
335 "#,
336 expect![[r#"
337 a[3:5]: ` b`
338 a[2:9]: `o bar b`
339 "#]],
340 );
341}
342
343#[test]
344fn string_4() {
345 gen_test(
346 "",
347 r#"BEGIN {
348 string a = "foo bar baz";
349 println("a[9:20]: `", substr(a, 9, 20), "`");
350 }
351 "#,
352 expect![[r#"
353 a[9:20]: `InvalidStringSlice { length: 11, start: 9, end: 20 }
354 "#]],
355 );
356}
357
358#[test]
359fn node_1() {
360 gen_test(
361 "def foo(a, b): hello()",
362 r#"enter function_definition {
363 println(text(node));
364 println(text(node.name));
365 }"#,
366 expect![[r#"
367 def foo(a, b): hello()
368 foo
369 "#]],
370 );
371}