(*
** 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
  | EXPadd of (exp, exp)
  | 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)

// overloading [print] with [print_exp]
overload print with print_exp
// overloading [prerr] with [prerr_exp]
overload prerr with prerr_exp

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

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] *)