Site Menu Project Specification Implementation Recommendations Reference Needs Updating Work in Progress Wastebasket Wiki Manual |
Flexible Array Fields In RecordsTerminologyDeterminate and Indeterminate Types
Array Bounds
Record Types and Fields
Declaration of Indeterminate Record TypesIndeterminate record types may be declared, provided that the type declaration meets all of the following conditions:
An example declaration of an indeterminate record type TYPE Foobar = RECORD a, b, c : Foo; (* other fields *) size : CARDINAL; (* discriminant field *) ~ buffer : ARRAY size OF OCTET; (* indeterminate field *) END; (* Foobar *) AllocationThe value returned by Records of an indeterminate type may only be allocated dynamically at runtime using the The compiler replaces a macro call to The allocation size is calculated by the following formula: allocSize(T) = TSIZE(T) + discriminant * TSIZE( baseType(T.indeterminateField) )
where T is the indeterminate record type, discriminant is the discriminant value passed to An example allocation of a new record of indeterminate type VAR foo : POINTER TO Foobar; BEGIN (* allocate a record of type Foobar with a buffer of 100 elements *) NEW foo OF 100; This source fragment is then replaced by the compiler with the following code fragment: ALLOCATE( foo, TSIZE(foo) + 100 * TSIZE(OCTET) ); IF foo # NIL THEN foo^.size := 100 END; Immutability of the Discriminant FieldThe discriminant field of a record of indeterminate type is automatically initialised when it is allocated. After initialisation the discriminant field becomes immutable and the compiler enforces its immutability as follows:
The following statements all result in compile time errors due to immutability of INC(foo^.size, 10); (* discriminant fields may not be passed as VAR parameter *) foo^.size := newSize; (* discriminant fields may not be assigned to *) foo^.size++; (* discriminant fields may not be used with ++ or -- *) Run-time Bounds CheckingAccess to the indeterminate array field of a record of indeterminate type is bounds checked at runtime in the same manner as access to a determinate array is checked. The compiler automatically inserts the code to check array subscripts against the discriminant field. Any attempt to access the array with a subscript that is out of bounds results in a run-time error. An example of an assignment to a variable size array field is shown below:
generates target code equivalent to
Assignment CompatibilityThe assignment compatibility of two records of indeterminate type cannot be verified at compile time. For this reason records of indeterminate type can only be copied field-wise, not record-wise. The following example shows how one record of type VAR foo, bar : POINTER TO Foobar; BEGIN foo^.a := bar^.a; foo^.b := bar^.b; foo^.c := bar^.c; FOR index, value IN foo^.buffer DO value := bar^.buffer[index] END; The following example will result in a compile time error:
Parameter passingSince the compatibility of records of indeterminate types cannot be determined at compile time, it follows that indeterminate record types may not be formal types and records of indeterminate type may not be passed as parameters unless the formal type is The following example declaration results in a compile time error: PROCEDURE clear ( f : Foobar ); (* compile time error: indeterminate record types may not be formal types *) The indeterminate field of a record of indeterminate type may be passed as a parameter whose formal type is an open array with the same element type as the indeterminate field's array type. An example of passing the indeterminate field PROCEDURE clear ( VAR buffer : ARRAY OF OCTET ); VAR index : CARDINAL; BEGIN FOR VALUE elem IN buffer DO elem := 0; END; END clear; BEGIN (* module initialisation *) clear( foo^.buffer ); DeallocationRecords of indeterminate type may only be deallocated using the An example deallocation of a record of type
This statement is then transformed by the compiler to the following code fragment
Outstanding IssuesThe following issues still need to be resolved Attempt to allocate without the use of
|