-------------------------------------------------------------------------------
-- (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 SLI;

separate (Sem.Wf_Basic_Declarative_Item.Wf_Basic_Declaration.Wf_Full_Type_Declaration)
procedure Wf_Enum
  (Node       : in STree.SyntaxNode;
   Scope      : in Dictionary.Scopes;
   Ident_Node : in STree.SyntaxNode;
   Dec_Loc    : in LexTokenManager.Token_Position)
is
   It                                             : STree.Iterator;
   Next_Node                                      : STree.SyntaxNode;
   Enumeration_Symbol, Enumeration_Literal_Symbol : Dictionary.Symbol;
   Item_Str, Store_Rep                            : LexTokenManager.Lex_String;
   Pos_Number, Last_Pos_Number                    : Maths.Value;
   Unused_Err_Code                                : Maths.ErrorCode;
begin
   Dictionary.Add_Enumeration_Type
     (Name        => Node_Lex_String (Node => Ident_Node),
      Comp_Unit   => ContextManager.Ops.Current_Unit,
      Declaration => Dictionary.Location'(Start_Position => Dec_Loc,
                                          End_Position   => Dec_Loc),
      Scope       => Scope,
      Context     => Dictionary.ProgramContext,
      The_Type    => Enumeration_Symbol);
   STree.Add_Node_Symbol (Node => Ident_Node,
                          Sym  => Enumeration_Symbol);
   if ErrorHandler.Generate_SLI then
      SLI.Generate_Xref_Symbol
        (Comp_Unit      => ContextManager.Ops.Current_Unit,
         Parse_Tree     => Ident_Node,
         Symbol         => Enumeration_Symbol,
         Is_Declaration => True);
   end if;
   Pos_Number := Maths.ZeroInteger;

   It := Find_First_Node (Node_Kind    => SP_Symbols.identifier,
                          From_Root    => Node,
                          In_Direction => STree.Down);

   while not STree.IsNull (It) loop
      Next_Node := Get_Node (It => It);
      --# assert Syntax_Node_Type (Next_Node, STree.Table) = SP_Symbols.identifier and
      --#   Next_Node = Get_Node (It) and
      --#   STree.Table = STree.Table~;
      Item_Str := Node_Lex_String (Node => Next_Node);
      if Dictionary.IsDefined
        (Name              => Item_Str,
         Scope             => Scope,
         Context           => Dictionary.ProofContext,
         Full_Package_Name => False) then
         ErrorHandler.Semantic_Error
           (Err_Num   => 10,
            Reference => ErrorHandler.No_Reference,
            Position  => Node_Position (Node => Next_Node),
            Id_Str    => Item_Str);
      else
         Maths.StorageRep (Pos_Number, Store_Rep);
         Dictionary.AddEnumerationLiteral
           (Name                  => Item_Str,
            Comp_Unit             => ContextManager.Ops.Current_Unit,
            Declaration           => Dictionary.Location'(Start_Position => Node_Position (Node => Next_Node),
                                                          End_Position   => Node_Position (Node => Next_Node)),
            Position              => Store_Rep,
            The_Type              => Enumeration_Symbol,
            TheEnumerationLiteral => Enumeration_Literal_Symbol);
         STree.Add_Node_Symbol (Node => Next_Node,
                                Sym  => Enumeration_Literal_Symbol);
         Last_Pos_Number := Pos_Number;
         --# accept Flow, 10, Unused_Err_Code, "Expected ineffective assignment";
         Maths.Add (Last_Pos_Number, Maths.OneInteger,
                    --to get
                    Pos_Number, Unused_Err_Code);
         --# end accept;
      end if;
      It := STree.NextNode (It);
   end loop;
   --# accept Flow, 33, Unused_Err_Code, "Expected to be neither referenced nor exported";
end Wf_Enum;
