comp.lang.ada
 help / color / mirror / Atom feed
* Record aggregates assignments and the black-box and else
@ 2010-05-07 21:23 Yannick Duchêne (Hibou57)
  2010-05-09  0:25 ` Randy Brukardt
  2010-05-10 15:20 ` Adam Beneschan
  0 siblings, 2 replies; 4+ messages in thread
From: Yannick Duchêne (Hibou57) @ 2010-05-07 21:23 UTC (permalink / raw)


Hi Ada novellers,


I've just had a quick check at the RM, to review what is the exact meaning  
of the black-box in aggregates assignment which are not initialization. I  
was to check if the black-box in this context (all but initialization),  
stands for the actual value or the default value defined in the record's  
full view declaration.

Well, it seems this always stands for the default value, not for the  
actually assigned value of the corresponding members.

[ARM 2005 4.3.1(19.1/2)]
> For a record_component_association with <>, if the component_declaration
> has a default_expression, that default_expression defines the value for
> the associated component(s); otherwise, the associated component(s) are
> initialized by default as for a stand-alone object of the component
> subtype (see 3.3.1).

I did not test on any compiler, as I wanted an answer from the standard's  
point of view.

So the following

    type Record_Type is record
       A : Natural := 1;
       B : Natural := 2;
    end record;

    ...

    R : Record_Type;

    ...

    R.A := 3;

    ...

    R := (A => <>, B => 5)

is expected to result in Record_Type'(A => 1, B => 5);

Now let's come to the reason why I was checking about this.

What I like with the aggregates assignments, is that the compiler will  
shout to wake you up as soon as you forget to think about the value of a  
member (particularly relevant if ever some members are added, this avoid  
you the bad story of out-of-date text sections).

But what about the efficiency of this construct when it is to be used on a  
record which has some members already fixed and which should not change ?

As said above, I like the aggregate assignment as a conscientious  
assignment where you assert you've though about each members in turn and  
none was sadly forgotten (a taste of safety).

If I do :

    R := (A => R.A, B => 5);

what is the most likely expected impact on the executable code efficiency,  
providing this kind of construct oftenly appears in multiple places of the  
source ? (the record type is obviously private and just accessed in the  
implementation).

Do you think most compilers will use the presence of an R's self component  
as an hint for some kind of optimization when applicable ?

-- 
No-no, this isn't an oops ...or I hope (TM) - Don't blame me... I'm just  
not lucky



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

* Re: Record aggregates assignments and the black-box and else
  2010-05-07 21:23 Record aggregates assignments and the black-box and else Yannick Duchêne (Hibou57)
@ 2010-05-09  0:25 ` Randy Brukardt
  2010-05-10 15:20 ` Adam Beneschan
  1 sibling, 0 replies; 4+ messages in thread
From: Randy Brukardt @ 2010-05-09  0:25 UTC (permalink / raw)


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 1090 bytes --]

"Yannick Duch�ne (Hibou57)" <yannick_duchene@yahoo.fr> wrote in message 
news:op.vcctpljtxmjfy8@garhos...
...
> If I do :
>
>    R := (A => R.A, B => 5);
>
> what is the most likely expected impact on the executable code efficiency, 
> providing this kind of construct oftenly appears in multiple places of the 
> source ? (the record type is obviously private and just accessed in the 
> implementation).
>
> Do you think most compilers will use the presence of an R's self component 
> as an hint for some kind of optimization when applicable ?

I can't speak for "most compilers", but Janus/Ada does this optimization (it 
will just assign R.B). The Janus/Ada compiler is full of aggregates like 
this, where "B" is a discriminant of the record. The only legal way to 
change the discriminant is a full record aggregate, and thus we have a lot 
of similar aggregates (our original compiler didn't enforce the not 
assigning of a discriminant, and the source got infested by such changes). 
Therefore, we have special-cased this assignment.

                                 Randy.





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

