Skip to content

Commit bf71113

Browse files
Implement timeout option
1 parent 1a2d635 commit bf71113

File tree

4 files changed

+101
-14
lines changed

4 files changed

+101
-14
lines changed

REPL/JSON.lean

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,14 @@ open Lean Elab InfoTree
1111

1212
namespace REPL
1313

14-
structure CommandOptions where
14+
/-- Base structure with timeout that all command types can inherit from -/
15+
structure BaseOptions where
16+
/--
17+
Optional timeout in milliseconds. If none, no timeout will be applied.
18+
-/
19+
timeout : Option Nat := none
20+
21+
structure CommandOptions extends BaseOptions where
1522
allTactics : Option Bool := none
1623
rootGoals : Option Bool := none
1724
/--
@@ -38,7 +45,7 @@ deriving ToJson, FromJson
3845
/--
3946
Run a tactic in a proof state.
4047
-/
41-
structure ProofStep where
48+
structure ProofStep extends BaseOptions where
4249
proofState : Nat
4350
tactic : String
4451
deriving ToJson, FromJson
@@ -170,21 +177,21 @@ structure Error where
170177
message : String
171178
deriving ToJson, FromJson
172179

173-
structure PickleEnvironment where
180+
structure PickleEnvironment extends BaseOptions where
174181
env : Nat
175182
pickleTo : System.FilePath
176183
deriving ToJson, FromJson
177184

178-
structure UnpickleEnvironment where
185+
structure UnpickleEnvironment extends BaseOptions where
179186
unpickleEnvFrom : System.FilePath
180187
deriving ToJson, FromJson
181188

182-
structure PickleProofState where
189+
structure PickleProofState extends BaseOptions where
183190
proofState : Nat
184191
pickleTo : System.FilePath
185192
deriving ToJson, FromJson
186193

187-
structure UnpickleProofState where
194+
structure UnpickleProofState extends BaseOptions where
188195
unpickleProofStateFrom : System.FilePath
189196
env : Option Nat
190197
deriving ToJson, FromJson

REPL/Main.lean

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -362,6 +362,23 @@ def runProofStep (s : ProofStep) : M IO (ProofStepResponse ⊕ Error) := do
362362
catch ex =>
363363
return .inr ⟨"Lean error:\n" ++ ex.toString⟩
364364

365+
/--
366+
Run a task with an optional timeout in milliseconds.
367+
-/
368+
def runWithTimeout (timeout? : Option Nat) (task : M IO α) : M IO α :=
369+
match timeout? with
370+
| none => task
371+
| some timeout => do
372+
let jobTask ← IO.asTask (prio := .dedicated) (StateT.run task (← get))
373+
let timeoutTask : IO (α × State) := do
374+
IO.sleep timeout.toUInt32
375+
throw <| IO.userError s!"Operation timed out after {timeout}ms"
376+
match ← IO.waitAny [jobTask, ← IO.asTask timeoutTask] with
377+
| .ok (a, state) => do
378+
modify fun _ => state
379+
return a
380+
| .error e => throw e
381+
365382
end REPL
366383

367384
open REPL
@@ -426,14 +443,16 @@ where loop : M IO Unit := do
426443
if query = "" then
427444
return ()
428445
if query.startsWith "#" || query.startsWith "--" then loop else
429-
IO.println <| toString <| ← match ← parse query with
430-
| .command r => return toJson (← runCommand r)
431-
| .file r => return toJson (← processFile r)
432-
| .proofStep r => return toJson (← runProofStep r)
433-
| .pickleEnvironment r => return toJson (← pickleCommandSnapshot r)
434-
| .unpickleEnvironment r => return toJson (← unpickleCommandSnapshot r)
435-
| .pickleProofSnapshot r => return toJson (← pickleProofSnapshot r)
436-
| .unpickleProofSnapshot r => return toJson (← unpickleProofSnapshot r)
446+
IO.println <| toString <| ← try
447+
match ← parse query with
448+
| .command r => return toJson (← runWithTimeout r.timeout (runCommand r))
449+
| .file r => return toJson (← runWithTimeout r.timeout (processFile r))
450+
| .proofStep r => return toJson (← runWithTimeout r.timeout (runProofStep r))
451+
| .pickleEnvironment r => return toJson (← runWithTimeout r.timeout (pickleCommandSnapshot r))
452+
| .unpickleEnvironment r => return toJson (← runWithTimeout r.timeout (unpickleCommandSnapshot r))
453+
| .pickleProofSnapshot r => return toJson (← runWithTimeout r.timeout (pickleProofSnapshot r))
454+
| .unpickleProofSnapshot r => return toJson (← runWithTimeout r.timeout (unpickleProofSnapshot r))
455+
catch e => return toJson (⟨e.toString⟩ : Error)
437456
printFlush "\n" -- easier to parse the output if there are blank lines
438457
loop
439458

test/timeout.expected.out

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
{"sorries":
2+
[{"proofState": 0,
3+
"pos": {"line": 1, "column": 49},
4+
"goal": "x : Nat\nh1 : x = 2\n⊢ x = 2",
5+
"endPos": {"line": 1, "column": 54}}],
6+
"messages":
7+
[{"severity": "warning",
8+
"pos": {"line": 1, "column": 8},
9+
"endPos": {"line": 1, "column": 10},
10+
"data": "declaration uses 'sorry'"}],
11+
"env": 0}
12+
13+
{"proofStatus": "Completed", "proofState": 1, "goals": []}
14+
15+
{"sorries":
16+
[{"proofState": 2,
17+
"pos": {"line": 1, "column": 49},
18+
"goal": "x : Nat\nh1 : x = 2\n⊢ x = 2",
19+
"endPos": {"line": 1, "column": 54}}],
20+
"messages":
21+
[{"severity": "warning",
22+
"pos": {"line": 1, "column": 8},
23+
"endPos": {"line": 1, "column": 10},
24+
"data": "declaration uses 'sorry'"}],
25+
"env": 1}
26+
27+
{"proofStatus": "Completed", "proofState": 3, "goals": []}
28+
29+
{"message": "Operation timed out after 1ms"}
30+
31+
{"message": "Unknown proof state."}
32+
33+
{"sorries":
34+
[{"proofState": 4,
35+
"pos": {"line": 1, "column": 49},
36+
"goal": "x : Nat\nh1 : x = 2\n⊢ x = 2",
37+
"endPos": {"line": 1, "column": 54}}],
38+
"messages":
39+
[{"severity": "warning",
40+
"pos": {"line": 1, "column": 8},
41+
"endPos": {"line": 1, "column": 10},
42+
"data": "declaration uses 'sorry'"}],
43+
"env": 2}
44+
45+
{"proofStatus": "Completed", "proofState": 5, "goals": []}
46+

test/timeout.in

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{"cmd": "theorem aa (x : Nat) (h1 : x = 2) : x = 2 := by sorry"}
2+
3+
{"tactic": "assumption", "proofState": 0}
4+
5+
{"cmd": "theorem aa (x : Nat) (h1 : x = 2) : x = 2 := by sorry", "timeout": 1000}
6+
7+
{"tactic": "assumption", "proofState": 2}
8+
9+
{"cmd": "theorem aa (x : Nat) (h1 : x = 2) : x = 2 := by sorry", "timeout": 1}
10+
11+
{"tactic": "assumption", "proofState": 4}
12+
13+
{"cmd": "theorem aa (x : Nat) (h1 : x = 2) : x = 2 := by sorry"}
14+
15+
{"tactic": "assumption", "proofState": 4}

0 commit comments

Comments
 (0)