1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
9 -- Copyright (C) 2008-2023, Free Software Foundation, Inc. --
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. --
21 -- GNAT was originally developed by the GNAT team at New York University. --
22 -- Extensive contributions were provided by Ada Core Technologies Inc. --
24 ------------------------------------------------------------------------------
26 with Atree
; use Atree
;
27 with Einfo
; use Einfo
;
28 with Einfo
.Entities
; use Einfo
.Entities
;
29 with Einfo
.Utils
; use Einfo
.Utils
;
30 with Errout
; use Errout
;
31 with Namet
; use Namet
;
32 with Nlists
; use Nlists
;
34 with Sinfo
; use Sinfo
;
35 with Sinfo
.Nodes
; use Sinfo
.Nodes
;
36 with Sinfo
.Utils
; use Sinfo
.Utils
;
37 with Sinput
; use Sinput
;
38 with Snames
; use Snames
;
39 with Uintp
; use Uintp
;
41 with System
.Case_Util
;
43 package body Pprint
is
45 List_Name_Count
: Natural := 0;
46 -- Counter used to prevent infinite recursion while computing name of
47 -- complex expressions.
49 ----------------------
50 -- Expression_Image --
51 ----------------------
53 function Expression_Image
55 Default
: String) return String
59 Take_Prefix
: Boolean := True;
60 Expand_Type
: Boolean := True) return String;
61 -- Return string corresponding to Expr. If no string can be extracted,
62 -- return "...". If Take_Prefix is True, go back to prefix when needed,
63 -- otherwise only consider the right-hand side of an expression. If
64 -- Expand_Type is True and Expr is a type, try to expand Expr (an
65 -- internally generated type) into a user understandable name.
67 function Count_Parentheses
(S
: String; C
: Character) return Natural
68 with Pre
=> C
in '(' |
')';
69 -- Returns the number of times parenthesis character C should be added
70 -- to string S for getting a correctly parenthesized result. For C = '('
71 -- this means prepending the character, for C = ')' this means appending
74 function Fix_Parentheses
(S
: String) return String;
75 -- Counts the number of required opening and closing parentheses in S to
76 -- respectively prepend and append for getting correct parentheses. Then
77 -- returns S with opening parentheses prepended and closing parentheses
78 -- appended so that the result is correctly parenthesized.
80 Max_List_Depth
: constant := 3;
81 -- Limit number of nested lists to print
83 Max_List_Length
: constant := 3;
84 -- Limit number of list elements to print
86 Max_Expr_Elements
: constant := 24;
87 -- Limit number of elements in an expression for use by Expr_Name
89 Num_Elements
: Natural := 0;
90 -- Current number of elements processed by Expr_Name
92 function List_Name
(List
: List_Id
) return String;
93 -- Return a string corresponding to List
99 function List_Name
(List
: List_Id
) return String is
100 Buf
: Bounded_String
;
103 Printed_Elmts
: Natural := 0;
106 -- Give up if the printed list is too deep
108 if List_Name_Count
> Max_List_Depth
then
112 List_Name_Count
:= List_Name_Count
+ 1;
114 Elmt
:= First
(List
);
115 while Present
(Elmt
) loop
117 -- Print component_association as "x | y | z => 12345"
119 if Nkind
(Elmt
) = N_Component_Association
then
121 Choice
: Node_Id
:= First
(Choices
(Elmt
));
123 while Present
(Choice
) loop
124 Append
(Buf
, Expr_Name
(Choice
));
127 if Present
(Choice
) then
132 Append
(Buf
, " => ");
133 Append
(Buf
, Expr_Name
(Expression
(Elmt
)));
135 -- Print parameter_association as "x => 12345"
137 elsif Nkind
(Elmt
) = N_Parameter_Association
then
138 Append
(Buf
, Expr_Name
(Selector_Name
(Elmt
)));
139 Append
(Buf
, " => ");
140 Append
(Buf
, Expr_Name
(Explicit_Actual_Parameter
(Elmt
)));
142 -- Print expression itself as "12345"
145 Append
(Buf
, Expr_Name
(Elmt
));
149 Printed_Elmts
:= Printed_Elmts
+ 1;
151 -- Separate next element with a comma, if necessary
153 if Present
(Elmt
) then
156 -- Abbreviate remaining elements as "...", if limit exceeded
158 if Printed_Elmts
= Max_List_Length
then
165 List_Name_Count
:= List_Name_Count
- 1;
167 return To_String
(Buf
);
176 Take_Prefix
: Boolean := True;
177 Expand_Type
: Boolean := True) return String
180 Num_Elements
:= Num_Elements
+ 1;
182 if Num_Elements
> Max_Expr_Elements
then
186 -- Just print pieces of aggregate nodes, even though they are not
187 -- expressions. It is too much trouble to handle them any better.
189 if Nkind
(Expr
) = N_Component_Association
then
191 pragma Assert
(Box_Present
(Expr
));
194 Buf
: Bounded_String
;
195 Choice
: Node_Id
:= First
(Choices
(Expr
));
197 while Present
(Choice
) loop
198 Append
(Buf
, Expr_Name
(Choice
));
201 if Present
(Choice
) then
206 Append
(Buf
, " => <>");
208 return To_String
(Buf
);
211 elsif Nkind
(Expr
) = N_Others_Choice
then
215 case N_Subexpr
'(Nkind (Expr)) is
217 return Ident_Image (Expr, Expression_Image.Expr, Expand_Type);
219 when N_Character_Literal =>
221 Char : constant Int := UI_To_Int (Char_Literal_Value (Expr));
223 if Char in 32 .. 126 then
224 return "'" & Character'Val (Char) & "'";
226 UI_Image (Char_Literal_Value (Expr));
228 "'\" & UI_Image_Buffer
(1 .. UI_Image_Length
) & "'";
232 when N_Integer_Literal
=>
233 return UI_Image
(Intval
(Expr
));
235 when N_Real_Literal
=>
236 return Real_Image
(Realval
(Expr
));
238 when N_String_Literal
=>
239 return String_Image
(Strval
(Expr
));
242 return "new " & Expr_Name
(Expression
(Expr
));
245 if Present
(Expressions
(Expr
)) then
246 return '(' & List_Name
(Expressions
(Expr
)) & ')';
248 -- Do not return empty string for (others => <>) aggregate
249 -- of a componentless record type. At least one caller (the
250 -- recursive call below in the N_Qualified_Expression case)
251 -- is not prepared to deal with a zero-length result.
253 elsif Null_Record_Present
(Expr
)
254 or else No
(First
(Component_Associations
(Expr
)))
256 return ("(null record)");
259 return '(' & List_Name
(Component_Associations
(Expr
)) & ')';
262 when N_Extension_Aggregate
=>
263 return '(' & Expr_Name
(Ancestor_Part
(Expr
))
264 & " with (" & List_Name
(Expressions
(Expr
)) & ')';
266 when N_Attribute_Reference
=>
269 Id
: constant Attribute_Id
:=
270 Get_Attribute_Id
(Attribute_Name
(Expr
));
272 -- Always use mixed case for attributes
274 Str
: constant String :=
275 Expr_Name
(Prefix
(Expr
))
277 & System
.Case_Util
.To_Mixed
278 (Get_Name_String
(Attribute_Name
(Expr
)));
284 if (Id
= Attribute_First
or else Id
= Attribute_Last
)
285 and then Str
(Str
'First) = '$'
287 N
:= Associated_Node_For_Itype
(Etype
(Prefix
(Expr
)));
290 if Nkind
(N
) = N_Full_Type_Declaration
then
291 N
:= Type_Definition
(N
);
294 if Nkind
(N
) = N_Subtype_Declaration
then
297 (Constraint
(Subtype_Indication
(N
)));
299 if List_Length
(Ranges
) = 1
300 and then Nkind
(First
(Ranges
)) in
302 N_Real_Range_Specification |
303 N_Signed_Integer_Type_Definition
305 if Id
= Attribute_First
then
308 (Low_Bound
(First
(Ranges
)), Str
);
312 (High_Bound
(First
(Ranges
)), Str
);
322 return ''' & Get_Name_String
(Attribute_Name
(Expr
));
325 when N_Explicit_Dereference
=>
326 Explicit_Dereference
: declare
327 function Deref_Suffix
return String;
328 -- Usually returns ".all", but will return "" if
329 -- Hide_Temp_Derefs is true and the prefix is a use of a
330 -- not-from-source object declared as
331 -- X : constant Some_Access_Type := Some_Expr'Reference;
332 -- (as is sometimes done in Exp_Util.Remove_Side_Effects).
338 function Deref_Suffix
return String is
343 and then Nkind
(Prefix
(Expr
)) = N_Identifier
344 and then Nkind
(Entity
(Prefix
(Expr
))) =
345 N_Defining_Identifier
347 Decl
:= Parent
(Entity
(Prefix
(Expr
)));
350 and then Nkind
(Decl
) = N_Object_Declaration
351 and then not Comes_From_Source
(Decl
)
352 and then Constant_Present
(Decl
)
353 and then Present
(Expression
(Decl
))
354 and then Nkind
(Expression
(Decl
)) = N_Reference
365 -- Start of processing for Explicit_Dereference
368 if Hide_Parameter_Blocks
369 and then Nkind
(Prefix
(Expr
)) = N_Selected_Component
370 and then Present
(Etype
(Prefix
(Expr
)))
371 and then Is_Access_Type
(Etype
(Prefix
(Expr
)))
372 and then Is_Param_Block_Component_Type
373 (Etype
(Prefix
(Expr
)))
375 -- Return "Foo" instead of "Parameter_Block.Foo.all"
377 return Expr_Name
(Selector_Name
(Prefix
(Expr
)));
379 elsif Take_Prefix
then
380 return Expr_Name
(Prefix
(Expr
)) & Deref_Suffix
;
384 end Explicit_Dereference
;
387 | N_Selected_Component
391 Expr_Name
(Prefix
(Expr
)) & "." &
392 Expr_Name
(Selector_Name
(Expr
));
394 return "." & Expr_Name
(Selector_Name
(Expr
));
397 when N_If_Expression
=>
399 Cond_Expr
: constant Node_Id
:= First
(Expressions
(Expr
));
400 Then_Expr
: constant Node_Id
:= Next
(Cond_Expr
);
401 Else_Expr
: constant Node_Id
:= Next
(Then_Expr
);
404 "if " & Expr_Name
(Cond_Expr
) & " then "
405 & Expr_Name
(Then_Expr
) & " else "
406 & Expr_Name
(Else_Expr
);
409 when N_Qualified_Expression
=>
411 Mark
: constant String :=
413 (Subtype_Mark
(Expr
), Expand_Type
=> False);
414 Str
: constant String := Expr_Name
(Expression
(Expr
));
416 if Str
(Str
'First) = '(' and then Str
(Str
'Last) = ')' then
417 return Mark
& "'" & Str
;
419 return Mark
& "'(" & Str
& ")";
423 when N_Expression_With_Actions
424 | N_Unchecked_Expression
426 return Expr_Name
(Expression
(Expr
));
428 when N_Raise_Constraint_Error
=>
429 if Present
(Condition
(Expr
)) then
431 "[constraint_error when "
432 & Expr_Name
(Condition
(Expr
)) & "]";
434 return "[constraint_error]";
437 when N_Raise_Program_Error
=>
438 if Present
(Condition
(Expr
)) then
440 "[program_error when "
441 & Expr_Name
(Condition
(Expr
)) & "]";
443 return "[program_error]";
446 when N_Raise_Storage_Error
=>
447 if Present
(Condition
(Expr
)) then
449 "[storage_error when "
450 & Expr_Name
(Condition
(Expr
)) & "]";
452 return "[storage_error]";
457 Expr_Name
(Low_Bound
(Expr
)) & ".." &
458 Expr_Name
(High_Bound
(Expr
));
462 Expr_Name
(Prefix
(Expr
)) & " (" &
463 Expr_Name
(Discrete_Range
(Expr
)) & ")";
467 Expr_Name
(Left_Opnd
(Expr
)) & " and then " &
468 Expr_Name
(Right_Opnd
(Expr
));
472 Expr_Name
(Left_Opnd
(Expr
)) & " in " &
473 Expr_Name
(Right_Opnd
(Expr
));
477 Expr_Name
(Left_Opnd
(Expr
)) & " not in " &
478 Expr_Name
(Right_Opnd
(Expr
));
482 Expr_Name
(Left_Opnd
(Expr
)) & " or else " &
483 Expr_Name
(Right_Opnd
(Expr
));
487 Expr_Name
(Left_Opnd
(Expr
)) & " and " &
488 Expr_Name
(Right_Opnd
(Expr
));
492 Expr_Name
(Left_Opnd
(Expr
)) & " or " &
493 Expr_Name
(Right_Opnd
(Expr
));
497 Expr_Name
(Left_Opnd
(Expr
)) & " xor " &
498 Expr_Name
(Right_Opnd
(Expr
));
502 Expr_Name
(Left_Opnd
(Expr
)) & " = " &
503 Expr_Name
(Right_Opnd
(Expr
));
507 Expr_Name
(Left_Opnd
(Expr
)) & " /= " &
508 Expr_Name
(Right_Opnd
(Expr
));
512 Expr_Name
(Left_Opnd
(Expr
)) & " < " &
513 Expr_Name
(Right_Opnd
(Expr
));
517 Expr_Name
(Left_Opnd
(Expr
)) & " <= " &
518 Expr_Name
(Right_Opnd
(Expr
));
522 Expr_Name
(Left_Opnd
(Expr
)) & " > " &
523 Expr_Name
(Right_Opnd
(Expr
));
527 Expr_Name
(Left_Opnd
(Expr
)) & " >= " &
528 Expr_Name
(Right_Opnd
(Expr
));
532 Expr_Name
(Left_Opnd
(Expr
)) & " + " &
533 Expr_Name
(Right_Opnd
(Expr
));
535 when N_Op_Subtract
=>
537 Expr_Name
(Left_Opnd
(Expr
)) & " - " &
538 Expr_Name
(Right_Opnd
(Expr
));
540 when N_Op_Multiply
=>
542 Expr_Name
(Left_Opnd
(Expr
)) & " * " &
543 Expr_Name
(Right_Opnd
(Expr
));
547 Expr_Name
(Left_Opnd
(Expr
)) & " / " &
548 Expr_Name
(Right_Opnd
(Expr
));
552 Expr_Name
(Left_Opnd
(Expr
)) & " mod " &
553 Expr_Name
(Right_Opnd
(Expr
));
557 Expr_Name
(Left_Opnd
(Expr
)) & " rem " &
558 Expr_Name
(Right_Opnd
(Expr
));
562 Expr_Name
(Left_Opnd
(Expr
)) & " ** " &
563 Expr_Name
(Right_Opnd
(Expr
));
565 when N_Op_Shift_Left
=>
567 Expr_Name
(Left_Opnd
(Expr
)) & " << " &
568 Expr_Name
(Right_Opnd
(Expr
));
570 when N_Op_Shift_Right | N_Op_Shift_Right_Arithmetic
=>
572 Expr_Name
(Left_Opnd
(Expr
)) & " >> " &
573 Expr_Name
(Right_Opnd
(Expr
));
577 Expr_Name
(Left_Opnd
(Expr
)) & " & " &
578 Expr_Name
(Right_Opnd
(Expr
));
581 return "+" & Expr_Name
(Right_Opnd
(Expr
));
584 return "-" & Expr_Name
(Right_Opnd
(Expr
));
587 return "abs " & Expr_Name
(Right_Opnd
(Expr
));
590 return "not (" & Expr_Name
(Right_Opnd
(Expr
)) & ")";
592 when N_Type_Conversion
=>
594 -- Most conversions are not very interesting (used inside
595 -- expanded checks to convert to larger ranges), so skip them.
597 return Expr_Name
(Expression
(Expr
));
599 when N_Unchecked_Type_Conversion
=>
601 -- Only keep the type conversion in complex cases
603 if not Is_Scalar_Type
(Etype
(Expr
))
604 or else not Is_Scalar_Type
(Etype
(Expression
(Expr
)))
605 or else Is_Modular_Integer_Type
(Etype
(Expr
)) /=
606 Is_Modular_Integer_Type
(Etype
(Expression
(Expr
)))
608 return Expr_Name
(Subtype_Mark
(Expr
)) &
609 "(" & Expr_Name
(Expression
(Expr
)) & ")";
611 return Expr_Name
(Expression
(Expr
));
614 when N_Indexed_Component
=>
617 Expr_Name
(Prefix
(Expr
))
618 & " (" & List_Name
(Expressions
(Expr
)) & ')';
620 return List_Name
(Expressions
(Expr
));
623 when N_Function_Call
=>
625 -- If Default = "", it means we're expanding the name of
626 -- a gnat temporary (and not really a function call), so add
627 -- parentheses around function call to mark it specially.
630 if Present
(Parameter_Associations
(Expr
)) then
632 & Expr_Name
(Name
(Expr
))
634 & List_Name
(Parameter_Associations
(Expr
))
637 return '(' & Expr_Name
(Name
(Expr
)) & ')';
639 elsif Present
(Parameter_Associations
(Expr
)) then
641 Expr_Name
(Name
(Expr
))
642 & " (" & List_Name
(Parameter_Associations
(Expr
)) & ')';
644 return Expr_Name
(Name
(Expr
));
650 when N_Case_Expression
652 | N_Interpolated_String_Literal
656 | N_Procedure_Call_Statement
657 | N_Quantified_Expression
666 -----------------------
667 -- Count_Parentheses --
668 -----------------------
670 function Count_Parentheses
(S
: String; C
: Character) return Natural is
672 procedure Next_Char
(Count
: in out Natural; C
, D
, Ch
: Character);
673 -- Process next character Ch and update the number Count of C
674 -- characters to add for correct parenthesizing, where D is the
675 -- opposite parenthesis.
681 procedure Next_Char
(Count
: in out Natural; C
, D
, Ch
: Character) is
685 elsif Ch
= C
and then Count
> 0 then
692 Count
: Natural := 0;
694 -- Start of processing for Count_Parentheses
698 for Ch
of reverse S
loop
699 Next_Char
(Count
, C
, ')', Ch
);
703 Next_Char
(Count
, C
, '(', Ch
);
708 end Count_Parentheses
;
710 ---------------------
711 -- Fix_Parentheses --
712 ---------------------
714 function Fix_Parentheses
(S
: String) return String is
715 Count_Open
: constant Natural := Count_Parentheses
(S
, '(');
716 Count_Close
: constant Natural := Count_Parentheses
(S
, ')');
718 return (1 .. Count_Open
=> '(') & S
& (1 .. Count_Close
=> ')');
723 Left
, Right
: Source_Ptr
;
725 -- Start of processing for Expression_Image
728 -- Since this is an expression pretty-printer, it should not be called
729 -- for anything but an expression. However, currently CodePeer calls
730 -- it for defining identifiers. This should be fixed in the CodePeer
731 -- itself, but for now simply return the default (if present) or print
732 -- name of the defining identifier.
734 if Nkind
(Expr
) = N_Defining_Identifier
then
735 pragma Assert
(CodePeer_Mode
);
736 if Comes_From_Source
(Expr
)
737 or else Opt
.Debug_Generated_Code
741 Nam
: constant Name_Id
:= Chars
(Expr
);
743 (Max_Length
=> Natural (Length_Of_Name
(Nam
)));
745 Adjust_Name_Case
(Buf
, Sloc
(Expr
));
747 return To_String
(Buf
);
754 S
: constant String :=
756 (Expr
=> Expr
, Orig_Expr
=> Expr
, Expand_Type
=> True);
766 pragma Assert
(Nkind
(Expr
) in N_Subexpr
);
769 -- ??? The following should be primarily needed for CodePeer
771 if not Comes_From_Source
(Expr
)
772 or else Opt
.Debug_Generated_Code
775 S
: constant String := Expr_Name
(Expr
);
785 -- Reach to the underlying expression for an expression-with-actions
787 if Nkind
(Expr
) = N_Expression_With_Actions
then
788 return Expression_Image
(Expression
(Expr
), Default
);
791 -- Compute left (start) and right (end) slocs for the expression
793 Left
:= First_Sloc
(Expr
);
794 Right
:= Last_Sloc
(Expr
);
801 Scn
: Source_Ptr
:= Left
;
802 Src
: constant not null Source_Buffer_Ptr
:=
803 Source_Text
(Get_Source_File_Index
(Scn
));
805 Threshold
: constant := 256;
806 Buffer
: String (1 .. Natural (Right
- Left
+ 1));
807 Index
: Natural := 0;
808 Skipping_Comment
: Boolean := False;
809 Underscore
: Boolean := False;
811 while Scn
<= Right
loop
814 -- Give up on non ASCII characters
816 when Character'Val (128) .. Character'Last =>
823 if not Skipping_Comment
and then not Underscore
then
826 Buffer
(Index
) := ' ';
829 -- CR/LF/FF is the end of any comment
835 Skipping_Comment
:= False;
840 if not Skipping_Comment
then
844 if Src
(Scn
) = '-' and then Src
(Scn
+ 1) = '-' then
845 Skipping_Comment
:= True;
848 Buffer
(Index
) := Src
(Scn
);
853 -- Give up on too long strings
855 if Index
>= Threshold
then
856 return Buffer
(1 .. Index
) & "...";
862 return Fix_Parentheses
(Buffer
(1 .. Index
));
864 end Expression_Image
;