Other data types include:
Bool is a boolean logical integer data type, where 0 is False and -1 is True. A Bool is a 2 byte Short, with a default of False.
A Variant is a data item used to communicate with COM objects. It contains an indicator of the type of data in addition to the actual data or a pointer to the data in the case of large data items. The variant structure itself is 16 bytes. The following table shows the variant types (enumAVarType) that can be created by ATEasy statements:
Name |
Value |
ATEasy equivalent |
vtEmpty |
0 |
Un-initialized Variant variable |
vtNull |
1 |
SQL-style Null |
vtI2 |
2 |
Short |
vtI4 |
3 |
Long |
vtR4 |
4 |
Float |
vtR8 |
5 |
Double |
vtCy |
6 |
Currency |
vtDate |
7 |
DateTime |
vtBStr |
8 |
BString |
vtDispatch |
9 |
Object |
vtError |
10 |
Error Code |
vtBool |
11 |
Bool |
vtVariant |
12 |
Variant |
vtUnknown |
13 |
Object of known type, for example, ACheckBox |
vtDecimal |
14 |
Decimal |
vtUI1 |
17 |
Byte |
vtI8 (ATEasy 5.0) |
20 |
DLong |
vtUI8 (ATEasy 5.0) |
21 |
DDWord |
If an ATEasy variable of a data type not listed above is assigned to a Variant variable, it is converted to the closest matching type as shown in the following table:
Name |
ATEasy data type to be converted |
vtI2 |
Word, WChar |
vtI4 |
DWord, Enum |
vtBStr |
String |
vtUI1 |
Char |
If an ATEasy struct variable is assigned to a variant variable, the data bytes of the structure will be converted to a one-dimensional array of bytes. ATEasy variables of type Procedure cannot be assigned to a variant -- the parser will flag this as an error.
If you assign one Variant to another, the resultant Variant will contain the value of the first Variant, but not the Variant itself, for example,
vnA = nA ! nA is Short
vnB = vnA
Then vnB contains the value of nA, not the Variant vnA.
If you assign a String to a Variant, ATEasy will first convert the value of the String variable to a BString and then store that value into the Variant.
If you assign an array to a Variant, ATEasy stores the entire array into the Variant, which can then be treated like an array, with subscripting, etc.
The default value for a Variant is Empty.
Variants offer great flexibility, but at the expense of inefficiency, and can cause some problems when assigning unexpected values.
You will get an error if you attempt to perform a mathematical operation or function on a Variant that does not contain a number or something that can be interpreted as a number (for example, 2.4E13 is a valid number). When a Variant tries to convert a non-numeric (such as a String containing a number) to a numeric value, it uses the Regional settings from the Windows Control Panel to interpret the decimal separator, thousands separator, and currency symbol.
Using operators on Variants containing strings can lead to some problems. For instance, if two Variants (each containing a numeric value) are separated by the "+" operator, a simple addition occurs. If the two Variants contained strings, however, a concatenation would occur. But if one of them is a numeric and the other is a string, the Variant will try to convert the string to an number and try to add them. If the conversion is unsuccessful, you will get a "Type mismatch" error. If you wanted concatenation, you would need to first convert the numeric to a string.
Variants can be used as a way of handling a variety of data types. For instance, since all the elements in an array must be of the same data type, you can set the data type of an array to Variant and then store objects alongside other data types in that array.
A Procedure data type is a reference to a procedure. The default is NoProcedure. For example, you wrote a function procedure named "Add(a,b)", which added the two variables 'a' and 'b' and returned their sum. Then you wrote a second function procedure named "Sub(a,b)" which subtracted the second variable from the first. Now you could assign a variable "prc" with data type of Procedure. Then you could assign "prc" to have different values in your code:
prc = Add ! Without the parentheses after the name Add
Print prc (2,3) ! Result is 5
prc = Sub
Print prc(2,3) ! Result is -1
Note: Any form procedure or event must be called from that form or a form of the same type. If your program calls a procedure by using a variable (of type Procedure, for example, the above "prc"), and the procedure it references is a form procedure (either a procedure of the form or one of its events, or subcomponent procedures or events), then that call must be from within the same form. ATEasy does not check the arguments of the Procedure variable (for example, "prc") at design time. When you try to execute it at run time, ATEasy will check the arguments by looking for the referenced form procedure within the scope of that form.
An Object variable can contain a COM object, stored in a 32-bit (4-byte) address and can have any valid object reference assigned to it. The default value is Nothing.
Early binding versus late binding: A variable of type "Object" is called late bound. Since it can contain any COM object, at run time ATEasy will have to perform validity checks to resolve the type, properties, methods, etc. If an Object variable is "declared" with a specific class, then only objects of that class can be assigned to the variable. The parser can verify if the attempted use is valid for that class, for example, the referenced member (property or method) exists. This is called early binding.
As examples of early and late binding, say you declare a variable with a Name of "ob1" and use a Type of "Object". It will be a late bound object variable. If you declare another variable with a Name of "ob2" and you enter a Type of "AMenu", since AMenu is a known class object, it will be an early bound object variable.
Note: ATEasy provides a way at design time to tell if you have correctly typed in the name of a user-defined Type and/or if the intended type has been defined. If in the Type field you enter a type in all one case (all lowercase or all uppercase, for example, "amenu" or "AMENU") and press the Return key, ATEasy will attempt to find that type. If it finds it, it will replace the type with the official name in mixed case, for example, "AMenu". If ATEasy does not find it, it will leave the field as it was typed. This is a hint to you as a programmer that you have an undeclared type. You can still proceed to write more code and worry about it later. But any time you parse that variable (for example, use any of the Run commands, such as CheckIt!, DoIt!, etc.), ATEasy will generate an error message ("Unresolved type"). At that point, you need to specify a known object type.
In ATEasy 5.0, Any is a built-in basic type and it behaves like an alias to another ATEasy variable or data element (for example, in a structure). That is, it holds not only 4 bytes of address of a symbol or an object, but also it keeps its data type (and more) information. The following list describes the usage of type Any:
You can have an array of Any
type. Each array item can be set to the address of symbol, e.g.,
aAnyArray[2]=&adNum[4].
You can compare two variables of type Any,
which point to 'compatible' data type - see examples below. They
are equal if and only if they point to the same.
You can assign Object to Any
--- its Punk (pointer to its UNKNOWN interface pointer) will be stored
in Any and later you can assign
it to the object symbol.
You can use AND
and OR operators like in
C.
You can add an offset to an Any,
subtract an Any from an Any to find out certain size info. But you
cannot add Any to a different Any.
The resulting type of the operator '&' is Any,
thus it restricts operations if its result is assigned to Any.
Certain operators that are applied to Any
behave the exactly the same way as they would be applied to the variable
which the Any variable points
to.
Warning: the user has to use this type with care because ATEasy cannot checking the validity of address, e.g., MemoryCopy(anyXXX, anyYYY, sixe of xxxyyy).....
When an Any variable is declared, its value is null, the address is
0, and the size is 0. After the assignment to the address of a double
variable (&), it becomes exactly like one of type double - its size
is 8 (sizeof),
type is Double (typeof),
and the address (&) of Any variable gives the same address as the
Double variable.
A Var/Val parameter in a DLL procedure can have the Any
data type. The Var parameter Any
is useful for low-level input and output procedures which need the address
of a data buffer.
The DLL procedure VAL Any data type can be used for passing a literal value/string since Var parameter does not allow literals. Internally, Var or Val Any parameter are treated as same; that is, its pointer is being passed.
The Any data type allows ATEasy code to pass a variable of any ATEasy data type instead of having to define a different DLL procedure for each data type to be passed to the DLL procedure. Such DLL procedures almost always have another parameter which is the number of bytes of data to transfer.
The following is an example of using the Any data type. Assume you have the following DLL procedure:
SendBinaryData (pData, lByteCount): Void
pData Var Any
lByteCount Val Long
If this DLL procedure is called as follows, the procedure will "send" the 8 bytes of the Double variable dValue:
SendBinaryData ( dValue, sizeof dValue )
and the following call will "send" the 24 bytes contained in the 2 by 3 array of Float, afArray:
SendBinaryData ( afArray, sizeof afArray )
The following examples illustrate Any variables are different from pointer variables in C:
any1=&a3i ! a3i
is an array of Long of size 3
any2=&a3i[0] ! now any2 is pointing to the address of the
first element
Suppose ai is an array of at least its size 3. The following assignments are all legal:
any1=ai
any2=7
but the following assignments are illegal (run-time errors):
any1=7
any2=ai
because the right hand sides' data types are not compatible with the left hand sides.
Both any1 and any2 have the same address: the address of the array(any1) is the same as the address of the first array element (any2). Yet they are different. Thus, the following comparison is False:
if any1=any2
Yet, if you ask the addresses explicitly, the following comparison is True:
if &any1=&any2
Basic Data Types, Data Conversion, Numeric, Strings, User Defined Date Types, APointer Typedef