gracefully handle case where a nested recursive variable appears directly on the rhs of a primcorec equation
authorblanchet
Sun, 20 Oct 2013 19:23:28 +0200
changeset 55622402fcacb5c88
parent 55621 41bd81a1c98e
child 55623 c0b0e1ea839e
gracefully handle case where a nested recursive variable appears directly on the rhs of a primcorec equation
src/HOL/BNF/Tools/bnf_fp_rec_sugar.ML
src/HOL/BNF/Tools/bnf_fp_rec_sugar_util.ML
     1.1 --- a/src/HOL/BNF/Tools/bnf_fp_rec_sugar.ML	Sun Oct 20 19:20:08 2013 +0200
     1.2 +++ b/src/HOL/BNF/Tools/bnf_fp_rec_sugar.ML	Sun Oct 20 19:23:28 2013 +0200
     1.3 @@ -168,7 +168,7 @@
     1.4      subst (SOME ~1)
     1.5    end;
     1.6  
     1.7 -fun subst_rec_calls lthy get_ctr_pos has_call ctr_args mutual_calls nested_calls t =
     1.8 +fun subst_rec_calls lthy get_ctr_pos has_call ctr_args mutual_calls nested_calls =
     1.9    let
    1.10      fun try_nested_rec bound_Ts y t =
    1.11        AList.lookup (op =) nested_calls y
    1.12 @@ -176,9 +176,12 @@
    1.13          massage_nested_rec_call lthy has_call (rewrite_map_arg get_ctr_pos) bound_Ts y y' t);
    1.14  
    1.15      fun subst bound_Ts (t as g' $ y) =
    1.16 -        let val y_head = head_of y in
    1.17 +        let
    1.18 +          fun subst_rec () = subst bound_Ts g' $ subst bound_Ts y;
    1.19 +          val y_head = head_of y;
    1.20 +        in
    1.21            if not (member (op =) ctr_args y_head) then
    1.22 -            subst bound_Ts g' $ subst bound_Ts y
    1.23 +            subst_rec ()
    1.24            else
    1.25              (case try_nested_rec bound_Ts y_head t of
    1.26                SOME t' => t'
    1.27 @@ -190,16 +193,21 @@
    1.28                     primrec_error_eqn "too few arguments in recursive call" t;
    1.29                     (case AList.lookup (op =) mutual_calls y of
    1.30                       SOME y' => list_comb (y', g_args)
    1.31 -                   | NONE => t))
    1.32 -                | NONE => t)
    1.33 +                   | NONE => subst_rec ()))
    1.34 +                | NONE => subst_rec ())
    1.35                end)
    1.36          end
    1.37        | subst bound_Ts (Abs (v, T, b)) = Abs (v, T, subst (T :: bound_Ts) b)
    1.38        | subst _ t = t
    1.39 +
    1.40 +    fun subst' t =
    1.41 +      if has_call t then
    1.42 +        (* FIXME detect this case earlier? *)
    1.43 +        primrec_error_eqn "recursive call not directly applied to constructor argument" t
    1.44 +      else
    1.45 +        try_nested_rec [] (head_of t) t |> the_default t
    1.46    in
    1.47 -    subst [] t
    1.48 -    |> tap (fn u => has_call u andalso (* FIXME detect this case earlier *)
    1.49 -      primrec_error_eqn "recursive call not directly applied to constructor argument" t)
    1.50 +    subst' o subst []
    1.51    end;
    1.52  
    1.53  fun build_rec_arg lthy (funs_data : eqn_data list list) has_call (ctr_spec : rec_ctr_spec)
     2.1 --- a/src/HOL/BNF/Tools/bnf_fp_rec_sugar_util.ML	Sun Oct 20 19:20:08 2013 +0200
     2.2 +++ b/src/HOL/BNF/Tools/bnf_fp_rec_sugar_util.ML	Sun Oct 20 19:23:28 2013 +0200
     2.3 @@ -274,17 +274,20 @@
     2.4          handle AINT_NO_MAP _ => massage_mutual_fun U T t;
     2.5  
     2.6      fun massage_call (t as t1 $ t2) =
     2.7 -        if t2 = y then
     2.8 -          massage_map yU yT (elim_y t1) $ y'
     2.9 -          handle AINT_NO_MAP t' => invalid_map ctxt t'
    2.10 +        if has_call t then
    2.11 +          if t2 = y then
    2.12 +            massage_map yU yT (elim_y t1) $ y'
    2.13 +            handle AINT_NO_MAP t' => invalid_map ctxt t'
    2.14 +          else
    2.15 +            let val (g, xs) = Term.strip_comb t2 in
    2.16 +              if g = y then
    2.17 +                if exists has_call xs then unexpected_rec_call ctxt t2
    2.18 +                else Term.list_comb (massage_call (mk_compN bound_Ts (length xs) (t1, y)), xs)
    2.19 +              else
    2.20 +                ill_formed_rec_call ctxt t
    2.21 +            end
    2.22          else
    2.23 -          let val (g, xs) = Term.strip_comb t2 in
    2.24 -            if g = y then
    2.25 -              if exists has_call xs then unexpected_rec_call ctxt t2
    2.26 -              else Term.list_comb (massage_call (mk_compN bound_Ts (length xs) (t1, y)), xs)
    2.27 -            else
    2.28 -              ill_formed_rec_call ctxt t
    2.29 -          end
    2.30 +          elim_y t
    2.31        | massage_call t = if t = y then y_of_y' () else ill_formed_rec_call ctxt t;
    2.32    in
    2.33      massage_call