deferred constants

182 views
Skip to first unread message

Matt Borchers

unread,
Jul 7, 2021, 3:31:34 PM7/7/21
to
Is it possible to define a constant in a package body that has it's initialization deferred to elaboration?

For example...

with Gnat.RegExp;
package body
pat : constant Gnat.RegExp.RegExp;
begin
pat := Gnat.RegExp.compile( "..." );
end;

Obviously it is not strictly necessary to create 'pat' as a constant, but it is ideal to define symbols as precise as possible. Without it being a constant, the compiler will obviously not check to make sure someone has not inadvertently overwritten it.

GNAT gives me the following errors:
- constant declaration requires initialization expression
- deferred constant is frozen before completion

The first error message is not true, but comes from the fact that the second IS true. Is there a way to postpone the freezing of a symbol until after elaboration?

Jeffrey R. Carter

unread,
Jul 7, 2021, 4:40:27 PM7/7/21
to
On 7/7/21 9:31 PM, Matt Borchers wrote:
> Is it possible to define a constant in a package body that has it's initialization deferred to elaboration?
>
> with Gnat.RegExp;
> package body
> pat : constant Gnat.RegExp.RegExp;
> begin
> pat := Gnat.RegExp.compile( "..." );
> end;

Deferred constants are defined in ARM 7.4
(http://www.ada-auth.org/standards/rm12_w_tc1/html/RM-7-4.html), which says they
may only appear in the visible part of a pkg spec, and the full declaration must
appear in the private part of the same pkg. So what you're trying is illegal.

In cases like this, you declare the object as a variable, with comments
indicating that it is set later and is then constant.

of course, in the example, one can simply do

Pat : constant Gnat.RegExp.RegExp := Gnat.RegExp.Compile ( "..." );

but there are cases where this is not possible.

--
Jeff Carter
"He had no conception of the instrument. He
was blowing into it."
Take the Money and Run
135

Stephen Leake

unread,
Jul 7, 2021, 4:41:15 PM7/7/21
to
Matt Borchers <mattbo...@gmail.com> writes:

> Is it possible to define a constant in a package body that has it's
> initialization deferred to elaboration?

No. It must be a variable.

> For example...
>
> with Gnat.RegExp;
> package body
> pat : constant Gnat.RegExp.RegExp;
> begin
> pat := Gnat.RegExp.compile( "..." );
> end;

What's wrong with this:

with Gnat.RegExp;
package body
pat : constant Gnat.RegExp.RegExp := Gnat.RegExp.compile( "..." );
end;


--
-- Stephe

Shark8

unread,
Jul 7, 2021, 4:44:33 PM7/7/21
to
Use RENAMES?

pat : Gnat.RegExp.RegExp renames Gnat.RegExp.compile( "..." );

Other than this, I would advise not using RegEx.

Matt Borchers

unread,
Jul 7, 2021, 7:15:43 PM7/7/21
to
Of course comments help, but the compiler does not enforce what is written in comments. (That I'm aware of.)
The fact that the example uses RegExp doesn't matter, it was just code I ran across and the example could be anything. BTW, what's wrong with Gnat.RegExp? It has worked in our code for years.

I was looking at old code and began wondering if there was a new or better way to add protection to this entity. It appears not when it is defined in the elaboration block.

I suppose I could just move the call to 'compile' out of the begin block of the package as people have suggested. At what point do constants defined by a function call get elaborated? Before or after the elaboration block? Might I then potentially encounter a elaboration race condition?

The RENAME is interesting as I have not seen that before. Is it a rename of the function call (invokes the function upon reference) or a rename of the function result?

Matt

Shark8

unread,
Jul 7, 2021, 7:37:23 PM7/7/21
to
On Wednesday, July 7, 2021 at 5:15:43 PM UTC-6, Matt Borchers wrote:
> Of course comments help, but the compiler does not enforce what is written in comments. (That I'm aware of.)
> The fact that the example uses RegExp doesn't matter, it was just code I ran across and the example could be anything. BTW, what's wrong with Gnat.RegExp? It has worked in our code for years.
Regular expressions are for regular languages; it is very easy to violate that restriction with your incoming data.
Most of my professional career has been doing maintenance, and RegEx are *terrible* when it comes to maintainability, to the point that I actively avoid them and advise others to as well, even for things that conceptually *could* be done via RegEx (e.g. recognizing an Integer) in favor of actual parsing... or if you need pattern-matching, something more robust like SNOBOL.

> I was looking at old code and began wondering if there was a new or better way to add protection to this entity. It appears not when it is defined in the elaboration block.
> I suppose I could just move the call to 'compile' out of the begin block of the package as people have suggested. At what point do constants defined by a function call get elaborated? Before or after the elaboration block? Might I then potentially encounter a elaboration race condition?
This is where the categorization pragmas/aspects come in: if a package that you are depending on are PURE or PREELABORATE then there can be no elaboration error. If the type you are relying on is PREELABORABLE_INITIALIZATION, then there can be no elaboration error. All other conditions are a solid *maybe* on having an elaboration error.

> The RENAME is interesting as I have not seen that before. Is it a rename of the function call (invokes the function upon reference) or a rename of the function result?
That form of RENAMES is the function result.
I've found it an excellent alternative to CONSTANT, as it signals my intent to have an alias for some result inside DECLARE blocks and certain internal objects. (eg Default_Map : Map renames Internal_Map_Generation(P1, P2); ... and then I can use "Default_Map" instead of calling the generation-function at each point and possibly messing things up should the parameters change.)

Stephen Leake

unread,
Jul 7, 2021, 9:21:44 PM7/7/21
to
Matt Borchers <mattbo...@gmail.com> writes:

> I suppose I could just move the call to 'compile' out of the begin
> block of the package as people have suggested. At what point do
> constants defined by a function call get elaborated? Before or after
> the elaboration block? Might I then potentially encounter a
> elaboration race condition?

The Ada rules guarrantee no race condition, but sometimes fixing
elaboration order gets tricky. GNAT offers (at least) two elaboration
models; see the user guide. Normally, you just write the code, and only
worry about elaboration if the compiler reports a problem.

> The RENAME is interesting as I have not seen that before. Is it a
> rename of the function call (invokes the function upon reference) or a
> rename of the function result?

The result; if the rename was in a block in a loop, the function be run
once for each iteration of the loop.

--
-- Stephe

Maxim Reznik

unread,
Jul 8, 2021, 10:18:43 AM7/8/21
to
Just write a constant declaration. It will be initialized at elaboration time.

package body Pks is

Thomas

unread,
Jul 6, 2022, 12:18:52 PMJul 6
to
In article <a6e2e912-8aa6-4ecf...@googlegroups.com>,
Shark8 <onewing...@gmail.com> wrote:

> On Wednesday, July 7, 2021 at 5:15:43 PM UTC-6, Matt Borchers wrote:

> > BTW, what's wrong with
> > Gnat.RegExp? It has worked in our code for years.

> Regular expressions are for regular languages; it is very easy to violate
> that restriction with your incoming data.
> Most of my professional career has been doing maintenance, and RegEx are
> *terrible* when it comes to maintainability, to the point that I actively
> avoid them and advise others to as well, even for things that conceptually
> *could* be done via RegEx (e.g. recognizing an Integer) in favor of actual
> parsing... or if you need pattern-matching, something more robust like
> SNOBOL.

interesting :-)

is it easy to integrate it in an ada program?
i'm thinking about AdaControl, which (if i'm right) uses RegEx a lot.


>
> > The RENAME is interesting as I have not seen that before. Is it a rename of
> > the function call (invokes the function upon reference) or a rename of the
> > function result?
> That form of RENAMES is the function result.
> I've found it an excellent alternative to CONSTANT, as it signals my intent
> to have an alias for some result inside DECLARE blocks and certain internal
> objects. (eg Default_Map : Map renames Internal_Map_Generation(P1, P2); ...
> and then I can use "Default_Map" instead of calling the generation-function
> at each point and possibly messing things up should the parameters change.)

why renames is better than constant in this case ?
could you explicit the difference between them, please?

--
RAPID maintainer
http://savannah.nongnu.org/projects/rapid/

J-P. Rosen

unread,
Jul 6, 2022, 1:56:48 PMJul 6
to
Le 06/07/2022 à 18:18, Thomas a écrit :
>> or if you need pattern-matching, something more robust like
>> SNOBOL.
> interesting:-)
I think AdaCore has (or used to have) a Snobol package. Snobol was
invented by Robert Dewar...

