-------------------------------------------------------------------------------
-- (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 SLI;

separate (Sem.Wf_Basic_Declarative_Item.Wf_Basic_Declaration.Wf_Full_Type_Declaration)
procedure Wf_Real
  (Node       : in     STree.SyntaxNode;
   Scope      : in     Dictionary.Scopes;
   Ident_Node : in     STree.SyntaxNode;
   Dec_Loc    : in     LexTokenManager.Token_Position;
   The_Heap   : in out Heap.HeapRecord)
is
   The_Child_Node : STree.SyntaxNode;

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

   procedure Check_Accuracy
     (Node        : in     STree.SyntaxNode;
      Scope       : in     Dictionary.Scopes;
      Is_Floating : in     Boolean;
      Has_Range   : in     Boolean;
      Dec_Loc     : in     LexTokenManager.Token_Position;
      The_Heap    : in out Heap.HeapRecord;
      Accuracy    :    out LexTokenManager.Lex_String)
   --# global in     CommandLineData.Content;
   --#        in     ContextManager.Ops.File_Heap;
   --#        in     ContextManager.Ops.Unit_Heap;
   --#        in     ContextManager.Ops.Unit_Stack;
   --#        in out Dictionary.Dict;
   --#        in out ErrorHandler.Error_Context;
   --#        in out LexTokenManager.State;
   --#        in out SLI.State;
   --#        in out SPARK_IO.File_Sys;
   --#        in out Statistics.TableUsage;
   --#        in out STree.Table;
   --#           out Aggregate_Stack.State;
   --# derives Accuracy                   from CommandLineData.Content,
   --#                                         ContextManager.Ops.Unit_Stack,
   --#                                         Dictionary.Dict,
   --#                                         Is_Floating,
   --#                                         LexTokenManager.State,
   --#                                         Node,
   --#                                         Scope,
   --#                                         STree.Table,
   --#                                         The_Heap &
   --#         Aggregate_Stack.State,
   --#         Dictionary.Dict,
   --#         LexTokenManager.State,
   --#         STree.Table,
   --#         The_Heap                   from CommandLineData.Content,
   --#                                         ContextManager.Ops.Unit_Stack,
   --#                                         Dictionary.Dict,
   --#                                         LexTokenManager.State,
   --#                                         Node,
   --#                                         Scope,
   --#                                         STree.Table,
   --#                                         The_Heap &
   --#         ErrorHandler.Error_Context,
   --#         SPARK_IO.File_Sys          from CommandLineData.Content,
   --#                                         ContextManager.Ops.File_Heap,
   --#                                         ContextManager.Ops.Unit_Heap,
   --#                                         ContextManager.Ops.Unit_Stack,
   --#                                         Dec_Loc,
   --#                                         Dictionary.Dict,
   --#                                         ErrorHandler.Error_Context,
   --#                                         Has_Range,
   --#                                         Is_Floating,
   --#                                         LexTokenManager.State,
   --#                                         Node,
   --#                                         Scope,
   --#                                         SLI.State,
   --#                                         SPARK_IO.File_Sys,
   --#                                         STree.Table,
   --#                                         The_Heap &
   --#         SLI.State                  from *,
   --#                                         CommandLineData.Content,
   --#                                         ContextManager.Ops.File_Heap,
   --#                                         ContextManager.Ops.Unit_Heap,
   --#                                         ContextManager.Ops.Unit_Stack,
   --#                                         Dictionary.Dict,
   --#                                         ErrorHandler.Error_Context,
   --#                                         LexTokenManager.State,
   --#                                         Node,
   --#                                         Scope,
   --#                                         SPARK_IO.File_Sys,
   --#                                         STree.Table,
   --#                                         The_Heap &
   --#         Statistics.TableUsage      from *,
   --#                                         CommandLineData.Content,
   --#                                         ContextManager.Ops.Unit_Stack,
   --#                                         Dictionary.Dict,
   --#                                         LexTokenManager.State,
   --#                                         Node,
   --#                                         Scope,
   --#                                         STree.Table,
   --#                                         The_Heap;
   --# pre Syntax_Node_Type (Node, STree.Table) = SP_Symbols.simple_expression;
   --# post STree.Table = STree.Table~;
   is
      Accuracy_Type         : Exp_Record;
      Unused_Component_Data : ComponentManager.ComponentData;
      Unwanted_Seq          : SeqAlgebra.Seq;

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

      function Type_Correct
        (Type_Sym    : Dictionary.Symbol;
         Scope       : Dictionary.Scopes;
         Is_Floating : Boolean)
        return        Boolean
      --# global in Dictionary.Dict;
      is
         Result : Boolean;
      begin
         if Is_Floating then
            Result := Dictionary.IsIntegerTypeMark (Type_Sym, Scope);
         else
            Result := Dictionary.IsRealTypeMark (Type_Sym, Scope);
         end if;
         return Result or else Dictionary.IsUnknownTypeMark (Type_Sym);
      end Type_Correct;

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

      function Error_To_Raise (Is_Floating : Boolean) return Natural is
         E : Natural;
      begin
         if Is_Floating then
            E := 108;
         else
            E := 109;
         end if;
         return E;
      end Error_To_Raise;

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

      procedure Check_Against_System_Constants
        (Dec_Loc       : in LexTokenManager.Token_Position;
         Has_Range     : in Boolean;
         Accuracy_Type : in Exp_Record)
      --# global in     CommandLineData.Content;
      --#        in     Dictionary.Dict;
      --#        in     LexTokenManager.State;
      --#        in out ErrorHandler.Error_Context;
      --#        in out SPARK_IO.File_Sys;
      --# derives ErrorHandler.Error_Context,
      --#         SPARK_IO.File_Sys          from Accuracy_Type,
      --#                                         CommandLineData.Content,
      --#                                         Dec_Loc,
      --#                                         Dictionary.Dict,
      --#                                         ErrorHandler.Error_Context,
      --#                                         Has_Range,
      --#                                         LexTokenManager.State,
      --#                                         SPARK_IO.File_Sys;
      is
         System_Sym          : Dictionary.Symbol;
         Max_Digits_Sym      : Dictionary.Symbol;
         Max_Base_Digits_Sym : Dictionary.Symbol;
         Unwanted_ME         : Maths.ErrorCode;
         Max_Val             : LexTokenManager.Lex_String;
         Result              : Maths.Value;
      begin
         case CommandLineData.Content.Language_Profile is
            when CommandLineData.SPARK83 =>
               -- No System in SPARK83, so nothing can be done here
               null;
            when CommandLineData.SPARK95_Onwards =>
               -- see if package System exists...
               System_Sym :=
                 Dictionary.LookupItem
                 (Name              => LexTokenManager.System_Token,
                  Scope             => Dictionary.GlobalScope,
                  Context           => Dictionary.ProgramContext,
                  Full_Package_Name => False);
               if not Dictionary.Is_Null_Symbol (System_Sym) then
                  if not Has_Range then
                     -- if so, and we're an unranged fp type then see if
                     -- System.Max_Digits exists ...
                     Max_Digits_Sym :=
                       Dictionary.LookupSelectedItem
                       (Prefix   => System_Sym,
                        Selector => LexTokenManager.Max_Digits_Token,
                        Scope    => Dictionary.GetScope (System_Sym),
                        Context  => Dictionary.ProgramContext);
                     if not Dictionary.Is_Null_Symbol (Max_Digits_Sym) then
                        -- if it does...
                        Max_Val := Dictionary.Get_Value (The_Constant => Max_Digits_Sym);
                        if LexTokenManager.Lex_String_Case_Insensitive_Compare
                          (Lex_Str1 => Max_Val,
                           Lex_Str2 => LexTokenManager.Null_String) /=
                          LexTokenManager.Str_Eq then
                           -- and if it has a sensible value, then check
                           -- that the requested number of digits does not
                           -- exceed it.
                           --# accept Flow, 10, Unwanted_ME, "Expected ineffective assignment";
                           Maths.Greater (Accuracy_Type.Value, Maths.ValueRep (Max_Val), Result, Unwanted_ME);
                           --# end accept;
                           if Result = Maths.BoolToValue (True) then
                              ErrorHandler.Semantic_Error
                                (Err_Num   => 785,
                                 Reference => ErrorHandler.No_Reference,
                                 Position  => Dec_Loc,
                                 Id_Str    => LexTokenManager.Null_String);
                           end if;
                        end if;
                     end if;
                  else
                     -- if so, and we're a ranged fp type then see if
                     -- System.Max_Base_Digits exists ...
                     Max_Base_Digits_Sym :=
                       Dictionary.LookupSelectedItem
                       (Prefix   => System_Sym,
                        Selector => LexTokenManager.Max_Base_Digits_Token,
                        Scope    => Dictionary.GetScope (System_Sym),
                        Context  => Dictionary.ProgramContext);
                     if not Dictionary.Is_Null_Symbol (Max_Base_Digits_Sym) then
                        -- if it does...
                        Max_Val := Dictionary.Get_Value (The_Constant => Max_Base_Digits_Sym);
                        if LexTokenManager.Lex_String_Case_Insensitive_Compare
                          (Lex_Str1 => Max_Val,
                           Lex_Str2 => LexTokenManager.Null_String) /=
                          LexTokenManager.Str_Eq then
                           -- and if it has a sensible value, then check
                           -- that the requested number of digits does not
                           -- exceed it.
                           --# accept Flow, 10, Unwanted_ME, "Expected ineffective assignment";
                           Maths.Greater (Accuracy_Type.Value, Maths.ValueRep (Max_Val), Result, Unwanted_ME);
                           --# end accept;
                           if Result = Maths.BoolToValue (True) then
                              ErrorHandler.Semantic_Error
                                (Err_Num   => 786,
                                 Reference => ErrorHandler.No_Reference,
                                 Position  => Dec_Loc,
                                 Id_Str    => LexTokenManager.Null_String);
                           end if;
                        end if;
                     end if;
                  end if;
               end if;
         end case;
         --# accept Flow, 33, Unwanted_ME, "Expected to be neither referenced nor exported";
      end Check_Against_System_Constants;

      procedure Check_Accuracy_Is_Positive
        (Node_Pos      : in LexTokenManager.Token_Position;
         Is_Floating   : in Boolean;
         Accuracy_Type : in Exp_Record)
      --# global in     CommandLineData.Content;
      --#        in     Dictionary.Dict;
      --#        in     LexTokenManager.State;
      --#        in out ErrorHandler.Error_Context;
      --#        in out SPARK_IO.File_Sys;
      --# derives ErrorHandler.Error_Context,
      --#         SPARK_IO.File_Sys          from Accuracy_Type,
      --#                                         CommandLineData.Content,
      --#                                         Dictionary.Dict,
      --#                                         ErrorHandler.Error_Context,
      --#                                         Is_Floating,
      --#                                         LexTokenManager.State,
      --#                                         Node_Pos,
      --#                                         SPARK_IO.File_Sys;
      is
         T   : Maths.Value;
         Err : Natural;
      begin
         T := Accuracy_Type.Value;
         Maths.Absolute (T);
         if (Accuracy_Type.Value = Maths.ZeroReal)
           or else (Accuracy_Type.Value = Maths.ZeroInteger)
           or else (Accuracy_Type.Value /= T) then

            if Is_Floating then
               Err := 787;
            else
               Err := 788;
            end if;
            ErrorHandler.Semantic_Error
              (Err_Num   => Err,
               Reference => ErrorHandler.No_Reference,
               Position  => Node_Pos,
               Id_Str    => LexTokenManager.Null_String);
         end if;
      end Check_Accuracy_Is_Positive;

   begin -- Check_Accuracy
      SeqAlgebra.CreateSeq (The_Heap, Unwanted_Seq);
      ComponentManager.Initialise (Unused_Component_Data);
      --# accept Flow, 10, Unused_Component_Data, "Expected ineffective assignment";
      Walk_Expression_P.Walk_Expression
        (Exp_Node                => Node,
         Scope                   => Scope,
         Type_Context            => Dictionary.GetUnknownTypeMark,
         Context_Requires_Static => True,
         Ref_Var                 => Unwanted_Seq,
         Result                  => Accuracy_Type,
         Component_Data          => Unused_Component_Data,
         The_Heap                => The_Heap);
      --# end accept;
      SeqAlgebra.DisposeOfSeq (The_Heap, Unwanted_Seq);
      Maths.StorageRep (Accuracy_Type.Value, Accuracy);
      if not Type_Correct (Type_Sym    => Accuracy_Type.Type_Symbol,
                           Scope       => Scope,
                           Is_Floating => Is_Floating) then
         Accuracy := LexTokenManager.Null_String; -- no value in error case
         ErrorHandler.Semantic_Error
           (Err_Num   => Error_To_Raise (Is_Floating => Is_Floating),
            Reference => ErrorHandler.No_Reference,
            Position  => Node_Position (Node => Node),
            Id_Str    => LexTokenManager.Null_String);
      end if;

      if Accuracy_Type.Is_Static then
         if Accuracy_Type.Is_ARange then
            ErrorHandler.Semantic_Error
              (Err_Num   => 114,
               Reference => ErrorHandler.No_Reference,
               Position  => Node_Position (Node => Node),
               Id_Str    => LexTokenManager.Null_String);
         else
            Check_Accuracy_Is_Positive
              (Node_Pos      => Node_Position (Node => Node),
               Is_Floating   => Is_Floating,
               Accuracy_Type => Accuracy_Type);
         end if;
      else
         ErrorHandler.Semantic_Error
           (Err_Num   => 36,
            Reference => 1,
            Position  => Node_Position (Node => Node),
            Id_Str    => LexTokenManager.Null_String);
      end if;
      if Is_Floating then
         -- Check against the target configuration file;
         -- System.Max_Digits or Max_Base_Digits may be defined.
         Check_Against_System_Constants (Dec_Loc       => Dec_Loc,
                                         Has_Range     => Has_Range,
                                         Accuracy_Type => Accuracy_Type);
      end if;
   end Check_Accuracy;

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

   procedure Check_Range_Item
     (Node        : in     STree.SyntaxNode;
      Scope       : in     Dictionary.Scopes;
      Is_Floating : in     Boolean;
      The_Heap    : in out Heap.HeapRecord;
      Static      :    out Boolean;
      Bound_Val   :    out LexTokenManager.Lex_String)
   --# global in     CommandLineData.Content;
   --#        in     ContextManager.Ops.File_Heap;
   --#        in     ContextManager.Ops.Unit_Heap;
   --#        in     ContextManager.Ops.Unit_Stack;
   --#        in out Dictionary.Dict;
   --#        in out ErrorHandler.Error_Context;
   --#        in out LexTokenManager.State;
   --#        in out SLI.State;
   --#        in out SPARK_IO.File_Sys;
   --#        in out Statistics.TableUsage;
   --#        in out STree.Table;
   --#           out Aggregate_Stack.State;
   --# derives Aggregate_Stack.State,
   --#         Dictionary.Dict,
   --#         LexTokenManager.State,
   --#         Static,
   --#         STree.Table,
   --#         The_Heap                   from CommandLineData.Content,
   --#                                         ContextManager.Ops.Unit_Stack,
   --#                                         Dictionary.Dict,
   --#                                         LexTokenManager.State,
   --#                                         Node,
   --#                                         Scope,
   --#                                         STree.Table,
   --#                                         The_Heap &
   --#         Bound_Val                  from CommandLineData.Content,
   --#                                         ContextManager.Ops.Unit_Stack,
   --#                                         Dictionary.Dict,
   --#                                         Is_Floating,
   --#                                         LexTokenManager.State,
   --#                                         Node,
   --#                                         Scope,
   --#                                         STree.Table,
   --#                                         The_Heap &
   --#         ErrorHandler.Error_Context,
   --#         SPARK_IO.File_Sys          from CommandLineData.Content,
   --#                                         ContextManager.Ops.File_Heap,
   --#                                         ContextManager.Ops.Unit_Heap,
   --#                                         ContextManager.Ops.Unit_Stack,
   --#                                         Dictionary.Dict,
   --#                                         ErrorHandler.Error_Context,
   --#                                         Is_Floating,
   --#                                         LexTokenManager.State,
   --#                                         Node,
   --#                                         Scope,
   --#                                         SLI.State,
   --#                                         SPARK_IO.File_Sys,
   --#                                         STree.Table,
   --#                                         The_Heap &
   --#         SLI.State                  from *,
   --#                                         CommandLineData.Content,
   --#                                         ContextManager.Ops.File_Heap,
   --#                                         ContextManager.Ops.Unit_Heap,
   --#                                         ContextManager.Ops.Unit_Stack,
   --#                                         Dictionary.Dict,
   --#                                         ErrorHandler.Error_Context,
   --#                                         LexTokenManager.State,
   --#                                         Node,
   --#                                         Scope,
   --#                                         SPARK_IO.File_Sys,
   --#                                         STree.Table,
   --#                                         The_Heap &
   --#         Statistics.TableUsage      from *,
   --#                                         CommandLineData.Content,
   --#                                         ContextManager.Ops.Unit_Stack,
   --#                                         Dictionary.Dict,
   --#                                         LexTokenManager.State,
   --#                                         Node,
   --#                                         Scope,
   --#                                         STree.Table,
   --#                                         The_Heap;
   --# pre Syntax_Node_Type (Node, STree.Table) = SP_Symbols.attribute or
   --#   Syntax_Node_Type (Node, STree.Table) = SP_Symbols.simple_expression;
   --# post STree.Table = STree.Table~;
   is
      Range_Type            : Exp_Record;
      Unused_Component_Data : ComponentManager.ComponentData;
      Unwanted_Seq          : SeqAlgebra.Seq;

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

      function Type_Correct
        (Type_Sym    : Dictionary.Symbol;
         Scope       : Dictionary.Scopes;
         Is_Floating : Boolean)
        return        Boolean
      --# global in Dictionary.Dict;
      is
         Result : Boolean;
      begin
         if Is_Floating then
            Result := Dictionary.IsRealTypeMark (Type_Sym, Scope);
         else
            Result := (Dictionary.IsUniversalRealType (Type_Sym) or else Dictionary.IsFixedPointTypeMark (Type_Sym, Scope));
         end if;
         return Result or else Dictionary.IsUnknownTypeMark (Type_Sym);
      end Type_Correct;

   begin -- Check_Range_Item
      SeqAlgebra.CreateSeq (The_Heap, Unwanted_Seq);
      ComponentManager.Initialise (Unused_Component_Data);
      --# accept Flow, 10, Unused_Component_Data, "Expected ineffective assignment";
      Walk_Expression_P.Walk_Expression
        (Exp_Node                => Node,
         Scope                   => Scope,
         Type_Context            => Dictionary.GetUnknownTypeMark,
         Context_Requires_Static => True,
         Ref_Var                 => Unwanted_Seq,
         Result                  => Range_Type,
         Component_Data          => Unused_Component_Data,
         The_Heap                => The_Heap);
      --# end accept;
      SeqAlgebra.DisposeOfSeq (The_Heap, Unwanted_Seq);
      Maths.StorageRep (Range_Type.Value, Bound_Val);
      if not Type_Correct (Type_Sym    => Range_Type.Type_Symbol,
                           Scope       => Scope,
                           Is_Floating => Is_Floating) then
         Bound_Val := LexTokenManager.Null_String;
         ErrorHandler.Semantic_Error
           (Err_Num   => 38,
            Reference => ErrorHandler.No_Reference,
            Position  => Node_Position (Node => Node),
            Id_Str    => LexTokenManager.Null_String);
      end if;
      Static := Range_Type.Is_Static;
   end Check_Range_Item;

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

   function Attribute_Found (Node : STree.SyntaxNode) return Boolean
   --# global in STree.Table;
   --# pre Syntax_Node_Type (Node, STree.Table) = SP_Symbols.range_constraint;
   is
   begin
      return Syntax_Node_Type (Node => Child_Node (Current_Node => Child_Node (Current_Node => Node))) = SP_Symbols.attribute;
   end Attribute_Found;

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

   procedure Wf_Floating_Point_Constraint
     (Node       : in     STree.SyntaxNode;
      Scope      : in     Dictionary.Scopes;
      Ident_Node : in     STree.SyntaxNode;
      Dec_Loc    : in     LexTokenManager.Token_Position;
      The_Heap   : in out Heap.HeapRecord)
   --# global in     CommandLineData.Content;
   --#        in     ContextManager.Ops.File_Heap;
   --#        in     ContextManager.Ops.Unit_Heap;
   --#        in     ContextManager.Ops.Unit_Stack;
   --#        in out Dictionary.Dict;
   --#        in out ErrorHandler.Error_Context;
   --#        in out LexTokenManager.State;
   --#        in out SLI.State;
   --#        in out SPARK_IO.File_Sys;
   --#        in out Statistics.TableUsage;
   --#        in out STree.Table;
   --#           out Aggregate_Stack.State;
   --# derives Aggregate_Stack.State,
   --#         LexTokenManager.State,
   --#         The_Heap                   from CommandLineData.Content,
   --#                                         ContextManager.Ops.Unit_Stack,
   --#                                         Dictionary.Dict,
   --#                                         LexTokenManager.State,
   --#                                         Node,
   --#                                         Scope,
   --#                                         STree.Table,
   --#                                         The_Heap &
   --#         Dictionary.Dict,
   --#         STree.Table                from CommandLineData.Content,
   --#                                         ContextManager.Ops.Unit_Stack,
   --#                                         Dec_Loc,
   --#                                         Dictionary.Dict,
   --#                                         Ident_Node,
   --#                                         LexTokenManager.State,
   --#                                         Node,
   --#                                         Scope,
   --#                                         STree.Table,
   --#                                         The_Heap &
   --#         ErrorHandler.Error_Context from *,
   --#                                         CommandLineData.Content,
   --#                                         ContextManager.Ops.File_Heap,
   --#                                         ContextManager.Ops.Unit_Heap,
   --#                                         ContextManager.Ops.Unit_Stack,
   --#                                         Dec_Loc,
   --#                                         Dictionary.Dict,
   --#                                         LexTokenManager.State,
   --#                                         Node,
   --#                                         Scope,
   --#                                         SLI.State,
   --#                                         SPARK_IO.File_Sys,
   --#                                         STree.Table,
   --#                                         The_Heap &
   --#         SLI.State,
   --#         SPARK_IO.File_Sys          from CommandLineData.Content,
   --#                                         ContextManager.Ops.File_Heap,
   --#                                         ContextManager.Ops.Unit_Heap,
   --#                                         ContextManager.Ops.Unit_Stack,
   --#                                         Dec_Loc,
   --#                                         Dictionary.Dict,
   --#                                         ErrorHandler.Error_Context,
   --#                                         Ident_Node,
   --#                                         LexTokenManager.State,
   --#                                         Node,
   --#                                         Scope,
   --#                                         SLI.State,
   --#                                         SPARK_IO.File_Sys,
   --#                                         STree.Table,
   --#                                         The_Heap &
   --#         Statistics.TableUsage      from *,
   --#                                         CommandLineData.Content,
   --#                                         ContextManager.Ops.Unit_Stack,
   --#                                         Dictionary.Dict,
   --#                                         LexTokenManager.State,
   --#                                         Node,
   --#                                         Scope,
   --#                                         STree.Table,
   --#                                         The_Heap;
   --# pre Syntax_Node_Type (Node, STree.Table) = SP_Symbols.floating_point_constraint and
   --#   Syntax_Node_Type (Ident_Node, STree.Table) = SP_Symbols.identifier;
   --# post STree.Table = STree.Table~;
   is
      Accuracy_Node, Range_Node       : STree.SyntaxNode;
      Range_Node_Pos                  : LexTokenManager.Token_Position;
      Left_Is_Static, Right_Is_Static : Boolean;
      Accuracy                        : LexTokenManager.Lex_String;
      Upper                           : LexTokenManager.Lex_String := LexTokenManager.Null_String;
      Lower                           : LexTokenManager.Lex_String := LexTokenManager.Null_String;
      Type_Symbol                     : Dictionary.Symbol;
   begin
      Accuracy_Node := Child_Node (Current_Node => Node);
      -- ASSUME Accuracy_Node = floating_accuracy_definition
      SystemErrors.RT_Assert
        (C       => Syntax_Node_Type (Node => Accuracy_Node) = SP_Symbols.floating_accuracy_definition,
         Sys_Err => SystemErrors.Invalid_Syntax_Tree,
         Msg     => "Expect Accuracy_Node = floating_accuracy_definition in Wf_Floating_Point_Constraint");

      Range_Node := Next_Sibling (Current_Node => Accuracy_Node);
      -- ASSUME Range_Node = range_constraint OR NULL
      SystemErrors.RT_Assert
        (C       => Range_Node = STree.NullNode or else Syntax_Node_Type (Node => Range_Node) = SP_Symbols.range_constraint,
         Sys_Err => SystemErrors.Invalid_Syntax_Tree,
         Msg     => "Expect Range_Node = range_constraint OR NULL in Wf_Floating_Point_Constraint");

      Accuracy_Node := Child_Node (Current_Node => Accuracy_Node);
      -- ASSUME Accuracy_Node = simple_expression
      SystemErrors.RT_Assert
        (C       => Syntax_Node_Type (Node => Accuracy_Node) = SP_Symbols.simple_expression,
         Sys_Err => SystemErrors.Invalid_Syntax_Tree,
         Msg     => "Expect Accuracy_Node = simple_expression in Wf_Floating_Point_Constraint");

      Check_Accuracy
        (Node        => Accuracy_Node,
         Scope       => Scope,
         Is_Floating => True,
         Has_Range   => Range_Node /= STree.NullNode,
         Dec_Loc     => Dec_Loc,
         The_Heap    => The_Heap,
         Accuracy    => Accuracy);

      if Syntax_Node_Type (Node => Range_Node) = SP_Symbols.range_constraint then
         -- ASSUME Range_Node = range_constraint
         if Attribute_Found (Node => Range_Node) then
            ErrorHandler.Semantic_Error
              (Err_Num   => 98,
               Reference => ErrorHandler.No_Reference,
               Position  => Node_Position (Node => Range_Node),
               Id_Str    => LexTokenManager.Null_String);
         else
            Range_Node_Pos := Node_Position (Node => Range_Node);
            Range_Node     := Child_Node (Current_Node => Child_Node (Current_Node => Range_Node));
            -- ASSUME Range_Node = attribute OR simple_expression
            SystemErrors.RT_Assert
              (C       => Syntax_Node_Type (Node => Range_Node) = SP_Symbols.attribute
                 or else Syntax_Node_Type (Node => Range_Node) = SP_Symbols.simple_expression,
               Sys_Err => SystemErrors.Invalid_Syntax_Tree,
               Msg     => "Expect Range_Node = attribute OR simple_expression in Wf_Floating_Point_Constraint");
            Check_Range_Item
              (Node        => Range_Node,
               Scope       => Scope,
               Is_Floating => True,
               The_Heap    => The_Heap,
               Static      => Left_Is_Static,
               Bound_Val   => Lower);
            Range_Node := Next_Sibling (Current_Node => Range_Node);
            -- ASSUME Range_Node = simple_expression OR NULL
            if Syntax_Node_Type (Node => Range_Node) = SP_Symbols.simple_expression then
               -- ASSUME Range_Node = simple_expression
               Check_Range_Item
                 (Node        => Range_Node,
                  Scope       => Scope,
                  Is_Floating => True,
                  The_Heap    => The_Heap,
                  Static      => Right_Is_Static,
                  Bound_Val   => Upper);
            elsif Range_Node = STree.NullNode then
               -- ASSUME Range_Node = NULL
               Right_Is_Static := True;
            else
               Right_Is_Static := True;
               SystemErrors.Fatal_Error
                 (Sys_Err => SystemErrors.Invalid_Syntax_Tree,
                  Msg     => "Expect Range_Node = simple_expression OR NULL in Wf_Floating_Point_Constraint");
            end if;

            if not (Left_Is_Static and then Right_Is_Static) then
               ErrorHandler.Semantic_Error
                 (Err_Num   => 45,
                  Reference => 1,
                  Position  => Range_Node_Pos,
                  Id_Str    => LexTokenManager.Null_String);
            end if;
         end if;
      end if;

      Empty_Type_Check (Dec_Loc => Dec_Loc,
                        Lower   => Lower,
                        Upper   => Upper);
      Dictionary.Add_Floating_Point_Type
        (Name        => Node_Lex_String (Node => Ident_Node),
         Comp_Unit   => ContextManager.Ops.Current_Unit,
         Declaration => Dictionary.Location'(Start_Position => Dec_Loc,
                                             End_Position   => Dec_Loc),
         Lower       => Lower,
         Upper       => Upper,
         Error_Bound => Accuracy,
         Scope       => Scope,
         Context     => Dictionary.ProgramContext,
         The_Type    => Type_Symbol);
      STree.Add_Node_Symbol (Node => Ident_Node,
                             Sym  => Type_Symbol);
      if ErrorHandler.Generate_SLI then
         SLI.Generate_Xref_Symbol
           (Comp_Unit      => ContextManager.Ops.Current_Unit,
            Parse_Tree     => Ident_Node,
            Symbol         => Type_Symbol,
            Is_Declaration => True);
      end if;
   end Wf_Floating_Point_Constraint;

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

   procedure Wf_Fixed_Point_Constraint
     (Node       : in     STree.SyntaxNode;
      Scope      : in     Dictionary.Scopes;
      Ident_Node : in     STree.SyntaxNode;
      Dec_Loc    : in     LexTokenManager.Token_Position;
      The_Heap   : in out Heap.HeapRecord)
   --# global in     CommandLineData.Content;
   --#        in     ContextManager.Ops.File_Heap;
   --#        in     ContextManager.Ops.Unit_Heap;
   --#        in     ContextManager.Ops.Unit_Stack;
   --#        in out Dictionary.Dict;
   --#        in out ErrorHandler.Error_Context;
   --#        in out LexTokenManager.State;
   --#        in out SLI.State;
   --#        in out SPARK_IO.File_Sys;
   --#        in out Statistics.TableUsage;
   --#        in out STree.Table;
   --#           out Aggregate_Stack.State;
   --# derives Aggregate_Stack.State,
   --#         LexTokenManager.State,
   --#         The_Heap                   from CommandLineData.Content,
   --#                                         ContextManager.Ops.Unit_Stack,
   --#                                         Dictionary.Dict,
   --#                                         LexTokenManager.State,
   --#                                         Node,
   --#                                         Scope,
   --#                                         STree.Table,
   --#                                         The_Heap &
   --#         Dictionary.Dict,
   --#         STree.Table                from CommandLineData.Content,
   --#                                         ContextManager.Ops.Unit_Stack,
   --#                                         Dec_Loc,
   --#                                         Dictionary.Dict,
   --#                                         Ident_Node,
   --#                                         LexTokenManager.State,
   --#                                         Node,
   --#                                         Scope,
   --#                                         STree.Table,
   --#                                         The_Heap &
   --#         ErrorHandler.Error_Context from *,
   --#                                         CommandLineData.Content,
   --#                                         ContextManager.Ops.File_Heap,
   --#                                         ContextManager.Ops.Unit_Heap,
   --#                                         ContextManager.Ops.Unit_Stack,
   --#                                         Dec_Loc,
   --#                                         Dictionary.Dict,
   --#                                         LexTokenManager.State,
   --#                                         Node,
   --#                                         Scope,
   --#                                         SLI.State,
   --#                                         SPARK_IO.File_Sys,
   --#                                         STree.Table,
   --#                                         The_Heap &
   --#         SLI.State,
   --#         SPARK_IO.File_Sys          from CommandLineData.Content,
   --#                                         ContextManager.Ops.File_Heap,
   --#                                         ContextManager.Ops.Unit_Heap,
   --#                                         ContextManager.Ops.Unit_Stack,
   --#                                         Dec_Loc,
   --#                                         Dictionary.Dict,
   --#                                         ErrorHandler.Error_Context,
   --#                                         Ident_Node,
   --#                                         LexTokenManager.State,
   --#                                         Node,
   --#                                         Scope,
   --#                                         SLI.State,
   --#                                         SPARK_IO.File_Sys,
   --#                                         STree.Table,
   --#                                         The_Heap &
   --#         Statistics.TableUsage      from *,
   --#                                         CommandLineData.Content,
   --#                                         ContextManager.Ops.Unit_Stack,
   --#                                         Dictionary.Dict,
   --#                                         LexTokenManager.State,
   --#                                         Node,
   --#                                         Scope,
   --#                                         STree.Table,
   --#                                         The_Heap;
   --# pre Syntax_Node_Type (Node, STree.Table) = SP_Symbols.fixed_point_constraint and
   --#   Syntax_Node_Type (Ident_Node, STree.Table) = SP_Symbols.identifier;
   --# post STree.Table = STree.Table~;
   is
      Accuracy_Node, Range_Node       : STree.SyntaxNode;
      Range_Node_Pos                  : LexTokenManager.Token_Position;
      Left_Is_Static, Right_Is_Static : Boolean;
      Accuracy                        : LexTokenManager.Lex_String;
      Upper                           : LexTokenManager.Lex_String := LexTokenManager.Null_String;
      Lower                           : LexTokenManager.Lex_String := LexTokenManager.Null_String;
      Type_Symbol                     : Dictionary.Symbol;
   begin
      Accuracy_Node := Child_Node (Current_Node => Node);
      -- ASSUME Accuracy_Node = fixed_accuracy_definition
      SystemErrors.RT_Assert
        (C       => Syntax_Node_Type (Node => Accuracy_Node) = SP_Symbols.fixed_accuracy_definition,
         Sys_Err => SystemErrors.Invalid_Syntax_Tree,
         Msg     => "Expect Accuracy_Node = fixed_accuracy_definition in Wf_Fixed_Point_Constraint");

      Range_Node := Next_Sibling (Current_Node => Accuracy_Node);
      -- ASSUME Range_Node = range_constraint OR NULL
      SystemErrors.RT_Assert
        (C       => Range_Node = STree.NullNode or else Syntax_Node_Type (Node => Range_Node) = SP_Symbols.range_constraint,
         Sys_Err => SystemErrors.Invalid_Syntax_Tree,
         Msg     => "Expect Range_Node = range_constraint OR NULL in Wf_Fixed_Point_Constraint");

      Accuracy_Node := Child_Node (Current_Node => Accuracy_Node);
      -- ASSUME Accuracy_Node = simple_expression
      SystemErrors.RT_Assert
        (C       => Syntax_Node_Type (Node => Accuracy_Node) = SP_Symbols.simple_expression,
         Sys_Err => SystemErrors.Invalid_Syntax_Tree,
         Msg     => "Expect Accuracy_Node = simple_expression in Wf_Fixed_Point_Constraint");

      Check_Accuracy
        (Node        => Accuracy_Node,
         Scope       => Scope,
         Is_Floating => False,
         Has_Range   => False,
         Dec_Loc     => Dec_Loc,
         The_Heap    => The_Heap,
         Accuracy    => Accuracy);

      if Syntax_Node_Type (Node => Range_Node) = SP_Symbols.range_constraint then
         -- ASSUME Range_Node = range_constraint
         if Attribute_Found (Node => Range_Node) then
            ErrorHandler.Semantic_Error
              (Err_Num   => 98,
               Reference => ErrorHandler.No_Reference,
               Position  => Node_Position (Node => Range_Node),
               Id_Str    => LexTokenManager.Null_String);
         else
            Range_Node_Pos := Node_Position (Node => Range_Node);
            Range_Node     := Child_Node (Current_Node => Child_Node (Current_Node => Range_Node));
            -- ASSUME Range_Node = attribute OR simple_expression
            SystemErrors.RT_Assert
              (C       => Syntax_Node_Type (Node => Range_Node) = SP_Symbols.attribute
                 or else Syntax_Node_Type (Node => Range_Node) = SP_Symbols.simple_expression,
               Sys_Err => SystemErrors.Invalid_Syntax_Tree,
               Msg     => "Expect Range_Node = attribute OR simple_expression in Wf_Fixed_Point_Constraint");
            Check_Range_Item
              (Node        => Range_Node,
               Scope       => Scope,
               Is_Floating => True,
               The_Heap    => The_Heap,
               Static      => Left_Is_Static,
               Bound_Val   => Lower);
            Range_Node := Next_Sibling (Current_Node => Range_Node);
            -- ASSUME Range_Node = simple_expression OR NULL
            if Syntax_Node_Type (Node => Range_Node) = SP_Symbols.simple_expression then
               -- ASSUME Range_Node = simple_expression
               Check_Range_Item
                 (Node        => Range_Node,
                  Scope       => Scope,
                  Is_Floating => True,
                  The_Heap    => The_Heap,
                  Static      => Right_Is_Static,
                  Bound_Val   => Upper);
            elsif Range_Node = STree.NullNode then
               -- ASSUME Range_Node = NULL
               Right_Is_Static := True;
            else
               Right_Is_Static := True;
               SystemErrors.Fatal_Error
                 (Sys_Err => SystemErrors.Invalid_Syntax_Tree,
                  Msg     => "Expect Range_Node = simple_expression OR NULL in Wf_Fixed_Point_Constraint");
            end if;

            if not (Left_Is_Static and then Right_Is_Static) then
               ErrorHandler.Semantic_Error
                 (Err_Num   => 45,
                  Reference => 1,
                  Position  => Range_Node_Pos,
                  Id_Str    => LexTokenManager.Null_String);
            end if;
         end if;
      elsif Range_Node = STree.NullNode then
         -- ASSUME Range_Node = NULL
         ErrorHandler.Semantic_Error
           (Err_Num   => 57,
            Reference => ErrorHandler.No_Reference,
            Position  => Dec_Loc,
            Id_Str    => LexTokenManager.Null_String);
      end if;

      Empty_Type_Check (Dec_Loc => Dec_Loc,
                        Lower   => Lower,
                        Upper   => Upper);
      Dictionary.Add_Fixed_Point_Type
        (Name        => Node_Lex_String (Node => Ident_Node),
         Comp_Unit   => ContextManager.Ops.Current_Unit,
         Declaration => Dictionary.Location'(Start_Position => Dec_Loc,
                                             End_Position   => Dec_Loc),
         Lower       => Lower,
         Upper       => Upper,
         Error_Bound => Accuracy,
         Scope       => Scope,
         Context     => Dictionary.ProgramContext,
         The_Type    => Type_Symbol);
      STree.Add_Node_Symbol (Node => Ident_Node,
                             Sym  => Type_Symbol);
      if ErrorHandler.Generate_SLI then
         SLI.Generate_Xref_Symbol
           (Comp_Unit      => ContextManager.Ops.Current_Unit,
            Parse_Tree     => Ident_Node,
            Symbol         => Type_Symbol,
            Is_Declaration => True);
      end if;
   end Wf_Fixed_Point_Constraint;

