Add SemihashMap interface, rename proof commands to goal commands, allow deletion

This commit is contained in:
Leni Aniva 2023-08-30 19:16:33 -07:00
parent b98304f78a
commit f1f1c20ff9
4 changed files with 95 additions and 20 deletions

View File

@ -38,6 +38,7 @@ def execute (command: Commands.Command): MainM Lean.Json := do
| "options.print" => run options_print | "options.print" => run options_print
| "goal.start" => run goal_start | "goal.start" => run goal_start
| "goal.tactic" => run goal_tactic | "goal.tactic" => run goal_tactic
| "goal.delete" => run goal_delete
| cmd => | cmd =>
let error: Commands.InteractionError := let error: Commands.InteractionError :=
errorCommand s!"Unknown command {cmd}" errorCommand s!"Unknown command {cmd}"
@ -117,7 +118,7 @@ def execute (command: Commands.Command): MainM Lean.Json := do
return .ok { } return .ok { }
options_print (_: Commands.OptionsPrint): MainM (CR Commands.OptionsPrintResult) := do options_print (_: Commands.OptionsPrint): MainM (CR Commands.OptionsPrintResult) := do
return .ok (← get).options return .ok (← get).options
goal_start (args: Commands.ProofStart): MainM (CR Commands.ProofStartResult) := do goal_start (args: Commands.GoalStart): MainM (CR Commands.GoalStartResult) := do
let state ← get let state ← get
let env ← Lean.MonadEnv.getEnv let env ← Lean.MonadEnv.getEnv
let expr?: Except _ Lean.Expr ← (match args.expr, args.copyFrom with let expr?: Except _ Lean.Expr ← (match args.expr, args.copyFrom with
@ -142,10 +143,10 @@ def execute (command: Commands.Command): MainM Lean.Json := do
let (goalStates, goalId) := state.goalStates.insert goalState let (goalStates, goalId) := state.goalStates.insert goalState
set { state with goalStates } set { state with goalStates }
return .ok { goalId } return .ok { goalId }
goal_tactic (args: Commands.ProofTactic): MainM (CR Commands.ProofTacticResult) := do goal_tactic (args: Commands.GoalTactic): MainM (CR Commands.GoalTacticResult) := do
let state ← get let state ← get
match state.goalStates.get? args.goalId with match state.goalStates.get? args.goalId with
| .none => return .error $ errorIndex "Invalid goal index {args.goalId}" | .none => return .error $ errorIndex s!"Invalid goal index {args.goalId}"
| .some goalState => | .some goalState =>
let result ← GoalState.execute goalState args.tactic |>.run state.options let result ← GoalState.execute goalState args.tactic |>.run state.options
match result with match result with
@ -164,5 +165,10 @@ def execute (command: Commands.Command): MainM Lean.Json := do
return .ok { goals? := .some sGoals.reverse.toArray, goalIds? := .some goalIds.reverse.toArray } return .ok { goals? := .some sGoals.reverse.toArray, goalIds? := .some goalIds.reverse.toArray }
| .failure messages => | .failure messages =>
return .ok { tacticErrors? := .some messages } return .ok { tacticErrors? := .some messages }
goal_delete (args: Commands.GoalDelete): MainM (CR Commands.GoalDeleteResult) := do
let state ← get
let goalStates := args.goalIds.foldl (λ map id => map.remove id) state.goalStates
set { state with goalStates }
return .ok {}
end Pantograph end Pantograph

View File

@ -130,20 +130,20 @@ structure OptionsPrint where
deriving Lean.FromJson deriving Lean.FromJson
abbrev OptionsPrintResult := Options abbrev OptionsPrintResult := Options
structure ProofStart where structure GoalStart where
-- Only one of the fields below may be populated. -- Only one of the fields below may be populated.
expr: Option String -- Proof expression expr: Option String -- Proof expression
copyFrom: Option String -- Theorem name copyFrom: Option String -- Theorem name
deriving Lean.FromJson deriving Lean.FromJson
structure ProofStartResult where structure GoalStartResult where
goalId: Nat := 0 -- Proof tree id goalId: Nat := 0 -- Proof tree id
deriving Lean.ToJson deriving Lean.ToJson
structure ProofTactic where structure GoalTactic where
-- Identifiers for tree, state, and goal -- Identifiers for tree, state, and goal
goalId: Nat goalId: Nat
tactic: String tactic: String
deriving Lean.FromJson deriving Lean.FromJson
structure ProofTacticResult where structure GoalTacticResult where
-- Existence of this field shows success -- Existence of this field shows success
goals?: Option (Array Goal) := .none goals?: Option (Array Goal) := .none
-- Next proof state id, if successful -- Next proof state id, if successful
@ -152,5 +152,12 @@ structure ProofTacticResult where
tacticErrors?: Option (Array String) := .none tacticErrors?: Option (Array String) := .none
deriving Lean.ToJson deriving Lean.ToJson
-- Remove a bunch of goals.
structure GoalDelete where
goalIds: List Nat
deriving Lean.FromJson
structure GoalDeleteResult where
deriving Lean.ToJson
end Pantograph.Commands end Pantograph.Commands

View File

@ -18,7 +18,56 @@ structure Imp (β: Type u) where
namespace Imp namespace Imp
structure WF (m: Imp β): Prop where
capacity: m.data.size = m.deallocs.size
front_dealloc: ∀ i: Fin m.deallocs.size, (i < m.allocFront) → (m.deallocs.get i) < m.allocFront
front_data: ∀ i: Fin m.data.size, (i ≥ m.allocFront) → (m.data.get i).isNone
def empty (capacity := 16): Imp β :=
{
data := mkArray capacity .none,
size := 0,
allocFront := 0,
deallocs := mkArray capacity 0,
lastDealloc := 0,
}
private theorem list_get_replicate (x: α) (i: Fin (List.replicate n x).length):
List.get (List.replicate n x) i = x := by
sorry
theorem empty_wf : WF (empty n: Imp β) := by
unfold empty
apply WF.mk
case capacity =>
conv =>
lhs
congr
simp
conv =>
rhs
congr
simp
simp
case front_dealloc =>
simp_all
intro i
intro a
contradiction
case front_data =>
simp_all
intro i
unfold Imp.data at i
simp at i
conv =>
lhs
unfold Array.get
unfold mkArray
simp [List.replicate]
rewrite [list_get_replicate]
-- FIXME: Merge this with the well-formed versions below so proof and code can
-- mesh seamlessly.
@[inline] def insert (map: Imp β) (v: β): (Imp β × Nat) := @[inline] def insert (map: Imp β) (v: β): (Imp β × Nat) :=
match map.lastDealloc with match map.lastDealloc with
| 0 => -- Capacity is full, buffer expansion is required | 0 => -- Capacity is full, buffer expansion is required
@ -53,8 +102,9 @@ namespace Imp
} }
(result, nextIndex) (result, nextIndex)
@[inline] def remove (map: Imp β) (index: Nat): Imp β := @[inline] def remove (map: Imp β) (index: Fin (map.size)): Imp β :=
match map.data.getD index .none with have h: index.val < map.data.size := by sorry
match map.data.get ⟨index.val, h⟩ with
| .none => map | .none => map
| .some _ => | .some _ =>
{ {
@ -66,24 +116,34 @@ namespace Imp
} }
/-- Retrieval is efficient -/ /-- Retrieval is efficient -/
@[inline] def get? (map: Imp β) (index: Nat): Option β := @[inline] def get? (map: Imp β) (index: Fin (map.size)): Option β :=
map.data.getD index .none have h: index.val < map.data.size := by sorry
map.data.get ⟨index.val, h⟩
@[inline] def capacity (map: Imp β): Nat := map.data.size @[inline] def capacity (map: Imp β): Nat := map.data.size
end Imp end Imp
def empty (capacity := 16): Imp β :=
{
data := mkArray capacity .none,
size := 0,
allocFront := 0,
deallocs := mkArray capacity 0,
lastDealloc := 0,
}
/-- /--
This is like a hashmap but you cannot control the keys. This is like a hashmap but you cannot control the keys.
-/ -/
def _root_.Pantograph.SemihashMap β := Imp β def _root_.Pantograph.SemihashMap β := {m: Imp β // m.WF}
@[inline] def empty (capacity := 16): SemihashMap β :=
⟨ Imp.empty capacity, Imp.empty_wf ⟩
@[inline] def insert (map: SemihashMap β) (v: β): (SemihashMap β × Nat) :=
let ⟨imp, pre⟩ := map
let ⟨result, id⟩ := imp.insert v
( ⟨ result, sorry ⟩, id)
@[inline] def remove (map: SemihashMap β) (index: Nat): SemihashMap β :=
let ⟨imp, pre⟩ := map
let result := imp.remove ⟨index, sorry⟩
⟨ result, sorry ⟩
@[inline] def get? (map: SemihashMap β) (index: Nat): Option β :=
let ⟨imp, _⟩ := map
imp.get? ⟨index, sorry⟩
@[inline] def size (map: SemihashMap β): Nat :=
let ⟨imp, _⟩ := map
imp.size
end Pantograph.SemihashMap end Pantograph.SemihashMap

View File

@ -56,6 +56,7 @@ $ env build/bin/Pantograph Init
goal.start {"expr": "∀ (n m : Nat), n + m = m + n"} goal.start {"expr": "∀ (n m : Nat), n + m = m + n"}
goal.tactic {"goalId": 0, "tactic": "intro n m"} goal.tactic {"goalId": 0, "tactic": "intro n m"}
goal.tactic {"goalId": 1, "tactic": "assumption"} goal.tactic {"goalId": 1, "tactic": "assumption"}
goal.delete {"goalIds": [0]}
stat {} stat {}
goal.tactic {"goalId": 1, "tactic": "rw [Nat.add_comm]"} goal.tactic {"goalId": 1, "tactic": "rw [Nat.add_comm]"}
stat stat
@ -76,6 +77,7 @@ See `Pantograph/Commands.lean` for a description of the parameters and return va
- `options.print`: Display the current set of options - `options.print`: Display the current set of options
- `goal.start {["name": <name>], ["expr": <expr>], ["copyFrom": <symbol>]}`: Start a new goal from a given expression or symbol - `goal.start {["name": <name>], ["expr": <expr>], ["copyFrom": <symbol>]}`: Start a new goal from a given expression or symbol
- `goal.tactic {"goalId": <id>, "tactic": <tactic>}`: Execute a tactic string on a given goal - `goal.tactic {"goalId": <id>, "tactic": <tactic>}`: Execute a tactic string on a given goal
- `goal.remove {"goalIds": [<id>]}"`: Remove a bunch of stored goals.
- `stat`: Display resource usage - `stat`: Display resource usage
## Errors ## Errors