load "bossLib"; open bossLib Defn TotalDefn;

Hol_datatype `exp  = Lam of num => exp
                   | App of exp => exp
                   | Var of num
                   | Let of (num # exp) list => exp
                   | Lit of num
                   | Plus `;
 
(* Here is a failed definition of a function that finds
 * the largest variable number in an expression.  
 *)
val maxVar_defn = 
 Hol_defn "maxVar"
   `(maxVar j (Lam n e)   = maxVar (if n > j then n else j) e) /\
    (maxVar j (App e1 e2) = maxVar (maxVar j e1) e2) /\
    (maxVar j (Var n)     = if n > j then n else j) /\
    (maxVar j (Let bs e)  = maxVarBs (maxVar j e) bs) /\
    (maxVar j (Lit n)     = j) /\
    (maxVar j Plus        = j) /\
    (maxVarBs j []        = j) /\
    (maxVarBs j ((n, e)::bs) = maxVarBs (if n > j then n else j) bs)`;

val (_::R::_) = guessR maxVar_defn;

val maxVar_defn_1 = set_reln maxVar_defn R;
val maxVar_tcs as 
    [tc1,tc2,nested_tc1,tc3,nested_tc2,tc4,tc5] = tcs_of maxVar_defn_1;

val non_nested_tcs = prove
(list_mk_conj [tc1,tc2,tc3,tc4,tc5],
 TC_SIMP_TAC [] []);

val maxVar_defn_2 = elim_tcs maxVar_defn_1 (CONJUNCTS non_nested_tcs);

val MV = Define `MV = maxVar_UNION_aux ^R`;
val maxVar_defn_3 = simp_tcs maxVar_defn_2 (REWRITE_CONV [SYM MV]);

val SOME union_defn = union_defn maxVar_defn_3;
val SOME aux_defn = aux_defn union_defn;

val [e1,e2,e3,e4,e5,e6,e7,e8] = 
   map (CONV_RULE (TC_SIMP_CONV [non_nested_tcs])) (Defn.eqns_of aux_defn);
val E3a = CONV_RULE (TC_SIMP_CONV [lam_count_def,DECIDE (Term`x<1+y = x<=y`)])
                    (DISCH_ALL E3);
tgoal maxVar_defn_3;
e (CONV_TAC (TC_SIMP_CONV []));

