Skip to content

Commit 67d1f60

Browse files
committed
fix
1 parent 5baf6f0 commit 67d1f60

3 files changed

Lines changed: 98 additions & 160 deletions

File tree

Foundation/FirstOrder/Basic/Calculus.lean

Lines changed: 26 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ end Sequent
3636

3737
/-- Derivation for one-sided $\mathbf{LK}$ -/
3838
inductive Derivation : Sequent L → Type _
39-
| protected id (r : L.Rel k) (v) : Derivation [.rel r v, .nrel r v]
39+
| identity (r : L.Rel k) (v) : Derivation [.rel r v, .nrel r v]
4040
| cut : Derivation (φ :: Γ) → Derivation (∼φ :: Δ) → Derivation (Γ ++ Δ)
4141
| wk : Derivation Δ → Δ ⊆ Γ → Derivation Γ
4242
| verum : Derivation [⊤]
@@ -52,19 +52,19 @@ namespace Derivation
5252
open Rewriting LawfulSyntacticRewriting
5353

5454
def height {Δ : Sequent L} : ⊢ᴷ Δ → ℕ
55-
| .id _ _ => 0
56-
| cut dp dn => (max (height dp) (height dn)).succ
57-
| wk d _ => d.height.succ
58-
| verum => 0
59-
| or d => d.height.succ
60-
| and dp dq => (max (height dp) (height dq)).succ
61-
| all d => d.height.succ
62-
| exs d => d.height.succ
55+
| identity _ _ => 0
56+
| cut dp dn => max dp.height dn.height + 1
57+
| wk d _ => d.height + 1
58+
| verum => 0
59+
| or d => d.height + 1
60+
| and dp dq => max (height dp) (height dq) + 1
61+
| all d => d.height + 1
62+
| exs d => d.height + 1
6363

6464
section height
6565

6666
@[simp] lemma height_id {k} {r : L.Rel k} {v} :
67-
height (Derivation.id r v) = 0 := rfl
67+
height (identity r v) = 0 := rfl
6868

6969
@[simp] lemma height_cut {φ} (dp : ⊢ᴷ φ :: Δ) (dn : ⊢ᴷ (∼φ) :: Δ) :
7070
height (cut dp dn) = (max (height dp) (height dn)).succ := rfl
@@ -93,43 +93,43 @@ def weakening (d : ⊢ᴷ Δ) (h : Δ ⊆ Γ := by simp) : ⊢ᴷ Γ := wk d h
9393

9494
def top (h : ⊤ ∈ Δ := by simp) : ⊢ᴷ Δ := verum.wk (by simp [h])
9595

96-
def id' (r : L.Rel k) (v) (hpos : Semiformula.rel r v ∈ Δ := by simp) (hneg : Semiformula.nrel r v ∈ Δ := by simp) : ⊢ᴷ Δ :=
97-
(Derivation.id r v).wk (by simp [hpos, hneg])
96+
def identity' (r : L.Rel k) (v) (hpos : Semiformula.rel r v ∈ Δ := by simp) (hneg : Semiformula.nrel r v ∈ Δ := by simp) : ⊢ᴷ Δ :=
97+
(identity r v).wk (by simp [hpos, hneg])
9898

9999
def tensor {φ ψ} (dφ : ⊢ᴷ φ :: Γ) (dψ : ⊢ᴷ ψ :: Δ) : ⊢ᴷ φ ⋏ ψ :: (Γ ++ Δ) := and dφ.weakening dψ.weakening
100100

101101
def rotate (d : ⊢ᴷ φ :: Γ) : ⊢ᴷ Γ ++ [φ] := d.weakening
102102

