/*
**
** BU CAS CS520, Fall 2009
**
** Instructor: Hongwei Xi (hwxi AT cs DOT bu DOT edu)
**
** Exercise 2.2 in Assignment 1
**
*/

//
// This solution makes use of the feature of lazy evaluation in ATS
//

staload "prelude/DATS/lazy.dats"

staload "prelude/DATS/list.dats"
staload "prelude/DATS/list0.dats"

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

typedef BT = BraunTree

fun braunToString (t: BT): string = case t of
  | E () => "E"
  | B (l, r) => "B(" + braunToString(l) + ", " + braunToString(r) + ")"
// end of [braunToString]

fun printBT (t: BT): void = print (braunToString t) // terribly inefficient!

fun heightBT (t: BT):<1,~ref> int =
  case+ t of E () => 0 | B (l, _) => 1 + heightBT l
// end of [heightBT]

fun genBT (n: int):<1,~ref> BT =
  if n > 0 then B (genBT (n/2), genBT ((n-1)/2)) else E ()
// end of [genBT]

val theBraunTreeList = fromBT 0 where {
  fun fromBT (n: int):<1,~ref> stream BT = $delay (stream_cons (genBT n, fromBT (n+1)))
} // end of [val]

fun listBT (h: int): list0 BT = let
  fun aux (h: int, ts: stream BT): list0 BT =
    case+ !ts of
    | stream_cons (t, ts) => let
        val h1 = heightBT t in
        if h1 < h then aux (h, ts) else
          (if h1 > h then list0_nil () else list0_cons (t, aux (h, ts)))
        // end of [if]
      end // end of [stream_cons]
    | stream_nil () => list0_nil ()
  // end of [aux]
in
  aux (h, theBraunTreeList)
end // end of [listBT]

val listBT9 = listBT 9
val n = list0_length (listBT9)
val () = printf ("length-of-listBT9 (256) = %i\n", @(n))

implement main () = ()

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

(* end of [listBraunTreesOfGivenHeight1.dats] *)