comp.lang.ada
 help / color / mirror / Atom feed
* Range check for type 'Integer'
@ 2013-06-17 10:57 Peter Brooks
  2013-06-17 11:23 ` Simon Clubley
                   ` (2 more replies)
  0 siblings, 3 replies; 57+ messages in thread
From: Peter Brooks @ 2013-06-17 10:57 UTC (permalink / raw)


I may be confused about this, but I don't understand the behaviour of
a very simple Ada program.

Firstly, this program does what I do expect:

"
procedure Compute_Loop is
type fred is range -3276732787230772307 .. 3276732787230772307;

 procedure Double(Item : in out fred) is
 begin -- procedure Double.
   Item := Item * 2;
 end Double;

 X : fred := 1;   -- Local variable X of type fred.

begin -- procedure Compute_loop
 loop
  Put("This is ");
  Put(Integer(X));
  New_Line;
  Double(X);
 end loop;
end Compute_Loop;
"

Output:

...
This is   268435456
This is   536870912
This is  1073741824
This is

raised CONSTRAINT_ERROR : compute_loop.adb:19 range check failed

Exactly the same program, but using type 'Integer' instead for 'fred'
gives:


...
This is   134217728
This is   268435456
This is   536870912
This is  1073741824
This is -2147483648
This is           0
This is           0
This is           0
This is           0
This is           0
This is           0
This is           0
This is           0
..... [forever]

So the 'Integer' has rolled over to negative and then rolled back to 0
- but with no run-time error.

Why is there no range check error on type Integer?

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: Range check for type 'Integer'
  2013-06-17 10:57 Range check for type 'Integer' Peter Brooks
@ 2013-06-17 11:23 ` Simon Clubley
  2013-06-17 11:54   ` Simon Wright
  2013-06-17 12:55   ` Peter Brooks
  2013-06-17 12:46 ` Dmitry A. Kazakov
  2013-06-17 13:23 ` Bug in 'gnatmake' (Was: Range check for type 'Integer') Jacob Sparre Andersen
  2 siblings, 2 replies; 57+ messages in thread
From: Simon Clubley @ 2013-06-17 11:23 UTC (permalink / raw)


On 2013-06-17, Peter Brooks <peter.h.m.brooks@gmail.com> wrote:
>
> So the 'Integer' has rolled over to negative and then rolled back to 0
> - but with no run-time error.
>
> Why is there no range check error on type Integer?

Because GNAT does not enable integer overflow detection by default; this
is a design decision which was a major mistake. You need to compile your
program using the switch to enable integer overflow detection.

BTW, this same program was posted a few days ago with the same problem
description. Is this a problem posed as part of a class you are taking ?

Simon.

-- 
Simon Clubley, clubley@remove_me.eisner.decus.org-Earth.UFP
Microsoft: Bringing you 1980s technology to a 21st century world


^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: Range check for type 'Integer'
  2013-06-17 11:23 ` Simon Clubley
@ 2013-06-17 11:54   ` Simon Wright
  2013-06-17 12:55   ` Peter Brooks
  1 sibling, 0 replies; 57+ messages in thread
From: Simon Wright @ 2013-06-17 11:54 UTC (permalink / raw)


Simon Clubley <clubley@remove_me.eisner.decus.org-Earth.UFP> writes:

> On 2013-06-17, Peter Brooks <peter.h.m.brooks@gmail.com> wrote:
>>
>> So the 'Integer' has rolled over to negative and then rolled back to
>> 0 - but with no run-time error.
>>
>> Why is there no range check error on type Integer?
>
> Because GNAT does not enable integer overflow detection by default;
> this is a design decision which was a major mistake. You need to
> compile your program using the switch to enable integer overflow
> detection.
>
> BTW, this same program was posted a few days ago with the same problem
> description. Is this a problem posed as part of a class you are taking
> ?

And, as stated before, compile with -gnato to enable integer overflow
detection.


^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: Range check for type 'Integer'
  2013-06-17 10:57 Range check for type 'Integer' Peter Brooks
  2013-06-17 11:23 ` Simon Clubley
@ 2013-06-17 12:46 ` Dmitry A. Kazakov
  2013-06-17 13:23 ` Bug in 'gnatmake' (Was: Range check for type 'Integer') Jacob Sparre Andersen
  2 siblings, 0 replies; 57+ messages in thread
From: Dmitry A. Kazakov @ 2013-06-17 12:46 UTC (permalink / raw)


On Mon, 17 Jun 2013 03:57:26 -0700 (PDT), Peter Brooks wrote:

> Exactly the same program, but using type 'Integer' instead for 'fred'
> gives:

[...]

> So the 'Integer' has rolled over to negative and then rolled back to 0
> - but with no run-time error.
> 
> Why is there no range check error on type Integer?

Because you didn't compiled it using -gnato. Integer is a build-in type for
which GNAT uses raw machine instructions. Possibly the decision not to add
checks was motivated by [wrong] premises of optimization for speed. AdaCore
was continuously blamed for that.

Anyway, when you use a user-defined type, GNAT is forced to add checks
because its range is narrower than the range of the machine type. This is
why the behavior changes when you use your type vs. Integer WITHOUT -gnato.
The same would happen if you used Positive because it is narrower than
Integer.

A similar case is represented by floating-point numbers. If you want (and
you should) to kill IEEE non-numbers on a machine that is natively IEEE,
you would use a type like

   type Sane_Number is new Float range Float'Range;

It looks like Float, but it is not. Sane_Number behaves as a proper number
(raise exception) where Float would produce garbage (NaN etc).

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de


^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: Range check for type 'Integer'
  2013-06-17 11:23 ` Simon Clubley
  2013-06-17 11:54   ` Simon Wright
@ 2013-06-17 12:55   ` Peter Brooks
  2013-06-17 13:28     ` Shark8
  2013-06-18 10:48     ` Stephen Leake
  1 sibling, 2 replies; 57+ messages in thread
From: Peter Brooks @ 2013-06-17 12:55 UTC (permalink / raw)


On Jun 17, 1:23 pm, Simon Clubley <clubley@remove_me.eisner.decus.org-
Earth.UFP> wrote:
> On 2013-06-17, Peter Brooks <peter.h.m.bro...@gmail.com> wrote:
>
>
>
> > So the 'Integer' has rolled over to negative and then rolled back to 0
> > - but with no run-time error.
>
> > Why is there no range check error on type Integer?
>
> Because GNAT does not enable integer overflow detection by default; this
> is a design decision which was a major mistake. You need to compile your
> program using the switch to enable integer overflow detection.
>
> BTW, this same program was posted a few days ago with the same problem
> description. Is this a problem posed as part of a class you are taking ?
>
Thank you for the answer.

Yes, in a way, I am taking a class. I last looked at Ada about thirty
years ago, and I'm trying to get myself back up to speed because I've
a problem to solve.

I couldn't find any books on Kindle - all the Ada books are hard copy
and old. So I'm going through all the on-line tutorials that I can
find, particularly those on Ada 2012. This example is from an on-line
tutorial.

I couldn't work out why range-checking wasn't working and changing the
type from Integer got it going - with your answer it now all makes
sense and I can go on to the next tutorial.

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Bug in 'gnatmake' (Was: Range check for type 'Integer')
  2013-06-17 10:57 Range check for type 'Integer' Peter Brooks
  2013-06-17 11:23 ` Simon Clubley
  2013-06-17 12:46 ` Dmitry A. Kazakov
@ 2013-06-17 13:23 ` Jacob Sparre Andersen
  2013-06-17 13:32   ` Bug in 'gnatmake' Jacob Sparre Andersen
                     ` (2 more replies)
  2 siblings, 3 replies; 57+ messages in thread
From: Jacob Sparre Andersen @ 2013-06-17 13:23 UTC (permalink / raw)


Peter Brooks wrote:

> This is   134217728
> This is   268435456
> This is   536870912
> This is  1073741824
> This is -2147483648
> This is           0
> This is           0
> This is           0
> This is           0
> This is           0
> This is           0
> This is           0
> This is           0
> ..... [forever]
>
> So the 'Integer' has rolled over to negative and then rolled back to 0
> - but with no run-time error.
>
> Why is there no range check error on type Integer?

Because there is a major error in the design of GNAT.  You have to give
'gnatmake' a very specific set of command line flags to turn it into an
Ada compiler:

   -fstack-check --  Generate stack checking code
   -gnata        --  Enable assertions
   -gnatE        --  Dynamic elaboration checking
   -gnato        --  Overflow checking

If you use the GNAT Project Manager (and '*.gpr' files), I suggest that
you copy this file project file and use it in all you (GNAT based) Ada
projects:

   http://repositories.jacob-sparre.dk/ada-user-journal-tools/src/40323d1c952e20020bd056f2df698d252c4cd87f/ada_2012.gpr?at=default

Here is a simple example of how to use the file:

   http://repositories.jacob-sparre.dk/ada-user-journal-tools/src/40323d1c952e20020bd056f2df698d252c4cd87f/auj_tools.gpr?at=default

The more complicated version has something like:

   package Compiler is
      for Default_Switches ("Ada")
        use Ada_2012.Compiler'Default_Switches ("Ada") &
            ("-some-extra-switches");
   end Compiler;

instead of:

   package Compiler renames Ada_2012.Compiler;

Greetings,

Jacob
-- 
"Never interrupt your enemy when he is making a mistake."


^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: Range check for type 'Integer'
  2013-06-17 12:55   ` Peter Brooks
@ 2013-06-17 13:28     ` Shark8
  2013-06-17 13:45       ` Peter Brooks
  2013-06-18 10:48     ` Stephen Leake
  1 sibling, 1 reply; 57+ messages in thread
From: Shark8 @ 2013-06-17 13:28 UTC (permalink / raw)


On Monday, June 17, 2013 6:55:26 AM UTC-6, Peter Brooks wrote:
> 
> I couldn't find any books on Kindle - all the Ada books are hard copy
> and old.

Sure there are electronic copies available; Ada for Software Engineers [Ada95] for example -- http://pnyf.inf.elte.hu/kto/oktatas/ada/books/ase.pdf

> So I'm going through all the on-line tutorials that I can
> find, particularly those on Ada 2012. This example is from an on-line
> tutorial.

Well, that's understandable -- the Ada 2012 standard was finalized in December.
(And it takes a lot to write a book, even in just electronic format.)

I have the beginnings of a toy LISP interpreter here:
http://blog.projectpolymath.org/ada-2012-tutorial_01/
http://blog.projectpolymath.org/ada-2012-tutorial_02/
source -- https://github.com/OneWingedShark/Ada_Tutorial


^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: Bug in 'gnatmake'
  2013-06-17 13:23 ` Bug in 'gnatmake' (Was: Range check for type 'Integer') Jacob Sparre Andersen
@ 2013-06-17 13:32   ` Jacob Sparre Andersen
  2013-06-17 16:50   ` Bug in 'gnatmake' (Was: Range check for type 'Integer') Robert A Duff
  2013-06-17 18:49   ` Bug in 'gnatmake' Simon Wright
  2 siblings, 0 replies; 57+ messages in thread
From: Jacob Sparre Andersen @ 2013-06-17 13:32 UTC (permalink / raw)


Jacob Sparre Andersen wrote:

> If you use the GNAT Project Manager (and '*.gpr' files), I suggest
> that you copy this file project file and use it in all you (GNAT
> based) Ada projects:
>
>    http://repositories.jacob-sparre.dk/ada-user-journal-tools/src/40323d1c952e20020bd056f2df698d252c4cd87f/ada_2012.gpr?at=default

Just in case there is any doubt:

Only the flags in that file marked "(part of Ada)" are really required
to turn 'gnatmake' into an Ada compiler.  The others are my personal
preferences and can thus safely be ignored.

Greetings,

Jacob
-- 
Trusted third party: Someone whom you know can violate your
                     security policy without getting caught.

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: Range check for type 'Integer'
  2013-06-17 13:28     ` Shark8
@ 2013-06-17 13:45       ` Peter Brooks
  2013-06-17 21:16         ` Shark8
  0 siblings, 1 reply; 57+ messages in thread
From: Peter Brooks @ 2013-06-17 13:45 UTC (permalink / raw)


On Jun 17, 3:28 pm, Shark8 <onewingedsh...@gmail.com> wrote:
> On Monday, June 17, 2013 6:55:26 AM UTC-6, Peter Brooks wrote:
>
> > I couldn't find any books on Kindle - all the Ada books are hard copy
> > and old.
>
> Sure there are electronic copies available; Ada for Software Engineers [Ada95] for example --http://pnyf.inf.elte.hu/kto/oktatas/ada/books/ase.pdf
>
> > So I'm going through all the on-line tutorials that I can
> > find, particularly those on Ada 2012. This example is from an on-line
> > tutorial.
>
> Well, that's understandable -- the Ada 2012 standard was finalized in December.
> (And it takes a lot to write a book, even in just electronic format.)
>
Having written four books myself, I do, truly, understand that! I was
not complaining, just explaining.
>
> I have the beginnings of a toy LISP interpreter here:http://blog.projectpolymath.org/ada-2012-tutorial_01/http://blog.projectpolymath.org/ada-2012-tutorial_02/
> source --https://github.com/OneWingedShark/Ada_Tutorial
>

That is brilliant - thank you very much!

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: Bug in 'gnatmake' (Was: Range check for type 'Integer')
  2013-06-17 13:23 ` Bug in 'gnatmake' (Was: Range check for type 'Integer') Jacob Sparre Andersen
  2013-06-17 13:32   ` Bug in 'gnatmake' Jacob Sparre Andersen
@ 2013-06-17 16:50   ` Robert A Duff
  2013-06-17 19:15     ` Peter Brooks
  2013-06-17 18:49   ` Bug in 'gnatmake' Simon Wright
  2 siblings, 1 reply; 57+ messages in thread
From: Robert A Duff @ 2013-06-17 16:50 UTC (permalink / raw)


Jacob Sparre Andersen <jacob@jacob-sparre.dk> writes:

> Because there is a major error in the design of GNAT.  You have to give
> 'gnatmake' a very specific set of command line flags to turn it into an
> Ada compiler:
>
>    -fstack-check --  Generate stack checking code
>    -gnata        --  Enable assertions
>    -gnatE        --  Dynamic elaboration checking
>    -gnato        --  Overflow checking

You should never use -gnatE, unless you are dealing with legacy
code that that won't work without it, and you can't afford to
fix the code.

-fstack-check is the default, at least on the most popular
targets.

You usually want -g (debugging info).  And the debugger works
better if you turn off optimizations (-O0).

- Bob

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: Bug in 'gnatmake'
  2013-06-17 13:23 ` Bug in 'gnatmake' (Was: Range check for type 'Integer') Jacob Sparre Andersen
  2013-06-17 13:32   ` Bug in 'gnatmake' Jacob Sparre Andersen
  2013-06-17 16:50   ` Bug in 'gnatmake' (Was: Range check for type 'Integer') Robert A Duff
@ 2013-06-17 18:49   ` Simon Wright
  2013-06-18  9:09     ` Elaboration order handling (Was: Bug in 'gnatmake') Jacob Sparre Andersen
  2 siblings, 1 reply; 57+ messages in thread
From: Simon Wright @ 2013-06-17 18:49 UTC (permalink / raw)


Jacob Sparre Andersen <jacob@jacob-sparre.dk> writes:

> Because there is a major error in the design of GNAT.  You have to give
> 'gnatmake' a very specific set of command line flags to turn it into an
> Ada compiler:
>
>    -fstack-check --  Generate stack checking code
>    -gnata        --  Enable assertions
>    -gnatE        --  Dynamic elaboration checking
>    -gnato        --  Overflow checking

Don't use -gnatE unless you really really want your code to be portable
to other compilers. You'd need to expend a lot of extra work to include
pragmas to ensure that elaboration takes place in an appropriate order;
GNAT does this for you if you leave out -gnatE.


^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: Bug in 'gnatmake' (Was: Range check for type 'Integer')
  2013-06-17 16:50   ` Bug in 'gnatmake' (Was: Range check for type 'Integer') Robert A Duff
@ 2013-06-17 19:15     ` Peter Brooks
  2013-06-17 21:09       ` Shark8
                         ` (2 more replies)
  0 siblings, 3 replies; 57+ messages in thread
From: Peter Brooks @ 2013-06-17 19:15 UTC (permalink / raw)


On Jun 17, 6:50 pm, Robert A Duff <bobd...@shell01.TheWorld.com>
wrote:
>
> You usually want -g (debugging info).  And the debugger works
> better if you turn off optimizations (-O0).
>
Since you mention it, I'm interested to know if there are many Ada
benchmarks.

Leaving on range, and other, checking must slow things down a tad, but
turning the optimiser on must speed them up. It'll only really matter
in CPU intensive stuff, but do you have any idea what the effects are?
More or less.

I know I could just take my code and try it, but it'd be interesting
to have a bigger picture of the performance question.


^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: Bug in 'gnatmake' (Was: Range check for type 'Integer')
  2013-06-17 19:15     ` Peter Brooks
@ 2013-06-17 21:09       ` Shark8
  2013-06-17 21:22       ` Jeffrey Carter
  2013-06-18  7:29       ` Georg Bauhaus
  2 siblings, 0 replies; 57+ messages in thread
From: Shark8 @ 2013-06-17 21:09 UTC (permalink / raw)


On Monday, June 17, 2013 1:15:26 PM UTC-6, Peter Brooks wrote:
> On Jun 17, 6:50 pm, Robert A Duff <bobd...@shell01.TheWorld.com>
> 
> wrote:
> >
> > You usually want -g (debugging info).  And the debugger works
> > better if you turn off optimizations (-O0).
> >
> 
> Since you mention it, I'm interested to know if there are many Ada
> benchmarks.
> 
> Leaving on range, and other, checking must slow things down a tad, but
> turning the optimiser on must speed them up. It'll only really matter
> in CPU intensive stuff, but do you have any idea what the effects are?

I'm not sure about that -- one user here did some testing (C++ vs Ada [w/ checks and w/o; IIRC, all optimized]) and found that the difference in C++ and checked Ada was basically measurement-error. [Again, IIRC.]

Also to note is that Ada compilers are generally good about removing unneeded checks FOR INDEX IN THE_ARRAY'RANGE LOOP, for example doesn't need any checks precisely *because* the checks are implicit in setting the ranges of the for-loop -- and that is the oversimple case.

> 
> I know I could just take my code and try it, but it'd be interesting
> to have a bigger picture of the performance question.

IMO this is somewhat akin to some people trying to optimize the number of tasks based on their CPU core-count -- that's the stupid way to go, use TASKs to split your program logically and let the run-time handle managing things. If there's more tasks than Cores, great the cores will all be active -- if not then another core can do more meaningful work from somewhere else, great! (IE no need to optimize so prematurely.)

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: Range check for type 'Integer'
  2013-06-17 13:45       ` Peter Brooks
@ 2013-06-17 21:16         ` Shark8
  0 siblings, 0 replies; 57+ messages in thread
From: Shark8 @ 2013-06-17 21:16 UTC (permalink / raw)


On Monday, June 17, 2013 7:45:06 AM UTC-6, Peter Brooks wrote:
> On Jun 17, 3:28 pm, Shark8 <onewingedsh...@gmail.com> wrote:
> 
> 
> > I have the beginnings of a toy LISP interpreter here:http://blog.projectpolymath.org/ada-2012-tutorial_01/http://blog.projectpolymath.org/ada-2012-tutorial_02/
> > source --https://github.com/OneWingedShark/Ada_Tutorial
> >
> 
> That is brilliant - thank you very much!

:D - Thank you.
I think that version has only the execution and input/output [working directly with streams] -- I never got around to implementing the "special forms" [conditionals] though.

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: Bug in 'gnatmake' (Was: Range check for type 'Integer')
  2013-06-17 19:15     ` Peter Brooks
  2013-06-17 21:09       ` Shark8
@ 2013-06-17 21:22       ` Jeffrey Carter
  2013-06-18  1:21         ` Peter Brooks
  2013-06-18  7:29       ` Georg Bauhaus
  2 siblings, 1 reply; 57+ messages in thread
From: Jeffrey Carter @ 2013-06-17 21:22 UTC (permalink / raw)



On 06/17/2013 12:15 PM, Peter Brooks wrote:
 >
 > Leaving on range, and other, checking must slow things down a tad, but
 > turning the optimiser on must speed them up. It'll only really matter
 > in CPU intensive stuff, but do you have any idea what the effects are?
 > More or less.

IMO, leaving on checks speeds things up a bit, if you're interested in correct 
code; code without buffer-overflow and integer-overflow vulnerabilities and the 
like. An Ada compiler can optimize away many index checks, for example, which 
doesn't happen to checks manually inserted in a language without automatic 
checks. So it should be the case that correct code in Ada is faster than 
equivalent code in a language without automatic checks.

Of course, if correctness isn't an issue, then things might work otherwise. But 
if correctness isn't an issue, the null program should be an acceptable solution 
to any problem, and that should be just as fast in Ada as in any other language.

 > I know I could just take my code and try it, but it'd be interesting
 > to have a bigger picture of the performance question.

There's always the Ada (83) beats assembler paper:

http://www.seas.gwu.edu/~adagroup/sigada-website/lawlis.html

-- 
Jeff Carter
"Pray that there's intelligent life somewhere up in
space, 'cause there's bugger all down here on earth."
Monty Python's Meaning of Life
61

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: Bug in 'gnatmake' (Was: Range check for type 'Integer')
  2013-06-17 21:22       ` Jeffrey Carter
@ 2013-06-18  1:21         ` Peter Brooks
  2013-06-18  6:33           ` Jeffrey Carter
  0 siblings, 1 reply; 57+ messages in thread
From: Peter Brooks @ 2013-06-18  1:21 UTC (permalink / raw)


On Jun 17, 11:22 pm, Jeffrey Carter
<spam.jrcarter....@spam.not.acm.org> wrote:
> On 06/17/2013 12:15 PM, Peter Brooks wrote:
>  >
>  > Leaving on range, and other, checking must slow things down a tad, but
>  > turning the optimiser on must speed them up. It'll only really matter
>  > in CPU intensive stuff, but do you have any idea what the effects are?
>  > More or less.
>
> IMO, leaving on checks speeds things up a bit, if you're interested in correct
> code; code without buffer-overflow and integer-overflow vulnerabilities and the
> like. An Ada compiler can optimize away many index checks, for example, which
> doesn't happen to checks manually inserted in a language without automatic
> checks. So it should be the case that correct code in Ada is faster than
> equivalent code in a language without automatic checks.
>
> Of course, if correctness isn't an issue, then things might work otherwise. But
> if correctness isn't an issue, the null program should be an acceptable solution
> to any problem, and that should be just as fast in Ada as in any other language.
>
>  > I know I could just take my code and try it, but it'd be interesting
>  > to have a bigger picture of the performance question.
>
> There's always the Ada (83) beats assembler paper:
>
> http://www.seas.gwu.edu/~adagroup/sigada-website/lawlis.html
>
Thank you for that - I'd not read it. It makes the point very well!

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: Bug in 'gnatmake' (Was: Range check for type 'Integer')
  2013-06-18  1:21         ` Peter Brooks
@ 2013-06-18  6:33           ` Jeffrey Carter
  0 siblings, 0 replies; 57+ messages in thread
