lemma inj_of_char: ‹inj of_char› proof (rule injI) fix c d assume"of_char c = of_char d" thenhave"char_of (of_char c) = char_of (of_char d)" by simp thenshow"c = d" by simp qed
lemma of_char_eqI: ‹c = d›if‹of_char c = of_char d› using that inj_of_char by (simp add: inj_eq)
lemma of_char_eq_iff [simp]: ‹of_char c = of_char d ⟷ c = d› by (auto intro: of_char_eqI)
lemma of_char_of [simp]: ‹of_char (char_of a) = a mod 256› proof - have‹[0..🚫 = [0, Suc 0, 2, 3, 4, 5, 6, 7 :: nat]› by (simp add: upt_eq_Cons_conv) thenhave‹[bit a 0, bit a 1, bit a 2, bit a 3, bit a 4, bit a 5, bit a 6, bit a 7] = map (bit a) [0..🚫› by simp thenhave‹of_char (char_of a) = take_bit 8 a› by (simp only: char_of_def of_char_def char.sel horner_sum_bit_eq_take_bit) thenshow ?thesis by (simp add: take_bit_eq_mod) qed
lemma char_of_mod_256 [simp]: ‹char_of (n mod 256) = char_of n› by (rule of_char_eqI) simp
lemma of_char_mod_256 [simp]: ‹of_char c mod 256 = of_char c› proof - have‹of_char (char_of (of_char c)) mod 256 = of_char (char_of (of_char c))› by (simp only: of_char_of) simp thenshow ?thesis by simp qed
lemma char_of_quasi_inj [simp]: ‹char_of m = char_of n ⟷ m mod 256 = n mod 256› (is‹?P ⟷ ?Q›) proof assume ?Q thenshow ?P by (auto intro: of_char_eqI) next assume ?P thenhave‹of_char (char_of m) = of_char (char_of n)› by simp thenshow ?Q by simp qed
lemma char_of_eq_iff: ‹char_of n = c ⟷ take_bit 8 n = of_char c› by (auto intro: of_char_eqI simp add: take_bit_eq_mod)
lemma inj_on_char_of_nat [simp]: "inj_on char_of {0::nat..<256}" by (rule inj_onI) simp
lemma nat_of_char_less_256 [simp]: "of_char c < (256 :: nat)" proof - have"of_char c mod (256 :: nat) < 256" by arith thenshow ?thesis by simp qed
lemma range_nat_of_char: "range of_char = {0::nat..<256}" proof (rule; rule) fix n :: nat assume"n ∈ range of_char" thenshow"n ∈ {0..<256}" by auto next fix n :: nat assume"n ∈ {0..<256}" thenhave"n = of_char (char_of n)" by simp thenshow"n ∈ range of_char" by (rule range_eqI) qed
lemma UNIV_char_of_nat: "UNIV = char_of ` {0::nat..<256}" proof - have"range (of_char :: char ==> nat) = of_char ` char_of ` {0::nat..<256}" by (simp add: image_image range_nat_of_char) with inj_of_char [where ?'a = nat] show ?thesis by (simp add: inj_image_eq_iff) qed
subsection‹Strings as dedicated type for target language code generation›
subsubsection ‹Logical specification›
context begin
qualified definition ascii_of :: "char ==> char" where"ascii_of c = Char (digit0 c) (digit1 c) (digit2 c) (digit3 c) (digit4 c) (digit5 c) (digit6 c) False"
instance by (standard; transfer) (simp add: equal)
end
end
instantiation String.literal :: linorder begin
context begin
qualified lift_definition less_eq_literal :: "String.literal ==> String.literal ==>bool" is"ord.lexordp_eq (λc d. of_char c < (of_char d :: nat))"
.
qualified lift_definition less_literal :: "String.literal ==> String.literal ==> bool" is"ord.lexordp (λc d. of_char c < (of_char d :: nat))"
.
instanceproof - from linorder_char interpret linorder "ord.lexordp_eq (λc d. of_char c < (of_char d :: nat))" "ord.lexordp (λc d. of_char c < (of_char d :: nat)) :: string ==> string ==> bool" by (rule linorder.lexordp_linorder) show"PROP ?thesis" by (standard; transfer) (simp_all add: less_le_not_le linear) qed
end
end
lemma infinite_literal: "infinite (UNIV :: String.literal set)" proof -
define S where"S = range (λn. replicate n CHR ''A'')" have"inj_on String.implode S" proof (rule inj_onI) fix cs ds assume"String.implode cs = String.implode ds" thenhave"String.explode (String.implode cs) = String.explode (String.implode ds)" by simp moreoverassume"cs ∈ S"and"ds ∈ S" ultimatelyshow"cs = ds" by (auto simp add: S_def) qed moreoverhave"infinite S" by (auto simp add: S_def dest: finite_range_imageI [of _ length]) ultimatelyhave"infinite (String.implode ` S)" by (simp add: finite_image_iff) thenshow ?thesis by (auto intro: finite_subset) qed
lemma [code]: ‹Literal' b0 b1 b2 b3 b4 b5 b6 s = String.literal_of_asciis [foldr (λb k. of_bool b + k * 2) [b0, b1, b2, b3, b4, b5, b6] 0] + s› proof - have‹foldr (λb k. of_bool b + k * 2) [b0, b1, b2, b3, b4, b5, b6] 0 = of_char (Char b0 b1 b2 b3 b4 b5 b6 False)› by simp moreoverhave‹Literal' b0 b1 b2 b3 b4 b5 b6 s = String.literal_of_asciis [of_char (Char b0 b1 b2 b3 b4 b5 b6 False)] + s› by (unfold Literal'_def) (transfer, simp only: list.simps comp_apply char_of_char, simp) ultimatelyshow ?thesis by simp qed
lemma [code_computation_unfold]: "String.Literal = Literal'" by simp
end
code_reserved
(SML) string String Char Str_Literal and (OCaml) string String Char Str_Literal and (Haskell) Str_Literal and (Scala) String Str_Literal
code_identifier code_module String ⇀
(SML) Str and (OCaml) Str and (Haskell) Str and (Scala) Str
code_printing
type_constructor String.literal ⇀
(SML) "string" and (OCaml) "string" and (Haskell) "String" and (Scala) "String"
| constant "STR ''''"⇀
(SML) "\"\"" and (OCaml) "\"\"" and (Haskell) "\"\"" and (Scala) "\"\""
code_printing code_module"Str_Literal"⇀
(SML) ‹structure Str_Literal : sig type int = IntInf.int val literal_of_asciis : int list -> string val asciis_of_literal : string -> int list end = struct open IntInf; fun map f [] = [] | map f (x :: xs) = f x :: map f xs; (* deliberate clone not relying on List._ structure *)
fun check_ascii k = if 0 <= k andalso k < 128 then k
else raise Fail "Non-ASCII character in literal";
val char_of_ascii = Char.chr o toInt o (fn k => k mod 128);
val ascii_of_char = check_ascii o fromInt o Char.ord;
val literal_of_asciis = String.implode o map char_of_ascii;
val asciis_of_literal = map ascii_of_char o String.explode;
end;›for constant String.literal_of_asciis String.asciis_of_literal and (OCaml) ‹module Str_Literal : sig val literal_of_asciis : Z.t list -> string val asciis_of_literal: string -> Z.t list end = struct (* deliberate clones not relying on List._ module *)
let rec length xs = match xs with
[] -> 0
| x :: xs -> 1 + length xs;;
let rec nth xs n = match xs with
(x :: xs) -> if n <= 0 then x else nth xs (n - 1);;
let rec map_range f n = if n <= 0 then []
else let m = n - 1 in map_range f m @ [f m];;
let implode f xs =
String.init (length xs) (fun n -> f (nth xs n));;
let explode f s =
map_range (fun n -> f (String.get s n)) (String.length s);;
let z_128 = Z.of_int 128;;
let check_ascii k = if 0 <= k && k < 128 then k
else failwith "Non-ASCII character in literal";;
let char_of_ascii k = Char.chr (Z.to_int (Z.rem k z_128));;
let ascii_of_char c = Z.of_int (check_ascii (Char.code c));;
let literal_of_asciis ks = implode char_of_ascii ks;;
let asciis_of_literal s = explode ascii_of_char s;;
end;;›for constant String.literal_of_asciis String.asciis_of_literal and (Haskell) ‹module Str_Literal(literalOfAsciis, asciisOfLiteral) where check_ascii :: Int -> Int check_ascii k | (0 🚫k && k 🚫28) = k | otherwise = error "Non-ASCII character in literal" charOfAscii :: Integer -> Char charOfAscii = toEnum . Prelude.fromInteger . (\k -> k `mod ` 128) asciiOfChar :: Char -> Integer asciiOfChar = toInteger . check_ascii . fromEnum literalOfAsciis :: [Integer] -> [Char] literalOfAsciis = map charOfAscii asciisOfLiteral :: [Char] -> [Integer] asciisOfLiteral = map asciiOfChar › and (Scala) ‹object Str_Literal { private def checkAscii(k : Int) : Int = 0 🚫k && k 🚫28 match { case true => k case false => sys.error("Non-ASCII character in literal") } private def charOfAscii(k : BigInt) : Char = (k % 128).charValue private def asciiOfChar(c : Char) : BigInt = BigInt(checkAscii(c.toInt)) def literalOfAsciis(ks : List[BigInt]) : String = ks.map(charOfAscii).mkString def asciisOfLiteral(s : String) : List[BigInt] = s.toList.map(asciiOfChar) } ›
| constant ‹(+) :: String.literal ==> String.literal ==> String.literal›⇀
(SML) infixl 18 "^" and (OCaml) infixr 6 "^" and (Haskell) infixr 5 "++" and (Scala) infixl 7 "+"
| constant String.literal_of_asciis ⇀
(SML) "Str'_Literal.literal'_of'_asciis" and (OCaml) "Str'_Literal.literal'_of'_asciis" and (Haskell) "Str'_Literal.literalOfAsciis" and (Scala) "Str'_Literal.literalOfAsciis"
| constant String.asciis_of_literal ⇀
(SML) "Str'_Literal.asciis'_of'_literal" and (OCaml) "Str'_Literal.asciis'_of'_literal" and (Haskell) "Str'_Literal.asciisOfLiteral" and (Scala) "Str'_Literal.asciisOfLiteral"
| class_instance String.literal :: equal ⇀
(Haskell) -
| constant ‹HOL.equal :: String.literal ==> String.literal ==> bool›⇀
(SML) "!((_ : string) = _)" and (OCaml) "!((_ : string) = _)" and (Haskell) infix 4 "==" and (Scala) infixl 5 "=="
| constant ‹(≤) :: String.literal ==> String.literal ==> bool›⇀
(SML) "!((_ : string) <= _)" and (OCaml) "!((_ : string) <= _)" and (Haskell) infix 4 "<=" 🍋‹Order operations for 🍋‹String.literal› work in Haskell only if no type classinstance needs to be generated, because String = [Char] in Haskell and🍋‹char list› need not have the same order as 🍋‹String.literal›.› and (Scala) infixl 4 "<=" and (Eval) infixl 6 "<="
| constant "(<) :: String.literal ==> String.literal ==> bool"⇀
(SML) "!((_ : string) < _)" and (OCaml) "!((_ : string) < _)" and (Haskell) infix 4 "<" and (Scala) infixl 4 "<" and (Eval) infixl 6 "<"
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.