src/HOL/Tools/Nitpick/nitpick_mono.ML
changeset 40995 3cae30b60577
parent 40994 3bdb8df0daf0
child 40996 63112be4a469
equal deleted inserted replaced
40994:3bdb8df0daf0 40995:3cae30b60577
    30 type var = int
    30 type var = int
    31 
    31 
    32 datatype annotation = Gen | New | Fls | Tru
    32 datatype annotation = Gen | New | Fls | Tru
    33 datatype annotation_atom = A of annotation | V of var
    33 datatype annotation_atom = A of annotation | V of var
    34 
    34 
    35 type assign = var * annotation
    35 type assign_literal = var * annotation
    36 
    36 
    37 datatype mtyp =
    37 datatype mtyp =
    38   MAlpha |
    38   MAlpha |
    39   MFun of mtyp * annotation_atom * mtyp |
    39   MFun of mtyp * annotation_atom * mtyp |
    40   MPair of mtyp * mtyp |
    40   MPair of mtyp * mtyp |
    80   | string_for_annotation Tru = "T"
    80   | string_for_annotation Tru = "T"
    81 
    81 
    82 fun string_for_annotation_atom (A a) = string_for_annotation a
    82 fun string_for_annotation_atom (A a) = string_for_annotation a
    83   | string_for_annotation_atom (V x) = string_for_var x
    83   | string_for_annotation_atom (V x) = string_for_var x
    84 
    84 
    85 fun string_for_assign (x, a) =
    85 fun string_for_assign_literal (x, a) =
    86   string_for_var x ^ " = " ^ string_for_annotation a
    86   string_for_var x ^ " = " ^ string_for_annotation a
    87 
    87 
    88 val bool_M = MType (@{type_name bool}, [])
    88 val bool_M = MType (@{type_name bool}, [])
    89 val dummy_M = MType (nitpick_prefix ^ "dummy", [])
    89 val dummy_M = MType (nitpick_prefix ^ "dummy", [])
    90 
    90 
   347   in aux end
   347   in aux end
   348 
   348 
   349 datatype comp_op = Eq | Leq
   349 datatype comp_op = Eq | Leq
   350 
   350 
   351 type comp = annotation_atom * annotation_atom * comp_op * var list
   351 type comp = annotation_atom * annotation_atom * comp_op * var list
   352 type assign_clause = assign list
   352 type assign_clause = assign_literal list
   353 
   353 
   354 type constraint_set = comp list * assign_clause list
   354 type constraint_set = comp list * assign_clause list
   355 
   355 
   356 fun string_for_comp_op Eq = "="
   356 fun string_for_comp_op Eq = "="
   357   | string_for_comp_op Leq = "\<le>"
   357   | string_for_comp_op Leq = "\<le>"
   360   string_for_annotation_atom aa1 ^ " " ^ string_for_comp_op cmp ^
   360   string_for_annotation_atom aa1 ^ " " ^ string_for_comp_op cmp ^
   361   subscript_string_for_vars " \<and> " xs ^ " " ^ string_for_annotation_atom aa2
   361   subscript_string_for_vars " \<and> " xs ^ " " ^ string_for_annotation_atom aa2
   362 
   362 
   363 fun string_for_assign_clause [] = "\<bot>"
   363 fun string_for_assign_clause [] = "\<bot>"
   364   | string_for_assign_clause asgs =
   364   | string_for_assign_clause asgs =
   365     space_implode " \<or> " (map string_for_assign asgs)
   365     space_implode " \<or> " (map string_for_assign_literal asgs)
   366 
   366 
   367 fun add_assign (x, a) clauses =
   367 fun add_assign_literal (x, a) clauses =
   368   if exists (fn [(x', a')] => x = x' andalso a <> a' | _ => false) clauses then
   368   if exists (fn [(x', a')] => x = x' andalso a <> a' | _ => false) clauses then
   369     NONE
   369     NONE
   370   else
   370   else
   371     SOME ([(x, a)] :: clauses)fun add_assign_conjunct _ NONE = NONE
   371     SOME ([(x, a)] :: clauses)fun add_assign_conjunct _ NONE = NONE
   372 
   372 
   375 
   375 
   376 fun do_annotation_atom_comp Eq [] aa1 aa2 (cset as (comps, clauses)) =
   376 fun do_annotation_atom_comp Eq [] aa1 aa2 (cset as (comps, clauses)) =
   377     (case (aa1, aa2) of
   377     (case (aa1, aa2) of
   378        (A a1, A a2) => if a1 = a2 then SOME cset else NONE
   378        (A a1, A a2) => if a1 = a2 then SOME cset else NONE
   379      | (V x1, A a2) =>
   379      | (V x1, A a2) =>
   380        clauses |> add_assign (x1, a2) |> Option.map (pair comps)
   380        clauses |> add_assign_literal (x1, a2) |> Option.map (pair comps)
   381      | (V _, V _) => SOME (insert (op =) (aa1, aa2, Eq, []) comps, clauses)
   381      | (V _, V _) => SOME (insert (op =) (aa1, aa2, Eq, []) comps, clauses)
   382      | _ => do_annotation_atom_comp Eq [] aa2 aa1 cset)
   382      | _ => do_annotation_atom_comp Eq [] aa2 aa1 cset)
   383   | do_annotation_atom_comp Leq [] aa1 aa2 (cset as (comps, clauses)) =
   383   | do_annotation_atom_comp Leq [] aa1 aa2 (cset as (comps, clauses)) =
   384     (case (aa1, aa2) of
   384     (case (aa1, aa2) of
   385        (_, A Gen) => SOME cset
   385        (_, A Gen) => SOME cset
   439 
   439 
   440 fun do_notin_mtype_fv _ _ _ NONE = NONE
   440 fun do_notin_mtype_fv _ _ _ NONE = NONE
   441   | do_notin_mtype_fv Minus _ MAlpha cset = cset
   441   | do_notin_mtype_fv Minus _ MAlpha cset = cset
   442   | do_notin_mtype_fv Plus [] MAlpha _ = NONE
   442   | do_notin_mtype_fv Plus [] MAlpha _ = NONE
   443   | do_notin_mtype_fv Plus [(x, a)] MAlpha (SOME clauses) =
   443   | do_notin_mtype_fv Plus [(x, a)] MAlpha (SOME clauses) =
   444     clauses |> add_assign (x, a)
   444     clauses |> add_assign_literal (x, a)
   445   | do_notin_mtype_fv Plus clause MAlpha (SOME clauses) =
   445   | do_notin_mtype_fv Plus clause MAlpha (SOME clauses) =
   446     SOME (insert (op =) clause clauses)
   446     SOME (insert (op =) clause clauses)
   447   | do_notin_mtype_fv sn clause (MFun (M1, A a, M2)) cset =
   447   | do_notin_mtype_fv sn clause (MFun (M1, A a, M2)) cset =
   448     cset |> (if a <> Gen andalso sn = Plus then do_notin_mtype_fv Plus clause M1
   448     cset |> (if a <> Gen andalso sn = Plus then do_notin_mtype_fv Plus clause M1
   449              else I)
   449              else I)
   493 
   493 
   494 fun prop_for_bool b = if b then PL.True else PL.False
   494 fun prop_for_bool b = if b then PL.True else PL.False
   495 fun prop_for_bool_var_equality (v1, v2) =
   495 fun prop_for_bool_var_equality (v1, v2) =
   496   PL.And (PL.Or (PL.BoolVar v1, PL.Not (PL.BoolVar v2)),
   496   PL.And (PL.Or (PL.BoolVar v1, PL.Not (PL.BoolVar v2)),
   497           PL.Or (PL.Not (PL.BoolVar v1), PL.BoolVar v2))
   497           PL.Or (PL.Not (PL.BoolVar v1), PL.BoolVar v2))
   498 fun prop_for_assign (x, a) =
   498 fun prop_for_assign_literal (x, a) =
   499   let val (b1, b2) = bools_from_annotation a in
   499   let val (b1, b2) = bools_from_annotation a in
   500     PL.And (PL.BoolVar (fst_var x) |> not b1 ? PL.Not,
   500     PL.And (PL.BoolVar (fst_var x) |> not b1 ? PL.Not,
   501             PL.BoolVar (snd_var x) |> not b2 ? PL.Not)
   501             PL.BoolVar (snd_var x) |> not b2 ? PL.Not)
   502   end
   502   end
   503 fun prop_for_atom_assign (A a', a) = prop_for_bool (a = a')
   503 fun prop_for_atom_assign (A a', a) = prop_for_bool (a = a')
   504   | prop_for_atom_assign (V x, a) = prop_for_assign (x, a)
   504   | prop_for_atom_assign (V x, a) = prop_for_assign_literal (x, a)
   505 fun prop_for_atom_equality (aa1, A a2) = prop_for_atom_assign (aa1, a2)
   505 fun prop_for_atom_equality (aa1, A a2) = prop_for_atom_assign (aa1, a2)
   506   | prop_for_atom_equality (A a1, aa2) = prop_for_atom_assign (aa2, a1)
   506   | prop_for_atom_equality (A a1, aa2) = prop_for_atom_assign (aa2, a1)
   507   | prop_for_atom_equality (V x1, V x2) =
   507   | prop_for_atom_equality (V x1, V x2) =
   508     PL.And (prop_for_bool_var_equality (pairself fst_var (x1, x2)),
   508     PL.And (prop_for_bool_var_equality (pairself fst_var (x1, x2)),
   509             prop_for_bool_var_equality (pairself snd_var (x1, x2)))
   509             prop_for_bool_var_equality (pairself snd_var (x1, x2)))
   510 val prop_for_assign_clause = PL.exists o map prop_for_assign
   510 val prop_for_assign_clause = PL.exists o map prop_for_assign_literal
   511 fun prop_for_exists_var_assign xs a =
   511 fun prop_for_exists_var_assign_literal xs a =
   512   PL.exists (map (fn x => prop_for_assign (x, a)) xs)
   512   PL.exists (map (fn x => prop_for_assign_literal (x, a)) xs)
   513 fun prop_for_comp (aa1, aa2, Eq, []) =
   513 fun prop_for_comp (aa1, aa2, Eq, []) =
   514     PL.SAnd (prop_for_comp (aa1, aa2, Leq, []),
   514     PL.SAnd (prop_for_comp (aa1, aa2, Leq, []),
   515              prop_for_comp (aa2, aa1, Leq, []))
   515              prop_for_comp (aa2, aa1, Leq, []))
   516   | prop_for_comp (aa1, aa2, Leq, []) =
   516   | prop_for_comp (aa1, aa2, Leq, []) =
   517     PL.SOr (prop_for_atom_equality (aa1, aa2), prop_for_atom_assign (aa2, Gen))
   517     PL.SOr (prop_for_atom_equality (aa1, aa2), prop_for_atom_assign (aa2, Gen))
   518   | prop_for_comp (aa1, aa2, cmp, xs) =
   518   | prop_for_comp (aa1, aa2, cmp, xs) =
   519     PL.SOr (prop_for_exists_var_assign xs Gen,
   519     PL.SOr (prop_for_exists_var_assign_literal xs Gen,
   520             prop_for_comp (aa1, aa2, cmp, []))
   520             prop_for_comp (aa1, aa2, cmp, []))
   521 
   521 
   522 (* The "calculus" parameter may be 1, 2, or 3, corresponding approximately to
   522 (* The "calculus" parameter may be 1, 2, or 3, corresponding approximately to
   523    the M1, M2, and M3 calculi from Blanchette & Krauss 2011. *)
   523    the M1, M2, and M3 calculi from Blanchette & Krauss 2011. *)
   524 fun variable_domain calculus =
   524 fun variable_domain calculus =
   525   [Gen] @ (if calculus > 1 then [Fls] else [])
   525   [Gen] @ (if calculus > 1 then [Fls] else [])
   526   @ (if calculus > 2 then [New, Tru] else [])
   526   @ (if calculus > 2 then [New, Tru] else [])
   527 
   527 
   528 fun prop_for_variable_domain calculus x =
   528 fun prop_for_variable_domain calculus x =
   529   PL.exists (map (curry prop_for_assign x) (variable_domain calculus))
   529   PL.exists (map (curry prop_for_assign_literal x) (variable_domain calculus))
   530 
   530 
   531 fun extract_assigns max_var assigns asgs =
   531 fun extract_assigns max_var assigns asgs =
   532   fold (fn x => fn accum =>
   532   fold (fn x => fn accum =>
   533            if AList.defined (op =) asgs x then
   533            if AList.defined (op =) asgs x then
   534              accum
   534              accum
   591    bound_frame: (int * annotation_atom) list,
   591    bound_frame: (int * annotation_atom) list,
   592    frees: (styp * mtyp) list,
   592    frees: (styp * mtyp) list,
   593    consts: (styp * mtyp) list}
   593    consts: (styp * mtyp) list}
   594 
   594 
   595 val string_for_frame =
   595 val string_for_frame =
   596   commas o map (fn (j, aa) => "#" ^ string_of_int j ^ " |-> " ^
   596   map (fn (j, aa) => "#" ^ string_of_int j ^ " |-> " ^
   597                               string_for_annotation_atom aa)
   597                      string_for_annotation_atom aa)
       
   598   #> commas #> enclose "[" "]"
   598 
   599 
   599 type accumulator = mtype_context * constraint_set
   600 type accumulator = mtype_context * constraint_set
   600 
   601 
   601 val initial_gamma =
   602 val initial_gamma =
   602   {bound_Ts = [], bound_Ms = [], bound_frame = [], frees = [], consts = []}
   603   {bound_Ts = [], bound_Ms = [], bound_frame = [], frees = [], consts = []}
   618    frees = frees, consts = consts}
   619    frees = frees, consts = consts}
   619 
   620 
   620 (* FIXME: make sure tracing messages are complete *)
   621 (* FIXME: make sure tracing messages are complete *)
   621 
   622 
   622 fun add_comp_frame a cmp frame =
   623 fun add_comp_frame a cmp frame =
   623   (trace_msg (fn () => "*** Add " ^ string_for_annotation a ^
   624   (trace_msg (fn () => "*** Add " ^ string_for_annotation a ^ " " ^
   624                        string_for_comp_op cmp ^ " frame " ^
   625                        string_for_comp_op cmp ^ " " ^
   625                        string_for_frame frame);
   626                        string_for_frame frame);
   626    fold (add_annotation_atom_comp cmp [] (A a) o snd) frame)
   627    fold (add_annotation_atom_comp cmp [] (A a) o snd) frame)
   627 
   628 
   628 fun add_bound_frame j frame =
   629 fun add_bound_frame j frame =
   629   let
   630   let
   638     fun do_var (j, A Fls) = (j, A (case sn of Plus => Fls | Minus => Tru))
   639     fun do_var (j, A Fls) = (j, A (case sn of Plus => Fls | Minus => Tru))
   639       | do_var (j, A Gen) = (j, A Gen)
   640       | do_var (j, A Gen) = (j, A Gen)
   640       | do_var (j, _) = (j, V (Unsynchronized.inc max_fresh))
   641       | do_var (j, _) = (j, V (Unsynchronized.inc max_fresh))
   641   in map do_var end
   642   in map do_var end
   642 
   643 
   643 fun add_imp_frames res_frame frame1 frame2 = I
   644 fun do_not_var j aa0 aa1 _ = I
   644 (*###
   645 (*
   645   let
   646 x1 ~= T | x0 = F
   646     fun do_var_pair (j, aa0) (_, aa1) (_, aa2) =
   647 x1 ~= F | x0 = T
   647   in map3 do_var_pair res_frame frame1 frame2 end
   648 x1 ~= G | x0 = G
       
   649 x1 ~= N | x0 = G
   648 *)
   650 *)
       
   651 
       
   652 fun do_conj_var j aa0 aa1 aa2 = I
       
   653 (*
       
   654   (x1 ≠ T | x2 ≠ T | x0 = T) &
       
   655   (x1 ≠ F | x0 = F) &
       
   656   (x2 ≠ F | x0 = F) &
       
   657   (x1 ≠ G | x2 = F | x0 = G) &
       
   658   (x1 ≠ N | x2 = F | x0 = G) &
       
   659   (x1 = F | x2 ≠ G | x0 = G) &
       
   660   (x1 = F | x2 ≠ N | x0 = G)"
       
   661 *)
       
   662 
       
   663 fun do_disj_var j aa0 aa1 aa2 = I
       
   664 fun do_imp_var j aa0 aa1 aa2 = I
       
   665 
       
   666 fun add_connective_frames do_var res_frame frame1 frame2 =
       
   667   fold I (map3 (fn (j, aa0) => fn (_, aa1) => fn (_, aa2) =>
       
   668                    do_var j aa0 aa1 aa2) res_frame frame1 frame2)
   649 
   669 
   650 fun consider_term (mdata as {hol_ctxt = {thy, ctxt, stds, ...}, alpha_T,
   670 fun consider_term (mdata as {hol_ctxt = {thy, ctxt, stds, ...}, alpha_T,
   651                              max_fresh, ...}) =
   671                              max_fresh, ...}) =
   652   let
   672   let
   653     fun is_enough_eta_expanded t =
   673     fun is_enough_eta_expanded t =
   720                MAbs (abs_s, abs_T, M1, aa',
   740                MAbs (abs_s, abs_T, M1, aa',
   721                      MApp (MApp (MRaw (connective_t,
   741                      MApp (MApp (MRaw (connective_t,
   722                                        mtype_for (fastype_of connective_t)),
   742                                        mtype_for (fastype_of connective_t)),
   723                                  MApp (bound_m, MRaw (Bound 0, M1))),
   743                                  MApp (bound_m, MRaw (Bound 0, M1))),
   724                            body_m))), accum)
   744                            body_m))), accum)
       
   745       end
       
   746     and do_connect do_var t0 t1 t2 (accum as ({bound_frame, ...}, _)) =
       
   747       let
       
   748         val frame1 = fresh_imp_frame mdata Minus bound_frame
       
   749         val frame2 = fresh_imp_frame mdata Plus bound_frame
       
   750         val (m1, accum) = accum |>> set_frame frame1 |> do_term t1
       
   751         val (m2, accum) = accum |>> set_frame frame2 |> do_term t2
       
   752       in
       
   753         (MApp (MApp (MRaw (t0, mtype_for (fastype_of t0)), m1), m2),
       
   754          accum |>> set_frame bound_frame
       
   755                ||> add_connective_frames do_var bound_frame frame1 frame2)
   725       end
   756       end
   726     and do_term t (accum as ({bound_Ts, bound_Ms, bound_frame, frees, consts},
   757     and do_term t (accum as ({bound_Ts, bound_Ms, bound_frame, frees, consts},
   727                              cset)) =
   758                              cset)) =
   728       (trace_msg (fn () => "  \<Gamma> \<turnstile> " ^
   759       (trace_msg (fn () => "  \<Gamma> \<turnstile> " ^
   729                            Syntax.string_of_term ctxt t ^ " : _?");
   760                            Syntax.string_of_term ctxt t ^ " : _?");
   877                         val M = mtype_for T
   908                         val M = mtype_for T
   878                         val aa = V (Unsynchronized.inc max_fresh)
   909                         val aa = V (Unsynchronized.inc max_fresh)
   879                         val (m', accum) =
   910                         val (m', accum) =
   880                           do_term t' (accum |>> push_bound aa T M)
   911                           do_term t' (accum |>> push_bound aa T M)
   881                       in (MAbs (s, T, M, aa, m'), accum |>> pop_bound) end))
   912                       in (MAbs (s, T, M, aa, m'), accum |>> pop_bound) end))
   882          | (t0 as @{const implies}) $ t1 $ t2 =>
       
   883            let
       
   884              val frame1 = fresh_imp_frame mdata Minus bound_frame
       
   885              val frame2 = fresh_imp_frame mdata Plus bound_frame
       
   886              val (m0, accum) = accum |> do_term t0
       
   887              val (m1, accum) = accum |>> set_frame frame1 |> do_term t1
       
   888              val (m2, accum) = accum |>> set_frame frame2 |> do_term t2
       
   889            in
       
   890              (MApp (MApp (m0, m1), m2),
       
   891               accum |>> set_frame bound_frame
       
   892                     ||> add_imp_frames bound_frame frame1 frame2)
       
   893            end
       
   894          | (t0 as Const (@{const_name All}, _))
   913          | (t0 as Const (@{const_name All}, _))
   895            $ Abs (s', T', (t10 as @{const HOL.implies})
   914            $ Abs (s', T', (t10 as @{const HOL.implies})
   896                           $ (t11 $ Bound 0) $ t12) =>
   915                           $ (t11 $ Bound 0) $ t12) =>
   897            do_bounded_quantifier t0 s' T' t10 t11 t12 accum
   916            do_bounded_quantifier t0 s' T' t10 t11 t12 accum
   898          | (t0 as Const (@{const_name Ex}, _))
   917          | (t0 as Const (@{const_name Ex}, _))
   899            $ Abs (s', T', (t10 as @{const HOL.conj})
   918            $ Abs (s', T', (t10 as @{const HOL.conj})
   900                           $ (t11 $ Bound 0) $ t12) =>
   919                           $ (t11 $ Bound 0) $ t12) =>
   901            do_bounded_quantifier t0 s' T' t10 t11 t12 accum
   920            do_bounded_quantifier t0 s' T' t10 t11 t12 accum
       
   921          | (t0 as @{const Not}) $ t1 =>
       
   922            let
       
   923              val frame1 = fresh_imp_frame mdata Minus bound_frame
       
   924              val (m1, accum) = accum |>> set_frame frame1 |> do_term t1
       
   925            in
       
   926              (MApp (MRaw (t0, mtype_for (fastype_of t0)), m1),
       
   927               accum |>> set_frame bound_frame
       
   928                     ||> add_connective_frames do_not_var bound_frame frame1
       
   929                                                          frame1)
       
   930            end
       
   931          | (t0 as @{const conj}) $ t1 $ t2 =>
       
   932            do_connect do_conj_var t0 t1 t2 accum
       
   933          | (t0 as @{const disj}) $ t1 $ t2 =>
       
   934            do_connect do_disj_var t0 t1 t2 accum
       
   935          | (t0 as @{const implies}) $ t1 $ t2 =>
       
   936            do_connect do_imp_var t0 t1 t2 accum
   902          | Const (@{const_name Let}, _) $ t1 $ t2 =>
   937          | Const (@{const_name Let}, _) $ t1 $ t2 =>
   903            do_term (betapply (t2, t1)) accum
   938            do_term (betapply (t2, t1)) accum
   904          | t1 $ t2 =>
   939          | t1 $ t2 =>
   905            let
   940            let
   906              val (m1, accum) = do_term t1 accum
   941              val (m1, accum) = do_term t1 accum