103-
def identity : (φ : Proposition L) → ⊢ᴷ [φ, ∼φ]
104-
| .rel R v | .nrel R v => id' R v
103+
def eta : (φ : Proposition L) → ⊢ᴷ [φ, ∼φ]
104+
| .rel R v | .nrel R v => identity' R v
105105
| ⊤ | ⊥ => top
106-
| φ ⋏ ψ => ((identity φ).tensor (identity ψ)).rotate.or.rotate
107-
| φ ⋎ ψ => ((identity φ).rotate.tensor (identity ψ).rotate).rotate.or
106+
| φ ⋏ ψ => ((eta φ).tensor (eta ψ)).rotate.or.rotate
107+
| φ ⋎ ψ => ((eta φ).rotate.tensor (eta ψ).rotate).rotate.or
108108
| ∀⁰ φ =>
109-
have : ⊢ᴷ [(∼φ.shift)/[&0], φ.free] := (identity φ.free).rotate.cast
109+
have : ⊢ᴷ [(∼φ.shift)/[&0], φ.free] := (eta φ.free).rotate.cast
110110
have : ⊢ᴷ φ.free :: [∃⁰ ∼φ]⁺ := this.exs.rotate.cast
111111
this.all
112112
| ∃⁰ φ =>
113-
have : ⊢ᴷ [(φ.shift)/[&0], (∼φ).free] := (identity φ.free).cast
113+
have : ⊢ᴷ [(φ.shift)/[&0], (∼φ).free] := (eta φ.free).cast
114114
have : ⊢ᴷ (∼φ).free :: [∃⁰ φ]⁺ := this.exs.rotate.cast
115115
this.all.rotate
116116
termination_by φ => φ.complexity
117117

118118
def close (φ : Proposition L) (hp : φ ∈ Δ := by simp) (hn : ∼φ ∈ Δ := by simp) : ⊢ᴷ Δ :=
119-
identity φ |>.weakening (by simp [hp, hn])
119+
eta φ |>.weakening (by simp [hp, hn])
120120

121121
instance : OneSidedLK (Derivation (L := L)) where
122122
verum := verum
123123
and d₁ d₂ := d₁.and d₂
124124
or d := d.or
125125
wk d ss := d.wk ss
126-
identity φ := identity φ
126+
identity φ := eta φ
127127

128128
instance : OneSidedLK.Cut (Derivation (L := L)) where
129129
cut dp dn := cut dp dn
130130

131131
def rewrite {Γ} (f : ℕ → SyntacticTerm L) : ⊢ᴷ Γ → ⊢ᴷ Γ.map (Rew.rewrite f ▹ ·)
132-
| .id R v => Derivation.id R (Rew.rewrite f ∘ v)
132+
| identity R v => identity R (Rew.rewrite f ∘ v)
133133
| cut (φ := φ) (Γ := Γ) (Δ := Δ) d₁ d₂ =>
134134
have d₁ : ⊢ᴷ Rew.rewrite f ▹ φ :: Γ.map (app (Rew.rewrite f)) := (d₁.rewrite f).cast
135135
have d₂ : ⊢ᴷ ∼(Rew.rewrite f ▹ φ) :: Δ.map (app (Rew.rewrite f)) := (d₂.rewrite f).cast
@@ -165,8 +165,8 @@ lemma shifts_image (Φ : L₁ →ᵥ L₂) {Δ : List (Proposition L₁)} :
165165
simp [Rewriting.shifts, Function.comp_def, Semiformula.lMap_shift]
166166

167167
def lMap (Φ : L₁ →ᵥ L₂) {Γ} : ⊢ᴷ Γ → ⊢ᴷ Γ.map (.lMap Φ)
168-
| .id r v =>
169-
.cast (Derivation.id (Φ.rel r) (fun i ↦ .lMap Φ (v i)))
168+
| identity r v =>
169+
.cast (identity (Φ.rel r) (fun i ↦ .lMap Φ (v i)))
170170
(by simp [Semiformula.lMap_rel, Semiformula.lMap_nrel])
171171
| cut (Γ := Γ) (Δ := Δ) (φ := φ) d dn =>
172172
have : ⊢ᴷ (Γ.map (.lMap Φ) ++ Δ.map (.lMap Φ) : Sequent L₂) :=
@@ -327,8 +327,8 @@ def disj₂ {Γ Δ : Sequent L} : ⊢ᴷ Γ ++ Δ → ⊢ᴷ ⋁Γ :: Δ := fun
327327
have d₁ : ⊢ᴷ (φ ⋎ ψ) ⋎ Φ :: Δ := this.disj₂
328328
have d₂ : ⊢ᴷ [(∼φ ⋏ ∼ψ) ⋏ ∼Φ, φ ⋎ ψ ⋎ Φ] :=
329329
have : ⊢ᴷ [φ, ψ ⋎ Φ, (∼φ ⋏ ∼ψ) ⋏ ∼Φ] :=
330-
((identity φ).rotate.tensor (identity ψ).rotate).tensor
331-
(identity Φ).rotate |>.rotate.rotate.or.weakening
330+
((eta φ).rotate.tensor (eta ψ).rotate).tensor
331+
(eta Φ).rotate |>.rotate.rotate.or.weakening
332332
this.or.rotate
333333
d₂.eCut d₁
334334
termination_by _ => Γ.length
@@ -370,7 +370,7 @@ lemma iff_context {𝓢 : Schema L} : 𝓢 ⊢ φ ↔ 𝓢 *⊢[𝐋𝐊¹] φ :
370370
have d : ⊢ᴷ [⋁(∼Γ) ⋎ φ] := d.cast (by simp [Semiformula.imp_eq])
371371
have : ⊢ᴷ ⋀Γ ⋏ ∼φ :: φ :: ∼Γ :=
372372
have : ⊢ᴷ ⋀Γ :: ∼Γ := Derivation.conj₂ fun φ h ↦ close φ (by simp) (by simp [h])
373-
this.tensor (identity φ).rotate |>.weakening
373+
this.tensor (eta φ).rotate |>.weakening
374374
refine ⟨⟨Γ, h, (d.eCut this).cast⟩⟩
375375

