Expressions [ HP Pascal/iX Reference Manual ] MPE/iX 5.0 Documentation
HP Pascal/iX Reference Manual
Expressions
Type Coercion
Pascal is very strict with respect to type checking. In any operation
such as assignment, binary operations, passing parameter, or indexing,
relevant types must be compatible according to the HP Pascal rules of
compatible types. Refer to "Type Compatibility" for more
information.
Type coercion allows the user to selectively circumvent the normally
strong type checking. The system programming extensions support several
forms of type coercion including ANYVAR, reference, and value. ANYVAR
type coercion (using the formal parameter mechanism ANYVAR) is described
in this chapter under "Procedures and Functions" .
Reference type coercion consists of type coercion of an actual parameter
that is being passed to a reference formal parameter, or type coercing a
pointer to a different pointer type before a dereference.
Value type coercion consists of type coercion of a constant, variable,
function result, or expression to a different type.
The syntax for type coercion looks like the application of a function to
an expression, where the name of the function is the name of the target
type of the coercion.
Syntax
Expression:
The expression being coerced may be a constant, variable, function
result, or expression involving unary and binary operators.
Syntactically, value type coercion is allowed:
* In an expression.
* On the right-hand side of an assignment statement.
* On an actual parameter.
By default, the compiler does not allow value type coercion. The
compiler option TYPE_COERCION allows the user to enable a certain level
of type coercion. There are three classes of type coercion based on the
source and target types: ordinal, pointer, and free union type coercion.
Ordinal and pointer type coercions are enabled by specifying the
conversion level of type coercion. Instances of free union type coercion
are enabled by specifying one of structural, representation, storage, or
noncompatible type coercion.
Ordinal Type Coercion.
The ordinal types are viewed as different sets of names for the points on
the integer number line. Given this view of ordinals, value type
coercion of one ordinal type to another is simply a renaming operation.
A type coercion expression is considered an ordinal coercion, if both the
source expression (expression being coerced) and the target type (type to
which the expression is being coerced) are any of the following types:
* The predefined types integer, shortint, char, Boolean, and Bit16.
* A user-declared enumerated type.
* A user-declared subrange type.
If the value of the source expression is out of range with respect to the
allowed values of the target type, a subrange violation occurs. If range
checking is on, this causes a run-time error.
Example
TYPE
color_t = (red,orange,yellow,green,chartreuse,blue,indigo,violet);
VAR
i : integer;
color : color_t;
BEGIN
...
color := chartreuse;
i := integer( color ); { i has the value 4 }
i := 3;
color := color_t( i ); { color has the value green }
i := 12;
color := color_t( i ); { will cause a run-time error }
...
END;
Pointer Type Coercion.
The pointer types are viewed as virtual addresses. Given this view,
value type coercion from one pointer type to another is a mapping from
one virtual address to another.
On implementations that have alignment restrictions, it is an error if
the alignment of the type that the source expression points to is smaller
than the alignment of the type that the target type points to. If range
checking is on, this causes a run-time error. See the HP Pascal/iX
Programmer's Guide or the HP Pascal/HP-UX Programmer's Guide, depending
on your implementation, for more information on alignment.
Coercion from long-to-long and short-to-short pointers is a one-to-one
mapping and involves no actual run-time conversion operations.
Coercion from a short to a long pointer, in implementations where long
pointers point to a wider class of objects than short pointers, may
involve amending the value of the short pointer with additional address
information that a long pointer requires.
Coercion from a long to a short pointer, in implementations where long
pointers point to a wider class of objects than short pointers, may
involve truncating the value of the long pointer. If this occurs, the
short pointer may not be able to address the original object pointed to
by the long pointer because of the short pointer's limited addressing.
This is an error. If range checking is on, this causes a run-time error.
Example
TYPE
integer_pointer = ^ integer;
real_pointer = ^ real;
VAR
ip : integer_pointer;
rp : real_pointer;
BEGIN
...
ip := integer_pointer( rp );
...
END;
Other Type Coercion.
All type coercions that do not fall under the categories of ordinal and
pointer type coercion can be viewed as the use of a free union, or
tagless variant record, where the implementation overlays the record
variants onto the same storage area.
The model for value type coercion:
type_1(expression)
is equivalent to the function call:
f_type_1(expression)
where f_type_1 is defined as:
FUNCTION f_type_1 (e: type_of_expression):type_1 ;
VAR
coerce_record : RECORD CASE Boolean OF
true: ( source_variant : type_of_expression );
false: ( target_variant : type_1 );
END;
BEGIN
coerce_record.source_variant := e;
f_type_1 := coerce_record.target_variant;
END;
The model for reference type coercion:
target_type ( source );
is equivalent to:
pointer_to_target_type ( addr ( source ) )
Whereas both ordinal and pointer type coercions may cause run-time errors
if the source values are not representable in the target type, the free
union form of type coercion never causes run-time errors.
Depending upon the source and target types, free union type coercion
consists of the following levels, listed in increasing order of freedom:
* Structural
* Representation
* Storage
* Noncompatible
Structural. A type coercion expression is considered to be structural if
the following are true:
* The bitsizes of the source and target types are the same.
* The alignment of the source and target types are the same.
* The source and target types are compatible.
* If the source and target are structured, then the corresponding
component in the two structures obey the above three rules of
bitsizes, alignment and compatibility.
Structural type coercions are enabled by specifying 'STRUCTURAL' in the
compiler option TYPE_COERCION.
Structural type coercion is essentially a renaming of the components of a
structure. Because the component types are guaranteed to be the same,
the storage allocated for the source and target types is also the same,
and reinterpreting the storage of the source as if it was of the target
type will produce correct results.
Example
$TYPE_COERCION 'STRUCTURAL'$
...
TYPE
source_t = RECORD
i : integer;
b : false..true;
end;
target_t = RECORD
j : minint..maxint;
c : Boolean;
END;
VAR
source : source_t;
target : target_t;
...
BEGIN
...
target := target_t(source);
...
END;
In the above example, the two record types are the same: their bitsizes
are identical and their corresponding components are the same.
Representation. A type coercion expression is considered to be
representation type coercion if the bitsizes of the source and target
types are the same. The internal structure of structured types for
either the source or target does not matter.
Representation type coercions are enabled by specifying 'REPRESENTATION'
in the compiler option TYPE_COERCION.
Example
$STANDARD_LEVEL 'HP_MODCAL'$
PROCEDURE write_hex( n : integer );
TYPE
nibble_array = PACKED ARRAY[0..7] OF 0..15;
hex_digit_t = array [0..15] OF char;
CONST
hex_digit = hex_digit_t[ '0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'a', 'b', 'c', 'd', 'e', 'f' ];
VAR
i : 0..7;
BEGIN
FOR i := 0 to 7 DO
$PUSH, TYPE_COERCION 'REPRESENTATION'$
WRITE( hex_digit[ nibble_array( n )[i] ] );
$POP$
END;
In the above example, the integer n is treated as an array of nibbles in
order to extract each nibble sequentially and write out its value in
hexadecimal. Since representation type coercion guarantees that the
source and target types are identical in size, the compiler can guarantee
that the entire integer is covered by the nibble array: there are no
bits missed.
Storage. A type coercion expression is considered to be storage type
coercion, if the size of the storage allocated for the source is greater
than the size of the storage allocated for the target type.
Storage type coercion guarantees that no nonexistent memory is accessed
and that no undefined bits are accessed.
The following illustrates storage type coercion. The compiler guarantees
that PROC never accesses a part of its formal parameter that is not
actually part of the actual parameter. This is because the actual
parameter is guaranteed to be larger than or the same size as the formal
parameter.
Example
TYPE
string_1 = STRING [255];
string_2 = STRING [80]
VAR
s1 : string_1;
s2 : string_2;
...
PROCEDURE PROC (VAR S : STRING_2);
BEGIN
...
END;
...
$PUSH, TYPE_COERCION 'STORAGE'$
PROC ( string_2 (s1) );
$POP$
Noncompatible. Noncompatible type coercion permits anything to be
coerced to anything. There is no guarantee that the accessed storage
exists, nor that there is any accessible storage.
Example
FUNCTION non_protected_space: integer;
TYPE
big_index = 0..max_array_size-1;
big_array = array[big_index] of integer;
VAR
idx : big_index;
int : integer;
BEGIN
idx := 0;
TRY
WHILE (idx <= max_array_size-1) DO BEGIN
$PUSH, TYPE_COERCION 'NONCOMPATIBLE'$
int := big_array( int )[idx];
$POP$
idx := idx + 1;
end;
non_protected_space := max_array_size-1;
RECOVER
non_protected_space := idx - 1;
END;
The previous example coerces an integer to an array of integers and keeps
accessing farther out into the array until it cannot access any further.
Note that this code assumes that:
* TRY-RECOVER traps the error condition that occurs when the array
access grows beyond the limits of the available space.
* The value of the variable idx is updated correctly when execution
is transferred to the RECOVER statement.
MPE/iX 5.0 Documentation