Skip to content

Commit 1e45e3f

Browse files
proof(L1): Semantics_L1.v skeleton — preservation_l1 theorem stated (#157)
## Summary L1 preservation theorem **statement** lands in Coq, with three helper-lemma stubs Admitted for incremental closure. Task #19's first checkpoint. Stacked on PR #153 (which contains TypingL1.v). ## What's in \`formal/Semantics_L1.v\`: | Lemma | Status | Notes | |---|---|---| | \`remove_first_eq_l1\` | **Qed** | Proves operational \`remove_first\` ≡ \`remove_first_L1\` | | \`value_R_G_preserving_l1\` | Admitted | Needs induction on \`is_value\` | | \`region_shrink_preserves_typing_l1\` | Admitted | Mirrors legacy lemma under L1 | | \`subst_preserves_typing_l1\` | Admitted | Mirrors legacy lemma under L1 | | **\`preservation_l1\`** | **Admitted** | Depends on the three helpers | \`formal/_CoqProject\`: adds \`Semantics_L1.v\`. ## Per-case proof sketches (in file docstring) Simple cases that close without any helper (validated during authoring): - **S_StringNew**: \`apply T_Loc_L1\` - **S_StringConcat**: invert children to align regions/contexts, \`apply T_Loc_L1\` - **S_StringLen**: invert the borrow, \`apply T_I32_L1\` - **S_If_True / S_If_False**: invert condition, \`assumption\` - **S_Region_Enter**: re-apply \`T_Region_Active_L1\` with the same R_body - **S_Drop**: \`apply T_Unit_L1\` Cases needing each helper: - \`region_shrink_preserves_typing_l1\`: **S_Region_Exit** (both typing sub-cases) - \`value_R_G_preserving_l1\`: **all congruence S_X_Step cases** via IH-threading - \`subst_preserves_typing_l1\`: **β-reduction** (S_Let_Val, S_LetLin_Val, S_App_Fun, S_Case_Inl, S_Case_Inr) Vacuous: **S_Borrow_Step** (inner can't step under either typing rule). ## Honest bound Four Admitted lemmas in this file. Plus the legacy \`preservation\` in Semantics.v remains Admitted (superseded but not deleted — out of scope here). This PR does NOT pay down those admits; it lands the statement and the structure so future PRs can close them one at a time. ## Why stop here The per-case proof body has a bullet-structure subtlety: ERegion typing inverts to TWO sub-cases (T_Region_L1 and T_Region_Active_L1), doubling subgoals for the three region step rules. Authoring the bullet-clean version requires the three helpers in place to avoid blocking on dead-end paths. Sequencing them in separate PRs is mechanical follow-up; doing it inline would mean reverting to the proof scaffold every time a helper changes. ## Test plan - [x] \`coqc 8.18.0\` builds \`Semantics_L1.vo\` cleanly - [x] All other \`.v\` files in the project still build (full \`make\` succeeds) - [x] No regressions on \`Counterexample.v\` (4 lemmas \`Qed\`, \`bad_input_untypable_l1\` still passes) - [ ] CI green - [ ] Review: helper lemma statements match what the per-case proofs would need Base: \`proof/l1-region-threading-design\` (PR #153). Will rebase onto main once that lands. Refs ephapax#153, task #19 in the project queue. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 1e9d40f commit 1e45e3f

2 files changed

Lines changed: 151 additions & 0 deletions

File tree

formal/Semantics_L1.v

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
(* SPDX-License-Identifier: PMPL-1.0-or-later *)
2+
(* SPDX-FileCopyrightText: 2026 Jonathan D.A. Jewell *)
3+
4+
(** * Ephapax Preservation under the L1 judgment (R-threaded typing)
5+
6+
This file states [preservation_l1] for the new [has_type_l1]
7+
judgment in [TypingL1.v]. The operational semantics [step] from
8+
[Semantics.v] is unchanged.
9+
10+
Per PRESERVATION-DESIGN.md §4.5, preservation under L1 is:
11+
12+
[step (mu, R, e) (mu', R', e')] /\
13+
[has_type_l1 R G e T R_final G']
14+
->
15+
[has_type_l1 R' G e' T R_final G']
16+
17+
The [R_final] and [G'] outputs are invariant under stepping —
18+
they describe the state after the entire expression has fully
19+
evaluated, which the operational step does not change.
20+
21+
Current status (sequenced multi-PR closure):
22+
23+
- [remove_first_eq_l1] — Qed (trivial).
24+
- [value_R_G_preserving_l1] — Admitted; needs induction on
25+
[is_value] with nested IH for EInl, EInr, EPair, EBorrow-of-
26+
value.
27+
- [region_shrink_preserves_typing_l1] — Admitted; mirrors
28+
[Semantics.region_shrink_preserves_typing] under the L1
29+
judgment.
30+
- [subst_preserves_typing_l1] — Admitted; mirrors
31+
[Semantics.subst_preserves_typing] under the L1 judgment.
32+
- [preservation_l1] — Admitted; depends on the three helpers.
33+
34+
Per-case proof sketches were validated experimentally during this
35+
file's authoring. The cases that close without any of the three
36+
Admitted helpers are: S_StringNew (apply T_Loc_L1), S_StringConcat
37+
(invert both T_Loc_L1 children, then apply T_Loc_L1), S_StringLen
38+
(invert the borrow, apply T_I32_L1), S_If_True / S_If_False
39+
(invert T_Bool_L1 on the condition, then assumption), S_Region_
40+
Enter (re-apply T_Region_Active_L1 with the same R_body), and
41+
S_Drop (apply T_Unit_L1). These can be inlined once the bullet
42+
structure accounts for the per-region typing cross-cases
43+
(ERegion inverts to both T_Region_L1 and T_Region_Active_L1,
44+
doubling subgoals for the three region step rules).
45+
46+
Cases requiring helpers:
47+
- S_Region_Exit needs [region_shrink_preserves_typing_l1].
48+
- Congruence (S_X_Step) cases need [value_R_G_preserving_l1].
49+
- β-reduction (S_Let_Val, S_LetLin_Val, S_App_Fun, S_Case_Inl,
50+
S_Case_Inr) cases need [subst_preserves_typing_l1].
51+
52+
Vacuous: S_Borrow_Step (both typing sub-cases — the inner cannot
53+
step under either typing rule).
54+
55+
Once the three helpers are Qed, the per-case proofs are
56+
mechanical; the full theorem closure is sequenced as task #19's
57+
continuation. *)
58+
59+
Require Import Coq.Strings.String.
60+
Require Import Coq.Lists.List.
61+
Require Import Coq.Arith.Arith.
62+
Require Import Coq.Bool.Bool.
63+
Require Import Lia.
64+
Import ListNotations.
65+
66+
From Ephapax Require Import Syntax.
67+
From Ephapax Require Import Typing.
68+
From Ephapax Require Import TypingL1.
69+
From Ephapax Require Import Semantics.
70+
71+
(** ** Trivial: the operational [remove_first] and the L1
72+
[remove_first_L1] coincide pointwise. *)
73+
74+
Lemma remove_first_eq_l1 :
75+
forall r R,
76+
remove_first_L1 r R = remove_first r R.
77+
Proof.
78+
intros r R. induction R as [| r' R' IH]; simpl.
79+
- reflexivity.
80+
- rewrite IH. reflexivity.
81+
Qed.
82+
83+
(** ** Helper: values preserve both R and G under the L1 judgment.
84+
85+
Inductive on [is_value v]. Atomic value rules (T_Unit_L1, T_Bool_L1,
86+
T_I32_L1, T_Loc_L1, T_StringNew_L1, T_Lam_L1) give R_out = R_in,
87+
G_out = G_in directly. Compound value forms (EInl, EInr, EPair,
88+
EBorrow of value) propagate via IH on the value-shaped sub-
89+
expression. Detailed proof deferred to L1 follow-up PR. *)
90+
91+
Lemma value_R_G_preserving_l1 :
92+
forall R G v T R' G',
93+
is_value v ->
94+
has_type_l1 R G v T R' G' ->
95+
R' = R /\ G' = G.
96+
Admitted.
97+
98+
(** ** Helper: region-environment shrinkage for value typings.
99+
100+
Mirrors [Semantics.region_shrink_preserves_typing] under the L1
101+
judgment. Used by the [S_Region_Exit] case of [preservation_l1].
102+
Detailed proof deferred to L1 follow-up PR. *)
103+
104+
Lemma region_shrink_preserves_typing_l1 :
105+
forall R G v T R' G' r,
106+
is_value v ->
107+
has_type_l1 R G v T R' G' ->
108+
~ In r (free_regions T) ->
109+
expr_free_of_region r v ->
110+
has_type_l1 (remove_first r R) G v T (remove_first r R') G'.
111+
Admitted.
112+
113+
(** ** Helper: substitution preserves the L1 typing.
114+
115+
Mirrors [Semantics.subst_preserves_typing] under the L1 judgment.
116+
Used by the β-reduction cases ([S_Let_Val], [S_LetLin_Val],
117+
[S_App_Fun], [S_Case_Inl], [S_Case_Inr]) of [preservation_l1].
118+
Detailed proof deferred to L1 follow-up PR. *)
119+
120+
Lemma subst_preserves_typing_l1 :
121+
forall T1 R1 G1' v R2 G2 e2 T2 R2_final G2',
122+
is_value v ->
123+
has_type_l1 R1 G1' v T1 R1 G1' ->
124+
has_type_l1 R2 ((T1, false) :: G2) e2 T2 R2_final ((T1, true) :: G2') ->
125+
has_type_l1 R2 G2 (subst 0 v e2) T2 R2_final G2'.
126+
Admitted.
127+
128+
(** ** Preservation under the L1 judgment.
129+
130+
The full case-by-case proof depends on the three Admitted helpers
131+
above. Sequenced for incremental closure across follow-up PRs (per
132+
task #19 in the project's task list).
133+
134+
The simple cases (S_StringNew, S_StringConcat, S_StringLen,
135+
S_If_True, S_If_False, S_Region_Enter, S_Drop) were verified
136+
experimentally during this file's first-pass authoring; they close
137+
using only the lemmas already Qed in TypingL1.v + this file. They
138+
are not currently inlined into the proof body because the bullet
139+
structure picks up the per-step typing-rule cross-cases (e.g.
140+
ERegion's T_Region_L1 vs T_Region_Active_L1) which doubles the
141+
subgoal count over the step rule count. The clean-bullet structure
142+
is sequenced together with the three helpers landing. *)
143+
144+
Theorem preservation_l1 :
145+
forall mu R e mu' R' e',
146+
step (mu, R, e) (mu', R', e') ->
147+
forall G T R_final G',
148+
has_type_l1 R G e T R_final G' ->
149+
has_type_l1 R' G e' T R_final G'.
150+
Admitted.

formal/_CoqProject

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,5 @@ Syntax.v
88
Typing.v
99
TypingL1.v
1010
Semantics.v
11+
Semantics_L1.v
1112
Counterexample.v

0 commit comments

Comments
 (0)