--
-- Version: @(#)lowlev.ada 1.1  Date: 5/30/84
--
-- Author:  Bryce Bardin
--          Ada Projects Section
--          Software Engineering Division
--          Ground Systems Group
--          Hughes Aircraft Company
--          Fullerton, CA
--
-- The following program tests length clauses in conjunction with
-- unchecked conversion.
--
-- Before running the test, No_Of_Bits must be set to the base 2 logarithm
-- of the successor of System.Max_Int, i.e., the total number of bits in
-- the largest integer type supported.
-- Note:  The place where this change is to be made is flagged by a
-- comment prefixed by "--!".
--
-- For a compiler to pass this test, it must obey the length clauses
-- and instantiate and use the unchecked conversions correctly.
-- The output will consist of Cases sets of three identical values.
-- If a conversion fails, the line will be flagged as an error.  A summary
-- error count and a "pass/fail" message will be output.
-- Ideally, an assembly listing should be provided which demonstrates
-- the efficiency of the compiled code.
--


with Text_Io;
use Text_Io;
with Unchecked_Conversion;
with System;
procedure Change_Types is

    --! Change this to Log2 (System.Max_Int + 1):
    No_Of_Bits : constant := 32;

    Cases : constant := 100;

    type Int is range 0 .. 2 ** No_Of_Bits - 1;
    for Int'Size use No_Of_Bits;

    --! Change this to System.Max_Int/(Cases - 1):
    Increment : constant Int := System.Max_Int / (Cases - 1);

    type Bit is (Off, On);
    for Bit use (Off => 0, On => 1);
    for Bit'Size use 1;

    subtype Bits is Positive range 1 .. No_Of_Bits;

    type Bit_String is array (Bits) of Bit;
    for Bit_String'Size use No_Of_Bits;

    I : Int;
    J : Int;
    B : Bit_String;
    Errors : Natural := 0;
    Column : constant := 16;

    package Int_Io is new Integer_Io (Int);
    use Int_Io;

    package Nat_Io is new Integer_Io (Natural);
    use Nat_Io;

    procedure Put (B : Bit_String) is
    begin
        Put ("2#");

        for N in Bits loop
            if B (N) = On then
                Put ("1");
            else
                Put ("0");
            end if;
        end loop;

        Put ("#");
    end Put;

    function To_Bit_String is new Unchecked_Conversion (Int, Bit_String);

    function To_Int is new Unchecked_Conversion (Bit_String, Int);

begin

    for N in 1 .. Cases loop

        I := Int (N - 1) * Increment;
        B := To_Bit_String (I);
        J := To_Int (B);

        if J /= I then
            Errors := Errors + 1;
            Put ("*** ERROR ***");
        end if;

        Set_Col (To => Column);
        Put ("I = ");
        Put (I, Base => 2);
        Put_Line (",");

        Set_Col (To => Column);
        Put ("B = ");
        Put (B);
        Put_Line (",");

        Set_Col (To => Column);
        Put ("J = ");
        Put (J, Base => 2);
        Put (".");
        New_Line (2);

    end loop;

    New_Line (2);

    if Errors > 0 then
        Put_Line ("*** TEST FAILED! ***");

        if Errors = 1 then
            Put_Line ("There was 1 error.");
        else
            Put ("There were ");
            Put (Errors, Width => 0);
            Put_Line (" errors.");
        end if;
    else
        Put_Line ("TEST PASSED!");
        Put_Line ("There were no errors.");
    end if;

end Change_Types;