(*
// This file is for Assignment 2, BU CAS CS 520, Fall, 2009
//
// Instructor: Hongwei Xi (hwxi AT cs DOT bu DOT edu)
//
*)

dataprop F91 (int, int) =
  | F91def1 (91, 91)
  | {i:int | i <= 100; i <> 91} {r1,r2:int}
    F91def2 (i, r2) of (F91 (i+11, r1), F91 (r1, r2))
  | {i:int | 101 <= i} {r:int}
    F91def3 (i, r) of F91 (i-10, r) // F91 (i-10, r) -> F91 (i, r)

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

extern prfun f91_lemma {i,r:int} (pf: F91 (i, r)): [r==91] void

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

// as an example, [f91_lemma1] proves that F91 (i, r) implies r = 91
// if 92 <= i and i <= 101 holds.

prfun f91_lemma1 {i:int | 92 <= i; i <= 101} {r:int} .<101-i>.
  (pf:  F91 (i, r)): [r==91] void =
  sif i == 101 then let
    prval F91def3 (pf1) = pf // pf1: F91 (101-10, r)
    prval F91def1 () = pf1
  in
    // empty
  end else let // 92 <= i <= 100
    prval F91def2 (pf1, pf2) = pf // pf1: F91 (i+11, r1); pf2: F91 (r1, r2)
    prval F91def3 (pf11) = pf1 // pf11: F91 (i+11-10, r1)
    prval () = f91_lemma1 {i+1} (pf11) // r1 == 91
    prval F91def1 () = pf2 // r2 == 91
  in
    // empty
  end // end of [sif]
// end of [f91_lemma1]

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

prfun f91_lemma2 {i:int | 92 <= i} {r:int} .<i>.
  (pf:  F91 (i, r)): [r==91] void =
  sif i > 101 then let
    prval F91def3 (pf1) = pf in f91_lemma2 (pf1)
  end else begin
    f91_lemma1 (pf)
  end // end of [sif]
// end of [f91_lemma2]

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

prfun f91_lemma3 {i:int} {r:int} .<max(0,91-i)>.
  (pf:  F91 (i, r)): [r==91] void =
  sif i <= 90 then let
    prval F91def2 (pf1, pf2) = pf
    prval () = f91_lemma3 (pf1); prval F91def1 () = pf2
  in
    // empty
  end else sif i >= 92 then f91_lemma2 (pf)
  else (* i == 91 *)
    let prval F91def1 () = pf in () end
  // end of [sif]
// end of [f91_lemma3]

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

implement f91_lemma (pf) = f91_lemma3 (pf)

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

(* end of [f91.dats] *)