376376
open Classical in

Foundation/Propositional/ClassicalSemantics/Tait.lean

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@ public import Foundation.Vorspiel.Set.Basic
88

99
namespace LO.Propositional
1010

11+
/-
1112
13+
TODO: fix
1214
1315
variable {α : Type*} {T : Theory α} {Γ : Sequent α}
1416
@@ -219,3 +221,5 @@ end Propositional
219221
220222
end LO
221223
end
224+
225+
-/

Foundation/Propositional/Tait/Calculus.lean

Lines changed: 68 additions & 134 deletions
Original file line numberDiff line numberDiff line change
@@ -7,158 +7,92 @@ public import Foundation.Logic.Calculus
77

88
namespace LO.Propositional
99

10-
variable {α : Type*}
11-
1210
abbrev Sequent (α : Type*) := List (NNFormula α)
1311

14-
inductive Derivation (T : Theory α) : Sequent α → Type _
15-
| axL (Δ a) : Derivation T (NNFormula.atom a :: NNFormula.natom a :: Δ)
16-
| verum (Δ) : Derivation T (⊤ :: Δ)
17-
| or {Δ φ ψ} : Derivation T (φ :: ψ :: Δ) → Derivation T (φ ⋎ ψ :: Δ)
18-
| and {Δ φ ψ} : Derivation T (φ :: Δ) → Derivation T (ψ :: Δ) → Derivation T (φ ⋏ ψ :: Δ)
19-
| wk {Δ Γ} : Derivation T Δ → Δ ⊆ Γ → Derivation T Γ
20-
| cut {Δ φ} : Derivation T (φ :: Δ) → Derivation T (∼φ :: Δ) → Derivation T Δ
21-
| axm {φ} : φ ∈ T → Derivation T [φ]
12+
inductive Derivation : Sequent α → Type _
13+
| identity (a : α) : Derivation [NNFormula.atom a, NNFormula.natom a]
14+
| cut : Derivation (φ :: Γ) → Derivation (∼φ :: Δ) → Derivation (Γ ++ Δ)
15+
| wk : Derivation Δ → Δ ⊆ Γ → Derivation Γ
16+
| verum : Derivation [⊤]
17+
| or : Derivation (φ :: ψ :: Γ) → Derivation (φ ⋎ ψ :: Γ)
18+
| and : Derivation (φ :: Γ) → Derivation (ψ :: Γ) → Derivation (φ ⋏ ψ :: Γ)
2219

23-
instance : OneSided (Theory α) (NNFormula α) := ⟨Derivation
20+
scoped prefix:45 "⊢ᴷ " => Derivation
2421

2522
namespace Derivation
2623

2724
variable {T U : Theory α} {Δ Δ₁ Δ₂ Γ : Sequent α}
2825

