-------------------------------------------------------------------------------
-- (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.
--
--=============================================================================

with SPARK_IO;

separate (Sem.Walk_Expression_P)
procedure Down_Wf_Name_Argument_List
  (Node       : in     STree.SyntaxNode;
   Scope      : in     Dictionary.Scopes;
   E_Stack    : in out Exp_Stack.Exp_Stack_Type;
   Heap_Param : in out Lists.List_Heap;
   Next_Node  :    out STree.SyntaxNode)
is
   Type_Info          : Sem.Exp_Record;
   Ptr                : Lists.List;
   Child, Child_Child : STree.SyntaxNode;
begin
   Exp_Stack.Pop (Item  => Type_Info,
                  Stack => E_Stack);
   case Type_Info.Sort is
      when Sem.Is_Unknown =>
         Type_Info := Unknown_Symbol_Record;
         Next_Node := STree.NullNode;
      when Sem.Is_Type_Mark =>
         Child := STree.Child_Node (Current_Node => Node);
         -- ASSUME Child = named_argument_association            OR positional_argument_association OR
         --                annotation_named_argument_association OR annotation_positional_argument_association
         if STree.Syntax_Node_Type (Node => Child) = SP_Symbols.positional_argument_association
           or else STree.Syntax_Node_Type (Node => Child) = SP_Symbols.annotation_positional_argument_association then
            -- ASSUME Child = positional_argument_association OR annotation_positional_argument_association
            Child_Child := STree.Child_Node (Current_Node => Child);
            -- ASSUME Child_Child = positional_argument_association            OR expression OR
            --                      annotation_positional_argument_association OR annotation_expression
            if STree.Syntax_Node_Type (Node => Child_Child) = SP_Symbols.expression
              or else STree.Syntax_Node_Type (Node => Child_Child) = SP_Symbols.annotation_expression then
               -- ASSUME Child_Child = expression OR annotation_expression
               Next_Node := Child;
            elsif STree.Syntax_Node_Type (Node => Child_Child) = SP_Symbols.positional_argument_association
              or else STree.Syntax_Node_Type (Node => Child_Child) = SP_Symbols.annotation_positional_argument_association then
               -- ASSUME Child_Child = positional_argument_association OR annotation_positional_argument_association
               Type_Info := Unknown_Symbol_Record;
               ErrorHandler.Semantic_Error
                 (Err_Num   => 32,
                  Reference => ErrorHandler.No_Reference,
                  Position  => STree.Node_Position (Node => STree.Parent_Node (Current_Node => Node)),
                  Id_Str    => LexTokenManager.Null_String);
               Next_Node := STree.NullNode;
            else
               Next_Node := STree.NullNode;
               SystemErrors.Fatal_Error
                 (Sys_Err => SystemErrors.Invalid_Syntax_Tree,
                  Msg     => "Expect Child_Child = positional_argument_association OR expression OR " &
                    "annotation_positional_argument_association OR annotation_expression in Down_Wf_Name_Argument_List");
            end if;
         elsif STree.Syntax_Node_Type (Node => Child) = SP_Symbols.named_argument_association
           or else STree.Syntax_Node_Type (Node => Child) = SP_Symbols.annotation_named_argument_association then
            -- ASSUME Child = named_argument_association OR annotation_named_argument_association
            Type_Info := Unknown_Symbol_Record;
            ErrorHandler.Semantic_Error
              (Err_Num   => 32,
               Reference => ErrorHandler.No_Reference,
               Position  => STree.Node_Position (Node => STree.Parent_Node (Current_Node => Node)),
               Id_Str    => LexTokenManager.Null_String);
            Next_Node := STree.NullNode;
         else
            Next_Node := STree.NullNode;
            SystemErrors.Fatal_Error
              (Sys_Err => SystemErrors.Invalid_Syntax_Tree,
               Msg     => "Expect Child = named_argument_association OR positional_argument_association OR " &
                 "annotation_named_argument_association OR annotation_positional_argument_association " &
                 "in Down_Wf_Name_Argument_List");
         end if;
      when Sem.Is_Function =>
         Child := STree.Child_Node (Current_Node => Node);
         -- ASSUME Child = named_argument_association            OR positional_argument_association OR
         --                annotation_named_argument_association OR annotation_positional_argument_association
         if STree.Syntax_Node_Type (Node => Child) = SP_Symbols.positional_argument_association
           or else STree.Syntax_Node_Type (Node => Child) = SP_Symbols.annotation_positional_argument_association then
            -- ASSUME Child = positional_argument_association OR annotation_positional_argument_association
            Type_Info.Param_Count := 0;
         elsif STree.Syntax_Node_Type (Node => Child) = SP_Symbols.named_argument_association
           or else STree.Syntax_Node_Type (Node => Child) = SP_Symbols.annotation_named_argument_association then
            -- ASSUME Child = named_argument_association OR annotation_named_argument_association
            Create_Name_List (List       => Ptr,
                              Heap_Param => Heap_Param);
            Type_Info.Param_List := Ptr;
         else
            SystemErrors.Fatal_Error
              (Sys_Err => SystemErrors.Invalid_Syntax_Tree,
               Msg     => "Expect Child = named_argument_association OR positional_argument_association OR " &
                 "annotation_named_argument_association OR annotation_positional_argument_association " &
                 "in Down_Wf_Name_Argument_List");
         end if;
         if STree.Syntax_Node_Type (Node => Node) = SP_Symbols.name_argument_list then
            Type_Info.Arg_List_Found := True;
         end if;
         Next_Node := Child;
      when Sem.Is_Object =>
         if Dictionary.IsArrayTypeMark (Type_Info.Type_Symbol, Scope) then
            Child := STree.Child_Node (Current_Node => Node);
            -- ASSUME Child = named_argument_association            OR positional_argument_association OR
            --                annotation_named_argument_association OR annotation_positional_argument_association
            if STree.Syntax_Node_Type (Node => Child) = SP_Symbols.positional_argument_association
              or else STree.Syntax_Node_Type (Node => Child) = SP_Symbols.annotation_positional_argument_association then
               -- ASSUME Child = positional_argument_association OR annotation_positional_argument_association
               Type_Info.Param_Count := 0;
               Type_Info.Is_Static   := False;
               if STree.Syntax_Node_Type (Node => Node) = SP_Symbols.name_argument_list then
                  Type_Info.Arg_List_Found := True;
               end if;
               Next_Node := Child;
            elsif STree.Syntax_Node_Type (Node => Child) = SP_Symbols.named_argument_association
              or else STree.Syntax_Node_Type (Node => Child) = SP_Symbols.annotation_named_argument_association then
               -- ASSUME Child = named_argument_association OR annotation_named_argument_association
               Type_Info := Unknown_Symbol_Record;
               ErrorHandler.Semantic_Error
                 (Err_Num   => 92,
                  Reference => ErrorHandler.No_Reference,
                  Position  => STree.Node_Position (Node => Node),
                  Id_Str    => LexTokenManager.Null_String);
               Next_Node := STree.NullNode;
            else
               Next_Node := STree.NullNode;
               SystemErrors.Fatal_Error
                 (Sys_Err => SystemErrors.Invalid_Syntax_Tree,
                  Msg     => "Expect Child = named_argument_association OR positional_argument_association OR " &
                    "annotation_named_argument_association OR annotation_positional_argument_association " &
                    "in Down_Wf_Name_Argument_List");
            end if;
         else
            Type_Info := Unknown_Symbol_Record;
            ErrorHandler.Semantic_Error
              (Err_Num   => 21,
               Reference => ErrorHandler.No_Reference,
               Position  => STree.Node_Position (Node => STree.Parent_Node (Current_Node => Node)),
               Id_Str    => LexTokenManager.Null_String);
            Next_Node := STree.NullNode;
         end if;
      when others =>
         Type_Info := Unknown_Symbol_Record;
         ErrorHandler.Semantic_Error
           (Err_Num   => 21,
            Reference => ErrorHandler.No_Reference,
            Position  => STree.Node_Position (Node => STree.Parent_Node (Current_Node => Node)),
            Id_Str    => LexTokenManager.Null_String);
         Next_Node := STree.NullNode;
   end case;
   Exp_Stack.Push (X     => Type_Info,
                   Stack => E_Stack);
end Down_Wf_Name_Argument_List;
