-------------------------------------------------------------------------------
-- (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.Wf_Basic_Declarative_Item)
procedure Wf_Basic_Declaration
  (Node           : in     STree.SyntaxNode;
   Current_Scope  : in     Dictionary.Scopes;
   Component_Data : in out ComponentManager.ComponentData;
   The_Heap       : in out Heap.HeapRecord)
is
   Node_To_Check : STree.SyntaxNode;

   procedure Wf_Constant_Declaration
     (Node          : in     STree.SyntaxNode;
      Current_Scope : in     Dictionary.Scopes;
      The_Heap      : in out Heap.HeapRecord)
   --# global in     CommandLineData.Content;
   --#        in     ContextManager.Ops.File_Heap;
   --#        in     ContextManager.Ops.Unit_Heap;
   --#        in     ContextManager.Ops.Unit_Stack;
   --#        in out Dictionary.Dict;
   --#        in out ErrorHandler.Error_Context;
   --#        in out LexTokenManager.State;
   --#        in out SLI.State;
   --#        in out SPARK_IO.File_Sys;
   --#        in out Statistics.TableUsage;
   --#        in out STree.Table;
   --#           out Aggregate_Stack.State;
   --# derives Aggregate_Stack.State,
   --#         Dictionary.Dict,
   --#         LexTokenManager.State,
   --#         STree.Table                from CommandLineData.Content,
   --#                                         ContextManager.Ops.Unit_Stack,
   --#                                         Current_Scope,
   --#                                         Dictionary.Dict,
   --#                                         LexTokenManager.State,
   --#                                         Node,
   --#                                         STree.Table,
   --#                                         The_Heap &
   --#         ErrorHandler.Error_Context,
   --#         SLI.State,
   --#         SPARK_IO.File_Sys          from CommandLineData.Content,
   --#                                         ContextManager.Ops.File_Heap,
   --#                                         ContextManager.Ops.Unit_Heap,
   --#                                         ContextManager.Ops.Unit_Stack,
   --#                                         Current_Scope,
   --#                                         Dictionary.Dict,
   --#                                         ErrorHandler.Error_Context,
   --#                                         LexTokenManager.State,
   --#                                         Node,
   --#                                         SLI.State,
   --#                                         SPARK_IO.File_Sys,
   --#                                         STree.Table,
   --#                                         The_Heap &
   --#         Statistics.TableUsage,
   --#         The_Heap                   from *,
   --#                                         CommandLineData.Content,
   --#                                         ContextManager.Ops.Unit_Stack,
   --#                                         Current_Scope,
   --#                                         Dictionary.Dict,
   --#                                         LexTokenManager.State,
   --#                                         Node,
   --#                                         STree.Table,
   --#                                         The_Heap;
   --# pre Syntax_Node_Type (Node, STree.Table) = SP_Symbols.constant_declaration;
   --# post STree.Table = STree.Table~;
   is
      Ident_Node, Type_Node, Exp_Node : STree.SyntaxNode;
      Type_Sym                        : Dictionary.Symbol;
      Exp_Type                        : Exp_Record;
      Unwanted_Seq                    : SeqAlgebra.Seq;
      Store_Val                       : LexTokenManager.Lex_String;
      Unused_Component_Data           : ComponentManager.ComponentData;

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

      procedure Create_Implicit_String_Subtype
        (String_Length      : in     Maths.Value;
         Location           : in     Dictionary.Location;
         The_String_Subtype :    out Dictionary.Symbol)
      --# global in     CommandLineData.Content;
      --#        in     ContextManager.Ops.Unit_Stack;
      --#        in out Dictionary.Dict;
      --#        in out LexTokenManager.State;
      --#        in out SPARK_IO.File_Sys;
      --# derives Dictionary.Dict,
      --#         SPARK_IO.File_Sys     from *,
      --#                                    CommandLineData.Content,
      --#                                    ContextManager.Ops.Unit_Stack,
      --#                                    Dictionary.Dict,
      --#                                    LexTokenManager.State,
      --#                                    Location,
      --#                                    String_Length &
      --#         LexTokenManager.State from *,
      --#                                    CommandLineData.Content,
      --#                                    Dictionary.Dict,
      --#                                    String_Length &
      --#         The_String_Subtype    from CommandLineData.Content,
      --#                                    ContextManager.Ops.Unit_Stack,
      --#                                    Dictionary.Dict,
      --#                                    LexTokenManager.State,
      --#                                    Location,
      --#                                    String_Length;
      is
         String_Subtype_Str                                          : E_Strings.T;
         String_Subtype_Lex_Str                                      : LexTokenManager.Lex_String;
         Index_Constraint, The_String_Subtype_Local, The_Array_Index : Dictionary.Symbol;
      begin
         -- First create an index subtype of the form positive__n
         Create_Implicit_Positive_Subtype
           (String_Length    => String_Length,
            Location         => Location,
            Index_Constraint => Index_Constraint);
         -- Create an ExaminerString of the form "String__n" where n is the string length
         String_Subtype_Str := E_Strings.Copy_String (Str => "String__");
         -- The value of "n" will not exceed a size that can be printed within an ExaminerString
         -- so the conversion will not truncate here.
         E_Strings.Append_Examiner_String (E_Str1 => String_Subtype_Str,
                                           E_Str2 => Maths.ValueToString (String_Length));
         -- Insert this name into the string table; either we add it an get the LexStr back or,
         -- if it is already there, we get the existing LexStr back
         -- Insert this name into the string table; either we add it and get the LexStr back or,
         -- if it is already there, we get the existing LexStr back
         LexTokenManager.Insert_Examiner_String (Str     => String_Subtype_Str,
                                                 Lex_Str => String_Subtype_Lex_Str);
         -- Look up type in Dictionary in case it has previously been added
         -- Note that we put these implicit subtype in Standard (where Positive and String themselves live)
         -- and that we declare them in proof rather than Ada context
         The_String_Subtype_Local :=
           Dictionary.LookupItem
           (Name              => String_Subtype_Lex_Str,
            Scope             => Dictionary.Set_Visibility
              (The_Visibility => Dictionary.Visible,
               The_Unit       => Dictionary.GetPredefinedPackageStandard),
            Context           => Dictionary.ProofContext,
            Full_Package_Name => False);
         if Dictionary.Is_Null_Symbol (The_String_Subtype_Local) then
            -- not previously added, so we add a new subtype here
            Dictionary.Add_Array_Subtype
              (Name             => String_Subtype_Lex_Str,
               Parent           => Dictionary.GetPredefinedStringType,
               Parent_Reference => Location,
               Comp_Unit        => ContextManager.Ops.Current_Unit,
               Declaration      => Location,
               Scope            => Dictionary.Set_Visibility
                 (The_Visibility => Dictionary.Visible,
                  The_Unit       => Dictionary.GetPredefinedPackageStandard),
               Context          => Dictionary.ProofContext,
               Static           => CommandLineData.Content.Language_Profile /= CommandLineData.SPARK83,
               The_Subtype      => The_String_Subtype_Local);
            --# accept Flow, 10, The_Array_Index, "Expected ineffective assignment to OK";
            Dictionary.AddArrayIndex
              (TheArrayType  => The_String_Subtype_Local,
               IndexType     => Index_Constraint,
               Comp_Unit     => ContextManager.Ops.Current_Unit,
               Declaration   => Location,
               TheArrayIndex => The_Array_Index);
            --# end accept;
         end if;
         The_String_Subtype := The_String_Subtype_Local;
         --# accept Flow, 33, The_Array_Index, "Expected to be neither referenced nor exported";
      end Create_Implicit_String_Subtype;

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

      function Valid_Named_Number_Type (Sym : Dictionary.Symbol) return Dictionary.Symbol
      --# global in CommandLineData.Content;
      --#        in Dictionary.Dict;
      -- This returns universal_real or universal_integer if a valid (according to tool
      -- variant) type is supplied or the unknown type mark if it not
      is
         Result : Dictionary.Symbol;
      begin
         case CommandLineData.Content.Language_Profile is
            when CommandLineData.SPARK83 =>
               if Dictionary.IsUniversalIntegerType (Sym) then
                  Result := Sym;
               elsif Dictionary.IsUniversalRealType (Sym) then
                  Result := Sym;
               else
                  Result := Dictionary.GetUnknownTypeMark;
               end if;
            when CommandLineData.SPARK95_Onwards =>
               if Dictionary.TypeIsInteger (Sym) or Dictionary.TypeIsModular (Sym) then
                  Result := Dictionary.GetUniversalIntegerType;
               elsif Dictionary.TypeIsReal (Sym) then
                  Result := Dictionary.GetUniversalRealType;
               else
                  Result := Dictionary.GetUnknownTypeMark;
               end if;
         end case;
         return Result;
      end Valid_Named_Number_Type;

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

      procedure Do_Identifier_List
        (Node, Exp_Node    : in STree.SyntaxNode;
         Type_Node_Pos     : in LexTokenManager.Token_Position;
         Type_Sym          : in Dictionary.Symbol;
         Current_Scope     : in Dictionary.Scopes;
         Exp_Is_Wellformed : in Boolean;
         Static            : in Boolean;
         Store_Val         : in LexTokenManager.Lex_String)
      --# 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,
      --#         STree.Table                from CommandLineData.Content,
      --#                                         ContextManager.Ops.Unit_Stack,
      --#                                         Current_Scope,
      --#                                         Dictionary.Dict,
      --#                                         Exp_Is_Wellformed,
      --#                                         Exp_Node,
      --#                                         LexTokenManager.State,
      --#                                         Node,
      --#                                         Static,
      --#                                         Store_Val,
      --#                                         STree.Table,
      --#                                         Type_Sym &
      --#         ErrorHandler.Error_Context,
      --#         SPARK_IO.File_Sys          from CommandLineData.Content,
      --#                                         ContextManager.Ops.Unit_Stack,
      --#                                         Current_Scope,
      --#                                         Dictionary.Dict,
      --#                                         ErrorHandler.Error_Context,
      --#                                         Exp_Is_Wellformed,
      --#                                         Exp_Node,
      --#                                         LexTokenManager.State,
      --#                                         Node,
      --#                                         SPARK_IO.File_Sys,
      --#                                         Static,
      --#                                         Store_Val,
      --#                                         STree.Table,
      --#                                         Type_Node_Pos,
      --#                                         Type_Sym;
      --# pre Syntax_Node_Type (Node, STree.Table) = SP_Symbols.identifier_list and
      --#   Syntax_Node_Type (Exp_Node, STree.Table) = SP_Symbols.expression;
      --# post STree.Table = STree.Table~;
      is
         Next_Node                     : STree.SyntaxNode;
         It                            : STree.Iterator;
         Ident_Str, Store_Val_Local    : LexTokenManager.Lex_String;
         Sym, The_Constant             : Dictionary.Symbol;
         OK_To_Add, Static_Local       : Boolean;
         Type_Location, Ident_Location : Dictionary.Location;

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

         function Is_Deferred_Constant_Resolution (Sym   : Dictionary.Symbol;
                                                   Scope : Dictionary.Scopes) return Boolean
         --# global in Dictionary.Dict;
         is
         begin
            return not Dictionary.Is_Declared (Item => Sym)
              and then Dictionary.Get_Visibility (Scope => Scope) = Dictionary.Privat
              and then Dictionary.IsDeferredConstant (Sym)
              and then Dictionary.GetRegion (Scope) = Dictionary.GetRegion (Dictionary.GetScope (Sym));
         end Is_Deferred_Constant_Resolution;

      begin -- Do_Identifier_List
         OK_To_Add     := False;
         Type_Location := Dictionary.Location'(Start_Position => Type_Node_Pos,
                                               End_Position   => Type_Node_Pos);

         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 STree.Table = STree.Table~ and
            --#   Syntax_Node_Type (Exp_Node, STree.Table) = SP_Symbols.expression and
            --#   Syntax_Node_Type (Next_Node, STree.Table) = SP_Symbols.identifier and
            --#   Next_Node = Get_Node (It);
            Ident_Str := Node_Lex_String (Node => Next_Node);
            Sym       :=
              Dictionary.LookupItem
              (Name              => Ident_Str,
               Scope             => Current_Scope,
               Context           => Dictionary.ProofContext,
               Full_Package_Name => False);

            if Dictionary.Is_Null_Symbol (Sym) then
               OK_To_Add := True;
            elsif Is_Deferred_Constant_Resolution (Sym   => Sym,
                                                   Scope => Current_Scope) then
               if Dictionary.Types_Are_Equal
                 (Left_Symbol        => Type_Sym,
                  Right_Symbol       => Dictionary.GetType (Sym),
                  Full_Range_Subtype => False) then
                  STree.Set_Node_Lex_String (Sym  => Sym,
                                             Node => Next_Node);
                  OK_To_Add := True;
               else
                  ErrorHandler.Semantic_Error
                    (Err_Num   => 22,
                     Reference => ErrorHandler.No_Reference,
                     Position  => Node_Position (Node => Next_Node),
                     Id_Str    => Ident_Str);
               end if;
            else -- already exists but is not a deferred constant completion
               if Dictionary.IsOwnVariable (Sym) or Dictionary.IsConstituent (Sym) then
                  -- A common mistake - trying to complete an own variable with
                  -- a constant declaration.  Spot this to give a better error
                  -- message here.
                  ErrorHandler.Semantic_Error
                    (Err_Num   => 12,
                     Reference => ErrorHandler.No_Reference,
                     Position  => Node_Position (Node => Next_Node),
                     Id_Str    => Ident_Str);
               else
                  ErrorHandler.Semantic_Error
                    (Err_Num   => 10,
                     Reference => ErrorHandler.No_Reference,
                     Position  => Node_Position (Node => Next_Node),
                     Id_Str    => Ident_Str);
               end if;
            end if;

            if OK_To_Add then
               Ident_Location :=
                 Dictionary.Location'
                 (Start_Position => Node_Position (Node => Next_Node),
                  End_Position   => Node_Position (Node => Next_Node));
               if Dictionary.IsPrivateTypeMark (Type_Sym, Current_Scope) then
                  Store_Val_Local := Store_Val;
                  Static_Local    := False;
               elsif Dictionary.IsRecordTypeMark (Type_Sym, Current_Scope) or else Dictionary.IsProtectedTypeMark (Type_Sym) then
                  Store_Val_Local := LexTokenManager.Null_String;
                  Static_Local    := False;
               else
                  Store_Val_Local := Store_Val;
                  Static_Local    := Static;
               end if;
               Dictionary.Add_Constant_Declaration
                 (Name              => Ident_Str,
                  Type_Mark         => Type_Sym,
                  Type_Reference    => Type_Location,
                  Value             => Store_Val_Local,
                  Exp_Is_Wellformed => Exp_Is_Wellformed,
                  Exp_Node          => STree.NodeToRef (Exp_Node),
                  Static            => Static_Local,
                  Comp_Unit         => ContextManager.Ops.Current_Unit,
                  Declaration       => Ident_Location,
                  Scope             => Current_Scope,
                  Context           => Dictionary.ProgramContext,
                  TheConstant       => The_Constant);
               STree.Add_Node_Symbol (Node => Next_Node,
                                      Sym  => The_Constant);
            end if;
            It := STree.NextNode (It);
         end loop;
      end Do_Identifier_List;

   begin -- Wf_Constant_Declaration
      Heap.Reset (The_Heap);
      Ident_Node := Child_Node (Current_Node => Node);
      -- ASSUME Ident_Node = identifier_list
      SystemErrors.RT_Assert
        (C       => Syntax_Node_Type (Node => Ident_Node) = SP_Symbols.identifier_list,
         Sys_Err => SystemErrors.Invalid_Syntax_Tree,
         Msg     => "Expect Ident_Node = identifier_list in Wf_Constant_Declaration");

      Type_Node := Next_Sibling (Current_Node => Ident_Node);
      -- ASSUME Type_Node = type_mark OR expression
      if Syntax_Node_Type (Node => Type_Node) = SP_Symbols.expression then
         -- ASSUME Type_Node = expression
         Exp_Node  := Type_Node;
         Type_Node := STree.NullNode;
         Type_Sym  := Dictionary.GetUnknownTypeMark;
      elsif Syntax_Node_Type (Node => Type_Node) = SP_Symbols.type_mark then
         -- ASSUME Type_Node = type_mark
         Exp_Node := Next_Sibling (Current_Node => Type_Node);
         Wf_Type_Mark
           (Node          => Type_Node,
            Current_Scope => Current_Scope,
            Context       => Dictionary.ProgramContext,
            Type_Sym      => Type_Sym);
         if Dictionary.Is_Unconstrained_Array_Type_Mark (Type_Sym, Current_Scope)
           and then not Dictionary.IsPredefinedStringType (Type_Sym) then
            -- allow string constants
            ErrorHandler.Semantic_Error
              (Err_Num   => 39,
               Reference => ErrorHandler.No_Reference,
               Position  => Node_Position (Node => Type_Node),
               Id_Str    => LexTokenManager.Null_String);
         elsif Dictionary.IsPredefinedSuspensionObjectType (Type_Sym) or else Dictionary.IsProtectedTypeMark (Type_Sym) then
            ErrorHandler.Semantic_Error
              (Err_Num   => 903,
               Reference => ErrorHandler.No_Reference,
               Position  => Node_Position (Node => Type_Node),
               Id_Str    => LexTokenManager.Null_String);
         elsif Dictionary.TypeIsGeneric (Type_Sym) then
            ErrorHandler.Semantic_Error
              (Err_Num   => 653,
               Reference => ErrorHandler.No_Reference,
               Position  => Node_Position (Node => Type_Node),
               Id_Str    => LexTokenManager.Null_String);
         end if;
      else
         Exp_Node := STree.NullNode;
         Type_Sym := Dictionary.NullSymbol;
         SystemErrors.Fatal_Error
           (Sys_Err => SystemErrors.Invalid_Syntax_Tree,
            Msg     => "Expect Type_Node = type_mark OR expression in Wf_Constant_Declaration");
      end if;

      -- ASSUME Type_Node = type_mark OR NULL
      SystemErrors.RT_Assert
        (C       => Type_Node = STree.NullNode or else Syntax_Node_Type (Node => Type_Node) = SP_Symbols.type_mark,
         Sys_Err => SystemErrors.Invalid_Syntax_Tree,
         Msg     => "Expect Type_Node = type_mark OR NULL in Wf_Constant_Declaration");

      -- ASSUME Exp_Node = expression
      SystemErrors.RT_Assert
        (C       => Syntax_Node_Type (Node => Exp_Node) = SP_Symbols.expression,
         Sys_Err => SystemErrors.Invalid_Syntax_Tree,
         Msg     => "Expect Exp_Node = expression in Wf_Constant_Declaration");

      SeqAlgebra.CreateSeq (The_Heap, Unwanted_Seq);
      ComponentManager.Initialise (Unused_Component_Data);
      --# accept Flow, 10, Unused_Component_Data, "Expected ineffective assignment";
      Walk_Expression_P.Walk_Expression
        (Exp_Node                => Exp_Node,
         Scope                   => Current_Scope,
         Type_Context            => Type_Sym,
         Context_Requires_Static => False,
         Ref_Var                 => Unwanted_Seq,
         Result                  => Exp_Type,
         Component_Data          => Unused_Component_Data,
         The_Heap                => The_Heap);
      --# end accept;
      SeqAlgebra.DisposeOfSeq (The_Heap, Unwanted_Seq);
      Maths.StorageRep (Exp_Type.Value, Store_Val); -- scalar value if needed later

      if Type_Node = STree.NullNode then -- must be a named number
         if Exp_Type.Is_ARange then
            ErrorHandler.Semantic_Error
              (Err_Num   => 114,
               Reference => ErrorHandler.No_Reference,
               Position  => Node_Position (Node => Exp_Node),
               Id_Str    => LexTokenManager.Null_String);
         else
            if not Exp_Type.Is_Constant then
               ErrorHandler.Semantic_Error
                 (Err_Num   => 37,
                  Reference => 13,
                  Position  => Node_Position (Node => Exp_Node),
                  Id_Str    => LexTokenManager.Null_String);
            end if;
            Type_Sym := Valid_Named_Number_Type (Sym => Exp_Type.Type_Symbol);
            if Dictionary.IsUnknownTypeMark (Type_Sym) then
               ErrorHandler.Semantic_Error
                 (Err_Num   => 38,
                  Reference => 10,
                  Position  => Node_Position (Node => Exp_Node),
                  Id_Str    => LexTokenManager.Null_String);
            end if;
         end if;

      else -- end of named number checks

         -- If it's a constant of a constrained String subtype like
         --    C : constant String_2 := "xx";
         -- or a String constant constrained by initialization, like
         --    C : constant String := "Wibble";
         -- then we need to grab the value of the initializing expression returned
         -- from WalkExpression and make sure it gets stored in the Dictionary.

         if Dictionary.IsPredefinedStringType (Dictionary.GetRootType (Type_Sym)) then

            -- If it's constrained by initialization, then we also need to create an implicit
            -- subtype for it, thus:
            if Dictionary.IsPredefinedStringType (Type_Sym) and then not Maths.HasNoValue (Exp_Type.Range_RHS) then
               -- but only create subtype if range known

               -- We have a constant of type string, implicitly constrained by its initializing
               -- string literal.  In this case we create a string subtype of the right length
               -- and substitute this subtype for string before adding the constant.
               Create_Implicit_String_Subtype
                 (String_Length      => Exp_Type.Range_RHS,
                  Location           => Dictionary.Location'(Start_Position => Node_Position (Node => Type_Node),
                                                             End_Position   => Node_Position (Node => Type_Node)),
                  The_String_Subtype => Type_Sym);
            end if;

            -- Grab the value of the initializing expression return from WalkExpression and
            -- record in Store_Val. This is used to populate the Dictionary later on in
            -- Do_Identifier_List
            Store_Val := Exp_Type.String_Value;
         end if;
         SystemErrors.RT_Assert
           (C       => Dictionary.Is_Null_Symbol (Exp_Type.Type_Symbol) or else Dictionary.IsTypeMark (Exp_Type.Type_Symbol),
            Sys_Err => SystemErrors.Invalid_Syntax_Tree,
            Msg     => "Expect Exp_Type.Type_Symbol to be a type in Wf_Constant_Declaration");
         Assignment_Check
           (Position    => Node_Position (Node => Exp_Node),
            Scope       => Current_Scope,
            Target_Type => Type_Sym,
            Exp_Result  => Exp_Type);
         if not Exp_Type.Is_Constant then
            ErrorHandler.Semantic_Error
              (Err_Num   => 37,
               Reference => 13,
               Position  => Node_Position (Node => Exp_Node),
               Id_Str    => LexTokenManager.Null_String);
         end if;
      end if;

      Do_Identifier_List
        (Node              => Ident_Node,
         Exp_Node          => Exp_Node,
         Type_Node_Pos     => Node_Position (Node => Type_Node),
         Type_Sym          => Type_Sym,
         Current_Scope     => Current_Scope,
         Exp_Is_Wellformed => not Exp_Type.Errors_In_Expression,
         Static            => Dictionary.IsStatic (Type_Sym, Current_Scope) and then Exp_Type.Is_Static,
         Store_Val         => Store_Val);

      Heap.ReportUsage (The_Heap);
   end Wf_Constant_Declaration;

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

   -- Note: Enclosing_Unit_Scope represents the scope of the enclosing program
   -- unit, whilst Declaration_Scope represents the scope of the current
   -- declaration. These are normally the same. The exception is the special
   -- case of a declaration within a protected type, where they may differ.
   -- For example, the declaration could be in the private part of the PT but
   -- the PT itself could be in the visible part of the enclosing unit.

   procedure Wf_Variable_Declaration
     (Node                 : in     STree.SyntaxNode;
      Enclosing_Unit_Scope : in     Dictionary.Scopes;
      Declaration_Scope    : in     Dictionary.Scopes;
      The_Heap             : in out Heap.HeapRecord)
   --# global in     CommandLineData.Content;
   --#        in     ContextManager.Ops.File_Heap;
   --#        in     ContextManager.Ops.Unit_Heap;
   --#        in     ContextManager.Ops.Unit_Stack;
   --#        in out Aggregate_Stack.State;
   --#        in out Dictionary.Dict;
   --#        in out ErrorHandler.Error_Context;
   --#        in out LexTokenManager.State;
   --#        in out SLI.State;
   --#        in out SPARK_IO.File_Sys;
   --#        in out Statistics.TableUsage;
   --#        in out STree.Table;
   --# derives Aggregate_Stack.State,
   --#         Dictionary.Dict,
   --#         LexTokenManager.State,
   --#         Statistics.TableUsage,
   --#         STree.Table,
   --#         The_Heap                   from *,
   --#                                         CommandLineData.Content,
   --#                                         ContextManager.Ops.Unit_Stack,
   --#                                         Declaration_Scope,
   --#                                         Dictionary.Dict,
   --#                                         Enclosing_Unit_Scope,
   --#                                         LexTokenManager.State,
   --#                                         Node,
   --#                                         STree.Table,
   --#                                         The_Heap &
   --#         ErrorHandler.Error_Context,
   --#         SLI.State,
   --#         SPARK_IO.File_Sys          from CommandLineData.Content,
   --#                                         ContextManager.Ops.File_Heap,
   --#                                         ContextManager.Ops.Unit_Heap,
   --#                                         ContextManager.Ops.Unit_Stack,
   --#                                         Declaration_Scope,
   --#                                         Dictionary.Dict,
   --#                                         Enclosing_Unit_Scope,
   --#                                         ErrorHandler.Error_Context,
   --#                                         LexTokenManager.State,
   --#                                         Node,
   --#                                         SLI.State,
   --#                                         SPARK_IO.File_Sys,
   --#                                         STree.Table,
   --#                                         The_Heap;
   --# pre Syntax_Node_Type (Node, STree.Table) = SP_Symbols.variable_declaration;
   --# post STree.Table = STree.Table~;
      is separate;

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

   procedure Wf_Full_Type_Declaration
     (Node           : in     STree.SyntaxNode;
      Scope          : in     Dictionary.Scopes;
      Component_Data : in out ComponentManager.ComponentData;
      The_Heap       : in out Heap.HeapRecord)
   --# global in     CommandLineData.Content;
   --#        in     ContextManager.Ops.File_Heap;
   --#        in     ContextManager.Ops.Unit_Heap;
   --#        in     ContextManager.Ops.Unit_Stack;
   --#        in out Aggregate_Stack.State;
   --#        in out Dictionary.Dict;
   --#        in out ErrorHandler.Error_Context;
   --#        in out LexTokenManager.State;
   --#        in out SLI.State;
   --#        in out SPARK_IO.File_Sys;
   --#        in out Statistics.TableUsage;
   --#        in out STree.Table;
   --# derives Aggregate_Stack.State,
   --#         Component_Data,
   --#         Dictionary.Dict,
   --#         LexTokenManager.State,
   --#         Statistics.TableUsage,
   --#         STree.Table,
   --#         The_Heap                   from *,
   --#                                         CommandLineData.Content,
   --#                                         Component_Data,
   --#                                         ContextManager.Ops.Unit_Stack,
   --#                                         Dictionary.Dict,
   --#                                         LexTokenManager.State,
   --#                                         Node,
   --#                                         Scope,
   --#                                         STree.Table,
   --#                                         The_Heap &
   --#         ErrorHandler.Error_Context,
   --#         SLI.State,
   --#         SPARK_IO.File_Sys          from CommandLineData.Content,
   --#                                         Component_Data,
   --#                                         ContextManager.Ops.File_Heap,
   --#                                         ContextManager.Ops.Unit_Heap,
   --#                                         ContextManager.Ops.Unit_Stack,
   --#                                         Dictionary.Dict,
   --#                                         ErrorHandler.Error_Context,
   --#                                         LexTokenManager.State,
   --#                                         Node,
   --#                                         Scope,
   --#                                         SLI.State,
   --#                                         SPARK_IO.File_Sys,
   --#                                         STree.Table,
   --#                                         The_Heap;
   --# pre Syntax_Node_Type (Node, STree.Table) = SP_Symbols.full_type_declaration;
   --# post STree.Table = STree.Table~;
      is separate;

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

   procedure Wf_Subtype_Declaration
     (Node     : in     STree.SyntaxNode;
      Scope    : in     Dictionary.Scopes;
      The_Heap : in out Heap.HeapRecord)
   --# global in     CommandLineData.Content;
   --#        in     ContextManager.Ops.File_Heap;
   --#        in     ContextManager.Ops.Unit_Heap;
   --#        in     ContextManager.Ops.Unit_Stack;
   --#        in out Aggregate_Stack.State;
   --#        in out Dictionary.Dict;
   --#        in out ErrorHandler.Error_Context;
   --#        in out LexTokenManager.State;
   --#        in out SLI.State;
   --#        in out SPARK_IO.File_Sys;
   --#        in out Statistics.TableUsage;
   --#        in out STree.Table;
   --# derives Aggregate_Stack.State,
   --#         Dictionary.Dict,
   --#         LexTokenManager.State,
   --#         Statistics.TableUsage,
   --#         STree.Table,
   --#         The_Heap                   from *,
   --#                                         CommandLineData.Content,
   --#                                         ContextManager.Ops.Unit_Stack,
   --#                                         Dictionary.Dict,
   --#                                         LexTokenManager.State,
   --#                                         Node,
   --#                                         Scope,
   --#                                         STree.Table,
   --#                                         The_Heap &
   --#         ErrorHandler.Error_Context,
   --#         SLI.State,
   --#         SPARK_IO.File_Sys          from CommandLineData.Content,
   --#                                         ContextManager.Ops.File_Heap,
   --#                                         ContextManager.Ops.Unit_Heap,
   --#                                         ContextManager.Ops.Unit_Stack,
   --#                                         Dictionary.Dict,
   --#                                         ErrorHandler.Error_Context,
   --#                                         LexTokenManager.State,
   --#                                         Node,
   --#                                         Scope,
   --#                                         SLI.State,
   --#                                         SPARK_IO.File_Sys,
   --#                                         STree.Table,
   --#                                         The_Heap;
   --# pre Syntax_Node_Type (Node, STree.Table) = SP_Symbols.subtype_declaration;
   --# post STree.Table = STree.Table~;
      is separate;

