Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
df07b53
Report errors in import statements.
Kripner Feb 17, 2025
a860ef8
Integrate PaperProof.BetterParser to enable proof trees.
Kripner Feb 21, 2025
8bdb5db
Allow extraction of only top-level infotrees.
Kripner Feb 21, 2025
9eaf0e5
Fix no_children infotree strategy.
Kripner Feb 24, 2025
961e261
Fix rw tactic spans computation.
Kripner Feb 24, 2025
2b441e2
Do not truncate tactic strings by the first newline.
Kripner Feb 27, 2025
016da44
Report raw InfoTrees.
Kripner Feb 28, 2025
7e9d514
Return a shallow infotree for each tactic invocation.
Kripner Mar 7, 2025
0ddcb1c
Report `at` clauses in `rw` tactics.
Kripner Mar 7, 2025
30aa122
Report metavariable context in each ProofStep.
Kripner Apr 1, 2025
82c1a33
Report metavariable context (including assignment dependencies) and s…
Kripner Apr 2, 2025
020cd3e
Merge branch 'leanprover-community:master' into master
Kripner Apr 2, 2025
835f383
Report goalInfo in sorries.
Kripner Apr 3, 2025
4161e2b
Fix: return goalInfos even when empty.
Kripner Apr 4, 2025
6d9d795
Add TODO.
Kripner Apr 9, 2025
817938d
Merge branch 'master' of github.com:Kripner/lean-repl
Kripner Apr 9, 2025
63b4bdb
Merge branch 'master' of github.com:leanprover-community/repl into le…
Kripner Apr 10, 2025
ddc5830
Merge branch 'leanprover-community-master'
Kripner Apr 10, 2025
1a8f085
Make `pf.hasSorry` the last check so that it can be safely ignored.
Kripner Apr 10, 2025
6b3329a
Revert "Make `pf.hasSorry` the last check so that it can be safely ig…
Kripner Apr 11, 2025
13076c8
Merge remote-tracking branch 'upstream/master'
Kripner Apr 11, 2025
d1995df
Proof step verification using kernel.
Kripner Apr 16, 2025
b9c90bf
Proof step verification using kernel. #2
Kripner Apr 16, 2025
c42b68d
Proof step verification using kernel. #3
Kripner Apr 16, 2025
8870e1e
Proof step verification using kernel. #4
Kripner Apr 16, 2025
4ac2b89
Proof step verification using kernel. #5
Kripner Apr 17, 2025
e6d40ad
Disable potentially expensive operations.
Kripner Apr 17, 2025
47ecb6a
Disable logs.
Kripner Apr 17, 2025
f2a8bb7
Snapshot pruning.
Kripner Apr 22, 2025
ea69f10
Extract goal assignment recursively.
Kripner Apr 23, 2025
b59028a
Logging to get insight into getFullAssignment.
Kripner Apr 23, 2025
39bc0dd
Simpler approach: check all mvars but replace only top-level ones.
Kripner Apr 23, 2025
302997c
Disable getProofStatus calculation.
Kripner Apr 23, 2025
896390c
Remove redundant check, remove prints.
Kripner Apr 24, 2025
cd2fcfd
Improve error messages.
Kripner Apr 24, 2025
df2e162
Split verification into two functions.
Kripner Apr 24, 2025
2aea4f8
Better circular assignment check.
Kripner Apr 25, 2025
a6f7225
Add declaration instead of simple type check.
Kripner Apr 25, 2025
69e41c1
Bring back addDecl.
Kripner Apr 26, 2025
3536196
Revert to simple type-check.
Kripner Apr 26, 2025
cce6249
Implement getFullMVars.
Kripner May 2, 2025
46c0871
Revert to addDecl
Kripner May 3, 2025
f54ffd7
More robust type check.
Kripner May 3, 2025
60a4ae0
Disable problematic sorry detection.
Kripner May 13, 2025
3620b47
Revert "Disable problematic sorry detection."
Kripner May 15, 2025
05b2e77
Bump version to v4.19.0
Kripner May 23, 2025
25ee5fc
Handle simp_rw.
Kripner Jun 19, 2025
78ce2d8
dbg prints
Kripner Jun 19, 2025
32c0091
Report stringified syntax of each tactic.
Kripner Jun 20, 2025
466e121
Do not break down simp_rw.
Kripner Jun 20, 2025
89fc83b
fix: call prettifySteps.
Kripner Jun 20, 2025
ad32154
Small rw fix.
Kripner Jun 20, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion REPL/Frontend.lean
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,9 @@ def processCommandsWithInfoTrees
(inputCtx : Parser.InputContext) (parserState : Parser.ModuleParserState)
(commandState : Command.State) : IO (Command.State × List Message × List InfoTree) := do
let commandState := { commandState with infoState.enabled := true }
let oldMessages := commandState.messages.toList
let s ← IO.processCommands inputCtx parserState commandState <&> Frontend.State.commandState
pure (s, s.messages.toList, s.infoState.trees.toList)
pure (s, oldMessages ++ s.messages.toList, s.infoState.trees.toList)

