ANY (any simple data type)

Top  Previous  Next

 

label ANY [,DIM( )] [,NAME( )] [,EXTERNAL] [,DLL] [,STATIC] [,THREAD] [,PRIVATE] [,PROTECTED]

 

ANY

A variable that may contain any value (numeric or string) or a reference to any simple data type.

DIM

Dimension the variable as an array.

NAME

Specify an alternate, "external" name for the field.

EXTERNAL

Specify the variable is defined, and its memory is allocated, in an external library. Not valid within FILE, QUEUE, or GROUP declarations.

DLL

Specify the variable is defined in a .DLL. This is required in addition to the EXTERNAL attribute.

STATIC

Specify the variable's memory is permanently allocated.

THREAD

Specify memory for the variable is allocated once for each execution thread. Also implicitly adds the STATIC attribute on Procedure Local data.

PRIVATE

Specify the variable is not visible outside the module containing the CLASS methods. Valid only in a CLASS.

PROTECTED

Specify the variable is not visible outside base CLASS and derived CLASS methods. Valid only in a CLASS.

 

ANY declares a variable of a reference type which points to an internal RTL data structure. That structure can hold values of any numeric or string type, and references to any simple data type and to GROUPs. This allows an ANY variable to be used as a "generic" data type. An ANY variable may be declared within a CLASS, GROUP, or QUEUE structure, and may not be declared within a FILE structure.

If an ANY variable is declared outside a GROUP or QUEUE structure it is initialized to a NULL reference. Such ANY variables must be declared without the AUTO attribute.

When an ANY variable is the destination of a simple assignment statement (destination = source) and it contains a NULL reference, the RTL first creates an internal object of a default type and sets the ANY variable to referencethat object, and then performs the assignment of the value of the source expression to that internal object. When an ANY variable is the destination of a simple assignment statement and it contains a non-NULL reference, the assignment changes value of a variable, or a structure pointed ay by that reference. An ANY variable uses REAL as its base type for numeric operations, which can mean loss of precision when assigned DECIMAL values with more that 14 significant digits.

When an ANY variable is the destination of a reference assignment statement (destination &= source), the RTL disposes its previous internal data and replaces it with a new object which holds a reference to the source variable. If the source of a reference assignment is NULL, the RTL disposes the previous internal data of the ANY variable from the left side, and then sets the ANY to a NULL reference.

 
 When an ANY variable is the parameter of the CLEAR statement, the data it points to is cleared.

An ANY can be named in the USE attribute of any control in a window or report, provided that the ANY contains a non-NULL reference. If an ANY variable named in the USE attribute has not been set to reference to some variable declared in the program, i.e. it references a default object created by the RTL, the program should not perform a reference assignment with such ANY as a destination. (See the rules of reference variables as USE variables)

 
 You cannot pass an ANY variable as a variable-parameter (by address) unless the calling procedure is prototyped to receive an untyped variable parameter (*?). If an ANY variable passed as a parameter of *? type has not been set to reference to some variable declared in the program, i.e. it references a default object created by the RTL, the program should not perform a reference assignment with such ANY as a destination, for example, from other threads, until the Procedure returns.

When an ANY variable is declared in a QUEUE structure, there are some special considerations that must be followed. This is due to the internal representation of an ANY and its polymorphic characteristics.

 

Use of CLEAR() and reference assignments with QUEUE entries.

 

Once an ANY variable in a QUEUE has been assigned a value, another simple assignment statement will assign a new value to the ANY. This means the previous value is replaced by the new value. If the first value has already been added to the QUEUE, then that entry will "point at" a value that no longer exists.

 

Once an ANY variable in a QUEUE has been reference assigned a variable (AnyVar &= SomeVariable), another reference assignment statement will assign a new variable to the ANY. This means the previous "pointer" is disposed of and replaced by the new "pointer." If the first reference has already been added to the QUEUE, then that entry will "point at" a "pointer" that no longer exists.

Therefore, Queue fields of type ANY must be set to NULLs by executing the CLEAR statement with the QUEUE record structure itself as parameter, i.e. the program must execute CLEAR(Queue), before setting new values of queue field of type ANY for the next ADD() or PUT(). This is because CLEAR for QUEUEs and GROUPs are not applied recursively to the data pointed at from fields of reference types. Therefore, CLEAR(queue) just sets fields of type ANY to NULLs without disposing of their internal data.

In addition, you need to reference assign a NULL to all queue fields of type ANY (Queue.AnyField &= NULL), prior to deleting the QUEUE entry, in order to avoid memory leaks.

 

Example:

MyQueue  QUEUE

AnyField ANY                     !Declare a variable to contain any value

Type      STRING(1)

        END

DueDate  DATE                     !Declare a date field

CODE

MyQueue.AnyField = 'SoftVelocity'!Assign a string value

MyQueue.Type = 'S'               !Flag data type

ADD(MyQueue)

CLEAR(MyQueue)                   !Clear the reference

MyQueue.AnyField &= DueDate      !Assign a Reference to a DATE

MyQueue.Type = 'R'               !Flag data type

ADD(MyQueue)

LOOP X# = RECORDS(MyQueue) TO 1 BY -1 !Process the QUEUE

 GET(MyQueue,X#)

 ASSERT(~ERRORCODE())

 CASE MyQueue.Type

 OF 'S'

  DO StringRoutine

 OF 'R'

  DO ReferenceRoutine

 END

 MyQueue.AnyField &= NULL         !Reference assign NULL before deleting

 DELETE(MyQueue)

 ASSERT(~ERRORCODE())

END

 

Use of ANY in CLASS/GROUP definitions.

If you do a reference assignment, or assign a value to an ANY that is a member of a CLASS or GROUP, you must clear the reference before destroying the class, otherwise the memory allocated by the reference assignment will not be freed.

Example:

AClass CLASS

AnyVar   ANY,PRIVATE

AMethod  PROCEDURE(FILE f)

Destruct PROCEDURE()

      END

 

TextFile FILE,DRIVER('ASCII')

         RECORD

Line       STRING(255)

         END

        END

 CODE

   AClass.AMethod(TextFile)

 

AClass.AMethod PROCEDURE(FILE TextFile)

AGroup &GROUP

 CODE

   AGroup &= TextFile{PROP:Record}

   SELF.AnyVar &= WHAT(AGroup, 1)

 

AClass.Destruct PROCEDURE()

 CODE

   SELF.AnyVar &= NULL  !Without this line the program will leak memory

 

The ANY data type is represented with the special dedicated Clarion.ClaAny class.

 

The ANY data type of Clarion .NET is compatible with the ANY data type of the WIN 32 Clarion.

Remarks:

1. Unlike WIN32 Clarion, you can use the type ANY in a NEW statement.

2. You can’t assign a reference to array to an ANY variable

 

See Also:

Simple Assignment Statements

Reference Assignment Statements