Data types

The Data Types table 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 Framework’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 include Char, DateTime, Guid, IntPtr, and UIntPtr. IntPtr and UIntPtr are included in the table below because of special alignment with Synergy .NET (see IntPtr and UIntPtr). See also Understanding .NET data types. For complete details on .NET data types, see the .NET Framework documentation in Microsoft Developer Network (MSDN).

Data Types

Type

Valid in

Description

Default value

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

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

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

a

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

0.0

float

a

Shorthand for 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

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

0

IntPtr

System.IntPtr

0

long

Shorthand for 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

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

0

short

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

0

string

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

^NULLb

ushort

Shorthand for System.UInt16

0

uint

Shorthand for System.UInt32

0

UIntPtr

System.UIntPtr

0

ulong

Shorthand for System.UInt64

0

^VAL

System.IntPtr in .NET; native int in traditional

NA

VOID

Method does not return a value

NA

@*

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

^NULLb

@class

A specific class type

^NULLb

@delegate

A specific delegate

^NULLb

@interface

A specific interface

^NULLb

@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

T (or other unused letter)

Generic type parameter

 

[#,#]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, [#,#,#,#]c)

^NULLb

a. Not recommended for use in traditional Synergy.

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

c. Portable class libraries and Universal Windows Platform (UWP) apps don’t support more than three dimensions in arrays.

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 Framework 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 Framework 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

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

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.

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 Framework System.Boolean structure.

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 Framework 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.

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.

Double

With Synergy .NET, double is a value type and maps to the .NET Framework 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 Framework 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 Framework 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. See %CNV_IP and %CNV_PI for more information.)

IntPtr and UIntPtr

The .NET Framework 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 Framework 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 (see System.String). With Synergy .NET, it maps to the .NET Framework 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.

Uint

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

Ulong

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

Ushort

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

^VAL

^VAL is a qualifier to subroutine parameters and return values. It 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 Framework System.IntPtr structure.

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 (see System.Object). With Synergy .NET, it maps to the .NET Framework 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=%syn_freechn, i, "tt:")
    writes(tt, person)
    close(tt)
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.

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)

[#,#]type

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

In traditional Synergy, [#,#]type maps to the Synergy System.Array class (see System.Array), 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 Framework 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 (see System.Array), 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 Framework 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 (see System.Array) 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 Framework 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 (see System.Array) and [#,#] can have 1 to 9 dimensions, inclusive ([#], [#,#], and so on, up to [#,#,#,#,#,#,#,#,#]).

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

The default value is ^NULL.

Data type identifiers

The following identifiers are definitions for data types, rather than actual data types.

D_ADDR

The D_ADDR type is used for routine addresses. It can be used for data fields, parameters, return types, and method properties in traditional Synergy and Synergy .NET. The default for D_ADDR is 0.

In traditional Synergy, D_ADDR maps to i4 for 32‑bit systems or i8 for 64‑bit systems.

In Synergy .NET, D_ADDR is a value type and maps to the .NET Framework System.IntPtr structure. See IntPtr and UIntPtr for more information about data alignment.

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_HANDLE

The D_HANDLE type is used to identify memory handles in traditional Synergy and Synergy .NET.