-------------------------------------------------------------------------------
-- (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 (Sem)
procedure Plant_Constraining_Type
  (Expression_Type : in Dictionary.Symbol;
   String_Length   : in Maths.Value;
   Actual_Node     : in STree.SyntaxNode)
is
   -- This procedure is used to plant a type symbol in the syntax tree, at the location of
   -- an actual parameter, for use by the VCG.  IFF the Expression_Type is String
   -- (indicating that the actual parameter is a string literal) then the parameter String_Length
   -- is used to create (or obtain if it's already declared) a subtype of Positive called Positive__n
   -- where n is the string length; this implicitly-declared subtype is then used as the constraint.
   -- For anything other than a string literal actual parameter we
   -- plant the symbol of the constraining array subtype.  The array subtype effectively passes
   -- the symbols of /all/ the constraining indexes however many dimensions the array has.

   Type_To_Plant : Dictionary.Symbol := Dictionary.NullSymbol;
begin
   if Dictionary.IsUnconstrainedArrayType (Dictionary.GetRootType (Expression_Type))
     and then not Dictionary.IsUnconstrainedArrayType (Expression_Type) then
      -- Not a string, so plant the array type
      Type_To_Plant := Expression_Type;
   elsif Dictionary.IsPredefinedStringType (Expression_Type) and then String_Length /= Maths.NoValue then
      -- If the actual is a String Literal like "Hello World", then the Expression_Type
      -- will be Predefined String and String_Length will have a well-defined value.
      -- In this case, we create an implicit constraining subtype.
      Create_Implicit_Positive_Subtype
        (String_Length    => String_Length,
         Location         => Dictionary.Location'(Start_Position => Node_Position (Node => Actual_Node),
                                                  End_Position   => Node_Position (Node => Actual_Node)),
         Index_Constraint => Type_To_Plant);
   end if;
   STree.Add_Node_Symbol (Node => Actual_Node,
                          Sym  => Type_To_Plant);
end Plant_Constraining_Type;
