-------------------------------------------------------------------------------
-- (C) Altran Praxis Limited
-------------------------------------------------------------------------------
--
-- The SPARK toolset is free software; you can redistribute it and/or modify it
-- under terms of the GNU General Public License as published by the Free
-- Software Foundation; either version 3, or (at your option) any later
-- version. The SPARK toolset is distributed in the hope that it will be
-- useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
-- Public License for more details. You should have received a copy of the GNU
-- General Public License distributed with the SPARK toolset; see file
-- COPYING3. If not, go to http://www.gnu.org/licenses for a complete copy of
-- the license.
--
--=============================================================================

separate (Maths)
function ValueToString (Num : Value) return E_Strings.T is
   OutBuffer : E_Strings.T;

   ---------------------------------------------------------

   procedure WriteChar (Ch : in Character)
   --# global in out OutBuffer;
   --# derives OutBuffer from *,
   --#                        Ch;
   is
   begin
      E_Strings.Append_Char (E_Str => OutBuffer,
                             Ch    => Ch);
   end WriteChar;

   ---------------------------------------------------------

   procedure DoSign
   --# global in     Num;
   --#        in out OutBuffer;
   --# derives OutBuffer from *,
   --#                        Num;
   is
   begin
      if not Num.IsPositive then
         WriteChar ('-');
      end if;
   end DoSign;

   ---------------------------------------------------------

   procedure PartToString (P   : in     Part;
                           Str :    out E_Strings.T)
   --# derives Str from P;
   is
      Hi : Natural;
   begin
      Str := E_Strings.Empty_String;
      Hi  := P.Length;
      for I in Natural range 1 .. Hi loop
         E_Strings.Append_Char (E_Str => Str,
                                Ch    => DigitToChar (P.Numerals ((Hi - I) + 1)));
      end loop;
   end PartToString;

   ----------------------------------------------

   procedure IntegerToString
   --# global in     Num;
   --#        in out OutBuffer;
   --# derives OutBuffer from *,
   --#                        Num;
   is
      ItemBuffer : E_Strings.T;
   begin
      DoSign;
      PartToString (Num.Numerator, ItemBuffer);
      E_Strings.Append_Examiner_String (E_Str1 => OutBuffer,
                                        E_Str2 => ItemBuffer);
   end IntegerToString;

   ----------------------------------------------

   procedure RealToString
   --# global in     Num;
   --#        in out OutBuffer;
   --# derives OutBuffer from *,
   --#                        Num;
   is
      ItemBuffer : E_Strings.T;
      IsRational : Boolean;
   begin
      IsRational := not (Num.Denominator = OnePart);
      if IsRational then
         WriteChar ('(');
      end if;
      DoSign;
      PartToString (Num.Numerator, ItemBuffer);
      E_Strings.Append_Examiner_String (E_Str1 => OutBuffer,
                                        E_Str2 => ItemBuffer);
      if IsRational then
         WriteChar ('/');
         PartToString (Num.Denominator, ItemBuffer);
         E_Strings.Append_Examiner_String (E_Str1 => OutBuffer,
                                           E_Str2 => ItemBuffer);
         WriteChar (')');
      end if;
   end RealToString;

   ----------------------------------------------

begin --ValueToString
   if Num.Sort = UnknownValue then
      OutBuffer := E_Strings.Copy_String (Str => "unknown value");
   elsif Num.Sort = TruthValue then
      if Num = FalseValue then
         OutBuffer := E_Strings.Copy_String (Str => "false");
      else
         OutBuffer := E_Strings.Copy_String (Str => "true");
      end if;
   else
      OutBuffer := E_Strings.Empty_String;
      if Num.Sort = IntegerValue then
         IntegerToString;
      else  --its a real
         RealToString;
      end if;
   end if;
   return OutBuffer;
end ValueToString;
