Basic language elements

This topic includes information about the following basic language elements:

Character set

The basic unit of Synergy DBL is the ASCII character. (Appendix B: ASCII Character Set contains the complete ASCII character set.) ASCII characters are combined into sequences that represent the elements of Synergy DBL. Certain characters, called delimiters, separate adjacent language elements in a statement. Note that identifier names and keywords are case insensitive in DBL.

This documentation refers to the following ASCII character subsets:

Numeric

0, 1, 2, 3, 4, 5, 6, 7, 8, and 9

Alphabetic

Uppercase characters A through Z and lowercase characters a through z

Alphanumeric

Both numeric and alphabetical characters

Alpha

All ASCII characters except the nonprintable characters (for example, carriage return, line feed, and form feed)

Data types

Synergy DBL supports all of the data types listed in Data types.

Statements

Synergy DBL provides six types of statements:

This section is merely intended as an introduction to Synergy DBL statements. You will find more complete information in Synergy DBL Statements.

In this documentation, we refer to the statement name as a “keyword.”

Declarative statements

Declarative statements declare the variables and definitions that the routine can access. Many, but not all, declarative statements appear in the data division or class definition of your program. The declared variables can be local to the routine, global to the routine, or used to exchange data with other routines.

ADDHANDLER

ADDHANDLER registers a method as an event handler for an event.

CLASS‑ENDCLASS

CLASS defines a class within the current namespace or within another class.

COMMON‑ENDCOMMON

COMMON defines a shared data record and its associated fields. A GLOBAL COMMON statement allocates a shared data area. An EXTERNAL COMMON statement references a data area that was allocated by a GLOBAL COMMON statement.

DATA

DATA defines a local stack variable in the procedure division.

DELEGATE‑ENDDELEGATE

DELEGATE‑ENDDELEGATE declares a delegate.

ENDPARAMS

ENDPARAMS indicates the end of a parameter list.

ENUM

ENUM declares an enumeration.

EVENT

EVENT declares an event.

EXTERNAL FUNCTION‑ENDEXTERNAL

EXTERNAL FUNCTION declares a user‑defined or system‑supplied external function.

FUNCTION‑ENDFUNCTION

FUNCTION indicates the beginning of a user‑defined function.

GLOBAL‑ENDGLOBAL

GLOBAL specifies that all RECORD definitions that follow the GLOBAL statement are stored in a global named data area instead of the local data area. ENDGLOBAL designates the end of a global data section.

GROUP‑ENDGROUP

GROUP defines a data structure within another data structure. A group member can be a field or another group. ENDGROUP designates the end of a group.

IMPORT

IMPORT imports the specified namespace from a prototype file or a .dbl source file into the current .dbl source file, enabling you to use members of that namespace without having to type the fully qualified member name.

INTERFACE‑ENDINTERFACE

INTERFACE defines an interface, which is like a contract that a class agrees to abide by.

LAMBDA

LAMBDA provides a way to generate inline methods that have access to variables within the method in which the lambda is declared.

LITERAL‑ENDLITERAL

LITERAL defines a data structure and its associated fields that cannot be modified during program execution.

MAIN‑ENDMAIN

MAIN indicates the beginning of a main routine.

METHOD‑ENDMETHOD

METHOD indicates the beginning of a method.

NAMESPACE‑ENDNAMESPACE

NAMESPACE creates a namespace, which enables you to group related entities together for use in a Synergy application.

PROC‑END

PROC indicates the end of the data division and the beginning of the procedure division. END designates the end of the procedure division.

PROPERTY‑ENDPROPERTY

PROPERTY indicates the beginning of a property, which must contain a get or set accessor method.

RECORD‑ENDRECORD

RECORD defines a data structure and its associated data fields. ENDRECORD designates the end of a record.

REMOVEHANDLER

REMOVEHANDLER unregisters a registered event handler.

STRUCTURE‑ENDSTRUCTURE

STRUCTURE defines how data is laid out, without allocating any data space.

SUBROUTINE‑ENDSUBROUTINE

SUBROUTINE indicates the beginning of an external subroutine.

