@@ -2,104 +2,134 @@ package lisa.utils
2
2
3
3
import lisa .kernel .proof .SequentCalculus .*
4
4
import lisa .utils .K
5
+ import lisa .utils .KernelHelpers .lambda
5
6
import lisa .prooflib .ProofTacticLib .*
6
- import lisa .fol .FOLHelpers .*
7
7
import lisa .fol .FOL as F
8
- import lisa .utils . KernelHelpers . lambda
8
+ import lisa .fol . FOLHelpers . *
9
9
10
10
object ProofsConverter {
11
11
12
12
// TODO: remove unnecessary variables "val s_..." in generated proofs -> need to keep track of which steps are used in other steps
13
13
// TODO: generate more realistic variable names
14
14
// TODO: handle automatic global variable declaration before theorems/proofs
15
15
16
- def scproof2code (p : K .SCProof , premises : Seq [String ] = Seq .empty, indent : Int = 0 , varPrefix : String = " s" ): String = {
17
- def scproofstep2line (ps : SCProofStep , stepNum : Int , premises : Seq [String ], indent : Int , varPrefix : String ): String = {
18
- def sequent2code (sq : Sequent ): String = asFront(sq).toString.replace(" ⇒" , " ==>" ).replace(" ⇔" , " <=>" )
19
- def formula2code (form : K .Formula ): String = asFront(form).toString.replace(" ⇒" , " ==>" ).replace(" ⇔" , " <=>" )
20
- def term2code (term : K .Term ): String = asFront(term).toString.replace(" ⇒" , " ==>" ).replace(" ⇔" , " <=>" )
16
+ private def indent (s : String , indent : Int = 2 ): String = s.split(" \n " ).map(" " * indent + _).mkString(" \n " )
17
+ private def unindent (s : String , indent : Int = 2 ): String = s.split(" \n " ).map(_.drop(indent)).mkString(" \n " )
18
+
19
+ private def any2code (a : K .Sequent | K .Formula | K .Term ): String = (a match
20
+ case sq : K .Sequent => asFront(sq)
21
+ case form : K .Formula => asFront(form)
22
+ case term : K .Term => asFront(term)
23
+ ).toString.replace(" ⇒" , " ==>" ).replace(" ⇔" , " <=>" )
24
+
25
+ def scproof2code (p : K .SCProof ): String = {
26
+ def scproof2codeAux (p : K .SCProof , varPrefix : String = " s" , premises : Seq [String ] = Seq .empty): String = {
27
+ def scproofstep2code (ps : SCProofStep , stepNum : Int , premises : Seq [String ], varPrefix : String ): String = {
21
28
22
- def index2stepvar (i : Int ): String =
23
- if i < - premises.size then throw new Exception (s " step $i is not defined " )
24
- else if i < 0 then premises(- i - 1 )
25
- else s " ${varPrefix}_ $i"
29
+ def index2stepvar (i : Int ): String =
30
+ if i < - premises.size then throw new Exception (s " step $i is not defined " )
31
+ else if i < 0 then premises(- i - 1 )
32
+ else s " ${varPrefix}_ $i"
26
33
27
- val varDecl = " " * indent + s " val ${varPrefix}_ $stepNum = "
28
- ps match
29
- case Sorry (_) => " sorry"
30
- case sp @ SCSubproof (_, _) =>
31
- varDecl + s " have( ${sequent2code(sp.bot)}) subproof { \n " + scproof2code(sp.sp, sp.premises.map(index2stepvar), indent + 1 , s " ${varPrefix}_ $stepNum" ) + " \n " + " " * indent + " }"
32
- case _ =>
33
- var tacticName = ps.getClass.getSimpleName
34
- var opening = " ("
35
- var closing = " )"
36
- val (bot_, step_ref_seq) = (ps match
37
- case Restate (bot, t1) =>
38
- opening = " .from("
39
- (bot, Seq (t1))
40
- case RestateTrue (bot) =>
41
- tacticName = " Restate"
42
- (bot, null )
43
- case Hypothesis (bot, phi) => (bot, null )
44
- case Cut (bot, t1, t2, phi) => (bot, Seq (t1, t2))
45
- case LeftAnd (bot, t1, phi, psi) => (bot, Seq (t1))
46
- case LeftOr (bot, t, disjuncts) => (bot, t)
47
- case LeftImplies (bot, t1, t2, phi, psi) => (bot, Seq (t1, t2))
48
- case LeftIff (bot, t1, phi, psi) => (bot, Seq (t1))
49
- case LeftNot (bot, t1, phi) => (bot, Seq (t1))
50
- case LeftForall (bot, t1, phi, x, t) => (bot, Seq (t1))
51
- case LeftExists (bot, t1, phi, x) => (bot, Seq (t1))
52
- case LeftExistsOne (bot, t1, phi, x) => (bot, Seq (t1))
53
- case RightAnd (bot, t, conjuncts) => (bot, t)
54
- case RightOr (bot, t1, phi, psi) => (bot, Seq (t1))
55
- case RightImplies (bot, t1, phi, psi) => (bot, Seq (t1))
56
- case RightIff (bot, t1, t2, phi, psi) => (bot, Seq (t1, t2))
57
- case RightNot (bot, t1, phi) => (bot, Seq (t1))
58
- case RightForall (bot, t1, phi, x) => (bot, Seq (t1))
59
- case RightExists (bot, t1, phi, x, t) => (bot, Seq (t1))
60
- case RightExistsOne (bot, t1, phi, x) => (bot, Seq (t1))
61
- case Weakening (bot, t1) => (bot, Seq (t1))
62
- case LeftRefl (bot, t1, phi) => (bot, Seq (t1))
63
- case RightRefl (bot, phi) => (bot, null )
64
- case LeftSubstEq (bot, t1, equals, lambdaPhi) => (bot, Seq (t1))
65
- case RightSubstEq (bot, t1, equals, lambdaPhi) => (bot, Seq (t1))
66
- case LeftSubstIff (bot, t1, equals, lambdaPhi) =>
67
- tacticName = s " LeftSubstIff.withParametersSimple(List( ${equals
68
- .map((a, b) => s " (( ${formula2code(a.body)}), ( ${formula2code(b.body)})) " )
69
- .mkString(" , " )}), lambda(Seq( ${lambdaPhi._1.map(asFrontLabel).mkString(" , " )}), ${formula2code(lambdaPhi._2)})) "
70
- (bot, Seq (t1))
71
- case RightSubstIff (bot, t1, equals, lambdaPhi) =>
72
- tacticName = s " RightSubstIff.withParametersSimple(List( ${equals
73
- .map((a, b) => s " (( ${formula2code(a.body)}), ( ${formula2code(b.body)})) " )
74
- .mkString(" , " )}), lambda(Seq( ${lambdaPhi._1.map(asFrontLabel).mkString(" , " )}), ${formula2code(lambdaPhi._2)})) "
75
- (bot, Seq (t1))
76
- case InstSchema (bot, t1, mCon, mPred, mTerm) =>
77
- if mCon.isEmpty && mPred.isEmpty then
78
- tacticName = s " InstFunSchema(Map( ${mTerm.toList
79
- .map((k, v) => s " ${asFrontLabel(k)} -> ${term2code(v.body)}" )
80
- .mkString(" , " )})) "
34
+ ps match
35
+ case Sorry (_) => " sorry"
36
+ case sp @ SCSubproof (_, _) =>
37
+ indent(
38
+ s " val ${varPrefix}_ $stepNum = have( ${any2code(sp.bot)}) subproof { \n " +
39
+ scproof2codeAux(sp.sp, s " ${varPrefix}_ $stepNum" , sp.premises.map(index2stepvar)) +
40
+ " \n }"
41
+ )
42
+ case _ =>
43
+ var tacticName = ps.getClass.getSimpleName
44
+ var opening = " ("
45
+ var closing = " )"
46
+ val (bot_, step_ref_seq) = (ps match
47
+ case Restate (bot, t1) =>
48
+ opening = " .from("
81
49
(bot, Seq (t1))
82
- else if mCon.isEmpty && mTerm.isEmpty then
83
- tacticName = s " InstPredSchema(Map( ${mPred.toList
84
- .map((k, v) => s " ${asFrontLabel(k)} -> ${formula2code(v.body)}" )
85
- .mkString(" , " )})) "
50
+ case RestateTrue (bot) =>
51
+ tacticName = " Restate"
52
+ (bot, null )
53
+ case Hypothesis (bot, phi) => (bot, null )
54
+ case Cut (bot, t1, t2, phi) => (bot, Seq (t1, t2))
55
+ case LeftAnd (bot, t1, phi, psi) => (bot, Seq (t1))
56
+ case LeftOr (bot, t, disjuncts) => (bot, t)
57
+ case LeftImplies (bot, t1, t2, phi, psi) => (bot, Seq (t1, t2))
58
+ case LeftIff (bot, t1, phi, psi) => (bot, Seq (t1))
59
+ case LeftNot (bot, t1, phi) => (bot, Seq (t1))
60
+ case LeftForall (bot, t1, phi, x, t) => (bot, Seq (t1))
61
+ case LeftExists (bot, t1, phi, x) => (bot, Seq (t1))
62
+ case LeftExistsOne (bot, t1, phi, x) => (bot, Seq (t1))
63
+ case RightAnd (bot, t, conjuncts) => (bot, t)
64
+ case RightOr (bot, t1, phi, psi) => (bot, Seq (t1))
65
+ case RightImplies (bot, t1, phi, psi) => (bot, Seq (t1))
66
+ case RightIff (bot, t1, t2, phi, psi) => (bot, Seq (t1, t2))
67
+ case RightNot (bot, t1, phi) => (bot, Seq (t1))
68
+ case RightForall (bot, t1, phi, x) => (bot, Seq (t1))
69
+ case RightExists (bot, t1, phi, x, t) => (bot, Seq (t1))
70
+ case RightExistsOne (bot, t1, phi, x) => (bot, Seq (t1))
71
+ case Weakening (bot, t1) => (bot, Seq (t1))
72
+ case LeftRefl (bot, t1, phi) => (bot, Seq (t1))
73
+ case RightRefl (bot, phi) => (bot, null )
74
+ case LeftSubstEq (bot, t1, equals, lambdaPhi) =>
75
+ tacticName = s " LeftSubstEq.withParametersSimple(List( ${equals
76
+ .map((a, b) => s " (( ${any2code(a.body)}), ( ${any2code(b.body)})) " )
77
+ .mkString(" , " )}), lambda(Seq( ${lambdaPhi._1.map(asFrontLabel).mkString(" , " )}), ${any2code(lambdaPhi._2)})) "
86
78
(bot, Seq (t1))
87
- else throw new Exception (" InstSchema not implemented" )
88
- case _ => throw new Exception (s " Tactic ${ps.getClass.getName} not implemented " )
89
- )
79
+ case RightSubstEq (bot, t1, equals, lambdaPhi) =>
80
+ tacticName = s " RightSubstEq.withParametersSimple(List( ${equals
81
+ .map((a, b) => s " (( ${any2code(a.body)}), ( ${any2code(b.body)})) " )
82
+ .mkString(" , " )}), lambda(Seq( ${lambdaPhi._1.map(asFrontLabel).mkString(" , " )}), ${any2code(lambdaPhi._2)})) "
83
+ (bot, Seq (t1))
84
+ case LeftSubstIff (bot, t1, equals, lambdaPhi) =>
85
+ tacticName = s " LeftSubstIff.withParametersSimple(List( ${equals
86
+ .map((a, b) => s " (( ${any2code(a.body)}), ( ${any2code(b.body)})) " )
87
+ .mkString(" , " )}), lambda(Seq( ${lambdaPhi._1.map(asFrontLabel).mkString(" , " )}), ${any2code(lambdaPhi._2)})) "
88
+ (bot, Seq (t1))
89
+ case RightSubstIff (bot, t1, equals, lambdaPhi) =>
90
+ tacticName = s " RightSubstIff.withParametersSimple(List( ${equals
91
+ .map((a, b) => s " (( ${any2code(a.body)}), ( ${any2code(b.body)})) " )
92
+ .mkString(" , " )}), lambda(Seq( ${lambdaPhi._1.map(asFrontLabel).mkString(" , " )}), ${any2code(lambdaPhi._2)})) "
93
+ (bot, Seq (t1))
94
+ case InstSchema (bot, t1, mCon, mPred, mTerm) =>
95
+ if mCon.isEmpty && mPred.isEmpty then
96
+ tacticName = s " InstFunSchema(Map( ${mTerm.toList
97
+ .map((k, v) => s " ${asFrontLabel(k)} -> ${any2code(v.body)}" )
98
+ .mkString(" , " )})) "
99
+ (bot, Seq (t1))
100
+ else if mCon.isEmpty && mTerm.isEmpty then
101
+ tacticName = s " InstPredSchema(Map( ${mPred.toList
102
+ .map((k, v) => s " ${asFrontLabel(k)} -> ${any2code(v.body)}" )
103
+ .mkString(" , " )})) "
104
+ (bot, Seq (t1))
105
+ else throw new Exception (" InstSchema not implemented" )
106
+ case _ => throw new Exception (s " Tactic ${ps.getClass.getName} not implemented " )
107
+ )
90
108
91
- varDecl + (
92
- if (step_ref_seq != null && step_ref_seq.size == 1 && stepNum > 0 && step_ref_seq.head + 1 == stepNum)
93
- then s " thenHave( ${sequent2code(bot_)}) by $tacticName"
94
- else
95
- s " have( ${sequent2code(bot_)}) by $tacticName" + (
96
- if step_ref_seq == null then " "
97
- else s " $opening${step_ref_seq.map(index2stepvar).mkString(" , " )}$closing"
109
+ indent(
110
+ s " val ${varPrefix}_ $stepNum = " + (
111
+ if (step_ref_seq != null && step_ref_seq.size == 1 && stepNum > 0 && step_ref_seq.head + 1 == stepNum)
112
+ then s " thenHave( ${any2code(bot_)}) by $tacticName"
113
+ else
114
+ s " have( ${any2code(bot_)}) by $tacticName" + (
115
+ if step_ref_seq == null then " "
116
+ else s " $opening${step_ref_seq.map(index2stepvar).mkString(" , " )}$closing"
117
+ )
98
118
)
99
- )
119
+ )
120
+ }
121
+
122
+ p.steps.zipWithIndex.map((ps, i) => scproofstep2code(ps, i, premises, varPrefix)).mkString(" \n " )
100
123
}
124
+ unindent(scproof2codeAux(p))
125
+ }
101
126
102
- p.steps.zipWithIndex.map((ps, i) => scproofstep2line(ps, i, premises, indent, varPrefix)).mkString(" \n " )
127
+ def generateTheoremCode (name : String , statement : K .Sequent , proof : K .SCProof ): String = {
128
+ s " val $name = Theorem( \n " +
129
+ indent(any2code(statement)) +
130
+ s " \n ) { \n " +
131
+ indent(scproof2code(proof)) +
132
+ s " \n } "
103
133
}
104
134
105
135
}
0 commit comments