-
Notifications
You must be signed in to change notification settings - Fork 0
/
AOT_commands.ML
1062 lines (952 loc) · 42.3 KB
/
AOT_commands.ML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
(*
This file contains modified parts of the Isabelle ML sources
which are distributed with Isabelle under the following conditions:
ISABELLE COPYRIGHT NOTICE, LICENCE AND DISCLAIMER.
Copyright (c) 1986-2021,
University of Cambridge,
Technische Universitaet Muenchen,
and contributors.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the University of Cambridge or the Technische
Universitaet Muenchen nor the names of their contributors may be used
to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*)
(**** RULIFICATION START *****)
structure AOT_RulifyInsts = Theory_Data (
type T = thm Symtab.table
val empty = Symtab.empty
val merge = Symtab.merge (K true)
);
structure AOT_RulifyElims = Theory_Data (
type T = (thm list) Symtab.table
val empty = Symtab.empty
val merge = Symtab.merge (K true)
);
structure AOT_VarifyRules = Theory_Data (
type T = (Context.generic->term->thm->thm option) Symtab.table
val empty = Symtab.empty
val merge = Symtab.join (K (fn (r,r2) =>
(fn ctxt => fn trm => fn thm => case r ctxt trm thm of SOME x => SOME x | _ => r2 ctxt trm thm
))
));
fun AOT_add_varify_rule (key,rule) =
Local_Theory.background_theory (fn thy => let
val oldrule = Symtab.lookup (AOT_VarifyRules.get thy) key
in
AOT_VarifyRules.map (Symtab.update (key,
fn ctxt => fn term => fn thm => (
case rule ctxt term thm of SOME r => SOME r
| _ => ((case oldrule of SOME r => r ctxt term thm | _ => NONE))
)
))
end thy)
fun AOT_rulify ctxt thm =
let
fun getUnvarifyRule ctxt thm (Const (name,_) $ args) = (
case Symtab.lookup (AOT_VarifyRules.get (Context.theory_of ctxt)) name of
SOME rule => (case rule ctxt args thm of SOME thm' => (
SOME thm'
) | _ => getUnvarifyRule ctxt thm args)
| NONE => getUnvarifyRule ctxt thm args
)
| getUnvarifyRule ctxt thm (A $ B) = (
case getUnvarifyRule ctxt thm A of SOME thm => SOME thm | NONE => getUnvarifyRule ctxt thm B
)
| getUnvarifyRule ctxt thm (Abs (_,_,T)) = getUnvarifyRule ctxt thm T
| getUnvarifyRule _ _ _ = NONE
fun getUnvarifyRules ctxt thm = (
case getUnvarifyRule ctxt thm (Thm.concl_of thm) of SOME thm' => thm'::getUnvarifyRules ctxt (thm RS thm')
| NONE => []
)
fun outermost_proper_const trm = case Term.strip_comb trm of
(Const (\<^const_name>\<open>Trueprop\<close>, _), [trm]) => outermost_proper_const trm
| (Const (\<^const_name>\<open>AOT_model_valid_in\<close>, _), [_,trm]) => outermost_proper_const trm
| (Const c, _) => SOME (Const c)
| _ => NONE
val (thm,inst_thms) =
case Option.mapPartial (fn Const (trm,_) => Symtab.lookup (AOT_RulifyInsts.get (Context.theory_of ctxt)) trm | _ => NONE)
(outermost_proper_const (Thm.concl_of thm))
of SOME instThm => (thm RS instThm,[instThm]) | _ => (thm,[])
val unvarifyRules = getUnvarifyRules ctxt thm
val unvarifiedThm = fold (fn rule => fn thm => thm RS rule) unvarifyRules thm
fun getRules term = case (Symtab.lookup (AOT_RulifyElims.get (Context.theory_of ctxt)) term) of SOME list => list | _ => []
fun getSimplifications thm =
case outermost_proper_const (Thm.concl_of thm) of
SOME (Const (const_name, _)) =>
(case getRules const_name of [] => [] |
rules => let
val simps = map (fn rule => let
val newthm = thm RS rule
val simps = map (fn thms => rule::thms) ((getSimplifications newthm): thm list list)
in case simps of [] => [[rule]] | _ => simps end) rules
in flat simps end)
| SOME _ => []
| NONE => []
val simps = getSimplifications unvarifiedThm
val simps = map (fn thms => inst_thms@unvarifyRules@thms) simps
in
simps
end
structure AOT_RulifyIntros = Theory_Data (
type T = thm Net.net
val empty = Net.empty
val merge = Net.merge (K true)
);
fun AOT_applyIntros ctxt thm = let
val net = AOT_RulifyIntros.get (Context.theory_of ctxt)
val _ = @{print} ("Prems:", cprems_of thm)
val thms = map (fn cprem => let
val prem = Thm.term_of cprem
val thms = Net.unify_term net prem
val thm = case thms of [] => NONE | thm::_ => (let
val name = ((Binding.name_of o Binding.qualified_name o Thm.get_name_hint) thm)
val _ = @{print} name
val match = try Thm.first_order_match (Thm.cconcl_of thm, cprem)
val _ = @{print} match
val thm = Option.map (fn match => Drule.instantiate_normalize match thm) match
in Option.map (fn thm => (name,thm)) thm end)
in thm end) (cprems_of thm)
val names = List.mapPartial (Option.map fst) thms
val thms = map (Option.map snd) thms
val _ = @{print} ("NAMES:", names, "THMS:", thms)
fun resolve_prems thm thms = let
val c = fold (fn SOME _ => (fn n => n + 1)| _ => I) thms 0
val (_,_,is) = fold (fn SOME _ => (fn (n,m,is) => (n+1,m,is@[n])) | _ => (fn (n,m,is) => (n,m+1,is@[m+c]))) thms (0,0,[])
val y = List.tabulate (List.length is, fn n => (List.nth (is,n),n))
fun quicksort [] = []
| quicksort ((k,x)::xs) =
let
val (left, right) = List.partition (fn (y,_) => y<k) xs
in
quicksort left @ [(k,x)] @ quicksort right
end
val is = map snd (quicksort y)
val thm = Drule.rearrange_prems is thm
val _ = @{print} (thm)
val thms = List.mapPartial I thms
val thm = thm OF thms
in thm end
val thm = resolve_prems thm thms
in
(names,thm)
end
(**** RULIFICATION END *****)
fun AOT_item_by_name name = Option.map fst (List.find (fn (_,n) => n = name) AOT_items)
fun AOT_name_of_item id = Option.map snd (List.find (fn (i,_) => id = i) AOT_items)
val print_AOT_syntax = Attrib.setup_config_bool @{binding "show_AOT_syntax"} (K false)
local
fun AOT_map_translation b (name:string, f) = (name, fn ctxt =>
if Config.get ctxt print_AOT_syntax = b
then f ctxt
else raise Match)
in
val AOT_syntax_print_translations =
map (fn (n,f:Proof.context -> term list -> term) =>
AOT_map_translation true (n,f))
val AOT_syntax_typed_print_translations
= map (fn (n,f:Proof.context -> typ -> term list -> term) =>
AOT_map_translation true (n,f))
val AOT_syntax_print_ast_translations
= map (fn (n,f:Proof.context -> Ast.ast list -> Ast.ast) =>
AOT_map_translation true (n,f))
end
fun AOT_get_item_number name = let
val name = hd (String.fields (equal #"[") name)
val name = String.fields (equal #":") name
in case (AOT_item_by_name (hd name)) of (SOME id) => SOME (
fold (fn sub => fn str => str ^ "." ^ sub) (tl name) (Int.toString id)
) | _ => NONE end
fun AOT_print_item_number (name:string) = case (AOT_get_item_number name)
of SOME str => Pretty.writeln (Pretty.str ("PLM item number (" ^ str ^ ")"))
| _ => ()
fun add_AOT_print_rule AOTsyntax raw_rules thy = let
val rules = map (fn (r, s) => let
val head = Ast.head_of_rule (s,r)
in (head, fn ctxt => fn asts =>
if Config.get ctxt print_AOT_syntax = AOTsyntax then
let
val orig = (Ast.mk_appl (Ast.Constant head) asts)
val normalized = Ast.normalize ctxt
(fn head' => if head = head' then [(s,r)] else []) orig
in
if orig = normalized then raise Match else normalized
end
else raise Match)
end) raw_rules
in Sign.print_ast_translation rules thy end
local
val trans_pat =
Scan.optional
(\<^keyword>\<open>(\<close>
|-- Parse.!!! (Parse.inner_syntax Parse.name --|
\<^keyword>\<open>)\<close>)) "logic"
-- Parse.inner_syntax Parse.string;
fun trans_arrow toks =
((\<^keyword>\<open>\<leftharpoondown>\<close> || \<^keyword>\<open><=\<close>)
>> K Syntax.Print_Rule) toks;
val trans_line =
trans_pat -- Parse.!!! (trans_arrow |-- trans_pat)
>> (fn (left, right) => (left, right));
fun add_trans_rule AOTsyntax raw_rules thy =
let
fun mapPair f (x, y) = (f x, f y)
val ctxt = Proof_Context.init_global thy;
val read_root = #1 o dest_Type o
Proof_Context.read_type_name {proper = true, strict = false} ctxt;
val raw_rules = map (mapPair (fn (r, s) =>
(Syntax_Phases.parse_ast_pattern ctxt (read_root r, s)))) raw_rules
in add_AOT_print_rule AOTsyntax raw_rules thy end
val _ =
Outer_Syntax.command
\<^command_keyword>\<open>AOT_syntax_print_translations\<close>
"add print translation rules for AOT syntax"
(Scan.repeat1 trans_line >> (Toplevel.theory o add_trans_rule true));
val _ =
Outer_Syntax.command
\<^command_keyword>\<open>AOT_no_syntax_print_translations\<close>
"add AOT print translation rules for non-AOT syntax"
(Scan.repeat1 trans_line >> (Toplevel.theory o add_trans_rule false));
in end
structure AOT_Theorems = Named_Thms(
val name = @{binding "AOT"}
val description = "AOT Theorems"
)
structure AOT_Definitions = Named_Thms(
val name = @{binding "AOT_defs"}
val description = "AOT Definitions"
)
structure AOT_ProofData = Proof_Data
(type T = term option
fun init _ = NONE)
fun AOT_note_theorems (name:Attrib.binding) thms = (
Local_Theory.background_theory
((Context.theory_map (fn thy => fold AOT_Theorems.add_thm
(map Drule.export_without_context (flat thms)) thy)
) #> (fn thy => let
val thms = flat thms
val idxs = List.tabulate (List.length thms, I)
val thy = fold (fn n => fn thy =>
let
val thm = List.nth (thms,n)
val name = fst name
val name = (case thms of [_] => name | _ => Binding.qualify_name true name (Int.toString n))
val simps = AOT_rulify (Context.Theory thy) thm
val thms = map (fn simps => (fold (fn rule => fn thm => thm RS rule) simps thm, map (fn thm => (Binding.name_of o Binding.qualified_name o Thm.get_name_hint) thm) simps)) simps
(* TODO *)
(* val thms = map (fn (thm,names) => let
val (moreNames,thm) = AOT_applyIntros (Context.Theory thy) thm
in (thm,names@moreNames) end) thms*)
val thms = map (apfst (Object_Logic.rulify (Proof_Context.init_global thy))) thms
val thy = fold (fn (thm,names) => fn thy =>
let
val thm = Drule.export_without_context thm
val name = fold (fn suffix => fn name => Binding.qualify_name true name suffix) names name
val (thms,thy) = Global_Theory.add_thms [((name,thm),[])] thy
val thy = Context.theory_map (fn thy => fold AOT_Theorems.add_thm thms thy) thy
in thy end) thms thy
in
thy
end
) idxs thy
in thy end)
)
)
fun AOT_note_definitions thms = Local_Theory.background_theory
(Context.theory_map (fold AOT_Definitions.add_thm
(map Drule.export_without_context (flat thms))))
structure AOT_DefinedConstants = Theory_Data (
type T = Termtab.set
val empty = Termtab.empty
val extend = I
val merge = Termtab.merge (K true)
);
fun AOT_note_defined_constant const =
Local_Theory.background_theory (AOT_DefinedConstants.map (Termtab.insert_set const))
fun AOT_read_prop nonterminal ctxt prop = (let
val ctxt' = Config.put Syntax.root nonterminal ctxt
val trm = Syntax.parse_term ctxt' prop
val typ = Term.fastype_of (Syntax.check_term ctxt' trm)
val trm = if typ = @{typ prop} then trm else HOLogic.mk_Trueprop trm
in trm end)
fun AOT_read_term nonterminal ctxt prop = (let
val ctxt' = Config.put Syntax.root nonterminal ctxt
val trm = Syntax.parse_term ctxt' prop
in trm end)
fun AOT_check_prop nonterminal ctxt prop =
AOT_read_prop nonterminal ctxt prop |> Syntax.check_prop ctxt;
let
fun close_form t =
fold_rev (fn (s, T) => fn t => HOLogic.mk_all (s, T, t)) (Term.add_frees t []) t
fun remove_case_prod (Const (\<^const_name>\<open>case_prod\<close>, _) $ x) = remove_case_prod x
| remove_case_prod (Const (\<^const_name>\<open>case_unit\<close>, _) $ x) = remove_case_prod x
| remove_case_prod (Abs (a,b,c)) = Abs (a,b,remove_case_prod c)
| remove_case_prod x = x
fun AOT_define_id (bnd,str,mx) (lhs,rhs,trm) ctxt =
let
val bnd_str = Binding.name_of bnd
val syn_typ = Syntax.parse_typ ctxt str
val lhs = remove_case_prod lhs
val rhs = remove_case_prod rhs
fun filter (name,_) = not (name = \<^const_name>\<open>case_prod\<close>
orelse name = \<^const_name>\<open>case_unit\<close>)
val (const_name, const_typ) = case (List.filter filter (Term.add_consts lhs []))
of [const] => const
| _ => raise Term.TERM
("Expected a single constant on the LHS of the definition.", [lhs])
val _ = Long_Name.base_name const_name = Long_Name.base_name bnd_str
orelse raise Term.TERM ("Left-hand side does not contain the definiens.", [lhs])
val (lhs_abs_vars, _) = Term.strip_abs lhs
val (rhs_abs_vars, rhs_abs_body) = Term.strip_abs rhs
val _ = lhs_abs_vars = rhs_abs_vars orelse raise Term.TERM
("Expected the LHS and RHS to abstract over the same free variables.", [lhs, rhs])
val body = rhs_abs_body
val witness = fold_rev (fn (s, T) => fn t => Term.absfree (s, T) t)
lhs_abs_vars body
val witness = Syntax.check_term ctxt witness
(* Construct the choice specification theorem. *)
val thm =
let
val cname = Long_Name.base_name const_name
val vname = if Symbol_Pos.is_identifier cname then cname else "x"
val trm = @{const Trueprop} $ HOLogic.mk_exists (vname, const_typ,
Term.abstract_over (Const (const_name, const_typ), trm))
val cwitness = Thm.cterm_of ctxt witness
val witness_exI = Thm.instantiate'
[SOME (Thm.ctyp_of_cterm cwitness)]
[NONE,SOME cwitness] exI
val simps = [
@{thm AOT_model_id_def},
@{thm AOT_model_nondenoing},
@{thm AOT_model_denotes_prod_def},
@{thm AOT_model_denotes_unit_def},
@{thm case_unit_Unity}
]
val thm = (Goal.prove ctxt [] [] trm (fn _ =>
resolve_tac ctxt [witness_exI] 1
THEN simp_tac (ctxt addsimps simps) 1))
val match = Thm.match (Thm.cprop_of thm, Thm.cterm_of ctxt trm)
in Drule.instantiate_normalize match thm end
(* Add the choice specification and cleanup and export the resulting theorem. *)
val oldctxt = ctxt
val (thm, ctxt) = Local_Theory.background_theory_result (fn lthy => let
val lthy = lthy |> Sign.add_consts [(bnd,const_typ,Mixfix.NoSyn)] |>
Sign.syntax true Syntax.mode_default [(bnd_str,syn_typ,mx)] |>
add_AOT_print_rule true [
(Ast.Constant bnd_str, Ast.Constant (Lexicon.mark_const const_name))
]
in
Choice_Specification.add_specification [("",bnd_str,false)] (lthy, thm)
|> apsnd Drule.export_without_context |> swap
end) (Proof_Context.concealed ctxt)
in
(ctxt |> Proof_Context.restore_naming oldctxt, thm)
end
fun AOT_define_equiv (bnd,str,mx) (lhs,rhs,trm) ctxt =
let
val bnd_str = Binding.name_of bnd
val syn_typ = Syntax.parse_typ ctxt str
val (const_name, const_typ) = case (Term.add_consts lhs []) of [const] => const
| _ => raise Term.TERM
("Expected a single constant on the LHS of the definition.", [lhs])
(* TODO: figure out how to properly compare the constant name with the binding *)
val _ = Long_Name.base_name const_name = Long_Name.base_name bnd_str
orelse raise Term.TERM ("Left-hand side does not contain the definiens.", [lhs])
(* Construct a witness for the choice specification theorem. *)
val frees = Term.add_frees trm []
val witness = let
val w = case Term.variant_frees trm [("w", @{typ w})] of [w] => w
| _ => raise Fail "Unexpected."
in
\<^const>\<open>AOT_model_proposition_choice\<close> $
Term.absfree w (\<^const>\<open>AOT_model_valid_in\<close> $ Free w $ rhs)
end
val witness = fold_rev (fn (s, T) => fn t => Term.absfree (s, T) t)
(List.rev frees) witness
(* Construct the choice specification theorem. *)
val thm =
let
val cname = Long_Name.base_name const_name
val vname = if Symbol_Pos.is_identifier cname then cname else "x"
val trm = @{const Trueprop} $ HOLogic.mk_exists (vname, const_typ,
Term.abstract_over (Const (const_name, const_typ), close_form trm))
val cwitness = Thm.cterm_of ctxt witness
val witness_exI = Thm.instantiate'
[SOME (Thm.ctyp_of_cterm cwitness)]
[NONE,SOME cwitness] exI
val simps = [
@{thm AOT_model_equiv_def},
@{thm AOT_model_proposition_choice_simp}
]
val thm = (Goal.prove ctxt [] [] trm (fn _ =>
resolve_tac ctxt [witness_exI] 1
THEN simp_tac (ctxt addsimps simps) 1))
val match = Thm.match (Thm.cprop_of thm, Thm.cterm_of ctxt trm)
in
Drule.instantiate_normalize match thm
end
(* Add the choice specification and cleanup and export the resulting theorem. *)
val oldctxt = ctxt
val (thm, ctxt) = Proof_Context.concealed ctxt |>
Local_Theory.background_theory_result (fn lthy => let
fun inst_all thy (name,typ) thm =
let
val cv = Thm.global_cterm_of thy (Free (name,typ))
val cT = Thm.global_ctyp_of thy typ
val spec' = Thm.instantiate' [SOME cT] [NONE, SOME cv] spec
in thm RS spec' end
fun remove_alls frees (thy, thm) = (thy, fold (inst_all thy) frees thm)
val lthy = lthy |> Sign.add_consts [(bnd,const_typ,Mixfix.NoSyn)] |>
Sign.syntax true Syntax.mode_default [(bnd_str,syn_typ,mx)] |>
add_AOT_print_rule true [
(Ast.Constant bnd_str, Ast.Constant (Lexicon.mark_const const_name))
]
in
Choice_Specification.add_specification [("",bnd_str,false)] (lthy, thm)
|> remove_alls frees |> apsnd Drule.export_without_context |> swap
end)
in
(ctxt |> Proof_Context.restore_naming oldctxt, thm)
end
fun AOT_define (((bnd,str,mx),(thmbind,thmattrs)),defprop) ctxt =
let
val bnd_str = Binding.name_of bnd
val syn_typ = Syntax.parse_typ ctxt str
(* Add a generic constant and the requested syntax to a temporary context. *)
val thy = Proof_Context.theory_of ctxt
val thy' = Sign.add_consts [(bnd, @{typ 'a}, Mixfix.NoSyn)] thy
val thy' = Sign.syntax true Syntax.mode_default [(bnd_str,syn_typ,mx)] thy'
(* Try to parse the definition using the temporary context. *)
val trm = AOT_check_prop @{nonterminal AOT_prop}
(Proof_Context.init_global thy') defprop
(* Extract lhs, rhs and the full definition from the parsed proposition
and delegate. *)
val (ctxt, thm) = case trm of (Const (\<^const_name>\<open>HOL.Trueprop\<close>, _) $
(trm as Const (n, _) $ lhs $ rhs)) =>
if n = \<^const_name>\<open>AOT_model_equiv_def\<close> then
AOT_define_equiv (bnd,str,mx) (lhs,rhs,trm) ctxt
else if n = \<^const_name>\<open>AOT_model_id_def\<close> then
AOT_define_id (bnd,str,mx) (lhs,rhs,trm) ctxt
else
raise Term.TERM ("Expected AOT definition.", [trm])
| _ => raise Term.TERM ("Expected AOT definition.", [trm])
val thmbind = if Binding.is_empty thmbind then bnd else thmbind
val _ = AOT_print_item_number (Binding.name_of thmbind)
in
ctxt |> Local_Theory.note ((thmbind, thmattrs), [thm]) |> snd |>
AOT_note_theorems (thmbind,thmattrs) [[thm]] |> AOT_note_definitions [[thm]] |>
AOT_note_defined_constant
(Proof_Context.read_const {proper=true,strict=true} ctxt (Binding.name_of bnd))
end
in
Outer_Syntax.local_theory
@{command_keyword AOT_define}
"AOT definition by equivalence."
(Parse.const_binding -- Parse_Spec.opt_thm_name ":" -- Parse.prop >> AOT_define)
end;
(* this is a stripped down version of Expression.read_statement
that mainly replaces Syntax.parse_prop with AOT_read_prop
and drops locale includes *)
local
fun mk_type T = (Logic.mk_type T, []);
fun mk_propp (p, pats) = (Type.constraint propT p, pats);
fun dest_type (T, []) = Logic.dest_type T
| dest_type _ = raise Fail "Unexpected."
fun dest_propp (p, pats) = (p, pats);
fun finish_fixes (parms: (string * typ) list) = map (fn (binding, _, mx) =>
let val x = Binding.name_of binding
in (binding, AList.lookup (op =) parms x, mx) end);
fun finish_elem parms (Element.Fixes fixes) = Element.Fixes (finish_fixes parms fixes)
| finish_elem _ (Element.Constrains _) = Element.Constrains []
| finish_elem _ (Element.Assumes asms) = Element.Assumes asms
| finish_elem _ (Element.Defines defs) = Element.Defines defs
| finish_elem _ (elem as Element.Notes _) = elem
| finish_elem _ (elem as Element.Lazy_Notes _) = elem;
fun extract_elem (Element.Fixes fixes) = map (#2 #> the_list #> map mk_type) fixes
| extract_elem (Element.Constrains csts) = map (#2 #> single #> map mk_type) csts
| extract_elem (Element.Assumes asms) = map (#2 #> map mk_propp) asms
| extract_elem (Element.Defines defs) =
map (fn (_, (t, ps)) => [mk_propp (t, ps)]) defs
| extract_elem (Element.Notes _) = []
| extract_elem (Element.Lazy_Notes _) = [];
fun restore_elem (Element.Fixes fixes, css) =
(fixes ~~ css) |> map (fn ((x, _, mx), cs) =>
(x, cs |> map dest_type |> try hd, mx)) |> Element.Fixes
| restore_elem (Element.Constrains csts, css) =
(csts ~~ css) |> map (fn ((x, _), cs) =>
(x, cs |> map dest_type |> hd)) |> Element.Constrains
| restore_elem (Element.Assumes asms, css) =
(asms ~~ css) |> map (fn ((b, _), cs) =>
(b, map dest_propp cs)) |> Element.Assumes
| restore_elem (Element.Defines defs, css) =
(defs ~~ css) |> map (fn ((b, _), [c]) =>
(b, dest_propp c) | _ => raise Fail "Unexpected") |> Element.Defines
| restore_elem (elem as Element.Notes _, _) = elem
| restore_elem (elem as Element.Lazy_Notes _, _) = elem;
fun prep (_, pats) (ctxt, t :: ts) =
let
val ctxt' = Proof_Context.augment t ctxt
in
((t, Syntax.check_props
(Proof_Context.set_mode Proof_Context.mode_pattern ctxt') pats),
(ctxt', ts))
end
| prep _ _ = raise Fail "Unexpected"
fun check cs ctxt =
let
val (cs', (ctxt', _)) = fold_map prep cs
(ctxt, Syntax.check_terms
(Proof_Context.set_mode Proof_Context.mode_schematic ctxt) (map fst cs));
in (cs', ctxt') end;
fun check_autofix elems concl ctxt =
let
val elem_css = map extract_elem elems;
val concl_cs = (map o map) mk_propp (map snd concl);
(* Type inference *)
val (css', ctxt') =
(fold_burrow o fold_burrow) check (elem_css @ [concl_cs]) ctxt;
val (elem_css', concl_cs') = chop (length elem_css) css' |> apsnd the_single;
in
((map restore_elem (elems ~~ elem_css'),
map fst concl ~~ concl_cs'), ctxt')
end;
fun prepare_stmt prep_prop ctxt stmt =
(case stmt of
Element.Shows raw_shows =>
raw_shows |> (map o apsnd o map) (fn (t, ps) =>
(prep_prop (Proof_Context.set_mode Proof_Context.mode_schematic ctxt) t,
map (prep_prop (Proof_Context.set_mode Proof_Context.mode_pattern ctxt)) ps))
| Element.Obtains _ => raise Fail "unsupported");
fun parse_elem prep_typ prep_term ctxt =
Element.map_ctxt
{binding = I,
typ = prep_typ ctxt,
term = prep_term (Proof_Context.set_mode Proof_Context.mode_schematic ctxt),
pattern = prep_term (Proof_Context.set_mode Proof_Context.mode_pattern ctxt),
fact = I,
attrib = I};
fun declare_elem prep_var (Element.Fixes fixes) ctxt =
let val (vars, _) = fold_map prep_var fixes ctxt
in ctxt |> Proof_Context.add_fixes vars |> snd end
| declare_elem prep_var (Element.Constrains csts) ctxt =
ctxt |> fold_map (fn (x, T) =>
prep_var (Binding.name x, SOME T, NoSyn)) csts |> snd
| declare_elem _ (Element.Assumes _) ctxt = ctxt
| declare_elem _ (Element.Defines _) ctxt = ctxt
| declare_elem _ (Element.Notes _) ctxt = ctxt
| declare_elem _ (Element.Lazy_Notes _) ctxt = ctxt;
fun prep_full_context_statement
parse_prop prop_root elem_root raw_elems raw_stmt ctxt1 =
let
fun prep_elem raw_elem ctxt =
let
val ctxt' = ctxt
|> Context_Position.set_visible false
|> declare_elem Proof_Context.read_var raw_elem
|> Context_Position.restore_visible ctxt;
val elems' = parse_elem Syntax.parse_typ (parse_prop elem_root) ctxt' raw_elem;
in (elems', ctxt') end;
val fors = fold_map Proof_Context.read_var [] ctxt1 |> fst;
val ctxt2 = ctxt1 |> Proof_Context.add_fixes fors |> snd;
val ctxt3 = ctxt2
fun prep_stmt elems ctxt = check_autofix elems
(prepare_stmt (parse_prop prop_root) ctxt raw_stmt) ctxt;
val ((elems', concl), ctxt4) = ctxt3
|> fold_map prep_elem raw_elems
|-> prep_stmt;
(* parameters from expression and elements *)
val xs = maps (fn Element.Fixes fixes =>
map (Variable.check_name o #1) fixes | _ => [])
(Element.Fixes fors :: elems');
val (parms, _) = fold_map Proof_Context.inferred_param xs ctxt4;
val elems'' = map (finish_elem parms) elems';
in (elems'', concl) end;
in
fun read_statement prop_root elem_root raw_elems raw_stmt ctxt =
let
val (elems, concl) = prep_full_context_statement
AOT_read_prop prop_root elem_root raw_elems raw_stmt ctxt;
val ctxt' = Proof_Context.set_stmt true ctxt
val (elems, ctxt') = fold_map Element.activate elems ctxt'
val _ = Proof_Context.restore_stmt ctxt ctxt'
in (concl, elems, ctxt) end;
end
(* End of Expression.read_statement variant. *)
val long_keyword =
Parse_Spec.includes >> K "" ||
Parse_Spec.long_statement_keyword;
val long_statement =
Scan.optional (Parse_Spec.opt_thm_name ":" --| Scan.ahead long_keyword)
Binding.empty_atts --
Scan.optional Parse_Spec.includes [] --Parse_Spec.long_statement
>> (fn ((binding, includes), (elems, concl)) =>
(true, binding, includes, elems, concl))
val short_statement =
Parse_Spec.statement -- Parse_Spec.if_statement -- Parse.for_fixes
>> (fn ((shows, assumes), fixes) =>
(false, Binding.empty_atts, [], [Element.Fixes fixes, Element.Assumes assumes],
Element.Shows shows))
fun setupStrictWorld ctxt = let
(* TODO: ideally not just a fixed name, but a variant name... *)
val (v,ctxt) = Proof_Context.add_fixes
[(Binding.make ("ws", Position.none), SOME @{typ w}, Mixfix.NoSyn)] ctxt |>
apfst the_single
in AOT_ProofData.put (SOME (Free (v, @{typ w}))) ctxt end
fun setupWeakWorld ctxt = AOT_ProofData.put (SOME @{const w\<^sub>0}) ctxt
fun mapStmt mapTerm _ (Element.Shows x) =
Element.Shows (map (map (fn (trm, trms) =>
(mapTerm trm, map mapTerm trms)) |> apsnd) x)
| mapStmt mapTerm mapTyp (Element.Obtains x) =
Element.Obtains (map ((fn (x, y) =>
(map (fn (a,b,c) => (a, Option.map mapTyp b, c)) x, map mapTerm y)) |> apsnd) x)
fun mapCtxt mapTerm mapTyp ctxtElem = Element.map_ctxt
{attrib = I, binding = I, fact = I, pattern = mapTerm, term = mapTerm, typ = mapTyp}
ctxtElem
fun AOT_theorem_cmd axiom modallyStrict long afterQed thmBinding
includes assumptions shows int ctxt =
let
val ctxt = Bundle.includes_cmd includes ctxt
val ctxt = if modallyStrict then setupStrictWorld ctxt else setupWeakWorld ctxt
val root = if axiom
then (if modallyStrict
then @{nonterminal "AOT_axiom"}
else @{nonterminal "AOT_act_axiom"})
else @{nonterminal AOT_prop}
val (stmts,assumptions,ctxt) = read_statement
root @{nonterminal AOT_prop} assumptions shows ctxt
val _ = AOT_print_item_number (Binding.name_of (fst thmBinding))
val _ = fold (fn ((bnd,_),_) => fn _ =>
AOT_print_item_number (Binding.name_of bnd)) stmts ()
val name = fold (fn (bnd,_) => fn b => if Binding.is_empty (fst b) then bnd else b) stmts thmBinding
in
Specification.theorem long "AOT_theorem" NONE (afterQed name) thmBinding []
assumptions (Element.Shows stmts) int ctxt
end
fun AOT_theorem spec note axiom modallyStrict descr =
Outer_Syntax.local_theory_to_proof' spec ("state " ^ descr)
((long_statement || short_statement) >>
(fn (long, binding, includes, elems, concl) =>
(AOT_theorem_cmd axiom modallyStrict long
(if note then AOT_note_theorems else K (K I)) binding includes elems concl)));
val _ = AOT_theorem \<^command_keyword>\<open>AOT_lemma\<close> false false true
"AOT modally-strict lemma";
val _ = AOT_theorem \<^command_keyword>\<open>AOT_theorem\<close> true false true
"AOT modally-strict theorem";
val _ = AOT_theorem \<^command_keyword>\<open>AOT_act_lemma\<close> false false false
"AOT modally-weak lemma";
val _ = AOT_theorem \<^command_keyword>\<open>AOT_act_theorem\<close> true false false
"AOT modally-weak theorem"
val _ = AOT_theorem \<^command_keyword>\<open>AOT_axiom\<close> true true true
"AOT modally-strict axiom";
val _ = AOT_theorem \<^command_keyword>\<open>AOT_act_axiom\<close> true true false
"AOT modally-weak axiom"
local
val structured_statement =
Parse_Spec.statement -- Parse_Spec.if_statement -- Parse.for_fixes
>> (fn ((shows, assumes), fixes) => (fixes, assumes, shows));
fun prep_stmt (fixes, assumes, shows) ctxt = let
val (concl, elems, _) = read_statement
@{nonterminal AOT_prop} @{nonterminal AOT_prop}
[Element.Fixes fixes, Element.Assumes assumes] (Element.Shows shows) ctxt
val (fixes, assumes) =
(fn ([Element.Fixes fixes, Element.Assumes assumes]) => (fixes, assumes)
| _ => raise Fail "Unexpected.") elems
fun mapAttr (a,[]) = (a,[])
| mapAttr _ = raise Match (* Unimplemented *)
val assumes = map (mapAttr |> apfst) assumes
val concl = map (mapAttr |> apfst) concl
in (fixes, assumes, concl) end
fun gen_cmd kind stmt int state = let
val (fixes, assumes, shows) = prep_stmt stmt (Proof.context_of state)
in (kind true NONE (K I) fixes assumes shows int) state end
in
val _ =
Outer_Syntax.command \<^command_keyword>\<open>AOT_show\<close>
"state local AOT goal, to refine pending subgoals"
(structured_statement >> (fn stmt =>
Toplevel.proof' (fn int => (gen_cmd Proof.show stmt int #> #2))));
val _ =
Outer_Syntax.command \<^command_keyword>\<open>AOT_thus\<close> "alias of \"then AOT_show\""
(structured_statement >> (fn stmt =>
Toplevel.proof' (fn int => Proof.chain #> (gen_cmd Proof.show stmt int #> #2))));
val _ =
Outer_Syntax.command \<^command_keyword>\<open>AOT_have\<close> "state local AOT goal"
(structured_statement >> (fn stmt =>
Toplevel.proof' (fn int => (gen_cmd Proof.have stmt int #> #2))));
val _ =
Outer_Syntax.command \<^command_keyword>\<open>AOT_hence\<close> "alias of \"then AOT_have\""
(structured_statement >> (fn stmt =>
Toplevel.proof' (fn int => Proof.chain #> (gen_cmd Proof.have stmt int #> #2))));
val _ =
Outer_Syntax.command \<^command_keyword>\<open>AOT_modally_strict {\<close>
"begin explicit AOT modally-strict proof block"
(Scan.succeed (Toplevel.proof (fn state => (Proof.map_context (fn ctxt => let
val v = singleton (Variable.variant_frees ctxt []) ("ws", @{typ w}) |> fst
val (_,ctxt) = Proof_Context.add_fixes
[(Binding.make (v, Position.none), SOME @{typ w}, Mixfix.NoSyn)] ctxt
val ctxt = AOT_ProofData.put (SOME (Free (v, @{typ w}))) ctxt
in ctxt end) (Proof.begin_block state)))));
val _ =
Outer_Syntax.command \<^command_keyword>\<open>AOT_actually {\<close>
"begin explicit AOT modally-fragile proof block"
(Scan.succeed (Toplevel.proof (fn state => (Proof.map_context (fn ctxt => let
val ctxt = AOT_ProofData.put (SOME (@{const w\<^sub>0})) ctxt
in ctxt end) (Proof.begin_block state)))));
val _ =
Outer_Syntax.command \<^command_keyword>\<open>AOT_assume\<close> "assume AOT propositions"
(structured_statement >> (fn stmt =>
Toplevel.proof' (fn _ => fn state => (let
val (fixes, assumes, shows) = prep_stmt stmt (Proof.context_of state)
in Proof.assume fixes (map snd assumes) shows state end))));
val _ =
Outer_Syntax.command \<^command_keyword>\<open>AOT_obtain\<close> "generalized AOT elimination"
(Parse.parbinding -- Scan.optional (Parse.vars --| Parse.where_) [] --
structured_statement >> (fn ((a, b), stmt) => Toplevel.proof'
(fn int => fn state => (let
val ctxt = Proof.context_of state
val b = map (fn (a,b,c) => (a,Option.map (Syntax.read_typ ctxt) b, c)) b
val bnds = map (fn (a,_,_) => a) b
val (_,ctxt) = Variable.add_fixes_binding bnds ctxt
val (fixes, assumes, shows) = prep_stmt stmt ctxt
in Obtain.obtain a b fixes (map snd assumes) shows int state end))));
end
structure AOT_no_atp = Named_Thms(
val name = @{binding "AOT_no_atp"}
val description = "AOT Theorem Blacklist"
)
val _ =
Outer_Syntax.command \<^command_keyword>\<open>AOT_sledgehammer\<close>
"sledgehammer restricted to AOT abstraction layer"
(Scan.succeed (Toplevel.keep_proof (fn state => let
val params = Sledgehammer_Commands.default_params (Toplevel.theory_of state) []
val ctxt = Toplevel.context_of state
fun all_facts_of ctxt =
let
val thy = Proof_Context.theory_of ctxt;
val transfer = Global_Theory.transfer_theories thy;
val global_facts = Global_Theory.facts_of thy;
in
(Facts.dest_all (Context.Proof ctxt) false [] global_facts
|> maps Facts.selections
|> map (apsnd transfer))
end
val facts = all_facts_of ctxt
val add_facts = filter
(fn fact => AOT_Theorems.member ctxt (snd fact)) facts |> map (fn (x,_) => (x,[]))
val del_facts = filter
(fn fact => AOT_no_atp.member ctxt (snd fact)) facts |> map (fn (x,_) => (x,[]))
val ctxt = Toplevel.proof_of state
val _ = Sledgehammer.run_sledgehammer params Sledgehammer_Prover.Normal NONE 1
{add = add_facts, del = del_facts, only = false} ctxt
in () end)))
val _ =
Outer_Syntax.command \<^command_keyword>\<open>AOT_sledgehammer_only\<close>
"sledgehammer restricted to AOT abstraction layer"
(Scan.succeed (Toplevel.keep_proof (fn state => let
val params = Sledgehammer_Commands.default_params (Toplevel.theory_of state) []
val ctxt = Toplevel.context_of state
fun all_facts_of ctxt =
let
val thy = Proof_Context.theory_of ctxt;
val transfer = Global_Theory.transfer_theories thy;
val local_facts = Proof_Context.facts_of ctxt;
val global_facts = Global_Theory.facts_of thy;
in
(Facts.dest_all (Context.Proof ctxt) false [global_facts] local_facts
|> maps Facts.selections
|> map (apsnd transfer) |> map fst) @
(Facts.dest_all (Context.Proof ctxt) false [] global_facts
|> maps Facts.selections
|> map (apsnd transfer)
|> filter (AOT_Theorems.member ctxt o snd) |> map fst)
end
val facts = all_facts_of ctxt
val result = map (fn x => (x,[])) facts
val ctxt = Toplevel.proof_of state
val _ = Sledgehammer.run_sledgehammer params Sledgehammer_Prover.Normal NONE 1
{add = result, del = [], only = true} ctxt
in () end)))
local
fun readTermPattern ctxt str = (let
val trm = case try (AOT_read_term @{nonterminal \<tau>'} ctxt) str of SOME x => x
| NONE =>
(case try (AOT_read_term @{nonterminal \<phi>'} ctxt) str of SOME x => x
| NONE => (AOT_read_term @{nonterminal AOT_prop} ctxt) str)
val trm = Syntax.check_term ctxt trm
fun varifyTerm (Const (\<^const_name>\<open>AOT_term_of_var\<close>, Type ("fun", [_, t])) $
Free (x, _)) = Var ((x, 0), t)
| varifyTerm (Free (x,t)) = Var ((x, 0), t)
| varifyTerm (x $ y) = varifyTerm x $ varifyTerm y
| varifyTerm (Abs (a, b, c)) = Abs(a, b, varifyTerm c)
| varifyTerm z = z
val trm = Term.map_types
(Term.map_type_tfree (fn (str,sort) => TVar ((str, 0), sort))) trm
val trm = varifyTerm trm
in trm end)
fun parseCriterion ctxt (Find_Theorems.Simp crit) =
(Find_Theorems.Simp (readTermPattern ctxt crit))
| parseCriterion ctxt (Find_Theorems.Pattern crit) =
(Find_Theorems.Pattern (readTermPattern ctxt crit))
| parseCriterion _ (Find_Theorems.Name x) = (Find_Theorems.Name x)
| parseCriterion _ Find_Theorems.Intro = Find_Theorems.Intro
| parseCriterion _ Find_Theorems.Elim = Find_Theorems.Elim
| parseCriterion _ Find_Theorems.Dest = Find_Theorems.Dest
| parseCriterion _ Find_Theorems.Solves = Find_Theorems.Solves
fun pretty_criterion ctxt (b, c) =
let
fun prfx s = if b then s else "-" ^ s;
in
(case c of
Find_Theorems.Name name => Pretty.str (prfx "name: " ^ quote name)
| Find_Theorems.Intro => Pretty.str (prfx "intro")
| Find_Theorems.Elim => Pretty.str (prfx "elim")
| Find_Theorems.Dest => Pretty.str (prfx "dest")
| Find_Theorems.Solves => Pretty.str (prfx "solves")
| Find_Theorems.Simp pat => Pretty.block [Pretty.str (prfx "simp:"), Pretty.brk 1,
Pretty.quote (Syntax.pretty_term ctxt (Term.show_dummy_patterns pat))]
| Find_Theorems.Pattern pat => Pretty.enclose (prfx "\"") "\""
[Syntax.pretty_term ctxt (Term.show_dummy_patterns pat)])
end;
datatype query = Criterion of (bool*string Find_Theorems.criterion) list |
Item of (int*string list)
fun pretty_theorems ctxt opt_lim rem_dups raw_spec =
let
fun pretty_ref ctxt thmref =
let
val (name, sel) =
(case thmref of
Facts.Named ((name, _), sel) => (name, sel)
| Facts.Fact _ => raise Fail "Illegal literal fact");
val item = case
AOT_get_item_number (Binding.name_of (Binding.qualified_name name))
of SOME str => [Pretty.str ("("^str^")"), Pretty.str ":", Pretty.brk 1]
| _ => []
in
item @ [Pretty.marks_str (#1 (Proof_Context.markup_extern_fact ctxt name), name),
Pretty.str (Facts.string_of_selection sel), Pretty.str ":", Pretty.brk 1]
end;
fun tailToStr delim tail = (fold (fn field => fn str => str^delim^field) tail "")
fun pretty_item (id, sub) = Pretty.str (
"item: "^quote (Int.toString id^tailToStr "." sub)^
" (name: "^quote ((the (AOT_name_of_item id))^tailToStr ":" sub)^")")
fun pretty_thm ctxt (thmref, thm) =
Pretty.block (pretty_ref ctxt thmref @ [Thm.pretty_thm ctxt thm])
val (spec, prefix) = (case raw_spec of Item (item, tail) =>
(case AOT_name_of_item item of SOME name =>
let val fullName = name^tailToStr ":" tail
in ([(true, Find_Theorems.Name fullName)], SOME fullName) end
| _ => raise Fail "Unknown PLM item number.")
| Criterion spec => (spec, NONE))
val criteria = map (apsnd (parseCriterion ctxt)) spec
val (opt_found, _) = Find_Theorems.find_theorems ctxt NONE (SOME 0) rem_dups criteria
val (_, theorems) = Find_Theorems.find_theorems ctxt NONE opt_found rem_dups criteria
val lim = the_default
(Options.default_int \<^system_option>\<open>find_theorems_limit\<close>) opt_lim;
val theorems = filter (fn (_,thm) => AOT_Theorems.member ctxt thm) theorems
val theorems = case prefix of SOME prefix =>
filter (fn (Facts.Named ((name, _), _), _) =>
let val unqualified = (Binding.name_of (Binding.qualified_name name))
in
String.isPrefix prefix unqualified
andalso (String.size unqualified <= String.size prefix orelse
let
val delim = String.sub (unqualified, String.size prefix)
in delim = #":" orelse delim = #"[" end)
end
| _ => false) theorems
| _ => theorems
val found = length theorems
val theorems = drop (Int.max (found - lim, 0)) theorems
val returned = length theorems
val tally_msg =
(if found <= lim then "displaying " ^ string_of_int returned ^ " theorem(s)"
else "found " ^ string_of_int found ^ " theorem(s)" ^
(if returned < found
then " (" ^ string_of_int returned ^ " displayed)"
else ""));
val position_markup = Position.markup (Position.thread_data ()) Markup.position;
val pretty = Pretty.block
(Pretty.fbreaks
(Pretty.mark position_markup (Pretty.keyword1 "AOT_find_theorems") ::
((case raw_spec of Item (id, sub) =>
[pretty_item (id, sub)] | _ => map (pretty_criterion ctxt) criteria)))) ::
Pretty.str "" ::
(if null theorems then [Pretty.str "found nothing"]
else
Pretty.str (tally_msg ^ ":") ::