Data manipulation statements

Data manipulation statements directly change data.

CLEAR

CLEAR initializes one or more variables to either blanks (for alpha variables) or zero representation (for numeric variables).

DECR

DECR decrements a numeric variable by 1.

INCR

INCR increments a numeric variable by 1.

INIT

INIT initializes a named data structure to its declared default values.

LOCASE

LOCASE converts all uppercase characters in an alphabetic variable to their corresponding lowercase characters.

SET

SET initializes a set of variables of the same data type to a single value.

UPCASE

UPCASE converts all lowercase characters in an alphabetic variable to their corresponding uppercase characters.

File manipulation statements

File manipulation statements access records within a file or group of files.

MERGE

MERGE merges the contents of two or more sorted files into a single file. Synergy DBL supports an in‑place merge and an n‑way merge.

SORT

SORT orders a file by specified key fields and places the sorted result in either a new file or the original file.

Control statements

When a routine is being executed, control begins with the statement that follows the PROC statement and flows sequentially to each successive statement. Control statements alter the order of execution by directing control to another statement, transferring control to another routine, ending processing of the current routine, or returning control to a referencing routine. This type of statement is used to create loops and internal functions within a program.

AWAIT

The AWAIT statement waits for an asynchronous task to complete.

BEGIN‑END

The BEGIN and END statements define a compound statement, which is logically considered to be a single statement.

CALL

CALL transfers control to an internal subroutine until a corresponding RETURN statement is executed. Synergy DBL provides both an unconditional form and a computed form, which transfers control based on the result of an expression.

CASE‑ENDCASE

CASE executes one of a set of statements based on the value of a selection expression.

DO FOREVER

DO FOREVER executes a statement repeatedly until a condition occurs to transfer control outside of the statement. (DO FOREVER works just like the REPEAT statement.)

DO‑UNTIL

DO‑UNTIL executes a statement repeatedly until the specified condition becomes true. The DO loop is always executed at least once.

EXIT

EXIT terminates execution of the current BEGIN‑END compound statement. Control is transferred to the END statement of the current compound statement.

EXITLOOP

EXITLOOP terminates execution of the current loop. Control is transferred to the statement that immediately follows the loop.

EXITTRY

EXITTRY exits a TRY statement.

FOR

FOR executes a statement repeatedly under the control of a specified variable. FOR has three forms:

FOREACH

FOREACH iterates sequentially through all elements in a collection.

FRETURN

FRETURN specifies the return value of a user‑defined function and returns control to the calling program.

GOTO

GOTO transfers program control to the specified label. Synergy DBL provides both an unconditional form and a computed form, which transfers control based on the result of an expression.

IF

IF executes a statement based on the result of an expression.

IF‑THEN‑ELSE

The IF‑THEN‑ELSE sequence executes one of two statements based on the result of an expression.

MRETURN

MRETURN returns control from a method to the calling program.

NEXTLOOP

NEXTLOOP terminates the current iteration of a loop and moves to the start of the next iteration. (NEXTLOOP performs like the EXIT statement within the BEGIN‑END block of a loop structure.)

NOP

NOP performs no operation. It is ignored.

OFFERROR

OFFERROR disables any runtime error trapping established by an ONERROR statement.

ONERROR

ONERROR enables program trapping of one or more runtime errors.

RAISEEVENT

RAISEEVENT executes all registered event handlers.

REPEAT

REPEAT executes a statement repeatedly until control is explicitly transferred outside of the statement. (REPEAT works just like the DO FOREVER statement.)

RETURN

RETURN completes the processing of an internal subroutine and returns control to the statement that follows the CALL that invoked the subroutine.

SLEEP

SLEEP suspends execution of a routine for the specified number of seconds.

STOP

STOP terminates execution of the current program. Synergy DBL provides two forms of this statement: an unconditional form, which returns control to the controlling system, and a chaining form, which passes control to another program.

THROW

THROW throws an exception.

TRY‑CATCH‑FINALLY‑ENDTRY

The TRY‑CATCH‑FINALLY‑ENDTRY block handles exceptions.

