```(*
** Course: Concepts of Programming Languages (BU CAS CS 320)
** Semester: Summer I, 2009
** Instructor: Hongwei Xi (hwxi AT cs DOT bu DOT edu)
*)

//
// Author: Hongwei Xi (hwxi AT cs DOT bu DOT edu)
// Time: May 27, 2009
//

(* ****** ****** *)

#include "BUCASCS320.hats"

(* ****** ****** *)

datatype weekday =
| Monday of ()
| Tuesday of ()
| Wednesday of ()
| Thursday of ()
| Friday of ()

fun isWednesday (day: weekday): bool =
case+ day of Wednesday () => true | _ => false
// end of [isWednesday]

(* ****** ****** *)

datatype order = LESS | EQUAL | GREATER

(* ****** ****** *)

(*

datatype option (a:t@ype) = Some(a) of a | None(a) of ()

*)

fun{a:t@ype} list0_last
(xs: list0 a): option0 a = let
fun loop (x: a, xs: list0 a): a =
case+ xs of
| list0_cons (x, xs) => loop (x, xs)
| list0_nil () => x
in
case+ xs of
| list0_cons (x, xs) => option0_some (loop (x, xs))
| list0_nil () => option0_none ()
end // end of [list0_last]

(* ****** ****** *)

datatype exp =
| EXPint of int
| EXPsub of (exp, exp)
| EXPmul of (exp, exp)
| EXPdiv of (exp, exp)
// end of [datatype exp]

// evaluating expressions of the type [exp]
fun exp_eval (e: exp): int = case+ e of
| EXPint i => i
| EXPadd (e1, e2) => exp_eval e1 + exp_eval e2
| EXPsub (e1, e2) => exp_eval e1 - exp_eval e2
| EXPmul (e1, e2) => exp_eval e1 * exp_eval e2
| EXPdiv (e1, e2) => exp_eval e1 / exp_eval e2
// end of [exp_eval]

(* ****** ****** *)

fun fprint_exp (out: FILEref, e: exp): void = let
// simple macro definitions
macdef prexp (e) = fprint_exp (out, ,(e))
macdef prstr (s) = fprint_string (out, ,(s))
in
case+ e of
| EXPint i => fprint_int (out, i)
| EXPadd (e1, e2) => begin
prstr "EXPadd("; prexp e1; prstr ", "; prexp e2; prstr ")"
end (* end of [EXPadd] *)
| EXPsub (e1, e2) => begin
prstr "EXPsub("; prexp e1; prstr ", "; prexp e2; prstr ")"
end (* end of [EXPsub] *)
| EXPmul (e1, e2) => begin
prstr "EXPmul("; prexp e1; prstr ", "; prexp e2; prstr ")"
end (* end of [EXPmul] *)
| EXPdiv (e1, e2) => begin
prstr "EXPdiv("; prexp e1; prstr ", "; prexp e2; prstr ")"
end (* end of [EXPdiv] *)
end // end of [fprint_exp]

fun print_exp (e: exp): void = fprint_exp (stdout_ref, e)
fun prerr_exp (e: exp): void = fprint_exp (stderr_ref, e)

(* ****** ****** *)

implement main () = let
val e1 = EXPmul (e2, EXPint 7) where {
val e2 = EXPsub (EXPint 5, EXPdiv (EXPint 11, EXPint 7))
}
val ans1 = exp_eval (e1)
in
print "e1 = "; print (e1); print_newline ();
print "ans1 = "; print (ans1); print_newline ()
end // end of [main]

(* ****** ****** *)

(* end of [code-2009-05-27.dats] *)
```