Skip to content

Commit b828b05

Browse files
committed
incrementality
1 parent a4c8c18 commit b828b05

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+257
-38
lines changed

REPL/Frontend.lean

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,12 @@ Wrapper for `IO.processCommands` that enables info states, and returns
1717
-/
1818
def processCommandsWithInfoTrees
1919
(inputCtx : Parser.InputContext) (parserState : Parser.ModuleParserState)
20-
(commandState : Command.State) : IO (Command.State × List Message × List InfoTree) := do
20+
(commandState : Command.State) (incrementalState? : Option IncrementalState := none) :
21+
IO (Command.State × IncrementalState × List Message × List InfoTree) := do
2122
let commandState := { commandState with infoState.enabled := true }
22-
let s ← IO.processCommands inputCtx parserState commandState <&> Frontend.State.commandState
23-
pure (s, s.messages.msgs.toList, s.infoState.trees.toList)
23+
let r ← IO.processCommandsIncrementally inputCtx parserState commandState incrementalState?
24+
let s := r.commandState
25+
pure (s, r, s.messages.msgs.toList, s.infoState.trees.toList)
2426

2527
/--
2628
Process some text input, with or without an existing command state.
@@ -31,8 +33,9 @@ Otherwise, we add to the existing environment.
3133
Returns the resulting command state, along with a list of messages and info trees.
3234
-/
3335
def processInput (input : String) (cmdState? : Option Command.State)
36+
(incrementalState? : Option IncrementalState := none)
3437
(opts : Options := {}) (fileName : Option String := none) :
35-
IO (Command.State × List Message × List InfoTree) := unsafe do
38+
IO (Command.State × IncrementalState × List Message × List InfoTree) := unsafe do
3639
Lean.initSearchPath (← Lean.findSysroot)
3740
enableInitializersExecution
3841
let fileName := fileName.getD "<input>"
@@ -44,4 +47,4 @@ def processInput (input : String) (cmdState? : Option Command.State)
4447
pure (parserState, (Command.mkState env messages opts))
4548
| some cmdState => do
4649
pure ({ : Parser.ModuleParserState }, cmdState)
47-
processCommandsWithInfoTrees inputCtx parserState commandState
50+
processCommandsWithInfoTrees inputCtx parserState commandState incrementalState?