> is it easy to integrate it in an ada program?
> i'm thinking about AdaControl, which (if i'm right) uses RegEx a lot.
>
AdaControl uses Gnat.Regexp


--
J-P. Rosen
Adalog
2 rue du Docteur Lombard, 92441 Issy-les-Moulineaux CEDEX
Tel: +33 1 45 29 21 52
https://www.adalog.fr

Jeffrey R.Carter

unread,
Jul 6, 2022, 3:11:04 PMJul 6
to
On 2022-07-06 19:56, J-P. Rosen wrote:
> I think AdaCore has (or used to have) a Snobol package. Snobol was invented by
> Robert Dewar...

SNOBOL was created by Farber,Griswold, and Polonsky in the 1960s. Dewar and
Belcher wrote the SPITBOL compiler in the 1970s. GNAT comes with the
GNAT.Spitbol.* packages for SNOBOL-like pattern matching.

--
Jeff Carter
"Monsieur Arthur King, who has the brain of a duck, you know."
Monty Python & the Holy Grail
09

Randy Brukardt

unread,
Jul 6, 2022, 8:44:16 PMJul 6
to
"Thomas" <fantome.foru...@free.fr.invalid> wrote in message
news:62c5b5e9$0$22251$426a...@news.free.fr...
In theory, a renames captures the function result object, so for a composite
type, you avoid copying it. That can be especially significant for
controlled types, where you avoid an extra Finalization (and that might be
critical if you are implementing Finalize). I believe there also are some
accessibility differences that might matter in unusual cases.

