Tests in interpretation

This commit is contained in:
Dmitry Boulytchev 2018-04-03 07:21:59 +03:00
parent b4f6f48e30
commit 44b8a96e34
9 changed files with 89 additions and 53 deletions

View file

@ -1,4 +1,4 @@
TESTS=test001 test002 test003 test004 test005 test006 test007 test008 test009 test010 test011 test012 test013 test014 test015 test016 test017 test018 test019 test020 test021 test022 test023 test024 test025 test026 test027 test028 test029 TESTS=test001 test002 test003 test004 test005 test006 test007 test008 test009 test010 test011 test012 test013 test014 test015 test016 test017 test018 test019 test020 test021 test022 test023 test024 test025 test026 test027 test028 test029 test030 test031
RC=../src/rc.opt RC=../src/rc.opt
@ -9,7 +9,7 @@ check: $(TESTS)
$(TESTS): %: %.expr $(TESTS): %: %.expr
# @$(RC) $< && cat $@.input | ./$@ > $@.log && diff $@.log orig/$@.log # @$(RC) $< && cat $@.input | ./$@ > $@.log && diff $@.log orig/$@.log
@cat $@.input | $(RC) -i $< > $@.log && diff $@.log orig/$@.log @cat $@.input | $(RC) -i $< > $@.log && diff $@.log orig/$@.log
@cat $@.input | $(RC) -s $< > $@.log && diff $@.log orig/$@.log # @cat $@.input | $(RC) -s $< > $@.log && diff $@.log orig/$@.log
clean: clean:
rm -f test*.log *.s *~ $(TESTS) rm -f test*.log *.s *~ $(TESTS)

View file

@ -1,9 +1,18 @@
> > > > > > > > > > > > > > > > > > > > > > 1 > 9
2 55
3 8
34
7
21
6
13
5
8
4 4
5 5
6 3
7 3
8 2
9 2
1
1

View file

@ -1,12 +1,14 @@
> > > > > > > 6 > 7
5 5040
4
3
2
1
1
2
3
4
5
6 6
720
5
120
4
24
3
6
2
2
1
1

14
regression/test030.expr Normal file
View file

@ -0,0 +1,14 @@
fun fib (n) {
if n <= 1
then return 1
else
return fib (n-1) + fib (n-2)
fi
}
read (n);
for i := n, i >= 1, i := i-1 do
write (i);
write (fib (i))
od

1
regression/test030.input Normal file
View file

@ -0,0 +1 @@
9

14
regression/test031.expr Normal file
View file

@ -0,0 +1,14 @@
fun fact (n) {
if n <= 1
then return 1
else
return n * fact (n-1)
fi
}
read (n);
for i := n, i >= 1, i := i-1 do
write (i);
write (fact (i))
od

1
regression/test031.input Normal file
View file

@ -0,0 +1 @@
7

View file

@ -58,18 +58,18 @@ module Expr =
*, /, % --- multiplication, division, reminder *, /, % --- multiplication, division, reminder
*) *)
(* The type of configuration: a state, an input stream, an output stream *) (* The type of configuration: a state, an input stream, an output stream, an optional value *)
type config = State.t * int list * int list type config = State.t * int list * int list * int option
(* Expression evaluator (* Expression evaluator
val eval : env -> config -> t -> int * config val eval : env -> config -> t -> int * config
Takes an environment, a configuration and an expresion, and returns another its value with another configuration. The Takes an environment, a configuration and an expresion, and returns another configuration. The
environment supplies the following method environment supplies the following method
method definition : env -> string -> int list -> config -> (int * config) method definition : env -> string -> int list -> config -> config
which takes an environment (of the same type), a name of the function, a list of actual parameters and a configuration, which takes an environment (of the same type), a name of the function, a list of actual parameters and a configuration,
an returns a pair: the return value for the call and the resulting configuration an returns a pair: the return value for the call and the resulting configuration
@ -94,17 +94,17 @@ module Expr =
| "!!" -> fun x y -> bti (itb x || itb y) | "!!" -> fun x y -> bti (itb x || itb y)
| _ -> failwith (Printf.sprintf "Unknown binary operator %s" op) | _ -> failwith (Printf.sprintf "Unknown binary operator %s" op)
let rec eval env ((st, i, o) as conf) expr = let rec eval env ((st, i, o, r) as conf) expr =
match expr with match expr with
| Const n -> n, conf | Const n -> (st, i, o, Some n)
| Var x -> State.eval st x, conf | Var x -> (st, i, o, Some (State.eval st x))
| Binop (op, x, y) -> | Binop (op, x, y) ->
let x, conf = eval env conf x in let (_, _, _, Some x) as conf = eval env conf x in
let y, conf = eval env conf y in let (st, i, o, Some y) as conf = eval env conf y in
to_func op x y, conf (st, i, o, Some (to_func op x y))
| Call (f, args) -> | Call (f, args) ->
let args, ((st, i, o) as conf) = let args, conf =
List.fold_left (fun (acc, conf) e -> let v, conf = eval env conf e in v::acc, conf) ([], conf) args List.fold_left (fun (acc, conf) e -> let (_, _, _, Some v) as conf = eval env conf e in v::acc, conf) ([], conf) args
in in
env#definition env f (List.rev args) conf env#definition env f (List.rev args) conf
@ -162,27 +162,22 @@ module Stmt =
Takes an environment, a configuration and a statement, and returns another configuration. The Takes an environment, a configuration and a statement, and returns another configuration. The
environment is the same as for expressions environment is the same as for expressions
*) *)
let rec eval env ((st, i, o) as conf) k stmt = let rec eval env ((st, i, o, r) as conf) k stmt =
let seq x y = let seq x = function Skip -> x | y -> Seq (x, y) in
match x, y with
| Skip, _ -> y
| _, Skip -> x
| _ -> Seq (x, y)
in
match stmt with match stmt with
| Read x -> eval env (match i with z::i' -> (State.update x z st, i', o) | _ -> failwith "Unexpected end of input") Skip k | Read x -> eval env (match i with z::i' -> (State.update x z st, i', o, r) | _ -> failwith "Unexpected end of input") Skip k
| Write e -> eval env (let v, (st, i, o) = Expr.eval env conf e in (st, i, o @ [v])) Skip k | Write e -> eval env (let (st, i, o, Some v) = Expr.eval env conf e in (st, i, o @ [v], r)) Skip k
| Assign (x, e) -> eval env (let v, (st, i, o) = Expr.eval env conf e in (State.update x v st, i, o)) Skip k | Assign (x, e) -> eval env (let (st, i, o, Some v) = Expr.eval env conf e in (State.update x v st, i, o, r)) Skip k
| Seq (s1, s2) -> eval env conf (seq s2 k) s1 | Seq (s1, s2) -> eval env conf (seq s2 k) s1
| Skip -> (match k with Skip -> conf | _ -> eval env conf Skip k) | Skip -> (match k with Skip -> conf | _ -> eval env conf Skip k)
| If (e, s1, s2) -> let v, conf = Expr.eval env conf e in eval env conf k (if v <> 0 then s1 else s2) | If (e, s1, s2) -> let (_, _, _, Some v) as conf = Expr.eval env conf e in eval env conf k (if v <> 0 then s1 else s2)
| While (e, s) -> let v, conf = Expr.eval env conf e in | While (e, s) -> let (_, _, _, Some v) as conf = Expr.eval env conf e in
if v = 0 if v = 0
then eval env conf Skip k then eval env conf Skip k
else eval env conf (seq stmt k) s else eval env conf (seq stmt k) s
| Repeat (s, e) -> eval env conf (seq (While (Expr.Binop ("==", e, Expr.Const 0), s)) k) s | Repeat (s, e) -> eval env conf (seq (While (Expr.Binop ("==", e, Expr.Const 0), s)) k) s
| Return e -> failwith "Not implemented" | Return e -> (match e with None -> (st, i, o, None) | Some e -> Expr.eval env conf e)
| Call (f, args) -> eval env (snd (Expr.eval env conf (Expr.Call (f, args)))) k Skip | Call (f, args) -> eval env (Expr.eval env conf (Expr.Call (f, args))) k Skip
(* Statement parser *) (* Statement parser *)
ostap ( ostap (
@ -251,16 +246,16 @@ type t = Definition.t list * Stmt.t
let eval (defs, body) i = let eval (defs, body) i =
let module M = Map.Make (String) in let module M = Map.Make (String) in
let m = List.fold_left (fun m ((name, _) as def) -> M.add name def m) M.empty defs in let m = List.fold_left (fun m ((name, _) as def) -> M.add name def m) M.empty defs in
let _, _, o = let _, _, o, _ =
Stmt.eval Stmt.eval
(object (object
method definition env f args (st, i, o) = method definition env f args (st, i, o, r) =
let xs, locs, s = snd @@ M.find f m in let xs, locs, s = snd @@ M.find f m in
let st' = List.fold_left (fun st (x, a) -> State.update x a st) (State.enter st (xs @ locs)) (List.combine xs args) in let st' = List.fold_left (fun st (x, a) -> State.update x a st) (State.enter st (xs @ locs)) (List.combine xs args) in
let st'', i', o' = Stmt.eval env (st', i, o) Skip s in let st'', i', o', r' = Stmt.eval env (st', i, o, r) Skip s in
0, (State.leave st'' st, i', o') (State.leave st'' st, i', o', r')
end) end)
(State.empty, i, []) (State.empty, i, [], None)
Skip Skip
body body
in in