USING‑ENDUSING

USING and USING‑RANGE execute one statement from a list of statements based on the result of an expression.

WHILE

WHILE executes a statement repeatedly based on the result of an expression. If the initial result is false, the WHILE statement never executes.

XCALL

XCALL transfers execution control to an external subroutine.

XRETURN

XRETURN completes the processing of an external subroutine and returns control to the statement that follows the XCALL statement in the calling routine.

Input/output statements

Input/output statements control the exchange of data between the executing program and the input/output devices attached to the computer system. Such devices include printers, terminals, mass storage devices (like disks and floppies), and any other data transmission devices attached to your computer system.

ACCEPT

ACCEPT receives the next sequential character from an input device. (Note that ACCEPT acts differently on OpenVMS; refer to the OpenVMS Development chapter in the Professional Series Portability Guide for more information.)

CLOSE

CLOSE completes any pending I/O activity and disassociates a Synergy DBL channel from a device or a file.

DELETE

DELETE removes a record from an ISAM file.

DISPLAY

DISPLAY outputs a sequence of one or more characters to a character‑oriented device or file.

FIND

FIND locates the position of a record within a file.

FLUSH

FLUSH flushes all buffers associated with a channel.

FORMS

FORMS outputs special form‑positioning characters to a character‑oriented device or file.

GET

GET reads a fixed‑length record from a specified point in a file. This is a binary operation that does not interpret the ASCII characters that are read.

GETS

GETS reads the next sequential fixed‑length record from a file. This is a binary operation that does not interpret the ASCII characters that are read.

OPEN

OPEN associates an internal Synergy DBL channel with an I/O device or file.

PURGE

PURGE ends I/O activity on a Synergy DBL channel. PURGE is equivalent to CLOSE, except that PURGE deletes a file opened in output (O) mode.

PUT

PUT outputs a fixed‑length record to a specified point in a file. This is a binary output operation, not a record operation, as is the WRITE statement.

PUTS

PUTS outputs a fixed‑length record, updating the next sequential record in the file. This is a binary output operation, not a record operation, as is the WRITE statement.

READ

READ obtains a record from a specified point in a file.

READS

READS reads the next sequential record from a file.

STORE

STORE adds a new record to an ISAM file.

UNLOCK

UNLOCK releases any record locks the current program may have on a specified channel.

WRITE

WRITE updates an existing record in a file.

WRITES

WRITES updates the next sequential record.

Interprogram communication statements

Interprogram communication statements pass and obtain data from interactive processes.

LPQUE

LPQUE queues a file for printing by the system.

RECV

RECV receives a message sent by a previously executed SEND statement (either in the current program or some other Synergy program).

SEND

SEND transmits a message to the current or a different program. The message is saved until a RECV statement retrieves it.

Preprocessor and compiler directives

Preprocessor directives are instructions for the preprocessor and are implemented before any code is compiled. Compiler directive statements instruct the Synergy compiler and are evaluated only when a program is compiled. Directives are not included in the resulting executable program. See Types of directives and syntax for more information.

.ALIGN

.ALIGN aligns the data location counter to a boundary.

.DEFINE

.DEFINE defines a replacement identifier and optionally assigns replacement text that will be substituted for that identifier. The replacement identifier can be used anywhere in the routine. (See .DEFINE for more information about text replacement.)

.IDENT

.IDENT defines a routine identifier string to be included in a routine’s object file.

.IF‑.ELSE‑.ENDC

The .IF‑.ELSE‑.ENDC conditional block specifies that compilation of the statements within the block depends on the truth value of an expression.

.IFDEF‑.ELSE‑.ENDC

The .IFDEF‑.ELSE‑.ENDC conditional block specifies that compilation of the statements within the block depends on the declaration of a variable or replacement identifier.

.IFNDEF‑.ELSE‑.ENDC

The .IFNDEF‑.ELSE‑.ENDC conditional block specifies that compilation of the statements within the block depends on the nondeclaration of a variable or replacement identifier.

.IFT, .IFF, .IFTF

