//
// Course: BU CAS CS 520
// Instructor: Hongwei Xi (hwxi AT cs DOT bu DOT edu)
//

//
// an encoding of binary trees in System F
//

abst@ype T // ...

(*
datatype tree = E of () | B (tree, T, tree)

// E: tree
// B: (tree, T, tree) -> tree
*)

typedef tree = {X:type}
  (X, (X, T, X) -<cloref> X) -<cloref> X

val E : tree =
  lam {X:type} (e: X, b: (X, T, X) -<cloref> X) =<cloref> e
// end of [val]

val B = lam (t1: tree, x: T, t2: tree) => lam {X:type}
  (e: X, b: (X, T, X) -<cloref> X) =<cloref> b (t1{X}(e, b), x, t2{X}(e, b))
// end of [val]

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

typedef int = intptr
val _0 = intptr_of_int (0)
val _1 = intptr_of_int (1)

fn size_tree (t: tree): int =
  t {int} (_0, lam (s1, _, s2) => _1 + s1 + s2)
// end of [size_tree]

fn height_tree (t: tree): int =
  t {int} (_0, lam (s1, _, s2) => _1 + max (s1, s2))
// end of [height_tree]

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

datatype tree1 = E1 of () | B1 of (tree1, T, tree1)

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

fn tree1_of_tree (t: tree): tree1 =
  t{tree1} (E1, lam (t1, x, t2) => B1 (t1, x, t2))
// end of [fn]

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

(* end of [tree.dats] *)