feat: trie for hierarchical names
This commit is contained in:
parent
f896bb27d6
commit
5064115ff1
3 changed files with 179 additions and 0 deletions
|
|
@ -17,3 +17,5 @@ import Lean.Data.Options
|
|||
import Lean.Data.Position
|
||||
import Lean.Data.SMap
|
||||
import Lean.Data.Trie
|
||||
import Lean.Data.PrefixTree
|
||||
import Lean.Data.NameTrie
|
||||
|
|
|
|||
66
src/Lean/Data/NameTrie.lean
Normal file
66
src/Lean/Data/NameTrie.lean
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
/-
|
||||
Copyright (c) 2020 Microsoft Corporation. All rights reserved.
|
||||
Released under Apache 2.0 license as described in the file LICENSE.
|
||||
Authors: Leonardo de Moura
|
||||
-/
|
||||
import Lean.Data.PrefixTree
|
||||
|
||||
namespace Lean
|
||||
|
||||
inductive NamePart
|
||||
| str (s : String)
|
||||
| num (n : Nat)
|
||||
|
||||
instance : ToString NamePart where
|
||||
toString
|
||||
| NamePart.str s => s
|
||||
| NamePart.num n => toString n
|
||||
|
||||
def NamePart.lt : NamePart → NamePart → Bool
|
||||
| NamePart.str a, NamePart.str b => a < b
|
||||
| NamePart.num a, NamePart.num b => a < b
|
||||
| NamePart.num _, NamePart.str _ => true
|
||||
| _, _ => false
|
||||
|
||||
def NameTrie (β : Type u) := PrefixTree NamePart β NamePart.lt
|
||||
|
||||
private def toKey (n : Name) : List NamePart :=
|
||||
loop n []
|
||||
where
|
||||
loop
|
||||
| Name.str p s _, parts => loop p (NamePart.str s :: parts)
|
||||
| Name.num p n _, parts => loop p (NamePart.num n :: parts)
|
||||
| Name.anonymous, parts => parts
|
||||
|
||||
def NameTrie.insert (t : NameTrie β) (n : Name) (b : β) : NameTrie β :=
|
||||
PrefixTree.insert t (toKey n) b
|
||||
|
||||
def NameTrie.empty : NameTrie β :=
|
||||
PrefixTree.empty
|
||||
|
||||
instance : Inhabited (NameTrie β) where
|
||||
default := NameTrie.empty
|
||||
|
||||
instance : EmptyCollection (NameTrie β) where
|
||||
emptyCollection := NameTrie.empty
|
||||
|
||||
def NameTrie.find? (t : NameTrie β) (k : Name) : Option β :=
|
||||
PrefixTree.find? t (toKey k)
|
||||
|
||||
@[inline]
|
||||
def NameTrie.foldMatchingM [Monad m] (t : NameTrie β) (k : Name) (init : σ) (f : β → σ → m σ) : m σ :=
|
||||
PrefixTree.foldMatchingM t (toKey k) init f
|
||||
|
||||
@[inline]
|
||||
def NameTrie.foldM [Monad m] (t : NameTrie β) (init : σ) (f : β → σ → m σ) : m σ :=
|
||||
t.foldMatchingM Name.anonymous init f
|
||||
|
||||
@[inline]
|
||||
def NameTrie.forMatchingM [Monad m] (t : NameTrie β) (k : Name) (f : β → m Unit) : m Unit :=
|
||||
PrefixTree.forMatchingM t (toKey k) f
|
||||
|
||||
@[inline]
|
||||
def NameTrie.forM [Monad m] (t : NameTrie β) (f : β → m Unit) : m Unit :=
|
||||
t.forMatchingM Name.anonymous f
|
||||
|
||||
end Lean
|
||||
111
src/Lean/Data/PrefixTree.lean
Normal file
111
src/Lean/Data/PrefixTree.lean
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
/-
|
||||
Copyright (c) 2020 Microsoft Corporation. All rights reserved.
|
||||
Released under Apache 2.0 license as described in the file LICENSE.
|
||||
Authors: Leonardo de Moura
|
||||
-/
|
||||
import Std.Data.RBMap
|
||||
|
||||
namespace Lean
|
||||
open Std
|
||||
|
||||
/- Similar to trie, but for arbitrary keys -/
|
||||
inductive PrefixTreeNode (α : Type u) (β : Type v) where
|
||||
| Node : Option β → RBNode α (fun _ => PrefixTreeNode α β) → PrefixTreeNode α β
|
||||
|
||||
instance : Inhabited (PrefixTreeNode α β) where
|
||||
default := PrefixTreeNode.Node none RBNode.leaf
|
||||
|
||||
namespace PrefixTreeNode
|
||||
|
||||
def empty : PrefixTreeNode α β :=
|
||||
PrefixTreeNode.Node none RBNode.leaf
|
||||
|
||||
@[specialize]
|
||||
partial def insert (t : PrefixTreeNode α β) (lt : α → α → Bool) (k : List α) (val : β) : PrefixTreeNode α β :=
|
||||
let rec insertEmpty (k : List α) : PrefixTreeNode α β :=
|
||||
match k with
|
||||
| [] => PrefixTreeNode.Node (some val) RBNode.leaf
|
||||
| k :: ks =>
|
||||
let t := insertEmpty ks
|
||||
PrefixTreeNode.Node none (RBNode.singleton k t)
|
||||
let rec loop
|
||||
| PrefixTreeNode.Node v m, [] =>
|
||||
PrefixTreeNode.Node (some val) m -- overrides old value
|
||||
| PrefixTreeNode.Node v m, k :: ks =>
|
||||
let t := match RBNode.find lt m k with
|
||||
| none => insertEmpty ks
|
||||
| some t => loop t ks
|
||||
PrefixTreeNode.Node v (RBNode.insert lt m k t)
|
||||
loop t k
|
||||
|
||||
@[specialize]
|
||||
partial def find? (t : PrefixTreeNode α β) (lt : α → α → Bool) (k : List α) : Option β :=
|
||||
let rec loop
|
||||
| PrefixTreeNode.Node val m, [] => val
|
||||
| PrefixTreeNode.Node val m, k :: ks =>
|
||||
match RBNode.find lt m k with
|
||||
| none => none
|
||||
| some t => loop t ks
|
||||
loop t k
|
||||
|
||||
@[specialize]
|
||||
partial def foldMatchingM [Monad m] (t : PrefixTreeNode α β) (lt : α → α → Bool) (k : List α) (init : σ) (f : β → σ → m σ) : m σ :=
|
||||
let rec fold : PrefixTreeNode α β → σ → m σ
|
||||
| PrefixTreeNode.Node b? n, d => do
|
||||
let d ← match b? with
|
||||
| none => pure d
|
||||
| some b => f b d
|
||||
n.foldM (init := d) fun d _ t => fold t d
|
||||
let rec find : List α → PrefixTreeNode α β → σ → m σ
|
||||
| [], t, d => fold t d
|
||||
| k::ks, PrefixTreeNode.Node _ m, d =>
|
||||
match RBNode.find lt m k with
|
||||
| none => pure init
|
||||
| some t => find ks t d
|
||||
find k t init
|
||||
|
||||
inductive WellFormed (lt : α → α → Bool) : PrefixTreeNode α β → Prop where
|
||||
| emptyWff : WellFormed lt empty
|
||||
| insertWff {t : PrefixTreeNode α β} {k : List α} {val : β} : WellFormed lt t → WellFormed lt (insert t lt k val)
|
||||
|
||||
end PrefixTreeNode
|
||||
|
||||
def PrefixTree (α : Type u) (β : Type v) (lt : α → α → Bool) : Type (max u v) :=
|
||||
{ t : PrefixTreeNode α β // t.WellFormed lt }
|
||||
|
||||
open PrefixTreeNode
|
||||
|
||||
def PrefixTree.empty : PrefixTree α β p :=
|
||||
⟨PrefixTreeNode.empty, WellFormed.emptyWff⟩
|
||||
|
||||
instance : Inhabited (PrefixTree α β p) where
|
||||
default := PrefixTree.empty
|
||||
|
||||
instance : EmptyCollection (PrefixTree α β p) where
|
||||
emptyCollection := PrefixTree.empty
|
||||
|
||||
@[inline]
|
||||
def PrefixTree.insert (t : PrefixTree α β p) (k : List α) (v : β) : PrefixTree α β p :=
|
||||
⟨t.val.insert p k v, WellFormed.insertWff t.property⟩
|
||||
|
||||
@[inline]
|
||||
def PrefixTree.find? (t : PrefixTree α β p) (k : List α) : Option β :=
|
||||
t.val.find? p k
|
||||
|
||||
@[inline]
|
||||
def PrefixTree.foldMatchingM [Monad m] (t : PrefixTree α β p) (k : List α) (init : σ) (f : β → σ → m σ) : m σ :=
|
||||
t.val.foldMatchingM p k init f
|
||||
|
||||
@[inline]
|
||||
def PrefixTree.foldM [Monad m] (t : PrefixTree α β p) (init : σ) (f : β → σ → m σ) : m σ :=
|
||||
t.foldMatchingM [] init f
|
||||
|
||||
@[inline]
|
||||
def PrefixTree.forMatchingM [Monad m] (t : PrefixTree α β p) (k : List α) (f : β → m Unit) : m Unit :=
|
||||
t.val.foldMatchingM p k () (fun b _ => f b)
|
||||
|
||||
@[inline]
|
||||
def PrefixTree.forM [Monad m] (t : PrefixTree α β p) (f : β → m Unit) : m Unit :=
|
||||
t.forMatchingM [] f
|
||||
|
||||
end Lean
|
||||
Loading…
Add table
Reference in a new issue