REPL/JSON.lean

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ If `env = some n`, builds on the existing environment `n`.
1717
-/
1818
structure Command where
1919
env : Option Nat
20+
incr : Option Nat
2021
cmd : String
2122
allTactics : Option Bool := none
2223
/--
@@ -112,6 +113,7 @@ A response to a Lean command.
112113
-/
113114
structure CommandResponse where
114115
env : Nat
116+
incr : Option Nat := none
115117
messages : List Message := []
116118
sorries : List Sorry := []
117119
tactics : List Tactic := []
@@ -125,6 +127,7 @@ def Json.nonemptyList [ToJson α] (k : String) : List α → List (String × Jso
125127
instance : ToJson CommandResponse where
126128
toJson r := Json.mkObj <| .join [
127129
[("env", r.env)],
130+
match r.incr with | some i => [("incr", i)] | none => [],
128131
Json.nonemptyList "messages" r.messages,
129132
Json.nonemptyList "sorries" r.sorries,
130133
Json.nonemptyList "tactics" r.tactics,
@@ -166,6 +169,15 @@ structure UnpickleEnvironment where
166169
unpickleEnvFrom : System.FilePath
167170
deriving ToJson, FromJson
168171

172+
structure PickleIncrementalState where
173+
incr : Nat
174+
pickleTo : System.FilePath
175+
deriving ToJson, FromJson
176+
177+
structure UnpickleIncrementalState where
178+
unpickleIncrFrom : System.FilePath
179+
deriving ToJson, FromJson
180+
169181
structure PickleProofState where
170182
proofState : Nat
171183
pickleTo : System.FilePath

REPL/Main.lean

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,8 @@ structure State where
6565
The user can run a declaration in a given environment using `{"cmd": "def f := 37", "env": 17}`.
6666
-/
6767
cmdStates : Array CommandSnapshot := #[]
68-
latestIncrementalitySnapshot : HashMap Nat Nat := {}
68+
incrementalStates : Array IncrementalState := #[]
69+
latestIncrementalState : HashMap Nat Nat := {}
6970
/--
7071
Proof states after individual tactics.
7172
The user can run a tactic in a given proof state using `{"tactic": "exact 42", "proofState": 5}`.
@@ -89,6 +90,11 @@ def recordCommandSnapshot (state : CommandSnapshot) : M m Nat := do
8990
modify fun s => { s with cmdStates := s.cmdStates.push state }
9091
return id
9192

93+
def recordIncrementalState (state : IncrementalState) : M m Nat := do
94+
let id := (← get).incrementalStates.size
95+
modify fun s => { s with incrementalStates := s.incrementalStates.push state }
96+
return id
97+
9298
/-- Record a `ProofSnapshot` into the REPL state, returning its index for future use. -/
9399
def recordProofSnapshot (proofState : ProofSnapshot) : M m Nat := do
94100
let id := (← get).proofStates.size
@@ -194,9 +200,24 @@ def runCommand (s : Command) : M IO (CommandResponse ⊕ Error) := do
194200
| none => pure (none, true)
195201
if notFound then
196202
return .inr ⟨"Unknown environment."
203+
let (incrementalStateBefore?, notFound) ← do
204+
let j? ← match s.incr with
205+
| none => match s.env with
206+
| none => pure none
207+
| some i => match (← get).latestIncrementalState.find? i with
208+
| none => pure none
209+
| j => pure j
210+
| some j => pure j
211+
match j? with
212+
| none => pure (none, false)
213+
| some j => do match (← get).incrementalStates[j]? with
214+
| some s => pure (some s, false)
215+
| none => pure (none, true)
216+
if notFound then
217+
return .inr ⟨"Unknown incremental state."
197218
let initialCmdState? := cmdSnapshot?.map fun c => c.cmdState
198-
let (cmdState, messages, trees) ← try
199-
IO.processInput s.cmd initialCmdState?
219+
let (cmdState, incrementalState, messages, trees) ← try
220+
IO.processInput s.cmd initialCmdState? incrementalStateBefore?
200221
catch ex =>
201222
return .inr ⟨ex.toString⟩
202223
let messages ← messages.mapM fun m => Message.of m
@@ -211,6 +232,9 @@ def runCommand (s : Command) : M IO (CommandResponse ⊕ Error) := do
211232
cmdContext := (cmdSnapshot?.map fun c => c.cmdContext).getD
212233
{ fileName := "", fileMap := default, tacticCache? := none, snap? := none } }
213234
let env ← recordCommandSnapshot cmdSnapshot
235+
let incr ← recordIncrementalState incrementalState
236+
if let some i := s.env then
237+
modify fun c => { c with latestIncrementalState := c.latestIncrementalState.insert i incr }
214238
let jsonTrees := match s.infotree with
215239
| some "full" => trees
216240
| some "tactics" => trees.bind InfoTree.retainTacticInfo
@@ -223,6 +247,7 @@ def runCommand (s : Command) : M IO (CommandResponse ⊕ Error) := do
223247
some <| Json.arr (← jsonTrees.toArray.mapM fun t => t.toJson none)
224248
return .inl
225249
{ env,
250+
incr,
226251
messages,
227252
sorries,
228253
tactics

test.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ for infile in $IN_DIR/*.in; do
2222

2323
# Run the command and store its output in a temporary file
2424
tmpfile=$(mktemp)
25-
.lake/build/bin/repl < "$infile" > "$tmpfile" 2>&1
25+
stdbuf -oL .lake/build/bin/repl < "$infile" > "$tmpfile" 2>&1
2626

2727
# Compare the output with the expected output
2828
if diff "$tmpfile" "$expectedfile"; then

test/all_tactics.expected.out

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,6 @@
99
"pos": {"line": 1, "column": 32},
1010
"goals": "t : Nat ⊢ Nat",
1111
"endPos": {"line": 1, "column": 39}}],
12+
"incr": 0,
1213
"env": 0}
1314

test/by_cases.expected.out

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
"pos": {"line": 1, "column": 8},
99
"endPos": {"line": 1, "column": 11},
1010
"data": "declaration uses 'sorry'"}],
11+
"incr": 0,
1112
"env": 0}
1213

1314
{"proofState": 1,

test/calc.expected.out

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,5 +28,6 @@
2828
"pos": {"line": 1, "column": 0},
2929
"endPos": {"line": 1, "column": 7},
3030
"data": "declaration uses 'sorry'"}],
31+
"incr": 0,
3132
"env": 0}
3233

test/def_eval.expected.out

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1-
{"env": 0}
1+
{"incr": 0, "env": 0}
22

33
{"messages":
44
[{"severity": "info",
55
"pos": {"line": 1, "column": 0},
66
"endPos": {"line": 1, "column": 6},
77
"data": "rfl : f = f"}],
8+
"incr": 1,
89
"env": 1}
910

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
{"env": 0}
1+
{"incr": 0, "env": 0}
22

test/have_by_sorry.expected.out

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,12 @@
77
[{"severity": "error",
88
"pos": {"line": 1, "column": 33},
99
"endPos": {"line": 2, "column": 28},
10-
"data": "unsolved goals\nx : Int\nh : x = 1\n⊢ x = x"}],
10+
"data": "unsolved goals\nx : Int\nh : x = 1\n⊢ x = x"},
11+
{"severity": "warning",
12+
"pos": {"line": 1, "column": 8},
13+
"endPos": {"line": 1, "column": 11},
14+
"data": "declaration uses 'sorry'"}],
15+
"incr": 0,
1116
"env": 0}
1217

1318
{"sorries":
@@ -20,6 +25,7 @@
2025
"pos": {"line": 1, "column": 8},
2126
"endPos": {"line": 1, "column": 11},
2227
"data": "declaration uses 'sorry'"}],
28+
"incr": 1,
2329
"env": 1}
2430

2531
{"sorries": [{"proofState": 2, "goal": "x : Int\n⊢ x = 1"}],

0 commit comments

Comments
 (0)