| 1 | 706 | jeremybenn | ------------------------------------------------------------------------------
 | 
      
         | 2 |  |  | --                                                                          --
 | 
      
         | 3 |  |  | --                         GNAT COMPILER COMPONENTS                         --
 | 
      
         | 4 |  |  | --                                                                          --
 | 
      
         | 5 |  |  | --                              S E M _ D I M                               --
 | 
      
         | 6 |  |  | --                                                                          --
 | 
      
         | 7 |  |  | --                                 B o d y                                  --
 | 
      
         | 8 |  |  | --                                                                          --
 | 
      
         | 9 |  |  | --          Copyright (C) 2011-2012, Free Software Foundation, Inc.         --
 | 
      
         | 10 |  |  | --                                                                          --
 | 
      
         | 11 |  |  | -- GNAT is free software;  you can  redistribute it  and/or modify it under --
 | 
      
         | 12 |  |  | -- terms of the  GNU General Public License as published  by the Free Soft- --
 | 
      
         | 13 |  |  | -- ware  Foundation;  either version 3,  or (at your option) any later ver- --
 | 
      
         | 14 |  |  | -- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
 | 
      
         | 15 |  |  | -- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
 | 
      
         | 16 |  |  | -- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
 | 
      
         | 17 |  |  | -- for  more details.  You should have  received  a copy of the GNU General --
 | 
      
         | 18 |  |  | -- Public License  distributed with GNAT; see file COPYING3.  If not, go to --
 | 
      
         | 19 |  |  | -- http://www.gnu.org/licenses for a complete copy of the license.          --
 | 
      
         | 20 |  |  | --                                                                          --
 | 
      
         | 21 |  |  | -- GNAT was originally developed  by the GNAT team at  New York University. --
 | 
      
         | 22 |  |  | -- Extensive contributions were provided by Ada Core Technologies Inc.      --
 | 
      
         | 23 |  |  | --                                                                          --
 | 
      
         | 24 |  |  | ------------------------------------------------------------------------------
 | 
      
         | 25 |  |  |  
 | 
      
         | 26 |  |  | with Aspects;  use Aspects;
 | 
      
         | 27 |  |  | with Atree;    use Atree;
 | 
      
         | 28 |  |  | with Einfo;    use Einfo;
 | 
      
         | 29 |  |  | with Errout;   use Errout;
 | 
      
         | 30 |  |  | with Lib;      use Lib;
 | 
      
         | 31 |  |  | with Namet;    use Namet;
 | 
      
         | 32 |  |  | with Nlists;   use Nlists;
 | 
      
         | 33 |  |  | with Nmake;    use Nmake;
 | 
      
         | 34 |  |  | with Opt;      use Opt;
 | 
      
         | 35 |  |  | with Rtsfind;  use Rtsfind;
 | 
      
         | 36 |  |  | with Sem;      use Sem;
 | 
      
         | 37 |  |  | with Sem_Eval; use Sem_Eval;
 | 
      
         | 38 |  |  | with Sem_Res;  use Sem_Res;
 | 
      
         | 39 |  |  | with Sinfo;    use Sinfo;
 | 
      
         | 40 |  |  | with Snames;   use Snames;
 | 
      
         | 41 |  |  | with Stand;    use Stand;
 | 
      
         | 42 |  |  | with Stringt;  use Stringt;
 | 
      
         | 43 |  |  | with Table;
 | 
      
         | 44 |  |  | with Tbuild;   use Tbuild;
 | 
      
         | 45 |  |  | with Uintp;    use Uintp;
 | 
      
         | 46 |  |  | with Urealp;   use Urealp;
 | 
      
         | 47 |  |  |  
 | 
      
         | 48 |  |  | with GNAT.HTable;
 | 
      
         | 49 |  |  |  
 | 
      
         | 50 |  |  | package body Sem_Dim is
 | 
      
         | 51 |  |  |  
 | 
      
         | 52 |  |  |    -------------------------
 | 
      
         | 53 |  |  |    -- Rational arithmetic --
 | 
      
         | 54 |  |  |    -------------------------
 | 
      
         | 55 |  |  |  
 | 
      
         | 56 |  |  |    type Whole is new Int;
 | 
      
         | 57 |  |  |    subtype Positive_Whole is Whole range 1 .. Whole'Last;
 | 
      
         | 58 |  |  |  
 | 
      
         | 59 |  |  |    type Rational is record
 | 
      
         | 60 |  |  |       Numerator   : Whole;
 | 
      
         | 61 |  |  |       Denominator : Positive_Whole;
 | 
      
         | 62 |  |  |    end record;
 | 
      
         | 63 |  |  |  
 | 
      
         | 64 |  |  |    Zero : constant Rational := Rational'(Numerator =>   0,
 | 
      
         | 65 |  |  |                                          Denominator => 1);
 | 
      
         | 66 |  |  |  
 | 
      
         | 67 |  |  |    No_Rational : constant Rational := Rational'(Numerator =>   0,
 | 
      
         | 68 |  |  |                                                 Denominator => 2);
 | 
      
         | 69 |  |  |    --  Used to indicate an expression that cannot be interpreted as a rational
 | 
      
         | 70 |  |  |    --  Returned value of the Create_Rational_From routine when parameter Expr
 | 
      
         | 71 |  |  |    --  is not a static representation of a rational.
 | 
      
         | 72 |  |  |  
 | 
      
         | 73 |  |  |    --  Rational constructors
 | 
      
         | 74 |  |  |  
 | 
      
         | 75 |  |  |    function "+" (Right : Whole) return Rational;
 | 
      
         | 76 |  |  |    function GCD (Left, Right : Whole) return Int;
 | 
      
         | 77 |  |  |    function Reduce (X : Rational) return Rational;
 | 
      
         | 78 |  |  |  
 | 
      
         | 79 |  |  |    --  Unary operator for Rational
 | 
      
         | 80 |  |  |  
 | 
      
         | 81 |  |  |    function "-" (Right : Rational) return Rational;
 | 
      
         | 82 |  |  |    function "abs" (Right : Rational) return Rational;
 | 
      
         | 83 |  |  |  
 | 
      
         | 84 |  |  |    --  Rational operations for Rationals
 | 
      
         | 85 |  |  |  
 | 
      
         | 86 |  |  |    function "+" (Left, Right : Rational) return Rational;
 | 
      
         | 87 |  |  |    function "-" (Left, Right : Rational) return Rational;
 | 
      
         | 88 |  |  |    function "*" (Left, Right : Rational) return Rational;
 | 
      
         | 89 |  |  |    function "/" (Left, Right : Rational) return Rational;
 | 
      
         | 90 |  |  |  
 | 
      
         | 91 |  |  |    ------------------
 | 
      
         | 92 |  |  |    -- System types --
 | 
      
         | 93 |  |  |    ------------------
 | 
      
         | 94 |  |  |  
 | 
      
         | 95 |  |  |    Max_Number_Of_Dimensions : constant := 7;
 | 
      
         | 96 |  |  |    --  Maximum number of dimensions in a dimension system
 | 
      
         | 97 |  |  |  
 | 
      
         | 98 |  |  |    High_Position_Bound : constant := Max_Number_Of_Dimensions;
 | 
      
         | 99 |  |  |    Invalid_Position    : constant := 0;
 | 
      
         | 100 |  |  |    Low_Position_Bound  : constant := 1;
 | 
      
         | 101 |  |  |  
 | 
      
         | 102 |  |  |    subtype Dimension_Position is
 | 
      
         | 103 |  |  |      Nat range Invalid_Position .. High_Position_Bound;
 | 
      
         | 104 |  |  |  
 | 
      
         | 105 |  |  |    type Name_Array is
 | 
      
         | 106 |  |  |      array (Dimension_Position range
 | 
      
         | 107 |  |  |               Low_Position_Bound .. High_Position_Bound) of Name_Id;
 | 
      
         | 108 |  |  |    --  A data structure used to store the names of all units within a system
 | 
      
         | 109 |  |  |  
 | 
      
         | 110 |  |  |    No_Names : constant Name_Array := (others => No_Name);
 | 
      
         | 111 |  |  |  
 | 
      
         | 112 |  |  |    type Symbol_Array is
 | 
      
         | 113 |  |  |      array (Dimension_Position range
 | 
      
         | 114 |  |  |               Low_Position_Bound ..  High_Position_Bound) of String_Id;
 | 
      
         | 115 |  |  |    --  A data structure used to store the symbols of all units within a system
 | 
      
         | 116 |  |  |  
 | 
      
         | 117 |  |  |    No_Symbols : constant Symbol_Array := (others => No_String);
 | 
      
         | 118 |  |  |  
 | 
      
         | 119 |  |  |    type System_Type is record
 | 
      
         | 120 |  |  |       Type_Decl : Node_Id;
 | 
      
         | 121 |  |  |       Names     : Name_Array;
 | 
      
         | 122 |  |  |       Symbols   : Symbol_Array;
 | 
      
         | 123 |  |  |       Count     : Dimension_Position;
 | 
      
         | 124 |  |  |    end record;
 | 
      
         | 125 |  |  |  
 | 
      
         | 126 |  |  |    Null_System : constant System_Type :=
 | 
      
         | 127 |  |  |                    (Empty, No_Names, No_Symbols, Invalid_Position);
 | 
      
         | 128 |  |  |  
 | 
      
         | 129 |  |  |    subtype System_Id is Nat;
 | 
      
         | 130 |  |  |  
 | 
      
         | 131 |  |  |    --  The following table maps types to systems
 | 
      
         | 132 |  |  |  
 | 
      
         | 133 |  |  |    package System_Table is new Table.Table (
 | 
      
         | 134 |  |  |      Table_Component_Type => System_Type,
 | 
      
         | 135 |  |  |      Table_Index_Type     => System_Id,
 | 
      
         | 136 |  |  |      Table_Low_Bound      => 1,
 | 
      
         | 137 |  |  |      Table_Initial        => 5,
 | 
      
         | 138 |  |  |      Table_Increment      => 5,
 | 
      
         | 139 |  |  |      Table_Name           => "System_Table");
 | 
      
         | 140 |  |  |  
 | 
      
         | 141 |  |  |    --------------------
 | 
      
         | 142 |  |  |    -- Dimension type --
 | 
      
         | 143 |  |  |    --------------------
 | 
      
         | 144 |  |  |  
 | 
      
         | 145 |  |  |    type Dimension_Type is
 | 
      
         | 146 |  |  |      array (Dimension_Position range
 | 
      
         | 147 |  |  |               Low_Position_Bound ..  High_Position_Bound) of Rational;
 | 
      
         | 148 |  |  |  
 | 
      
         | 149 |  |  |    Null_Dimension : constant Dimension_Type := (others => Zero);
 | 
      
         | 150 |  |  |  
 | 
      
         | 151 |  |  |    type Dimension_Table_Range is range 0 .. 510;
 | 
      
         | 152 |  |  |    function Dimension_Table_Hash (Key : Node_Id) return Dimension_Table_Range;
 | 
      
         | 153 |  |  |  
 | 
      
         | 154 |  |  |    --  The following table associates nodes with dimensions
 | 
      
         | 155 |  |  |  
 | 
      
         | 156 |  |  |    package Dimension_Table is new
 | 
      
         | 157 |  |  |      GNAT.HTable.Simple_HTable
 | 
      
         | 158 |  |  |        (Header_Num => Dimension_Table_Range,
 | 
      
         | 159 |  |  |         Element    => Dimension_Type,
 | 
      
         | 160 |  |  |         No_Element => Null_Dimension,
 | 
      
         | 161 |  |  |         Key        => Node_Id,
 | 
      
         | 162 |  |  |         Hash       => Dimension_Table_Hash,
 | 
      
         | 163 |  |  |         Equal      => "=");
 | 
      
         | 164 |  |  |  
 | 
      
         | 165 |  |  |    ------------------
 | 
      
         | 166 |  |  |    -- Symbol types --
 | 
      
         | 167 |  |  |    ------------------
 | 
      
         | 168 |  |  |  
 | 
      
         | 169 |  |  |    type Symbol_Table_Range is range 0 .. 510;
 | 
      
         | 170 |  |  |    function Symbol_Table_Hash (Key : Entity_Id) return Symbol_Table_Range;
 | 
      
         | 171 |  |  |  
 | 
      
         | 172 |  |  |    --  Each subtype with a dimension has a symbolic representation of the
 | 
      
         | 173 |  |  |    --  related unit. This table establishes a relation between the subtype
 | 
      
         | 174 |  |  |    --  and the symbol.
 | 
      
         | 175 |  |  |  
 | 
      
         | 176 |  |  |    package Symbol_Table is new
 | 
      
         | 177 |  |  |      GNAT.HTable.Simple_HTable
 | 
      
         | 178 |  |  |        (Header_Num => Symbol_Table_Range,
 | 
      
         | 179 |  |  |         Element    => String_Id,
 | 
      
         | 180 |  |  |         No_Element => No_String,
 | 
      
         | 181 |  |  |         Key        => Entity_Id,
 | 
      
         | 182 |  |  |         Hash       => Symbol_Table_Hash,
 | 
      
         | 183 |  |  |         Equal      => "=");
 | 
      
         | 184 |  |  |  
 | 
      
         | 185 |  |  |    --  The following array enumerates all contexts which may contain or
 | 
      
         | 186 |  |  |    --  produce a dimension.
 | 
      
         | 187 |  |  |  
 | 
      
         | 188 |  |  |    OK_For_Dimension : constant array (Node_Kind) of Boolean :=
 | 
      
         | 189 |  |  |      (N_Attribute_Reference       => True,
 | 
      
         | 190 |  |  |       N_Defining_Identifier       => True,
 | 
      
         | 191 |  |  |       N_Function_Call             => True,
 | 
      
         | 192 |  |  |       N_Identifier                => True,
 | 
      
         | 193 |  |  |       N_Indexed_Component         => True,
 | 
      
         | 194 |  |  |       N_Integer_Literal           => True,
 | 
      
         | 195 |  |  |       N_Op_Abs                    => True,
 | 
      
         | 196 |  |  |       N_Op_Add                    => True,
 | 
      
         | 197 |  |  |       N_Op_Divide                 => True,
 | 
      
         | 198 |  |  |       N_Op_Expon                  => True,
 | 
      
         | 199 |  |  |       N_Op_Minus                  => True,
 | 
      
         | 200 |  |  |       N_Op_Mod                    => True,
 | 
      
         | 201 |  |  |       N_Op_Multiply               => True,
 | 
      
         | 202 |  |  |       N_Op_Plus                   => True,
 | 
      
         | 203 |  |  |       N_Op_Rem                    => True,
 | 
      
         | 204 |  |  |       N_Op_Subtract               => True,
 | 
      
         | 205 |  |  |       N_Qualified_Expression      => True,
 | 
      
         | 206 |  |  |       N_Real_Literal              => True,
 | 
      
         | 207 |  |  |       N_Selected_Component        => True,
 | 
      
         | 208 |  |  |       N_Slice                     => True,
 | 
      
         | 209 |  |  |       N_Type_Conversion           => True,
 | 
      
         | 210 |  |  |       N_Unchecked_Type_Conversion => True,
 | 
      
         | 211 |  |  |  
 | 
      
         | 212 |  |  |       others                      => False);
 | 
      
         | 213 |  |  |  
 | 
      
         | 214 |  |  |    -----------------------
 | 
      
         | 215 |  |  |    -- Local Subprograms --
 | 
      
         | 216 |  |  |    -----------------------
 | 
      
         | 217 |  |  |  
 | 
      
         | 218 |  |  |    procedure Analyze_Dimension_Assignment_Statement (N : Node_Id);
 | 
      
         | 219 |  |  |    --  Subroutine of Analyze_Dimension for assignment statement. Check that the
 | 
      
         | 220 |  |  |    --  dimensions of the left-hand side and the right-hand side of N match.
 | 
      
         | 221 |  |  |  
 | 
      
         | 222 |  |  |    procedure Analyze_Dimension_Binary_Op (N : Node_Id);
 | 
      
         | 223 |  |  |    --  Subroutine of Analyze_Dimension for binary operators. Check the
 | 
      
         | 224 |  |  |    --  dimensions of the right and the left operand permit the operation.
 | 
      
         | 225 |  |  |    --  Then, evaluate the resulting dimensions for each binary operator.
 | 
      
         | 226 |  |  |  
 | 
      
         | 227 |  |  |    procedure Analyze_Dimension_Component_Declaration (N : Node_Id);
 | 
      
         | 228 |  |  |    --  Subroutine of Analyze_Dimension for component declaration. Check that
 | 
      
         | 229 |  |  |    --  the dimensions of the type of N and of the expression match.
 | 
      
         | 230 |  |  |  
 | 
      
         | 231 |  |  |    procedure Analyze_Dimension_Extended_Return_Statement (N : Node_Id);
 | 
      
         | 232 |  |  |    --  Subroutine of Analyze_Dimension for extended return statement. Check
 | 
      
         | 233 |  |  |    --  that the dimensions of the returned type and of the returned object
 | 
      
         | 234 |  |  |    --  match.
 | 
      
         | 235 |  |  |  
 | 
      
         | 236 |  |  |    procedure Analyze_Dimension_Function_Call (N : Node_Id);
 | 
      
         | 237 |  |  |    --  Subroutine of Analyze_Dimension for function call. General case:
 | 
      
         | 238 |  |  |    --  propagate the dimensions from the returned type to N. Elementary
 | 
      
         | 239 |  |  |    --  function case (Ada.Numerics.Generic_Elementary_Functions): If N
 | 
      
         | 240 |  |  |    --  is a Sqrt call, then evaluate the resulting dimensions as half the
 | 
      
         | 241 |  |  |    --  dimensions of the parameter. Otherwise, verify that each parameters
 | 
      
         | 242 |  |  |    --  are dimensionless.
 | 
      
         | 243 |  |  |  
 | 
      
         | 244 |  |  |    procedure Analyze_Dimension_Has_Etype (N : Node_Id);
 | 
      
         | 245 |  |  |    --  Subroutine of Analyze_Dimension for a subset of N_Has_Etype denoted by
 | 
      
         | 246 |  |  |    --  the list below:
 | 
      
         | 247 |  |  |    --    N_Attribute_Reference
 | 
      
         | 248 |  |  |    --    N_Identifier
 | 
      
         | 249 |  |  |    --    N_Indexed_Component
 | 
      
         | 250 |  |  |    --    N_Qualified_Expression
 | 
      
         | 251 |  |  |    --    N_Selected_Component
 | 
      
         | 252 |  |  |    --    N_Slice
 | 
      
         | 253 |  |  |    --    N_Type_Conversion
 | 
      
         | 254 |  |  |    --    N_Unchecked_Type_Conversion
 | 
      
         | 255 |  |  |  
 | 
      
         | 256 |  |  |    procedure Analyze_Dimension_Object_Declaration (N : Node_Id);
 | 
      
         | 257 |  |  |    --  Subroutine of Analyze_Dimension for object declaration. Check that
 | 
      
         | 258 |  |  |    --  the dimensions of the object type and the dimensions of the expression
 | 
      
         | 259 |  |  |    --  (if expression is present) match. Note that when the expression is
 | 
      
         | 260 |  |  |    --  a literal, no error is returned. This special case allows object
 | 
      
         | 261 |  |  |    --  declaration such as: m : constant Length := 1.0;
 | 
      
         | 262 |  |  |  
 | 
      
         | 263 |  |  |    procedure Analyze_Dimension_Object_Renaming_Declaration (N : Node_Id);
 | 
      
         | 264 |  |  |    --  Subroutine of Analyze_Dimension for object renaming declaration. Check
 | 
      
         | 265 |  |  |    --  the dimensions of the type and of the renamed object name of N match.
 | 
      
         | 266 |  |  |  
 | 
      
         | 267 |  |  |    procedure Analyze_Dimension_Simple_Return_Statement (N : Node_Id);
 | 
      
         | 268 |  |  |    --  Subroutine of Analyze_Dimension for simple return statement
 | 
      
         | 269 |  |  |    --  Check that the dimensions of the returned type and of the returned
 | 
      
         | 270 |  |  |    --  expression match.
 | 
      
         | 271 |  |  |  
 | 
      
         | 272 |  |  |    procedure Analyze_Dimension_Subtype_Declaration (N : Node_Id);
 | 
      
         | 273 |  |  |    --  Subroutine of Analyze_Dimension for subtype declaration. Propagate the
 | 
      
         | 274 |  |  |    --  dimensions from the parent type to the identifier of N. Note that if
 | 
      
         | 275 |  |  |    --  both the identifier and the parent type of N are not dimensionless,
 | 
      
         | 276 |  |  |    --  return an error.
 | 
      
         | 277 |  |  |  
 | 
      
         | 278 |  |  |    procedure Analyze_Dimension_Unary_Op (N : Node_Id);
 | 
      
         | 279 |  |  |    --  Subroutine of Analyze_Dimension for unary operators. For Plus, Minus and
 | 
      
         | 280 |  |  |    --  Abs operators, propagate the dimensions from the operand to N.
 | 
      
         | 281 |  |  |  
 | 
      
         | 282 |  |  |    function Create_Rational_From
 | 
      
         | 283 |  |  |      (Expr     : Node_Id;
 | 
      
         | 284 |  |  |       Complain : Boolean) return Rational;
 | 
      
         | 285 |  |  |    --  Given an arbitrary expression Expr, return a valid rational if Expr can
 | 
      
         | 286 |  |  |    --  be interpreted as a rational. Otherwise return No_Rational and also an
 | 
      
         | 287 |  |  |    --  error message if Complain is set to True.
 | 
      
         | 288 |  |  |  
 | 
      
         | 289 |  |  |    function Dimensions_Of (N : Node_Id) return Dimension_Type;
 | 
      
         | 290 |  |  |    --  Return the dimension vector of node N
 | 
      
         | 291 |  |  |  
 | 
      
         | 292 |  |  |    function Dimensions_Msg_Of (N : Node_Id) return String;
 | 
      
         | 293 |  |  |    --  Given a node, return "has dimension" followed by the dimension vector of
 | 
      
         | 294 |  |  |    --  N or "is dimensionless" if N is dimensionless.
 | 
      
         | 295 |  |  |  
 | 
      
         | 296 |  |  |    procedure Eval_Op_Expon_With_Rational_Exponent
 | 
      
         | 297 |  |  |      (N              : Node_Id;
 | 
      
         | 298 |  |  |       Exponent_Value : Rational);
 | 
      
         | 299 |  |  |    --  Evaluate the exponent it is a rational and the operand has a dimension
 | 
      
         | 300 |  |  |  
 | 
      
         | 301 |  |  |    function Exists (Dim : Dimension_Type) return Boolean;
 | 
      
         | 302 |  |  |    --  Returns True iff Dim does not denote the null dimension
 | 
      
         | 303 |  |  |  
 | 
      
         | 304 |  |  |    function Exists (Sys : System_Type) return Boolean;
 | 
      
         | 305 |  |  |    --  Returns True iff Sys does not denote the null system
 | 
      
         | 306 |  |  |  
 | 
      
         | 307 |  |  |    function From_Dimension_To_String_Of_Symbols
 | 
      
         | 308 |  |  |      (Dims   : Dimension_Type;
 | 
      
         | 309 |  |  |       System : System_Type) return String_Id;
 | 
      
         | 310 |  |  |    --  Given a dimension vector and a dimension system, return the proper
 | 
      
         | 311 |  |  |    --  string of symbols.
 | 
      
         | 312 |  |  |  
 | 
      
         | 313 |  |  |    function Is_Dim_IO_Package_Entity (E : Entity_Id) return Boolean;
 | 
      
         | 314 |  |  |    --  Return True if E is the package entity of System.Dim.Float_IO or
 | 
      
         | 315 |  |  |    --  System.Dim.Integer_IO.
 | 
      
         | 316 |  |  |  
 | 
      
         | 317 |  |  |    function Is_Invalid (Position : Dimension_Position) return Boolean;
 | 
      
         | 318 |  |  |    --  Return True if Pos denotes the invalid position
 | 
      
         | 319 |  |  |  
 | 
      
         | 320 |  |  |    procedure Move_Dimensions (From : Node_Id; To : Node_Id);
 | 
      
         | 321 |  |  |    --  Copy dimension vector of From to To, delete dimension vector of From
 | 
      
         | 322 |  |  |  
 | 
      
         | 323 |  |  |    procedure Remove_Dimensions (N : Node_Id);
 | 
      
         | 324 |  |  |    --  Remove the dimension vector of node N
 | 
      
         | 325 |  |  |  
 | 
      
         | 326 |  |  |    procedure Set_Dimensions (N : Node_Id; Val : Dimension_Type);
 | 
      
         | 327 |  |  |    --  Associate a dimension vector with a node
 | 
      
         | 328 |  |  |  
 | 
      
         | 329 |  |  |    procedure Set_Symbol (E : Entity_Id; Val : String_Id);
 | 
      
         | 330 |  |  |    --  Associate a symbol representation of a dimension vector with a subtype
 | 
      
         | 331 |  |  |  
 | 
      
         | 332 |  |  |    function Symbol_Of (E : Entity_Id) return String_Id;
 | 
      
         | 333 |  |  |    --  E denotes a subtype with a dimension. Return the symbol representation
 | 
      
         | 334 |  |  |    --  of the dimension vector.
 | 
      
         | 335 |  |  |  
 | 
      
         | 336 |  |  |    function System_Of (E : Entity_Id) return System_Type;
 | 
      
         | 337 |  |  |    --  E denotes a type, return associated system of the type if it has one
 | 
      
         | 338 |  |  |  
 | 
      
         | 339 |  |  |    ---------
 | 
      
         | 340 |  |  |    -- "+" --
 | 
      
         | 341 |  |  |    ---------
 | 
      
         | 342 |  |  |  
 | 
      
         | 343 |  |  |    function "+" (Right : Whole) return Rational is
 | 
      
         | 344 |  |  |    begin
 | 
      
         | 345 |  |  |       return Rational'(Numerator =>   Right,
 | 
      
         | 346 |  |  |                        Denominator => 1);
 | 
      
         | 347 |  |  |    end "+";
 | 
      
         | 348 |  |  |  
 | 
      
         | 349 |  |  |    function "+" (Left, Right : Rational) return Rational is
 | 
      
         | 350 |  |  |       R : constant Rational :=
 | 
      
         | 351 |  |  |             Rational'(Numerator =>   Left.Numerator * Right.Denominator +
 | 
      
         | 352 |  |  |                                        Left.Denominator * Right.Numerator,
 | 
      
         | 353 |  |  |                       Denominator => Left.Denominator * Right.Denominator);
 | 
      
         | 354 |  |  |    begin
 | 
      
         | 355 |  |  |       return Reduce (R);
 | 
      
         | 356 |  |  |    end "+";
 | 
      
         | 357 |  |  |  
 | 
      
         | 358 |  |  |    ---------
 | 
      
         | 359 |  |  |    -- "-" --
 | 
      
         | 360 |  |  |    ---------
 | 
      
         | 361 |  |  |  
 | 
      
         | 362 |  |  |    function "-" (Right : Rational) return Rational is
 | 
      
         | 363 |  |  |    begin
 | 
      
         | 364 |  |  |       return Rational'(Numerator =>   -Right.Numerator,
 | 
      
         | 365 |  |  |                        Denominator => Right.Denominator);
 | 
      
         | 366 |  |  |    end "-";
 | 
      
         | 367 |  |  |  
 | 
      
         | 368 |  |  |    function "-" (Left, Right : Rational) return Rational is
 | 
      
         | 369 |  |  |       R : constant Rational :=
 | 
      
         | 370 |  |  |             Rational'(Numerator =>   Left.Numerator * Right.Denominator -
 | 
      
         | 371 |  |  |                                        Left.Denominator * Right.Numerator,
 | 
      
         | 372 |  |  |                       Denominator => Left.Denominator * Right.Denominator);
 | 
      
         | 373 |  |  |  
 | 
      
         | 374 |  |  |    begin
 | 
      
         | 375 |  |  |       return Reduce (R);
 | 
      
         | 376 |  |  |    end "-";
 | 
      
         | 377 |  |  |  
 | 
      
         | 378 |  |  |    ---------
 | 
      
         | 379 |  |  |    -- "*" --
 | 
      
         | 380 |  |  |    ---------
 | 
      
         | 381 |  |  |  
 | 
      
         | 382 |  |  |    function "*" (Left, Right : Rational) return Rational is
 | 
      
         | 383 |  |  |       R : constant Rational :=
 | 
      
         | 384 |  |  |             Rational'(Numerator =>   Left.Numerator * Right.Numerator,
 | 
      
         | 385 |  |  |                       Denominator => Left.Denominator * Right.Denominator);
 | 
      
         | 386 |  |  |    begin
 | 
      
         | 387 |  |  |       return Reduce (R);
 | 
      
         | 388 |  |  |    end "*";
 | 
      
         | 389 |  |  |  
 | 
      
         | 390 |  |  |    ---------
 | 
      
         | 391 |  |  |    -- "/" --
 | 
      
         | 392 |  |  |    ---------
 | 
      
         | 393 |  |  |  
 | 
      
         | 394 |  |  |    function "/" (Left, Right : Rational) return Rational is
 | 
      
         | 395 |  |  |       R : constant Rational := abs Right;
 | 
      
         | 396 |  |  |       L : Rational := Left;
 | 
      
         | 397 |  |  |  
 | 
      
         | 398 |  |  |    begin
 | 
      
         | 399 |  |  |       if Right.Numerator < 0 then
 | 
      
         | 400 |  |  |          L.Numerator := Whole (-Integer (L.Numerator));
 | 
      
         | 401 |  |  |       end if;
 | 
      
         | 402 |  |  |  
 | 
      
         | 403 |  |  |       return Reduce (Rational'(Numerator =>   L.Numerator * R.Denominator,
 | 
      
         | 404 |  |  |                                Denominator => L.Denominator * R.Numerator));
 | 
      
         | 405 |  |  |    end "/";
 | 
      
         | 406 |  |  |    -----------
 | 
      
         | 407 |  |  |    -- "abs" --
 | 
      
         | 408 |  |  |    -----------
 | 
      
         | 409 |  |  |  
 | 
      
         | 410 |  |  |    function "abs" (Right : Rational) return Rational is
 | 
      
         | 411 |  |  |    begin
 | 
      
         | 412 |  |  |       return Rational'(Numerator =>   abs Right.Numerator,
 | 
      
         | 413 |  |  |                        Denominator => Right.Denominator);
 | 
      
         | 414 |  |  |    end "abs";
 | 
      
         | 415 |  |  |  
 | 
      
         | 416 |  |  |    ------------------------------
 | 
      
         | 417 |  |  |    -- Analyze_Aspect_Dimension --
 | 
      
         | 418 |  |  |    ------------------------------
 | 
      
         | 419 |  |  |  
 | 
      
         | 420 |  |  |    --  with Dimension => DIMENSION_FOR_SUBTYPE
 | 
      
         | 421 |  |  |    --  DIMENSION_FOR_SUBTYPE ::= (DIMENSION_STRING, DIMENSION_RATIONALS)
 | 
      
         | 422 |  |  |    --  DIMENSION_RATIONALS ::=
 | 
      
         | 423 |  |  |    --    RATIONAL,  {, RATIONAL}
 | 
      
         | 424 |  |  |    --  | RATIONAL {, RATIONAL}, others => RATIONAL
 | 
      
         | 425 |  |  |    --  | DISCRETE_CHOICE_LIST => RATIONAL
 | 
      
         | 426 |  |  |    --  RATIONAL ::= [-] NUMERAL [/ NUMERAL]
 | 
      
         | 427 |  |  |  
 | 
      
         | 428 |  |  |    --  (see Analyze_Aspect_Dimension_System for DIMENSION_STRING grammar)
 | 
      
         | 429 |  |  |  
 | 
      
         | 430 |  |  |    procedure Analyze_Aspect_Dimension
 | 
      
         | 431 |  |  |      (N    : Node_Id;
 | 
      
         | 432 |  |  |       Id   : Entity_Id;
 | 
      
         | 433 |  |  |       Aggr : Node_Id)
 | 
      
         | 434 |  |  |    is
 | 
      
         | 435 |  |  |       Def_Id    : constant Entity_Id := Defining_Identifier (N);
 | 
      
         | 436 |  |  |  
 | 
      
         | 437 |  |  |       Processed : array (Dimension_Type'Range) of Boolean := (others => False);
 | 
      
         | 438 |  |  |       --  This array is used when processing ranges or Others_Choice as part of
 | 
      
         | 439 |  |  |       --  the dimension aggregate.
 | 
      
         | 440 |  |  |  
 | 
      
         | 441 |  |  |       Dimensions : Dimension_Type := Null_Dimension;
 | 
      
         | 442 |  |  |  
 | 
      
         | 443 |  |  |       procedure Extract_Power
 | 
      
         | 444 |  |  |         (Expr     : Node_Id;
 | 
      
         | 445 |  |  |          Position : Dimension_Position);
 | 
      
         | 446 |  |  |       --  Given an expression with denotes a rational number, read the number
 | 
      
         | 447 |  |  |       --  and associate it with Position in Dimensions.
 | 
      
         | 448 |  |  |  
 | 
      
         | 449 |  |  |       function Has_Compile_Time_Known_Expressions
 | 
      
         | 450 |  |  |         (Aggr : Node_Id) return Boolean;
 | 
      
         | 451 |  |  |       --  Determine whether aggregate Aggr contains only expressions that are
 | 
      
         | 452 |  |  |       --  known at compile time.
 | 
      
         | 453 |  |  |  
 | 
      
         | 454 |  |  |       function Position_In_System
 | 
      
         | 455 |  |  |         (Id     : Node_Id;
 | 
      
         | 456 |  |  |          System : System_Type) return Dimension_Position;
 | 
      
         | 457 |  |  |       --  Given an identifier which denotes a dimension, return the position of
 | 
      
         | 458 |  |  |       --  that dimension within System.
 | 
      
         | 459 |  |  |  
 | 
      
         | 460 |  |  |       -------------------
 | 
      
         | 461 |  |  |       -- Extract_Power --
 | 
      
         | 462 |  |  |       -------------------
 | 
      
         | 463 |  |  |  
 | 
      
         | 464 |  |  |       procedure Extract_Power
 | 
      
         | 465 |  |  |         (Expr     : Node_Id;
 | 
      
         | 466 |  |  |          Position : Dimension_Position)
 | 
      
         | 467 |  |  |       is
 | 
      
         | 468 |  |  |       begin
 | 
      
         | 469 |  |  |          if Is_Integer_Type (Def_Id) then
 | 
      
         | 470 |  |  |             Dimensions (Position) := +Whole (UI_To_Int (Expr_Value (Expr)));
 | 
      
         | 471 |  |  |          else
 | 
      
         | 472 |  |  |             Dimensions (Position) := Create_Rational_From (Expr, True);
 | 
      
         | 473 |  |  |          end if;
 | 
      
         | 474 |  |  |  
 | 
      
         | 475 |  |  |          Processed (Position) := True;
 | 
      
         | 476 |  |  |       end Extract_Power;
 | 
      
         | 477 |  |  |  
 | 
      
         | 478 |  |  |       ----------------------------------------
 | 
      
         | 479 |  |  |       -- Has_Compile_Time_Known_Expressions --
 | 
      
         | 480 |  |  |       ----------------------------------------
 | 
      
         | 481 |  |  |  
 | 
      
         | 482 |  |  |       function Has_Compile_Time_Known_Expressions
 | 
      
         | 483 |  |  |         (Aggr : Node_Id) return Boolean
 | 
      
         | 484 |  |  |       is
 | 
      
         | 485 |  |  |          Comp : Node_Id;
 | 
      
         | 486 |  |  |          Expr : Node_Id;
 | 
      
         | 487 |  |  |  
 | 
      
         | 488 |  |  |       begin
 | 
      
         | 489 |  |  |          Expr := First (Expressions (Aggr));
 | 
      
         | 490 |  |  |          if Present (Expr) then
 | 
      
         | 491 |  |  |  
 | 
      
         | 492 |  |  |             --  The first expression within the aggregate describes the
 | 
      
         | 493 |  |  |             --  symbolic name of a dimension, skip it.
 | 
      
         | 494 |  |  |  
 | 
      
         | 495 |  |  |             Next (Expr);
 | 
      
         | 496 |  |  |             while Present (Expr) loop
 | 
      
         | 497 |  |  |                Analyze_And_Resolve (Expr);
 | 
      
         | 498 |  |  |  
 | 
      
         | 499 |  |  |                if not Compile_Time_Known_Value (Expr) then
 | 
      
         | 500 |  |  |                   return False;
 | 
      
         | 501 |  |  |                end if;
 | 
      
         | 502 |  |  |  
 | 
      
         | 503 |  |  |                Next (Expr);
 | 
      
         | 504 |  |  |             end loop;
 | 
      
         | 505 |  |  |          end if;
 | 
      
         | 506 |  |  |  
 | 
      
         | 507 |  |  |          Comp := First (Component_Associations (Aggr));
 | 
      
         | 508 |  |  |          while Present (Comp) loop
 | 
      
         | 509 |  |  |             Expr := Expression (Comp);
 | 
      
         | 510 |  |  |  
 | 
      
         | 511 |  |  |             Analyze_And_Resolve (Expr);
 | 
      
         | 512 |  |  |  
 | 
      
         | 513 |  |  |             if not Compile_Time_Known_Value (Expr) then
 | 
      
         | 514 |  |  |                return False;
 | 
      
         | 515 |  |  |             end if;
 | 
      
         | 516 |  |  |  
 | 
      
         | 517 |  |  |             Next (Comp);
 | 
      
         | 518 |  |  |          end loop;
 | 
      
         | 519 |  |  |  
 | 
      
         | 520 |  |  |          return True;
 | 
      
         | 521 |  |  |       end Has_Compile_Time_Known_Expressions;
 | 
      
         | 522 |  |  |  
 | 
      
         | 523 |  |  |       ------------------------
 | 
      
         | 524 |  |  |       -- Position_In_System --
 | 
      
         | 525 |  |  |       ------------------------
 | 
      
         | 526 |  |  |  
 | 
      
         | 527 |  |  |       function Position_In_System
 | 
      
         | 528 |  |  |         (Id     : Node_Id;
 | 
      
         | 529 |  |  |          System : System_Type) return Dimension_Position
 | 
      
         | 530 |  |  |       is
 | 
      
         | 531 |  |  |          Dimension_Name : constant Name_Id := Chars (Id);
 | 
      
         | 532 |  |  |  
 | 
      
         | 533 |  |  |       begin
 | 
      
         | 534 |  |  |          for Position in System.Names'Range loop
 | 
      
         | 535 |  |  |             if Dimension_Name = System.Names (Position) then
 | 
      
         | 536 |  |  |                return Position;
 | 
      
         | 537 |  |  |             end if;
 | 
      
         | 538 |  |  |          end loop;
 | 
      
         | 539 |  |  |  
 | 
      
         | 540 |  |  |          return Invalid_Position;
 | 
      
         | 541 |  |  |       end Position_In_System;
 | 
      
         | 542 |  |  |  
 | 
      
         | 543 |  |  |       --  Local variables
 | 
      
         | 544 |  |  |  
 | 
      
         | 545 |  |  |       Assoc          : Node_Id;
 | 
      
         | 546 |  |  |       Choice         : Node_Id;
 | 
      
         | 547 |  |  |       Expr           : Node_Id;
 | 
      
         | 548 |  |  |       Num_Choices    : Nat := 0;
 | 
      
         | 549 |  |  |       Num_Dimensions : Nat := 0;
 | 
      
         | 550 |  |  |       Others_Seen    : Boolean := False;
 | 
      
         | 551 |  |  |       Position       : Nat := 0;
 | 
      
         | 552 |  |  |       Sub_Ind        : Node_Id;
 | 
      
         | 553 |  |  |       Symbol         : String_Id;
 | 
      
         | 554 |  |  |       Symbol_Decl    : Node_Id;
 | 
      
         | 555 |  |  |       System         : System_Type;
 | 
      
         | 556 |  |  |       Typ            : Entity_Id;
 | 
      
         | 557 |  |  |  
 | 
      
         | 558 |  |  |       Errors_Count : Nat;
 | 
      
         | 559 |  |  |       --  Errors_Count is a count of errors detected by the compiler so far
 | 
      
         | 560 |  |  |       --  just before the extraction of names and values in the aggregate
 | 
      
         | 561 |  |  |       --  (Step 3).
 | 
      
         | 562 |  |  |       --
 | 
      
         | 563 |  |  |       --  At the end of the analysis, there is a check to verify that this
 | 
      
         | 564 |  |  |       --  count equals to Serious_Errors_Detected i.e. no erros have been
 | 
      
         | 565 |  |  |       --  encountered during the process. Otherwise the Dimension_Table is
 | 
      
         | 566 |  |  |       --  not filled.
 | 
      
         | 567 |  |  |  
 | 
      
         | 568 |  |  |    --  Start of processing for Analyze_Aspect_Dimension
 | 
      
         | 569 |  |  |  
 | 
      
         | 570 |  |  |    begin
 | 
      
         | 571 |  |  |       --  STEP 1: Legality of aspect
 | 
      
         | 572 |  |  |  
 | 
      
         | 573 |  |  |       if Nkind (N) /= N_Subtype_Declaration then
 | 
      
         | 574 |  |  |          Error_Msg_NE ("aspect& must apply to subtype declaration", N, Id);
 | 
      
         | 575 |  |  |          return;
 | 
      
         | 576 |  |  |       end if;
 | 
      
         | 577 |  |  |  
 | 
      
         | 578 |  |  |       Sub_Ind := Subtype_Indication (N);
 | 
      
         | 579 |  |  |       Typ := Etype (Sub_Ind);
 | 
      
         | 580 |  |  |       System := System_Of (Typ);
 | 
      
         | 581 |  |  |  
 | 
      
         | 582 |  |  |       if Nkind (Sub_Ind) = N_Subtype_Indication then
 | 
      
         | 583 |  |  |          Error_Msg_NE
 | 
      
         | 584 |  |  |            ("constraint not allowed with aspect&", Constraint (Sub_Ind), Id);
 | 
      
         | 585 |  |  |          return;
 | 
      
         | 586 |  |  |       end if;
 | 
      
         | 587 |  |  |  
 | 
      
         | 588 |  |  |       if Nkind (Aggr) /= N_Aggregate then
 | 
      
         | 589 |  |  |          Error_Msg_N ("aggregate expected", Aggr);
 | 
      
         | 590 |  |  |          return;
 | 
      
         | 591 |  |  |       end if;
 | 
      
         | 592 |  |  |  
 | 
      
         | 593 |  |  |       --  Each expression in dimension aggregate must be known at compile time
 | 
      
         | 594 |  |  |  
 | 
      
         | 595 |  |  |       if not Has_Compile_Time_Known_Expressions (Aggr) then
 | 
      
         | 596 |  |  |          Error_Msg_N ("values of aggregate must be static", Aggr);
 | 
      
         | 597 |  |  |          return;
 | 
      
         | 598 |  |  |       end if;
 | 
      
         | 599 |  |  |  
 | 
      
         | 600 |  |  |       --  The dimension declarations are useless if the parent type does not
 | 
      
         | 601 |  |  |       --  declare a valid system.
 | 
      
         | 602 |  |  |  
 | 
      
         | 603 |  |  |       if not Exists (System) then
 | 
      
         | 604 |  |  |          Error_Msg_NE
 | 
      
         | 605 |  |  |            ("parent type of& lacks dimension system", Sub_Ind, Def_Id);
 | 
      
         | 606 |  |  |          return;
 | 
      
         | 607 |  |  |       end if;
 | 
      
         | 608 |  |  |  
 | 
      
         | 609 |  |  |       --  STEP 2: Structural verification of the dimension aggregate
 | 
      
         | 610 |  |  |  
 | 
      
         | 611 |  |  |       --  The first entry in the aggregate is the symbolic representation of
 | 
      
         | 612 |  |  |       --  the dimension.
 | 
      
         | 613 |  |  |  
 | 
      
         | 614 |  |  |       Symbol_Decl := First (Expressions (Aggr));
 | 
      
         | 615 |  |  |  
 | 
      
         | 616 |  |  |       if No (Symbol_Decl)
 | 
      
         | 617 |  |  |         or else not Nkind_In (Symbol_Decl, N_Character_Literal,
 | 
      
         | 618 |  |  |                                            N_String_Literal)
 | 
      
         | 619 |  |  |       then
 | 
      
         | 620 |  |  |          Error_Msg_N ("first argument must be character or string", Aggr);
 | 
      
         | 621 |  |  |          return;
 | 
      
         | 622 |  |  |       end if;
 | 
      
         | 623 |  |  |  
 | 
      
         | 624 |  |  |       --  STEP 3: Name and value extraction
 | 
      
         | 625 |  |  |  
 | 
      
         | 626 |  |  |       --  Get the number of errors detected by the compiler so far
 | 
      
         | 627 |  |  |  
 | 
      
         | 628 |  |  |       Errors_Count := Serious_Errors_Detected;
 | 
      
         | 629 |  |  |  
 | 
      
         | 630 |  |  |       --  Positional elements
 | 
      
         | 631 |  |  |  
 | 
      
         | 632 |  |  |       Expr := Next (Symbol_Decl);
 | 
      
         | 633 |  |  |       Position := Low_Position_Bound;
 | 
      
         | 634 |  |  |       while Present (Expr) loop
 | 
      
         | 635 |  |  |          if Position > High_Position_Bound then
 | 
      
         | 636 |  |  |             Error_Msg_N
 | 
      
         | 637 |  |  |               ("type& has more dimensions than system allows", Def_Id);
 | 
      
         | 638 |  |  |             exit;
 | 
      
         | 639 |  |  |          end if;
 | 
      
         | 640 |  |  |  
 | 
      
         | 641 |  |  |          Extract_Power (Expr, Position);
 | 
      
         | 642 |  |  |  
 | 
      
         | 643 |  |  |          Position := Position + 1;
 | 
      
         | 644 |  |  |          Num_Dimensions := Num_Dimensions + 1;
 | 
      
         | 645 |  |  |  
 | 
      
         | 646 |  |  |          Next (Expr);
 | 
      
         | 647 |  |  |       end loop;
 | 
      
         | 648 |  |  |  
 | 
      
         | 649 |  |  |       --  Named elements
 | 
      
         | 650 |  |  |  
 | 
      
         | 651 |  |  |       Assoc := First (Component_Associations (Aggr));
 | 
      
         | 652 |  |  |       while Present (Assoc) loop
 | 
      
         | 653 |  |  |          Expr   := Expression (Assoc);
 | 
      
         | 654 |  |  |          Choice := First (Choices (Assoc));
 | 
      
         | 655 |  |  |          while Present (Choice) loop
 | 
      
         | 656 |  |  |  
 | 
      
         | 657 |  |  |             --  Identifier case: NAME => EXPRESSION
 | 
      
         | 658 |  |  |  
 | 
      
         | 659 |  |  |             if Nkind (Choice) = N_Identifier then
 | 
      
         | 660 |  |  |                Position := Position_In_System (Choice, System);
 | 
      
         | 661 |  |  |  
 | 
      
         | 662 |  |  |                if Is_Invalid (Position) then
 | 
      
         | 663 |  |  |                   Error_Msg_N ("dimension name& not part of system", Choice);
 | 
      
         | 664 |  |  |                else
 | 
      
         | 665 |  |  |                   Extract_Power (Expr, Position);
 | 
      
         | 666 |  |  |                end if;
 | 
      
         | 667 |  |  |  
 | 
      
         | 668 |  |  |             --  Range case: NAME .. NAME => EXPRESSION
 | 
      
         | 669 |  |  |  
 | 
      
         | 670 |  |  |             elsif Nkind (Choice) = N_Range then
 | 
      
         | 671 |  |  |                declare
 | 
      
         | 672 |  |  |                   Low      : constant Node_Id := Low_Bound (Choice);
 | 
      
         | 673 |  |  |                   High     : constant Node_Id := High_Bound (Choice);
 | 
      
         | 674 |  |  |                   Low_Pos  : Dimension_Position;
 | 
      
         | 675 |  |  |                   High_Pos : Dimension_Position;
 | 
      
         | 676 |  |  |  
 | 
      
         | 677 |  |  |                begin
 | 
      
         | 678 |  |  |                   if Nkind (Low) /= N_Identifier then
 | 
      
         | 679 |  |  |                      Error_Msg_N ("bound must denote a dimension name", Low);
 | 
      
         | 680 |  |  |  
 | 
      
         | 681 |  |  |                   elsif Nkind (High) /= N_Identifier then
 | 
      
         | 682 |  |  |                      Error_Msg_N ("bound must denote a dimension name", High);
 | 
      
         | 683 |  |  |  
 | 
      
         | 684 |  |  |                   else
 | 
      
         | 685 |  |  |                      Low_Pos  := Position_In_System (Low, System);
 | 
      
         | 686 |  |  |                      High_Pos := Position_In_System (High, System);
 | 
      
         | 687 |  |  |  
 | 
      
         | 688 |  |  |                      if Is_Invalid (Low_Pos) then
 | 
      
         | 689 |  |  |                         Error_Msg_N ("dimension name& not part of system",
 | 
      
         | 690 |  |  |                                      Low);
 | 
      
         | 691 |  |  |  
 | 
      
         | 692 |  |  |                      elsif Is_Invalid (High_Pos) then
 | 
      
         | 693 |  |  |                         Error_Msg_N ("dimension name& not part of system",
 | 
      
         | 694 |  |  |                                      High);
 | 
      
         | 695 |  |  |  
 | 
      
         | 696 |  |  |                      elsif Low_Pos > High_Pos then
 | 
      
         | 697 |  |  |                         Error_Msg_N ("expected low to high range", Choice);
 | 
      
         | 698 |  |  |  
 | 
      
         | 699 |  |  |                      else
 | 
      
         | 700 |  |  |                         for Position in Low_Pos .. High_Pos loop
 | 
      
         | 701 |  |  |                            Extract_Power (Expr, Position);
 | 
      
         | 702 |  |  |                         end loop;
 | 
      
         | 703 |  |  |                      end if;
 | 
      
         | 704 |  |  |                   end if;
 | 
      
         | 705 |  |  |                end;
 | 
      
         | 706 |  |  |  
 | 
      
         | 707 |  |  |             --  Others case: OTHERS => EXPRESSION
 | 
      
         | 708 |  |  |  
 | 
      
         | 709 |  |  |             elsif Nkind (Choice) = N_Others_Choice then
 | 
      
         | 710 |  |  |                if Present (Next (Choice))
 | 
      
         | 711 |  |  |                  or else Present (Prev (Choice))
 | 
      
         | 712 |  |  |                then
 | 
      
         | 713 |  |  |                   Error_Msg_N
 | 
      
         | 714 |  |  |                     ("OTHERS must appear alone in a choice list", Choice);
 | 
      
         | 715 |  |  |  
 | 
      
         | 716 |  |  |                elsif Present (Next (Assoc)) then
 | 
      
         | 717 |  |  |                   Error_Msg_N
 | 
      
         | 718 |  |  |                     ("OTHERS must appear last in an aggregate", Choice);
 | 
      
         | 719 |  |  |  
 | 
      
         | 720 |  |  |                elsif Others_Seen then
 | 
      
         | 721 |  |  |                   Error_Msg_N ("multiple OTHERS not allowed", Choice);
 | 
      
         | 722 |  |  |  
 | 
      
         | 723 |  |  |                else
 | 
      
         | 724 |  |  |                   --  Fill the non-processed dimensions with the default value
 | 
      
         | 725 |  |  |                   --  supplied by others.
 | 
      
         | 726 |  |  |  
 | 
      
         | 727 |  |  |                   for Position in Processed'Range loop
 | 
      
         | 728 |  |  |                      if not Processed (Position) then
 | 
      
         | 729 |  |  |                         Extract_Power (Expr, Position);
 | 
      
         | 730 |  |  |                      end if;
 | 
      
         | 731 |  |  |                   end loop;
 | 
      
         | 732 |  |  |                end if;
 | 
      
         | 733 |  |  |  
 | 
      
         | 734 |  |  |                Others_Seen := True;
 | 
      
         | 735 |  |  |  
 | 
      
         | 736 |  |  |             --  All other cases are erroneous declarations of dimension names
 | 
      
         | 737 |  |  |  
 | 
      
         | 738 |  |  |             else
 | 
      
         | 739 |  |  |                Error_Msg_NE ("wrong syntax for aspect&", Choice, Id);
 | 
      
         | 740 |  |  |             end if;
 | 
      
         | 741 |  |  |  
 | 
      
         | 742 |  |  |             Num_Choices := Num_Choices + 1;
 | 
      
         | 743 |  |  |             Next (Choice);
 | 
      
         | 744 |  |  |          end loop;
 | 
      
         | 745 |  |  |  
 | 
      
         | 746 |  |  |          Num_Dimensions := Num_Dimensions + 1;
 | 
      
         | 747 |  |  |          Next (Assoc);
 | 
      
         | 748 |  |  |       end loop;
 | 
      
         | 749 |  |  |  
 | 
      
         | 750 |  |  |       --  STEP 4: Consistency of system and dimensions
 | 
      
         | 751 |  |  |  
 | 
      
         | 752 |  |  |       if Present (Next (Symbol_Decl))
 | 
      
         | 753 |  |  |         and then (Num_Choices > 1
 | 
      
         | 754 |  |  |                    or else (Num_Choices = 1 and then not Others_Seen))
 | 
      
         | 755 |  |  |       then
 | 
      
         | 756 |  |  |          Error_Msg_N
 | 
      
         | 757 |  |  |            ("named associations cannot follow positional associations", Aggr);
 | 
      
         | 758 |  |  |  
 | 
      
         | 759 |  |  |       elsif Num_Dimensions > System.Count then
 | 
      
         | 760 |  |  |          Error_Msg_N ("type& has more dimensions than system allows", Def_Id);
 | 
      
         | 761 |  |  |  
 | 
      
         | 762 |  |  |       elsif Num_Dimensions < System.Count and then not Others_Seen then
 | 
      
         | 763 |  |  |          Error_Msg_N ("type& has less dimensions than system allows", Def_Id);
 | 
      
         | 764 |  |  |       end if;
 | 
      
         | 765 |  |  |  
 | 
      
         | 766 |  |  |       --  STEP 5: Dimension symbol extraction
 | 
      
         | 767 |  |  |  
 | 
      
         | 768 |  |  |       if Nkind (Symbol_Decl) = N_Character_Literal then
 | 
      
         | 769 |  |  |          Start_String;
 | 
      
         | 770 |  |  |          Store_String_Char (UI_To_CC (Char_Literal_Value (Symbol_Decl)));
 | 
      
         | 771 |  |  |          Symbol := End_String;
 | 
      
         | 772 |  |  |  
 | 
      
         | 773 |  |  |       else
 | 
      
         | 774 |  |  |          Symbol := Strval (Symbol_Decl);
 | 
      
         | 775 |  |  |       end if;
 | 
      
         | 776 |  |  |  
 | 
      
         | 777 |  |  |       if String_Length (Symbol) = 0 and then not Exists (Dimensions) then
 | 
      
         | 778 |  |  |          Error_Msg_N ("useless dimension declaration", Aggr);
 | 
      
         | 779 |  |  |       end if;
 | 
      
         | 780 |  |  |  
 | 
      
         | 781 |  |  |       --  STEP 6: Storage of extracted values
 | 
      
         | 782 |  |  |  
 | 
      
         | 783 |  |  |       --  Check that no errors have been detected during the analysis
 | 
      
         | 784 |  |  |  
 | 
      
         | 785 |  |  |       if Errors_Count = Serious_Errors_Detected then
 | 
      
         | 786 |  |  |          if String_Length (Symbol) /= 0 then
 | 
      
         | 787 |  |  |             Set_Symbol (Def_Id, Symbol);
 | 
      
         | 788 |  |  |          end if;
 | 
      
         | 789 |  |  |  
 | 
      
         | 790 |  |  |          if Exists (Dimensions) then
 | 
      
         | 791 |  |  |             Set_Dimensions (Def_Id, Dimensions);
 | 
      
         | 792 |  |  |          end if;
 | 
      
         | 793 |  |  |       end if;
 | 
      
         | 794 |  |  |    end Analyze_Aspect_Dimension;
 | 
      
         | 795 |  |  |  
 | 
      
         | 796 |  |  |    -------------------------------------
 | 
      
         | 797 |  |  |    -- Analyze_Aspect_Dimension_System --
 | 
      
         | 798 |  |  |    -------------------------------------
 | 
      
         | 799 |  |  |  
 | 
      
         | 800 |  |  |    --  with Dimension_System => DIMENSION_PAIRS
 | 
      
         | 801 |  |  |  
 | 
      
         | 802 |  |  |    --  DIMENSION_PAIRS ::=
 | 
      
         | 803 |  |  |    --    (DIMENSION_PAIR
 | 
      
         | 804 |  |  |    --      [, DIMENSION_PAIR]
 | 
      
         | 805 |  |  |    --      [, DIMENSION_PAIR]
 | 
      
         | 806 |  |  |    --      [, DIMENSION_PAIR]
 | 
      
         | 807 |  |  |    --      [, DIMENSION_PAIR]
 | 
      
         | 808 |  |  |    --      [, DIMENSION_PAIR]
 | 
      
         | 809 |  |  |    --      [, DIMENSION_PAIR])
 | 
      
         | 810 |  |  |    --  DIMENSION_PAIR ::= (DIMENSION_IDENTIFIER, DIMENSION_STRING)
 | 
      
         | 811 |  |  |    --  DIMENSION_IDENTIFIER ::= IDENTIFIER
 | 
      
         | 812 |  |  |    --  DIMENSION_STRING ::= STRING_LITERAL | CHARACTER_LITERAL
 | 
      
         | 813 |  |  |  
 | 
      
         | 814 |  |  |    procedure Analyze_Aspect_Dimension_System
 | 
      
         | 815 |  |  |      (N    : Node_Id;
 | 
      
         | 816 |  |  |       Id   : Entity_Id;
 | 
      
         | 817 |  |  |       Aggr : Node_Id)
 | 
      
         | 818 |  |  |    is
 | 
      
         | 819 |  |  |       function Is_Derived_Numeric_Type (N : Node_Id) return Boolean;
 | 
      
         | 820 |  |  |       --  Determine whether type declaration N denotes a numeric derived type
 | 
      
         | 821 |  |  |  
 | 
      
         | 822 |  |  |       -------------------------------
 | 
      
         | 823 |  |  |       -- Is_Derived_Numeric_Type --
 | 
      
         | 824 |  |  |       -------------------------------
 | 
      
         | 825 |  |  |  
 | 
      
         | 826 |  |  |       function Is_Derived_Numeric_Type (N : Node_Id) return Boolean is
 | 
      
         | 827 |  |  |       begin
 | 
      
         | 828 |  |  |          return
 | 
      
         | 829 |  |  |            Nkind (N) = N_Full_Type_Declaration
 | 
      
         | 830 |  |  |              and then Nkind (Type_Definition (N)) = N_Derived_Type_Definition
 | 
      
         | 831 |  |  |              and then Is_Numeric_Type
 | 
      
         | 832 |  |  |                         (Entity (Subtype_Indication (Type_Definition (N))));
 | 
      
         | 833 |  |  |       end Is_Derived_Numeric_Type;
 | 
      
         | 834 |  |  |  
 | 
      
         | 835 |  |  |       --  Local variables
 | 
      
         | 836 |  |  |  
 | 
      
         | 837 |  |  |       Dim_Name     : Node_Id;
 | 
      
         | 838 |  |  |       Dim_Pair     : Node_Id;
 | 
      
         | 839 |  |  |       Dim_Symbol   : Node_Id;
 | 
      
         | 840 |  |  |       Dim_System   : System_Type  := Null_System;
 | 
      
         | 841 |  |  |       Names        : Name_Array   := No_Names;
 | 
      
         | 842 |  |  |       Position     : Nat := 0;
 | 
      
         | 843 |  |  |       Symbols      : Symbol_Array := No_Symbols;
 | 
      
         | 844 |  |  |  
 | 
      
         | 845 |  |  |       Errors_Count : Nat;
 | 
      
         | 846 |  |  |       --  Errors_Count is a count of errors detected by the compiler so far
 | 
      
         | 847 |  |  |       --  just before the extraction of names and symbols in the aggregate
 | 
      
         | 848 |  |  |       --  (Step 3).
 | 
      
         | 849 |  |  |       --
 | 
      
         | 850 |  |  |       --  At the end of the analysis, there is a check to verify that this
 | 
      
         | 851 |  |  |       --  count equals Serious_Errors_Detected i.e. no errors have been
 | 
      
         | 852 |  |  |       --  encountered during the process. Otherwise the System_Table is
 | 
      
         | 853 |  |  |       --  not filled.
 | 
      
         | 854 |  |  |  
 | 
      
         | 855 |  |  |    --  Start of processing for Analyze_Aspect_Dimension_System
 | 
      
         | 856 |  |  |  
 | 
      
         | 857 |  |  |    begin
 | 
      
         | 858 |  |  |       --  STEP 1: Legality of aspect
 | 
      
         | 859 |  |  |  
 | 
      
         | 860 |  |  |       if not Is_Derived_Numeric_Type (N) then
 | 
      
         | 861 |  |  |          Error_Msg_NE
 | 
      
         | 862 |  |  |            ("aspect& must apply to numeric derived type declaration", N, Id);
 | 
      
         | 863 |  |  |          return;
 | 
      
         | 864 |  |  |       end if;
 | 
      
         | 865 |  |  |  
 | 
      
         | 866 |  |  |       if Nkind (Aggr) /= N_Aggregate then
 | 
      
         | 867 |  |  |          Error_Msg_N ("aggregate expected", Aggr);
 | 
      
         | 868 |  |  |          return;
 | 
      
         | 869 |  |  |       end if;
 | 
      
         | 870 |  |  |  
 | 
      
         | 871 |  |  |       --  STEP 2: Structural verification of the dimension aggregate
 | 
      
         | 872 |  |  |  
 | 
      
         | 873 |  |  |       if Present (Component_Associations (Aggr)) then
 | 
      
         | 874 |  |  |          Error_Msg_N ("expected positional aggregate", Aggr);
 | 
      
         | 875 |  |  |          return;
 | 
      
         | 876 |  |  |       end if;
 | 
      
         | 877 |  |  |  
 | 
      
         | 878 |  |  |       --  STEP 3: Name and Symbol extraction
 | 
      
         | 879 |  |  |  
 | 
      
         | 880 |  |  |       Dim_Pair     := First (Expressions (Aggr));
 | 
      
         | 881 |  |  |       Errors_Count := Serious_Errors_Detected;
 | 
      
         | 882 |  |  |       while Present (Dim_Pair) loop
 | 
      
         | 883 |  |  |          Position := Position + 1;
 | 
      
         | 884 |  |  |  
 | 
      
         | 885 |  |  |          if Position > High_Position_Bound then
 | 
      
         | 886 |  |  |             Error_Msg_N
 | 
      
         | 887 |  |  |               ("too many dimensions in system", Aggr);
 | 
      
         | 888 |  |  |             exit;
 | 
      
         | 889 |  |  |          end if;
 | 
      
         | 890 |  |  |  
 | 
      
         | 891 |  |  |          if Nkind (Dim_Pair) /= N_Aggregate then
 | 
      
         | 892 |  |  |             Error_Msg_N ("aggregate expected", Dim_Pair);
 | 
      
         | 893 |  |  |  
 | 
      
         | 894 |  |  |          else
 | 
      
         | 895 |  |  |             if Present (Component_Associations (Dim_Pair)) then
 | 
      
         | 896 |  |  |                Error_Msg_N ("expected positional aggregate", Dim_Pair);
 | 
      
         | 897 |  |  |  
 | 
      
         | 898 |  |  |             else
 | 
      
         | 899 |  |  |                if List_Length (Expressions (Dim_Pair)) = 2 then
 | 
      
         | 900 |  |  |                   Dim_Name := First (Expressions (Dim_Pair));
 | 
      
         | 901 |  |  |                   Dim_Symbol := Next (Dim_Name);
 | 
      
         | 902 |  |  |  
 | 
      
         | 903 |  |  |                   --  Check the first argument for each pair is a name
 | 
      
         | 904 |  |  |  
 | 
      
         | 905 |  |  |                   if Nkind (Dim_Name) = N_Identifier then
 | 
      
         | 906 |  |  |                      Names (Position) := Chars (Dim_Name);
 | 
      
         | 907 |  |  |                   else
 | 
      
         | 908 |  |  |                      Error_Msg_N ("expected dimension name", Dim_Name);
 | 
      
         | 909 |  |  |                   end if;
 | 
      
         | 910 |  |  |  
 | 
      
         | 911 |  |  |                   --  Check the second argument for each pair is a string or a
 | 
      
         | 912 |  |  |                   --  character.
 | 
      
         | 913 |  |  |  
 | 
      
         | 914 |  |  |                   if not Nkind_In
 | 
      
         | 915 |  |  |                            (Dim_Symbol,
 | 
      
         | 916 |  |  |                               N_String_Literal,
 | 
      
         | 917 |  |  |                               N_Character_Literal)
 | 
      
         | 918 |  |  |                   then
 | 
      
         | 919 |  |  |                      Error_Msg_N ("expected dimension string or character",
 | 
      
         | 920 |  |  |                                   Dim_Symbol);
 | 
      
         | 921 |  |  |  
 | 
      
         | 922 |  |  |                   else
 | 
      
         | 923 |  |  |                      --  String case
 | 
      
         | 924 |  |  |  
 | 
      
         | 925 |  |  |                      if Nkind (Dim_Symbol) = N_String_Literal then
 | 
      
         | 926 |  |  |                         Symbols (Position) := Strval (Dim_Symbol);
 | 
      
         | 927 |  |  |  
 | 
      
         | 928 |  |  |                      --  Character case
 | 
      
         | 929 |  |  |  
 | 
      
         | 930 |  |  |                      else
 | 
      
         | 931 |  |  |                         Start_String;
 | 
      
         | 932 |  |  |                         Store_String_Char
 | 
      
         | 933 |  |  |                           (UI_To_CC (Char_Literal_Value (Dim_Symbol)));
 | 
      
         | 934 |  |  |                         Symbols (Position) := End_String;
 | 
      
         | 935 |  |  |                      end if;
 | 
      
         | 936 |  |  |  
 | 
      
         | 937 |  |  |                      --  Verify that the string is not empty
 | 
      
         | 938 |  |  |  
 | 
      
         | 939 |  |  |                      if String_Length (Symbols (Position)) = 0 then
 | 
      
         | 940 |  |  |                         Error_Msg_N
 | 
      
         | 941 |  |  |                           ("empty string not allowed here", Dim_Symbol);
 | 
      
         | 942 |  |  |                      end if;
 | 
      
         | 943 |  |  |                   end if;
 | 
      
         | 944 |  |  |  
 | 
      
         | 945 |  |  |                else
 | 
      
         | 946 |  |  |                   Error_Msg_N
 | 
      
         | 947 |  |  |                     ("two expressions expected in aggregate", Dim_Pair);
 | 
      
         | 948 |  |  |                end if;
 | 
      
         | 949 |  |  |             end if;
 | 
      
         | 950 |  |  |          end if;
 | 
      
         | 951 |  |  |  
 | 
      
         | 952 |  |  |          Next (Dim_Pair);
 | 
      
         | 953 |  |  |       end loop;
 | 
      
         | 954 |  |  |  
 | 
      
         | 955 |  |  |       --  STEP 4: Storage of extracted values
 | 
      
         | 956 |  |  |  
 | 
      
         | 957 |  |  |       --  Check that no errors have been detected during the analysis
 | 
      
         | 958 |  |  |  
 | 
      
         | 959 |  |  |       if Errors_Count = Serious_Errors_Detected then
 | 
      
         | 960 |  |  |          Dim_System.Type_Decl := N;
 | 
      
         | 961 |  |  |          Dim_System.Names := Names;
 | 
      
         | 962 |  |  |          Dim_System.Count := Position;
 | 
      
         | 963 |  |  |          Dim_System.Symbols := Symbols;
 | 
      
         | 964 |  |  |          System_Table.Append (Dim_System);
 | 
      
         | 965 |  |  |       end if;
 | 
      
         | 966 |  |  |    end Analyze_Aspect_Dimension_System;
 | 
      
         | 967 |  |  |  
 | 
      
         | 968 |  |  |    -----------------------
 | 
      
         | 969 |  |  |    -- Analyze_Dimension --
 | 
      
         | 970 |  |  |    -----------------------
 | 
      
         | 971 |  |  |  
 | 
      
         | 972 |  |  |    --  This dispatch routine propagates dimensions for each node
 | 
      
         | 973 |  |  |  
 | 
      
         | 974 |  |  |    procedure Analyze_Dimension (N : Node_Id) is
 | 
      
         | 975 |  |  |    begin
 | 
      
         | 976 |  |  |       --  Aspect is an Ada 2012 feature
 | 
      
         | 977 |  |  |  
 | 
      
         | 978 |  |  |       if Ada_Version < Ada_2012 then
 | 
      
         | 979 |  |  |          return;
 | 
      
         | 980 |  |  |       end if;
 | 
      
         | 981 |  |  |  
 | 
      
         | 982 |  |  |       case Nkind (N) is
 | 
      
         | 983 |  |  |  
 | 
      
         | 984 |  |  |          when N_Assignment_Statement =>
 | 
      
         | 985 |  |  |             Analyze_Dimension_Assignment_Statement (N);
 | 
      
         | 986 |  |  |  
 | 
      
         | 987 |  |  |          when N_Binary_Op =>
 | 
      
         | 988 |  |  |             Analyze_Dimension_Binary_Op (N);
 | 
      
         | 989 |  |  |  
 | 
      
         | 990 |  |  |          when N_Component_Declaration =>
 | 
      
         | 991 |  |  |             Analyze_Dimension_Component_Declaration (N);
 | 
      
         | 992 |  |  |  
 | 
      
         | 993 |  |  |          when N_Extended_Return_Statement =>
 | 
      
         | 994 |  |  |             Analyze_Dimension_Extended_Return_Statement (N);
 | 
      
         | 995 |  |  |  
 | 
      
         | 996 |  |  |          when N_Function_Call =>
 | 
      
         | 997 |  |  |             Analyze_Dimension_Function_Call (N);
 | 
      
         | 998 |  |  |  
 | 
      
         | 999 |  |  |          when N_Attribute_Reference       |
 | 
      
         | 1000 |  |  |               N_Identifier                |
 | 
      
         | 1001 |  |  |               N_Indexed_Component         |
 | 
      
         | 1002 |  |  |               N_Qualified_Expression      |
 | 
      
         | 1003 |  |  |               N_Selected_Component        |
 | 
      
         | 1004 |  |  |               N_Slice                     |
 | 
      
         | 1005 |  |  |               N_Type_Conversion           |
 | 
      
         | 1006 |  |  |               N_Unchecked_Type_Conversion =>
 | 
      
         | 1007 |  |  |             Analyze_Dimension_Has_Etype (N);
 | 
      
         | 1008 |  |  |  
 | 
      
         | 1009 |  |  |          when N_Object_Declaration =>
 | 
      
         | 1010 |  |  |             Analyze_Dimension_Object_Declaration (N);
 | 
      
         | 1011 |  |  |  
 | 
      
         | 1012 |  |  |          when N_Object_Renaming_Declaration =>
 | 
      
         | 1013 |  |  |             Analyze_Dimension_Object_Renaming_Declaration (N);
 | 
      
         | 1014 |  |  |  
 | 
      
         | 1015 |  |  |          when N_Simple_Return_Statement =>
 | 
      
         | 1016 |  |  |             if not Comes_From_Extended_Return_Statement (N) then
 | 
      
         | 1017 |  |  |                Analyze_Dimension_Simple_Return_Statement (N);
 | 
      
         | 1018 |  |  |             end if;
 | 
      
         | 1019 |  |  |  
 | 
      
         | 1020 |  |  |          when N_Subtype_Declaration =>
 | 
      
         | 1021 |  |  |             Analyze_Dimension_Subtype_Declaration (N);
 | 
      
         | 1022 |  |  |  
 | 
      
         | 1023 |  |  |          when N_Unary_Op =>
 | 
      
         | 1024 |  |  |             Analyze_Dimension_Unary_Op (N);
 | 
      
         | 1025 |  |  |  
 | 
      
         | 1026 |  |  |          when others => null;
 | 
      
         | 1027 |  |  |  
 | 
      
         | 1028 |  |  |       end case;
 | 
      
         | 1029 |  |  |    end Analyze_Dimension;
 | 
      
         | 1030 |  |  |  
 | 
      
         | 1031 |  |  |    --------------------------------------------
 | 
      
         | 1032 |  |  |    -- Analyze_Dimension_Assignment_Statement --
 | 
      
         | 1033 |  |  |    --------------------------------------------
 | 
      
         | 1034 |  |  |  
 | 
      
         | 1035 |  |  |    procedure Analyze_Dimension_Assignment_Statement (N : Node_Id) is
 | 
      
         | 1036 |  |  |       Lhs         : constant Node_Id := Name (N);
 | 
      
         | 1037 |  |  |       Dims_Of_Lhs : constant Dimension_Type := Dimensions_Of (Lhs);
 | 
      
         | 1038 |  |  |       Rhs         : constant Node_Id := Expression (N);
 | 
      
         | 1039 |  |  |       Dims_Of_Rhs : constant Dimension_Type := Dimensions_Of (Rhs);
 | 
      
         | 1040 |  |  |  
 | 
      
         | 1041 |  |  |       procedure Error_Dim_Msg_For_Assignment_Statement
 | 
      
         | 1042 |  |  |         (N   : Node_Id;
 | 
      
         | 1043 |  |  |          Lhs : Node_Id;
 | 
      
         | 1044 |  |  |          Rhs : Node_Id);
 | 
      
         | 1045 |  |  |       --  Error using Error_Msg_N at node N. Output the dimensions of left
 | 
      
         | 1046 |  |  |       --  and right hand sides.
 | 
      
         | 1047 |  |  |  
 | 
      
         | 1048 |  |  |       --------------------------------------------
 | 
      
         | 1049 |  |  |       -- Error_Dim_Msg_For_Assignment_Statement --
 | 
      
         | 1050 |  |  |       --------------------------------------------
 | 
      
         | 1051 |  |  |  
 | 
      
         | 1052 |  |  |       procedure Error_Dim_Msg_For_Assignment_Statement
 | 
      
         | 1053 |  |  |         (N   : Node_Id;
 | 
      
         | 1054 |  |  |          Lhs : Node_Id;
 | 
      
         | 1055 |  |  |          Rhs : Node_Id)
 | 
      
         | 1056 |  |  |       is
 | 
      
         | 1057 |  |  |       begin
 | 
      
         | 1058 |  |  |          Error_Msg_N ("dimensions mismatch in assignment", N);
 | 
      
         | 1059 |  |  |          Error_Msg_N ("\left-hand side " & Dimensions_Msg_Of (Lhs), N);
 | 
      
         | 1060 |  |  |          Error_Msg_N ("\right-hand side " & Dimensions_Msg_Of (Rhs), N);
 | 
      
         | 1061 |  |  |       end Error_Dim_Msg_For_Assignment_Statement;
 | 
      
         | 1062 |  |  |  
 | 
      
         | 1063 |  |  |    --  Start of processing for Analyze_Dimension_Assignment
 | 
      
         | 1064 |  |  |  
 | 
      
         | 1065 |  |  |    begin
 | 
      
         | 1066 |  |  |       if Dims_Of_Lhs /= Dims_Of_Rhs then
 | 
      
         | 1067 |  |  |          Error_Dim_Msg_For_Assignment_Statement (N, Lhs, Rhs);
 | 
      
         | 1068 |  |  |       end if;
 | 
      
         | 1069 |  |  |    end Analyze_Dimension_Assignment_Statement;
 | 
      
         | 1070 |  |  |  
 | 
      
         | 1071 |  |  |    ---------------------------------
 | 
      
         | 1072 |  |  |    -- Analyze_Dimension_Binary_Op --
 | 
      
         | 1073 |  |  |    ---------------------------------
 | 
      
         | 1074 |  |  |  
 | 
      
         | 1075 |  |  |    --  Check and propagate the dimensions for binary operators
 | 
      
         | 1076 |  |  |    --  Note that when the dimensions mismatch, no dimension is propagated to N.
 | 
      
         | 1077 |  |  |  
 | 
      
         | 1078 |  |  |    procedure Analyze_Dimension_Binary_Op (N : Node_Id) is
 | 
      
         | 1079 |  |  |       N_Kind : constant Node_Kind := Nkind (N);
 | 
      
         | 1080 |  |  |  
 | 
      
         | 1081 |  |  |       procedure Error_Dim_Msg_For_Binary_Op (N, L, R : Node_Id);
 | 
      
         | 1082 |  |  |       --  Error using Error_Msg_NE and Error_Msg_N at node N. Output the
 | 
      
         | 1083 |  |  |       --  dimensions of both operands.
 | 
      
         | 1084 |  |  |  
 | 
      
         | 1085 |  |  |       ---------------------------------
 | 
      
         | 1086 |  |  |       -- Error_Dim_Msg_For_Binary_Op --
 | 
      
         | 1087 |  |  |       ---------------------------------
 | 
      
         | 1088 |  |  |  
 | 
      
         | 1089 |  |  |       procedure Error_Dim_Msg_For_Binary_Op (N, L, R : Node_Id) is
 | 
      
         | 1090 |  |  |       begin
 | 
      
         | 1091 |  |  |          Error_Msg_NE ("both operands for operation& must have same " &
 | 
      
         | 1092 |  |  |                        "dimensions",
 | 
      
         | 1093 |  |  |                        N,
 | 
      
         | 1094 |  |  |                        Entity (N));
 | 
      
         | 1095 |  |  |          Error_Msg_N ("\left operand " & Dimensions_Msg_Of (L), N);
 | 
      
         | 1096 |  |  |          Error_Msg_N ("\right operand " & Dimensions_Msg_Of (R), N);
 | 
      
         | 1097 |  |  |       end Error_Dim_Msg_For_Binary_Op;
 | 
      
         | 1098 |  |  |  
 | 
      
         | 1099 |  |  |    --  Start of processing for Analyze_Dimension_Binary_Op
 | 
      
         | 1100 |  |  |  
 | 
      
         | 1101 |  |  |    begin
 | 
      
         | 1102 |  |  |       if Nkind_In (N_Kind, N_Op_Add, N_Op_Expon, N_Op_Subtract)
 | 
      
         | 1103 |  |  |         or else N_Kind in N_Multiplying_Operator
 | 
      
         | 1104 |  |  |         or else N_Kind in N_Op_Compare
 | 
      
         | 1105 |  |  |       then
 | 
      
         | 1106 |  |  |          declare
 | 
      
         | 1107 |  |  |             L                : constant Node_Id := Left_Opnd (N);
 | 
      
         | 1108 |  |  |             Dims_Of_L        : constant Dimension_Type := Dimensions_Of (L);
 | 
      
         | 1109 |  |  |             L_Has_Dimensions : constant Boolean := Exists (Dims_Of_L);
 | 
      
         | 1110 |  |  |             R                : constant Node_Id := Right_Opnd (N);
 | 
      
         | 1111 |  |  |             Dims_Of_R        : constant Dimension_Type := Dimensions_Of (R);
 | 
      
         | 1112 |  |  |             R_Has_Dimensions : constant Boolean := Exists (Dims_Of_R);
 | 
      
         | 1113 |  |  |             Dims_Of_N        : Dimension_Type := Null_Dimension;
 | 
      
         | 1114 |  |  |  
 | 
      
         | 1115 |  |  |          begin
 | 
      
         | 1116 |  |  |             --  N_Op_Add, N_Op_Mod, N_Op_Rem or N_Op_Subtract case
 | 
      
         | 1117 |  |  |  
 | 
      
         | 1118 |  |  |             if Nkind_In (N, N_Op_Add, N_Op_Mod, N_Op_Rem, N_Op_Subtract) then
 | 
      
         | 1119 |  |  |  
 | 
      
         | 1120 |  |  |                --  Check both operands have same dimension
 | 
      
         | 1121 |  |  |  
 | 
      
         | 1122 |  |  |                if Dims_Of_L /= Dims_Of_R then
 | 
      
         | 1123 |  |  |                   Error_Dim_Msg_For_Binary_Op (N, L, R);
 | 
      
         | 1124 |  |  |                else
 | 
      
         | 1125 |  |  |                   --  Check both operands are not dimensionless
 | 
      
         | 1126 |  |  |  
 | 
      
         | 1127 |  |  |                   if Exists (Dims_Of_L) then
 | 
      
         | 1128 |  |  |                      Set_Dimensions (N, Dims_Of_L);
 | 
      
         | 1129 |  |  |                   end if;
 | 
      
         | 1130 |  |  |                end if;
 | 
      
         | 1131 |  |  |  
 | 
      
         | 1132 |  |  |             --  N_Op_Multiply or N_Op_Divide case
 | 
      
         | 1133 |  |  |  
 | 
      
         | 1134 |  |  |             elsif Nkind_In (N_Kind, N_Op_Multiply, N_Op_Divide) then
 | 
      
         | 1135 |  |  |  
 | 
      
         | 1136 |  |  |                --  Check at least one operand is not dimensionless
 | 
      
         | 1137 |  |  |  
 | 
      
         | 1138 |  |  |                if L_Has_Dimensions or R_Has_Dimensions then
 | 
      
         | 1139 |  |  |  
 | 
      
         | 1140 |  |  |                   --  Multiplication case
 | 
      
         | 1141 |  |  |  
 | 
      
         | 1142 |  |  |                   --  Get both operands dimensions and add them
 | 
      
         | 1143 |  |  |  
 | 
      
         | 1144 |  |  |                   if N_Kind = N_Op_Multiply then
 | 
      
         | 1145 |  |  |                      for Position in Dimension_Type'Range loop
 | 
      
         | 1146 |  |  |                         Dims_Of_N (Position) :=
 | 
      
         | 1147 |  |  |                           Dims_Of_L (Position) + Dims_Of_R (Position);
 | 
      
         | 1148 |  |  |                      end loop;
 | 
      
         | 1149 |  |  |  
 | 
      
         | 1150 |  |  |                   --  Division case
 | 
      
         | 1151 |  |  |  
 | 
      
         | 1152 |  |  |                   --  Get both operands dimensions and subtract them
 | 
      
         | 1153 |  |  |  
 | 
      
         | 1154 |  |  |                   else
 | 
      
         | 1155 |  |  |                      for Position in Dimension_Type'Range loop
 | 
      
         | 1156 |  |  |                         Dims_Of_N (Position) :=
 | 
      
         | 1157 |  |  |                           Dims_Of_L (Position) - Dims_Of_R (Position);
 | 
      
         | 1158 |  |  |                      end loop;
 | 
      
         | 1159 |  |  |                   end if;
 | 
      
         | 1160 |  |  |  
 | 
      
         | 1161 |  |  |                   if Exists (Dims_Of_N) then
 | 
      
         | 1162 |  |  |                      Set_Dimensions (N, Dims_Of_N);
 | 
      
         | 1163 |  |  |                   end if;
 | 
      
         | 1164 |  |  |                end if;
 | 
      
         | 1165 |  |  |  
 | 
      
         | 1166 |  |  |             --  Exponentiation case
 | 
      
         | 1167 |  |  |  
 | 
      
         | 1168 |  |  |             --  Note: a rational exponent is allowed for dimensioned operand
 | 
      
         | 1169 |  |  |  
 | 
      
         | 1170 |  |  |             elsif N_Kind = N_Op_Expon then
 | 
      
         | 1171 |  |  |  
 | 
      
         | 1172 |  |  |                --  Check the left operand is not dimensionless. Note that the
 | 
      
         | 1173 |  |  |                --  value of the exponent must be known compile time. Otherwise,
 | 
      
         | 1174 |  |  |                --  the exponentiation evaluation will return an error message.
 | 
      
         | 1175 |  |  |  
 | 
      
         | 1176 |  |  |                if L_Has_Dimensions
 | 
      
         | 1177 |  |  |                  and then Compile_Time_Known_Value (R)
 | 
      
         | 1178 |  |  |                then
 | 
      
         | 1179 |  |  |                   declare
 | 
      
         | 1180 |  |  |                      Exponent_Value : Rational := Zero;
 | 
      
         | 1181 |  |  |  
 | 
      
         | 1182 |  |  |                   begin
 | 
      
         | 1183 |  |  |                      --  Real operand case
 | 
      
         | 1184 |  |  |  
 | 
      
         | 1185 |  |  |                      if Is_Real_Type (Etype (L)) then
 | 
      
         | 1186 |  |  |  
 | 
      
         | 1187 |  |  |                         --  Define the exponent as a Rational number
 | 
      
         | 1188 |  |  |  
 | 
      
         | 1189 |  |  |                         Exponent_Value := Create_Rational_From (R, False);
 | 
      
         | 1190 |  |  |  
 | 
      
         | 1191 |  |  |                         --  Verify that the exponent cannot be interpreted
 | 
      
         | 1192 |  |  |                         --  as a rational, otherwise interpret the exponent
 | 
      
         | 1193 |  |  |                         --  as an integer.
 | 
      
         | 1194 |  |  |  
 | 
      
         | 1195 |  |  |                         if Exponent_Value = No_Rational then
 | 
      
         | 1196 |  |  |                            Exponent_Value :=
 | 
      
         | 1197 |  |  |                              +Whole (UI_To_Int (Expr_Value (R)));
 | 
      
         | 1198 |  |  |                         end if;
 | 
      
         | 1199 |  |  |  
 | 
      
         | 1200 |  |  |                      --  Integer operand case.
 | 
      
         | 1201 |  |  |  
 | 
      
         | 1202 |  |  |                      --  For integer operand, the exponent cannot be
 | 
      
         | 1203 |  |  |                      --  interpreted as a rational.
 | 
      
         | 1204 |  |  |  
 | 
      
         | 1205 |  |  |                      else
 | 
      
         | 1206 |  |  |                         Exponent_Value := +Whole (UI_To_Int (Expr_Value (R)));
 | 
      
         | 1207 |  |  |                      end if;
 | 
      
         | 1208 |  |  |  
 | 
      
         | 1209 |  |  |                      for Position in Dimension_Type'Range loop
 | 
      
         | 1210 |  |  |                         Dims_Of_N (Position) :=
 | 
      
         | 1211 |  |  |                           Dims_Of_L (Position) * Exponent_Value;
 | 
      
         | 1212 |  |  |                      end loop;
 | 
      
         | 1213 |  |  |  
 | 
      
         | 1214 |  |  |                      if Exists (Dims_Of_N) then
 | 
      
         | 1215 |  |  |                         Set_Dimensions (N, Dims_Of_N);
 | 
      
         | 1216 |  |  |                      end if;
 | 
      
         | 1217 |  |  |                   end;
 | 
      
         | 1218 |  |  |                end if;
 | 
      
         | 1219 |  |  |  
 | 
      
         | 1220 |  |  |             --  Comparison cases
 | 
      
         | 1221 |  |  |  
 | 
      
         | 1222 |  |  |             --  For relational operations, only dimension checking is
 | 
      
         | 1223 |  |  |             --  performed (no propagation).
 | 
      
         | 1224 |  |  |  
 | 
      
         | 1225 |  |  |             elsif N_Kind in N_Op_Compare then
 | 
      
         | 1226 |  |  |                if (L_Has_Dimensions or R_Has_Dimensions)
 | 
      
         | 1227 |  |  |                  and then Dims_Of_L /= Dims_Of_R
 | 
      
         | 1228 |  |  |                then
 | 
      
         | 1229 |  |  |                   Error_Dim_Msg_For_Binary_Op (N, L, R);
 | 
      
         | 1230 |  |  |                end if;
 | 
      
         | 1231 |  |  |             end if;
 | 
      
         | 1232 |  |  |  
 | 
      
         | 1233 |  |  |             --  Removal of dimensions for each operands
 | 
      
         | 1234 |  |  |  
 | 
      
         | 1235 |  |  |             Remove_Dimensions (L);
 | 
      
         | 1236 |  |  |             Remove_Dimensions (R);
 | 
      
         | 1237 |  |  |          end;
 | 
      
         | 1238 |  |  |       end if;
 | 
      
         | 1239 |  |  |    end Analyze_Dimension_Binary_Op;
 | 
      
         | 1240 |  |  |  
 | 
      
         | 1241 |  |  |    ---------------------------------------------
 | 
      
         | 1242 |  |  |    -- Analyze_Dimension_Component_Declaration --
 | 
      
         | 1243 |  |  |    ---------------------------------------------
 | 
      
         | 1244 |  |  |  
 | 
      
         | 1245 |  |  |    procedure Analyze_Dimension_Component_Declaration (N : Node_Id) is
 | 
      
         | 1246 |  |  |       Expr         : constant Node_Id        := Expression (N);
 | 
      
         | 1247 |  |  |       Id           : constant Entity_Id      := Defining_Identifier (N);
 | 
      
         | 1248 |  |  |       Etyp         : constant Entity_Id      := Etype (Id);
 | 
      
         | 1249 |  |  |       Dims_Of_Etyp : constant Dimension_Type := Dimensions_Of (Etyp);
 | 
      
         | 1250 |  |  |       Dims_Of_Expr : Dimension_Type;
 | 
      
         | 1251 |  |  |  
 | 
      
         | 1252 |  |  |       procedure Error_Dim_Msg_For_Component_Declaration
 | 
      
         | 1253 |  |  |         (N    : Node_Id;
 | 
      
         | 1254 |  |  |          Etyp : Entity_Id;
 | 
      
         | 1255 |  |  |          Expr : Node_Id);
 | 
      
         | 1256 |  |  |       --  Error using Error_Msg_N at node N. Output the dimensions of the
 | 
      
         | 1257 |  |  |       --  type Etyp and the expression Expr of N.
 | 
      
         | 1258 |  |  |  
 | 
      
         | 1259 |  |  |       ---------------------------------------------
 | 
      
         | 1260 |  |  |       -- Error_Dim_Msg_For_Component_Declaration --
 | 
      
         | 1261 |  |  |       ---------------------------------------------
 | 
      
         | 1262 |  |  |  
 | 
      
         | 1263 |  |  |       procedure Error_Dim_Msg_For_Component_Declaration
 | 
      
         | 1264 |  |  |         (N    : Node_Id;
 | 
      
         | 1265 |  |  |          Etyp : Entity_Id;
 | 
      
         | 1266 |  |  |          Expr : Node_Id) is
 | 
      
         | 1267 |  |  |       begin
 | 
      
         | 1268 |  |  |          Error_Msg_N ("dimensions mismatch in component declaration", N);
 | 
      
         | 1269 |  |  |          Error_Msg_N ("\component type " & Dimensions_Msg_Of (Etyp), N);
 | 
      
         | 1270 |  |  |          Error_Msg_N ("\component expression " & Dimensions_Msg_Of (Expr), N);
 | 
      
         | 1271 |  |  |       end Error_Dim_Msg_For_Component_Declaration;
 | 
      
         | 1272 |  |  |  
 | 
      
         | 1273 |  |  |    --  Start of processing for Analyze_Dimension_Component_Declaration
 | 
      
         | 1274 |  |  |  
 | 
      
         | 1275 |  |  |    begin
 | 
      
         | 1276 |  |  |       if Present (Expr) then
 | 
      
         | 1277 |  |  |          Dims_Of_Expr := Dimensions_Of (Expr);
 | 
      
         | 1278 |  |  |  
 | 
      
         | 1279 |  |  |          --  Return an error if the dimension of the expression and the
 | 
      
         | 1280 |  |  |          --  dimension of the type mismatch.
 | 
      
         | 1281 |  |  |  
 | 
      
         | 1282 |  |  |          if Dims_Of_Etyp /= Dims_Of_Expr then
 | 
      
         | 1283 |  |  |             Error_Dim_Msg_For_Component_Declaration (N, Etyp, Expr);
 | 
      
         | 1284 |  |  |          end if;
 | 
      
         | 1285 |  |  |  
 | 
      
         | 1286 |  |  |          --  Removal of dimensions in expression
 | 
      
         | 1287 |  |  |  
 | 
      
         | 1288 |  |  |          Remove_Dimensions (Expr);
 | 
      
         | 1289 |  |  |       end if;
 | 
      
         | 1290 |  |  |    end Analyze_Dimension_Component_Declaration;
 | 
      
         | 1291 |  |  |  
 | 
      
         | 1292 |  |  |    -------------------------------------------------
 | 
      
         | 1293 |  |  |    -- Analyze_Dimension_Extended_Return_Statement --
 | 
      
         | 1294 |  |  |    -------------------------------------------------
 | 
      
         | 1295 |  |  |  
 | 
      
         | 1296 |  |  |    procedure Analyze_Dimension_Extended_Return_Statement (N : Node_Id) is
 | 
      
         | 1297 |  |  |       Return_Ent            : constant Entity_Id :=
 | 
      
         | 1298 |  |  |                                 Return_Statement_Entity (N);
 | 
      
         | 1299 |  |  |       Return_Etyp           : constant Entity_Id :=
 | 
      
         | 1300 |  |  |                                 Etype (Return_Applies_To (Return_Ent));
 | 
      
         | 1301 |  |  |       Dims_Of_Return_Etyp   : constant Dimension_Type :=
 | 
      
         | 1302 |  |  |                                 Dimensions_Of (Return_Etyp);
 | 
      
         | 1303 |  |  |       Return_Obj_Decls      : constant List_Id :=
 | 
      
         | 1304 |  |  |                                 Return_Object_Declarations (N);
 | 
      
         | 1305 |  |  |       Dims_Of_Return_Obj_Id : Dimension_Type;
 | 
      
         | 1306 |  |  |       Return_Obj_Decl       : Node_Id;
 | 
      
         | 1307 |  |  |       Return_Obj_Id         : Entity_Id;
 | 
      
         | 1308 |  |  |  
 | 
      
         | 1309 |  |  |       procedure Error_Dim_Msg_For_Extended_Return_Statement
 | 
      
         | 1310 |  |  |         (N             : Node_Id;
 | 
      
         | 1311 |  |  |          Return_Etyp   : Entity_Id;
 | 
      
         | 1312 |  |  |          Return_Obj_Id : Entity_Id);
 | 
      
         | 1313 |  |  |       --  Error using Error_Msg_N at node N. Output the dimensions of the
 | 
      
         | 1314 |  |  |       --  returned type Return_Etyp and the returned object Return_Obj_Id of N.
 | 
      
         | 1315 |  |  |  
 | 
      
         | 1316 |  |  |       -------------------------------------------------
 | 
      
         | 1317 |  |  |       -- Error_Dim_Msg_For_Extended_Return_Statement --
 | 
      
         | 1318 |  |  |       -------------------------------------------------
 | 
      
         | 1319 |  |  |  
 | 
      
         | 1320 |  |  |       procedure Error_Dim_Msg_For_Extended_Return_Statement
 | 
      
         | 1321 |  |  |         (N             : Node_Id;
 | 
      
         | 1322 |  |  |          Return_Etyp   : Entity_Id;
 | 
      
         | 1323 |  |  |          Return_Obj_Id : Entity_Id)
 | 
      
         | 1324 |  |  |       is
 | 
      
         | 1325 |  |  |       begin
 | 
      
         | 1326 |  |  |          Error_Msg_N ("dimensions mismatch in extended return statement", N);
 | 
      
         | 1327 |  |  |          Error_Msg_N ("\returned type " & Dimensions_Msg_Of (Return_Etyp), N);
 | 
      
         | 1328 |  |  |          Error_Msg_N ("\returned object " & Dimensions_Msg_Of (Return_Obj_Id),
 | 
      
         | 1329 |  |  |                       N);
 | 
      
         | 1330 |  |  |       end Error_Dim_Msg_For_Extended_Return_Statement;
 | 
      
         | 1331 |  |  |  
 | 
      
         | 1332 |  |  |    --  Start of processing for Analyze_Dimension_Extended_Return_Statement
 | 
      
         | 1333 |  |  |  
 | 
      
         | 1334 |  |  |    begin
 | 
      
         | 1335 |  |  |       if Present (Return_Obj_Decls) then
 | 
      
         | 1336 |  |  |          Return_Obj_Decl := First (Return_Obj_Decls);
 | 
      
         | 1337 |  |  |          while Present (Return_Obj_Decl) loop
 | 
      
         | 1338 |  |  |             if Nkind (Return_Obj_Decl) = N_Object_Declaration then
 | 
      
         | 1339 |  |  |                Return_Obj_Id := Defining_Identifier (Return_Obj_Decl);
 | 
      
         | 1340 |  |  |  
 | 
      
         | 1341 |  |  |                if Is_Return_Object (Return_Obj_Id) then
 | 
      
         | 1342 |  |  |                   Dims_Of_Return_Obj_Id := Dimensions_Of (Return_Obj_Id);
 | 
      
         | 1343 |  |  |  
 | 
      
         | 1344 |  |  |                   if Dims_Of_Return_Etyp /= Dims_Of_Return_Obj_Id then
 | 
      
         | 1345 |  |  |                      Error_Dim_Msg_For_Extended_Return_Statement
 | 
      
         | 1346 |  |  |                        (N, Return_Etyp, Return_Obj_Id);
 | 
      
         | 1347 |  |  |                      return;
 | 
      
         | 1348 |  |  |                   end if;
 | 
      
         | 1349 |  |  |                end if;
 | 
      
         | 1350 |  |  |             end if;
 | 
      
         | 1351 |  |  |  
 | 
      
         | 1352 |  |  |             Next (Return_Obj_Decl);
 | 
      
         | 1353 |  |  |          end loop;
 | 
      
         | 1354 |  |  |       end if;
 | 
      
         | 1355 |  |  |    end Analyze_Dimension_Extended_Return_Statement;
 | 
      
         | 1356 |  |  |  
 | 
      
         | 1357 |  |  |    -------------------------------------
 | 
      
         | 1358 |  |  |    -- Analyze_Dimension_Function_Call --
 | 
      
         | 1359 |  |  |    -------------------------------------
 | 
      
         | 1360 |  |  |  
 | 
      
         | 1361 |  |  |    --  Propagate the dimensions from the returned type to the call node. Note
 | 
      
         | 1362 |  |  |    --  that there is a special treatment for elementary function calls. Indeed
 | 
      
         | 1363 |  |  |    --  for Sqrt call, the resulting dimensions equal to half the dimensions of
 | 
      
         | 1364 |  |  |    --  the actual, and for other elementary calls, this routine check that
 | 
      
         | 1365 |  |  |    --  every actuals are dimensionless.
 | 
      
         | 1366 |  |  |  
 | 
      
         | 1367 |  |  |    procedure Analyze_Dimension_Function_Call (N : Node_Id) is
 | 
      
         | 1368 |  |  |       Actuals        : constant List_Id := Parameter_Associations (N);
 | 
      
         | 1369 |  |  |       Name_Call      : constant Node_Id := Name (N);
 | 
      
         | 1370 |  |  |       Actual         : Node_Id;
 | 
      
         | 1371 |  |  |       Dims_Of_Actual : Dimension_Type;
 | 
      
         | 1372 |  |  |       Dims_Of_Call   : Dimension_Type;
 | 
      
         | 1373 |  |  |       Ent            : Entity_Id;
 | 
      
         | 1374 |  |  |  
 | 
      
         | 1375 |  |  |       function Is_Elementary_Function_Entity (E : Entity_Id) return Boolean;
 | 
      
         | 1376 |  |  |       --  Given E, the original subprogram entity, return True if call is to an
 | 
      
         | 1377 |  |  |       --  elementary function (see Ada.Numerics.Generic_Elementary_Functions).
 | 
      
         | 1378 |  |  |  
 | 
      
         | 1379 |  |  |       -----------------------------------
 | 
      
         | 1380 |  |  |       -- Is_Elementary_Function_Entity --
 | 
      
         | 1381 |  |  |       -----------------------------------
 | 
      
         | 1382 |  |  |  
 | 
      
         | 1383 |  |  |       function Is_Elementary_Function_Entity (E : Entity_Id) return Boolean is
 | 
      
         | 1384 |  |  |          Loc : constant Source_Ptr := Sloc (E);
 | 
      
         | 1385 |  |  |  
 | 
      
         | 1386 |  |  |       begin
 | 
      
         | 1387 |  |  |          --  Is function entity in Ada.Numerics.Generic_Elementary_Functions?
 | 
      
         | 1388 |  |  |  
 | 
      
         | 1389 |  |  |          return
 | 
      
         | 1390 |  |  |            Loc > No_Location
 | 
      
         | 1391 |  |  |              and then
 | 
      
         | 1392 |  |  |                Is_RTU
 | 
      
         | 1393 |  |  |                 (Cunit_Entity (Get_Source_Unit (Loc)),
 | 
      
         | 1394 |  |  |                  Ada_Numerics_Generic_Elementary_Functions);
 | 
      
         | 1395 |  |  |       end Is_Elementary_Function_Entity;
 | 
      
         | 1396 |  |  |  
 | 
      
         | 1397 |  |  |    --  Start of processing for Analyze_Dimension_Function_Call
 | 
      
         | 1398 |  |  |  
 | 
      
         | 1399 |  |  |    begin
 | 
      
         | 1400 |  |  |       --  Look for elementary function call
 | 
      
         | 1401 |  |  |  
 | 
      
         | 1402 |  |  |       if Is_Entity_Name (Name_Call) then
 | 
      
         | 1403 |  |  |          Ent := Entity (Name_Call);
 | 
      
         | 1404 |  |  |  
 | 
      
         | 1405 |  |  |          --  Get the original subprogram entity following the renaming chain
 | 
      
         | 1406 |  |  |  
 | 
      
         | 1407 |  |  |          if Present (Alias (Ent)) then
 | 
      
         | 1408 |  |  |             Ent := Alias (Ent);
 | 
      
         | 1409 |  |  |          end if;
 | 
      
         | 1410 |  |  |  
 | 
      
         | 1411 |  |  |          --  Elementary function case
 | 
      
         | 1412 |  |  |  
 | 
      
         | 1413 |  |  |          if Is_Elementary_Function_Entity (Ent) then
 | 
      
         | 1414 |  |  |  
 | 
      
         | 1415 |  |  |          --  Sqrt function call case
 | 
      
         | 1416 |  |  |  
 | 
      
         | 1417 |  |  |             if Chars (Ent) = Name_Sqrt then
 | 
      
         | 1418 |  |  |                Dims_Of_Call := Dimensions_Of (First (Actuals));
 | 
      
         | 1419 |  |  |  
 | 
      
         | 1420 |  |  |                if Exists (Dims_Of_Call) then
 | 
      
         | 1421 |  |  |                   for Position in Dims_Of_Call'Range loop
 | 
      
         | 1422 |  |  |                      Dims_Of_Call (Position) :=
 | 
      
         | 1423 |  |  |                        Dims_Of_Call (Position) * Rational'(Numerator   => 1,
 | 
      
         | 1424 |  |  |                                                            Denominator => 2);
 | 
      
         | 1425 |  |  |                   end loop;
 | 
      
         | 1426 |  |  |  
 | 
      
         | 1427 |  |  |                   Set_Dimensions (N, Dims_Of_Call);
 | 
      
         | 1428 |  |  |                end if;
 | 
      
         | 1429 |  |  |  
 | 
      
         | 1430 |  |  |             --  All other elementary functions case. Note that every actual
 | 
      
         | 1431 |  |  |             --  here should be dimensionless.
 | 
      
         | 1432 |  |  |  
 | 
      
         | 1433 |  |  |             else
 | 
      
         | 1434 |  |  |                Actual := First (Actuals);
 | 
      
         | 1435 |  |  |                while Present (Actual) loop
 | 
      
         | 1436 |  |  |                   Dims_Of_Actual := Dimensions_Of (Actual);
 | 
      
         | 1437 |  |  |  
 | 
      
         | 1438 |  |  |                   if Exists (Dims_Of_Actual) then
 | 
      
         | 1439 |  |  |                      Error_Msg_NE ("parameter should be dimensionless for " &
 | 
      
         | 1440 |  |  |                                    "elementary function&",
 | 
      
         | 1441 |  |  |                                    Actual, Name_Call);
 | 
      
         | 1442 |  |  |                      Error_Msg_N ("\parameter " & Dimensions_Msg_Of (Actual),
 | 
      
         | 1443 |  |  |                                   Actual);
 | 
      
         | 1444 |  |  |                   end if;
 | 
      
         | 1445 |  |  |  
 | 
      
         | 1446 |  |  |                   Next (Actual);
 | 
      
         | 1447 |  |  |                end loop;
 | 
      
         | 1448 |  |  |             end if;
 | 
      
         | 1449 |  |  |  
 | 
      
         | 1450 |  |  |             return;
 | 
      
         | 1451 |  |  |          end if;
 | 
      
         | 1452 |  |  |       end if;
 | 
      
         | 1453 |  |  |  
 | 
      
         | 1454 |  |  |       --  Other cases
 | 
      
         | 1455 |  |  |  
 | 
      
         | 1456 |  |  |       Analyze_Dimension_Has_Etype (N);
 | 
      
         | 1457 |  |  |    end Analyze_Dimension_Function_Call;
 | 
      
         | 1458 |  |  |  
 | 
      
         | 1459 |  |  |    ---------------------------------
 | 
      
         | 1460 |  |  |    -- Analyze_Dimension_Has_Etype --
 | 
      
         | 1461 |  |  |    ---------------------------------
 | 
      
         | 1462 |  |  |  
 | 
      
         | 1463 |  |  |    procedure Analyze_Dimension_Has_Etype (N : Node_Id) is
 | 
      
         | 1464 |  |  |       Etyp         : constant Entity_Id := Etype (N);
 | 
      
         | 1465 |  |  |       Dims_Of_Etyp : constant Dimension_Type := Dimensions_Of (Etyp);
 | 
      
         | 1466 |  |  |  
 | 
      
         | 1467 |  |  |    begin
 | 
      
         | 1468 |  |  |       --  Propagation of the dimensions from the type
 | 
      
         | 1469 |  |  |  
 | 
      
         | 1470 |  |  |       if Exists (Dims_Of_Etyp) then
 | 
      
         | 1471 |  |  |          Set_Dimensions (N, Dims_Of_Etyp);
 | 
      
         | 1472 |  |  |       end if;
 | 
      
         | 1473 |  |  |  
 | 
      
         | 1474 |  |  |       --  Removal of dimensions in expression
 | 
      
         | 1475 |  |  |  
 | 
      
         | 1476 |  |  |       case Nkind (N) is
 | 
      
         | 1477 |  |  |  
 | 
      
         | 1478 |  |  |          when N_Attribute_Reference |
 | 
      
         | 1479 |  |  |               N_Indexed_Component   =>
 | 
      
         | 1480 |  |  |             declare
 | 
      
         | 1481 |  |  |                Expr  : Node_Id;
 | 
      
         | 1482 |  |  |                Exprs : constant List_Id := Expressions (N);
 | 
      
         | 1483 |  |  |  
 | 
      
         | 1484 |  |  |             begin
 | 
      
         | 1485 |  |  |                if Present (Exprs) then
 | 
      
         | 1486 |  |  |                   Expr := First (Exprs);
 | 
      
         | 1487 |  |  |                   while Present (Expr) loop
 | 
      
         | 1488 |  |  |                      Remove_Dimensions (Expr);
 | 
      
         | 1489 |  |  |                      Next (Expr);
 | 
      
         | 1490 |  |  |                   end loop;
 | 
      
         | 1491 |  |  |                end if;
 | 
      
         | 1492 |  |  |             end;
 | 
      
         | 1493 |  |  |  
 | 
      
         | 1494 |  |  |          when N_Qualified_Expression      |
 | 
      
         | 1495 |  |  |               N_Type_Conversion           |
 | 
      
         | 1496 |  |  |               N_Unchecked_Type_Conversion =>
 | 
      
         | 1497 |  |  |             Remove_Dimensions (Expression (N));
 | 
      
         | 1498 |  |  |  
 | 
      
         | 1499 |  |  |          when N_Selected_Component =>
 | 
      
         | 1500 |  |  |             Remove_Dimensions (Selector_Name (N));
 | 
      
         | 1501 |  |  |  
 | 
      
         | 1502 |  |  |          when others => null;
 | 
      
         | 1503 |  |  |  
 | 
      
         | 1504 |  |  |       end case;
 | 
      
         | 1505 |  |  |    end Analyze_Dimension_Has_Etype;
 | 
      
         | 1506 |  |  |  
 | 
      
         | 1507 |  |  |    ------------------------------------------
 | 
      
         | 1508 |  |  |    -- Analyze_Dimension_Object_Declaration --
 | 
      
         | 1509 |  |  |    ------------------------------------------
 | 
      
         | 1510 |  |  |  
 | 
      
         | 1511 |  |  |    procedure Analyze_Dimension_Object_Declaration (N : Node_Id) is
 | 
      
         | 1512 |  |  |       Expr        : constant Node_Id   := Expression (N);
 | 
      
         | 1513 |  |  |       Id          : constant Entity_Id := Defining_Identifier (N);
 | 
      
         | 1514 |  |  |       Etyp        : constant Entity_Id := Etype (Id);
 | 
      
         | 1515 |  |  |       Dim_Of_Etyp : constant Dimension_Type := Dimensions_Of (Etyp);
 | 
      
         | 1516 |  |  |       Dim_Of_Expr : Dimension_Type;
 | 
      
         | 1517 |  |  |  
 | 
      
         | 1518 |  |  |       procedure Error_Dim_Msg_For_Object_Declaration
 | 
      
         | 1519 |  |  |         (N    : Node_Id;
 | 
      
         | 1520 |  |  |          Etyp : Entity_Id;
 | 
      
         | 1521 |  |  |          Expr : Node_Id);
 | 
      
         | 1522 |  |  |       --  Error using Error_Msg_N at node N. Output the dimensions of the
 | 
      
         | 1523 |  |  |       --  type Etyp and of the expression Expr.
 | 
      
         | 1524 |  |  |  
 | 
      
         | 1525 |  |  |       ------------------------------------------
 | 
      
         | 1526 |  |  |       -- Error_Dim_Msg_For_Object_Declaration --
 | 
      
         | 1527 |  |  |       ------------------------------------------
 | 
      
         | 1528 |  |  |  
 | 
      
         | 1529 |  |  |       procedure Error_Dim_Msg_For_Object_Declaration
 | 
      
         | 1530 |  |  |         (N    : Node_Id;
 | 
      
         | 1531 |  |  |          Etyp : Entity_Id;
 | 
      
         | 1532 |  |  |          Expr : Node_Id) is
 | 
      
         | 1533 |  |  |       begin
 | 
      
         | 1534 |  |  |          Error_Msg_N ("dimensions mismatch in object declaration", N);
 | 
      
         | 1535 |  |  |          Error_Msg_N ("\object type " & Dimensions_Msg_Of (Etyp), N);
 | 
      
         | 1536 |  |  |          Error_Msg_N ("\object expression " & Dimensions_Msg_Of (Expr), N);
 | 
      
         | 1537 |  |  |       end Error_Dim_Msg_For_Object_Declaration;
 | 
      
         | 1538 |  |  |  
 | 
      
         | 1539 |  |  |    --  Start of processing for Analyze_Dimension_Object_Declaration
 | 
      
         | 1540 |  |  |  
 | 
      
         | 1541 |  |  |    begin
 | 
      
         | 1542 |  |  |       --  Expression is present
 | 
      
         | 1543 |  |  |  
 | 
      
         | 1544 |  |  |       if Present (Expr) then
 | 
      
         | 1545 |  |  |          Dim_Of_Expr := Dimensions_Of (Expr);
 | 
      
         | 1546 |  |  |  
 | 
      
         | 1547 |  |  |          --  case when expression is not a literal and when dimensions of the
 | 
      
         | 1548 |  |  |          --  expression and of the type mismatch
 | 
      
         | 1549 |  |  |  
 | 
      
         | 1550 |  |  |          if not Nkind_In (Original_Node (Expr),
 | 
      
         | 1551 |  |  |                              N_Real_Literal,
 | 
      
         | 1552 |  |  |                              N_Integer_Literal)
 | 
      
         | 1553 |  |  |            and then Dim_Of_Expr /= Dim_Of_Etyp
 | 
      
         | 1554 |  |  |          then
 | 
      
         | 1555 |  |  |             Error_Dim_Msg_For_Object_Declaration (N, Etyp, Expr);
 | 
      
         | 1556 |  |  |          end if;
 | 
      
         | 1557 |  |  |  
 | 
      
         | 1558 |  |  |          --  Removal of dimensions in expression
 | 
      
         | 1559 |  |  |  
 | 
      
         | 1560 |  |  |          Remove_Dimensions (Expr);
 | 
      
         | 1561 |  |  |       end if;
 | 
      
         | 1562 |  |  |    end Analyze_Dimension_Object_Declaration;
 | 
      
         | 1563 |  |  |  
 | 
      
         | 1564 |  |  |    ---------------------------------------------------
 | 
      
         | 1565 |  |  |    -- Analyze_Dimension_Object_Renaming_Declaration --
 | 
      
         | 1566 |  |  |    ---------------------------------------------------
 | 
      
         | 1567 |  |  |  
 | 
      
         | 1568 |  |  |    procedure Analyze_Dimension_Object_Renaming_Declaration (N : Node_Id) is
 | 
      
         | 1569 |  |  |       Renamed_Name : constant Node_Id := Name (N);
 | 
      
         | 1570 |  |  |       Sub_Mark     : constant Node_Id := Subtype_Mark (N);
 | 
      
         | 1571 |  |  |  
 | 
      
         | 1572 |  |  |       procedure Error_Dim_Msg_For_Object_Renaming_Declaration
 | 
      
         | 1573 |  |  |         (N            : Node_Id;
 | 
      
         | 1574 |  |  |          Sub_Mark     : Node_Id;
 | 
      
         | 1575 |  |  |          Renamed_Name : Node_Id);
 | 
      
         | 1576 |  |  |       --  Error using Error_Msg_N at node N. Output the dimensions of
 | 
      
         | 1577 |  |  |       --  Sub_Mark and of Renamed_Name.
 | 
      
         | 1578 |  |  |  
 | 
      
         | 1579 |  |  |       ---------------------------------------------------
 | 
      
         | 1580 |  |  |       -- Error_Dim_Msg_For_Object_Renaming_Declaration --
 | 
      
         | 1581 |  |  |       ---------------------------------------------------
 | 
      
         | 1582 |  |  |  
 | 
      
         | 1583 |  |  |       procedure Error_Dim_Msg_For_Object_Renaming_Declaration
 | 
      
         | 1584 |  |  |         (N            : Node_Id;
 | 
      
         | 1585 |  |  |          Sub_Mark     : Node_Id;
 | 
      
         | 1586 |  |  |          Renamed_Name : Node_Id) is
 | 
      
         | 1587 |  |  |       begin
 | 
      
         | 1588 |  |  |          Error_Msg_N ("dimensions mismatch in object renaming declaration",
 | 
      
         | 1589 |  |  |                       N);
 | 
      
         | 1590 |  |  |          Error_Msg_N ("\type " & Dimensions_Msg_Of (Sub_Mark), N);
 | 
      
         | 1591 |  |  |          Error_Msg_N ("\renamed object " & Dimensions_Msg_Of (Renamed_Name),
 | 
      
         | 1592 |  |  |                       N);
 | 
      
         | 1593 |  |  |       end Error_Dim_Msg_For_Object_Renaming_Declaration;
 | 
      
         | 1594 |  |  |  
 | 
      
         | 1595 |  |  |    --  Start of processing for Analyze_Dimension_Object_Renaming_Declaration
 | 
      
         | 1596 |  |  |  
 | 
      
         | 1597 |  |  |    begin
 | 
      
         | 1598 |  |  |       if Dimensions_Of (Renamed_Name) /= Dimensions_Of (Sub_Mark) then
 | 
      
         | 1599 |  |  |          Error_Dim_Msg_For_Object_Renaming_Declaration
 | 
      
         | 1600 |  |  |            (N, Sub_Mark, Renamed_Name);
 | 
      
         | 1601 |  |  |       end if;
 | 
      
         | 1602 |  |  |    end Analyze_Dimension_Object_Renaming_Declaration;
 | 
      
         | 1603 |  |  |  
 | 
      
         | 1604 |  |  |    -----------------------------------------------
 | 
      
         | 1605 |  |  |    -- Analyze_Dimension_Simple_Return_Statement --
 | 
      
         | 1606 |  |  |    -----------------------------------------------
 | 
      
         | 1607 |  |  |  
 | 
      
         | 1608 |  |  |    procedure Analyze_Dimension_Simple_Return_Statement (N : Node_Id) is
 | 
      
         | 1609 |  |  |       Expr                : constant Node_Id := Expression (N);
 | 
      
         | 1610 |  |  |       Dims_Of_Expr        : constant Dimension_Type := Dimensions_Of (Expr);
 | 
      
         | 1611 |  |  |       Return_Ent          : constant Entity_Id := Return_Statement_Entity (N);
 | 
      
         | 1612 |  |  |       Return_Etyp         : constant Entity_Id :=
 | 
      
         | 1613 |  |  |                               Etype (Return_Applies_To (Return_Ent));
 | 
      
         | 1614 |  |  |       Dims_Of_Return_Etyp : constant Dimension_Type :=
 | 
      
         | 1615 |  |  |                               Dimensions_Of (Return_Etyp);
 | 
      
         | 1616 |  |  |  
 | 
      
         | 1617 |  |  |       procedure Error_Dim_Msg_For_Simple_Return_Statement
 | 
      
         | 1618 |  |  |         (N           : Node_Id;
 | 
      
         | 1619 |  |  |          Return_Etyp : Entity_Id;
 | 
      
         | 1620 |  |  |          Expr        : Node_Id);
 | 
      
         | 1621 |  |  |       --  Error using Error_Msg_N at node N. Output the dimensions of the
 | 
      
         | 1622 |  |  |       --  returned type Return_Etyp and the returned expression Expr of N.
 | 
      
         | 1623 |  |  |  
 | 
      
         | 1624 |  |  |       -----------------------------------------------
 | 
      
         | 1625 |  |  |       -- Error_Dim_Msg_For_Simple_Return_Statement --
 | 
      
         | 1626 |  |  |       -----------------------------------------------
 | 
      
         | 1627 |  |  |  
 | 
      
         | 1628 |  |  |       procedure Error_Dim_Msg_For_Simple_Return_Statement
 | 
      
         | 1629 |  |  |         (N           : Node_Id;
 | 
      
         | 1630 |  |  |          Return_Etyp : Entity_Id;
 | 
      
         | 1631 |  |  |          Expr        : Node_Id)
 | 
      
         | 1632 |  |  |       is
 | 
      
         | 1633 |  |  |       begin
 | 
      
         | 1634 |  |  |          Error_Msg_N ("dimensions mismatch in return statement", N);
 | 
      
         | 1635 |  |  |          Error_Msg_N ("\returned type " & Dimensions_Msg_Of (Return_Etyp), N);
 | 
      
         | 1636 |  |  |          Error_Msg_N ("\returned expression " & Dimensions_Msg_Of (Expr), N);
 | 
      
         | 1637 |  |  |       end Error_Dim_Msg_For_Simple_Return_Statement;
 | 
      
         | 1638 |  |  |  
 | 
      
         | 1639 |  |  |    --  Start of processing for Analyze_Dimension_Simple_Return_Statement
 | 
      
         | 1640 |  |  |  
 | 
      
         | 1641 |  |  |    begin
 | 
      
         | 1642 |  |  |       if Dims_Of_Return_Etyp /= Dims_Of_Expr then
 | 
      
         | 1643 |  |  |          Error_Dim_Msg_For_Simple_Return_Statement (N, Return_Etyp, Expr);
 | 
      
         | 1644 |  |  |          Remove_Dimensions (Expr);
 | 
      
         | 1645 |  |  |       end if;
 | 
      
         | 1646 |  |  |    end Analyze_Dimension_Simple_Return_Statement;
 | 
      
         | 1647 |  |  |  
 | 
      
         | 1648 |  |  |    -------------------------------------------
 | 
      
         | 1649 |  |  |    -- Analyze_Dimension_Subtype_Declaration --
 | 
      
         | 1650 |  |  |    -------------------------------------------
 | 
      
         | 1651 |  |  |  
 | 
      
         | 1652 |  |  |    procedure Analyze_Dimension_Subtype_Declaration (N : Node_Id) is
 | 
      
         | 1653 |  |  |       Id           : constant Entity_Id := Defining_Identifier (N);
 | 
      
         | 1654 |  |  |       Dims_Of_Id   : constant Dimension_Type := Dimensions_Of (Id);
 | 
      
         | 1655 |  |  |       Dims_Of_Etyp : Dimension_Type;
 | 
      
         | 1656 |  |  |       Etyp         : Node_Id;
 | 
      
         | 1657 |  |  |  
 | 
      
         | 1658 |  |  |    begin
 | 
      
         | 1659 |  |  |       --  No constraint case in subtype declaration
 | 
      
         | 1660 |  |  |  
 | 
      
         | 1661 |  |  |       if Nkind (Subtype_Indication (N)) /= N_Subtype_Indication then
 | 
      
         | 1662 |  |  |          Etyp := Etype (Subtype_Indication (N));
 | 
      
         | 1663 |  |  |          Dims_Of_Etyp := Dimensions_Of (Etyp);
 | 
      
         | 1664 |  |  |  
 | 
      
         | 1665 |  |  |          if Exists (Dims_Of_Etyp) then
 | 
      
         | 1666 |  |  |  
 | 
      
         | 1667 |  |  |             --  If subtype already has a dimension (from Aspect_Dimension),
 | 
      
         | 1668 |  |  |             --  it cannot inherit a dimension from its subtype.
 | 
      
         | 1669 |  |  |  
 | 
      
         | 1670 |  |  |             if Exists (Dims_Of_Id) then
 | 
      
         | 1671 |  |  |                Error_Msg_N ("subtype& already" & Dimensions_Msg_Of (Id), N);
 | 
      
         | 1672 |  |  |             else
 | 
      
         | 1673 |  |  |                Set_Dimensions (Id, Dims_Of_Etyp);
 | 
      
         | 1674 |  |  |                Set_Symbol (Id, Symbol_Of (Etyp));
 | 
      
         | 1675 |  |  |             end if;
 | 
      
         | 1676 |  |  |          end if;
 | 
      
         | 1677 |  |  |  
 | 
      
         | 1678 |  |  |       --  Constraint present in subtype declaration
 | 
      
         | 1679 |  |  |  
 | 
      
         | 1680 |  |  |       else
 | 
      
         | 1681 |  |  |          Etyp := Etype (Subtype_Mark (Subtype_Indication (N)));
 | 
      
         | 1682 |  |  |          Dims_Of_Etyp := Dimensions_Of (Etyp);
 | 
      
         | 1683 |  |  |  
 | 
      
         | 1684 |  |  |          if Exists (Dims_Of_Etyp) then
 | 
      
         | 1685 |  |  |             Set_Dimensions (Id, Dims_Of_Etyp);
 | 
      
         | 1686 |  |  |             Set_Symbol (Id, Symbol_Of (Etyp));
 | 
      
         | 1687 |  |  |          end if;
 | 
      
         | 1688 |  |  |       end if;
 | 
      
         | 1689 |  |  |    end Analyze_Dimension_Subtype_Declaration;
 | 
      
         | 1690 |  |  |  
 | 
      
         | 1691 |  |  |    --------------------------------
 | 
      
         | 1692 |  |  |    -- Analyze_Dimension_Unary_Op --
 | 
      
         | 1693 |  |  |    --------------------------------
 | 
      
         | 1694 |  |  |  
 | 
      
         | 1695 |  |  |    procedure Analyze_Dimension_Unary_Op (N : Node_Id) is
 | 
      
         | 1696 |  |  |    begin
 | 
      
         | 1697 |  |  |       case Nkind (N) is
 | 
      
         | 1698 |  |  |          when N_Op_Plus | N_Op_Minus | N_Op_Abs =>
 | 
      
         | 1699 |  |  |             declare
 | 
      
         | 1700 |  |  |                R : constant Node_Id := Right_Opnd (N);
 | 
      
         | 1701 |  |  |  
 | 
      
         | 1702 |  |  |             begin
 | 
      
         | 1703 |  |  |                --  Propagate the dimension if the operand is not dimensionless
 | 
      
         | 1704 |  |  |  
 | 
      
         | 1705 |  |  |                Move_Dimensions (R, N);
 | 
      
         | 1706 |  |  |             end;
 | 
      
         | 1707 |  |  |  
 | 
      
         | 1708 |  |  |          when others => null;
 | 
      
         | 1709 |  |  |  
 | 
      
         | 1710 |  |  |       end case;
 | 
      
         | 1711 |  |  |    end Analyze_Dimension_Unary_Op;
 | 
      
         | 1712 |  |  |  
 | 
      
         | 1713 |  |  |    --------------------------
 | 
      
         | 1714 |  |  |    -- Create_Rational_From --
 | 
      
         | 1715 |  |  |    --------------------------
 | 
      
         | 1716 |  |  |  
 | 
      
         | 1717 |  |  |    --  RATIONAL ::= [-] NUMERAL [/ NUMERAL]
 | 
      
         | 1718 |  |  |  
 | 
      
         | 1719 |  |  |    --  A rational number is a number that can be expressed as the quotient or
 | 
      
         | 1720 |  |  |    --  fraction a/b of two integers, where b is non-zero positive.
 | 
      
         | 1721 |  |  |  
 | 
      
         | 1722 |  |  |    function Create_Rational_From
 | 
      
         | 1723 |  |  |      (Expr     : Node_Id;
 | 
      
         | 1724 |  |  |       Complain : Boolean) return Rational
 | 
      
         | 1725 |  |  |    is
 | 
      
         | 1726 |  |  |       Or_Node_Of_Expr : constant Node_Id := Original_Node (Expr);
 | 
      
         | 1727 |  |  |       Result          : Rational := No_Rational;
 | 
      
         | 1728 |  |  |  
 | 
      
         | 1729 |  |  |       function Process_Minus (N : Node_Id) return Rational;
 | 
      
         | 1730 |  |  |       --  Create a rational from a N_Op_Minus node
 | 
      
         | 1731 |  |  |  
 | 
      
         | 1732 |  |  |       function Process_Divide (N : Node_Id) return Rational;
 | 
      
         | 1733 |  |  |       --  Create a rational from a N_Op_Divide node
 | 
      
         | 1734 |  |  |  
 | 
      
         | 1735 |  |  |       function Process_Literal (N : Node_Id) return Rational;
 | 
      
         | 1736 |  |  |       --  Create a rational from a N_Integer_Literal node
 | 
      
         | 1737 |  |  |  
 | 
      
         | 1738 |  |  |       -------------------
 | 
      
         | 1739 |  |  |       -- Process_Minus --
 | 
      
         | 1740 |  |  |       -------------------
 | 
      
         | 1741 |  |  |  
 | 
      
         | 1742 |  |  |       function Process_Minus (N : Node_Id) return Rational is
 | 
      
         | 1743 |  |  |          Right  : constant Node_Id := Original_Node (Right_Opnd (N));
 | 
      
         | 1744 |  |  |          Result : Rational;
 | 
      
         | 1745 |  |  |  
 | 
      
         | 1746 |  |  |       begin
 | 
      
         | 1747 |  |  |          --  Operand is an integer literal
 | 
      
         | 1748 |  |  |  
 | 
      
         | 1749 |  |  |          if Nkind (Right) = N_Integer_Literal then
 | 
      
         | 1750 |  |  |             Result := -Process_Literal (Right);
 | 
      
         | 1751 |  |  |  
 | 
      
         | 1752 |  |  |          --  Operand is a divide operator
 | 
      
         | 1753 |  |  |  
 | 
      
         | 1754 |  |  |          elsif Nkind (Right) = N_Op_Divide then
 | 
      
         | 1755 |  |  |             Result := -Process_Divide (Right);
 | 
      
         | 1756 |  |  |  
 | 
      
         | 1757 |  |  |          else
 | 
      
         | 1758 |  |  |             Result := No_Rational;
 | 
      
         | 1759 |  |  |          end if;
 | 
      
         | 1760 |  |  |  
 | 
      
         | 1761 |  |  |          return Result;
 | 
      
         | 1762 |  |  |       end Process_Minus;
 | 
      
         | 1763 |  |  |  
 | 
      
         | 1764 |  |  |       --------------------
 | 
      
         | 1765 |  |  |       -- Process_Divide --
 | 
      
         | 1766 |  |  |       --------------------
 | 
      
         | 1767 |  |  |  
 | 
      
         | 1768 |  |  |       function Process_Divide (N : Node_Id) return Rational is
 | 
      
         | 1769 |  |  |          Left      : constant Node_Id := Original_Node (Left_Opnd (N));
 | 
      
         | 1770 |  |  |          Right     : constant Node_Id := Original_Node (Right_Opnd (N));
 | 
      
         | 1771 |  |  |          Left_Rat  : Rational;
 | 
      
         | 1772 |  |  |          Result    : Rational := No_Rational;
 | 
      
         | 1773 |  |  |          Right_Rat : Rational;
 | 
      
         | 1774 |  |  |  
 | 
      
         | 1775 |  |  |       begin
 | 
      
         | 1776 |  |  |          --  Both left and right operands are an integer literal
 | 
      
         | 1777 |  |  |  
 | 
      
         | 1778 |  |  |          if Nkind (Left) = N_Integer_Literal
 | 
      
         | 1779 |  |  |            and then Nkind (Right) = N_Integer_Literal
 | 
      
         | 1780 |  |  |          then
 | 
      
         | 1781 |  |  |             Left_Rat := Process_Literal (Left);
 | 
      
         | 1782 |  |  |             Right_Rat := Process_Literal (Right);
 | 
      
         | 1783 |  |  |             Result := Left_Rat / Right_Rat;
 | 
      
         | 1784 |  |  |          end if;
 | 
      
         | 1785 |  |  |  
 | 
      
         | 1786 |  |  |          return Result;
 | 
      
         | 1787 |  |  |       end Process_Divide;
 | 
      
         | 1788 |  |  |  
 | 
      
         | 1789 |  |  |       ---------------------
 | 
      
         | 1790 |  |  |       -- Process_Literal --
 | 
      
         | 1791 |  |  |       ---------------------
 | 
      
         | 1792 |  |  |  
 | 
      
         | 1793 |  |  |       function Process_Literal (N : Node_Id) return Rational is
 | 
      
         | 1794 |  |  |       begin
 | 
      
         | 1795 |  |  |          return +Whole (UI_To_Int (Intval (N)));
 | 
      
         | 1796 |  |  |       end Process_Literal;
 | 
      
         | 1797 |  |  |  
 | 
      
         | 1798 |  |  |    --  Start of processing for Create_Rational_From
 | 
      
         | 1799 |  |  |  
 | 
      
         | 1800 |  |  |    begin
 | 
      
         | 1801 |  |  |       --  Check the expression is either a division of two integers or an
 | 
      
         | 1802 |  |  |       --  integer itself. Note that the check applies to the original node
 | 
      
         | 1803 |  |  |       --  since the node could have already been rewritten.
 | 
      
         | 1804 |  |  |  
 | 
      
         | 1805 |  |  |       --  Integer literal case
 | 
      
         | 1806 |  |  |  
 | 
      
         | 1807 |  |  |       if Nkind (Or_Node_Of_Expr) = N_Integer_Literal then
 | 
      
         | 1808 |  |  |          Result := Process_Literal (Or_Node_Of_Expr);
 | 
      
         | 1809 |  |  |  
 | 
      
         | 1810 |  |  |       --  Divide operator case
 | 
      
         | 1811 |  |  |  
 | 
      
         | 1812 |  |  |       elsif Nkind (Or_Node_Of_Expr) = N_Op_Divide then
 | 
      
         | 1813 |  |  |          Result := Process_Divide (Or_Node_Of_Expr);
 | 
      
         | 1814 |  |  |  
 | 
      
         | 1815 |  |  |       --  Minus operator case
 | 
      
         | 1816 |  |  |  
 | 
      
         | 1817 |  |  |       elsif Nkind (Or_Node_Of_Expr) = N_Op_Minus then
 | 
      
         | 1818 |  |  |          Result := Process_Minus (Or_Node_Of_Expr);
 | 
      
         | 1819 |  |  |       end if;
 | 
      
         | 1820 |  |  |  
 | 
      
         | 1821 |  |  |       --  When Expr cannot be interpreted as a rational and Complain is true,
 | 
      
         | 1822 |  |  |       --  generate an error message.
 | 
      
         | 1823 |  |  |  
 | 
      
         | 1824 |  |  |       if Complain and then Result = No_Rational then
 | 
      
         | 1825 |  |  |          Error_Msg_N ("must be a rational", Expr);
 | 
      
         | 1826 |  |  |       end if;
 | 
      
         | 1827 |  |  |  
 | 
      
         | 1828 |  |  |       return Result;
 | 
      
         | 1829 |  |  |    end Create_Rational_From;
 | 
      
         | 1830 |  |  |  
 | 
      
         | 1831 |  |  |    -------------------
 | 
      
         | 1832 |  |  |    -- Dimensions_Of --
 | 
      
         | 1833 |  |  |    -------------------
 | 
      
         | 1834 |  |  |  
 | 
      
         | 1835 |  |  |    function Dimensions_Of (N : Node_Id) return Dimension_Type is
 | 
      
         | 1836 |  |  |    begin
 | 
      
         | 1837 |  |  |       return Dimension_Table.Get (N);
 | 
      
         | 1838 |  |  |    end Dimensions_Of;
 | 
      
         | 1839 |  |  |  
 | 
      
         | 1840 |  |  |    -----------------------
 | 
      
         | 1841 |  |  |    -- Dimensions_Msg_Of --
 | 
      
         | 1842 |  |  |    -----------------------
 | 
      
         | 1843 |  |  |  
 | 
      
         | 1844 |  |  |    function Dimensions_Msg_Of (N : Node_Id) return String is
 | 
      
         | 1845 |  |  |       Dims_Of_N      : constant Dimension_Type := Dimensions_Of (N);
 | 
      
         | 1846 |  |  |       Dimensions_Msg : Name_Id;
 | 
      
         | 1847 |  |  |       System         : System_Type;
 | 
      
         | 1848 |  |  |  
 | 
      
         | 1849 |  |  |       procedure Add_Dimension_Vector_To_Buffer
 | 
      
         | 1850 |  |  |         (Dims   : Dimension_Type;
 | 
      
         | 1851 |  |  |          System : System_Type);
 | 
      
         | 1852 |  |  |       --  Given a Dims and System, add to Name_Buffer the string representation
 | 
      
         | 1853 |  |  |       --  of a dimension vector.
 | 
      
         | 1854 |  |  |  
 | 
      
         | 1855 |  |  |       procedure Add_Whole_To_Buffer (W : Whole);
 | 
      
         | 1856 |  |  |       --  Add image of Whole to Name_Buffer
 | 
      
         | 1857 |  |  |  
 | 
      
         | 1858 |  |  |       ------------------------------------
 | 
      
         | 1859 |  |  |       -- Add_Dimension_Vector_To_Buffer --
 | 
      
         | 1860 |  |  |       ------------------------------------
 | 
      
         | 1861 |  |  |  
 | 
      
         | 1862 |  |  |       procedure Add_Dimension_Vector_To_Buffer
 | 
      
         | 1863 |  |  |         (Dims   : Dimension_Type;
 | 
      
         | 1864 |  |  |          System : System_Type)
 | 
      
         | 1865 |  |  |       is
 | 
      
         | 1866 |  |  |          Dim_Power : Rational;
 | 
      
         | 1867 |  |  |          First_Dim : Boolean := True;
 | 
      
         | 1868 |  |  |  
 | 
      
         | 1869 |  |  |       begin
 | 
      
         | 1870 |  |  |          Add_Char_To_Name_Buffer ('(');
 | 
      
         | 1871 |  |  |  
 | 
      
         | 1872 |  |  |          for Position in Dims_Of_N'First ..  System.Count loop
 | 
      
         | 1873 |  |  |             Dim_Power := Dims (Position);
 | 
      
         | 1874 |  |  |  
 | 
      
         | 1875 |  |  |             if First_Dim then
 | 
      
         | 1876 |  |  |                First_Dim := False;
 | 
      
         | 1877 |  |  |             else
 | 
      
         | 1878 |  |  |                Add_Str_To_Name_Buffer (", ");
 | 
      
         | 1879 |  |  |             end if;
 | 
      
         | 1880 |  |  |  
 | 
      
         | 1881 |  |  |             Add_Whole_To_Buffer (Dim_Power.Numerator);
 | 
      
         | 1882 |  |  |  
 | 
      
         | 1883 |  |  |             if Dim_Power.Denominator /= 1 then
 | 
      
         | 1884 |  |  |                Add_Char_To_Name_Buffer ('/');
 | 
      
         | 1885 |  |  |                Add_Whole_To_Buffer (Dim_Power.Denominator);
 | 
      
         | 1886 |  |  |             end if;
 | 
      
         | 1887 |  |  |          end loop;
 | 
      
         | 1888 |  |  |  
 | 
      
         | 1889 |  |  |          Add_Char_To_Name_Buffer (')');
 | 
      
         | 1890 |  |  |       end Add_Dimension_Vector_To_Buffer;
 | 
      
         | 1891 |  |  |  
 | 
      
         | 1892 |  |  |       -------------------------
 | 
      
         | 1893 |  |  |       -- Add_Whole_To_Buffer --
 | 
      
         | 1894 |  |  |       -------------------------
 | 
      
         | 1895 |  |  |  
 | 
      
         | 1896 |  |  |       procedure Add_Whole_To_Buffer (W : Whole) is
 | 
      
         | 1897 |  |  |       begin
 | 
      
         | 1898 |  |  |          UI_Image (UI_From_Int (Int (W)));
 | 
      
         | 1899 |  |  |          Add_Str_To_Name_Buffer (UI_Image_Buffer (1 .. UI_Image_Length));
 | 
      
         | 1900 |  |  |       end Add_Whole_To_Buffer;
 | 
      
         | 1901 |  |  |  
 | 
      
         | 1902 |  |  |    --  Start of processing for Dimensions_Msg_Of
 | 
      
         | 1903 |  |  |  
 | 
      
         | 1904 |  |  |    begin
 | 
      
         | 1905 |  |  |       --  Initialization of Name_Buffer
 | 
      
         | 1906 |  |  |  
 | 
      
         | 1907 |  |  |       Name_Len := 0;
 | 
      
         | 1908 |  |  |  
 | 
      
         | 1909 |  |  |       if Exists (Dims_Of_N) then
 | 
      
         | 1910 |  |  |          System := System_Of (Base_Type (Etype (N)));
 | 
      
         | 1911 |  |  |          Add_Str_To_Name_Buffer ("has dimensions ");
 | 
      
         | 1912 |  |  |          Add_Dimension_Vector_To_Buffer (Dims_Of_N, System);
 | 
      
         | 1913 |  |  |       else
 | 
      
         | 1914 |  |  |          Add_Str_To_Name_Buffer ("is dimensionless");
 | 
      
         | 1915 |  |  |       end if;
 | 
      
         | 1916 |  |  |  
 | 
      
         | 1917 |  |  |       Dimensions_Msg := Name_Find;
 | 
      
         | 1918 |  |  |       return Get_Name_String (Dimensions_Msg);
 | 
      
         | 1919 |  |  |    end Dimensions_Msg_Of;
 | 
      
         | 1920 |  |  |  
 | 
      
         | 1921 |  |  |    --------------------------
 | 
      
         | 1922 |  |  |    -- Dimension_Table_Hash --
 | 
      
         | 1923 |  |  |    --------------------------
 | 
      
         | 1924 |  |  |  
 | 
      
         | 1925 |  |  |    function Dimension_Table_Hash
 | 
      
         | 1926 |  |  |      (Key : Node_Id) return Dimension_Table_Range
 | 
      
         | 1927 |  |  |    is
 | 
      
         | 1928 |  |  |    begin
 | 
      
         | 1929 |  |  |       return Dimension_Table_Range (Key mod 511);
 | 
      
         | 1930 |  |  |    end Dimension_Table_Hash;
 | 
      
         | 1931 |  |  |  
 | 
      
         | 1932 |  |  |    ----------------------------------------
 | 
      
         | 1933 |  |  |    -- Eval_Op_Expon_For_Dimensioned_Type --
 | 
      
         | 1934 |  |  |    ----------------------------------------
 | 
      
         | 1935 |  |  |  
 | 
      
         | 1936 |  |  |    --  Evaluate the expon operator for real dimensioned type.
 | 
      
         | 1937 |  |  |  
 | 
      
         | 1938 |  |  |    --  Note that if the exponent is an integer (denominator = 1) the node is
 | 
      
         | 1939 |  |  |    --  evaluated by the regular Eval_Op_Expon routine (see Sem_Eval).
 | 
      
         | 1940 |  |  |  
 | 
      
         | 1941 |  |  |    procedure Eval_Op_Expon_For_Dimensioned_Type
 | 
      
         | 1942 |  |  |      (N    : Node_Id;
 | 
      
         | 1943 |  |  |       Btyp : Entity_Id)
 | 
      
         | 1944 |  |  |    is
 | 
      
         | 1945 |  |  |       R       : constant Node_Id := Right_Opnd (N);
 | 
      
         | 1946 |  |  |       R_Value : Rational := No_Rational;
 | 
      
         | 1947 |  |  |  
 | 
      
         | 1948 |  |  |    begin
 | 
      
         | 1949 |  |  |       if Is_Real_Type (Btyp) then
 | 
      
         | 1950 |  |  |          R_Value := Create_Rational_From (R, False);
 | 
      
         | 1951 |  |  |       end if;
 | 
      
         | 1952 |  |  |  
 | 
      
         | 1953 |  |  |       --  Check that the exponent is not an integer
 | 
      
         | 1954 |  |  |  
 | 
      
         | 1955 |  |  |       if R_Value /= No_Rational and then R_Value.Denominator /= 1 then
 | 
      
         | 1956 |  |  |          Eval_Op_Expon_With_Rational_Exponent (N, R_Value);
 | 
      
         | 1957 |  |  |       else
 | 
      
         | 1958 |  |  |          Eval_Op_Expon (N);
 | 
      
         | 1959 |  |  |       end if;
 | 
      
         | 1960 |  |  |    end Eval_Op_Expon_For_Dimensioned_Type;
 | 
      
         | 1961 |  |  |  
 | 
      
         | 1962 |  |  |    ------------------------------------------
 | 
      
         | 1963 |  |  |    -- Eval_Op_Expon_With_Rational_Exponent --
 | 
      
         | 1964 |  |  |    ------------------------------------------
 | 
      
         | 1965 |  |  |  
 | 
      
         | 1966 |  |  |    --  For dimensioned operand in exponentiation, exponent is allowed to be a
 | 
      
         | 1967 |  |  |    --  Rational and not only an Integer like for dimensionless operands. For
 | 
      
         | 1968 |  |  |    --  that particular case, the left operand is rewritten as a function call
 | 
      
         | 1969 |  |  |    --  using the function Expon_LLF from s-llflex.ads.
 | 
      
         | 1970 |  |  |  
 | 
      
         | 1971 |  |  |    procedure Eval_Op_Expon_With_Rational_Exponent
 | 
      
         | 1972 |  |  |      (N              : Node_Id;
 | 
      
         | 1973 |  |  |       Exponent_Value : Rational)
 | 
      
         | 1974 |  |  |    is
 | 
      
         | 1975 |  |  |       Dims_Of_N             : constant Dimension_Type := Dimensions_Of (N);
 | 
      
         | 1976 |  |  |       L                     : constant Node_Id := Left_Opnd (N);
 | 
      
         | 1977 |  |  |       Etyp_Of_L             : constant Entity_Id := Etype (L);
 | 
      
         | 1978 |  |  |       Btyp_Of_L             : constant Entity_Id := Base_Type (Etyp_Of_L);
 | 
      
         | 1979 |  |  |       Loc                   : constant Source_Ptr := Sloc (N);
 | 
      
         | 1980 |  |  |       Actual_1              : Node_Id;
 | 
      
         | 1981 |  |  |       Actual_2              : Node_Id;
 | 
      
         | 1982 |  |  |       Dim_Power             : Rational;
 | 
      
         | 1983 |  |  |       List_Of_Dims          : List_Id;
 | 
      
         | 1984 |  |  |       New_Aspect            : Node_Id;
 | 
      
         | 1985 |  |  |       New_Aspects           : List_Id;
 | 
      
         | 1986 |  |  |       New_Id                : Entity_Id;
 | 
      
         | 1987 |  |  |       New_N                 : Node_Id;
 | 
      
         | 1988 |  |  |       New_Subtyp_Decl_For_L : Node_Id;
 | 
      
         | 1989 |  |  |       System                : System_Type;
 | 
      
         | 1990 |  |  |  
 | 
      
         | 1991 |  |  |    begin
 | 
      
         | 1992 |  |  |       --  Case when the operand is not dimensionless
 | 
      
         | 1993 |  |  |  
 | 
      
         | 1994 |  |  |       if Exists (Dims_Of_N) then
 | 
      
         | 1995 |  |  |  
 | 
      
         | 1996 |  |  |          --  Get the corresponding System_Type to know the exact number of
 | 
      
         | 1997 |  |  |          --  dimensions in the system.
 | 
      
         | 1998 |  |  |  
 | 
      
         | 1999 |  |  |          System := System_Of (Btyp_Of_L);
 | 
      
         | 2000 |  |  |  
 | 
      
         | 2001 |  |  |          --  Generation of a new subtype with the proper dimensions
 | 
      
         | 2002 |  |  |  
 | 
      
         | 2003 |  |  |          --  In order to rewrite the operator as a type conversion, a new
 | 
      
         | 2004 |  |  |          --  dimensioned subtype with the resulting dimensions of the
 | 
      
         | 2005 |  |  |          --  exponentiation must be created.
 | 
      
         | 2006 |  |  |  
 | 
      
         | 2007 |  |  |          --  Generate:
 | 
      
         | 2008 |  |  |  
 | 
      
         | 2009 |  |  |          --  Btyp_Of_L   : constant Entity_Id := Base_Type (Etyp_Of_L);
 | 
      
         | 2010 |  |  |          --  System      : constant System_Id :=
 | 
      
         | 2011 |  |  |          --                  Get_Dimension_System_Id (Btyp_Of_L);
 | 
      
         | 2012 |  |  |          --  Num_Of_Dims : constant Number_Of_Dimensions :=
 | 
      
         | 2013 |  |  |          --                  Dimension_Systems.Table (System).Dimension_Count;
 | 
      
         | 2014 |  |  |  
 | 
      
         | 2015 |  |  |          --  subtype T is Btyp_Of_L
 | 
      
         | 2016 |  |  |          --    with
 | 
      
         | 2017 |  |  |          --      Dimension => ("",
 | 
      
         | 2018 |  |  |          --        Dims_Of_N (1).Numerator / Dims_Of_N (1).Denominator,
 | 
      
         | 2019 |  |  |          --        Dims_Of_N (2).Numerator / Dims_Of_N (2).Denominator,
 | 
      
         | 2020 |  |  |          --        ...
 | 
      
         | 2021 |  |  |          --        Dims_Of_N (Num_Of_Dims).Numerator /
 | 
      
         | 2022 |  |  |          --          Dims_Of_N (Num_Of_Dims).Denominator);
 | 
      
         | 2023 |  |  |  
 | 
      
         | 2024 |  |  |          --  Step 1: Generate the new aggregate for the aspect Dimension
 | 
      
         | 2025 |  |  |  
 | 
      
         | 2026 |  |  |          New_Aspects  := Empty_List;
 | 
      
         | 2027 |  |  |          List_Of_Dims := New_List;
 | 
      
         | 2028 |  |  |          Append (Make_String_Literal (Loc, ""), List_Of_Dims);
 | 
      
         | 2029 |  |  |  
 | 
      
         | 2030 |  |  |          for Position in Dims_Of_N'First ..  System.Count loop
 | 
      
         | 2031 |  |  |             Dim_Power := Dims_Of_N (Position);
 | 
      
         | 2032 |  |  |             Append_To (List_Of_Dims,
 | 
      
         | 2033 |  |  |                Make_Op_Divide (Loc,
 | 
      
         | 2034 |  |  |                  Left_Opnd  =>
 | 
      
         | 2035 |  |  |                    Make_Integer_Literal (Loc,
 | 
      
         | 2036 |  |  |                      Int (Dim_Power.Numerator)),
 | 
      
         | 2037 |  |  |                  Right_Opnd =>
 | 
      
         | 2038 |  |  |                    Make_Integer_Literal (Loc,
 | 
      
         | 2039 |  |  |                      Int (Dim_Power.Denominator))));
 | 
      
         | 2040 |  |  |          end loop;
 | 
      
         | 2041 |  |  |  
 | 
      
         | 2042 |  |  |          --  Step 2: Create the new Aspect Specification for Aspect Dimension
 | 
      
         | 2043 |  |  |  
 | 
      
         | 2044 |  |  |          New_Aspect :=
 | 
      
         | 2045 |  |  |            Make_Aspect_Specification (Loc,
 | 
      
         | 2046 |  |  |              Identifier => Make_Identifier (Loc, Name_Dimension),
 | 
      
         | 2047 |  |  |              Expression => Make_Aggregate (Loc, Expressions => List_Of_Dims));
 | 
      
         | 2048 |  |  |  
 | 
      
         | 2049 |  |  |          --  Step 3: Make a temporary identifier for the new subtype
 | 
      
         | 2050 |  |  |  
 | 
      
         | 2051 |  |  |          New_Id := Make_Temporary (Loc, 'T');
 | 
      
         | 2052 |  |  |          Set_Is_Internal (New_Id);
 | 
      
         | 2053 |  |  |  
 | 
      
         | 2054 |  |  |          --  Step 4: Declaration of the new subtype
 | 
      
         | 2055 |  |  |  
 | 
      
         | 2056 |  |  |          New_Subtyp_Decl_For_L :=
 | 
      
         | 2057 |  |  |             Make_Subtype_Declaration (Loc,
 | 
      
         | 2058 |  |  |                Defining_Identifier => New_Id,
 | 
      
         | 2059 |  |  |                Subtype_Indication  => New_Occurrence_Of (Btyp_Of_L, Loc));
 | 
      
         | 2060 |  |  |  
 | 
      
         | 2061 |  |  |          Append (New_Aspect, New_Aspects);
 | 
      
         | 2062 |  |  |          Set_Parent (New_Aspects, New_Subtyp_Decl_For_L);
 | 
      
         | 2063 |  |  |          Set_Aspect_Specifications (New_Subtyp_Decl_For_L, New_Aspects);
 | 
      
         | 2064 |  |  |  
 | 
      
         | 2065 |  |  |          Analyze (New_Subtyp_Decl_For_L);
 | 
      
         | 2066 |  |  |  
 | 
      
         | 2067 |  |  |       --  Case where the operand is dimensionless
 | 
      
         | 2068 |  |  |  
 | 
      
         | 2069 |  |  |       else
 | 
      
         | 2070 |  |  |          New_Id := Btyp_Of_L;
 | 
      
         | 2071 |  |  |       end if;
 | 
      
         | 2072 |  |  |  
 | 
      
         | 2073 |  |  |       --  Replacement of N by New_N
 | 
      
         | 2074 |  |  |  
 | 
      
         | 2075 |  |  |       --  Generate:
 | 
      
         | 2076 |  |  |  
 | 
      
         | 2077 |  |  |       --  Actual_1 := Long_Long_Float (L),
 | 
      
         | 2078 |  |  |  
 | 
      
         | 2079 |  |  |       --  Actual_2 := Long_Long_Float (Exponent_Value.Numerator) /
 | 
      
         | 2080 |  |  |       --                Long_Long_Float (Exponent_Value.Denominator);
 | 
      
         | 2081 |  |  |  
 | 
      
         | 2082 |  |  |       --  (T (Expon_LLF (Actual_1, Actual_2)));
 | 
      
         | 2083 |  |  |  
 | 
      
         | 2084 |  |  |       --  where T is the subtype declared in step 1
 | 
      
         | 2085 |  |  |  
 | 
      
         | 2086 |  |  |       --  The node is rewritten as a type conversion
 | 
      
         | 2087 |  |  |  
 | 
      
         | 2088 |  |  |       --  Step 1: Creation of the two parameters of Expon_LLF function call
 | 
      
         | 2089 |  |  |  
 | 
      
         | 2090 |  |  |       Actual_1 :=
 | 
      
         | 2091 |  |  |         Make_Type_Conversion (Loc,
 | 
      
         | 2092 |  |  |           Subtype_Mark => New_Reference_To (Standard_Long_Long_Float, Loc),
 | 
      
         | 2093 |  |  |           Expression   => Relocate_Node (L));
 | 
      
         | 2094 |  |  |  
 | 
      
         | 2095 |  |  |       Actual_2 :=
 | 
      
         | 2096 |  |  |         Make_Op_Divide (Loc,
 | 
      
         | 2097 |  |  |           Left_Opnd  =>
 | 
      
         | 2098 |  |  |             Make_Real_Literal (Loc,
 | 
      
         | 2099 |  |  |               UR_From_Uint (UI_From_Int (Int (Exponent_Value.Numerator)))),
 | 
      
         | 2100 |  |  |           Right_Opnd =>
 | 
      
         | 2101 |  |  |             Make_Real_Literal (Loc,
 | 
      
         | 2102 |  |  |               UR_From_Uint (UI_From_Int (Int (Exponent_Value.Denominator)))));
 | 
      
         | 2103 |  |  |  
 | 
      
         | 2104 |  |  |       --  Step 2: Creation of New_N
 | 
      
         | 2105 |  |  |  
 | 
      
         | 2106 |  |  |       New_N :=
 | 
      
         | 2107 |  |  |          Make_Type_Conversion (Loc,
 | 
      
         | 2108 |  |  |            Subtype_Mark => New_Reference_To (New_Id, Loc),
 | 
      
         | 2109 |  |  |            Expression =>
 | 
      
         | 2110 |  |  |              Make_Function_Call (Loc,
 | 
      
         | 2111 |  |  |                Name => New_Reference_To (RTE (RE_Expon_LLF), Loc),
 | 
      
         | 2112 |  |  |                Parameter_Associations => New_List (
 | 
      
         | 2113 |  |  |                  Actual_1, Actual_2)));
 | 
      
         | 2114 |  |  |  
 | 
      
         | 2115 |  |  |       --  Step 3: Rewrite N with the result
 | 
      
         | 2116 |  |  |  
 | 
      
         | 2117 |  |  |       Rewrite (N, New_N);
 | 
      
         | 2118 |  |  |       Set_Etype (N, New_Id);
 | 
      
         | 2119 |  |  |       Analyze_And_Resolve (N, New_Id);
 | 
      
         | 2120 |  |  |    end Eval_Op_Expon_With_Rational_Exponent;
 | 
      
         | 2121 |  |  |  
 | 
      
         | 2122 |  |  |    ------------
 | 
      
         | 2123 |  |  |    -- Exists --
 | 
      
         | 2124 |  |  |    ------------
 | 
      
         | 2125 |  |  |  
 | 
      
         | 2126 |  |  |    function Exists (Dim : Dimension_Type) return Boolean is
 | 
      
         | 2127 |  |  |    begin
 | 
      
         | 2128 |  |  |       return Dim /= Null_Dimension;
 | 
      
         | 2129 |  |  |    end Exists;
 | 
      
         | 2130 |  |  |  
 | 
      
         | 2131 |  |  |    function Exists (Sys : System_Type) return Boolean is
 | 
      
         | 2132 |  |  |    begin
 | 
      
         | 2133 |  |  |       return Sys /= Null_System;
 | 
      
         | 2134 |  |  |    end Exists;
 | 
      
         | 2135 |  |  |  
 | 
      
         | 2136 |  |  |    -------------------------------------------
 | 
      
         | 2137 |  |  |    -- Expand_Put_Call_With_Dimension_Symbol --
 | 
      
         | 2138 |  |  |    -------------------------------------------
 | 
      
         | 2139 |  |  |  
 | 
      
         | 2140 |  |  |    --  For procedure Put defined in System.Dim.Float_IO/System.Dim.Integer_IO,
 | 
      
         | 2141 |  |  |    --  the default string parameter must be rewritten to include the dimension
 | 
      
         | 2142 |  |  |    --  symbols in the output of a dimensioned object.
 | 
      
         | 2143 |  |  |  
 | 
      
         | 2144 |  |  |    --  Case 1: the parameter is a variable
 | 
      
         | 2145 |  |  |  
 | 
      
         | 2146 |  |  |    --  The default string parameter is replaced by the symbol defined in the
 | 
      
         | 2147 |  |  |    --  aspect Dimension of the subtype. For instance to output a speed:
 | 
      
         | 2148 |  |  |  
 | 
      
         | 2149 |  |  |    --  subtype Force is Mks_Type
 | 
      
         | 2150 |  |  |    --    with
 | 
      
         | 2151 |  |  |    --      Dimension => ("N",
 | 
      
         | 2152 |  |  |    --        Meter =>    1,
 | 
      
         | 2153 |  |  |    --        Kilogram => 1,
 | 
      
         | 2154 |  |  |    --        Second =>   -2,
 | 
      
         | 2155 |  |  |    --        others =>   0);
 | 
      
         | 2156 |  |  |    --  F : Force := 2.1 * m * kg * s**(-2);
 | 
      
         | 2157 |  |  |    --  Put (F);
 | 
      
         | 2158 |  |  |    --  > 2.1 N
 | 
      
         | 2159 |  |  |  
 | 
      
         | 2160 |  |  |    --  Case 2: the parameter is an expression
 | 
      
         | 2161 |  |  |  
 | 
      
         | 2162 |  |  |    --  In this case we call the procedure Expand_Put_Call_With_Dimension_Symbol
 | 
      
         | 2163 |  |  |    --  that creates the string of symbols (for instance "m.s**(-1)") and
 | 
      
         | 2164 |  |  |    --  rewrites the default string parameter of Put with the corresponding
 | 
      
         | 2165 |  |  |    --  the String_Id. For instance:
 | 
      
         | 2166 |  |  |  
 | 
      
         | 2167 |  |  |    --  Put (2.1 * m * kg * s**(-2));
 | 
      
         | 2168 |  |  |    --  > 2.1 m.kg.s**(-2)
 | 
      
         | 2169 |  |  |  
 | 
      
         | 2170 |  |  |    procedure Expand_Put_Call_With_Dimension_Symbol (N : Node_Id) is
 | 
      
         | 2171 |  |  |       Actuals        : constant List_Id := Parameter_Associations (N);
 | 
      
         | 2172 |  |  |       Loc            : constant Source_Ptr := Sloc (N);
 | 
      
         | 2173 |  |  |       Name_Call      : constant Node_Id := Name (N);
 | 
      
         | 2174 |  |  |       New_Actuals    : constant List_Id := New_List;
 | 
      
         | 2175 |  |  |       Actual         : Node_Id;
 | 
      
         | 2176 |  |  |       Dims_Of_Actual : Dimension_Type;
 | 
      
         | 2177 |  |  |       Etyp           : Entity_Id;
 | 
      
         | 2178 |  |  |       New_Str_Lit    : Node_Id := Empty;
 | 
      
         | 2179 |  |  |       System         : System_Type;
 | 
      
         | 2180 |  |  |  
 | 
      
         | 2181 |  |  |       function Has_Dimension_Symbols return Boolean;
 | 
      
         | 2182 |  |  |       --  Return True if the current Put call already has a parameter
 | 
      
         | 2183 |  |  |       --  association for parameter "Symbols" with the correct string of
 | 
      
         | 2184 |  |  |       --  symbols.
 | 
      
         | 2185 |  |  |  
 | 
      
         | 2186 |  |  |       function Is_Procedure_Put_Call return Boolean;
 | 
      
         | 2187 |  |  |       --  Return True if the current call is a call of an instantiation of a
 | 
      
         | 2188 |  |  |       --  procedure Put defined in the package System.Dim.Float_IO and
 | 
      
         | 2189 |  |  |       --  System.Dim.Integer_IO.
 | 
      
         | 2190 |  |  |  
 | 
      
         | 2191 |  |  |       function Item_Actual return Node_Id;
 | 
      
         | 2192 |  |  |       --  Return the item actual parameter node in the put call
 | 
      
         | 2193 |  |  |  
 | 
      
         | 2194 |  |  |       ---------------------------
 | 
      
         | 2195 |  |  |       -- Has_Dimension_Symbols --
 | 
      
         | 2196 |  |  |       ---------------------------
 | 
      
         | 2197 |  |  |  
 | 
      
         | 2198 |  |  |       function Has_Dimension_Symbols return Boolean is
 | 
      
         | 2199 |  |  |          Actual : Node_Id;
 | 
      
         | 2200 |  |  |  
 | 
      
         | 2201 |  |  |       begin
 | 
      
         | 2202 |  |  |          Actual := First (Actuals);
 | 
      
         | 2203 |  |  |  
 | 
      
         | 2204 |  |  |          --  Look for a symbols parameter association in the list of actuals
 | 
      
         | 2205 |  |  |  
 | 
      
         | 2206 |  |  |          while Present (Actual) loop
 | 
      
         | 2207 |  |  |             if Nkind (Actual) = N_Parameter_Association
 | 
      
         | 2208 |  |  |               and then Chars (Selector_Name (Actual)) = Name_Symbols
 | 
      
         | 2209 |  |  |             then
 | 
      
         | 2210 |  |  |  
 | 
      
         | 2211 |  |  |                --  return True if the actual comes from source or if the string
 | 
      
         | 2212 |  |  |                --  of symbols doesn't have the default value (i.e "").
 | 
      
         | 2213 |  |  |  
 | 
      
         | 2214 |  |  |                return Comes_From_Source (Actual)
 | 
      
         | 2215 |  |  |                         or else String_Length
 | 
      
         | 2216 |  |  |                                   (Strval
 | 
      
         | 2217 |  |  |                                     (Explicit_Actual_Parameter (Actual))) /= 0;
 | 
      
         | 2218 |  |  |             end if;
 | 
      
         | 2219 |  |  |  
 | 
      
         | 2220 |  |  |             Next (Actual);
 | 
      
         | 2221 |  |  |          end loop;
 | 
      
         | 2222 |  |  |  
 | 
      
         | 2223 |  |  |          --  At this point, the call has no parameter association
 | 
      
         | 2224 |  |  |          --  Look to the last actual since the symbols parameter is the last
 | 
      
         | 2225 |  |  |          --  one.
 | 
      
         | 2226 |  |  |  
 | 
      
         | 2227 |  |  |          return Nkind (Last (Actuals)) = N_String_Literal;
 | 
      
         | 2228 |  |  |       end Has_Dimension_Symbols;
 | 
      
         | 2229 |  |  |  
 | 
      
         | 2230 |  |  |       ---------------------------
 | 
      
         | 2231 |  |  |       -- Is_Procedure_Put_Call --
 | 
      
         | 2232 |  |  |       ---------------------------
 | 
      
         | 2233 |  |  |  
 | 
      
         | 2234 |  |  |       function Is_Procedure_Put_Call return Boolean is
 | 
      
         | 2235 |  |  |          Ent : Entity_Id;
 | 
      
         | 2236 |  |  |          Loc : Source_Ptr;
 | 
      
         | 2237 |  |  |  
 | 
      
         | 2238 |  |  |       begin
 | 
      
         | 2239 |  |  |          --  There are three different Put routines in each generic dim IO
 | 
      
         | 2240 |  |  |          --  package. Verify the current procedure call is one of them.
 | 
      
         | 2241 |  |  |  
 | 
      
         | 2242 |  |  |          if Is_Entity_Name (Name_Call) then
 | 
      
         | 2243 |  |  |             Ent := Entity (Name_Call);
 | 
      
         | 2244 |  |  |  
 | 
      
         | 2245 |  |  |             --  Get the original subprogram entity following the renaming chain
 | 
      
         | 2246 |  |  |  
 | 
      
         | 2247 |  |  |             if Present (Alias (Ent)) then
 | 
      
         | 2248 |  |  |                Ent := Alias (Ent);
 | 
      
         | 2249 |  |  |             end if;
 | 
      
         | 2250 |  |  |  
 | 
      
         | 2251 |  |  |             Loc := Sloc (Ent);
 | 
      
         | 2252 |  |  |  
 | 
      
         | 2253 |  |  |             --  Check the name of the entity subprogram is Put and verify this
 | 
      
         | 2254 |  |  |             --  entity is located in either System.Dim.Float_IO or
 | 
      
         | 2255 |  |  |             --  System.Dim.Integer_IO.
 | 
      
         | 2256 |  |  |  
 | 
      
         | 2257 |  |  |             return Chars (Ent) = Name_Put
 | 
      
         | 2258 |  |  |               and then Loc > No_Location
 | 
      
         | 2259 |  |  |               and then Is_Dim_IO_Package_Entity
 | 
      
         | 2260 |  |  |                          (Cunit_Entity (Get_Source_Unit (Loc)));
 | 
      
         | 2261 |  |  |          end if;
 | 
      
         | 2262 |  |  |  
 | 
      
         | 2263 |  |  |          return False;
 | 
      
         | 2264 |  |  |       end Is_Procedure_Put_Call;
 | 
      
         | 2265 |  |  |  
 | 
      
         | 2266 |  |  |       -----------------
 | 
      
         | 2267 |  |  |       -- Item_Actual --
 | 
      
         | 2268 |  |  |       -----------------
 | 
      
         | 2269 |  |  |  
 | 
      
         | 2270 |  |  |       function Item_Actual return Node_Id is
 | 
      
         | 2271 |  |  |          Actual : Node_Id;
 | 
      
         | 2272 |  |  |  
 | 
      
         | 2273 |  |  |       begin
 | 
      
         | 2274 |  |  |          --  Look for the item actual as a parameter association
 | 
      
         | 2275 |  |  |  
 | 
      
         | 2276 |  |  |          Actual := First (Actuals);
 | 
      
         | 2277 |  |  |          while Present (Actual) loop
 | 
      
         | 2278 |  |  |             if Nkind (Actual) = N_Parameter_Association
 | 
      
         | 2279 |  |  |               and then Chars (Selector_Name (Actual)) = Name_Item
 | 
      
         | 2280 |  |  |             then
 | 
      
         | 2281 |  |  |                return Explicit_Actual_Parameter (Actual);
 | 
      
         | 2282 |  |  |             end if;
 | 
      
         | 2283 |  |  |  
 | 
      
         | 2284 |  |  |             Next (Actual);
 | 
      
         | 2285 |  |  |          end loop;
 | 
      
         | 2286 |  |  |  
 | 
      
         | 2287 |  |  |          --  Case where the item has been defined without an association
 | 
      
         | 2288 |  |  |  
 | 
      
         | 2289 |  |  |          Actual := First (Actuals);
 | 
      
         | 2290 |  |  |  
 | 
      
         | 2291 |  |  |          --  Depending on the procedure Put, Item actual could be first or
 | 
      
         | 2292 |  |  |          --  second in the list of actuals.
 | 
      
         | 2293 |  |  |  
 | 
      
         | 2294 |  |  |          if Has_Dimension_System (Base_Type (Etype (Actual))) then
 | 
      
         | 2295 |  |  |             return Actual;
 | 
      
         | 2296 |  |  |          else
 | 
      
         | 2297 |  |  |             return Next (Actual);
 | 
      
         | 2298 |  |  |          end if;
 | 
      
         | 2299 |  |  |       end Item_Actual;
 | 
      
         | 2300 |  |  |  
 | 
      
         | 2301 |  |  |    --  Start of processing for Expand_Put_Call_With_Dimension_Symbol
 | 
      
         | 2302 |  |  |  
 | 
      
         | 2303 |  |  |    begin
 | 
      
         | 2304 |  |  |       if Is_Procedure_Put_Call and then not Has_Dimension_Symbols then
 | 
      
         | 2305 |  |  |          Actual := Item_Actual;
 | 
      
         | 2306 |  |  |          Dims_Of_Actual := Dimensions_Of (Actual);
 | 
      
         | 2307 |  |  |          Etyp := Etype (Actual);
 | 
      
         | 2308 |  |  |  
 | 
      
         | 2309 |  |  |          --  Add the symbol as a suffix of the value if the subtype has a
 | 
      
         | 2310 |  |  |          --  dimension symbol or if the parameter is not dimensionless.
 | 
      
         | 2311 |  |  |  
 | 
      
         | 2312 |  |  |          if Symbol_Of (Etyp) /= No_String then
 | 
      
         | 2313 |  |  |             Start_String;
 | 
      
         | 2314 |  |  |  
 | 
      
         | 2315 |  |  |             --  Put a space between the value and the dimension
 | 
      
         | 2316 |  |  |  
 | 
      
         | 2317 |  |  |             Store_String_Char (' ');
 | 
      
         | 2318 |  |  |             Store_String_Chars (Symbol_Of (Etyp));
 | 
      
         | 2319 |  |  |             New_Str_Lit := Make_String_Literal (Loc, End_String);
 | 
      
         | 2320 |  |  |  
 | 
      
         | 2321 |  |  |          --  Check that the item is not dimensionless
 | 
      
         | 2322 |  |  |  
 | 
      
         | 2323 |  |  |          --  Create the new String_Literal with the new String_Id generated by
 | 
      
         | 2324 |  |  |          --  the routine From_Dimension_To_String.
 | 
      
         | 2325 |  |  |  
 | 
      
         | 2326 |  |  |          elsif Exists (Dims_Of_Actual) then
 | 
      
         | 2327 |  |  |             System := System_Of (Base_Type (Etyp));
 | 
      
         | 2328 |  |  |             New_Str_Lit :=
 | 
      
         | 2329 |  |  |               Make_String_Literal (Loc,
 | 
      
         | 2330 |  |  |                 From_Dimension_To_String_Of_Symbols (Dims_Of_Actual, System));
 | 
      
         | 2331 |  |  |          end if;
 | 
      
         | 2332 |  |  |  
 | 
      
         | 2333 |  |  |          if Present (New_Str_Lit) then
 | 
      
         | 2334 |  |  |  
 | 
      
         | 2335 |  |  |             --  Insert all actuals in New_Actuals
 | 
      
         | 2336 |  |  |  
 | 
      
         | 2337 |  |  |             Actual := First (Actuals);
 | 
      
         | 2338 |  |  |             while Present (Actual) loop
 | 
      
         | 2339 |  |  |  
 | 
      
         | 2340 |  |  |                --  Copy every actuals in New_Actuals except the Symbols
 | 
      
         | 2341 |  |  |                --  parameter association.
 | 
      
         | 2342 |  |  |  
 | 
      
         | 2343 |  |  |                if Nkind (Actual) = N_Parameter_Association
 | 
      
         | 2344 |  |  |                  and then Chars (Selector_Name (Actual)) /= Name_Symbols
 | 
      
         | 2345 |  |  |                then
 | 
      
         | 2346 |  |  |                   Append_To (New_Actuals,
 | 
      
         | 2347 |  |  |                      Make_Parameter_Association (Loc,
 | 
      
         | 2348 |  |  |                         Selector_Name => New_Copy (Selector_Name (Actual)),
 | 
      
         | 2349 |  |  |                         Explicit_Actual_Parameter =>
 | 
      
         | 2350 |  |  |                            New_Copy (Explicit_Actual_Parameter (Actual))));
 | 
      
         | 2351 |  |  |  
 | 
      
         | 2352 |  |  |                elsif Nkind (Actual) /= N_Parameter_Association then
 | 
      
         | 2353 |  |  |                   Append_To (New_Actuals, New_Copy (Actual));
 | 
      
         | 2354 |  |  |                end if;
 | 
      
         | 2355 |  |  |  
 | 
      
         | 2356 |  |  |                Next (Actual);
 | 
      
         | 2357 |  |  |             end loop;
 | 
      
         | 2358 |  |  |  
 | 
      
         | 2359 |  |  |             --  Create new Symbols param association and append to New_Actuals
 | 
      
         | 2360 |  |  |  
 | 
      
         | 2361 |  |  |             Append_To (New_Actuals,
 | 
      
         | 2362 |  |  |               Make_Parameter_Association (Loc,
 | 
      
         | 2363 |  |  |                 Selector_Name => Make_Identifier (Loc, Name_Symbols),
 | 
      
         | 2364 |  |  |                 Explicit_Actual_Parameter => New_Str_Lit));
 | 
      
         | 2365 |  |  |  
 | 
      
         | 2366 |  |  |             --  Rewrite and analyze the procedure call
 | 
      
         | 2367 |  |  |  
 | 
      
         | 2368 |  |  |             Rewrite (N,
 | 
      
         | 2369 |  |  |               Make_Procedure_Call_Statement (Loc,
 | 
      
         | 2370 |  |  |                 Name =>                   New_Copy (Name_Call),
 | 
      
         | 2371 |  |  |                 Parameter_Associations => New_Actuals));
 | 
      
         | 2372 |  |  |  
 | 
      
         | 2373 |  |  |             Analyze (N);
 | 
      
         | 2374 |  |  |          end if;
 | 
      
         | 2375 |  |  |       end if;
 | 
      
         | 2376 |  |  |    end Expand_Put_Call_With_Dimension_Symbol;
 | 
      
         | 2377 |  |  |  
 | 
      
         | 2378 |  |  |    -----------------------------------------
 | 
      
         | 2379 |  |  |    -- From_Dimension_To_String_Of_Symbols --
 | 
      
         | 2380 |  |  |    -----------------------------------------
 | 
      
         | 2381 |  |  |  
 | 
      
         | 2382 |  |  |    --  Given a dimension vector and the corresponding dimension system,
 | 
      
         | 2383 |  |  |    --  create a String_Id to output the dimension symbols corresponding to
 | 
      
         | 2384 |  |  |    --  the dimensions Dims.
 | 
      
         | 2385 |  |  |  
 | 
      
         | 2386 |  |  |    function From_Dimension_To_String_Of_Symbols
 | 
      
         | 2387 |  |  |      (Dims   : Dimension_Type;
 | 
      
         | 2388 |  |  |       System : System_Type) return String_Id
 | 
      
         | 2389 |  |  |    is
 | 
      
         | 2390 |  |  |       Dimension_Power     : Rational;
 | 
      
         | 2391 |  |  |       First_Symbol_In_Str : Boolean := True;
 | 
      
         | 2392 |  |  |  
 | 
      
         | 2393 |  |  |    begin
 | 
      
         | 2394 |  |  |       --  Initialization of the new String_Id
 | 
      
         | 2395 |  |  |  
 | 
      
         | 2396 |  |  |       Start_String;
 | 
      
         | 2397 |  |  |  
 | 
      
         | 2398 |  |  |       --  Put a space between the value and the symbols
 | 
      
         | 2399 |  |  |  
 | 
      
         | 2400 |  |  |       Store_String_Char (' ');
 | 
      
         | 2401 |  |  |  
 | 
      
         | 2402 |  |  |       for Position in Dimension_Type'Range loop
 | 
      
         | 2403 |  |  |          Dimension_Power := Dims (Position);
 | 
      
         | 2404 |  |  |          if Dimension_Power /= Zero then
 | 
      
         | 2405 |  |  |  
 | 
      
         | 2406 |  |  |             if First_Symbol_In_Str then
 | 
      
         | 2407 |  |  |                First_Symbol_In_Str := False;
 | 
      
         | 2408 |  |  |             else
 | 
      
         | 2409 |  |  |                Store_String_Char ('.');
 | 
      
         | 2410 |  |  |             end if;
 | 
      
         | 2411 |  |  |  
 | 
      
         | 2412 |  |  |             --  Positive dimension case
 | 
      
         | 2413 |  |  |  
 | 
      
         | 2414 |  |  |             if Dimension_Power.Numerator > 0 then
 | 
      
         | 2415 |  |  |                if System.Symbols (Position) = No_String then
 | 
      
         | 2416 |  |  |                   Store_String_Chars
 | 
      
         | 2417 |  |  |                     (Get_Name_String (System.Names (Position)));
 | 
      
         | 2418 |  |  |                else
 | 
      
         | 2419 |  |  |                   Store_String_Chars (System.Symbols (Position));
 | 
      
         | 2420 |  |  |                end if;
 | 
      
         | 2421 |  |  |  
 | 
      
         | 2422 |  |  |                --  Integer case
 | 
      
         | 2423 |  |  |  
 | 
      
         | 2424 |  |  |                if Dimension_Power.Denominator = 1 then
 | 
      
         | 2425 |  |  |                   if Dimension_Power.Numerator /= 1 then
 | 
      
         | 2426 |  |  |                      Store_String_Chars ("**");
 | 
      
         | 2427 |  |  |                      Store_String_Int (Int (Dimension_Power.Numerator));
 | 
      
         | 2428 |  |  |                   end if;
 | 
      
         | 2429 |  |  |  
 | 
      
         | 2430 |  |  |                --  Rational case when denominator /= 1
 | 
      
         | 2431 |  |  |  
 | 
      
         | 2432 |  |  |                else
 | 
      
         | 2433 |  |  |                   Store_String_Chars ("**");
 | 
      
         | 2434 |  |  |                   Store_String_Char ('(');
 | 
      
         | 2435 |  |  |                   Store_String_Int (Int (Dimension_Power.Numerator));
 | 
      
         | 2436 |  |  |                   Store_String_Char ('/');
 | 
      
         | 2437 |  |  |                   Store_String_Int (Int (Dimension_Power.Denominator));
 | 
      
         | 2438 |  |  |                   Store_String_Char (')');
 | 
      
         | 2439 |  |  |                end if;
 | 
      
         | 2440 |  |  |  
 | 
      
         | 2441 |  |  |             --  Negative dimension case
 | 
      
         | 2442 |  |  |  
 | 
      
         | 2443 |  |  |             else
 | 
      
         | 2444 |  |  |                if System.Symbols (Position) = No_String then
 | 
      
         | 2445 |  |  |                   Store_String_Chars
 | 
      
         | 2446 |  |  |                     (Get_Name_String (System.Names (Position)));
 | 
      
         | 2447 |  |  |                else
 | 
      
         | 2448 |  |  |                   Store_String_Chars (System.Symbols (Position));
 | 
      
         | 2449 |  |  |                end if;
 | 
      
         | 2450 |  |  |  
 | 
      
         | 2451 |  |  |                Store_String_Chars ("**");
 | 
      
         | 2452 |  |  |                Store_String_Char ('(');
 | 
      
         | 2453 |  |  |                Store_String_Char ('-');
 | 
      
         | 2454 |  |  |                Store_String_Int (Int (-Dimension_Power.Numerator));
 | 
      
         | 2455 |  |  |  
 | 
      
         | 2456 |  |  |                --  Integer case
 | 
      
         | 2457 |  |  |  
 | 
      
         | 2458 |  |  |                if Dimension_Power.Denominator = 1 then
 | 
      
         | 2459 |  |  |                   Store_String_Char (')');
 | 
      
         | 2460 |  |  |  
 | 
      
         | 2461 |  |  |                --  Rational case when denominator /= 1
 | 
      
         | 2462 |  |  |  
 | 
      
         | 2463 |  |  |                else
 | 
      
         | 2464 |  |  |                   Store_String_Char ('/');
 | 
      
         | 2465 |  |  |                   Store_String_Int (Int (Dimension_Power.Denominator));
 | 
      
         | 2466 |  |  |                   Store_String_Char (')');
 | 
      
         | 2467 |  |  |                end if;
 | 
      
         | 2468 |  |  |             end if;
 | 
      
         | 2469 |  |  |          end if;
 | 
      
         | 2470 |  |  |       end loop;
 | 
      
         | 2471 |  |  |  
 | 
      
         | 2472 |  |  |       return End_String;
 | 
      
         | 2473 |  |  |    end From_Dimension_To_String_Of_Symbols;
 | 
      
         | 2474 |  |  |  
 | 
      
         | 2475 |  |  |    ---------
 | 
      
         | 2476 |  |  |    -- GCD --
 | 
      
         | 2477 |  |  |    ---------
 | 
      
         | 2478 |  |  |  
 | 
      
         | 2479 |  |  |    function GCD (Left, Right : Whole) return Int is
 | 
      
         | 2480 |  |  |       L : Whole;
 | 
      
         | 2481 |  |  |       R : Whole;
 | 
      
         | 2482 |  |  |  
 | 
      
         | 2483 |  |  |    begin
 | 
      
         | 2484 |  |  |       L := Left;
 | 
      
         | 2485 |  |  |       R := Right;
 | 
      
         | 2486 |  |  |       while R /= 0 loop
 | 
      
         | 2487 |  |  |          L := L mod R;
 | 
      
         | 2488 |  |  |  
 | 
      
         | 2489 |  |  |          if L = 0 then
 | 
      
         | 2490 |  |  |             return Int (R);
 | 
      
         | 2491 |  |  |          end if;
 | 
      
         | 2492 |  |  |  
 | 
      
         | 2493 |  |  |          R := R mod L;
 | 
      
         | 2494 |  |  |       end loop;
 | 
      
         | 2495 |  |  |  
 | 
      
         | 2496 |  |  |       return Int (L);
 | 
      
         | 2497 |  |  |    end GCD;
 | 
      
         | 2498 |  |  |  
 | 
      
         | 2499 |  |  |    --------------------------
 | 
      
         | 2500 |  |  |    -- Has_Dimension_System --
 | 
      
         | 2501 |  |  |    --------------------------
 | 
      
         | 2502 |  |  |  
 | 
      
         | 2503 |  |  |    function Has_Dimension_System (Typ : Entity_Id) return Boolean is
 | 
      
         | 2504 |  |  |    begin
 | 
      
         | 2505 |  |  |       return Exists (System_Of (Typ));
 | 
      
         | 2506 |  |  |    end Has_Dimension_System;
 | 
      
         | 2507 |  |  |  
 | 
      
         | 2508 |  |  |    ------------------------------
 | 
      
         | 2509 |  |  |    -- Is_Dim_IO_Package_Entity --
 | 
      
         | 2510 |  |  |    ------------------------------
 | 
      
         | 2511 |  |  |  
 | 
      
         | 2512 |  |  |    function Is_Dim_IO_Package_Entity (E : Entity_Id) return Boolean is
 | 
      
         | 2513 |  |  |    begin
 | 
      
         | 2514 |  |  |       --  Check the package entity corresponds to System.Dim.Float_IO or
 | 
      
         | 2515 |  |  |       --  System.Dim.Integer_IO.
 | 
      
         | 2516 |  |  |  
 | 
      
         | 2517 |  |  |       return
 | 
      
         | 2518 |  |  |         Is_RTU (E, System_Dim_Float_IO)
 | 
      
         | 2519 |  |  |           or Is_RTU (E, System_Dim_Integer_IO);
 | 
      
         | 2520 |  |  |    end Is_Dim_IO_Package_Entity;
 | 
      
         | 2521 |  |  |  
 | 
      
         | 2522 |  |  |    -------------------------------------
 | 
      
         | 2523 |  |  |    -- Is_Dim_IO_Package_Instantiation --
 | 
      
         | 2524 |  |  |    -------------------------------------
 | 
      
         | 2525 |  |  |  
 | 
      
         | 2526 |  |  |    function Is_Dim_IO_Package_Instantiation (N : Node_Id) return Boolean is
 | 
      
         | 2527 |  |  |       Gen_Id : constant Node_Id := Name (N);
 | 
      
         | 2528 |  |  |  
 | 
      
         | 2529 |  |  |    begin
 | 
      
         | 2530 |  |  |       --  Check that the instantiated package is either System.Dim.Float_IO
 | 
      
         | 2531 |  |  |       --  or System.Dim.Integer_IO.
 | 
      
         | 2532 |  |  |  
 | 
      
         | 2533 |  |  |       return
 | 
      
         | 2534 |  |  |         Is_Entity_Name (Gen_Id)
 | 
      
         | 2535 |  |  |           and then Is_Dim_IO_Package_Entity (Entity (Gen_Id));
 | 
      
         | 2536 |  |  |    end Is_Dim_IO_Package_Instantiation;
 | 
      
         | 2537 |  |  |  
 | 
      
         | 2538 |  |  |    ----------------
 | 
      
         | 2539 |  |  |    -- Is_Invalid --
 | 
      
         | 2540 |  |  |    ----------------
 | 
      
         | 2541 |  |  |  
 | 
      
         | 2542 |  |  |    function Is_Invalid (Position : Dimension_Position) return Boolean is
 | 
      
         | 2543 |  |  |    begin
 | 
      
         | 2544 |  |  |       return Position = Invalid_Position;
 | 
      
         | 2545 |  |  |    end Is_Invalid;
 | 
      
         | 2546 |  |  |  
 | 
      
         | 2547 |  |  |    ---------------------
 | 
      
         | 2548 |  |  |    -- Move_Dimensions --
 | 
      
         | 2549 |  |  |    ---------------------
 | 
      
         | 2550 |  |  |  
 | 
      
         | 2551 |  |  |    procedure Move_Dimensions (From, To : Node_Id) is
 | 
      
         | 2552 |  |  |       Dims_Of_From : constant Dimension_Type := Dimensions_Of (From);
 | 
      
         | 2553 |  |  |  
 | 
      
         | 2554 |  |  |    begin
 | 
      
         | 2555 |  |  |       --  Copy the dimension of 'From to 'To' and remove dimension of 'From'
 | 
      
         | 2556 |  |  |  
 | 
      
         | 2557 |  |  |       if Exists (Dims_Of_From) then
 | 
      
         | 2558 |  |  |          Set_Dimensions (To, Dims_Of_From);
 | 
      
         | 2559 |  |  |          Remove_Dimensions (From);
 | 
      
         | 2560 |  |  |       end if;
 | 
      
         | 2561 |  |  |    end Move_Dimensions;
 | 
      
         | 2562 |  |  |  
 | 
      
         | 2563 |  |  |    ------------
 | 
      
         | 2564 |  |  |    -- Reduce --
 | 
      
         | 2565 |  |  |    ------------
 | 
      
         | 2566 |  |  |  
 | 
      
         | 2567 |  |  |    function Reduce (X : Rational) return Rational is
 | 
      
         | 2568 |  |  |    begin
 | 
      
         | 2569 |  |  |       if X.Numerator = 0 then
 | 
      
         | 2570 |  |  |          return Zero;
 | 
      
         | 2571 |  |  |       end if;
 | 
      
         | 2572 |  |  |  
 | 
      
         | 2573 |  |  |       declare
 | 
      
         | 2574 |  |  |          G : constant Int := GCD (X.Numerator, X.Denominator);
 | 
      
         | 2575 |  |  |       begin
 | 
      
         | 2576 |  |  |          return Rational'(Numerator =>   Whole (Int (X.Numerator) / G),
 | 
      
         | 2577 |  |  |                           Denominator => Whole (Int (X.Denominator) / G));
 | 
      
         | 2578 |  |  |       end;
 | 
      
         | 2579 |  |  |    end Reduce;
 | 
      
         | 2580 |  |  |  
 | 
      
         | 2581 |  |  |    -----------------------
 | 
      
         | 2582 |  |  |    -- Remove_Dimensions --
 | 
      
         | 2583 |  |  |    -----------------------
 | 
      
         | 2584 |  |  |  
 | 
      
         | 2585 |  |  |    procedure Remove_Dimensions (N : Node_Id) is
 | 
      
         | 2586 |  |  |       Dims_Of_N : constant Dimension_Type := Dimensions_Of (N);
 | 
      
         | 2587 |  |  |    begin
 | 
      
         | 2588 |  |  |       if Exists (Dims_Of_N) then
 | 
      
         | 2589 |  |  |          Dimension_Table.Remove (N);
 | 
      
         | 2590 |  |  |       end if;
 | 
      
         | 2591 |  |  |    end Remove_Dimensions;
 | 
      
         | 2592 |  |  |  
 | 
      
         | 2593 |  |  |    ------------------------------
 | 
      
         | 2594 |  |  |    -- Remove_Dimension_In_Call --
 | 
      
         | 2595 |  |  |    ------------------------------
 | 
      
         | 2596 |  |  |  
 | 
      
         | 2597 |  |  |    procedure Remove_Dimension_In_Call (Call : Node_Id) is
 | 
      
         | 2598 |  |  |       Actual : Node_Id;
 | 
      
         | 2599 |  |  |  
 | 
      
         | 2600 |  |  |    begin
 | 
      
         | 2601 |  |  |       if Ada_Version < Ada_2012 then
 | 
      
         | 2602 |  |  |          return;
 | 
      
         | 2603 |  |  |       end if;
 | 
      
         | 2604 |  |  |  
 | 
      
         | 2605 |  |  |       Actual := First (Parameter_Associations (Call));
 | 
      
         | 2606 |  |  |  
 | 
      
         | 2607 |  |  |       while Present (Actual) loop
 | 
      
         | 2608 |  |  |          Remove_Dimensions (Actual);
 | 
      
         | 2609 |  |  |          Next (Actual);
 | 
      
         | 2610 |  |  |       end loop;
 | 
      
         | 2611 |  |  |    end Remove_Dimension_In_Call;
 | 
      
         | 2612 |  |  |  
 | 
      
         | 2613 |  |  |    -----------------------------------
 | 
      
         | 2614 |  |  |    -- Remove_Dimension_In_Statement --
 | 
      
         | 2615 |  |  |    -----------------------------------
 | 
      
         | 2616 |  |  |  
 | 
      
         | 2617 |  |  |    --  Removal of dimension in statement as part of the Analyze_Statements
 | 
      
         | 2618 |  |  |    --  routine (see package Sem_Ch5).
 | 
      
         | 2619 |  |  |  
 | 
      
         | 2620 |  |  |    procedure Remove_Dimension_In_Statement (Stmt : Node_Id) is
 | 
      
         | 2621 |  |  |    begin
 | 
      
         | 2622 |  |  |       if Ada_Version < Ada_2012 then
 | 
      
         | 2623 |  |  |          return;
 | 
      
         | 2624 |  |  |       end if;
 | 
      
         | 2625 |  |  |  
 | 
      
         | 2626 |  |  |       --  Remove dimension in parameter specifications for accept statement
 | 
      
         | 2627 |  |  |  
 | 
      
         | 2628 |  |  |       if Nkind (Stmt) = N_Accept_Statement then
 | 
      
         | 2629 |  |  |          declare
 | 
      
         | 2630 |  |  |             Param : Node_Id := First (Parameter_Specifications (Stmt));
 | 
      
         | 2631 |  |  |          begin
 | 
      
         | 2632 |  |  |             while Present (Param) loop
 | 
      
         | 2633 |  |  |                Remove_Dimensions (Param);
 | 
      
         | 2634 |  |  |                Next (Param);
 | 
      
         | 2635 |  |  |             end loop;
 | 
      
         | 2636 |  |  |          end;
 | 
      
         | 2637 |  |  |  
 | 
      
         | 2638 |  |  |       --  Remove dimension of name and expression in assignments
 | 
      
         | 2639 |  |  |  
 | 
      
         | 2640 |  |  |       elsif Nkind (Stmt) = N_Assignment_Statement then
 | 
      
         | 2641 |  |  |          Remove_Dimensions (Expression (Stmt));
 | 
      
         | 2642 |  |  |          Remove_Dimensions (Name (Stmt));
 | 
      
         | 2643 |  |  |       end if;
 | 
      
         | 2644 |  |  |    end Remove_Dimension_In_Statement;
 | 
      
         | 2645 |  |  |  
 | 
      
         | 2646 |  |  |    --------------------
 | 
      
         | 2647 |  |  |    -- Set_Dimensions --
 | 
      
         | 2648 |  |  |    --------------------
 | 
      
         | 2649 |  |  |  
 | 
      
         | 2650 |  |  |    procedure Set_Dimensions (N : Node_Id; Val : Dimension_Type) is
 | 
      
         | 2651 |  |  |    begin
 | 
      
         | 2652 |  |  |       pragma Assert (OK_For_Dimension (Nkind (N)));
 | 
      
         | 2653 |  |  |       pragma Assert (Exists (Val));
 | 
      
         | 2654 |  |  |  
 | 
      
         | 2655 |  |  |       Dimension_Table.Set (N, Val);
 | 
      
         | 2656 |  |  |    end Set_Dimensions;
 | 
      
         | 2657 |  |  |  
 | 
      
         | 2658 |  |  |    ----------------
 | 
      
         | 2659 |  |  |    -- Set_Symbol --
 | 
      
         | 2660 |  |  |    ----------------
 | 
      
         | 2661 |  |  |  
 | 
      
         | 2662 |  |  |    procedure Set_Symbol (E : Entity_Id; Val : String_Id) is
 | 
      
         | 2663 |  |  |    begin
 | 
      
         | 2664 |  |  |       Symbol_Table.Set (E, Val);
 | 
      
         | 2665 |  |  |    end Set_Symbol;
 | 
      
         | 2666 |  |  |  
 | 
      
         | 2667 |  |  |    ---------------
 | 
      
         | 2668 |  |  |    -- Symbol_Of --
 | 
      
         | 2669 |  |  |    ---------------
 | 
      
         | 2670 |  |  |  
 | 
      
         | 2671 |  |  |    function Symbol_Of (E : Entity_Id) return String_Id is
 | 
      
         | 2672 |  |  |    begin
 | 
      
         | 2673 |  |  |       return Symbol_Table.Get (E);
 | 
      
         | 2674 |  |  |    end Symbol_Of;
 | 
      
         | 2675 |  |  |  
 | 
      
         | 2676 |  |  |    -----------------------
 | 
      
         | 2677 |  |  |    -- Symbol_Table_Hash --
 | 
      
         | 2678 |  |  |    -----------------------
 | 
      
         | 2679 |  |  |  
 | 
      
         | 2680 |  |  |    function Symbol_Table_Hash (Key : Entity_Id) return Symbol_Table_Range is
 | 
      
         | 2681 |  |  |    begin
 | 
      
         | 2682 |  |  |       return Symbol_Table_Range (Key mod 511);
 | 
      
         | 2683 |  |  |    end Symbol_Table_Hash;
 | 
      
         | 2684 |  |  |  
 | 
      
         | 2685 |  |  |    ---------------
 | 
      
         | 2686 |  |  |    -- System_Of --
 | 
      
         | 2687 |  |  |    ---------------
 | 
      
         | 2688 |  |  |  
 | 
      
         | 2689 |  |  |    function System_Of (E : Entity_Id) return System_Type is
 | 
      
         | 2690 |  |  |       Type_Decl : constant Node_Id := Parent (E);
 | 
      
         | 2691 |  |  |  
 | 
      
         | 2692 |  |  |    begin
 | 
      
         | 2693 |  |  |       --  Look for Type_Decl in System_Table
 | 
      
         | 2694 |  |  |  
 | 
      
         | 2695 |  |  |       for Dim_Sys in 1 .. System_Table.Last loop
 | 
      
         | 2696 |  |  |          if Type_Decl = System_Table.Table (Dim_Sys).Type_Decl then
 | 
      
         | 2697 |  |  |             return System_Table.Table (Dim_Sys);
 | 
      
         | 2698 |  |  |          end if;
 | 
      
         | 2699 |  |  |       end loop;
 | 
      
         | 2700 |  |  |  
 | 
      
         | 2701 |  |  |       return Null_System;
 | 
      
         | 2702 |  |  |    end System_Of;
 | 
      
         | 2703 |  |  |  
 | 
      
         | 2704 |  |  | end Sem_Dim;
 |