abstype id_t
extern fun id_make (name: string): id_t
extern fun eq_id_id (_: id_t, _: id_t): bool
overload = with eq_id_id
extern fun print_id (_: id_t): void
overload print with print_id
local
assume id_t = string
in
implement id_make (name) = name
implement eq_id_id (x, y) = eq_string_string (x, y)
implement print_id (x) = print_string x
end
datatype binop = Plus | Minus | Times | Div
datatype stm = CompoundStm of (stm, stm)
| AssignStm of (id_t, exp)
| PrintStm of explst
and exp = IdExp of id_t
| NumExp of int
| OpExp of (exp, binop, exp)
| EseqExp of (stm, exp)
where explst = List exp
abstype table_t
extern fun table_make (): table_t
extern fun lookup (tbl: table_t, x: id_t): int
extern fun update (tbl: table_t, x: id_t, v: int): table_t
local
assume table_t = List @(id_t, int)
in
implement table_make () = list_nil ()
implement lookup (tbl, x0) = case+ tbl of
| list_cons (xv, tbl) => if (x0 = xv.0) then xv.1 else lookup (tbl, x0)
| list_nil () => begin
0 end
implement update (tbl, x0, v_new) = case+ tbl of
| list_cons (xv, tbl) => begin
if x0 = xv.0 then
list_cons (@(x0, v_new), tbl)
else
list_cons (xv, update (tbl, x0, v_new))
end | list_nil () => list_cons (@(x0, v_new), list_nil ())
end
extern fun interpStm (tbl: table_t, _: stm): table_t
extern fun interpExp (tbl: table_t, _: exp): @(int, table_t)
implement interpStm (tbl, stm) = case+ stm of
| CompoundStm (stm1, stm2) => let
val tbl = interpStm (tbl, stm1) in interpStm (tbl, stm2)
end | AssignStm (id, exp) => let
val @(v, tbl) = interpExp (tbl, exp) in update (tbl, id, v)
end | PrintStm (exps) => loop (tbl, exps, 0) where {
fun loop (tbl: table_t, exps: explst, i: int): table_t =
case+ exps of
| list_cons (exp, exps) => let
val (v, tbl) = interpExp (tbl, exp)
in
if i > 0 then print ' '; print v; loop (tbl, exps, i+1)
end | list_nil () => (print_newline (); tbl)
}
implement interpExp (tbl, exp) = case+ exp of
| IdExp id => let val v = lookup (tbl, id) in @(v, tbl) end
| NumExp v => @(v, tbl)
| OpExp (exp1, binop, exp2) => let
val (v1, tbl) = interpExp (tbl, exp1)
val (v2, tbl) = interpExp (tbl, exp2)
val v = (case+ binop of
| Plus () => v1 + v2 | Minus () => v1 - v2 | Times () => v1 * v2 | Div () => v1 / v2
) : int
in
(v, tbl)
end | EseqExp (stm, exp) => let
val tbl = interpStm (tbl, stm) in interpExp (tbl, exp)
end
extern fun interp (_: stm): void
implement interp (stm) = let
val tbl0 = table_make (); val tbl = interpStm (tbl0, stm)
in
end
implement main () = let
val a_id = id_make "a"
val b_id = id_make "b"
val a_exp = IdExp a_id
val b_exp = IdExp b_id
val stm1 = AssignStm (a_id, OpExp (NumExp 5, Plus, NumExp 3))
val stm2 = PrintStm $lst (a_exp, OpExp (a_exp, Minus, NumExp 1))
val stm3 = AssignStm (b_id, EseqExp (stm2, OpExp (NumExp 10, Times, a_exp)))
val stm4 = CompoundStm (stm1, stm3)
val stm5 = CompoundStm (stm4, PrintStm $lst (b_exp))
in
interp (stm5)
end