ada: Remove GNATcheck violations
[official-gcc.git] / gcc / ada / libgnat / s-vauspe.ads
blobb276eed510509769961b092fa8b712f4ce600c98
1 ------------------------------------------------------------------------------
2 -- --
3 -- GNAT COMPILER COMPONENTS --
4 -- --
5 -- S Y S T E M . V A L U E _ U _ S P E C --
6 -- --
7 -- S p e c --
8 -- --
9 -- Copyright (C) 2022-2023, Free Software Foundation, Inc. --
10 -- --
11 -- GNAT is free software; you can redistribute it and/or modify it under --
12 -- terms of the GNU General Public License as published by the Free Soft- --
13 -- ware Foundation; either version 3, or (at your option) any later ver- --
14 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
15 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
16 -- or FITNESS FOR A PARTICULAR PURPOSE. --
17 -- --
18 -- As a special exception under Section 7 of GPL version 3, you are granted --
19 -- additional permissions described in the GCC Runtime Library Exception, --
20 -- version 3.1, as published by the Free Software Foundation. --
21 -- --
22 -- You should have received a copy of the GNU General Public License and --
23 -- a copy of the GCC Runtime Library Exception along with this program; --
24 -- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
25 -- <http://www.gnu.org/licenses/>. --
26 -- --
27 -- GNAT was originally developed by the GNAT team at New York University. --
28 -- Extensive contributions were provided by Ada Core Technologies Inc. --
29 -- --
30 ------------------------------------------------------------------------------
32 -- This package contains the specification entities using for the formal
33 -- verification of the routines for scanning modular Unsigned values.
35 -- Preconditions in this unit are meant for analysis only, not for run-time
36 -- checking, so that the expected exceptions are raised. This is enforced by
37 -- setting the corresponding assertion policy to Ignore. Postconditions and
38 -- contract cases should not be executed at runtime as well, in order not to
39 -- slow down the execution of these functions.
41 pragma Assertion_Policy (Pre => Ignore,
42 Post => Ignore,
43 Contract_Cases => Ignore,
44 Ghost => Ignore,
45 Subprogram_Variant => Ignore);
47 with System.Val_Spec; use System.Val_Spec;
49 generic
51 type Uns is mod <>;
53 package System.Value_U_Spec with
54 Ghost,
55 SPARK_Mode,
56 Always_Terminates
58 pragma Preelaborate;
60 -- Maximum value of exponent for 10 that fits in Uns'Base
61 function Max_Log10 return Natural is
62 (case Uns'Base'Size is
63 when 8 => 2,
64 when 16 => 4,
65 when 32 => 9,
66 when 64 => 19,
67 when 128 => 38,
68 when others => raise Program_Error)
69 with Ghost;
71 pragma Annotate (Gnatcheck, Exempt_On, "Discriminated_Records",
72 "variant record only used in proof code");
73 type Uns_Option (Overflow : Boolean := False) is record
74 case Overflow is
75 when True =>
76 null;
77 when False =>
78 Value : Uns := 0;
79 end case;
80 end record;
81 pragma Annotate (Gnatcheck, Exempt_Off, "Discriminated_Records");
83 function Wrap_Option (Value : Uns) return Uns_Option is
84 (Overflow => False, Value => Value);
86 function Only_Decimal_Ghost
87 (Str : String;
88 From, To : Integer)
89 return Boolean
91 (for all J in From .. To => Str (J) in '0' .. '9')
92 with
93 Pre => From > To or else (From >= Str'First and then To <= Str'Last);
94 -- Ghost function that returns True if S has only decimal characters
95 -- from index From to index To.
97 function Only_Hexa_Ghost (Str : String; From, To : Integer) return Boolean
99 (for all J in From .. To =>
100 Str (J) in '0' .. '9' | 'a' .. 'f' | 'A' .. 'F' | '_')
101 with
102 Pre => From > To or else (From >= Str'First and then To <= Str'Last);
103 -- Ghost function that returns True if S has only hexadecimal characters
104 -- from index From to index To.
106 function Last_Hexa_Ghost (Str : String) return Positive
107 with
108 Pre => Str /= ""
109 and then Str (Str'First) in '0' .. '9' | 'a' .. 'f' | 'A' .. 'F',
110 Post => Last_Hexa_Ghost'Result in Str'Range
111 and then (if Last_Hexa_Ghost'Result < Str'Last then
112 Str (Last_Hexa_Ghost'Result + 1) not in
113 '0' .. '9' | 'a' .. 'f' | 'A' .. 'F' | '_')
114 and then Only_Hexa_Ghost (Str, Str'First, Last_Hexa_Ghost'Result);
115 -- Ghost function that returns the index of the last character in S that
116 -- is either an hexadecimal digit or an underscore, which necessarily
117 -- exists given the precondition on Str.
119 function Is_Based_Format_Ghost (Str : String) return Boolean
121 (Str /= ""
122 and then Str (Str'First) in '0' .. '9' | 'a' .. 'f' | 'A' .. 'F'
123 and then
124 (declare
125 L : constant Positive := Last_Hexa_Ghost (Str);
126 begin
127 Str (L) /= '_'
128 and then (for all J in Str'First .. L =>
129 (if Str (J) = '_' then Str (J + 1) /= '_'))));
130 -- Ghost function that determines if Str has the correct format for a
131 -- based number, consisting in a sequence of hexadecimal digits possibly
132 -- separated by single underscores. It may be followed by other characters.
134 function Hexa_To_Unsigned_Ghost (X : Character) return Uns is
135 (case X is
136 when '0' .. '9' => Character'Pos (X) - Character'Pos ('0'),
137 when 'a' .. 'f' => Character'Pos (X) - Character'Pos ('a') + 10,
138 when 'A' .. 'F' => Character'Pos (X) - Character'Pos ('A') + 10,
139 when others => raise Program_Error)
140 with
141 Pre => X in '0' .. '9' | 'a' .. 'f' | 'A' .. 'F';
142 -- Ghost function that computes the value corresponding to an hexadecimal
143 -- digit.
145 function Scan_Overflows_Ghost
146 (Digit : Uns;
147 Base : Uns;
148 Acc : Uns) return Boolean
150 (Digit >= Base
151 or else Acc > Uns'Last / Base
152 or else Uns'Last - Digit < Base * Acc);
153 -- Ghost function which returns True if Digit + Base * Acc overflows or
154 -- Digit is greater than Base, as this is used by the algorithm for the
155 -- test of overflow.
157 function Scan_Based_Number_Ghost
158 (Str : String;
159 From, To : Integer;
160 Base : Uns := 10;
161 Acc : Uns := 0) return Uns_Option
162 with
163 Subprogram_Variant => (Increases => From),
164 Pre => Str'Last /= Positive'Last
165 and then
166 (From > To or else (From >= Str'First and then To <= Str'Last))
167 and then Only_Hexa_Ghost (Str, From, To);
168 -- Ghost function that recursively computes the based number in Str,
169 -- assuming Acc has been scanned already and scanning continues at index
170 -- From.
172 -- Lemmas unfolding the recursive definition of Scan_Based_Number_Ghost
174 procedure Lemma_Scan_Based_Number_Ghost_Base
175 (Str : String;
176 From, To : Integer;
177 Base : Uns := 10;
178 Acc : Uns := 0)
179 with
180 Global => null,
181 Pre => Str'Last /= Positive'Last
182 and then
183 (From > To or else (From >= Str'First and then To <= Str'Last))
184 and then Only_Hexa_Ghost (Str, From, To),
185 Post =>
186 (if From > To
187 then Scan_Based_Number_Ghost (Str, From, To, Base, Acc) =
188 (Overflow => False, Value => Acc));
189 -- Base case: Scan_Based_Number_Ghost returns Acc if From is bigger than To
191 procedure Lemma_Scan_Based_Number_Ghost_Underscore
192 (Str : String;
193 From, To : Integer;
194 Base : Uns := 10;
195 Acc : Uns := 0)
196 with
197 Global => null,
198 Pre => Str'Last /= Positive'Last
199 and then
200 (From > To or else (From >= Str'First and then To <= Str'Last))
201 and then Only_Hexa_Ghost (Str, From, To),
202 Post =>
203 (if From <= To and then Str (From) = '_'
204 then Scan_Based_Number_Ghost (Str, From, To, Base, Acc) =
205 Scan_Based_Number_Ghost (Str, From + 1, To, Base, Acc));
206 -- Underscore case: underscores are ignored while scanning
208 procedure Lemma_Scan_Based_Number_Ghost_Overflow
209 (Str : String;
210 From, To : Integer;
211 Base : Uns := 10;
212 Acc : Uns := 0)
213 with
214 Global => null,
215 Pre => Str'Last /= Positive'Last
216 and then
217 (From > To or else (From >= Str'First and then To <= Str'Last))
218 and then Only_Hexa_Ghost (Str, From, To),
219 Post =>
220 (if From <= To
221 and then Str (From) /= '_'
222 and then Scan_Overflows_Ghost
223 (Hexa_To_Unsigned_Ghost (Str (From)), Base, Acc)
224 then Scan_Based_Number_Ghost (Str, From, To, Base, Acc) =
225 (Overflow => True));
226 -- Overflow case: scanning a digit which causes an overflow
228 procedure Lemma_Scan_Based_Number_Ghost_Step
229 (Str : String;
230 From, To : Integer;
231 Base : Uns := 10;
232 Acc : Uns := 0)
233 with
234 Global => null,
235 Pre => Str'Last /= Positive'Last
236 and then
237 (From > To or else (From >= Str'First and then To <= Str'Last))
238 and then Only_Hexa_Ghost (Str, From, To),
239 Post =>
240 (if From <= To
241 and then Str (From) /= '_'
242 and then not Scan_Overflows_Ghost
243 (Hexa_To_Unsigned_Ghost (Str (From)), Base, Acc)
244 then Scan_Based_Number_Ghost (Str, From, To, Base, Acc) =
245 Scan_Based_Number_Ghost
246 (Str, From + 1, To, Base,
247 Base * Acc + Hexa_To_Unsigned_Ghost (Str (From))));
248 -- Normal case: scanning a digit without overflows
250 function Exponent_Unsigned_Ghost
251 (Value : Uns;
252 Exp : Natural;
253 Base : Uns := 10) return Uns_Option
254 with
255 Subprogram_Variant => (Decreases => Exp);
256 -- Ghost function that recursively computes Value * Base ** Exp
258 -- Lemmas unfolding the recursive definition of Exponent_Unsigned_Ghost
260 procedure Lemma_Exponent_Unsigned_Ghost_Base
261 (Value : Uns;
262 Exp : Natural;
263 Base : Uns := 10)
264 with
265 Post =>
266 (if Exp = 0 or Value = 0
267 then Exponent_Unsigned_Ghost (Value, Exp, Base) =
268 (Overflow => False, Value => Value));
269 -- Base case: Exponent_Unsigned_Ghost returns 0 if Value or Exp is 0
271 procedure Lemma_Exponent_Unsigned_Ghost_Overflow
272 (Value : Uns;
273 Exp : Natural;
274 Base : Uns := 10)
275 with
276 Post =>
277 (if Exp /= 0
278 and then Value /= 0
279 and then Scan_Overflows_Ghost (0, Base, Value)
280 then Exponent_Unsigned_Ghost (Value, Exp, Base) = (Overflow => True));
281 -- Overflow case: the next multiplication overflows
283 procedure Lemma_Exponent_Unsigned_Ghost_Step
284 (Value : Uns;
285 Exp : Natural;
286 Base : Uns := 10)
287 with
288 Post =>
289 (if Exp /= 0
290 and then Value /= 0
291 and then not Scan_Overflows_Ghost (0, Base, Value)
292 then Exponent_Unsigned_Ghost (Value, Exp, Base) =
293 Exponent_Unsigned_Ghost (Value * Base, Exp - 1, Base));
294 -- Normal case: exponentiation without overflows
296 function Raw_Unsigned_Starts_As_Based_Ghost
297 (Str : String;
298 Last_Num_Init, To : Integer)
299 return Boolean
301 (Last_Num_Init < To - 1
302 and then Str (Last_Num_Init + 1) in '#' | ':'
303 and then Str (Last_Num_Init + 2) in
304 '0' .. '9' | 'a' .. 'f' | 'A' .. 'F')
305 with Ghost,
306 Pre => Last_Num_Init in Str'Range
307 and then To in Str'Range;
308 -- Return True if Str starts as a based number
310 function Raw_Unsigned_Is_Based_Ghost
311 (Str : String;
312 Last_Num_Init : Integer;
313 Last_Num_Based : Integer;
314 To : Integer)
315 return Boolean
317 (Raw_Unsigned_Starts_As_Based_Ghost (Str, Last_Num_Init, To)
318 and then Last_Num_Based < To
319 and then Str (Last_Num_Based + 1) = Str (Last_Num_Init + 1))
320 with Ghost,
321 Pre => Last_Num_Init in Str'Range
322 and then Last_Num_Based in Last_Num_Init .. Str'Last
323 and then To in Str'Range;
324 -- Return True if Str is a based number
326 function Is_Raw_Unsigned_Format_Ghost (Str : String) return Boolean is
327 (Is_Natural_Format_Ghost (Str)
328 and then
329 (declare
330 Last_Num_Init : constant Integer := Last_Number_Ghost (Str);
331 Starts_As_Based : constant Boolean :=
332 Raw_Unsigned_Starts_As_Based_Ghost (Str, Last_Num_Init, Str'Last);
333 Last_Num_Based : constant Integer :=
334 (if Starts_As_Based
335 then Last_Hexa_Ghost (Str (Last_Num_Init + 2 .. Str'Last))
336 else Last_Num_Init);
337 Is_Based : constant Boolean :=
338 Raw_Unsigned_Is_Based_Ghost
339 (Str, Last_Num_Init, Last_Num_Based, Str'Last);
340 First_Exp : constant Integer :=
341 (if Is_Based then Last_Num_Based + 2 else Last_Num_Init + 1);
342 begin
343 (if Starts_As_Based then
344 Is_Based_Format_Ghost (Str (Last_Num_Init + 2 .. Str'Last))
345 and then Last_Num_Based < Str'Last)
346 and then Is_Opt_Exponent_Format_Ghost
347 (Str (First_Exp .. Str'Last))))
348 with
349 Pre => Str'Last /= Positive'Last;
350 -- Ghost function that determines if Str has the correct format for an
351 -- unsigned number without a sign character.
352 -- It is a natural number in base 10, optionally followed by a based
353 -- number surrounded by delimiters # or :, optionally followed by an
354 -- exponent part.
356 type Split_Value_Ghost is record
357 Value : Uns;
358 Base : Uns;
359 Expon : Natural;
360 end record;
362 function Scan_Split_No_Overflow_Ghost
363 (Str : String;
364 From, To : Integer)
365 return Boolean
367 (declare
368 Last_Num_Init : constant Integer :=
369 Last_Number_Ghost (Str (From .. To));
370 Init_Val : constant Uns_Option :=
371 Scan_Based_Number_Ghost (Str, From, Last_Num_Init);
372 Starts_As_Based : constant Boolean :=
373 Raw_Unsigned_Starts_As_Based_Ghost (Str, Last_Num_Init, To);
374 Last_Num_Based : constant Integer :=
375 (if Starts_As_Based
376 then Last_Hexa_Ghost (Str (Last_Num_Init + 2 .. To))
377 else Last_Num_Init);
378 Based_Val : constant Uns_Option :=
379 (if Starts_As_Based and then not Init_Val.Overflow
380 then Scan_Based_Number_Ghost
381 (Str, Last_Num_Init + 2, Last_Num_Based, Init_Val.Value)
382 else Init_Val);
383 begin
384 not Init_Val.Overflow
385 and then
386 (Last_Num_Init >= To - 1
387 or else Str (Last_Num_Init + 1) not in '#' | ':'
388 or else Init_Val.Value in 2 .. 16)
389 and then
390 (not Starts_As_Based
391 or else not Based_Val.Overflow))
392 with
393 Pre => Str'Last /= Positive'Last
394 and then From in Str'Range
395 and then To in From .. Str'Last
396 and then Str (From) in '0' .. '9';
397 -- Ghost function that determines if an overflow might occur while scanning
398 -- the representation of an unsigned number. The computation overflows if
399 -- either:
400 -- * The computation of the decimal part overflows,
401 -- * The decimal part is followed by a valid delimiter for a based
402 -- part, and the number corresponding to the base is not a valid base,
403 -- or
404 -- * The computation of the based part overflows.
406 pragma Warnings (Off, "constant * is not referenced");
407 function Scan_Split_Value_Ghost
408 (Str : String;
409 From, To : Integer)
410 return Split_Value_Ghost
412 (declare
413 Last_Num_Init : constant Integer :=
414 Last_Number_Ghost (Str (From .. To));
415 Init_Val : constant Uns_Option :=
416 Scan_Based_Number_Ghost (Str, From, Last_Num_Init);
417 Starts_As_Based : constant Boolean :=
418 Raw_Unsigned_Starts_As_Based_Ghost (Str, Last_Num_Init, To);
419 Last_Num_Based : constant Integer :=
420 (if Starts_As_Based
421 then Last_Hexa_Ghost (Str (Last_Num_Init + 2 .. To))
422 else Last_Num_Init);
423 Is_Based : constant Boolean :=
424 Raw_Unsigned_Is_Based_Ghost (Str, Last_Num_Init, Last_Num_Based, To);
425 Based_Val : constant Uns_Option :=
426 (if Starts_As_Based and then not Init_Val.Overflow
427 then Scan_Based_Number_Ghost
428 (Str, Last_Num_Init + 2, Last_Num_Based, Init_Val.Value)
429 else Init_Val);
430 First_Exp : constant Integer :=
431 (if Is_Based then Last_Num_Based + 2 else Last_Num_Init + 1);
432 Expon : constant Natural :=
433 (if Starts_As_Exponent_Format_Ghost (Str (First_Exp .. To))
434 then Scan_Exponent_Ghost (Str (First_Exp .. To))
435 else 0);
436 Base : constant Uns :=
437 (if Is_Based then Init_Val.Value else 10);
438 Value : constant Uns :=
439 (if Is_Based then Based_Val.Value else Init_Val.Value);
440 begin
441 (Value => Value, Base => Base, Expon => Expon))
442 with
443 Pre => Str'Last /= Positive'Last
444 and then From in Str'Range
445 and then To in From .. Str'Last
446 and then Str (From) in '0' .. '9'
447 and then Scan_Split_No_Overflow_Ghost (Str, From, To);
448 -- Ghost function that scans an unsigned number without a sign character
449 -- and return a record containing the values scanned for its value, its
450 -- base, and its exponent.
451 pragma Warnings (On, "constant * is not referenced");
453 function Raw_Unsigned_No_Overflow_Ghost
454 (Str : String;
455 From, To : Integer)
456 return Boolean
458 (Scan_Split_No_Overflow_Ghost (Str, From, To)
459 and then
460 (declare
461 Val : constant Split_Value_Ghost := Scan_Split_Value_Ghost
462 (Str, From, To);
463 begin
464 not Exponent_Unsigned_Ghost
465 (Val.Value, Val.Expon, Val.Base).Overflow))
466 with
467 Pre => Str'Last /= Positive'Last
468 and then From in Str'Range
469 and then To in From .. Str'Last
470 and then Str (From) in '0' .. '9';
471 -- Ghost function that determines if the computation of the unsigned number
472 -- represented by Str will overflow. The computation overflows if either:
473 -- * The scan of the string overflows, or
474 -- * The computation of the exponentiation overflows.
476 function Scan_Raw_Unsigned_Ghost
477 (Str : String;
478 From, To : Integer)
479 return Uns
481 (declare
482 Val : constant Split_Value_Ghost := Scan_Split_Value_Ghost
483 (Str, From, To);
484 begin
485 Exponent_Unsigned_Ghost (Val.Value, Val.Expon, Val.Base).Value)
486 with
487 Pre => Str'Last /= Positive'Last
488 and then From in Str'Range
489 and then To in From .. Str'Last
490 and then Str (From) in '0' .. '9'
491 and then Raw_Unsigned_No_Overflow_Ghost (Str, From, To);
492 -- Ghost function that scans an unsigned number without a sign character
494 function Raw_Unsigned_Last_Ghost
495 (Str : String;
496 From, To : Integer)
497 return Positive
499 (declare
500 Last_Num_Init : constant Integer :=
501 Last_Number_Ghost (Str (From .. To));
502 Starts_As_Based : constant Boolean :=
503 Raw_Unsigned_Starts_As_Based_Ghost (Str, Last_Num_Init, To);
504 Last_Num_Based : constant Integer :=
505 (if Starts_As_Based
506 then Last_Hexa_Ghost (Str (Last_Num_Init + 2 .. To))
507 else Last_Num_Init);
508 Is_Based : constant Boolean :=
509 Raw_Unsigned_Is_Based_Ghost (Str, Last_Num_Init, Last_Num_Based, To);
510 First_Exp : constant Integer :=
511 (if Is_Based then Last_Num_Based + 2 else Last_Num_Init + 1);
512 begin
513 (if not Starts_As_Exponent_Format_Ghost (Str (First_Exp .. To))
514 then First_Exp
515 elsif Str (First_Exp + 1) in '-' | '+' then
516 Last_Number_Ghost (Str (First_Exp + 2 .. To)) + 1
517 else Last_Number_Ghost (Str (First_Exp + 1 .. To)) + 1))
518 with
519 Pre => Str'Last /= Positive'Last
520 and then From in Str'Range
521 and then To in From .. Str'Last
522 and then Str (From) in '0' .. '9',
523 Post => Raw_Unsigned_Last_Ghost'Result >= From;
524 -- Ghost function that returns the position of the cursor once an unsigned
525 -- number has been seen.
527 function Slide_To_1 (Str : String) return String
528 with
529 Post =>
530 Only_Space_Ghost (Str, Str'First, Str'Last) =
531 (for all J in Str'First .. Str'Last =>
532 Slide_To_1'Result (J - Str'First + 1) = ' ');
533 -- Slides Str so that it starts at 1
535 function Slide_If_Necessary (Str : String) return String is
536 (if Str'Last = Positive'Last then Slide_To_1 (Str) else Str);
537 -- If Str'Last = Positive'Last then slides Str so that it starts at 1
539 function Is_Unsigned_Ghost (Str : String) return Boolean is
540 (declare
541 Non_Blank : constant Positive := First_Non_Space_Ghost
542 (Str, Str'First, Str'Last);
543 Fst_Num : constant Positive :=
544 (if Str (Non_Blank) = '+' then Non_Blank + 1 else Non_Blank);
545 begin
546 Is_Raw_Unsigned_Format_Ghost (Str (Fst_Num .. Str'Last))
547 and then Raw_Unsigned_No_Overflow_Ghost (Str, Fst_Num, Str'Last)
548 and then Only_Space_Ghost
549 (Str, Raw_Unsigned_Last_Ghost (Str, Fst_Num, Str'Last), Str'Last))
550 with
551 Pre => not Only_Space_Ghost (Str, Str'First, Str'Last)
552 and then Str'Last /= Positive'Last;
553 -- Ghost function that determines if Str has the correct format for an
554 -- unsigned number, consisting in some blank characters, an optional
555 -- + sign, a raw unsigned number which does not overflow and then some
556 -- more blank characters.
558 function Is_Value_Unsigned_Ghost (Str : String; Val : Uns) return Boolean is
559 (declare
560 Non_Blank : constant Positive := First_Non_Space_Ghost
561 (Str, Str'First, Str'Last);
562 Fst_Num : constant Positive :=
563 (if Str (Non_Blank) = '+' then Non_Blank + 1 else Non_Blank);
564 begin
565 Val = Scan_Raw_Unsigned_Ghost (Str, Fst_Num, Str'Last))
566 with
567 Pre => not Only_Space_Ghost (Str, Str'First, Str'Last)
568 and then Str'Last /= Positive'Last
569 and then Is_Unsigned_Ghost (Str);
570 -- Ghost function that returns True if Val is the value corresponding to
571 -- the unsigned number represented by Str.
573 procedure Prove_Scan_Based_Number_Ghost_Eq
574 (Str1, Str2 : String;
575 From, To : Integer;
576 Base : Uns := 10;
577 Acc : Uns := 0)
578 with
579 Subprogram_Variant => (Increases => From),
580 Pre => Str1'Last /= Positive'Last
581 and then Str2'Last /= Positive'Last
582 and then
583 (From > To or else (From >= Str1'First and then To <= Str1'Last))
584 and then
585 (From > To or else (From >= Str2'First and then To <= Str2'Last))
586 and then Only_Hexa_Ghost (Str1, From, To)
587 and then (for all J in From .. To => Str1 (J) = Str2 (J)),
588 Post =>
589 Scan_Based_Number_Ghost (Str1, From, To, Base, Acc)
590 = Scan_Based_Number_Ghost (Str2, From, To, Base, Acc);
591 -- Scan_Based_Number_Ghost returns the same value on two slices which are
592 -- equal.
594 procedure Prove_Scan_Only_Decimal_Ghost
595 (Str : String;
596 Val : Uns)
597 with
598 Pre => Str'Last /= Positive'Last
599 and then Str'Length >= 2
600 and then Str (Str'First) = ' '
601 and then Only_Decimal_Ghost (Str, Str'First + 1, Str'Last)
602 and then Scan_Based_Number_Ghost (Str, Str'First + 1, Str'Last)
603 = Wrap_Option (Val),
604 Post => Is_Unsigned_Ghost (Slide_If_Necessary (Str))
605 and then
606 Is_Value_Unsigned_Ghost (Slide_If_Necessary (Str), Val);
607 -- Ghost lemma used in the proof of 'Image implementation, to prove that
608 -- the result of Value_Unsigned on a decimal string is the same as the
609 -- result of Scan_Based_Number_Ghost.
611 -- Bundle Uns type with other types, constants and subprograms used in
612 -- ghost code, so that this package can be instantiated once and used
613 -- multiple times as generic formal for a given Int type.
615 private
617 ----------------
618 -- Slide_To_1 --
619 ----------------
621 function Slide_To_1 (Str : String) return String is
622 (declare
623 Res : constant String (1 .. Str'Length) := Str;
624 begin
625 Res);
627 end System.Value_U_Spec;