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) *)
(************************************************************************)
(************************************************************************)
Contributed by Laurent Théry (INRIA);
Adapted to Coq V8 by the Coq Development Team
Require Import Bool BinPos BinNat PeanoNat Nnat Coq.Strings.Byte.
Definition of ascii character as a 8 bits constructor
Inductive ascii : Set := Ascii (_ _ _ _ _ _ _ _ : bool). Declare Scope char_scope. Delimit Scope char_scope with char. Bind Scope char_scope with ascii. Definition zero := Ascii false false false false false false false false. Definition one := Ascii true false false false false false false false. Definition shift (c : bool) (a : ascii) := match a with | Ascii a1 a2 a3 a4 a5 a6 a7 a8 => Ascii c a1 a2 a3 a4 a5 a6 a7 end.
Definition of a decidable function that is effective
forall a b : ascii, {a = b} + {a <> b}decide equality; apply bool_dec. Defined. Local Open Scope lazy_bool_scope. Definition eqb (a b : ascii) : bool := match a, b with | Ascii a0 a1 a2 a3 a4 a5 a6 a7, Ascii b0 b1 b2 b3 b4 b5 b6 b7 => Bool.eqb a0 b0 &&& Bool.eqb a1 b1 &&& Bool.eqb a2 b2 &&& Bool.eqb a3 b3 &&& Bool.eqb a4 b4 &&& Bool.eqb a5 b5 &&& Bool.eqb a6 b6 &&& Bool.eqb a7 b7 end. Infix "=?" := eqb : char_scope.forall a b : ascii, {a = b} + {a <> b}a, b:asciireflect (a = b) (a =? b)%chara, b:asciireflect (a = b) (a =? b)%charb0, b1, b2, b3, b4, b5, b6, b7, b, b8, b9, b10, b11, b12, b13, b14:boolreflect (Ascii b0 b1 b2 b3 b4 b5 b6 b7 = Ascii b b8 b9 b10 b11 b12 b13 b14) (Bool.eqb b0 b &&& Bool.eqb b1 b8 &&& Bool.eqb b2 b9 &&& Bool.eqb b3 b10 &&& Bool.eqb b4 b11 &&& Bool.eqb b5 b12 &&& Bool.eqb b6 b13 &&& Bool.eqb b7 b14)now constructor. Qed. Ltac t_eqb := repeat first [ congruence | progress subst | apply conj | match goal with | [ |- context[eqb ?x ?y] ] => destruct (eqb_spec x y) end | intro ].b, b8, b9, b10, b11, b12, b13, b14:boolreflect (Ascii b b8 b9 b10 b11 b12 b13 b14 = Ascii b b8 b9 b10 b11 b12 b13 b14) truex:ascii(x =? x)%char = truet_eqb. Qed.x:ascii(x =? x)%char = truex, y:ascii(x =? y)%char = (y =? x)%chart_eqb. Qed.x, y:ascii(x =? y)%char = (y =? x)%charn, m:ascii(n =? m)%char = true <-> n = mt_eqb. Qed.n, m:ascii(n =? m)%char = true <-> n = mx, y:ascii(x =? y)%char = false <-> x <> yt_eqb. Qed.x, y:ascii(x =? y)%char = false <-> x <> yMorphisms.Proper (Morphisms.respectful eq (Morphisms.respectful eq eq)) eqbt_eqb. Qed.Morphisms.Proper (Morphisms.respectful eq (Morphisms.respectful eq eq)) eqb
Auxiliary function that turns a positive into an ascii by
looking at the last 8 bits, ie z mod 2^8
Definition ascii_of_pos : positive -> ascii :=
let loop := fix loop n p :=
match n with
| O => zero
| S n' =>
match p with
| xH => one
| xI p' => shift true (loop n' p')
| xO p' => shift false (loop n' p')
end
end
in loop 8.
Conversion from N to ascii
Definition ascii_of_N (n : N) :=
match n with
| N0 => zero
| Npos p => ascii_of_pos p
end.
Same for nat
Definition ascii_of_nat (a : nat) := ascii_of_N (N.of_nat a).
The opposite functions
Local Open Scope list_scope. Fixpoint N_of_digits (l:list bool) : N := match l with | nil => 0 | b :: l' => (if b then 1 else 0) + 2*(N_of_digits l') end%N. Definition N_of_ascii (a : ascii) : N := let (a0,a1,a2,a3,a4,a5,a6,a7) := a in N_of_digits (a0::a1::a2::a3::a4::a5::a6::a7::nil). Definition nat_of_ascii (a : ascii) : nat := N.to_nat (N_of_ascii a).
Proofs that we have indeed opposite function (below 256)
forall a : ascii, ascii_of_N (N_of_ascii a) = adestruct a as [[|][|][|][|][|][|][|][|]]; vm_compute; reflexivity. Qed.forall a : ascii, ascii_of_N (N_of_ascii a) = aforall n : N, (n < 256)%N -> N_of_ascii (ascii_of_N n) = nforall n : N, (n < 256)%N -> N_of_ascii (ascii_of_N n) = n(0 < 256)%N -> N_of_ascii (ascii_of_N 0) = 0%Np:positive(N.pos p < 256)%N -> N_of_ascii (ascii_of_N (N.pos p)) = N.pos pdo 8 (destruct p; [ | | intros; vm_compute; reflexivity ]); intro H; vm_compute in H; destruct p; discriminate. Qed.p:positive(N.pos p < 256)%N -> N_of_ascii (ascii_of_N (N.pos p)) = N.pos pforall a : ascii, (N_of_ascii a < 256)%Ndestruct a as [[|][|][|][|][|][|][|][|]]; vm_compute; reflexivity. Qed.forall a : ascii, (N_of_ascii a < 256)%Nforall a : ascii, ascii_of_nat (nat_of_ascii a) = adestruct a as [[|][|][|][|][|][|][|][|]]; compute; reflexivity. Qed.forall a : ascii, ascii_of_nat (nat_of_ascii a) = aforall n : nat, n < 256 -> nat_of_ascii (ascii_of_nat n) = nforall n : nat, n < 256 -> nat_of_ascii (ascii_of_nat n) = nn:natH:n < 256nat_of_ascii (ascii_of_nat n) = nn:natH:n < 256N.to_nat (N_of_ascii (ascii_of_N (N.of_nat n))) = nn:natH:n < 256N.to_nat (N.of_nat n) = nn:natH:n < 256(N.of_nat n < 256)%Nn:natH:n < 256(N.of_nat n < 256)%Nn:natH:n < 256(N.of_nat n ?= 256)%N = Ltn:natH:n < 256(N.of_nat n ?= N.of_nat 256)%N = Ltnow apply Nat.compare_lt_iff. Qed.n:natH:n < 256(n ?= 256) = Ltforall a : ascii, nat_of_ascii a < 256forall a : ascii, nat_of_ascii a < 256a:asciiN.to_nat (N_of_ascii a) < 256a:asciiN.to_nat (N_of_ascii a) < N.to_nat 256apply N_ascii_bounded. Qed.a:ascii(N_of_ascii a < 256)%N
Ascii characters can be represented in scope char_scope as follows:
For instance, both "065" and "A" denote the character `uppercase
A', and both "034" and """" denote the character `double quote'.
Notice that the ascii characters of code >= 128 do not denote
stand-alone utf8 characters so that only the notation "nnn" is
available for them (unless your terminal is able to represent them,
which is typically not the case in coqide).
- "c" represents itself if c is a character of code < 128,
- """" is an exception: it represents the ascii character 34 (double quote),
- "nnn" represents the ascii character of decimal code nnn.
Definition ascii_of_byte (b : byte) : ascii := let '(b0, (b1, (b2, (b3, (b4, (b5, (b6, b7))))))) := Byte.to_bits b in Ascii b0 b1 b2 b3 b4 b5 b6 b7. Definition byte_of_ascii (a : ascii) : byte := let (b0, b1, b2, b3, b4, b5, b6, b7) := a in Byte.of_bits (b0, (b1, (b2, (b3, (b4, (b5, (b6, b7))))))).x:asciiascii_of_byte (byte_of_ascii x) = xx:asciiascii_of_byte (byte_of_ascii x) = xdestruct x; rewrite to_bits_of_bits; reflexivity. Qed.x:ascii(let '(b0, (b1, (b2, (b3, (b4, (b5, (b6, b7))))))) := to_bits (let (b0, b1, b2, b3, b4, b5, b6, b7) := x in of_bits (b0, (b1, (b2, (b3, (b4, (b5, (b6, b7)))))))) in Ascii b0 b1 b2 b3 b4 b5 b6 b7) = xx:bytebyte_of_ascii (ascii_of_byte x) = xx:bytebyte_of_ascii (ascii_of_byte x) = xx:byte(let (b0, b1, b2, b3, b4, b5, b6, b7) := let '(b0, (b1, (b2, (b3, (b4, (b5, (b6, b7))))))) := to_bits x in Ascii b0 b1 b2 b3 b4 b5 b6 b7 in of_bits (b0, (b1, (b2, (b3, (b4, (b5, (b6, b7)))))))) = xrewrite of_bits_to_bits; reflexivity. Qed.x:byteof_bits (to_bits x) = xx:byteascii_of_byte x = ascii_of_N (to_N x)destruct x; reflexivity. Qed.x:byteascii_of_byte x = ascii_of_N (to_N x)x:byteascii_of_byte x = ascii_of_nat (to_nat x)destruct x; reflexivity. Qed.x:byteascii_of_byte x = ascii_of_nat (to_nat x)x:asciiSome (byte_of_ascii x) = of_N (N_of_ascii x)rewrite <- (ascii_of_byte_of_ascii x); destruct (byte_of_ascii x); reflexivity. Qed.x:asciiSome (byte_of_ascii x) = of_N (N_of_ascii x)x:asciiSome (byte_of_ascii x) = of_nat (nat_of_ascii x)rewrite <- (ascii_of_byte_of_ascii x); destruct (byte_of_ascii x); reflexivity. Qed. Module Export AsciiSyntax. String Notation ascii ascii_of_byte byte_of_ascii : char_scope. End AsciiSyntax. Local Open Scope char_scope. Example Space := " ". Example DoubleQuote := """". Example Beep := "007".x:asciiSome (byte_of_ascii x) = of_nat (nat_of_ascii x)