lean4-htt/library/init/data/to_string.lean
Leonardo de Moura 4eefc41b6e refactor(*): wrap string in a structure
We want to make sure string users do not depend on the string
implementation. This is the first step.

We need this refactoring *now* to make sure it will not be
super painful to address issue #1175
2017-06-07 17:30:49 -07:00

105 lines
3.5 KiB
Text
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/-
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.string.basic init.data.bool.basic init.data.subtype.basic
import init.data.unsigned.basic init.data.prod init.data.sum.basic init.data.nat.div
open sum subtype nat
universes u v
class has_to_string (α : Type u) :=
(to_string : α → string)
def to_string {α : Type u} [has_to_string α] : α → string :=
has_to_string.to_string
instance : has_to_string bool :=
⟨λ b, cond b "tt" "ff"⟩
instance {p : Prop} : has_to_string (decidable p) :=
-- Remark: type class inference will not consider local instance `b` in the new elaborator
⟨λ b : decidable p, @ite p b _ "tt" "ff"⟩
protected def list.to_string_aux {α : Type u} [has_to_string α] : bool → list α → string
| b [] := ""
| tt (x::xs) := to_string x ++ list.to_string_aux ff xs
| ff (x::xs) := ", " ++ to_string x ++ list.to_string_aux ff xs
protected def list.to_string {α : Type u} [has_to_string α] : list α → string
| [] := "[]"
| (x::xs) := "[" ++ list.to_string_aux tt (x::xs) ++ "]"
instance {α : Type u} [has_to_string α] : has_to_string (list α) :=
⟨list.to_string⟩
instance : has_to_string unit :=
⟨λ u, "star"⟩
instance {α : Type u} [has_to_string α] : has_to_string (option α) :=
⟨λ o, match o with | none := "none" | (some a) := "(some " ++ to_string a ++ ")" end⟩
instance {α : Type u} {β : Type v} [has_to_string α] [has_to_string β] : has_to_string (α ⊕ β) :=
⟨λ s, match s with | (inl a) := "(inl " ++ to_string a ++ ")" | (inr b) := "(inr " ++ to_string b ++ ")" end⟩
instance {α : Type u} {β : Type v} [has_to_string α] [has_to_string β] : has_to_string (α × β) :=
⟨λ ⟨a, b⟩, "(" ++ to_string a ++ ", " ++ to_string b ++ ")"⟩
instance {α : Type u} {β : α → Type v} [has_to_string α] [s : ∀ x, has_to_string (β x)] : has_to_string (sigma β) :=
⟨λ ⟨a, b⟩, "⟨" ++ to_string a ++ ", " ++ to_string b ++ "⟩"⟩
instance {α : Type u} {p : α → Prop} [has_to_string α] : has_to_string (subtype p) :=
⟨λ s, to_string (val s)⟩
/- Remark: the code generator replaces this definition with one that display natural numbers in decimal notation -/
protected def nat.to_string : nat → string
| 0 := "zero"
| (succ a) := "(succ " ++ nat.to_string a ++ ")"
instance : has_to_string nat :=
⟨nat.to_string⟩
def hex_digit_to_string (n : nat) : string :=
if n ≤ 9 then to_string n
else if n = 10 then "a"
else if n = 11 then "b"
else if n = 12 then "c"
else if n = 13 then "d"
else if n = 14 then "e"
else "f"
def char_to_hex (c : char) : string :=
let n := char.to_nat c,
d2 := n / 16,
d1 := n % 16
in hex_digit_to_string d2 ++ hex_digit_to_string d1
def char.quote_core (c : char) : string :=
if c = '\n' then "\\n"
else if c = '\t' then "\\t"
else if c = '\\' then "\\\\"
else if c = '\"' then "\\\""
else if char.to_nat c <= 31 then "\\x" ++ char_to_hex c
else c.to_string
instance : has_to_string char :=
⟨λ c, "'" ++ char.quote_core c ++ "'"⟩
def string.quote_aux : list char → string
| [] := ""
| (x::xs) := char.quote_core x ++ string.quote_aux xs
def string.quote (s : string) : string :=
if s.is_empty = tt then "\"\""
else "\"" ++ string.quote_aux s.to_list ++ "\""
instance : has_to_string string :=
⟨string.quote⟩
instance (n : nat) : has_to_string (fin n) :=
⟨λ f, to_string (fin.val f)⟩
instance : has_to_string unsigned :=
⟨λ n, to_string (fin.val n)⟩