Every piece of data that is created or manipulated by a VSI Pascal program has a data type. The data type determines the range of values, set of valid operations, and maximum storage allocation for each piece of data.
1 – Ordinal
The values in an ordinal type have a one-to-one correspondence with the set of positive integers. The values are ordered so that each has a unique ordinal value indicating its position in a list of values of that type.
1.1 – INTEGER Types
VSI Pascal provides the INTEGER, INTEGER64 (not available on all systems) integer types. Also provided are the INTEGER8, INTEGER16, and INTEGER32 types, which are used as synonyms for subranges of the INTEGER type. The range of integer values consists of positive and negative integer values and of the value 0. The range boundaries depend on the architecture of the machine you are using. The largest possible value of the INTEGER type is represented by the predeclared constant MAXINT. The largest possible value of the INTEGER64 type is represented by the predeclared constant MAXINT64.
1.1.1 – Standard Int Radix
Extended digit notation allows you to express integer values in
terms of a base number. VSI Pascal accepts numbers in bases 2
through 36.
Syntax:
[[ + | - ]] base-number#[[']]extended-digit[[']]
The 'base-number' specifies the base of the number.
The 'extended-digit' specifies the notation that is appropriate
for the specified base.
You can use extended-digit notation in the same way you use the
conventional integer notation, with the following exceptions:
o Extended-digit values cannot be used as labels.
o Extended-digit notation for INTEGER objects cannot be used
to express numbers outside the range of 0 to MAXINT. (To
express signed numbers, place the unary plus operator (+) or
the unary minus operator (-) in front of the notation;
setting or clearing the high order bit does not set or clear
the sign bit.)
VSI Pascal allows the use of spaces and tabs to make the
extended-digit notation easier to read. To use spaces and tabs,
enclose the extended digit in single quotation marks (' '). The
following are integer values in the extended-digit notation:
2#10000011
2#'1000 0011'
32#1J
-16#'7FFF FFFF'
1.1.2 – Nonstandard Int Radix
VSI Pascal provides another extended integer convention for
compatibility with previous versions of the language. This
notation specifies an integer in either binary (base 2), octal
(base 8), or hexadecimal (base 16) notation.
Syntax:
b
[[ + | - ]] % o [[']]extended-digit[[']]
x
The 'b', 'o', or 'x' specifies binary, octal, or hexidecimal
notation, respectively.
The 'extended-digit' specifies the notation that is appropriate
for the specified base.
The following are extended integer values in the VSI Pascal
specific notation:
%b'1000 0011'
%O'7712'
-%x'DEC'
1.2 – INTEGER_ADDRESS
The INTEGER_ADDRESS predefined type is an integer that has the same underlying bit size as a pointer. On OpenVMS systems, INTEGER_ADDRESS is equivalent to INTEGER32.
1.3 – INTEGER8
The INTEGER8 predefined type is equivalent to the following:
Syntax:
TYPE INTEGER8=[BYTE]-128..127;{ 16#80..16#7F}
1.4 – INTEGER16
The INTEGER16 predefined type is equivalent to the following:
Syntax:
TYPE INTEGER16=[WORD]-32768..32767;{ 16#8000..16#7FFF }
1.5 – INTEGER32
The INTEGER32 predefined type is equivalent to the following:
Syntax:
TYPE INTEGER32=[LONG]-2147483648..2147483647;{ 16#80000000..16#7FFFFFFF }
1.6 – INTEGER64
The INTEGER64 predefined type is equivalent to the following:
Syntax:
INTEGER64=[QUAD]-9223372036854775808..9223372036854775807;
{ 16#8000000000000000..16#7FFFFFFFFFFFFFFF }
The INTEGER64 predefined type is not available on OpenVMS VAX
systems.
1.7 – UNSIGNED Types
VSI Pascal provides the UNSIGNED and UNSIGNED64 types (not available on all systems). Also provided are the UNSIGNED8, UNSIGNED16, UNSIGNED32, CARDINAL, CARDINAL16, and CARDINAL32 types, which are used as synonyms for the UNSIGNED type. The range of unsigned values consists of nonnegative integer values. The largest possible value of the UNSIGNED data type is represented by the predefined constant MAXUNSIGNED. The largest value for the UNSIGNED64 data type is represented by the predefined constant MAXUNSIGNED64. The smallest possible value for the UNSIGNED data type is 0.
1.8 – Standard Uns Radix
Extended digit notation allows you to express unsigned integer
values in terms of a base number. VSI Pascal accepts numbers in
bases 2 through 36.
Syntax:
[[ + | - ]] base-number#[[']]extended-digit[[']]
The 'base-number' specifies the base of the number.
The 'extended-digit' specifies the notation that is appropriate
for the specified base.
You can use extended-digit notation in the same way you use the
conventional unsigned integer notation, except that
extended-digit values cannot be used as labels.
VSI Pascal allows the use of spaces and tabs to make the
extended-digit notation easier to read. To use spaces and tabs,
enclose the extended digit in single quotation marks (' '). The
following are unsigned integer values in the extended-digit
notation:
16#80000000
16#'8000 0000'
16#'FFFF FFFF'
1.8.1 – Nonstandard Uns Radix
VSI Pascal provides another extended integer convention only for
the sake of compatibility with previous versions of the
language. This notation specifies an unsigned integer in either
binary (base 2), octal (base 8), or hexadecimal (base 16)
notation.
Syntax:
b
[[ + | - ]] % o [[']]extended-digit[[']]
x
The 'b', 'o', or 'x' specifies binary, octal, or hexidecimal
notation, respectively.
The 'extended-digit' specifies the notation that is appropriate
for the specified base.
The following are unsigned integer values in the VSI Pascal
specific notation:
%x'8000 0000'
%x'FFFF FFFF'
1.9 – UNSIGNED8
The UNSIGNED8 data type is equivalent to the following:
Syntax:
TYPE UNSIGNED8 = [BYTE]UINT(0)..UINT(255); {0..16#FF}
1.10 – UNSIGNED16
The UNSIGNED16 data type is equivalent to the following:
Syntax:
TYPE UNSIGNED16 = [WORD]UINT(0)..UINT(65535); {0..16#FFFF}
1.11 – UNSIGNED32
The UNSIGNED32 data type is equivalent to the following:
Syntax:
TYPE UNSIGNED32 = [LONG]UINT(0)..UINT(4294967295); {0..16#FFFFFFFF}
1.12 – UNSIGNED64
The UNSIGNED64 data type is equivalent to the following (OpenVMS
Alpha and OpenVMS I64 systems only):
Syntax:
TYPE UNSIGNED64 = [QUAD]UINT(0)..UINT(18446744073709551615);
{0..16#FFFFFFFFFFFFFFFF}
1.13 – CHAR
The CHAR data type consists of single character values from the
ASCII character set. The largest possible value of the CHAR
data type is the predefined constant MAXCHAR.
To specify a character constant, enclose a printable ASCII
character in single quotation marks. To specify the
single-quote character, enclose two single quotation marks in
single quotation marks. Each of the following is a valid
character constant:
'A'
'0' {This is character 0, not the integer value 0}
'''' {The apostrophe character}
'?'
You can specify nonprinting characters, such as a
control-character, by writing an empty string followed
immediately by the ordinal value of the character in the ASCII
character set, or by using the CHR function followed by the
ordinal value of the character in the ASCII character set. For
example, both of the following specify the bell control
character:
''(7)
CHR(7)
1.14 – Boolean
Boolean values are the result of testing relationships for truth or validity. The Boolean data type consists of the two predeclared identifiers FALSE and TRUE. The expression ORD(FALSE) results in the value 0; ORD(TRUE) returns the integer 1.
1.15 – Enumerated
An enumerated type is a user-defined ordered set of constant
values specified by identifiers.
Syntax:
({enumerated-identifier},...)
The 'enumerated-identifier' is an identifier of the enumerated
type being defined. VSI Pascal allows a maximum of 65,535
identifiers in an enumerated type.
The values of an enumerated type begin with the value 0 and
follow a left-to-right order. Subsequent identifiers have a
value one greater than the identifier preceding it.
Example: X : ( Spring, Summer, Fall, Winter )
In this enumerated type, Spring (value 0) and Summer (value 1)
are less than Fall (value 2) because they precede Fall in the
list of constant values. Winter (value 3) is greater than Fall
because it follows Fall.
An identifier in an enumerated type cannot be defined for any
other purpose in the same block.
1.16 – Subrange
A subrange type is user-defined and specifies a limited portion
of another ordinal type (called the base type). The subrange
syntax indicates the lower and upper limits of the type.
Syntax:
lower-bound..upper-bound
The 'lower-bound' is a constant expression or a formal
discriminant identifier that establishes the lower limit of the
subrange.
The 'upper-bound' is a constant expression or a formal
discriminant identifier that establishes the upper limit of the
subrange. The value of the upper bound must be greater than or
equal to the value of the lower bound.
The base type can be any enumerated or predefined ordinal type.
The values in the subrange type appear in the same order as they
are in the base type. For instance, the result of the ORD
function applied to a value of a subrange type is the ordinal
value that is associated with the relative position of the value
in the base type, not in the subrange type.
You can use a subrange type anywhere in a program that its base
type is legal. A value of a subrange type is converted to a
value of its base type before it is used in an operation. All
rules that govern the operations performed on an ordinal type
pertain to subranges of that type.
Example: TYPE
Day = ( Mon, Tues, Wed, Thurs, Fri, Sat, Sun );
Weekday = Mon..Fri; {subrange of base type Day}
Digit = '0'..'9'; {subrange of base type CHAR}
Month = 1 .. 31; {subrange of base type INTEGER}
On OpenVMS Alpha and OpenVMS I64 systems, you cannot specify the
size of INTEGER and UNSIGNED subranges to be larger than 32-bits
eventhough such values would be legal in executable statements.
For example:
TYPE S = 0..8796093022208;
is not supported, while
VAR S : INTEGER64;
BEGIN
S := 8796093022208
END
is legal.
2 – Real
Real types specify real number values with different degrees of precision.
2.1 – REAL
The REAL type denotes single-precision real values. The REAL
type is synonymous with the SINGLE type. The largest REAL value
is denoted by MAXREAL. The smallest REAL value is denoted by
MINREAL. EPSREAL denotes the result of subtracting 1.0 from the
smallest REAL value that is greater than 1.0.
Example: 2.4
2.3e2 {exponential notation}
On OpenVMS VAX systems, REAL uses the F_Floating format. On
OpenVMS Alpha systems, REAL can take one of two formats:
F_Floating and IEEE S_Floating. To specify a format, use either
the FLOAT attribute or the /FLOAT command line qualifier.
The default format on OpenVMS VAX and OpenVMS Alpha systems is
F_Floating. The default format on OpenVMS I64 systems is IEEE
S_Floating. On OpenVMS I64 systems, F_Floating is supported by
converting to/from IEEE S_Floating for all floating point
operations.
2.2 – SINGLE
The SINGLE type denotes single-precision real values. The SINGLE type is synonymous with the REAL type.
2.3 – F_FLOAT
The F_FLOAT type denotes a F_Floating single-precision real value regardless of the setting of the FLOAT attribute or /FLOAT command line qualifier.
2.4 – S_FLOAT
The S_FLOAT type denotes a IEEE S_Floating single-precision real value regardless of the setting of the FLOAT attribute or /FLOAT command line qualifier. S_FLOAT is supported on OpenVMS Alpha and OpenVMS I64 systems only.
2.5 – DOUBLE
The DOUBLE type denotes double-precision real values. To
indicate a double-precision real number, you must include a real
number or an integer, the letter D (or d), and an integer
exponent with its minus sign or optional plus sign. The largest
DOUBLE value is denoted by MAXDOUBLE. The smallest DOUBLE value
is denoted by MINDOUBLE. EPSDOUBLE denotes the result of
subtracting 1.0d0 from the smallest DOUBLE value that is greater
than 1.0d0.
Example: 0D0
4.371528665D-3
On OpenVMS VAX systems, DOUBLE exists in two formats:
D_Floating and G_Floating. On OpenVMS Alpha and OpenVMS I64
systems, DOUBLE exists in three formats: D_Floating,
G_Floating, and IEEE T_Floating.
To specify a format, you can use either the FLOAT attribute or
the /FLOAT command line qualifier. On OpenVMS VAX systems, the
default format is D_Floating. On OpenVMS Alpha systems, the
default format is G_Floating. On OpenVMS I64, the default
format is IEEE T_Floating.
2.6 – D_FLOAT
The D_FLOAT type denotes a D_Floating double-precision real value regardless of the setting of the FLOAT attribute or /FLOAT command line qualifier.
2.7 – G_FLOAT
The G_FLOAT type denotes a G_Floating double-precision real value regardless of the setting of the FLOAT attribute or /FLOAT command line qualifier.
2.8 – T_FLOAT
The T_FLOAT type denotes an IEEE T_Floating double-precision real value regardless of the setting of the FLOAT attribute or /FLOAT command line qualifier. T_FLOAT is supported only on OpenVMS Alpha and OpenVMS I64 Systems.
2.9 – QUADRUPLE
The QUADRUPLE type denotes quadruple-precision real values. To
indicate a quadruple-precision real number, you must include a
real number or an integer, the letter Q (or q), and an integer
exponent with its minus sign or optional plus sign. The largest
QUADRUPLE value is denoted by MAXQUADRUPLE. The smallest
QUADRUPLE value is denoted by MINQUADRUPLE. EPSQUADRUPLE
denotes the result of subtracting 1.0q0 from the smallest
QUADRUPLE value that is greater than 1.0q0.
Example: 0.11435Q3
3362Q2
0.11825q-4
On OpenVMS VAX systems, QUADRUPLE uses the H_Floating format.
On OpenVMS Alpha and OpenVMS I64 systems, QUADRUPLE uses the
X_Floating format.
2.10 – H_FLOAT
The H_FLOAT type denotes quadruple-precision real values. The H_FLOAT type is synonymous with the QUADRUPLE type on OpenVMS VAX systems. H_FLOAT is supported only on OpenVMS VAX Systems.
2.11 – X_FLOAT
The X_FLOAT type denotes quadruple-precision real values. The X_FLOAT type is synonymous with the QUADRUPLE type on OpenVMS Alpha and OpenVMS I64 systems. X_FLOAT is supported only on OpenVMS Alpha and OpenVMS I64 systems.
3 – Pointer Types
A pointer type allows you to refer to a dynamic variable.
Dynamic variables do not have lifetimes that are strictly
related to the scope of a routine, module, or program; you can
create and eliminate them at various times during program
execution. Also, pointer types clearly define the type of an
object, but you can create or eliminate objects during program
execution. A pointer type has the following syntax:
[[attribute-list]] ^ [[attribute-list]] base-type-identifier
The 'attribute-list' is one or more optional identifiers that
provide additional information about the base type.
The 'base-type-identifier' is the type identifier of the dynamic
variable to which the pointer type refers. (If the base type is
an undiscriminated schema type, you need to supply actual
discriminants when you call the NEW function.)
Unlike other variables, dynamic variables do not have
identifiers. Instead, you access them indirectly with pointers.
Call the NEW procedure to allocate storage for dynamic
variables. Call the DISPOSE procedure to deallocate this
storage.
Example: TYPE
Reservation = RECORD
Name : VARYING[30] OF CHAR;
Class : ( standby, coach, first );
Flight_number : INTEGER;
Next_passenger : ^Reservation;
END;
VAR
Ticket : Reservation;
In this example, 'Next_passenger' is a pointer to the record
type 'Reservation'. The variable 'Ticket' is declared as type
'Reservation'. By manipulating the pointer variable,
'Ticket.Next_passenger', a linked list of records can be created
using these definitions.
By default, all pointer types are 32-bits wide. The NEW
procedure uses LIB$GET_VM to allocate memory and LIB$FREE_VM to
dispose of memory. On OpenVMS Alpha and OpenVMS I64, the [QUAD]
attribute may be specified before the "^" character resulting in
a 64-bit pointer. Using 64-bit pointers causes the NEW and
DISPOSE procedures to LIB$GET_VM_64 to allocate memory and
LIB$FREE_VM_64 to dispose of memory, respectively.
3.1 – C_STR_T
The C_STR_T predefined type is provided to interface with routines written in the C language using null-terminated strings. C_STR_T behaves like a normal pointer type in that you can assign NIL into it and the optional pointer checking code will check for dereferencing of a NIL pointer. The individual characters can be used by dereferencing the pointer and using an array index. No bounds checking will be performed even if array bounds checking is enabled. You cannot dereference a C_STR_T pointer without also indexing a single character. If you want to access an entire null-terminated string, see the PAS_STR function.
3.2 – POINTER
The POINTER predefined type is compatible with all pointer
types. Variables or functions of type POINTER cannot be
dereferenced or used with the NEW and DISPOSE procedures. In
order to access the data, you must assign the pointer value into
a variable of a particular pointer type or typecast the pointer
to a particular pointer type. For example, you can use the
POINTER type in the following ways:
o To assign to or from any other type of pointer, including
function result variables
o To compare equality with any other type of pointer
o To pass actual parameters of type POINTER to VAR and value
parameters of any other type of pointer
o To accept parameters of any other type of pointer with
formal parameters of type POINTER
3.3 – UNIV_PTR
The predefined UNIV_PTR type is equivalent to:
TYPE
UNIV_PTR = POINTER;
4 – Structured Types
The structured data types are user-defined and consist of components. Each component of a structured data type has its own data type; components can be any type. To express values of structured objects (arrays, records, and sets), you can use a list of values called constructors. Constructors are valid in the TYPE, CONST, VAR, and executable sections of your program. See the "HP Pascal Language Reference Manual" for examples of valid constructors and examples that show how to assign values to individual components of structured objects.
4.1 – RECORD
A record is a group of components (called fields) that can be of
various data types. Each record component may contain one or
more data items.
Syntax:
[[PACKED]] RECORD [[field-list]] END
END
If field-list is not specified, an empty record is created. The
following is an example of a record type:
RECORD
Part : INTEGER;
Received : RECORD
Month : ( Jan, Feb, Mar, Apr, May, June,
Jul, Aug, Sep, Oct, Nov, Dec );
Day : 1..31;
Year : INTEGER;
END;
END;
4.1.1 – Field list
The syntax for a field-list is as follows:
{ {{field-identifier},... : [[attribute-list]] type};...
[[; variant-clause]] [[;]] variant-clause [[;]] }
The 'field-identifier' is the name of a field.
The 'attribute-list' is one or more optional identifiers that
provide additional information about the field.
The 'type' is the type of the corresponding field. A field can
be of any type.
The 'variant-clause' is the variant part of a record. A variant
can contain different types or amounts of data at different
times during program execution. The syntax for a variant clause
is as follows:
CASE { [[tag-identifier : ]] [[attribute-list]]
tag-type-identifier}| discriminant-identifier } OF
{{case-label-list} : (field-list)};...
[[ [[;]] OTHERWISE (field-list)]]
The 'tag-identifier' is the name of the tag field. The tag
field is all of the elements between the reserved words CASE and
OF.
The 'attribute-list' is one or more optional identifiers that
provide additional information about the variant.
The 'tag-type-identifier' is the type identifier for the tag
field.
The 'discriminant-identifier' is the name of the formal
discriminant of a schema type. The value of the corresponding
actual discriminant selects the active variant. Once you select
the variant by discrimination, you cannot change it again.
The 'case-label-list' consists of one or more constant values of
the tag field type either separated by commas. A case constant
is either a single constant value (for example, 1) or a range of
values (for example, 5..10).
The 'field-list' consists of the names, types, and attributes of
one or more fields. At the end of a field list, you can specify
another variant clause. The field-list can be empty.
'OTHERWISE' is equivalent to a case label list that contains tag
values (if any) not previously used in the record. The variant
labeled with OTHERWISE is the current variant when the
tag-identifier has a value that does not occur in any of the
case label lists.
The following is an example of a variant record:
RECORD
Part : 1..9999;
CASE On_Order : Boolean OF
TRUE : ( Order_Quantity : INTEGER;
Price : REAL );
FALSE : ( Rec_Quantity : INTEGER;
Cost : REAL );
END;
In this example, the last two fields in the record vary
depending on whether the part is on order. Records for which
the value of the tag-identifier On_Order is TRUE will contain
information about the current order; those for which it is
FALSE, about the previous shipment.
4.1.2 – Standard record constructor
Record constructors are lists of values that you can use to
initialize a record.
Syntax:
[[data-type]] [ [[{{component},... : component-value};... ]]
[[{CASE [[tag-identifier :]] tag-value OF
[{{component},... : component-value};... ]
OTHERWISE ZERO [[;]] }]] ]
The 'data_type' specifies the constructor's data type. If you
use the constructor in the executable section or in the CONST
section, a data-type identifier is required. Do not use a type
identifier in initial-state specifiers elsewhere in the
declaration section or in nested constructors.
The 'component' specifies a field in the fixed-part of the
record. Fields in the constructor do not have to appear in the
same order as they do in the type definition. (If you choose,
you can specify fields from the variant-part as long as the
fields do not overlap.)
The 'component-value' specifies a value same data type as the
component. These values are compile-time values; if you use the
constructor in the executable section, you can also use run-time
values.
'CASE' provides a constructor for the variant portion of a
record. If the record contains a variant, its constructor must
be the last component in the constructor list.
The 'tag-identifier' specifies the tag-identifier of the variant
portion of the record. This is only required if the variant
part contained a tag-identifier.
The 'tag-value' determines which component list is applicable
according to the variant portion of the record.
'OTHERWISE ZERO' sets all remaining components to their binary
zero value. If you use OTHERWISE ZERO, it must be the last
component in the constructor.
When you specify constructors for a record that contains nested
records, specify the type of the outermost record, but do not
specify the type of the constructors for any nested records.
The following are examples of record variables and possible
standard record constructors:
Example:
TYPE
Player_Rec = RECORD
Wins : INTEGER;
Losses : INTEGER;
Percentage : REAL;
END;
VAR
Player1 : Player_Rec VALUE [Wins: 18; Losses: 3;
Percentage: 21/18]
This record constructor appears in the variable declaration
section, so the constructor type is optional, and compile-time
values are required.
Example:
TYPE
Player_Rec = RECORD
Wins : INTEGER;
Losses : INTEGER;
Percentage : REAL;
END;
VAR
Player1, Player2 : Player_Rec;
{In the executable section}
Player1 := Player_Rec[Wins:18; Losses: y; Percentage: Y+18/18];
This record constructor appears in the executable section, so
the constructor type is required and run-time expressions are
legal.
4.1.3 – Nonstandard record constructor
Syntax:
[[data-type]] ([[{component-value},...]]
[[tag-value, {component-value},...]])
The 'data_type' specifies the constructor's data type. If you
use the constructor in the executable section, a data-type
identifier is required. Do not use a type identifier in the VAR
or VALUE sections, or for a nested constructor.
The 'component-value' specifies a compile-time value of the same
data type as the component. The compiler assigns the first
value to the first record component, the second value to the
second component, and so forth.
The 'tag-value' specifies a value for the tag-identifier of a
variant record component. The value that you specify as this
component of the constructor determines the types and positions
of the remaining component values (according to the variant
portion of the type definition).
The following is an example of a record variable and a possible
nonstandard record constructor:
Rec : RECORD
Person : VARYING [30] OF CHAR;
Address : RECORD
Number : INTEGER;
Street : VARYING [30] OF CHAR;
Zip : 0..9999;
END;
Age : 0..150:
END;
('Blaise Pascal', (1623, 'Pensees Street', 91662), 39)
4.2 – ARRAY
An array is a group of components (called elements) that all
have the same data type and share a common identifier. An
individual element of an array is referred to by an ordinal
index (or subscript) that designates the element's position (or
order) in the array.
Syntax:
[[PACKED]] ARRAY [ {[[attribute-list]] index-type},... ] OF
[[attribute-list]] component-type
The 'attribute-list' is one or more optional identifiers that
provide information about the component type.
The 'index-type' is the type of the index, which can be any
ordinal type or discriminated ordinal schema type.
The 'component-type' is the type of the array components, which
can be any type. The components of an array can be another
array.
Example: ARRAY [0..4] OF INTEGER
An array, whose components are themselves arrays, is called a
multidimensional array. An array can have any number of
dimensions, and each dimension can have a different index type.
Example: ARRAY [0..4, 'A'..'D'] OF INTEGER
This array is declared as two-dimensional. To refer to a
component of this two-dimensional array, specify the variable
name followed by the two bracketed index values. For example
X[0,'A'] or X[0]['A'] specify the component in 'X' at position
'0', 'A'.
4.2.1 – Standard array constructor
Array constructors are lists of values that you can use to
specify an array value.
Syntax:
[[data-type]] [ [[{{{component | component-subrange}},... :
component-value};... ]] [[OTHERWISE component-value [[;]] ]] ]
The 'data-type' specifies the constructor's data type. If you
use the constructor in the executable section or in the CONST
section, a data-type identifier is required. Do not use a type
identifier in initial-state specifiers elsewhere in the
declaration section or in nested constructors.
The 'component' or a 'component-subrange' specifies an element
number to which the component-value applies. You can specify a
subrange of components. Array elements do not have to be
specified in order. The component must be a compile-time value
or constant.
The 'component-value' specifies the value to be assigned to the
array elements in the component-list; the value must be of the
same data type as the array-component type. This value is a
compile-time value; if you use the constructor in the executable
section, you can also use a run-time value.
'OTHERWISE' specifies a value to be assigned to all array
elements that have not already been assigned values.
When using array constructors, you must initialize all elements
of the array; you cannot partially initialize the array.
When you specify constructors for multidimensional arrays in the
executable section, only specify the type of the outermost
array.
4.2.1.1 – Examples
The following examples show possible constructors for the array
Numbers:
VAR
Numbers : Count VALUE [1..3,5 : 1; 4,6 : 2; 7..9 : 3; 10 : 6];
{or, in the executable section}
Numbers := Count[1..3,5 : 1; 4,6 : 2; 7..9 : 3; 10 : x+3];
These constructors give the first, second, third, and fifth
component the value 1; the fourth and sixth component the value
2; and the seventh, eighth, and ninth components the value 3.
The first constructor gives the tenth component the value 6; the
second constructor, since it is in the executable section, can
assign the run-time value x+3 to the tenth component.
Numbers := Count[4,6 : 2; 7..9 : 3; 10 : x+3; OTHERWISE 1];
To specify constructor values for all remaining elements, you
can use the OTHERWISE clause.
4.2.2 – Nonstandard array constructor
Syntax:
[[data-type]] ([[{component-value},...]]
[[REPEAT component-value]])
The 'data-type' specifies the constructor's data type. If you
use the constructor in the executable section, a data-type
identifier is required. Do not use a type identifier in the VAR
or VALUE sections, or for a nested constructor.
The 'component-value' specifies the compile-time value to be
assigned to the corresponding array element. The compiler
assigns the first value to the first element, the second value
to the second element, and so forth. If you want to assign more
than one value to more than one consecutive element, you can use
the following syntax for a component-value:
n OF value
For instance, the following component value assigns the value of
15 to the first three components of an array:
VAR
Array1 : ARRAY [1..4] OF INTEGER;
VALUE
Array1 := ( 3 OF 15, 78 );
You cannot use the OF reserved word in a REPEAT clause.
'REPEAT' specifies a value to be assigned to all array elements
that have not already been assigned values.
The following is an example of an array variable and a possible
array constructor:
Result : ARRAY [1..2, 0..4] OF INTEGER;
((0,1,2,3,4),(5,6,7,8,9))
4.3 – SET
A set is a collection of data items of the same ordinal type
(called the base type). The SET type definition specifies the
values that can be elements of a variable of that type.
Syntax:
[[PACKED]] SET OF [[attribute-list]] base-type
The 'attribute-list' is one or more optional identifiers that
provide additional information about the base type.
The 'base-type' is the ordinal type identifier or type
definition, or discriminated schema type, from which the set
elements are selected. Note that real numbers cannot be
elements of a set type.
Example: SET OF CHAR
Some possible set constructors for this set type are:
['A, 'E', 'I', 'O', 'U']
['B'..'D', 'F'..'H', 'J'..'N', 'P'..'T', 'V'..'Z']
4.3.1 – Set constructor
Set constructors are lists of values that you can use to
initialize a set. The syntax for set constructors is as
follows:
[[data-type]] [ [[{component-value},...]] ]
The 'data-type' is the data type of the constructor. This
identifier is optional when used in the CONST and executable
sections; do not use this identifier in the TYPE and VAR
sections or in nested constructors.
The 'component-value' specifies values within the range of the
defined data type. Component values can be subranges (..) to
indicate consecutive values that appear in the set definition.
These values are compile-time values; if you use the constructor
in the executable section, you can also use run-time values.
A set having no elements is called an empty set and is written
as empty brackets ([]).
A possible constructor for a variable of type SET OF 35..115 is
the following:
VAR
Numbers : SET OF 35..115 VALUE [39, 67, 110..115];
{In the executable section, run-time expressions are legal:}
Numbers := [39, 67, x+95, 110..115]
The set constructors contain up to nine values: 39, 67, 95 or
x+95, and integers between 110 and 115, inclusive. If the
expression x+95 evaluates to an integer outside the range
35..115, then VSI Pascal includes no set element for that
expression.
4.4 – File
A file is a sequence of components of the same type. The number
of components is not fixed, so a file can be any length. The
FILE type definition identifies the component type.
Syntax:
[[PACKED]] FILE OF [[attribute-list]] component-type
The 'attribute-list' is one or more optional identifiers that
provide additional information about the file components.
The 'component-type' is the type of the file components which
can be any ordinal, real, pointer, or structured type, except
for the following:
o A nonstatic type
o A structured type with a nonstatic component
o A file type
o A structured type with a file component
The arithmetic, relational, Boolean, and assignment operators
cannot be used with file variables or structures containing file
components. You cannot form constructors of file types.
Example: FILE OF Boolean
This example shows a file of Boolean values. If a variable,
'TRUTHS', is declared of this type, the file buffer is denoted by
TRUTHS^.
4.4.1 – Text file
VSI Pascal supplies a predefined file type called TEXT. Files of type TEXT are sequences of characters with special markers (end-of-line and end-of-file) added to the file. Although each character of a TEXT file is one file component, the end-of-line marker allows you to process the file line-by-line (using READLN, WRITELN, or EOLN), if you choose. The predeclared file variables INPUT and OUTPUT are files of type TEXT. They refer to the standard input and output files. The file type FILE OF CHAR differs from TEXT files in that FILE OF CHAR allows a single character to be the unit of transfer between a program and its associated I/O devices and that FILE OF CHAR files do not include special markers. FILE OF CHAR components are always read with the READ procedure, and must be read exclusively into variables of type CHAR, including CHAR components of structured variables. You cannot use the EOLN, READLN, and WRITELN routines on FILE OF CHAR files.
4.4.2 – External and internal files
VSI Pascal makes distinctions between external and internal files. An internal file has a name in a directory and exists outside the context of a VSI Pascal program. An internal file has no name and is not retained after the program finishes execution. A file declared in the program heading is external by default. A file declared in a nested block is internal by default. To change the default for internal files, call the OPEN procedure or specify a filename on the EXTEND, RESET, or REWRITE procedures. The file is then considered external and is retained with the specified name after the program has finished execution. If you open an internal file with the EXTEND, RESET, or REWRITE procedure, the file remains an internal file.
5 – Schema Types
A schema type is a user-defined construct that provides a
template for a family of distinct data types. A schema type
definition contains one or more formal discriminants that take
the place of specific boundary values or variant-record
selectors. By specifying boundary or selector values to a
schema type, you form a valid data type; the provided boundary
or selector values are called actual discriminants.
Syntax:
schema-identifier
({discriminant-identifier},... : [[attribute-list]]
ordinal-type-name};...) = [[attribute-list]] type-denoter;
The 'schema-identifier' is the name of the schema.
The 'discriminant-identifier' is the name of a formal
discriminant.
The 'ordinal-type-name' is the type of the formal discriminant,
which must be an ordinal type.
The 'attribute-list' is one or more identifiers that provide
additional information about the type-denoter.
The 'type-denoter' is the type definition of the components of
the schema. This must define a new record, array, set, or
subrange type.
Each schema type definition requires at least one discriminant
identifier. A discriminant identifier does not have to be used
in the type-denoter definition, but it is used to determine type
compatibility. Discriminant identifiers can appear anywhere a
value is required in this definition.
TYPE
Array_Template( Upper_Bound : INTEGER )
The identifier Upper_Bound is the formal discriminant of the
Array_Template schema. The Array_Template schema is not a
complete description of data. It is not a valid data type until
you provide an actual discriminant that designates the upper
boundary of the array template.
Actual discriminants can be compile-time or run-time
expressions. This expression must be assignment compatible with
the ordinal type specified for the formal discriminant. Also,
the actual discriminant value must be inside the range specified
for the formal discriminant; in the case of subranges, the upper
value must be greater than or equal to the lower value.
5.1 – Discriminated Schema
A discriminated schema is a schema type that has been provided
actual discriminants. Discriminated schema can appear in either
the TYPE or the VAR sections. For example:
TYPE
Array_Template( Upper_Bound : INTEGER )
VAR
Array_Type1 : Array_Template( 10 ); {ARRAY [1..10] OF INTEGER;}
Array_Type2 : Array_Template( x ); {Upper boundary determined
at run-time by variable or
function call}
In this example, the actual discriminants 10 and x complete the
boundaries for Array_Template, forming two complete data types
within the same schema type family. The type specifiers
Array_Template( 10 ) and Array_Template( x ) are examples of
discriminated schema.
5.2 – Undiscriminated Schema
An undiscriminated schema is a schema type that has not been
provided actual discriminants. You can use an undiscriminated
schema as the domain type of a pointer or as the type of a
formal parameter. For example:
TYPE
Ptr_to_Array_Template = ^Array_Template;
Array_Template( Upper_Bound : INTEGER )
The Array_Template schema is not a complete description of data.
It is not a valid data type until you provide an actual
discriminant that designates the upper boundary of the array
template.
6 – String Types
You can use schema and data types to store and to manipulate
character strings. These types have the following order of
complexity:
1. CHAR type
2. PACKED ARRAY OF CHAR user-defined types
3. VARYING OF CHAR user-defined types
4. STRING predefined schema
Objects of the CHAR data type are character strings with a
length of 1 and are lowest in the order of character string
complexity. You can assign CHAR data to variables of the other
string types.
The PACKED ARRAY OF CHAR types allow you to specify fixed-length
character strings. The VARYING OF CHAR types are a VSI Pascal
extension that allows you to specify varying-length character
strings with a constant maximum length. The STRING types
provide a standard way for you to specify storage for
varying-length character strings with a maximum length that can
be specified at run time.
To provide values for variables of these types, you should use a
character-string constant (or an expression that evaluates to a
character string) instead of an array constructor. Using array
constructors with STRING and VARYING OF CHAR types generates an
error; to use array constructors with PACKED ARRAY OF CHAR
types, you must specify component values for every element in
the array (otherwise, you generate an error).
Example:
VAR
String1 : VARYING[10] OF CHAR VALUE 'abc';
6.1 – String
The STRING predefined schema provides a way of declaring
variable-length character strings. The compiler stores STRING
data as though it were stored in the following schema
definition:
TYPE
STRING ( Capacity : INTEGER ) = VARYING[Capacity] OF CHAR;
The syntax of the discriminated schema is as follows:
STRING ( Capacity )
The 'Capacity' is an integer in the range 1..65,535 that
indicates the length of the longest possible string.
To use the predefined STRING schema, you provide an upper bound
as the actual discriminant. Consider the following example:
VAR
Short_String : STRING( 5 ); {Maximum length of 5 characters}
Long_String : STRING( 100 ); {Maximum length of 100 characters}
You can assign string constants to STRING variables from length
0 to the specified upper bound. The compiler allocates enough
storage space to hold a string of the maximum length. A STRING
variable with length 0 is the empty string (''). You can only
use character-string constants (or expressions that evaluate to
character strings) to assign values to variables of these types;
you cannot use standard array constructors.
You can access the CAPACITY predeclared identifier as you would
a schema discriminant, and you can access the LENGTH and BODY
predeclared identifiers as you would access fields of a record.
The CAPACITY identifier allows you to access the actual
discriminant of the STRING schema; the LENGTH identifier allows
you to access the current length of the string object; and the
BODY identifier contains the current string object, including
whatever is in memory up to the capacity of the discriminated
schema.
6.2 – PACKED
User-defined packed arrays of characters with specific lower and upper bounds provide a method of specifying fixed-length character strings. The string's lower bound must equal 1. The upper bound establishes the fixed length of the string.
6.2.1 – Examples
The following example shows a declaration of a character string
variable of twenty characters:
VAR
My_String : PACKED ARRAY[1..20] OF CHAR;
Note that if the upper bound of the array exceeds 65,535, if the
PACKED reserved word is not used, or if the array's components
are not byte-sized characters, the compiler does not treat the
array as a character string.
6.3 – Varying of char
The VARYING OF CHAR user-defined types are a VSI Pascal
extension that provides a way of declaring variable-length
character strings with a compile-time maximum length. If you
require portable code, use the STRING predefined schema types to
specify variable-length character strings.
Syntax:
VARYING [upper-bound] OF [[attribute-list]] CHAR
The 'upper-bound' is an integer in the range from 1 through
65,535 that indicates the length of the longest possible string.
The 'attribute-list' is one or more optional identifiers that
provide additional information about the VARYING OF CHAR string
components.
To assign values to fixed-length character strings, you can use
a character-string constant (or an expression that evaluates to
a character string). When assigning into fixed-length strings,
the compiler adds blanks to extend a string shorter than the
maximum characters declared. If you specify a string longer
than the maximum characters declared, an error occurs. You can
also use an array constructor as long as you specify characters
for every component of the array as specified in the
declaration.
Although a VARYING OF CHAR is a distinct type, it possesses some
of the properties of both record and array types. A VARYING
string is actually stored as though it were a record with two
fields, LENGTH and BODY (which are predeclared identifiers in
VSI Pascal). The LENGTH field contains the length of the
current character string; the BODY field contains the string.
Either field can be accessed in the same way record fields are
accessed (VARY.LENGTH, VARY.BODY).
Example: VARYING [25] OF CHAR
This VARYING OF CHAR type could have the following values:
'Wolfgang Amadeus Mozart'
'Bach'
7 – Misc Types
VSI Pascal provides a predefined data types that can be used with specific routines.
7.1 – TIMESTAMP
The TIMESTAMP predefined type is used in conjunction with the GETTIMESTAMP procedure or with the DATE or TIME functions. GETTIMESTAMP initializes a variable of type TIMESTAMP; DATE and TIME function results are of type TIMESTAMP.