feat: State and environment pickling #120

Open
aniva wants to merge 6 commits from serial/pickle into dev
3 changed files with 45 additions and 25 deletions
Showing only changes of commit 2790553180 - Show all commits

View File

@ -183,6 +183,12 @@ structure EnvAdd where
structure EnvAddResult where structure EnvAddResult where
deriving Lean.ToJson deriving Lean.ToJson
structure EnvSaveLoad where
path: System.FilePath
deriving Lean.FromJson
structure EnvSaveLoadResult where
deriving Lean.ToJson
/-- Set options; See `Options` struct above for meanings -/ /-- Set options; See `Options` struct above for meanings -/
structure OptionsSet where structure OptionsSet where
printJsonPretty?: Option Bool printJsonPretty?: Option Bool

View File

@ -1,5 +1,6 @@
import Lean.Environment import Lean.Environment
import Lean.Replay import Lean.Replay
import Init.System.IOError
import Std.Data.HashMap import Std.Data.HashMap
/-! /-!
@ -43,9 +44,6 @@ unsafe def withUnpickle [Monad m] [MonadLiftT IO m] {α β : Type}
let r ← f x let r ← f x
region.free region.free
pure r pure r
end Pantograph
namespace Lean.Environment
/-- /--
Pickle an `Environment` to disk. Pickle an `Environment` to disk.
@ -57,7 +55,7 @@ and when unpickling, we build a fresh `Environment` from the imports,
and then add the new constants. and then add the new constants.
-/ -/
@[export pantograph_env_pickle_m] @[export pantograph_env_pickle_m]
def pickle (env : Environment) (path : System.FilePath) : IO Unit := def env_pickle (env : Environment) (path : System.FilePath) : IO Unit :=
Pantograph.pickle path (env.header.imports, env.constants.map₂) Pantograph.pickle path (env.header.imports, env.constants.map₂)
/-- /--
@ -67,9 +65,9 @@ We construct a fresh `Environment` with the relevant imports,
and then replace the new constants. and then replace the new constants.
-/ -/
@[export pantograph_env_unpickle_m] @[export pantograph_env_unpickle_m]
def unpickle (path : System.FilePath) : IO (Environment × CompactedRegion) := unsafe do def env_unpickle (path : System.FilePath) : IO (Environment × CompactedRegion) := unsafe do
let ((imports, map₂), region) ← Pantograph.unpickle (Array Import × PHashMap Name ConstantInfo) path let ((imports, map₂), region) ← Pantograph.unpickle (Array Import × PHashMap Name ConstantInfo) path
let env ← importModules imports {} 0 let env ← importModules imports {} 0
return (← env.replay (Std.HashMap.ofList map₂.toList), region) return (← env.replay (Std.HashMap.ofList map₂.toList), region)
end Lean.Environment end Pantograph

View File

@ -24,6 +24,7 @@ def runMetaInMainM { α } (metaM: Lean.MetaM α): MainM α :=
def runTermElabInMainM { α } (termElabM: Lean.Elab.TermElabM α) : MainM α := def runTermElabInMainM { α } (termElabM: Lean.Elab.TermElabM α) : MainM α :=
termElabM.run' (ctx := defaultElabContext) |>.run' termElabM.run' (ctx := defaultElabContext) |>.run'
/-- Main loop command of the REPL -/
def execute (command: Protocol.Command): MainM Lean.Json := do def execute (command: Protocol.Command): MainM Lean.Json := do
let run { α β: Type } [Lean.FromJson α] [Lean.ToJson β] (comm: α → MainM (CR β)): MainM Lean.Json := let run { α β: Type } [Lean.FromJson α] [Lean.ToJson β] (comm: α → MainM (CR β)): MainM Lean.Json :=
match Lean.fromJson? command.payload with match Lean.fromJson? command.payload with
@ -32,28 +33,35 @@ def execute (command: Protocol.Command): MainM Lean.Json := do
| .ok result => return Lean.toJson result | .ok result => return Lean.toJson result
| .error ierror => return Lean.toJson ierror | .error ierror => return Lean.toJson ierror
| .error error => return Lean.toJson $ errorCommand s!"Unable to parse json: {error}" | .error error => return Lean.toJson $ errorCommand s!"Unable to parse json: {error}"
match command.cmd with try
| "reset" => run reset match command.cmd with
| "stat" => run stat | "reset" => run reset
| "expr.echo" => run expr_echo | "stat" => run stat
| "env.catalog" => run env_catalog | "expr.echo" => run expr_echo
| "env.inspect" => run env_inspect | "env.catalog" => run env_catalog
| "env.add" => run env_add | "env.inspect" => run env_inspect
| "options.set" => run options_set | "env.add" => run env_add
| "options.print" => run options_print | "env.save" => run env_save
| "goal.start" => run goal_start | "env.load" => run env_load
| "goal.tactic" => run goal_tactic | "options.set" => run options_set
| "goal.continue" => run goal_continue | "options.print" => run options_print
| "goal.delete" => run goal_delete | "goal.start" => run goal_start
| "goal.print" => run goal_print | "goal.tactic" => run goal_tactic
| "frontend.process" => run frontend_process | "goal.continue" => run goal_continue
| cmd => | "goal.delete" => run goal_delete
let error: Protocol.InteractionError := | "goal.print" => run goal_print
errorCommand s!"Unknown command {cmd}" | "frontend.process" => run frontend_process
return Lean.toJson error | cmd =>
let error: Protocol.InteractionError :=
errorCommand s!"Unknown command {cmd}"
return Lean.toJson error
catch ex => do
let error ← ex.toMessageData.toString
return Lean.toJson $ errorIO error
where where
errorCommand := errorI "command" errorCommand := errorI "command"
errorIndex := errorI "index" errorIndex := errorI "index"
errorIO := errorI "io"
newGoalState (goalState: GoalState) : MainM Nat := do newGoalState (goalState: GoalState) : MainM Nat := do
let state ← get let state ← get
let stateId := state.nextId let stateId := state.nextId
@ -80,6 +88,14 @@ def execute (command: Protocol.Command): MainM Lean.Json := do
Environment.inspect args state.options Environment.inspect args state.options
env_add (args: Protocol.EnvAdd): MainM (CR Protocol.EnvAddResult) := do env_add (args: Protocol.EnvAdd): MainM (CR Protocol.EnvAddResult) := do
Environment.addDecl args Environment.addDecl args
env_save (args: Protocol.EnvSaveLoad): MainM (CR Protocol.EnvSaveLoadResult) := do
let env ← Lean.MonadEnv.getEnv
env_pickle env args.path
return .ok {}
env_load (args: Protocol.EnvSaveLoad): MainM (CR Protocol.EnvSaveLoadResult) := do
let (env, _) ← env_unpickle args.path
Lean.setEnv env
return .ok {}
expr_echo (args: Protocol.ExprEcho): MainM (CR Protocol.ExprEchoResult) := do expr_echo (args: Protocol.ExprEcho): MainM (CR Protocol.ExprEchoResult) := do
let state ← get let state ← get
exprEcho args.expr (expectedType? := args.type?) (levels := args.levels.getD #[]) (options := state.options) exprEcho args.expr (expectedType? := args.type?) (levels := args.levels.getD #[]) (options := state.options)