.IFT, .IFF, and .IFTF are used within conditional blocks to provide greater control over conditional processing. .IFT tests whether the original condition of the current conditional block was true. .IFF tests whether the original condition was false. .IFTF allows processing regardless of whether the original condition was true or false.

.INCLUDE

.INCLUDE causes the compiler to read source code from another source file or from the Repository. Included statements are compiled as if they were part of the current routine at the point where the .INCLUDE statement appears.

.LIST and .NOLIST

.LIST and .NOLIST control the listing of source code.

.NODEBUG

.NODEBUG prevents the debugger from stopping at breakpoints, watchpoints, or anything else that causes the program to pause.

.NOPROTO‑.PROTO

.NOPROTO turns off prototype generation for a block of source code in a program, and .PROTO turns it back on.

.PAGE

.PAGE ends the current listing page and begins a new listing page.

.REGION‑.ENDREGION

.REGION‑.ENDREGION specifies a collapsible region of code that you can hide from view.

.START

.START optionally sets or unsets compilation flags that control the information printed in the program listing. See .START for a complete list of compilation flags.

.TITLE

.TITLE changes the title in the listing page header.

.UNDEFINE

.UNDEFINE removes the declaration of a replacement identifier that was established by a previous .DEFINE directive.

Identifiers

Identifiers are used as names for namespaces, classes, methods, subroutines, functions, parameters, records, fields, and properties. Identifiers begin with an alpha character (or an underscore in Synergy .NET), optionally followed by a sequence of alphanumeric characters, underscores (_), and dollar signs ($) that identify a statement, variable, or routine to the compiler. For example, Read, a10, namelast, and TAX$RATE_single are all valid identifiers. Destructor method identifiers prefix a tilde (~) to the name of the class.

Identifiers are not case sensitive. For example, NAME_FIRST is the same as name_first and NAME_first.

An identifier section is one of the sections in a nested identifier which may include namespace, class, or member name. For example, the following identifier has three identifier sections:

mynamespace.myclass.myfield

The maximum length of an identifier section is 30 characters on Windows and UNIX and 31 characters on OpenVMS.

All identifiers within a scope, such as classes and structures in a namespace or member identifiers in a class, must be distinct, independent of kind, except where the names are identical and resolved via overloading, such as two routines with the same name but different parameters. A scope is defined to be the smallest of one of the following groupings that has the identifier declared as one of its members, not including inherited members:

Thus, you cannot have two fields with the same name, or a field and a method with the same name in the same class, but you can have two methods with the same name in the same class if their method signatures are different. A field name and a property in the same class can have the same name as long as the case is different.

You can’t have two classes with the same name or a class and structure with the same name in the same namespace.

Two method signatures are considered to match if their identifier, number of arguments, and argument types match exactly. Two subroutine or function signatures are considered a match if their identifiers match exactly.

Keywords

Keywords (like READ, END, and .DEFINE) have predefined meanings in Synergy DBL and identify statements and compiler directives. They must be spelled exactly as documented.

Replacement identifiers

A replacement identifier defines a text string that is to be substituted for the identifier throughout the program. A replacement identifier is defined by the .DEFINE statement.

Variable names

Variable names are identifiers that refer to data records, groups, and fields. A variable name can have a maximum of 30 characters. Although variable names appear in a program listing exactly as you typed them, the compiler translates the names to uppercase. For example, the compiler recognizes both of the following identifiers as the identifier ABCDE:

aBcdE
abcDe

Statement labels

You can label any statement in the procedure division with a symbolic name. Several of the program control statements can reference this label, enabling you to transfer control to a specific statement during program execution. For example, you might use a label to transfer control to an error‑trapping routine or when using a CALL statement.

The statement label must be the first nonblank item in the statement, followed by a comma and must be unique within the routine. A statement label can have a maximum of 30 characters on Windows and UNIX and 31 characters on OpenVMS.

Here’s an example:

    call lbl02          ;Unlabeled, references label lbl02
      .
      .
      .
lbl02,                  ;Labeled
    incr flg
    return

Routine names

