Data types

The Data Types table below summarizes the data types available for use in Synergy DBL. The “Valid in” columns indicates whether types can be used with traditional Synergy and Synergy .NET. See Data type descriptions for more details on each data type. See Where data types can be used for information on where (fields, parameters, return values) these types can be used.    

Note

The Data Types table includes the .NET data types for which we have created a shorthand type (e.g., “uint” for System.UInt32), those for which there is also support in traditional Synergy, and those for which we perform some special handling. However, you can use any data type in .NET’s System namespace when you compile with the Synergy .NET compiler. (This namespace is imported automatically when you use the Synergy .NET compiler.) For example, commonly used types including Char, DateTime, Guid, IntPtr, and UIntPtr. Char, IntPtr, and UIntPtr are included in the table below because of special alignment with Synergy .NET (see Char and IntPtr and UIntPtr). See also Understanding .NET data types. For complete details on .NET data types, see System Namespace in the Microsoft documentation.

Data Types

Type

Valid in

Description

Default valuea

Traditional

.NET

a

Alpha

NA

a*

Alpha with initial value

The initial value used to size the a

asize

Fixed-length 8-bit character sequence

Spaces of specified size

boolean

System.Boolean in .NET; maps to i4 in traditional

false

byte

System.Byte in .NET (an unsigned 8-bit integer); maps to i1 in traditional (a signed 8-bit integer)

0

char

System.Char in .NET (a 16-bit numeric value); supports values for only one byte in traditional 0

d

Decimal

NA

d*

Decimal with initial value

The initial value used to size the d

dsize

Fixed-length decimal

Array of character “0” (zero) of specified size

d.

Implied-decimal

NA

dsize.precision

Fixed-length implied-decimal

Array of character “0” (zero) of specified size

decimal

System.Decimal in .NET; maps to d28.10 in traditional

0.0 in .NET; array of character “0” (zero) of size 28 in traditional

double

b

System.Double in .NET; maps to d28.10 in traditional

0.0

float

b

System.Single in .NET; maps to d28.10 in traditional

0.0

i

Integer

NA

i*

Integer with initial value

The initial value used to size the i

i1

Signed 8-bit integer

0

i2

Signed 16-bit integer

0

i4

Signed 32-bit integer

0

i8

Signed 64-bit integer

0

int

System.Int32 in .NET; maps to i4 in traditional

0

IntPtr

System.IntPtr

0

long

System.Int64 in .NET; maps to i8 in traditional

0

n

Whole number numeric

NA

n.

Implied and whole number numeric

NA

p

Packed

NA

psize

Packed

Array of character “0” (zero) of specified size

p.

Implied-packed

NA

psize.precision

Implied-packed

Array of character “0” (zero) of specified size and precision

sbyte

System.Sbyte in .NET; maps to i1 in traditional (a signed 8-bit integer)

0

short

System.Int16 in .NET; maps to i2 in traditional

0

string

System.String in .NET; Synergy DBL System.String in traditional

^NULLc

T (or other unused letter)

Generic type parameter

 

uint

System.UInt32

0

UIntPtr

System.UIntPtr

0

ulong

System.UInt64

0

ushort

System.UInt16

0

^VAL

A calling convention. See ^VAL below.

NA

VOID

Method does not return a value

NA

@*

System.Object in .NET; shorthand for Synergy DBL System.Object in traditional

^NULLc

@class

A specific class type

^NULLc

@delegate

A specific delegate

^NULLc

@interface

A specific interface

^NULLc

@type

A specific boxed type

Depends on data type

enumeration

A specific enumeration

0

structure

A specific structure type

Individual fields are initialized based on their type

