forked from leodemoura/RadixExperiment
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathSlides.lean
More file actions
273 lines (211 loc) · 8.75 KB
/
Copy pathSlides.lean
File metadata and controls
273 lines (211 loc) · 8.75 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
import VersoSlides
import Verso.Doc.Concrete
import Radix
open VersoSlides
set_option maxHeartbeats 800000
set_option linter.unusedVariables false
#doc (Slides) "Lean for AI, AI for Lean" =>
%%%
theme := "white"
slideNumber := true
transition := "slide"
%%%
# Lean for AI, AI for Lean
%%%
backgroundColor := "#312e81"
%%%
Leonardo de Moura
Lean FRO | March 2026
# The Result
10 AI agents built a *verified embedded DSL* with proved optimizations in *a single weekend*.
- Zero `sorry` — 52 theorems, all complete
- 5 verified compiler optimizations
- Determinism, type safety, memory safety — all proved
- Linear ownership typing with soundness proof
- Interpreter correctness — sound and complete
- 27 modules, ~7,400 lines of Lean
# Lessons Learned
- I did not touch the code. Zero lines. Full agent autonomy.
- Unlike most human users, Claude _reads the documentation_. One stuck agent? I said "Read the `grind` docs." It downloaded, understood, unblocked.
- Examples are powerful: agents found our DSL declaration examples and adopted the same pattern for Radix syntax.
- Claude struggled with _mutual induction_ — but found workarounds every time.
- Claude struggled with _monadic code_ and avoided it. We don't have enough examples for that.
- I created a GitHub token scoped to the Radix repo only. Good thing — Claude tried to push to `leanprover/lean4`.
- Toolchain version issues (v4.29.0) confused Claude when generating these slides.
# Radix — A Real Program
```lean -show
open Radix
```
Agents write Radix using concrete syntax macros. Verso elaborates every line:
```lean
def slideBubbleSort := `[RStmt|
let arr := new uint64[][10];
arr[0] := 5; arr[1] := 3; arr[2] := 8;
arr[3] := 1; arr[4] := 9; arr[5] := 2;
arr[6] := 7; arr[7] := 4; arr[8] := 6;
arr[9] := 0;
i := 0;
while (i < 9) {
j := 0;
while (j < 9 - i) {
let a : uint64 = arr[j];
let b : uint64 = arr[j + 1];
if (a > b) {
arr[j] := b;
arr[j + 1] := a;
}
j := j + 1;
}
i := i + 1;
}
]
```
# Big-Step Semantics — 16 Rules
```lean
-- Big-step: ⟨σ, s⟩ ⇓ r
-- 16 rules: skip, assign, decl, seqNormal, seqReturn,
-- ifTrue, ifFalse, whileTrue, whileReturn, whileFalse,
-- alloc, free, arrSet, ret, block, callStmt, scope
example : BigStep σ .skip (.normal σ) :=
BigStep.skip
example (he : e.eval σ = some v)
(hs : σ.setVar x v = some σ') :
BigStep σ (.assign x e) (.normal σ') :=
BigStep.assign he hs
example (h₁ : BigStep σ₁ s₁ (.normal σ₂))
(h₂ : BigStep σ₂ s₂ r) :
BigStep σ₁ (s₁ ;; s₂) r :=
BigStep.seqNormal h₁ h₂
example (hc : e.eval σ₁ = some (.bool true))
(hb : BigStep σ₁ b (.normal σ₂))
(hw : BigStep σ₂ (.while e b) r) :
BigStep σ₁ (.while e b) r :=
BigStep.whileTrue hc hb hw
```
# Determinism — `grind` Does The Work
```lean
-- Same state + same statement → same result
-- 80-line proof by induction on h₁
-- grind closes equational contradictions
example (h₁ : BigStep σ s r₁)
(h₂ : BigStep σ s r₂) : r₁ = r₂ :=
BigStep.det h₁ h₂
```
In the real proof: `cases h₂ with | assign => grind` handles equational cases. `grind` decides contradictions like `some true = some false`. Explicit IH application for recursive cases (`seq`, `while`, `call`, `scope`).
# Interpreter Correctness — Sound and Complete
A fuel-based interpreter (`Stmt.interp`) proved equivalent to the relational semantics in both directions:
```lean
-- Completeness: BigStep implies interp succeeds
example (h : BigStep σ s r) :
∃ fuel, s.interp fuel σ =
(.ok r.retVal, r.state) :=
Stmt.interp_complete h
-- Soundness: interp success implies BigStep
example (h : s.interp fuel σ = (.ok rv, σ')) :
BigStep σ s (toStmtResult rv σ') :=
Stmt.interp_sound h
```
The relational semantics is the spec. The interpreter is the implementation. These two theorems say they agree exactly.
# Verified Optimizations — 5 Passes, 0 Sorry
```lean
-- Each pass: Stmt → Stmt with correctness theorem
-- "If the original runs, the optimized runs too"
example (h : BigStep σ s r) :
BigStep σ s.constFold r :=
Stmt.constFold_correct h
example (h : BigStep σ s r) :
BigStep σ s.deadCodeElim r :=
Stmt.deadCodeElim_correct h
example (h : BigStep σ s r) :
BigStep σ s.copyPropagation r :=
Stmt.copyProp_correct h
example (h : BigStep σ s r) :
BigStep σ s.constPropagation r :=
Stmt.constPropagation_correct h
example (h : BigStep σ s r) (hf : σ.funs = funs) :
∀ depth, BigStep σ (s.inline funs depth) r :=
Stmt.inline_correct h hf
```
# Optimizations — What The Proofs Actually Look Like
*Constant folding:* `Expr.inferTag` conservatively infers output types to guard identity rules. `e + 0 → e` is sound when `e` produces `uint64`. `e * 0 → 0` is NOT sound — if `e` fails (e.g., out-of-bounds), the original returns `none` but the rewrite returns `some 0`.
*Copy propagation:* `CopyMap.agrees` invariant — every mapping `x → y` means `σ.getVar x = σ.getVar y`. Reset at control flow joins to stay sound.
*Inline:* rewrites `callStmt` into `scope` (frame-isolated body), bounded depth, non-recursive only. Proves function table invariant preserved through execution.
# Linear Ownership — Soundness
```lean
-- LinearOk O s O' : owned-set O → stmt s → owned-set O'
-- 13 rules. Key ones:
example : LinearOk O .skip O :=
LinearOk.skip
example (h : x ∉ O) :
LinearOk O (.alloc x ty sz) (O.insert x) :=
LinearOk.alloc h
example (h : x ∈ O) :
LinearOk O (.free (.var x)) (O.erase x) :=
LinearOk.free h
example (h₁ : LinearOk O s₁ O')
(h₂ : LinearOk O' s₂ O'') :
LinearOk O (s₁ ;; s₂) O'' :=
LinearOk.seq h₁ h₂
```
# Linear Ownership — The Real Invariant
The soundness proof (644 lines) maintains `OwnershipInv` — a three-part invariant:
- *(1) Heap well-formed:* all stored addresses < `nextAddr`
- *(2) Liveness:* every owned variable holds a live heap address
- *(3) Distinctness:* different owned variables hold different addresses
```lean
-- Soundness: OwnershipInv preserved through execution
example (hlin : LinearOk O s O')
(hstep : BigStep σ s (.normal σ'))
(hinv : OwnershipInv σ O)
(hwt : WellTypedFuns σ.funs) :
OwnershipInv σ' O' :=
LinearOk.soundness hlin hstep hinv hwt
```
Proved by induction on BigStep — every rule preserves all three parts. The `alloc` case uses `Heap.alloc_fresh` for distinctness. The `free` case uses `Heap.free_preserves_ne`.
# The 10 Agents
%%%
transition := "fade"
%%%
Not 10 interchangeable "coding agents." 10 _domain experts_:
:::hstack
- _Chris Lattner_ — AST, IR, module structure
- _Simon Peyton Jones_ — types, syntax macros
- _Xavier Leroy_ — verification strategy
- _Adam Chlipala_ — proof engineering
- _Emina Torlak_ — type checking, tests
- _Derek Dreyer_ — semantics, memory model
- _John Regehr_ — edge cases, coverage
- _Dan Grossman_ — memory safety proofs
- _Nadia Polikarpova_ — formal specifications
- _Tiark Rompf_ — interpreter, optimizations
:::
All Claude. One weekend.
# The Surprise
%%%
transition := "fade"
%%%
The agents gave us _better feedback on Lean_ than our human users.
- More precise: structured error context, not "it doesn't work"
- More systematic: they hit every edge case, not just the one they needed
- More actionable: "tactic X fails on pattern Y because Z"
Adam's `grind` report was better than most human post-mortems.
# Optimize Lean for AI too, not just humans.
%%%
backgroundColor := "#312e81"
%%%
Nobody has built this yet.
# The Spec and The Feedback Loop
- _Better diagnostics:_ when a tactic fails, structured error metadata — not just prose. Claude happily processes them.
- _Links to documentation:_ tactic docstrings and error messages should contain links to the actual documentation. Claude reads them.
- _Faster startup:_ Claude can try different approaches more efficiently.
- _More examples:_ and instructions on how to find them. Claude started the Radix project by reading all our examples in the core repo.
- _Attribute guides:_ teach Claude how to use `@[simp]`, `@[grind]`, etc.
- _Implicit information:_ a pretty printer that shows implicit arguments and avoids exponential blowup. Claude claims it will help — confirming with Anthropic.
_Next experiment:_ Two agent teams in parallel. One builds a hard project and generates friction reports. The other patches Lean to eliminate the friction. We architect and steer.
# A Probable Future
%%%
backgroundColor := "#312e81"
%%%
- People will not write Lean. AI will write it. Humans read and audit.
- People will not write Verso. AI will produce lectures, papers, slides — with machine-checked math and code. Humans focus on the content.
Humans move up the stack. They become designers, architects, readers, auditors.