-------------------------------------------------------------------------------
-- (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 Wf_Formal_Part
  (Node             : in STree.SyntaxNode;
   Current_Scope    : in Dictionary.Scopes;
   Subprog_Sym      : in Dictionary.Symbol;
   First_Occurrence : in Boolean;
   Context          : in Dictionary.Contexts)
is

   -- look up table: if First_Occurrence then we are dealing with Abstract spec else REfined
   type Which_Abstractions is array (Boolean) of Dictionary.Abstractions;
   Which_Abstraction : constant Which_Abstractions :=
     Which_Abstractions'(False => Dictionary.IsRefined,
                         True  => Dictionary.IsAbstract);

   It                        : STree.Iterator;
   Parameter_Count           : Natural;
   Parameter_List_Has_Errors : Boolean := False;
   Next_Node                 : STree.SyntaxNode;

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

   procedure Wf_Param
     (Node             : in     STree.SyntaxNode;
      Current_Scope    : in     Dictionary.Scopes;
      Subprog_Sym      : in     Dictionary.Symbol;
      First_Occurrence : in     Boolean;
      Context          : in     Dictionary.Contexts;
      Param_Count      : in out Natural;
      Errors_Found     : in out Boolean)
   --# global in     CommandLineData.Content;
   --#        in     ContextManager.Ops.Unit_Stack;
   --#        in     LexTokenManager.State;
   --#        in out Dictionary.Dict;
   --#        in out ErrorHandler.Error_Context;
   --#        in out SPARK_IO.File_Sys;
   --#        in out STree.Table;
   --# derives Dictionary.Dict,
   --#         Errors_Found               from *,
   --#                                         CommandLineData.Content,
   --#                                         Context,
   --#                                         ContextManager.Ops.Unit_Stack,
   --#                                         Current_Scope,
   --#                                         Dictionary.Dict,
   --#                                         First_Occurrence,
   --#                                         LexTokenManager.State,
   --#                                         Node,
   --#                                         Param_Count,
   --#                                         STree.Table,
   --#                                         Subprog_Sym &
   --#         ErrorHandler.Error_Context,
   --#         SPARK_IO.File_Sys          from CommandLineData.Content,
   --#                                         Context,
   --#                                         ContextManager.Ops.Unit_Stack,
   --#                                         Current_Scope,
   --#                                         Dictionary.Dict,
   --#                                         ErrorHandler.Error_Context,
   --#                                         First_Occurrence,
   --#                                         LexTokenManager.State,
   --#                                         Node,
   --#                                         Param_Count,
   --#                                         SPARK_IO.File_Sys,
   --#                                         STree.Table,
   --#                                         Subprog_Sym &
   --#         Param_Count,
   --#         STree.Table                from *,
   --#                                         CommandLineData.Content,
   --#                                         Context,
   --#                                         Current_Scope,
   --#                                         Dictionary.Dict,
   --#                                         LexTokenManager.State,
   --#                                         Node,
   --#                                         STree.Table;
   --# pre Syntax_Node_Type (Node, STree.Table) = SP_Symbols.parameter_specification;
   --# post STree.Table = STree.Table~;
      is separate;

begin -- Wf_Formal_Part
   Parameter_Count := 0;
   It              :=
     Find_First_Node (Node_Kind    => SP_Symbols.parameter_specification,
                      From_Root    => Node,
                      In_Direction => STree.Down);
   while not STree.IsNull (It) loop
      Next_Node := Get_Node (It => It);
      --# assert STree.Table = STree.Table~ and
      --#   Syntax_Node_Type (Next_Node, STree.Table) = SP_Symbols.parameter_specification and
      --#   Next_Node = Get_Node (It);
      Wf_Param
        (Node             => Next_Node,
         Current_Scope    => Current_Scope,
         Subprog_Sym      => Subprog_Sym,
         First_Occurrence => First_Occurrence,
         Context          => Context,
         Param_Count      => Parameter_Count,
         Errors_Found     => Parameter_List_Has_Errors);
      It := STree.NextNode (It);
   end loop;

   if Parameter_List_Has_Errors then
      Dictionary.SetSubprogramSignatureNotWellformed (Which_Abstraction (First_Occurrence), Subprog_Sym);
   end if;

   if not First_Occurrence and then Parameter_Count /= Dictionary.GetNumberOfSubprogramParameters (Subprog_Sym) then
      Dictionary.SetSubprogramSignatureNotWellformed (Dictionary.IsRefined, Subprog_Sym);
      ErrorHandler.Semantic_Error
        (Err_Num   => 152,
         Reference => ErrorHandler.No_Reference,
         Position  => Node_Position (Node => Node),
         Id_Str    => Dictionary.GetSimpleName (Subprog_Sym));
   end if;
end Wf_Formal_Part;
