1 module List = ListLabels
2 module String = StringLabels
14 | CompoundStm of stm * stm
15 | AssignStm of id * exp
16 | PrintStm of exp list
20 | OpExp of exp * binop * exp
21 | EseqExp of stm * exp
23 exception Unknown_identifier of string
25 val maxargs : stm -> int option
26 (** Option because a program may not have any print statements at all. *)
28 val interp : stm -> unit
29 (** raises Unknown_identifier, if such is encountered *)
33 val empty : ('k, 'v) t
34 val set : ('k, 'v) t -> k:'k -> v:'v -> ('k, 'v) t
35 val get : ('k, 'v) t -> k:'k -> 'v option
37 type ('k, 'v) t = ('k * 'v) list
39 let set t ~k ~v = (k, v) :: t
41 let rec search = function
43 | (key, v) :: _ when key = k -> Some v
44 | (_, _) :: rest -> search rest
58 | CompoundStm of stm * stm
59 | AssignStm of id * exp
60 | PrintStm of exp list
64 | OpExp of exp * binop * exp
65 | EseqExp of stm * exp
67 exception Unknown_identifier of string
69 let interp_binop op v1 v2 =
76 let rec interp_stm tbl_0 stm =
79 let (tbl_1, val_ints) =
82 ~f:(fun e (tbl0, vs) ->
83 let (tbl1, v) = interp_exp tbl0 e in
87 let val_strings = List.map val_ints ~f:string_of_int in
88 print_endline (String.concat val_strings ~sep:" ");
90 | AssignStm (id, e) ->
91 let (tbl_1, v) = interp_exp tbl_0 e in
92 Table.set tbl_1 ~k:id ~v
93 | CompoundStm (s1, s2) ->
94 let tbl_1 = interp_stm tbl_0 s1 in
97 and interp_exp tbl_0 exp =
100 ( match Table.get tbl_0 ~k:id with
101 | Some v -> (tbl_0, v)
102 | None -> raise (Unknown_identifier id)
104 | NumExp n -> (tbl_0, n)
105 | OpExp (e1, op, e2) ->
106 let (tbl_1, v1) = interp_exp tbl_0 e1 in
107 let (tbl_2, v2) = interp_exp tbl_1 e2 in
108 (tbl_2, interp_binop op v1 v2)
110 let tbl_1 = interp_stm tbl_0 s in
114 let interp stm : unit =
115 ignore (interp_stm (Table.empty) stm)
117 (* 01.p.1: Write ML function (maxargs : stm -> int) that tells the
118 * maximum number of arguments of any print statement within any
119 * subexpression of a given statement. For example, maxargs(prog)
123 let opt_max_update opt n =
126 | Some m -> Some (max m n)
128 let opt_max_merge a b =
130 | None , None -> None
133 | Some _, Some n -> opt_max_update a n
135 let rec check_stm max_opt stm =
139 ~init:(opt_max_update max_opt (List.length exps))
141 | AssignStm (_, e) ->
143 | CompoundStm (s1, s2) ->
144 opt_max_merge (check_stm max_opt s1) (check_stm max_opt s2)
145 and check_exp max_opt exp =
147 | IdExp _ | NumExp _ -> max_opt
148 | OpExp (e1, _, e2) ->
149 opt_max_merge (check_exp max_opt e1) (check_exp max_opt e2)
151 opt_max_merge (check_stm max_opt s) (check_exp max_opt e)
158 * b := (print(a, a - 1), 10 * a);
162 ( Spl.AssignStm ("a", Spl.OpExp (Spl.NumExp 5, Spl.Plus, Spl.NumExp 3))
169 ; Spl.OpExp (Spl.IdExp "a", Spl.Minus, Spl.NumExp 1)
171 , Spl.OpExp (Spl.NumExp 10, Spl.Times, Spl.IdExp "a")
174 , Spl.PrintStm [Spl.IdExp "b"]
178 let spl_prog_noprint =
184 ("a", Spl.OpExp (Spl.NumExp 5, Spl.Plus, Spl.NumExp 3))
186 ("b", Spl.OpExp (Spl.NumExp 10, Spl.Times, Spl.IdExp "a"))
190 let string_of_maxargs int_opt =
192 | Some n -> string_of_int n
195 Printf.printf "maxargs : spl_prog_orig -> %s\n"
196 (string_of_maxargs (Spl.maxargs spl_prog_orig));
197 Printf.printf "maxargs : spl_prog_noprint -> %s\n"
198 (string_of_maxargs (Spl.maxargs spl_prog_noprint));
199 print_endline "BEGIN Spl.interp spl_prog_orig";
200 Spl.interp spl_prog_orig;
201 print_endline "END Spl.interp spl_prog_orig"