From: Jeffrey Carter @ 2013-06-18  6:33 UTC (permalink / raw)


On 06/17/2013 06:21 PM, Peter Brooks wrote:
> On Jun 17, 11:22 pm, Jeffrey Carter
> <spam.jrcarter....@spam.not.acm.org> wrote:
>>
>> There's always the Ada (83) beats assembler paper:
>>
>> http://www.seas.gwu.edu/~adagroup/sigada-website/lawlis.html
>>
> Thank you for that - I'd not read it. It makes the point very well!

You might also be interested in "C vs Ada: arguing performance religion" by 
David Syiek of Tartan, /Ada Letters/, 1995 Dec.

"I was to run the well-known "Hennessy" benchmarks through the Tartan Ada C3x 
compiler and compare the results to the ones recendy [sic] computed for 
comparing Tartan C against Texas Instruments C in our sales literature.

"... The geometric means of the ratios shows that Tartan Ada (v5.1) is about 9% 
faster than Tartan C (v2.0) which is in turn about 28% faster than TIC (v4.5)."

https://dl.acm.org/citation.cfm?id=216578.216583&coll=DL&dl=GUIDE&CFID=340838929&CFTOKEN=38294996

-- 
Jeff Carter
"Pray that there's intelligent life somewhere up in
space, 'cause there's bugger all down here on earth."
Monty Python's Meaning of Life
61

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: Bug in 'gnatmake' (Was: Range check for type 'Integer')
  2013-06-17 19:15     ` Peter Brooks
  2013-06-17 21:09       ` Shark8
  2013-06-17 21:22       ` Jeffrey Carter
@ 2013-06-18  7:29       ` Georg Bauhaus
  2 siblings, 0 replies; 57+ messages in thread
From: Georg Bauhaus @ 2013-06-18  7:29 UTC (permalink / raw)


On 17.06.13 21:15, Peter Brooks wrote:
> On Jun 17, 6:50 pm, Robert A Duff <bobd...@shell01.TheWorld.com>
> wrote:
>>
>> You usually want -g (debugging info).  And the debugger works
>> better if you turn off optimizations (-O0).
>>
> Since you mention it, I'm interested to know if there are many Ada
> benchmarks.
  

A current state of affairs is partly reflected in

http://benchmarksgame.alioth.debian.org/u64q/benchmark.php?test=all&lang=gnat&data=u64q

When compiling the programs with aggressive optimization turned on,
suppressing all checks has not always had significant effects.
You can try the above programs with or without -gnatp.

While the benchmark is always changing a bit, and the particulars of
submissions called into question every now and then, the overall
results have been stabilizing. There is no clear winner among the
GCC languages. (It turns out that Intel's Fortran compiler can be hard
to beat on Intel CPUs.)

When differences are large among programs written in a language
that GCC supports, the differences are usually changing the algorithm
slightly. In some cases, though, Ada's type system has good effects
without such changes because it lets us choose scalar types that suit
the problem better, both logically, and hardware-wise.

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Elaboration order handling (Was: Bug in 'gnatmake')
  2013-06-17 18:49   ` Bug in 'gnatmake' Simon Wright
@ 2013-06-18  9:09     ` Jacob Sparre Andersen
  2013-06-18 17:09       ` Robert A Duff
  0 siblings, 1 reply; 57+ messages in thread
From: Jacob Sparre Andersen @ 2013-06-18  9:09 UTC (permalink / raw)


Simon Wright wrote:

> Don't use -gnatE unless you really really want your code to be
> portable to other compilers. You'd need to expend a lot of extra work
> to include pragmas to ensure that elaboration takes place in an
> appropriate order; GNAT does this for you if you leave out -gnatE.

I really really want my code to be portable to other compilers.  (But I
also use Ada 2012, which currently counters that wish.  Feel free to
call me inconsistent.)

And yes, occassionally I spend some time getting elaboration order
right.

Is there a reason the GNAT default elaboration ordering hasn't made its
way into the reference manual?

Greetings,

Jacob
-- 
Photos from the Faroe Islands:
       http://billeder.sparre-andersen.dk/The_Faroe_Islands/


^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: Range check for type 'Integer'
  2013-06-17 12:55   ` Peter Brooks
  2013-06-17 13:28     ` Shark8
@ 2013-06-18 10:48     ` Stephen Leake
  1 sibling, 0 replies; 57+ messages in thread
From: Stephen Leake @ 2013-06-18 10:48 UTC (permalink / raw)


Peter Brooks <peter.h.m.brooks@gmail.com> writes:

>> > Why is there no range check error on type Integer?
>>
> This example is from an on-line
> tutorial.

Can you fix the tutorial to include -gnato? that would lower the
frequency of this question on this newsgroup :).

-- 
-- Stephe


^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: Elaboration order handling (Was: Bug in 'gnatmake')
  2013-06-18  9:09     ` Elaboration order handling (Was: Bug in 'gnatmake') Jacob Sparre Andersen
@ 2013-06-18 17:09       ` Robert A Duff
  2013-06-18 22:52         ` Adam Beneschan
  2013-06-19 13:07         ` Bill Findlay
  0 siblings, 2 replies; 57+ messages in thread
From: Robert A Duff @ 2013-06-18 17:09 UTC (permalink / raw)


Jacob Sparre Andersen <jacob@jacob-sparre.dk> writes:

> Simon Wright wrote:
>
>> Don't use -gnatE unless you really really want your code to be
>> portable to other compilers. You'd need to expend a lot of extra work
>> to include pragmas to ensure that elaboration takes place in an
>> appropriate order; GNAT does this for you if you leave out -gnatE.
>
> I really really want my code to be portable to other compilers.

-gnatE doesn't really help with that.  -gnatE is for porting code
written for other Ada compilers TO GNAT.  (It's also for compiling
ACATS tests that test the standard Ada elaboration rules.)
-gnatE doesn't magically make GNAT use the same order as some
other Ada compiler(s).  We don't even know what algorithm those
compilers use to choose the order, and they're all probably
different.  All we know is that people trying to port code
from one compiler to another have a lot of trouble with elab
order.

If you want your code to be portable, you need to insert pragma
Elaborate_All all over the place.  It's nearly impossible to get that
right by hand, so you should use the GNAT switch that makes it tell you
where Elaborate_All should go.  Don't use -gnatE in this case.

>...(But I
> also use Ada 2012, which currently counters that wish.  Feel free to
> call me inconsistent.)

;-)

> And yes, occassionally I spend some time getting elaboration order
> right.

What do you mean by "right", and how do you know when you have
achieved it?

> Is there a reason the GNAT default elaboration ordering hasn't made its
> way into the reference manual?

I don't think it has ever been seriously considered.  It would be
an incompatible change, unless we made it a user-controlled option.
And it would be a big burden on all those other compilers who
implemented (only) the standard Ada rules.

It is certainly a big language-design flaw that the elab order is
implementation defined.  Ada code tends to be pretty portable for the
most part, but elab order is one of the top issues that cause
non-portability.  That and overuse of representation clauses.

- Bob

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: Elaboration order handling (Was: Bug in 'gnatmake')
  2013-06-18 17:09       ` Robert A Duff
@ 2013-06-18 22:52         ` Adam Beneschan
  2013-06-19  1:21           ` Jeffrey Carter
  2013-06-19 12:22           ` Robert A Duff
  2013-06-19 13:07         ` Bill Findlay
  1 sibling, 2 replies; 57+ messages in thread
From: Adam Beneschan @ 2013-06-18 22:52 UTC (permalink / raw)


On Tuesday, June 18, 2013 10:09:21 AM UTC-7, Robert A Duff wrote:

> It is certainly a big language-design flaw that the elab order is
> implementation defined.  Ada code tends to be pretty portable for the
> most part, but elab order is one of the top issues that cause
> non-portability.  That and overuse of representation clauses.

Yeah, but if they had decided to specify the order instead of leaving it implementation-defined, what order could they have chosen?  Alphabetical?  (Think about what joy that would have caused the ARG when Unicode support was added to the language!!!)  I think the problem is that, unlike some cases (like subprogram parameters, where the language designers *could* have specified left-to-right evaluation instead of implementation-defined order), there's no natural ordering of library packages in a program.  So I don't even see the beginning of a solution.

                               -- Adam

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: Elaboration order handling (Was: Bug in 'gnatmake')
  2013-06-18 22:52         ` Adam Beneschan
@ 2013-06-19  1:21           ` Jeffrey Carter
  2013-06-19 12:38             ` Robert A Duff
  2013-06-19 12:22           ` Robert A Duff
  1 sibling, 1 reply; 57+ messages in thread
From: Jeffrey Carter @ 2013-06-19  1:21 UTC (permalink / raw)


On 06/18/2013 03:52 PM, Adam Beneschan wrote:
>
> Yeah, but if they had decided to specify the order instead of leaving it
> implementation-defined, what order could they have chosen?  Alphabetical?
> (Think about what joy that would have caused the ARG when Unicode support was
> added to the language!!!)  I think the problem is that, unlike some cases
> (like subprogram parameters, where the language designers *could* have
> specified left-to-right evaluation instead of implementation-defined order),
> there's no natural ordering of library packages in a program.  So I don't
> even see the beginning of a solution.

Elaboration order isn't entirely implementation defined, is it? There's a 
partial order defined by calls made during elaboration from one pkg to another. 
Within that ordering there may be groups of pkgs that may be elaborated in any 
order after the pkgs that must be elaborated before them and before the pkgs 
they must be elaborated before. Within those groups, why not use lexical order 
of pkg names?

-- 
Jeff Carter
"Ah, go away or I'll kill ya."
Never Give a Sucker an Even Break
100


^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: Elaboration order handling (Was: Bug in 'gnatmake')
  2013-06-18 22:52         ` Adam Beneschan
  2013-06-19  1:21           ` Jeffrey Carter
@ 2013-06-19 12:22           ` Robert A Duff
  2013-06-19 15:46             ` Adam Beneschan
                               ` (2 more replies)
  1 sibling, 3 replies; 57+ messages in thread
From: Robert A Duff @ 2013-06-19 12:22 UTC (permalink / raw)


Adam Beneschan <adam@irvine.com> writes:

> On Tuesday, June 18, 2013 10:09:21 AM UTC-7, Robert A Duff wrote:
>
>> It is certainly a big language-design flaw that the elab order is
>> implementation defined.  Ada code tends to be pretty portable for the
>> most part, but elab order is one of the top issues that cause
>> non-portability.  That and overuse of representation clauses.
>
> Yeah, but if they had decided to specify the order instead of leaving
> it implementation-defined, what order could they have chosen?
> Alphabetical?

Lexicographic order would work.  Or backwards of that.  Or apply
"rot-13" to the bytes and then do lexicographic order.  ;-)

Or you could base it on the order in which 'with' clauses
happen to appear.

Programmers shouldn't be depending on lexicographic (or whatever) order,
but if they do so by accident, it's best that their program still works
10 years later when it is ported (probably by a different set of
programmers).

>...(Think about what joy that would have caused the ARG
> when Unicode support was added to the language!!!)  I think the
> problem is that, unlike some cases (like subprogram parameters, where
> the language designers *could* have specified left-to-right evaluation
> instead of implementation-defined order), there's no natural ordering
> of library packages in a program.

There's no reason the order has to be "natural".  I'm just saying it
should be the same on all implementations.

The situation with parameters is different:  Allowing the compiler to
choose any order has a disadvantage (portability problems) and an
advantage (efficiency).  There's a tradeoff.  I happen to think
they made the wrong choice, but reasonable people can disagree
on that point.

But with elab order, there is exactly ZERO benefit to allowing
arbitrary orders.  And the disadvantage is huge:  I've seen people
wasting boatloads of money on this!

>...So I don't even see the beginning
> of a solution.