29-
def length {Δ : Sequent α} : T ⟹ Δ → ℕ
30-
| axL _ _ => 0
31-
| verum _ => 0
32-
| or d => d.length.succ
33-
| and dp dq => (max (length dp) (length dq)).succ
34-
| wk d _ => d.length.succ
35-
| cut dp dn => (max (length dp) (length dn)).succ
36-
| axm _ => 0
26+
def height {Δ : Sequent α} : ⊢ᴷ Δ → ℕ
27+
|identity _ => 0
28+
| cut dp dn => max dp.height dn.height + 1
29+
| wk d _ => d.height + 1
30+
| verum => 0
31+
| or d => d.height + 1
32+
| and dp dq => max (height dp) (height dq) + 1
3733

38-
protected def cast (d : T ⟹ Δ) (e : Δ = Γ) : T ⟹ Γ := cast (by simp [e]) d
34+
protected def cast (d : ⊢ᴷ Δ) (e : Δ = Γ) : ⊢ᴷ Γ := cast (by simp [e]) d
3935

40-
@[simp] lemma length_cast (d : T ⟹ Δ) (e : Δ = Γ) : length (Derivation.cast d e) = length d := by
36+
@[simp] lemma height_cast (d : ⊢ᴷ Δ) (e : Δ = Γ) : height (Derivation.cast d e) = height d := by
4137
rcases e with rfl; simp [Derivation.cast]
4238