Routine names identify which main routine, external subroutine, or function is being referenced. Like all other identifiers, a routine name can have a maximum of 30 characters on Windows and UNIX and 31 characters on OpenVMS.

To call a global routine from within a class that contains a routine of the same name, include ^global as part of the routine name path. For example,

xcall ^global.sub1()

Data reference operation names

A data reference operation name identifies a data reference operation. See Data reference operations for more information.

Textual literals

A textual literal is either a sequence of characters enclosed between matching delimiters (single or double quotation marks) or a sequence of numeric characters, which may be preceded by a plus or minus sign. A literal represents a specific value that is defined at compile time and cannot be changed during execution.

In Synergy .NET, a literal or literal cast as type object or passed to a parameter of type object has its type changed from a Synergy literal type to the corresponding .NET literal type, and then it is boxed. (For example, “abc” is type string, and 10 is @int.) If you want a Synergy literal type instead, cast the literal as the desired Synergy type (@a or @i).

Alpha literals

An alpha literal is a sequence of characters enclosed in matching single or double quotation marks. An alpha literal can be up to 255 characters long.

Here are some examples of alpha literals:

If an alpha literal contains either a single or double quotation mark and you’re using the same character as the delimiter, you must use two successive characters to represent a single embedded mark. The examples below illustrate embedded delimiters: two successive quotation marks are required to specify one quotation mark within the literal.

If the embedded character is different from the ones delimiting the literal, you don’t need to double the embedded character (as shown in the examples below).

Sometimes it’s more convenient to split an alpha literal into smaller physical parts. For example, you might do this if you’re using the literal to initialize an entire record and you want to append comments to each field. The Synergy compiler concatenates several alpha literals if they are separated only by blanks and tabs. (If sections of the alpha literal are on continuation lines, each line must begin with the continuation character [&].)

For example:

"This is "     "an alpha "     "literal"

and

"This is "
&"an alpha "
&"literal"

are functionally the single alpha literal

"This is an alpha literal"

The blanks and tabs between the separate alpha literals are not part of the concatenated literal. (See Continuation lines for a warning about splitting alpha literals across two or more physical lines.)

Alpha literals are case sensitive.

Decimal literals

A decimal literal is any consecutive sequence of numeric characters, which may be preceded by a plus (+) or minus (–) sign. A decimal literal can consist of a maximum of 28 digits. The compiler strips nonsignificant leading zeros to a minimum of one digit. For example, the literal 00003 is stored as 3. The literal 000 is stored as 0.

Here are some examples of decimal literals:

Implied‑decimal literals

An implied‑decimal literal is a sequence of not more than 28 numeric characters, which may be preceded by a plus or minus sign. A maximum of 28 digits can appear before the decimal point, and a maximum of 28 can occur after it, but the two combined cannot exceed 28 total digits. The decimal point cannot be the first or the last character in an implied‑decimal literal; at least one leading and trailing digit must appear before and after the decimal point.

Here are some examples:

The compiler strips nonsignificant leading and/or trailing zeros prior to processing.

Integer literals

You cannot explicitly write an actual integer literal in a source line in the same way that you can specify alpha, decimal, and implied‑decimal literals. However, if you include a decimal literal in an arithmetic expression with an integer variable, the compiler builds an integer literal into the code.

Tip

You can also use %INTEGER with a numeric literal argument to create an integer literal.

Error literals

An error literal has the format $ERR_mnemonic, where mnemonic is an error identification mnemonic. One error literal is defined for every trappable runtime error. (For example, $ERR_DIVIDE specifies the “Divide by zero” error.)

The entire error literal is treated as a decimal literal, and you can use error literals with ONERROR statements, in I/O error lists, and anywhere else in your program that you can use decimal literals. Here’s an example:

onerror($ERR_IOFAIL, $ERR_DIGIT) proc_err1, 
  &    ($ERR_EOF) proc_err2
read(CHN, data, rec_id) [$ERR_IOFAIL=proc_err1]

The Synergy Errors tab contains a complete list of Synergy DBL error mnemonics, numbers, and messages.

Variables

