45 ("star_linear_preds", ["true"]), |
54 ("star_linear_preds", ["true"]), |
46 ("uncurry", ["true"]), |
55 ("uncurry", ["true"]), |
47 ("fast_descrs", ["true"]), |
56 ("fast_descrs", ["true"]), |
48 ("peephole_optim", ["true"]), |
57 ("peephole_optim", ["true"]), |
49 ("timeout", ["30 s"]), |
58 ("timeout", ["30 s"]), |
50 ("auto_timeout", ["5 s"]), |
|
51 ("tac_timeout", ["500 ms"]), |
59 ("tac_timeout", ["500 ms"]), |
52 ("sym_break", ["20"]), |
60 ("sym_break", ["20"]), |
53 ("sharing_depth", ["3"]), |
61 ("sharing_depth", ["3"]), |
54 ("flatten_props", ["false"]), |
62 ("flatten_props", ["false"]), |
55 ("max_threads", ["0"]), |
63 ("max_threads", ["0"]), |
124 | [] => ["false"] |
131 | [] => ["false"] |
125 | _ => value) |
132 | _ => value) |
126 | NONE => (name, value) |
133 | NONE => (name, value) |
127 |
134 |
128 structure TheoryData = TheoryDataFun( |
135 structure TheoryData = TheoryDataFun( |
129 type T = {params: raw_param list, registered_auto: bool} |
136 type T = {params: raw_param list} |
130 val empty = {params = rev default_default_params, registered_auto = false} |
137 val empty = {params = rev default_default_params} |
131 val copy = I |
138 val copy = I |
132 val extend = I |
139 val extend = I |
133 fun merge _ ({params = ps1, registered_auto = a1}, |
140 fun merge _ ({params = ps1}, {params = ps2}) = |
134 {params = ps2, registered_auto = a2}) = |
141 {params = AList.merge (op =) (op =) (ps1, ps2)}) |
135 {params = AList.merge (op =) (op =) (ps1, ps2), |
|
136 registered_auto = a1 orelse a2}) |
|
137 |
142 |
138 (* raw_param -> theory -> theory *) |
143 (* raw_param -> theory -> theory *) |
139 fun set_default_raw_param param thy = |
144 fun set_default_raw_param param thy = |
140 let val {params, registered_auto} = TheoryData.get thy in |
145 let val {params} = TheoryData.get thy in |
141 TheoryData.put |
146 TheoryData.put |
142 {params = AList.update (op =) (unnegate_raw_param param) params, |
147 {params = AList.update (op =) (unnegate_raw_param param) params} thy |
143 registered_auto = registered_auto} thy |
|
144 end |
148 end |
145 (* theory -> raw_param list *) |
149 (* theory -> raw_param list *) |
146 val default_raw_params = #params o TheoryData.get |
150 val default_raw_params = #params o TheoryData.get |
147 |
|
148 (* theory -> theory *) |
|
149 fun set_registered_auto thy = |
|
150 TheoryData.put {params = default_raw_params thy, registered_auto = true} thy |
|
151 (* theory -> bool *) |
|
152 val is_registered_auto = #registered_auto o TheoryData.get |
|
153 |
151 |
154 (* string -> bool *) |
152 (* string -> bool *) |
155 fun is_punctuation s = (s = "," orelse s = "-" orelse s = "\<midarrow>") |
153 fun is_punctuation s = (s = "," orelse s = "-" orelse s = "\<midarrow>") |
156 |
154 |
157 (* string list -> string *) |
155 (* string list -> string *) |
311 val skolemize = lookup_bool "skolemize" |
309 val skolemize = lookup_bool "skolemize" |
312 val star_linear_preds = lookup_bool "star_linear_preds" |
310 val star_linear_preds = lookup_bool "star_linear_preds" |
313 val uncurry = lookup_bool "uncurry" |
311 val uncurry = lookup_bool "uncurry" |
314 val fast_descrs = lookup_bool "fast_descrs" |
312 val fast_descrs = lookup_bool "fast_descrs" |
315 val peephole_optim = lookup_bool "peephole_optim" |
313 val peephole_optim = lookup_bool "peephole_optim" |
316 val timeout = if auto then lookup_time "auto_timeout" |
314 val timeout = if auto then NONE else lookup_time "timeout" |
317 else lookup_time "timeout" |
|
318 val tac_timeout = lookup_time "tac_timeout" |
315 val tac_timeout = lookup_time "tac_timeout" |
319 val sym_break = Int.max (0, lookup_int "sym_break") |
316 val sym_break = Int.max (0, lookup_int "sym_break") |
320 val sharing_depth = Int.max (1, lookup_int "sharing_depth") |
317 val sharing_depth = Int.max (1, lookup_int "sharing_depth") |
321 val flatten_props = lookup_bool "flatten_props" |
318 val flatten_props = lookup_bool "flatten_props" |
322 val max_threads = Int.max (0, lookup_int "max_threads") |
319 val max_threads = Int.max (0, lookup_int "max_threads") |
324 val show_skolems = show_all orelse lookup_bool "show_skolems" |
321 val show_skolems = show_all orelse lookup_bool "show_skolems" |
325 val show_datatypes = show_all orelse lookup_bool "show_datatypes" |
322 val show_datatypes = show_all orelse lookup_bool "show_datatypes" |
326 val show_consts = show_all orelse lookup_bool "show_consts" |
323 val show_consts = show_all orelse lookup_bool "show_consts" |
327 val formats = lookup_ints_assigns read_term_polymorphic "format" 0 |
324 val formats = lookup_ints_assigns read_term_polymorphic "format" 0 |
328 val evals = lookup_term_list "eval" |
325 val evals = lookup_term_list "eval" |
329 val max_potential = if auto then 0 |
326 val max_potential = |
330 else Int.max (0, lookup_int "max_potential") |
327 if auto then 0 else Int.max (0, lookup_int "max_potential") |
331 val max_genuine = Int.max (0, lookup_int "max_genuine") |
328 val max_genuine = Int.max (0, lookup_int "max_genuine") |
332 val check_potential = lookup_bool "check_potential" |
329 val check_potential = lookup_bool "check_potential" |
333 val check_genuine = lookup_bool "check_genuine" |
330 val check_genuine = lookup_bool "check_genuine" |
334 val batch_size = case lookup_int_option "batch_size" of |
331 val batch_size = case lookup_int_option "batch_size" of |
335 SOME n => Int.max (1, n) |
332 SOME n => Int.max (1, n) |
410 | Kodkod.SYNTAX (_, details) => |
407 | Kodkod.SYNTAX (_, details) => |
411 (warning ("Ill-formed Kodkodi output: " ^ details ^ "."); x) |
408 (warning ("Ill-formed Kodkodi output: " ^ details ^ "."); x) |
412 | Refute.REFUTE (loc, details) => |
409 | Refute.REFUTE (loc, details) => |
413 error ("Unhandled Refute error (" ^ quote loc ^ "): " ^ details ^ ".") |
410 error ("Unhandled Refute error (" ^ quote loc ^ "): " ^ details ^ ".") |
414 |
411 |
415 (* raw_param list -> bool -> int -> Proof.state -> Proof.state *) |
412 (* raw_param list -> bool -> int -> Proof.state -> bool * Proof.state *) |
416 fun pick_nits override_params auto subgoal state = |
413 fun pick_nits override_params auto subgoal state = |
417 let |
414 let |
418 val thy = Proof.theory_of state |
415 val thy = Proof.theory_of state |
419 val ctxt = Proof.context_of state |
416 val ctxt = Proof.context_of state |
420 val thm = snd (snd (Proof.get_goal state)) |
417 val thm = state |> Proof.get_goal |> snd |> snd |
421 val _ = List.app check_raw_param override_params |
418 val _ = List.app check_raw_param override_params |
422 val params as {blocking, debug, ...} = |
419 val params as {blocking, debug, ...} = |
423 extract_params ctxt auto (default_raw_params thy) override_params |
420 extract_params ctxt auto (default_raw_params thy) override_params |
424 (* unit -> Proof.state *) |
421 (* unit -> bool * Proof.state *) |
425 fun go () = |
422 fun go () = |
426 (if auto then perhaps o try |
423 (false, state) |
427 else if debug then fn f => fn x => f x |
424 |> (if auto then perhaps o try |
428 else handle_exceptions ctxt) |
425 else if debug then fn f => fn x => f x |
429 (fn state => pick_nits_in_subgoal state params auto subgoal |> snd) |
426 else handle_exceptions ctxt) |
430 state |
427 (fn (_, state) => pick_nits_in_subgoal state params auto subgoal |
|
428 |>> equal "genuine") |
431 in |
429 in |
432 if auto orelse blocking then |
430 if auto orelse blocking then go () |
433 go () |
431 else (SimpleThread.fork true (fn () => (go (); ())); (false, state)) |
434 else |
|
435 (SimpleThread.fork true (fn () => (go (); ())); |
|
436 state) |
|
437 end |
432 end |
438 |
433 |
439 (* (TableFun().key * string list) list option * int option |
434 (* (TableFun().key * string list) list option * int option |
440 -> Toplevel.transition -> Toplevel.transition *) |
435 -> Toplevel.transition -> Toplevel.transition *) |
441 fun nitpick_trans (opt_params, opt_subgoal) = |
436 fun nitpick_trans (opt_params, opt_subgoal) = |
442 Toplevel.keep (K () |
437 Toplevel.keep (K () |
443 o pick_nits (these opt_params) false (the_default 1 opt_subgoal) |
438 o snd o pick_nits (these opt_params) false (the_default 1 opt_subgoal) |
444 o Toplevel.proof_of) |
439 o Toplevel.proof_of) |
445 |
440 |
446 (* raw_param -> string *) |
441 (* raw_param -> string *) |
447 fun string_for_raw_param (name, value) = |
442 fun string_for_raw_param (name, value) = |
448 name ^ " = " ^ stringify_raw_param_value value |
443 name ^ " = " ^ stringify_raw_param_value value |
449 |
|
450 (* bool -> Proof.state -> Proof.state *) |
|
451 fun pick_nits_auto interactive state = |
|
452 let val thy = Proof.theory_of state in |
|
453 ((interactive andalso not (!Toplevel.quiet) |
|
454 andalso the (general_lookup_bool false (default_raw_params thy) |
|
455 (SOME false) "auto")) |
|
456 ? pick_nits [] true 0) state |
|
457 end |
|
458 |
|
459 (* theory -> theory *) |
|
460 fun register_auto thy = |
|
461 (not (is_registered_auto thy) |
|
462 ? (set_registered_auto |
|
463 #> Context.theory_map (Specification.add_theorem_hook pick_nits_auto))) |
|
464 thy |
|
465 |
444 |
466 (* (TableFun().key * string) list option -> Toplevel.transition |
445 (* (TableFun().key * string) list option -> Toplevel.transition |
467 -> Toplevel.transition *) |
446 -> Toplevel.transition *) |
468 fun nitpick_params_trans opt_params = |
447 fun nitpick_params_trans opt_params = |
469 Toplevel.theory |
448 Toplevel.theory |
470 (fn thy => |
449 (fold set_default_raw_param (these opt_params) |
471 let val thy = fold set_default_raw_param (these opt_params) thy in |
450 #> tap (fn thy => |
472 writeln ("Default parameters for Nitpick:\n" ^ |
451 writeln ("Default parameters for Nitpick:\n" ^ |
473 (case rev (default_raw_params thy) of |
452 (case rev (default_raw_params thy) of |
474 [] => "none" |
453 [] => "none" |
475 | params => |
454 | params => |
476 (map check_raw_param params; |
455 (map check_raw_param params; |
477 params |> map string_for_raw_param |> sort_strings |
456 params |> map string_for_raw_param |
478 |> cat_lines))); |
457 |> sort_strings |> cat_lines))))) |
479 register_auto thy |
|
480 end) |
|
481 |
458 |
482 (* OuterParse.token list |
459 (* OuterParse.token list |
483 -> (Toplevel.transition -> Toplevel.transition) * OuterParse.token list *) |
460 -> (Toplevel.transition -> Toplevel.transition) * OuterParse.token list *) |
484 fun scan_nitpick_command tokens = |
461 val scan_nitpick_command = |
485 (scan_params -- Scan.option OuterParse.nat) tokens |>> nitpick_trans |
462 (scan_params -- Scan.option OuterParse.nat) #>> nitpick_trans |
486 fun scan_nitpick_params_command tokens = |
463 val scan_nitpick_params_command = scan_params #>> nitpick_params_trans |
487 scan_params tokens |>> nitpick_params_trans |
|
488 |
464 |
489 val _ = OuterSyntax.improper_command "nitpick" |
465 val _ = OuterSyntax.improper_command "nitpick" |
490 "try to find a counterexample for a given subgoal using Kodkod" |
466 "try to find a counterexample for a given subgoal using Kodkod" |
491 OuterKeyword.diag scan_nitpick_command |
467 OuterKeyword.diag scan_nitpick_command |
492 val _ = OuterSyntax.command "nitpick_params" |
468 val _ = OuterSyntax.command "nitpick_params" |
493 "set and display the default parameters for Nitpick" |
469 "set and display the default parameters for Nitpick" |
494 OuterKeyword.thy_decl scan_nitpick_params_command |
470 OuterKeyword.thy_decl scan_nitpick_params_command |
495 |
471 |
|
472 (* Proof.state -> bool * Proof.state *) |
|
473 fun auto_nitpick state = |
|
474 if not (!auto) then (false, state) else pick_nits [] true 1 state |
|
475 |
|
476 val setup = Auto_Counterexample.register_tool ("nitpick", auto_nitpick) |
|
477 |
496 end; |
478 end; |