I don't see what the big deal is.  Any legal Ada identifier can be
represented as a Wide_Wide_String, and every Ada 2012 implementation
supports the "<" operator on those.  So one trivial solution is to
simply sort based on that "<", in cases where the current rules about
'with' clauses and pragmas leave the order undefined.

Another solution just occurred to me:  Require the programmer
to put in enough pragmas Elaborate_All (etc) that there is only
one possible order.  Probably not a good idea, but it would
solve the portability problem.

- Bob


^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: Elaboration order handling (Was: Bug in 'gnatmake')
  2013-06-19  1:21           ` Jeffrey Carter
@ 2013-06-19 12:38             ` Robert A Duff
  2013-06-19 20:43               ` Georg Bauhaus
  0 siblings, 1 reply; 57+ messages in thread
From: Robert A Duff @ 2013-06-19 12:38 UTC (permalink / raw)


Jeffrey Carter <spam.jrcarter.not@spam.not.acm.org> writes:

> Elaboration order isn't entirely implementation defined, is it?

No, it's not.

>...There's
> a partial order defined by calls made during elaboration from one pkg to
> another.

In standard Ada, there's a partial order defined by 'with' clauses,
parent/child relationships, and various pragmas.

GNAT takes into account calls made during elaboration, but standard
Ada does not.  And GNAT's rules are necessarily conservative
(see Halting Problem).

>...Within that ordering there may be groups of pkgs that may be
> elaborated in any order after the pkgs that must be elaborated before
> them and before the pkgs they must be elaborated before. Within those
> groups, why not use lexical order of pkg names?

Good idea.  ;-)

It doesn't solve all the problems with Ada's elaboration model,
but it solves the most expensive one (portability).  We'd still
have the problem that the chosen order can be wrong.  And the
fact that programmers have to deal with a bunch of kludgy
pragmas.  And the fact that what should be a compile-time error
is a run-time exception.  And the fact that the order is global,
rather than localized to the children of a single package.

Oh, and the fact that the whole model is overly restrictive.
For example, it makes perfect sense to say:

    package Symbols is
        type Symbol is private;
        function Intern(S: String) return Symbol;
        Empty_Symbol: constant Symbol := Intern(""); -- Wrong!

But that doesn't work in Ada.  It works fine in my hobby
language.  ;-)

- Bob

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: Elaboration order handling (Was: Bug in 'gnatmake')
  2013-06-18 17:09       ` Robert A Duff
  2013-06-18 22:52         ` Adam Beneschan
@ 2013-06-19 13:07         ` Bill Findlay
  1 sibling, 0 replies; 57+ messages in thread
From: Bill Findlay @ 2013-06-19 13:07 UTC (permalink / raw)


On 18/06/2013 18:09, in article wcczjun4a7y.fsf@shell01.TheWorld.com,
"Robert A Duff" <bobduff@shell01.TheWorld.com> wrote:
 
> If you want your code to be portable, you need to insert pragma
> Elaborate_All all over the place.  It's nearly impossible to get that
> right by hand, so you should use the GNAT switch that makes it tell you
> where Elaborate_All should go.  Don't use -gnatE in this case.

Many thanks for that tip, Robert.

I did not know about -gnatwl, and had dozens of Elaborate_All pragmas,
which I now know to have been mostly unnecessary.

-- 
Bill Findlay
with blueyonder.co.uk;
use  surname & forename;

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: Elaboration order handling (Was: Bug in 'gnatmake')
  2013-06-19 12:22           ` Robert A Duff
@ 2013-06-19 15:46             ` Adam Beneschan
  2013-06-19 16:41               ` Robert A Duff
  2013-06-19 20:47               ` Georg Bauhaus
  2013-06-19 21:00             ` Georg Bauhaus
  2013-06-19 22:26             ` Randy Brukardt
  2 siblings, 2 replies; 57+ messages in thread
From: Adam Beneschan @ 2013-06-19 15:46 UTC (permalink / raw)


On Wednesday, June 19, 2013 5:22:30 AM UTC-7, Robert A Duff wrote:

> Lexicographic order would work.  Or backwards of that.  Or apply
> "rot-13" to the bytes and then do lexicographic order.  ;-)

I guess it could work, but I gotta tell you--that seems really weird.  I've never heard of another language where the semantics could depend on the lexicographical order of the identifiers.


> Or you could base it on the order in which 'with' clauses 
> happen to appear.

No, I don't think that would work.  Say there are two packages, Pack1 and Pack2, that get included in the program, and there is no rule (in the current language) that specifies which one gets elaborated first.  Adding a rule based on the "with" clause order would work if Pack1 and Pack2 are both with'ed by the same package, Pack3, and are not with'ed anywhere else.  But other than that one narrow case, I don't see how you could write a rule to base elaboration order on "with" clause order.

                            -- Adam


^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: Elaboration order handling (Was: Bug in 'gnatmake')
  2013-06-19 15:46             ` Adam Beneschan
@ 2013-06-19 16:41               ` Robert A Duff
  2013-06-19 20:47               ` Georg Bauhaus
  1 sibling, 0 replies; 57+ messages in thread
From: Robert A Duff @ 2013-06-19 16:41 UTC (permalink / raw)


Adam Beneschan <adam@irvine.com> writes:

> On Wednesday, June 19, 2013 5:22:30 AM UTC-7, Robert A Duff wrote:
>
>> Lexicographic order would work.  Or backwards of that.  Or apply
>> "rot-13" to the bytes and then do lexicographic order.  ;-)
>
> I guess it could work, but I gotta tell you--that seems really weird.
> I've never heard of another language where the semantics could depend
> on the lexicographical order of the identifiers.

Well, the GNAT dialect of Ada does just that!  Is it weird to have
it in the Ada RM, but not so weird to have it in the GNAT RM?

Yes, it's kind of weird to use that order, but there's no other order
that's any less weird.  What we want is an arbitrary order that is
the same for all compilers.  "Arbitrary" in the sense that we don't
care what the order is, and we don't deliberately write code that
depends on it.

>> Or you could base it on the order in which 'with' clauses 
>> happen to appear.
>
> No, I don't think that would work.  Say there are two packages, Pack1
> and Pack2, that get included in the program, and there is no rule (in
> the current language) that specifies which one gets elaborated first.

The with clauses (and parent/child relationships and so forth) form
a directed graph.  You can define an order in which to walk it
however you like, so long as it's deterministic.  You could say,
start at the main procedure spec.  Walk all of the with'ed specs,
in the order mentioned.  Walk the corresponding body.  ("Walk" is
recursive, of course.  And as usual for graph walks, you keep track
of which nodes have been visited, and if you run across an
already-visited node, do nothing.)

This visits all the library items in a well-defined order, and if all
compilers were required to use that algorithm, it would be a portable
order.  Then you say that whenever the current Ada rules allow
multiple orders, you must choose the order from the above graph-walking
algorithm.

> Adding a rule based on the "with" clause order would work if Pack1 and
> Pack2 are both with'ed by the same package, Pack3, and are not with'ed
> anywhere else.  But other than that one narrow case, I don't see how
> you could write a rule to base elaboration order on "with" clause
> order.

If Pack1 and Pack2 are with-ed elsewhere (than Pack3), then either
that "elsewhere" comes before or after Pack3 in the walk (or some
of each).  Whichever 'with Pack1' you run across first in the walk
is the one that determines where Pack1 occurs in the order.

- Bob


^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: Elaboration order handling (Was: Bug in 'gnatmake')
  2013-06-19 12:38             ` Robert A Duff
@ 2013-06-19 20:43               ` Georg Bauhaus
  2013-06-20  0:37                 ` Robert A Duff
  0 siblings, 1 reply; 57+ messages in thread
From: Georg Bauhaus @ 2013-06-19 20:43 UTC (permalink / raw)


On 19.06.13 14:38, Robert A Duff wrote:

> Oh, and the fact that the whole model is overly restrictive.
> For example, it makes perfect sense to say:
>
>      package Symbols is
>          type Symbol is private;
>          function Intern(S: String) return Symbol;
>          Empty_Symbol: constant Symbol := Intern(""); -- Wrong!
>
> But that doesn't work in Ada.  It works fine in my hobby
> language.  ;-)

Does your hobby language allow separate compilation?




^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: Elaboration order handling (Was: Bug in 'gnatmake')
  2013-06-19 15:46             ` Adam Beneschan
  2013-06-19 16:41               ` Robert A Duff
@ 2013-06-19 20:47               ` Georg Bauhaus
  2013-06-19 21:36                 ` Adam Beneschan
  2013-06-20  0:57                 ` Robert A Duff
  1 sibling, 2 replies; 57+ messages in thread
From: Georg Bauhaus @ 2013-06-19 20:47 UTC (permalink / raw)


On 19.06.13 17:46, Adam Beneschan wrote:
> On Wednesday, June 19, 2013 5:22:30 AM UTC-7, Robert A Duff wrote:
>
>> Lexicographic order would work.  Or backwards of that.  Or apply
>> "rot-13" to the bytes and then do lexicographic order.  ;-)
>
> I guess it could work, but I gotta tell you--that seems really weird.  I've never heard of another language where the semantics could depend on the lexicographical order of the identifiers.

Having had to live with products of programmers favoring symbolic
cleverness, I naturally think of what happens when some project
depend on lexicographical order and then someone wishes to give
packages different names. ARGH!



^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: Elaboration order handling (Was: Bug in 'gnatmake')
  2013-06-19 12:22           ` Robert A Duff
  2013-06-19 15:46             ` Adam Beneschan
@ 2013-06-19 21:00             ` Georg Bauhaus
  2013-06-19 22:26             ` Randy Brukardt
  2 siblings, 0 replies; 57+ messages in thread
From: Georg Bauhaus @ 2013-06-19 21:00 UTC (permalink / raw)


On 19.06.13 14:22, Robert A Duff wrote:
> But with elab order, there is exactly ZERO benefit to allowing
> arbitrary orders.  And the disadvantage is huge:  I've seen people
> wasting boatloads of money on this!

Nevertheless, elaboration control of some sort is a thing that I'd
really like to have available in the languages I need to use every day.
They don't have a notion of elaboration, so I need to just be careful™.
This wastes time, nerves, and money.

Like so: Test effects of current order ... watch traces ... think hard
... iterate.

Lack of elaboration control also puts entire systems at risk once you
run them in an unforeseen situation, let alone port them to a new
environment.

Structurally, the kind of work I need to do in order to establish
an elaboration order that works is much like having to manually
elaborate a scheme of control of shared variables, but without
anything like a protected object.

I known I'm not alone wishing elaboration order were available in
popular languages, but popular languages are of the GTD kind, and
pushed out the door for making quick money, not for saving others'
money (and being payed for that).



^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: Elaboration order handling (Was: Bug in 'gnatmake')
  2013-06-19 20:47               ` Georg Bauhaus
@ 2013-06-19 21:36                 ` Adam Beneschan
  2013-06-20  0:57                 ` Robert A Duff
  1 sibling, 0 replies; 57+ messages in thread
From: Adam Beneschan @ 2013-06-19 21:36 UTC (permalink / raw)


On Wednesday, June 19, 2013 1:47:29 PM UTC-7, Georg Bauhaus wrote:
> On 19.06.13 17:46, Adam Beneschan wrote:
> > On Wednesday, June 19, 2013 5:22:30 AM UTC-7, Robert A Duff wrote:
> 
> >> Lexicographic order would work.  Or backwards of that.  Or apply
> 
> >> "rot-13" to the bytes and then do lexicographic order.  ;-)
> 
> > I guess it could work, but I gotta tell you--that seems really weird.  I've never heard of another language where the semantics could depend on the lexicographical order of the identifiers.
> 
> Having had to live with products of programmers favoring symbolic
> cleverness, I naturally think of what happens when some project
> depend on lexicographical order and then someone wishes to give
> packages different names. ARGH!

