-------------------------------------------------------------------------------
-- (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_Package_Declaration.Wf_Package_Specification.Wf_Anno)
procedure Wf_Own
  (Node       : in     STree.SyntaxNode;
   Pack_Sym   : in     Dictionary.Symbol;
   Scope_Type : in     Enclosing_Scope_Types;
   Scope      : in     Dictionary.Scopes;
   The_Heap   : in out Heap.HeapRecord)
is
   It        : STree.Iterator;
   Next_Node : STree.SyntaxNode;

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

   procedure Wf_Own_Variable_Specification
     (Node       : in     STree.SyntaxNode;
      Pack_Sym   : in     Dictionary.Symbol;
      Scope_Type : in     Enclosing_Scope_Types;
      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,
   --#                                         Pack_Sym,
   --#                                         Scope,
   --#                                         Scope_Type,
   --#                                         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,
   --#                                         Pack_Sym,
   --#                                         Scope,
   --#                                         Scope_Type,
   --#                                         SLI.State,
   --#                                         SPARK_IO.File_Sys,
   --#                                         STree.Table,
   --#                                         The_Heap;
   --# pre Syntax_Node_Type (Node, STree.Table) = SP_Symbols.own_variable_specification;
   --# post STree.Table = STree.Table~;
   is
      type Wff_Rules is (Use_Embedded, Use_Library);
      type Modes is record
         Value    : Dictionary.Modes;
         Is_Valid : Boolean;
      end record;

      Wff_Rule                                                              : Wff_Rules;
      Type_Announced                                                        : Boolean;
      Type_Node, Property_List_Node, Ident_List_Node, Ident_Node, Next_Node : STree.SyntaxNode;
      It                                                                    : STree.Iterator;
      Mode                                                                  : Modes;
      Is_Protected, Is_Task                                                 : Boolean;
      Announced_Type                                                        : Dictionary.Symbol;
      Type_To_Use                                                           : Dictionary.Symbol;
      Own_Var_Sym                                                           : Dictionary.Symbol;
      Ident_Str                                                             : LexTokenManager.Lex_String;
      Valid                                                                 : Boolean;

      procedure Check_Own_Var_Type
        (Node     : in     STree.SyntaxNode;
         Pack_Sym : in     Dictionary.Symbol;
         Scope    : in     Dictionary.Scopes;
         Type_Sym :    out Dictionary.Symbol)
      --# 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,
      --#         Type_Sym                   from CommandLineData.Content,
      --#                                         ContextManager.Ops.Unit_Stack,
      --#                                         Dictionary.Dict,
      --#                                         LexTokenManager.State,
      --#                                         Node,
      --#                                         Pack_Sym,
      --#                                         Scope,
      --#                                         STree.Table &
      --#         ErrorHandler.Error_Context from *,
      --#                                         CommandLineData.Content,
      --#                                         Dictionary.Dict,
      --#                                         LexTokenManager.State,
      --#                                         Node,
      --#                                         Scope,
      --#                                         SPARK_IO.File_Sys,
      --#                                         STree.Table &
      --#         SPARK_IO.File_Sys          from *,
      --#                                         CommandLineData.Content,
      --#                                         ContextManager.Ops.Unit_Stack,
      --#                                         Dictionary.Dict,
      --#                                         ErrorHandler.Error_Context,
      --#                                         LexTokenManager.State,
      --#                                         Node,
      --#                                         Pack_Sym,
      --#                                         Scope,
      --#                                         STree.Table;
      --# pre Syntax_Node_Type (Node, STree.Table) = SP_Symbols.type_mark;
      --# post (Dictionary.Is_Null_Symbol (Type_Sym) or Dictionary.IsTypeMark (Type_Sym, Dictionary.Dict)) and STree.Table = STree.Table~;
      is
         Type_String  : LexTokenManager.Lex_String;
         Current_Node : STree.SyntaxNode;
      begin
         Current_Node := Child_Node (Current_Node => Child_Node (Current_Node => Node));
         -- ASSUME Current_Node = identifier OR dotted_simple_name
         if Syntax_Node_Type (Node => Current_Node) = SP_Symbols.identifier then
            -- ASSUME Current_Node = identifier
            -- simple identifier which either exists or is an announcement
            Type_String := Node_Lex_String (Node => Current_Node);
            Type_Sym    :=
              Dictionary.LookupItem
              (Name              => Type_String,
               Scope             => Scope,
               Context           => Dictionary.ProofContext,
               Full_Package_Name => False);
            if Dictionary.Is_Null_Symbol (Type_Sym) then
               -- process type announcement
               Dictionary.Add_Type_Announcement
                 (Name        => Type_String,
                  Comp_Unit   => ContextManager.Ops.Current_Unit,
                  Declaration => Dictionary.Location'(Start_Position => Node_Position (Node => Current_Node),
                                                      End_Position   => Node_Position (Node => Current_Node)),
                  The_Package => Pack_Sym,
                  The_Type    => Type_Sym);
               STree.Add_Node_Symbol (Node => Current_Node,
                                      Sym  => Type_Sym);
            elsif not Dictionary.IsTypeMark (Type_Sym) then
               -- illegal type mark
               Type_Sym := Dictionary.GetUnknownTypeMark;
               ErrorHandler.Semantic_Error
                 (Err_Num   => 63,
                  Reference => ErrorHandler.No_Reference,
                  Position  => Node_Position (Node => Current_Node),
                  Id_Str    => Type_String);
            else
               STree.Set_Node_Lex_String (Sym  => Type_Sym,
                                          Node => Current_Node);
            end if;
         elsif Syntax_Node_Type (Node => Current_Node) = SP_Symbols.dotted_simple_name then
            -- ASSUME Current_Node = dotted_simple_name
            -- dotted identifier, this must already exist as type
            Wf_Type_Mark (Node          => Node,
                          Current_Scope => Scope,
                          Context       => Dictionary.ProofContext,
                          Type_Sym      => Type_Sym);
            -- check to prevent use of abstract proof types outside their package
            if Dictionary.TypeIsAbstractProof (Type_Sym) then
               ErrorHandler.Semantic_Error_Sym
                 (Err_Num   => 148,
                  Reference => ErrorHandler.No_Reference,
                  Position  => Node_Position (Node => Node),
                  Sym       => Type_Sym,
                  Scope     => Scope);
               Type_Sym := Dictionary.GetUnknownTypeMark;
            end if;
         else
            Type_Sym := Dictionary.NullSymbol;
            SystemErrors.Fatal_Error
              (Sys_Err => SystemErrors.Invalid_Syntax_Tree,
               Msg     => "Expect Current_Node = identifier OR dotted_simple_name in Check_Own_Var_Type");
         end if;
      end Check_Own_Var_Type;

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

      procedure Check_Modifiers
        (Node           : in     STree.SyntaxNode;
         Ident_Node     : in     STree.SyntaxNode;
         Announced_Type : in     Dictionary.Symbol;
         Mode           :    out Modes;
         Is_Protected   :    out Boolean;
         Is_Task        :    out Boolean;
         Valid          :    out Boolean)
      --# 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 Announced_Type,
      --#                                         CommandLineData.Content,
      --#                                         Dictionary.Dict,
      --#                                         ErrorHandler.Error_Context,
      --#                                         Ident_Node,
      --#                                         LexTokenManager.State,
      --#                                         Node,
      --#                                         SPARK_IO.File_Sys,
      --#                                         STree.Table &
      --#         Is_Protected,
      --#         Is_Task,
      --#         Mode                       from Node,
      --#                                         STree.Table &
      --#         Valid                      from Announced_Type,
      --#                                         CommandLineData.Content,
      --#                                         Dictionary.Dict,
      --#                                         Node,
      --#                                         STree.Table;
      --# pre Syntax_Node_Type (Node, STree.Table) = SP_Symbols.own_variable_modifier and
      --#   Syntax_Node_Type (Ident_Node, STree.Table) = SP_Symbols.identifier;
      is
         Modifier_Node, From_Node : STree.SyntaxNode;
         Err_Node_Pos             : LexTokenManager.Token_Position;

         procedure Get_Mode
           (From_Node    : in     STree.SyntaxNode;
            Err_Node_Pos : in     LexTokenManager.Token_Position;
            The_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,
         --#                                         Err_Node_Pos,
         --#                                         From_Node,
         --#                                         LexTokenManager.State,
         --#                                         SPARK_IO.File_Sys,
         --#                                         STree.Table &
         --#         The_Mode                   from From_Node,
         --#                                         STree.Table;
         --# pre Syntax_Node_Type (From_Node, STree.Table) = SP_Symbols.in_mode or
         --#   Syntax_Node_Type (From_Node, STree.Table) = SP_Symbols.inout_mode or
         --#   Syntax_Node_Type (From_Node, STree.Table) = SP_Symbols.out_mode or
         --#   From_Node = STree.NullNode;
         is
         begin
            The_Mode := Modes'(Value    => Dictionary.DefaultMode,
                               Is_Valid => True);
            if From_Node /= STree.NullNode then
               -- Mode is present
               case Syntax_Node_Type (Node => From_Node) is
                  when SP_Symbols.in_mode =>
                     -- ASSUME From_Node = in_mode
                     The_Mode := Modes'(Value    => Dictionary.InMode,
                                        Is_Valid => True);
                  when SP_Symbols.out_mode =>
                     -- ASSUME From_Node = out_mode
                     The_Mode := Modes'(Value    => Dictionary.OutMode,
                                        Is_Valid => True);
                  when SP_Symbols.inout_mode =>
                     -- ASSUME From_Node = inout_mode
                     The_Mode := Modes'(Value    => Dictionary.InOutMode,
                                        Is_Valid => False);
                     ErrorHandler.Semantic_Error
                       (Err_Num   => 700,
                        Reference => ErrorHandler.No_Reference,
                        Position  => Err_Node_Pos,
                        Id_Str    => LexTokenManager.Null_String);
                  when others =>
                     SystemErrors.Fatal_Error
                       (Sys_Err => SystemErrors.Invalid_Syntax_Tree,
                        Msg     => "Expect From_Node = in_mode OR inout_mode OR out_mode OR NULL in Get_Mode");
               end case;
            end if;
         end Get_Mode;

      begin -- Check_Modifiers
         Mode         := Modes'(Value    => Dictionary.DefaultMode,
                                Is_Valid => True);
         Is_Protected := False; -- default answers
         Is_Task      := False;

         Err_Node_Pos  := Node_Position (Node => Next_Sibling (Current_Node => Node));
         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
               From_Node := Child_Node (Current_Node => Modifier_Node);
               -- ASSUME From_Node = in_mode OR inout_mode OR out_mode OR NULL
               SystemErrors.RT_Assert
                 (C       => From_Node = STree.NullNode
                    or else Syntax_Node_Type (Node => From_Node) = SP_Symbols.in_mode
                    or else Syntax_Node_Type (Node => From_Node) = SP_Symbols.inout_mode
                    or else Syntax_Node_Type (Node => From_Node) = SP_Symbols.out_mode,
                  Sys_Err => SystemErrors.Invalid_Syntax_Tree,
                  Msg     => "Expect From_Node = in_mode OR inout_mode OR out_mode OR NULL in Check_Modifiers");
               Get_Mode (From_Node    => From_Node,
                         Err_Node_Pos => Err_Node_Pos,
                         The_Mode     => Mode);
            when SP_Symbols.protected_moded_modifier =>
               -- ASSUME Modifier_Node = protected_moded_modifier
               From_Node := Next_Sibling (Current_Node => Child_Node (Current_Node => Modifier_Node));
               -- ASSUME From_Node = in_mode OR out_mode
               SystemErrors.RT_Assert
                 (C       => Syntax_Node_Type (Node => From_Node) = SP_Symbols.in_mode
                    or else Syntax_Node_Type (Node => From_Node) = SP_Symbols.out_mode,
                  Sys_Err => SystemErrors.Invalid_Syntax_Tree,
                  Msg     => "Expect From_Node = in_mode OR out_mode in Check_Modifiers");
               Get_Mode (From_Node    => From_Node,
                         Err_Node_Pos => Err_Node_Pos,
                         The_Mode     => Mode);
               Is_Protected := True;
            when SP_Symbols.protected_modifier =>
               -- ASSUME Modifier_Node = protected_modifier
               Is_Protected := True;
            when SP_Symbols.task_modifier =>
               -- ASSUME Modifier_Node = task_modifier
               Is_Task := True;
            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_Modifiers");
         end case;

         Check_Task_Modifier_Consistency
           (The_Own_Var_Type => Announced_Type,
            The_Var_Type     => Dictionary.NullSymbol,
            Modifier_Is_Task => Is_Task,
            Error_Node       => Ident_Node,
            Consistent       => Valid);

         if Valid then -- make sure we don't get two errors
            Check_Protected_Modifier_Consistency
              (The_Type              => Announced_Type,
               Modifier_Is_Protected => Is_Protected,
               Error_Node            => Ident_Node,
               Consistent            => Valid);
         end if;
      end Check_Modifiers;

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

      procedure Validate
        (Node         : in     STree.SyntaxNode;
         Wff_Rule     : in     Wff_Rules;
         Pack_Sym     : in     Dictionary.Symbol;
         Scope        : in     Dictionary.Scopes;
         Mode         : in     Modes;
         Is_Protected : in     Boolean;
         Is_Task      : in     Boolean;
         Valid        :    out Boolean)
      --# 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,
      --#                                         Is_Protected,
      --#                                         Is_Task,
      --#                                         LexTokenManager.State,
      --#                                         Mode,
      --#                                         Node,
      --#                                         Pack_Sym,
      --#                                         Scope,
      --#                                         SPARK_IO.File_Sys,
      --#                                         STree.Table,
      --#                                         Wff_Rule &
      --#         STree.Table,
      --#         Valid                      from CommandLineData.Content,
      --#                                         Dictionary.Dict,
      --#                                         Is_Protected,
      --#                                         Is_Task,
      --#                                         LexTokenManager.State,
      --#                                         Mode,
      --#                                         Node,
      --#                                         Pack_Sym,
      --#                                         Scope,
      --#                                         STree.Table,
      --#                                         Wff_Rule;
      --# pre Syntax_Node_Type (Node, STree.Table) = SP_Symbols.identifier;
      --# post STree.Table = STree.Table~;
      is
         Ident_Str       : LexTokenManager.Lex_String;
         Enclosing_Scope : Dictionary.Scopes;
         Sym             : Dictionary.Symbol;
         Err_Num         : Natural;
      begin
         Ident_Str := Node_Lex_String (Node => Node);
         Valid     := False;
         case Wff_Rule is
            when Use_Library =>
               if (Is_Task or else Is_Protected) and then not CommandLineData.Ravenscar_Selected then
                  ErrorHandler.Semantic_Error
                    (Err_Num   => 850,
                     Reference => ErrorHandler.No_Reference,
                     Position  => Node_Position (Node => Node),
                     Id_Str    => LexTokenManager.Null_String);
               elsif Dictionary.IsDefined
                 (Name              => Ident_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 => Node),
                     Id_Str    => Ident_Str);
               else
                  Valid := True;
               end if;
            when Use_Embedded =>
               Enclosing_Scope := Dictionary.GetEnclosingScope (Scope);
               Sym             :=
                 Dictionary.LookupSelectedItem
                 (Prefix   => Pack_Sym,
                  Selector => Ident_Str,
                  Scope    => Enclosing_Scope,
                  Context  => Dictionary.ProofContext);
               if (Is_Task or else Is_Protected) and then not CommandLineData.Ravenscar_Selected then
                  ErrorHandler.Semantic_Error
                    (Err_Num   => 850,
                     Reference => ErrorHandler.No_Reference,
                     Position  => Node_Position (Node => Node),
                     Id_Str    => LexTokenManager.Null_String);
               elsif Dictionary.Is_Null_Symbol (Sym)
                 or else not Dictionary.IsRefinementConstituent (Dictionary.GetRegion (Enclosing_Scope), Sym) then
                  ErrorHandler.Semantic_Error
                    (Err_Num   => 88,
                     Reference => ErrorHandler.No_Reference,
                     Position  => Node_Position (Node => Node),
                     Id_Str    => Ident_Str);
               elsif not Dictionary.IsDefined
                 (Name              => Ident_Str,
                  Scope             => Scope,
                  Context           => Dictionary.ProofContext,
                  Full_Package_Name => False)
                 or else (Dictionary.IsOwnVariable (Sym) and not Dictionary.OwnVariableIsAnnounced (Sym)) then
                  -- potentially ok to add, the own variable name matches a refinement
                  -- constituent of the enclosing package, we just need to check that
                  -- any modes are the same, and that the protected status is also the
                  -- same.
                  if Mode.Value = Dictionary.GetConstituentMode (Sym) then
                     Valid := not Is_Protected;
                     if Is_Protected then
                        -- Cannot have protected refinement constituents
                        ErrorHandler.Semantic_Error
                          (Err_Num   => 859,
                           Reference => ErrorHandler.No_Reference,
                           Position  => Node_Position (Node => Node),
                           Id_Str    => Ident_Str);
                     else
                        STree.Set_Node_Lex_String (Sym  => Sym,
                                                   Node => Node);
                     end if;
                  else
                     if Dictionary.GetConstituentMode (Sym) = Dictionary.InMode then
                        Err_Num := 702; -- must be IN
                     elsif Dictionary.GetConstituentMode (Sym) = Dictionary.OutMode then
                        Err_Num := 703; -- must be OUT
                     else
                        Err_Num := 704; -- no mode permitted
                     end if;
                     Valid := False;
                     ErrorHandler.Semantic_Error
                       (Err_Num   => Err_Num,
                        Reference => ErrorHandler.No_Reference,
                        Position  => Node_Position (Node => Node),
                        Id_Str    => Ident_Str);
                  end if;
               else -- illegal redeclaration
                  ErrorHandler.Semantic_Error
                    (Err_Num   => 10,
                     Reference => ErrorHandler.No_Reference,
                     Position  => Node_Position (Node => Node),
                     Id_Str    => Ident_Str);
               end if;
         end case;
      end Validate;

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

      procedure Wf_Own_Task
        (Node           : in     STree.SyntaxNode;
         Ident_Str      : in     LexTokenManager.Lex_String;
         Declaration    : in     Dictionary.Location;
         Type_Announced : in     Boolean;
         Announced_Type : in     Dictionary.Symbol;
         Pack_Sym       : in     Dictionary.Symbol;
         Task_Sym       :    out Dictionary.Symbol)
      --# 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,
      --#         Task_Sym                   from Announced_Type,
      --#                                         ContextManager.Ops.Unit_Stack,
      --#                                         Declaration,
      --#                                         Dictionary.Dict,
      --#                                         Ident_Str,
      --#                                         Pack_Sym,
      --#                                         Type_Announced &
      --#         ErrorHandler.Error_Context,
      --#         SPARK_IO.File_Sys          from CommandLineData.Content,
      --#                                         Dictionary.Dict,
      --#                                         ErrorHandler.Error_Context,
      --#                                         Ident_Str,
      --#                                         LexTokenManager.State,
      --#                                         Node,
      --#                                         SPARK_IO.File_Sys,
      --#                                         STree.Table,
      --#                                         Type_Announced;
      --# pre Syntax_Node_Type (Node, STree.Table) = SP_Symbols.own_variable_specification;
      is
      begin
         if not Type_Announced then
            Task_Sym := Dictionary.NullSymbol;
            -- Tasks must announce their type
            ErrorHandler.Semantic_Error
              (Err_Num   => 925,
               Reference => ErrorHandler.No_Reference,
               Position  => Node_Position (Node => Node),
               Id_Str    => Ident_Str);
         else
            Dictionary.AddOwnTask
              (Name        => Ident_Str,
               Comp_Unit   => ContextManager.Ops.Current_Unit,
               Declaration => Declaration,
               TypeMark    => Announced_Type,
               ThePackage  => Pack_Sym,
               TaskSym     => Task_Sym);
         end if;
      end Wf_Own_Task;

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

      procedure Check_For_Illegal_Multiple_Instances
        (Own_Var_Sym : in Dictionary.Symbol;
         Node_Pos    : in LexTokenManager.Token_Position;
         Scope       : in Dictionary.Scopes)
      --# global in     CommandLineData.Content;
      --#        in     Dictionary.Dict;
      --#        in     LexTokenManager.State;
      --#        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_Pos,
      --#                                         Own_Var_Sym,
      --#                                         Scope,
      --#                                         SPARK_IO.File_Sys;
      is
         It              : Dictionary.Iterator;
         Search_Sym      : Dictionary.Symbol;
         Own_Var_Type    : Dictionary.Symbol;
         Search_Type     : Dictionary.Symbol;
         Duplicate_Found : Boolean := False;
      begin
         -- This restriction only applies to protected own variables
         if Dictionary.GetOwnVariableProtected (Own_Var_Sym)
           and then Dictionary.OwnVariableHasType (OwnVariable => Own_Var_Sym,
                                                   Scope       => Scope) then
            Own_Var_Type := Dictionary.GetType (Own_Var_Sym);
            -- go through all the own variables
            It := Dictionary.FirstOwnVariable (Dictionary.GetRegion (Scope));
            while not Dictionary.IsNullIterator (It) loop
               Search_Sym := Dictionary.CurrentSymbol (It);
               -- don't compare it against itself
               if not Dictionary.Variables_Are_Equal (Left_Symbol  => Search_Sym,
                                                      Right_Symbol => Own_Var_Sym) then
                  if Dictionary.OwnVariableHasType (OwnVariable => Search_Sym,
                                                    Scope       => Scope) then
                     Search_Type := Dictionary.GetType (Search_Sym);
                     -- are the types the same?
                     if Dictionary.Types_Are_Equal
                       (Left_Symbol        => Search_Type,
                        Right_Symbol       => Own_Var_Type,
                        Full_Range_Subtype => False) then
                        -- If either has a protects property then report illegal
                        -- multiple instance of the type.
                        if Dictionary.FirstVirtualElement (Own_Var_Type) /= Dictionary.NullIterator
                          or else Dictionary.FirstVirtualElement (Search_Type) /= Dictionary.NullIterator then
                           ErrorHandler.Semantic_Error_Sym
                             (Err_Num   => 942,
                              Reference => ErrorHandler.No_Reference,
                              Position  => Node_Pos,
                              Sym       => Own_Var_Type,
                              Scope     => Scope);
                           Duplicate_Found := True;
                        end if;
                     end if;
                  end if;
               end if;
               exit when Duplicate_Found;
               It := Dictionary.NextSymbol (It);
            end loop;
         end if;
      end Check_For_Illegal_Multiple_Instances;

   begin -- Wf_Own_Variable_Specification

      -- determine if there is a type announcement and/or properties
      Ident_List_Node := Child_Node (Current_Node => Node);
      -- ASSUME Ident_List_Node = own_variable_list
      SystemErrors.RT_Assert
        (C       => Syntax_Node_Type (Node => Ident_List_Node) = SP_Symbols.own_variable_list,
         Sys_Err => SystemErrors.Invalid_Syntax_Tree,
         Msg     => "Expect Ident_List_Node = own_variable_list in Wf_Own_Variable_Specification");

      Announced_Type := Dictionary.GetUnknownTypeMark;
      Type_Node      := Node; -- so that errors get reported somewhere other than the null node
      Type_Announced := False;

      -- determine what checks we will need to do on each own var
      if Scope_Type = In_Package then
         Wff_Rule := Use_Embedded;
      else
         Wff_Rule := Use_Library;
      end if;

      Next_Node := Next_Sibling (Current_Node => Ident_List_Node);
      -- ASSUME Next_Node = type_mark OR property_list OR NULL
      if Syntax_Node_Type (Node => Next_Node) = SP_Symbols.type_mark then
         -- ASSUME Next_Node = type_mark
         Type_Announced := True;
         Type_Node      := Next_Node;
         Check_Own_Var_Type (Node     => Type_Node,
                             Pack_Sym => Pack_Sym,
                             Scope    => Scope,
                             Type_Sym => Announced_Type);
         Property_List_Node := Next_Sibling (Current_Node => Type_Node);
      elsif Next_Node = STree.NullNode or else Syntax_Node_Type (Node => Next_Node) = SP_Symbols.property_list then
         Property_List_Node := Next_Node;
      else
         Property_List_Node := STree.NullNode;
         SystemErrors.Fatal_Error
           (Sys_Err => SystemErrors.Invalid_Syntax_Tree,
            Msg     => "Expect Next_Node = type_mark OR property_list OR NULL in Wf_Own_Variable_Specification");
      end if;
      -- ASSUME Property_List_Node = property_list OR NULL
      SystemErrors.RT_Assert
        (C       => Property_List_Node = STree.NullNode
           or else Syntax_Node_Type (Node => Property_List_Node) = SP_Symbols.property_list,
         Sys_Err => SystemErrors.Invalid_Syntax_Tree,
         Msg     => "Expect Property_List_Node = property_list OR NULL in Wf_Own_Variable_Specification");

      -- loop through each own variable calling a validate routine for each
      It :=
        Find_First_Node (Node_Kind    => SP_Symbols.own_variable_modifier,
                         From_Root    => Ident_List_Node,
                         In_Direction => STree.Down);
      while not STree.IsNull (It) loop
         Next_Node := Get_Node (It => It);
         SystemErrors.RT_Assert
           (C       => Dictionary.IsTypeMark (Announced_Type),
            Sys_Err => SystemErrors.Invalid_Syntax_Tree,
            Msg     => "Expect Announced_Type to be a type in Wf_Own_Variable_Specification");
         --# assert STree.Table = STree.Table~ and
         --#   Syntax_Node_Type (Next_Node, STree.Table) = SP_Symbols.own_variable_modifier and
         --#   Dictionary.IsTypeMark (Announced_Type, Dictionary.Dict) and
         --#   Next_Node = Get_Node (It);
         Ident_Node := Child_Node (Current_Node => Child_Node (Current_Node => Next_Sibling (Current_Node => Next_Node)));
         -- ASSUME Ident_Node = identifier
         SystemErrors.RT_Assert
           (C       => Syntax_Node_Type (Node => Ident_Node) = SP_Symbols.identifier,
            Sys_Err => SystemErrors.Invalid_Syntax_Tree,
            Msg     => "Expect Ident_Node = identifier in Wf_Own_Variable_Specification");

         Check_Modifiers
           (Node           => Next_Node,
            Ident_Node     => Ident_Node,
            Announced_Type => Announced_Type,
            Mode           => Mode,
            Is_Protected   => Is_Protected,
            Is_Task        => Is_Task,
            Valid          => Valid);
         if Valid then
            Validate
              (Node         => Ident_Node,
               Wff_Rule     => Wff_Rule,
               Pack_Sym     => Pack_Sym,
               Scope        => Scope,
               Mode         => Mode,
               Is_Protected => Is_Protected,
               Is_Task      => Is_Task,
               Valid        => Valid);
            Ident_Str := Node_Lex_String (Node => Ident_Node);
            if Valid and then Type_Announced then
               if Dictionary.IsSubtype (Announced_Type)
                 and then Dictionary.IsProtectedTypeMark (Dictionary.GetRootType (Announced_Type)) then
                  -- Cannot use subtypes of protected types in own variable type announcements
                  ErrorHandler.Semantic_Error
                    (Err_Num   => 948,
                     Reference => ErrorHandler.No_Reference,
                     Position  => Node_Position (Node => Node),
                     Id_Str    => Ident_Str);
               else
                  if Dictionary.FirstVirtualElement (Announced_Type) /= Dictionary.NullIterator then
                     -- There is an own variable declaring a protects list for this type and
                     -- hence this is an illegal second instance.
                     --
                     Valid := False;
                     ErrorHandler.Semantic_Error_Sym
                       (Err_Num   => 942,
                        Reference => ErrorHandler.No_Reference,
                        Position  => Node_Position (Node => Ident_Node),
                        Sym       => Announced_Type,
                        Scope     => Scope);
                  else
                     Valid := True;
                  end if;
               end if;
            end if;

            if Valid then
               if Is_Task then
                  Wf_Own_Task
                    (Node           => Node,
                     Ident_Str      => Ident_Str,
                     Declaration    => Dictionary.Location'(Start_Position => Node_Position (Node => Ident_Node),
                                                            End_Position   => Node_Position (Node => Ident_Node)),
                     Type_Announced => Type_Announced,
                     Announced_Type => Announced_Type,
                     Pack_Sym       => Pack_Sym,
                     Task_Sym       => Own_Var_Sym);
               else
                  --# accept Flow, 41, "Expected stable expression";
                  if Type_Announced then
                     --# end accept;
                     Type_To_Use := Announced_Type;
                  else -- create a default proof type and return that
                     Dictionary.Add_Default_Abstract_Proof_Type
                       (Name        => Ident_Str,
                        Comp_Unit   => ContextManager.Ops.Current_Unit,
                        Declaration => Dictionary.Location'(Start_Position => Node_Position (Node => Ident_Node),
                                                            End_Position   => Node_Position (Node => Ident_Node)),
                        Scope       => Scope,
                        The_Type    => Type_To_Use);
                  end if;
                  STree.Add_Node_Symbol (Node => Ident_Node,
                                         Sym  => Type_To_Use);

                  if Mode.Is_Valid then
                     Dictionary.Add_Own_Variable
                       (Name                => Ident_Str,
                        The_Package         => Pack_Sym,
                        Mode                => Mode.Value,
                        Is_Protected        => Is_Protected,
                        Is_Interrupt_Stream => False,
                        Comp_Unit           => ContextManager.Ops.Current_Unit,
                        Declaration         => Dictionary.Location'(Start_Position => Node_Position (Node => Ident_Node),
                                                                    End_Position   => Node_Position (Node => Ident_Node)),
                        Var_Symbol          => Own_Var_Sym);
                     if Is_Protected and then Mode.Value = Dictionary.DefaultMode then
                        -- Protected own variables are implicitly initialized and hence
                        -- effectively appear in the initializes clause.
                        -- Protected streams should not implicitly appear in the
                        -- initializes clause as we will never initialize them.
                        Dictionary.AddInitializedOwnVariable
                          (Own_Var_Sym,
                           Dictionary.Location'(Start_Position => Node_Position (Node => Ident_Node),
                                                End_Position   => Node_Position (Node => Ident_Node)));
                     end if;
                     Dictionary.AddOwnVariableType
                       (Own_Var_Sym,
                        Type_To_Use,
                        Dictionary.Location'(Start_Position => Node_Position (Node => Type_Node),
                                             End_Position   => Node_Position (Node => Type_Node)));
                  else
                     Own_Var_Sym := Dictionary.NullSymbol;
                  end if;
               end if;
               if Syntax_Node_Type (Node => Property_List_Node) = SP_Symbols.property_list
                 and then not Dictionary.Is_Null_Symbol (Own_Var_Sym) then
                  -- ASSUME Property_List_Node = property_list
                  Wf_Property_List
                    (Node          => Property_List_Node,
                     Type_Node_Pos => Node_Position (Node => Type_Node),
                     Scope         => Scope,
                     The_Owner     => Own_Var_Sym,
                     The_Heap      => The_Heap);
               end if;
               if not Dictionary.Is_Null_Symbol (Own_Var_Sym) and then Dictionary.IsOwnVariable (Own_Var_Sym) then
                  Check_For_Illegal_Multiple_Instances
                    (Own_Var_Sym => Own_Var_Sym,
                     Node_Pos    => Node_Position (Node => Ident_Node),
                     Scope       => Scope);
               end if;
            end if;
         end if;
         It := STree.NextNode (It);
      end loop;
   end Wf_Own_Variable_Specification;

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

   procedure Check_All_Refinements_Accounted_For (Own_Var_Clause_Node : in STree.SyntaxNode;
                                                  Pack_Sym            : in Dictionary.Symbol)
   --# 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,
   --#                                         Own_Var_Clause_Node,
   --#                                         Pack_Sym,
   --#                                         SPARK_IO.File_Sys,
   --#                                         STree.Table;
   --# pre Syntax_Node_Type (Own_Var_Clause_Node, STree.Table) = SP_Symbols.own_variable_clause;
   is
      Var_Sym : Dictionary.Symbol;
      It      : Dictionary.Iterator;
      Err_Pos : LexTokenManager.Token_Position;

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

      function Find_Last_In_Own_Var_Clause (Own_Var_Clause_Node : STree.SyntaxNode) return LexTokenManager.Token_Position
      --# global in STree.Table;
      --# pre Syntax_Node_Type (Own_Var_Clause_Node, STree.Table) = SP_Symbols.own_variable_clause;
      is
         Ret_Node, Next_Node : STree.SyntaxNode;
      begin
         Ret_Node := Child_Node (Current_Node => Child_Node (Current_Node => Own_Var_Clause_Node));
         -- ASSUME Ret_Node = own_variable_clause_rep OR own_variable_specification
         SystemErrors.RT_Assert
           (C       => Syntax_Node_Type (Node => Ret_Node) = SP_Symbols.own_variable_clause_rep
              or else Syntax_Node_Type (Node => Ret_Node) = SP_Symbols.own_variable_specification,
            Sys_Err => SystemErrors.Invalid_Syntax_Tree,
            Msg     => "Expect Ret_Node = own_variable_clause_rep OR own_variable_specification in Find_Last_In_Own_Var_Clause");

         Next_Node := Next_Sibling (Current_Node => Ret_Node);
         -- ASSUME Next_Node = own_variable_specification OR NULL
         if Syntax_Node_Type (Node => Next_Node) = SP_Symbols.own_variable_specification then
            -- ASSUME Next_Node = own_variable_specification
            Ret_Node := Next_Node;
         elsif Next_Node /= STree.NullNode then
            Ret_Node := STree.NullNode;
            SystemErrors.Fatal_Error
              (Sys_Err => SystemErrors.Invalid_Syntax_Tree,
               Msg     => "Expect Next_Node = own_variable_specification OR NULL in Find_Last_In_Own_Var_Clause");
         end if;
         -- ASSUME Ret_Node = own_variable_specification
         SystemErrors.RT_Assert
           (C       => Syntax_Node_Type (Node => Ret_Node) = SP_Symbols.own_variable_specification,
            Sys_Err => SystemErrors.Invalid_Syntax_Tree,
            Msg     => "Expect Ret_Node = own_variable_specification in Find_Last_In_Own_Var_Clause");

         Ret_Node := Child_Node (Current_Node => Child_Node (Current_Node => Ret_Node));
         -- ASSUME Ret_Node = own_variable_list OR own_variable_modifier
         SystemErrors.RT_Assert
           (C       => Syntax_Node_Type (Node => Ret_Node) = SP_Symbols.own_variable_list
              or else Syntax_Node_Type (Node => Ret_Node) = SP_Symbols.own_variable_modifier,
            Sys_Err => SystemErrors.Invalid_Syntax_Tree,
            Msg     => "Expect Ret_Node = own_variable_list OR own_variable_modifier in Find_Last_In_Own_Var_Clause");

         Next_Node := Next_Sibling (Current_Node => Ret_Node);
         -- ASSUME Next_Node = own_variable_modifier OR own_variable
         if Syntax_Node_Type (Node => Next_Node) = SP_Symbols.own_variable_modifier then
            -- ASSUME Next_Node = own_variable_modifier
            Ret_Node := Next_Node;
         elsif Syntax_Node_Type (Node => Next_Node) /= SP_Symbols.own_variable then
            Ret_Node := STree.NullNode;
            SystemErrors.Fatal_Error
              (Sys_Err => SystemErrors.Invalid_Syntax_Tree,
               Msg     => "Expect Next_Node = own_variable_modifier OR own_variable in Find_Last_In_Own_Var_Clause");
         end if;
         -- ASSUME Ret_Node = own_variable_modifier
         SystemErrors.RT_Assert
           (C       => Syntax_Node_Type (Node => Ret_Node) = SP_Symbols.own_variable_modifier,
            Sys_Err => SystemErrors.Invalid_Syntax_Tree,
            Msg     => "Expect Ret_Node = own_variable_modifier in Find_Last_In_Own_Var_Clause");
         return Node_Position (Node => Next_Sibling (Current_Node => Ret_Node));
      end Find_Last_In_Own_Var_Clause;

   begin -- Check_All_Refinements_Accounted_For
      Err_Pos := Find_Last_In_Own_Var_Clause (Own_Var_Clause_Node => Own_Var_Clause_Node);
      It      := Dictionary.FirstOwnVariable (Pack_Sym);
      while not Dictionary.IsNullIterator (It) loop
         Var_Sym := Dictionary.CurrentSymbol (It);
         if not Dictionary.OwnVariableIsAnnounced (Var_Sym) then
            ErrorHandler.Semantic_Error
              (Err_Num   => 77,
               Reference => ErrorHandler.No_Reference,
               Position  => Err_Pos,
               Id_Str    => Dictionary.GetSimpleName (Var_Sym));
         end if;
         It := Dictionary.NextSymbol (It);
      end loop;
   end Check_All_Refinements_Accounted_For;

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

   procedure Check_Owner_Body_Not_Yet_Declared (Own_Var_Clause_Node : in STree.SyntaxNode;
                                                Pack_Sym            : in Dictionary.Symbol)
   --# 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,
   --#                                         Own_Var_Clause_Node,
   --#                                         Pack_Sym,
   --#                                         SPARK_IO.File_Sys,
   --#                                         STree.Table;
   --# pre Syntax_Node_Type (Own_Var_Clause_Node, STree.Table) = SP_Symbols.own_variable_clause;
   is
      Owner : Dictionary.Symbol;
   begin
      Owner := Dictionary.GetPackageOwner (Pack_Sym);
      if not Dictionary.Is_Null_Symbol (Owner) and then Dictionary.HasBody (Owner) then
         ErrorHandler.Semantic_Error
           (Err_Num   => 620,
            Reference => ErrorHandler.No_Reference,
            Position  => Node_Position (Node => Own_Var_Clause_Node),
            Id_Str    => Dictionary.GetSimpleName (Owner));
      end if;
   end Check_Owner_Body_Not_Yet_Declared;

begin -- Wf_Own
   It := Find_First_Node (Node_Kind    => SP_Symbols.own_variable_specification,
                          From_Root    => Node,
                          In_Direction => STree.Down);
   while not STree.IsNull (It) loop
      Next_Node := Get_Node (It => It);
      --# assert STree.Table = STree.Table~ and
      --#   Syntax_Node_Type (Next_Node, STree.Table) = SP_Symbols.own_variable_specification and
      --#   Next_Node = Get_Node (It);
      Wf_Own_Variable_Specification
        (Node       => Next_Node,
         Pack_Sym   => Pack_Sym,
         Scope_Type => Scope_Type,
         Scope      => Scope,
         The_Heap   => The_Heap);
      It := STree.NextNode (It);
   end loop;

   if Scope_Type = In_Package then
      Check_All_Refinements_Accounted_For (Own_Var_Clause_Node => Node,
                                           Pack_Sym            => Pack_Sym);
   elsif Scope_Type = In_Library then
      Check_Owner_Body_Not_Yet_Declared (Own_Var_Clause_Node => Node,
                                         Pack_Sym            => Pack_Sym);
   end if;
end Wf_Own;
