blob: 4f80d525bc3ef62c8b55a2e71b8ac014426b31df [file]
/-
Copyright (c) 2018 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Author: Leonardo de Moura
-/
import Std.Data.HashSet
import Std.Data.RBMap
import Std.Data.RBTree
namespace Lean
instance : Coe String Name := ⟨Name.mkSimple⟩
namespace Name
@[export lean_name_hash] def hashEx : Name → USize :=
Name.hash
def getPrefix : Name → Name
| anonymous => anonymous
| str p s _ => p
| num p s _ => p
def getRoot : Name → Name
| anonymous => anonymous
| n@(str anonymous _ _) => n
| n@(num anonymous _ _) => n
| str n _ _ => getRoot n
| num n _ _ => getRoot n
def getString! : Name → String
| str _ s _ => s
| _ => unreachable!
def getNumParts : Name → Nat
| anonymous => 0
| str p _ _ => getNumParts p + 1
| num p _ _ => getNumParts p + 1
def updatePrefix : Name → Name → Name
| anonymous, newP => anonymous
| str p s _, newP => Name.mkStr newP s
| num p s _, newP => Name.mkNum newP s
def components' : Name → List Name
| anonymous => []
| str n s _ => Name.mkStr anonymous s :: components' n
| num n v _ => Name.mkNum anonymous v :: components' n
def components (n : Name) : List Name :=
n.components'.reverse
def eqStr : Name → String → Bool
| str anonymous s _, s' => s == s'
| _, _ => false
def isPrefixOf : Name → Name → Bool
| p, anonymous => p == anonymous
| p, n@(num p' _ _) => p == n || isPrefixOf p p'
| p, n@(str p' _ _) => p == n || isPrefixOf p p'
def isSuffixOf : Name → Name → Bool
| anonymous, _ => true
| str p₁ s₁ _, str p₂ s₂ _ => s₁ == s₂ && isSuffixOf p₁ p₂
| num p₁ n₁ _, num p₂ n₂ _ => n₁ == n₂ && isSuffixOf p₁ p₂
| _, _ => false
def cmp : Name → Name → Ordering
| anonymous, anonymous => Ordering.eq
| anonymous, _ => Ordering.lt
| _, anonymous => Ordering.gt
| num p₁ i₁ _, num p₂ i₂ _ =>
match cmp p₁ p₂ with
| Ordering.eq => compare i₁ i₂
| ord => ord
| num _ _ _, str _ _ _ => Ordering.lt
| str _ _ _, num _ _ _ => Ordering.gt
| str p₁ n₁ _, str p₂ n₂ _ =>
match cmp p₁ p₂ with
| Ordering.eq => compare n₁ n₂
| ord => ord
def lt (x y : Name) : Bool :=
cmp x y == Ordering.lt
def quickCmpAux : Name → Name → Ordering
| anonymous, anonymous => Ordering.eq
| anonymous, _ => Ordering.lt
| _, anonymous => Ordering.gt
| num n v _, num n' v' _ =>
match compare v v' with
| Ordering.eq => n.quickCmpAux n'
| ord => ord
| num _ _ _, str _ _ _ => Ordering.lt
| str _ _ _, num _ _ _ => Ordering.gt
| str n s _, str n' s' _ =>
match compare s s' with
| Ordering.eq => n.quickCmpAux n'
| ord => ord
def quickCmp (n₁ n₂ : Name) : Ordering :=
match compare n₁.hash n₂.hash with
| Ordering.eq => quickCmpAux n₁ n₂
| ord => ord
def quickLt (n₁ n₂ : Name) : Bool :=
quickCmp n₁ n₂ == Ordering.lt
/- Alternative HasLt instance. -/
@[inline] protected def hasLtQuick : LT Name :=
⟨fun a b => Name.quickLt a b = true⟩
@[inline] instance : DecidableRel (@LT.lt Name Name.hasLtQuick) :=
inferInstanceAs (DecidableRel (fun a b => Name.quickLt a b = true))
/- The frontend does not allow user declarations to start with `_` in any of its parts.
We use name parts starting with `_` internally to create auxiliary names (e.g., `_private`). -/
def isInternal : Name → Bool
| str p s _ => s.get 0 == '_' || isInternal p
| num p _ _ => isInternal p
| _ => false
def isAtomic : Name → Bool
| anonymous => true
| str anonymous _ _ => true
| num anonymous _ _ => true
| _ => false
def isAnonymous : Name → Bool
| anonymous => true
| _ => false
def isStr : Name → Bool
| str .. => true
| _ => false
def isNum : Name → Bool
| num .. => true
| _ => false
end Name
open Std (RBMap RBTree mkRBMap mkRBTree)
def NameMap (α : Type) := Std.RBMap Name α Name.quickCmp
@[inline] def mkNameMap (α : Type) : NameMap α := Std.mkRBMap Name α Name.quickCmp
namespace NameMap
variable {α : Type}
instance (α : Type) : EmptyCollection (NameMap α) := ⟨mkNameMap α⟩
instance (α : Type) : Inhabited (NameMap α) where
default := {}
def insert (m : NameMap α) (n : Name) (a : α) := Std.RBMap.insert m n a
def contains (m : NameMap α) (n : Name) : Bool := Std.RBMap.contains m n
@[inline] def find? (m : NameMap α) (n : Name) : Option α := Std.RBMap.find? m n
end NameMap
def NameSet := RBTree Name Name.quickCmp
namespace NameSet
def empty : NameSet := mkRBTree Name Name.quickCmp
instance : EmptyCollection NameSet := ⟨empty⟩
instance : Inhabited NameSet := ⟨{}⟩
def insert (s : NameSet) (n : Name) : NameSet := Std.RBTree.insert s n
def contains (s : NameSet) (n : Name) : Bool := Std.RBMap.contains s n
instance : ForIn m NameSet Name :=
inferInstanceAs (ForIn _ (Std.RBTree ..) ..)
end NameSet
def NameHashSet := Std.HashSet Name
namespace NameHashSet
@[inline] def empty : NameHashSet := Std.HashSet.empty
instance : EmptyCollection NameHashSet := ⟨empty⟩
instance : Inhabited NameHashSet := ⟨{}⟩
def insert (s : NameHashSet) (n : Name) := Std.HashSet.insert s n
def contains (s : NameHashSet) (n : Name) : Bool := Std.HashSet.contains s n
end NameHashSet
end Lean
open Lean
def String.toName (s : String) : Name :=
let ps := s.splitOn ".";
ps.foldl (fun n p => Name.mkStr n p.trim) Name.anonymous