Yeah, I thought about that.  It would seem strange to have a program that had been tested suddenly quit working when a programmer decides to change the name of a package, and makes no other change.  That would certainly be a frustrating occurrence.  

On the other hand, the current situation isn't any better.  If you have two packages whose elaboration order isn't defined by the language, the compiler could elaborate them in one order, and then in a future build, could choose the reverse order for whatever reason it chooses.  Depending on the compiler, changing the name of a package could cause that to happen, if (say) that causes an old package name to be removed from the middle of some internal list and then inserted at the end of the list with the new name, which could cause a difference in how the compiler determines the elaboration order.

The more I think about it, the more I think the answer is that the elaboration of library package P should just be prohibited from calling subprograms in another package Q, or accessing variables declared in Q's specification, unless there is an Elaborate(_All) pragma, or unless there's some other reason Q must be elaborated before P (e.g. P's *specification* says "with Q"), or Q is Pure, or perhaps some other things.  Writing the rules to make sure this happens wouldn't be easy.  It probably means that P's elaboration code also can't call a subprogram in P unless that subprogram is also declared as "promising not to call anything outside this package".  There would have to be restrictions on dispatching calls and calls through access-to-subprograms.  I'm not sure this would be a feasible solution.  But to me, having the language defined so that "if the elaboration order is undefined, we'll put restrictions on things so that the order can't possibly matter" seems better, theoretically, than coming up with some unnatural order just so that we can say "something is defined".  That's just my gut feeling.  Since I doubt anyone is really going to think about adding this to Ada, all this is hypothetical until Bob decides to finally define and implement his hobby language.   :-)

                               -- Adam




^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: Elaboration order handling (Was: Bug in 'gnatmake')
  2013-06-19 12:22           ` Robert A Duff
  2013-06-19 15:46             ` Adam Beneschan
  2013-06-19 21:00             ` Georg Bauhaus
@ 2013-06-19 22:26             ` Randy Brukardt
  2013-06-20  0:31               ` Robert A Duff
  2 siblings, 1 reply; 57+ messages in thread
From: Randy Brukardt @ 2013-06-19 22:26 UTC (permalink / raw)


"Robert A Duff" <bobduff@shell01.TheWorld.com> wrote in message 
news:wccip1acmt5.fsf@shell01.TheWorld.com...
...
> I don't see what the big deal is.  Any legal Ada identifier can be
> represented as a Wide_Wide_String, and every Ada 2012 implementation
> supports the "<" operator on those.  So one trivial solution is to
> simply sort based on that "<", in cases where the current rules about
> 'with' clauses and pragmas leave the order undefined.

That doesn't work because Ada identifiers are case-insensitive, while "<" is 
case-sensitive. You could get orders that depend on the case of the 
identifiers, and in fact you could get children coming before parents.

A direct conversion to some specific case doesn't work portably in Unicode 
(because it depends on what version Unicode you are using, while the 
case-insensitive compare is guarenteed to work the same in all versions of 
Unicode).

The net effect is that ordering is not very reliable in case-insensitive 
Unicode identifiers, like Ada's. Cool, huh?

                                                Randy.


^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: Elaboration order handling (Was: Bug in 'gnatmake')
  2013-06-19 22:26             ` Randy Brukardt
@ 2013-06-20  0:31               ` Robert A Duff
  2013-06-20 21:36                 ` Randy Brukardt
  0 siblings, 1 reply; 57+ messages in thread
From: Robert A Duff @ 2013-06-20  0:31 UTC (permalink / raw)


"Randy Brukardt" <randy@rrsoftware.com> writes:

> "Robert A Duff" <bobduff@shell01.TheWorld.com> wrote in message 
> news:wccip1acmt5.fsf@shell01.TheWorld.com...
> ...
>> I don't see what the big deal is.  Any legal Ada identifier can be
>> represented as a Wide_Wide_String, and every Ada 2012 implementation
>> supports the "<" operator on those.  So one trivial solution is to
>> simply sort based on that "<", in cases where the current rules about
>> 'with' clauses and pragmas leave the order undefined.
>
> That doesn't work because Ada identifiers are case-insensitive, while "<" is 
> case-sensitive. You could get orders that depend on the case of the 
> identifiers, 

Groan.  More proof of the theorem, "Nothing is simple."

>...and in fact you could get children coming before parents.

No, no.  All the existing elab-order requirements would still apply.
I'm suggesting only that we'd be better off if the cases where the
current rules allow an implementation-defined order were language
defined.

Certainly a child package spec can't be elaborated before its parent spec!

> A direct conversion to some specific case doesn't work portably in Unicode 
> (because it depends on what version Unicode you are using, while the 
> case-insensitive compare is guarenteed to work the same in all versions of 
> Unicode).

Wait, are you saying that it's impossible to implement a
case-insensitive sort in unicode?  Such a sort is all that's needed
here.

Anyway, there's some "perfect/enemy/good-enough" thing going on here.
Even solving the problem for programs that use only plain-old 7-bit ASCII
would have saved zillions of dollars.

> The net effect is that ordering is not very reliable in case-insensitive 
> Unicode identifiers, like Ada's. Cool, huh?

Bleah.

- Bob

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: Elaboration order handling (Was: Bug in 'gnatmake')
  2013-06-19 20:43               ` Georg Bauhaus
@ 2013-06-20  0:37                 ` Robert A Duff
  2013-06-20 19:56                   ` Georg Bauhaus
  0 siblings, 1 reply; 57+ messages in thread
From: Robert A Duff @ 2013-06-20  0:37 UTC (permalink / raw)


Georg Bauhaus <rm.dash-bauhaus@futureapps.de> writes:

> On 19.06.13 14:38, Robert A Duff wrote:
>
>> Oh, and the fact that the whole model is overly restrictive.
>> For example, it makes perfect sense to say:
>>
>>      package Symbols is
>>          type Symbol is private;
>>          function Intern(S: String) return Symbol;
>>          Empty_Symbol: constant Symbol := Intern(""); -- Wrong!
>>
>> But that doesn't work in Ada.  It works fine in my hobby
>> language.  ;-)
>
> Does your hobby language allow separate compilation?

Yes.

But I don't see how the compilation model ("separate compilation") is
relevant to questions about the elaboration model, which is a run-time
issue.

- Bob


^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: Elaboration order handling (Was: Bug in 'gnatmake')
  2013-06-19 20:47               ` Georg Bauhaus
  2013-06-19 21:36                 ` Adam Beneschan
@ 2013-06-20  0:57                 ` Robert A Duff
  2013-06-20  1:09                   ` Jeffrey Carter
                                     ` (2 more replies)
  1 sibling, 3 replies; 57+ messages in thread
From: Robert A Duff @ 2013-06-20  0:57 UTC (permalink / raw)


Georg Bauhaus <rm.dash-bauhaus@futureapps.de> writes:

> Having had to live with products of programmers favoring symbolic
> cleverness, I naturally think of what happens when some project
> depend on lexicographical order and then someone wishes to give
> packages different names. ARGH!

Of course programmers shouldn't do that (depend on lexicographical
order).  But as I said before, that's already possible with GNAT -- it
uses lexicographical order.  I doubt if anyone depends on that on
purpose, but it's easy to do so by accident.

And with standard Ada, it's even worse: the order can change for any
reason, or for no reason.  The implementation is allowed to roll dice
to determine the order!  Even running the exact same program without
recompiling could change order!

- Bob


^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: Elaboration order handling (Was: Bug in 'gnatmake')
  2013-06-20  0:57                 ` Robert A Duff
@ 2013-06-20  1:09                   ` Jeffrey Carter
  2013-06-20  2:29                     ` Adam Beneschan
  2013-06-20 15:11                     ` Robert A Duff
  2013-06-20  2:11                   ` Elaboration order handling (Was: Bug in 'gnatmake') Adam Beneschan
  2013-06-20 11:24                   ` G.B.
  2 siblings, 2 replies; 57+ messages in thread
From: Jeffrey Carter @ 2013-06-20  1:09 UTC (permalink / raw)


Since we're discussing elaboration order, there's a case that I wonder about:

with B;

package A is
    function F (I : Integer) return B.Thing;

    function R return Integer;
end A;

package body A is
    function F (I : Integer) return B.Thing is
       -- null;
    begin -- F
       return B.To_Thing (I);
    end F;

    function R return Integer is
       -- null;
    begin -- R
       return 7;
    end R;
end A;

package B is
    type Thing is private;

    function To_Thing (I : Integer) return Thing;
private -- B
    type Thing is new Integer;
end B;

with A;

package body B is
    function To_Thing (I : Integer) return Thing is
       -- null;
    begin -- To_Thing
       return Thing (I);
    end To_Thing;

    C : constant Integer := A.R;
end B;

It seems to me there's a valid elaboration order for these:

* spec of B
* spec of A
* body of A
* body of B

I've never been able to get such code to bind, though. Is there some way to get 
this accepted, or is it illegal Ada?

-- 
Jeff Carter
"Now go away or I shall taunt you a second time."
Monty Python & the Holy Grail
07


^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: Elaboration order handling (Was: Bug in 'gnatmake')
  2013-06-20  0:57                 ` Robert A Duff
  2013-06-20  1:09                   ` Jeffrey Carter
@ 2013-06-20  2:11                   ` Adam Beneschan
  2013-06-20 14:44                     ` Robert A Duff
  2013-06-20 11:24                   ` G.B.
  2 siblings, 1 reply; 57+ messages in thread
From: Adam Beneschan @ 2013-06-20  2:11 UTC (permalink / raw)


On Wednesday, June 19, 2013 5:57:35 PM UTC-7, Robert A Duff wrote:

> And with standard Ada, it's even worse: the order can change for any
> reason, or for no reason.  The implementation is allowed to roll dice
> to determine the order!  Even running the exact same program without
> recompiling could change order!

You say that like it's a bad thing.  Actually, I can see a use for a compiler option to use a random number generator to determine the elaboration order (or other things that are implementation-dependent), because if the program relies on the order when it shouldn't, a random order will increase the chance that repeated testing will expose the problem.

                            -- Adam

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: Elaboration order handling (Was: Bug in 'gnatmake')
  2013-06-20  1:09                   ` Jeffrey Carter
@ 2013-06-20  2:29                     ` Adam Beneschan
  2013-06-20  6:08                       ` Jeffrey Carter
  2013-06-20 15:11                     ` Robert A Duff
  1 sibling, 1 reply; 57+ messages in thread
From: Adam Beneschan @ 2013-06-20  2:29 UTC (permalink / raw)


On Wednesday, June 19, 2013 6:09:24 PM UTC-7, Jeffrey Carter wrote:
> Since we're discussing elaboration order, there's a case that I wonder about:
> 
> with B;
> 
> package A is
>     function F (I : Integer) return B.Thing;
> 
>     function R return Integer;
> end A;
> 
> package body A is
>     function F (I : Integer) return B.Thing is
>        -- null;
>     begin -- F
>        return B.To_Thing (I);
>     end F;
> 
>     function R return Integer is
>        -- null;
>     begin -- R
>        return 7;
>     end R;
> 
> end A;
> 
> package B is
>     type Thing is private;
> 
>     function To_Thing (I : Integer) return Thing;
> private -- B
>     type Thing is new Integer;
> end B;
> 
> with A;
> 
> package body B is
>     function To_Thing (I : Integer) return Thing is
>        -- null;
>     begin -- To_Thing
>        return Thing (I);
>     end To_Thing;
> 
>     C : constant Integer := A.R;
> end B;
> 
> It seems to me there's a valid elaboration order for these:
> 
> * spec of B
> * spec of A
> * body of A
> * body of B
> 
> I've never been able to get such code to bind, though. Is there some way to get 
> this accepted, or is it illegal Ada?

It's legal Ada (and should run without raising Program_Error).  It looks like http://docs.adacore.com/gnat-unw-docs/html/gnat_ugn_36.html, especially C.10, discusses this sort of situation, but I don't know if you looked there already.

                                -- Adam


^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: Elaboration order handling (Was: Bug in 'gnatmake')
  2013-06-20  2:29                     ` Adam Beneschan
