fix: implement String.toName using decodeNameLit

fixes #2231
This commit is contained in:
Mario Carneiro 2023-05-24 20:39:56 -04:00 committed by Leonardo de Moura
parent 8d0504b3b7
commit 01ba75661e
5 changed files with 28 additions and 45 deletions

View file

@ -836,22 +836,30 @@ private partial def splitNameLitAux (ss : Substring) (acc : List Substring) : Li
def splitNameLit (ss : Substring) : List Substring :=
splitNameLitAux ss [] |>.reverse
def _root_.Substring.toName (s : Substring) : Name :=
match splitNameLitAux s [] with
| [] => .anonymous
| comps => comps.foldr (init := Name.anonymous)
fun comp n =>
let comp := comp.toString
if isIdBeginEscape comp.front then
Name.mkStr n (comp.drop 1 |>.dropRight 1)
else if comp.front.isDigit then
if let some k := decodeNatLitVal? comp then
Name.mkNum n k
else
unreachable!
else
Name.mkStr n comp
def _root_.String.toName (s : String) : Name :=
s.toSubstring.toName
def decodeNameLit (s : String) : Option Name :=
if s.get 0 == '`' then
match splitNameLitAux (s.toSubstring.drop 1) [] with
| [] => none
| comps => some <| comps.foldr (init := Name.anonymous)
fun comp n =>
let comp := comp.toString
if isIdBeginEscape comp.front then
Name.mkStr n (comp.drop 1 |>.dropRight 1)
else if comp.front.isDigit then
if let some k := decodeNatLitVal? comp then
Name.mkNum n k
else
unreachable!
else
Name.mkStr n comp
match (s.toSubstring.drop 1).toName with
| .anonymous => none
| name => some name
else
none

View file

@ -81,8 +81,8 @@ instance : FromJson Name where
if s == "[anonymous]" then
return Name.anonymous
else
let some n := Syntax.decodeNameLit ("`" ++ s)
| throw s!"expected a `Name`, got '{j}'"
let n := s.toName
if n.isAnonymous then throw s!"expected a `Name`, got '{j}'"
return n
instance : ToJson Name where

View file

@ -34,9 +34,10 @@ def fromString (s : String) : Except String RefIdent := do
-- See `FromJson Name`
let name ← match sName with
| "[anonymous]" => pure Name.anonymous
| _ => match Syntax.decodeNameLit ("`" ++ sName) with
| some n => pure n
| none => throw s!"expected a Name, got {sName}"
| _ =>
let n := s.toName
if n.isAnonymous then throw s!"expected a Name, got {sName}"
else pure n
match sPrefix with
| "c:" => return RefIdent.const name
| "f:" => return RefIdent.fvar <| FVarId.mk name

View file

@ -151,7 +151,3 @@ end Name
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

View file

@ -62,28 +62,6 @@ def getOptionDescr (name : Name) : IO String := do
let decl ← getOptionDecl name
pure decl.descr
def setOptionFromString (opts : Options) (entry : String) : IO Options := do
let ps := (entry.splitOn "=").map String.trim
let [key, val] ← pure ps | throw $ IO.userError "invalid configuration option entry, it must be of the form '<key> = <value>'"
let key := Name.mkSimple key
let defValue ← getOptionDefaultValue key
match defValue with
| DataValue.ofString _ => pure $ opts.setString key val
| DataValue.ofBool _ =>
if key == `true then pure $ opts.setBool key true
else if key == `false then pure $ opts.setBool key false
else throw $ IO.userError s!"invalid Bool option value '{val}'"
| DataValue.ofName _ => pure $ opts.setName key val.toName
| DataValue.ofNat _ =>
match val.toNat? with
| none => throw (IO.userError s!"invalid Nat option value '{val}'")
| some v => pure $ opts.setNat key v
| DataValue.ofInt _ =>
match val.toInt? with
| none => throw (IO.userError s!"invalid Int option value '{val}'")
| some v => pure $ opts.setInt key v
| DataValue.ofSyntax _ => throw (IO.userError s!"invalid Syntax option value")
class MonadOptions (m : Type → Type) where
getOptions : m Options