begin -- Wf_Real
   The_Child_Node := Child_Node (Current_Node => Node);
   if Syntax_Node_Type (Node => The_Child_Node) = SP_Symbols.fixed_point_constraint then
      -- ASSUME Next_Node = fixed_point_constraint
      Wf_Fixed_Point_Constraint
        (Node       => The_Child_Node,
         Scope      => Scope,
         Ident_Node => Ident_Node,
         Dec_Loc    => Dec_Loc,
         The_Heap   => The_Heap);
   elsif Syntax_Node_Type (Node => The_Child_Node) = SP_Symbols.floating_point_constraint then
      -- ASSUME Next_Node = floating_point_constraint
      Wf_Floating_Point_Constraint
        (Node       => The_Child_Node,
         Scope      => Scope,
         Ident_Node => Ident_Node,
         Dec_Loc    => Dec_Loc,
         The_Heap   => The_Heap);
   else
      SystemErrors.Fatal_Error
        (Sys_Err => SystemErrors.Invalid_Syntax_Tree,
         Msg     => "Expect Node = floating_point_constraint OR fixed_point_constraint in Wf_Real");
   end if;
   Heap.ReportUsage (The_Heap);
   --# accept Flow, 602, Aggregate_Stack.State, Aggregate_Stack.State, "Partial initialization OK here";
end Wf_Real;
