comp.lang.ada
 help / color / mirror / Atom feed
* Reconsidering assignment
@ 2007-06-06 21:33 Maciej Sobczak
  2007-06-06 22:52 ` Ray Blaak
                   ` (2 more replies)
  0 siblings, 3 replies; 69+ messages in thread
From: Maciej Sobczak @ 2007-06-06 21:33 UTC (permalink / raw)


My discussion with Dmitry in another thread looked as if completely
abandoned by everybody, so I decided to start a new thread.

As a short recap, my point was that assignment of T'Class should be
banned. Dmitry has challenged me with analogies to regular
unconstrained types where my construct fell apart.
After some rethinking of the whole issue I believe I have something
reasonably consistent.
Here it goes.

First of all, the motivation.
The motivation is to create (at least in theory) a type system where
CONSTRAINT_ERROR can be raised only in those places where explicit
conversions are required. In other words, whenever an implicit
conversion is allowed, it must follow that the absence of constraint
error can be statically provable. This makes sense in high-integrity
systems, because the places of potentially raised exceptions are
distinguished in source code.
The motivation is also to have a system that is consistent enough to
cover both unconstrained types and class-wide types - these are
similar enough to give them consistent treatment.

<disclaimer>
I'm learning Ada for about one year. I'm still missing the proper
terminology, so please bring me on track whenever I go astray - but
remember that I'm writing here about some hypothetical Ada-like-but-
better language, not about Ada2005. This allows me to get away with
some terminology details. ;-)
</disclaimer>

Some important foundations.
A type can be unconstrained/constrained. It can be also a subtype of
another type, adding some more constraints. An important observation
is that the value-space and constraint-space might be or might not be
equivalent within the given type. This distinction will be needed
later to justify handling of various fundamental constructs.

I will consider three different types that quite widely represent what
we can have in Ada, and reconsider the examples from my previous posts
(and those of Dmitry):
- Integer (any number type, actually) as a type that has equivalent
value-space and constraint-space.
- String as a type that has different (although inclusive) value- and
constraint-spaces.
- Tagged types and class-wide types.

1. Integer and its subtypes (like Positive).
An Integer object has some value - and only that. Any subtype of
Integer is defined within the same space, which means that this only
thing that Integer has is also subject for the constraint check. In
other words, *every* modification of the Integer (or subtype of)
object is potentially violating the constraint.

Consider:

procedure P1(X : in Integer);
procedure P2(X : out Positive);
procedure Swap(X, Y : in out Integer);

declare
  X : Integer := -1;
  Y : Positive := 1;
begin
  P1(X); -- (1) OK (matching)
  P1(Y); -- (1) OK (actual is stricter)
  P2(Y); -- (2) OK (matching)
  P2(X); -- (2) OK (actual is wider)
  Swap(X, Y); -- (3) compile-time error on second parameter
end;

The call at (3) should banned. For types that have equivalent value-
and constraint- spaces, the rules for parameter passing are as
follows:
1. "in" formal parameters can get actual parameters that have
constraints matching or stricter
2. "out" formal parameters can get actual parameters that have
constraints matching or wider
3. "in out" formal parameters can only get actual parameters that have
matching constraints.

Any violation of these rules leads to potential constraint error that
cannot be prevented at compile-time.

2. String.
Unconstrained array types have different value- and constraint-spaces
(in the sense that they can have many different values within the same
constraint). This means that there is a whole class of modifications
that can be statically proven not to involve the constraint.
Consider:

procedure To_Upper(S : in out String);

Such a procedure is perfectly reasonable.
What is not reasonable is this:

procedure Swap(X, Y : in out String);

The problem comes from the fact that the two formal parameters could
be initialized with actual parameters that have different constraints.
This alone is not yet a problem (and we have to allow this
signature!), but the body of Swap would have to contain some
operations that potentially violate the constraint of each actual
parameter. Potentially - meaning that run-time error could be raised.
The solution is to introduce the concept of restricted parameters.
Consider:

procedure Safe_Swap(X, Y : in out String) with X'Length = Y'Length;

The restriction says that this procedure can be called only with
actual parameters that have the same length. There is still a lot we
can do in the body (remember that value-space is different that
constraint-space), but the safety can be protected at the call-site.
Even statically:

declare
  S1 : String := "abc";
  S2 : String := "xyz";
  S3 : String := "klmnop";
begin
  Safe_Swap(S1, S2); -- OK
  Safe_Swap(S1, S3); -- compile-time error
  Safe_Swap(S1, S3(1..3)); -- OK
end;

Now is the time to bring the assignment.
The rule is simple: the language provides the assignment operation
with restriction that its parameters must have equal constraint, if
there are any.
This allows to actually implement the Safe_Swap body!

3. Tagged types.
I promised that this construct will consistently cover tagged types.
Notice that for class-wide types that value-space and constraint-space
are different, similarly to unconstrained arrays, and *unlike* number
types.
This means that there is a room for modifications that don't involve
constraint, so we can and should allow in out T'Class. For example,
the geometry package might have the Object type with some hypothetical
"center" coordinates and the primitive operation Move that can move
around the plane whatever specific figure we throw at it:

procedure Move(A : in out Object'Class; DX, DY : in Real);

This can work without modifying the constraint (tag), so should be
allowed.
But the naive Swap procedure should not be allowed - I mean, the
signature is OK, but there is no way to implement it.
We can have this instead:

procedure Safe_Swap(X, Y : in out Object'Class) with X'Tag = Y'Tag;

declare
  T1 : Triangle := ...;
  T2 : Triangle := ...;
  C : Circle := ...;
begin
  Safe_Swap(T1, T2); -- OK
  Safe_Swap(T1, C); -- compile-time error
end;

Again, the language offers the assignment operation with similar
signature (that is, restricted). This can be even inherited,
dispatching, whatever. But has to be restricted, because T'Class is
(sort of) unconstrained type:

declare
  T1 : Triangle := ...;
  T2 : Triangle := ...;
  C : Circle := ...;
begin
  T1 := T2; -- OK
  C := T1; -- compile-time error (violating the restriction)
end;

Of course, programmers can provide their own assignment overloads for
whatever combination of types they care, but then it is *their*
business. And their responsability.


I believe that the above is consistent and meets the initial goals.
The two things I was lacking before are:
1. Understanding the distinction between value-space and constraint-
space (and the fact that their relation makes a difference between
Integers and tagged types)
2. The hypothetical restricted functions; these are actually more
general beasts, since the restriction can be about just anything.
Whether it is enforced at compile- or run-time is another story, but
for the sake of meeting my motivation of not having exceptions where
implicit conversions are allowed I expect that restricted parameters
follow the same logic and are themselves statically checked, with run-
time checks injected in those places where the actual parameters are
explicitly converted to match formals.

Now - what am I missing? :-)

--
Maciej Sobczak
http://www.msobczak.com/




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

end of thread, other threads:[~2007-06-12 10:03 UTC | newest]

Thread overview: 69+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-06-06 21:33 Reconsidering assignment Maciej Sobczak
2007-06-06 22:52 ` Ray Blaak
2007-06-07  7:15   ` Maciej Sobczak
2007-06-07 16:34     ` Ray Blaak
2007-06-07  7:10 ` Stefan Lucks
2007-06-07  7:32   ` Maciej Sobczak
2007-06-07 11:11     ` Stefan Lucks
2007-06-07 16:28   ` Ray Blaak
2007-06-07  9:27 ` Dmitry A. Kazakov
2007-06-07 16:54   ` contracted exceptions (was Re: Reconsidering assignment) Ray Blaak
2007-06-07 20:04     ` contracted exceptions Robert A Duff
2007-06-07 21:11       ` Ray Blaak
2007-06-07 23:44         ` Robert A Duff
2007-06-08  2:19       ` Randy Brukardt
2007-06-08  7:39         ` Dmitry A. Kazakov
2007-06-08  8:53           ` Ray Blaak
2007-06-08 12:08             ` Dmitry A. Kazakov
2007-06-08 17:31               ` Ray Blaak
2007-06-08 18:00                 ` Dmitry A. Kazakov
2007-06-08 18:20                   ` Georg Bauhaus
2007-06-08 18:56                     ` Dmitry A. Kazakov
2007-06-08 19:15                   ` Simon Wright
2007-06-09  0:14                     ` Randy Brukardt
2007-06-09  2:44                       ` Larry Kilgallen
2007-06-09  8:21                     ` Dmitry A. Kazakov
2007-06-09 12:32                       ` Simon Wright
2007-06-09 18:38                         ` Dmitry A. Kazakov
2007-06-09 21:04                           ` Simon Wright
2007-06-10  9:21                             ` Dmitry A. Kazakov
2007-06-10 11:49                               ` Simon Wright
2007-06-10 15:20                                 ` Dmitry A. Kazakov
2007-06-11  4:13                                   ` Ray Blaak
2007-06-11  7:58                                     ` Dmitry A. Kazakov
2007-06-11 17:06                                       ` Ray Blaak
2007-06-11 19:57                                         ` Dmitry A. Kazakov
2007-06-10 18:14                                 ` Georg Bauhaus
2007-06-10 18:12                               ` Georg Bauhaus
2007-06-11  7:55                                 ` Dmitry A. Kazakov
2007-06-11 14:15                         ` Bob Spooner
2007-06-11 15:14                           ` Georg Bauhaus
2007-06-11 15:20                             ` (see below)
2007-06-11 16:39                               ` Georg Bauhaus
2007-06-11 19:50                           ` Simon Wright
2007-06-08 11:26         ` Martin Krischik
2007-06-08 12:02         ` Robert A Duff
2007-06-08 11:22     ` contracted exceptions (was Re: Reconsidering assignment) Martin Krischik
2007-06-08 17:44       ` Ray Blaak
2007-06-08 12:10     ` contracted exceptions Robert A Duff
2007-06-08 15:56       ` Stefan Lucks
2007-06-08 20:27         ` Pascal Obry
2007-06-09  0:19           ` Randy Brukardt
2007-06-09 18:04             ` Robert A Duff
2007-06-09 18:37               ` Dmitry A. Kazakov
2007-06-09 20:43                 ` Robert A Duff
2007-06-10  9:21                   ` Dmitry A. Kazakov
2007-06-11 19:18                   ` Randy Brukardt
2007-06-12  6:55                     ` Jean-Pierre Rosen
2007-06-08 17:40       ` Ray Blaak
2007-06-09 18:14         ` Robert A Duff
2007-06-08 19:18       ` Simon Wright
2007-06-09 22:37   ` Reconsidering assignment Maciej Sobczak
2007-06-10  9:21     ` Dmitry A. Kazakov
2007-06-11  9:04       ` Maciej Sobczak
2007-06-11 13:09         ` Dmitry A. Kazakov
2007-06-11 18:57     ` Randy Brukardt
2007-06-11 21:12       ` Maciej Sobczak
2007-06-12  8:31         ` Dmitry A. Kazakov
2007-06-12  9:31           ` Georg Bauhaus
2007-06-12 10:03             ` Dmitry A. Kazakov

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