@ 2013-06-20  6:08                       ` Jeffrey Carter
  0 siblings, 0 replies; 57+ messages in thread
From: Jeffrey Carter @ 2013-06-20  6:08 UTC (permalink / raw)


On 06/19/2013 07:29 PM, Adam Beneschan wrote:
>
> It's legal Ada (and should run without raising Program_Error).  It looks like
> http://docs.adacore.com/gnat-unw-docs/html/gnat_ugn_36.html, especially C.10,
> discusses this sort of situation, but I don't know if you looked there
> already.

No, I hadn't. Thanks for pointing it out. I'd always tried to fix this using 
"pragma Elaborate[_All]" in the context clauses, which always failed. I hadn't 
considered the effect of putting "pragma Elaborate_Body" in the spec of A. With 
that, I can get it to build.

-- 
Jeff Carter
"Now go away or I shall taunt you a second time."
Monty Python & the Holy Grail
07


^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: Elaboration order handling (Was: Bug in 'gnatmake')
  2013-06-20  0:57                 ` Robert A Duff
  2013-06-20  1:09                   ` Jeffrey Carter
  2013-06-20  2:11                   ` Elaboration order handling (Was: Bug in 'gnatmake') Adam Beneschan
@ 2013-06-20 11:24                   ` G.B.
  2013-06-20 15:23                     ` Robert A Duff
  2 siblings, 1 reply; 57+ messages in thread
From: G.B. @ 2013-06-20 11:24 UTC (permalink / raw)


On 20.06.13 02:57, Robert A Duff wrote:
> Georg Bauhaus <rm.dash-bauhaus@futureapps.de> writes:
>
>> Having had to live with products of programmers favoring symbolic
>> cleverness, I naturally think of what happens when some project
>> depend on lexicographical order and then someone wishes to give
>> packages different names. ARGH!
>
> Of course programmers shouldn't do that (depend on lexicographical
> order).

Well, programmers will depend on anything that is known,
more so if the standard defines it. (Like INT_MAX/Max_Int
is 2**31-1, you know...)

However, a configuration pragma for elaboration should be fine?
It says,
  "Take this way of walking the dependency graph"

Stating the way then prevents configuration from being an
implicit consequence of the LRM. It also adds a way of
testing different paths of elaboration.


^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: Elaboration order handling (Was: Bug in 'gnatmake')
  2013-06-20  2:11                   ` Elaboration order handling (Was: Bug in 'gnatmake') Adam Beneschan
@ 2013-06-20 14:44                     ` Robert A Duff
  0 siblings, 0 replies; 57+ messages in thread
From: Robert A Duff @ 2013-06-20 14:44 UTC (permalink / raw)


Adam Beneschan <adam@irvine.com> writes:

> On Wednesday, June 19, 2013 5:57:35 PM UTC-7, Robert A Duff wrote:
>
>> And with standard Ada, it's even worse: the order can change for any
>> reason, or for no reason.  The implementation is allowed to roll dice
>> to determine the order!  Even running the exact same program without
>> recompiling could change order!
>
> You say that like it's a bad thing.

Yes, I do.  ;-)

> Actually, I can see a use for a compiler option to use a random number
> generator to determine the elaboration order (or other things that are
> implementation-dependent), because if the program relies on the order
> when it shouldn't, a random order will increase the chance that
> repeated testing will expose the problem.

Yes, I agree that would be useful.  But only as an option, and only
for testing.

It would be a useful option even if Ada were designed as I've been
saying it should (such that elaboration order is
deterministic/portable).  If the rule was "lexicographic order",
as I have suggested, I still don't think programmers should
depend on lexicographic order, and this option could help
prevent that.

- Bob

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: Elaboration order handling (Was: Bug in 'gnatmake')
  2013-06-20  1:09                   ` Jeffrey Carter
  2013-06-20  2:29                     ` Adam Beneschan
@ 2013-06-20 15:11                     ` Robert A Duff
  2013-06-21  5:26                       ` Jeffrey Carter
  1 sibling, 1 reply; 57+ messages in thread
From: Robert A Duff @ 2013-06-20 15:11 UTC (permalink / raw)


Jeffrey Carter <spam.jrcarter.not@spam.not.acm.org> writes:

> Since we're discussing elaboration order, there's a case that I wonder about:

A case of mutually-recursive packages.  That's unusual, because it's
usually better to design software in layers, where higher layers
use the lower layers, but not vice-versa.

But sometimes such mutually-dependent packages are exactly the
right thing.

> with B;
>
> package A is
>    function F (I : Integer) return B.Thing;
>
>    function R return Integer;
> end A;
>
> package body A is
>    function F (I : Integer) return B.Thing is
>       -- null;
>    begin -- F
>       return B.To_Thing (I);
>    end F;
>
>    function R return Integer is
>       -- null;
>    begin -- R
>       return 7;
>    end R;
> end A;
>
> package B is
>    type Thing is private;
>
>    function To_Thing (I : Integer) return Thing;
> private -- B
>    type Thing is new Integer;
> end B;
>
> with A;
>
> package body B is
>    function To_Thing (I : Integer) return Thing is
>       -- null;
>    begin -- To_Thing
>       return Thing (I);
>    end To_Thing;
>
>    C : constant Integer := A.R;
> end B;

In standard Ada, the above is perfectly legal, and does not
raise Program_Error.

> It seems to me there's a valid elaboration order for these:
>
> * spec of B
> * spec of A
> * body of A
> * body of B

Yes, and that is the only order allowed by the RM.

> I've never been able to get such code to bind, though. Is there some way
> to get this accepted, or is it illegal Ada?

Without -gnatE, GNAT will complain about an elaboration cycle,
because it is inserting an implicit "pragma Elaborate_All(A);"
on the body of B.  It does that because it's trying to preserve
abstraction -- it wants the code to work no matter what
A.R does (it's not looking at the body of A.R while compiling
body of B).  In fact, A.R could have called A.F, in which case
the program is broken -- the only allowed order causes Program_Error
in standard Ada, and the whole point of the not-gnatE mode is
to do all such run-time checks statically.
Imagine adding that call to A.F during maintenance.

And the reason the implicit pragma causes a cycle is that 
Elaborate_All is transitive -- it requires the body of
B to be elaborated before the body of B, which is impossible.

But you've got mutual recursion here, so A and B are necessarily
tightly coupled, and you, the programmer, can know that A.R does
NOT call anything in B.  In that case, you can solve the problem
by putting "pragma Elaborate(A);" on the body of B.  GNAT uses
that Elaborate *instead* of the implicit Elaborate_All, and Elaborate
is nontransitive, so it all works, using the order you showed above.

But be careful:  If you later change A.R to call A.F, you'll be
in trouble.

The other way to get this example to work is to use -gnatE.
I don't recommend that.

- Bob

P.S. I don't like your convention of putting "-- null;" in empty
declarative parts!  Comments should impart useful information,
and empty declarative parts are nothing special, and anyway,
I can see it's empty without a comment.

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: Elaboration order handling (Was: Bug in 'gnatmake')
  2013-06-20 11:24                   ` G.B.
@ 2013-06-20 15:23                     ` Robert A Duff
  0 siblings, 0 replies; 57+ messages in thread
From: Robert A Duff @ 2013-06-20 15:23 UTC (permalink / raw)


"G.B." <rm-dash-bau-haus@dash.futureapps.de> writes:

> Well, programmers will depend on anything that is known,
> more so if the standard defines it. (Like INT_MAX/Max_Int
> is 2**31-1, you know...)

True.  But Ada is supposed to catch errors as early as possible.
The case I'm complaining about here (where the programmer
accidentally depends on the order chosen by some compiler,
when that order is not required by the RM) is not caught at
compile time.  It's not caught at link time.  It's not caught
at run time during testing, nor by your customers.

It's caught 4 years later, when the programmer who made the mistake
is gone, and some other programmer tries to port to a different
Ada compiler.  That's a huge waste of money.

Anyway, the language design should focus on preventing mistakes,
rather than preventing incompetent programmers from doing
damage -- the latter is a fool's errand.

> However, a configuration pragma for elaboration should be fine?
> It says,
>  "Take this way of walking the dependency graph"
>
> Stating the way then prevents configuration from being an
> implicit consequence of the LRM. It also adds a way of
> testing different paths of elaboration.

We already have too many elaboration-control pragmas.  I'm not
sure adding another one is the right approach.

Having said that, GNAT does support something like what you
suggest -- as a switch, not a pragma.

- Bob


^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: Elaboration order handling (Was: Bug in 'gnatmake')
  2013-06-20  0:37                 ` Robert A Duff
@ 2013-06-20 19:56                   ` Georg Bauhaus
  0 siblings, 0 replies; 57+ messages in thread
From: Georg Bauhaus @ 2013-06-20 19:56 UTC (permalink / raw)


On 20.06.13 02:37, Robert A Duff wrote:
> Georg Bauhaus <rm.dash-bauhaus@futureapps.de> writes:
>
>> On 19.06.13 14:38, Robert A Duff wrote:
>>
>>> Oh, and the fact that the whole model is overly restrictive.
>>> For example, it makes perfect sense to say:
>>>
>>>       package Symbols is
>>>           type Symbol is private;
>>>           function Intern(S: String) return Symbol;
>>>           Empty_Symbol: constant Symbol := Intern(""); -- Wrong!
>>>
>>> But that doesn't work in Ada.  It works fine in my hobby
>>> language.  ;-)
>>
>> Does your hobby language allow separate compilation?
>
> Yes.
>
> But I don't see how the compilation model ("separate compilation") is
> relevant to questions about the elaboration model, which is a run-time
> issue.

just wondering how compilation will be unaffected if
- some unit Client references Symbols.Empty_Symbol and
- the latter needs, for its elaboration (if any) the body
   of function Intern,
so that
- when optimizing, inlining, etc., everything needed for
   Intern would be needed, too.




^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: Elaboration order handling (Was: Bug in 'gnatmake')
  2013-06-20  0:31               ` Robert A Duff
@ 2013-06-20 21:36                 ` Randy Brukardt
  0 siblings, 0 replies; 57+ messages in thread
From: Randy Brukardt @ 2013-06-20 21:36 UTC (permalink / raw)


"Robert A Duff" <bobduff@shell01.TheWorld.com> wrote in message 
news:wcc38sd7hch.fsf@shell01.TheWorld.com...
> "Randy Brukardt" <randy@rrsoftware.com> writes:
...
>> A direct conversion to some specific case doesn't work portably in 
>> Unicode
>> (because it depends on what version Unicode you are using, while the
>> case-insensitive compare is guarenteed to work the same in all versions 
>> of
>> Unicode).
>
> Wait, are you saying that it's impossible to implement a
> case-insensitive sort in unicode?  Such a sort is all that's needed
> here.

Of course not. You could do case-folding on each item, and do an ordered 
compare on that. It's well defined, but the ordering might be nonsense for 
some particular (natural) language. (Case-folding is designed for 
case-insensitive equality compares, the ordering is whatever it is.)

> Anyway, there's some "perfect/enemy/good-enough" thing going on here.
> Even solving the problem for programs that use only plain-old 7-bit ASCII
> would have saved zillions of dollars.

True enough. It's unfortunate that the GNAT solution wasn't thought of much 
sooner, nor that we can't seem to find a compatible solution. (But I don't 
think anyone has really tried, either, I don't think this particular issue 
has ever been on the ARG's agenda.)