In most cases, however, they are essentially the same, generating
essentially the same code. So it is a matter of preference which to pick. (I
usually use "constant" unless avoiding a copy is necessary.)

Randy.


J-P. Rosen

unread,
Jul 7, 2022, 1:51:02 AMJul 7
to
Le 06/07/2022 à 21:11, Jeffrey R.Carter a écrit :
> On 2022-07-06 19:56, J-P. Rosen wrote:
>> I think AdaCore has (or used to have) a Snobol package. Snobol was
>> invented by Robert Dewar...
>
> SNOBOL was created by Farber,Griswold, and Polonsky in the 1960s. Dewar
> and Belcher wrote the SPITBOL compiler in the 1970s. GNAT comes with the
> GNAT.Spitbol.* packages for SNOBOL-like pattern matching.
>

Right. I'm always confused which is which...

Thomas

unread,
Jul 11, 2022, 1:45:56 PMJul 11
to
In article <ta5a8t$5vnn$1...@dont-email.me>,
"Randy Brukardt" <ra...@rrsoftware.com> wrote:

> "Thomas" <fantome.foru...@free.fr.invalid> wrote in message
> news:62c5b5e9$0$22251$426a...@news.free.fr...
> > In article <a6e2e912-8aa6-4ecf...@googlegroups.com>,
> > Shark8 <onewing...@gmail.com> wrote:
> >> > The RENAME is interesting as I have not seen that before. Is it a
> >> > rename of
> >> > the function call (invokes the function upon reference) or a rename of
> >> > the
> >> > function result?
> >> That form of RENAMES is the function result.
> >> I've found it an excellent alternative to CONSTANT, as it signals my
> >> intent
> >> to have an alias for some result inside DECLARE blocks and certain
> >> internal
> >> objects. (eg Default_Map : Map renames Internal_Map_Generation(P1, P2);

> >
> > why renames is better than constant in this case ?
> > could you explicit the difference between them, please?
>
> In theory, a renames captures the function result object, so for a composite
> type, you avoid copying it. That can be especially significant for
> controlled types, where you avoid an extra Finalization

yes, i remember that i had to use a renames with a limited type :-)



> I believe there also are some
> accessibility differences that might matter in unusual cases.

> it is a matter of preference which to pick. (I
> usually use "constant" unless avoiding a copy is necessary.)

(i don't know if that's the case of "some accessibility differences": )

i don't like that constant keyword is forbidden in a renames.


i find it less readable when the pointed object is constant,
since it is not remembered at the point of the renames, and one could
think that it can be changed.
in other words, at the review time we have to check at the source of the
renames to know if it is constant or not.


