/- Copyright (c) 2016 Microsoft Corporation. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Author: Leonardo de Moura -/ prelude import Init.Data.Format.Basic import Init.Data.Int.Basic import Init.Data.Nat.Div import Init.Data.UInt import Init.Control.Id open Sum Subtype Nat open Std class Repr (α : Type u) where reprPrec : α → Nat → Format export Repr (reprPrec) abbrev repr [Repr α] (a : α) : Format := reprPrec a 0 abbrev reprStr [Repr α] (a : α) : String := reprPrec a 0 |>.pretty abbrev reprArg [Repr α] (a : α) : Format := reprPrec a max_prec /- Auxiliary class for marking types that should be considered atomic by `Repr` methods. We use it at `Repr (List α)` to decide whether `bracketFill` should be used or not. -/ class ReprAtom (α : Type u) -- This instance is needed because `id` is not reducible instance [Repr α] : Repr (id α) := inferInstanceAs (Repr α) instance [Repr α] : Repr (Id α) := inferInstanceAs (Repr α) instance : Repr Bool where reprPrec | true, _ => "true" | false, _ => "false" def Repr.addAppParen (f : Format) (prec : Nat) : Format := if prec >= max_prec then Format.paren f else f instance : Repr (Decidable p) where reprPrec | Decidable.isTrue _, prec => Repr.addAppParen "isTrue _" prec | Decidable.isFalse _, prec => Repr.addAppParen "isFalse _" prec instance : Repr PUnit.{u+1} where reprPrec _ _ := "PUnit.unit" instance [Repr α] : Repr (ULift.{v} α) where reprPrec v prec := Repr.addAppParen ("ULift.up " ++ reprArg v.1) prec instance : Repr Unit where reprPrec _ _ := "()" instance [Repr α] : Repr (Option α) where reprPrec | none, _ => "none" | some a, prec => Repr.addAppParen ("some " ++ reprArg a) prec instance [Repr α] [Repr β] : Repr (Sum α β) where reprPrec | Sum.inl a, prec => Repr.addAppParen ("Sum.inl " ++ reprArg a) prec | Sum.inr b, prec => Repr.addAppParen ("Sum.inr " ++ reprArg b) prec class ReprTuple (α : Type u) where reprTuple : α → List Format → List Format export ReprTuple (reprTuple) instance [Repr α] : ReprTuple α where reprTuple a xs := repr a :: xs instance [Repr α] [ReprTuple β] : ReprTuple (α × β) where reprTuple | (a, b), xs => reprTuple b (repr a :: xs) instance [Repr α] [ReprTuple β] : Repr (α × β) where reprPrec | (a, b), _ => Format.bracket "(" (Format.joinSep (reprTuple b [repr a]).reverse ("," ++ Format.line)) ")" instance {β : α → Type v} [Repr α] [(x : α) → Repr (β x)] : Repr (Sigma β) where reprPrec | ⟨a, b⟩, _ => Format.bracket "⟨" (repr a ++ ", " ++ repr b) "⟩" instance {p : α → Prop} [Repr α] : Repr (Subtype p) where reprPrec s prec := reprPrec s.val prec namespace Nat def digitChar (n : Nat) : Char := if n = 0 then '0' else if n = 1 then '1' else if n = 2 then '2' else if n = 3 then '3' else if n = 4 then '4' else if n = 5 then '5' else if n = 6 then '6' else if n = 7 then '7' else if n = 8 then '8' else if n = 9 then '9' else if n = 0xa then 'a' else if n = 0xb then 'b' else if n = 0xc then 'c' else if n = 0xd then 'd' else if n = 0xe then 'e' else if n = 0xf then 'f' else '*' def toDigitsCore (base : Nat) : Nat → Nat → List Char → List Char | 0, _, ds => ds | fuel+1, n, ds => let d := digitChar <| n % base; let n' := n / base; if n' = 0 then d::ds else toDigitsCore base fuel n' (d::ds) def toDigits (base : Nat) (n : Nat) : List Char := toDigitsCore base (n+1) n [] protected def repr (n : Nat) : String := (toDigits 10 n).asString def superDigitChar (n : Nat) : Char := if n = 0 then '⁰' else if n = 1 then '¹' else if n = 2 then '²' else if n = 3 then '³' else if n = 4 then '⁴' else if n = 5 then '⁵' else if n = 6 then '⁶' else if n = 7 then '⁷' else if n = 8 then '⁸' else if n = 9 then '⁹' else '*' partial def toSuperDigitsAux : Nat → List Char → List Char | n, ds => let d := superDigitChar <| n % 10; let n' := n / 10; if n' = 0 then d::ds else toSuperDigitsAux n' (d::ds) def toSuperDigits (n : Nat) : List Char := toSuperDigitsAux n [] def toSuperscriptString (n : Nat) : String := (toSuperDigits n).asString end Nat instance : Repr Nat where reprPrec n _ := Nat.repr n def Int.repr : Int → String | ofNat m => Nat.repr m | negSucc m => "-" ++ Nat.repr (succ m) instance : Repr Int where reprPrec i _ := i.repr def hexDigitRepr (n : Nat) : String := String.singleton <| Nat.digitChar n def charToHex (c : Char) : String := let n := Char.toNat c; let d2 := n / 16; let d1 := n % 16; hexDigitRepr d2 ++ hexDigitRepr d1 def Char.quoteCore (c : Char) : String := if c = '\n' then "\\n" else if c = '\t' then "\\t" else if c = '\\' then "\\\\" else if c = '\"' then "\\\"" else if c.toNat <= 31 ∨ c = '\x7f' then "\\x" ++ charToHex c else String.singleton c def Char.quote (c : Char) : String := "'" ++ Char.quoteCore c ++ "'" instance : Repr Char where reprPrec c _ := c.quote protected def Char.repr (c : Char) : String := c.quote def String.quote (s : String) : String := if s.isEmpty then "\"\"" else s.foldl (fun s c => s ++ c.quoteCore) "\"" ++ "\"" instance : Repr String where reprPrec s _ := s.quote instance : Repr String.Pos where reprPrec p _ := "{ byteIdx := " ++ repr p.byteIdx ++ " }" instance : Repr Substring where reprPrec s _ := Format.text <| String.quote s.toString ++ ".toSubstring" instance : Repr String.Iterator where reprPrec | ⟨s, pos⟩, prec => Repr.addAppParen ("String.Iterator.mk " ++ reprArg s ++ " " ++ reprArg pos) prec instance (n : Nat) : Repr (Fin n) where reprPrec f _ := repr f.val instance : Repr UInt8 where reprPrec n _ := repr n.toNat instance : Repr UInt16 where reprPrec n _ := repr n.toNat instance : Repr UInt32 where reprPrec n _ := repr n.toNat instance : Repr UInt64 where reprPrec n _ := repr n.toNat instance : Repr USize where reprPrec n _ := repr n.toNat instance [Repr α] : Repr (List α) where reprPrec a n := let _ : ToFormat α := ⟨repr⟩ match a, n with | [], _ => "[]" | as, _ => Format.bracket "[" (Format.joinSep as ("," ++ Format.line)) "]" instance [Repr α] [ReprAtom α] : Repr (List α) where reprPrec a n := let _ : ToFormat α := ⟨repr⟩ match a, n with | [], _ => "[]" | as, _ => Format.bracketFill "[" (Format.joinSep as ("," ++ Format.line)) "]" instance : ReprAtom Bool := ⟨⟩ instance : ReprAtom Nat := ⟨⟩ instance : ReprAtom Int := ⟨⟩ instance : ReprAtom Char := ⟨⟩ instance : ReprAtom String := ⟨⟩ instance : ReprAtom UInt8 := ⟨⟩ instance : ReprAtom UInt16 := ⟨⟩ instance : ReprAtom UInt32 := ⟨⟩ instance : ReprAtom UInt64 := ⟨⟩ instance : ReprAtom USize := ⟨⟩ deriving instance Repr for Lean.SourceInfo