aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcorbinea2006-09-20 17:18:18 +0000
committercorbinea2006-09-20 17:18:18 +0000
commit0f4f723a5608075ff4aa48290314df30843efbcb (patch)
tree09316ca71749b9218972ca801356388c04d29b4c
parentc6b9d70f9292fc9f4b5f272b5b955af0e8fe0bea (diff)
Declarative Proof Language: main commit
git-svn-id: svn+ssh://scm.gforge.inria.fr/svn/coq/trunk@9154 85f007b7-540e-0410-9357-904b9bb8a0f7
-rw-r--r--.depend162
-rw-r--r--.depend.camlp41
-rw-r--r--Makefile28
-rw-r--r--contrib/first-order/formula.ml1
-rw-r--r--contrib/first-order/g_ground.ml439
-rw-r--r--contrib/funind/tacinvutils.ml5
-rw-r--r--contrib/interface/showproof.ml30
-rw-r--r--contrib/interface/xlate.ml10
-rw-r--r--contrib/rtauto/refl_tauto.ml1
-rw-r--r--contrib/xml/proof2aproof.ml19
-rw-r--r--contrib/xml/proofTree2Xml.ml48
-rw-r--r--ide/coq.ml40
-rw-r--r--ide/coq.mli3
-rw-r--r--ide/coqide.ml548
-rw-r--r--ide/utils/editable_cells.ml2
-rw-r--r--interp/constrintern.ml8
-rw-r--r--interp/constrintern.mli8
-rw-r--r--parsing/g_decl_mode.ml4171
-rw-r--r--parsing/g_proofs.ml41
-rw-r--r--parsing/g_vernac.ml442
-rw-r--r--parsing/pcoq.ml46
-rw-r--r--parsing/pcoq.mli7
-rw-r--r--parsing/ppdecl_proof.ml180
-rw-r--r--parsing/ppdecl_proof.mli2
-rw-r--r--parsing/ppvernac.ml9
-rw-r--r--parsing/printer.ml88
-rw-r--r--parsing/printer.mli2
-rw-r--r--parsing/tactic_printer.ml153
-rw-r--r--parsing/tactic_printer.mli4
-rw-r--r--pretyping/evarutil.ml6
-rw-r--r--pretyping/evd.ml13
-rw-r--r--pretyping/evd.mli4
-rw-r--r--proofs/decl_expr.mli108
-rw-r--r--proofs/decl_mode.ml121
-rw-r--r--proofs/decl_mode.mli73
-rw-r--r--proofs/evar_refiner.ml4
-rw-r--r--proofs/evar_refiner.mli2
-rw-r--r--proofs/logic.ml8
-rw-r--r--proofs/pfedit.ml22
-rw-r--r--proofs/pfedit.mli4
-rw-r--r--proofs/proof_trees.ml25
-rw-r--r--proofs/proof_trees.mli4
-rw-r--r--proofs/proof_type.ml9
-rw-r--r--proofs/proof_type.mli11
-rw-r--r--proofs/refiner.ml122
-rw-r--r--proofs/refiner.mli10
-rw-r--r--tactics/auto.ml5
-rw-r--r--tactics/decl_interp.ml429
-rw-r--r--tactics/decl_interp.mli18
-rw-r--r--tactics/decl_proof_instr.ml1474
-rw-r--r--tactics/decl_proof_instr.mli118
-rw-r--r--tactics/evar_tactics.ml2
-rw-r--r--tactics/leminv.ml2
-rw-r--r--tactics/tacinterp.mli3
-rw-r--r--toplevel/vernacentries.ml65
-rw-r--r--toplevel/vernacexpr.ml9
56 files changed, 3796 insertions, 453 deletions
diff --git a/.depend b/.depend
index f0051f8771..35caa4d023 100644
--- a/.depend
+++ b/.depend
@@ -129,11 +129,12 @@ parsing/lexer.cmi: lib/util.cmi lib/pp.cmi
parsing/pcoq.cmi: toplevel/vernacexpr.cmo lib/util.cmi interp/topconstr.cmi \
proofs/tacexpr.cmo pretyping/rawterm.cmi kernel/names.cmi \
library/libnames.cmi interp/genarg.cmi parsing/extend.cmi \
- library/decl_kinds.cmo lib/bigint.cmi
+ library/decl_kinds.cmo proofs/decl_expr.cmi lib/bigint.cmi
parsing/ppconstr.cmi: lib/util.cmi interp/topconstr.cmi kernel/term.cmi \
proofs/tacexpr.cmo pretyping/rawterm.cmi interp/ppextend.cmi lib/pp.cmi \
parsing/pcoq.cmi kernel/names.cmi library/libnames.cmi interp/genarg.cmi \
kernel/environ.cmi
+parsing/ppdecl_proof.cmi: lib/pp.cmi kernel/environ.cmi proofs/decl_expr.cmi
parsing/pptactic.cmi: interp/topconstr.cmi kernel/term.cmi proofs/tacexpr.cmo \
pretyping/rawterm.cmi proofs/proof_type.cmi pretyping/pretyping.cmi \
interp/ppextend.cmi lib/pp.cmi library/libnames.cmi interp/genarg.cmi \
@@ -183,7 +184,7 @@ pretyping/evarutil.cmi: lib/util.cmi kernel/term.cmi kernel/sign.cmi \
kernel/names.cmi pretyping/evd.cmi kernel/environ.cmi
pretyping/evd.cmi: lib/util.cmi kernel/term.cmi kernel/sign.cmi \
kernel/reduction.cmi lib/pp.cmi kernel/names.cmi kernel/mod_subst.cmi \
- library/libnames.cmi kernel/environ.cmi
+ library/libnames.cmi kernel/environ.cmi lib/dyn.cmi
pretyping/indrec.cmi: kernel/term.cmi kernel/names.cmi \
pretyping/inductiveops.cmi pretyping/evd.cmi kernel/environ.cmi \
kernel/declarations.cmi
@@ -227,6 +228,12 @@ pretyping/vnorm.cmi: kernel/term.cmi kernel/reduction.cmi kernel/names.cmi \
proofs/clenvtac.cmi: lib/util.cmi kernel/term.cmi kernel/sign.cmi \
proofs/proof_type.cmi kernel/names.cmi pretyping/evd.cmi \
pretyping/clenv.cmi
+proofs/decl_expr.cmi: lib/util.cmi interp/topconstr.cmi kernel/term.cmi \
+ proofs/tacexpr.cmo pretyping/rawterm.cmi kernel/names.cmi \
+ interp/genarg.cmi
+proofs/decl_mode.cmi: kernel/term.cmi proofs/tacmach.cmi \
+ proofs/proof_type.cmi kernel/names.cmi pretyping/evd.cmi lib/dyn.cmi \
+ proofs/decl_expr.cmi
proofs/evar_refiner.cmi: interp/topconstr.cmi kernel/term.cmi \
proofs/refiner.cmi pretyping/rawterm.cmi kernel/names.cmi \
pretyping/evd.cmi kernel/environ.cmi
@@ -238,11 +245,11 @@ proofs/pfedit.cmi: lib/util.cmi interp/topconstr.cmi kernel/term.cmi \
library/decl_kinds.cmo
proofs/proof_trees.cmi: lib/util.cmi kernel/term.cmi kernel/sign.cmi \
proofs/proof_type.cmi lib/pp.cmi kernel/names.cmi pretyping/evd.cmi \
- kernel/environ.cmi
+ kernel/environ.cmi lib/dyn.cmi
proofs/proof_type.cmi: lib/util.cmi kernel/term.cmi proofs/tacexpr.cmo \
pretyping/rawterm.cmi pretyping/pattern.cmi library/nametab.cmi \
kernel/names.cmi library/libnames.cmi interp/genarg.cmi pretyping/evd.cmi \
- kernel/environ.cmi
+ kernel/environ.cmi proofs/decl_expr.cmi
proofs/redexpr.cmi: kernel/term.cmi pretyping/reductionops.cmi \
pretyping/rawterm.cmi kernel/names.cmi kernel/closure.cmi
proofs/refiner.cmi: pretyping/termops.cmi kernel/term.cmi proofs/tacexpr.cmo \
@@ -267,6 +274,13 @@ tactics/autorewrite.cmi: kernel/term.cmi tactics/tacticals.cmi \
tactics/btermdn.cmi: kernel/term.cmi pretyping/pattern.cmi
tactics/contradiction.cmi: kernel/term.cmi pretyping/rawterm.cmi \
proofs/proof_type.cmi kernel/names.cmi
+tactics/decl_interp.cmi: tactics/tacinterp.cmi kernel/mod_subst.cmi \
+ pretyping/evd.cmi kernel/environ.cmi proofs/decl_mode.cmi \
+ proofs/decl_expr.cmi
+tactics/decl_proof_instr.cmi: kernel/term.cmi proofs/tacmach.cmi \
+ proofs/refiner.cmi pretyping/rawterm.cmi proofs/proof_type.cmi \
+ kernel/names.cmi kernel/environ.cmi proofs/decl_mode.cmi \
+ proofs/decl_expr.cmi
tactics/dhyp.cmi: toplevel/vernacexpr.cmo interp/topconstr.cmi \
proofs/tacmach.cmi proofs/tacexpr.cmo kernel/names.cmi
tactics/eauto.cmi: interp/topconstr.cmi kernel/term.cmi proofs/tacexpr.cmo \
@@ -545,13 +559,13 @@ ide/config_parser.cmx: lib/util.cmx ide/config_parser.cmi
ide/coqide.cmo: toplevel/vernacexpr.cmo lib/util.cmi ide/undo.cmi \
lib/system.cmi ide/preferences.cmi lib/pp.cmi proofs/pfedit.cmi \
ide/ideutils.cmi ide/highlight.cmo ide/find_phrase.cmo \
- config/coq_config.cmi ide/coq_commands.cmo ide/coq.cmi \
- ide/command_windows.cmi ide/blaster_window.cmo ide/coqide.cmi
+ proofs/decl_mode.cmi config/coq_config.cmi ide/coq_commands.cmo \
+ ide/coq.cmi ide/command_windows.cmi ide/blaster_window.cmo ide/coqide.cmi
ide/coqide.cmx: toplevel/vernacexpr.cmx lib/util.cmx ide/undo.cmx \
lib/system.cmx ide/preferences.cmx lib/pp.cmx proofs/pfedit.cmx \
ide/ideutils.cmx ide/highlight.cmx ide/find_phrase.cmx \
- config/coq_config.cmx ide/coq_commands.cmx ide/coq.cmx \
- ide/command_windows.cmx ide/blaster_window.cmx ide/coqide.cmi
+ proofs/decl_mode.cmx config/coq_config.cmx ide/coq_commands.cmx \
+ ide/coq.cmx ide/command_windows.cmx ide/blaster_window.cmx ide/coqide.cmi
ide/coq.cmo: toplevel/vernacexpr.cmo toplevel/vernacentries.cmi \
toplevel/vernac.cmi lib/util.cmi pretyping/termops.cmi kernel/term.cmi \
proofs/tacmach.cmi tactics/tacinterp.cmi lib/system.cmi \
@@ -561,8 +575,8 @@ ide/coq.cmo: toplevel/vernacexpr.cmo toplevel/vernacentries.cmi \
library/library.cmi library/libnames.cmi library/lib.cmi ide/ideutils.cmi \
tactics/hipattern.cmi library/goptions.cmi library/global.cmi \
pretyping/evd.cmi pretyping/evarutil.cmi kernel/environ.cmi \
- kernel/declarations.cmi toplevel/coqtop.cmi config/coq_config.cmi \
- toplevel/cerrors.cmi ide/coq.cmi
+ kernel/declarations.cmi proofs/decl_mode.cmi toplevel/coqtop.cmi \
+ config/coq_config.cmi toplevel/cerrors.cmi ide/coq.cmi
ide/coq.cmx: toplevel/vernacexpr.cmx toplevel/vernacentries.cmx \
toplevel/vernac.cmx lib/util.cmx pretyping/termops.cmx kernel/term.cmx \
proofs/tacmach.cmx tactics/tacinterp.cmx lib/system.cmx \
@@ -572,8 +586,8 @@ ide/coq.cmx: toplevel/vernacexpr.cmx toplevel/vernacentries.cmx \
library/library.cmx library/libnames.cmx library/lib.cmx ide/ideutils.cmx \
tactics/hipattern.cmx library/goptions.cmx library/global.cmx \
pretyping/evd.cmx pretyping/evarutil.cmx kernel/environ.cmx \
- kernel/declarations.cmx toplevel/coqtop.cmx config/coq_config.cmx \
- toplevel/cerrors.cmx ide/coq.cmi
+ kernel/declarations.cmx proofs/decl_mode.cmx toplevel/coqtop.cmx \
+ config/coq_config.cmx toplevel/cerrors.cmx ide/coq.cmi
ide/coq_tactics.cmo: ide/coq_tactics.cmi
ide/coq_tactics.cmx: ide/coq_tactics.cmi
ide/find_phrase.cmo: ide/ideutils.cmi
@@ -1050,6 +1064,12 @@ parsing/g_constr.cmo: lib/util.cmi interp/topconstr.cmi kernel/term.cmi \
parsing/g_constr.cmx: lib/util.cmx interp/topconstr.cmx kernel/term.cmx \
pretyping/rawterm.cmx lib/pp.cmx parsing/pcoq.cmx kernel/names.cmx \
library/libnames.cmx parsing/lexer.cmx lib/bigint.cmx
+parsing/g_decl_mode.cmo: interp/topconstr.cmi kernel/term.cmi \
+ parsing/pcoq.cmi kernel/names.cmi library/libnames.cmi interp/genarg.cmi \
+ proofs/decl_expr.cmi
+parsing/g_decl_mode.cmx: interp/topconstr.cmx kernel/term.cmx \
+ parsing/pcoq.cmx kernel/names.cmx library/libnames.cmx interp/genarg.cmx \
+ proofs/decl_expr.cmi
parsing/g_ltac.cmo: toplevel/vernacexpr.cmo lib/util.cmi interp/topconstr.cmi \
proofs/tacexpr.cmo pretyping/rawterm.cmi lib/pp.cmi parsing/pcoq.cmi \
kernel/names.cmi
@@ -1109,13 +1129,13 @@ parsing/g_vernac.cmo: toplevel/vernacexpr.cmo lib/util.cmi \
lib/pp.cmi parsing/pcoq.cmi lib/options.cmi kernel/names.cmi \
library/nameops.cmi parsing/lexer.cmi library/goptions.cmi \
interp/genarg.cmi parsing/g_constr.cmo parsing/extend.cmi \
- library/decl_kinds.cmo toplevel/class.cmi
+ proofs/decl_mode.cmi library/decl_kinds.cmo toplevel/class.cmi
parsing/g_vernac.cmx: toplevel/vernacexpr.cmx lib/util.cmx \
interp/topconstr.cmx pretyping/recordops.cmx interp/ppextend.cmx \
lib/pp.cmx parsing/pcoq.cmx lib/options.cmx kernel/names.cmx \
library/nameops.cmx parsing/lexer.cmx library/goptions.cmx \
interp/genarg.cmx parsing/g_constr.cmx parsing/extend.cmx \
- library/decl_kinds.cmx toplevel/class.cmx
+ proofs/decl_mode.cmx library/decl_kinds.cmx toplevel/class.cmx
parsing/g_xml.cmo: lib/util.cmi kernel/term.cmi proofs/tacexpr.cmo \
pretyping/rawterm.cmi lib/pp.cmi parsing/pcoq.cmi library/nametab.cmi \
kernel/names.cmi library/libnames.cmi pretyping/inductiveops.cmi \
@@ -1158,6 +1178,14 @@ parsing/ppconstr.cmx: lib/util.cmx kernel/univ.cmx interp/topconstr.cmx \
library/nameops.cmx library/libnames.cmx interp/genarg.cmx \
pretyping/evd.cmx interp/constrextern.cmx lib/bigint.cmx \
parsing/ppconstr.cmi
+parsing/ppdecl_proof.cmo: lib/util.cmi kernel/term.cmi parsing/printer.cmi \
+ parsing/pptactic.cmi parsing/ppconstr.cmi lib/pp.cmi kernel/names.cmi \
+ library/nameops.cmi kernel/environ.cmi proofs/decl_expr.cmi \
+ parsing/ppdecl_proof.cmi
+parsing/ppdecl_proof.cmx: lib/util.cmx kernel/term.cmx parsing/printer.cmx \
+ parsing/pptactic.cmx parsing/ppconstr.cmx lib/pp.cmx kernel/names.cmx \
+ library/nameops.cmx kernel/environ.cmx proofs/decl_expr.cmi \
+ parsing/ppdecl_proof.cmi
parsing/pptactic.cmo: lib/util.cmi interp/topconstr.cmi pretyping/termops.cmi \
kernel/term.cmi proofs/tactic_debug.cmi proofs/tacexpr.cmo \
pretyping/rawterm.cmi parsing/printer.cmi interp/ppextend.cmi \
@@ -1216,14 +1244,14 @@ parsing/printer.cmo: lib/util.cmi pretyping/termops.cmi kernel/term.cmi \
library/nametab.cmi kernel/names.cmi library/nameops.cmi \
library/libnames.cmi library/global.cmi pretyping/evd.cmi \
pretyping/evarutil.cmi kernel/environ.cmi library/declare.cmi \
- interp/constrextern.cmi parsing/printer.cmi
+ proofs/decl_mode.cmi interp/constrextern.cmi parsing/printer.cmi
parsing/printer.cmx: lib/util.cmx pretyping/termops.cmx kernel/term.cmx \
kernel/sign.cmx proofs/refiner.cmx proofs/proof_type.cmx \
parsing/ppconstr.cmx lib/pp.cmx proofs/pfedit.cmx lib/options.cmx \
library/nametab.cmx kernel/names.cmx library/nameops.cmx \
library/libnames.cmx library/global.cmx pretyping/evd.cmx \
pretyping/evarutil.cmx kernel/environ.cmx library/declare.cmx \
- interp/constrextern.cmx parsing/printer.cmi
+ proofs/decl_mode.cmx interp/constrextern.cmx parsing/printer.cmi
parsing/printmod.cmo: lib/util.cmi lib/pp.cmi library/nametab.cmi \
kernel/names.cmi library/nameops.cmi library/libnames.cmi \
library/global.cmi kernel/declarations.cmi parsing/printmod.cmi
@@ -1268,14 +1296,14 @@ parsing/tacextend.cmx: lib/util.cmx parsing/q_util.cmx parsing/q_coqast.cmx \
parsing/argextend.cmx
parsing/tactic_printer.cmo: lib/util.cmi proofs/tacexpr.cmo kernel/sign.cmi \
proofs/refiner.cmi proofs/proof_type.cmi proofs/proof_trees.cmi \
- parsing/printer.cmi parsing/pptactic.cmi lib/pp.cmi proofs/logic.cmi \
- library/global.cmi pretyping/evd.cmi kernel/environ.cmi \
- parsing/tactic_printer.cmi
+ parsing/printer.cmi parsing/pptactic.cmi parsing/ppdecl_proof.cmi \
+ lib/pp.cmi proofs/logic.cmi library/global.cmi pretyping/evd.cmi \
+ kernel/environ.cmi proofs/decl_expr.cmi parsing/tactic_printer.cmi
parsing/tactic_printer.cmx: lib/util.cmx proofs/tacexpr.cmx kernel/sign.cmx \
proofs/refiner.cmx proofs/proof_type.cmx proofs/proof_trees.cmx \
- parsing/printer.cmx parsing/pptactic.cmx lib/pp.cmx proofs/logic.cmx \
- library/global.cmx pretyping/evd.cmx kernel/environ.cmx \
- parsing/tactic_printer.cmi
+ parsing/printer.cmx parsing/pptactic.cmx parsing/ppdecl_proof.cmx \
+ lib/pp.cmx proofs/logic.cmx library/global.cmx pretyping/evd.cmx \
+ kernel/environ.cmx proofs/decl_expr.cmi parsing/tactic_printer.cmi
parsing/vernacextend.cmo: lib/util.cmi parsing/q_util.cmi \
parsing/q_coqast.cmo lib/pp_control.cmi lib/pp.cmi interp/genarg.cmi \
parsing/argextend.cmo
@@ -1389,12 +1417,12 @@ pretyping/evarutil.cmx: lib/util.cmx kernel/univ.cmx pretyping/typing.cmx \
pretyping/evd.cmo: lib/util.cmi kernel/univ.cmi pretyping/termops.cmi \
kernel/term.cmi kernel/sign.cmi kernel/reduction.cmi lib/pp.cmi \
kernel/names.cmi library/nameops.cmi kernel/mod_subst.cmi \
- library/libnames.cmi library/global.cmi kernel/environ.cmi \
+ library/libnames.cmi library/global.cmi kernel/environ.cmi lib/dyn.cmi \
pretyping/evd.cmi
pretyping/evd.cmx: lib/util.cmx kernel/univ.cmx pretyping/termops.cmx \
kernel/term.cmx kernel/sign.cmx kernel/reduction.cmx lib/pp.cmx \
kernel/names.cmx library/nameops.cmx kernel/mod_subst.cmx \
- library/libnames.cmx library/global.cmx kernel/environ.cmx \
+ library/libnames.cmx library/global.cmx kernel/environ.cmx lib/dyn.cmx \
pretyping/evd.cmi
pretyping/indrec.cmo: lib/util.cmi kernel/typeops.cmi kernel/type_errors.cmi \
pretyping/termops.cmi kernel/term.cmi kernel/sign.cmi \
@@ -1580,6 +1608,12 @@ proofs/clenvtac.cmx: lib/util.cmx pretyping/unification.cmx \
proofs/logic.cmx pretyping/evd.cmx pretyping/evarutil.cmx \
proofs/evar_refiner.cmx kernel/environ.cmx pretyping/clenv.cmx \
proofs/clenvtac.cmi
+proofs/decl_mode.cmo: lib/util.cmi kernel/term.cmi proofs/refiner.cmi \
+ proofs/proof_trees.cmi proofs/pfedit.cmi kernel/names.cmi \
+ pretyping/evd.cmi lib/dyn.cmi proofs/decl_expr.cmi proofs/decl_mode.cmi
+proofs/decl_mode.cmx: lib/util.cmx kernel/term.cmx proofs/refiner.cmx \
+ proofs/proof_trees.cmx proofs/pfedit.cmx kernel/names.cmx \
+ pretyping/evd.cmx lib/dyn.cmx proofs/decl_expr.cmi proofs/decl_mode.cmi
proofs/evar_refiner.cmo: lib/util.cmi kernel/term.cmi kernel/sign.cmi \
proofs/refiner.cmi proofs/proof_trees.cmi pretyping/pretyping.cmi \
kernel/names.cmi pretyping/evd.cmi pretyping/evarutil.cmi \
@@ -1623,21 +1657,23 @@ proofs/proof_trees.cmo: lib/util.cmi pretyping/typing.cmi \
kernel/sign.cmi proofs/proof_type.cmi lib/pp.cmi library/nametab.cmi \
kernel/names.cmi library/nameops.cmi library/libnames.cmi \
pretyping/evd.cmi pretyping/evarutil.cmi kernel/environ.cmi \
- pretyping/detyping.cmi kernel/closure.cmi proofs/proof_trees.cmi
+ pretyping/detyping.cmi proofs/decl_expr.cmi kernel/closure.cmi \
+ proofs/proof_trees.cmi
proofs/proof_trees.cmx: lib/util.cmx pretyping/typing.cmx \
pretyping/termops.cmx kernel/term.cmx pretyping/tacred.cmx \
kernel/sign.cmx proofs/proof_type.cmx lib/pp.cmx library/nametab.cmx \
kernel/names.cmx library/nameops.cmx library/libnames.cmx \
pretyping/evd.cmx pretyping/evarutil.cmx kernel/environ.cmx \
- pretyping/detyping.cmx kernel/closure.cmx proofs/proof_trees.cmi
+ pretyping/detyping.cmx proofs/decl_expr.cmi kernel/closure.cmx \
+ proofs/proof_trees.cmi
proofs/proof_type.cmo: lib/util.cmi kernel/term.cmi proofs/tacexpr.cmo \
pretyping/rawterm.cmi pretyping/pattern.cmi library/nametab.cmi \
kernel/names.cmi library/libnames.cmi interp/genarg.cmi pretyping/evd.cmi \
- kernel/environ.cmi proofs/proof_type.cmi
+ kernel/environ.cmi proofs/decl_expr.cmi proofs/proof_type.cmi
proofs/proof_type.cmx: lib/util.cmx kernel/term.cmx proofs/tacexpr.cmx \
pretyping/rawterm.cmx pretyping/pattern.cmx library/nametab.cmx \
kernel/names.cmx library/libnames.cmx interp/genarg.cmx pretyping/evd.cmx \
- kernel/environ.cmx proofs/proof_type.cmi
+ kernel/environ.cmx proofs/decl_expr.cmi proofs/proof_type.cmi
proofs/redexpr.cmo: pretyping/vnorm.cmi lib/util.cmi kernel/typeops.cmi \
kernel/term.cmi pretyping/tacred.cmi library/summary.cmi \
pretyping/reductionops.cmi pretyping/rawterm.cmi lib/pp.cmi \
@@ -1754,6 +1790,46 @@ tactics/contradiction.cmx: lib/util.cmx kernel/term.cmx tactics/tactics.cmx \
tactics/tacticals.cmx proofs/tacmach.cmx pretyping/reductionops.cmx \
pretyping/rawterm.cmx proofs/proof_type.cmx tactics/hipattern.cmx \
interp/coqlib.cmx tactics/contradiction.cmi
+tactics/decl_interp.cmo: lib/util.cmi interp/topconstr.cmi \
+ pretyping/termops.cmi kernel/term.cmi proofs/tacmach.cmi \
+ tactics/tacinterp.cmi pretyping/rawterm.cmi pretyping/pretyping.cmi \
+ lib/pp.cmi kernel/names.cmi library/nameops.cmi library/libnames.cmi \
+ library/global.cmi pretyping/evd.cmi kernel/environ.cmi \
+ pretyping/detyping.cmi kernel/declarations.cmi proofs/decl_mode.cmi \
+ proofs/decl_expr.cmi interp/coqlib.cmi interp/constrintern.cmi \
+ kernel/closure.cmi tactics/decl_interp.cmi
+tactics/decl_interp.cmx: lib/util.cmx interp/topconstr.cmx \
+ pretyping/termops.cmx kernel/term.cmx proofs/tacmach.cmx \
+ tactics/tacinterp.cmx pretyping/rawterm.cmx pretyping/pretyping.cmx \
+ lib/pp.cmx kernel/names.cmx library/nameops.cmx library/libnames.cmx \
+ library/global.cmx pretyping/evd.cmx kernel/environ.cmx \
+ pretyping/detyping.cmx kernel/declarations.cmx proofs/decl_mode.cmx \
+ proofs/decl_expr.cmi interp/coqlib.cmx interp/constrintern.cmx \
+ kernel/closure.cmx tactics/decl_interp.cmi
+tactics/decl_proof_instr.cmo: lib/util.cmi pretyping/unification.cmi \
+ pretyping/termops.cmi kernel/term.cmi tactics/tactics.cmi \
+ tactics/tacticals.cmi proofs/tacmach.cmi tactics/tacinterp.cmi \
+ proofs/tacexpr.cmo proofs/refiner.cmi pretyping/reductionops.cmi \
+ kernel/reduction.cmi pretyping/rawterm.cmi proofs/proof_type.cmi \
+ proofs/proof_trees.cmi parsing/printer.cmi lib/pp.cmi proofs/pfedit.cmi \
+ kernel/names.cmi library/nameops.cmi library/libnames.cmi \
+ pretyping/inductiveops.cmi kernel/inductive.cmi library/goptions.cmi \
+ library/global.cmi interp/genarg.cmi pretyping/evd.cmi kernel/environ.cmi \
+ kernel/declarations.cmi proofs/decl_mode.cmi tactics/decl_interp.cmi \
+ proofs/decl_expr.cmi interp/coqlib.cmi kernel/closure.cmi \
+ tactics/decl_proof_instr.cmi
+tactics/decl_proof_instr.cmx: lib/util.cmx pretyping/unification.cmx \
+ pretyping/termops.cmx kernel/term.cmx tactics/tactics.cmx \
+ tactics/tacticals.cmx proofs/tacmach.cmx tactics/tacinterp.cmx \
+ proofs/tacexpr.cmx proofs/refiner.cmx pretyping/reductionops.cmx \
+ kernel/reduction.cmx pretyping/rawterm.cmx proofs/proof_type.cmx \
+ proofs/proof_trees.cmx parsing/printer.cmx lib/pp.cmx proofs/pfedit.cmx \
+ kernel/names.cmx library/nameops.cmx library/libnames.cmx \
+ pretyping/inductiveops.cmx kernel/inductive.cmx library/goptions.cmx \
+ library/global.cmx interp/genarg.cmx pretyping/evd.cmx kernel/environ.cmx \
+ kernel/declarations.cmx proofs/decl_mode.cmx tactics/decl_interp.cmx \
+ proofs/decl_expr.cmi interp/coqlib.cmx kernel/closure.cmx \
+ tactics/decl_proof_instr.cmi
tactics/dhyp.cmo: lib/util.cmi kernel/term.cmi tactics/tactics.cmi \
tactics/tacticals.cmi proofs/tacmach.cmi proofs/tacexpr.cmo \
library/summary.cmi proofs/refiner.cmi kernel/reduction.cmi \
@@ -2327,10 +2403,10 @@ toplevel/vernacentries.cmo: kernel/vm.cmi toplevel/vernacinterp.cmi \
library/impargs.cmi library/goptions.cmi library/global.cmi \
pretyping/evd.cmi pretyping/evarutil.cmi kernel/environ.cmi \
kernel/entries.cmi pretyping/detyping.cmi library/declaremods.cmi \
- kernel/declarations.cmi library/decl_kinds.cmo interp/constrintern.cmi \
- interp/constrextern.cmi toplevel/command.cmi pretyping/classops.cmi \
- toplevel/class.cmi tactics/autorewrite.cmi tactics/auto.cmi \
- toplevel/vernacentries.cmi
+ kernel/declarations.cmi tactics/decl_proof_instr.cmi proofs/decl_mode.cmi \
+ library/decl_kinds.cmo interp/constrintern.cmi interp/constrextern.cmi \
+ toplevel/command.cmi pretyping/classops.cmi toplevel/class.cmi \
+ tactics/autorewrite.cmi tactics/auto.cmi toplevel/vernacentries.cmi
toplevel/vernacentries.cmx: kernel/vm.cmx toplevel/vernacinterp.cmx \
toplevel/vernacexpr.cmx kernel/vconv.cmx lib/util.cmx kernel/univ.cmx \
kernel/typeops.cmx interp/topconstr.cmx pretyping/termops.cmx \
@@ -2350,18 +2426,20 @@ toplevel/vernacentries.cmx: kernel/vm.cmx toplevel/vernacinterp.cmx \
library/impargs.cmx library/goptions.cmx library/global.cmx \
pretyping/evd.cmx pretyping/evarutil.cmx kernel/environ.cmx \
kernel/entries.cmx pretyping/detyping.cmx library/declaremods.cmx \
- kernel/declarations.cmx library/decl_kinds.cmx interp/constrintern.cmx \
- interp/constrextern.cmx toplevel/command.cmx pretyping/classops.cmx \
- toplevel/class.cmx tactics/autorewrite.cmx tactics/auto.cmx \
- toplevel/vernacentries.cmi
+ kernel/declarations.cmx tactics/decl_proof_instr.cmx proofs/decl_mode.cmx \
+ library/decl_kinds.cmx interp/constrintern.cmx interp/constrextern.cmx \
+ toplevel/command.cmx pretyping/classops.cmx toplevel/class.cmx \
+ tactics/autorewrite.cmx tactics/auto.cmx toplevel/vernacentries.cmi
toplevel/vernacexpr.cmo: lib/util.cmi interp/topconstr.cmi proofs/tacexpr.cmo \
pretyping/rawterm.cmi interp/ppextend.cmi library/nametab.cmi \
kernel/names.cmi library/libnames.cmi library/goptions.cmi \
- interp/genarg.cmi parsing/extend.cmi library/decl_kinds.cmo
+ interp/genarg.cmi parsing/extend.cmi library/decl_kinds.cmo \
+ proofs/decl_expr.cmi
toplevel/vernacexpr.cmx: lib/util.cmx interp/topconstr.cmx proofs/tacexpr.cmx \
pretyping/rawterm.cmx interp/ppextend.cmx library/nametab.cmx \
kernel/names.cmx library/libnames.cmx library/goptions.cmx \
- interp/genarg.cmx parsing/extend.cmx library/decl_kinds.cmx
+ interp/genarg.cmx parsing/extend.cmx library/decl_kinds.cmx \
+ proofs/decl_expr.cmi
toplevel/vernacinterp.cmo: toplevel/vernacexpr.cmo lib/util.cmi \
tactics/tacinterp.cmi proofs/tacexpr.cmo proofs/proof_type.cmi lib/pp.cmi \
lib/options.cmi kernel/names.cmi library/libnames.cmi toplevel/himsg.cmi \
@@ -2774,14 +2852,16 @@ contrib/first-order/g_ground.cmo: lib/util.cmi kernel/term.cmi \
parsing/pptactic.cmi lib/pp.cmi parsing/pcoq.cmi kernel/names.cmi \
library/libnames.cmi contrib/first-order/ground.cmi library/goptions.cmi \
interp/genarg.cmi contrib/first-order/formula.cmi parsing/egrammar.cmi \
- toplevel/cerrors.cmi tactics/auto.cmi
+ tactics/decl_proof_instr.cmi toplevel/cerrors.cmi contrib/cc/cctac.cmi \
+ tactics/auto.cmi
contrib/first-order/g_ground.cmx: lib/util.cmx kernel/term.cmx \
tactics/tactics.cmx tactics/tacticals.cmx tactics/tacinterp.cmx \
proofs/tacexpr.cmx contrib/first-order/sequent.cmx proofs/refiner.cmx \
parsing/pptactic.cmx lib/pp.cmx parsing/pcoq.cmx kernel/names.cmx \
library/libnames.cmx contrib/first-order/ground.cmx library/goptions.cmx \
interp/genarg.cmx contrib/first-order/formula.cmx parsing/egrammar.cmx \
- toplevel/cerrors.cmx tactics/auto.cmx
+ tactics/decl_proof_instr.cmx toplevel/cerrors.cmx contrib/cc/cctac.cmx \
+ tactics/auto.cmx
contrib/first-order/ground.cmo: kernel/term.cmi tactics/tactics.cmi \
tactics/tacticals.cmi proofs/tactic_debug.cmi proofs/tacmach.cmi \
tactics/tacinterp.cmi contrib/first-order/sequent.cmi \
@@ -4006,6 +4086,8 @@ parsing/vernacextend.cmo:
parsing/vernacextend.cmx:
parsing/q_constr.cmo:
parsing/q_constr.cmx:
+parsing/g_decl_mode.cmo: parsing/grammar.cma
+parsing/g_decl_mode.cmx: parsing/grammar.cma
toplevel/mltop.cmo:
toplevel/mltop.cmx:
lib/pp.cmo:
diff --git a/.depend.camlp4 b/.depend.camlp4
index e1a671bc49..895c785750 100644
--- a/.depend.camlp4
+++ b/.depend.camlp4
@@ -42,6 +42,7 @@ parsing/argextend.ml:
parsing/tacextend.ml:
parsing/vernacextend.ml:
parsing/q_constr.ml:
+parsing/g_decl_mode.ml: parsing/grammar.cma
toplevel/mltop.ml:
lib/pp.ml:
lib/compat.ml:
diff --git a/Makefile b/Makefile
index 2e2eef1bf7..1369e8109d 100644
--- a/Makefile
+++ b/Makefile
@@ -73,6 +73,9 @@ LOCALINCLUDES=-I config -I tools -I tools/coqdoc \
MLINCLUDES=$(LOCALINCLUDES) -I $(MYCAMLP4LIB)
+OCAMLC += $(CAMLFLAGS)
+OCAMLOPT += $(CAMLFLAGS)
+
BYTEFLAGS=$(MLINCLUDES) $(CAMLDEBUG) $(USERFLAGS)
OPTFLAGS=$(MLINCLUDES) $(CAMLTIMEPROF) $(USERFLAGS)
DEPFLAGS=$(LOCALINCLUDES)
@@ -162,20 +165,21 @@ PROOFS=\
proofs/proof_trees.cmo proofs/logic.cmo \
proofs/refiner.cmo proofs/evar_refiner.cmo proofs/tacmach.cmo \
proofs/pfedit.cmo proofs/tactic_debug.cmo \
- proofs/clenvtac.cmo
+ proofs/clenvtac.cmo proofs/decl_mode.cmo
PARSING=\
parsing/extend.cmo \
parsing/pcoq.cmo parsing/egrammar.cmo parsing/g_xml.cmo \
parsing/ppconstr.cmo parsing/printer.cmo \
- parsing/pptactic.cmo parsing/tactic_printer.cmo \
+ parsing/pptactic.cmo parsing/ppdecl_proof.cmo parsing/tactic_printer.cmo \
parsing/printmod.cmo parsing/prettyp.cmo parsing/search.cmo
HIGHPARSING=\
parsing/g_constr.cmo parsing/g_vernac.cmo parsing/g_prim.cmo \
parsing/g_proofs.cmo parsing/g_tactic.cmo parsing/g_ltac.cmo \
parsing/g_natsyntax.cmo parsing/g_zsyntax.cmo parsing/g_rsyntax.cmo \
- parsing/g_ascii_syntax.cmo parsing/g_string_syntax.cmo
+ parsing/g_ascii_syntax.cmo parsing/g_string_syntax.cmo \
+ parsing/g_decl_mode.cmo
TACTICS=\
tactics/dn.cmo tactics/termdn.cmo tactics/btermdn.cmo \
@@ -186,11 +190,12 @@ TACTICS=\
tactics/dhyp.cmo tactics/auto.cmo \
tactics/setoid_replace.cmo tactics/equality.cmo \
tactics/contradiction.cmo tactics/inv.cmo tactics/leminv.cmo \
- tactics/tacinterp.cmo tactics/autorewrite.cmo
+ tactics/tacinterp.cmo tactics/autorewrite.cmo \
+ tactics/decl_interp.cmo tactics/decl_proof_instr.cmo
TOPLEVEL=\
toplevel/himsg.cmo toplevel/cerrors.cmo toplevel/class.cmo \
- toplevel/vernacexpr.cmo toplevel/metasyntax.cmo \
+ toplevel/vernacexpr.cmo toplevel/metasyntax.cmo \
toplevel/command.cmo toplevel/record.cmo \
parsing/ppvernac.cmo \
toplevel/vernacinterp.cmo toplevel/mltop.cmo \
@@ -1398,7 +1403,7 @@ GRAMMARNEEDEDCMO=\
proofs/tacexpr.cmo \
parsing/lexer.cmo parsing/extend.cmo \
toplevel/vernacexpr.cmo parsing/pcoq.cmo parsing/q_util.cmo \
- parsing/q_coqast.cmo
+ parsing/q_coqast.cmo
CAMLP4EXTENSIONSCMO=\
parsing/argextend.cmo parsing/tacextend.cmo parsing/vernacextend.cmo
@@ -1438,9 +1443,12 @@ PRINTERSCMO=\
interp/constrextern.cmo interp/syntax_def.cmo interp/constrintern.cmo \
proofs/proof_trees.cmo proofs/logic.cmo proofs/refiner.cmo \
proofs/tacexpr.cmo \
- proofs/evar_refiner.cmo proofs/pfedit.cmo proofs/tactic_debug.cmo \
+ proofs/evar_refiner.cmo proofs/pfedit.cmo proofs/tactic_debug.cmo \
+ proofs/decl_mode.cmo \
parsing/ppconstr.cmo parsing/extend.cmo parsing/pcoq.cmo \
- parsing/printer.cmo parsing/pptactic.cmo parsing/tactic_printer.cmo \
+ parsing/printer.cmo parsing/pptactic.cmo \
+ parsing/ppdecl_proof.cmo \
+ parsing/tactic_printer.cmo \
parsing/egrammar.cmo toplevel/himsg.cmo \
toplevel/cerrors.cmo toplevel/vernacexpr.cmo toplevel/vernacinterp.cmo \
dev/top_printers.cmo
@@ -1468,7 +1476,9 @@ ML4FILES +=parsing/g_minicoq.ml4 \
parsing/g_xml.ml4 parsing/g_constr.ml4 \
parsing/g_tactic.ml4 parsing/g_ltac.ml4 \
parsing/argextend.ml4 parsing/tacextend.ml4 \
- parsing/vernacextend.ml4 parsing/q_constr.ml4
+ parsing/vernacextend.ml4 parsing/q_constr.ml4 \
+ parsing/g_decl_mode.ml4
+
# beforedepend:: $(GRAMMARCMO)
diff --git a/contrib/first-order/formula.ml b/contrib/first-order/formula.ml
index 4e256981fc..fe41b96cbb 100644
--- a/contrib/first-order/formula.ml
+++ b/contrib/first-order/formula.ml
@@ -46,7 +46,6 @@ let rec nb_prod_after n c=
| _ -> 0
let construct_nhyps ind gls =
- let env=pf_env gls in
let nparams = (fst (Global.lookup_inductive ind)).mind_nparams in
let constr_types = Inductiveops.arities_of_constructors (pf_env gls) ind in
let hyp = nb_prod_after nparams in
diff --git a/contrib/first-order/g_ground.ml4 b/contrib/first-order/g_ground.ml4
index 451ac33d8c..39ab02cc14 100644
--- a/contrib/first-order/g_ground.ml4
+++ b/contrib/first-order/g_ground.ml4
@@ -24,7 +24,7 @@ open Libnames
(* declaring search depth as a global option *)
-let ground_depth=ref 5
+let ground_depth=ref 3
let _=
let gdopt=
@@ -34,13 +34,28 @@ let _=
optread=(fun ()->Some !ground_depth);
optwrite=
(function
- None->ground_depth:=5
+ None->ground_depth:=3
| Some i->ground_depth:=(max i 0))}
in
declare_int_option gdopt
-
+
+let congruence_depth=ref 100
+
+let _=
+ let gdopt=
+ { optsync=true;
+ optname="Congruence Depth";
+ optkey=SecondaryTable("Congruence","Depth");
+ optread=(fun ()->Some !congruence_depth);
+ optwrite=
+ (function
+ None->congruence_depth:=0
+ | Some i->congruence_depth:=(max i 0))}
+ in
+ declare_int_option gdopt
+
let default_solver=(Tacinterp.interp <:tactic<auto with *>>)
-
+
let fail_solver=tclFAIL 0 (Pp.str "GTauto failed")
type external_env=
@@ -94,3 +109,19 @@ TACTIC EXTEND gintuition
[ "gintuition" tactic_opt(t) ] ->
[ gen_ground_tac false (option_map eval_tactic t) Void ]
END
+
+
+let default_declarative_automation gls =
+ tclORELSE
+ (Cctac.congruence_tac !congruence_depth [])
+ (gen_ground_tac true
+ (Some (tclTHEN
+ default_solver
+ (Cctac.congruence_tac !congruence_depth [])))
+ Void) gls
+
+
+
+let () =
+ Decl_proof_instr.register_automation_tac default_declarative_automation
+
diff --git a/contrib/funind/tacinvutils.ml b/contrib/funind/tacinvutils.ml
index 2877c19db9..ce775e0bee 100644
--- a/contrib/funind/tacinvutils.ml
+++ b/contrib/funind/tacinvutils.ml
@@ -72,10 +72,11 @@ let rec mkevarmap_from_listex lex =
let _ = prstr ("evar n. " ^ string_of_int ex ^ " ") in
let _ = prstr "OF TYPE: " in
let _ = prconstr typ in*)
- let info ={
+ let info = {
evar_concl = typ;
evar_hyps = empty_named_context_val;
- evar_body = Evar_empty} in
+ evar_body = Evar_empty;
+ evar_extra = None} in
Evd.add (mkevarmap_from_listex lex') ex info
let mkEq typ c1 c2 =
diff --git a/contrib/interface/showproof.ml b/contrib/interface/showproof.ml
index ce2ee1e7da..bec24af1be 100644
--- a/contrib/interface/showproof.ml
+++ b/contrib/interface/showproof.ml
@@ -156,16 +156,16 @@ let seq_to_lnhyp sign sign' cl =
let rule_is_complex r =
match r with
- Tactic (TacArg (Tacexp t),_) -> true
- | Tactic (TacAtom (_,TacAuto _), _) -> true
- | Tactic (TacAtom (_,TacSymmetry _), _) -> true
+ Nested (Tactic
+ (TacArg (Tacexp _)
+ |TacAtom (_,(TacAuto _|TacSymmetry _))),_) -> true
|_ -> false
;;
let rule_to_ntactic r =
let rt =
(match r with
- Tactic (t,_) -> t
+ Nested(Tactic t,_) -> t
| Prim (Refine h) -> TacAtom (dummy_loc,TacExact h)
| _ -> TacAtom (dummy_loc, TacIntroPattern [])) in
if rule_is_complex r
@@ -234,17 +234,17 @@ let to_nproof sigma osign pf =
(List.map (fun x -> (to_nproof_rec sigma sign x).t_proof)
spfl) in
(match r with
- Tactic (TacAtom (_, TacAuto _),_) ->
- if spfl=[]
- then
- {t_info="to_prove";
- t_goal= {newhyp=[];
- t_concl=concl ntree;
- t_full_concl=ntree.t_goal.t_full_concl;
- t_full_env=ntree.t_goal.t_full_env};
- t_proof= Proof (TacAtom (dummy_loc,TacExtend (dummy_loc,"InfoAuto",[])), [ntree])}
- else ntree
- | _ -> ntree))
+ Nested(Tactic (TacAtom (_, TacAuto _)),_) ->
+ if spfl=[]
+ then
+ {t_info="to_prove";
+ t_goal= {newhyp=[];
+ t_concl=concl ntree;
+ t_full_concl=ntree.t_goal.t_full_concl;
+ t_full_env=ntree.t_goal.t_full_env};
+ t_proof= Proof (TacAtom (dummy_loc,TacExtend (dummy_loc,"InfoAuto",[])), [ntree])}
+ else ntree
+ | _ -> ntree))
else
{t_info="to_prove";
t_goal=(seq_to_lnhyp oldsign nsign cl);
diff --git a/contrib/interface/xlate.ml b/contrib/interface/xlate.ml
index 88a9014eec..292a428739 100644
--- a/contrib/interface/xlate.ml
+++ b/contrib/interface/xlate.ml
@@ -1641,6 +1641,15 @@ let rec xlate_vernac =
CT_solve (CT_int n, xlate_tactic tac,
if b then CT_dotdot
else CT_coerce_NONE_to_DOTDOT_OPT CT_none)
+
+(* MMode *)
+
+ | (VernacDeclProof | VernacReturn | VernacProofInstr _) ->
+ anomaly "No MMode in CTcoq"
+
+
+(* /MMode *)
+
| VernacFocus nopt -> CT_focus (xlate_int_opt nopt)
| VernacUnfocus -> CT_unfocus
|VernacExtend("Extraction", [f;l]) ->
@@ -1784,6 +1793,7 @@ let rec xlate_vernac =
| VernacShow ShowExistentials -> CT_show_existentials
| VernacShow ShowScript -> CT_show_script
| VernacShow(ShowMatch _) -> xlate_error "TODO: VernacShow(ShowMatch _)"
+ | VernacShow(ShowThesis) -> xlate_error "TODO: VernacShow(ShowThesis _)"
| VernacGo arg -> CT_go (xlate_locn arg)
| VernacShow (ExplainProof l) -> CT_explain_proof (nums_to_int_list l)
| VernacShow (ExplainTree l) ->
diff --git a/contrib/rtauto/refl_tauto.ml b/contrib/rtauto/refl_tauto.ml
index 801122476e..b0e6b6ecff 100644
--- a/contrib/rtauto/refl_tauto.ml
+++ b/contrib/rtauto/refl_tauto.ml
@@ -303,7 +303,6 @@ let rtauto_tac gls=
end in
let build_start_time=System.get_time () in
let _ = step_count := 0; node_count := 0 in
- let nhyps = List.length hyps in
let main = mkApp (force node_count l_Reflect,
[|build_env gamma;
build_form formula;
diff --git a/contrib/xml/proof2aproof.ml b/contrib/xml/proof2aproof.ml
index 678b650cc8..92cbf6df52 100644
--- a/contrib/xml/proof2aproof.ml
+++ b/contrib/xml/proof2aproof.ml
@@ -63,21 +63,24 @@ let nf_evar sigma ~preserve =
(* Warning: statuses, goals, prim_rules and tactic_exprs are not unshared! *)
let rec unshare_proof_tree =
let module PT = Proof_type in
- function {PT.open_subgoals = status ; PT.goal = goal ; PT.ref = ref} ->
+ function {PT.open_subgoals = status ;
+ PT.goal = goal ;
+ PT.ref = ref} ->
let unshared_ref =
match ref with
None -> None
| Some (rule,pfs) ->
let unshared_rule =
match rule with
- PT.Prim prim -> PT.Prim prim
- | PT.Change_evars -> PT.Change_evars
- | PT.Tactic (tactic_expr, pf) ->
- PT.Tactic (tactic_expr, unshare_proof_tree pf)
- in
+ PT.Nested (cmpd, pf) ->
+ PT.Nested (cmpd, unshare_proof_tree pf)
+ | other -> other
+ in
Some (unshared_rule, List.map unshare_proof_tree pfs)
in
- {PT.open_subgoals = status ; PT.goal = goal ; PT.ref = unshared_ref}
+ {PT.open_subgoals = status ;
+ PT.goal = goal ;
+ PT.ref = unshared_ref}
;;
module ProofTreeHash =
@@ -103,7 +106,7 @@ let extract_open_proof sigma pf =
{PT.ref=Some(PT.Prim _,_)} as pf ->
L.prim_extractor proof_extractor vl pf
- | {PT.ref=Some(PT.Tactic (_,hidden_proof),spfl)} ->
+ | {PT.ref=Some(PT.Nested (_,hidden_proof),spfl)} ->
let sgl,v = Refiner.frontier hidden_proof in
let flat_proof = v spfl in
ProofTreeHash.add proof_tree_to_flattened_proof_tree node flat_proof ;
diff --git a/contrib/xml/proofTree2Xml.ml4 b/contrib/xml/proofTree2Xml.ml4
index 578c1ed2f3..d382ef955c 100644
--- a/contrib/xml/proofTree2Xml.ml4
+++ b/contrib/xml/proofTree2Xml.ml4
@@ -141,7 +141,7 @@ Pp.ppnl (Pp.(++) (Pp.str
(fun i n -> [< i ; (aux n old_hyps) >]) [<>] nodes)
| {PT.goal=goal;
- PT.ref=Some(PT.Tactic (tactic_expr,hidden_proof),nodes)} ->
+ PT.ref=Some(PT.Nested (PT.Tactic tactic_expr,hidden_proof),nodes)} ->
(* [hidden_proof] is the proof of the tactic; *)
(* [nodes] are the proof of the subgoals generated by the tactic; *)
(* [flat_proof] if the proof-tree obtained substituting [nodes] *)
@@ -194,6 +194,12 @@ Pp.ppnl (Pp.(++) (Pp.str
(List.fold_left
(fun i n -> [< i ; (aux n old_hyps) >]) [<>] nodes)
+ | {PT.ref=Some((PT.Nested(PT.Proof_instr (_,_),_)|PT.Decl_proof _),nodes)} ->
+ Util.anomaly "Not Implemented"
+
+ | {PT.ref=Some(PT.Daimon,_)} ->
+ X.xml_empty "Hidden_open_goal" of_attribute
+
| {PT.ref=None;PT.goal=goal} ->
X.xml_empty "Open_goal" of_attribute
in
diff --git a/ide/coq.ml b/ide/coq.ml
index f19cd91c9b..3d489dcb54 100644
--- a/ide/coq.ml
+++ b/ide/coq.ml
@@ -19,6 +19,7 @@ open Printer
open Environ
open Evarutil
open Evd
+open Decl_mode
open Hipattern
open Tacmach
open Reductionops
@@ -110,7 +111,9 @@ let is_in_coq_path f =
false
let is_in_proof_mode () =
- try ignore (get_pftreestate ()); true with _ -> false
+ match Decl_mode.get_current_mode () with
+ Decl_mode.Mode_none -> false
+ | _ -> true
let user_error_loc l s =
raise (Stdpp.Exc_located (l, Util.UserError ("CoqIde", s)))
@@ -252,6 +255,7 @@ type hyp = env * evar_map *
((identifier * string) * constr option * constr) *
(string * string)
type concl = env * evar_map * constr * string
+type meta = env * evar_map * string
type goal = hyp list * concl
let prepare_hyp sigma env ((i,c,d) as a) =
@@ -273,6 +277,37 @@ let prepare_goal sigma g =
(prepare_hyps sigma env,
(env, sigma, g.evar_concl, msg (pr_lconstr_env_at_top env g.evar_concl)))
+let prepare_hyps_filter info sigma env =
+ assert (rel_context env = []);
+ let hyps =
+ fold_named_context
+ (fun env ((id,_,_) as d) acc ->
+ if true || Idset.mem id info.pm_hyps then
+ let hyp = prepare_hyp sigma env d in hyp :: acc
+ else acc)
+ env ~init:[]
+ in
+ List.rev hyps
+
+let prepare_meta sigma env (m,typ) =
+ env, sigma,
+ (msg (str " ?" ++ int m ++ str " : " ++ pr_lconstr_env_at_top env typ))
+
+let prepare_metas info sigma env =
+ List.fold_right
+ (fun cpl acc ->
+ let meta = prepare_meta sigma env cpl in meta :: acc)
+ info.pm_subgoals []
+
+let get_current_pm_goal () =
+ let pfts = get_pftreestate () in
+ let gls = try nth_goal_of_pftreestate 1 pfts with _ -> raise Not_found in
+ let info = Decl_mode.get_info gls.it in
+ let env = pf_env gls in
+ let sigma= sig_sig gls in
+ (prepare_hyps_filter info sigma env,
+ prepare_metas info sigma env)
+
let get_current_goals () =
let pfts = get_pftreestate () in
let gls = fst (Refiner.frontier (Tacmach.proof_of_pftreestate pfts)) in
@@ -281,14 +316,13 @@ let get_current_goals () =
let get_current_goals_nb () =
try List.length (get_current_goals ()) with _ -> 0
-
let print_no_goal () =
let pfts = get_pftreestate () in
let gls = fst (Refiner.frontier (Tacmach.proof_of_pftreestate pfts)) in
assert (gls = []);
let sigma = Tacmach.project (Tacmach.top_goal_of_pftreestate pfts) in
- msg (Printer.pr_subgoals sigma gls)
+ msg (Printer.pr_subgoals (Decl_mode.get_end_command pfts) sigma gls)
type word_class = Normal | Kwd | Reserved
diff --git a/ide/coq.mli b/ide/coq.mli
index b6c0ed89cd..7b43a0c958 100644
--- a/ide/coq.mli
+++ b/ide/coq.mli
@@ -27,11 +27,14 @@ val is_state_preserving : Vernacexpr.vernac_expr -> bool
type hyp = env * evar_map *
((identifier*string) * constr option * constr) * (string * string)
+type meta = env * evar_map * string
type concl = env * evar_map * constr * string
type goal = hyp list * concl
val get_current_goals : unit -> goal list
+val get_current_pm_goal : unit -> hyp list * meta list
+
val get_current_goals_nb : unit -> int
val print_no_goal : unit -> string
diff --git a/ide/coqide.ml b/ide/coqide.ml
index 2d8291c146..b63cddd579 100644
--- a/ide/coqide.ml
+++ b/ide/coqide.ml
@@ -175,8 +175,9 @@ object('self)
method reset_initial : unit
method send_to_coq :
bool -> bool -> string ->
- bool -> bool -> bool -> (Util.loc * Vernacexpr.vernac_expr) option
+ bool -> bool -> bool -> (bool*(Util.loc * Vernacexpr.vernac_expr)) option
method set_message : string -> unit
+ method show_pm_goal : unit
method show_goals : unit
method show_goals_full : unit
method undo_last_step : unit
@@ -789,50 +790,88 @@ object(self)
(String.make previous_line_spaces ' ')
end
+ method show_pm_goal =
+ proof_buffer#insert
+ (Printf.sprintf " *** Declarative Mode ***\n");
+ try
+ let (hyps,metas) = get_current_pm_goal () in
+ List.iter
+ (fun ((_,_,_,(s,_)) as _hyp) ->
+ proof_buffer#insert (s^"\n"))
+ hyps;
+ proof_buffer#insert
+ (String.make 38 '_' ^ "\n");
+ List.iter
+ (fun (_,_,m) ->
+ proof_buffer#insert (m^"\n"))
+ metas;
+ let my_mark = `NAME "end_of_conclusion" in
+ proof_buffer#move_mark
+ ~where:((proof_buffer#get_iter_at_mark `INSERT))
+ my_mark;
+ ignore (proof_view#scroll_to_mark my_mark)
+ with Not_found ->
+ match Decl_mode.get_end_command (Pfedit.get_pftreestate ()) with
+ Some endc ->
+ proof_buffer#insert
+ ("Subproof completed, now type "^endc^".")
+ | None ->
+ proof_buffer#insert "Proof completed."
method show_goals =
try
proof_view#buffer#set_text "";
- let s = Coq.get_current_goals () in
- match s with
- | [] -> proof_buffer#insert (Coq.print_no_goal ())
- | (hyps,concl)::r ->
- let goal_nb = List.length s in
- proof_buffer#insert (Printf.sprintf "%d subgoal%s\n"
- goal_nb
- (if goal_nb<=1 then "" else "s"));
- List.iter
- (fun ((_,_,_,(s,_)) as _hyp) ->
- proof_buffer#insert (s^"\n"))
- hyps;
- proof_buffer#insert (String.make 38 '_' ^ "(1/"^
- (string_of_int goal_nb)^
- ")\n")
- ;
- let _,_,_,sconcl = concl in
- proof_buffer#insert sconcl;
- proof_buffer#insert "\n";
- let my_mark = `NAME "end_of_conclusion" in
- proof_buffer#move_mark
- ~where:((proof_buffer#get_iter_at_mark `INSERT)) my_mark;
- proof_buffer#insert "\n\n";
- let i = ref 1 in
- List.iter
- (function (_,(_,_,_,concl)) ->
- incr i;
- proof_buffer#insert (String.make 38 '_' ^"("^
- (string_of_int !i)^
- "/"^
- (string_of_int goal_nb)^
- ")\n");
- proof_buffer#insert concl;
- proof_buffer#insert "\n\n";
- )
- r;
- ignore (proof_view#scroll_to_mark my_mark)
- with e -> prerr_endline ("Don't worry be happy despite: "^Printexc.to_string e)
-
-
+ match Decl_mode.get_current_mode () with
+ Decl_mode.Mode_none -> proof_buffer#insert (Coq.print_no_goal ())
+ | Decl_mode.Mode_tactic ->
+ begin
+ let s = Coq.get_current_goals () in
+ match s with
+ | [] -> proof_buffer#insert (Coq.print_no_goal ())
+ | (hyps,concl)::r ->
+ let goal_nb = List.length s in
+ proof_buffer#insert
+ (Printf.sprintf "%d subgoal%s\n"
+ goal_nb
+ (if goal_nb<=1 then "" else "s"));
+ List.iter
+ (fun ((_,_,_,(s,_)) as _hyp) ->
+ proof_buffer#insert (s^"\n"))
+ hyps;
+ proof_buffer#insert
+ (String.make 38 '_' ^ "(1/"^
+ (string_of_int goal_nb)^
+ ")\n") ;
+ let _,_,_,sconcl = concl in
+ proof_buffer#insert sconcl;
+ proof_buffer#insert "\n";
+ let my_mark = `NAME "end_of_conclusion" in
+ proof_buffer#move_mark
+ ~where:((proof_buffer#get_iter_at_mark `INSERT))
+ my_mark;
+ proof_buffer#insert "\n\n";
+ let i = ref 1 in
+ List.iter
+ (function (_,(_,_,_,concl)) ->
+ incr i;
+ proof_buffer#insert
+ (String.make 38 '_' ^"("^
+ (string_of_int !i)^
+ "/"^
+ (string_of_int goal_nb)^
+ ")\n");
+ proof_buffer#insert concl;
+ proof_buffer#insert "\n\n";
+ )
+ r;
+ ignore (proof_view#scroll_to_mark my_mark)
+ end
+ | Decl_mode.Mode_proof ->
+ self#show_pm_goal
+ with e ->
+ prerr_endline ("Don't worry be happy despite: "^Printexc.to_string e)
+
+
val mutable full_goal_done = true
method show_goals_full =
@@ -840,148 +879,160 @@ object(self)
begin
try
proof_view#buffer#set_text "";
- let s = Coq.get_current_goals () in
- let last_shown_area = proof_buffer#create_tag [`BACKGROUND "light green"]
- in
- match s with
- | [] -> proof_buffer#insert (Coq.print_no_goal ())
- | (hyps,concl)::r ->
- let goal_nb = List.length s in
- proof_buffer#insert (Printf.sprintf "%d subgoal%s\n"
- goal_nb
- (if goal_nb<=1 then "" else "s"));
- let coq_menu commands =
- let tag = proof_buffer#create_tag []
- in
- ignore
- (tag#connect#event ~callback:
- (fun ~origin ev it ->
- begin match GdkEvent.get_type ev with
- | `BUTTON_PRESS ->
- let ev = (GdkEvent.Button.cast ev) in
- if (GdkEvent.Button.button ev) = 3
- then begin
- let loc_menu = GMenu.menu () in
- let factory = new GMenu.factory loc_menu in
- let add_coq_command (cp,ip) =
- ignore
- (factory#add_item cp
- ~callback:
- (fun () -> ignore
- (self#insert_this_phrase_on_success
- true
- true
- false
- ("progress "^ip^"\n")
- (ip^"\n"))
- )
- )
- in
- List.iter add_coq_command commands;
- loc_menu#popup
- ~button:3
- ~time:(GdkEvent.Button.time ev);
- end
- | `MOTION_NOTIFY ->
- proof_buffer#remove_tag
- ~start:proof_buffer#start_iter
- ~stop:proof_buffer#end_iter
- last_shown_area;
- prerr_endline "Before find_tag_limits";
-
- let s,e = find_tag_limits tag
+ match Decl_mode.get_current_mode () with
+ Decl_mode.Mode_none ->
+ proof_buffer#insert (Coq.print_no_goal ())
+ | Decl_mode.Mode_tactic ->
+ begin
+ match Coq.get_current_goals () with
+ [] -> Util.anomaly "show_goals_full"
+ | ((hyps,concl)::r) as s ->
+ let last_shown_area =
+ proof_buffer#create_tag [`BACKGROUND "light green"]
+ in
+ let goal_nb = List.length s in
+ proof_buffer#insert (Printf.sprintf "%d subgoal%s\n"
+ goal_nb
+ (if goal_nb<=1 then "" else "s"));
+ let coq_menu commands =
+ let tag = proof_buffer#create_tag []
+ in
+ ignore
+ (tag#connect#event ~callback:
+ (fun ~origin ev it ->
+ begin match GdkEvent.get_type ev with
+ | `BUTTON_PRESS ->
+ let ev = (GdkEvent.Button.cast ev) in
+ if (GdkEvent.Button.button ev) = 3
+ then begin
+ let loc_menu = GMenu.menu () in
+ let factory =
+ new GMenu.factory loc_menu in
+ let add_coq_command (cp,ip) =
+ ignore
+ (factory#add_item cp
+ ~callback:
+ (fun () -> ignore
+ (self#insert_this_phrase_on_success
+ true
+ true
+ false
+ ("progress "^ip^"\n")
+ (ip^"\n"))
+ )
+ )
+ in
+ List.iter add_coq_command commands;
+ loc_menu#popup
+ ~button:3
+ ~time:(GdkEvent.Button.time ev);
+ end
+ | `MOTION_NOTIFY ->
+ proof_buffer#remove_tag
+ ~start:proof_buffer#start_iter
+ ~stop:proof_buffer#end_iter
+ last_shown_area;
+ prerr_endline "Before find_tag_limits";
+
+ let s,e = find_tag_limits tag
(new GText.iter it)
- in
- prerr_endline "After find_tag_limits";
- proof_buffer#apply_tag
- ~start:s
- ~stop:e
- last_shown_area;
-
- prerr_endline "Applied tag";
- ()
- | _ -> ()
- end;false
- )
- );
- tag
- in
- List.iter
- (fun ((_,_,_,(s,_)) as hyp) ->
- let tag = coq_menu (hyp_menu hyp) in
- proof_buffer#insert ~tags:[tag] (s^"\n"))
- hyps;
- proof_buffer#insert
- (String.make 38 '_' ^"(1/"^
- (string_of_int goal_nb)^
- ")\n")
- ;
- let tag = coq_menu (concl_menu concl) in
- let _,_,_,sconcl = concl in
- proof_buffer#insert ~tags:[tag] sconcl;
- proof_buffer#insert "\n";
- let my_mark = `NAME "end_of_conclusion" in
- proof_buffer#move_mark
- ~where:((proof_buffer#get_iter_at_mark `INSERT)) my_mark;
- proof_buffer#insert "\n\n";
- let i = ref 1 in
- List.iter
- (function (_,(_,_,_,concl)) ->
- incr i;
- proof_buffer#insert
- (String.make 38 '_' ^"("^
- (string_of_int !i)^
- "/"^
- (string_of_int goal_nb)^
- ")\n");
- proof_buffer#insert concl;
- proof_buffer#insert "\n\n";
- )
- r;
- ignore (proof_view#scroll_to_mark my_mark) ;
- full_goal_done <- true;
- with e -> prerr_endline (Printexc.to_string e)
+ in
+ prerr_endline "After find_tag_limits";
+ proof_buffer#apply_tag
+ ~start:s
+ ~stop:e
+ last_shown_area;
+
+ prerr_endline "Applied tag";
+ ()
+ | _ -> ()
+ end;false
+ )
+ );
+ tag
+ in
+ List.iter
+ (fun ((_,_,_,(s,_)) as hyp) ->
+ let tag = coq_menu (hyp_menu hyp) in
+ proof_buffer#insert ~tags:[tag] (s^"\n"))
+ hyps;
+ proof_buffer#insert
+ (String.make 38 '_' ^"(1/"^
+ (string_of_int goal_nb)^
+ ")\n")
+ ;
+ let tag = coq_menu (concl_menu concl) in
+ let _,_,_,sconcl = concl in
+ proof_buffer#insert ~tags:[tag] sconcl;
+ proof_buffer#insert "\n";
+ let my_mark = `NAME "end_of_conclusion" in
+ proof_buffer#move_mark
+ ~where:((proof_buffer#get_iter_at_mark `INSERT)) my_mark;
+ proof_buffer#insert "\n\n";
+ let i = ref 1 in
+ List.iter
+ (function (_,(_,_,_,concl)) ->
+ incr i;
+ proof_buffer#insert
+ (String.make 38 '_' ^"("^
+ (string_of_int !i)^
+ "/"^
+ (string_of_int goal_nb)^
+ ")\n");
+ proof_buffer#insert concl;
+ proof_buffer#insert "\n\n";
+ )
+ r;
+ ignore (proof_view#scroll_to_mark my_mark) ;
+ full_goal_done <- true
+ end
+ | Decl_mode.Mode_proof ->
+ self#show_pm_goal
+ with e -> prerr_endline (Printexc.to_string e)
end
-
+
method send_to_coq verbosely replace phrase show_output show_error localize =
let display_output msg =
self#insert_message (if show_output then msg else "") in
let display_error e =
let (s,loc) = Coq.process_exn e in
- assert (Glib.Utf8.validate s);
- self#insert_message s;
- message_view#misc#draw None;
- if localize then
- (match Util.option_map Util.unloc loc with
- | None -> ()
- | Some (start,stop) ->
- let convert_pos = byte_offset_to_char_offset phrase in
- let start = convert_pos start in
- let stop = convert_pos stop in
- let i = self#get_start_of_input in
- let starti = i#forward_chars start in
- let stopi = i#forward_chars stop in
- input_buffer#apply_tag_by_name "error"
- ~start:starti
- ~stop:stopi;
- input_buffer#place_cursor starti) in
- try
- full_goal_done <- false;
- prerr_endline "Send_to_coq starting now";
- if replace then begin
- let r,info = Coq.interp_and_replace ("info " ^ phrase) in
- let msg = read_stdout () in
- sync display_output msg;
- Some r
- end else begin
- let r = Coq.interp verbosely phrase in
- let msg = read_stdout () in
- sync display_output msg;
- Some r
- end
- with e ->
- if show_error then sync display_error e;
- None
+ assert (Glib.Utf8.validate s);
+ self#insert_message s;
+ message_view#misc#draw None;
+ if localize then
+ (match Util.option_map Util.unloc loc with
+ | None -> ()
+ | Some (start,stop) ->
+ let convert_pos = byte_offset_to_char_offset phrase in
+ let start = convert_pos start in
+ let stop = convert_pos stop in
+ let i = self#get_start_of_input in
+ let starti = i#forward_chars start in
+ let stopi = i#forward_chars stop in
+ input_buffer#apply_tag_by_name "error"
+ ~start:starti
+ ~stop:stopi;
+ input_buffer#place_cursor starti) in
+ try
+ full_goal_done <- false;
+ prerr_endline "Send_to_coq starting now";
+ Decl_mode.clear_daimon_flag ();
+ if replace then begin
+ let r,info = Coq.interp_and_replace ("info " ^ phrase) in
+ let complete = not (Decl_mode.get_daimon_flag ()) in
+ let msg = read_stdout () in
+ sync display_output msg;
+ Some (complete,r)
+ end else begin
+ let r = Coq.interp verbosely phrase in
+ let complete = not (Decl_mode.get_daimon_flag ()) in
+ let msg = read_stdout () in
+ sync display_output msg;
+ Some (complete,r)
+ end
+ with e ->
+ if show_error then sync display_error e;
+ None
method find_phrase_starting_at (start:GText.iter) =
prerr_endline "find_phrase_starting_at starting now";
@@ -1089,10 +1140,11 @@ object(self)
input_view#set_editable true;
!pop_info ();
end in
- let mark_processed (start,stop) ast =
- let b = input_buffer in
+ let mark_processed complete (start,stop) ast =
+ let b = input_buffer in
b#move_mark ~where:stop (`NAME "start_of_input");
- b#apply_tag_by_name "processed" ~start ~stop;
+ b#apply_tag_by_name
+ (if complete then "processed" else "unjustified") ~start ~stop;
if (self#get_insert#compare) stop <= 0 then
begin
b#place_cursor stop;
@@ -1100,67 +1152,69 @@ object(self)
end;
let start_of_phrase_mark = `MARK (b#create_mark start) in
let end_of_phrase_mark = `MARK (b#create_mark stop) in
- push_phrase
- start_of_phrase_mark
- end_of_phrase_mark ast;
- if display_goals then self#show_goals;
- remove_tag (start,stop) in
+ push_phrase
+ start_of_phrase_mark
+ end_of_phrase_mark ast;
+ if display_goals then self#show_goals;
+ remove_tag (start,stop) in
begin
match sync get_next_phrase () with
None -> false
| Some (loc,phrase) ->
- (match self#send_to_coq verbosely false phrase true true true with
- | Some ast -> sync (mark_processed loc) ast; true
- | None -> sync remove_tag loc; false)
+ (match self#send_to_coq verbosely false phrase true true true with
+ | Some (complete,ast) ->
+ sync (mark_processed complete) loc ast; true
+ | None -> sync remove_tag loc; false)
end
-
+
method insert_this_phrase_on_success
show_output show_msg localize coqphrase insertphrase =
- let mark_processed ast =
+ let mark_processed complete ast =
let stop = self#get_start_of_input in
- if stop#starts_line then
- input_buffer#insert ~iter:stop insertphrase
- else input_buffer#insert ~iter:stop ("\n"^insertphrase);
- let start = self#get_start_of_input in
- input_buffer#move_mark ~where:stop (`NAME "start_of_input");
- input_buffer#apply_tag_by_name "processed" ~start ~stop;
- if (self#get_insert#compare) stop <= 0 then
- input_buffer#place_cursor stop;
- let start_of_phrase_mark = `MARK (input_buffer#create_mark start) in
- let end_of_phrase_mark = `MARK (input_buffer#create_mark stop) in
- push_phrase start_of_phrase_mark end_of_phrase_mark ast;
- self#show_goals;
- (*Auto insert save on success...
- try (match Coq.get_current_goals () with
- | [] ->
- (match self#send_to_coq "Save.\n" true true true with
+ if stop#starts_line then
+ input_buffer#insert ~iter:stop insertphrase
+ else input_buffer#insert ~iter:stop ("\n"^insertphrase);
+ let start = self#get_start_of_input in
+ input_buffer#move_mark ~where:stop (`NAME "start_of_input");
+ input_buffer#apply_tag_by_name
+ (if complete then "processed" else "unjustified") ~start ~stop;
+ if (self#get_insert#compare) stop <= 0 then
+ input_buffer#place_cursor stop;
+ let start_of_phrase_mark = `MARK (input_buffer#create_mark start) in
+ let end_of_phrase_mark = `MARK (input_buffer#create_mark stop) in
+ push_phrase start_of_phrase_mark end_of_phrase_mark ast;
+ self#show_goals;
+ (*Auto insert save on success...
+ try (match Coq.get_current_goals () with
+ | [] ->
+ (match self#send_to_coq "Save.\n" true true true with
| Some ast ->
- begin
- let stop = self#get_start_of_input in
- if stop#starts_line then
- input_buffer#insert ~iter:stop "Save.\n"
- else input_buffer#insert ~iter:stop "\nSave.\n";
- let start = self#get_start_of_input in
- input_buffer#move_mark ~where:stop (`NAME"start_of_input");
- input_buffer#apply_tag_by_name "processed" ~start ~stop;
- if (self#get_insert#compare) stop <= 0 then
- input_buffer#place_cursor stop;
- let start_of_phrase_mark =
- `MARK (input_buffer#create_mark start) in
- let end_of_phrase_mark =
- `MARK (input_buffer#create_mark stop) in
- push_phrase start_of_phrase_mark end_of_phrase_mark ast
- end
+ begin
+ let stop = self#get_start_of_input in
+ if stop#starts_line then
+ input_buffer#insert ~iter:stop "Save.\n"
+ else input_buffer#insert ~iter:stop "\nSave.\n";
+ let start = self#get_start_of_input in
+ input_buffer#move_mark ~where:stop (`NAME"start_of_input");
+ input_buffer#apply_tag_by_name "processed" ~start ~stop;
+ if (self#get_insert#compare) stop <= 0 then
+ input_buffer#place_cursor stop;
+ let start_of_phrase_mark =
+ `MARK (input_buffer#create_mark start) in
+ let end_of_phrase_mark =
+ `MARK (input_buffer#create_mark stop) in
+ push_phrase start_of_phrase_mark end_of_phrase_mark ast
+ end
| None -> ())
- | _ -> ())
- with _ -> ()*) in
- match self#send_to_coq false false coqphrase show_output show_msg localize with
- | Some ast -> sync mark_processed ast; true
- | None ->
- sync
- (fun _ -> self#insert_message ("Unsuccessfully tried: "^coqphrase))
- ();
- false
+ | _ -> ())
+ with _ -> ()*) in
+ match self#send_to_coq false false coqphrase show_output show_msg localize with
+ | Some (complete,ast) -> sync (mark_processed complete) ast; true
+ | None ->
+ sync
+ (fun _ -> self#insert_message ("Unsuccessfully tried: "^coqphrase))
+ ();
+ false
method process_until_iter_or_error stop =
let stop' = `OFFSET stop#offset in
@@ -1196,6 +1250,7 @@ object(self)
let stop = input_buffer#get_iter_at_mark inf.stop in
input_buffer#move_mark ~where:start (`NAME "start_of_input");
input_buffer#remove_tag_by_name "processed" ~start ~stop;
+ input_buffer#remove_tag_by_name "unjustified" ~start ~stop;
input_buffer#delete_mark inf.start;
input_buffer#delete_mark inf.stop;
)
@@ -1260,6 +1315,10 @@ object(self)
~start
~stop:self#get_start_of_input
"processed";
+ input_buffer#remove_tag_by_name
+ ~start
+ ~stop:self#get_start_of_input
+ "unjustified";
prerr_endline "Moving (long) start_of_input...";
input_buffer#move_mark ~where:start (`NAME "start_of_input");
self#show_goals;
@@ -1269,9 +1328,9 @@ object(self)
with _ ->
!push_info "WARNING: undo failed badly -> Coq might be in an inconsistent state.
Please restart and report NOW.";
- end
- else prerr_endline "backtrack_to : discarded (...)"
-
+ end
+ else prerr_endline "backtrack_to : discarded (...)"
+
method backtrack_to i =
if Mutex.try_lock coq_may_stop then
(!push_info "Undoing...";self#backtrack_to_no_lock i ; Mutex.unlock coq_may_stop;
@@ -1296,6 +1355,10 @@ Please restart and report NOW.";
~start
~stop:(input_buffer#get_iter_at_mark last_command.stop)
"processed";
+ input_buffer#remove_tag_by_name
+ ~start
+ ~stop:(input_buffer#get_iter_at_mark last_command.stop)
+ "unjustified";
prerr_endline "Moving start_of_input";
input_buffer#move_mark
~where:start
@@ -1356,6 +1419,7 @@ Please restart and report NOW.";
let c = Blaster_window.present_blaster_window () in
if Mutex.try_lock c#lock then begin
c#clear ();
+ Decl_mode.check_not_proof_mode "No blaster in Proof mode";
let current_gls = try get_current_goals () with _ -> [] in
let set_goal i (s,t) =
@@ -1555,10 +1619,16 @@ Please restart and report NOW.";
~callback:(fun tag ~start ~stop ->
if (start#compare self#get_start_of_input)>=0
then
- input_buffer#remove_tag_by_name
- ~start
- ~stop
- "processed"
+ begin
+ input_buffer#remove_tag_by_name
+ ~start
+ ~stop
+ "processed";
+ input_buffer#remove_tag_by_name
+ ~start
+ ~stop
+ "unjustified"
+ end
)
);
ignore (input_buffer#connect#after#insert_text
@@ -1694,6 +1764,10 @@ let create_input_tab filename =
ignore (tv1#buffer#create_tag
~name:"processed"
[`BACKGROUND "light green" ;`EDITABLE false]);
+ ignore (tv1#buffer#create_tag (* Proof mode *)
+ ~name:"unjustified"
+ [`UNDERLINE `SINGLE ; `FOREGROUND "red";
+ `BACKGROUND "gold" ;`EDITABLE false]);
ignore (tv1#buffer#create_tag
~name:"found"
[`BACKGROUND "blue"; `FOREGROUND "white"]);
diff --git a/ide/utils/editable_cells.ml b/ide/utils/editable_cells.ml
index e6d2f4d48c..5441f4abe0 100644
--- a/ide/utils/editable_cells.ml
+++ b/ide/utils/editable_cells.ml
@@ -85,7 +85,7 @@ let create l =
| [] -> ()
| path::_ ->
let iter = store#get_iter path in
- GtkTree.TreePath.prev path;
+ ignore (GtkTree.TreePath.prev path);
let upiter = store#get_iter path in
ignore (store#swap iter upiter);
));
diff --git a/interp/constrintern.ml b/interp/constrintern.ml
index 76d0a1bf69..8e5faf01d5 100644
--- a/interp/constrintern.ml
+++ b/interp/constrintern.ml
@@ -1073,6 +1073,14 @@ let intern_gen isarity sigma env
let intern_constr sigma env c = intern_gen false sigma env c
+let intern_pattern env patt =
+ try
+ intern_cases_pattern env [] ([],[]) None patt
+ with
+ InternalisationError (loc,e) ->
+ user_err_loc (loc,"internalize",explain_internalisation_error e)
+
+
let intern_ltac isarity ltacvars sigma env c =
intern_gen isarity sigma env ~ltacvars:ltacvars c
diff --git a/interp/constrintern.mli b/interp/constrintern.mli
index 4603565e34..12aaeec17f 100644
--- a/interp/constrintern.mli
+++ b/interp/constrintern.mli
@@ -55,6 +55,14 @@ val intern_gen : bool -> evar_map -> env ->
?impls:full_implicits_env -> ?allow_soapp:bool -> ?ltacvars:ltac_sign ->
constr_expr -> rawconstr
+val intern_pattern : env -> cases_pattern_expr ->
+ Names.identifier list *
+ ((Names.identifier * Names.identifier) list * Rawterm.cases_pattern) list
+
+val intern_pattern : env -> cases_pattern_expr ->
+ Names.identifier list *
+ ((Names.identifier * Names.identifier) list * Rawterm.cases_pattern) list
+
(*s Composing internalisation with pretyping *)
(* Main interpretation function *)
diff --git a/parsing/g_decl_mode.ml4 b/parsing/g_decl_mode.ml4
new file mode 100644
index 0000000000..8d7fd1f189
--- /dev/null
+++ b/parsing/g_decl_mode.ml4
@@ -0,0 +1,171 @@
+(************************************************************************)
+(* v * The Coq Proof Assistant / The Coq Development Team *)
+(* <O___,, * CNRS-Ecole Polytechnique-INRIA Futurs-Universite Paris Sud *)
+(* \VV/ **************************************************************)
+(* // * This file is distributed under the terms of the *)
+(* * GNU Lesser General Public License Version 2.1 *)
+(************************************************************************)
+
+(* $Id:$ *)
+(*i camlp4deps: "parsing/grammar.cma" i*)
+
+open Decl_expr
+open Names
+open Term
+open Genarg
+open Pcoq
+
+open Pcoq.Constr
+open Pcoq.Tactic
+open Pcoq.Vernac_
+
+let none_is_empty = function
+ None -> []
+ | Some l -> l
+
+GEXTEND Gram
+GLOBAL: proof_instr;
+ thesis :
+ [[ "thesis" -> Plain
+ | "thesis"; "for"; i=ident -> (For i)
+ | "thesis"; "["; n=INT ;"]" -> (Sub (int_of_string n))
+ ]];
+ statement :
+ [[ i=ident ; ":" ; c=constr -> {st_label=Name i;st_it=c}
+ | i=ident -> {st_label=Anonymous;
+ st_it=Topconstr.CRef (Libnames.Ident (loc, i))}
+ | c=constr -> {st_label=Anonymous;st_it=c}
+ ]];
+ constr_or_thesis :
+ [[ t=thesis -> Thesis t ] |
+ [ c=constr -> This c
+ ]];
+ statement_or_thesis :
+ [
+ [ t=thesis -> {st_label=Anonymous;st_it=Thesis t} ]
+ |
+ [ i=ident ; ":" ; cot=constr_or_thesis -> {st_label=Name i;st_it=cot}
+ | i=ident -> {st_label=Anonymous;
+ st_it=This (Topconstr.CRef (Libnames.Ident (loc, i)))}
+ | c=constr -> {st_label=Anonymous;st_it=This c}
+ ]
+ ];
+ justification :
+ [[ -> Automated []
+ | IDENT "by"; l=LIST1 constr SEP "," -> Automated l
+ | IDENT "by"; IDENT "tactic"; tac=tactic -> By_tactic tac ]]
+ ;
+ simple_cut_or_thesis :
+ [[ ls = statement_or_thesis;
+ j=justification -> {cut_stat=ls;cut_by=j} ]]
+ ;
+ simple_cut :
+ [[ ls = statement;
+ j=justification -> {cut_stat=ls;cut_by=j} ]]
+ ;
+ elim_type:
+ [[ IDENT "induction" -> ET_Induction
+ | IDENT "cases" -> ET_Case_analysis ]]
+ ;
+ block_type :
+ [[ IDENT "claim" -> B_claim
+ | IDENT "focus" -> B_focus
+ | IDENT "proof" -> B_proof
+ | et=elim_type -> B_elim et ]]
+ ;
+ elim_obj:
+ [[ IDENT "on"; c=constr -> Real c
+ | IDENT "of"; c=simple_cut -> Virtual c ]]
+ ;
+ elim_step:
+ [[ IDENT "consider" ; h=vars ; IDENT "from" ; c=constr -> Pconsider (c,h)
+ | IDENT "per"; et=elim_type; obj=elim_obj -> Pper (et,obj)]]
+ ;
+ rew_step :
+ [[ "~=" ; c=simple_cut -> (Rhs,c)
+ | "=~" ; c=simple_cut -> (Lhs,c)]]
+ ;
+ cut_step:
+ [[ "then"; tt=elim_step -> Pthen tt
+ | "then"; c=simple_cut_or_thesis -> Pthen (Pcut c)
+ | IDENT "thus"; tt=rew_step -> Pthus (let s,c=tt in Prew (s,c))
+ | IDENT "thus"; c=simple_cut_or_thesis -> Pthus (Pcut c)
+ | IDENT "hence"; c=simple_cut_or_thesis -> Phence (Pcut c)
+ | tt=elim_step -> tt
+ | tt=rew_step -> let s,c=tt in Prew (s,c);
+ | IDENT "have"; c=simple_cut_or_thesis -> Pcut c;
+ | IDENT "claim"; c=statement -> Pclaim c;
+ | IDENT "focus"; IDENT "on"; c=statement -> Pfocus c;
+ | "end"; bt = block_type -> Pend bt;
+ | IDENT "escape" -> Pescape ]]
+ ;
+ (* examiner s'il est possible de faire R _ et _ R pour R une relation qcq*)
+ loc_id:
+ [[ id=ident -> fun x -> (loc,(id,x)) ]];
+ hyp:
+ [[ id=loc_id -> id None ;
+ | id=loc_id ; ":" ; c=constr -> id (Some c)]]
+ ;
+ vars:
+ [[ name=hyp -> [Hvar name]
+ | name=hyp; ","; v=vars -> (Hvar name) :: v
+ | name=hyp; IDENT "be";
+ IDENT "such"; IDENT "that"; h=hyps -> (Hvar name)::h
+ | name=hyp;
+ IDENT "such"; IDENT "that"; h=hyps -> (Hvar name)::h
+ ]]
+ ;
+ hyps:
+ [[ IDENT "we"; IDENT "have"; v=vars -> v
+ | st=statement; IDENT "and"; h=hyps -> Hprop st::h
+ | st=statement; IDENT "and"; v=vars -> Hprop st::v
+ | st=statement -> [Hprop st]
+ ]]
+ ;
+ vars_or_thesis:
+ [[name=hyp -> [Hvar name]
+ |name=hyp; ","; v=vars_or_thesis -> (Hvar name) :: v
+ |name=hyp; OPT[IDENT "be"];
+ IDENT "such"; IDENT "that"; h=hyps_or_thesis -> (Hvar name)::h
+ ]]
+ ;
+ hyps_or_thesis:
+ [[ IDENT "we"; IDENT "have"; v=vars_or_thesis -> v
+ | st=statement_or_thesis; IDENT "and"; h=hyps_or_thesis -> Hprop st::h
+ | st=statement_or_thesis; IDENT "and"; v=vars_or_thesis -> Hprop st::v
+ | st=statement_or_thesis -> [Hprop st];
+ ]]
+ ;
+ intro_step:
+ [[ IDENT "suppose" ; h=hyps -> Psuppose h
+ | IDENT "suppose" ; IDENT "it"; IDENT "is" ; c=pattern LEVEL "0" ;
+ po=OPT[ IDENT "with"; p=LIST1 hyp -> p ] ;
+ ho=OPT[ IDENT "and" ; h=hyps_or_thesis -> h ] ->
+ Pcase (none_is_empty po,c,none_is_empty ho)
+ | "let" ; v=vars -> Plet v
+ | IDENT "take"; witnesses = LIST1 constr SEP "," -> Ptake witnesses
+ | IDENT "assume"; h=hyps -> Passume h
+ | IDENT "given"; h=vars -> Pgiven h
+ | IDENT "define"; id=ident; args=LIST0 hyp;
+ "as"; body=constr -> Pdefine(id,args,body)
+ | IDENT "reconsider"; id=ident; "as" ; typ=constr -> Pcast (This id,typ)
+ | IDENT "reconsider"; t=thesis; "as" ; typ=constr -> Pcast (Thesis t ,typ)
+ ]]
+ ;
+ emphasis :
+ [[ -> 0
+ | "*" -> 1
+ | "**" -> 2
+ | "***" -> 3
+ ]]
+ ;
+ bare_proof_instr:
+ [[ c = cut_step -> c ;
+ | i = intro_step -> i ]]
+ ;
+ proof_instr :
+ [[ e=emphasis;i=bare_proof_instr -> {emph=e;instr=i}]]
+ ;
+END;;
+
+
diff --git a/parsing/g_proofs.ml4 b/parsing/g_proofs.ml4
index a1a7030990..afa5160116 100644
--- a/parsing/g_proofs.ml4
+++ b/parsing/g_proofs.ml4
@@ -75,6 +75,7 @@ GEXTEND Gram
| IDENT "Show"; IDENT "Intro" -> VernacShow (ShowIntros false)
| IDENT "Show"; IDENT "Intros" -> VernacShow (ShowIntros true)
| IDENT "Show"; IDENT "Match"; id = identref -> VernacShow (ShowMatch id)
+ | IDENT "Show"; IDENT "Thesis" -> VernacShow ShowThesis
| IDENT "Explain"; IDENT "Proof"; l = LIST0 integer ->
VernacShow (ExplainProof l)
| IDENT "Explain"; IDENT "Proof"; IDENT "Tree"; l = LIST0 integer ->
diff --git a/parsing/g_vernac.ml4 b/parsing/g_vernac.ml4
index 510fe529f0..81663bb918 100644
--- a/parsing/g_vernac.ml4
+++ b/parsing/g_vernac.ml4
@@ -15,6 +15,7 @@ open Names
open Topconstr
open Vernacexpr
open Pcoq
+open Decl_mode
open Tactic
open Decl_kinds
open Genarg
@@ -34,13 +35,28 @@ let _ = List.iter (fun s -> Lexer.add_token ("",s)) vernac_kw
(* compilation on PowerPC and Sun architectures *)
let check_command = Gram.Entry.create "vernac:check_command"
+
+let tactic_mode = Gram.Entry.create "vernac:tactic_command"
+let proof_mode = Gram.Entry.create "vernac:proof_command"
+let noedit_mode = Gram.Entry.create "vernac:noedit_command"
+
let class_rawexpr = Gram.Entry.create "vernac:class_rawexpr"
let thm_token = Gram.Entry.create "vernac:thm_token"
let def_body = Gram.Entry.create "vernac:def_body"
+let get_command_entry () =
+ match Decl_mode.get_current_mode () with
+ Mode_proof -> proof_mode
+ | Mode_tactic -> tactic_mode
+ | Mode_none -> noedit_mode
+
+let default_command_entry =
+ Gram.Entry.of_parser "command_entry"
+ (fun strm -> Gram.Entry.parse_token (get_command_entry ()) strm)
+
let no_hook _ _ = ()
GEXTEND Gram
- GLOBAL: vernac gallina_ext;
+ GLOBAL: vernac gallina_ext tactic_mode proof_mode noedit_mode;
vernac:
(* Better to parse "." here: in case of failure (e.g. in coerce_to_var), *)
(* "." is still in the stream and discard_to_dot works correctly *)
@@ -54,9 +70,15 @@ GEXTEND Gram
vernac: FIRST
[ [ IDENT "Time"; v = vernac -> VernacTime v ] ]
;
- vernac: LAST
- [ [ gln = OPT[n=natural; ":" -> n];
- tac = subgoal_command -> tac gln ] ]
+ vernac: LAST
+ [ [ prfcom = default_command_entry -> prfcom ] ]
+ ;
+ noedit_mode:
+ [ [ c = subgoal_command -> c None] ]
+ ;
+ tactic_mode:
+ [ [ gln = OPT[n=natural; ":" -> n];
+ tac = subgoal_command -> tac gln ] ]
;
subgoal_command:
[ [ c = check_command; "." -> c
@@ -66,6 +88,12 @@ GEXTEND Gram
let g = match g with Some gl -> gl | _ -> 1 in
VernacSolve(g,tac,use_dft_tac)) ] ]
;
+ proof_mode:
+ [ [ instr = proof_instr; "." -> VernacProofInstr instr ] ]
+ ;
+ proof_mode: LAST
+ [ [ c=subgoal_command -> c (Some 1) ] ]
+ ;
located_vernac:
[ [ v = vernac -> loc, v ] ]
;
@@ -556,7 +584,9 @@ GEXTEND Gram
| IDENT "Remove"; table = IDENT; field = IDENT; v= LIST1 option_ref_value
-> VernacRemoveOption (SecondaryTable (table,field), v)
| IDENT "Remove"; table = IDENT; v = LIST1 option_ref_value ->
- VernacRemoveOption (PrimaryTable table, v) ] ]
+ VernacRemoveOption (PrimaryTable table, v)
+ | IDENT "proof" -> VernacDeclProof
+ | "return" -> VernacReturn ]]
;
check_command: (* TODO: rapprocher Eval et Check *)
[ [ IDENT "Eval"; r = Tactic.red_expr; "in"; c = lconstr ->
@@ -596,7 +626,7 @@ GEXTEND Gram
| IDENT "Scopes" -> PrintScopes
| IDENT "Scope"; s = IDENT -> PrintScope s
| IDENT "Visibility"; s = OPT IDENT -> PrintVisibility s
- | IDENT "Implicit"; qid = global -> PrintImplicit qid ] ]
+ | IDENT "Implicit"; qid = global -> PrintImplicit qid ] ]
;
class_rawexpr:
[ [ IDENT "Funclass" -> FunClass
diff --git a/parsing/pcoq.ml4 b/parsing/pcoq.ml4
index 92c68ff94e..c3a571a137 100644
--- a/parsing/pcoq.ml4
+++ b/parsing/pcoq.ml4
@@ -451,6 +451,12 @@ module Vernac_ =
let syntax = gec_vernac "syntax_command"
let vernac = gec_vernac "Vernac_.vernac"
+ (* MMode *)
+
+ let proof_instr = Gram.Entry.create "proofmode:instr"
+
+ (* /MMode *)
+
let vernac_eoi = eoi_entry vernac
end
diff --git a/parsing/pcoq.mli b/parsing/pcoq.mli
index 404f3ab90d..27239599ca 100644
--- a/parsing/pcoq.mli
+++ b/parsing/pcoq.mli
@@ -196,6 +196,13 @@ module Vernac_ :
val command : vernac_expr Gram.Entry.e
val syntax : vernac_expr Gram.Entry.e
val vernac : vernac_expr Gram.Entry.e
+
+ (* MMode *)
+
+ val proof_instr : Decl_expr.raw_proof_instr Gram.Entry.e
+
+ (*/ MMode *)
+
val vernac_eoi : vernac_expr Gram.Entry.e
end
diff --git a/parsing/ppdecl_proof.ml b/parsing/ppdecl_proof.ml
new file mode 100644
index 0000000000..7e57885cb0
--- /dev/null
+++ b/parsing/ppdecl_proof.ml
@@ -0,0 +1,180 @@
+(************************************************************************)
+(* v * The Coq Proof Assistant / The Coq Development Team *)
+(* <O___,, * CNRS-Ecole Polytechnique-INRIA Futurs-Universite Paris Sud *)
+(* \VV/ **************************************************************)
+(* // * This file is distributed under the terms of the *)
+(* * GNU Lesser General Public License Version 2.1 *)
+(************************************************************************)
+
+(* $Id:$ *)
+
+open Util
+open Pp
+open Decl_expr
+open Names
+open Nameops
+
+let pr_constr = Printer.pr_constr_env
+let pr_tac = Pptactic.pr_glob_tactic
+let pr_pat mpat = Ppconstr.pr_cases_pattern_expr mpat.pat_expr
+
+let pr_label = function
+ Anonymous -> mt ()
+ | Name id -> pr_id id ++ spc () ++ str ":" ++ spc ()
+
+let pr_justification env = function
+ Automated [] -> mt ()
+ | Automated (_::_ as l) ->
+ spc () ++ str "by" ++ spc () ++
+ prlist_with_sep (fun () -> str ",") (pr_constr env) l
+ | By_tactic tac ->
+ spc () ++ str "by" ++ spc () ++ str "tactic" ++ pr_tac env tac
+
+let pr_statement pr_it env st =
+ pr_label st.st_label ++ pr_it env st.st_it
+
+let pr_or_thesis pr_this env = function
+ Thesis Plain -> str "thesis"
+ | Thesis (For id) ->
+ str "thesis" ++ spc() ++ str "for" ++ spc () ++ pr_id id
+ | Thesis (Sub n) -> str "thesis[" ++ int n ++ str "]"
+ | This c -> pr_this env c
+
+let pr_cut pr_it env c =
+ hov 1 (pr_statement pr_it env c.cut_stat) ++
+ pr_justification env c.cut_by
+
+let type_or_thesis = function
+ Thesis _ -> Term.mkProp
+ | This c -> c
+
+let _I x = x
+
+let rec print_hyps pconstr gtyp env _and _be hyps =
+ let _andp = if _and then str "and" ++spc () else mt () in
+ match hyps with
+ (Hvar _ ::_) as rest ->
+ spc () ++ _andp ++ str "we have" ++
+ print_vars pconstr gtyp env false _be rest
+ | Hprop st :: rest ->
+ begin
+ let nenv =
+ match st.st_label with
+ Anonymous -> env
+ | Name id -> Environ.push_named (id,None,gtyp st.st_it) env in
+ spc() ++ _andp ++ pr_statement pconstr env st ++
+ print_hyps pconstr gtyp nenv true _be rest
+ end
+ | [] -> mt ()
+
+and print_vars pconstr gtyp env _and _be vars =
+ match vars with
+ Hvar st :: rest ->
+ begin
+ let nenv =
+ match st.st_label with
+ Anonymous -> anomaly "anonymous variable"
+ | Name id -> Environ.push_named (id,None,st.st_it) env in
+ let _andp = if _and then pr_coma () else mt () in
+ spc() ++ _andp ++
+ pr_statement pr_constr env st ++
+ print_vars pconstr gtyp nenv true _be rest
+ end
+ | (Hprop _ :: _) as rest ->
+ let _st = if _be then
+ str "be such that"
+ else
+ str "such that" in
+ spc() ++ _st ++ print_hyps pconstr gtyp env false _be rest
+ | [] -> mt ()
+
+let pr_elim_type = function
+ ET_Case_analysis -> str "cases"
+ | ET_Induction -> str "induction"
+
+let pr_casee env =function
+ Real c -> str "on" ++ spc () ++ pr_constr env c
+ | Virtual cut -> str "of" ++ spc () ++ pr_cut pr_constr env cut
+
+let pr_side = function
+ Lhs -> str "=~"
+ | Rhs -> str "~="
+
+let rec pr_bare_proof_instr _then _thus env = function
+ | Pescape -> str "escape"
+ | Pthen i -> pr_bare_proof_instr true _thus env i
+ | Pthus i -> pr_bare_proof_instr _then true env i
+ | Phence i -> pr_bare_proof_instr true true env i
+ | Pcut c ->
+ begin
+ match _then,_thus with
+ false,false -> str "have" ++ spc () ++
+ pr_cut (pr_or_thesis pr_constr) env c
+ | false,true -> str "thus" ++ spc () ++
+ pr_cut (pr_or_thesis pr_constr) env c
+ | true,false -> str "then" ++ spc () ++
+ pr_cut (pr_or_thesis pr_constr) env c
+ | true,true -> str "hence" ++ spc () ++
+ pr_cut (pr_or_thesis pr_constr) env c
+ end
+ | Prew (sid,c) ->
+ (if _thus then str "thus" else str " ") ++ spc () ++
+ pr_side sid ++ spc () ++ pr_cut pr_constr env c
+ | Passume hyps ->
+ str "assume" ++ print_hyps pr_constr _I env false false hyps
+ | Plet hyps ->
+ str "let" ++ print_vars pr_constr _I env false true hyps
+ | Pclaim st ->
+ str "claim" ++ spc () ++ pr_statement pr_constr env st
+ | Pfocus st ->
+ str "focus on" ++ spc () ++ pr_statement pr_constr env st
+ | Pconsider (id,hyps) ->
+ str "consider" ++ print_vars pr_constr _I env false false hyps
+ ++ spc () ++ str "from " ++ pr_constr env id
+ | Pgiven hyps ->
+ str "given" ++ print_vars pr_constr _I env false false hyps
+ | Ptake witl ->
+ str "take" ++ spc () ++
+ prlist_with_sep pr_coma (pr_constr env) witl
+ | Pdefine (id,args,body) ->
+ str "define" ++ spc () ++ pr_id id ++ spc () ++
+ prlist_with_sep spc
+ (fun st -> str "(" ++
+ pr_statement pr_constr env st ++ str ")") args ++ spc () ++
+ str "as" ++ (pr_constr env body)
+ | Pcast (id,typ) ->
+ str "reconsider" ++ spc () ++
+ pr_or_thesis (fun _ -> pr_id) env id ++ spc () ++
+ str "as" ++ (pr_constr env typ)
+ | Psuppose hyps ->
+ str "suppose" ++
+ print_hyps pr_constr _I env false false hyps
+ | Pcase (params,pat,hyps) ->
+ str "suppose it is" ++ spc () ++ pr_pat pat ++
+ (if params = [] then mt () else
+ (spc () ++ str "with" ++ spc () ++
+ prlist_with_sep spc
+ (fun st -> str "(" ++
+ pr_statement pr_constr env st ++ str ")") params ++ spc ()))
+ ++
+ (if hyps = [] then mt () else
+ (spc () ++ str "and" ++
+ print_hyps (pr_or_thesis pr_constr) type_or_thesis
+ env false false hyps))
+ | Pper (et,c) ->
+ str "per" ++ spc () ++ pr_elim_type et ++ spc () ++
+ pr_casee env c
+ | Pend (B_elim et) -> str "end" ++ spc () ++ pr_elim_type et
+ | _ -> anomaly "unprintable instruction"
+
+let pr_emph = function
+ 0 -> str " "
+ | 1 -> str "* "
+ | 2 -> str "** "
+ | 3 -> str "*** "
+ | _ -> anomaly "unknown emphasis"
+
+let pr_proof_instr env instr =
+ pr_emph instr.emph ++ spc () ++
+ pr_bare_proof_instr false false env instr.instr
+
diff --git a/parsing/ppdecl_proof.mli b/parsing/ppdecl_proof.mli
new file mode 100644
index 0000000000..b0f0e110ce
--- /dev/null
+++ b/parsing/ppdecl_proof.mli
@@ -0,0 +1,2 @@
+
+val pr_proof_instr : Environ.env -> Decl_expr.proof_instr -> Pp.std_ppcmds
diff --git a/parsing/ppvernac.ml b/parsing/ppvernac.ml
index 5e13a11245..c749223519 100644
--- a/parsing/ppvernac.ml
+++ b/parsing/ppvernac.ml
@@ -410,6 +410,7 @@ let rec pr_vernac = function
| ShowProofNames -> str"Show Conjectures"
| ShowIntros b -> str"Show " ++ (if b then str"Intros" else str"Intro")
| ShowMatch id -> str"Show Match " ++ pr_lident id
+ | ShowThesis -> str "Show Thesis"
| ExplainProof l -> str"Explain Proof" ++ spc() ++ prlist_with_sep sep int l
| ExplainTree l -> str"Explain Proof Tree" ++ spc() ++ prlist_with_sep sep int l
in pr_showable s
@@ -681,6 +682,14 @@ let rec pr_vernac = function
| VernacSolveExistential (i,c) ->
str"Existential " ++ int i ++ pr_lconstrarg c
+ (* MMode *)
+
+ | VernacProofInstr instr -> anomaly "Not implemented"
+ | VernacDeclProof -> str "proof"
+ | VernacReturn -> str "return"
+
+ (* /MMode *)
+
(* Auxiliary file and library management *)
| VernacRequireFrom (exp,spe,f) -> hov 2
(str"Require" ++ spc() ++ pr_require_token exp ++
diff --git a/parsing/printer.ml b/parsing/printer.ml
index e1c8b2505e..1b069c5ee1 100644
--- a/parsing/printer.ml
+++ b/parsing/printer.ml
@@ -23,6 +23,7 @@ open Nametab
open Ppconstr
open Evd
open Proof_type
+open Decl_mode
open Refiner
open Pfedit
open Ppconstr
@@ -108,6 +109,13 @@ let pr_evaluable_reference ref =
| EvalVarRef sp -> VarRef sp in
pr_global ref'
+(*let pr_rawterm t =
+ pr_lconstr (Constrextern.extern_rawconstr Idset.empty t)*)
+
+(*open Pattern
+
+let pr_pattern t = pr_pattern_env (Global.env()) empty_names_context t*)
+
(**********************************************************************)
(* Contexts and declarations *)
@@ -219,23 +227,53 @@ let pr_context_of env = match Options.print_hyps_limit () with
| None -> hv 0 (pr_context_unlimited env)
| Some n -> hv 0 (pr_context_limit n env)
+(* display goal parts (Proof mode) *)
+
+let pr_restricted_named_context among env =
+ hv 0 (fold_named_context
+ (fun env ((id,_,_) as d) pps ->
+ if true || Idset.mem id among then
+ pps ++
+ fnl () ++ str (emacs_str (String.make 1 (Char.chr 253))) ++
+ pr_var_decl env d
+ else
+ pps)
+ env ~init:(mt ()))
+
+let pr_subgoal_metas metas env=
+ let pr_one (meta,typ) =
+ str "?" ++ int meta ++ str " : " ++
+ hov 0 (pr_ltype_env_at_top env typ) ++ fnl () ++
+ str (emacs_str (String.make 1 (Char.chr 253))) in
+ hv 0 (prlist_with_sep mt pr_one metas)
(* display complete goal *)
let pr_goal g =
let env = evar_env g in
- let penv = pr_context_of env in
- let pc = pr_ltype_env_at_top env g.evar_concl in
- str" " ++ hv 0 (penv ++ fnl () ++
- str (emacs_str (String.make 1 (Char.chr 253))) ++
- str "============================" ++ fnl () ++
- str" " ++ pc) ++ fnl ()
-
+ let preamb,penv,pc =
+ if g.evar_extra = None then
+ mt (),
+ pr_context_of env,
+ pr_ltype_env_at_top env g.evar_concl
+ else
+ let {pm_subgoals=metas;pm_hyps=among} = get_info g in
+ (str " *** Declarative Mode ***" ++ fnl ()++fnl ()),
+ pr_restricted_named_context among env,
+ pr_subgoal_metas metas env
+ in
+ preamb ++
+ str" " ++ hv 0 (penv ++ fnl () ++
+ str (emacs_str (String.make 1 (Char.chr 253))) ++
+ str "============================" ++ fnl () ++
+ str" " ++ pc) ++ fnl ()
+
(* display the conclusion of a goal *)
let pr_concl n g =
let env = evar_env g in
let pc = pr_ltype_env_at_top env g.evar_concl in
- str (emacs_str (String.make 1 (Char.chr 253))) ++
- str "subgoal " ++ int n ++ str " is:" ++ cut () ++ str" " ++ pc
+ str (emacs_str (String.make 1 (Char.chr 253))) ++
+ str "subgoal " ++ int n ++ str " is:" ++ cut () ++ str" " ++ pc
+
(* display evar type: a context and a type *)
let pr_evgl_sign gl =
@@ -266,15 +304,22 @@ let pr_subgoal n =
prrec n
(* Print open subgoals. Checks for uninstantiated existential variables *)
-let pr_subgoals sigma = function
+let pr_subgoals close_cmd sigma = function
| [] ->
- let exl = Evarutil.non_instantiated sigma in
- if exl = [] then
- (str"Proof completed." ++ fnl ())
- else
- let pei = pr_evars_int 1 exl in
- (str "No more subgoals but non-instantiated existential " ++
- str "variables :" ++fnl () ++ (hov 0 pei))
+ begin
+ match close_cmd with
+ Some cmd ->
+ (str "Subproof completed, now type " ++ str cmd ++
+ str "." ++ fnl ())
+ | None ->
+ let exl = Evarutil.non_instantiated sigma in
+ if exl = [] then
+ (str"Proof completed." ++ fnl ())
+ else
+ let pei = pr_evars_int 1 exl in
+ (str "No more subgoals but non-instantiated existential " ++
+ str "variables :" ++fnl () ++ (hov 0 pei))
+ end
| [g] ->
let pg = pr_goal g in
v 0 (str ("1 "^"subgoal") ++cut () ++ pg)
@@ -291,12 +336,12 @@ let pr_subgoals sigma = function
v 0 (int(List.length rest+1) ++ str" subgoals" ++ cut ()
++ pg1 ++ prest ++ fnl ())
-
-let pr_subgoals_of_pfts pfts =
+let pr_subgoals_of_pfts pfts =
+ let close_cmd = Decl_mode.get_end_command pfts in
let gls = fst (Refiner.frontier (proof_of_pftreestate pfts)) in
let sigma = (top_goal_of_pftreestate pfts).sigma in
- pr_subgoals sigma gls
-
+ pr_subgoals close_cmd sigma gls
+
let pr_open_subgoals () =
let pfts = get_pftreestate () in
match focus() with
@@ -351,7 +396,6 @@ let pr_prim_rule = function
(pr_id f ++ str" : " ++ pr_lconstr ar ++ print_mut oth)
| [] -> mt () in
(str"cofix " ++ pr_id f ++ str" with " ++ print_mut others)
-
| Refine c ->
str(if occur_meta c then "refine " else "exact ") ++
Constrextern.with_meta_as_hole pr_constr c
diff --git a/parsing/printer.mli b/parsing/printer.mli
index cd9b526a48..c63d7d71f0 100644
--- a/parsing/printer.mli
+++ b/parsing/printer.mli
@@ -87,7 +87,7 @@ val pr_context_of : env -> std_ppcmds
(* Proofs *)
val pr_goal : goal -> std_ppcmds
-val pr_subgoals : evar_map -> goal list -> std_ppcmds
+val pr_subgoals : string option -> evar_map -> goal list -> std_ppcmds
val pr_subgoal : int -> goal list -> std_ppcmds
val pr_open_subgoals : unit -> std_ppcmds
diff --git a/parsing/tactic_printer.ml b/parsing/tactic_printer.ml
index c003500533..e1cc8463c3 100644
--- a/parsing/tactic_printer.ml
+++ b/parsing/tactic_printer.ml
@@ -15,6 +15,7 @@ open Evd
open Tacexpr
open Proof_type
open Proof_trees
+open Decl_expr
open Logic
open Printer
@@ -25,9 +26,19 @@ let pr_tactic = function
| t ->
Pptactic.pr_tactic (Global.env()) t
+let pr_proof_instr instr =
+ Ppdecl_proof.pr_proof_instr (Global.env()) instr
+
let pr_rule = function
| Prim r -> hov 0 (pr_prim_rule r)
- | Tactic (texp,_) -> hov 0 (pr_tactic texp)
+ | Nested(cmpd,_) ->
+ begin
+ match cmpd with
+ Tactic texp -> hov 0 (pr_tactic texp)
+ | Proof_instr (_,instr) -> hov 0 (pr_proof_instr instr)
+ end
+ | Daimon -> str "<Daimon>"
+ | Decl_proof _ -> str "proof"
| Change_evars ->
(* This is internal tactic and cannot be replayed at user-level.
Function pr_rule_dot below is used when we want to hide
@@ -52,59 +63,145 @@ let thin_sign osign sign =
sign ~init:Environ.empty_named_context_val
let rec print_proof sigma osign pf =
- let {evar_hyps=hyps; evar_concl=cl;
- evar_body=body} = pf.goal in
- let hyps = Environ.named_context_of_val hyps in
+ let hyps = Environ.named_context_of_val pf.goal.evar_hyps in
let hyps' = thin_sign osign hyps in
match pf.ref with
| None ->
- hov 0 (pr_goal {evar_hyps=hyps'; evar_concl=cl; evar_body=body})
+ hov 0 (pr_goal {pf.goal with evar_hyps=hyps'})
| Some(r,spfl) ->
hov 0
- (hov 0 (pr_goal {evar_hyps=hyps'; evar_concl=cl; evar_body=body}) ++
+ (hov 0 (pr_goal {pf.goal with evar_hyps=hyps'}) ++
spc () ++ str" BY " ++
hov 0 (pr_rule r) ++ fnl () ++
str" " ++
- hov 0 (prlist_with_sep pr_fnl (print_proof sigma hyps) spfl)
-)
+ hov 0 (prlist_with_sep pr_fnl (print_proof sigma hyps) spfl))
let pr_change gl =
- str"Change " ++
+ str"change " ++
pr_lconstr_env (Global.env_of_context gl.evar_hyps) gl.evar_concl ++ str"."
-let rec print_script nochange sigma osign pf =
- let {evar_hyps=sign; evar_concl=cl} = pf.goal in
- let sign = Environ.named_context_of_val sign in
+let rec print_decl_script tac_printer nochange sigma pf =
+ match pf.ref with
+ | None ->
+ (if nochange then
+ (str"<Your Proof Text here>")
+ else
+ pr_change pf.goal)
+ ++ fnl ()
+ | Some (Daimon,_) -> mt ()
+ | Some (Nested(Proof_instr (opened,instr),_) as rule,subprfs) ->
+ begin
+ match instr.instr,subprfs with
+ Pescape,[{ref=Some(_,subsubprfs)}] ->
+ hov 7
+ (pr_rule_dot rule ++ fnl () ++
+ prlist_with_sep pr_fnl tac_printer subsubprfs) ++ fnl () ++
+ if opened then mt () else str "return."
+ | Pclaim _,[body;cont] ->
+ hov 2
+ (pr_rule_dot rule ++ fnl () ++
+ print_decl_script tac_printer nochange sigma body) ++
+ fnl () ++
+ if opened then mt () else str "end claim." ++ fnl () ++
+ print_decl_script tac_printer nochange sigma cont
+ | Pfocus _,[body;cont] ->
+ hov 2
+ (pr_rule_dot rule ++ fnl () ++
+ print_decl_script tac_printer nochange sigma body) ++
+ fnl () ++
+ if opened then mt () else str "end focus." ++ fnl () ++
+ print_decl_script tac_printer nochange sigma cont
+ | (Psuppose _ |Pcase (_,_,_)),[body;cont] ->
+ hov 2
+ (pr_rule_dot rule ++ fnl () ++
+ print_decl_script tac_printer nochange sigma body) ++
+ fnl () ++
+ print_decl_script tac_printer nochange sigma cont
+ | _,[next] ->
+ pr_rule_dot rule ++ fnl () ++
+ print_decl_script tac_printer nochange sigma next
+ | _,[] ->
+ pr_rule_dot rule
+ | _,_ -> anomaly "unknown branching instruction"
+ end
+ | _ -> anomaly "Not Applicable"
+
+let rec print_script nochange sigma pf =
match pf.ref with
| None ->
(if nochange then
- (str"<Your Tactic Text here>")
- else
- pr_change pf.goal)
+ (str"<Your Tactic Text here>")
+ else
+ pr_change pf.goal)
++ fnl ()
- | Some(r,spfl) ->
- ((if nochange then (mt ()) else (pr_change pf.goal ++ fnl ())) ++
- pr_rule_dot r ++ fnl () ++
- prlist_with_sep pr_fnl
- (print_script nochange sigma sign) spfl)
+ | Some(Decl_proof opened,script) ->
+ assert (List.length script = 1);
+ begin
+ if nochange then (mt ()) else (pr_change pf.goal ++ fnl ())
+ end ++
+ begin
+ hov 0 (str "proof." ++ fnl () ++
+ print_decl_script (print_script nochange sigma)
+ nochange sigma (List.hd script))
+ end ++ fnl () ++
+ begin
+ if opened then mt () else (str "end proof." ++ fnl ())
+ end
+ | Some(Daimon,spfl) ->
+ ((if nochange then (mt ()) else (pr_change pf.goal ++ fnl ())) ++
+ prlist_with_sep pr_fnl
+ (print_script nochange sigma) spfl )
+ | Some(rule,spfl) ->
+ ((if nochange then (mt ()) else (pr_change pf.goal ++ fnl ())) ++
+ pr_rule_dot rule ++ fnl () ++
+ prlist_with_sep pr_fnl
+ (print_script nochange sigma) spfl )
(* printed by Show Script command *)
-let print_treescript nochange sigma _osign pf =
+
+let print_treescript nochange sigma pf =
let rec aux top pf =
match pf.ref with
| None ->
if nochange then
- (str"<Your Tactic Text here>")
+ if pf.goal.evar_extra=None then
+ (str"<Your Tactic Text here>")
+ else (str"<Your Proof Text here>")
else
(pr_change pf.goal)
+ | Some(Decl_proof opened,script) ->
+ assert (List.length script = 1);
+ begin
+ if nochange then (mt ()) else (pr_change pf.goal ++ fnl ())
+ end ++
+ hov 0
+ begin str "proof." ++ fnl () ++
+ print_decl_script (aux false)
+ nochange sigma (List.hd script)
+ end ++ fnl () ++
+ begin
+ if opened then mt () else (str "end proof." ++ fnl ())
+ end
+ | Some(Daimon,spfl) ->
+ ((if nochange then (mt ()) else (pr_change pf.goal ++ fnl ())) ++
+ prlist_with_sep pr_fnl
+ (print_script nochange sigma) spfl )
| Some(r,spfl) ->
(if nochange then mt () else (pr_change pf.goal ++ fnl ())) ++
- pr_rule_dot r ++
- match spfl with
- | [] -> mt ()
- | [spf] -> fnl () ++ (if top then mt () else str " ") ++ aux top spf
- | _ -> fnl () ++ str " " ++
- hov 0 (prlist_with_sep fnl (aux false) spfl)
+ pr_rule_dot r ++ fnl () ++
+ begin
+ if List.length spfl > 1 then
+ fnl () ++
+ str " " ++ hov 0 (aux false (List.hd spfl)) ++ fnl () ++
+ hov 0 (prlist_with_sep fnl (aux false) (List.tl spfl))
+ else
+ match spfl with
+ | [] -> mt ()
+ | [spf] -> fnl () ++
+ (if top then mt () else str " ") ++ aux top spf
+ | _ -> fnl () ++ str " " ++
+ hov 0 (prlist_with_sep fnl (aux false) spfl)
+ end
in hov 0 (aux true pf)
let rec print_info_script sigma osign pf =
diff --git a/parsing/tactic_printer.mli b/parsing/tactic_printer.mli
index b4ad0143ef..4e78a96875 100644
--- a/parsing/tactic_printer.mli
+++ b/parsing/tactic_printer.mli
@@ -22,6 +22,6 @@ val print_proof : evar_map -> named_context -> proof_tree -> std_ppcmds
val pr_rule : rule -> std_ppcmds
val pr_tactic : tactic_expr -> std_ppcmds
val print_script :
- bool -> evar_map -> named_context -> proof_tree -> std_ppcmds
+ bool -> evar_map -> proof_tree -> std_ppcmds
val print_treescript :
- bool -> evar_map -> named_context -> proof_tree -> std_ppcmds
+ bool -> evar_map -> proof_tree -> std_ppcmds
diff --git a/pretyping/evarutil.ml b/pretyping/evarutil.ml
index 262214c3a7..16227d4ba6 100644
--- a/pretyping/evarutil.ml
+++ b/pretyping/evarutil.ml
@@ -56,9 +56,9 @@ let jv_nf_evar = Pretype_errors.jv_nf_evar
let tj_nf_evar = Pretype_errors.tj_nf_evar
let nf_evar_info evc info =
- { evar_concl = Reductionops.nf_evar evc info.evar_concl;
- evar_hyps = map_named_val (Reductionops.nf_evar evc) info.evar_hyps;
- evar_body = info.evar_body}
+ { info with
+ evar_concl = Reductionops.nf_evar evc info.evar_concl;
+ evar_hyps = map_named_val (Reductionops.nf_evar evc) info.evar_hyps}
let nf_evars evm = Evd.fold (fun ev evi evm' -> Evd.add evm' ev (nf_evar_info evm evi))
evm Evd.empty
diff --git a/pretyping/evd.ml b/pretyping/evd.ml
index 8b7f82cc33..5a353978d4 100644
--- a/pretyping/evd.ml
+++ b/pretyping/evd.ml
@@ -30,7 +30,8 @@ type evar_body =
type evar_info = {
evar_concl : constr;
evar_hyps : named_context_val;
- evar_body : evar_body}
+ evar_body : evar_body;
+ evar_extra : Dyn.t option}
let evar_context evi = named_context_of_val evi.evar_hyps
@@ -64,9 +65,8 @@ let define evd ev body =
try find evd ev
with Not_found -> error "Evd.define: cannot define undeclared evar" in
let newinfo =
- { evar_concl = oldinfo.evar_concl;
- evar_hyps = oldinfo.evar_hyps;
- evar_body = Evar_defined body} in
+ { oldinfo with
+ evar_body = Evar_defined body } in
match oldinfo.evar_body with
| Evar_empty -> Evarmap.add ev newinfo evd
| _ -> anomaly "Evd.define: cannot define an isevar twice"
@@ -393,7 +393,10 @@ let evar_define sp body isevars =
let evar_declare hyps evn ty ?(src=(dummy_loc,InternalHole)) evd =
{ evd with
evars = add evd.evars evn
- {evar_hyps=hyps; evar_concl=ty; evar_body=Evar_empty};
+ {evar_hyps=hyps;
+ evar_concl=ty;
+ evar_body=Evar_empty;
+ evar_extra=None};
history = (evn,src)::evd.history }
let is_defined_evar isevars (n,_) = is_defined isevars.evars n
diff --git a/pretyping/evd.mli b/pretyping/evd.mli
index 6481ff2012..601c6c8b03 100644
--- a/pretyping/evd.mli
+++ b/pretyping/evd.mli
@@ -32,7 +32,8 @@ type evar_body =
type evar_info = {
evar_concl : constr;
evar_hyps : Environ.named_context_val;
- evar_body : evar_body}
+ evar_body : evar_body;
+ evar_extra : Dyn.t option}
val eq_evar_info : evar_info -> evar_info -> bool
val evar_context : evar_info -> named_context
@@ -94,6 +95,7 @@ type 'a freelisted = {
rebus : 'a;
freemetas : Metaset.t }
+val metavars_of : constr -> Metaset.t
val mk_freelisted : constr -> constr freelisted
val map_fl : ('a -> 'b) -> 'a freelisted -> 'b freelisted
diff --git a/proofs/decl_expr.mli b/proofs/decl_expr.mli
new file mode 100644
index 0000000000..24af3842cb
--- /dev/null
+++ b/proofs/decl_expr.mli
@@ -0,0 +1,108 @@
+(************************************************************************)
+(* v * The Coq Proof Assistant / The Coq Development Team *)
+(* <O___,, * CNRS-Ecole Polytechnique-INRIA Futurs-Universite Paris Sud *)
+(* \VV/ **************************************************************)
+(* // * This file is distributed under the terms of the *)
+(* * GNU Lesser General Public License Version 2.1 *)
+(************************************************************************)
+
+(* $Id:$ *)
+
+open Names
+open Util
+open Tacexpr
+
+type ('constr,'tac) justification =
+ By_tactic of 'tac
+| Automated of 'constr list
+
+type 'it statement =
+ {st_label:name;
+ st_it:'it}
+
+type thesis_kind =
+ Plain
+ | Sub of int
+ | For of identifier
+
+type 'this or_thesis =
+ This of 'this
+ | Thesis of thesis_kind
+
+type side = Lhs | Rhs
+
+type elim_type =
+ ET_Case_analysis
+ | ET_Induction
+
+type block_type =
+ B_proof
+ | B_claim
+ | B_focus
+ | B_elim of elim_type
+
+type ('it,'constr,'tac) cut =
+ {cut_stat: 'it statement;
+ cut_by: ('constr,'tac) justification}
+
+type ('var,'constr) hyp =
+ Hvar of 'var
+ | Hprop of 'constr statement
+
+type ('constr,'tac) casee =
+ Real of 'constr
+ | Virtual of ('constr,'constr,'tac) cut
+
+type ('hyp,'constr,'pat,'tac) bare_proof_instr =
+ | Pthen of ('hyp,'constr,'pat,'tac) bare_proof_instr
+ | Pthus of ('hyp,'constr,'pat,'tac) bare_proof_instr
+ | Phence of ('hyp,'constr,'pat,'tac) bare_proof_instr
+ | Pcut of ('constr or_thesis,'constr,'tac) cut
+ | Prew of side * ('constr,'constr,'tac) cut
+ | Passume of ('hyp,'constr) hyp list
+ | Plet of ('hyp,'constr) hyp list
+ | Pgiven of ('hyp,'constr) hyp list
+ | Pconsider of 'constr*('hyp,'constr) hyp list
+ | Pclaim of 'constr statement
+ | Pfocus of 'constr statement
+ | Pdefine of identifier * 'hyp list * 'constr
+ | Pcast of identifier or_thesis * 'constr
+ | Psuppose of ('hyp,'constr) hyp list
+ | Pcase of 'hyp list*'pat*(('hyp,'constr or_thesis) hyp list)
+ | Ptake of 'constr list
+ | Pper of elim_type * ('constr,'tac) casee
+ | Pend of block_type
+ | Pescape
+
+type emphasis = int
+
+type ('hyp,'constr,'pat,'tac) gen_proof_instr=
+ {emph: emphasis;
+ instr: ('hyp,'constr,'pat,'tac) bare_proof_instr }
+
+
+type raw_proof_instr =
+ ((identifier*(Topconstr.constr_expr option)) located,
+ Topconstr.constr_expr,
+ Topconstr.cases_pattern_expr,
+ raw_tactic_expr) gen_proof_instr
+
+type glob_proof_instr =
+ ((identifier*(Genarg.rawconstr_and_expr option)) located,
+ Genarg.rawconstr_and_expr,
+ Topconstr.cases_pattern_expr,
+ Tacexpr.glob_tactic_expr) gen_proof_instr
+
+type proof_pattern =
+ {pat_vars: Term.types statement list;
+ pat_aliases: (Term.constr*Term.types) statement list;
+ pat_constr: Term.constr;
+ pat_typ: Term.types;
+ pat_pat: Rawterm.cases_pattern;
+ pat_expr: Topconstr.cases_pattern_expr}
+
+type proof_instr =
+ (Term.constr statement,
+ Term.constr,
+ proof_pattern,
+ Tacexpr.glob_tactic_expr) gen_proof_instr
diff --git a/proofs/decl_mode.ml b/proofs/decl_mode.ml
new file mode 100644
index 0000000000..094c562532
--- /dev/null
+++ b/proofs/decl_mode.ml
@@ -0,0 +1,121 @@
+(************************************************************************)
+(* v * The Coq Proof Assistant / The Coq Development Team *)
+(* <O___,, * CNRS-Ecole Polytechnique-INRIA Futurs-Universite Paris Sud *)
+(* \VV/ **************************************************************)
+(* // * This file is distributed under the terms of the *)
+(* * GNU Lesser General Public License Version 2.1 *)
+(************************************************************************)
+
+(* $Id:$ *)
+
+open Names
+open Term
+open Evd
+open Util
+
+let daimon_flag = ref false
+
+let set_daimon_flag () = daimon_flag:=true
+let clear_daimon_flag () = daimon_flag:=false
+let get_daimon_flag () = !daimon_flag
+
+type command_mode =
+ Mode_tactic
+ | Mode_proof
+ | Mode_none
+
+let mode_of_pftreestate pts =
+ let goal = sig_it (Refiner.top_goal_of_pftreestate pts) in
+ if goal.evar_extra = None then
+ Mode_tactic
+ else
+ Mode_proof
+
+let get_current_mode () =
+ try
+ mode_of_pftreestate (Pfedit.get_pftreestate ())
+ with _ -> Mode_none
+
+let check_not_proof_mode str =
+ if get_current_mode () = Mode_proof then
+ error str
+
+type split_tree=
+ Push of (Idset.t * split_tree)
+ | Split of (Idset.t * inductive * (Idset.t * split_tree) option array)
+ | Pop of split_tree
+ | End_of_branch of (identifier * int)
+
+type elim_kind =
+ EK_dep of split_tree
+ | EK_nodep
+ | EK_unknown
+
+type per_info =
+ {per_casee:constr;
+ per_ctype:types;
+ per_ind:inductive;
+ per_pred:constr;
+ per_args:constr list;
+ per_params:constr list;
+ per_nparams:int}
+
+type stack_info =
+ Per of Decl_expr.elim_type * per_info * elim_kind * identifier list
+ | Suppose_case
+ | Claim
+ | Focus_claim
+
+type pm_info =
+ { pm_last: Names.name (* anonymous if none *);
+ pm_hyps: Idset.t;
+ pm_partial_goal : constr ; (* partial goal construction *)
+ pm_subgoals : (metavariable*constr) list;
+ pm_stack : stack_info list }
+
+let pm_in,pm_out = Dyn.create "pm_info"
+
+let get_info gl=
+ match gl.evar_extra with
+ None -> invalid_arg "get_info"
+ | Some extra ->
+ try pm_out extra with _ -> invalid_arg "get_info"
+
+let get_stack pts =
+ let info = get_info (sig_it (Refiner.nth_goal_of_pftreestate 1 pts)) in
+ info.pm_stack
+
+let get_top_stack pts =
+ let info = get_info (sig_it (Refiner.top_goal_of_pftreestate pts)) in
+ info.pm_stack
+
+let get_end_command pts =
+ match mode_of_pftreestate pts with
+ Mode_proof ->
+ Some
+ begin
+ match get_top_stack pts with
+ [] -> "\"end proof\""
+ | Claim::_ -> "\"end claim\""
+ | Focus_claim::_-> "\"end focus\""
+ | (Suppose_case :: Per (et,_,_,_) :: _
+ | Per (et,_,_,_) :: _ ) ->
+ begin
+ match et with
+ Decl_expr.ET_Case_analysis ->
+ "\"end cases\" or start a new case"
+ | Decl_expr.ET_Induction ->
+ "\"end induction\" or start a new case"
+ end
+ | _ -> anomaly "lonely suppose"
+ end
+ | Mode_tactic ->
+ begin
+ try
+ ignore
+ (Refiner.up_until_matching_rule Proof_trees.is_proof_instr pts);
+ Some "\"return\""
+ with Not_found -> None
+ end
+ | Mode_none ->
+ error "no proof in progress"
diff --git a/proofs/decl_mode.mli b/proofs/decl_mode.mli
new file mode 100644
index 0000000000..0dd1cb33c3
--- /dev/null
+++ b/proofs/decl_mode.mli
@@ -0,0 +1,73 @@
+(************************************************************************)
+(* v * The Coq Proof Assistant / The Coq Development Team *)
+(* <O___,, * CNRS-Ecole Polytechnique-INRIA Futurs-Universite Paris Sud *)
+(* \VV/ **************************************************************)
+(* // * This file is distributed under the terms of the *)
+(* * GNU Lesser General Public License Version 2.1 *)
+(************************************************************************)
+
+(* $Id:$ *)
+
+open Names
+open Term
+open Evd
+open Tacmach
+
+val set_daimon_flag : unit -> unit
+val clear_daimon_flag : unit -> unit
+val get_daimon_flag : unit -> bool
+
+type command_mode =
+ Mode_tactic
+ | Mode_proof
+ | Mode_none
+
+val mode_of_pftreestate : pftreestate -> command_mode
+
+val get_current_mode : unit -> command_mode
+
+val check_not_proof_mode : string -> unit
+
+type split_tree=
+ Push of (Idset.t * split_tree)
+ | Split of (Idset.t * inductive * (Idset.t*split_tree) option array)
+ | Pop of split_tree
+ | End_of_branch of (identifier * int)
+
+type elim_kind =
+ EK_dep of split_tree
+ | EK_nodep
+ | EK_unknown
+
+
+type per_info =
+ {per_casee:constr;
+ per_ctype:types;
+ per_ind:inductive;
+ per_pred:constr;
+ per_args:constr list;
+ per_params:constr list;
+ per_nparams:int}
+
+type stack_info =
+ Per of Decl_expr.elim_type * per_info * elim_kind * Names.identifier list
+ | Suppose_case
+ | Claim
+ | Focus_claim
+
+type pm_info =
+ { pm_last: Names.name (* anonymous if none *);
+ pm_hyps: Idset.t;
+ pm_partial_goal : constr ; (* partial goal construction *)
+ pm_subgoals : (metavariable*constr) list;
+ pm_stack : stack_info list }
+
+val pm_in : pm_info -> Dyn.t
+
+val get_info : Proof_type.goal -> pm_info
+
+val get_end_command : pftreestate -> string option
+
+val get_stack : pftreestate -> stack_info list
+
+val get_top_stack : pftreestate -> stack_info list
diff --git a/proofs/evar_refiner.ml b/proofs/evar_refiner.ml
index d5ea25bd30..b0f933a504 100644
--- a/proofs/evar_refiner.ml
+++ b/proofs/evar_refiner.ml
@@ -22,7 +22,7 @@ open Refiner
(* w_tactic pour instantiate *)
-let w_refine env ev rawc evd =
+let w_refine ev rawc evd =
if Evd.is_defined (evars_of evd) ev then
error "Instantiate called on already-defined evar";
let e_info = Evd.find (evars_of evd) ev in
@@ -45,5 +45,5 @@ let instantiate_pf_com n com pfts =
let env = Evd.evar_env evi in
let rawc = Constrintern.intern_constr sigma env com in
let evd = create_evar_defs sigma in
- let evd' = w_refine env sp rawc evd in
+ let evd' = w_refine sp rawc evd in
change_constraints_pftreestate (evars_of evd') pfts
diff --git a/proofs/evar_refiner.mli b/proofs/evar_refiner.mli
index 090671e046..7b9da802c1 100644
--- a/proofs/evar_refiner.mli
+++ b/proofs/evar_refiner.mli
@@ -18,7 +18,7 @@ open Refiner
(* Refinement of existential variables. *)
-val w_refine : env -> evar -> Rawterm.rawconstr -> evar_defs -> evar_defs
+val w_refine : evar -> Rawterm.rawconstr -> evar_defs -> evar_defs
val instantiate_pf_com :
int -> Topconstr.constr_expr -> pftreestate -> pftreestate
diff --git a/proofs/logic.ml b/proofs/logic.ml
index 209c3bb65f..b5c8011051 100644
--- a/proofs/logic.ml
+++ b/proofs/logic.ml
@@ -88,7 +88,7 @@ let clear_hyps ids gl =
if List.mem id' cleared_ids then
error (string_of_id id'^" is used in conclusion"))
(global_vars_set env ncl);
- mk_goal nhyps ncl
+ mk_goal nhyps ncl gl.evar_extra
(* The ClearBody tactic *)
@@ -264,6 +264,7 @@ let goal_type_of env sigma c =
let rec mk_refgoals sigma goal goalacc conclty trm =
let env = evar_env goal in
let hyps = goal.evar_hyps in
+ let mk_goal hyps concl = mk_goal hyps concl goal.evar_extra in
(*
if not (occur_meta trm) then
let t'ty = (unsafe_machine env sigma trm).uj_type in
@@ -315,6 +316,7 @@ let rec mk_refgoals sigma goal goalacc conclty trm =
and mk_hdgoals sigma goal goalacc trm =
let env = evar_env goal in
let hyps = goal.evar_hyps in
+ let mk_goal hyps concl = mk_goal hyps concl goal.evar_extra in
match kind_of_term trm with
| Cast (c,_, ty) when isMeta c ->
check_typability env sigma ty;
@@ -392,6 +394,7 @@ let prim_refiner r sigma goal =
let env = evar_env goal in
let sign = goal.evar_hyps in
let cl = goal.evar_concl in
+ let mk_goal hyps concl = mk_goal hyps concl goal.evar_extra in
match r with
(* Logical rules *)
| Intro id ->
@@ -474,7 +477,8 @@ let prim_refiner r sigma goal =
let _ = find_coinductive env sigma b in ()
with Not_found ->
error ("All methods must construct elements " ^
- "in coinductive types")
+ "in coinductiv-> goal
+e types")
in
let all = (f,cl)::others in
List.iter (fun (_,c) -> check_is_coind env c) all;
diff --git a/proofs/pfedit.ml b/proofs/pfedit.ml
index f724589f69..c6cb86dc92 100644
--- a/proofs/pfedit.ml
+++ b/proofs/pfedit.ml
@@ -150,6 +150,14 @@ let subtree_solved () =
is_complete_proof (proof_of_pftreestate pts) &
not (is_top_pftreestate pts)
+let tree_solved () =
+ let pts = get_pftreestate () in
+ is_complete_proof (proof_of_pftreestate pts)
+
+let top_tree_solved () =
+ let pts = get_pftreestate () in
+ is_complete_proof (proof_of_pftreestate (top_of_tree pts))
+
(*********************************************************************)
(* Undo functions *)
(*********************************************************************)
@@ -243,7 +251,7 @@ let set_end_tac tac =
(*********************************************************************)
let start_proof na str sign concl hook =
- let top_goal = mk_goal sign concl in
+ let top_goal = mk_goal sign concl None in
let ts = {
top_end_tac = None;
top_goal = top_goal;
@@ -253,7 +261,6 @@ let start_proof na str sign concl hook =
start(na,ts);
set_current_proof na
-
let solve_nth k tac =
let pft = get_pftreestate () in
if not (List.mem (-1) (cursor_of_pftreestate pft)) then
@@ -309,7 +316,6 @@ let traverse_prev_unproven () = mutate prev_unproven
let traverse_next_unproven () = mutate next_unproven
-
(* The goal focused on *)
let focus_n = ref 0
let make_focus n = focus_n := n
@@ -317,5 +323,11 @@ let focus () = !focus_n
let focused_goal () = let n = !focus_n in if n=0 then 1 else n
let reset_top_of_tree () =
- let pts = get_pftreestate () in
- if not (is_top_pftreestate pts) then mutate top_of_tree
+ mutate top_of_tree
+
+let reset_top_of_script () =
+ mutate (fun pts ->
+ try
+ up_until_matching_rule is_proof_instr pts
+ with Not_found -> top_of_tree pts)
+
diff --git a/proofs/pfedit.mli b/proofs/pfedit.mli
index 8871e7e00c..c3d531c692 100644
--- a/proofs/pfedit.mli
+++ b/proofs/pfedit.mli
@@ -172,8 +172,12 @@ val make_focus : int -> unit
val focus : unit -> int
val focused_goal : unit -> int
val subtree_solved : unit -> bool
+val tree_solved : unit -> bool
+val top_tree_solved : unit -> bool
val reset_top_of_tree : unit -> unit
+val reset_top_of_script : unit -> unit
+
val traverse : int -> unit
val traverse_nth_goal : int -> unit
val traverse_next_unproven : unit -> unit
diff --git a/proofs/proof_trees.ml b/proofs/proof_trees.ml
index 73cc5d2736..c7a32682aa 100644
--- a/proofs/proof_trees.ml
+++ b/proofs/proof_trees.ml
@@ -18,6 +18,7 @@ open Sign
open Evd
open Environ
open Evarutil
+open Decl_expr
open Proof_type
open Tacred
open Typing
@@ -32,9 +33,9 @@ let is_bind = function
(* Functions on goals *)
-let mk_goal hyps cl =
+let mk_goal hyps cl extra =
{ evar_hyps = hyps; evar_concl = cl;
- evar_body = Evar_empty}
+ evar_body = Evar_empty; evar_extra = extra }
(* Functions on proof trees *)
@@ -52,7 +53,7 @@ let children_of_proof pf =
let goal_of_proof pf = pf.goal
let subproof_of_proof pf = match pf.ref with
- | Some (Tactic (_,pf), _) -> pf
+ | Some (Nested (_,pf), _) -> pf
| _ -> failwith "subproof_of_proof"
let status_of_proof pf = pf.open_subgoals
@@ -62,7 +63,7 @@ let is_complete_proof pf = pf.open_subgoals = 0
let is_leaf_proof pf = (pf.ref = None)
let is_tactic_proof pf = match pf.ref with
- | Some (Tactic _, _) -> true
+ | Some (Nested (Tactic _,_),_) -> true
| _ -> false
@@ -72,6 +73,22 @@ let pf_lookup_name_as_renamed env ccl s =
let pf_lookup_index_as_renamed env ccl n =
Detyping.lookup_index_as_renamed env ccl n
+(* Functions on rules (Proof mode) *)
+
+let is_dem_rule = function
+ Decl_proof _ -> true
+ | _ -> false
+
+let is_proof_instr = function
+ Nested(Proof_instr (_,_),_) -> true
+ | _ -> false
+
+let is_focussing_command = function
+ Decl_proof b -> b
+ | Nested (Proof_instr (b,_),_) -> b
+ | _ -> false
+
+
(*********************************************************************)
(* Pretty printing functions *)
(*********************************************************************)
diff --git a/proofs/proof_trees.mli b/proofs/proof_trees.mli
index 1b691e2584..dcbddbd9e8 100644
--- a/proofs/proof_trees.mli
+++ b/proofs/proof_trees.mli
@@ -21,7 +21,7 @@ open Proof_type
(* This module declares readable constraints, and a few utilities on
constraints and proof trees *)
-val mk_goal : named_context_val -> constr -> goal
+val mk_goal : named_context_val -> constr -> Dyn.t option -> goal
val rule_of_proof : proof_tree -> rule
val ref_of_proof : proof_tree -> (rule * proof_tree list)
@@ -36,6 +36,8 @@ val is_tactic_proof : proof_tree -> bool
val pf_lookup_name_as_renamed : env -> constr -> identifier -> int option
val pf_lookup_index_as_renamed : env -> constr -> int -> int option
+val is_proof_instr : rule -> bool
+val is_focussing_command : rule -> bool
(*s Pretty printing functions. *)
diff --git a/proofs/proof_type.ml b/proofs/proof_type.ml
index db3c0e7e25..4037237026 100644
--- a/proofs/proof_type.ml
+++ b/proofs/proof_type.ml
@@ -16,6 +16,7 @@ open Libnames
open Term
open Util
open Tacexpr
+open Decl_expr
open Rawterm
open Genarg
open Nametab
@@ -52,9 +53,15 @@ type proof_tree = {
and rule =
| Prim of prim_rule
- | Tactic of tactic_expr * proof_tree
+ | Nested of compound_rule * proof_tree
+ | Decl_proof of bool
+ | Daimon
| Change_evars
+and compound_rule=
+ | Tactic of tactic_expr
+ | Proof_instr of bool*proof_instr (* the boolean is for focus restrictions *)
+
and goal = evar_info
and tactic = goal sigma -> (goal list sigma * validation)
diff --git a/proofs/proof_type.mli b/proofs/proof_type.mli
index e222730582..74c36c9811 100644
--- a/proofs/proof_type.mli
+++ b/proofs/proof_type.mli
@@ -16,6 +16,7 @@ open Libnames
open Term
open Util
open Tacexpr
+open Decl_expr
open Rawterm
open Genarg
open Nametab
@@ -46,7 +47,7 @@ type prim_rule =
evar_body = Evar_Empty;
evar_info = { pgm : [The Realizer pgm if any]
lc : [Set of evar num occurring in subgoal] }}
- sigma = { stamp = [an int characterizing the ed field, for quick compare]
+ sigma = { stamp = [an int chardacterizing the ed field, for quick compare]
ed : [A set of existential variables depending in the subgoal]
number of first evar,
it = { evar_concl = [the type of first evar]
@@ -80,9 +81,15 @@ type proof_tree = {
and rule =
| Prim of prim_rule
- | Tactic of tactic_expr * proof_tree
+ | Nested of compound_rule * proof_tree
+ | Decl_proof of bool
+ | Daimon
| Change_evars
+and compound_rule=
+ | Tactic of tactic_expr
+ | Proof_instr of bool * proof_instr
+
and goal = evar_info
and tactic = goal sigma -> (goal list sigma * validation)
diff --git a/proofs/refiner.ml b/proofs/refiner.ml
index ee4b672a18..48c9238e05 100644
--- a/proofs/refiner.ml
+++ b/proofs/refiner.ml
@@ -50,10 +50,10 @@ let norm_goal sigma gl =
let red_fun = Evarutil.nf_evar sigma in
let ncl = red_fun gl.evar_concl in
let ngl =
- { evar_concl = ncl;
- evar_hyps = map_named_val red_fun gl.evar_hyps;
- evar_body = gl.evar_body} in
- if Evd.eq_evar_info ngl gl then None else Some ngl
+ { gl with
+ evar_concl = ncl;
+ evar_hyps = map_named_val red_fun gl.evar_hyps } in
+ if Evd.eq_evar_info ngl gl then None else Some ngl
(* [mapshape [ l1 ; ... ; lk ] [ v1 ; ... ; vk ] [ p_1 ; .... ; p_(l1+...+lk) ]]
@@ -91,9 +91,9 @@ let rec frontier p =
(List.flatten gll,
(fun retpfl ->
let pfl' = mapshape (List.map List.length gll) vl retpfl in
- { open_subgoals = and_status (List.map pf_status pfl');
- goal = p.goal;
- ref = Some(r,pfl')}))
+ { p with
+ open_subgoals = and_status (List.map pf_status pfl');
+ ref = Some(r,pfl')}))
let rec frontier_map_rec f n p =
@@ -111,9 +111,9 @@ let rec frontier_map_rec f n p =
(fun (n,acc) p -> (n-p.open_subgoals,frontier_map_rec f n p::acc))
(n,[]) pfl in
let pfl' = List.rev rpfl' in
- { open_subgoals = and_status (List.map pf_status pfl');
- goal = p.goal;
- ref = Some(r,pfl')}
+ { p with
+ open_subgoals = and_status (List.map pf_status pfl');
+ ref = Some(r,pfl')}
let frontier_map f n p =
let nmax = p.open_subgoals in
@@ -137,9 +137,9 @@ let rec frontier_mapi_rec f i p =
(fun (n,acc) p -> (n+p.open_subgoals,frontier_mapi_rec f n p::acc))
(i,[]) pfl in
let pfl' = List.rev rpfl' in
- { open_subgoals = and_status (List.map pf_status pfl');
- goal = p.goal;
- ref = Some(r,pfl')}
+ { p with
+ open_subgoals = and_status (List.map pf_status pfl');
+ ref = Some(r,pfl')}
let frontier_mapi f p = frontier_mapi_rec f 1 p
@@ -152,10 +152,10 @@ let rec nb_unsolved_goals pf = pf.open_subgoals
(* leaf g is the canonical incomplete proof of a goal g *)
-let leaf g = {
- open_subgoals = 1;
- goal = g;
- ref = None }
+let leaf g =
+ { open_subgoals = 1;
+ goal = g;
+ ref = None }
(* Tactics table. *)
@@ -187,15 +187,19 @@ let lookup_tactic s =
let check_subproof_connection gl spfl =
list_for_all2eq (fun g pf -> Evd.eq_evar_info g pf.goal) gl spfl
-let abstract_tactic_expr te tacfun gls =
- let (sgl_sigma,v) = tacfun gls in
- let hidden_proof = v (List.map leaf sgl_sigma.it) in
+
+let abstract_operation syntax semantics gls =
+ let (sgl_sigma,validation) = semantics gls in
+ let hidden_proof = validation (List.map leaf sgl_sigma.it) in
(sgl_sigma,
fun spfl ->
assert (check_subproof_connection sgl_sigma.it spfl);
{ open_subgoals = and_status (List.map pf_status spfl);
goal = gls.it;
- ref = Some(Tactic(te,hidden_proof),spfl) })
+ ref = Some(Nested(syntax,hidden_proof),spfl)})
+
+let abstract_tactic_expr te tacfun gls =
+ abstract_operation (Tactic te) tacfun gls
let refiner = function
| Prim pr as r ->
@@ -209,8 +213,21 @@ let refiner = function
goal = goal_sigma.it;
ref = Some(r,spfl) })))
- | Tactic _ -> failwith "Refiner: should not occur"
+
+ | Nested (_,_) | Decl_proof _ ->
+ failwith "Refiner: should not occur"
+ (* Daimon is a canonical unfinished proof *)
+
+ | Daimon ->
+ fun gls ->
+ ({it=[];sigma=gls.sigma},
+ fun spfl ->
+ assert (spfl=[]);
+ { open_subgoals = 0;
+ goal = gls.it;
+ ref = Some(Daimon,[])})
+
(* [Local_constraints lc] makes the local constraints be [lc] and
normalizes evars *)
@@ -271,14 +288,16 @@ let extract_open_proof sigma pf =
let rec proof_extractor vl = function
| {ref=Some(Prim _,_)} as pf -> prim_extractor proof_extractor vl pf
- | {ref=Some(Tactic (_,hidden_proof),spfl)} ->
+ | {ref=Some(Nested(_,hidden_proof),spfl)} ->
let sgl,v = frontier hidden_proof in
let flat_proof = v spfl in
proof_extractor vl flat_proof
-
+
| {ref=Some(Change_evars,[pf])} -> (proof_extractor vl) pf
+
+ | {ref=Some(Decl_proof _,[pf])} -> (proof_extractor vl) pf
- | {ref=None;goal=goal} ->
+ | {ref=(None|Some(Daimon,[]));goal=goal} ->
let visible_rels =
map_succeed
(fun id ->
@@ -680,9 +699,9 @@ let descend n p =
let pf' = List.hd pfl' in
let spfl = left@(pf'::right) in
let newstatus = and_status (List.map pf_status spfl) in
- { open_subgoals = newstatus;
- goal = p.goal;
- ref = Some(r,spfl) }
+ { p with
+ open_subgoals = newstatus;
+ ref = Some(r,spfl) }
else
error "descend: validation"))
| _ -> assert false)
@@ -699,7 +718,7 @@ let traverse n pts = match n with
tpfsigma = pts.tpfsigma })
| -1 -> (* go to the hidden tactic-proof, if any, otherwise fail *)
(match pts.tpf.ref with
- | Some (Tactic (_,spf),_) ->
+ | Some (Nested (_,spf),_) ->
let v = (fun pfl -> pts.tpf) in
{ tpf = spf;
tstack = (-1,v)::pts.tstack;
@@ -718,10 +737,11 @@ let app_tac sigr tac p =
sigr := gll.sigma;
v (List.map leaf gll.it)
-(* solve the nth subgoal with tactic tac *)
-let solve_nth_pftreestate n tac pts =
+(* modify proof state at current position *)
+
+let map_pftreestate f pts =
let sigr = ref pts.tpfsigma in
- let tpf' = frontier_map (app_tac sigr tac) n pts.tpf in
+ let tpf' = f sigr pts.tpf in
let tpf'' =
if !sigr == pts.tpfsigma then tpf'
else frontier_mapi (fun _ g -> app_tac sigr norm_evar_tac g) tpf' in
@@ -729,6 +749,12 @@ let solve_nth_pftreestate n tac pts =
tpfsigma = !sigr;
tstack = pts.tstack }
+(* solve the nth subgoal with tactic tac *)
+
+let solve_nth_pftreestate n tac =
+ map_pftreestate
+ (fun sigr pt -> frontier_map (app_tac sigr tac) n pt)
+
let solve_pftreestate = solve_nth_pftreestate 1
(* This function implements a poor man's undo at the current goal.
@@ -880,6 +906,38 @@ let prev_unproven pts =
let rec top_of_tree pts =
if is_top_pftreestate pts then pts else top_of_tree(traverse 0 pts)
+let change_rule f pts =
+ let mark_top _ pt =
+ match pt.ref with
+ Some (oldrule,l) ->
+ {pt with ref=Some (f oldrule,l)}
+ | _ -> invalid_arg "change_rule" in
+ map_pftreestate mark_top pts
+
+let match_rule p pts =
+ match (proof_of_pftreestate pts).ref with
+ Some (r,_) -> p r
+ | None -> false
+
+let rec up_until_matching_rule p pts =
+ if is_top_pftreestate pts then
+ raise Not_found
+ else
+ let one_up = traverse 0 pts in
+ if match_rule p one_up then
+ pts
+ else
+ up_until_matching_rule p one_up
+
+let rec up_to_matching_rule p pts =
+ if match_rule p pts then
+ pts
+ else
+ if is_top_pftreestate pts then
+ raise Not_found
+ else
+ let one_up = traverse 0 pts in
+ up_to_matching_rule p one_up
(* Change evars *)
let tclEVARS sigma gls = tclIDTAC {gls with sigma=sigma}
diff --git a/proofs/refiner.mli b/proofs/refiner.mli
index 41b312e5db..097ff99a93 100644
--- a/proofs/refiner.mli
+++ b/proofs/refiner.mli
@@ -40,6 +40,7 @@ val lookup_tactic : string -> (closed_generic_argument list) -> tactic
(* [abstract_tactic tac] hides the (partial) proof produced by [tac] under
a single proof node *)
+val abstract_operation : compound_rule -> tactic -> tactic
val abstract_tactic : atomic_tactic_expr -> tactic -> tactic
val abstract_tactic_expr : tactic_expr -> tactic -> tactic
val abstract_extended_tactic : string -> closed_generic_argument list -> tactic -> tactic
@@ -170,11 +171,14 @@ type pftreestate
val proof_of_pftreestate : pftreestate -> proof_tree
val cursor_of_pftreestate : pftreestate -> int list
val is_top_pftreestate : pftreestate -> bool
+val match_rule : (rule -> bool) -> pftreestate -> bool
val evc_of_pftreestate : pftreestate -> evar_map
val top_goal_of_pftreestate : pftreestate -> goal sigma
val nth_goal_of_pftreestate : int -> pftreestate -> goal sigma
val traverse : int -> pftreestate -> pftreestate
+val map_pftreestate :
+ (evar_map ref -> proof_tree -> proof_tree) -> pftreestate -> pftreestate
val solve_nth_pftreestate : int -> tactic -> pftreestate -> pftreestate
val solve_pftreestate : tactic -> pftreestate -> pftreestate
@@ -193,6 +197,12 @@ val node_next_unproven : int -> pftreestate -> pftreestate
val next_unproven : pftreestate -> pftreestate
val prev_unproven : pftreestate -> pftreestate
val top_of_tree : pftreestate -> pftreestate
+val match_rule : (rule -> bool) -> pftreestate -> bool
+val up_until_matching_rule : (rule -> bool) ->
+ pftreestate -> pftreestate
+val up_to_matching_rule : (rule -> bool) ->
+ pftreestate -> pftreestate
+val change_rule : (rule -> rule) -> pftreestate -> pftreestate
val change_constraints_pftreestate
: evar_map -> pftreestate -> pftreestate
diff --git a/tactics/auto.ml b/tactics/auto.ml
index 1ecb29f7e4..d1caa98625 100644
--- a/tactics/auto.ml
+++ b/tactics/auto.ml
@@ -192,7 +192,10 @@ let make_exact_entry (c,cty) =
{ pri=0; pat=None; code=Give_exact c })
let dummy_goal =
- {it={evar_hyps=empty_named_context_val;evar_concl=mkProp;evar_body=Evar_empty};
+ {it={evar_hyps=empty_named_context_val;
+ evar_concl=mkProp;
+ evar_body=Evar_empty;
+ evar_extra=None};
sigma=Evd.empty}
let make_apply_entry env sigma (eapply,verbose) (c,cty) =
diff --git a/tactics/decl_interp.ml b/tactics/decl_interp.ml
new file mode 100644
index 0000000000..8ace0a085b
--- /dev/null
+++ b/tactics/decl_interp.ml
@@ -0,0 +1,429 @@
+(************************************************************************)
+(* v * The Coq Proof Assistant / The Coq Development Team *)
+(* <O___,, * CNRS-Ecole Polytechnique-INRIA Futurs-Universite Paris Sud *)
+(* \VV/ **************************************************************)
+(* // * This file is distributed under the terms of the *)
+(* * GNU Lesser General Public License Version 2.1 *)
+(************************************************************************)
+
+(* $Id:$ *)
+
+open Util
+open Names
+open Topconstr
+open Tacinterp
+open Tacmach
+open Decl_expr
+open Decl_mode
+open Pretyping.Default
+open Rawterm
+open Term
+open Pp
+
+let raw_app (loc,hd,args) = if args =[] then hd else RApp(loc,hd,args)
+
+let intern_justification globs = function
+ Automated l -> Automated (List.map (intern_constr globs) l)
+ | By_tactic tac -> By_tactic (intern_tactic globs tac)
+
+let intern_statement intern_it globs st =
+ {st_label=st.st_label;
+ st_it=intern_it globs st.st_it}
+
+let intern_constr_or_thesis globs = function
+ Thesis n -> Thesis n
+ | This c -> This (intern_constr globs c)
+
+let add_var id globs=
+ let l1,l2=globs.ltacvars in
+ {globs with ltacvars= (id::l1),(id::l2)}
+
+let add_name nam globs=
+ match nam with
+ Anonymous -> globs
+ | Name id -> add_var id globs
+
+let intern_hyp iconstr globs = function
+ Hvar (loc,(id,topt)) -> add_var id globs,
+ Hvar (loc,(id,option_map (intern_constr globs) topt))
+ | Hprop st -> add_name st.st_label globs,
+ Hprop (intern_statement iconstr globs st)
+
+let intern_hyps iconstr globs hyps =
+ snd (list_fold_map (intern_hyp iconstr) globs hyps)
+
+let intern_cut intern_it globs cut=
+ {cut_stat=intern_statement intern_it globs cut.cut_stat;
+ cut_by=intern_justification globs cut.cut_by}
+
+let intern_casee globs = function
+ Real c -> Real (intern_constr globs c)
+ | Virtual cut -> Virtual (intern_cut intern_constr globs cut)
+
+let intern_hyp_list args globs =
+ let intern_one globs (loc,(id,opttyp)) =
+ (add_var id globs),
+ (loc,(id,option_map (intern_constr globs) opttyp)) in
+ list_fold_map intern_one globs args
+
+let intern_fundecl args body globs=
+ let nglobs,nargs = intern_hyp_list args globs in
+ nargs,intern_constr nglobs body
+
+let rec add_vars_of_simple_pattern globs = function
+ CPatAlias (loc,p,id) ->
+ add_vars_of_simple_pattern (add_var id globs) p
+(* Stdpp.raise_with_loc loc
+ (UserError ("simple_pattern",str "\"as\" is not allowed here"))*)
+ | CPatOr (loc, _)->
+ Stdpp.raise_with_loc loc
+ (UserError ("simple_pattern",str "\"(_ | _)\" is not allowed here"))
+ | CPatDelimiters (_,_,p) ->
+ add_vars_of_simple_pattern globs p
+ | CPatCstr (_,_,pl) | CPatNotation(_,_,pl) ->
+ List.fold_left add_vars_of_simple_pattern globs pl
+ | CPatAtom (_,Some (Libnames.Ident (_,id))) -> add_var id globs
+ | _ -> globs
+
+let rec intern_bare_proof_instr globs = function
+ Pthus i -> Pthus (intern_bare_proof_instr globs i)
+ | Pthen i -> Pthen (intern_bare_proof_instr globs i)
+ | Phence i -> Phence (intern_bare_proof_instr globs i)
+ | Pcut c -> Pcut (intern_cut intern_constr_or_thesis globs c)
+ | Prew (s,c) -> Prew (s,intern_cut intern_constr globs c)
+ | Psuppose hyps -> Psuppose (intern_hyps intern_constr globs hyps)
+ | Pcase (params,pat,hyps) ->
+ let nglobs,nparams = intern_hyp_list params globs in
+ let nnglobs= add_vars_of_simple_pattern nglobs pat in
+ let nhyps = intern_hyps intern_constr_or_thesis nnglobs hyps in
+ Pcase (nparams,pat,nhyps)
+ | Ptake witl -> Ptake (List.map (intern_constr globs) witl)
+ | Pconsider (c,hyps) -> Pconsider (intern_constr globs c,
+ intern_hyps intern_constr globs hyps)
+ | Pper (et,c) -> Pper (et,intern_casee globs c)
+ | Pend bt -> Pend bt
+ | Pescape -> Pescape
+ | Passume hyps -> Passume (intern_hyps intern_constr globs hyps)
+ | Pgiven hyps -> Pgiven (intern_hyps intern_constr globs hyps)
+ | Plet hyps -> Plet (intern_hyps intern_constr globs hyps)
+ | Pclaim st -> Pclaim (intern_statement intern_constr globs st)
+ | Pfocus st -> Pfocus (intern_statement intern_constr globs st)
+ | Pdefine (id,args,body) ->
+ let nargs,nbody = intern_fundecl args body globs in
+ Pdefine (id,nargs,nbody)
+ | Pcast (id,typ) ->
+ Pcast (id,intern_constr globs typ)
+
+let rec intern_proof_instr globs instr=
+ {emph = instr.emph;
+ instr = intern_bare_proof_instr globs instr.instr}
+
+let interp_justification env sigma = function
+ Automated l ->
+ Automated (List.map (fun c ->understand env sigma (fst c)) l)
+ | By_tactic tac -> By_tactic tac
+
+let interp_constr check_sort env sigma c =
+ if check_sort then
+ understand_type env sigma (fst c)
+ else
+ understand env sigma (fst c)
+
+let special_whd env =
+ let infos=Closure.create_clos_infos Closure.betadeltaiota env in
+ (fun t -> Closure.whd_val infos (Closure.inject t))
+
+let _eq = Libnames.constr_of_reference (Coqlib.glob_eq)
+
+let decompose_eq env id =
+ let typ = Environ.named_type id env in
+ let whd = special_whd env typ in
+ match kind_of_term whd with
+ App (f,args)->
+ if eq_constr f _eq && (Array.length args)=3
+ then args.(0)
+ else error "previous step is not an equality"
+ | _ -> error "previous step is not an equality"
+
+let get_eq_typ info env =
+ let last_id =
+ match info.pm_last with
+ Anonymous -> error "no previous equality"
+ | Name id -> id in
+ let typ = decompose_eq env last_id in
+ typ
+
+let interp_constr_in_type typ env sigma c =
+ understand env sigma (fst c) ~expected_type:typ
+
+let interp_statement interp_it env sigma st =
+ {st_label=st.st_label;
+ st_it=interp_it env sigma st.st_it}
+
+let interp_constr_or_thesis check_sort env sigma = function
+ Thesis n -> Thesis n
+ | This c -> This (interp_constr check_sort env sigma c)
+
+let type_tester_var body typ =
+ raw_app(dummy_loc,
+ RLambda(dummy_loc,Anonymous,typ,
+ RSort (dummy_loc,RProp Null)),body)
+
+let abstract_one_hyp inject h raw =
+ match h with
+ Hvar (loc,(id,None)) ->
+ RProd (dummy_loc,Name id, RHole (loc,Evd.BinderType (Name id)), raw)
+ | Hvar (loc,(id,Some typ)) ->
+ RProd (dummy_loc,Name id,fst typ, raw)
+ | Hprop st ->
+ RProd (dummy_loc,st.st_label,inject st.st_it, raw)
+
+let rawconstr_of_hyps inject hyps =
+ List.fold_right (abstract_one_hyp inject) hyps (RSort (dummy_loc,RProp Null))
+
+let rec match_hyps blend names constr = function
+ [] -> []
+ | hyp::q ->
+ let (name,typ,body)=destProd constr in
+ let st= {st_label=name;st_it=substl names typ} in
+ let qnames=
+ match name with
+ Anonymous -> mkMeta 0 :: names
+ | Name id -> mkVar id :: names in
+ let qhyp = match hyp with
+ Hprop st' -> Hprop (blend st st')
+ | Hvar _ -> Hvar st in
+ qhyp::(match_hyps blend qnames body q)
+
+let interp_hyps_gen inject blend env sigma hyps =
+ let constr=understand env sigma (rawconstr_of_hyps inject hyps) in
+ match_hyps blend [] constr hyps
+
+let interp_hyps = interp_hyps_gen fst (fun x _ -> x)
+
+let dummy_prefix= id_of_string "__"
+
+let rec deanonymize ids =
+ function
+ PatVar (loc,Anonymous) ->
+ let (found,known) = !ids in
+ let new_id=Nameops.next_ident_away dummy_prefix known in
+ let _= ids:= (loc,new_id) :: found , new_id :: known in
+ PatVar (loc,Name new_id)
+ | PatVar (loc,Name id) as pat ->
+ let (found,known) = !ids in
+ let _= ids:= (loc,id) :: found , known in
+ pat
+ | PatCstr(loc,cstr,lpat,nam) ->
+ PatCstr(loc,cstr,List.map (deanonymize ids) lpat,nam)
+
+let rec raw_of_pat =
+ function
+ PatVar (loc,Anonymous) -> anomaly "Anonymous pattern variable"
+ | PatVar (loc,Name id) ->
+ RVar (loc,id)
+ | PatCstr(loc,((ind,_) as cstr),lpat,_) ->
+ let mind= fst (Global.lookup_inductive ind) in
+ let rec add_params n q =
+ if n<=0 then q else
+ add_params (pred n) (RHole(dummy_loc,
+ Evd.TomatchTypeParameter(ind,n))::q) in
+ let args = List.map raw_of_pat lpat in
+ raw_app(loc,RRef(dummy_loc,Libnames.ConstructRef cstr),
+ add_params mind.Declarations.mind_nparams args)
+
+let prod_one_hyp = function
+ (loc,(id,None)) ->
+ (fun raw ->
+ RProd (dummy_loc,Name id,
+ RHole (loc,Evd.BinderType (Name id)), raw))
+ | (loc,(id,Some typ)) ->
+ (fun raw ->
+ RProd (dummy_loc,Name id,fst typ, raw))
+
+let prod_one_id (loc,id) raw =
+ RProd (dummy_loc,Name id,
+ RHole (loc,Evd.BinderType (Name id)), raw)
+
+let let_in_one_alias (id,pat) raw =
+ RLetIn (dummy_loc,Name id,raw_of_pat pat, raw)
+
+let rec bind_primary_aliases map pat =
+ match pat with
+ PatVar (_,_) -> map
+ | PatCstr(loc,_,lpat,nam) ->
+ let map1 =
+ match nam with
+ Anonymous -> map
+ | Name id -> (id,pat)::map
+ in
+ List.fold_left bind_primary_aliases map1 lpat
+
+let bind_secondary_aliases map subst =
+ List.fold_left (fun map (ids,idp) -> (ids,List.assoc idp map)::map) map subst
+
+let bind_aliases patvars subst patt =
+ let map = bind_primary_aliases [] patt in
+ let map1 = bind_secondary_aliases map subst in
+ List.rev map1
+
+let interp_pattern env pat_expr =
+ let patvars,pats = Constrintern.intern_pattern env pat_expr in
+ match pats with
+ [] -> anomaly "empty pattern list"
+ | [subst,patt] ->
+ (patvars,bind_aliases patvars subst patt,patt)
+ | _ -> anomaly "undetected disjunctive pattern"
+
+let rec match_args dest names constr = function
+ [] -> [],names,substl names constr
+ | _::q ->
+ let (name,typ,body)=dest constr in
+ let st={st_label=name;st_it=substl names typ} in
+ let qnames=
+ match name with
+ Anonymous -> assert false
+ | Name id -> mkVar id :: names in
+ let args,bnames,body = match_args dest qnames body q in
+ st::args,bnames,body
+
+let rec match_aliases names constr = function
+ [] -> [],names,substl names constr
+ | _::q ->
+ let (name,c,typ,body)=destLetIn constr in
+ let st={st_label=name;st_it=(substl names c,substl names typ)} in
+ let qnames=
+ match name with
+ Anonymous -> assert false
+ | Name id -> mkVar id :: names in
+ let args,bnames,body = match_aliases qnames body q in
+ st::args,bnames,body
+
+let detype_ground c = Detyping.detype false [] [] c
+
+let interp_cases info env sigma params (pat:cases_pattern_expr) hyps =
+ let et,pinfo =
+ match info.pm_stack with
+ Per(et,pi,_,_)::_ -> et,pi
+ | _ -> error "No proof per cases/induction/inversion in progress." in
+ let mib,oib=Global.lookup_inductive pinfo.per_ind in
+ let num_params = pinfo.per_nparams in
+ let _ =
+ let expected = mib.Declarations.mind_nparams - num_params in
+ if List.length params <> expected then
+ errorlabstrm "suppose it is"
+ (str "Wrong number of extra arguments : " ++
+ (if expected = 0 then str "none" else int expected) ++
+ str "expected") in
+ let app_ind =
+ let rind = RRef (dummy_loc,Libnames.IndRef pinfo.per_ind) in
+ let rparams = List.map detype_ground pinfo.per_params in
+ let rparams_rec =
+ List.map
+ (fun (loc,(id,_)) ->
+ RVar (loc,id)) params in
+ let dum_args=
+ list_tabulate (fun _ -> RHole (dummy_loc,Evd.QuestionMark))
+ oib.Declarations.mind_nrealargs in
+ raw_app(dummy_loc,rind,rparams@rparams_rec@dum_args) in
+ let pat_vars,aliases,patt = interp_pattern env pat in
+ let inject = function
+ Thesis (Plain) -> Rawterm.RSort(dummy_loc,RProp Null)
+ | Thesis (Sub n) ->
+ error "thesis[_] is not allowed here"
+ | Thesis (For rec_occ) ->
+ if not (List.mem rec_occ pat_vars) then
+ errorlabstrm "suppose it is"
+ (str "Variable " ++ Nameops.pr_id rec_occ ++
+ str " does not occur in pattern.");
+ Rawterm.RSort(dummy_loc,RProp Null)
+ | This (c,_) -> c in
+ let term1 = rawconstr_of_hyps inject hyps in
+ let loc_ids,npatt =
+ let rids=ref ([],pat_vars) in
+ let npatt= deanonymize rids patt in
+ List.rev (fst !rids),npatt in
+ let term2 =
+ RLetIn(dummy_loc,Anonymous,
+ RCast(dummy_loc,raw_of_pat npatt,
+ CastConv DEFAULTcast,app_ind),term1) in
+ let term3=List.fold_right let_in_one_alias aliases term2 in
+ let term4=List.fold_right prod_one_id loc_ids term3 in
+ let term5=List.fold_right prod_one_hyp params term4 in
+ let constr = understand sigma env term5 in
+ let tparams,nam4,rest4 = match_args destProd [] constr params in
+ let tpatvars,nam3,rest3 = match_args destProd nam4 rest4 loc_ids in
+ let taliases,nam2,rest2 = match_aliases nam3 rest3 aliases in
+ let (_,pat_pat,pat_typ,rest1) = destLetIn rest2 in
+ let blend st st' =
+ match st'.st_it with
+ Thesis nam -> {st_it=Thesis nam;st_label=st'.st_label}
+ | This _ -> {st_it = This st.st_it;st_label=st.st_label} in
+ let thyps = match_hyps blend nam2 (Termops.pop rest1) hyps in
+ tparams,{pat_vars=tpatvars;
+ pat_aliases=taliases;
+ pat_constr=pat_pat;
+ pat_typ=pat_typ;
+ pat_pat=patt;
+ pat_expr=pat},thyps
+
+let interp_cut interp_it env sigma cut=
+ {cut_stat=interp_statement interp_it env sigma cut.cut_stat;
+ cut_by=interp_justification env sigma cut.cut_by}
+
+let interp_casee env sigma = function
+ Real c -> Real (understand env sigma (fst c))
+ | Virtual cut -> Virtual (interp_cut (interp_constr true) env sigma cut)
+
+let abstract_one_arg = function
+ (loc,(id,None)) ->
+ (fun raw ->
+ RLambda (dummy_loc,Name id,
+ RHole (loc,Evd.BinderType (Name id)), raw))
+ | (loc,(id,Some typ)) ->
+ (fun raw ->
+ RLambda (dummy_loc,Name id,fst typ, raw))
+
+let rawconstr_of_fun args body =
+ List.fold_right abstract_one_arg args (fst body)
+
+let interp_fun env sigma args body =
+ let constr=understand env sigma (rawconstr_of_fun args body) in
+ match_args destLambda [] constr args
+
+let rec interp_bare_proof_instr info sigma env = function
+ Pthus i -> Pthus (interp_bare_proof_instr info sigma env i)
+ | Pthen i -> Pthen (interp_bare_proof_instr info sigma env i)
+ | Phence i -> Phence (interp_bare_proof_instr info sigma env i)
+ | Pcut c -> Pcut (interp_cut (interp_constr_or_thesis true) sigma env c)
+ | Prew (s,c) -> Prew (s,interp_cut
+ (interp_constr_in_type (get_eq_typ info env))
+ sigma env c)
+ | Psuppose hyps -> Psuppose (interp_hyps sigma env hyps)
+ | Pcase (params,pat,hyps) ->
+ let tparams,tpat,thyps = interp_cases info env sigma params pat hyps in
+ Pcase (tparams,tpat,thyps)
+ | Ptake witl ->
+ Ptake (List.map (fun c -> understand sigma env (fst c)) witl)
+ | Pconsider (c,hyps) -> Pconsider (interp_constr false sigma env c,
+ interp_hyps sigma env hyps)
+ | Pper (et,c) -> Pper (et,interp_casee sigma env c)
+ | Pend bt -> Pend bt
+ | Pescape -> Pescape
+ | Passume hyps -> Passume (interp_hyps sigma env hyps)
+ | Pgiven hyps -> Pgiven (interp_hyps sigma env hyps)
+ | Plet hyps -> Plet (interp_hyps sigma env hyps)
+ | Pclaim st -> Pclaim (interp_statement (interp_constr true) sigma env st)
+ | Pfocus st -> Pfocus (interp_statement (interp_constr true) sigma env st)
+ | Pdefine (id,args,body) ->
+ let nargs,_,nbody = interp_fun sigma env args body in
+ Pdefine (id,nargs,nbody)
+ | Pcast (id,typ) ->
+ Pcast(id,interp_constr true sigma env typ)
+
+let rec interp_proof_instr info sigma env instr=
+ {emph = instr.emph;
+ instr = interp_bare_proof_instr info sigma env instr.instr}
+
+
+
diff --git a/tactics/decl_interp.mli b/tactics/decl_interp.mli
new file mode 100644
index 0000000000..08d97646e6
--- /dev/null
+++ b/tactics/decl_interp.mli
@@ -0,0 +1,18 @@
+(************************************************************************)
+(* v * The Coq Proof Assistant / The Coq Development Team *)
+(* <O___,, * CNRS-Ecole Polytechnique-INRIA Futurs-Universite Paris Sud *)
+(* \VV/ **************************************************************)
+(* // * This file is distributed under the terms of the *)
+(* * GNU Lesser General Public License Version 2.1 *)
+(************************************************************************)
+
+(* $Id:$ *)
+
+open Tacinterp
+open Decl_expr
+open Mod_subst
+
+
+val intern_proof_instr : glob_sign -> raw_proof_instr -> glob_proof_instr
+val interp_proof_instr : Decl_mode.pm_info ->
+ Evd.evar_map -> Environ.env -> glob_proof_instr -> proof_instr
diff --git a/tactics/decl_proof_instr.ml b/tactics/decl_proof_instr.ml
new file mode 100644
index 0000000000..26a2bd48e9
--- /dev/null
+++ b/tactics/decl_proof_instr.ml
@@ -0,0 +1,1474 @@
+(************************************************************************)
+(* v * The Coq Proof Assistant / The Coq Development Team *)
+(* <O___,, * CNRS-Ecole Polytechnique-INRIA Futurs-Universite Paris Sud *)
+(* \VV/ **************************************************************)
+(* // * This file is distributed under the terms of the *)
+(* * GNU Lesser General Public License Version 2.1 *)
+(************************************************************************)
+
+(* $Id:$ *)
+
+open Util
+open Pp
+open Evd
+
+open Refiner
+open Proof_type
+open Proof_trees
+open Tacmach
+open Tacinterp
+open Decl_expr
+open Decl_mode
+open Decl_interp
+open Rawterm
+open Names
+open Declarations
+open Tactics
+open Tacticals
+open Term
+open Termops
+open Reductionops
+open Goptions
+
+(* Strictness option *)
+
+let get_its_info gls = get_info gls.it
+
+let get_strictness,set_strictness =
+ let strictness = ref false in
+ (fun () -> (!strictness)),(fun b -> strictness:=b)
+
+let _ =
+ declare_bool_option
+ { optsync = true;
+ optname = "strict mode";
+ optkey = (SecondaryTable ("Strict","Proofs"));
+ optread = get_strictness;
+ optwrite = set_strictness }
+
+let tcl_change_info_gen info_gen =
+ (fun gls ->
+ let gl =sig_it gls in
+ {it=[{gl with evar_extra=info_gen}];sigma=sig_sig gls},
+ function
+ [pftree] ->
+ {pftree with
+ goal=gl;
+ ref=Some (Change_evars,[pftree])}
+ | _ -> anomaly "change_info : Wrong number of subtrees")
+
+let tcl_change_info info gls = tcl_change_info_gen (Some (pm_in info)) gls
+
+let tcl_erase_info gls = tcl_change_info_gen None gls
+
+let special_whd gl=
+ let infos=Closure.create_clos_infos Closure.betadeltaiota (pf_env gl) in
+ (fun t -> Closure.whd_val infos (Closure.inject t))
+
+let special_nf gl=
+ let infos=Closure.create_clos_infos Closure.betaiotazeta (pf_env gl) in
+ (fun t -> Closure.norm_val infos (Closure.inject t))
+
+let is_good_inductive env ind =
+ let mib,oib = Inductive.lookup_mind_specif env ind in
+ oib.mind_nrealargs = 0 && not (Inductiveops.mis_is_recursive (ind,mib,oib))
+
+let check_not_per pts =
+ if not (Proof_trees.is_complete_proof (proof_of_pftreestate pts)) then
+ match get_stack pts with
+ Per (_,_,_,_)::_ ->
+ error "You are inside a proof per cases/induction.\n\
+Please \"suppose\" something or \"end\" it now."
+ | _ -> ()
+
+let get_thesis gls0 =
+ let info = get_its_info gls0 in
+ match info.pm_subgoals with
+ [m,thesis] -> thesis
+ | _ -> error "Thesis is split"
+
+let mk_evd metalist gls =
+ let evd0= create_evar_defs (sig_sig gls) in
+ let add_one (meta,typ) evd =
+ meta_declare meta typ evd in
+ List.fold_right add_one metalist evd0
+
+(* start a proof *)
+
+let start_proof_tac gls=
+ let gl=sig_it gls in
+ let info={pm_last=Anonymous;
+ pm_partial_goal=mkMeta 1;
+ pm_hyps=
+ begin
+ let hyps = pf_ids_of_hyps gls in
+ List.fold_right Idset.add hyps Idset.empty
+ end;
+ pm_subgoals= [1,gl.evar_concl];
+ pm_stack=[]} in
+ {it=[{gl with evar_extra=Some (pm_in info)}];sigma=sig_sig gls},
+ function
+ [pftree] ->
+ {pftree with
+ goal=gl;
+ ref=Some (Decl_proof true,[pftree])}
+ | _ -> anomaly "Dem : Wrong number of subtrees"
+
+let go_to_proof_mode () =
+ Pfedit.mutate
+ (fun pts -> nth_unproven 1 (solve_pftreestate start_proof_tac pts))
+
+(* closing gaps *)
+
+let daimon_tac gls =
+ set_daimon_flag ();
+ ({it=[];sigma=sig_sig gls},
+ function
+ [] ->
+ {open_subgoals=0;
+ goal=sig_it gls;
+ ref=Some (Daimon,[])}
+ | _ -> anomaly "Daimon: Wrong number of subtrees")
+
+let daimon _ pftree =
+ set_daimon_flag ();
+ {pftree with
+ open_subgoals=0;
+ ref=Some (Daimon,[])}
+
+let daimon_subtree = map_pftreestate (fun _ -> frontier_mapi daimon )
+
+(* marking closed blocks *)
+
+let rec is_focussing_instr = function
+ Pthus i | Pthen i | Phence i -> is_focussing_instr i
+ | Pescape | Pper _ | Pclaim _ | Pfocus _
+ | Psuppose _ | Pcase (_,_,_) -> true
+ | _ -> false
+
+let mark_rule_as_done = function
+ Decl_proof true -> Decl_proof false
+ | Decl_proof false ->
+ anomaly "already marked as done"
+ | Nested(Proof_instr (lock_focus,instr),spfl) ->
+ if lock_focus then
+ Nested(Proof_instr (false,instr),spfl)
+ else
+ anomaly "already marked as done"
+ | _ -> anomaly "mark_rule_as_done"
+
+let mark_proof_tree_as_done pt =
+ match pt.ref with
+ None -> anomaly "mark_proof_tree_as_done"
+ | Some (r,spfl) ->
+ {pt with ref= Some (mark_rule_as_done r,spfl)}
+
+let mark_as_done pts =
+ map_pftreestate
+ (fun _ -> mark_proof_tree_as_done)
+ (traverse 0 pts)
+
+(* post-instruction focus management *)
+
+let goto_current_focus pts = up_until_matching_rule is_focussing_command pts
+
+let goto_current_focus_or_top pts =
+ try
+ up_until_matching_rule is_focussing_command pts
+ with Not_found -> top_of_tree pts
+
+(* return *)
+
+let close_tactic_mode pts =
+ let pts1=
+ try goto_current_focus pts
+ with Not_found ->
+ error "\"return\" cannot be used outside of Declarative Proof Mode" in
+ let pts2 = daimon_subtree pts1 in
+ let pts3 = mark_as_done pts2 in
+ goto_current_focus pts3
+
+let return_from_tactic_mode () = Pfedit.mutate close_tactic_mode
+
+(* end proof/claim *)
+
+let close_block bt pts =
+ let stack =
+ if Proof_trees.is_complete_proof (proof_of_pftreestate pts) then
+ get_top_stack pts
+ else
+ get_stack pts in
+ match bt,stack with
+ B_claim, Claim::_ | B_focus, Focus_claim::_ | B_proof, [] ->
+ daimon_subtree (goto_current_focus pts)
+ | _, Claim::_ ->
+ error "\"end claim\" expected"
+ | _, Focus_claim::_ ->
+ error "\"end focus\" expected"
+ | _, [] ->
+ error "\"end proof\" expected"
+ | _, (Per (et,_,_,_)::_|Suppose_case::Per (et,_,_,_)::_) ->
+ begin
+ match et with
+ ET_Case_analysis -> error "\"end cases\" expected"
+ | ET_Induction -> error "\"end induction\" expected"
+ end
+ | _,_ -> anomaly "lonely suppose on stack"
+
+(* utility for suppose / suppose it is *)
+
+let close_previous_case pts =
+ if
+ Proof_trees.is_complete_proof (proof_of_pftreestate pts)
+ then
+ match get_top_stack pts with
+ Per (et,_,_,_) :: _ -> anomaly "Weird case occured ..."
+ | Suppose_case :: Per (et,_,_,_) :: _ ->
+ goto_current_focus (mark_as_done pts)
+ | _ -> error "Not inside a proof per cases or induction."
+ else
+ match get_stack pts with
+ Per (et,_,_,_) :: _ -> pts
+ | Suppose_case :: Per (et,_,_,_) :: _ ->
+ goto_current_focus (mark_as_done (daimon_subtree pts))
+ | _ -> error "Not inside a proof per cases or induction."
+
+(* Proof instructions *)
+
+(* automation *)
+
+let filter_hyps f gls =
+ let filter_aux (id,_,_) =
+ if f id then
+ tclIDTAC
+ else
+ tclTRY (clear [id]) in
+ tclMAP filter_aux (Environ.named_context_of_val gls.it.evar_hyps) gls
+
+let local_hyp_prefix = id_of_string "___"
+
+let add_justification_hyps keep items gls =
+ let add_aux c gls=
+ match kind_of_term c with
+ Var id ->
+ keep:=Idset.add id !keep;
+ tclIDTAC gls
+ | _ ->
+ let id=pf_get_new_id local_hyp_prefix gls in
+ keep:=Idset.add id !keep;
+ letin_tac false (Names.Name id) c Tacexpr.nowhere gls in
+ tclMAP add_aux items gls
+
+let apply_to_prepared_goal items kont gls =
+ let tokeep = ref Idset.empty in
+ let auxres = add_justification_hyps tokeep items gls in
+ tclTHENLIST
+ [ (fun _ -> auxres);
+ filter_hyps (let keep = !tokeep in fun id -> Idset.mem id keep);
+ kont ] gls
+
+let my_automation_tac = ref
+ (fun gls -> anomaly "No automation registered")
+
+let register_automation_tac tac = my_automation_tac:= tac
+
+let automation_tac gls = !my_automation_tac gls
+
+let justification tac gls=
+ tclORELSE
+ (tclSOLVE [tac])
+ (fun gls ->
+ if get_strictness () then
+ error "insufficient justification"
+ else
+ begin
+ msgnl (str "Warning: insufficient justification");
+ daimon_tac gls
+ end) gls
+
+let default_justification items gls=
+ justification (apply_to_prepared_goal items automation_tac) gls
+
+(* code for have/then/thus/hence *)
+
+type stackd_elt =
+{se_meta:metavariable;
+ se_type:types;
+ se_last_meta:metavariable;
+ se_meta_list:(metavariable*types) list;
+ se_evd: evar_defs}
+
+let rec replace_in_list m l = function
+ [] -> raise Not_found
+ | c::q -> if m=fst c then l@q else c::replace_in_list m l q
+
+let enstack_subsubgoals env se stack gls=
+ let hd,params = decompose_app (special_whd gls se.se_type) in
+ match kind_of_term hd with
+ Ind ind when is_good_inductive env ind ->
+ let mib,oib=
+ Inductive.lookup_mind_specif env ind in
+ let gentypes=
+ Inductive.arities_of_constructors ind (mib,oib) in
+ let process i gentyp =
+ let constructor = mkConstruct(ind,succ i)
+ (* constructors numbering*) in
+ let appterm = applist (constructor,params) in
+ let apptype = Term.prod_applist gentyp params in
+ let rc,_ = Reduction.dest_prod env apptype in
+ let rec meta_aux last lenv = function
+ [] -> (last,lenv,[])
+ | (nam,_,typ)::q ->
+ let nlast=succ last in
+ let (llast,holes,metas) =
+ meta_aux nlast (mkMeta nlast :: lenv) q in
+ (llast,holes,(nlast,special_nf gls (substl lenv typ))::metas) in
+ let (nlast,holes,nmetas) =
+ meta_aux se.se_last_meta [] (List.rev rc) in
+ let refiner = applist (appterm,List.rev holes) in
+ let evd = meta_assign se.se_meta refiner se.se_evd in
+ let ncreated = replace_in_list
+ se.se_meta nmetas se.se_meta_list in
+ let evd0 = List.fold_left
+ (fun evd (m,typ) -> meta_declare m typ evd) evd nmetas in
+ List.iter (fun (m,typ) ->
+ Stack.push
+ {se_meta=m;
+ se_type=typ;
+ se_evd=evd0;
+ se_meta_list=ncreated;
+ se_last_meta=nlast} stack) (List.rev nmetas)
+ in
+ Array.iteri process gentypes
+ | _ -> ()
+
+let find_subsubgoal env c ctyp skip evd metas gls =
+ let stack = Stack.create () in
+ let max_meta =
+ List.fold_left (fun a (m,_) -> max a m) 0 metas in
+ let _ =
+ List.iter (fun (m,typ) ->
+ Stack.push
+ {se_meta=m;
+ se_type=typ;
+ se_last_meta=max_meta;
+ se_meta_list=metas;
+ se_evd=evd} stack) (List.rev metas) in
+ let rec dfs n =
+ let se = Stack.pop stack in
+ try
+ let unifier =
+ Unification.w_unify true env Reduction.CUMUL
+ ctyp se.se_type se.se_evd in
+ if n <= 0 then
+ {se with se_evd=meta_assign se.se_meta c unifier}
+ else
+ dfs (pred n)
+ with _ ->
+ begin
+ enstack_subsubgoals env se stack gls;
+ dfs n
+ end in
+ let nse= try dfs skip with Stack.Empty -> raise Not_found in
+ nse.se_meta_list,nse.se_evd
+
+let rec nf_list evd =
+ function
+ [] -> []
+ | (m,typ)::others ->
+ if meta_defined evd m then
+ nf_list evd others
+ else
+ (m,nf_meta evd typ)::nf_list evd others
+
+
+let rec max_linear_context meta_one c =
+ if !meta_one = None then
+ if isMeta c then
+ begin
+ meta_one:= Some c;
+ mkMeta 1
+ end
+ else
+ try
+ map_constr (max_linear_context meta_one) c
+ with Not_found ->
+ begin
+ meta_one:= Some c;
+ mkMeta 1
+ end
+ else
+ if isMeta c then
+ raise Not_found
+ else
+ map_constr (max_linear_context meta_one) c
+
+let thus_tac c ctyp gls =
+ let info = get_its_info gls in
+ let evd0 = mk_evd info.pm_subgoals gls in
+ let list,evd =
+ try
+ find_subsubgoal (pf_env gls) c ctyp 0 evd0 info.pm_subgoals gls
+ with Not_found ->
+ error "I could not relate this statement to the thesis" in
+ let nflist = nf_list evd list in
+ let nfgoal = nf_meta evd info.pm_partial_goal in
+(* let _ = msgnl (str "Partial goal : " ++
+ print_constr_env (pf_env gls) nfgoal) in *)
+ let rgl = ref None in
+ let refiner = max_linear_context rgl nfgoal in
+ match !rgl with
+ None -> exact_check refiner gls
+ | Some pgl when not (isMeta refiner) ->
+ let ninfo={info with
+ pm_partial_goal = pgl;
+ pm_subgoals = nflist} in
+ tclTHEN
+ (Tactics.refine refiner)
+ (tcl_change_info ninfo)
+ gls
+ | _ ->
+ let ninfo={info with
+ pm_partial_goal = nfgoal;
+ pm_subgoals = nflist} in
+ tcl_change_info ninfo gls
+
+let anon_id_base = id_of_string "__"
+
+
+let mk_stat_or_thesis info = function
+ This c -> c
+ | Thesis (For _ ) ->
+ error "\"thesis for ...\" is not applicable here"
+ | Thesis (Sub n) ->
+ begin
+ try List.assoc n info.pm_subgoals
+ with Not_found -> error "No such part in thesis."
+ end
+ | Thesis Plain ->
+ match info.pm_subgoals with
+ [_,c] -> c
+ | _ -> error
+ "\"thesis\" is split, please specify which part you refer to."
+
+let instr_cut mkstat _thus _then cut gls0 =
+ let info = get_its_info gls0 in
+ let just_tac gls =
+ match cut.cut_by with
+ Automated l ->
+ let elems =
+ if _then then
+ match info.pm_last with
+ Anonymous -> l
+ | Name id -> (mkVar id) ::l
+ else l in
+ default_justification elems gls
+ | By_tactic t ->
+ justification (Tacinterp.eval_tactic t) gls in
+ let c_id = match cut.cut_stat.st_label with
+ Anonymous ->
+ pf_get_new_id (id_of_string "_fact") gls0
+ | Name id -> id in
+ let c_stat = mkstat info cut.cut_stat.st_it in
+ let thus_tac gls=
+ if _thus then
+ thus_tac (mkVar c_id) c_stat gls
+ else tclIDTAC gls in
+ let ninfo = {info with pm_last=Name c_id} in
+ tclTHENS (internal_cut c_id c_stat)
+ [tclTHEN tcl_erase_info just_tac;
+ tclTHEN (tcl_change_info ninfo) thus_tac] gls0
+
+(* iterated equality *)
+let _eq = Libnames.constr_of_reference (Coqlib.glob_eq)
+
+let decompose_eq id gls =
+ let typ = pf_get_hyp_typ gls id in
+ let whd = (special_whd gls typ) in
+ match kind_of_term whd with
+ App (f,args)->
+ if eq_constr f _eq && (Array.length args)=3
+ then (args.(0),
+ args.(1),
+ args.(2))
+ else error "previous step is not an equality"
+ | _ -> error "previous step is not an equality"
+
+let instr_rew _thus rew_side cut gls0 =
+ let info = get_its_info gls0 in
+ let last_id =
+ match info.pm_last with
+ Anonymous -> error "no previous equality"
+ | Name id -> id in
+ let typ,lhs,rhs = decompose_eq last_id gls0 in
+ let just_tac gls =
+ match cut.cut_by with
+ Automated l ->
+ let elems = (mkVar last_id) :: l in
+ default_justification elems gls
+ | By_tactic t ->
+ justification (Tacinterp.eval_tactic t) gls in
+ let c_id = match cut.cut_stat.st_label with
+ Anonymous ->
+ pf_get_new_id (id_of_string "_eq") gls0
+ | Name id -> id in
+ let ninfo = {info with pm_last=Name c_id} in
+ let thus_tac new_eq gls=
+ if _thus then
+ thus_tac (mkVar c_id) new_eq gls
+ else tclIDTAC gls in
+ match rew_side with
+ Lhs ->
+ let new_eq = mkApp(_eq,[|typ;cut.cut_stat.st_it;rhs|]) in
+ tclTHENS (internal_cut c_id new_eq)
+ [tclTHEN tcl_erase_info
+ (tclTHENS (transitivity lhs)
+ [just_tac;exact_check (mkVar last_id)]);
+ tclTHEN (tcl_change_info ninfo) (thus_tac new_eq)] gls0
+ | Rhs ->
+ let new_eq = mkApp(_eq,[|typ;lhs;cut.cut_stat.st_it|]) in
+ tclTHENS (internal_cut c_id new_eq)
+ [tclTHEN tcl_erase_info
+ (tclTHENS (transitivity rhs)
+ [exact_check (mkVar last_id);just_tac]);
+ tclTHEN (tcl_change_info ninfo) (thus_tac new_eq)] gls0
+
+
+
+(* tactics for claim/focus *)
+
+let instr_claim _thus st gls0 =
+ let info = get_its_info gls0 in
+ let id = match st.st_label with
+ Anonymous -> pf_get_new_id (id_of_string "_claim") gls0
+ | Name id -> id in
+ let thus_tac gls=
+ if _thus then
+ thus_tac (mkVar id) st.st_it gls
+ else tclIDTAC gls in
+ let ninfo1 = {info with
+ pm_stack=
+ (if _thus then Focus_claim else Claim)::info.pm_stack;
+ pm_partial_goal=mkMeta 1;
+ pm_subgoals = [1,st.st_it]} in
+ let ninfo2 = {info with pm_last=Name id} in
+ tclTHENS (internal_cut id st.st_it)
+ [tcl_change_info ninfo1;
+ tclTHEN (tcl_change_info ninfo2) thus_tac] gls0
+
+(* tactics for assume *)
+
+let reset_concl gls =
+ let info = get_its_info gls in
+ tcl_change_info
+ {info with
+ pm_partial_goal=mkMeta 1;
+ pm_subgoals= [1,gls.it.evar_concl]} gls
+
+let set_last id gls =
+ let info = get_its_info gls in
+ tcl_change_info
+ {info with
+ pm_last=Name id} gls
+
+let intro_pm id gls=
+ let info = get_its_info gls in
+ match info.pm_subgoals with
+ [(_,typ)] ->
+ tclTHEN (intro_mustbe_force id) reset_concl gls
+ | _ -> error "Goal is split"
+
+let push_intro_tac coerce nam gls =
+ let hid =
+ match nam with
+ Anonymous -> pf_get_new_id (id_of_string "_hyp") gls
+ | Name id -> id in
+ let mark_id gls0 =
+ let info = get_its_info gls0 in
+ let ninfo = {info with
+ pm_last = Name hid;
+ pm_hyps = Idset.add hid info.pm_hyps } in
+ tcl_change_info ninfo gls0 in
+ tclTHENLIST
+ [intro_pm hid;
+ coerce hid;
+ mark_id]
+ gls
+
+let assume_tac hyps gls =
+ List.fold_right
+ (fun (Hvar st | Hprop st) ->
+ tclTHEN
+ (push_intro_tac
+ (fun id ->
+ convert_hyp (id,None,st.st_it)) st.st_label))
+ hyps tclIDTAC gls
+
+let assume_hyps_or_theses hyps gls =
+ List.fold_right
+ (function
+ (Hvar {st_label=nam;st_it=c} | Hprop {st_label=nam;st_it=This c}) ->
+ tclTHEN
+ (push_intro_tac
+ (fun id ->
+ convert_hyp (id,None,c)) nam)
+ | Hprop {st_label=nam;st_it=Thesis (tk)} ->
+ tclTHEN
+ (push_intro_tac
+ (fun id -> tclIDTAC) nam))
+ hyps tclIDTAC gls
+
+let assume_st hyps gls =
+ List.fold_right
+ (fun st ->
+ tclTHEN
+ (push_intro_tac
+ (fun id -> convert_hyp (id,None,st.st_it)) st.st_label))
+ hyps tclIDTAC gls
+
+let assume_st_letin hyps gls =
+ List.fold_right
+ (fun st ->
+ tclTHEN
+ (push_intro_tac
+ (fun id ->
+ convert_hyp (id,Some (fst st.st_it),snd st.st_it)) st.st_label))
+ hyps tclIDTAC gls
+
+(* tactics for consider/given *)
+
+let update_goal_info gls =
+ let info = get_its_info gls in
+ match info.pm_subgoals with
+ [m,_] -> tcl_change_info {info with pm_subgoals =[m,pf_concl gls]} gls
+ | _ -> error "thesis is split"
+
+let conjunction_arity id gls =
+ let typ = pf_get_hyp_typ gls id in
+ let hd,params = decompose_app (special_whd gls typ) in
+ let env =pf_env gls in
+ match kind_of_term hd with
+ Ind ind when is_good_inductive env ind ->
+ let mib,oib=
+ Inductive.lookup_mind_specif env ind in
+ let gentypes=
+ Inductive.arities_of_constructors ind (mib,oib) in
+ let _ = if Array.length gentypes <> 1 then raise Not_found in
+ let apptype = Term.prod_applist gentypes.(0) params in
+ let rc,_ = Reduction.dest_prod env apptype in
+ List.length rc
+ | _ -> raise Not_found
+
+let rec intron_then n ids ltac gls =
+ if n<=0 then
+ tclTHEN
+ (fun gls ->
+ if List.exists (fun id -> occur_id [] id (pf_concl gls)) ids then
+ update_goal_info gls
+ else
+ tclIDTAC gls)
+ (ltac ids)
+ gls
+ else
+ let id = pf_get_new_id (id_of_string "_tmp") gls in
+ tclTHEN
+ (intro_mustbe_force id)
+ (intron_then (pred n) (id::ids) ltac) gls
+
+let pm_rename_hyp id hid gls =
+ if occur_id [] id (pf_concl gls) then
+ tclTHEN (rename_hyp id hid) update_goal_info gls
+ else
+ rename_hyp id hid gls
+
+let rec consider_match may_intro introduced available expected gls =
+ match available,expected with
+ [],[] ->
+ if not may_intro then
+ set_last (List.hd introduced) gls
+ else
+ let info = get_its_info gls in
+ let nameset=List.fold_right Idset.add introduced info.pm_hyps in
+ tcl_change_info {info with
+ pm_last = Name (List.hd introduced);
+ pm_hyps = nameset} gls
+ | _,[] -> error "last statements do not match a complete hypothesis"
+ (* should tell which ones *)
+ | [],hyps ->
+ if may_intro then
+ begin
+ let id = pf_get_new_id (id_of_string "_tmp") gls in
+ tclIFTHENELSE
+ (intro_pm id)
+ (consider_match true [] [id] hyps)
+ (fun _ ->
+ error "not enough sub-hypotheses to match statements")
+ gls
+ end
+ else
+ error "not enough sub-hypotheses to match statements"
+ (* should tell which ones *)
+ | id::rest_ids,(Hvar st | Hprop st)::rest ->
+ tclIFTHENELSE (convert_hyp (id,None,st.st_it))
+ begin
+ match st.st_label with
+ Anonymous ->
+ consider_match may_intro (id::introduced) rest_ids rest
+ | Name hid ->
+ tclTHENLIST
+ [pm_rename_hyp id hid;
+ consider_match may_intro (hid::introduced) rest_ids rest]
+ end
+ begin
+ (fun gls ->
+ let nhyps =
+ try conjunction_arity id gls with
+ Not_found -> error "matching hypothesis not found" in
+ tclTHENLIST
+ [general_case_analysis (mkVar id,NoBindings);
+ intron_then nhyps []
+ (fun l -> consider_match may_intro introduced
+ (List.rev_append l rest_ids) expected)] gls)
+ end
+ gls
+
+let consider_tac c hyps gls =
+ match kind_of_term (strip_outer_cast c) with
+ Var id ->
+ consider_match false [] [id] hyps gls
+ | _ ->
+ let id = pf_get_new_id (id_of_string "_tmp") gls in
+ tclTHEN
+ (forward None (Genarg.IntroIdentifier id) c)
+ (consider_match false [] [id] hyps) gls
+
+
+let given_tac hyps gls =
+ consider_match true [] [] hyps gls
+
+(* tactics for take *)
+
+let rec take_tac wits gls =
+ match wits with
+ [] -> tclIDTAC gls
+ | wit::rest ->
+ let typ = pf_type_of gls wit in
+ tclTHEN (thus_tac wit typ) (take_tac rest) gls
+
+
+(* tactics for define *)
+
+let rec build_function args body =
+ match args with
+ st::rest ->
+ let pfun= lift 1 (build_function rest body) in
+ let id = match st.st_label with
+ Anonymous -> assert false
+ | Name id -> id in
+ mkLambda (Name id, st.st_it, subst_term (mkVar id) pfun)
+ | [] -> body
+
+let define_tac id args body gls =
+ let t = build_function args body in
+ letin_tac true (Name id) t Tacexpr.nowhere gls
+
+(* tactics for reconsider *)
+
+let cast_tac id_or_thesis typ gls =
+ let info = get_its_info gls in
+ match id_or_thesis with
+ This id ->
+ let (_,body,_) = pf_get_hyp gls id in
+ convert_hyp (id,body,typ) gls
+ | Thesis (For _ ) ->
+ error "\"thesis for ...\" is not applicable here"
+ | Thesis (Sub n) ->
+ begin
+ let old_typ =
+ try List.assoc n info.pm_subgoals
+ with Not_found -> error "No such part in thesis." in
+ if is_conv_leq (pf_env gls) (sig_sig gls) typ old_typ then
+ let new_sg = List.merge
+ (fun (n,_) (p,_) -> Pervasives.compare n p)
+ [n,typ] (List.remove_assoc n info.pm_subgoals) in
+ tcl_change_info {info with pm_subgoals=new_sg} gls
+ else
+ error "not convertible"
+ end
+ | Thesis Plain ->
+ match info.pm_subgoals with
+ [m,c] ->
+ tclTHEN
+ (convert_concl typ DEFAULTcast)
+ (tcl_change_info {info with pm_subgoals= [m,typ]}) gls
+ | _ -> error
+ "\"thesis\" is split, please specify which part you refer to."
+
+
+(* per cases *)
+
+let start_tree env ind =
+ let constrs = (snd (Inductive.lookup_mind_specif env ind)).mind_consnames in
+ Split (Idset.empty,ind,Array.map (fun _ -> None) constrs)
+
+let build_per_info etype casee gls =
+ let concl=get_thesis gls in
+ let env=pf_env gls in
+ let ctyp=pf_type_of gls casee in
+ let is_dep = dependent casee concl in
+ let hd,args = decompose_app (special_whd gls ctyp) in
+ let ind =
+ try
+ destInd hd
+ with _ ->
+ error "Case analysis must be done on an inductive object" in
+ let nparams =
+ let mind = fst (Global.lookup_inductive ind) in
+ match etype with
+ ET_Induction -> mind.mind_nparams_rec
+ | _ -> mind.mind_nparams in
+ let params,real_args = list_chop nparams args in
+ let abstract_obj body c =
+ let typ=pf_type_of gls c in
+ lambda_create env (typ,subst_term c body) in
+ let pred= List.fold_left abstract_obj
+ (lambda_create env (ctyp,subst_term casee concl)) real_args in
+ is_dep,
+ {per_casee=casee;
+ per_ctype=ctyp;
+ per_ind=ind;
+ per_pred=pred;
+ per_args=real_args;
+ per_params=params;
+ per_nparams=nparams}
+
+let per_tac etype casee gls=
+ let env=pf_env gls in
+ let info = get_its_info gls in
+ match casee with
+ Real c ->
+ let is_dep,per_info = build_per_info etype c gls in
+ let ek =
+ if is_dep then
+ EK_dep (start_tree env per_info.per_ind)
+ else EK_unknown in
+ tcl_change_info
+ {info with
+ pm_stack=
+ Per(etype,per_info,ek,[])::info.pm_stack} gls
+ | Virtual cut ->
+ assert (cut.cut_stat.st_label=Anonymous);
+ let id = pf_get_new_id (id_of_string "_matched") gls in
+ let c = mkVar id in
+ let modified_cut =
+ {cut with cut_stat={cut.cut_stat with st_label=Name id}} in
+ tclTHEN
+ (instr_cut (fun _ c -> c) false false modified_cut)
+ (fun gls0 ->
+ let is_dep,per_info = build_per_info etype c gls0 in
+ assert (not is_dep);
+ tcl_change_info
+ {info with pm_stack=
+ Per(etype,per_info,EK_unknown,[])::info.pm_stack} gls0)
+ gls
+
+(* suppose *)
+
+let rec build_product args body =
+ match args with
+ (Hprop st| Hvar st )::rest ->
+ let pprod= lift 1 (build_product rest body) in
+ let lbody =
+ match st.st_label with
+ Anonymous -> body
+ | Name id -> subst_term (mkVar id) pprod in
+ mkProd (st.st_label, st.st_it, lbody)
+ | [] -> body
+
+let register_nodep_subcase id= function
+ Per(et,pi,ek,clauses)::s ->
+ begin
+ match ek with
+ EK_unknown -> clauses,Per(et,pi,EK_nodep,id::clauses)::s
+ | EK_nodep -> clauses,Per(et,pi,EK_nodep,id::clauses)::s
+ | EK_dep _ -> error "Do not mix \"suppose\" with \"suppose it is\"."
+ end
+ | _ -> anomaly "wrong stack state"
+
+let suppose_tac hyps gls0 =
+ let info = get_its_info gls0 in
+ let thesis = get_thesis gls0 in
+ let id = pf_get_new_id (id_of_string "_subcase") gls0 in
+ let clause = build_product hyps thesis in
+ let ninfo1 = {info with
+ pm_stack=Suppose_case::info.pm_stack;
+ pm_partial_goal=mkMeta 1;
+ pm_subgoals = [1,clause]} in
+ let old_clauses,stack = register_nodep_subcase id info.pm_stack in
+ let ninfo2 = {info with
+ pm_stack=stack} in
+ tclTHENS (internal_cut id clause)
+ [tclTHENLIST [tcl_change_info ninfo1;
+ assume_tac hyps;
+ clear old_clauses];
+ tcl_change_info ninfo2] gls0
+
+(* suppose it is ... *)
+
+(* pattern matching compiling *)
+
+let rec nb_prod_after n c=
+ match kind_of_term c with
+ | Prod (_,_,b) ->if n>0 then nb_prod_after (n-1) b else
+ 1+(nb_prod_after 0 b)
+ | _ -> 0
+
+let constructor_arities env ind =
+ let nparams = (fst (Global.lookup_inductive ind)).mind_nparams in
+ let constr_types = Inductiveops.arities_of_constructors env ind in
+ let hyp = nb_prod_after nparams in
+ Array.map hyp constr_types
+
+let rec n_push rest ids n =
+ if n<=0 then Pop rest else Push (ids,n_push rest ids (pred n))
+
+let explode_branches ids env ind rest=
+ Array.map (fun n -> Some (Idset.empty,n_push rest ids n)) (constructor_arities env ind)
+
+let rec tree_of_pats env ((id,_) as cpl) pats =
+ match pats with
+ [] -> End_of_branch cpl
+ | args::stack ->
+ match args with
+ [] -> Pop (tree_of_pats env cpl stack)
+ | patt :: rest_args ->
+ match patt with
+ PatVar (_,v) ->
+ Push (Idset.singleton id,
+ tree_of_pats env cpl (rest_args::stack))
+ | PatCstr (_,(ind,cnum),args,nam) ->
+ let _,mind = Inductive.lookup_mind_specif env ind in
+ let br= Array.map (fun _ -> None) mind.mind_consnames in
+ br.(pred cnum) <-
+ Some (Idset.singleton id,
+ tree_of_pats env cpl (args::rest_args::stack));
+ Split(Idset.empty,ind,br)
+
+let rec add_branch env ((id,_) as cpl) pats tree=
+ match pats with
+ [] ->
+ begin
+ match tree with
+ End_of_branch cpl0 -> End_of_branch cpl0
+ (* this ensures precedence *)
+ | _ -> anomaly "tree is expected to end here"
+ end
+ | args::stack ->
+ match args with
+ [] ->
+ begin
+ match tree with
+ Pop t -> Pop (add_branch env cpl stack t)
+ | _ -> anomaly "we should pop here"
+ end
+ | patt :: rest_args ->
+ match patt with
+ PatVar (_,v) ->
+ begin
+ match tree with
+ Push (ids,t) ->
+ Push (Idset.add id ids,
+ add_branch env cpl (rest_args::stack) t)
+ | Split (ids,ind,br) ->
+ Split (Idset.add id ids,
+ ind,array_map2
+ (append_branch env cpl 1
+ (rest_args::stack))
+ (constructor_arities env ind) br)
+ | _ -> anomaly "No pop/stop expected here"
+ end
+ | PatCstr (_,(ind,cnum),args,nam) ->
+ match tree with
+ Push (ids,t) ->
+ let br = explode_branches ids env ind t in
+ let _ =
+ br.(pred cnum)<-
+ option_map
+ (fun (ids,tree) ->
+ Idset.add id ids,
+ add_branch env cpl
+ (args::rest_args::stack) tree)
+ br.(pred cnum) in
+ Split (ids,ind,br)
+ | Split (ids,ind0,br0) ->
+ assert (ind=ind0);
+ let br=Array.copy br0 in
+ let ca = constructor_arities env ind in
+ let _= br.(pred cnum)<-
+ append_branch env cpl 0 (args::rest_args::stack)
+ ca.(pred cnum) br.(pred cnum) in
+ Split (ids,ind,br)
+ | _ -> anomaly "No pop/stop expected here"
+and append_branch env ((id,_) as cpl) depth pats nargs = function
+ Some (ids,tree) ->
+ Some (Idset.add id ids,append_tree env cpl depth pats tree)
+ | None ->
+ Some (* (n_push (tree_of_pats env cpl pats)
+ (Idset.singleton id) nargs) *)
+ (Idset.singleton id,tree_of_pats env cpl pats)
+and append_tree env ((id,_) as cpl) depth pats tree =
+ if depth<=0 then add_branch env cpl pats tree
+ else match tree with
+ Pop t -> Pop (append_tree env cpl (pred depth) pats t)
+ | Push (ids,t) -> Push (Idset.add id ids,
+ append_tree env cpl depth pats t)
+ | End_of_branch _ -> anomaly "Premature end of branch"
+ | Split (ids,ind,branches) ->
+ Split (Idset.add id ids,ind,
+ array_map2
+ (append_branch env cpl (succ depth) pats)
+ (constructor_arities env ind)
+ branches)
+
+(* suppose it is *)
+
+let rec st_assoc id = function
+ [] -> raise Not_found
+ | st::_ when st.st_label = id -> st.st_it
+ | _ :: rest -> st_assoc id rest
+
+let thesis_for obj typ per_info env=
+ let rc,hd1=decompose_prod typ in
+ let cind,all_args=decompose_app typ in
+ let ind = destInd cind in
+ let _ = if ind <> per_info.per_ind then
+ errorlabstrm "thesis_for"
+ ((Printer.pr_constr_env env obj) ++ spc () ++
+ str "cannot give an induction hypothesis (wrong inductive type)") in
+ let params,args = list_chop per_info.per_nparams all_args in
+ let _ = if not (List.for_all2 eq_constr params per_info.per_params) then
+ errorlabstrm "thesis_for"
+ ((Printer.pr_constr_env env obj) ++ spc () ++
+ str "cannot give an induction hypothesis (wrong parameters)") in
+ let hd2 = (applist ((lift (List.length rc) per_info.per_pred),args@[obj])) in
+ compose_prod rc (whd_beta hd2)
+
+let rec build_product_dep pat_info per_info args body gls =
+ match args with
+ (Hprop {st_label=nam;st_it=This c}
+ | Hvar {st_label=nam;st_it=c})::rest ->
+ let pprod=
+ lift 1 (build_product_dep pat_info per_info rest body gls) in
+ let lbody =
+ match nam with
+ Anonymous -> body
+ | Name id -> subst_var id pprod in
+ mkProd (nam,c,lbody)
+ | Hprop ({st_it=Thesis tk} as st)::rest ->
+ let pprod=
+ lift 1 (build_product_dep pat_info per_info rest body gls) in
+ let lbody =
+ match st.st_label with
+ Anonymous -> body
+ | Name id -> subst_var id pprod in
+ let ptyp =
+ match tk with
+ For id ->
+ let obj = mkVar id in
+ let typ =
+ try st_assoc (Name id) pat_info.pat_vars
+ with Not_found ->
+ snd (st_assoc (Name id) pat_info.pat_aliases) in
+ thesis_for obj typ per_info (pf_env gls)
+ | Plain -> get_thesis gls
+ | Sub n -> anomaly "Subthesis in cases" in
+ mkProd (st.st_label,ptyp,lbody)
+ | [] -> body
+
+let build_dep_clause params pat_info per_info hyps gls =
+ let concl=
+ thesis_for pat_info.pat_constr pat_info.pat_typ per_info (pf_env gls) in
+ let open_clause =
+ build_product_dep pat_info per_info hyps concl gls in
+ let prod_one st body =
+ match st.st_label with
+ Anonymous -> mkProd(Anonymous,st.st_it,lift 1 body)
+ | Name id -> mkNamedProd id st.st_it (lift 1 body) in
+ let let_one_in st body =
+ match st.st_label with
+ Anonymous -> mkLetIn(Anonymous,fst st.st_it,snd st.st_it,lift 1 body)
+ | Name id ->
+ mkNamedLetIn id (fst st.st_it) (snd st.st_it) (lift 1 body) in
+ let aliased_clause =
+ List.fold_right let_one_in pat_info.pat_aliases open_clause in
+ List.fold_right prod_one (params@pat_info.pat_vars) aliased_clause
+
+let rec register_dep_subcase id env per_info pat = function
+ EK_nodep -> error "Only \"suppose it is\" can be used here."
+ | EK_unknown ->
+ register_dep_subcase id env per_info pat
+ (EK_dep (start_tree env per_info.per_ind))
+ | EK_dep tree -> EK_dep (add_branch env id [[pat]] tree)
+
+let case_tac params pat_info hyps gls0 =
+ let info = get_its_info gls0 in
+ let id = pf_get_new_id (id_of_string "_subcase") gls0 in
+ let et,per_info,ek,old_clauses,rest =
+ match info.pm_stack with
+ Per (et,pi,ek,old_clauses)::rest -> (et,pi,ek,old_clauses,rest)
+ | _ -> anomaly "wrong place for cases" in
+ let clause = build_dep_clause params pat_info per_info hyps gls0 in
+ let ninfo1 = {info with
+ pm_stack=Suppose_case::info.pm_stack;
+ pm_partial_goal=mkMeta 1;
+ pm_subgoals = [1,clause]} in
+ let nek =
+ register_dep_subcase (id,List.length hyps) (pf_env gls0) per_info
+ pat_info.pat_pat ek in
+ let ninfo2 = {info with
+ pm_stack=Per(et,per_info,nek,id::old_clauses)::rest} in
+ tclTHENS (internal_cut id clause)
+ [tclTHENLIST
+ [tcl_change_info ninfo1;
+ assume_st (params@pat_info.pat_vars);
+ assume_st_letin pat_info.pat_aliases;
+ assume_hyps_or_theses hyps;
+ clear old_clauses];
+ tcl_change_info ninfo2] gls0
+
+(* end cases *)
+
+type instance_stack =
+ (constr option*bool*(constr list) list) list
+
+let initial_instance_stack ids =
+ List.map (fun id -> id,[None,false,[]]) ids
+
+let push_one_arg arg = function
+ [] -> anomaly "impossible"
+ | (head,is_rec,args) :: ctx ->
+ ((head,is_rec,(arg::args)) :: ctx)
+
+let push_arg arg stacks =
+ List.map (fun (id,stack) -> (id,push_one_arg arg stack)) stacks
+
+
+let push_one_head c is_rec ids (id,stack) =
+ let head = if Idset.mem id ids then Some c else None in
+ id,(head,is_rec,[]) :: stack
+
+let push_head c is_rec ids stacks =
+ List.map (push_one_head c is_rec ids) stacks
+
+let pop_one rec_flag (id,stack) =
+ let nstack=
+ match stack with
+ [] -> anomaly "impossible"
+ | [c] as l -> l
+ | (Some head,is_rec,args)::(head0,is_rec0,args0)::ctx ->
+ let arg = applist (head,(List.rev args)) in
+ rec_flag:= !rec_flag || is_rec;
+ (head0,is_rec0,(arg::args0))::ctx
+ | (None,is_rec,args)::(head0,is_rec0,args0)::ctx ->
+ rec_flag:= !rec_flag || is_rec;
+ (head0,is_rec0,(args@args0))::ctx
+ in id,nstack
+
+let pop_stacks stacks =
+ let rec_flag= ref false in
+ let nstacks = List.map (pop_one rec_flag) stacks in
+ !rec_flag , nstacks
+
+let patvar_base = id_of_string "__"
+
+let test_fun (str:string) = ()
+
+let hrec_for obj_id fix_id per_info gls=
+ let obj=mkVar obj_id in
+ let typ=pf_get_hyp_typ gls obj_id in
+ let rc,hd1=decompose_prod typ in
+ let cind,all_args=decompose_app typ in
+ match kind_of_term cind with
+ Ind ind when ind=per_info.per_ind ->
+ let params,args= list_chop per_info.per_nparams all_args in
+ if try
+ (List.for_all2 eq_constr params per_info.per_params)
+ with Invalid_argument _ -> false then
+ let hd2 = applist (mkVar fix_id,args@[obj]) in
+ Some (compose_lam rc (whd_beta hd2))
+ else None
+ | _ -> None
+
+let rec execute_cases at_top fix_name per_info kont0 stacks tree gls =
+ match tree with
+ Pop t ->
+ let is_rec,nstacks = pop_stacks stacks in
+ if is_rec then
+ let _ = test_fun "is_rec=true" in
+ let c_id = pf_get_new_id (id_of_string "_hrec") gls in
+ tclTHEN
+ (intro_mustbe_force c_id)
+ (execute_cases false fix_name per_info kont0 nstacks t) gls
+ else
+ execute_cases false fix_name per_info kont0 nstacks t gls
+ | Push (_,t) ->
+ let id = pf_get_new_id patvar_base gls in
+ let nstacks = push_arg (mkVar id) stacks in
+ let kont = execute_cases false fix_name per_info kont0 nstacks t in
+ tclTHEN
+ (intro_mustbe_force id)
+ begin
+ match fix_name with
+ Anonymous -> kont
+ | Name fix_id ->
+ (fun gls ->
+ if at_top then
+ kont gls
+ else
+ match hrec_for id fix_id per_info gls with
+ None -> kont gls
+ | Some c_obj ->
+ let c_id =
+ pf_get_new_id (id_of_string "_hrec") gls in
+ tclTHENLIST
+ [generalize [c_obj];
+ intro_mustbe_force c_id;
+ kont] gls)
+ end gls
+ | Split(ids,ind,br) ->
+ let (_,typ,_)=destProd (pf_concl gls) in
+ let hd,args=decompose_app (special_whd gls typ) in
+ let _ = assert (ind = destInd hd) in
+ let nparams = (fst (Global.lookup_inductive ind)).mind_nparams in
+ let params = list_firstn nparams args in
+ let constr i =applist (mkConstruct(ind,succ i),params) in
+ let next_tac is_rec i = function
+ Some (sub_ids,tree) ->
+ let br_stacks =
+ List.filter (fun (id,_) -> Idset.mem id sub_ids) stacks in
+ let p_stacks =
+ push_head (constr i) is_rec ids br_stacks in
+ execute_cases false fix_name per_info kont0 p_stacks tree
+ | None ->
+ msgnl (str "Warning : missing case");
+ kont0 (mkMeta 1)
+ in
+ let id = pf_get_new_id patvar_base gls in
+ let kont is_rec =
+ tclTHENSV
+ (general_case_analysis (mkVar id,NoBindings))
+ (Array.mapi (next_tac is_rec) br) in
+ tclTHEN
+ (intro_mustbe_force id)
+ begin
+ match fix_name with
+ Anonymous -> kont false
+ | Name fix_id ->
+ (fun gls ->
+ if at_top then
+ kont false gls
+ else
+ match hrec_for id fix_id per_info gls with
+ None -> kont false gls
+ | Some c_obj ->
+ tclTHENLIST
+ [generalize [c_obj];
+ kont true] gls)
+ end gls
+ | End_of_branch (id,nhyps) ->
+ match List.assoc id stacks with
+ [None,_,args] ->
+ let metas = list_tabulate (fun n -> mkMeta (succ n)) nhyps in
+ kont0 (applist (mkVar id,List.rev_append args metas)) gls
+ | _ -> anomaly "wrong stack size"
+
+let end_tac et2 gls =
+ let info = get_its_info gls in
+ let et1,pi,ek,clauses =
+ match info.pm_stack with
+ Suppose_case::_ ->
+ anomaly "This case should already be trapped"
+ | Claim::_ ->
+ error "\"end claim\" expected."
+ | Focus_claim::_ ->
+ error "\"end focus\" expected."
+ | Per(et',pi,ek,clauses)::_ -> (et',pi,ek,clauses)
+ | [] ->
+ anomaly "This case should already be trapped" in
+ let et =
+ if et1 <> et2 then
+ match et1 with
+ ET_Case_analysis ->
+ error "\"end cases\" expected."
+ | ET_Induction ->
+ error "\"end induction\" expected."
+ else et1 in
+ tclTHEN
+ tcl_erase_info
+ begin
+ match et,ek with
+ _,EK_unknown ->
+ tclSOLVE [simplest_elim pi.per_casee]
+ | ET_Case_analysis,EK_nodep ->
+ tclTHEN
+ (general_case_analysis (pi.per_casee,NoBindings))
+ (default_justification (List.map mkVar clauses))
+ | ET_Induction,EK_nodep ->
+ tclTHENLIST
+ [generalize (pi.per_args@[pi.per_casee]);
+ simple_induct (AnonHyp (succ (List.length pi.per_args)));
+ default_justification (List.map mkVar clauses)]
+ | ET_Case_analysis,EK_dep tree ->
+ tclTHENLIST
+ [generalize (pi.per_args@[pi.per_casee]);
+ execute_cases true Anonymous pi
+ (fun c -> tclTHENLIST
+ [refine c;
+ clear clauses;
+ justification assumption])
+ (initial_instance_stack clauses) tree]
+ | ET_Induction,EK_dep tree ->
+ tclTHEN (generalize (pi.per_args@[pi.per_casee]))
+ begin
+ fun gls0 ->
+ let fix_id = pf_get_new_id (id_of_string "_fix") gls0 in
+ tclTHEN
+ (fix (Some fix_id) (succ (List.length pi.per_args)))
+ (execute_cases true (Name fix_id) pi
+ (fun c ->
+ tclTHENLIST
+ [clear [fix_id];
+ refine c;
+ clear clauses;
+ justification assumption
+ (* justification automation_tac *)])
+ (initial_instance_stack clauses) tree) gls0
+ end
+ end gls
+
+(* escape *)
+
+let rec abstract_metas n avoid head = function
+ [] -> 1,head,[]
+ | (meta,typ)::rest ->
+ let id = Nameops.next_ident_away (id_of_string "_sbgl") avoid in
+ let p,term,args = abstract_metas (succ n) (id::avoid) head rest in
+ succ p,mkLambda(Name id,typ,subst_meta [meta,mkRel p] term),
+ (mkMeta n)::args
+
+let build_refining_context gls =
+ let info = get_its_info gls in
+ let avoid=pf_ids_of_hyps gls in
+ let _,fn,args=abstract_metas 1 avoid info.pm_partial_goal info.pm_subgoals in
+ applist (fn,args)
+
+let escape_command pts =
+ let pts1 = nth_unproven 1 pts in
+ let gls = top_goal_of_pftreestate pts1 in
+ let term = build_refining_context gls in
+ let tac = tclTHEN
+ (abstract_operation (Proof_instr (true,{emph=0;instr=Pescape})) tcl_erase_info)
+ (Tactics.refine term) in
+ traverse 1 (solve_pftreestate tac pts1)
+
+(* General instruction engine *)
+
+let rec do_proof_instr_gen _thus _then instr =
+ match instr with
+ Pthus i ->
+ assert (not _thus);
+ do_proof_instr_gen true _then i
+ | Pthen i ->
+ assert (not _then);
+ do_proof_instr_gen _thus true i
+ | Phence i ->
+ assert (not (_then || _thus));
+ do_proof_instr_gen true true i
+ | Pcut c ->
+ instr_cut mk_stat_or_thesis _thus _then c
+ | Prew (s,c) ->
+ assert (not _then);
+ instr_rew _thus s c
+ | Pconsider (c,hyps) -> consider_tac c hyps
+ | Pgiven hyps -> given_tac hyps
+ | Passume hyps -> assume_tac hyps
+ | Plet hyps -> assume_tac hyps
+ | Pclaim st -> instr_claim false st
+ | Pfocus st -> instr_claim true st
+ | Ptake witl -> take_tac witl
+ | Pdefine (id,args,body) -> define_tac id args body
+ | Pcast (id,typ) -> cast_tac id typ
+ | Pper (et,cs) -> per_tac et cs
+ | Psuppose hyps -> suppose_tac hyps
+ | Pcase (params,pat_info,hyps) -> case_tac params pat_info hyps
+ | Pend (B_elim et) -> end_tac et
+ | Pend _ | Pescape -> anomaly "Not applicable"
+
+let eval_instr {instr=instr} =
+ do_proof_instr_gen false false instr
+
+let rec preprocess pts instr =
+ match instr with
+ Phence i |Pthus i | Pthen i -> preprocess pts i
+ | Pcut _ | Passume _ | Plet _ | Pclaim _ | Pfocus _
+ | Pconsider (_,_) | Pcast (_,_) | Pgiven _ | Ptake _
+ | Pdefine (_,_,_) | Pper _ | Prew _ ->
+ check_not_per pts;
+ true,pts
+ | Pescape ->
+ check_not_per pts;
+ false,pts
+ | Pcase _ | Psuppose _ | Pend (B_elim _) ->
+ true,close_previous_case pts
+ | Pend bt ->
+ false,close_block bt pts
+
+let rec postprocess pts instr =
+ match instr with
+ Phence i | Pthus i | Pthen i -> postprocess pts i
+ | Pcut _ | Passume _ | Plet _ | Pconsider (_,_) | Pcast (_,_)
+ | Pgiven _ | Ptake _ | Pdefine (_,_,_) | Prew (_,_) -> pts
+ | Pclaim _ | Pfocus _ | Psuppose _ | Pcase _ | Pper _ -> nth_unproven 1 pts
+ | Pescape ->
+ escape_command pts
+ | Pend _ ->
+ goto_current_focus_or_top (mark_as_done pts)
+
+let do_instr raw_instr pts =
+ let has_tactic,pts1 = preprocess pts raw_instr.instr in
+ let pts2 =
+ if has_tactic then
+ let gl = nth_goal_of_pftreestate 1 pts1 in
+ let env= pf_env gl in
+ let sigma= project gl in
+ let ist = {ltacvars = ([],[]); ltacrecvars = [];
+ gsigma = sigma; genv = env} in
+ let glob_instr = intern_proof_instr ist raw_instr in
+ let instr =
+ interp_proof_instr (get_its_info gl) sigma env glob_instr in
+ let lock_focus = is_focussing_instr instr.instr in
+ let marker= Proof_instr (lock_focus,instr) in
+ solve_nth_pftreestate 1
+ (abstract_operation marker (eval_instr instr)) pts1
+ else pts1 in
+ postprocess pts2 raw_instr.instr
+
+let proof_instr raw_instr =
+ Pfedit.mutate (do_instr raw_instr)
+
+(*
+
+(* STUFF FOR ITERATED RELATIONS *)
+let decompose_bin_app t=
+ let hd,args = destApp
+
+let identify_transitivity_lemma c =
+ let varx,tx,c1 = destProd c in
+ let vary,ty,c2 = destProd (pop c1) in
+ let varz,tz,c3 = destProd (pop c2) in
+ let _,p1,c4 = destProd (pop c3) in
+ let _,lp2,lp3 = destProd (pop c4) in
+ let p2=pop lp2 in
+ let p3=pop lp3 in
+*)
+
diff --git a/tactics/decl_proof_instr.mli b/tactics/decl_proof_instr.mli
new file mode 100644
index 0000000000..ba8dc7b668
--- /dev/null
+++ b/tactics/decl_proof_instr.mli
@@ -0,0 +1,118 @@
+(************************************************************************)
+(* v * The Coq Proof Assistant / The Coq Development Team *)
+(* <O___,, * CNRS-Ecole Polytechnique-INRIA Futurs-Universite Paris Sud *)
+(* \VV/ **************************************************************)
+(* // * This file is distributed under the terms of the *)
+(* * GNU Lesser General Public License Version 2.1 *)
+(************************************************************************)
+
+(* $Id:$ *)
+
+open Refiner
+open Names
+open Term
+open Tacmach
+
+val go_to_proof_mode: unit -> unit
+val return_from_tactic_mode: unit -> unit
+
+val register_automation_tac: tactic -> unit
+
+val automation_tac : tactic
+
+val daimon_subtree: pftreestate -> pftreestate
+
+val do_instr: Decl_expr.raw_proof_instr -> pftreestate -> pftreestate
+val proof_instr: Decl_expr.raw_proof_instr -> unit
+
+val tcl_change_info : Decl_mode.pm_info -> tactic
+
+val mark_proof_tree_as_done : Proof_type.proof_tree -> Proof_type.proof_tree
+
+val mark_as_done : pftreestate -> pftreestate
+
+val execute_cases : bool ->
+ Names.name ->
+ Decl_mode.per_info ->
+ (Term.constr -> Proof_type.tactic) ->
+ (Names.Idset.elt * (Term.constr option * bool * Term.constr list) list)
+ list ->
+ Decl_mode.split_tree -> Proof_type.tactic
+
+val tree_of_pats :
+ Environ.env ->
+ Names.Idset.elt * int ->
+ Rawterm.cases_pattern list list -> Decl_mode.split_tree
+val add_branch :
+ Environ.env ->
+ Names.Idset.elt * int ->
+ Rawterm.cases_pattern list list ->
+ Decl_mode.split_tree -> Decl_mode.split_tree
+val append_branch :
+ Environ.env ->
+ Names.Idset.elt * int ->
+ int ->
+ Rawterm.cases_pattern list list ->
+ int ->
+ (Names.Idset.t * Decl_mode.split_tree) option ->
+ (Names.Idset.t * Decl_mode.split_tree) option
+
+val append_tree : Environ.env ->
+ Names.Idset.elt * int ->
+ int ->
+ Rawterm.cases_pattern list list ->
+ Decl_mode.split_tree -> Decl_mode.split_tree
+
+val build_dep_clause : Term.types Decl_expr.statement list ->
+ Decl_expr.proof_pattern ->
+ Decl_mode.per_info ->
+ (Term.types Decl_expr.statement, Term.types Decl_expr.or_thesis)
+ Decl_expr.hyp list -> Proof_type.goal Tacmach.sigma -> Term.types
+
+val register_dep_subcase :
+ Names.identifier * int ->
+ Environ.env ->
+ Decl_mode.per_info ->
+ Rawterm.cases_pattern -> Decl_mode.elim_kind -> Decl_mode.elim_kind
+
+val thesis_for : Term.constr ->
+ Term.constr -> Decl_mode.per_info -> Environ.env -> Term.constr
+
+val close_previous_case : pftreestate -> pftreestate
+
+val test_fun : string -> unit
+
+
+val pop_stacks :
+ (Names.identifier *
+ (Term.constr option * bool * Term.constr list) list) list ->
+ bool *
+ (Names.identifier *
+ (Term.constr option * bool * Term.constr list) list) list
+
+
+val push_head : Term.constr ->
+ bool ->
+ Names.Idset.t ->
+ (Names.identifier *
+ (Term.constr option * bool * Term.constr list) list) list ->
+ (Names.identifier *
+ (Term.constr option * bool * Term.constr list) list) list
+
+val push_arg : Term.constr ->
+ (Names.identifier *
+ (Term.constr option * bool * Term.constr list) list) list ->
+ (Names.identifier *
+ (Term.constr option * bool * Term.constr list) list) list
+
+val hrec_for:
+ Names.identifier ->
+ Names.identifier ->
+ Decl_mode.per_info -> Proof_type.goal Tacmach.sigma -> Term.constr option
+
+val consider_match :
+ bool ->
+ Names.Idset.elt list ->
+ Names.Idset.elt list ->
+ (Term.types Decl_expr.statement, Term.types) Decl_expr.hyp list ->
+ Proof_type.tactic
diff --git a/tactics/evar_tactics.ml b/tactics/evar_tactics.ml
index d01cd8ca25..6339ed5363 100644
--- a/tactics/evar_tactics.ml
+++ b/tactics/evar_tactics.ml
@@ -51,7 +51,7 @@ let instantiate n rawc ido gl =
error "not enough uninstantiated existential variables";
if n <= 0 then error "incorrect existential variable index";
let ev,_ = destEvar (List.nth evl (n-1)) in
- let evd' = w_refine (pf_env gl) ev rawc (create_evar_defs sigma) in
+ let evd' = w_refine ev rawc (create_evar_defs sigma) in
Refiner.tclEVARS (evars_of evd') gl
(*
diff --git a/tactics/leminv.ml b/tactics/leminv.ml
index e78731f57f..a0ff76968a 100644
--- a/tactics/leminv.ml
+++ b/tactics/leminv.ml
@@ -217,7 +217,7 @@ let inversion_scheme env sigma t sort dep_option inv_op =
(str"Computed inversion goal was not closed in initial signature");
*)
let invSign = named_context_val invEnv in
- let pfs = mk_pftreestate (mk_goal invSign invGoal) in
+ let pfs = mk_pftreestate (mk_goal invSign invGoal None) in
let pfs = solve_pftreestate (tclTHEN intro (onLastHyp inv_op)) pfs in
let (pfterm,meta_types) = extract_open_pftreestate pfs in
let global_named_context = Global.named_context () in
diff --git a/tactics/tacinterp.mli b/tactics/tacinterp.mli
index bccdd39439..fea10de7f8 100644
--- a/tactics/tacinterp.mli
+++ b/tactics/tacinterp.mli
@@ -84,6 +84,9 @@ val interp_genarg :
val intern_genarg :
glob_sign -> raw_generic_argument -> glob_generic_argument
+val intern_tactic :
+ glob_sign -> raw_tactic_expr -> glob_tactic_expr
+
val intern_constr :
glob_sign -> constr_expr -> rawconstr_and_expr
diff --git a/toplevel/vernacentries.ml b/toplevel/vernacentries.ml
index 09c63fc431..edff6b225e 100644
--- a/toplevel/vernacentries.ml
+++ b/toplevel/vernacentries.ml
@@ -20,6 +20,7 @@ open Term
open Pfedit
open Tacmach
open Proof_trees
+open Decl_mode
open Constrintern
open Prettyp
open Printer
@@ -93,7 +94,10 @@ let show_script () =
let pts = get_pftreestate () in
let pf = proof_of_pftreestate pts
and evc = evc_of_pftreestate pts in
- msgnl (print_treescript true evc (Global.named_context()) pf)
+ msgnl (print_treescript true evc pf)
+
+let show_thesis () =
+ msgnl (anomaly "TODO" )
let show_top_evars () =
let pfts = get_pftreestate () in
@@ -532,6 +536,7 @@ let vernac_identity_coercion stre id qids qidt =
let vernac_solve n tcom b =
if not (refining ()) then
error "Unknown command of the non proof-editing mode";
+ Decl_mode.check_not_proof_mode "Unknown proof instruction";
begin
if b then
solve_nth n (Tacinterp.hide_interp tcom (get_end_tac ()))
@@ -542,7 +547,7 @@ let vernac_solve n tcom b =
if subtree_solved () then begin
Options.if_verbose msgnl (str "Subgoal proved");
make_focus 0;
- reset_top_of_tree ()
+ reset_top_of_script ()
end;
print_subgoals();
if !pcoq <> None then (out_some !pcoq).solve n
@@ -559,8 +564,35 @@ let vernac_set_end_tac tac =
if not (refining ()) then
error "Unknown command of the non proof-editing mode";
if tac <> (Tacexpr.TacId []) then set_end_tac (Tacinterp.interp tac) else ()
- (* TO DO verifier s'il faut pas mettre exist s | TacId s ici*)
-
+ (* TO DO verifier s'il faut pas mettre exist s | TacId s ici*)
+
+(***********************)
+(* Proof Language Mode *)
+
+let vernac_decl_proof () =
+ check_not_proof_mode "Already in Proof Mode";
+ if tree_solved () then
+ error "Nothing left to prove here."
+ else
+ begin
+ Decl_proof_instr.go_to_proof_mode ();
+ print_subgoals ()
+ end
+
+let vernac_return () =
+ match get_current_mode () with
+ Mode_tactic ->
+ Decl_proof_instr.return_from_tactic_mode ();
+ print_subgoals ()
+ | Mode_proof ->
+ error "\"return\" is only used after \"escape\"."
+ | Mode_none ->
+ error "There is no proof to end."
+
+let vernac_proof_instr instr =
+ Decl_proof_instr.proof_instr instr;
+ print_subgoals ()
+
(*****************************)
(* Auxiliary file management *)
@@ -993,13 +1025,16 @@ let vernac_backtrack snum pnum naborts =
(* Est-ce normal que "Focus" ne semble pas se comporter comme "Focus 1" ? *)
-let vernac_focus = function
- | None -> traverse_nth_goal 1; print_subgoals ()
- | Some n -> traverse_nth_goal n; print_subgoals ()
-
+let vernac_focus gln =
+ check_not_proof_mode "No focussing or Unfocussing in Proof Mode.";
+ match gln with
+ | None -> traverse_nth_goal 1; print_subgoals ()
+ | Some n -> traverse_nth_goal n; print_subgoals ()
+
(* Reset the focus to the top of the tree *)
let vernac_unfocus () =
- make_focus 0; reset_top_of_tree (); print_subgoals ()
+ check_not_proof_mode "No focussing or Unfocussing in Proof Mode.";
+ make_focus 0; reset_top_of_script (); print_subgoals ()
let vernac_go = function
| GoTo n -> Pfedit.traverse n;show_node()
@@ -1018,7 +1053,7 @@ let apply_subproof f occ =
f evc (Global.named_context()) pf
let explain_proof occ =
- msg (apply_subproof (print_treescript true) occ)
+ msg (apply_subproof (fun evd _ -> print_treescript true evd) occ)
let explain_tree occ =
msg (apply_subproof print_proof occ)
@@ -1042,9 +1077,11 @@ let vernac_show = function
msgnl (prlist_with_sep pr_spc pr_id (Pfedit.get_all_proof_names()))
| ShowIntros all -> show_intro all
| ShowMatch id -> show_match id
+ | ShowThesis -> show_thesis ()
| ExplainProof occ -> explain_proof occ
| ExplainTree occ -> explain_tree occ
+
let vernac_check_guard () =
let pts = get_pftreestate () in
let pf = proof_of_pftreestate pts in
@@ -1109,6 +1146,14 @@ let interp c = match c with
| VernacSolve (n,tac,b) -> vernac_solve n tac b
| VernacSolveExistential (n,c) -> vernac_solve_existential n c
+ (* MMode *)
+
+ | VernacDeclProof -> vernac_decl_proof ()
+ | VernacReturn -> vernac_return ()
+ | VernacProofInstr stp -> vernac_proof_instr stp
+
+ (* /MMode *)
+
(* Auxiliary file and library management *)
| VernacRequireFrom (exp,spec,f) -> vernac_require_from exp spec f
| VernacAddLoadPath (isrec,s,alias) -> vernac_add_loadpath isrec s alias
diff --git a/toplevel/vernacexpr.ml b/toplevel/vernacexpr.ml
index 8b654e12d2..a87221c758 100644
--- a/toplevel/vernacexpr.ml
+++ b/toplevel/vernacexpr.ml
@@ -99,6 +99,7 @@ type showable =
| ShowProofNames
| ShowIntros of bool
| ShowMatch of lident
+ | ShowThesis
| ExplainProof of int list
| ExplainTree of int list
@@ -222,9 +223,17 @@ type vernac_expr =
module_binder list * module_type_ast option
(* Solving *)
+
| VernacSolve of int * raw_tactic_expr * bool
| VernacSolveExistential of int * constr_expr
+ (* Proof Mode *)
+
+ | VernacDeclProof
+ | VernacReturn
+ | VernacProofInstr of Decl_expr.raw_proof_instr
+
+
(* Auxiliary file and library management *)
| VernacRequireFrom of export_flag option * specif_flag option * lstring
| VernacAddLoadPath of rec_flag * lstring * dir_path option