-------------------------------------------------------------------------------
-- (C) Altran Praxis Limited
-------------------------------------------------------------------------------
--
-- The SPARK toolset is free software; you can redistribute it and/or modify it
-- under terms of the GNU General Public License as published by the Free
-- Software Foundation; either version 3, or (at your option) any later
-- version. The SPARK toolset is distributed in the hope that it will be
-- useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
-- Public License for more details. You should have received a copy of the GNU
-- General Public License distributed with the SPARK toolset; see file
-- COPYING3. If not, go to http://www.gnu.org/licenses for a complete copy of
-- the license.
--
--=============================================================================

with E_Strings;

separate (DAG.BuildGraph)
procedure IncorporateConstraints
  (Semantic_Error_In_Subprogram : in Boolean;
   Type_Check_Exports           : in Boolean;
   Scope                        : in Dictionary.Scopes)
is
   type Equalities is (UseEquals, UseImplication);

   PreConNode, PostConNode : STree.SyntaxNode;

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

   -- returns IsRefined if we are dealing with a subprogram that has a second,
   -- refined annotation, otherwise returns IsAbstract.
   -- Note that we are interested here in whether it has a second proof annotation
   --       or a second flow annotation, either is enough to trigger refinement VCs
   -- Note: When we do package initialization constraits we may need to extend this
   --       function to handle that case as well
   function Which_Abstraction (Scope : Dictionary.Scopes) return Dictionary.Abstractions
   --# global in Dictionary.Dict;
   is
      Result : Dictionary.Abstractions := Dictionary.IsAbstract;
      Sym    : Dictionary.Symbol;
   begin
      Sym := Dictionary.GetRegion (Scope);
      if Dictionary.Is_Subprogram (Sym) or else Dictionary.IsTaskType (Sym) then
         Result :=
           Dictionary.GetConstraintAbstraction
           (Sym,
            Dictionary.Set_Visibility (The_Visibility => Dictionary.Local,
                                       The_Unit       => Sym));
      end if;
      return Result;
   end Which_Abstraction;

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

   procedure Plant_Precondition
     (Node                         : in STree.SyntaxNode;
      Semantic_Error_In_Subprogram : in Boolean;
      Scope                        : in Dictionary.Scopes)
   --# global in     CommandLineData.Content;
   --#        in     ImportConstraints;
   --#        in     LoopStack;
   --#        in     STree.Table;
   --#        in out ContainsReals;
   --#        in out Dictionary.Dict;
   --#        in out ErrorHandler.Error_Context;
   --#        in out Graph.Table;
   --#        in out LexTokenManager.State;
   --#        in out SPARK_IO.File_Sys;
   --#        in out Statistics.TableUsage;
   --#        in out VCGFailure;
   --#        in out VCGHeap;
   --# derives ContainsReals,
   --#         Dictionary.Dict,
   --#         LexTokenManager.State,
   --#         VCGFailure                 from *,
   --#                                         CommandLineData.Content,
   --#                                         Dictionary.Dict,
   --#                                         LexTokenManager.State,
   --#                                         LoopStack,
   --#                                         Node,
   --#                                         Scope,
   --#                                         Semantic_Error_In_Subprogram,
   --#                                         STree.Table,
   --#                                         VCGHeap &
   --#         ErrorHandler.Error_Context,
   --#         SPARK_IO.File_Sys          from CommandLineData.Content,
   --#                                         Dictionary.Dict,
   --#                                         ErrorHandler.Error_Context,
   --#                                         LexTokenManager.State,
   --#                                         LoopStack,
   --#                                         Node,
   --#                                         Scope,
   --#                                         Semantic_Error_In_Subprogram,
   --#                                         SPARK_IO.File_Sys,
   --#                                         STree.Table,
   --#                                         VCGHeap &
   --#         Graph.Table,
   --#         Statistics.TableUsage,
   --#         VCGHeap                    from *,
   --#                                         CommandLineData.Content,
   --#                                         Dictionary.Dict,
   --#                                         ImportConstraints,
   --#                                         LexTokenManager.State,
   --#                                         LoopStack,
   --#                                         Node,
   --#                                         Scope,
   --#                                         Semantic_Error_In_Subprogram,
   --#                                         STree.Table,
   --#                                         VCGHeap;
   is
      DAG_Cell                : Cells.Cell;
      Conjoined_Function_Defs : Cells.Cell;
      Function_Defs           : CStacks.Stack;
   begin
      Graph.Set_First_Proof_Context (X => Graph.Precondition);
      -- if there is no precondition, or the subprogram contains semantic errors, then
      -- we force the precondition to TRUE
      if Semantic_Error_In_Subprogram or else Node = STree.NullNode then
         CreateTrueCell (VCGHeap, DAG_Cell);
      else
         -- otherwise we traverse the predicate and build a DAG for it.

         -- Initialize the function definition stack
         CStacks.CreateStack (Function_Defs);

         Build_Annotation_Expression
           (Exp_Node                         => Node,
            Instantiated_Subprogram          => Dictionary.NullSymbol,
            Scope                            => Scope,
            Calling_Scope                    => Scope,
            Force_Abstract                   => False,
            Loop_Stack                       => LoopStack,
            Generate_Function_Instantiations => True,
            VC_Failure                       => VCGFailure,
            VC_Contains_Reals                => ContainsReals,
            VCG_Heap                         => VCGHeap,
            DAG_Root                         => DAG_Cell,
            Function_Defs                    => Function_Defs);

         if not CStacks.IsEmpty (Function_Defs) then
            -- Functions are called within the precondition of the subprogram
            -- Conjoin all the function definitions on the stack
            --# accept F, 10, Function_Defs, "The stack has been emptied";
            Join_And (Stack    => Function_Defs,
                      Conjunct => Conjoined_Function_Defs,
                      VCG_Heap => VCGHeap);
            --# end accept;

            -- conjoin the function definitions with the precondition
            Cells.Utility.Conjoin (VCGHeap, Conjoined_Function_Defs, DAG_Cell);
         end if;
      end if;

      if not Cells.Is_Null_Cell (ImportConstraints) then
         Cells.Utility.Conjoin (VCGHeap, ImportConstraints, DAG_Cell);
      end if;
      Graph.Set_First_Assertion_Locn (X => DAG_Cell);
   end Plant_Precondition;

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

   -- SubstituteImplicit replaces each occurrence of the implicit
   -- variable (Implicit_Var) in a function return annotation (Return_Anno_DAG).
   -- by the expression of the return statement (referenced by RetExpDAG).
   -- The return annotation is updated in place.
   procedure SubstituteImplicit
     (Return_Anno_DAG : in out Cells.Cell;
      Implicit_Var    : in     Dictionary.Symbol;
      RetExpDAG       : in     Cells.Cell)
   -- the thing to substitute
   --# global in     Dictionary.Dict;
   --#        in out Statistics.TableUsage;
   --#        in out VCGHeap;
   --# derives Return_Anno_DAG,
   --#         Statistics.TableUsage,
   --#         VCGHeap               from *,
   --#                                    Dictionary.Dict,
   --#                                    Implicit_Var,
   --#                                    RetExpDAG,
   --#                                    Return_Anno_DAG,
   --#                                    VCGHeap;
   is
      P                : Cells.Cell;
      S                : CStacks.Stack;
      The_Substitution : Cells.Cell;
   begin
      --  We need to take a copy of the thing we're substituting to
      --  ensure we don't tangle up the graphs :)
      Structures.CopyStructure (VCGHeap, RetExpDAG, The_Substitution);

      -- DAG traversal algorithm of D.E. Knuth, Fundamental Algorithms, p.317;
      CStacks.CreateStack (S);
      P := Return_Anno_DAG;
      loop
         loop
            exit when Cells.Is_Null_Cell (P);
            CStacks.Push (VCGHeap, P, S);
            if Is_Leaf (Node     => P,
                        VCG_Heap => VCGHeap) then
               P := Cells.Null_Cell;
            else
               P := LeftPtr (VCGHeap, P);
            end if;
         end loop;
         exit when CStacks.IsEmpty (S);
         P := CStacks.Top (VCGHeap, S);
         CStacks.Pop (VCGHeap, S);
         if Is_Leaf (Node     => P,
                     VCG_Heap => VCGHeap) then
            if Dictionary.IsImplicitReturnVariable (Cells.Get_Symbol_Value (VCGHeap, P))
              and then Dictionary.Implicit_Return_Variables_Are_Equal
              (Left_Symbol  => Cells.Get_Symbol_Value (VCGHeap, P),
               Right_Symbol => Implicit_Var) then
               Cells.Copy_Contents (VCGHeap, The_Substitution, P);
            end if;
            P := Cells.Null_Cell;
         else
            P := RightPtr (VCGHeap, P);
         end if;
      end loop;
      --# accept F, 31, Return_Anno_DAG, "Return_Anno_DAG is indirectly updated via the local pointer P" &
      --#        F, 50, Return_Anno_DAG, Implicit_Var, "Return_Anno_DAG indirectly references Implicit_Var via local pointer P" &
      --#        F, 50, Return_Anno_DAG, RetExpDAG, "Return_Anno_DAG indirectly references RetExpDAG via local pointer P" &
      --#        F, 50, Return_Anno_DAG, VCGHeap, "Return_Anno_DAG indirectly references VCGHeap via local pointer P" &
      --#        F, 50, Return_Anno_DAG, Dictionary.Dict, "Return_Anno_DAG indirectly references Dictionary.Dict via local pointer P" &
      --#        W, 3, "Suppress warnings on ReturnAnnoDAG";
      -- Return_Anno_DAG appears to be only an input to Ada but it is
      -- effectively a pointer to a data structure which is updated.
      pragma Warnings (Off, Return_Anno_DAG);
   end SubstituteImplicit;

   -----------------------------------------------------------------------------------
   -- In general we don't need to RT check procedure exports because any expression
   -- used to assign to them will have been checked; however, where stream variables
   -- are involved we may have rogue values returned from the environment.  To avoid
   -- a large number of unnecessary checks we need to detect the special cases where
   -- streams are involved.
   -----------------------------------------------------------------------------------

   procedure Plant_Postcondition
     (Node                         : in STree.SyntaxNode;
      Subprog                      : in Dictionary.Symbol;
      Abstraction                  : in Dictionary.Abstractions;
      Semantic_Error_In_Subprogram : in Boolean;
      Type_Check_Exports           : in Boolean;
      Scope                        : in Dictionary.Scopes)
   --# global in     CommandLineData.Content;
   --#        in     LoopStack;
   --#        in     STree.Table;
   --#        in out ContainsReals;
   --#        in out Dictionary.Dict;
   --#        in out ErrorHandler.Error_Context;
   --#        in out Graph.Table;
   --#        in out LexTokenManager.State;
   --#        in out SPARK_IO.File_Sys;
   --#        in out Statistics.TableUsage;
   --#        in out StmtStack.S;
   --#        in out VCGFailure;
   --#        in out VCGHeap;
   --# derives ContainsReals,
   --#         Dictionary.Dict,
   --#         Graph.Table,
   --#         LexTokenManager.State,
   --#         Statistics.TableUsage,
   --#         VCGFailure,
   --#         VCGHeap                    from *,
   --#                                         Abstraction,
   --#                                         CommandLineData.Content,
   --#                                         Dictionary.Dict,
   --#                                         Graph.Table,
   --#                                         LexTokenManager.State,
   --#                                         LoopStack,
   --#                                         Node,
   --#                                         Scope,
   --#                                         Semantic_Error_In_Subprogram,
   --#                                         StmtStack.S,
   --#                                         STree.Table,
   --#                                         Subprog,
   --#                                         Type_Check_Exports,
   --#                                         VCGHeap &
   --#         ErrorHandler.Error_Context from *,
   --#                                         CommandLineData.Content,
   --#                                         Dictionary.Dict,
   --#                                         LexTokenManager.State,
   --#                                         LoopStack,
   --#                                         Node,
   --#                                         Scope,
   --#                                         Semantic_Error_In_Subprogram,
   --#                                         SPARK_IO.File_Sys,
   --#                                         STree.Table,
   --#                                         VCGHeap &
   --#         SPARK_IO.File_Sys          from *,
   --#                                         Abstraction,
   --#                                         CommandLineData.Content,
   --#                                         Dictionary.Dict,
   --#                                         ErrorHandler.Error_Context,
   --#                                         Graph.Table,
   --#                                         LexTokenManager.State,
   --#                                         LoopStack,
   --#                                         Node,
   --#                                         Scope,
   --#                                         Semantic_Error_In_Subprogram,
   --#                                         StmtStack.S,
   --#                                         STree.Table,
   --#                                         Subprog,
   --#                                         Type_Check_Exports,
   --#                                         VCGHeap &
   --#         StmtStack.S                from *,
   --#                                         CommandLineData.Content,
   --#                                         Dictionary.Dict,
   --#                                         Graph.Table,
   --#                                         LexTokenManager.State,
   --#                                         LoopStack,
   --#                                         Node,
   --#                                         Scope,
   --#                                         Semantic_Error_In_Subprogram,
   --#                                         STree.Table,
   --#                                         VCGHeap;
   is
      DAG_Cell                : Cells.Cell;
      Conjoined_Function_Defs : Cells.Cell;
      Function_Defs           : CStacks.Stack;

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

      procedure Check_Type_Of_Exports
        (Abstraction : in     Dictionary.Abstractions;
         SubProg     : in     Dictionary.Symbol;
         Scope       : in     Dictionary.Scopes;
         Conjuncts   : in out Cells.Cell)
      --# global in     CommandLineData.Content;
      --#        in out ContainsReals;
      --#        in out Dictionary.Dict;
      --#        in out LexTokenManager.State;
      --#        in out SPARK_IO.File_Sys;
      --#        in out Statistics.TableUsage;
      --#        in out VCGFailure;
      --#        in out VCGHeap;
      --# derives Conjuncts,
      --#         ContainsReals,
      --#         Dictionary.Dict,
      --#         LexTokenManager.State,
      --#         SPARK_IO.File_Sys,
      --#         Statistics.TableUsage,
      --#         VCGFailure,
      --#         VCGHeap               from *,
      --#                                    Abstraction,
      --#                                    CommandLineData.Content,
      --#                                    Conjuncts,
      --#                                    Dictionary.Dict,
      --#                                    LexTokenManager.State,
      --#                                    Scope,
      --#                                    SubProg,
      --#                                    VCGHeap;
      is
         It        : Dictionary.Iterator;
         ExportVar : Dictionary.Symbol;
         Type_Sym  : Dictionary.Symbol;
         Data_View : Dictionary.Abstractions;

         function ExportDependsOnStream
           (Export      : Dictionary.Symbol;
            Abstraction : Dictionary.Abstractions;
            SubProg     : Dictionary.Symbol)
           return        Boolean
         --# global in Dictionary.Dict;
         is
            ImportIt : Dictionary.Iterator;
            Result   : Boolean := False;
         begin -- ExportDependsOnStream
            ImportIt := Dictionary.FirstDependency (Abstraction, SubProg, Export);
            while not Dictionary.IsNullIterator (ImportIt) loop
               if Dictionary.GetOwnVariableOrConstituentMode (Dictionary.CurrentSymbol (ImportIt)) = Dictionary.InMode then
                  Result := True;
                  exit;
               end if;

               ImportIt := Dictionary.NextSymbol (ImportIt);
            end loop;
            return Result;
         end ExportDependsOnStream;

      begin -- Check_Type_Of_Exports

         if Abstraction = Dictionary.IsRefined then
            -- The view of the pre and post condition is refined.
            -- Determine whether the view of the data should be
            -- Abstract (Proof Refinement only) or
            -- Refined  (Data Refinement is present).
            if Dictionary.IsNullIterator (Dictionary.FirstGlobalVariable (Dictionary.IsRefined, SubProg)) then
               -- No Data Refinement.
               Data_View := Dictionary.IsAbstract;
            else
               -- Data Refinement is present.
               Data_View := Dictionary.IsRefined;
            end if;
         else
            -- Only proof refinement is present.
            Data_View := Dictionary.IsAbstract;
         end if;

         It := Dictionary.FirstExport (Data_View, SubProg);
         while not Dictionary.IsNullIterator (It) loop
            ExportVar := Dictionary.CurrentSymbol (It);
            if ExportDependsOnStream (Export      => ExportVar,
                                      Abstraction => Abstraction,
                                      SubProg     => SubProg)
              and then
              -- RTC only for exports which are dependent on streams
              IsDirectlyVisible (ExportVar, Scope)
              and then
              -- and which are visible in Ada context
              (Dictionary.GetOwnVariableOrConstituentMode (ExportVar) = Dictionary.DefaultMode) then
               -- no RTC unless stream has been assigned to some non-moded export --903

               Type_Sym := Dictionary.GetType (ExportVar);
               -- cannot plant the type constraint check directly because it
               -- refers to the postcond.  Need to conjoin it with
               -- the rest of the postcond instead
               if not Dictionary.IsPrivateType (Type_Sym, Scope) or else Dictionary.IsPredefinedTimeType (Type_Sym) then
                  ConjoinParamConstraint (Type_Sym, ExportVar, Scope, False, Conjuncts);
               end if;
            end if;

            It := Dictionary.NextSymbol (It);
         end loop;
      end Check_Type_Of_Exports;

   begin -- Plant_Postcondition
      if Semantic_Error_In_Subprogram then
         -- If subprgoram has semantic errors then force postcondition to FALSE to help user notice problem
         CreateFalseCell (VCGHeap, DAG_Cell);
      else
         -- Otherwise build TRUE or actual postcondition
         if Node = STree.NullNode then
            CreateTrueCell (VCGHeap, DAG_Cell);
            if Type_Check_Exports then
               Check_Type_Of_Exports (Abstraction => Abstraction,
                                      SubProg     => Subprog,
                                      Scope       => Scope,
                                      Conjuncts   => DAG_Cell);
            end if;
         else
            -- Initialize the function definition stack
            CStacks.CreateStack (Function_Defs);

            Build_Annotation_Expression
              (Exp_Node                         => Node,
               Instantiated_Subprogram          => Dictionary.NullSymbol,
               Scope                            => Scope,
               Calling_Scope                    => Scope,
               Force_Abstract                   => False,
               Loop_Stack                       => LoopStack,
               Generate_Function_Instantiations => True,
               VC_Failure                       => VCGFailure,
               VC_Contains_Reals                => ContainsReals,
               VCG_Heap                         => VCGHeap,
               DAG_Root                         => DAG_Cell,
               Function_Defs                    => Function_Defs);

            if not CStacks.IsEmpty (Function_Defs) then
               -- Functions are called within the postcondition of the subprogram
               -- Conjoin all the function definitions on the stack
               --# accept F, 10, Function_Defs, "The stack has been emptied";
               Join_And (Stack    => Function_Defs,
                         Conjunct => Conjoined_Function_Defs,
                         VCG_Heap => VCGHeap);
               --# end accept;
               -- Insert a null statement as a place holder for the conjoined
               -- function defs;
               ModelNullStmt (VCGHeap);
               -- and attach the function definitions to the null statement
               IncorporateAssumption (VCGHeap, Conjoined_Function_Defs);
            end if;

            if Type_Check_Exports then
               Check_Type_Of_Exports (Abstraction => Abstraction,
                                      SubProg     => Subprog,
                                      Scope       => Scope,
                                      Conjuncts   => DAG_Cell);
            end if;
         end if;
      end if;

      Graph.Set_Proof_Context (X => Graph.Postcondition);
      Graph.Set_Assertion_Locn (X => DAG_Cell);

   end Plant_Postcondition;

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

   -- Plant_Return_Expression is called to insert constraints determined from
   -- the return annotation and the return type of a function which must be
   -- proven to be satisfied the body of the function.
   -- Plant_Return_Expression traverses the syntax tree for a sequnece of
   -- statements of the function subprogram to locate the
   -- (only) return statement which will be the last statement of the sequence.
   -- Once the return statement has been located the return expression subtree
   -- is obtained and is used as the basis of a new DAG node which is a
   -- translation of the return annotation.  The DAG node represents:
   --   for an explicit return annotation the expression
   --     return_expression <-> return_annotation -- for a Boolean return type
   --     return_expression  =  return_annotation -- for other return types
   --  for an implicit return annotation
   --     Each instance of the implicit_variable in the return-annotation is
   --     substituted with the return_expression.
   --  when there is no return annotation present the DAG node represents
   --  the expression "true".
   -- Once the DAG node has been associated with the appropriate expression
   -- a further constraint to check that the value of the return expression is
   -- in-type is conjoined to the DAG node.
   procedure Plant_Return_Expression
     (Return_Type                  : in Dictionary.Symbol;
      Node                         : in STree.SyntaxNode;
      Semantic_Error_In_Subprogram : in Boolean;
      Scope                        : in Dictionary.Scopes)
   --# global in     CommandLineData.Content;
   --#        in     DoAssumeLocalRvalues;
   --#        in     LineNmbr;
   --#        in     LoopStack;
   --#        in     StartNode;
   --#        in     STree.Table;
   --#        in out CheckStack;
   --#        in out ContainsReals;
   --#        in out Dictionary.Dict;
   --#        in out ErrorHandler.Error_Context;
   --#        in out FlowHeap;
   --#        in out Graph.Table;
   --#        in out KindOfStackedCheck;
   --#        in out LexTokenManager.State;
   --#        in out ShortCircuitStack;
   --#        in out SPARK_IO.File_Sys;
   --#        in out Statistics.TableUsage;
   --#        in out StmtStack.S;
   --#        in out VCGFailure;
   --#        in out VCGHeap;
   --# derives CheckStack,
   --#         FlowHeap,
   --#         KindOfStackedCheck,
   --#         ShortCircuitStack          from CheckStack,
   --#                                         CommandLineData.Content,
   --#                                         Dictionary.Dict,
   --#                                         DoAssumeLocalRvalues,
   --#                                         FlowHeap,
   --#                                         Graph.Table,
   --#                                         KindOfStackedCheck,
   --#                                         LexTokenManager.State,
   --#                                         LineNmbr,
   --#                                         LoopStack,
   --#                                         Scope,
   --#                                         Semantic_Error_In_Subprogram,
   --#                                         ShortCircuitStack,
   --#                                         StartNode,
   --#                                         StmtStack.S,
   --#                                         STree.Table,
   --#                                         VCGHeap &
   --#         ContainsReals,
   --#         Dictionary.Dict,
   --#         LexTokenManager.State,
   --#         VCGFailure                 from *,
   --#                                         CheckStack,
   --#                                         CommandLineData.Content,
   --#                                         Dictionary.Dict,
   --#                                         DoAssumeLocalRvalues,
   --#                                         FlowHeap,
   --#                                         Graph.Table,
   --#                                         KindOfStackedCheck,
   --#                                         LexTokenManager.State,
   --#                                         LineNmbr,
   --#                                         LoopStack,
   --#                                         Node,
   --#                                         Scope,
   --#                                         Semantic_Error_In_Subprogram,
   --#                                         ShortCircuitStack,
   --#                                         StartNode,
   --#                                         StmtStack.S,
   --#                                         STree.Table,
   --#                                         VCGHeap &
   --#         ErrorHandler.Error_Context,
   --#         SPARK_IO.File_Sys          from CheckStack,
   --#                                         CommandLineData.Content,
   --#                                         Dictionary.Dict,
   --#                                         DoAssumeLocalRvalues,
   --#                                         ErrorHandler.Error_Context,
   --#                                         FlowHeap,
   --#                                         Graph.Table,
   --#                                         KindOfStackedCheck,
   --#                                         LexTokenManager.State,
   --#                                         LineNmbr,
   --#                                         LoopStack,
   --#                                         Node,
   --#                                         Scope,
   --#                                         Semantic_Error_In_Subprogram,
   --#                                         ShortCircuitStack,
   --#                                         SPARK_IO.File_Sys,
   --#                                         StartNode,
   --#                                         StmtStack.S,
   --#                                         STree.Table,
   --#                                         VCGHeap &
   --#         Graph.Table,
   --#         Statistics.TableUsage,
   --#         StmtStack.S,
   --#         VCGHeap                    from *,
   --#                                         CheckStack,
   --#                                         CommandLineData.Content,
   --#                                         Dictionary.Dict,
   --#                                         DoAssumeLocalRvalues,
   --#                                         FlowHeap,
   --#                                         Graph.Table,
   --#                                         KindOfStackedCheck,
   --#                                         LexTokenManager.State,
   --#                                         LineNmbr,
   --#                                         LoopStack,
   --#                                         Node,
   --#                                         Return_Type,
   --#                                         Scope,
   --#                                         Semantic_Error_In_Subprogram,
   --#                                         ShortCircuitStack,
   --#                                         StartNode,
   --#                                         StmtStack.S,
   --#                                         STree.Table,
   --#                                         VCGHeap;
   is
      Return_Expression_Node                      : STree.SyntaxNode;
      RetExpDAG, AnnoRetExpDAG, Postcondition_DAG : Cells.Cell;
      Implicit_Var                                : Dictionary.Symbol;
      TheAnnoDAG, CopyRetExpDAG                   : Cells.Cell;
      Conjoined_Function_Defs                     : Cells.Cell;
      Function_Defs                               : CStacks.Stack;

      procedure ConjoinToReturnExpr
        (Type_Sym : in     Dictionary.Symbol;
         Expr     : in     Cells.Cell;
         Scope    : in     Dictionary.Scopes;
         DAG_Cell : in out Cells.Cell)
      --# global in     Dictionary.Dict;
      --#        in out ContainsReals;
      --#        in out Statistics.TableUsage;
      --#        in out VCGHeap;
      --# derives ContainsReals         from *,
      --#                                    Dictionary.Dict,
      --#                                    Type_Sym &
      --#         DAG_Cell,
      --#         Statistics.TableUsage,
      --#         VCGHeap               from *,
      --#                                    DAG_Cell,
      --#                                    Dictionary.Dict,
      --#                                    Expr,
      --#                                    Scope,
      --#                                    Type_Sym,
      --#                                    VCGHeap;
      is
         Conjunct_Cell : Cells.Cell;
      begin
         if DiscreteTypeWithCheck (Type_Sym, Scope) then
            Type_Constraint.Process_Discrete
              (The_Type       => Type_Sym,
               The_Expression => Expr,
               The_Constraint => Conjunct_Cell,
               VCG_Heap       => VCGHeap);
            Cells.Utility.Conjoin (VCGHeap, Conjunct_Cell, DAG_Cell);
         end if;
         if IsRealType (Type_Sym) then
            ContainsReals := True;
         end if;
      end ConjoinToReturnExpr;

   begin -- Plant_Return_Expression
      if Semantic_Error_In_Subprogram then
         -- If subprogram body has semantic errors then force postcondition to FALSE
         Graph.Set_Proof_Context (X => Graph.Postcondition);
         CreateFalseCell (VCGHeap, TheAnnoDAG);
         Graph.Set_Assertion_Locn (X => TheAnnoDAG);
      else
         -- otherwise traverse return expression and construct predicate DAG
         Return_Expression_Node := STree.Child_Node (Current_Node => StartNode);

         -- Now we have a sequence_of_statements which can be reduced to:
         -- sequence_of_statements statement | statement ;
         -- (See SPARK.LLA)
         -- If the sequence_of_statements is a sequence_of_statements followed by
         -- a statement then skip to the statement (which will be the final statement
         -- in the subprogram).
         if STree.Syntax_Node_Type (Node => Return_Expression_Node) = SP_Symbols.sequence_of_statements then
            Return_Expression_Node := STree.Next_Sibling (Current_Node => Return_Expression_Node);
         end if;

         -- The final statement in the subprogram should be a return statement, but we
         -- need to cater for labels because a statement can be reduced to:
         -- simple_statement | sequence_of_labels simple_statement ...
         -- (and a simple_statement can be reduced to a return_statement).

         -- The child node will either be a simple_statement or a sequence_of_labels
         Return_Expression_Node := STree.Child_Node (Current_Node => Return_Expression_Node);

         -- Skip the label(s) if present.
         if STree.Syntax_Node_Type (Node => Return_Expression_Node) = SP_Symbols.sequence_of_labels then
            Return_Expression_Node := STree.Next_Sibling (Current_Node => Return_Expression_Node);
         end if;

         -- Now we have reached the final statement in the subprogram. This should be
         -- a return statement. Locate the return expression...
         while STree.Syntax_Node_Type (Node => Return_Expression_Node) /= SP_Symbols.expression loop
            -- SEQUENCE_OF_LABELS
            Return_Expression_Node := STree.Child_Node (Current_Node => Return_Expression_Node);
         end loop;

         -- create DAG for SPARK return expression
         BuildExpnDAG
           (Return_Expression_Node,
            Scope,
            Scope,
            LineNmbr,
            True,
            DoAssumeLocalRvalues,
            LoopStack,
            FlowHeap,
            VCGHeap,
            ContainsReals,
            VCGFailure,
            ShortCircuitStack,
            CheckStack,
            KindOfStackedCheck,
            -- to get
            RetExpDAG);
         UnStackRtcs (LineNmbr, VCGHeap, CheckStack, KindOfStackedCheck);
         Structures.CopyStructure (VCGHeap, RetExpDAG, CopyRetExpDAG);

         -- now deal with return annotation if there is one
         if Node /= STree.NullNode then
            -- set up the function definition stack
            CStacks.CreateStack (Function_Defs);
            if STree.Syntax_Node_Type (Node => Node) = SP_Symbols.annotation_expression then
               -- build post condition for simple return expression
               Build_Annotation_Expression
                 (Exp_Node                         => Node,
                  Instantiated_Subprogram          => Dictionary.NullSymbol,
                  Scope                            => Scope,
                  Calling_Scope                    => Scope,
                  Force_Abstract                   => False,
                  Loop_Stack                       => LoopStack,
                  Generate_Function_Instantiations => True,
                  VC_Failure                       => VCGFailure,
                  VC_Contains_Reals                => ContainsReals,
                  VCG_Heap                         => VCGHeap,
                  DAG_Root                         => AnnoRetExpDAG,
                  Function_Defs                    => Function_Defs);

               -- set two DAGs to be equal
               -- use <-> for boolean functions otherwise use =
               if Dictionary.TypeIsBoolean (Return_Type) then
                  CreateOpCell (Postcondition_DAG, VCGHeap, SP_Symbols.is_equivalent_to);
               else
                  CreateOpCell (Postcondition_DAG, VCGHeap, SP_Symbols.equals);
               end if;
               SetLeftArgument (Postcondition_DAG, RetExpDAG, VCGHeap);
               SetRightArgument (Postcondition_DAG, AnnoRetExpDAG, VCGHeap);
               TheAnnoDAG := Postcondition_DAG;

               -- Indicate that there is no implicit var associated with this
               -- return annotation.
               Implicit_Var := Dictionary.NullSymbol;

            else -- build post condition for implicit return expression

               -- get symbol of implicit return var
               Implicit_Var :=
                 Dictionary.GetImplicitReturnVariable (Which_Abstraction (Scope => Scope), Dictionary.GetRegion (Scope));

               -- walk predicate part of implicit return statement
               Build_Annotation_Expression
                 (Exp_Node                         => STree.Next_Sibling (Current_Node => Node),
                  Instantiated_Subprogram          => Dictionary.NullSymbol,
                  Scope                            => Dictionary.Set_Visibility (The_Visibility => Dictionary.Local,
                                                                                 The_Unit       => Implicit_Var),
                  Calling_Scope                    => Scope,
                  Force_Abstract                   => False,
                  Loop_Stack                       => LoopStack,
                  Generate_Function_Instantiations => True,
                  VC_Failure                       => VCGFailure,
                  VC_Contains_Reals                => ContainsReals,
                  VCG_Heap                         => VCGHeap,
                  DAG_Root                         => AnnoRetExpDAG,
                  Function_Defs                    => Function_Defs);

               -- now subsitute actual return expression DAG for occurrences of
               -- implicit return variable
               SubstituteImplicit (AnnoRetExpDAG, Implicit_Var, RetExpDAG);

               TheAnnoDAG := AnnoRetExpDAG;

            end if;

            if not CStacks.IsEmpty (Function_Defs) then
               -- Functions are called within the return annotation of the subprogram
               -- Conjoin all the function definitions on the stack
               --# accept F, 10, Function_Defs, "The stack has been emptied";
               Join_And (Stack    => Function_Defs,
                         Conjunct => Conjoined_Function_Defs,
                         VCG_Heap => VCGHeap);
               --# end accept;

               -- Check to see if we need to substitute an implicit variable
               if not Dictionary.Is_Null_Symbol (Implicit_Var) then
                  -- The return anno does have an implicit variable we must
                  -- do a subsitution
                  SubstituteImplicit (Conjoined_Function_Defs, Implicit_Var, RetExpDAG);
               end if;

               -- Insert a null statement as a place holder for the conjoined
               -- function defs;
               ModelNullStmt (VCGHeap);
               -- and attach the function definitions to the null statement
               IncorporateAssumption (VCGHeap, Conjoined_Function_Defs);
            end if;

         else -- no return expression given so plant true
            CreateTrueCell (VCGHeap, TheAnnoDAG);
         end if;

         -- We still want to do the check that the return expression is in type,
         -- in contrast to CheckTypeofExports in ModelPostCondition.
         ConjoinToReturnExpr
           (Type_Sym => Dictionary.GetType (Dictionary.GetRegion (Scope)),
            Expr     => CopyRetExpDAG,
            Scope    => Scope,
            DAG_Cell => TheAnnoDAG);

         Graph.Set_Proof_Context (X => Graph.Postcondition);
         Graph.Set_Assertion_Locn (X => TheAnnoDAG);
      end if;
   end Plant_Return_Expression;

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

   -- Procedure, used for generation of refinement and subclass checks, for creating
   -- required anno DAGs; created so we can deal with absence of explicit pre/post con
   -- and create a "true" cell instead
   procedure CreateAnnotationDAG
     (Start_Node              : in     STree.SyntaxNode;
      Scope                   : in     Dictionary.Scopes;
      Force_Abstract          : in     Boolean;
      Conjoined_Function_Defs :    out Cells.Cell;
      DAG_Root                :    out Cells.Cell)
   --# global in     CommandLineData.Content;
   --#        in     LoopStack;
   --#        in     STree.Table;
   --#        in out ContainsReals;
   --#        in out Dictionary.Dict;
   --#        in out ErrorHandler.Error_Context;
   --#        in out LexTokenManager.State;
   --#        in out SPARK_IO.File_Sys;
   --#        in out Statistics.TableUsage;
   --#        in out VCGFailure;
   --#        in out VCGHeap;
   --# derives Conjoined_Function_Defs,
   --#         DAG_Root,
   --#         Dictionary.Dict,
   --#         LexTokenManager.State,
   --#         VCGHeap                    from CommandLineData.Content,
   --#                                         Dictionary.Dict,
   --#                                         Force_Abstract,
   --#                                         LexTokenManager.State,
   --#                                         LoopStack,
   --#                                         Scope,
   --#                                         Start_Node,
   --#                                         STree.Table,
   --#                                         VCGHeap &
   --#         ContainsReals,
   --#         Statistics.TableUsage,
   --#         VCGFailure                 from *,
   --#                                         CommandLineData.Content,
   --#                                         Dictionary.Dict,
   --#                                         Force_Abstract,
   --#                                         LexTokenManager.State,
   --#                                         LoopStack,
   --#                                         Scope,
   --#                                         Start_Node,
   --#                                         STree.Table,
   --#                                         VCGHeap &
   --#         ErrorHandler.Error_Context,
   --#         SPARK_IO.File_Sys          from CommandLineData.Content,
   --#                                         Dictionary.Dict,
   --#                                         ErrorHandler.Error_Context,
   --#                                         Force_Abstract,
   --#                                         LexTokenManager.State,
   --#                                         LoopStack,
   --#                                         Scope,
   --#                                         SPARK_IO.File_Sys,
   --#                                         Start_Node,
   --#                                         STree.Table,
   --#                                         VCGHeap;
   is
      Function_Defs : CStacks.Stack;
   begin
      if Start_Node = STree.NullNode then
         -- The expression is null so assume True for both the expression
         -- and the called function definitions
         CreateTrueCell (VCGHeap, DAG_Root);
         CreateTrueCell (VCGHeap, Conjoined_Function_Defs);
      else
         -- Create stack for the definition of any functions called within the
         -- annotation expression
         CStacks.CreateStack (Function_Defs);

         Build_Annotation_Expression
           (Exp_Node                         => Start_Node,
            Instantiated_Subprogram          => Dictionary.NullSymbol,
            Scope                            => Scope,
            Calling_Scope                    => Scope,
            Force_Abstract                   => Force_Abstract,
            Loop_Stack                       => LoopStack,
            Generate_Function_Instantiations => True,
            VC_Failure                       => VCGFailure,
            VC_Contains_Reals                => ContainsReals,
            VCG_Heap                         => VCGHeap,
            DAG_Root                         => DAG_Root,
            Function_Defs                    => Function_Defs);

         -- Functions are called within the annotation expression
         -- conjoin their definitions.
         --# accept F, 10, Function_Defs, "The stack has been emptied";
         Join_And (Stack    => Function_Defs,
                   Conjunct => Conjoined_Function_Defs,
                   VCG_Heap => VCGHeap);
         --# end accept;
      end if;
   end CreateAnnotationDAG;

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

   -- Performs similar function to CreateAnnotationDAG but deals with function
   -- return annotations (both explicit and implicit).  This procedure used to be
   -- local to Plant_Refinement_Checks but has been moved out so that it can also
   -- be used by Plant_Sub_Class_Checks.
   procedure CreateFunctionAnnotationDAG
     (Sub_Prog                : in     Dictionary.Symbol;
      StartNode               : in     STree.SyntaxNode;
      Scope                   : in     Dictionary.Scopes;
      ForceAbstract           : in     Boolean;
      Return_Cell             : in     Cells.Cell;
      EqualityOperator        : in     Equalities;
      Abstraction             : in     Dictionary.Abstractions;
      Conjoined_Function_Defs :    out Cells.Cell;
      DAGRoot                 :    out Cells.Cell)
   --# global in     CommandLineData.Content;
   --#        in     LoopStack;
   --#        in     STree.Table;
   --#        in out ContainsReals;
   --#        in out Dictionary.Dict;
   --#        in out ErrorHandler.Error_Context;
   --#        in out LexTokenManager.State;
   --#        in out SPARK_IO.File_Sys;
   --#        in out Statistics.TableUsage;
   --#        in out VCGFailure;
   --#        in out VCGHeap;
   --# derives Conjoined_Function_Defs    from Abstraction,
   --#                                         CommandLineData.Content,
   --#                                         Dictionary.Dict,
   --#                                         ForceAbstract,
   --#                                         LexTokenManager.State,
   --#                                         LoopStack,
   --#                                         Return_Cell,
   --#                                         Scope,
   --#                                         StartNode,
   --#                                         STree.Table,
   --#                                         Sub_Prog,
   --#                                         VCGHeap &
   --#         ContainsReals,
   --#         Dictionary.Dict,
   --#         LexTokenManager.State,
   --#         VCGFailure                 from *,
   --#                                         Abstraction,
   --#                                         CommandLineData.Content,
   --#                                         Dictionary.Dict,
   --#                                         ForceAbstract,
   --#                                         LexTokenManager.State,
   --#                                         LoopStack,
   --#                                         Scope,
   --#                                         StartNode,
   --#                                         STree.Table,
   --#                                         Sub_Prog,
   --#                                         VCGHeap &
   --#         DAGRoot,
   --#         VCGHeap                    from Abstraction,
   --#                                         CommandLineData.Content,
   --#                                         Dictionary.Dict,
   --#                                         EqualityOperator,
   --#                                         ForceAbstract,
   --#                                         LexTokenManager.State,
   --#                                         LoopStack,
   --#                                         Return_Cell,
   --#                                         Scope,
   --#                                         StartNode,
   --#                                         STree.Table,
   --#                                         Sub_Prog,
   --#                                         VCGHeap &
   --#         ErrorHandler.Error_Context,
   --#         SPARK_IO.File_Sys          from Abstraction,
   --#                                         CommandLineData.Content,
   --#                                         Dictionary.Dict,
   --#                                         ErrorHandler.Error_Context,
   --#                                         ForceAbstract,
   --#                                         LexTokenManager.State,
   --#                                         LoopStack,
   --#                                         Scope,
   --#                                         SPARK_IO.File_Sys,
   --#                                         StartNode,
   --#                                         STree.Table,
   --#                                         Sub_Prog,
   --#                                         VCGHeap &
   --#         Statistics.TableUsage      from *,
   --#                                         Abstraction,
   --#                                         CommandLineData.Content,
   --#                                         Dictionary.Dict,
   --#                                         EqualityOperator,
   --#                                         ForceAbstract,
   --#                                         LexTokenManager.State,
   --#                                         LoopStack,
   --#                                         Return_Cell,
   --#                                         Scope,
   --#                                         StartNode,
   --#                                         STree.Table,
   --#                                         Sub_Prog,
   --#                                         VCGHeap;
   is
      DAGRootLocal, ExpnDAGRoot : Cells.Cell;
      Implicit_Return_Var       : Dictionary.Symbol;
   begin -- CreateFunctionAnnotationDAG
      if StartNode = STree.NullNode then
         CreateTrueCell (VCGHeap, DAGRootLocal);
         Conjoined_Function_Defs := Cells.Null_Cell;
      elsif STree.Syntax_Node_Type (Node => StartNode) = SP_Symbols.annotation_expression then
         -- build post condition for simple return expression
         CreateAnnotationDAG
           (Start_Node              => StartNode,
            Scope                   => Scope,
            Force_Abstract          => ForceAbstract,
            Conjoined_Function_Defs => Conjoined_Function_Defs,
            DAG_Root                => ExpnDAGRoot);
         -- now we need to equate the ReturnCell with the ExpnDAG
         -- first cet up the desired operator
         if EqualityOperator = UseEquals then
            CreateOpCell (DAGRootLocal, VCGHeap, SP_Symbols.equals);
         else
            CreateOpCell (DAGRootLocal, VCGHeap, SP_Symbols.is_equivalent_to);
         end if;
         -- and build expression
         SetLeftArgument (DAGRootLocal, Return_Cell, VCGHeap);
         SetRightArgument (DAGRootLocal, ExpnDAGRoot, VCGHeap);

      else -- build post condition for implicit return expression
         Implicit_Return_Var := Dictionary.GetImplicitReturnVariable (Abstraction, Sub_Prog);
         CreateAnnotationDAG
           (Start_Node              => STree.Next_Sibling (Current_Node => StartNode),
            Scope                   => Dictionary.Set_Visibility (The_Visibility => Dictionary.Local,
                                                                  The_Unit       => Implicit_Return_Var),
            Force_Abstract          => ForceAbstract,
            Conjoined_Function_Defs => Conjoined_Function_Defs,
            DAG_Root                => DAGRootLocal);

         -- substitute ReturnCell for all location in the above expression where
         -- the original annotation had an implciit return variable
         SubstituteImplicit (DAGRootLocal, Implicit_Return_Var, Return_Cell);
         -- Also substuitute the implicit return variable in all function definitions.
         SubstituteImplicit (Conjoined_Function_Defs, Implicit_Return_Var, Return_Cell);
      end if;
      DAGRoot := DAGRootLocal;
   end CreateFunctionAnnotationDAG;

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

   procedure Plant_Refinement_Checks (Scope : Dictionary.Scopes)
   --# global in     CommandLineData.Content;
   --#        in     ImportConstraints;
   --#        in     LoopStack;
   --#        in     STree.Table;
   --#        in out ContainsReals;
   --#        in out Dictionary.Dict;
   --#        in out ErrorHandler.Error_Context;
   --#        in out Graph.Table;
   --#        in out LexTokenManager.State;
   --#        in out SPARK_IO.File_Sys;
   --#        in out Statistics.TableUsage;
   --#        in out VCGFailure;
   --#        in out VCGHeap;
   --# derives ContainsReals,
   --#         Dictionary.Dict,
   --#         Graph.Table,
   --#         LexTokenManager.State,
   --#         Statistics.TableUsage,
   --#         VCGFailure,
   --#         VCGHeap                    from *,
   --#                                         CommandLineData.Content,
   --#                                         Dictionary.Dict,
   --#                                         ImportConstraints,
   --#                                         LexTokenManager.State,
   --#                                         LoopStack,
   --#                                         Scope,
   --#                                         STree.Table,
   --#                                         VCGHeap &
   --#         ErrorHandler.Error_Context,
   --#         SPARK_IO.File_Sys          from CommandLineData.Content,
   --#                                         Dictionary.Dict,
   --#                                         ErrorHandler.Error_Context,
   --#                                         ImportConstraints,
   --#                                         LexTokenManager.State,
   --#                                         LoopStack,
   --#                                         Scope,
   --#                                         SPARK_IO.File_Sys,
   --#                                         STree.Table,
   --#                                         VCGHeap;
   is
      Sub_Prog                : Dictionary.Symbol;
      PreCheck                : Cells.Cell;
      AbstractPre             : Cells.Cell;
      RefinedPre              : Cells.Cell;
      PreCheckHyp             : Cells.Cell;
      CommonHypotheses        : Cells.Cell;
      DataRefinement          : Cells.Cell;
      Conjoined_Function_Defs : Cells.Cell;
      Data_View               : Dictionary.Abstractions;

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

      procedure Create_Data_Refinement (Sub_Prog    : in     Dictionary.Symbol;
                                        In_Post_Con : in     Boolean;
                                        The_DAG     :    out Cells.Cell)
      --# global in     CommandLineData.Content;
      --#        in     Dictionary.Dict;
      --#        in out LexTokenManager.State;
      --#        in out Statistics.TableUsage;
      --#        in out VCGHeap;
      --# derives LexTokenManager.State from *,
      --#                                    CommandLineData.Content,
      --#                                    Dictionary.Dict,
      --#                                    Sub_Prog &
      --#         Statistics.TableUsage,
      --#         VCGHeap               from *,
      --#                                    CommandLineData.Content,
      --#                                    Dictionary.Dict,
      --#                                    In_Post_Con,
      --#                                    LexTokenManager.State,
      --#                                    Sub_Prog,
      --#                                    VCGHeap &
      --#         The_DAG               from CommandLineData.Content,
      --#                                    Dictionary.Dict,
      --#                                    In_Post_Con,
      --#                                    LexTokenManager.State,
      --#                                    Sub_Prog,
      --#                                    VCGHeap;
      is
         type Passes is (ProcessGlobals, ProcessParameters);
         pragma Unreferenced (ProcessParameters);
         It                        : Dictionary.Iterator;
         Abstract_It               : Dictionary.Iterator;
         Abstract_Sym, Current_Sym : Dictionary.Symbol;
         First_Item                : Boolean := True;
         DAG_Root, DAG_Local       : Cells.Cell;

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

         procedure Build_One_Refinement
           (Refined_Sym                       : in     Dictionary.Symbol;
            In_Post_Con, Is_Import, Is_Export : in     Boolean;
            Sub_Prog                          : in     Dictionary.Symbol;
            The_DAG                           :    out Cells.Cell)
         --# global in     CommandLineData.Content;
         --#        in     Dictionary.Dict;
         --#        in out LexTokenManager.State;
         --#        in out Statistics.TableUsage;
         --#        in out VCGHeap;
         --# derives LexTokenManager.State from *,
         --#                                    CommandLineData.Content,
         --#                                    Dictionary.Dict,
         --#                                    Refined_Sym,
         --#                                    Sub_Prog &
         --#         Statistics.TableUsage,
         --#         VCGHeap               from *,
         --#                                    CommandLineData.Content,
         --#                                    Dictionary.Dict,
         --#                                    In_Post_Con,
         --#                                    Is_Export,
         --#                                    Is_Import,
         --#                                    LexTokenManager.State,
         --#                                    Refined_Sym,
         --#                                    Sub_Prog,
         --#                                    VCGHeap &
         --#         The_DAG               from CommandLineData.Content,
         --#                                    Dictionary.Dict,
         --#                                    In_Post_Con,
         --#                                    Is_Export,
         --#                                    Is_Import,
         --#                                    LexTokenManager.State,
         --#                                    Refined_Sym,
         --#                                    Sub_Prog,
         --#                                    VCGHeap;

         is
            Tilde_Version, Operator_Cell, Field_Cell, Concrete_Cell, Abstract_Cell : Cells.Cell;
            Field_Name                                                             : LexTokenManager.Lex_String;

            procedure Build_Field_Name
            --# global in     CommandLineData.Content;
            --#        in     Dictionary.Dict;
            --#        in     Refined_Sym;
            --#        in     Sub_Prog;
            --#        in out LexTokenManager.State;
            --#           out Field_Name;
            --# derives Field_Name,
            --#         LexTokenManager.State from CommandLineData.Content,
            --#                                    Dictionary.Dict,
            --#                                    LexTokenManager.State,
            --#                                    Refined_Sym,
            --#                                    Sub_Prog;
            is
               Prefix : E_Strings.T;
            begin -- Build_Field_Name
               Prefix :=
                 Dictionary.GetAnyPrefixNeeded
                 (Sym       => Refined_Sym,
                  Scope     => Dictionary.Set_Visibility
                    (The_Visibility => Dictionary.Local,
                     The_Unit       => Dictionary.GetEnclosingPackage (Dictionary.GetScope (Sub_Prog))),
                  Separator => "__");
               if E_Strings.Get_Length (E_Str => Prefix) > 0 then
                  E_Strings.Append_String (E_Str => Prefix,
                                           Str   => "__");
               end if;
               E_Strings.Append_Examiner_String
                 (E_Str1 => Prefix,
                  E_Str2 => LexTokenManager.Lex_String_To_String (Lex_Str => Dictionary.GetSimpleName (Refined_Sym)));
               LexTokenManager.Insert_Examiner_String (Str     => Prefix,
                                                       Lex_Str => Field_Name);
            end Build_Field_Name;

         begin  -- Build_One_Refinement

            -- first define the operator to use
            CreateOpCell (Operator_Cell, VCGHeap, SP_Symbols.equals);
            if Dictionary.TypeIsBoolean (Dictionary.GetType (Refined_Sym)) then
               Cells.Set_Op_Symbol (VCGHeap, Operator_Cell, SP_Symbols.is_equivalent_to);
            end if;

            -- now create lhs
            CreateReferenceCell (Concrete_Cell, VCGHeap, Refined_Sym);

            -- now rhs
            CreateCellKind (Field_Cell, VCGHeap, Cell_Storage.Field_Access_Function);
            Cells.Set_Symbol_Value (VCGHeap, Field_Cell, Refined_Sym);
            Build_Field_Name;
            Cells.Set_Lex_Str (VCGHeap, Field_Cell, Field_Name);

            CreateReferenceCell (Abstract_Cell, VCGHeap, Dictionary.GetSubject (Refined_Sym));

            SetRightArgument (Field_Cell, Abstract_Cell, VCGHeap);

            -- assemble
            SetLeftArgument (Operator_Cell, Concrete_Cell, VCGHeap);
            SetRightArgument (Operator_Cell, Field_Cell, VCGHeap);

            -- mark as initial values if needed
            if In_Post_Con then
               -- might need some tildes else definitely don't
               if Is_Import then
                  -- must be either a pure import or and import/export either of which
                  -- need a tilded version of some sort.  Whatever form this takes, the
                  -- abstract side will be tilded
                  Structures.CopyStructure (VCGHeap, Operator_Cell, Tilde_Version);
                  SetTilde (Abstract_Cell, VCGHeap);
                  if Is_Export then
                     -- item is both imported and exported so we need to tilde both sides
                     SetTilde (Concrete_Cell, VCGHeap);
                  end if; -- Is_Export
                  Cells.Utility.Conjoin (VCGHeap, Tilde_Version, Operator_Cell);
               end if; -- Is_Import
            end if; -- In_Post_Condition

            -- return
            The_DAG := Operator_Cell;
         end Build_One_Refinement;

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

         function Requires_Refinement_Relation (Sym : Dictionary.Symbol) return Boolean
         --# global in Dictionary.Dict;
         --#        in Sub_Prog;
         is
         begin
            return Dictionary.IsConstituent (Sym)
              and then Dictionary.IsPackage (Dictionary.GetOwner (Dictionary.GetSubject (Sym)))
              and then Dictionary.Packages_Are_Equal
              (Left_Symbol  => Dictionary.GetOwner (Dictionary.GetSubject (Sym)),
               Right_Symbol => Dictionary.GetEnclosingPackage (Dictionary.GetScope (Sub_Prog)));
         end Requires_Refinement_Relation;

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

         function Is_Abstract_Own_Variable_Of_This_Package (Sym : Dictionary.Symbol) return Boolean
         --# global in Dictionary.Dict;
         --#        in Sub_Prog;
         is
         begin
            return Dictionary.IsRefinedOwnVariable (Sym)
              and then Dictionary.IsPackage (Dictionary.GetOwner (Sym))
              and then Dictionary.Packages_Are_Equal
              (Left_Symbol  => Dictionary.GetOwner (Sym),
               Right_Symbol => Dictionary.GetEnclosingPackage (Dictionary.GetScope (Sub_Prog)));
         end Is_Abstract_Own_Variable_Of_This_Package;

      begin -- Create_Data_Refinement
         DAG_Root := Cells.Null_Cell;
         for I in Passes loop
            if I = ProcessGlobals then
               It := Dictionary.FirstGlobalVariable (Dictionary.IsRefined, Sub_Prog);
            else
               It := Dictionary.FirstSubprogramParameter (Sub_Prog);
            end if;

            while not Dictionary.IsNullIterator (It) loop
               Current_Sym := Dictionary.CurrentSymbol (It);

               -- we are interested if Current_Sym is a refinement constituent of a
               -- locally-declared abstract own variable
               if Requires_Refinement_Relation (Sym => Current_Sym) then

                  Build_One_Refinement
                    (Refined_Sym => Current_Sym,
                     In_Post_Con => In_Post_Con,
                     Is_Import   => Dictionary.IsImport (Dictionary.IsRefined, Sub_Prog, Current_Sym),
                     Is_Export   => Dictionary.IsExport (Dictionary.IsRefined, Sub_Prog, Current_Sym),
                     Sub_Prog    => Sub_Prog,
                     The_DAG     => DAG_Local);
                  if First_Item then
                     DAG_Root   := DAG_Local;
                     First_Item := False;
                  else
                     Cells.Utility.Conjoin (VCGHeap, DAG_Local, DAG_Root);
                  end if;
               end if;
               It := Dictionary.NextSymbol (It);
            end loop;
         end loop;

         -- now loop through all constituents of the abstract own variables involved and
         -- treat their constituents as imports (i.e. read but unchanged) if they are not
         -- referenced at all by the subprogram.  Clearly if they are not referenced at all
         -- then they must be unchanged.  We need hypotheses to this effect to complete the
         -- data refinement

         Abstract_It := Dictionary.FirstGlobalVariable (Dictionary.IsAbstract, Sub_Prog);
         while not Dictionary.IsNullIterator (Abstract_It) loop
            Abstract_Sym := Dictionary.CurrentSymbol (Abstract_It);

            if Is_Abstract_Own_Variable_Of_This_Package (Sym => Abstract_Sym) then

               It := Dictionary.FirstConstituent (Abstract_Sym);
               while not Dictionary.IsNullIterator (It) loop
                  Current_Sym := Dictionary.CurrentSymbol (It);

                  -- we only need to do something if this constituent is neither an import or an
                  -- export in the refined view, otherwise it will already have been handled by
                  -- code above
                  if not (Dictionary.IsImport (Dictionary.IsRefined, Sub_Prog, Current_Sym) or
                            Dictionary.IsExport (Dictionary.IsRefined, Sub_Prog, Current_Sym)) then

                     Build_One_Refinement
                       (Refined_Sym => Current_Sym,
                        In_Post_Con => In_Post_Con,
                        Is_Import   => True,
                        Is_Export   => False,
                        Sub_Prog    => Sub_Prog,
                        The_DAG     => DAG_Local);
                     if First_Item then
                        DAG_Root   := DAG_Local;
                        First_Item := False;
                     else
                        Cells.Utility.Conjoin (VCGHeap, DAG_Local, DAG_Root);
                     end if;
                  end if;
                  It := Dictionary.NextSymbol (It);
               end loop;
            end if;

            Abstract_It := Dictionary.NextSymbol (Abstract_It);
         end loop;

         The_DAG := DAG_Root;
      end Create_Data_Refinement;

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

      -- procedure for use in creating both procedure and function
      -- refinement post condition checks; this procedure creates the
      -- things which are common to all cases such as twiddled pre cons
      procedure CreateCommonHypotheses
        (Data_View        : in     Dictionary.Abstractions;
         AbstractPre      : in     Cells.Cell;
         RefinedPre       : in     Cells.Cell;
         CommonHypotheses :    out Cells.Cell)
      --# global in     CommandLineData.Content;
      --#        in     Dictionary.Dict;
      --#        in     ImportConstraints;
      --#        in     Sub_Prog;
      --#        in out LexTokenManager.State;
      --#        in out Statistics.TableUsage;
      --#        in out VCGHeap;
      --# derives CommonHypotheses,
      --#         VCGHeap               from AbstractPre,
      --#                                    CommandLineData.Content,
      --#                                    Data_View,
      --#                                    Dictionary.Dict,
      --#                                    ImportConstraints,
      --#                                    LexTokenManager.State,
      --#                                    RefinedPre,
      --#                                    Sub_Prog,
      --#                                    VCGHeap &
      --#         LexTokenManager.State from *,
      --#                                    CommandLineData.Content,
      --#                                    Data_View,
      --#                                    Dictionary.Dict,
      --#                                    Sub_Prog &
      --#         Statistics.TableUsage from *,
      --#                                    AbstractPre,
      --#                                    CommandLineData.Content,
      --#                                    Data_View,
      --#                                    Dictionary.Dict,
      --#                                    ImportConstraints,
      --#                                    LexTokenManager.State,
      --#                                    RefinedPre,
      --#                                    Sub_Prog,
      --#                                    VCGHeap;
      is
         CopyOfImportConstraints, CopyOfAbstractPre, CopyOfRefinedPre, DataRefinement : Cells.Cell;
      begin
         Structures.CopyStructure (VCGHeap, AbstractPre, CopyOfAbstractPre);
         Structures.CopyStructure (VCGHeap, RefinedPre, CopyOfRefinedPre);

         -- The two precondition components of the hypothesis need any
         -- import/exports to be twiddled.
         -- Note that the refined precondition may have an abstract or refined
         -- data view depending on whether Data Refinement is present.
         SubstituteTwiddled (Dictionary.IsAbstract, Sub_Prog, CopyOfAbstractPre);
         SubstituteTwiddled (Data_View, Sub_Prog, CopyOfRefinedPre);

         -- Now assemble common parts of hypotheses
         Cells.Utility.Conjoin (VCGHeap, CopyOfRefinedPre, CopyOfAbstractPre);

         if Data_View = Dictionary.IsRefined then
            -- Data refinement is present and so add it to the common hypotheses.
            Create_Data_Refinement (Sub_Prog    => Sub_Prog,
                                    In_Post_Con => True,
                                    The_DAG     => DataRefinement);
            Cells.Utility.Conjoin (VCGHeap, DataRefinement, CopyOfAbstractPre);
         end if;

         -- Obtain a copy of the import constraints for use in the refinement VCs.
         Structures.CopyStructure (VCGHeap, ImportConstraints, CopyOfImportConstraints);

         -- Add in import type information if it exists
         -- Note that import types may have an abstract or refined
         -- data view depending on whether Data Refinement is present.
         if not Cells.Is_Null_Cell (CopyOfImportConstraints) then
            SubstituteTwiddled (Data_View, Sub_Prog, CopyOfImportConstraints);
            Cells.Utility.Conjoin (VCGHeap, CopyOfImportConstraints, CopyOfAbstractPre);
         end if;

         -- and return result
         CommonHypotheses := CopyOfAbstractPre;
      end CreateCommonHypotheses;

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

      procedure ProcedureRefinementPostCheck
        (Data_View        : in Dictionary.Abstractions;
         CommonHypotheses : in Cells.Cell;
         Scope            : in Dictionary.Scopes)
      --# global in     CommandLineData.Content;
      --#        in     LoopStack;
      --#        in     STree.Table;
      --#        in     Sub_Prog;
      --#        in out ContainsReals;
      --#        in out Dictionary.Dict;
      --#        in out ErrorHandler.Error_Context;
      --#        in out Graph.Table;
      --#        in out LexTokenManager.State;
      --#        in out SPARK_IO.File_Sys;
      --#        in out Statistics.TableUsage;
      --#        in out VCGFailure;
      --#        in out VCGHeap;
      --# derives ContainsReals,
      --#         Dictionary.Dict,
      --#         LexTokenManager.State,
      --#         VCGFailure                 from *,
      --#                                         CommandLineData.Content,
      --#                                         Data_View,
      --#                                         Dictionary.Dict,
      --#                                         LexTokenManager.State,
      --#                                         LoopStack,
      --#                                         Scope,
      --#                                         STree.Table,
      --#                                         Sub_Prog,
      --#                                         VCGHeap &
      --#         ErrorHandler.Error_Context from *,
      --#                                         CommandLineData.Content,
      --#                                         Dictionary.Dict,
      --#                                         LexTokenManager.State,
      --#                                         LoopStack,
      --#                                         SPARK_IO.File_Sys,
      --#                                         STree.Table,
      --#                                         Sub_Prog,
      --#                                         VCGHeap &
      --#         Graph.Table,
      --#         Statistics.TableUsage,
      --#         VCGHeap                    from *,
      --#                                         CommandLineData.Content,
      --#                                         CommonHypotheses,
      --#                                         Data_View,
      --#                                         Dictionary.Dict,
      --#                                         LexTokenManager.State,
      --#                                         LoopStack,
      --#                                         Scope,
      --#                                         STree.Table,
      --#                                         Sub_Prog,
      --#                                         VCGHeap &
      --#         SPARK_IO.File_Sys          from *,
      --#                                         CommandLineData.Content,
      --#                                         Data_View,
      --#                                         Dictionary.Dict,
      --#                                         ErrorHandler.Error_Context,
      --#                                         LexTokenManager.State,
      --#                                         LoopStack,
      --#                                         Scope,
      --#                                         STree.Table,
      --#                                         Sub_Prog,
      --#                                         VCGHeap;
      is
         PostCheck               : Cells.Cell;
         PostHypotheses          : Cells.Cell;
         AbstractPost            : Cells.Cell;
         RefinedPost             : Cells.Cell;
         ExportConstraints       : Cells.Cell;
         Conjoined_Function_Defs : Cells.Cell;
         Initial_Function_Defs   : Cells.Cell;

         procedure GetExportConstraints (Data_View : in Dictionary.Abstractions;
                                         Scope     : in Dictionary.Scopes)
         --# global in     CommandLineData.Content;
         --#        in     Sub_Prog;
         --#        in out ContainsReals;
         --#        in out Dictionary.Dict;
         --#        in out LexTokenManager.State;
         --#        in out SPARK_IO.File_Sys;
         --#        in out Statistics.TableUsage;
         --#        in out VCGFailure;
         --#        in out VCGHeap;
         --#           out ExportConstraints;
         --# derives ContainsReals,
         --#         Dictionary.Dict,
         --#         LexTokenManager.State,
         --#         SPARK_IO.File_Sys,
         --#         Statistics.TableUsage,
         --#         VCGFailure,
         --#         VCGHeap               from *,
         --#                                    CommandLineData.Content,
         --#                                    Data_View,
         --#                                    Dictionary.Dict,
         --#                                    LexTokenManager.State,
         --#                                    Scope,
         --#                                    Sub_Prog,
         --#                                    VCGHeap &
         --#         ExportConstraints     from CommandLineData.Content,
         --#                                    Data_View,
         --#                                    Dictionary.Dict,
         --#                                    LexTokenManager.State,
         --#                                    Scope,
         --#                                    Sub_Prog,
         --#                                    VCGHeap;
         is
            ExportIt        : Dictionary.Iterator;
            VarSym, TypeSym : Dictionary.Symbol;
         begin -- GetExportConstraints
            ExportConstraints := Cells.Null_Cell;
            -- The data view of the Exports may be Abstract or Refined
            -- dependent on the use of Data Refinement.
            ExportIt := Dictionary.FirstExport (Data_View, Sub_Prog);
            while not Dictionary.IsNullIterator (ExportIt) loop
               VarSym := Dictionary.CurrentSymbol (ExportIt);
               if IsDirectlyVisible (VarSym, Scope) then
                  TypeSym := Dictionary.GetType (VarSym);

                  if not Dictionary.IsPrivateType (TypeSym, Scope) or else Dictionary.IsPredefinedTimeType (TypeSym) then

                     ConjoinParamConstraint (TypeSym, VarSym, Scope, False, ExportConstraints);
                  end if;
               end if;
               ExportIt := Dictionary.NextSymbol (ExportIt);
            end loop;
         end GetExportConstraints;

      begin -- ProcedureRefinementPostCheck
         CreateAnnotationDAG
           (Start_Node              => STree.RefToNode (Dictionary.GetPostcondition (Dictionary.IsAbstract, Sub_Prog)),
            Scope                   => Dictionary.Set_Visibility (The_Visibility => Dictionary.Privat,
                                                                  The_Unit       => Sub_Prog),
            Force_Abstract          => True,
            Conjoined_Function_Defs => Initial_Function_Defs,
            DAG_Root                => AbstractPost);

         CreateAnnotationDAG
           (Start_Node              => STree.RefToNode (Dictionary.GetPostcondition (Dictionary.IsRefined, Sub_Prog)),
            Scope                   => Dictionary.Set_Visibility (The_Visibility => Dictionary.Local,
                                                                  The_Unit       => Sub_Prog),
            Force_Abstract          => False,
            Conjoined_Function_Defs => Conjoined_Function_Defs,
            DAG_Root                => RefinedPost);

         -- Conjoin all of the called function definitions.
         -- True if there are none.
         Cells.Utility.Conjoin (VCGHeap, Initial_Function_Defs, Conjoined_Function_Defs);

         PostHypotheses := CommonHypotheses;

         -- build in info that exports must be in type
         GetExportConstraints (Data_View => Data_View,
                               Scope     => Scope);
         if not Cells.Is_Null_Cell (ExportConstraints) then
            Cells.Utility.Conjoin (VCGHeap, ExportConstraints, PostHypotheses);
         end if;
         Cells.Utility.Conjoin (VCGHeap, RefinedPost, PostHypotheses);

         -- conjoin called function definitions to the Post Hypotheses
         Cells.Utility.Conjoin (VCGHeap, Conjoined_Function_Defs, PostHypotheses);

         Cells.Create_Cell (VCGHeap, PostCheck);

         SetRightArgument (PostCheck, PostHypotheses, VCGHeap);     -- set up hypothesis
         SetAuxPtr (PostCheck, AbstractPost, VCGHeap);       -- set up conclusion
         Graph.Set_Refinement_Post_Check (X => PostCheck);           -- pass it to graph
      end ProcedureRefinementPostCheck;

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

      procedure FunctionRefinementPostCheck (CommonHypotheses : in Cells.Cell;
                                             Scope            : in Dictionary.Scopes)
      --# global in     CommandLineData.Content;
      --#        in     LoopStack;
      --#        in     STree.Table;
      --#        in     Sub_Prog;
      --#        in out ContainsReals;
      --#        in out Dictionary.Dict;
      --#        in out ErrorHandler.Error_Context;
      --#        in out Graph.Table;
      --#        in out LexTokenManager.State;
      --#        in out SPARK_IO.File_Sys;
      --#        in out Statistics.TableUsage;
      --#        in out VCGFailure;
      --#        in out VCGHeap;
      --# derives ContainsReals,
      --#         Dictionary.Dict,
      --#         LexTokenManager.State,
      --#         VCGFailure                 from *,
      --#                                         CommandLineData.Content,
      --#                                         Dictionary.Dict,
      --#                                         LexTokenManager.State,
      --#                                         LoopStack,
      --#                                         Scope,
      --#                                         STree.Table,
      --#                                         Sub_Prog,
      --#                                         VCGHeap &
      --#         ErrorHandler.Error_Context from *,
      --#                                         CommandLineData.Content,
      --#                                         Dictionary.Dict,
      --#                                         LexTokenManager.State,
      --#                                         LoopStack,
      --#                                         SPARK_IO.File_Sys,
      --#                                         STree.Table,
      --#                                         Sub_Prog,
      --#                                         VCGHeap &
      --#         Graph.Table,
      --#         Statistics.TableUsage,
      --#         VCGHeap                    from *,
      --#                                         CommandLineData.Content,
      --#                                         CommonHypotheses,
      --#                                         Dictionary.Dict,
      --#                                         LexTokenManager.State,
      --#                                         LoopStack,
      --#                                         Scope,
      --#                                         STree.Table,
      --#                                         Sub_Prog,
      --#                                         VCGHeap &
      --#         SPARK_IO.File_Sys          from *,
      --#                                         CommandLineData.Content,
      --#                                         Dictionary.Dict,
      --#                                         ErrorHandler.Error_Context,
      --#                                         LexTokenManager.State,
      --#                                         LoopStack,
      --#                                         Scope,
      --#                                         STree.Table,
      --#                                         Sub_Prog,
      --#                                         VCGHeap;
      is
         Return_Type             : Dictionary.Symbol;
         Return_Cell             : Cells.Cell;
         EqualityOperator        : Equalities;
         ExportConstraint        : Cells.Cell;
         PostCheck               : Cells.Cell;
         PostHypotheses          : Cells.Cell;
         AbstractPost            : Cells.Cell;
         RefinedPost             : Cells.Cell;
         Conjoined_Function_Defs : Cells.Cell;
         Initial_Function_Defs   : Cells.Cell;
      begin
         -- identify function return type
         Return_Type := Dictionary.GetType (Sub_Prog);

         -- create a ReturnVar cell containing the function return type
         CreateCellKind (Return_Cell, VCGHeap, Cell_Storage.Return_Var);
         Cells.Set_Symbol_Value (VCGHeap, Return_Cell, Return_Type);

         -- for explicit returns we need to equate the ReturnVar to the returned expression
         -- so we need to choose the appropriate operator
         if Dictionary.TypeIsBoolean (Return_Type) then
            EqualityOperator := UseImplication;
         else
            EqualityOperator := UseEquals;
         end if;

         -- now build abstract and refined "post conditions"
         CreateFunctionAnnotationDAG
           (Sub_Prog                => Sub_Prog,
            StartNode               => STree.RefToNode (Dictionary.GetPostcondition (Dictionary.IsAbstract, Sub_Prog)),
            Scope                   => Dictionary.Set_Visibility (The_Visibility => Dictionary.Privat,
                                                                  The_Unit       => Sub_Prog),
            ForceAbstract           => True,
            Return_Cell             => Return_Cell,
            EqualityOperator        => EqualityOperator,
            Abstraction             => Dictionary.IsAbstract,
            Conjoined_Function_Defs => Initial_Function_Defs,
            DAGRoot                 => AbstractPost);

         CreateFunctionAnnotationDAG
           (Sub_Prog                => Sub_Prog,
            StartNode               => STree.RefToNode (Dictionary.GetPostcondition (Dictionary.IsRefined, Sub_Prog)),
            Scope                   => Dictionary.Set_Visibility (The_Visibility => Dictionary.Local,
                                                                  The_Unit       => Sub_Prog),
            ForceAbstract           => False,
            Return_Cell             => Return_Cell,
            EqualityOperator        => EqualityOperator,
            Abstraction             => Dictionary.IsRefined,
            Conjoined_Function_Defs => Conjoined_Function_Defs,
            DAGRoot                 => RefinedPost);

         -- Conjoin all of the called function definitions.
         -- True if there are none.
         Cells.Utility.Conjoin (VCGHeap, Initial_Function_Defs, Conjoined_Function_Defs);

         PostHypotheses := CommonHypotheses;

         -- add in constraint that returned valued must be in type
         Type_Constraint.Make
           (The_Type              => Return_Type,
            The_Expression        => Return_Cell,
            Scope                 => Scope,
            Consider_Always_Valid => False,
            The_Constraint        => ExportConstraint,
            VCG_Heap              => VCGHeap,
            VC_Contains_Reals     => ContainsReals,
            VC_Failure            => VCGFailure);

         Cells.Utility.Conjoin (VCGHeap, ExportConstraint, PostHypotheses);
         Cells.Utility.Conjoin (VCGHeap, RefinedPost, PostHypotheses);

         -- conjoin called function definitions to the Post Hypotheses
         Cells.Utility.Conjoin (VCGHeap, Conjoined_Function_Defs, PostHypotheses);

         Cells.Create_Cell (VCGHeap, PostCheck);

         SetRightArgument (PostCheck, PostHypotheses, VCGHeap);     -- set up hypothesis
         SetAuxPtr (PostCheck, AbstractPost, VCGHeap);       -- set up conclusion
         Graph.Set_Refinement_Post_Check (X => PostCheck);           -- pass it to graph

      end FunctionRefinementPostCheck;

   begin -- Plant_Refinement_Checks
      Sub_Prog := Dictionary.GetRegion (Scope);

      -- first create VC: abstract pre --> refined pre
      CreateAnnotationDAG
        (Start_Node              => STree.RefToNode (Dictionary.GetPrecondition (Dictionary.IsAbstract, Sub_Prog)),
         Scope                   => Dictionary.Set_Visibility (The_Visibility => Dictionary.Privat,
                                                               The_Unit       => Sub_Prog),
         Force_Abstract          => True,
         Conjoined_Function_Defs => Conjoined_Function_Defs,
         DAG_Root                => PreCheckHyp);

      Structures.CopyStructure (VCGHeap, PreCheckHyp, AbstractPre);

      -- Determine whether the view of the data should be
      -- Abstract (Proof Refinement only) or
      -- Refined  (Data Refinement is present).
      Create_Data_Refinement (Sub_Prog    => Sub_Prog,
                              In_Post_Con => False,
                              The_DAG     => DataRefinement);
      if Cells.Is_Null_Cell (DataRefinement) then

         -- No Data Refinement.
         Data_View := Dictionary.IsAbstract;
      else
         -- Data Refinement is present.
         Data_View := Dictionary.IsRefined;
      end if;

      if Data_View = Dictionary.IsRefined then
         -- Data Refinement is present and so add it in to the hypotheses
         Cells.Utility.Conjoin (VCGHeap, DataRefinement, PreCheckHyp);
      end if;

      if not Cells.Is_Null_Cell (ImportConstraints) then
         -- add in import type information to hypotheses if these exist
         Cells.Utility.Conjoin (VCGHeap, ImportConstraints, PreCheckHyp);
      end if;

      -- Conjoin any function definitions called in the abstract pre condition
      -- to the Pre check Hypotheses
      Cells.Utility.Conjoin (VCGHeap, Conjoined_Function_Defs, PreCheckHyp);

      CreateAnnotationDAG
        (Start_Node              => STree.RefToNode (Dictionary.GetPrecondition (Dictionary.IsRefined, Sub_Prog)),
         Scope                   => Dictionary.Set_Visibility (The_Visibility => Dictionary.Local,
                                                               The_Unit       => Sub_Prog),
         Force_Abstract          => False,
         Conjoined_Function_Defs => Conjoined_Function_Defs,
         DAG_Root                => RefinedPre);

      -- Conjoin any function definitions called in the refined pre condition
      -- to the Pre check Hypotheses
      Cells.Utility.Conjoin (VCGHeap, Conjoined_Function_Defs, PreCheckHyp);

      Cells.Create_Cell (VCGHeap, PreCheck);
      SetRightArgument (PreCheck, PreCheckHyp, VCGHeap);    -- set up hypothesis
      SetAuxPtr (PreCheck, RefinedPre, VCGHeap);     -- set up conclusion
      Graph.Set_Refinement_Pre_Check (X => PreCheck);        -- pass to graph

      -- now create VC: refined post /\ refined pre /\ abstract pre --> abstract post

      CreateCommonHypotheses (Data_View, AbstractPre, RefinedPre, CommonHypotheses);

      if Dictionary.IsFunction (Dictionary.GetRegion (Scope)) then
         FunctionRefinementPostCheck (CommonHypotheses => CommonHypotheses,
                                      Scope            => Scope);
      else
         ProcedureRefinementPostCheck (Data_View        => Data_View,
                                       CommonHypotheses => CommonHypotheses,
                                       Scope            => Scope);
      end if;

   end Plant_Refinement_Checks;

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

   procedure Plant_Sub_Class_Checks (Scope : in Dictionary.Scopes)
   --# global in     CommandLineData.Content;
   --#        in     LoopStack;
   --#        in     STree.Table;
   --#        in out ContainsReals;
   --#        in out Dictionary.Dict;
   --#        in out ErrorHandler.Error_Context;
   --#        in out Graph.Table;
   --#        in out LexTokenManager.State;
   --#        in out SPARK_IO.File_Sys;
   --#        in out Statistics.TableUsage;
   --#        in out VCGFailure;
   --#        in out VCGHeap;
   --# derives ContainsReals,
   --#         Dictionary.Dict,
   --#         Graph.Table,
   --#         LexTokenManager.State,
   --#         Statistics.TableUsage,
   --#         VCGFailure,
   --#         VCGHeap                    from *,
   --#                                         CommandLineData.Content,
   --#                                         Dictionary.Dict,
   --#                                         LexTokenManager.State,
   --#                                         LoopStack,
   --#                                         Scope,
   --#                                         STree.Table,
   --#                                         VCGHeap &
   --#         ErrorHandler.Error_Context,
   --#         SPARK_IO.File_Sys          from CommandLineData.Content,
   --#                                         Dictionary.Dict,
   --#                                         ErrorHandler.Error_Context,
   --#                                         LexTokenManager.State,
   --#                                         LoopStack,
   --#                                         Scope,
   --#                                         SPARK_IO.File_Sys,
   --#                                         STree.Table,
   --#                                         VCGHeap;
   is
      Sub_Prog, Root_Sub_Prog                                 : Dictionary.Symbol;
      Pre_Cell, Post_Cell, RootPre, RootPost, ExtPre, ExtPost : Cells.Cell;
      Return_Type                                             : Dictionary.Symbol;
      Return_Cell                                             : Cells.Cell;
      Conjoined_Function_Defs                                 : Cells.Cell;
      EqualityOperator                                        : Equalities;

      procedure SubstituteParameters (Subprog, RootSubprog : in Dictionary.Symbol;
                                      RootConstraintRoot   : in Cells.Cell)
      --# global in     Dictionary.Dict;
      --#        in out Statistics.TableUsage;
      --#        in out VCGHeap;
      --# derives Statistics.TableUsage,
      --#         VCGHeap               from *,
      --#                                    Dictionary.Dict,
      --#                                    RootConstraintRoot,
      --#                                    RootSubprog,
      --#                                    Subprog,
      --#                                    VCGHeap;
      is
         P, NewP : Cells.Cell;
         S       : CStacks.Stack;
         VarSym  : Dictionary.Symbol;
      begin
         -- DAG traversal algorithm of D.E. Knuth, Fundamental Algorithms, p.317;
         CStacks.CreateStack (S);
         P := RootConstraintRoot;
         loop
            loop
               exit when Cells.Is_Null_Cell (P);
               CStacks.Push (VCGHeap, P, S);
               if Is_Leaf (Node     => P,
                           VCG_Heap => VCGHeap) then
                  P := Cells.Null_Cell;
               else
                  P := LeftPtr (VCGHeap, P);
               end if;
            end loop;
            exit when CStacks.IsEmpty (S);
            P := CStacks.Top (VCGHeap, S);
            CStacks.Pop (VCGHeap, S);
            if Is_Leaf (Node     => P,
                        VCG_Heap => VCGHeap) then
               if Cells.Get_Kind (VCGHeap, P) = Cell_Storage.Reference then
                  VarSym := Cells.Get_Symbol_Value (VCGHeap, P);
                  if Dictionary.IsSubprogramParameter (VarSym) then
                     -- Substitute name.
                     Cells.Set_Symbol_Value
                       (VCGHeap,
                        P,
                        Dictionary.GetSubprogramParameter (Subprog, Dictionary.GetSubprogramParameterNumber (VarSym)));
                     if Dictionary.Types_Are_Equal
                       (Left_Symbol        => Dictionary.GetType (VarSym),
                        Right_Symbol       => Dictionary.GetSubprogramControllingType (RootSubprog),
                        Full_Range_Subtype => False) then
                        -- Substitute an inherit dereference to the parameter used in Subprog (because we are
                        -- constructing VC in terms of Sub_Prog not Root_Sub_Prog so references to the controlling
                        -- parameter of Root_Sub_Prog must be replaced by fld_inherit ("controlling param of Sub_Prog")
                        Cells.Create_Cell (VCGHeap, NewP);
                        Cells.Copy_Contents (VCGHeap, P, NewP);
                        InsertInheritDeReference (Cells.Get_Symbol_Value (VCGHeap, P), VCGHeap, NewP);
                        Cells.Copy_Contents (VCGHeap, NewP, P);
                     end if;
                  end if;
               end if;
               P := Cells.Null_Cell;
            else
               P := RightPtr (VCGHeap, P);
            end if;
         end loop;
      end SubstituteParameters;

   begin  -- Plant_Sub_Class_Checks
      Sub_Prog := Dictionary.GetRegion (Scope);
      if Dictionary.Is_Subprogram (Sub_Prog) then
         Root_Sub_Prog := Dictionary.GetOverriddenSubprogram (Sub_Prog);
         if not Dictionary.Is_Null_Symbol (Root_Sub_Prog) then
            -- subclass integrity checks required

            -- first do preconditon check: abstract root pre -> abstract extended pre
            -- create abstract root pre
            CreateAnnotationDAG
              (Start_Node              => STree.RefToNode (Dictionary.GetPrecondition (Dictionary.IsAbstract, Root_Sub_Prog)),
               Scope                   => Dictionary.Set_Visibility (The_Visibility => Dictionary.Local,
                                                                     The_Unit       => Root_Sub_Prog),
               Force_Abstract          => True,
               Conjoined_Function_Defs => Conjoined_Function_Defs,
               DAG_Root                => RootPre);

            -- Conjoin the called function definitions from the root precondition
            -- with the hypotheses for the root precondition
            Cells.Utility.Conjoin (VCGHeap, Conjoined_Function_Defs, RootPre);

            -- change parameter names in root op to match those in extended op
            SubstituteParameters (Sub_Prog, Root_Sub_Prog, RootPre);

            -- create abstract extended pre
            CreateAnnotationDAG
              (Start_Node              => STree.RefToNode (Dictionary.GetPrecondition (Dictionary.IsAbstract, Sub_Prog)),
               Scope                   => Dictionary.Set_Visibility (The_Visibility => Dictionary.Local,
                                                                     The_Unit       => Sub_Prog),
               Force_Abstract          => True,
               Conjoined_Function_Defs => Conjoined_Function_Defs,
               DAG_Root                => ExtPre);

            -- Conjoin the called function definitions from the extended precondition
            -- with the hypotheses for the root precondition
            Cells.Utility.Conjoin (VCGHeap, Conjoined_Function_Defs, RootPre);

            -- assemble check
            Cells.Create_Cell (VCGHeap, Pre_Cell);
            SetRightArgument (Pre_Cell, RootPre, VCGHeap);   -- set up hypothesis
            SetAuxPtr (Pre_Cell, ExtPre, VCGHeap);           -- set up conclusion
            Graph.Set_Subclass_Pre_Check (X => Pre_Cell);   -- pass to graph

            -- go on to do post check here
            if Dictionary.IsFunction (Sub_Prog) then
               Return_Type := Dictionary.GetType (Sub_Prog);
               -- create a ReturnVar cell containing the function return type
               CreateCellKind (Return_Cell, VCGHeap, Cell_Storage.Return_Var);
               Cells.Set_Symbol_Value (VCGHeap, Return_Cell, Return_Type);

               -- for explicit returns we need to equate the ReturnVar to the returned expression
               -- so we need to choose the appropriate operator
               if Dictionary.TypeIsBoolean (Return_Type) then
                  EqualityOperator := UseImplication;
               else
                  EqualityOperator := UseEquals;
               end if;
               -- now create "postcondition" DAGs
               CreateFunctionAnnotationDAG
                 (Sub_Prog,
                  STree.RefToNode (Dictionary.GetPostcondition (Dictionary.IsAbstract, Sub_Prog)),
                  Dictionary.Set_Visibility (The_Visibility => Dictionary.Local,
                                             The_Unit       => Sub_Prog),
                  True,
                  Return_Cell,
                  EqualityOperator,
                  Dictionary.IsAbstract,
                  -- to get
                  Conjoined_Function_Defs,
                  ExtPost);

               -- Conjoin the called function definitions from the extended postcondition
               -- with the hypotheses for the extended postcondition
               Cells.Utility.Conjoin (VCGHeap, Conjoined_Function_Defs, ExtPost);

               CreateFunctionAnnotationDAG
                 (Root_Sub_Prog,
                  STree.RefToNode (Dictionary.GetPostcondition (Dictionary.IsAbstract, Root_Sub_Prog)),
                  Dictionary.Set_Visibility (The_Visibility => Dictionary.Local,
                                             The_Unit       => Root_Sub_Prog),
                  True,
                  Return_Cell,
                  EqualityOperator,
                  Dictionary.IsAbstract,
                  -- to get
                  Conjoined_Function_Defs,
                  RootPost);

               -- Conjoin the called function definitions from the root postcondition
               -- with the hypotheses for the extended postcondition
               Cells.Utility.Conjoin (VCGHeap, Conjoined_Function_Defs, ExtPost);

            else -- procedure

               -- create abstract extended post
               CreateAnnotationDAG
                 (Start_Node              => STree.RefToNode (Dictionary.GetPostcondition (Dictionary.IsAbstract, Sub_Prog)),
                  Scope                   => Dictionary.Set_Visibility (The_Visibility => Dictionary.Local,
                                                                        The_Unit       => Sub_Prog),
                  Force_Abstract          => True,
                  Conjoined_Function_Defs => Conjoined_Function_Defs,
                  DAG_Root                => ExtPost);

               -- Conjoin the called function definitions from the extended postcondition
               -- with the hypotheses for the extended postcondition
               Cells.Utility.Conjoin (VCGHeap, Conjoined_Function_Defs, ExtPost);

               -- create abstract root post
               CreateAnnotationDAG
                 (Start_Node              => STree.RefToNode (Dictionary.GetPostcondition (Dictionary.IsAbstract, Root_Sub_Prog)),
                  Scope                   => Dictionary.Set_Visibility (The_Visibility => Dictionary.Local,
                                                                        The_Unit       => Root_Sub_Prog),
                  Force_Abstract          => True,
                  Conjoined_Function_Defs => Conjoined_Function_Defs,
                  DAG_Root                => RootPost);

               -- Conjoin the called function definitions from the root postcondition
               -- with the hypotheses for the extended postcondition
               Cells.Utility.Conjoin (VCGHeap, Conjoined_Function_Defs, ExtPost);
            end if;

            SubstituteParameters (Sub_Prog, Root_Sub_Prog, RootPost);
            -- assemble check
            Cells.Create_Cell (VCGHeap, Post_Cell);
            SetRightArgument (Post_Cell, ExtPost, VCGHeap);   -- set up hypothesis
            SetAuxPtr (Post_Cell, RootPost, VCGHeap);         -- set up conclusion
            Graph.Set_Subclass_Post_Check (X => Post_Cell);  -- pass to graph
         end if;
      end if;
   end Plant_Sub_Class_Checks;

begin -- IncorporateConstraints

   -- first do Pre Condition if Subprogram
   if Dictionary.Is_Subprogram (Dictionary.GetRegion (Scope)) or else Dictionary.IsTaskType (Dictionary.GetRegion (Scope)) then
      PreConNode :=
        STree.RefToNode (Dictionary.GetPrecondition (Which_Abstraction (Scope => Scope), Dictionary.GetRegion (Scope)));
      Plant_Precondition (Node                         => PreConNode,
                          Semantic_Error_In_Subprogram => Semantic_Error_In_Subprogram,
                          Scope                        => Scope);

      if not Semantic_Error_In_Subprogram then
         -- Only create these VCs in the absence of semantic errors in the subprgoram body
         if Which_Abstraction (Scope => Scope) = Dictionary.IsRefined then
            -- then a second annotation has been found so refinement proof is needed
            Plant_Refinement_Checks (Scope => Scope);
         end if;
         Plant_Sub_Class_Checks (Scope => Scope);
      end if;
   end if;

   -- then Post Condition for subprogram or package init
   PostConNode :=
     STree.RefToNode (Dictionary.GetPostcondition (Which_Abstraction (Scope => Scope), Dictionary.GetRegion (Scope)));

   if Dictionary.IsFunction (Dictionary.GetRegion (Scope)) then
      Plant_Return_Expression
        (Return_Type                  => Dictionary.GetType (Dictionary.GetRegion (Scope)),
         Node                         => PostConNode,
         Semantic_Error_In_Subprogram => Semantic_Error_In_Subprogram,
         Scope                        => Scope);
   else
      Plant_Postcondition
        (Node                         => PostConNode,
         Subprog                      => Dictionary.GetRegion (Scope),
         Abstraction                  => Which_Abstraction (Scope => Scope),
         Semantic_Error_In_Subprogram => Semantic_Error_In_Subprogram,
         Type_Check_Exports           => Type_Check_Exports,
         Scope                        => Scope);
   end if;
end IncorporateConstraints;
