src/HOL/Tools/Nitpick/nitpick_model.ML
changeset 34969 7b8c366e34a2
parent 34961 18b41bba42b5
child 34985 5e492a862b34
equal deleted inserted replaced
34968:475aef44d5fb 34969:7b8c366e34a2
     1 (*  Title:      HOL/Tools/Nitpick/nitpick_model.ML
     1 (*  Title:      HOL/Tools/Nitpick/nitpick_model.ML
     2     Author:     Jasmin Blanchette, TU Muenchen
     2     Author:     Jasmin Blanchette, TU Muenchen
     3     Copyright   2009
     3     Copyright   2009, 2010
     4 
     4 
     5 Model reconstruction for Nitpick.
     5 Model reconstruction for Nitpick.
     6 *)
     6 *)
     7 
     7 
     8 signature NITPICK_MODEL =
     8 signature NITPICK_MODEL =
    51 val unrep = "\<dots>"
    51 val unrep = "\<dots>"
    52 val maybe_mixfix = "_\<^sup>?"
    52 val maybe_mixfix = "_\<^sup>?"
    53 val base_mixfix = "_\<^bsub>base\<^esub>"
    53 val base_mixfix = "_\<^bsub>base\<^esub>"
    54 val step_mixfix = "_\<^bsub>step\<^esub>"
    54 val step_mixfix = "_\<^bsub>step\<^esub>"
    55 val abs_mixfix = "\<guillemotleft>_\<guillemotright>"
    55 val abs_mixfix = "\<guillemotleft>_\<guillemotright>"
    56 val non_opt_name = nitpick_prefix ^ "non_opt"
    56 val opt_flag = nitpick_prefix ^ "opt"
       
    57 val non_opt_flag = nitpick_prefix ^ "non_opt"
    57 
    58 
    58 (* string -> int -> string *)
    59 (* string -> int -> string *)
    59 fun atom_suffix s j =
    60 fun atom_suffix s j =
    60   nat_subscript (j + 1)
    61   nat_subscript (j + 1)
    61   |> (s <> "" andalso Symbol.is_ascii_digit (List.last (explode s)))
    62   |> (s <> "" andalso Symbol.is_ascii_digit (List.last (explode s)))
    62      ? prefix "\<^isub>,"
    63      ? prefix "\<^isub>,"
    63 (* string -> typ -> int -> string *)
    64 (* string -> typ -> int -> string *)
    64 fun atom_name prefix (T as Type (s, _)) j =
    65 fun atom_name prefix (T as Type (s, _)) j =
    65     prefix ^ substring (shortest_name s, 0, 1) ^ atom_suffix s j
    66     let val s' = shortest_name s in
       
    67       prefix ^ (if String.isPrefix "\\" s' then s' else substring (s', 0, 1)) ^
       
    68       atom_suffix s j
       
    69     end
    66   | atom_name prefix (T as TFree (s, _)) j =
    70   | atom_name prefix (T as TFree (s, _)) j =
    67     prefix ^ perhaps (try (unprefix "'")) s ^ atom_suffix s j
    71     prefix ^ perhaps (try (unprefix "'")) s ^ atom_suffix s j
    68   | atom_name _ T _ = raise TYPE ("Nitpick_Model.atom_name", [T], [])
    72   | atom_name _ T _ = raise TYPE ("Nitpick_Model.atom_name", [T], [])
    69 (* bool -> typ -> int -> term *)
    73 (* bool -> typ -> int -> term *)
    70 fun atom for_auto T j =
    74 fun atom for_auto T j =
   137 (* bool -> typ -> typ -> (term * term) list -> term *)
   141 (* bool -> typ -> typ -> (term * term) list -> term *)
   138 fun make_plain_fun maybe_opt T1 T2 =
   142 fun make_plain_fun maybe_opt T1 T2 =
   139   let
   143   let
   140     (* typ -> typ -> (term * term) list -> term *)
   144     (* typ -> typ -> (term * term) list -> term *)
   141     fun aux T1 T2 [] =
   145     fun aux T1 T2 [] =
   142         Const (if maybe_opt orelse T2 <> bool_T then @{const_name undefined}
   146         Const (if maybe_opt then opt_flag else non_opt_flag, T1 --> T2)
   143                else non_opt_name, T1 --> T2)
       
   144       | aux T1 T2 ((t1, t2) :: ps) =
   147       | aux T1 T2 ((t1, t2) :: ps) =
   145         Const (@{const_name fun_upd}, (T1 --> T2) --> T1 --> T2 --> T1 --> T2)
   148         Const (@{const_name fun_upd}, (T1 --> T2) --> T1 --> T2 --> T1 --> T2)
   146         $ aux T1 T2 ps $ t1 $ t2
   149         $ aux T1 T2 ps $ t1 $ t2
   147   in aux T1 T2 o rev end
   150   in aux T1 T2 o rev end
   148 (* term -> bool *)
   151 (* term -> bool *)
   149 fun is_plain_fun (Const (s, _)) =
   152 fun is_plain_fun (Const (s, _)) = (s = opt_flag orelse s = non_opt_flag)
   150     (s = @{const_name undefined} orelse s = non_opt_name)
       
   151   | is_plain_fun (Const (@{const_name fun_upd}, _) $ t0 $ _ $ _) =
   153   | is_plain_fun (Const (@{const_name fun_upd}, _) $ t0 $ _ $ _) =
   152     is_plain_fun t0
   154     is_plain_fun t0
   153   | is_plain_fun _ = false
   155   | is_plain_fun _ = false
   154 (* term -> bool * (term list * term list) *)
   156 (* term -> bool * (term list * term list) *)
   155 val dest_plain_fun =
   157 val dest_plain_fun =
   156   let
   158   let
   157     (* term -> term list * term list *)
   159     (* term -> bool * (term list * term list) *)
   158     fun aux (Const (s, _)) = (s <> non_opt_name, ([], []))
   160     fun aux (Const (s, _)) = (s <> non_opt_flag, ([], []))
   159       | aux (Const (@{const_name fun_upd}, _) $ t0 $ t1 $ t2) =
   161       | aux (Const (@{const_name fun_upd}, _) $ t0 $ t1 $ t2) =
   160         let val (s, (ts1, ts2)) = aux t0 in (s, (t1 :: ts1, t2 :: ts2)) end
   162         let val (s, (ts1, ts2)) = aux t0 in (s, (t1 :: ts1, t2 :: ts2)) end
   161       | aux t = raise TERM ("Nitpick_Model.dest_plain_fun", [t])
   163       | aux t = raise TERM ("Nitpick_Model.dest_plain_fun", [t])
   162   in apsnd (pairself rev) o aux end
   164   in apsnd (pairself rev) o aux end
   163 
   165 
   298             $ (Const (@{const_name Some}, T2' --> T2) $ Const (unknown, T2'))
   300             $ (Const (@{const_name Some}, T2' --> T2) $ Const (unknown, T2'))
   299           else
   301           else
   300             aux' ps
   302             aux' ps
   301       in aux end
   303       in aux end
   302     (* typ list -> term -> term *)
   304     (* typ list -> term -> term *)
   303     fun setify_mapify_funs Ts t =
   305     fun polish_funs Ts t =
   304       (case fastype_of1 (Ts, t) of
   306       (case fastype_of1 (Ts, t) of
   305          Type ("fun", [T1, T2]) =>
   307          Type ("fun", [T1, T2]) =>
   306          if is_plain_fun t then
   308          if is_plain_fun t then
   307            case T2 of
   309            case T2 of
   308              @{typ bool} =>
   310              @{typ bool} =>
   309              let
   311              let
   310                val (maybe_opt, ts_pair) =
   312                val (maybe_opt, ts_pair) =
   311                  dest_plain_fun t ||> pairself (map (setify_mapify_funs Ts))
   313                  dest_plain_fun t ||> pairself (map (polish_funs Ts))
   312              in
   314              in
   313                make_set maybe_opt T1 T2
   315                make_set maybe_opt T1 T2
   314                         (sort_wrt (truth_const_sort_key o snd) (op ~~ ts_pair))
   316                         (sort_wrt (truth_const_sort_key o snd) (op ~~ ts_pair))
   315              end
   317              end
   316            | Type (@{type_name option}, [T2']) =>
   318            | Type (@{type_name option}, [T2']) =>
   317              let
   319              let
   318                val ts_pair = snd (dest_plain_fun t)
   320                val ts_pair = snd (dest_plain_fun t)
   319                              |> pairself (map (setify_mapify_funs Ts))
   321                              |> pairself (map (polish_funs Ts))
   320              in make_map T1 T2 T2' (rev (op ~~ ts_pair)) end
   322              in make_map T1 T2 T2' (rev (op ~~ ts_pair)) end
   321            | _ => raise SAME ()
   323            | _ => raise SAME ()
   322          else
   324          else
   323            raise SAME ()
   325            raise SAME ()
   324        | _ => raise SAME ())
   326        | _ => raise SAME ())
   325       handle SAME () =>
   327       handle SAME () =>
   326              case t of
   328              case t of
   327                t1 $ t2 => setify_mapify_funs Ts t1 $ setify_mapify_funs Ts t2
   329                (t1 as Const (@{const_name fun_upd}, _) $ t11 $ _)
   328              | Abs (s, T, t') => Abs (s, T, setify_mapify_funs (T :: Ts) t')
   330                $ (t2 as Const (s, _)) =>
   329              | _ => t
   331                if s = unknown then polish_funs Ts t11
       
   332                else polish_funs Ts t1 $ polish_funs Ts t2
       
   333              | t1 $ t2 => polish_funs Ts t1 $ polish_funs Ts t2
       
   334              | Abs (s, T, t') => Abs (s, T, polish_funs (T :: Ts) t')
       
   335              | Const (s, Type ("fun", [T1, T2])) =>
       
   336                if s = opt_flag orelse s = non_opt_flag then
       
   337                  Abs ("x", T1, Const (unknown, T2))
       
   338                else
       
   339                  t
       
   340              | t => t
   330     (* bool -> typ -> typ -> typ -> term list -> term list -> term *)
   341     (* bool -> typ -> typ -> typ -> term list -> term list -> term *)
   331     fun make_fun maybe_opt T1 T2 T' ts1 ts2 =
   342     fun make_fun maybe_opt T1 T2 T' ts1 ts2 =
   332       ts1 ~~ ts2 |> sort (nice_term_ord o pairself fst)
   343       ts1 ~~ ts2 |> sort (nice_term_ord o pairself fst)
   333                  |> make_plain_fun (maybe_opt andalso not for_auto) T1 T2
   344                  |> make_plain_fun (maybe_opt andalso not for_auto) T1 T2
   334                  |> unbit_and_unbox_term
   345                  |> unbit_and_unbox_term
   369           HOLogic.mk_number nat_T (card_of_type card_assigns T - j - 1)
   380           HOLogic.mk_number nat_T (card_of_type card_assigns T - j - 1)
   370         else if T = @{typ bisim_iterator} then
   381         else if T = @{typ bisim_iterator} then
   371           HOLogic.mk_number nat_T j
   382           HOLogic.mk_number nat_T j
   372         else case datatype_spec datatypes T of
   383         else case datatype_spec datatypes T of
   373           NONE => atom for_auto T j
   384           NONE => atom for_auto T j
   374         | SOME {shallow = true, ...} => atom for_auto T j
   385         | SOME {deep = false, ...} => atom for_auto T j
   375         | SOME {co, constrs, ...} =>
   386         | SOME {co, constrs, ...} =>
   376           let
   387           let
   377             (* styp -> int list *)
   388             (* styp -> int list *)
   378             fun tuples_for_const (s, T) =
   389             fun tuples_for_const (s, T) =
   379               tuple_list_for_name rel_table bounds (ConstName (s, T, Any))
   390               tuple_list_for_name rel_table bounds (ConstName (s, T, Any))
   435                          | n1 => case HOLogic.dest_number t2 |> snd of
   446                          | n1 => case HOLogic.dest_number t2 |> snd of
   436                                    1 => mk_num n1
   447                                    1 => mk_num n1
   437                                  | n2 => Const (@{const_name Algebras.divide},
   448                                  | n2 => Const (@{const_name Algebras.divide},
   438                                                 num_T --> num_T --> num_T)
   449                                                 num_T --> num_T --> num_T)
   439                                          $ mk_num n1 $ mk_num n2)
   450                                          $ mk_num n1 $ mk_num n2)
   440                       | _ => raise TERM ("Nitpick_Model.reconstruct_term.term_\
   451                       | _ => raise TERM ("Nitpick_Model.reconstruct_term.\
   441                                          \for_atom (Abs_Frac)", ts)
   452                                          \term_for_atom (Abs_Frac)", ts)
   442                     end
   453                     end
   443                   else if not for_auto andalso
   454                   else if not for_auto andalso
   444                           (is_abs_fun thy constr_x orelse
   455                           (is_abs_fun thy constr_x orelse
   445                            constr_s = @{const_name Quot}) then
   456                            constr_s = @{const_name Quot}) then
   446                     Const (abs_name, constr_T) $ the_single ts
   457                     Const (abs_name, constr_T) $ the_single ts
       
   458                   else if not for_auto andalso
       
   459                           constr_s = @{const_name NonStd} then
       
   460                     Const (fst (dest_Const (the_single ts)), T)
   447                   else
   461                   else
   448                     list_comb (Const constr_x, ts)
   462                     list_comb (Const constr_x, ts)
   449               in
   463               in
   450                 if co then
   464                 if co then
   451                   let val var = var () in
   465                   let val var = var () in
   507       | term_for_rep seen T _ R jss =
   521       | term_for_rep seen T _ R jss =
   508         raise ARG ("Nitpick_Model.reconstruct_term.term_for_rep",
   522         raise ARG ("Nitpick_Model.reconstruct_term.term_for_rep",
   509                    Refute.string_of_typ T ^ " " ^ string_for_rep R ^ " " ^
   523                    Refute.string_of_typ T ^ " " ^ string_for_rep R ^ " " ^
   510                    string_of_int (length jss))
   524                    string_of_int (length jss))
   511   in
   525   in
   512     (not for_auto ? setify_mapify_funs []) o unbit_and_unbox_term
   526     (not for_auto ? polish_funs []) o unbit_and_unbox_term oooo term_for_rep []
   513     oooo term_for_rep []
       
   514   end
   527   end
   515 
   528 
   516 (* scope -> nut list -> nut NameTable.table -> KK.raw_bound list -> nut
   529 (* scope -> nut list -> nut NameTable.table -> KK.raw_bound list -> nut
   517    -> term *)
   530    -> term *)
   518 fun term_for_name scope sel_names rel_table bounds name =
   531 fun term_for_name scope sel_names rel_table bounds name =
   520     tuple_list_for_name rel_table bounds name
   533     tuple_list_for_name rel_table bounds name
   521     |> reconstruct_term ("", "", "", "") scope sel_names rel_table bounds T T
   534     |> reconstruct_term ("", "", "", "") scope sel_names rel_table bounds T T
   522                         (rep_of name)
   535                         (rep_of name)
   523   end
   536   end
   524 
   537 
   525 (* Proof.context
   538 (* Proof.context -> (string * string * string * string) * Proof.context *)
   526    -> (string * string * string * string * string) * Proof.context *)
       
   527 fun add_wacky_syntax ctxt =
   539 fun add_wacky_syntax ctxt =
   528   let
   540   let
   529     (* term -> string *)
   541     (* term -> string *)
   530     val name_of = fst o dest_Const
   542     val name_of = fst o dest_Const
   531     val thy = ProofContext.theory_of ctxt |> Context.reject_draft
   543     val thy = ProofContext.theory_of ctxt |> Context.reject_draft
   571 
   583 
   572 (* params -> scope -> (term option * int list) list -> styp list -> nut list
   584 (* params -> scope -> (term option * int list) list -> styp list -> nut list
   573   -> nut list -> nut list -> nut NameTable.table -> KK.raw_bound list
   585   -> nut list -> nut list -> nut NameTable.table -> KK.raw_bound list
   574   -> Pretty.T * bool *)
   586   -> Pretty.T * bool *)
   575 fun reconstruct_hol_model {show_skolems, show_datatypes, show_consts}
   587 fun reconstruct_hol_model {show_skolems, show_datatypes, show_consts}
   576         ({ext_ctxt as {thy, ctxt, max_bisim_depth, boxes, wfs, user_axioms,
   588         ({ext_ctxt as {thy, ctxt, max_bisim_depth, boxes, stds, wfs,
   577                        debug, binary_ints, destroy_constrs, specialize,
   589                        user_axioms, debug, binary_ints, destroy_constrs,
   578                        skolemize, star_linear_preds, uncurry, fast_descrs,
   590                        specialize, skolemize, star_linear_preds, uncurry,
   579                        tac_timeout, evals, case_names, def_table, nondef_table,
   591                        fast_descrs, tac_timeout, evals, case_names, def_table,
   580                        user_nondefs, simp_table, psimp_table, intro_table,
   592                        nondef_table, user_nondefs, simp_table, psimp_table,
   581                        ground_thm_table, ersatz_table, skolems, special_funs,
   593                        intro_table, ground_thm_table, ersatz_table, skolems,
   582                        unrolled_preds, wf_cache, constr_cache},
   594                        special_funs, unrolled_preds, wf_cache, constr_cache},
   583          card_assigns, bits, bisim_depth, datatypes, ofs} : scope)
   595          card_assigns, bits, bisim_depth, datatypes, ofs} : scope)
   584         formats all_frees free_names sel_names nonsel_names rel_table bounds =
   596         formats all_frees free_names sel_names nonsel_names rel_table bounds =
   585   let
   597   let
   586     val (wacky_names as (_, base_name, step_name, _), ctxt) =
   598     val (wacky_names as (_, base_name, step_name, _), ctxt) =
   587       add_wacky_syntax ctxt
   599       add_wacky_syntax ctxt
   588     val ext_ctxt =
   600     val ext_ctxt =
   589       {thy = thy, ctxt = ctxt, max_bisim_depth = max_bisim_depth, boxes = boxes,
   601       {thy = thy, ctxt = ctxt, max_bisim_depth = max_bisim_depth, boxes = boxes,
   590        wfs = wfs, user_axioms = user_axioms, debug = debug,
   602        stds = stds, wfs = wfs, user_axioms = user_axioms, debug = debug,
   591        binary_ints = binary_ints, destroy_constrs = destroy_constrs,
   603        binary_ints = binary_ints, destroy_constrs = destroy_constrs,
   592        specialize = specialize, skolemize = skolemize,
   604        specialize = specialize, skolemize = skolemize,
   593        star_linear_preds = star_linear_preds, uncurry = uncurry,
   605        star_linear_preds = star_linear_preds, uncurry = uncurry,
   594        fast_descrs = fast_descrs, tac_timeout = tac_timeout, evals = evals,
   606        fast_descrs = fast_descrs, tac_timeout = tac_timeout, evals = evals,
   595        case_names = case_names, def_table = def_table,
   607        case_names = case_names, def_table = def_table,
   648     (* dtype_spec -> Pretty.T *)
   660     (* dtype_spec -> Pretty.T *)
   649     fun pretty_for_datatype ({typ, card, complete, ...} : dtype_spec) =
   661     fun pretty_for_datatype ({typ, card, complete, ...} : dtype_spec) =
   650       Pretty.block (Pretty.breaks
   662       Pretty.block (Pretty.breaks
   651           [Syntax.pretty_typ ctxt (unbit_and_unbox_type typ), Pretty.str "=",
   663           [Syntax.pretty_typ ctxt (unbit_and_unbox_type typ), Pretty.str "=",
   652            Pretty.enum "," "{" "}"
   664            Pretty.enum "," "{" "}"
   653                (map (Syntax.pretty_term ctxt) (all_values_of_type card typ)
   665                (map (Syntax.pretty_term ctxt) (all_values_of_type card typ) @
   654                 @ (if complete then [] else [Pretty.str unrep]))])
   666                 (if complete then [] else [Pretty.str unrep]))])
   655     (* typ -> dtype_spec list *)
   667     (* typ -> dtype_spec list *)
   656     fun integer_datatype T =
   668     fun integer_datatype T =
   657       [{typ = T, card = card_of_type card_assigns T, co = false,
   669       [{typ = T, card = card_of_type card_assigns T, co = false,
   658         complete = false, concrete = true, shallow = false, constrs = []}]
   670         complete = false, concrete = true, deep = true, constrs = []}]
   659       handle TYPE ("Nitpick_HOL.card_of_type", _, _) => []
   671       handle TYPE ("Nitpick_HOL.card_of_type", _, _) => []
   660     val (codatatypes, datatypes) =
   672     val (codatatypes, datatypes) =
   661       datatypes |> filter_out #shallow
   673       datatypes |> filter #deep |> List.partition #co
   662                 |> List.partition #co
       
   663                 ||> append (integer_datatype nat_T @ integer_datatype int_T)
   674                 ||> append (integer_datatype nat_T @ integer_datatype int_T)
   664     val block_of_datatypes =
   675     val block_of_datatypes =
   665       if show_datatypes andalso not (null datatypes) then
   676       if show_datatypes andalso not (null datatypes) then
   666         [Pretty.big_list ("Datatype" ^ plural_s_for_list datatypes ^ ":")
   677         [Pretty.big_list ("Datatype" ^ plural_s_for_list datatypes ^ ":")
   667                          (map pretty_for_datatype datatypes)]
   678                          (map pretty_for_datatype datatypes)]