comp.lang.ada
 help / color / mirror / Atom feed
* how to do things like procedure foo(A: string) is bar: string := A; begin; ...;end;
@ 2017-12-16 20:56 Mehdi Saada
  2017-12-16 21:49 ` Jeffrey R. Carter
  2017-12-18  6:39 ` Robert Eachus
  0 siblings, 2 replies; 12+ messages in thread
From: Mehdi Saada @ 2017-12-16 20:56 UTC (permalink / raw)


DATA being strings components of the records LEFT and RIGHT, is the expression (LEFT.DATA & RIGHT.DATA)'Range possible ?
I try to implement something like
procedure foo(A: string) is
   bar: string := A;
begin
...
end;
but A'Length isn't known at compilation. In fact I want to use bar only like a macro, to avoid puting things like LEFT.DATA & RIGHT.DATA everywhere and not being able to use attributes (Range, length & co).


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

* Re: how to do things like procedure foo(A: string) is bar: string := A; begin; ...;end;
  2017-12-16 20:56 how to do things like procedure foo(A: string) is bar: string := A; begin; ...;end; Mehdi Saada
@ 2017-12-16 21:49 ` Jeffrey R. Carter
  2017-12-17 12:40   ` Mehdi Saada
  2017-12-18  6:39 ` Robert Eachus
  1 sibling, 1 reply; 12+ messages in thread
From: Jeffrey R. Carter @ 2017-12-16 21:49 UTC (permalink / raw)


On 12/16/2017 09:56 PM, Mehdi Saada wrote:
> I try to implement something like
> procedure foo(A: string) is
>     bar: string := A;
> begin
> ...
> end;

I'm not clear what you're asking, but this is legal Ada. Bar gets its bounds 
from its initialization expression. I presume that you want to call it with

Foo (A => Left.Data & Right.Data);

which is also legal. If the only reason for Foo is to have a shorter name, you 
can also do

declare
    Bar : String := Left.Data & Right.Data;
begin
    ...
end;

-- 
Jeff Carter
"[T]he [Agile] idea that it's bad to spend an
appropriate time at the beginning of the project
to clarify the overall requirements and design
is nonsense."
Bertrand Meyer
149


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

* Re: how to do things like procedure foo(A: string) is bar: string := A; begin; ...;end;
  2017-12-16 21:49 ` Jeffrey R. Carter
@ 2017-12-17 12:40   ` Mehdi Saada
  2017-12-17 13:25     ` Jere
                       ` (2 more replies)
  0 siblings, 3 replies; 12+ messages in thread
From: Mehdi Saada @ 2017-12-17 12:40 UTC (permalink / raw)


Fine. It means a variable's bounds must be known at initizialisation, not compilation ? I had a boggus idea of what "static" means, or when it's necessary. A boggus idea of how the whole head + stack works. I'm still not sure, but it does simplify writing things a lot.
Thanks.


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

* Re: how to do things like procedure foo(A: string) is bar: string := A; begin; ...;end;
  2017-12-17 12:40   ` Mehdi Saada
@ 2017-12-17 13:25     ` Jere
  2017-12-17 13:49       ` Jere
  2017-12-17 13:51     ` Jeffrey R. Carter
  2017-12-18 22:22     ` Randy Brukardt
  2 siblings, 1 reply; 12+ messages in thread
From: Jere @ 2017-12-17 13:25 UTC (permalink / raw)


On Sunday, December 17, 2017 at 7:41:02 AM UTC-5, Mehdi Saada wrote:
> Fine. It means a variable's bounds must be known at initizialisation, not compilation ? I had a boggus idea of what "static" means, or when it's necessary. A boggus idea of how the whole head + stack works. I'm still not sure, but it does simplify writing things a lot.
> Thanks.

