Ada is a language that is, in many respects, similar to Pascal. However, it is not a "superset" of Pascal. The statement syntax is slightly different (simpler, in the opinion of many), and many familiar Pascal features are implemented somewhat differently. As a learning aid to those experienced in Pascal but new to Ada, this appendix summarizes areas in which the languages differ enough to cause some difficulty in the form of compilation errors.
The most important difference between Ada and Pascal is that the strong Ada standard, coupled with the compiler validation process, ensure that the same Ada language is accepted by all compilers. Syntactic extensions, such as are found in most useful Pascal systems, do not occur in Ada. On the other hand, the Ada language defined by the standard covers nearly all the features of the Pascal extensions.
The Pascal standard requires a rigid declaration order (constants, types, variables, subprograms) that is relaxed by some implementations. Ada declaration order is somewhat more flexible. The Ada standard refers to "basic declarative items" and "later declarative items." Among the former are declarations of constants, types, and variables; among the latter are functions and procedures. (Other declarations are beyond the scope of this book.) In the declarative part of a program or subprogram, basic declarative items can be freely intermixed--with the understanding, of course, that everything must be declared before it is referenced. All basic items must precede all later items; put simply, subprogram declarations must follow the others.
In Pascal, the words TYPE
, CONST
, and
VAR
appear only once in a declarative section. In Ada, each type
or subtype declaration must be opened by TYPE
or
SUBTYPE
, respectively. A constant is declared as, for example,
FirstLetter: CONSTANT Character := 'A';and the reserved word
VAR
is not used at all; a variable is simply
declared as, for example,
Sum : Integer;A record type declaration must be closed by
END RECORD
.
All control structures are fully bracketed in Ada, including IF-END
IF
, LOOP-END LOOP
, CASE-END CASE
. Further, a
semicolon terminates a statement--it does not separate statements, as in
Pascal. This yields a syntax that is easier to use correctly than Pascal's. For
example, the Pascal statement
IF X < Y THEN A := B;is written in Ada as
IF X < Y THEN A := B; END IF;and the Pascal statement
IF X < Y THEN BEGIN A := B; Z := X END ELSE BEGIN A := X; Z := B END;is written in Ada as
IF X < Y THEN A := B; Z := X; ELSE A := X; Z := B; END IF;The fully-bracketed syntax ensures that a "dangling
ELSE
" cannot be
written.
FOR
loop control variables are declared implicitly; this is the
only exception to the rule that everything must be explicitly declared. A
FOR
counter is local to the loop body. Declaring the loop counter
as a variable, as in Pascal, does no real harm, but it declares a different
variable, which is then hidden by the actual loop counter and therefore not
visible in the loop body.
FOR
loop ranges are often stated as type or subtype names, as in
FOR Count IN IndexRange LOOPAda has no
REPEAT
loop structure; instead, use LOOP-END
LOOP
with an EXIT WHEN
clause at the bottom of the loop.
The choice variable in a CASE
statement must be of a discrete
(integer or enumeration) type; the various CASE
choices must
cover, in a nonoverlapping fashion, all possible values of the choice variable.
Two-dimensional arrays are not arrays of arrays. Therefore,
A(J)(K)
is not the same as A(J,K)
: The former
indeed refers to an array of arrays, the latter to a two-dimensional array. One
reason these are different structures in Ada is that the standard does
not specify the storage mapping (row- or column-major) for
multidimensional arrays. This allows a clever implementer to use a nonlinear
mapping, for example. In practice, most current Ada compilers use a row-major
mapping, in keeping with Pascal and C rules.
The type of a record field must always be a type name; it cannot be an
anonymous type such as ARRAY
or RECORD
. To build
hierarchical record types, build the lower-level ones first, then use their
names as fields in the higher-level ones.
There is nothing in Ada that corresponds to Pascal's WITH
. All
record and array references must always be fully qualified.
Variant records are much more tightly controlled in Ada than in Pascal. It
is not possible to write a "free union," or variant record without a
discriminant (tag field). In Pascal and C, free unions are frequently used to
evade type checking, but cannot be used for this purpose in Ada. (Ada has a
generic function called Unchecked_Conversion
that indeed is used
to evade type checking, but use of this is beyond the scope of this book).
There is no SET
type in Ada. A package giving the equivalent
functionality is presented in full as Programs 11.14 and 11.15.
This matter is discussed at length throughout the book. The most important thing to remember is that Ada uses named type equivalence, not structural equivalence. For example, given the declarations
A, B: ARRAY(1..10) OF Float; C : ARRAY(1..10) OF Float;the array assignment statements
A := B; C := B;are both invalid, because each of the three arrays has a different anonymous type, assigned by the compiler. (Some Pascal compilers would allow the first assignment.) To allow the array assignments, one must give a type name:
TYPE List IS ARRAY(1..10) OF Float; A, B: List; C: List;Both assignments are now valid. The Pascal style of using anonymous types is not used in this book, and we recommend against it.
Ada's parameter modes IN
, OUT
, and IN
OUT
are only roughly equivalent to the value and VAR
parameters of Pascal.
Within the body of a subprogram, IN
parameters can only be read,
never written. The main difference between OUT
and IN
OUT
parameters is that the current value of an actual IN
OUT
parameter is passed to the procedure, whereas, in general, the value
of an actual OUT
parameter is not passed, and can therefore assume
to be undefined until given a value by the subprogram. Functions cannot have
OUT
or IN OUT
parameters.
There is no efficiency to be gained by passing as IN OUT
an
array to be used as an IN
parameter. This is common in Pascal,
where large arrays are usually passed as VAR
parameters. Pascal
requires VAR
parameters to be passed by reference and value
parameters to be copied. The rules in Ada are different: Scalar parameters are
always passed by value/result, whatever their mode. Ada permits composite
(array and record) parameters to be passed by value/result, but compilers
almost never do this, especially if the composites are large. Practical
compilers pass arrays and large records by reference even if they are
IN
; since IN
parameters cannot be written, there is
no danger of changing their value in the calling program.
In the case of scalar OUT
and IN OUT
parameters,
the values are copied back to the calling program at normal completion
of the procedure call. That is, if the procedure call completes by propagating
an exception to the caller, the parameter values are not copied back and
therefore the caller still has theoriginal values.
The input/output statements in Ada are ordinary procedure calls, which means
that only a single integer, float, character, string, or enumeration value can
be read or displayed with each call of Get
or Put
.
One cannot supply an arbitrary number of parameters to input/output statements,
as one would do in Pascal. Doing so will surely result in compilation errors of
the form "unmatched procedure call," when the compiler searches for a
Get
or Put
whose expected parameters match the
supplied ones.
PRIVATE
type.
Endless grief awaits Ada users who confuse the use of the semicolon with the
use of IS
; with some compilers, this leads to long sequences of
propagation error messages. The worst offense is using a semicolon instead of
IS
in a subprogram declaration, as one would do in Pascal.
PROCEDURE DoSomething(X : Integer); ---- <---- this means TROUBLE! -- declarations BEGIN -- statements END DoSomething;The problem is that it is legal to use the semicolon, but the meaning is not what you expect. The line
PROCEDURE DoSomething(X : Integer);is not a declaration, but a procedure specification, similar to a Pascal
FORWARD
specification. Confusing the semicolon with the
IS
is therefore almost guaranteed to lead to a large number of
propagation errors from the compiler: Since the Ada parser treats the statement
as a specification, it is confused by the declarations and
BEGIN-END
block that follow, which seem to be out of context and
not well-formed. IS
is precisely the way that Ada knows a
procedure body is expected next; the user forgets this at his or her
peril.
Subprogram specifications appear as a part of package specifications, and can
also be useful in contexts where a Pascal FORWARD
would be
written. In the latter case, the first line of the body must be
identical to the specification, except for replacing the semicolon by
IS
. This is different from Pascal, where the parameter list is not
repeated.
Copyright © 1996 by Addison-Wesley Publishing Company, Inc.