src/HOL/Tools/BNF/bnf_gfp_rec_sugar.ML
changeset 59989 7b80ddb65e3e
parent 59948 c8860ec6fc80
child 60001 0e1b220ec4c9
equal deleted inserted replaced
59988:c92afea6eb4b 59989:7b80ddb65e3e
    49   val fold_rev_let_if_case: Proof.context -> (term list -> term -> 'a -> 'a) -> typ list ->
    49   val fold_rev_let_if_case: Proof.context -> (term list -> term -> 'a -> 'a) -> typ list ->
    50     term -> 'a -> 'a
    50     term -> 'a -> 'a
    51   val massage_let_if_case: Proof.context -> (term -> bool) -> (typ list -> term -> term) ->
    51   val massage_let_if_case: Proof.context -> (term -> bool) -> (typ list -> term -> term) ->
    52     typ list -> term -> term
    52     typ list -> term -> term
    53   val massage_nested_corec_call: Proof.context -> (term -> bool) ->
    53   val massage_nested_corec_call: Proof.context -> (term -> bool) ->
    54     (typ list -> typ -> typ -> term -> term) -> (typ -> typ -> term -> term) -> typ list -> typ ->
    54     (typ list -> typ -> typ -> term -> term) -> (typ list -> typ -> typ -> term -> term) ->
    55     term -> term
    55     typ list -> typ -> typ -> term -> term
    56   val expand_to_ctr_term: Proof.context -> string -> typ list -> term -> term
    56   val expand_to_ctr_term: Proof.context -> string -> typ list -> term -> term
    57   val massage_corec_code_rhs: Proof.context -> (typ list -> term -> term list -> term) ->
    57   val massage_corec_code_rhs: Proof.context -> (typ list -> term -> term list -> term) ->
    58     typ list -> term -> term
    58     typ list -> term -> term
    59   val fold_rev_corec_code_rhs: Proof.context -> (term list -> term -> term list -> 'a -> 'a) ->
    59   val fold_rev_corec_code_rhs: Proof.context -> (term list -> term -> term list -> 'a -> 'a) ->
    60     typ list -> term -> 'a -> 'a
    60     typ list -> term -> 'a -> 'a
   304       if Term.is_dummy_pattern t then Const (@{const_name undefined}, fastype_of t) else t)
   304       if Term.is_dummy_pattern t then Const (@{const_name undefined}, fastype_of t) else t)
   305   end;
   305   end;
   306 
   306 
   307 fun curried_type (Type (@{type_name fun}, [Type (@{type_name prod}, Ts), T])) = Ts ---> T;
   307 fun curried_type (Type (@{type_name fun}, [Type (@{type_name prod}, Ts), T])) = Ts ---> T;
   308 
   308 
   309 fun massage_nested_corec_call ctxt has_call massage_call wrap_noncall bound_Ts U t0 =
   309 fun massage_nested_corec_call ctxt has_call massage_call massage_noncall bound_Ts U T t0 =
   310   let
   310   let
   311     fun check_no_call t = if has_call t then unexpected_corec_call ctxt [t0] t else ();
   311     fun check_no_call t = if has_call t then unexpected_corec_call ctxt [t0] t else ();
   312 
   312 
   313     fun massage_mutual_call bound_Ts (Type (@{type_name fun}, [_, U2]))
   313     fun massage_mutual_call bound_Ts (Type (@{type_name fun}, [_, U2]))
   314         (Type (@{type_name fun}, [T1, T2])) t =
   314         (Type (@{type_name fun}, [T1, T2])) t =
   315         Abs (Name.uu, T1, massage_mutual_call bound_Ts U2 T2 (incr_boundvars 1 t $ Bound 0))
   315         Abs (Name.uu, T1, massage_mutual_call bound_Ts U2 T2 (incr_boundvars 1 t $ Bound 0))
   316       | massage_mutual_call bound_Ts U T t =
   316       | massage_mutual_call bound_Ts U T t =
   317         if has_call t then massage_call bound_Ts T U t else wrap_noncall T U t;
   317         (if has_call t then massage_call else massage_noncall) bound_Ts U T t;
   318 
   318 
   319     fun massage_map bound_Ts (Type (_, Us)) (Type (s, Ts)) t =
   319     fun massage_map bound_Ts (Type (_, Us)) (Type (s, Ts)) t =
   320         (case try (dest_map ctxt s) t of
   320         (case try (dest_map ctxt s) t of
   321           SOME (map0, fs) =>
   321           SOME (map0, fs) =>
   322           let
   322           let
   372                 in
   372                 in
   373                   Const (@{const_name case_prod}, U' --> U) $ massage_any_call bound_Ts U' T' t'
   373                   Const (@{const_name case_prod}, U' --> U) $ massage_any_call bound_Ts U' T' t'
   374                 end
   374                 end
   375               | t1 $ t2 =>
   375               | t1 $ t2 =>
   376                 (if has_call t2 then
   376                 (if has_call t2 then
   377                   massage_mutual_call bound_Ts U T t
   377                    massage_mutual_call bound_Ts U T t
   378                 else
   378                  else
   379                   massage_map bound_Ts U T t1 $ t2
   379                    massage_map bound_Ts U T t1 $ t2
   380                   handle NO_MAP _ => massage_mutual_call bound_Ts U T t)
   380                    handle NO_MAP _ => massage_mutual_call bound_Ts U T t)
   381               | Abs (s, T', t') =>
   381               | Abs (s, T', t') =>
   382                 Abs (s, T', massage_any_call (T' :: bound_Ts) (range_type U) (range_type T) t')
   382                 Abs (s, T', massage_any_call (T' :: bound_Ts) (range_type U) (range_type T) t')
   383               | _ => massage_mutual_call bound_Ts U T t))
   383               | _ => massage_mutual_call bound_Ts U T t))
   384           | _ => ill_formed_corec_call ctxt t)
   384           | _ => ill_formed_corec_call ctxt t)
   385         else
   385         else
   386           wrap_noncall T U t) bound_Ts;
   386           massage_noncall bound_Ts U T t) bound_Ts;
   387 
   387 
   388     val T = fastype_of1 (bound_Ts, t0);
   388     val T = fastype_of1 (bound_Ts, t0);
   389   in
   389   in
   390     if has_call t0 then massage_any_call bound_Ts U T t0 else wrap_noncall T U t0
   390     (if has_call t0 then massage_any_call else massage_noncall) bound_Ts U T t0
   391   end;
   391   end;
   392 
   392 
   393 fun expand_to_ctr_term ctxt s Ts t =
   393 fun expand_to_ctr_term ctxt s Ts t =
   394   (case ctr_sugar_of ctxt s of
   394   (case ctr_sugar_of ctxt s of
   395     SOME {ctrs, casex, ...} =>
   395     SOME {ctrs, casex, ...} =>
   892 fun build_corec_arg_nested_call ctxt has_call (sel_eqns : coeqn_data_sel list) sel =
   892 fun build_corec_arg_nested_call ctxt has_call (sel_eqns : coeqn_data_sel list) sel =
   893   (case find_first (curry (op =) sel o #sel) sel_eqns of
   893   (case find_first (curry (op =) sel o #sel) sel_eqns of
   894     NONE => I
   894     NONE => I
   895   | SOME {fun_args, rhs_term, ...} =>
   895   | SOME {fun_args, rhs_term, ...} =>
   896     let
   896     let
   897       fun massage_call bound_Ts T U t0 =
   897       fun massage_call bound_Ts U T t0 =
   898         let
   898         let
   899           val U2 =
   899           val U2 =
   900             (case try dest_sumT U of
   900             (case try dest_sumT U of
   901               SOME (U1, U2) => if U1 = T then U2 else invalid_map ctxt t0
   901               SOME (U1, U2) => if U1 = T then U2 else invalid_map ctxt t0
   902             | NONE => invalid_map ctxt t0);
   902             | NONE => invalid_map ctxt t0);
   917               if is_Free t andalso has_call t then Inr_const T U2 $ HOLogic.unit else t;
   917               if is_Free t andalso has_call t then Inr_const T U2 $ HOLogic.unit else t;
   918           in
   918           in
   919             rewrite bound_Ts t0
   919             rewrite bound_Ts t0
   920           end;
   920           end;
   921 
   921 
   922       fun wrap_noncall T U t = build_map ctxt [] (uncurry Inl_const o dest_sumT o snd) (T, U) $ t;
   922       fun massage_noncall bound_Ts U T t =
       
   923         build_map ctxt [] (uncurry Inl_const o dest_sumT o snd) (T, U) $ t;
   923 
   924 
   924       val bound_Ts = List.rev (map fastype_of fun_args);
   925       val bound_Ts = List.rev (map fastype_of fun_args);
   925 
       
   926       fun build t =
       
   927         rhs_term
       
   928         |> massage_nested_corec_call ctxt has_call massage_call wrap_noncall bound_Ts
       
   929           (range_type (fastype_of t))
       
   930         |> abs_tuple_balanced fun_args;
       
   931     in
   926     in
   932       build
   927       fn t =>
       
   928       rhs_term
       
   929       |> massage_nested_corec_call ctxt has_call massage_call massage_noncall bound_Ts
       
   930         (range_type (fastype_of t)) (fastype_of1 (bound_Ts, rhs_term))
       
   931       |> abs_tuple_balanced fun_args
   933     end);
   932     end);
   934 
   933 
   935 fun build_corec_args_sel ctxt has_call (all_sel_eqns : coeqn_data_sel list)
   934 fun build_corec_args_sel ctxt has_call (all_sel_eqns : coeqn_data_sel list)
   936     (ctr_spec : corec_ctr_spec) =
   935     (ctr_spec : corec_ctr_spec) =
   937   (case filter (curry (op =) (#ctr ctr_spec) o #ctr) all_sel_eqns of
   936   (case filter (curry (op =) (#ctr ctr_spec) o #ctr) all_sel_eqns of