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