A variable is an identifier that refers to a data location in your program. Before using a variable in statements in the procedure division, you must first define it in the data division. The data division statement that defines the name and data type of the variable also determines the characteristics of the variable’s data area: size, possible initial values, and position relative to the other variables.

Shared variables (common records, global records, and global literals) can be declared by any routine in a program and can be accessed by any routine in a program. A shared variable name must be unique. Variables that are not shared are local to the routine in which they are declared.

Variable path specifications

A path uniquely references a named record or a field within a data structure (as specified by the RECORD or GROUP statement). Variable path specifications have the following format:

[struct_name.][struct_name….]field_name

Paths have the following characteristics:

record a
    group b
      fld           ,a2
      group c
        nam         ,a20
        city        ,a10
      endgroup
    endgroup

You can reference the field city with the following paths:

city
a.city
b.city
c.city
a.b.city
a.c.city
b.c.city
a.b.c.city

Note that you don’t have to use the whole path name to reference a field.

record inhouse
    accnt           ,d5
    name            ,a30
    address         ,a40
    zip             ,d10
record client
    accnt           ,[100]d5
    group customer  ,[100]a
      name          ,a30
      group bldg    ,a
        group address ,a
          street    ,a4
          zip       ,d10
        endgroup
      endgroup
      group contact ,a
        name        ,a30
        group address ,a
          street    ,a40
          zip       ,d10
        endgroup
      endgroup
    endgroup

the following paths are valid:

contact.name
contact.address.street
customer[5].bldg.address.street
client.accnt
inhouse.accnt
inhouse.name

while the following paths are invalid because they are not unique:

name
customer[1].name
address.street
accnt

If you specify one of these paths, the compiler generates a “Path specification is ambiguous” error (AMBIGUOUS).

group customer      ,a
    name            ,a30
    group address   ,a
      street        ,a40
      zip           ,d10
    endgroup
    group contact   ,a
      name          ,a30
      group address ,a
        street      ,a40
        zip         ,d10
      endgroup
    endgroup
endgroup

Because partial path names can access fields, the second address group’s street field can be referenced in any of the following ways:

customer.contact.address.street 
customer.contact.street 
contact.street 

The path specification

customer.address.street 

generates a “Path specification is ambiguous” compiler error, because it could reference either the first address group or the second. The only way to reference the data in the first address group is by ranging. See Ranged references for information.

group var1          ,a
    group and       ,d4
      var2          ,d4
    endgroup
endgroup

and you reference it with the following path:

var1.and.var2

the Synergy compiler interprets this reference as a path, not a Boolean expression. (To use it as a Boolean expression, add a space before and after the .AND. operator.)

Object paths

You can refer to the current instance of a class within the class using the this keyword. For example,

this.mymethod()

Path specifications that contain classes are resolved in the following order:

Real arrays

When referencing a real array, you must specify each declared dimension. For example, if you declare a variable as follows:

record
    brk         ,[3,4]d1

the references brk[1,2] and brk[2,2] are valid because each dimension is referenced.

In contrast, brk[1] is not valid, and the compiler generates an “Incorrect number of dimensions” error (INVNUMDIM), because it specifies only one of the two dimensions.

The reference brk[ ], however, is valid and refers to the entire scope, or contents, of the dimensioned array as a single element. The maximum size of a scope reference is 65,535. If the array is larger than 65,535 bytes, the scope size is modulo 65,535.

If your dimension specification is larger than the declared size of its corresponding array dimension, you can reference outside the defined area up to the end of the data area, except for class data fields and when ‑qstrict or ‑qcheck is specified. We recommend using ‑qcheck in all development environments and ‑qstrict for all production builds.

Here’s an example that references a real array:

record demo
    alpha       ,[3,2]d2 ,      12 ,34,
  &                             56 ,78,
  &                             98 ,76
    beta        ,[2,4]a3,       "JOE" ,"JIM" ,"TED" ,"SAM",
  &                             "LOU" ,"NED" ,"BOB" ,"DAN"

Data is referenced as follows:

Variable reference

Data obtained

alpha[1,2]

34