begin -- Wf_Basic_Declaration
   Node_To_Check := Child_Node (Current_Node => Node);
   -- ASSUME Node_To_Check = object_declaration OR full_type_declaration OR subtype_declaration
   if Syntax_Node_Type (Node => Node_To_Check) = SP_Symbols.object_declaration then
      -- ASSUME Node_To_Check = object_declaration
      Node_To_Check := Child_Node (Current_Node => Node_To_Check);
      -- ASSUME Node_To_Check = constant_declaration OR variable_declaration
      if Syntax_Node_Type (Node => Node_To_Check) = SP_Symbols.variable_declaration then
         -- ASSUME Node_To_Check = variable_declaration
         -- In the case of a basic variable declaration the scope of the
         -- enclosing program unit and the scope of the declaration are
         -- the same, hence Current_Scope is used for both parameters.
         Wf_Variable_Declaration
           (Node                 => Node_To_Check,
            Enclosing_Unit_Scope => Current_Scope,
            Declaration_Scope    => Current_Scope,
            The_Heap             => The_Heap);
      elsif Syntax_Node_Type (Node => Node_To_Check) = SP_Symbols.constant_declaration then
         -- ASSUME Node_To_Check = constant_declaration
         Wf_Constant_Declaration (Node          => Node_To_Check,
                                  Current_Scope => Current_Scope,
                                  The_Heap      => The_Heap);
      else
         SystemErrors.Fatal_Error
           (Sys_Err => SystemErrors.Invalid_Syntax_Tree,
            Msg     => "Expect Node_To_Check = constant_declaration OR variable_declaration in Wf_Basic_Declaration");
      end if;
   elsif Syntax_Node_Type (Node => Node_To_Check) = SP_Symbols.full_type_declaration then
      -- ASSUME Node_To_Check = full_type_declaration
      Wf_Full_Type_Declaration
        (Node           => Node_To_Check,
         Scope          => Current_Scope,
         Component_Data => Component_Data,
         The_Heap       => The_Heap);

   elsif Syntax_Node_Type (Node => Node_To_Check) = SP_Symbols.subtype_declaration then
      -- ASSUME Node_To_Check = subtype_declaration
      Wf_Subtype_Declaration (Node     => Node_To_Check,
                              Scope    => Current_Scope,
                              The_Heap => The_Heap);
   else
      SystemErrors.Fatal_Error
        (Sys_Err => SystemErrors.Invalid_Syntax_Tree,
         Msg     => "Expect Node_To_Check = object_declaration OR full_type_declaration OR " &
           "subtype_declaration in Wf_Basic_Declaration");
   end if;
end Wf_Basic_Declaration;