>> The net effect is that ordering is not very reliable in case-insensitive
>> Unicode identifiers, like Ada's. Cool, huh?
>
> Bleah.

Yeah, Unicode brings its own problems, which are often ignored by its 
proponents. I personally think that programming languages (as opposed to 
program input/output) should stick to 7-bit ASCII, but of course that's 
never been politically possible.

                                              Randy.




^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: Elaboration order handling (Was: Bug in 'gnatmake')
  2013-06-20 15:11                     ` Robert A Duff
@ 2013-06-21  5:26                       ` Jeffrey Carter
  2013-06-21 15:48                         ` Adam Beneschan
  2013-06-21 18:58                         ` null declarative parts (was: Re: Elaboration order handling) Robert A Duff
  0 siblings, 2 replies; 57+ messages in thread
From: Jeffrey Carter @ 2013-06-21  5:26 UTC (permalink / raw)


On 06/20/2013 08:11 AM, Robert A Duff wrote:
>
> P.S. I don't like your convention of putting "-- null;" in empty
> declarative parts!  Comments should impart useful information,
> and empty declarative parts are nothing special, and anyway,
> I can see it's empty without a comment.

The I guess you'd prefer

while Function_With_Side_Effects loop
end loop;

to the Ada requirement that you have to put a null statement in there? I like 
the idea that something that's empty has to have something special in it to show 
that it's deliberately empty, and think it should apply to declarative parts, as 
well.

-- 
Jeff Carter
"I blow my nose on you."
Monty Python & the Holy Grail
03


^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: Elaboration order handling (Was: Bug in 'gnatmake')
  2013-06-21  5:26                       ` Jeffrey Carter
@ 2013-06-21 15:48                         ` Adam Beneschan
  2013-06-21 18:35                           ` Jeffrey Carter
  2013-06-21 18:58                         ` null declarative parts (was: Re: Elaboration order handling) Robert A Duff
  1 sibling, 1 reply; 57+ messages in thread
From: Adam Beneschan @ 2013-06-21 15:48 UTC (permalink / raw)


On Thursday, June 20, 2013 10:26:14 PM UTC-7, Jeffrey Carter wrote:
> On 06/20/2013 08:11 AM, Robert A Duff wrote:
> The I guess you'd prefer
> 
> 
> while Function_With_Side_Effects loop
> 
> end loop;
> 
> to the Ada requirement that you have to put a null statement in there? I like 
> the idea that something that's empty has to have something special in it to show 
> that it's deliberately empty, and think it should apply to declarative parts, as 
> well.
> 

Do you do that with empty parameter lists?

   procedure Proc_1
                    --(null)
                              is
   ...

How about empty constraints?  The definition of <subtype_indication> is [null_exclusion] <subtype_mark> [constraint].  If the constraint is empty, shouldn't you have to put something in there to indicate that it's deliberately empty?

    I : Integer; --null constraint

Obviously this could get ridiculous, and the point is that of course you cannot apply what you're saying consistently.  There are things where showing that you mean for something to be deliberately empty is helpful, and things where it isn't.  And like Bob, I think declarative parts are on the "isn't" side of the line.  My really fuzzy explanation of this is that, intuitively, the body of a procedure or the body of a WHILE loop is a "thing" in and of itself--it's the thing that tells what the procedure does, or the thing that you're looping--while a declarative part isn't so much a thing as a "place"--it's the place where you put declarations, if you have any, but it doesn't really stand on its own merits as a "thing".  It's really hard to explain what I mean.  From a reader's standpoint, I had no idea what you were trying to do.  If you say

   procedure Proc_2 is
       -- null;
   begin
       whatever;
   end;

I'd think that you had originally written Proc_2 as a null procedure and then added a body later, and left the commented-out "null" in as an indication that the procedure used to be null in the previous version.  Your example above had only functions, which just made it all the more confusing since there are no null functions.

                             -- Adam

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: Elaboration order handling (Was: Bug in 'gnatmake')
  2013-06-21 15:48                         ` Adam Beneschan
@ 2013-06-21 18:35                           ` Jeffrey Carter
  2013-06-21 19:10                             ` Robert A Duff
  2013-06-21 20:43                             ` Adam Beneschan
  0 siblings, 2 replies; 57+ messages in thread
From: Jeffrey Carter @ 2013-06-21 18:35 UTC (permalink / raw)


On 06/21/2013 08:48 AM, Adam Beneschan wrote:
> On Thursday, June 20, 2013 10:26:14 PM UTC-7, Jeffrey Carter wrote:
>
> Do you do that with empty parameter lists?
>
> procedure Proc_1
>     --(null)
> is ...
>
> How about empty constraints?  The definition of <subtype_indication> is
> [null_exclusion] <subtype_mark> [constraint].  If the constraint is empty,
> shouldn't you have to put something in there to indicate that it's
> deliberately empty?
>
>     I : Integer; --null constraint

None of those are places the language could require a null statement, so I think 
you're comparing apples to oranges.

(By "statement", I mean something with a terminator semicolon that I count as a 
statement when counting statements, which includes declarations. By "null 
statement" I mean a statement identical to Ada's null statement, even if it's a 
declaration. So, yes, the language could require a null statement in a 
declarative part.)

It appears that the language designers considered declarative regions to be 
different enough from executable regions to require null statements in the 
latter and not the former, and most people go along with that without really 
thinking about it. I thought about it and don't see a significant distinction. 
In NINA (a language probably no one will like but me) a declarative part has to 
have at least one declaration, and "null;" must appear if there are no other 
declarations.

-- 
Jeff Carter
"Sheriff murdered, crops burned, stores looted,
people stampeded, and cattle raped."
Blazing Saddles
35

^ permalink raw reply	[flat|nested] 57+ messages in thread

* null declarative parts (was: Re: Elaboration order handling)
  2013-06-21  5:26                       ` Jeffrey Carter
  2013-06-21 15:48                         ` Adam Beneschan
@ 2013-06-21 18:58                         ` Robert A Duff
  2013-06-21 20:42                           ` null declarative parts Georg Bauhaus
  1 sibling, 1 reply; 57+ messages in thread
From: Robert A Duff @ 2013-06-21 18:58 UTC (permalink / raw)


Jeffrey Carter <spam.jrcarter.not@spam.not.acm.org> writes:

> On 06/20/2013 08:11 AM, Robert A Duff wrote:
>>
>> P.S. I don't like your convention of putting "-- null;" in empty
>> declarative parts!  Comments should impart useful information,
>> and empty declarative parts are nothing special, and anyway,
>> I can see it's empty without a comment.
>
> The I guess you'd prefer
>
> while Function_With_Side_Effects loop
> end loop;

A loop with no statements is something special and rare; the reader's
attention should be drawn to it.  So I don't mind putting "null;".
Empty declarative parts are not special, and are common.

I wouldn't mind if Ada didn't require "null;" in that loop, but
then I'd leave a blank line to make it stand out:

    while Function_With_Side_Effects loop

    end loop;

Or I'd put a comment:

    while Function_With_Side_Effects loop
        -- Nothing to do here.
    end loop;

Or maybe even a comment explaining why there's nothing to do.

I'm not 100% opposed to functions with side effects, but they should
be rare, and the above loop code is therefore dubious.  So it should
stand out.

Certain languages like C and Pascal have an error-prone syntax:

    while (...);
               ^ There's an empty loop body there, but you can't see it!

There are (at least) two ways to fix that:  (1) Require null statements
to be explicit.  (2) Require "end loop", "end if", and so on.
Ada does both, which is a belts and suspenders solution.
I think (2) is a great idea.  As for (1), I can take it or leave it --
shrug.

On a related subject, I would eliminate the "begin" in the middle of
a procedure body, and allow mixing of declarations and statements
without using block statements.  I would ALLOW block statements,
but their syntax would be something like:

    begin
        ... -- statements and declarations
    end;

Since declarations are executable in Ada, it makes no sense to have
a strong separation between the declarations and the statements
of a procedure body (and similar constructs).  That syntax is
a vestige that was inherited from Pascal for no good reason.

> to the Ada requirement that you have to put a null statement in there? I
> like the idea that something that's empty has to have something special
> in it to show that it's deliberately empty, and think it should apply to
> declarative parts, as well.

I don't expect to convince you.  It's largely a matter of taste.
I tried to explain the reasons for my "taste" above.

You probably like the syntax "(null record)" for an empty aggregate;
I would prefer "[]" (with square brackets).  I might leave a blank,
to emphasize its emptiness -- "[ ]" -- but that's as far as I'd go.

- Bob

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: Elaboration order handling (Was: Bug in 'gnatmake')
  2013-06-21 18:35                           ` Jeffrey Carter
@ 2013-06-21 19:10                             ` Robert A Duff
  2013-06-21 21:27                               ` Jeffrey Carter
  2013-06-21 20:43                             ` Adam Beneschan
  1 sibling, 1 reply; 57+ messages in thread
From: Robert A Duff @ 2013-06-21 19:10 UTC (permalink / raw)


Jeffrey Carter <spam.jrcarter.not@spam.not.acm.org> writes:

> (By "statement", I mean something with a terminator semicolon that I
> count as a statement when counting statements, which includes
> declarations. By "null statement" I mean a statement identical to Ada's
> null statement, even if it's a declaration. So, yes, the language could
> require a null statement in a declarative part.)

Interesting.  You are very close to agreeing with me that statements and
declarations are more-or-less the same thing (syntactically), and
wherever one is allowed, so should the other.  What's wrong with
statements in a package spec (or body decl part)?  If you allow "null;"
in a declarative part, then why not allow an assignment statement, or a
procedure call?  And if you do that, there's no point at all to the
"begin" that appears in the middle of a procedure body.

Once in a while, I want to initialize an object using statements,
because the "X: T := ...;" syntax doesn't work for some reason.

    package body P is
        X : ...;

        package Dummy is end;
        package body Dummy is
        begin
            for I in ... loop
                X(I) := ...;
            end loop;
        end Dummy;
        ... -- 1000 more lines of code

That extra Dummy package doesn't aid readability.  The other choice,
moving the initialization way down into the "begin...end P;" part
is also bad, because the initialization is far away from the
declaration, and there's lots of opportunity to use uninitialized
variables in between.

- Bob

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: null declarative parts
  2013-06-21 18:58                         ` null declarative parts (was: Re: Elaboration order handling) Robert A Duff
@ 2013-06-21 20:42                           ` Georg Bauhaus
  0 siblings, 0 replies; 57+ messages in thread
From: Georg Bauhaus @ 2013-06-21 20:42 UTC (permalink / raw)


On 21.06.13 20:58, Robert A Duff wrote:

> You probably like the syntax "(null record)" for an empty aggregate;
> I would prefer "[]" (with square brackets).  I might leave a blank,
> to emphasize its emptiness -- "[ ]" -- but that's as far as I'd go.

One meaning of [] is good, many meanings are bad.

[]-s added for null records would, I fear, (1) increase the puzzlement
of programmers in the popular languages market where we regularly
need to learn "new" languages that have [] but differ about its meaning.
(Just wasted 3 hours on forgetting that a deletion operator applied
to a [] (a list) and an index will remove the element, but not
the slot (will not splice), which is unlike what it does with
a table and an "index". Which is unlike what it does to whatever
[] means in C++, and don't mix that with Python, Javascript,
or the list notations of MLispThica.)

(2) A SIGCSE paper convincingly argues (against PL Turing) that it
is a good thing to have [] and {} and other brackets besides () to
denote different things, unlike Ada. But I'd hope that the used of
[] converges to only one or two commonly accepted meanings of [].





^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: Elaboration order handling (Was: Bug in 'gnatmake')
  2013-06-21 18:35                           ` Jeffrey Carter
  2013-06-21 19:10                             ` Robert A Duff