/--
Process some text input, with or without an existing command state.
Expand Down
124 changes: 121 additions & 3 deletions REPL/JSON.lean
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ Authors: Scott Morrison
import Lean.Data.Json
import Lean.Message
import Lean.Elab.InfoTree.Main
import Lean.Meta.Basic
import Lean.Meta.CollectMVars
import REPL.Lean.InfoTree.ToJson

open Lean Elab InfoTree

Expand All @@ -19,6 +22,7 @@ structure CommandOptions where
Anything else is ignored.
-/
infotree : Option String
proofTrees : Option Bool := none

/-- Run Lean commands.
If `env = none`, starts a new session (in which you can use `import`).
Expand All @@ -34,6 +38,11 @@ structure File extends CommandOptions where
path : System.FilePath
deriving FromJson

structure PruneSnapshots where
cmdFromId : Option Nat
proofFromId : Option Nat
deriving ToJson, FromJson

/--
Run a tactic in a proof state.
-/
Expand Down Expand Up @@ -71,11 +80,29 @@ def Message.of (m : Lean.Message) : IO Message := do pure <|
| .error => .error,
data := (← m.data.toString).trim }

structure HypothesisInfo where
username : String
type : String
value : Option String
-- unique identifier for the hypothesis, fvarId
id : String
isProof : String
deriving Inhabited, ToJson, FromJson

structure GoalInfo where
username : String
type : String
hyps : List HypothesisInfo
-- unique identifier for the goal, mvarId
id : MVarId
deriving Inhabited, ToJson, FromJson

/-- A Lean `sorry`. -/
structure Sorry where
pos : Pos
endPos : Pos
goal : String
goalInfo: Option GoalInfo
/--
The index of the proof state at the sorry.
You can use the `ProofStep` instruction to run a tactic at this state.
Expand All @@ -86,16 +113,20 @@ deriving FromJson
instance : ToJson Sorry where
toJson r := Json.mkObj <| .flatten [
[("goal", r.goal)],
match r.goalInfo with
| some goalInfo => [("goalInfo", toJson goalInfo)]
| none => [],
[("proofState", toJson r.proofState)],
if r.pos.line ≠ 0 then [("pos", toJson r.pos)] else [],
if r.endPos.line ≠ 0 then [("endPos", toJson r.endPos)] else [],
]

/-- Construct the JSON representation of a Lean sorry. -/
def Sorry.of (goal : String) (pos endPos : Lean.Position) (proofState : Option Nat) : Sorry :=
def Sorry.of (goal : String) (goalInfo : Option GoalInfo) (pos endPos : Lean.Position) (proofState : Option Nat) : Sorry :=
{ pos := ⟨pos.line, pos.column⟩,
endPos := ⟨endPos.line, endPos.column⟩,
goal,
goalInfo,
proofState }

structure Tactic where
Expand All @@ -116,6 +147,83 @@ def Tactic.of (goals tactic : String) (pos endPos : Lean.Position) (proofState :
proofState,
usedConstants }

private def mayBeProof (expr : Expr) : MetaM String := do
let type : Expr ← Lean.Meta.inferType expr
if ← Meta.isProof expr then
return "proof"
if type.isSort then
return "universe"
else
return "data"

def printGoalInfo (printCtx : ContextInfo) (id : MVarId) : IO GoalInfo := do
let some decl := printCtx.mctx.findDecl? id
| panic! "printGoalInfo: goal not found in the mctx"
-- to get tombstones in name ✝ for unreachable hypothesis
let lctx := decl.lctx |>.sanitizeNames.run' {options := {}}
let ppContext := printCtx.toPPContext lctx

let hyps ← lctx.foldrM (init := []) (fun hypDecl acc => do
if hypDecl.isAuxDecl || hypDecl.isImplementationDetail then
return acc

let type ← liftM (ppExprWithInfos ppContext hypDecl.type)
let value ← liftM (hypDecl.value?.mapM (ppExprWithInfos ppContext))
let isProof : String ← printCtx.runMetaM decl.lctx (mayBeProof hypDecl.toExpr)
return ({
username := hypDecl.userName.toString,
type := type.fmt.pretty,
value := value.map (·.fmt.pretty),
id := hypDecl.fvarId.name.toString,
isProof := isProof,
} : HypothesisInfo) :: acc)
return ⟨ decl.userName.toString, (← ppExprWithInfos ppContext decl.type).fmt.pretty, hyps, id⟩


