-------------------------------------------------------------------------------
-- (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 Cells;
with Dictionary;
with ExaminerConstants;
with E_Strings;
with Labels;
with SPARK_IO;

use type SPARK_IO.File_Status;

--# inherit Cells,
--#         Clists,
--#         CommandLineData,
--#         DAG_IO,
--#         Debug,
--#         Declarations,
--#         Dictionary,
--#         ExaminerConstants,
--#         E_Strings,
--#         Labels,
--#         LexTokenManager,
--#         Pairs,
--#         SPARK_IO,
--#         Statistics,
--#         Structures,
--#         SystemErrors;

package Graph
--# own Table : Table_Type;
--# initializes Table;
is
   ----------------------------------------------------------------------------
   -- The Graph.Table state forms the core data structure of the VC Generator.
   --
   -- It represents the Basic Path Graph (BPG) of the subprogram for which
   -- we are generating VCs.
   --
   -- The BPG is initially built by DAG.BuildGraph, based on data coming
   -- from the Syntax Tree, Dictionary and Flow Analyser.  This BPG has many
   -- "Unspecified" nodes representing every statement of the subprogram under
   -- analysis.  The "arcs" of the graph (between nodes) reflect the simple
   -- control-flow structure of the source program.  Each of these is
   -- generated with a predicate/action Pair structure, representing the
   -- path-traversal condition and (possible) assignment performed by that arc.
   --
   -- After DAG.BuildGraph, the calling environment then invokes Graph.Gen_VCs.
   --
   -- After Gen_VCs
   -- -------------
   -- All "Unspecified" nodes are removed, leaving only nodes representing
   -- the pre-codition, post-condition, assertions, checks and so on.
   -- At this point the Pair attached to each arc represents the Verification
   -- Condition for that basic path, after application of Hoare's assignment
   -- axiom to generate weakest pre-conditions and so on.
   --
   ----------------------------------------------------------------------------

   type Dump_Kind is (DPCs, VCs, PFs);
   subtype Valid_Dump_Kind is Dump_Kind range DPCs .. VCs;
   subtype DOT_Dump_Kind is Dump_Kind range VCs .. PFs;

   --# type Table_Type is abstract; -- for proof functions below

   -- Each node (or "Statement") in the basic-path graph (BPG) is numbered thus...
   subtype Matrix_Index is Integer range 1 .. ExaminerConstants.VCGMatrixOrder;

   -- ...and has a type:
   type Proof_Context_Type is (
                               Assertion, -- Explicit assert annotation
                               Default_Assertion, -- Examiner-generated assertion (loop invariant)
                               Check_Statement, -- Explicit check annotation
                               Run_Time_Check, -- Examiner-generated run-time check
                               Precon_Check, -- Check of a call to a subprogram with a precondition
                               Postcondition, -- Postcodition
                               Precondition, -- Precondition
                               Unspecified); -- Other nodes

   ----------------------------------------------------------------------
   -- The BPG has various attributes which are manipulated by the
   -- following operations
   ----------------------------------------------------------------------

   -----------------------
   -- Number of Statements
   -----------------------

   function Get_Nmbr_Of_Stmts return Matrix_Index;
   --# global in Table;

   procedure Inc_Nmbr_Of_Stmts;
   --# global in out Table;
   --# derives Table from *;
   --# pre Get_Nmbr_Of_Stmts (Table) < ExaminerConstants.VCGMatrixOrder;
   --# post Get_Nmbr_Of_Stmts (Table) = Get_Nmbr_Of_Stmts (Table~) + 1;

   procedure Set_Nmbr_Of_Stmts (N : in Matrix_Index);
   --# global in out Table;
   --# derives Table from *,
   --#                    N;
   --# post Get_Nmbr_Of_Stmts (Table) = N;

   -----------------
   -- Proof Contexts
   -----------------

   -- Returns the Proof_Context_Type for statement N
   --# function Get_Proof_Context (T : in Table_Type;
   --#                             N : in Matrix_Index) return Proof_Context_Type;

   -- Sets the Proof Context of the largest numbered statement
   procedure Set_Proof_Context (X : in Proof_Context_Type);
   --# global in out Table;
   --# derives Table from *,
   --#                    X;
   --# post Get_Proof_Context (Table, Get_Nmbr_Of_Stmts (Table)) = X;

   -- Sets the Proof Context for the precondition, which
   -- is always statement 1.
   procedure Set_First_Proof_Context (X : in Proof_Context_Type);
   --# global in out Table;
   --# derives Table from *,
   --#                    X;
   --# post Get_Proof_Context (Table, 1) = X;

   ---------------------
   -- Assertion Location
   ---------------------

   -- Each statement in the BPG may have a (possibly null)
   -- Assertion associated with it.  This is an FDL predicate
   -- represented as s DAG.

   -- Returns the Assertion for the node denoted by Get_Nmbr_Of_Stms
   function Get_Assertion_Locn return  Cells.Cell;
   --# global in Table;

   -- Returns the Assertion for the node denoted by Get_Nmbr_Of_Stms - 1
   function Get_Preceding_Assertion_Locn return  Cells.Cell;
   --# global in Table;
   --# pre Get_Nmbr_Of_Stmts (Table) > 1;

   -- Sets the Assertion for the node denoted by Get_Nmbr_Of_Stms
   procedure Set_Assertion_Locn (X : in Cells.Cell);
   --# global in out Table;
   --# derives Table from *,
   --#                    X;
   --# post Get_Assertion_Locn (Table) = X;

   -- Sets the Assertion for the precondition, which is always statement 1
   procedure Set_First_Assertion_Locn (X : in Cells.Cell);
   --# global in out Table;
   --# derives Table from *,
   --#                    X;

   --------------------------------------------------------------------
   -- Text_Line_Nmbr - associates a statement with a source line number
   --------------------------------------------------------------------

   -- Set the line number associated with the statement denoted by Get_Nmbr_Of_Stmts
   procedure Set_Text_Line_Nmbr (X : in Integer);
   --# global in out Table;
   --# derives Table from *,
   --#                    X;

   -- Set the line number associated with statement denoted by Index
   procedure Insert_Text_Line_Nmbr (Index : in Matrix_Index;
                                    X     : in Integer);
   --# global in out Table;
   --# derives Table from *,
   --#                    Index,
   --#                    X;

   ------------------------------------------------------------------
   -- Refinements VCs - In addition to those generated directly
   -- from the BPG, two additional VCs are generated for consistency
   -- of state refinement and two more for sub-class consistency (aka
   -- the VCs for "LSP" or "Covariance".)  These are stored in four
   -- further attributes of this package, thus:
   ------------------------------------------------------------------

   procedure Set_Refinement_Pre_Check (X : in Cells.Cell);
   --# global in out Table;
   --# derives Table from *,
   --#                    X;

   procedure Set_Refinement_Post_Check (X : in Cells.Cell);
   --# global in out Table;
   --# derives Table from *,
   --#                    X;

   procedure Set_Subclass_Pre_Check (X : in Cells.Cell);
   --# global in out Table;
   --# derives Table from *,
   --#                    X;

   procedure Set_Subclass_Post_Check (X : in Cells.Cell);
   --# global in out Table;
   --# derives Table from *,
   --#                    X;

   --------------------------------------
   -- (Re-)Initialization of this package
   --------------------------------------

   -- Reset the BPG ready to start over with a new subprogram.
   -- The Table state is returned to the same state it was
   -- in following the elaboration of this package.
   procedure Reinitialize_Graph;
   --# global out Table;
   --# derives Table from ;

   ------------------------------------------------------------------
   -- Creation of the BPG
   --
   -- The BPG is stored as a matrix of "Coefficients", each
   -- of which represents an arc from statement I to
   -- statement J with Label K.
   --
   -- The following procedure provides a Constructor for
   -- adding an arc to the BPG
   ------------------------------------------------------------------
   procedure Create_Coeff (Heap : in out Cells.Heap_Record;
                           I, J : in     Matrix_Index;
                           K    : in     Labels.Label);
   --# global in out Statistics.TableUsage;
   --#        in out Table;
   --# derives Heap                  from *,
   --#                                    I,
   --#                                    J,
   --#                                    K,
   --#                                    Table &
   --#         Statistics.TableUsage from *,
   --#                                    Heap &
   --#         Table                 from *,
   --#                                    Heap,
   --#                                    I,
   --#                                    J;

   -- ...and lookup of a Label given statements I and J
   function Coefficient (Heap : Cells.Heap_Record;
                         I, J : Matrix_Index) return Labels.Label;
   --# global in Table;

   ------------------------------------------------------------------
   -- Generation and Printing of Verification Conditions
   ------------------------------------------------------------------

   -- Gen_VCs essentially reduces the BPG by removing "Unspecified"
   -- statements, using Hoare's assignment axiom.  The traveral-
   -- condition and action of such statements are back-substituted,
   -- and this process is repeated until only explicit pre-condition,
   -- post-condition, assertion, and check statements are left.
   -- The arcs between those remaining statements are left decorated
   -- with their appropriate VC.
   procedure Gen_VCs
     (Heap             : in out Cells.Heap_Record;
      Output_File      : in     SPARK_IO.File_Type;
      Output_File_Name : in     E_Strings.T;
      Scope            : in     Dictionary.Scopes;
      Gen_VC_Failure   :    out Boolean);
   --# global in     CommandLineData.Content;
   --#        in out SPARK_IO.File_Sys;
   --#        in out Statistics.TableUsage;
   --#        in out Table;
   --# derives Gen_VC_Failure,
   --#         Heap,
   --#         Table                 from CommandLineData.Content,
   --#                                    Heap,
   --#                                    Table &
   --#         SPARK_IO.File_Sys     from *,
   --#                                    CommandLineData.Content,
   --#                                    Heap,
   --#                                    Output_File,
   --#                                    Table &
   --#         Statistics.TableUsage from *,
   --#                                    CommandLineData.Content,
   --#                                    Heap,
   --#                                    Table &
   --#         null                  from Output_File_Name,
   --#                                    Scope;

   procedure Print_VCs_Or_DPCs
     (Heap        : in out Cells.Heap_Record;
      Output_File : in     SPARK_IO.File_Type;
      Scope       : in     Dictionary.Scopes;
      Kind        : in     Valid_Dump_Kind);
   --# global in     CommandLineData.Content;
   --#        in     Dictionary.Dict;
   --#        in     Table;
   --#        in out Declarations.State;
   --#        in out LexTokenManager.State;
   --#        in out SPARK_IO.File_Sys;
   --#        in out Statistics.TableUsage;
   --# derives Declarations.State,
   --#         Heap,
   --#         LexTokenManager.State,
   --#         Statistics.TableUsage from *,
   --#                                    Declarations.State,
   --#                                    Dictionary.Dict,
   --#                                    Heap,
   --#                                    Kind,
   --#                                    LexTokenManager.State,
   --#                                    Table &
   --#         SPARK_IO.File_Sys     from *,
   --#                                    CommandLineData.Content,
   --#                                    Declarations.State,
   --#                                    Dictionary.Dict,
   --#                                    Heap,
   --#                                    Kind,
   --#                                    LexTokenManager.State,
   --#                                    Output_File,
   --#                                    Scope,
   --#                                    Table;

   -------------------------------------------
   -- Debug and Tracing
   -------------------------------------------

   -- Produces a human-readable output of Graph.Table on standard output
   procedure Dump_Graph_Table (Heap           : in out Cells.Heap_Record;
                               Scope          : in     Dictionary.Scopes;
                               Print_Edges_As : in     DOT_Dump_Kind);
   --# global in Table;
   --# derives Heap from * &
   --#         null from Print_Edges_As,
   --#                   Scope,
   --#                   Table;

   -- Produces BPG in DOT format.
   -- The DOT format is that expected by the tools from www.graphviz.org
   --
   -- Output_File_Name is the name of the VCG file being generated.  This is
   -- transformed by removing the ".vcg" extension, adding the numeric
   -- suffix given, then adding ".dot" as a new extension.  This allows
   -- for a numerically indexed sequence of graphs to be produced for a single
   -- subprogram.
   procedure Dump_Graph_Dot
     (Heap                    : in out Cells.Heap_Record;
      Output_File_Name        : in     E_Strings.T;
      Output_File_Name_Suffix : in     Natural;
      Scope                   : in     Dictionary.Scopes;
      Print_Edges_As          : in     DOT_Dump_Kind);
   --# global in Table;
   --# derives Heap from * &
   --#         null from Output_File_Name,
   --#                   Output_File_Name_Suffix,
   --#                   Print_Edges_As,
   --#                   Scope,
   --#                   Table;

end Graph;