* Re: Record aggregates assignments and the black-box and else
  2010-05-07 21:23 Record aggregates assignments and the black-box and else Yannick Duchêne (Hibou57)
  2010-05-09  0:25 ` Randy Brukardt
@ 2010-05-10 15:20 ` Adam Beneschan
  2010-05-10 19:03   ` Yannick Duchêne (Hibou57)
  1 sibling, 1 reply; 4+ messages in thread
From: Adam Beneschan @ 2010-05-10 15:20 UTC (permalink / raw)


On May 7, 2:23 pm, Yannick Duchêne (Hibou57)
<yannick_duch...@yahoo.fr> wrote:

> If I do :
>
>     R := (A => R.A, B => 5);
>
> what is the most likely expected impact on the executable code efficiency,  
> providing this kind of construct oftenly appears in multiple places of the  
> source ? (the record type is obviously private and just accessed in the  
> implementation).
>
> Do you think most compilers will use the presence of an R's self component  
> as an hint for some kind of optimization when applicable ?

This isn't as simple as it looks.  The language semantics demand that
for an aggregate, the program creates a temporary object of the type
whose value is the aggregage; then it assigns R to that temporary
object.  One consequence is that if an exception is raised while
building the temporary object, R will be unaffected.  (There are
exceptions.  If controlled types are involved, I think that compilers
are allowed or required to generate code that builds the aggregate
directly in R instead of using a temporary object.  Also, if
Record_Type were limited, you couldn't do the assignment, but an
aggregate in some other contexts would *not* cause a temporary object
to be built.  I don't feel like going into details right now.)

I'm not sure what happens in a case like this:

   R := (A => R.A, B => 5);

where R was previously uninitialized.  Even though R.A is supposed to
have subtype "Natural", if it's uninitialized and thus garbage, it
could have a negative value.  Thus, it's possible that this
assignment, which is conceptually part of the assignment that creates
the temporary object:

   Temp_Object.A := R.A;

could raise an exception if R.A happened to have a garbage negative
value.  However, I don't think compilers are required to generate code
that checks this.  Since both sides are supposed to be "Natural", the
compiler can do the assignment without any checking, and is not
required to check that the value on the right side is valid.

Anyway, assuming that the compiler determines that R.A will not raise
an exception, and that B => 5 cannot raise an exception either, and
there aren't any other reasons why R has to be preserved while the
temporary object is being created, it might decide that there's no
reason to create a temporary object.  This is permissible since the
semantics would be exactly the same in all cases.  Then it's
conceivable that the compiler could generate code that looks like

   R.A := R.A;
   R.B := 5;

and then, in its optimization process, notice that the first
assignment is useless.  So it's possible that a compiler may optimize
the code in the way you were suggesting.  However, the compiler does
need to do a fair amount of checking to determine that a temp object
is unneeded, and there may be compilers that don't do all that work.

So I guess the answer to your question is probably that some compilers
will optimize the way you want, and others won't.

                                   -- Adam



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

* Re: Record aggregates assignments and the black-box and else
  2010-05-10 15:20 ` Adam Beneschan
@ 2010-05-10 19:03   ` Yannick Duchêne (Hibou57)
  0 siblings, 0 replies; 4+ messages in thread
From: Yannick Duchêne (Hibou57) @ 2010-05-10 19:03 UTC (permalink / raw)


Le Mon, 10 May 2010 17:20:08 +0200, Adam Beneschan <adam@irvine.com> a  
écrit:
> where R was previously uninitialized.  Even though R.A is supposed to
> have subtype "Natural", if it's uninitialized and thus garbage, it
> could have a negative value.  Thus, it's possible that this
> assignment, which is conceptually part of the assignment that creates
> the temporary object:
>
>    Temp_Object.A := R.A;
>
> could raise an exception if R.A happened to have a garbage negative
> value.
What should be involved here, is access to uninitialized value rather than  
range-check error. Unfortunately, I don't know a way to achieve this in  
Ada (except with some GNAT pragma which requires to initialize scalars so  
as to be sure it will later raise a range-check error if it was not  
properly initialized... still indirect)

> Anyway, assuming that the compiler determines that R.A will not raise
> an exception, and that B => 5 cannot raise an exception either, and
> there aren't any other reasons why R has to be preserved while the
> temporary object is being created, it might decide that there's no
> reason to create a temporary object.  This is permissible since the
> semantics would be exactly the same in all cases.  Then it's
> conceivable that the compiler could generate code that looks like
I agree with you about this semantic equivalence.


-- 
No-no, this isn't an oops ...or I hope (TM) - Don't blame me... I'm just  
not lucky



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

end of thread, other threads:[~2010-05-10 19:03 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-05-07 21:23 Record aggregates assignments and the black-box and else Yannick Duchêne (Hibou57)
2010-05-09  0:25 ` Randy Brukardt
2010-05-10 15:20 ` Adam Beneschan
2010-05-10 19:03   ` Yannick Duchêne (Hibou57)

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