instance : BEq GoalInfo where
beq g1 g2 := g1.id == g2.id

instance : Hashable GoalInfo where
hash g := hash g.id
structure MetavarDecl.Json where
mvarId : String
userName : String
type : String
mvarsInType : List MVarId
value : Option String
deriving ToJson, FromJson

structure MetavarContext.Json where
decls : Array MetavarDecl.Json
deriving ToJson, FromJson

def MetavarContext.toJson (mctx : MetavarContext) (ctx : ContextInfo) : IO MetavarContext.Json := do
let mut decls := #[]
for (mvarId, decl) in mctx.decls do
let (_, typeMVars) ← ctx.runMetaM decl.lctx ((Meta.collectMVars decl.type).run {})
decls := decls.push {
mvarId := toString mvarId.name
userName := toString decl.userName
type := (← ctx.ppExpr {} decl.type).pretty
mvarsInType := typeMVars.result.toList
-- value := (mctx.getExprAssignmentCore? mvarId).map toString
value := "N/A"
}
return { decls }

structure ProofStepInfo where
tacticString : String
infoTree : Option Json
goalBefore : GoalInfo
goalsAfter : List GoalInfo
mctxBefore : Option MetavarContext.Json
mctxAfter : Option MetavarContext.Json
tacticDependsOn : List String
spawnedGoals : List GoalInfo
start : Option Lean.Position
finish : Option Lean.Position
deriving Inhabited, ToJson, FromJson

/--
A response to a Lean command.
`env` can be used in later calls, to build on the stored environment.
Expand All @@ -126,6 +234,7 @@ structure CommandResponse where
sorries : List Sorry := []
tactics : List Tactic := []
infotree : Option Json := none
proofTreeEdges : Option (List (List ProofStepInfo)) := none
deriving FromJson

def Json.nonemptyList [ToJson α] (k : String) : List α → List (String × Json)
Expand All @@ -138,7 +247,10 @@ instance : ToJson CommandResponse where
Json.nonemptyList "messages" r.messages,
Json.nonemptyList "sorries" r.sorries,
Json.nonemptyList "tactics" r.tactics,
match r.infotree with | some j => [("infotree", j)] | none => []
match r.infotree with | some j => [("infotree", j)] | none => [],
match r.proofTreeEdges with
| some edges => Json.nonemptyList "proofTreeEdges" edges
| none => [],
]

/--
Expand All @@ -151,17 +263,23 @@ structure ProofStepResponse where
messages : List Message := []
sorries : List Sorry := []
traces : List String
goalInfos: List GoalInfo := []
mctxAfter : Option MetavarContext.Json
proofStatus : String
stepVerification : String
deriving ToJson, FromJson

instance : ToJson ProofStepResponse where
toJson r := Json.mkObj <| .flatten [
[("proofState", r.proofState)],
[("goals", toJson r.goals)],
[("goalInfos", toJson r.goalInfos)],
Json.nonemptyList "messages" r.messages,
Json.nonemptyList "sorries" r.sorries,
Json.nonemptyList "traces" r.traces,
[("proofStatus", r.proofStatus)]
match r.mctxAfter with | some mctxAfter => [("mctxAfter", toJson mctxAfter)] | none => [],
[("proofStatus", r.proofStatus)],
[("stepVerification", r.stepVerification)]
]

/-- Json wrapper for an error. -/
Expand Down
6 changes: 3 additions & 3 deletions REPL/Lean/InfoTree/ToJson.lean
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ deriving ToJson

structure Syntax.Json where
pp : Option String
-- raw : String
raw : String
range : Range
deriving ToJson

Expand All @@ -42,7 +42,7 @@ def _root_.Lean.Syntax.toJson (stx : Syntax) (ctx : ContextInfo) (lctx : LocalCo
pp := match (← ctx.ppSyntax lctx stx).pretty with
| "failed to pretty print term (use 'set_option pp.rawOnError true' for raw representation)" => none
| pp => some pp
-- raw := toString stx
raw := toString stx
range := stx.toRange ctx }

structure TacticInfo.Json where
Expand All @@ -58,7 +58,7 @@ def TacticInfo.toJson (i : TacticInfo) (ctx : ContextInfo) : IO TacticInfo.Json
name := i.name?
stx :=
{ pp := Format.pretty (← i.pp ctx),
-- raw := toString i.info.stx,
raw := toString i.stx,
range := i.stx.toRange ctx },
goalsBefore := (← i.goalState ctx).map Format.pretty,
goalsAfter := (← i.goalStateAfter ctx).map Format.pretty }
Expand Down
Loading