-- Inputs a numbers in range 0 .. 999 and prints its reverse

-- Demonstrates 3 parameter modes: In, Out, and In Out

-- In mode parameters are used to send information into a procedure
-- Out mode parameters are used to send information back from a procedure
-- In Out mode parameters are used to send information both in to and back from a procedure
-- Default mode is In

pragma Ada_2012;  -- Make sure 2012 compiler is used.  Needed for expression functions.
with ada.text_io; use ada.text_io; 
with ada.integer_text_io; use ada.integer_text_io; 
procedure modes2  is 
    subtype Digit is Natural range 0 .. 9;
    subtype Small_Nat is Natural range 0 .. 999;

    function ones_dig(n: Small_Nat) return Digit is (n mod 10);
    function tens_dig(n: Small_Nat) return Digit is ((n / 10) mod 10);
    function hundreds_dig(n: Small_Nat) return Digit is (n / 100);

    -- Returns the digits of n1
    -- Has both In mode and Out mode parameters
    procedure find_digits(n: In Small_Nat; d1, d10, d100: Out Digit) is
    begin
        d1 := ones_dig(n);
        d10 := tens_dig(n);
        d100 := hundreds_dig(n);
    end find_digits;

    -- Reverses its parameter!
    -- Parameter is In Out mode!
    procedure reverse_it(n1: In Out Small_Nat) is
        d1, d10, d100: Digit;
    begin
        find_digits(n1, d1, d10, d100);
        n1 := 100 * d1 + 10 * d10 + d100;
    end reverse_it;

    s: Small_Nat;
begin
    get(s);

    put_line("Original number: " & s'img);

    reverse_it(s);    -- Reverse the number.  Modifies s!  Original value is lost!

    put_line("Reversed number: " & s'img);

exception
    when constraint_error => put_line("Value out of range");
    when others => put_line("Error occurred");
end modes2;

-- Input: 123
-- Output:
--|Original number:  123
--|Reversed number:  321