Version 1.4 of ais/ai-00282.txt

Unformatted version of ais/ai-00282.txt version 1.4
Other versions for file ais/ai-00282.txt

!standard 10.03 (00)          01-12-26 AI95-00282/01
!class amendment 01-12-26
!status No Action (8-0-2) 03-10-03
!status work item 01-12-26
!status received 01-12-11
!priority Low
!difficulty Medium
!subject Ada unit information symbols
!summary
(TBD.)
!problem
When trying to trace an Ada program, there exists no reliable means to precisely know which part of the code emits a particular trace.
!proposal
Create a special package where calls to its functions are replaced at compile time by the corresponding values.
package Ada.Compilation_Unit is -- Returns the name of the file function File_Name return String;
-- Returns the line number where its call is made function Line_Number return String; function Line_Number return Natural;
-- Returns the full Ada path of the enclosing scope function Scope_Path return String;
-- Returns the Ada simple name of the enclosing scope function Scope_Name return String;
end Ada.Compilation_Unit;
!discussion
This is a common problem. Some existing Ada compilers provide some of the desired information by various means, but a standard solution would be preferable.
!example
!ACATS test
!appendix

!topic Ada unit information symbols
!reference RM95-10.1.1
!from Bernard Maudry
!discussion

When trying to trace an Ada program, there exists no reliable mean to precisely
know which part of the code emits a particular trace.

I propose to create a special package where calls to its functions are replaced
at compile time by the corresponding values.

package Ada.Compilation_Unit is
  -- Returns the name of the file
  function File_Name return String;

  -- Returns the line number where its call is made
  function Line_Number return String;
  function Line_Number return Natural;

  -- Returns the full Ada path of the enclosing scope
  function Scope_Path return String;

  -- Returns the Ada simple name of the enclosing scope
  function Scope_Name return String;

end Ada.Compilation_Unit;

*************************************************************

From: David C. Hoos, Sr.
Date: December 18, 2001 10:17 AM

Another nice addition to a package such as this would
be the date and time it was compiled, and the compiler
switches used.

*************************************************************

From: Nick Roberts
Date: Saturday, January 19, 2002  1:39 PM

I would prefer that it were left up to a compiler to put this kind of
information (including full scope path, source file name, line number,
identification of the build, some kind of stack trace) into the string that
is returned by the Ada.Exceptions.Exception_Information function for an
exception occurance originating at a particular point in the program.

Some exception catcher (actually in the application program or invisibly
around it) could then catch the exception and output this information.

This would tend to be a neater technique, for simple debugging purposes.
For something more elaborate, ASIS or the like would seem to be the more
likely tool.

*************************************************************

From: Randy Brukardt
Date: Monday, January 21, 2002  4:37 PM

Some compilers do this already (Janus/Ada has always done it). However, to
do so has a performance and/or program size penalty (it means adding some
code to every check and exception raise and to calling sequences, and it
also requires saving a lot of information when an exception is raised).
Thus, we have to allow it to be turned off. Certainly, some compilers
(especially for embedded systems) could not support the overhead.

The proposal would allow the programmer capture the information without
paying a performance penalty except when it is used. That seems preferable
for many types of applications.

While I don't find much need for this feature myself (the compiler I use
does an excellent job of this already), I certainly can see why others would
want something like it. And I couldn't live without it (which is why I
generally develop with Janus/Ada and test the result on other compilers).

*************************************************************

From: Pascal Leroy
Date: Tuesday, January 22, 2002  5:17 AM