43-
def verum' (h : ⊤ ∈ Δ) : T ⟹ Δ := (verum Δ).wk (by simp [h])
44-
45-
def axL' (a : α)
46-
(h : NNFormula.atom a ∈ Δ) (hn : NNFormula.natom a ∈ Δ) : T ⟹ Δ := (axL Δ a).wk (by simp [h, hn])
47-
48-
def em {φ : NNFormula α} {Δ : Sequent α} (hpos : φ ∈ Δ) (hneg : ∼φ ∈ Δ) : T ⟹ Δ := by
49-
induction φ using NNFormula.rec' generalizing Δ <;> simp at hneg
50-
case hverum => exact verum' hpos
51-
case hfalsum => exact verum' hneg
52-
case hatom a => exact axL' a hpos hneg
53-
case hnatom a => exact axL' a hneg hpos
54-
case hand φ ψ ihp ihq =>
55-
have ihp : T ⟹ φ :: ∼φ :: ∼ψ :: Δ := ihp (by simp) (by simp)
56-
have ihq : T ⟹ ψ :: ∼φ :: ∼ψ :: Δ := ihq (by simp) (by simp)
57-
have : T ⟹ ∼φ :: ∼ψ :: Δ := (ihp.and ihq).wk (by simp [hpos])
58-
exact this.or.wk (by simp [hneg])
59-
case hor φ ψ ihp ihq =>
60-
have ihp : T ⟹ ∼φ :: φ :: ψ :: Δ := ihp (by simp) (by simp)
61-
have ihq : T ⟹ ∼ψ :: φ :: ψ :: Δ := ihq (by simp) (by simp)
62-
have : T ⟹ φ :: ψ :: Δ := (ihp.and ihq).wk (by simp [hneg])
63-
exact this.or.wk (by simp [hpos])
64-
65-
instance : Tait (NNFormula α) (Theory α) where
66-
verum := fun _ Δ => Derivation.verum Δ
67-
and := fun dp dq => Derivation.cast (dp.and dq) (by simp)
68-
or := fun d => Derivation.cast d.or (by simp)
69-
wk := fun d ss => d.wk ss
70-
em := fun hp hn => Derivation.em hp hn
71-
72-
instance : Tait.Cut (NNFormula α) (Theory α) := ⟨Derivation.cut⟩
73-
74-
def trans (F : U ⊢!* T) {Γ : Sequent α} : T ⟹ Γ → U ⟹ Γ
75-
| axL Γ φ => axL Γ φ
76-
| verum Γ => verum Γ
77-
| and d₁ d₂ => and (trans F d₁) (trans F d₂)
78-
| or d => or (trans F d)
79-
| wk d ss => wk (trans F d) ss
80-
| cut d₁ d₂ => cut (trans F d₁) (trans F d₂)
81-
| axm h => F h
82-
83-
instance : Tait.Axiomatized (NNFormula α) (Theory α) where
84-
axm {_ _ h} := axm h
85-
trans {_ _ _ F d} := trans (fun h ↦ F _ h) d
86-
87-
variable [DecidableEq α]
88-
89-
def compact {Γ : Sequent α} : T ⟹ Γ → (s : { s : Finset (NNFormula α) // ↑s ⊆ T}) × (s : Theory α) ⟹ Γ
90-
| axL Γ φ => ⟨⟨∅, by simp⟩, axL Γ φ⟩
91-
| verum Γ => ⟨⟨∅, by simp⟩, verum Γ⟩
92-
| and d₁ d₂ =>
93-
let ⟨s₁, d₁⟩ := compact d₁
94-
let ⟨s₂, d₂⟩ := compact d₂
95-
⟨⟨(s₁ ∪ s₂ : Finset (NNFormula α)), by simp [s₁.prop, s₂.prop]⟩,
96-
and (Tait.ofAxiomSubset (by simp) d₁) (Tait.ofAxiomSubset (by simp) d₂)⟩
97-
| or d =>
98-
let ⟨s, d⟩ := compact d
99-
⟨s, or d⟩
100-
| wk d ss =>
101-
let ⟨s, d⟩ := compact d
102-
⟨s, wk d ss⟩
103-
| cut d₁ d₂ =>
104-
let ⟨s₁, d₁⟩ := compact d₁
105-
let ⟨s₂, d₂⟩ := compact d₂
106-
⟨⟨(s₁ ∪ s₂ : Finset (NNFormula α)), by simp [s₁.prop, s₂.prop]⟩,
107-
cut (Tait.ofAxiomSubset (by simp) d₁) (Tait.ofAxiomSubset (by simp) d₂)⟩
108-
| axm (φ := φ) h =>
109-
⟨⟨{φ}, by simp [h]⟩, axm (by simp)⟩
110-
111-
instance : Entailment.Compact (Theory α) where
112-
Γ b := (compact b).1
113-
ΓPrf b := (compact b).2
114-
Γ_subset b := by simpa using (compact b).1.prop
115-
Γ_finite b := by simp
116-
117-
def deductionAux {Γ : Sequent α} {φ} : T ⟹ Γ → T \ {φ} ⟹ ∼φ :: Γ
118-
| axL Γ φ => wk (axL Γ φ) (by simp)
119-
| verum Γ => wk (verum Γ) (by simp)
120-
| and d₁ d₂ =>
121-
Tait.rotate₁ <| and (Tait.rotate₁ <| deductionAux d₁) (Tait.rotate₁ <| deductionAux d₂)
122-
| or d => Tait.rotate₁ <| Tait.or <| Tait.wk (deductionAux d) (by intro x; simp; tauto)
123-
| wk d ss => wk (deductionAux d) <| List.cons_subset_cons (∼φ) ss
124-
| cut d₁ d₂ => cut (Tait.rotate₁ <| deductionAux d₁) (Tait.rotate₁ <| deductionAux d₂)
125-
| axm (φ := ψ) h =>
126-
if hq : φ = ψ then em (φ := φ) (by simp [hq]) (by simp) else
127-
Tait.wk (show T \ {φ} ⟹ [ψ] from Tait.axm (by simp [h, Ne.symm hq])) (by simp)
128-
129-
def deduction {Γ : Sequent α} {φ} (d : insert φ T ⟹ Γ) : T ⟹ ∼φ :: Γ := Tait.ofAxiomSubset (by simp) (deductionAux d)
130-
131-
lemma inconsistent_iff_provable :
132-
Entailment.Inconsistent (insert φ T) ↔ T ⊢ ∼φ := by
133-
constructor
134-
· intro h; exact ⟨deduction (Tait.inconsistent_iff_provable.mp h).get⟩
135-
· rintro b
136-
exact Entailment.inconsistent_of_provable_of_unprovable (φ := φ) (Entailment.by_axm _ <| by simp) (Entailment.wk! (by simp) b)
137-
138-
lemma consistent_iff_unprovable :
139-
Entailment.Consistent (insert φ T) ↔ T ⊬ ∼φ := by simp [←Entailment.not_inconsistent_iff_consistent, inconsistent_iff_provable]
140-
141-
omit [DecidableEq α]
142-
@[simp] lemma inconsistent_theory_iff :
143-
Entailment.Inconsistent (Entailment.theory T) ↔ Entailment.Inconsistent T := by
144-
constructor
145-
· intro h
146-
exact Entailment.inconsistent_iff_provable_bot.mpr
147-
<| Entailment.StrongCut.cut! (by simp) <| Entailment.inconsistent_iff_provable_bot.mp h
148-
· intro h; exact h.of_supset (by simpa using Entailment.Axiomatized.axm_subset T)
149-
150-
@[simp] lemma consistent_theory_iff :
151-
Entailment.Consistent (Entailment.theory T) ↔ Entailment.Consistent T := by simp [←Entailment.not_inconsistent_iff_consistent, inconsistent_theory_iff]
39+
def weakening (d : ⊢ᴷ Δ) (h : Δ ⊆ Γ := by simp) : ⊢ᴷ Γ := wk d h
40+
41+
def top (h : ⊤ ∈ Δ := by simp) : ⊢ᴷ Δ := verum.wk (by simp [h])
42+
43+
def identity' (a : α) (hpos : .atom a ∈ Δ := by simp) (hneg : .natom a ∈ Δ := by simp) : ⊢ᴷ Δ :=
44+
(identity a).wk (by simp [hpos, hneg])
45+
46+
def tensor {φ ψ} (dφ : ⊢ᴷ φ :: Γ) (dψ : ⊢ᴷ ψ :: Δ) : ⊢ᴷ φ ⋏ ψ :: (Γ ++ Δ) := and dφ.weakening dψ.weakening
47+
48+
def rotate (d : ⊢ᴷ φ :: Γ) : ⊢ᴷ Γ ++ [φ] := d.weakening
49+
50+
def eta : (φ : NNFormula α) → ⊢ᴷ [φ, ∼φ]
51+
| .atom a | .natom a => identity' a
52+
| ⊤ | ⊥ => top
53+
| φ ⋏ ψ => ((eta φ).tensor (eta ψ)).rotate.or.rotate
54+
| φ ⋎ ψ => ((eta φ).rotate.tensor (eta ψ).rotate).rotate.or
55+
56+
def close (φ : NNFormula α) (hp : φ ∈ Δ := by simp) (hn : ∼φ ∈ Δ := by simp) : ⊢ᴷ Δ :=
57+
eta φ |>.weakening (by simp [hp, hn])
58+
59+
instance : OneSidedLK (Derivation (α := α)) where
60+
verum := verum
61+
and d₁ d₂ := d₁.and d₂
62+
or d := d.or
63+
wk d ss := d.wk ss
64+
identity φ := eta φ
65+
66+
instance : OneSidedLK.Cut (Derivation (α := α)) where
67+
cut dp dn := cut dp dn
15268

15369
end Derivation
15470

155-
abbrev Sequent.Tautology (Γ : Sequent α) := (∅ : Theory α) ⟹ Γ
71+
/-! ## Classical proof system -/
15672

157-
abbrev Sequent.IsTautology (Γ : Sequent α) := (∅ : Theory α) ⟹! Γ
73+
inductive Proof.Symbol (α : Type*) : Type
74+
| symbol
15875

159-
abbrev NNFormula.Tautology (φ : NNFormula α) := Sequent.Tautology [φ]
76+
notation "𝐋𝐊⁰" => Proof.Symbol.symbol
16077

161-
abbrev NNFormula.IsTautology (φ : NNFormula α) := Sequent.IsTautology [φ]
78+
abbrev Proof (φ : NNFormula α) := ⊢ᴷ [φ]
79+
80+
instance : Entailment (Proof.Symbol α) (NNFormula α) where
81+
Prf _ := Proof
82+
83+
namespace Proof
84+
85+
lemma def_eq (φ : NNFormula α) : (𝐋𝐊⁰ ⊢! φ) = (⊢ᴷ [φ]) := rfl
86+
87+
instance : OneSidedLK.EmptyEntailment (Derivation (α := α)) (𝐋𝐊⁰ : Proof.Symbol α) where
88+
equiv := Equiv.refl _
89+
90+
instance classical : Entailment.Cl (𝐋𝐊⁰ : Proof.Symbol α) := inferInstance
91+
92+
end Proof
93+
94+
abbrev NNFormula.IsTautology (φ : NNFormula α) : Prop := 𝐋𝐊⁰ ⊢ φ
16295

16396
end LO.Propositional
97+
16498
end

0 commit comments

Comments
 (0)