1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
|
-- F732A00.A
--
-- Grant of Unlimited Rights
--
-- The Ada Conformity Assessment Authority (ACAA) holds unlimited
-- rights in the software and documentation contained herein. Unlimited
-- rights are the same as those granted by the U.S. Government for older
-- parts of the Ada Conformity Assessment Test Suite, and are defined
-- in DFAR 252.227-7013(a)(19). By making this public release, the ACAA
-- intends to confer upon all recipients unlimited rights equal to those
-- held by the ACAA. These rights include rights to use, duplicate,
-- release or disclose the released technical data and computer software
-- in whole or in part, in any manner and for any purpose whatsoever, and
-- to have or permit others to do so.
--
-- DISCLAIMER
--
-- ALL MATERIALS OR INFORMATION HEREIN RELEASED, MADE AVAILABLE OR
-- DISCLOSED ARE AS IS. THE ACAA MAKES NO EXPRESS OR IMPLIED
-- WARRANTY AS TO ANY MATTER WHATSOEVER, INCLUDING THE CONDITIONS OF THE
-- SOFTWARE, DOCUMENTATION OR OTHER INFORMATION RELEASED, MADE AVAILABLE
-- OR DISCLOSED, OR THE OWNERSHIP, MERCHANTABILITY, OR FITNESS FOR A
-- PARTICULAR PURPOSE OF SAID MATERIAL.
--
-- Notice
--
-- The ACAA has created and maintains the Ada Conformity Assessment Test
-- Suite for the purpose of conformity assessments conducted in accordance
-- with the International Standard ISO/IEC 18009 - Ada: Conformity
-- assessment of a language processor. This test suite should not be used
-- to make claims of conformance unless used in accordance with
-- ISO/IEC 18009 and any applicable ACAA procedures.
--*
--
-- FOUNDATION DESCRIPTION:
-- This foundation provides the basis for testing aspect Type_Invariant
-- on a private type.
--
-- Note that a default-initialized object of type Change_Constrained_Type
-- will always fail an invariant check. This is necessary to be able
-- to test 7.3.2(10/4).
--
-- This foundation is based on a package for generating "Diagrams" for
-- bellringing. The type invariant is that each bell occurs once and only
-- once.
--
-- CHANGE HISTORY:
-- 25 Dec 14 JAC Initial pre-release version.
-- 15 Jan 15 RLB Renamed and re-described as a foundation.
-- Redid so that all important types are
-- default-initialized consistently (nothing
-- uninitialized should matter).
-- 13 Mar 15 RLB Eliminated overlong lines.
-- 09 Apr 15 RLB Added types and operations to support checks
-- on parts of a type.
--
--!
package F732A00 is
pragma Assertion_Policy (Check);
No_Of_Bells : constant := 8;
type Bell_Range_Type is range 1 .. No_Of_Bells;
type Change_Constrained_Type is private
with
Type_Invariant => Each_Bell_Occurs_Once (Change_Constrained_Type) and
And_Only_Once (Change_Constrained_Type);
subtype Swappable_Bell_Range_Type is Bell_Range_Type range
1 .. No_Of_Bells - 1;
subtype Number_Of_Pairs_To_Swap_Type is Bell_Range_Type range 1 ..
No_Of_Bells / 2;
type Pairs_To_Swap_Type is array (Number_Of_Pairs_To_Swap_Type range <>) of
Swappable_Bell_Range_Type;
type Bells_To_Swap_Type
(Number_Of_Pairs_To_Swap : Number_Of_Pairs_To_Swap_Type) is record
Pairs_To_Swap : Pairs_To_Swap_Type (1 .. Number_Of_Pairs_To_Swap);
end record;
function Each_Bell_Occurs_Once (Change : Change_Constrained_Type) return
Boolean;
function And_Only_Once (Change : Change_Constrained_Type) return
Boolean;
function Rounds_With_Default_Initialisation return Change_Constrained_Type;
function Rounds return Change_Constrained_Type;
function Invalid_Change return Change_Constrained_Type;
procedure Hunt_For_One_Change
(Change : in out Change_Constrained_Type;
Tenor_Behind : in Boolean := True);
function At_Lead_End (Change : in Change_Constrained_Type) return Boolean;
procedure Grandsire_Change (Change : in out Change_Constrained_Type)
with
Pre => No_Of_Bells >= 5;
procedure Invalid_Grandsire_Change (Change : in out Change_Constrained_Type)
with
Pre => No_Of_Bells >= 5;
function Swaps_Dont_Overlap (Bells_To_Swap : in Bells_To_Swap_Type) return
Boolean;
procedure Swap_Places
(Change : in out Change_Constrained_Type;
Bells_To_Swap : in Bells_To_Swap_Type)
with
Pre => Swaps_Dont_Overlap (Bells_To_Swap);
type Concert_Type is array (Positive range <>) of Change_Constrained_Type;
-- A "concert" is a list of changes.
type Concert_Kind is (Null_Concert, OK_Len_3, OK_Len_6,
One_Invalid_Change_First_of_2, One_Invalid_Change_Last_of_3,
Four_Invalid_Changes);
function Get_Concert (Kind : in Concert_Kind) return Concert_Type;
type Alter_Kind is (Set_Invalid, Set_Valid);
procedure Alter_Concert_Part (Concert : in out Concert_Type;
Index : in Natural;
Kind : in Alter_Kind)
with Pre => Index in Concert'Range;
private
type Change_Constrained_Type is array (Bell_Range_Type) of Bell_Range_Type
with Default_Component_Value => Bell_Range_Type'First;
-- Note: Any default-initialized object will fail an invariant check,
-- no matter where it is used.
end F732A00;
package body F732A00 is
pragma Assertion_Policy (Check);
Change_Number : Natural := 0;
function Each_Bell_Occurs_Once (Change : Change_Constrained_Type) return
Boolean is
(for all Bell_Number in Bell_Range_Type =>
(for some Bell in Bell_Range_Type =>
Change (Bell) = Bell_Number
)
);
function And_Only_Once (Change : Change_Constrained_Type) return
Boolean is
(not
(for some Bell in Bell_Range_Type'First .. Bell_Range_Type'Last -1 =>
(for some Other_Bell in Bell + 1 .. Bell_Range_Type'Last =>
Change (Bell) = Change (Other_Bell)
)
)
);
function Rounds_With_Default_Initialisation
return Change_Constrained_Type is
-- Default initialisation checks the type invariant even within the
-- package, RM 7.3.2(10/3)
Change : Change_Constrained_Type;
begin
for Bell in Bell_Range_Type loop
Change (Bell) := Bell;
end loop;
return Change;
end Rounds_With_Default_Initialisation;
function Rounds return Change_Constrained_Type is
-- Can knowingly set to something that breaches the type invariant, but
-- can't use default initialisation as that still checks the type
-- invariant, RM 7.3.2(10/3) doesn't exclude within the package.
Change : Change_Constrained_Type := (others => Bell_Range_Type'First);
begin
for Bell in Bell_Range_Type loop
Change (Bell) := Bell;
end loop;
return Change;
end Rounds;
function Invalid_Change return Change_Constrained_Type is
-- Can knowingly set to something that breaches the type invariant
-- within the package.
Change : constant Change_Constrained_Type :=
(others => Bell_Range_Type'First);
begin
return Change;
end Invalid_Change;
procedure Swap_Bell_With_Following_Bell
(Change : in out Change_Constrained_Type;
Bell_To_Swap : in Swappable_Bell_Range_Type) is
Temp : Bell_Range_Type;
begin
Temp := Change (Bell_To_Swap);
Change (Bell_To_Swap) := Change (Bell_To_Swap + 1);
Change (Bell_To_Swap + 1) := Temp;
end Swap_Bell_With_Following_Bell;
procedure Hunt_For_One_Change
(Change : in out Change_Constrained_Type;
Tenor_Behind : in Boolean := True) is
Hunt_On_How_Many : constant Bell_Range_Type :=
(if Tenor_Behind then No_Of_Bells - 1 else No_Of_Bells);
begin
-- If Even Change_Number
if Change_Number mod 2 = 0 then
for Place in 1 .. Hunt_On_How_Many - 1 loop
-- If Odd Place
if Place mod 2 = 1 then
Swap_Bell_With_Following_Bell
(Change => Change,
Bell_To_Swap => Place);
end if;
end loop;
else -- Odd Change_Number
for Place in 1 .. Hunt_On_How_Many - 1 loop
-- If Even Place
if Place mod 2 = 0 then
Swap_Bell_With_Following_Bell
(Change => Change,
Bell_To_Swap => Place);
end if;
end loop;
end if;
Change_Number := Change_Number + 1;
end Hunt_For_One_Change;
function At_Lead_End (Change : in Change_Constrained_Type) return Boolean is
(Change (1) = 1);
procedure Grandsire_Change (Change : in out Change_Constrained_Type) is
begin
Swap_Bell_With_Following_Bell
(Change => Change,
Bell_To_Swap => 1);
for Place in Bell_Range_Type range 4 .. No_Of_Bells - 1 loop
if Place mod 2 = 0 then
Swap_Bell_With_Following_Bell
(Change => Change,
Bell_To_Swap => Place);
end if;
end loop;
Change_Number := Change_Number + 1;
end Grandsire_Change;
procedure Broken_Swap_Bell_With_Following_Bell
(Change : in out Change_Constrained_Type;
Bell_To_Swap : in Swappable_Bell_Range_Type) is
Temp : Bell_Range_Type;
begin
Temp := Change (Bell_To_Swap);
Change (Bell_To_Swap) := Change (Bell_To_Swap + 1);
-- Last line of swap missing.
end Broken_Swap_Bell_With_Following_Bell;
procedure Invalid_Grandsire_Change (
Change : in out Change_Constrained_Type) is
-- A routine that uses a buggy Swap routine to make a mess.
-- Note that the local broken swap does NOT check the invariant after
-- each call; if we cleaned up the mess before the end of this routine,
-- there would be no problem.
begin
Broken_Swap_Bell_With_Following_Bell
(Change => Change,
Bell_To_Swap => 1);
for Place in Bell_Range_Type range 4 .. No_Of_Bells - 1 loop
if Place mod 2 = 0 then
Broken_Swap_Bell_With_Following_Bell
(Change => Change,
Bell_To_Swap => Place);
end if;
end loop;
Change_Number := Change_Number + 1;
end Invalid_Grandsire_Change;
function Swaps_Dont_Overlap (Bells_To_Swap : in Bells_To_Swap_Type) return
Boolean is
(for all Pair_To_Swap in 1 .. Bells_To_Swap.Number_Of_Pairs_To_Swap - 1 =>
Bells_To_Swap.Pairs_To_Swap (Pair_To_Swap + 1) >=
Bells_To_Swap.Pairs_To_Swap (Pair_To_Swap) + 2
);
procedure Swap_Places
(Change : in out Change_Constrained_Type;
Bells_To_Swap : in Bells_To_Swap_Type) is
begin
for Pair_To_Swap in 1 .. Bells_To_Swap.Number_Of_Pairs_To_Swap loop
Swap_Bell_With_Following_Bell
(Change => Change,
Bell_To_Swap => Bells_To_Swap.Pairs_To_Swap (Pair_To_Swap));
end loop;
Change_Number := Change_Number + 1;
end Swap_Places;
function Get_Concert (Kind : in Concert_Kind) return Concert_Type is
begin
-- Careful: we can't call any public functions or procedures if they
-- might fail, as we're trying to check that the checks are made on
-- the result, not on the creation of the aggregates.
case Kind is
when Null_Concert =>
return N : Concert_Type (1 .. 0);
when OK_Len_3 =>
return O3 : Concert_Type (1 .. 3) := (others => Rounds);
when OK_Len_6 =>
return O6 : Concert_Type (1 .. 6) := (others => Rounds) do
Grandsire_Change (O6(4));
end return;
when One_Invalid_Change_First_of_2 =>
return OIF : Concert_Type (1 .. 2) := (Rounds, Rounds) do
-- We have to explicitly initialize this,
-- as default initialization is always checked.
OIF(1) := (others => Bell_Range_Type'First);
end return;
when One_Invalid_Change_Last_of_3 =>
return OIL : Concert_Type (1 .. 3) := (Rounds, Rounds, Rounds) do
-- We have to explicitly initialize this,
-- as default initialization is always checked.
OIL(3) := (others => Bell_Range_Type'Last);
end return;
when Four_Invalid_Changes =>
return FIC : Concert_Type (2 .. 5) := (others => (others => 2));
-- We have to explicitly initialize this,
-- as default initialization is always checked.
end case;
end Get_Concert;
procedure Alter_Concert_Part (Concert : in out Concert_Type;
Index : in Natural;
Kind : in Alter_Kind) is
begin
if Kind = Set_Invalid then
Concert(Index)(Bell_Range_Type'First) :=
Concert(Index)(Bell_Range_Type'Last);
else -- if Set_Valid
Grandsire_Change (Concert(Index));
end if;
end Alter_Concert_Part;
end F732A00;
|