@ 2013-06-21 20:43                             ` Adam Beneschan
  2013-06-21 21:44                               ` Jeffrey Carter
  1 sibling, 1 reply; 57+ messages in thread
From: Adam Beneschan @ 2013-06-21 20:43 UTC (permalink / raw)


On Friday, June 21, 2013 11:35:28 AM UTC-7, Jeffrey Carter wrote:
> On 06/21/2013 08:48 AM, Adam Beneschan wrote:

> None of those are places the language could require a null statement, so I think 
> you're comparing apples to oranges.
> 
> (By "statement", I mean something with a terminator semicolon that I count as a 
> statement when counting statements, which includes declarations. By "null 
> statement" I mean a statement identical to Ada's null statement, even if it's a 
> declaration.

All you said was "I like the idea that something that's empty has to have something special in it to show that it's deliberately empty."  You didn't say that that applied only to things ending in a semicolon.  Don't blame me for "comparing apples to oranges" when all you said was "fruit".


> So, yes, the language could require a null statement in a  
> declarative part.)

Well, it could have, prior to Ada 2005.  That's no longer possible, because of null procedures.


> It appears that the language designers considered declarative regions to be  
> different enough from executable regions to require null statements in the 
> latter and not the former, and most people go along with that without really 
> thinking about it. I thought about it and don't see a significant distinction. 

Then why do you want a separate declarative part at all?  Many popular languages these days don't separate the two, and let you put declarations anywhere you can put a code statement, or even in the middle of another statement.  So if you don't see a significant distinction, why not be consistent?

                          -- Adam

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: Elaboration order handling (Was: Bug in 'gnatmake')
  2013-06-21 19:10                             ` Robert A Duff
@ 2013-06-21 21:27                               ` Jeffrey Carter
  0 siblings, 0 replies; 57+ messages in thread
From: Jeffrey Carter @ 2013-06-21 21:27 UTC (permalink / raw)


On 06/21/2013 12:10 PM, Robert A Duff wrote:
 >
 > Interesting.  You are very close to agreeing with me that statements and
> declarations are more-or-less the same thing (syntactically), and
> wherever one is allowed, so should the other.  What's wrong with
> statements in a package spec (or body decl part)?  If you allow "null;"
> in a declarative part, then why not allow an assignment statement, or a
> procedure call?  And if you do that, there's no point at all to the
> "begin" that appears in the middle of a procedure body.

I've seen code in languages that allow mixing of declarations and executable 
statements, and I didn't like it. Maybe this is because I'm used to Ada (and 
Pascal before it), but I found it difficult to find a declaration when I needed 
to. (Tools can help, but are not always available; since I don't use these 
languages, I wasn't using tools when I looked at them.)

> Once in a while, I want to initialize an object using statements,
> because the "X: T := ...;" syntax doesn't work for some reason.
>
>      package body P is
>          X : ...;
>
>          package Dummy is end;
>          package body Dummy is
>          begin
>              for I in ... loop
>                  X(I) := ...;
>              end loop;
>          end Dummy;
>          ... -- 1000 more lines of code
>
> That extra Dummy package doesn't aid readability.  The other choice,
> moving the initialization way down into the "begin...end P;" part
> is also bad, because the initialization is far away from the
> declaration, and there's lots of opportunity to use uninitialized
> variables in between.

The "X : T := ...;" syntax almost always works if the initialization expression 
is a function call:

package body P is
    function Initialize_X return T is ...

    X : T := Initialize_X;

I built some default-initialized types with fairly complex initialization in 
Ada-83 using such functions, which is why I didn't think Ada-95 really needed 
user-defined initialization. Finalization was another matter.

-- 
Jeff Carter
"Sheriff murdered, crops burned, stores looted,
people stampeded, and cattle raped."
Blazing Saddles
35

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: Elaboration order handling (Was: Bug in 'gnatmake')
  2013-06-21 20:43                             ` Adam Beneschan
@ 2013-06-21 21:44                               ` Jeffrey Carter
  2013-06-21 23:47                                 ` Robert A Duff
  0 siblings, 1 reply; 57+ messages in thread
From: Jeffrey Carter @ 2013-06-21 21:44 UTC (permalink / raw)


On 06/21/2013 01:43 PM, Adam Beneschan wrote:
>
> All you said was "I like the idea that something that's empty has to have
> something special in it to show that it's deliberately empty."  You didn't
> say that that applied only to things ending in a semicolon.  Don't blame me
> for "comparing apples to oranges" when all you said was "fruit".

True enough. It seemed obvious to me, but obviously wasn't.

> Well, it could have, prior to Ada 2005.  That's no longer possible, because
> of null procedures.

Ah, yes, another unnecessary shortcut.

> Then why do you want a separate declarative part at all?  Many popular
> languages these days don't separate the two, and let you put declarations
> anywhere you can put a code statement, or even in the middle of another
> statement.  So if you don't see a significant distinction, why not be
> consistent?

I addressed this in detail in a reply to Duff. Basically, I find it hard to find 
a specific declaration when reading such languages.

-- 
Jeff Carter
"Sheriff murdered, crops burned, stores looted,
people stampeded, and cattle raped."
Blazing Saddles
35


^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: Elaboration order handling (Was: Bug in 'gnatmake')
  2013-06-21 21:44                               ` Jeffrey Carter
@ 2013-06-21 23:47                                 ` Robert A Duff
  2013-06-23 14:43                                   ` AdaMagica
  0 siblings, 1 reply; 57+ messages in thread
From: Robert A Duff @ 2013-06-21 23:47 UTC (permalink / raw)


Jeffrey Carter <spam.jrcarter.not@spam.not.acm.org> writes:

> On 06/21/2013 01:43 PM, Adam Beneschan wrote:
>> Well, it could have, prior to Ada 2005.  That's no longer possible, because
>> of null procedures.
>
> Ah, yes, another unnecessary shortcut.

It is important to the way interfaces work that procedures can be known
to do nothing on their SPEC.  I suppose it would be possible to allow
"is begin null; end;" on the spec, but that would be more complicated
-- requires either special syntax rules, or special semantic rules.

So "is null;" makes sense for that.

It is also useful for optimization purposes for procedures to be
known to do nothing.  E.g. Finalize defaults to doing nothing,
so a type that does not override Finalize can be optimized to avoid
finalization overhead, without looking at bodies of non-visible things.

> I addressed this in detail in a reply to Duff. Basically, I find it hard
> to find a specific declaration when reading such languages.

It takes some getting used to, but I don't find it onerous.  You already
need to search for things in Ada as it is -- the declaration could be in
some outer block or procedure or parent package or some use-claused
package.

And in some cases, it makes it EASIER to find the declaration, because it
comes just before.  Compare:

        X, Y : T;
        Init (X, Y);
        ... -- 100 lines
    begin

versus:

        X, Y : T;
        ... -- 100 lines
    begin
        Init (X, Y); -- far away from X and Y

- Bob


^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: Elaboration order handling (Was: Bug in 'gnatmake')
  2013-06-21 23:47                                 ` Robert A Duff
@ 2013-06-23 14:43                                   ` AdaMagica
  0 siblings, 0 replies; 57+ messages in thread
From: AdaMagica @ 2013-06-23 14:43 UTC (permalink / raw)


>         X, Y : T;
>         Init (X, Y);
>         ... -- 100 lines
>     begin
>
> versus:
>
>         X, Y : T;
>         ... -- 100 lines
>     begin
>         Init (X, Y); -- far away from X and Y

I'm quite astonished about this kind of discussion... I would say a declare block like this is very very bad style. I cannot imagine some code where 100 lines to declare things are needed which could not be reformulated in some other way.

You can always come up with some fancy code to demonstrate some obscure case which would never go thru in real life - I'd reject such a code in an inspection.

And I like null statements and (null record); and IIRC steelman or some other ...man said empty parentheses and empty blocks look very much like something was forgotten, so either dont write them (subprograms without params) or put null inside as an indication there actually is nothing. (Of course you can still forget something.)

Ada is wordy (eloquent, talkative, garrulous) by deliberation...


^ permalink raw reply	[flat|nested] 57+ messages in thread

end of thread, other threads:[~2013-06-23 14:43 UTC | newest]

Thread overview: 57+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-06-17 10:57 Range check for type 'Integer' Peter Brooks
2013-06-17 11:23 ` Simon Clubley
2013-06-17 11:54   ` Simon Wright
2013-06-17 12:55   ` Peter Brooks
2013-06-17 13:28     ` Shark8
2013-06-17 13:45       ` Peter Brooks
2013-06-17 21:16         ` Shark8
2013-06-18 10:48     ` Stephen Leake
2013-06-17 12:46 ` Dmitry A. Kazakov
2013-06-17 13:23 ` Bug in 'gnatmake' (Was: Range check for type 'Integer') Jacob Sparre Andersen
2013-06-17 13:32   ` Bug in 'gnatmake' Jacob Sparre Andersen
2013-06-17 16:50   ` Bug in 'gnatmake' (Was: Range check for type 'Integer') Robert A Duff
2013-06-17 19:15     ` Peter Brooks
2013-06-17 21:09       ` Shark8
2013-06-17 21:22       ` Jeffrey Carter
2013-06-18  1:21         ` Peter Brooks
2013-06-18  6:33           ` Jeffrey Carter
2013-06-18  7:29       ` Georg Bauhaus
2013-06-17 18:49   ` Bug in 'gnatmake' Simon Wright
2013-06-18  9:09     ` Elaboration order handling (Was: Bug in 'gnatmake') Jacob Sparre Andersen
2013-06-18 17:09       ` Robert A Duff
2013-06-18 22:52         ` Adam Beneschan
2013-06-19  1:21           ` Jeffrey Carter
2013-06-19 12:38             ` Robert A Duff
2013-06-19 20:43               ` Georg Bauhaus
2013-06-20  0:37                 ` Robert A Duff
2013-06-20 19:56                   ` Georg Bauhaus
2013-06-19 12:22           ` Robert A Duff
2013-06-19 15:46             ` Adam Beneschan
2013-06-19 16:41               ` Robert A Duff
2013-06-19 20:47               ` Georg Bauhaus
2013-06-19 21:36                 ` Adam Beneschan
2013-06-20  0:57                 ` Robert A Duff
2013-06-20  1:09                   ` Jeffrey Carter
2013-06-20  2:29                     ` Adam Beneschan
2013-06-20  6:08                       ` Jeffrey Carter
2013-06-20 15:11                     ` Robert A Duff
2013-06-21  5:26                       ` Jeffrey Carter
2013-06-21 15:48                         ` Adam Beneschan
2013-06-21 18:35                           ` Jeffrey Carter
2013-06-21 19:10                             ` Robert A Duff
2013-06-21 21:27                               ` Jeffrey Carter
2013-06-21 20:43                             ` Adam Beneschan
2013-06-21 21:44                               ` Jeffrey Carter
2013-06-21 23:47                                 ` Robert A Duff
2013-06-23 14:43                                   ` AdaMagica
2013-06-21 18:58                         ` null declarative parts (was: Re: Elaboration order handling) Robert A Duff
2013-06-21 20:42                           ` null declarative parts Georg Bauhaus
2013-06-20  2:11                   ` Elaboration order handling (Was: Bug in 'gnatmake') Adam Beneschan
2013-06-20 14:44                     ` Robert A Duff
2013-06-20 11:24                   ` G.B.
2013-06-20 15:23                     ` Robert A Duff
2013-06-19 21:00             ` Georg Bauhaus
2013-06-19 22:26             ` Randy Brukardt
2013-06-20  0:31               ` Robert A Duff
2013-06-20 21:36                 ` Randy Brukardt
2013-06-19 13:07         ` Bill Findlay

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox