mirror of
https://github.com/ProgramSnail/Lama.git
synced 2025-12-06 23:08:46 +00:00
Procedures in interpretation
This commit is contained in:
parent
30697f19eb
commit
b4ef95c8bc
22 changed files with 337 additions and 188 deletions
|
|
@ -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
|
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
|
||||||
|
|
||||||
RC=../src/rc.opt
|
RC=../src/rc.opt
|
||||||
|
|
||||||
|
|
@ -7,9 +7,9 @@ RC=../src/rc.opt
|
||||||
check: $(TESTS)
|
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)
|
||||||
|
|
|
||||||
|
|
@ -1 +1,2 @@
|
||||||
> 6765
|
> 3
|
||||||
|
8
|
||||||
|
|
|
||||||
|
|
@ -1 +1,12 @@
|
||||||
> 3628800
|
> 1
|
||||||
|
100
|
||||||
|
200
|
||||||
|
300
|
||||||
|
2
|
||||||
|
100
|
||||||
|
200
|
||||||
|
300
|
||||||
|
3
|
||||||
|
100
|
||||||
|
200
|
||||||
|
300
|
||||||
|
|
|
||||||
|
|
@ -1 +1,21 @@
|
||||||
> > 125
|
> 1
|
||||||
|
100
|
||||||
|
200
|
||||||
|
300
|
||||||
|
100
|
||||||
|
200
|
||||||
|
300
|
||||||
|
2
|
||||||
|
100
|
||||||
|
200
|
||||||
|
300
|
||||||
|
100
|
||||||
|
200
|
||||||
|
300
|
||||||
|
3
|
||||||
|
100
|
||||||
|
200
|
||||||
|
300
|
||||||
|
100
|
||||||
|
200
|
||||||
|
300
|
||||||
|
|
|
||||||
|
|
@ -1,136 +1,35 @@
|
||||||
73
|
> 1
|
||||||
32
|
100
|
||||||
119
|
200
|
||||||
105
|
300
|
||||||
108
|
|
||||||
108
|
|
||||||
32
|
|
||||||
114
|
|
||||||
101
|
|
||||||
109
|
|
||||||
101
|
|
||||||
109
|
|
||||||
98
|
|
||||||
101
|
|
||||||
114
|
|
||||||
32
|
|
||||||
65
|
|
||||||
112
|
|
||||||
114
|
|
||||||
105
|
|
||||||
108
|
|
||||||
46
|
|
||||||
0
|
|
||||||
114
|
|
||||||
101
|
|
||||||
109
|
|
||||||
101
|
|
||||||
109
|
|
||||||
98
|
|
||||||
101
|
|
||||||
114
|
|
||||||
0
|
|
||||||
114
|
|
||||||
101
|
|
||||||
109
|
|
||||||
101
|
|
||||||
109
|
|
||||||
98
|
|
||||||
101
|
|
||||||
114
|
|
||||||
0
|
|
||||||
22
|
|
||||||
0
|
|
||||||
73
|
|
||||||
32
|
|
||||||
119
|
|
||||||
106
|
|
||||||
108
|
|
||||||
108
|
|
||||||
32
|
|
||||||
114
|
|
||||||
101
|
|
||||||
109
|
|
||||||
101
|
|
||||||
109
|
|
||||||
98
|
|
||||||
101
|
|
||||||
114
|
|
||||||
32
|
|
||||||
65
|
|
||||||
112
|
|
||||||
114
|
|
||||||
106
|
|
||||||
108
|
|
||||||
46
|
|
||||||
0
|
|
||||||
73
|
|
||||||
32
|
|
||||||
119
|
|
||||||
105
|
|
||||||
108
|
|
||||||
108
|
|
||||||
32
|
|
||||||
114
|
|
||||||
101
|
|
||||||
109
|
|
||||||
101
|
|
||||||
109
|
|
||||||
98
|
|
||||||
101
|
|
||||||
114
|
|
||||||
32
|
|
||||||
65
|
|
||||||
112
|
|
||||||
114
|
|
||||||
105
|
|
||||||
108
|
|
||||||
46
|
|
||||||
0
|
|
||||||
73
|
|
||||||
32
|
|
||||||
119
|
|
||||||
106
|
|
||||||
108
|
|
||||||
108
|
|
||||||
32
|
|
||||||
114
|
|
||||||
101
|
|
||||||
109
|
|
||||||
101
|
|
||||||
109
|
|
||||||
98
|
|
||||||
101
|
|
||||||
114
|
|
||||||
32
|
|
||||||
65
|
|
||||||
112
|
|
||||||
114
|
|
||||||
106
|
|
||||||
108
|
|
||||||
46
|
|
||||||
73
|
|
||||||
32
|
|
||||||
119
|
|
||||||
105
|
|
||||||
108
|
|
||||||
108
|
|
||||||
32
|
|
||||||
114
|
|
||||||
101
|
|
||||||
109
|
|
||||||
101
|
|
||||||
109
|
|
||||||
98
|
|
||||||
101
|
|
||||||
114
|
|
||||||
32
|
|
||||||
65
|
|
||||||
112
|
|
||||||
114
|
|
||||||
105
|
|
||||||
108
|
|
||||||
46
|
|
||||||
1
|
1
|
||||||
-1
|
2
|
||||||
0
|
100
|
||||||
|
200
|
||||||
|
300
|
||||||
|
3
|
||||||
|
100
|
||||||
|
200
|
||||||
|
300
|
||||||
|
3
|
||||||
|
4
|
||||||
|
100
|
||||||
|
200
|
||||||
|
300
|
||||||
|
5
|
||||||
|
100
|
||||||
|
200
|
||||||
|
300
|
||||||
|
5
|
||||||
|
100
|
||||||
|
200
|
||||||
|
300
|
||||||
|
100
|
||||||
|
200
|
||||||
|
300
|
||||||
|
100
|
||||||
|
200
|
||||||
|
300
|
||||||
|
100
|
||||||
|
200
|
||||||
|
300
|
||||||
|
|
|
||||||
|
|
@ -1,2 +1,14 @@
|
||||||
|
> 7
|
||||||
|
5040
|
||||||
|
6
|
||||||
|
720
|
||||||
|
5
|
||||||
|
120
|
||||||
|
4
|
||||||
|
24
|
||||||
|
3
|
||||||
|
6
|
||||||
|
2
|
||||||
|
2
|
||||||
|
1
|
||||||
1
|
1
|
||||||
100
|
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,18 @@
|
||||||
> > > > > 5
|
> 9
|
||||||
6
|
55
|
||||||
7
|
8
|
||||||
|
34
|
||||||
|
7
|
||||||
|
21
|
||||||
|
6
|
||||||
|
13
|
||||||
|
5
|
||||||
8
|
8
|
||||||
9
|
|
||||||
1
|
|
||||||
2
|
|
||||||
3
|
|
||||||
4
|
4
|
||||||
5
|
5
|
||||||
|
3
|
||||||
|
3
|
||||||
|
2
|
||||||
|
2
|
||||||
|
1
|
||||||
|
1
|
||||||
|
|
|
||||||
13
regression/test024.expr
Normal file
13
regression/test024.expr
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
fun test1 () {
|
||||||
|
a := 3
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test2 (b) {
|
||||||
|
a := b
|
||||||
|
}
|
||||||
|
|
||||||
|
test1 ();
|
||||||
|
write (a);
|
||||||
|
|
||||||
|
test2 (8);
|
||||||
|
write (a)
|
||||||
1
regression/test024.input
Normal file
1
regression/test024.input
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
0
|
||||||
29
regression/test025.expr
Normal file
29
regression/test025.expr
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
fun test1 (a) {
|
||||||
|
write (a)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test2 (b) {
|
||||||
|
write (b)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test3 (c) {
|
||||||
|
write (c)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun print () {
|
||||||
|
write (a);
|
||||||
|
write (b);
|
||||||
|
write (c)
|
||||||
|
}
|
||||||
|
|
||||||
|
a := 100;
|
||||||
|
b := 200;
|
||||||
|
c := 300;
|
||||||
|
|
||||||
|
test1 (1);
|
||||||
|
print ();
|
||||||
|
test2 (2);
|
||||||
|
print ();
|
||||||
|
test3 (3);
|
||||||
|
print ()
|
||||||
|
|
||||||
1
regression/test025.input
Normal file
1
regression/test025.input
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
0
|
||||||
32
regression/test026.expr
Normal file
32
regression/test026.expr
Normal file
|
|
@ -0,0 +1,32 @@
|
||||||
|
fun test1 (a) {
|
||||||
|
write (a);
|
||||||
|
print ()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test2 (b) {
|
||||||
|
write (b);
|
||||||
|
print ()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test3 (c) {
|
||||||
|
write (c);
|
||||||
|
print ()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun print () {
|
||||||
|
write (a);
|
||||||
|
write (b);
|
||||||
|
write (c)
|
||||||
|
}
|
||||||
|
|
||||||
|
a := 100;
|
||||||
|
b := 200;
|
||||||
|
c := 300;
|
||||||
|
|
||||||
|
test1 (1);
|
||||||
|
print ();
|
||||||
|
test2 (2);
|
||||||
|
print ();
|
||||||
|
test3 (3);
|
||||||
|
print ()
|
||||||
|
|
||||||
1
regression/test026.input
Normal file
1
regression/test026.input
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
0
|
||||||
28
regression/test027.expr
Normal file
28
regression/test027.expr
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
fun print () {
|
||||||
|
write (a);
|
||||||
|
write (b);
|
||||||
|
write (c)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test1 (a) {
|
||||||
|
write (a);
|
||||||
|
print ();
|
||||||
|
write (a);
|
||||||
|
if a < 4 then
|
||||||
|
test2 (a+1);
|
||||||
|
print ()
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test2 (b) {
|
||||||
|
write (b);
|
||||||
|
print ();
|
||||||
|
test1 (b+1);
|
||||||
|
print ()
|
||||||
|
}
|
||||||
|
|
||||||
|
a := 100;
|
||||||
|
b := 200;
|
||||||
|
c := 300;
|
||||||
|
|
||||||
|
test1 (1)
|
||||||
1
regression/test027.input
Normal file
1
regression/test027.input
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
0
|
||||||
16
regression/test028.expr
Normal file
16
regression/test028.expr
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
fun fact (n) {
|
||||||
|
if n <= 1
|
||||||
|
then result := 1
|
||||||
|
else
|
||||||
|
fact (n-1);
|
||||||
|
result := result * n
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
read (n);
|
||||||
|
|
||||||
|
for i := n, i >= 1, i := i-1 do
|
||||||
|
fact (i);
|
||||||
|
write (i);
|
||||||
|
write (result)
|
||||||
|
od
|
||||||
1
regression/test028.input
Normal file
1
regression/test028.input
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
7
|
||||||
18
regression/test029.expr
Normal file
18
regression/test029.expr
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
fun fib (n) local r {
|
||||||
|
if n <= 1
|
||||||
|
then result := 1
|
||||||
|
else
|
||||||
|
fib (n-1);
|
||||||
|
r := result;
|
||||||
|
fib (n-2);
|
||||||
|
result := result + r
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
read (n);
|
||||||
|
|
||||||
|
for i := n, i >= 1, i := i-1 do
|
||||||
|
fib (i);
|
||||||
|
write (i);
|
||||||
|
write (result)
|
||||||
|
od
|
||||||
1
regression/test029.input
Normal file
1
regression/test029.input
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
9
|
||||||
|
|
@ -6,7 +6,7 @@ let parse infile =
|
||||||
(object
|
(object
|
||||||
inherit Matcher.t s
|
inherit Matcher.t s
|
||||||
inherit Util.Lexers.decimal s
|
inherit Util.Lexers.decimal s
|
||||||
inherit Util.Lexers.ident ["read"; "write"; "skip"; "if"; "then"; "else"; "elif"; "fi"; "while"; "do"; "od"; "repeat"; "until"; "for"] s
|
inherit Util.Lexers.ident ["read"; "write"; "skip"; "if"; "then"; "else"; "elif"; "fi"; "while"; "do"; "od"; "repeat"; "until"; "for"; "fun"; "local"] s
|
||||||
inherit Util.Lexers.skip [
|
inherit Util.Lexers.skip [
|
||||||
Matcher.Skip.whitespaces " \t\n";
|
Matcher.Skip.whitespaces " \t\n";
|
||||||
Matcher.Skip.lineComment "--";
|
Matcher.Skip.lineComment "--";
|
||||||
|
|
@ -25,9 +25,11 @@ let main =
|
||||||
match parse infile with
|
match parse infile with
|
||||||
| `Ok prog ->
|
| `Ok prog ->
|
||||||
if to_compile
|
if to_compile
|
||||||
then
|
then failwith "Not implemented yet"
|
||||||
|
(*
|
||||||
let basename = Filename.chop_suffix infile ".expr" in
|
let basename = Filename.chop_suffix infile ".expr" in
|
||||||
ignore @@ X86.build prog basename
|
ignore @@ X86.build prog basename
|
||||||
|
*)
|
||||||
else
|
else
|
||||||
let rec read acc =
|
let rec read acc =
|
||||||
try
|
try
|
||||||
|
|
@ -40,7 +42,7 @@ let main =
|
||||||
let output =
|
let output =
|
||||||
if interpret
|
if interpret
|
||||||
then Language.eval prog input
|
then Language.eval prog input
|
||||||
else SM.run (SM.compile prog) input
|
else failwith "Not implemented yet" (*SM.run (SM.compile prog) input*)
|
||||||
in
|
in
|
||||||
List.iter (fun i -> Printf.printf "%d\n" i) output
|
List.iter (fun i -> Printf.printf "%d\n" i) output
|
||||||
| `Fail er -> Printf.eprintf "Syntax error: %s\n" er
|
| `Fail er -> Printf.eprintf "Syntax error: %s\n" er
|
||||||
|
|
|
||||||
114
src/Language.ml
114
src/Language.ml
|
|
@ -4,7 +4,38 @@
|
||||||
open GT
|
open GT
|
||||||
|
|
||||||
(* Opening a library for combinator-based syntax analysis *)
|
(* Opening a library for combinator-based syntax analysis *)
|
||||||
open Ostap.Combinators
|
open Ostap
|
||||||
|
open Combinators
|
||||||
|
|
||||||
|
(* States *)
|
||||||
|
module State =
|
||||||
|
struct
|
||||||
|
|
||||||
|
(* State: global state, local state, scope variables *)
|
||||||
|
type t = {g : string -> int; l : string -> int; scope : string list}
|
||||||
|
|
||||||
|
(* Empty state *)
|
||||||
|
let empty =
|
||||||
|
let e x = failwith (Printf.sprintf "Undefined variable: %s" x) in
|
||||||
|
{g = e; l = e; scope = []}
|
||||||
|
|
||||||
|
(* Update: non-destructively "modifies" the state s by binding the variable x
|
||||||
|
to value v and returns the new state w.r.t. a scope
|
||||||
|
*)
|
||||||
|
let update x v s =
|
||||||
|
let u x v s = fun y -> if x = y then v else s y in
|
||||||
|
if List.mem x s.scope then {s with l = u x v s.l} else {s with g = u x v s.g}
|
||||||
|
|
||||||
|
(* Evals a variable in a state w.r.t. a scope *)
|
||||||
|
let eval s x = (if List.mem x s.scope then s.l else s.g) x
|
||||||
|
|
||||||
|
(* Creates a new scope, based on a given state *)
|
||||||
|
let push_scope st xs = {empty with g = st.g; scope = xs}
|
||||||
|
|
||||||
|
(* Drops a scope *)
|
||||||
|
let drop_scope st st' = {st' with g = st.g}
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
(* Simple expressions: syntax and semantics *)
|
(* Simple expressions: syntax and semantics *)
|
||||||
module Expr =
|
module Expr =
|
||||||
|
|
@ -26,17 +57,6 @@ module Expr =
|
||||||
*, /, % --- multiplication, division, reminder
|
*, /, % --- multiplication, division, reminder
|
||||||
*)
|
*)
|
||||||
|
|
||||||
(* State: a partial map from variables to integer values. *)
|
|
||||||
type state = string -> int
|
|
||||||
|
|
||||||
(* Empty state: maps every variable into nothing. *)
|
|
||||||
let empty = fun x -> failwith (Printf.sprintf "Undefined variable %s" x)
|
|
||||||
|
|
||||||
(* Update: non-destructively "modifies" the state s by binding the variable x
|
|
||||||
to value v and returns the new state.
|
|
||||||
*)
|
|
||||||
let update x v s = fun y -> if x = y then v else s y
|
|
||||||
|
|
||||||
(* Expression evaluator
|
(* Expression evaluator
|
||||||
|
|
||||||
val eval : state -> t -> int
|
val eval : state -> t -> int
|
||||||
|
|
@ -67,7 +87,7 @@ module Expr =
|
||||||
let rec eval st expr =
|
let rec eval st expr =
|
||||||
match expr with
|
match expr with
|
||||||
| Const n -> n
|
| Const n -> n
|
||||||
| Var x -> st x
|
| Var x -> State.eval st x
|
||||||
| Binop (op, x, y) -> to_func op (eval st x) (eval st y)
|
| Binop (op, x, y) -> to_func op (eval st x) (eval st y)
|
||||||
|
|
||||||
(* Expression parser. You can use the following terminals:
|
(* Expression parser. You can use the following terminals:
|
||||||
|
|
@ -114,27 +134,38 @@ module Stmt =
|
||||||
(* empty statement *) | Skip
|
(* empty statement *) | Skip
|
||||||
(* conditional *) | If of Expr.t * t * t
|
(* conditional *) | If of Expr.t * t * t
|
||||||
(* loop with a pre-condition *) | While of Expr.t * t
|
(* loop with a pre-condition *) | While of Expr.t * t
|
||||||
(* loop with a post-condition *) | Repeat of t * Expr.t with show
|
(* loop with a post-condition *) | Repeat of t * Expr.t
|
||||||
|
(* call a procedure *) | Call of string * Expr.t list with show
|
||||||
|
|
||||||
(* The type of configuration: a state, an input stream, an output stream *)
|
(* The type of configuration: a state, an input stream, an output stream *)
|
||||||
type config = Expr.state * int list * int list
|
type config = State.t * int list * int list
|
||||||
|
|
||||||
(* Statement evaluator
|
(* Statement evaluator
|
||||||
|
|
||||||
val eval : config -> t -> config
|
val eval : env -> config -> t -> config
|
||||||
|
|
||||||
Takes a configuration and a statement, and returns another configuration
|
Takes an environment, a configuration and a statement, and returns another configuration. The
|
||||||
|
environment supplies the following method
|
||||||
|
|
||||||
|
method definition : string -> (string list, t)
|
||||||
|
|
||||||
|
which returns a list of formal parameters and a body for given definition
|
||||||
*)
|
*)
|
||||||
let rec eval ((st, i, o) as conf) stmt =
|
let rec eval env ((st, i, o) as conf) stmt =
|
||||||
match stmt with
|
match stmt with
|
||||||
| Read x -> (match i with z::i' -> (Expr.update x z st, i', o) | _ -> failwith "Unexpected end of input")
|
| Read x -> (match i with z::i' -> (State.update x z st, i', o) | _ -> failwith "Unexpected end of input")
|
||||||
| Write e -> (st, i, o @ [Expr.eval st e])
|
| Write e -> (st, i, o @ [Expr.eval st e])
|
||||||
| Assign (x, e) -> (Expr.update x (Expr.eval st e) st, i, o)
|
| Assign (x, e) -> (State.update x (Expr.eval st e) st, i, o)
|
||||||
| Seq (s1, s2) -> eval (eval conf s1) s2
|
| Seq (s1, s2) -> eval env (eval env conf s1) s2
|
||||||
| Skip -> conf
|
| Skip -> conf
|
||||||
| If (e, s1, s2) -> eval conf (if Expr.eval st e <> 0 then s1 else s2)
|
| If (e, s1, s2) -> eval env conf (if Expr.eval st e <> 0 then s1 else s2)
|
||||||
| While (e, s) -> if Expr.eval st e = 0 then conf else eval (eval conf s) stmt
|
| While (e, s) -> if Expr.eval st e = 0 then conf else eval env (eval env conf s) stmt
|
||||||
| Repeat (s, e) -> let (st, _, _) as conf' = eval conf s in if Expr.eval st e = 0 then eval conf' stmt else conf'
|
| Repeat (s, e) -> let (st, _, _) as conf' = eval env conf s in if Expr.eval st e = 0 then eval env conf' stmt else conf'
|
||||||
|
| Call (f, args) -> let args = List.map (Expr.eval st) args in
|
||||||
|
let xs, locs, s = env#definition f in
|
||||||
|
let st' = List.fold_left (fun st (x, a) -> State.update x a st) (State.push_scope st (xs @ locs)) (List.combine xs args) in
|
||||||
|
let st'', i', o' = eval env (st', i, o) s in
|
||||||
|
(State.drop_scope st'' st, i', o')
|
||||||
|
|
||||||
(* Statement parser *)
|
(* Statement parser *)
|
||||||
ostap (
|
ostap (
|
||||||
|
|
@ -162,15 +193,36 @@ module Stmt =
|
||||||
Seq (i, While (c, Seq (b, s)))
|
Seq (i, While (c, Seq (b, s)))
|
||||||
}
|
}
|
||||||
| %"repeat" s:parse %"until" e:!(Expr.parse) {Repeat (s, e)}
|
| %"repeat" s:parse %"until" e:!(Expr.parse) {Repeat (s, e)}
|
||||||
| x:IDENT ":=" e:!(Expr.parse) {Assign (x, e)}
|
| x:IDENT
|
||||||
|
s:(":=" e :!(Expr.parse) {Assign (x, e)} |
|
||||||
|
"(" args:!(Util.list0)[Expr.parse] ")" {Call (x, args)}
|
||||||
|
) {s}
|
||||||
|
)
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
(* Function and procedure definitions *)
|
||||||
|
module Definition =
|
||||||
|
struct
|
||||||
|
|
||||||
|
(* The type for a definition: name, argument list, local variables, body *)
|
||||||
|
type t = string * (string list * string list * Stmt.t)
|
||||||
|
|
||||||
|
ostap (
|
||||||
|
arg : IDENT;
|
||||||
|
parse: %"fun" name:IDENT "(" args:!(Util.list0 arg) ")"
|
||||||
|
locs:(%"local" !(Util.list arg))?
|
||||||
|
"{" body:!(Stmt.parse) "}" {
|
||||||
|
(name, (args, (match locs with None -> [] | Some l -> l), body))
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
(* The top-level definitions *)
|
(* The top-level definitions *)
|
||||||
|
|
||||||
(* The top-level syntax category is statement *)
|
(* The top-level syntax category is a pair of definition list and statement (program body) *)
|
||||||
type t = Stmt.t
|
type t = Definition.t list * Stmt.t
|
||||||
|
|
||||||
(* Top-level evaluator
|
(* Top-level evaluator
|
||||||
|
|
||||||
|
|
@ -178,8 +230,10 @@ type t = Stmt.t
|
||||||
|
|
||||||
Takes a program and its input stream, and returns the output stream
|
Takes a program and its input stream, and returns the output stream
|
||||||
*)
|
*)
|
||||||
let eval p i =
|
let eval (defs, body) i =
|
||||||
let _, _, o = Stmt.eval (Expr.empty, i, []) p in o
|
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 _, _, o = Stmt.eval (object method definition f = snd @@ M.find f m end) (State.empty, i, []) body in o
|
||||||
|
|
||||||
(* Top-level parser *)
|
(* Top-level parser *)
|
||||||
let parse = Stmt.parse
|
let parse = ostap (!(Definition.parse)* !(Stmt.parse))
|
||||||
|
|
|
||||||
|
|
@ -36,8 +36,8 @@ let rec eval env ((stack, ((st, i, o) as c)) as conf) = function
|
||||||
| READ -> let z::i' = i in eval env (z::stack, (st, i', o)) prg'
|
| READ -> let z::i' = i in eval env (z::stack, (st, i', o)) prg'
|
||||||
| WRITE -> let z::stack' = stack in eval env (stack', (st, i, o @ [z])) prg'
|
| WRITE -> let z::stack' = stack in eval env (stack', (st, i, o @ [z])) prg'
|
||||||
| CONST i -> eval env (i::stack, c) prg'
|
| CONST i -> eval env (i::stack, c) prg'
|
||||||
| LD x -> eval env (st x :: stack, c) prg'
|
| LD x -> eval env (State.eval st x :: stack, c) prg'
|
||||||
| ST x -> let z::stack' = stack in eval env (stack', (Expr.update x z st, i, o)) prg'
|
| ST x -> let z::stack' = stack in eval env (stack', (State.update x z st, i, o)) prg'
|
||||||
| LABEL _ -> eval env conf prg'
|
| LABEL _ -> eval env conf prg'
|
||||||
| JMP l -> eval env conf (env#labeled l)
|
| JMP l -> eval env conf (env#labeled l)
|
||||||
| CJMP (c, l) -> let x::stack' = stack in eval env conf (if (c = "z" && x = 0) || (c = "nz" && x <> 0) then env#labeled l else prg')
|
| CJMP (c, l) -> let x::stack' = stack in eval env conf (if (c = "z" && x = 0) || (c = "nz" && x <> 0) then env#labeled l else prg')
|
||||||
|
|
@ -57,7 +57,7 @@ let run p i =
|
||||||
| _ :: tl -> make_map m tl
|
| _ :: tl -> make_map m tl
|
||||||
in
|
in
|
||||||
let m = make_map M.empty p in
|
let m = make_map M.empty p in
|
||||||
let (_, (_, _, o)) = eval (object method labeled l = M.find l m end) ([], (Expr.empty, i, [])) p in o
|
let (_, (_, _, o)) = eval (object method labeled l = M.find l m end) ([], (State.empty, i, [])) p in o
|
||||||
|
|
||||||
(* Stack machine compiler
|
(* Stack machine compiler
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue