-- Demonstrates declaring variables with ranges and defining subtypes

-- Why: Better demonstrates programmer intent
-- Why: errors are caught as early as possible (on assignment, not later use)
-- Why: Allows program properties to be proved (discuss  later)

with ada.integer_text_io; use ada.integer_text_io; 
procedure ranges_and_subtypes  is 
    i: Integer range -50 .. 100;    -- Other values not allowed

    subtype Tiny_Pos is Integer range 1 .. 5;

    subtype Non_Zero is Integer
      with Static_Predicate => Non_Zero /= 0;

    subtype Small_Primes is Integer
      with Static_Predicate => Small_Primes in 2 .. 3 | 5 | 7 | 11 | 13 | 17 | 19;

    subtype Small_Even is Integer range 0 .. 100
      with Dynamic_Predicate => Small_Even mod 2 = 0;

    s: Tiny_Pos;
    nz : Non_Zero;
begin
    s := 0;       -- Warning: Will cause constraint error at runtime

    get(i);       -- Error if outside range -50 .. 100
    get(s);       -- Error if outside range  3 .. 5
    get(nz);      -- Error if 0

    put(i);      
    put(s);      
    put(nz);      

    for i in Small_Primes loop
       put(i);
    end loop;

    -- for i in Small_Even loop  -- Type with Dynamic_Predicate not allowed

end ranges_and_subtypes;