[#,#]type

Dynamic array of the specified type

Depends on value type

[#,#]@type

[#,#]@class

[#,#]@*

Dynamic array, where array can have up to 9 dimensions (for example, [#,#,#,#])

^NULLc

D_ADDR

A data type identifier for a routine address 0
D_ADDRSIZE The size of a native pointer NA
D_GRFA_TYPE GRFA-required type and size NA
D_HANDLE

A data type identifier for a memory handle NA
D_MAXINT Maximum supported int size NA
D_NATINT Size of native int in C NA
D_NATLNG Size of native long in C NA
D_RFA_TYPE RFA-required type and size NA

a. In traditional Synergy, fields in stack records and DATA statements, other than objects, have no default value.

b. Not recommended for use in traditional Synergy.

c. ^NULL represents an uninstantiated object handle and can be used wherever an object can be used.

Understanding .NET data types

With Synergy .NET, there are three basic types of data types: value types, descriptor types, and class types. All inherit from the .NET class System.Object. This means, for example, that you can use System.Object methods, such as ToString, with all Synergy .NET data types.

1. Data types in Synergy .NET.

Value types are structures in the .NET System namespace (System.Int32, for example). They directly access data and are, therefore, the most efficient data types. For example, in Synergy .NET, int maps to the System.Int structure.

Descriptor types use a class that contains information on the data type and memory location of actual data. Consequently, descriptor types aren’t as efficient as value types, but they do have the following advantages:

In this classification, all other data types are class types. This includes System.Object itself, as well as @class, @interface, @delegate, @value_type, and any other class data type, such as System.String.

The table below shows how the Synergy .NET data types are classified:

Value types

Descriptor types

Class types

boolean

byte

char

decimal

double

float

int

IntPtr

long

sbyte

short

structurea

T

uint

UIntPtr

ulong

ushort

^VAL

a

a*

asize

d

d.

d*

dsize

dsize.precision

i

i*

i1, i2, i4, i8b

n

n.

structurea

@*, System, System.Object

@class

@delegate

@interface

@value_type

[#,#]value

[#,#]@*

[#,#]@class

[#,#]@value

enumeration

T

a. If the CLS modifier is included in the structure definition, it’s a value type; otherwise it’s a descriptor type.

b. When passed, i1, i2, i4, and i8 are descriptor types. Otherwise, Synergy .NET optimizes them by making them value types.

When resolving types. the compiler first looks for an exact case match. If an exact match is not found, type resolution becomes case insensitive. For example, if we have

fld1, @class1
fld2, @Class1

and both class1 and Class1 are defined, they will resolve to those names exactly. However, if there is only a class1 or a CLASS1, it will resolve to either of those names.

Nullable types

A nullable type represents all values of an underlying data type plus an additional null value. (For example, a nullable Boolean type can have a value of true, false, or null.) A nullable type maps to the System.Nullable structure, and its primary purpose is to enable you to set value types to ^NULL.

To declare a nullable type, specify a question mark (?) after the data type. For example,

Myfield, integer?

Only non-Synergy value types may be specified as nullable types. If nullable syntax is specified on a Synergy type (such as a, d, etc.), for example,

nafld, a20?

an “Invalid expression at or near ?” error (INVEXPR) is generated.

Since Nullable is a generic type, you can alternatively declare a nullable type as follows:

Myfield,  Nullable<T>

The default value for an item whose type is nullable is ^NULL.

You can use a cast to convert from a nullable type to its “base” type, as in the example below:

intvar = (int)nullableintvar
nullableintvar = ^null

IF (nullable) is true when the result is not ^NULL or 0, and IF (!nullable) is true when the result is ^NULL or 0.

Data type descriptions

Alpha

An alpha value (a, a*, asize) is a consecutive sequence of characters that can be treated as a unit of information. Alpha data can include only printable ASCII characters, and alpha values are limited to 65,535 characters on 32-bit platforms running traditional Synergy.

See Where data types can be used for more information.

Alpha types are descriptor types and have the same functionality for both traditional Synergy and Synergy .NET.

Video

See the Synergex YouTube video Alpha Data for more information about the alpha data type.

Boolean

The boolean data type represents a Boolean (true/false) value. The default boolean value is false.

With traditional Synergy, boolean maps to i4. A boolean value is evaluated as %TRUE if true, and as %FALSE if false.

With Synergy .NET, boolean is a value type and maps to the .NET System.Boolean structure.

Video

See the Synergex YouTube video Boolean Data for more information about the boolean data type.

Byte

With traditional Synergy, the byte data type represents an eight-bit signed integer and maps to i1. With Synergy .NET, byte represents an eight-bit unsigned integer and maps to the .NET System.Byte structure. The default for a byte value is 0.

If you are using byte as a signed integer in traditional Synergy, we recommend that you use sbyte instead.

Char

With traditional Synergy, the char data type represents a C# char (a 16-bit numeric value, which maps to the .NET System.Char structure). Char enables a DBL program to reserve a field of size 2 and write records with chars in them, which can then be read by C# programs.

Decimal and implied-decimal

The d, d*, and dsize types represent decimal data, which are signed, whole numbers that consist of ASCII numeric characters. The d., dsize.precision, and decimal types represent implied decimal data, which are signed numbers that consist of a whole number part and a fractional precision.

See Where data types can be used for more information, and note the following:

Note

The f designation for the fixed-point data type in previous versions of Synergy DBL is still valid with traditional Synergy, where it is processed as implied-decimal. Fixed-point is not supported in Synergy .NET.

Video

See the Synergex YouTube videos Decimal Data and Implied-Decimal Data for more information about the decimal and implied-decimal data types.

Double

With Synergy .NET, double is a value type and maps to the .NET System.Double structure. The default value is 0.0.

Double is not recommended for use with traditional Synergy (where it maps to d28.10 and has a default of 0.0).

Float

With Synergy .NET, float is a value type and maps to the .NET System.Single structure. The default is 0.0.

Float is not recommended for use with traditional Synergy (where it maps to d28.10 and has a default of 0.0).

Integer

An integer value is a byte-oriented, binary representation of a signed whole number. Depending on how and where it is specified, an integer can be a value type or a descriptor type.

These types have the same functionality for both traditional Synergy and Synergy .NET. In general, they are descriptor types, but Synergy .NET usually optimizes them by making them value types and mapping them to the .NET System.SByte, System.Short, System.Int32, and System.Int64 value types.

Note that these types are stored in native integer form, so data files that contain integer data (including ISAM files) are not portable between big-endian and little-endian machines. (To convert integer data between native and portable formats, use the %CNV_IP and %CNV_PI intrinsic functions.)

Video

See the Synergex YouTube video Integer Data for more information about the integer data type.

IntPtr and UIntPtr

The .NET System.IntPtr and System.UIntPtr. Both are unsigned integers of native size, depending on platform (4 bytes on 32-bit and 8 bytes on 64-bit). Because .NET assemblies are platform agnostic, IntPtr and UIntPtr are aligned on an 8-byte boundary on both 32-bit and 64-bit systems, and they always take up 8 bytes, even though they use only four bytes for data on 32-bit systems. (Synergy .NET only)

Long

With traditional Synergy, long maps to i8. With Synergy .NET, long is a value type and maps to System.Int64. The default value is 0.

Numeric

The numeric types, n and n., define numeric parameters for subroutines, functions, and classes (with some exceptions; see Where data types can be used). Numeric parameters can be used to pass any of the numeric data types: decimal, packed, or integer (for n), and implied decimal or implied packed (for n.). The parameter is accessed as the type used in the calling routine. (You can use ^DATATYPE to find the data type passed.)

Numeric types are descriptor types and have the same functionality for both traditional Synergy and Synergy .NET.

Packed and implied-packed

Data in packed or implied-packed form (p, psize, p., or psize.precision) is stored as two digits per byte, plus an extra byte for the sign.

Whenever a packed or implied-packed field is used in an expression, it is converted to a decimal or implied-decimal field, respectively. Because of these restrictions, the only way to pass an expression to a subroutine or function in packed form is to assign it to a packed field before using it. (See Assignment statements for information about assigning an expression to a packed field.)

Note that packed and implied-packed types cannot be used with classes and are not supported with the Synergy .NET compiler. See Where data types can be used for more information.

Sbyte

With traditional Synergy, sbyte maps to an i1. With Synergy .NET, the sbyte data type represents an eight-bit signed integer. It is a value type and maps to the .NET System.Sbyte structure. The default value is 0.

Short

With traditional Synergy, short maps to an i2. With Synergy .NET, short is a value type and maps to System.Int16. The default value is 0.

String

With traditional Synergy, String (or System.String) maps to the Synergy DBL System.String class. With Synergy .NET, it maps to the .NET System.String class. In either case, the default value is ^NULL.

Note the following for traditional Synergy:

In Synergy .NET, String can also be concatenated with a number or an object.

Video

See the Synergex YouTube video String Data for more information about the string data type.

T

T represents a generic type parameter. Note that you can use any letter (not just T), with the restrictions that a generic type parameter cannot have the same name as a data type, and a generic type parameter name must be unique within the type parameters for the current declaration. See Generic types (.NET) for more information. (Synergy .NET only)

Uint

Uint is a value type and maps to the .NET System.UInt32 structure. The default value is 0. (Synergy .NET only)

Ulong

Ulong is a value type and maps to the .NET System.UInt64 structure. The default value is 0. (Synergy .NET only)

Ushort

Ushort is a value type and maps to the .NET System.UInt16 structure. The default value is 0. (Synergy .NET only)

^VAL

^VAL is a calling convention rather than an actual data type. It is a qualifier to subroutine parameters and return values and specifies that the parameter or return value will be passed by value as a native integer.

With traditional Synergy, ^VAL values map to i4 for 32-bit systems and i8 for 64-bit systems. With Synergy .NET, ^VAL is a value type and maps to the .NET System.IntPtr structure. You can have an argument of type ^VAL that identifies a calling convention using a value up to the size of a 32-bit or 64-bit int in traditional Synergy or a System.Intptr value in Synergy.NET.

See ^VAL for more information.

VOID

VOID specifies that a method does not return a value.

@*, Object, System.Object

@*, Object, or System.Object is the parent class of all objects, including all other data types. With traditional Synergy, this maps to the Synergy DBL System.Object class. With Synergy .NET, it maps to the .NET System.Object class, and because .NET assemblies are agnostic, it always takes 16 bytes and is aligned on a 16-byte boundary on both 32-bit and 64-bit systems.

The default value is ^NULL.

@class

@class assigns an object reference to a field, parameter, return type, or method property. That class becomes the variable’s type and you can use the object to access the class’s functionality.

If the class identifier is not unique within all imported namespaces, you must qualify the identifier with its namespace. If it is unique, specifying the namespace is optional. For example, if class1 is unique, a declaration using just class1 will work:

my_object   ,@class1

If class1 is not unique, the declaration might look like this:

my_object   ,@UserNS.class1

You can use @class in a named or unnamed record with traditional Synergy or Synergy .NET. The default value is ^NULL.

@delegate

@delegate assigns a delegate to a field, parameter, return type, or method property. The delegate becomes the variable’s type, and you can use the variable to access the delegate.

If the delegate identifier is not unique within all imported namespaces, you must qualify the identifier with its namespace. If it is unique, specifying the namespace is optional.

You can use @delegate in a named or unnamed record. The default value is ^NULL. (Synergy .NET only)

@interface

@interface assigns an interface to a field, parameter, return type, or method property. The interface becomes the variable’s type, and you can use the variable to access the interface. (Synergy .NET only)

If the interface identifier is not unique within imported namespaces, you must qualify the identifier with its namespace. If it is unique, specifying the namespace is optional. For example, if interface1 is unique a declaration using interface1 will work:

my_object   ,@interface1

If interface1 is not unique, the declaration might look like this:

my_object   ,@UserNS.interface1

You can use @interface in a named or unnamed record. The default value is ^NULL.

@type

@type assigns a boxed type to a field, parameter, return value, or method property. In traditional Synergy, type may be an non-class data type. In Synergy .NET, type may be any value or descriptor type. (See the classification lists in Understanding .NET data types for how types are classified in Synergy .NET.)

You can use @type in a named or unnamed record with traditional Synergy or Synergy .NET. The default value depends on the data type.

enumeration

The enumeration data type represents a set of related values. It has a name and one or more enumeration values associated with it. The compiler allows these values, or other integer values, to be assigned to a variable of the enumeration type. Enumeration values are represented by integer values, and with traditional Synergy, the enumeration type maps to i4. With Synergy .NET, it maps to System.Enum. The default value is 0.

It is possible to assign an integer value (including Boolean) to an enumeration variable by casting the integer value to the enumeration type. A cast is also required when an integer is expected but an enumeration is given, for example, in a conditional such as

if (intvar .eq. (int)color.red)

If the enumeration identifier is not unique within all imported namespaces, you must qualify the identifier with its namespace. If it is unique, specifying the namespace is optional.

The enumeration type supports bitwise comparisons and the == and != operations. See ENUM for details on declaring an enumeration.

structure

A defined structure can be used as a data type for a field, parameter, return type, property, or local variable. The resulting construct is called a structfield. For example,

var1    ,mystruct

A structfield replaces group syntax to allow definition of a variable (or array) that is strongly prototyped when passed as a routine argument. It supersedes the syntax of using ^M with an alpha field. It is especially useful when used in conjunction with the System.Collections.ArrayList class to provide dynamic arrays of structures to replace using %MEM_PROC and ^M.

The following example shows how to declare a field as a structure and use that structure:

structure MyStructure
    first       ,a10
    last        ,a10    ,"Initial"
endstructure
subroutine TestStructure
stack record
    tt          ,i4
    person      ,MyStructure    ;Declare a field that has the size of the structure
proc
    init person                   ;Clear first and set last to "Initial"
    person.first = "Joe"          ;Assign a value to a field in the structure
    open(tt=0, i, "tt:")
    writes(tt, person)
    close(tt)
    xreturn
endsubroutine

If the structure identifier is not unique within all imported namespaces, you must qualify the identifier with its namespace. If it is unique, specifying the namespace is optional.

Note that you can use structfields with traditional Synergy or Synergy .NET, where structfield is a value type (i.e., the CLS modifier is included in the structure definition). Wherever possible, if you’re using .NET value types, you should use CLS structures for efficiency reasons. CLS is ignored in traditional Synergy.

Individual fields are initialized based on their type. See Using a structure with a structfield for more information.

[#,#]type

[#,#]type defines a dynamic array of the specified data type.

In traditional Synergy, [#,#]type maps to the Synergy System.Array class, and [#,#] can have 1 to 9 dimensions, inclusive ([#], [#,#], and so on, up to [#,#,#,#,#,#,#,#,#]). Type may be any non-class data type other than a, d, i, d28.10, or float. (For a, d, i, etc., use [#,#]@type.) For example,

my_str_array    ,[#,#]struct1

In Synergy .NET, [#,#]type maps to the .NET System.Array class. Type may be any value or descriptor type. (See the classification lists in Understanding .NET data types for how types are classified in Synergy .NET.) The [#,#] is shorthand for System.Array.

The default value is ^NULL.

[#,#]@type

[#,#]@type defines a dynamic array in which the element is the specified boxed data type.

In traditional Synergy, [#,#]@type maps to the Synergy System.Array class, and [#,#] can have 1 to 9 dimensions, inclusive ([#], [#,#], and so on, up to [#,#,#,#,#,#,#,#,#]). Type may be any non-class data type.

In Synergy .NET, [#,#]@type maps to the .NET System.Array class. Type may be any value or descriptor type. (See the classification lists in Understanding .NET data types for how types are classified in Synergy .NET.) The [#,#] is shorthand for System.Array.

The default value is ^NULL.

[#,#]@class

[#,#]@class defines a dynamic array of the specified class. (The [#,#] is shorthand for System.Array.)

In traditional Synergy, [#,#]@class maps to the Synergy System.Array class and [#,#] can have 1 to 9 dimensions, inclusive ([#], [#,#], and so on, up to [#,#,#,#,#,#,#,#,#]). For example,

my_dyn_array     ,[#,#,#]@system.string

In Synergy .NET, [#,#]@class maps to the .NET System.Array class.

The default value is ^NULL.

[#,#]@*

[#,#]@ defines a dynamic array of any type of object. (The [#,#] is shorthand for System.Array.)

In traditional Synergy, [#,#]@ maps to the Synergy System.Array class and [#,#] can have 1 to 9 dimensions, inclusive ([#], [#,#], and so on, up to [#,#,#,#,#,#,#,#,#]).

In Synergy .NET, [#,#]@ maps to the .NET System.Array class.

The default value is ^NULL.

D_ADDR

The D_ADDR type is used for routine addresses for data fields, parameters, return types, and method properties. It’s a definition for a data type, rather than an actual data type. The default value is 0.

D_ADDR is i8 on 64-bit application targets and .NET AnyCPU and i4 on OpenVMS and 32-bit application targets.

D_ADDR is not supported for use with ^M or arguments to functions that take ^M. Handles for ^M should be defined using D_HANDLE.

D_ADDRSIZE

D_ADDRSIZE is 8 on 64-bit application targets and .NET AnyCPU and 4 on OpenVMS and 32-bit application targets.

D_GRFA_TYPE

A built-in type that is available when declaring a GRFA variable. It is defined as an a10.

D_HANDLE

The D_HANDLE type is used to identify memory handles in traditional Synergy and Synergy .NET. It’s a definition for a data type, rather than an actual data type. It is an i4.

D_MAXINT

D_MAXINT is the maximum supported int size. D_MAXINT is always i8 on all current application targets.

D_NATINT

D_NATINT is the platform-defined size of the int data type in the operating system C header files. D_NATINT is always i4.

D_NATLNG

D_NATLNG is the platform-defined size of the long data type in the operating system C header files. D_NATLNG is i8 on .NET and all 64-bit application targets except non-.NET Windows. On non-.NET Windows and all 32-bit application targets, it is i4.

D_RFA_TYPE

D_RFA_TYPE is a built-in type that is available when declaring an RFA variable. It is defined as a6.