I don't write compilers, but there are different ways to attack that problem.  
My guess is that when Foo is called and has an unconstrained String type, then 
the compiler probably pushes the length of the String to the stack as well as 
the string itself (or perhaps the string object stores it for unconstrained 
strings..again...don't know the implementations used).  Then inside of Foo when 
it goes to allocate stack space, it can use those fields to calculate how much 
stack it needs for the local string vars that are initialized.  There honestly 
might be a completely different implementation (perhaps Randy or another 
compiler writer can chime in), but the point is there are ways for it to be 
done.

Now if constrained subtypes of String are used:

type Name_String is String(1..10);
procedure foo(L,R : Name_String);

Then everything can be done at compile time.

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

* Re: how to do things like procedure foo(A: string) is bar: string := A; begin; ...;end;
  2017-12-17 13:25     ` Jere
@ 2017-12-17 13:49       ` Jere
  0 siblings, 0 replies; 12+ messages in thread
From: Jere @ 2017-12-17 13:49 UTC (permalink / raw)


On Sunday, December 17, 2017 at 8:25:11 AM UTC-5, Jere wrote:
> On Sunday, December 17, 2017 at 7:41:02 AM UTC-5, Mehdi Saada wrote:
> > Fine. It means a variable's bounds must be known at initizialisation, not compilation ? I had a boggus idea of what "static" means, or when it's necessary. A boggus idea of how the whole head + stack works. I'm still not sure, but it does simplify writing things a lot.
> > Thanks.
> 
> type Name_String is String(1..10);
> procedure foo(L,R : Name_String);
> 
> Then everything can be done at compile time.

sorry, subtype Name_String, not type Name_String

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

* Re: how to do things like procedure foo(A: string) is bar: string := A; begin; ...;end;
  2017-12-17 12:40   ` Mehdi Saada
  2017-12-17 13:25     ` Jere
@ 2017-12-17 13:51     ` Jeffrey R. Carter
  2017-12-18 22:22     ` Randy Brukardt
  2 siblings, 0 replies; 12+ messages in thread
From: Jeffrey R. Carter @ 2017-12-17 13:51 UTC (permalink / raw)


On 12/17/2017 01:40 PM, Mehdi Saada wrote:
> Fine. It means a variable's bounds must be known at initizialisation, not compilation ? I had a boggus idea of what "static" means, or when it's necessary. A boggus idea of how the whole head + stack works. I'm still not sure, but it does simplify writing things a lot.

For unconstrained array types, the bounds of an object can be determined at run 
time. This applies equally to explicit bounds like

S : String (3 .. N);

where N is not known until run time, or bounds obtained from an initialization 
expression not known until run time.

"Static" basically means known at compile time. (The actual definition in the 
ARM is more complicated, but this will work fine in most cases.)

What you're really dealing with here is the subtype of the object. These are 
equivalent to

subtype anonymous is String (3 .. N);
S : anonymous;

and

anonymous_c : constant String := Initialization_Expression;
subtype anonymous is String (anonymous_c'range);
S : anonymous := anonymous_c;

Subtypes need not be static.

-- 
Jeff Carter
"When Roman engineers built a bridge, they had to stand under it
while the first legion marched across. If programmers today
worked under similar ground rules, they might well find
themselves getting much more interested in Ada!"
Robert Dewar
62


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

* Re: how to do things like procedure foo(A: string) is bar: string := A; begin; ...;end;
  2017-12-16 20:56 how to do things like procedure foo(A: string) is bar: string := A; begin; ...;end; Mehdi Saada
  2017-12-16 21:49 ` Jeffrey R. Carter
@ 2017-12-18  6:39 ` Robert Eachus
  2017-12-18 15:34   ` Mehdi Saada
  2017-12-19 22:52   ` Robert Eachus
  1 sibling, 2 replies; 12+ messages in thread
From: Robert Eachus @ 2017-12-18  6:39 UTC (permalink / raw)


On Saturday, December 16, 2017 at 3:56:45 PM UTC-5, Mehdi Saada wrote:
> DATA being strings components of the records LEFT and RIGHT, is the expression (LEFT.DATA & RIGHT.DATA)'Range possible ?
> I try to implement something like
> procedure foo(A: string) is
>    bar: string := A;
> begin
> ...
> end;
> but A'Length isn't known at compilation. In fact I want to use bar only like a macro, to avoid puting things like LEFT.DATA & RIGHT.DATA everywhere and not being able to use attributes (Range, length & co).

There is no problem with your example.  There is a potential (mental) gotcha if you concatenate a character or a null string literal to the beginning of another string literal.  A bit of thinking should tell you that such strings begin at 1, not Integer'First, and the last is Left.Data'First + Right.Data'Length.

If your subprogram Foo has an unconstrained String parameter (yours does) then the bounds of A are the bounds of the actual argument, and can be different on every call.  If you have a constrained String (i.e. String(6..15) or whatever) then inside Foo the bounds are those of the formal parameter.  If the LENGTHS of (constrained) formal and actual don't match, Constraint_Error will be raised.

As I said, there is not a problem in Ada--but everyone will eventually run into a couple of bugs because they unthinkingly assumed that the actual for the unconstrained formal starts at 1.

So now if you see something like:

   function Foo(S: String) return String is
   begin
     if S'Length < 80
     then return "" & S;
     else...

You will have a clue what is going on. ;-)


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

* Re: how to do things like procedure foo(A: string) is bar: string := A; begin; ...;end;
  2017-12-18  6:39 ` Robert Eachus
@ 2017-12-18 15:34   ` Mehdi Saada
  2017-12-18 17:31     ` Anh Vo
  2017-12-18 21:14     ` Robert Eachus
  2017-12-19 22:52   ` Robert Eachus
  1 sibling, 2 replies; 12+ messages in thread
From: Mehdi Saada @ 2017-12-18 15:34 UTC (permalink / raw)


I got it pretty early (was clear in the course) that array, and strings for the matter, can have arbitrary bounds. So with unconstrained formal parameters I always use 'LENGHT, 'First and 'Last, and no 'Range in for loop.
But your "" & S was mind-boggling... It does have the effect of changings bounds without touching the content. Very useful, thanks !
Not sure about the constrained formal parameter part. What happens when you call something like
function FOO(T: String range 5..9) return String;
with a parameter whose index subtype's bounds are say, 1..4 ? You say it would raise Constraint_Error ? If so I can see the point. There's never too much facultative checks.


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

* Re: how to do things like procedure foo(A: string) is bar: string := A; begin; ...;end;
  2017-12-18 15:34   ` Mehdi Saada
@ 2017-12-18 17:31     ` Anh Vo
  2017-12-18 21:14     ` Robert Eachus
  1 sibling, 0 replies; 12+ messages in thread
From: Anh Vo @ 2017-12-18 17:31 UTC (permalink / raw)


On Monday, December 18, 2017 at 7:34:50 AM UTC-8, Mehdi Saada wrote:
> I got it pretty early (was clear in the course) that array, and strings for the matter, can have arbitrary bounds. So with unconstrained formal parameters I always use 'LENGHT, 'First and 'Last, and no 'Range in for loop.

It must be your typo of 'Length. Otherwise, the compiler will reject your code for sure.

Anh Vo


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

* Re: how to do things like procedure foo(A: string) is bar: string := A; begin; ...;end;
  2017-12-18 15:34   ` Mehdi Saada
  2017-12-18 17:31     ` Anh Vo
@ 2017-12-18 21:14     ` Robert Eachus
  1 sibling, 0 replies; 12+ messages in thread
From: Robert Eachus @ 2017-12-18 21:14 UTC (permalink / raw)


On Monday, December 18, 2017 at 10:34:50 AM UTC-5, Mehdi Saada wrote:
 
> Not sure about the constrained formal parameter part. What happens when you call something like
> function FOO(T: String range 5..9) return String;
> with a parameter whose index subtype's bounds are say, 1..4 ? You say it would raise Constraint_Error ? If so I can see the point. There's never too much facultative checks.

Yes, the bounds don't have to match, but the lengths do. (I hope the different lengths were not a typo.)  However, there is another problem.  Way, way back subroutine parameters were changed to eliminate range constraints.  You can say:

subtype PS is String range(1..4);
subtype TS is String range(5..9);
procedure Foo(T: TS);
...
Foo(PS); --raises Constraint_Error
Foo('X' & PS); -- OK.

But:
procedure Foo(T: String range 5..9)...  -- will fail at compile time.

Why were formal parameters changed to eliminate (syntatic) constraints?  They didn't accomplish much other than to confuse users.  You can get the same effect by using explicit subtype declarations--as above--if you want it.  Making things explicit helps both reader and programmer in those cases.


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

* Re: how to do things like procedure foo(A: string) is bar: string := A; begin; ...;end;
  2017-12-17 12:40   ` Mehdi Saada
  2017-12-17 13:25     ` Jere
  2017-12-17 13:51     ` Jeffrey R. Carter
@ 2017-12-18 22:22     ` Randy Brukardt
  2 siblings, 0 replies; 12+ messages in thread
From: Randy Brukardt @ 2017-12-18 22:22 UTC (permalink / raw)


"Mehdi Saada" <00120260a@gmail.com> wrote in message 
news:1e659202-ab0b-44a5-9549-3e41fa465ab4@googlegroups.com...
>Fine. It means a variable's bounds must be known at initizialisation, not 
>compilation ?
> I had a boggus idea of what "static" means, or when it's necessary.

"Static" means (approximately) "determinable at compile-time". And it is 
rarely necessary (mostly for type declarations [but not subtype 
declarations] and representation clauses). The vast majority of things allow 
any legal expression of the correct type.

                                       Randy.




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

* Re: how to do things like procedure foo(A: string) is bar: string := A; begin; ...;end;
  2017-12-18  6:39 ` Robert Eachus
  2017-12-18 15:34   ` Mehdi Saada
@ 2017-12-19 22:52   ` Robert Eachus
  1 sibling, 0 replies; 12+ messages in thread
From: Robert Eachus @ 2017-12-19 22:52 UTC (permalink / raw)


On Monday, December 18, 2017 at 1:39:40 AM UTC-5, Robert Eachus wrote:
>  A bit of thinking should tell you that such strings begin at 1, not Integer'First, and the last is Left.Data'First + Right.Data'Length.

Oops! Editing error:  ...Left.Data'Length + Right.Data'Length...

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

end of thread, other threads:[~2017-12-19 22:52 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-12-16 20:56 how to do things like procedure foo(A: string) is bar: string := A; begin; ...;end; Mehdi Saada
2017-12-16 21:49 ` Jeffrey R. Carter
2017-12-17 12:40   ` Mehdi Saada
2017-12-17 13:25     ` Jere
2017-12-17 13:49       ` Jere
2017-12-17 13:51     ` Jeffrey R. Carter
2017-12-18 22:22     ` Randy Brukardt
2017-12-18  6:39 ` Robert Eachus
2017-12-18 15:34   ` Mehdi Saada
2017-12-18 17:31     ` Anh Vo
2017-12-18 21:14     ` Robert Eachus
2017-12-19 22:52   ` Robert Eachus

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