src/HOL/BNF/Tools/bnf_fp_rec_sugar_util.ML
changeset 53734 7613573f023a
parent 53732 e2c0d0426d2b
child 53741 c9068aade859
equal deleted inserted replaced
53733:cfd6257331ca 53734:7613573f023a
   148     val flat_fs' = map_args flat_fs;
   148     val flat_fs' = map_args flat_fs;
   149   in
   149   in
   150     permute_like (op aconv) flat_fs fs flat_fs'
   150     permute_like (op aconv) flat_fs fs flat_fs'
   151   end;
   151   end;
   152 
   152 
   153 fun massage_indirect_rec_call ctxt has_call massage_unapplied_direct_call bound_Ts y y' =
   153 fun massage_indirect_rec_call ctxt has_call raw_massage_fun bound_Ts y y' =
   154   let
   154   let
   155     val typof = curry fastype_of1 bound_Ts;
   155     val typof = curry fastype_of1 bound_Ts;
   156     val build_map_fst = build_map ctxt (fst_const o fst);
   156     val build_map_fst = build_map ctxt (fst_const o fst);
   157 
   157 
   158     val yT = typof y;
   158     val yT = typof y;
   159     val yU = typof y';
   159     val yU = typof y';
   160 
   160 
   161     fun y_of_y' () = build_map_fst (yU, yT) $ y';
   161     fun y_of_y' () = build_map_fst (yU, yT) $ y';
   162     val elim_y = Term.map_aterms (fn t => if t = y then y_of_y' () else t);
   162     val elim_y = Term.map_aterms (fn t => if t = y then y_of_y' () else t);
   163 
   163 
   164     fun check_and_massage_unapplied_direct_call U T t =
   164     fun massage_direct_fun U T t =
   165       if has_call t then
   165       if has_call t then factor_out_types ctxt raw_massage_fun HOLogic.dest_prodT U T t
   166         factor_out_types ctxt massage_unapplied_direct_call HOLogic.dest_prodT U T t
   166       else HOLogic.mk_comp (t, build_map_fst (U, T));
   167       else
       
   168         HOLogic.mk_comp (t, build_map_fst (U, T));
       
   169 
   167 
   170     fun massage_map (Type (_, Us)) (Type (s, Ts)) t =
   168     fun massage_map (Type (_, Us)) (Type (s, Ts)) t =
   171         (case try (dest_map ctxt s) t of
   169         (case try (dest_map ctxt s) t of
   172           SOME (map0, fs) =>
   170           SOME (map0, fs) =>
   173           let
   171           let
   182     and massage_map_or_map_arg U T t =
   180     and massage_map_or_map_arg U T t =
   183       if T = U then
   181       if T = U then
   184         if has_call t then unexpected_rec_call ctxt t else t
   182         if has_call t then unexpected_rec_call ctxt t else t
   185       else
   183       else
   186         massage_map U T t
   184         massage_map U T t
   187         handle AINT_NO_MAP _ => check_and_massage_unapplied_direct_call U T t;
   185         handle AINT_NO_MAP _ => massage_direct_fun U T t;
   188 
   186 
   189     fun massage_call (t as t1 $ t2) =
   187     fun massage_call (t as t1 $ t2) =
   190         if t2 = y then
   188         if t2 = y then
   191           massage_map yU yT (elim_y t1) $ y'
   189           massage_map yU yT (elim_y t1) $ y'
   192           handle AINT_NO_MAP t' => invalid_map ctxt t'
   190           handle AINT_NO_MAP t' => invalid_map ctxt t'
   219       | _ => f t)
   217       | _ => f t)
   220   in
   218   in
   221     fld
   219     fld
   222   end;
   220   end;
   223 
   221 
   224 fun massage_direct_corec_call ctxt has_call massage_direct_call U t =
   222 fun massage_direct_corec_call ctxt has_call raw_massage_call U t =
   225   massage_let_and_if ctxt has_call massage_direct_call U t;
   223   massage_let_and_if ctxt has_call raw_massage_call U t;
   226 
   224 
   227 fun massage_indirect_corec_call ctxt has_call massage_direct_call bound_Ts U t =
   225 fun massage_indirect_corec_call ctxt has_call raw_massage_call bound_Ts U t =
   228   let
   226   let
   229     val typof = curry fastype_of1 bound_Ts;
   227     val typof = curry fastype_of1 bound_Ts;
   230     val build_map_Inl = build_map ctxt (uncurry Inl_const o dest_sumT o snd)
   228     val build_map_Inl = build_map ctxt (uncurry Inl_const o dest_sumT o snd)
   231 
   229 
   232     fun check_and_massage_direct_call U T t =
   230     fun massage_direct_call U T t =
   233       if has_call t then factor_out_types ctxt massage_direct_call dest_sumT U T t
   231       if has_call t then factor_out_types ctxt raw_massage_call dest_sumT U T t
   234       else build_map_Inl (T, U) $ t;
   232       else build_map_Inl (T, U) $ t;
   235 
   233 
   236     fun check_and_massage_unapplied_direct_call U T t =
   234     fun massage_direct_fun U T t =
   237       let val var = Var ((Name.uu, Term.maxidx_of_term t + 1), domain_type (typof t)) in
   235       let val var = Var ((Name.uu, Term.maxidx_of_term t + 1), domain_type (typof t)) in
   238         Term.lambda var (check_and_massage_direct_call U T (t $ var))
   236         Term.lambda var (massage_direct_call U T (t $ var))
   239       end;
   237       end;
   240 
   238 
   241     fun massage_map (Type (_, Us)) (Type (s, Ts)) t =
   239     fun massage_map (Type (_, Us)) (Type (s, Ts)) t =
   242         (case try (dest_map ctxt s) t of
   240         (case try (dest_map ctxt s) t of
   243           SOME (map0, fs) =>
   241           SOME (map0, fs) =>
   253     and massage_map_or_map_arg U T t =
   251     and massage_map_or_map_arg U T t =
   254       if T = U then
   252       if T = U then
   255         if has_call t then unexpected_corec_call ctxt t else t
   253         if has_call t then unexpected_corec_call ctxt t else t
   256       else
   254       else
   257         massage_map U T t
   255         massage_map U T t
   258         handle AINT_NO_MAP _ => check_and_massage_unapplied_direct_call U T t;
   256         handle AINT_NO_MAP _ => massage_direct_fun U T t;
   259 
   257 
   260     fun massage_call U T =
   258     fun massage_call U T =
   261       massage_let_and_if ctxt has_call (fn t =>
   259       massage_let_and_if ctxt has_call (fn t =>
   262         if has_call t then
   260         if has_call t then
   263           (case U of
   261           (case U of
   269               end
   267               end
   270             | NONE =>
   268             | NONE =>
   271               (case t of
   269               (case t of
   272                 t1 $ t2 =>
   270                 t1 $ t2 =>
   273                 (if has_call t2 then
   271                 (if has_call t2 then
   274                   check_and_massage_direct_call U T t
   272                   massage_direct_call U T t
   275                 else
   273                 else
   276                   massage_map U T t1 $ t2
   274                   massage_map U T t1 $ t2
   277                   handle AINT_NO_MAP _ => check_and_massage_direct_call U T t)
   275                   handle AINT_NO_MAP _ => massage_direct_call U T t)
   278               | Abs (s, T', t') => Abs (s, T', massage_call (range_type U) (range_type T) t')
   276               | Abs (s, T', t') => Abs (s, T', massage_call (range_type U) (range_type T) t')
   279               | _ => check_and_massage_direct_call U T t))
   277               | _ => massage_direct_call U T t))
   280           | _ => ill_formed_corec_call ctxt t)
   278           | _ => ill_formed_corec_call ctxt t)
   281         else
   279         else
   282           build_map_Inl (T, U) $ t) U
   280           build_map_Inl (T, U) $ t) U
   283   in
   281   in
   284     massage_call U (typof t) t
   282     massage_call U (typof t) t