-------------------------------------------------------------------------------
-- (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.CompUnit.Wf_Package_Body.Wf_Refine)
procedure Wf_Clause (Node  : in STree.SyntaxNode;
                     Scope : in Dictionary.Scopes) is
   Subject_Sym      : Dictionary.Symbol;
   Subject_Node     : STree.SyntaxNode;
   Subject_Loc      : LexTokenManager.Token_Position;
   Constituent_Node : STree.SyntaxNode;

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

   procedure Do_Subject (Subject_Node : in     STree.SyntaxNode;
                         Scope        : in     Dictionary.Scopes;
                         Subject_Sym  :    out Dictionary.Symbol)
   --# global in     CommandLineData.Content;
   --#        in     Dictionary.Dict;
   --#        in     LexTokenManager.State;
   --#        in out ErrorHandler.Error_Context;
   --#        in out SPARK_IO.File_Sys;
   --#        in out STree.Table;
   --# derives ErrorHandler.Error_Context,
   --#         SPARK_IO.File_Sys          from CommandLineData.Content,
   --#                                         Dictionary.Dict,
   --#                                         ErrorHandler.Error_Context,
   --#                                         LexTokenManager.State,
   --#                                         Scope,
   --#                                         SPARK_IO.File_Sys,
   --#                                         STree.Table,
   --#                                         Subject_Node &
   --#         STree.Table,
   --#         Subject_Sym                from CommandLineData.Content,
   --#                                         Dictionary.Dict,
   --#                                         LexTokenManager.State,
   --#                                         Scope,
   --#                                         STree.Table,
   --#                                         Subject_Node;
   --# pre Syntax_Node_Type (Subject_Node, STree.Table) = SP_Symbols.identifier;
   --# post STree.Table = STree.Table~;
   is
      Var_Sym : Dictionary.Symbol;
      Var_Pos : LexTokenManager.Token_Position;
      Var_Str : LexTokenManager.Lex_String;
   begin
      Var_Str := Node_Lex_String (Node => Subject_Node);
      Var_Pos := Node_Position (Node => Subject_Node);
      Var_Sym :=
        Dictionary.LookupItem
        (Name              => Var_Str,
         Scope             => Dictionary.Set_Visibility (The_Visibility => Dictionary.Visible,
                                                         The_Unit       => Dictionary.GetRegion (Scope)),
         Context           => Dictionary.ProofContext,
         Full_Package_Name => False);
      if Dictionary.Is_Null_Symbol (Var_Sym) then
         -- not declared or visible
         ErrorHandler.Semantic_Error
           (Err_Num   => 136,
            Reference => ErrorHandler.No_Reference,
            Position  => Var_Pos,
            Id_Str    => Var_Str);
         Subject_Sym := Dictionary.NullSymbol;
      elsif Dictionary.IsOwnVariable (Var_Sym) then
         -- possibly ok, it's an own var
         if not Dictionary.GetOwnVariableProtected (Var_Sym) then
            -- cannot refine protected state
            if not Dictionary.IsVirtualElement (Var_Sym) then
               -- cannot refine virtual elements
               if Dictionary.Is_Declared (Item => Var_Sym) -- declared as concrete
                 or else Dictionary.OwnVariableHasConstituents (Var_Sym) then -- or already refined away so raise error 73
                  ErrorHandler.Semantic_Error
                    (Err_Num   => 73,
                     Reference => ErrorHandler.No_Reference,
                     Position  => Var_Pos,
                     Id_Str    => Var_Str);
                  Subject_Sym := Dictionary.NullSymbol;
               elsif Dictionary.OwnVariableHasType (Var_Sym, Scope) then
                  -- type announced so refinement valid only if type is abstract proof type
                  if Dictionary.Is_Declared (Item => Dictionary.GetType (Var_Sym)) then
                     -- type is concrete type so refinement definitely illegal
                     ErrorHandler.Semantic_Error
                       (Err_Num   => 73,
                        Reference => ErrorHandler.No_Reference,
                        Position  => Var_Pos,
                        Id_Str    => Var_Str);
                     Subject_Sym := Dictionary.NullSymbol;
                  else
                     -- type not declared so we don't know whether problem is illegal refinement
                     -- or missing abstract type declaration.  Need special error message here
                     ErrorHandler.Semantic_Error
                       (Err_Num   => 273,
                        Reference => ErrorHandler.No_Reference,
                        Position  => Var_Pos,
                        Id_Str    => Var_Str);
                     Subject_Sym := Dictionary.NullSymbol;
                  end if;
               else  -- this is the valid case
                  STree.Set_Node_Lex_String (Sym  => Var_Sym,
                                             Node => Subject_Node);
                  Subject_Sym := Var_Sym;
               end if;
            else -- it's a virtual element which cannot be refined
               ErrorHandler.Semantic_Error
                 (Err_Num   => 858,
                  Reference => ErrorHandler.No_Reference,
                  Position  => Var_Pos,
                  Id_Str    => Var_Str);
               Subject_Sym := Dictionary.NullSymbol;
            end if;
         else -- it's a protected own variable which cannot be refined
            ErrorHandler.Semantic_Error
              (Err_Num   => 859,
               Reference => ErrorHandler.No_Reference,
               Position  => Var_Pos,
               Id_Str    => Var_Str);
            Subject_Sym := Dictionary.NullSymbol;
         end if;
      else -- it's not an own variable so it can't be refined
         ErrorHandler.Semantic_Error
           (Err_Num   => 74,
            Reference => ErrorHandler.No_Reference,
            Position  => Var_Pos,
            Id_Str    => Var_Str);
         Subject_Sym := Dictionary.NullSymbol;
      end if;
   end Do_Subject;

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

   procedure Do_Constituent_List
     (Constituent_List_Node : in STree.SyntaxNode;
      Scope                 : in Dictionary.Scopes;
      Subject_Sym           : in Dictionary.Symbol;
      Subject_Loc           : in LexTokenManager.Token_Position)
   --# 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,
   --#                                         Constituent_List_Node,
   --#                                         ContextManager.Ops.Unit_Stack,
   --#                                         Dictionary.Dict,
   --#                                         LexTokenManager.State,
   --#                                         Scope,
   --#                                         STree.Table,
   --#                                         Subject_Sym &
   --#         ErrorHandler.Error_Context,
   --#         SPARK_IO.File_Sys          from CommandLineData.Content,
   --#                                         Constituent_List_Node,
   --#                                         ContextManager.Ops.Unit_Stack,
   --#                                         Dictionary.Dict,
   --#                                         ErrorHandler.Error_Context,
   --#                                         LexTokenManager.State,
   --#                                         Scope,
   --#                                         SPARK_IO.File_Sys,
   --#                                         STree.Table,
   --#                                         Subject_Loc,
   --#                                         Subject_Sym;
   --# pre Syntax_Node_Type (Constituent_List_Node, STree.Table) = SP_Symbols.constituent_list;
   --# post STree.Table = STree.Table~;
   is
      type Modes is record
         Value    : Dictionary.Modes;
         Is_Valid : Boolean;
      end record;

      It               : STree.Iterator;
      Constituent_Node : STree.SyntaxNode;
      Mode             : Modes;

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

      procedure Do_Constituent
        (Constituent_Node : in STree.SyntaxNode;
         Scope            : in Dictionary.Scopes;
         Subject_Sym      : in Dictionary.Symbol;
         Mode             : in Modes;
         Subject_Loc      : in LexTokenManager.Token_Position)
      --# 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            from *,
      --#                                         CommandLineData.Content,
      --#                                         Constituent_Node,
      --#                                         ContextManager.Ops.Unit_Stack,
      --#                                         LexTokenManager.State,
      --#                                         Mode,
      --#                                         Scope,
      --#                                         STree.Table,
      --#                                         Subject_Sym &
      --#         ErrorHandler.Error_Context from *,
      --#                                         CommandLineData.Content,
      --#                                         Constituent_Node,
      --#                                         Dictionary.Dict,
      --#                                         LexTokenManager.State,
      --#                                         Mode,
      --#                                         Scope,
      --#                                         SPARK_IO.File_Sys,
      --#                                         STree.Table,
      --#                                         Subject_Sym &
      --#         SPARK_IO.File_Sys          from *,
      --#                                         CommandLineData.Content,
      --#                                         Constituent_Node,
      --#                                         ContextManager.Ops.Unit_Stack,
      --#                                         Dictionary.Dict,
      --#                                         ErrorHandler.Error_Context,
      --#                                         LexTokenManager.State,
      --#                                         Mode,
      --#                                         Scope,
      --#                                         STree.Table,
      --#                                         Subject_Loc,
      --#                                         Subject_Sym &
      --#         STree.Table                from *,
      --#                                         CommandLineData.Content,
      --#                                         Constituent_Node,
      --#                                         Dictionary.Dict,
      --#                                         LexTokenManager.State,
      --#                                         Scope,
      --#                                         Subject_Sym;
      --# pre Syntax_Node_Type (Constituent_Node, STree.Table) = SP_Symbols.entire_variable;
      --# post STree.Table = STree.Table~;
      is
         First_Node       : STree.SyntaxNode;
         Second_Node      : STree.SyntaxNode;
         Child_First_Node : STree.SyntaxNode;

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

         procedure Do_Concrete_Constituent
           (Var_Node    : in STree.SyntaxNode;
            Scope       : in Dictionary.Scopes;
            Subject_Sym : in Dictionary.Symbol;
            Mode        : in Modes;
            Subject_Loc : in LexTokenManager.Token_Position)
         --# global in     CommandLineData.Content;
         --#        in     ContextManager.Ops.Unit_Stack;
         --#        in     LexTokenManager.State;
         --#        in     STree.Table;
         --#        in out Dictionary.Dict;
         --#        in out ErrorHandler.Error_Context;
         --#        in out SPARK_IO.File_Sys;
         --# derives Dictionary.Dict            from *,
         --#                                         CommandLineData.Content,
         --#                                         ContextManager.Ops.Unit_Stack,
         --#                                         LexTokenManager.State,
         --#                                         Mode,
         --#                                         Scope,
         --#                                         STree.Table,
         --#                                         Subject_Sym,
         --#                                         Var_Node &
         --#         ErrorHandler.Error_Context from *,
         --#                                         CommandLineData.Content,
         --#                                         Dictionary.Dict,
         --#                                         LexTokenManager.State,
         --#                                         Scope,
         --#                                         SPARK_IO.File_Sys,
         --#                                         STree.Table,
         --#                                         Var_Node &
         --#         SPARK_IO.File_Sys          from *,
         --#                                         CommandLineData.Content,
         --#                                         ContextManager.Ops.Unit_Stack,
         --#                                         Dictionary.Dict,
         --#                                         ErrorHandler.Error_Context,
         --#                                         LexTokenManager.State,
         --#                                         Mode,
         --#                                         Scope,
         --#                                         STree.Table,
         --#                                         Subject_Loc,
         --#                                         Subject_Sym,
         --#                                         Var_Node;
         --# pre Syntax_Node_Type (Var_Node, STree.Table) = SP_Symbols.identifier;
         is
            Var_Pos : LexTokenManager.Token_Position;
            Var_Str : LexTokenManager.Lex_String;
         begin
            Var_Str := Node_Lex_String (Node => Var_Node);
            Var_Pos := Node_Position (Node => Var_Node);
            if Dictionary.IsDefined
              (Name              => Var_Str,
               Scope             => Scope,
               Context           => Dictionary.ProofContext,
               Full_Package_Name => False) then
               ErrorHandler.Semantic_Error
                 (Err_Num   => 10,
                  Reference => ErrorHandler.No_Reference,
                  Position  => Var_Pos,
                  Id_Str    => Var_Str);
            elsif Mode.Is_Valid then
               Dictionary.AddConstituent
                 (Name                 => Var_Str,
                  Subject              => Subject_Sym,
                  Mode                 => Mode.Value,
                  SubjectReference     => Dictionary.Location'(Start_Position => Subject_Loc,
                                                               End_Position   => Subject_Loc),
                  Comp_Unit            => ContextManager.Ops.Current_Unit,
                  ConstituentReference => Dictionary.Location'(Start_Position => Var_Pos,
                                                               End_Position   => Var_Pos));
            end if;
         end Do_Concrete_Constituent;

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

         procedure Do_Embedded_Constituent
           (Pack_Node   : in STree.SyntaxNode;
            Var_Node    : in STree.SyntaxNode;
            Scope       : in Dictionary.Scopes;
            Subject_Sym : in Dictionary.Symbol;
            Mode        : in Modes;
            Subject_Loc : in LexTokenManager.Token_Position)
         --# 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            from *,
         --#                                         CommandLineData.Content,
         --#                                         ContextManager.Ops.Unit_Stack,
         --#                                         LexTokenManager.State,
         --#                                         Mode,
         --#                                         Pack_Node,
         --#                                         Scope,
         --#                                         STree.Table,
         --#                                         Subject_Sym,
         --#                                         Var_Node &
         --#         ErrorHandler.Error_Context from *,
         --#                                         CommandLineData.Content,
         --#                                         Dictionary.Dict,
         --#                                         LexTokenManager.State,
         --#                                         Pack_Node,
         --#                                         Scope,
         --#                                         SPARK_IO.File_Sys,
         --#                                         STree.Table,
         --#                                         Var_Node &
         --#         SPARK_IO.File_Sys          from *,
         --#                                         CommandLineData.Content,
         --#                                         ContextManager.Ops.Unit_Stack,
         --#                                         Dictionary.Dict,
         --#                                         ErrorHandler.Error_Context,
         --#                                         LexTokenManager.State,
         --#                                         Mode,
         --#                                         Pack_Node,
         --#                                         Scope,
         --#                                         STree.Table,
         --#                                         Subject_Loc,
         --#                                         Subject_Sym,
         --#                                         Var_Node &
         --#         STree.Table                from *,
         --#                                         CommandLineData.Content,
         --#                                         Dictionary.Dict,
         --#                                         LexTokenManager.State,
         --#                                         Pack_Node,
         --#                                         Scope;
         --# pre Syntax_Node_Type (Pack_Node, STree.Table) = SP_Symbols.identifier and
         --#   Syntax_Node_Type (Var_Node, STree.Table) = SP_Symbols.identifier;
         --# post STree.Table = STree.Table~;
         is
            Pack_Sym  : Dictionary.Symbol;
            Pack_Pos  : LexTokenManager.Token_Position;
            Pack_Str  : LexTokenManager.Lex_String;
            Var_Sym   : Dictionary.Symbol;
            Var_Pos   : LexTokenManager.Token_Position;
            Var_Str   : LexTokenManager.Lex_String;
            Ok_To_Add : Boolean;
         begin
            Ok_To_Add := False;
            Pack_Str  := Node_Lex_String (Node => Pack_Node);
            Pack_Pos  := Node_Position (Node => Pack_Node);
            Var_Str   := Node_Lex_String (Node => Var_Node);
            Var_Pos   := Node_Position (Node => Var_Node);
            Pack_Sym  :=
              Dictionary.LookupItem
              (Name              => Pack_Str,
               Scope             => Scope,
               Context           => Dictionary.ProofContext,
               Full_Package_Name => False);
            if Dictionary.Is_Null_Symbol (Pack_Sym) then
               Ok_To_Add := True;
            elsif Dictionary.IsPackage (Pack_Sym) then
               if Dictionary.GetContext (Pack_Sym) = Dictionary.ProgramContext then
                  ErrorHandler.Semantic_Error
                    (Err_Num   => 75,
                     Reference => ErrorHandler.No_Reference,
                     Position  => Pack_Pos,
                     Id_Str    => Pack_Str);
               else
                  STree.Set_Node_Lex_String (Sym  => Pack_Sym,
                                             Node => Pack_Node);
                  Var_Sym :=
                    Dictionary.LookupSelectedItem
                    (Prefix   => Pack_Sym,
                     Selector => Var_Str,
                     Scope    => Scope,
                     Context  => Dictionary.ProofContext);
                  if Dictionary.Is_Null_Symbol (Var_Sym) then
                     Ok_To_Add := True;
                  else
                     ErrorHandler.Semantic_Error
                       (Err_Num   => 10,
                        Reference => ErrorHandler.No_Reference,
                        Position  => Var_Pos,
                        Id_Str    => Var_Str);
                  end if;
               end if;
            else
               ErrorHandler.Semantic_Error
                 (Err_Num   => 76,
                  Reference => ErrorHandler.No_Reference,
                  Position  => Pack_Pos,
                  Id_Str    => Pack_Str);
            end if;

            if Ok_To_Add and then Mode.Is_Valid then
               Dictionary.AddEmbeddedConstituent
                 (PackageName          => Pack_Str,
                  VariableName         => Var_Str,
                  Subject              => Subject_Sym,
                  Mode                 => Mode.Value,
                  SubjectReference     => Dictionary.Location'(Start_Position => Subject_Loc,
                                                               End_Position   => Subject_Loc),
                  Comp_Unit            => ContextManager.Ops.Current_Unit,
                  ConstituentReference => Dictionary.Location'(Start_Position => Var_Pos,
                                                               End_Position   => Var_Pos));
            end if;
         end Do_Embedded_Constituent;

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

         procedure Do_Child_Constituent
           (Pack_D_Simple_Name_Node : in STree.SyntaxNode;
            Var_Node                : in STree.SyntaxNode;
            Scope                   : in Dictionary.Scopes;
            Subject_Sym             : in Dictionary.Symbol;
            Mode                    : in Modes;
            Subject_Loc             : in LexTokenManager.Token_Position)
         --# 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            from *,
         --#                                         CommandLineData.Content,
         --#                                         ContextManager.Ops.Unit_Stack,
         --#                                         LexTokenManager.State,
         --#                                         Mode,
         --#                                         Pack_D_Simple_Name_Node,
         --#                                         Scope,
         --#                                         STree.Table,
         --#                                         Subject_Sym,
         --#                                         Var_Node &
         --#         ErrorHandler.Error_Context from *,
         --#                                         CommandLineData.Content,
         --#                                         Dictionary.Dict,
         --#                                         LexTokenManager.State,
         --#                                         Mode,
         --#                                         Pack_D_Simple_Name_Node,
         --#                                         Scope,
         --#                                         SPARK_IO.File_Sys,
         --#                                         STree.Table,
         --#                                         Subject_Sym,
         --#                                         Var_Node &
         --#         SPARK_IO.File_Sys          from *,
         --#                                         CommandLineData.Content,
         --#                                         ContextManager.Ops.Unit_Stack,
         --#                                         Dictionary.Dict,
         --#                                         ErrorHandler.Error_Context,
         --#                                         LexTokenManager.State,
         --#                                         Mode,
         --#                                         Pack_D_Simple_Name_Node,
         --#                                         Scope,
         --#                                         STree.Table,
         --#                                         Subject_Loc,
         --#                                         Subject_Sym,
         --#                                         Var_Node &
         --#         STree.Table                from *,
         --#                                         CommandLineData.Content,
         --#                                         Dictionary.Dict,
         --#                                         LexTokenManager.State,
         --#                                         Pack_D_Simple_Name_Node,
         --#                                         Scope,
         --#                                         Subject_Sym,
         --#                                         Var_Node;
         --# pre Syntax_Node_Type (Pack_D_Simple_Name_Node, STree.Table) = SP_Symbols.dotted_simple_name and
         --#   Syntax_Node_Type (Var_Node, STree.Table) = SP_Symbols.identifier;
         --# post STree.Table = STree.Table~;
         is
            Pack_Sym  : Dictionary.Symbol;
            Pack_Pos  : LexTokenManager.Token_Position;
            Pack_Str  : LexTokenManager.Lex_String;
            Pack_Node : STree.SyntaxNode;
            Var_Sym   : Dictionary.Symbol;
            Var_Pos   : LexTokenManager.Token_Position;
            Var_Str   : LexTokenManager.Lex_String;
            Owner     : Dictionary.Symbol;
            Err_Num   : Natural;
         begin
            Pack_Node := Last_Child_Of (Start_Node => Pack_D_Simple_Name_Node);
            -- ASSUME Pack_Node = identifier
            SystemErrors.RT_Assert
              (C       => Syntax_Node_Type (Node => Pack_Node) = SP_Symbols.identifier,
               Sys_Err => SystemErrors.Invalid_Syntax_Tree,
               Msg     => "Expect Pack_Node = identifier in Do_Child_Constituent");
            Pack_Str := Node_Lex_String (Node => Pack_Node);
            Pack_Pos := Node_Position (Node => Pack_Node);
            Pack_Sym :=
              Dictionary.LookupItem
              (Name              => Pack_Str,
               Scope             => Dictionary.GlobalScope,
               Context           => Dictionary.ProofContext,
               Full_Package_Name => False);
            loop
               --# assert Syntax_Node_Type (Var_Node, STree.Table) = SP_Symbols.identifier and
               --#   Syntax_Node_Type (Pack_Node, STree.Table) = SP_Symbols.identifier and
               --#   STree.Table = STree.Table~;
               if Dictionary.Is_Null_Symbol (Pack_Sym) then
                  ErrorHandler.Semantic_Error
                    (Err_Num   => 137,
                     Reference => ErrorHandler.No_Reference,
                     Position  => Pack_Pos,
                     Id_Str    => Pack_Str);
                  exit;
               end if;

               if not Dictionary.IsPackage (Pack_Sym) then
                  ErrorHandler.Semantic_Error
                    (Err_Num   => 18,
                     Reference => ErrorHandler.No_Reference,
                     Position  => Pack_Pos,
                     Id_Str    => Pack_Str);
                  Pack_Sym := Dictionary.NullSymbol;
                  exit;
               end if;

               STree.Set_Node_Lex_String (Sym  => Pack_Sym,
                                          Node => Pack_Node);
               Pack_Node := Next_Sibling (Current_Node => Parent_Node (Current_Node => Pack_Node));
               -- ASSUME Pack_Node = identifier
               SystemErrors.RT_Assert
                 (C       => Syntax_Node_Type (Node => Pack_Node) = SP_Symbols.identifier,
                  Sys_Err => SystemErrors.Invalid_Syntax_Tree,
                  Msg     => "Expect Pack_Node = identifier in Do_Child_Constituent");

               exit when Pack_Node = Var_Node;

               Pack_Str := Node_Lex_String (Node => Pack_Node);
               Pack_Pos := Node_Position (Node => Pack_Node);
               Pack_Sym :=
                 Dictionary.LookupSelectedItem
                 (Prefix   => Pack_Sym,
                  Selector => Pack_Str,
                  Scope    => Dictionary.GlobalScope,
                  Context  => Dictionary.ProofContext);
            end loop;

            if not Dictionary.Is_Null_Symbol (Pack_Sym) then
               Owner := Dictionary.GetRegion (Scope);
               if not Dictionary.Packages_Are_Equal
                 (Left_Symbol  => Dictionary.GetPackageOwner (Pack_Sym),
                  Right_Symbol => Owner) then
                  -- package not owned by subject package
                  ErrorHandler.Semantic_Error
                    (Err_Num   => 619,
                     Reference => ErrorHandler.No_Reference,
                     Position  => Pack_Pos,
                     Id_Str    => Pack_Str);
               else
                  Var_Str := Node_Lex_String (Node => Var_Node);
                  Var_Pos := Node_Position (Node => Var_Node);
                  Var_Sym :=
                    Dictionary.LookupSelectedItem
                    (Prefix   => Pack_Sym,
                     Selector => Var_Str,
                     Scope    => Scope,
                     Context  => Dictionary.ProofContext);
                  if Dictionary.Is_Null_Symbol (Var_Sym) then
                     -- constituent own variable not found
                     ErrorHandler.Semantic_Error
                       (Err_Num   => 138,
                        Reference => ErrorHandler.No_Reference,
                        Position  => Var_Pos,
                        Id_Str    => Var_Str);
                  elsif not Dictionary.IsOwnVariable (Var_Sym) then
                     ErrorHandler.Semantic_Error
                       (Err_Num   => 74,
                        Reference => ErrorHandler.No_Reference,
                        Position  => Var_Pos,
                        Id_Str    => Var_Str);
                  elsif Dictionary.IsRefinementConstituent (Owner, Var_Sym) then
                     -- already declared as constituent
                     ErrorHandler.Semantic_Error
                       (Err_Num   => 10,
                        Reference => ErrorHandler.No_Reference,
                        Position  => Var_Pos,
                        Id_Str    => Var_Str);
                  else -- valid constituent
                     if Dictionary.OwnVariableIsInitialized (Subject_Sym) /= Dictionary.OwnVariableIsInitialized (Var_Sym) then
                        -- subject and constituent have different initialization
                        if Dictionary.OwnVariableIsInitialized (Subject_Sym) then
                           -- if subject is initialized and constituent is not then
                           -- it is only an error if the constituent is not a stream var
                           if Dictionary.GetOwnVariableOrConstituentMode (Var_Sym) = Dictionary.DefaultMode then
                              ErrorHandler.Semantic_Error
                                (Err_Num   => 622,
                                 Reference => ErrorHandler.No_Reference,
                                 Position  => Var_Pos,
                                 Id_Str    => Var_Str);
                           else
                              STree.Set_Node_Lex_String (Sym  => Var_Sym,
                                                         Node => Var_Node);
                           end if;
                        else
                           ErrorHandler.Semantic_Error
                             (Err_Num   => 623,
                              Reference => ErrorHandler.No_Reference,
                              Position  => Var_Pos,
                              Id_Str    => Var_Str);
                        end if;
                     else
                        STree.Set_Node_Lex_String (Sym  => Var_Sym,
                                                   Node => Var_Node);
                     end if;

                     -- constituent must have same mode as own variable it being
                     -- associated with
                     if Mode.Value /= Dictionary.GetOwnVariableMode (Var_Sym) then
                        if Dictionary.GetOwnVariableMode (Var_Sym) = Dictionary.InMode then
                           Err_Num := 705; -- must be IN
                        elsif Dictionary.GetOwnVariableMode (Var_Sym) = Dictionary.OutMode then
                           Err_Num := 706; -- must be OUT
                        else
                           Err_Num := 707; -- no mode permitted
                        end if;
                        ErrorHandler.Semantic_Error
                          (Err_Num   => Err_Num,
                           Reference => ErrorHandler.No_Reference,
                           Position  => Var_Pos,
                           Id_Str    => Var_Str);
                     end if;
                     -- end of mode checks

                     if Mode.Is_Valid then
                        Dictionary.AddChildConstituent
                          (Variable             => Var_Sym,
                           Subject              => Subject_Sym,
                           Mode                 => Mode.Value,
                           SubjectReference     => Dictionary.Location'(Start_Position => Subject_Loc,
                                                                        End_Position   => Subject_Loc),
                           Comp_Unit            => ContextManager.Ops.Current_Unit,
                           ConstituentReference => Dictionary.Location'(Start_Position => Var_Pos,
                                                                        End_Position   => Var_Pos));
                     end if;
                  end if;
               end if;
            end if;
         end Do_Child_Constituent;

      begin -- Do_Constituent
         First_Node := Child_Node (Current_Node => Child_Node (Current_Node => Constituent_Node));
         -- ASSUME First_Node = dotted_simple_name OR identifier
         if Syntax_Node_Type (Node => First_Node) = SP_Symbols.identifier then
            -- ASSUME First_Node = identifier
            Do_Concrete_Constituent
              (Var_Node    => First_Node,
               Scope       => Scope,
               Subject_Sym => Subject_Sym,
               Mode        => Mode,
               Subject_Loc => Subject_Loc);
         elsif Syntax_Node_Type (Node => First_Node) = SP_Symbols.dotted_simple_name then
            -- ASSUME First_Node = dotted_simple_name
            Second_Node := Next_Sibling (Current_Node => First_Node);
            -- ASSUME Second_Node = identifier
            SystemErrors.RT_Assert
              (C       => Syntax_Node_Type (Node => Second_Node) = SP_Symbols.identifier,
               Sys_Err => SystemErrors.Invalid_Syntax_Tree,
               Msg     => "Expect Second_Node = identifier in Do_Constituent");
            Child_First_Node := Child_Node (Current_Node => First_Node);
            -- ASSUME Child_First_Node = dotted_simple_name OR identifier
            if Syntax_Node_Type (Node => Child_First_Node) = SP_Symbols.identifier then
               -- ASSUME Child_First_Node = identifier
               Do_Embedded_Constituent
                 (Pack_Node   => Child_First_Node,
                  Var_Node    => Second_Node,
                  Scope       => Scope,
                  Subject_Sym => Subject_Sym,
                  Mode        => Mode,
                  Subject_Loc => Subject_Loc);
            elsif Syntax_Node_Type (Node => Child_First_Node) = SP_Symbols.dotted_simple_name then
               -- ASSUME Child_First_Node = dotted_simple_name
               if CommandLineData.Content.Language_Profile /= CommandLineData.SPARK83 then
                  Do_Child_Constituent
                    (Pack_D_Simple_Name_Node => Child_First_Node,
                     Var_Node                => Second_Node,
                     Scope                   => Scope,
                     Subject_Sym             => Subject_Sym,
                     Mode                    => Mode,
                     Subject_Loc             => Subject_Loc);
               else
                  ErrorHandler.Semantic_Error
                    (Err_Num   => 156,
                     Reference => ErrorHandler.No_Reference,
                     Position  => Node_Position (Node => Constituent_Node),
                     Id_Str    => LexTokenManager.Null_String);
               end if;
            else
               SystemErrors.Fatal_Error
                 (Sys_Err => SystemErrors.Invalid_Syntax_Tree,
                  Msg     => "Expect Child_First_Node = dotted_simple_name OR identifier in Do_Constituent");
            end if;
         else
            SystemErrors.Fatal_Error
              (Sys_Err => SystemErrors.Invalid_Syntax_Tree,
               Msg     => "Expect First_Node = dotted_simple_name OR identifier in Do_Constituent");
         end if;
      end Do_Constituent;

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

      procedure Check_Modifier (Node        : in     STree.SyntaxNode;
                                Subject_Sym : in     Dictionary.Symbol;
                                Mode        :    out Modes)
      --# global in     CommandLineData.Content;
      --#        in     Dictionary.Dict;
      --#        in     LexTokenManager.State;
      --#        in     STree.Table;
      --#        in out ErrorHandler.Error_Context;
      --#        in out SPARK_IO.File_Sys;
      --# derives ErrorHandler.Error_Context,
      --#         SPARK_IO.File_Sys          from CommandLineData.Content,
      --#                                         Dictionary.Dict,
      --#                                         ErrorHandler.Error_Context,
      --#                                         LexTokenManager.State,
      --#                                         Node,
      --#                                         SPARK_IO.File_Sys,
      --#                                         STree.Table,
      --#                                         Subject_Sym &
      --#         Mode                       from Dictionary.Dict,
      --#                                         Node,
      --#                                         STree.Table,
      --#                                         Subject_Sym;
      --# pre Syntax_Node_Type (Node, STree.Table) = SP_Symbols.own_variable_modifier;
      is
         Modifier_Node, Err_Node, Mode_Node : STree.SyntaxNode;
         Subject_Mode                       : Dictionary.Modes;
      begin
         Subject_Mode := Dictionary.GetOwnVariableMode (Subject_Sym);
         Mode         := Modes'(Value    => Dictionary.DefaultMode,
                                Is_Valid => False);
         Err_Node     := Next_Sibling (Current_Node => Node);
         -- ASSUME Err_Node = entire_variable
         SystemErrors.RT_Assert
           (C       => Syntax_Node_Type (Node => Err_Node) = SP_Symbols.entire_variable,
            Sys_Err => SystemErrors.Invalid_Syntax_Tree,
            Msg     => "Expect Err_Node = entire_variable in Check_Modifier");

         Modifier_Node := Child_Node (Current_Node => Node);
         -- ASSUME Modifier_Node = mode OR protected_modifier OR protected_moded_modifier OR task_modifier
         case Syntax_Node_Type (Node => Modifier_Node) is
            when SP_Symbols.mode =>
               -- ASSUME Modifier_Node = mode
               Mode_Node := Child_Node (Current_Node => Modifier_Node);
               -- ASSUME Mode_Node = in_mode OR inout_mode OR out_mode OR NULL
               if Mode_Node = STree.NullNode then
                  -- ASSUME Mode_Node = NULL
                  -- Default is legal only if subject is Default
                  if Subject_Mode = Dictionary.DefaultMode then
                     Mode := Modes'(Value    => Dictionary.DefaultMode,
                                    Is_Valid => True);
                  else
                     ErrorHandler.Semantic_Error
                       (Err_Num   => 701,
                        Reference => ErrorHandler.No_Reference,
                        Position  => Node_Position (Node => Err_Node),
                        Id_Str    => Dictionary.GetSimpleName (Subject_Sym));
                  end if;
               else
                  -- ASSUME Mode_Node = in_mode OR inout_mode OR out_mode
                  case Syntax_Node_Type (Node => Mode_Node) is
                     when SP_Symbols.in_mode =>
                        -- ASSUME Mode_Node = in_mode
                        -- IN is legal if subject is IN or subject if Default
                        if Subject_Mode = Dictionary.DefaultMode or else Subject_Mode = Dictionary.InMode then
                           Mode := Modes'(Value    => Dictionary.InMode,
                                          Is_Valid => True);
                        else
                           ErrorHandler.Semantic_Error
                             (Err_Num   => 701,
                              Reference => ErrorHandler.No_Reference,
                              Position  => Node_Position (Node => Err_Node),
                              Id_Str    => Dictionary.GetSimpleName (Subject_Sym));
                        end if;
                     when SP_Symbols.out_mode =>
                        -- ASSUME Mode_Node = out_mode
                        -- OUT is legal if subject is OUT or subject if Default
                        if Subject_Mode = Dictionary.DefaultMode or else Subject_Mode = Dictionary.OutMode then
                           Mode := Modes'(Value    => Dictionary.OutMode,
                                          Is_Valid => True);
                        else
                           ErrorHandler.Semantic_Error
                             (Err_Num   => 701,
                              Reference => ErrorHandler.No_Reference,
                              Position  => Node_Position (Node => Err_Node),
                              Id_Str    => Dictionary.GetSimpleName (Subject_Sym));
                        end if;
                     when SP_Symbols.inout_mode =>
                        -- ASSUME Mode_Node = inout_mode
                        ErrorHandler.Semantic_Error
                          (Err_Num   => 700,
                           Reference => ErrorHandler.No_Reference,
                           Position  => Node_Position (Node => Err_Node),
                           Id_Str    => LexTokenManager.Null_String);
                     when others =>
                        SystemErrors.Fatal_Error
                          (Sys_Err => SystemErrors.Invalid_Syntax_Tree,
                           Msg     => "Expect Mode_Node = in_mode OR inout_mode OR out_mode OR NULL in Check_Modifier");
                  end case;
               end if;
            when SP_Symbols.protected_modifier =>
               -- ASSUME Modifier_Node = protected_modifier
               -- Refinement constituents cannot be protected.
               ErrorHandler.Semantic_Error
                 (Err_Num   => 859,
                  Reference => ErrorHandler.No_Reference,
                  Position  => Node_Position (Node => Err_Node),
                  Id_Str    => Dictionary.GetSimpleName (Subject_Sym));
            when SP_Symbols.protected_moded_modifier | SP_Symbols.task_modifier =>
               -- ASSUME Modifier_Node = protected_moded_modifier OR task_modifier
               null;
            when others =>
               SystemErrors.Fatal_Error
                 (Sys_Err => SystemErrors.Invalid_Syntax_Tree,
                  Msg     => "Expect Modifier_Node = mode OR protected_modifier OR " &
                    "protected_moded_modifier OR task_modifier in Check_Modifier");
         end case;
      end Check_Modifier;

   begin -- Do_Constituent_List
      It :=
        Find_First_Node
        (Node_Kind    => SP_Symbols.own_variable_modifier,
         From_Root    => Constituent_List_Node,
         In_Direction => STree.Down);
      while not STree.IsNull (It) loop
         Constituent_Node := Get_Node (It => It);
         --# assert Syntax_Node_Type (Constituent_Node, STree.Table) = SP_Symbols.own_variable_modifier and
         --#   Constituent_Node = Get_Node (It) and
         --#   STree.Table = STree.Table~;
         Check_Modifier (Node        => Constituent_Node,
                         Subject_Sym => Subject_Sym,
                         Mode        => Mode);
         Constituent_Node := Next_Sibling (Current_Node => Constituent_Node);
         -- ASSUME Constituent_Node = entire_variable
         SystemErrors.RT_Assert
           (C       => Syntax_Node_Type (Node => Constituent_Node) = SP_Symbols.entire_variable,
            Sys_Err => SystemErrors.Invalid_Syntax_Tree,
            Msg     => "Expect Constituent_Node = entire_variable in Do_Constituent_List");
         Do_Constituent
           (Constituent_Node => Constituent_Node,
            Scope            => Scope,
            Subject_Sym      => Subject_Sym,
            Mode             => Mode,
            Subject_Loc      => Subject_Loc);
         It := STree.NextNode (It);
      end loop;
   end Do_Constituent_List;

