import GolangLean.Core.Semantics namespace GolangLean.Core /-! # Determinism of TGC big-step. `BigStep h env e v₁ h₁ → BigStep h env e v₂ h₂ → v₁ = v₂ ∧ h₁ = h₂` By induction on the first derivation, with case analysis on the second. For each pair of constructors, either the term-shape forces them to agree (so we apply the IHs to the sub-derivations) or, in the `ifte` case where two rules share a term shape, an IH on the condition gives a contradictory boolean. -/ theorem BigStep.deterministic {h : Heap} {env : Env} {e : Term} {v₁ v₂ : Value} {h₁ h₂ : Heap} (D₁ : BigStep h env e v₁ h₁) (D₂ : BigStep h env e v₂ h₂) : v₁ = v₂ ∧ h₁ = h₂ := by induction D₁ generalizing v₂ h₂ with | unitR => cases D₂; exact ⟨rfl, rfl⟩ | intLitR n => cases D₂; exact ⟨rfl, rfl⟩ | boolLitR b => cases D₂; exact ⟨rfl, rfl⟩ | varR hLook => cases D₂ with | varR hLook' => have heq := hLook.symm.trans hLook' exact ⟨Option.some.inj heq, rfl⟩ | lamR x body => cases D₂; exact ⟨rfl, rfl⟩ | appR _ _ _ ih1 ih2 ihb => cases D₂ with | appR D1' D2' Db' => have ⟨hClos, hH1⟩ := ih1 D1' injection hClos with hx hbody henv subst hx; subst hbody; subst henv; subst hH1 have ⟨hArg, hH2⟩ := ih2 D2' subst hArg; subst hH2 exact ihb Db' | letInR _ _ ih1 ih2 => cases D₂ with | letInR D1' D2' => have ⟨hv1, hH1⟩ := ih1 D1' subst hv1; subst hH1 exact ih2 D2' | ifTR _ _ ihc iht => cases D₂ with | ifTR Dc' Dt' => have ⟨_, hH1⟩ := ihc Dc' subst hH1 exact iht Dt' | ifFR Dc' _ => have ⟨hb, _⟩ := ihc Dc' injection hb with hb_eq exact Bool.noConfusion hb_eq | ifFR _ _ ihc ihf => cases D₂ with | ifTR Dc' _ => have ⟨hb, _⟩ := ihc Dc' injection hb with hb_eq exact Bool.noConfusion hb_eq | ifFR Dc' Df' => have ⟨_, hH1⟩ := ihc Dc' subst hH1 exact ihf Df' | binopR _ _ Hop ih1 ih2 => cases D₂ with | binopR D1' D2' Hop' => have ⟨hv1, hH1⟩ := ih1 D1' subst hv1; subst hH1 have ⟨hv2, hH2⟩ := ih2 D2' subst hv2; subst hH2 have heq := Hop.symm.trans Hop' exact ⟨Option.some.inj heq, rfl⟩ | refMkR _ ih => cases D₂ with | refMkR D' => have ⟨hv, hH⟩ := ih D' subst hv; subst hH exact ⟨rfl, rfl⟩ | derefR _ Hget ih => cases D₂ with | derefR D' Hget' => have ⟨hloc, hH⟩ := ih D' injection hloc with hloceq subst hloceq; subst hH have heq := Hget.symm.trans Hget' exact ⟨Option.some.inj heq, rfl⟩ | assignR _ _ _ ih1 ih2 => cases D₂ with | assignR D1' D2' _ => have ⟨hloc, hH1⟩ := ih1 D1' injection hloc with hloceq subst hloceq; subst hH1 have ⟨hv, hH2⟩ := ih2 D2' subst hv; subst hH2 exact ⟨rfl, rfl⟩ | seqR _ _ ih1 ih2 => cases D₂ with | seqR D1' D2' => have ⟨_, hH1⟩ := ih1 D1' subst hH1 exact ih2 D2' end GolangLean.Core