```(*
** 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 28, 2009
//

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

#include "BUCASCS320.hats"

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

// this example shows how integer lists are represented internally

datatype intlist =
| intlist_nil
| intlist_cons of (int, intlist)

fun sumlist (xs: intlist): int =
case+ xs of
| intlist_nil () => 0
| intlist_cons (x, xs) => x + sumlist (xs)
// end of [sumlist]

extern fun sumlist2 (xs: intlist): int = "csumlist"

#define :: intlist_cons
#define nil intlist_nil
implement main () = let
val xs = 1 :: 2 :: 3 :: 4 :: 5 :: nil ()
val sum = sumlist (xs)
val sum2 = sumlist2 (xs)
in
printf ("sum = %i\n", @(sum));
printf ("sum2 = %i\n", @(sum2))
end // end of [main]

%{\$

typedef
struct cintlst {
} cintlst_struct ;

ats_int_type csumlist (ats_ptr_type xs) {
int res = 0 ;
while (xs) { // xs is not null
xs = ((cintlst_struct*)xs)-> tail;
}
return res ;
}

%}

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

//
// this example demonstrates a *proper* way to make use of exception
//

datatype bt = E | B of (bt, bt)

fun eq_bt_bt (t1: bt, t2: bt): bool =
case+ (t1, t2) of
| (B (t11, t12), B (t21, t22)) =>
eq_bt_bt (t11, t21) andalso eq_bt_bt (t12, t22)
| (E _ , E _) => true
| (_, _) => false
// end of [eq_bt_bt]

extern fun isPerfect (t: bt): bool

(*

// very inefficient
implement isPerfect (t) = case+ t of
| B (t1, t2) =>
if (isPerfect t1 andalso isPerfect t2) then t1 = t2 else false
| E () => true
// end of [isPerfect]

*)

(*

implement isPerfect (t) = let
// aux (t) = ~1 implies that t is not perfect;
// aux (t) >= 0 implies that t is perfect and its size equals aux (t)
fun aux (t: bt): int =
case+ t of
| B (t1, t2) => let
val r1 = aux (t1)
in
case+ 0 of
| _ when r1 >= 0 => let
val r2 = aux (t2) in
if r2 >= 0 then
(if r1 = r2 then 1 + r1 + r2 else ~1)
else ~1
end // end of [_ when ...]
| _ (*r1 = ~1*) => ~1
end // end of [B]
| E () => 0
// end of [aux]
val r = aux (t)
in
if r >= 0 then true else false
end (* end of [isPerfect] *)

*)

implement isPerfect (t) = let
exception NotPerfectException of ()
// if aux (t) returns then t is perfect and its size equals aux (t)
fun aux (t: bt): int = case+ t of
| B (t1, t2) => let
val r1 = aux (t1)
val r2 = aux (t2)
in
if r1 = r2 then 1 + r1 + r2 else \$raise NotPerfectException ()
end
| E () => 0
// end of [aux]
in
try let
val _(*r*) = aux (t) in true
end with
| ~NotPerfectException () => false
// end of [try]
end // end of [isPerfect]

(*

implement main () = let
val t0 = E ()
val t1 = B (t0, t0)
val t2 = B (t1, t1) // perfect
val t3 = B (t1, t2) // not perfect
val ans2 = isPerfect (t2) // true
val () = (print "ans2 (true) = "; print ans2; print_newline ())
val ans3 = isPerfect (t3) // false
val () = (print "ans3 (false) = "; print ans3; print_newline ())
in
// nothing
end // end of [main]

*)

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

// this example illustrates a *nonsensical* use of exception:

fun{a:t@ype} list_length (xs: list0 a): int = let
exception SubscriptException of ()
val res = ref_make_elt<int> (0)
fun aux (xs: list0 a): void = case+ xs of
| list0_cons (_, xs) => (!res := !res + 1; aux xs)
| list0_nil () => \$raise SubscriptException ()
// end of [aux]
in
try (aux xs; 0) with ~SubscriptException () => !res
end // end of [list_length]

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

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