(Re Nick's message)
I don't think this covers the same need, as the original request didn't mention
exceptions at all.  In an application that periodically logs what it's doing
(even in the absence of exceptions) I can see the value of putting some form of
information about the source code used to produce the program.

While I understand the need (and sympathize with it to some extend), I hate the
proposal where all these functions are magic and get substituted at compile
time.  I also hate the fact that it essentially kills incremental compilation.

*************************************************************

From: Jean-Pierre Rosen
Date: Tuesday, January 22, 2002  6:36 AM

Agreed. Wouldn't attributes be more appropriate? I.e.
Compilation_Unit'Source_Name, Compilation_Unit'Compilation_Date...

*************************************************************

From: Bernard Maudry
Date: Tuesday, January 22, 2002  2:27 AM

The main goal of my proposal is a lot more general than exception tracing. It
helps to trace the behavior of a program at run time, even if there are no
exceptions raised. This is particularly helpful in parallel or distributed
computing, in order to verify that the proper calculations are made in response
to given events, and, if not, to locate quickly where the deviation occurred.

This feature will provide a reliable information about the origin of each trace
at a very low cost for such reliable identification.

It also seems to me that its implementation in a compiler is straightforward,
but I would like to hear from compiler implementors about this particular
point.

*************************************************************

From: Gary Dismukes
Sent: Tuesday, January 22, 2002  4:15 PM

GNAT provides a set of capabilities similar to what you propose in
the package GNAT.Source_Info.  These are intrinsic subprograms that
have a straightforward implementation.

*************************************************************

From: Pascal Leroy
Sent: Wednesday, January 23, 2002  3:34 AM

> Agreed. Wouldn't attributes be more appropriate?
> I.e. Compilation_Unit'Source_Name, Compilation_Unit'Compilation_Date...

Yes, I would definitely prefer something like that.

> GNAT provides a set of capabilities similar to what you propose in
> the package GNAT.Source_Info.  These are intrinsic subprograms that
> have a straightforward implementation.

What happens when these subprograms are renamed or passed to a generic (and
referenced in the body)?  These are questions that are best left unanswered
IMO.

> It also seems to me that its implementation in a compiler is straightforward,
> but I would like to hear from compiler implementers about this particular
> point.

In our case, in the presence of incremental compilation, it is perfectly
possible for the line numbers to change without causing a recompilation (e.g.
if you add/remove comments or whitespace).  It is also possible for a unit to
be copied from one library to another while remaining compiled.  In these
circumstances, File_Name and Line_Number could end up lying about the exact
file name or line number.

The problem with Line_Number is one that we solve to some extent for debugging
purposes.  However, it is not obvious to me what to do with File_Name.

But then keep in mind that the language doesn't specify the source
representation of programs, so this capability would have to give a lot of
flexibility to the implementers.

*************************************************************

From: Bernard Maudry
Date: Wednesday, January 23, 2002  6:12 AM

> Wouldn't attributes be more appropriate? I.e.
> Compilation_Unit'Source_Name, Compilation_Unit'Compilation_Date...

The problem with this solution is the prefix, which is not independent of the
unit it is placed in. It helps for the line numbers, but not for the others
facilities as it becomes the same as writing directly the corresponding string.
In particular for code generators, it has not the same simplicity as the
solution I proposed.

I have nothing against using attributes, but it needs a unit independent prefix
like Ada'Line_Number, Ada'Scope_Path, etc...
(you can change Ada by anything you think more convenient, but I like Ada ;-).

> In our case, in the presence of incremental compilation, it is perfectly
> possible for the line numbers to change without causing a recompilation
> (e.g. if you add/remove comments or whitespace).  It is also possible for
> a unit to be copied from one library to another while remaining compiled.
> In these circumstances, File_Name and Line_Number could end up lying about
> the exact file name or line number.
> The problem with Line_Number is one that we solve to some extent for
> debugging purposes.  However, it is not obvious to me what to do with
> File_Name.

Understood. In fact, line number and (full) scope name are really essential for
the purpose of tracing, file name and path name are just helpful.

> But then keep in mind that the language doesn't specify the source
> representation of programs, so this capability would have to give a lot of
> flexibility to the implementers.

My main goal is to get this facility, and in a 'simple to use' manner. The
purpose of the Ada specification is also to indicate which flexibility is
allowed to the implementors.

*************************************************************

From: Nick Roberts
Date: Tuesday, January 22, 2002  12:13 PM

I'm undecided whether I feel Bernard Maudry's suggested package (or
something like it) needs to be specified by the standard. It does feel a bit
like something that is out of the domain of a language specification (and
more in the realm of the APSE).

Pretty much the required functionality could be achieved by placing a
distinctive string in the source code everywhere a piece of 'metadata' is
needed (embedded in a string literal), and then processing the source files
by a rather simple macro substitution pre-processor. E.g.:

   Log_Coverage("<!MAKE!> <!FILE!> <!LINE!>");

or

   Raise(Foo_Error'Exception_ID,"Foo error in <!FILE!> at <!LINE!>");

One (perhaps minor) advantage of this scheme is that it would more strongly
signal that the replacements are location-dependant in the code. Seeing a
call to e.g.:

   Log_Coverage( Ada.Compilation_Unit.Build_Version & ' ' &
                 Ada.Compilation_Unit.File_Name & ' ' &
                 Ada.Compilation_Unit.Line_Number );

several times in a piece of code, another programmer (on a bad day ;-) might
be tempted to tidy them away into a procedure somewhere, replacing them all
with a call to that procedure. (And then wondering why his supervisor throws
a strop :-)

One (also perhaps minor) disadvantage can be seen by considering the
substitution for <!MAKE!>. It may be difficult for this to replaced with a
build number allocated by the compiler itself, since it could be known to
the pre-processor. Some other build identification would have to be used
instead.

Plainly the need for a pre-processor will slow down the overall rebuild
process, unless the pre-processor is already needed for something else
anyway. But on today's super-fast machines such concerns are tending to
vanish. The potential for a faulty pre-processor to foul up otherwise good
code remains a possible concern.

I suppose a [cynical|pragmatic] analysis is that using a pre-processor will
have the advantage of certainly being compatible with all current and future
compilers.

*************************************************************

From: Pascal Leroy
Date: Wednesday, January 23, 2002  3:20 AM

While some implementations do offer preprocessors (with which you can achieve
more-or-less the desired effect), standardizing a preprocessor as part of the
revision of the language is a no-no.

*************************************************************

From: Randy Brukardt
Date: Wednesday, January 23, 2002  9:42 PM

I agree with Pascal and Jean-Pierre that attributes would be more
appropriate. I do not want to see subprograms added to Ada that cannot be
implemented in Ada. (These certainly cannot be implemented in Ada, unless
ASIS is linked in to every program!)

Magic subprograms tend to pervade the front end of our compiler, appearing
in at least six different places. These probably wouldn't be quite as bad as
Unchecked_Conversion because they would be static, but there would be quite
a bit of work involved.

Pascal's concerns about renames of these point out that having these as
subprograms would be problematic. And the generic issues (especially for the
shared generics used by our compiler) would be very messy.

Bernard mentioned that he didn't like the fact that the prefix of these
attributes is not independent of the unit. But that doesn't seem to have
anything to do with the usability of the feature. Ada isn't about making
code easy to write! And <subprog>'Full_Name and <subprog>'Line_Number and
<comp_unit>'File_Name all are useful. There is no value to 'Simple_Name -
just type it. I don't understand the point about code generators at all.
What code generator is so brain-damaged that it doesn't know what unit it is
generating? Certainly the Claw Builder code generator knows what unit it is
generating, and would have no problem emitting the appropriate prefix. That
would be the least of problems in creating a useful Ada code generator.

If the attribute prefixes are some magic value (or if the original proposal
is used), we have a situation where a chunk of code may do very different
things if it is moved. Ada avoids that as much as possible; we try to avoid
position-dependent constructs.

My big concern with this, though, is the difficulty of defining and
implementing this properly in generics. What is the full scope name of an
entity declared in the generic body? Is it based on the name of the
instance, or on the name of the template? The former would be a significant
impediment when implementing shared generics (part of the name would have to
be passed in, and thus these items could not be static in a generic unit);
and the latter would be harder to implement for template implementations
(which would probably have to figure out what the original name was). One
presumes the line numbers always would refer to those in the template, but
of course implementations would have to take care in figuring them.

If the full scope name depends on the name of the instance, the full scope
name could be used in various ways to make generic units dependent on where
they are instantiated. I think that would be very bad, as it would be an
abstraction violation.

Anyway, this looks worse and worse on close inspection. The value of this
proposal is low, so I don't think we can justify introducing a lot of
problems with it.

*************************************************************

From: Pascal Leroy
Date: Thursday, January 24, 2002  4:31 AM

> If the attribute prefixes are some magic value (or if the original proposal
> is used), we have a situation where a chunk of code may do very different
> things if it is moved. Ada avoids that as much as possible; we try to avoid
> position-dependent constructs.

Well, the essence of the Line_Number attribute is to be position-dependent, so
you'd have to be pragmatic here.  I don't like the notion of using Ada as the
prefix, though, because Ada is not visible everywhere.

> My big concern with this, though, is the difficulty of defining and
> implementing this properly in generics. What is the full scope name of an
> entity declared in the generic body?

You'd have similar problems when using these attributes in default expressions.
Does it take the line/scope of the place where the expression occurs, or the
place where it is evaluated?

The way out of this conendrum is again to be pragmatic: we want these attributes
to return useful information, but we don't want to overspecify.  The RM language
would have to state that they return some implementation-defined value, with an
implementation advice saying that the value should identify as precisely as
possible the scope/line where the attribute appears.  Then, trust the
implementers to do something reasonable given the constraints of their
technology.

> Anyway, this looks worse and worse on close inspection. The value of this
> proposal is low, so I don't think we can justify introducing a lot of
> problems with it.

I disagree.  I have often felt the need for a feature like that.  It would be
useful to standardize it, in order to be able to log information in a way that
is independent of the compiler.  But we should not insist that the actual output
produced be the same for different compilers.

*************************************************************

From: Tucker Taft
Date: Thursday, January 24, 2002  6:35 AM

GNAT has used "Standard" as a prefix for various attributes,
and that seems most appropriate, since it is visible
everywhere.

*************************************************************

From: Bob Duff
Date: Thursday, January 24, 2002  8:57 AM

> Well, the essence of the Line_Number attribute is to be position-dependent,
> so you'd have to be pragmatic here.  I don't like the notion of using Ada
> as the prefix, though, because Ada is not visible everywhere.

GNAT uses Standard as the prefix of a whole bunch of attributes that
don't relate to any particular entity.  It's annoyingly long, though,
for the purpose here.  OTOH, you could simply require the prefix to be
Ada, and require (the predefined) Ada to be visible.  I usually put the
code for a whole program or large subsystem under a single root package,
and that root package says "with Ada; use Ada;", so that would be
convenient.  It's still a kludge, though.

> > Anyway, this looks worse and worse on close inspection. The value of this
> > proposal is low, so I don't think we can justify introducing a lot of
> > problems with it.
>
> I disagree.  I have often felt the need for a feature like that.  It would be
> useful to standardize it, in order to be able to log information in a way
> that is independent of the compiler.  But we should not insist that the
> actual output produced be the same for different compilers.

I tend to agree with Randy, that this feature is not worth the trouble.

*************************************************************


Questions? Ask the ACAA Technical Agent