src/HOL/BNF/Tools/bnf_fp_rec_sugar_util.ML
changeset 54206 1c26d55b8d73
parent 54205 bdb83bc60780
child 54238 58742c759205
equal deleted inserted replaced
54205:bdb83bc60780 54206:1c26d55b8d73
   223   | mk_partial_compN n gT fT g =
   223   | mk_partial_compN n gT fT g =
   224     let val g' = mk_partial_compN (n - 1) gT (range_type fT) g in
   224     let val g' = mk_partial_compN (n - 1) gT (range_type fT) g in
   225       mk_partial_comp (fastype_of g') fT g'
   225       mk_partial_comp (fastype_of g') fT g'
   226     end;
   226     end;
   227 
   227 
   228 fun mk_compN bound_Ts n (g, f) =
   228 fun mk_compN n bound_Ts (g, f) =
   229   let val typof = curry fastype_of1 bound_Ts in
   229   let val typof = curry fastype_of1 bound_Ts in
   230     mk_partial_compN n (typof g) (typof f) g $ f
   230     mk_partial_compN n (typof g) (typof f) g $ f
   231   end;
   231   end;
       
   232 
       
   233 val mk_comp = mk_compN 1;
   232 
   234 
   233 fun factor_out_types ctxt massage destU U T =
   235 fun factor_out_types ctxt massage destU U T =
   234   (case try destU U of
   236   (case try destU U of
   235     SOME (U1, U2) => if U1 = T then massage T U2 else invalid_map ctxt
   237     SOME (U1, U2) => if U1 = T then massage T U2 else invalid_map ctxt
   236   | NONE => invalid_map ctxt);
   238   | NONE => invalid_map ctxt);
   243     permute_like (op aconv) flat_fs fs flat_fs'
   245     permute_like (op aconv) flat_fs fs flat_fs'
   244   end;
   246   end;
   245 
   247 
   246 fun massage_nested_rec_call ctxt has_call raw_massage_fun bound_Ts y y' =
   248 fun massage_nested_rec_call ctxt has_call raw_massage_fun bound_Ts y y' =
   247   let
   249   let
       
   250     fun check_no_call t = if has_call t then unexpected_rec_call ctxt t else ();
       
   251 
   248     val typof = curry fastype_of1 bound_Ts;
   252     val typof = curry fastype_of1 bound_Ts;
   249     val build_map_fst = build_map ctxt (fst_const o fst);
   253     val build_map_fst = build_map ctxt (fst_const o fst);
   250 
   254 
   251     val yT = typof y;
   255     val yT = typof y;
   252     val yU = typof y';
   256     val yU = typof y';
   253 
   257 
   254     fun y_of_y' () = build_map_fst (yU, yT) $ y';
   258     fun y_of_y' () = build_map_fst (yU, yT) $ y';
   255     val elim_y = Term.map_aterms (fn t => if t = y then y_of_y' () else t);
   259     val elim_y = Term.map_aterms (fn t => if t = y then y_of_y' () else t);
   256 
   260 
   257     fun massage_mutual_fun U T t =
   261     fun massage_mutual_fun U T t =
   258       if has_call t then factor_out_types ctxt raw_massage_fun HOLogic.dest_prodT U T t
   262       (case t of
   259       else HOLogic.mk_comp (t, build_map_fst (U, T));
   263         Const (@{const_name comp}, comp_T) $ t1 $ t2 =>
       
   264         mk_comp bound_Ts (tap check_no_call t1, massage_mutual_fun U T t2)
       
   265       | _ =>
       
   266         if has_call t then factor_out_types ctxt raw_massage_fun HOLogic.dest_prodT U T t
       
   267         else mk_comp bound_Ts (t, build_map_fst (U, T)));
   260 
   268 
   261     fun massage_map (Type (_, Us)) (Type (s, Ts)) t =
   269     fun massage_map (Type (_, Us)) (Type (s, Ts)) t =
   262         (case try (dest_map ctxt s) t of
   270         (case try (dest_map ctxt s) t of
   263           SOME (map0, fs) =>
   271           SOME (map0, fs) =>
   264           let
   272           let
   270           end
   278           end
   271         | NONE => raise AINT_NO_MAP t)
   279         | NONE => raise AINT_NO_MAP t)
   272       | massage_map _ _ t = raise AINT_NO_MAP t
   280       | massage_map _ _ t = raise AINT_NO_MAP t
   273     and massage_map_or_map_arg U T t =
   281     and massage_map_or_map_arg U T t =
   274       if T = U then
   282       if T = U then
   275         if has_call t then unexpected_rec_call ctxt t else t
   283         tap check_no_call t
   276       else
   284       else
   277         massage_map U T t
   285         massage_map U T t
   278         handle AINT_NO_MAP _ => massage_mutual_fun U T t;
   286         handle AINT_NO_MAP _ => massage_mutual_fun U T t;
   279 
   287 
   280     fun massage_call (t as t1 $ t2) =
   288     fun massage_call (t as t1 $ t2) =
   284             handle AINT_NO_MAP t' => invalid_map ctxt t'
   292             handle AINT_NO_MAP t' => invalid_map ctxt t'
   285           else
   293           else
   286             let val (g, xs) = Term.strip_comb t2 in
   294             let val (g, xs) = Term.strip_comb t2 in
   287               if g = y then
   295               if g = y then
   288                 if exists has_call xs then unexpected_rec_call ctxt t2
   296                 if exists has_call xs then unexpected_rec_call ctxt t2
   289                 else Term.list_comb (massage_call (mk_compN bound_Ts (length xs) (t1, y)), xs)
   297                 else Term.list_comb (massage_call (mk_compN (length xs) bound_Ts (t1, y)), xs)
   290               else
   298               else
   291                 ill_formed_rec_call ctxt t
   299                 ill_formed_rec_call ctxt t
   292             end
   300             end
   293         else
   301         else
   294           elim_y t
   302           elim_y t
   409       else build_map_Inl (T, U) $ t;
   417       else build_map_Inl (T, U) $ t;
   410 
   418 
   411     fun massage_mutual_fun bound_Ts U T t =
   419     fun massage_mutual_fun bound_Ts U T t =
   412       (case t of
   420       (case t of
   413         Const (@{const_name comp}, comp_T) $ t1 $ t2 =>
   421         Const (@{const_name comp}, comp_T) $ t1 $ t2 =>
   414         mk_compN bound_Ts 1 (massage_mutual_fun bound_Ts U T t1, tap check_no_call t2)
   422         mk_comp bound_Ts (massage_mutual_fun bound_Ts U T t1, tap check_no_call t2)
   415       | _ =>
   423       | _ =>
   416         let
   424         let
   417           val var = Var ((Name.uu, Term.maxidx_of_term t + 1),
   425           val var = Var ((Name.uu, Term.maxidx_of_term t + 1),
   418             domain_type (fastype_of1 (bound_Ts, t)));
   426             domain_type (fastype_of1 (bound_Ts, t)));
   419         in
   427         in