2023-05-09 16:39:24 -07:00
|
|
|
|
import Lean.Data.Json
|
2023-05-09 22:51:19 -07:00
|
|
|
|
import Lean.Environment
|
2023-05-07 15:19:45 -07:00
|
|
|
|
|
2023-05-09 22:51:19 -07:00
|
|
|
|
import Pantograph.Commands
|
2023-05-09 16:39:24 -07:00
|
|
|
|
|
|
|
|
|
namespace Pantograph
|
|
|
|
|
|
2023-05-09 22:51:19 -07:00
|
|
|
|
-- Utilities
|
|
|
|
|
def option_expect (o: Option α) (error: String): Except String α :=
|
|
|
|
|
match o with
|
|
|
|
|
| .some value => return value
|
|
|
|
|
| .none => throw error
|
|
|
|
|
|
2023-05-09 16:39:24 -07:00
|
|
|
|
structure State where
|
2023-05-09 22:51:19 -07:00
|
|
|
|
environments: Array Lean.Environment
|
2023-05-09 16:39:24 -07:00
|
|
|
|
|
|
|
|
|
-- State monad
|
|
|
|
|
abbrev T (m: Type → Type) := StateT State m
|
2023-05-09 22:51:19 -07:00
|
|
|
|
abbrev Subroutine α := ExceptT String (T IO) α
|
|
|
|
|
|
|
|
|
|
def nextId (s: State): Nat := s.environments.size
|
2023-05-09 18:01:09 -07:00
|
|
|
|
|
|
|
|
|
structure Command where
|
|
|
|
|
cmd: String
|
|
|
|
|
payload: Lean.Json
|
|
|
|
|
deriving Lean.FromJson
|
|
|
|
|
|
2023-05-09 22:51:19 -07:00
|
|
|
|
namespace Commands
|
|
|
|
|
|
|
|
|
|
def create (args: Create): Subroutine CreateResult := do
|
|
|
|
|
let state ← get
|
|
|
|
|
let id := nextId state
|
|
|
|
|
let env ← Lean.importModules
|
|
|
|
|
(imports := args.imports.map strTransform)
|
|
|
|
|
(opts := {})
|
|
|
|
|
(trustLevel := 1)
|
|
|
|
|
modify fun s => { environments := s.environments.push env }
|
|
|
|
|
return { id := id }
|
|
|
|
|
where strTransform (s: String): Lean.Import :=
|
|
|
|
|
let li := s.split (λ c => c == '.')
|
|
|
|
|
let name := li.foldl (λ pre segment => Lean.Name.str pre segment) Lean.Name.anonymous
|
|
|
|
|
{ module := name, runtimeOnly := false }
|
|
|
|
|
|
|
|
|
|
def catalog (args: Catalog): Subroutine CatalogResult := do
|
|
|
|
|
let state ← get
|
|
|
|
|
match state.environments.get? args.id with
|
|
|
|
|
| .some env =>
|
2023-05-12 01:08:36 -07:00
|
|
|
|
let names := env.constants.fold (init := []) (λ es name info =>
|
|
|
|
|
if info.isUnsafe ∨ es.length > 500 then es else (toString name)::es)
|
|
|
|
|
--let names := env.constants.toList.map (λ ⟨x, _⟩ => toString x)
|
2023-05-09 22:51:19 -07:00
|
|
|
|
return { theorems := names }
|
|
|
|
|
| .none => throw s!"Invalid environment id {args.id}"
|
2023-05-09 18:01:09 -07:00
|
|
|
|
|
2023-05-09 22:51:19 -07:00
|
|
|
|
unsafe def clear: Subroutine ClearResult := do
|
|
|
|
|
let state ← get
|
|
|
|
|
for env in state.environments do
|
|
|
|
|
env.freeRegions
|
|
|
|
|
return { n := state.environments.size }
|
2023-05-09 16:39:24 -07:00
|
|
|
|
|
2023-05-09 22:51:19 -07:00
|
|
|
|
end Commands
|
2023-05-09 16:39:24 -07:00
|
|
|
|
end Pantograph
|
|
|
|
|
|
|
|
|
|
open Pantograph
|
|
|
|
|
|
2023-05-09 22:51:19 -07:00
|
|
|
|
unsafe def execute (command: String): ExceptT String (T IO) Lean.Json := do
|
2023-05-09 16:39:24 -07:00
|
|
|
|
let obj ← Lean.Json.parse command
|
2023-05-09 18:01:09 -07:00
|
|
|
|
let command: Command ← Lean.fromJson? obj
|
|
|
|
|
match command.cmd with
|
|
|
|
|
| "create" =>
|
2023-05-09 22:51:19 -07:00
|
|
|
|
let args: Commands.Create ← Lean.fromJson? command.payload
|
|
|
|
|
let ret ← Commands.create args
|
|
|
|
|
return Lean.toJson ret
|
2023-05-09 18:01:09 -07:00
|
|
|
|
| "catalog" =>
|
2023-05-09 22:51:19 -07:00
|
|
|
|
let args: Commands.Catalog ← Lean.fromJson? command.payload
|
|
|
|
|
let ret ← Commands.catalog args
|
|
|
|
|
return Lean.toJson ret
|
|
|
|
|
| "clear" =>
|
|
|
|
|
-- Delete all the environments
|
|
|
|
|
let ret ← Commands.clear
|
|
|
|
|
return Lean.toJson ret
|
2023-05-09 18:01:09 -07:00
|
|
|
|
| cmd => throw s!"Unknown verb: {cmd}"
|
2023-05-09 16:39:24 -07:00
|
|
|
|
|
2023-05-09 22:51:19 -07:00
|
|
|
|
|
2023-05-09 16:39:24 -07:00
|
|
|
|
-- Main IO functions
|
|
|
|
|
|
|
|
|
|
unsafe def getLines : IO String := do
|
|
|
|
|
match (← (← IO.getStdin).getLine) with
|
|
|
|
|
| "" => pure ""
|
|
|
|
|
| "\n" => pure "\n"
|
|
|
|
|
| line => pure <| line ++ (← getLines)
|
|
|
|
|
|
|
|
|
|
unsafe def loop : T IO Unit := do
|
|
|
|
|
let command ← getLines
|
|
|
|
|
if command == "" then return ()
|
2023-05-09 18:01:09 -07:00
|
|
|
|
let ret ← execute command
|
|
|
|
|
match ret with
|
2023-05-09 22:51:19 -07:00
|
|
|
|
| .error e => IO.println s!"Error: {e}"
|
2023-05-09 16:39:24 -07:00
|
|
|
|
| .ok obj => IO.println <| toString <| obj
|
2023-05-09 22:51:19 -07:00
|
|
|
|
loop
|
2023-05-09 16:39:24 -07:00
|
|
|
|
|
2023-05-12 01:08:36 -07:00
|
|
|
|
unsafe def main : IO Unit := do
|
|
|
|
|
Lean.initSearchPath (← Lean.findSysroot)
|
2023-05-09 16:39:24 -07:00
|
|
|
|
StateT.run' loop ⟨#[]⟩
|