begin -- Wf_Clause
   Subject_Node := Child_Node (Current_Node => Node);
   -- ASSUME Subject_Node = identifier
   SystemErrors.RT_Assert
     (C       => Syntax_Node_Type (Node => Subject_Node) = SP_Symbols.identifier,
      Sys_Err => SystemErrors.Invalid_Syntax_Tree,
      Msg     => "Expect Subject_Node = identifier in Wf_Clause");
   Subject_Loc      := Node_Position (Node => Subject_Node);
   Constituent_Node := Next_Sibling (Current_Node => Subject_Node);
   -- ASSUME Constituent_Node = constituent_list OR NULL
   if Constituent_Node = STree.NullNode then
      -- ASSUME Constituent_Node = NULL
      -- There is _no_ constituent node at all.  This used to be
      -- rejected by the gammar alone, but this resulted in a poor
      -- error message, and it's a common "beginner" mistake.
      -- The grammar now accepts this, so we can detect and reject it
      -- here with a much better message.
      ErrorHandler.Semantic_Error
        (Err_Num   => 115,
         Reference => ErrorHandler.No_Reference,
         Position  => Subject_Loc,
         Id_Str    => LexTokenManager.Null_String);
   elsif Syntax_Node_Type (Node => Constituent_Node) = SP_Symbols.constituent_list then
      -- ASSUME Constituent_Node = constituent_list
      Do_Subject (Subject_Node => Subject_Node,
                  Scope        => Scope,
                  Subject_Sym  => Subject_Sym);
      if not Dictionary.Is_Null_Symbol (Subject_Sym) then
         Do_Constituent_List
           (Constituent_List_Node => Constituent_Node,
            Scope                 => Scope,
            Subject_Sym           => Subject_Sym,
            Subject_Loc           => Subject_Loc);
      end if;
   else
      SystemErrors.Fatal_Error
        (Sys_Err => SystemErrors.Invalid_Syntax_Tree,
         Msg     => "Expect Constituent_Node = constituent_list OR NULL in Wf_Clause");
   end if;

end Wf_Clause;
