Built with Alectryon, running Coq+SerAPI v8.10.0+0.7.0. Coq sources are in this panel; goals and messages will appear in the other. Bubbles () indicate interactive fragments: hover for details, tap to reveal contents. Use Ctrl+↑ Ctrl+↓ to navigate, Ctrl+🖱️ to focus.
(************************************************************************) (* * The Coq Proof Assistant / The Coq Development Team *) (* v * INRIA, CNRS and contributors - Copyright 1999-2018 *) (* <O___,, * (see CREDITS file for the list of authors) *) (* \VV/ **************************************************************) (* // * This file is distributed under the terms of the *) (* * GNU Lesser General Public License Version 2.1 *) (* * (see LICENSE file for the text of the license) *) (************************************************************************) Require Import Decimal Ascii String.
Pretty straightforward, which is precisely the point of the
Decimal.int datatype. The only catch is Decimal.Nil : we could
choose to convert it as "" or as "0". In the first case, it is
awkward to consider "" (or "-") as a number, while in the second case
we don't have a perfect bijection. Since the second variant is implemented
thanks to the first one, we provide both.
Local Open Scope string_scope.
Parsing one char
Definition uint_of_char (a:ascii)(d:option uint) := match d with | None => None | Some d => match a with | "0" => Some (D0 d) | "1" => Some (D1 d) | "2" => Some (D2 d) | "3" => Some (D3 d) | "4" => Some (D4 d) | "5" => Some (D5 d) | "6" => Some (D6 d) | "7" => Some (D7 d) | "8" => Some (D8 d) | "9" => Some (D9 d) | _ => None end end%char.c:asciid, d':uintuint_of_char c (Some d) = Some d' -> c = "0"%char /\ d' = D0 d \/ c = "1"%char /\ d' = D1 d \/ c = "2"%char /\ d' = D2 d \/ c = "3"%char /\ d' = D3 d \/ c = "4"%char /\ d' = D4 d \/ c = "5"%char /\ d' = D5 d \/ c = "6"%char /\ d' = D6 d \/ c = "7"%char /\ d' = D7 d \/ c = "8"%char /\ d' = D8 d \/ c = "9"%char /\ d' = D9 ddestruct c as [[|] [|] [|] [|] [|] [|] [|] [|]]; intros [= <-]; intuition. Qed.c:asciid, d':uintuint_of_char c (Some d) = Some d' -> c = "0"%char /\ d' = D0 d \/ c = "1"%char /\ d' = D1 d \/ c = "2"%char /\ d' = D2 d \/ c = "3"%char /\ d' = D3 d \/ c = "4"%char /\ d' = D4 d \/ c = "5"%char /\ d' = D5 d \/ c = "6"%char /\ d' = D6 d \/ c = "7"%char /\ d' = D7 d \/ c = "8"%char /\ d' = D8 d \/ c = "9"%char /\ d' = D9 d
Decimal/String conversion where Nil is ""
Module NilEmpty. Fixpoint string_of_uint (d:uint) := match d with | Nil => EmptyString | D0 d => String "0" (string_of_uint d) | D1 d => String "1" (string_of_uint d) | D2 d => String "2" (string_of_uint d) | D3 d => String "3" (string_of_uint d) | D4 d => String "4" (string_of_uint d) | D5 d => String "5" (string_of_uint d) | D6 d => String "6" (string_of_uint d) | D7 d => String "7" (string_of_uint d) | D8 d => String "8" (string_of_uint d) | D9 d => String "9" (string_of_uint d) end. Fixpoint uint_of_string s := match s with | EmptyString => Some Nil | String a s => uint_of_char a (uint_of_string s) end. Definition string_of_int (d:int) := match d with | Pos d => string_of_uint d | Neg d => String "-" (string_of_uint d) end. Definition int_of_string s := match s with | EmptyString => Some (Pos Nil) | String a s' => if Ascii.eqb a "-" then option_map Neg (uint_of_string s') else option_map Pos (uint_of_string s) end. (* NB: For the moment whitespace between - and digits are not accepted. And in this variant [int_of_string "-" = Some (Neg Nil)]. Compute int_of_string "-123456890123456890123456890123456890". Compute string_of_int (-123456890123456890123456890123456890). *)
Corresponding proofs
d:uintuint_of_string (string_of_uint d) = Some dinduction d; simpl; rewrite ?IHd; simpl; auto. Qed.d:uintuint_of_string (string_of_uint d) = Some ds:stringd:uintuint_of_string s = Some d -> string_of_uint d = ss:stringd:uintuint_of_string s = Some d -> string_of_uint d = ss:stringforall d : uint, uint_of_string s = Some d -> string_of_uint d = sforall d : uint, Some Nil = Some d -> string_of_uint d = ""a:asciis:stringIHs:forall d : uint, uint_of_string s = Some d -> string_of_uint d = sforall d : uint, uint_of_char a (uint_of_string s) = Some d -> string_of_uint d = String a snow intros d [= <-].forall d : uint, Some Nil = Some d -> string_of_uint d = ""a:asciis:stringIHs:forall d : uint, uint_of_string s = Some d -> string_of_uint d = sforall d : uint, uint_of_char a (uint_of_string s) = Some d -> string_of_uint d = String a sa:asciis:stringIHs:forall d0 : uint, uint_of_string s = Some d0 -> string_of_uint d0 = sd:uintuint_of_char a (uint_of_string s) = Some d -> string_of_uint d = String a sa:asciis:stringu:uintIHs:forall d0 : uint, Some u = Some d0 -> string_of_uint d0 = sd:uintH:uint_of_char a (Some u) = Some dstring_of_uint d = String a sintuition subst; simpl; f_equal; auto. Qed.a:asciis:stringu:uintIHs:forall d0 : uint, Some u = Some d0 -> string_of_uint d0 = sd:uintH:a = "0"%char /\ d = D0 u \/ a = "1"%char /\ d = D1 u \/ a = "2"%char /\ d = D2 u \/ a = "3"%char /\ d = D3 u \/ a = "4"%char /\ d = D4 u \/ a = "5"%char /\ d = D5 u \/ a = "6"%char /\ d = D6 u \/ a = "7"%char /\ d = D7 u \/ a = "8"%char /\ d = D8 u \/ a = "9"%char /\ d = D9 ustring_of_uint d = String a sd:intint_of_string (string_of_int d) = Some dd:intint_of_string (string_of_int d) = Some dd:uintint_of_string (string_of_uint d) = Some (Pos d)d:uintoption_map Neg (uint_of_string (string_of_uint d)) = Some (Neg d)d:uintint_of_string (string_of_uint d) = Some (Pos d)d:uintmatch string_of_uint d with | "" => Some (Pos Nil) | String a s' => if (a =? "-")%char then option_map Neg (uint_of_string s') else option_map Pos (uint_of_string (string_of_uint d)) end = Some (Pos d)d:uintHd:string_of_uint d = ""Some (Pos Nil) = Some (Pos d)d:uinta:asciis:stringHd:string_of_uint d = String a s(if (a =? "-")%char then option_map Neg (uint_of_string s) else option_map Pos (uint_of_string (String a s))) = Some (Pos d)now destruct d.d:uintHd:string_of_uint d = ""Some (Pos Nil) = Some (Pos d)d:uinta:asciis:stringHd:string_of_uint d = String a s(if (a =? "-")%char then option_map Neg (uint_of_string s) else option_map Pos (uint_of_string (String a s))) = Some (Pos d)d:uinta:asciis:stringHd:string_of_uint d = String a sa = "-"%char -> option_map Neg (uint_of_string s) = Some (Pos d)d:uinta:asciis:stringHd:string_of_uint d = String a sa <> "-"%char -> option_map Pos (uint_of_string (String a s)) = Some (Pos d)d:uinta:asciis:stringHd:string_of_uint d = String a sa = "-"%char -> option_map Neg (uint_of_string s) = Some (Pos d)now destruct d.d:uints:stringHd:string_of_uint d = String "-" soption_map Neg (uint_of_string s) = Some (Pos d)rewrite <- Hd, usu; auto.d:uinta:asciis:stringHd:string_of_uint d = String a sa <> "-"%char -> option_map Pos (uint_of_string (String a s)) = Some (Pos d)rewrite usu; auto. Qed.d:uintoption_map Neg (uint_of_string (string_of_uint d)) = Some (Neg d)s:stringd:intint_of_string s = Some d -> string_of_int d = ss:stringd:intint_of_string s = Some d -> string_of_int d = sa:asciis:stringd:int(if (a =? "-")%char then option_map Neg (uint_of_string s) else option_map Pos (uint_of_char a (uint_of_string s))) = Some d -> string_of_int d = String a sa:asciis:stringd:inta = "-"%char -> option_map Neg (uint_of_string s) = Some d -> string_of_int d = String a sa:asciis:stringd:inta <> "-"%char -> option_map Pos (uint_of_char a (uint_of_string s)) = Some d -> string_of_int d = String a sa:asciis:stringd:inta = "-"%char -> option_map Neg (uint_of_string s) = Some d -> string_of_int d = String a ss:stringd:intoption_map Neg (uint_of_string s) = Some d -> string_of_int d = String "-" ss:stringu:uintHs:uint_of_string s = Some ustring_of_int (Neg u) = String "-" snow apply sus.s:stringu:uintHs:uint_of_string s = Some ustring_of_uint u = sa:asciis:stringd:inta <> "-"%char -> option_map Pos (uint_of_char a (uint_of_string s)) = Some d -> string_of_int d = String a sa:asciis:stringd:uinta <> "-"%char -> option_map Pos (uint_of_char a (uint_of_string s)) = Some (Pos d) -> string_of_int (Pos d) = String a sa:asciis:stringd:uinta <> "-"%char -> option_map Pos (uint_of_char a (uint_of_string s)) = Some (Pos d) -> string_of_uint d = String a sa:asciis:stringd:uintn:a <> "-"%charH:option_map Pos (uint_of_char a (uint_of_string s)) = Some (Pos d)string_of_uint d = String a sdestruct uint_of_char; simpl in *; congruence. Qed. End NilEmpty.a:asciis:stringd:uintn:a <> "-"%charH:option_map Pos (uint_of_char a (uint_of_string s)) = Some (Pos d)uint_of_char a (uint_of_string s) = Some d
Decimal/String conversions where Nil is "0"
Module NilZero. Definition string_of_uint (d:uint) := match d with | Nil => "0" | _ => NilEmpty.string_of_uint d end. Definition uint_of_string s := match s with | EmptyString => None | _ => NilEmpty.uint_of_string s end. Definition string_of_int (d:int) := match d with | Pos d => string_of_uint d | Neg d => String "-" (string_of_uint d) end. Definition int_of_string s := match s with | EmptyString => None | String a s' => if Ascii.eqb a "-" then option_map Neg (uint_of_string s') else option_map Pos (uint_of_string s) end.
Corresponding proofs
s:stringuint_of_string s <> Some Nils:stringuint_of_string s <> Some NilNone <> Some Nila:asciis:stringuint_of_char a (NilEmpty.uint_of_string s) <> Some Nileasy.None <> Some Nila:asciis:stringuint_of_char a (NilEmpty.uint_of_string s) <> Some Nila:asciis:stringu:uintH:uint_of_char a (Some u) = Some NilFalsenow intuition subst. Qed.a:asciis:stringu:uintH:a = "0"%char /\ Nil = D0 u \/ a = "1"%char /\ Nil = D1 u \/ a = "2"%char /\ Nil = D2 u \/ a = "3"%char /\ Nil = D3 u \/ a = "4"%char /\ Nil = D4 u \/ a = "5"%char /\ Nil = D5 u \/ a = "6"%char /\ Nil = D6 u \/ a = "7"%char /\ Nil = D7 u \/ a = "8"%char /\ Nil = D8 u \/ a = "9"%char /\ Nil = D9 uFalses:stringd:uintuint_of_string s = Some d -> string_of_uint d = ss:stringd:uintuint_of_string s = Some d -> string_of_uint d = sa:asciis:stringd:uintH:uint_of_string (String a s) = Some dstring_of_uint d = String a snow destruct d. Qed.a:asciis:stringd:uintH:NilEmpty.string_of_uint d = String a sstring_of_uint d = String a sd:uintd <> Nil -> uint_of_string (string_of_uint d) = Some ddestruct d; (now destruct 1) || (intros _; apply NilEmpty.usu). Qed.d:uintd <> Nil -> uint_of_string (string_of_uint d) = Some duint_of_string (string_of_uint Nil) = Some 0%uintreflexivity. Qed.uint_of_string (string_of_uint Nil) = Some 0%uintd:uintuint_of_string (string_of_uint d) = Some d \/ uint_of_string (string_of_uint d) = Some 0%uintdestruct d; (now right) || (left; now apply usu). Qed.d:uintuint_of_string (string_of_uint d) = Some d \/ uint_of_string (string_of_uint d) = Some 0%uintd:intd <> Pos Nil -> d <> Neg Nil -> int_of_string (string_of_int d) = Some dd:intd <> Pos Nil -> d <> Neg Nil -> int_of_string (string_of_int d) = Some dd:uintPos d <> Pos Nil -> Pos d <> Neg Nil -> int_of_string (string_of_uint d) = Some (Pos d)d:uintNeg d <> Pos Nil -> Neg d <> Neg Nil -> option_map Neg (uint_of_string (string_of_uint d)) = Some (Neg d)d:uintPos d <> Pos Nil -> Pos d <> Neg Nil -> int_of_string (string_of_uint d) = Some (Pos d)d:uintH:Pos d <> Pos Nilint_of_string (string_of_uint d) = Some (Pos d)d:uintH:Pos d <> Pos Nilmatch string_of_uint d with | "" => None | String a s' => if (a =? "-")%char then option_map Neg (uint_of_string s') else option_map Pos (uint_of_string (string_of_uint d)) end = Some (Pos d)d:uintH:Pos d <> Pos NilHd:string_of_uint d = ""None = Some (Pos d)d:uintH:Pos d <> Pos Nila:asciis:stringHd:string_of_uint d = String a s(if (a =? "-")%char then option_map Neg (uint_of_string s) else option_map Pos (uint_of_string (String a s))) = Some (Pos d)now destruct d.d:uintH:Pos d <> Pos NilHd:string_of_uint d = ""None = Some (Pos d)d:uintH:Pos d <> Pos Nila:asciis:stringHd:string_of_uint d = String a s(if (a =? "-")%char then option_map Neg (uint_of_string s) else option_map Pos (uint_of_string (String a s))) = Some (Pos d)d:uintH:Pos d <> Pos Nila:asciis:stringHd:string_of_uint d = String a sa = "-"%char -> option_map Neg (uint_of_string s) = Some (Pos d)d:uintH:Pos d <> Pos Nila:asciis:stringHd:string_of_uint d = String a sa <> "-"%char -> option_map Pos (uint_of_string (String a s)) = Some (Pos d)d:uintH:Pos d <> Pos Nila:asciis:stringHd:string_of_uint d = String a sa = "-"%char -> option_map Neg (uint_of_string s) = Some (Pos d)now destruct d.d:uintH:Pos d <> Pos Nils:stringHd:string_of_uint d = String "-" soption_map Neg (uint_of_string s) = Some (Pos d)d:uintH:Pos d <> Pos Nila:asciis:stringHd:string_of_uint d = String a sa <> "-"%char -> option_map Pos (uint_of_string (String a s)) = Some (Pos d)now intros ->.d:uintH:Pos d <> Pos Nila:asciis:stringHd:string_of_uint d = String a sd <> Nild:uintNeg d <> Pos Nil -> Neg d <> Neg Nil -> option_map Neg (uint_of_string (string_of_uint d)) = Some (Neg d)d:uintH:Neg d <> Neg Niloption_map Neg (uint_of_string (string_of_uint d)) = Some (Neg d)now intros ->. Qed.d:uintH:Neg d <> Neg Nild <> Nilint_of_string (string_of_int (Pos Nil)) = Some 0%intreflexivity. Qed.int_of_string (string_of_int (Pos Nil)) = Some 0%int
Warning! (-0) won't parse (compatibility with the behavior of Z).
int_of_string (string_of_int (Neg Nil)) = Some (-0)%intreflexivity. Qed.int_of_string (string_of_int (Neg Nil)) = Some (-0)%ints:stringd:intint_of_string s = Some d -> string_of_int d = ss:stringd:intint_of_string s = Some d -> string_of_int d = sa:asciis:stringd:int(if (a =? "-")%char then option_map Neg (uint_of_string s) else option_map Pos (uint_of_char a (NilEmpty.uint_of_string s))) = Some d -> string_of_int d = String a sa:asciis:stringd:inta = "-"%char -> option_map Neg (uint_of_string s) = Some d -> string_of_int d = String a sa:asciis:stringd:inta <> "-"%char -> option_map Pos (uint_of_char a (NilEmpty.uint_of_string s)) = Some d -> string_of_int d = String a sa:asciis:stringd:inta = "-"%char -> option_map Neg (uint_of_string s) = Some d -> string_of_int d = String a ss:stringd:intoption_map Neg (uint_of_string s) = Some d -> string_of_int d = String "-" ss:stringu:uintHs:uint_of_string s = Some ustring_of_int (Neg u) = String "-" snow apply sus.s:stringu:uintHs:uint_of_string s = Some ustring_of_uint u = sa:asciis:stringd:inta <> "-"%char -> option_map Pos (uint_of_char a (NilEmpty.uint_of_string s)) = Some d -> string_of_int d = String a sa:asciis:stringd:uinta <> "-"%char -> option_map Pos (uint_of_char a (NilEmpty.uint_of_string s)) = Some (Pos d) -> string_of_int (Pos d) = String a sa:asciis:stringd:uinta <> "-"%char -> option_map Pos (uint_of_char a (NilEmpty.uint_of_string s)) = Some (Pos d) -> string_of_uint d = String a sa:asciis:stringd:uintn:a <> "-"%charH:option_map Pos (uint_of_char a (NilEmpty.uint_of_string s)) = Some (Pos d)string_of_uint d = String a sdestruct uint_of_char; simpl in *; congruence. Qed. End NilZero.a:asciis:stringd:uintn:a <> "-"%charH:option_map Pos (uint_of_char a (NilEmpty.uint_of_string s)) = Some (Pos d)uint_of_char a (NilEmpty.uint_of_string s) = Some d