moreover, when the pointed object is variable,
constant keyword in a renames could mean that the variable could not be
modified when used with the "constant renames" identifier.

i understand that it conflicts with the rule: "the constant keyword
means that the value never changes"

i suppose that some people already thought about that ...

but i don't understant what kind of pb there can be with the 1st case,
so i would find nice to have the constant keyword when the pointed
object is one, even if it stay forbidden in the other case.



(sorry for my english, I did not sleep well)

Thomas

unread,
Jul 11, 2022, 1:49:26 PMJul 11
to
In article <ta4icu$3hjj$1...@dont-email.me>,
"J-P. Rosen" <ro...@adalog.fr> wrote:

> Le 06/07/2022 à 18:18, Thomas a écrit :
> >> or if you need pattern-matching, something more robust like
> >> SNOBOL.
> > interesting:-)
> I think AdaCore has (or used to have) a Snobol package. Snobol was
> invented by Robert Dewar...
>
> > is it easy to integrate it in an ada program?
> > i'm thinking about AdaControl, which (if i'm right) uses RegEx a lot.
> >
> AdaControl uses Gnat.Regexp

do you have sth against SPITBOL?
do you disagree Shark8 ?

or is it because no one asked for it, or no time for that?

J-P. Rosen

unread,
Jul 12, 2022, 1:13:38 AMJul 12
to
Le 11/07/2022 à 19:49, Thomas a écrit :
>> AdaControl uses Gnat.Regexp
> do you have sth against SPITBOL?No, but
1) Regexp is sufficient for my needs
2) I don't want my users to have to learn Spitbol. Everybody knows
regexp (at least the simple forms).

Randy Brukardt

unread,
Jul 12, 2022, 2:54:48 AMJul 12
to
"Thomas" <fantome.foru...@free.fr.invalid> wrote in message
news:62cc61d1$0$22254$426a...@news.free.fr...
....
> i find it less readable when the pointed object is constant,
> since it is not remembered at the point of the renames, and one could
> think that it can be changed.
> in other words, at the review time we have to check at the source of the
> renames to know if it is constant or not.

With a renames, you *always* have to check the original object, since the
properties specified in the renames are ignored in most cases. You *will*
get in trouble if you pay attention to them. That's one reason for
minimizing the use of renames (if your program can afford a copy, a copy is
almost always safer anyway, and when it isn't you have to avoid aliasing and
thus avoid renames).


> moreover, when the pointed object is variable,
> constant keyword in a renames could mean that the variable could not be
> modified when used with the "constant renames" identifier.
>
> i understand that it conflicts with the rule: "the constant keyword
> means that the value never changes"

This is a False statement for Ada, (the details are painful), it's true for
elementary types and some others, but not most composite types.

> i suppose that some people already thought about that ...

I don't recall anyone proposing this, but given the way renames works, it
would either be useless or different from everything else.

That's because a rename ignores the properties declared with it and use the
ones of the actual object. In particular, things like subtypes are not used
at all for a rename - even if specified. If you care about those things, you
need to use a constant. :-)

It would have been better if Ada had used some sort of matching rule, but
Ada 83 did not have static matching, and it was too incompatible to
introduce it in Ada 95, and that will not change.

> but i don't understant what kind of pb there can be with the 1st case,
> so i would find nice to have the constant keyword when the pointed
> object is one, even if it stay forbidden in the other case.

No problem, per se, just completely different than the current model of
renames.

If you think this is important, you should submit something via the new
Community Input site. (Not announced yet, but should be working - it's in
beta now, so if it fails, we need to know that.) See arg.adaic.org.

Randy.


G.B.

unread,
Jul 12, 2022, 10:45:03 AMJul 12
to
On 12.07.22 07:13, J-P. Rosen wrote:
> Le 11/07/2022 à 19:49, Thomas a écrit :
> >> AdaControl uses Gnat.Regexp
> > do you have sth against SPITBOL?No, but
> 1) Regexp is sufficient for my needs
> 2) I don't want my users to have to learn Spitbol.

Learning Spitbol is great fun, though!

> Everybody knows regexp (at least the simple forms).

Everybody thinks they know regex (at least the simple forms)... ;-)

Reply all
Reply to author
Forward
0 new messages