alpha[3,1]

98

alpha[3]

INVNUMDIM error

alpha[3,3]

JO

alpha[4,1]

JO

alpha[ ]

123456789876

beta[ ]

JOEJIMTEDSAMLOUNEDBOBDAN

beta[1,3]

TED

beta[2,4]

DAN

Variable references

You can specify variables in a simple, subscripted, or ranged form. Each form is described below. (This information also applies to all Synergex array classes: Synergex.SynergyDE.Collections.ArrayList, System.Collections.ArrayList, and System.Array.)

Simple references

A simple reference consists of the name of a data area, without any subscripting or range specifications. If it’s not defined as an array, the reference refers to the entire data area. Otherwise, the simple reference refers to the first element of the array or the element of the array at the specific index specified inside square brackets ([]) next to the variable name (i.e., variable_name[indexer]). In Synergy .NET, you can also use the square bracket format to access the indexer of any class that has an integer indexer method.

Here are some examples of simple references:

Subscripted references

A subscripted reference refers to an individual element within a list of like elements. The variable name is followed by the subscript value, which is enclosed in parentheses. The subscript value can be any numeric expression greater than zero and defines which element in the list is being accessed. For example, a subscript value of 1 represents the first element in the list.

Any variable reference can be subscripted, provided the data area is accessible to the routine. If the data area is inaccessible, or if the subscript value is less than one, an “Invalid subscript specified” error ($ERR_SUBSCR) is generated. Note that you cannot subscript beyond the defined size of class data fields and records or when the ‑qcheck compiler option is specified.

To understand how subscripted variables work, consider the following example.

Assume the following data division statements:

record demo
    alpha               ,3d4,           3, 9876, 4321
    beta                ,a6,            "ABCDEF"
    gamma               ,d3,            545
    delta               ,4a2,           "LM", "NP", "RS" ,"TV"
    episilon            ,3d3.2,         6.75, 1.23, 8.00
    group theta         ,[3]a
      one                ,d3,           123
      two                ,a3,           "abc"
    endgroup

Data is allocated as follows (shaded boxes are not part of the data space):

Variable

Data area (characters)

alpha(1)

0

0

0

3

 

 

alpha(2)

9

8

7

6

 

 

alpha(3)

4

3

2

1

 

 

beta

A

B

C

D

E

F

gamma

5

4

5

 

 

 

delta(1)

L

M

 

 

 

 

delta(2)

N

P

 

 

 

 

delta(3)

R

S

 

 

 

 

delta(4)

T

V

 

 

 

 

epsilon(1)

6

7

5

 

 

 

epsilon(2)

1

2

3

 

 

 

epsilon(3)

8

0

0

 

 

 

theta[1].one

1

2

3

 

 

 

theta[1].two

a

b

c

 

 

 

theta[2].one

1

2

3

 

 

 

theta[2].two

a

b

c

 

 

 

theta[3].one

1

2

3

 

 

 

theta[3].two

a

b

c

 

 

 

Here are some sample variable references:

Variable reference

Data obtained

Explanation

demo

000398764321ABCDEF545LMNPRSTV675123800123abc123abc123abc

Refers to the entire data area.

alpha

0003

Refers to the first element of the array.

alpha(1)

0003

Refers to the first element of the array.

alpha(3)

4321

Refers to the third element of the array.

alpha(4)

ABCD

Refers to the fourth group of four characters after the beginning of alpha’s data area (because a single alpha data item is four characters).

alpha(5)

EF54

Refers to the fifth group of four characters after the beginning of alpha’s data area.

beta(2)

545LMN

Refers to the second group of six characters after the beginning beta’s data area (because a single beta data item is six characters).

gamma
(alpha(1))

PRS

Refers to the third group of three characters after the beginning of gamma’s data area (because the variable alpha(1) has a value of 3 and a single gamma data item is three characters).

delta(4)

TV

Refers to the fourth element of the array.

delta(‑3)

$ERR_SUBSCR

The subscript value is less than one.

epsilon(3)

8.00

Refers to the third element of the array. (The decimal point is shown here for clarity; it is not stored in the data area.)

