[Header]
open K
open Unix
open Translate
open Sm5
let stdout_redirect_f = "stdout_redirect.txt"
let stdin_redirect_f = "stdin_redirect.txt"
let read_all filename =
let chan = open_in filename in
let res = really_input_string chan (in_channel_length chan) in
let _ = close_in chan in
res
let test_run pgm_str input_str =
(* Translate the program *)
let pgm = Parser.program Lexer.start (Lexing.from_string pgm_str) in
let sm5_pgm = Translator.trans pgm in
(* Write testcase input string to a file *)
let chan = open_out stdin_redirect_f in
let _ = Printf.fprintf chan input_str in
let _ = close_out chan in
(* Stdin Redirection *)
let new_stdin = open_in stdin_redirect_f in
let _ = Unix.dup2 (Unix.descr_of_in_channel new_stdin) Unix.stdin in
(* Stdout Redirection *)
let new_stdout = open_out stdout_redirect_f in
let _ = Unix.dup2 (Unix.descr_of_out_channel new_stdout) Unix.stdout in
(* Run the translated program *)
let _ = Sm5.run sm5_pgm in
read_all stdout_redirect_f
[Test]
(* 1. read, write, arithmetic *)
test_run "let x :=0 in (read x; write (5 + 6 * x - 8 / 4))" "7\n"
[Value]
"45\n"
[Test]
(* 2. branches *)
test_run
"let x := 0 in
read x;
if (5 < x) then (
if (false = false) then (
if not(true = 3) then (write (21)) else (write (22))
)
else (write (23))
)
else (write (24))"
"6\n"
[Value]
"21\n"
[Test]
(* 3. Result of sequence expression *)
test_run
"let x := 0 in
read x;
write(write(11); 12; x)"
"13\n"
[Value]
"11\n13\n"
[Test]
(* 4. Result of WRITE expression *)
test_run
"let x := 0 in
read x;
write((write((write(x)) + 5)) - 10)"
"20\n"
[Value]
"20\n25\n15\n"
[Test]
(* 5. While + LetV *)
test_run
"let x := 0 in
read x;
let i := 0 in
let sum := 0 in
while (i < x) do (
sum := sum + i;
i := i + 1
);
write(sum)"
"10\n"
[Value]
"45\n"
[Test]
(* 6. Factorial with for loop *)
test_run
"
let x := 1 in
let y := 0 in
let z := 0 in
read y;
for z := 1 to y do (
x := x * z
);
write x
"
"6"
[Value]
"720\n"
[Test]
(* 7. FOR loop *)
test_run
"let x := 0 in
read x;
let sum := 0 in
let i := 0 in
let j := 0 in
while (i < x) do (
while ( j < i ) do (
j := i + j
);
sum := sum + i;
i := i + 1
);
write(i);
write(j);
write(sum)
"
"10\n"
[Value]
"10\n15\n45\n"
[Test]
(* 8. LetF + CallV *)
test_run
"let proc f (x) = x + 10 in
let x := 0 in
read x;
(write (f (x) + 10))"
"1\n"
[Value]
"21\n"
[Test]
(* 9. Recursive call *)
test_run
"let proc f (x) =
if (x < 1) then 1 else (x + f (x-1)) in
let x:= 0 in
read x;
(write (f (x)))"
"10\n"
[Value]
"56\n"
[Test]
(* 10. LetF + CallV + CallR *)
test_run
"let proc f (x) = (x := 3) in
let proc g (x) = (x := 3) in
let x := 1 in
let y := 2 in
f ; g (y); (write (x+y))"
"1\n2\n"
[Value]
"5\n"
[Test]
(* 11. Read and write *)
test_run "let x := 0 in while (0 < (read x)) do (write x)" "3\n2\n5\n0\n"
[Value]
"3\n2\n5\n"
[Test]
(* 12. Simple bonus *)
test_run "let x := true in if x then (write 1) else (write 0)" ""
[Value]
"1\n"
[Test]
(* 13. Assign, revisited *)
test_run
"let x := () in
let y := () in
let z := () in
let w := 0 in
read w;
if ( (x := 1) + (y := 2) + (z := 3) = 6 ) then (write (w *10)) else (write 0)"
"10\n"
[Value]
"100\n"
[Test]
(* 14. Scope *)
test_run
"let x := 0 in
write(
(let x := 1 in (x := 5); ((x := x + 1) * (let x := 2 in (x := x + 1)))) +
(let y := 2 in 2 * x)
)"
""
[Value]
"18\n"
[Test]
(* 15. Assignment in FOR loop *)
test_run
"let x := 1 in
let sum := 0 in
let k := 0 in
read k;
for x := 1 to k do (
x := 2 * x;
sum := sum + x
); (write sum)"
"10\n"
[Value]
"110\n"
[Test]
(* 16. Arguments in CallF *)
test_run
"let y := 2 in
let z := 0 in
let proc f (x) = x * y + z in
read z;
write (f (1))"
"2\n"
[Value]
"4\n"
[Test]
(* 17. Arguments in CallR *)
test_run
"let x := 1 in
let y := 2 in
let z := 3 in
let proc f (x) = (x := x + (y := y + 1) + (z := z + 1)) in
f ; (write (x+y+z))"
""
[Value]
"15\n"
[Test]
(* 18. Scope case II *)
test_run
"let a := 0 in
let proc f (x) = x + 1 in
let x := 2 in
read a;
write (a * (x + x))"
"10\n"
[Value]
"40\n"
[Test]
(* Scope case III *)
test_run
"let x := 1 in
let y := 2 in
let z := 3 in
let proc f (x) = (x := x + y) in
let proc g (x) = (x := x + z) in
let y := 4 in
let z := 5 in
write (f ( g ))"
""
[Value]
"9\n"
[Test]
(* 20. Complex scope *)
test_run
"let x := 1 in
let y := 5 in
let proc f (z) =
if z then (x := x + 1) else (y := y - 2)
in
let x := 10 in
let y := 50 in
let proc g (z) =
if z then (x := x + 5) else (y := y - 10)
in
write (
g (true) + g (false) + x + y + f (true) + f (false) + x + y
)"
""
[Value]
"170\n"