epsilon(4)

123

Refers to the fourth group of three characters after the beginning of epsilon’s data area.

theta[1].two(2)

123

Refers to the second set of three characters after the first array element in the group.

theta[3].two(2)

$ERR_SUBSCR

Refers to data outside of the data area accessible to the program.

Alpha(4) and alpha(5) are both valid references because they don’t extend beyond the total data space allocated by the data division statements. Theta[3].two(2), on the other hand, attempts to refer past the end of the data area, which is not possible.

Notice that beta and gamma can be subscripted even though they are simple variable references.

Ranged references

A ranged reference is a variable reference followed by a range specification, either in absolute or relative form, that is enclosed in parentheses. In either case, the specification indicates starting and ending character positions relative to the beginning of the variable’s data space. The ranged variable’s value is the sequence of characters between the starting and ending positions, inclusive. If the range in a variable reference goes beyond the first variable, Synergy DBL continues to the next variable to obtain data.

You can range real arrays. Here’s an example:

brk[1,2](1,23)

You cannot range subscripted arrays. The following generates an error:

array(4)(1,23)

If the variable being ranged is implied‑decimal, it is interpreted as decimal. Note that you cannot range beyond the defined size of class data fields and records or when the ‑qcheck compiler option is specified.

Absolute ranging

The absolute form of a range specification indicates the starting and ending positions of a character sequence using two numeric expressions separated by a comma.

Absolute ranging has the following format:

variable(start_pos,end_pos)

Here’s an example:

record abs
    alpha               ,d8,            10203405
    beta                ,a13,           "ABCDEFGHIJKLM"
    gamma               ,[3,2]a3,       "ABC", "DEF",
  &                                     "GHI", "JKL",
  &                                     "MNO", "PQR"
    group theta         ,[3]a
      one               ,d3,            123
      two               ,a3,            "abc"
    endgroup

Variable reference

Data obtained

alpha(2,4)

020

alpha(8,13)

5ABCDE

beta(3,6)

CDEF

beta(alpha(2,3),alpha(7,8))

BCDE

beta(alpha(2,3)+2,5)

DE

beta(13,14)

MA

gamma[1,2](2,3)

EF

gamma[2,2](3,6)

LMNO

alpha(6,3)

$ERR_SUBSCR

theta[1].two(2,8)

bc123ab

Note that the ability to access characters that extend past (or in front of) the specified field has been deprecated. For backward compatibility, the Synergy Runtime will continue to support this type of access. However, we recommend that you compile and run with ‑qcheck and make the appropriate changes to avoid future memory access violations.

Relative ranging

The relative form of a range specification indicates the starting or ending character position and length of a character sequence range using two numeric expressions separated by a colon. The value that is referenced depends on the sign of the length. For positive lengths, the specified position is the starting point, and the value is the character sequence of the specified length that begins at that position. For negative lengths, the position is the ending point, and the value is the character sequence that begins the specified number of characters before that position.

Relative ranging has the following format:

variable(position:length)

Here’s an example of a data division:

record abs
    alpha       ,d8,            10203405
    beta        ,a13,           "ABCDEFGHIJKLM"
    gamma       ,[3,2]a3,       "ABC", "DEF",
  &                             "GHI", "JKL",
  &                             "MNO", "PQR"
    group theta         ,[3]a
      one       ,d3,    123
      two       ,a3,    "abc"
    endgroup 

Variable reference

Data obtained

alpha(3:1)

2

alpha(3:2)

20

alpha(6:‑2)

34

beta(13:2)

MA

gamma[1,2](1:2)

DE

gamma[1,1](1:12)

ABCDEFGHIJKL

gamma[3,2](1:12)

PQR123abc123

beta(2:‑15)

$ERR_SUBSCR

theta[2].one(3:10)

3abc123abc

Note that the ability to access characters that extend past (or in front of) the specified field has been deprecated. For backward compatibility, the Synergy Runtime will continue to support this type of access. However, we recommend that you compile and run with ‑qcheck and make the appropriate changes to avoid future memory access violations.