The Assignment Statement

The Assignment Statement 1

Format 1

Statement Option – RTRIM.. 1

Expressions. 2

Numeric expressions. 2

String Expressions. 2

Assignments with += etc. 4

Functions and Special Values. 4

Generic Assignments. 4

Redefinitions and Generic Assignment 6

Tables and Subscripted References. 6

 

Assignment statements compute and copy data from field to field within your program. They may be simple assignments: -

Record1.Customer-Name = 'Robert';

They may involve calculations

LineItem.Extended-Value = Part.UnitCost * LineItem.Quantity;

Generic assignments may assign many fields at once

OutputRecord.* = InputRecord.* ;

Format 

Assignment statements have this general format: -

target [, target]... = expression [Option];

 

The assignment symbol is normally “=”, but may instead be “+=”, “-=”, “*=”, or “/=”.  See notes below.

 

They follow these general rules

1.      Referenced fields and records must have already been defined within the program.

2.      Multiple targets are only valid for simple assignments.

a.      You may not specify more than one generic target, i.e.

            Record1.*, Record2,* = Record3.*

is not valid

b.      You may not specify multiple targets if you are using a string expression.  Thus

String1, String2 = Field1 && Field2

is not valid.

c.      All targets must have the same general type. For example, you cannot mix numeric, string, and date fields.

3.      The target(s) must be compatible with the expression. Thus if the expression is a string, the target cannot be a numeric field

4.      If the target is a generic reference, then the expression must be a single generic reference.  For example

OutputRecord.* = InputRecord.*

See Generic Assignments below for more information.

Statement Options – RTRIM, EXCEPT

RTRIM.  This is only valid for String expressions, or for assignments of single CHAR fields to VARCHAR - see below.

EXCEPT.  This is only valid for Generic Assignments – see below.

 

Possible development.  Future options may include

LTRIM, RTRIM, ROUND, ROUNDUP, ROUNDDOWN

Or perhaps the syntax of built-in functions will be enhanced to allow them to be nested, avoiding the need for these as statement option.

Expressions

If the target is a field (or several fields), then the expression can be

·         a constant

Record1.Customer-Name = 'Robert';

Record1.MinimumPayment = 100.00;

·         a reference to another field

Record1.Customer-Name = InScreen.Customer-Name

·         an expression in which a value is calculated

Record1.MinimumPayment = Parameter.PaymentClass * 100;

Record1.Customer-Name = Input.FamilyName && ', ' && Input.GivenName;

There are several types of expressions.  The expression type is determined from the target variable: if the target is numeric then the expression must be numeric, and so on.

Numeric expressions. 

These have a numeric value. An example is

Parameter.PaymentClass * 100

Numeric expressions may include

·         Numbers (numeric constants)

·         Numeric fields – fields with type DECIMAL, MONEY, BIGINT, INTEGER, SMALLINT, FLOAT, LONG

·         Arithmetic operators + (Plus), - (Minus), * (Multiply), / (Divide), and ** (to the power of)

·         Parentheses, i.e. brackets, to group operands and operators

Arithmetic expressions are evaluated according to the normal rules of Mathematics, meaning that the expression is evaluated left to right except that anything within (…) is evaluated first, and Multiplication and Division is done before Addition and subtraction.

 

Here are some examples. With B = 2, C = 3, D = 4, and E = 5,

A = B + C * D

A is set to 14: C * D is evaluated first giving 12, this is added to 2. 

If we wanted B and C to be added first we’d put them in brackets: this sets A to 20: -

A = (B + C) * D

It doesn’t hurt to add brackets when they’re unnecessary. For example, A = B + (C * D) is equivalent to A = B + C * D, but it may be clearer to a human reader. 

 

While you can make arithmetic expressions as complicated as you like, several simpler expressions may be easier to understand, both for you and other human readers, and for Jazz software. 

String Expressions

These have a string value, and are normally simple assignments of a string constant or a CHAR or VARCHAR field: -

Record1.Customer-Name = 'John'

Record1.Customer-Name = InScreen.Customer-Name

Note however that EVERY field has a string value, not just CHAR and VARCHAR fields, so that you can assign a numeric (DECIMAL, MONEY, etc), date (DATE, TIME, DATETIME), or other field to a CHAR or VARCHAR target field. In a string expression the field’s string-format value will be used.   Numeric values will be printed as a string of numbers without any particular format: you should use PIC format if you want to control the format for a string assignment.

 

If the assignment target is longer than the string value, then the value is extended with blanks. For example, if Record1.Customer-Name had been defined as CHAR(30), then

Record1.Customer-Name = 'John'

would assign 'Johnbbbbbbbbbbbbbbbbbbbbbbbbbbb' to it. Here “b” represents a blank.

 

If the expression value is longer than the target string, the value is truncated.

 

The only operator permitted in a string expression is “&&”, meaning “Concatenate”. This joins the two (or more) string elements together.  Each element can be a CHAR or VARCHAR field, or a string constant: -

DEFINE Record1 DATA(

        FamilyName VARCHAR(30),

        GivenName VARCHAR(30));

DEFINE Record2 DATA(

        NAME VARCHAR(62));

Record1.FamilyName = 'Barnes';

Record1.GivenName = 'Robert';

Record2.Name = Record1.FamilyName && ', ' && Record1.GivenName;

This assigns 'Barnes, Robert' to Record2.Name.  Concatenation expressions are interpreted left-to-right, and should not contain brackets or other punctuation.

 

Note the constant, ', ', separating the two fields. Without this we’d get a result like 'BarnesRobert'.

 

Note also the use of VARCHAR: if FamilyName and GivenName had been defined CHAR then the value would have included 24 blanks after “Barnes”. Compare the results above with

DEFINE Record1 DATA(

        FamilyName CHAR(30),

        GivenName CHAR(30));

DEFINE Record2 DATA(

        NAME VARCHAR(62));

Record1.FamilyName = 'Barnes';

Record1.GivenName = 'Robert';

Record2.Name = Record1.FamilyName && ', ' && Record1.GivenName;

Here Record2.Name is set to 'Barnes                        , Robert                         '.

RTRIM

If the statement includes the RTRIM option then the excess blanks to the right of CHAR field values are trimmed out: -

Record2.Name = Record1.FamilyName && ', ' && Record1.GivenName RTRIM;

This gives the same result as when VARCHAR fields were used, except that if the CHAR field is all spaces then RTRIM leaves one space. 

 

RTRIM affects only values of CHAR and fields from 3270 screens, it does not affect constants or fields with any other type.  Thus you could write

Record2.Name = Record1.FamilyName && ',       ' && Record1.GivenName RTRIM;

and have several blanks inserted between FamilyName and GivenName.  Similarly, RTRIM is ignored for VARCHAR fields and fields from 3270 screens, as these have built-in length fields.   Thus with

DEFINE Record1 DATA(

        FamilyName VARCHAR(30),

        GivenName VARCHAR(30));

DEFINE Record2 DATA(

        NAME VARCHAR(62));

the assignment

Record1.FamilyName = 'Barnes';

assigns 'Barnes' to the the data area of Record1.FamilyName, and 6 to its length.  The assignment

Record1.GivenName = 'Robert    ';

assigns 'Robertbbbb'  (b represents a blank) and 10 to its length. 

 Record2.Name = Record1.GivenName && Record1.FamilyName RTRIM;

Because Record1.GivenName and Record1.FamilyName are VARCHAR fields RTRIM is ignored and Record2.Name is set to 'RobertbbbbBarnes' using the VARCHAR fields’ lengths.  You’ll get exactly the same results if RTRIM is omitted.

Assignments with += etc

The target variable can appear in the source expression. For example, incrementing a loop variable is simply achieved with

LoopCount = LoopCount + 1

The assignment symbols +=, -=, *=, and /= are convenient shorthand for this kind of assignment. Thus

LoopCount += 1

is equivalent to the earlier assignment. +=, -=, *=, /= are valid for numeric assignments

 

Planned:  &= should be valid for string assignment and be equivalent to

Name = Name && expression

Functions and Special Values

You can refer to any COBOL special values, for example Spaces and Zero, and COBOL Intrinsic Functions: -

w.name1 = spaces;

You can refer to Jazz built-in Functions, which will be named starting with $.   There are also some Jazz special names that you can refer to, such as JZ.JZReturnCode, that have meaning in particular contexts.

 

For a list of these functions and names, refer to JazzLRMBuiltInFunctions

Generic Assignments

A generic assignment assigns all the fields of one record or group to the like-named fields in another (except for FILLER).  For example, suppose that we had defined INPUT1 and RECORD1 like this:-

DEFINE INPUT1 DATA(

        NAME CHAR(30),

        ADDRESS CHAR(30),

        CITY CHAR(15),

        BALANCE MONEY(7,2));

DEFINE RECORD1 DATA(

        CODE CHAR(1),

        NAME CHAR(30),

        BALANCE MONEY(7,2)); 

 

Now if we write

RECORD1.* = INPUT1.*;

this is equivalent to the simple assignment statements:

RECORD1.NAME = INPUT1.NAME;

RECORD1.BALANCE = INPUT1.BALANCE;

Fields CITY, ADDRESS, and CODE are ignored.

 

The source of a generic assignment must be another generic expression or the Jazz function $Init (which Jazz will qualify to JAZZ.$Init):-

T.* = JAZZ.$Init;

This is identical in effect to the assignment statement

T = JAZZ.$Init;

 

It is NOT valid to assign a single field or constant to a generic expression: -

T.* = SPACES;

#543 S Source SPACES is invalid for a generic assignment. Reason: Constant

 

To be included in a generic assignment the fields must have the same names, including the names of containing groups. For example, record In1A is defined like this: -

DEFINE IN1A TYPE(FB) DATA(

    Region PIC '99',

    Filler CHAR(3),

    District PIC '99',

    Filler CHAR(4),

    Name CHAR(15),       

    Filler CHAR(2),    

    SalesThisMonth PIC '99999.99',

    Filler CHAR(3),   

    SalesYTD PIC '99999.99',   

    Filler CHAR(4),     

    Cardholder CHAR(1),   

    Filler CHAR(4),      

    DateCommenced CHAR(10),

    Filler CHAR(14))

    DSNAME '@Project.@Group.SRCLIB(DTDTA1)';

and record IN1 is defined like this: -

DEFINE IN1 TYPE(VB) DATA(

    JZ-Key GROUP KEY,

        Region DECIMAL(3),

        District DECIMAL(3),

        END GROUP,

    Name CHAR(15),

    SalesThisMonth DECIMAL(7,2),

    SalesYTD DECIMAL(7,2),

    Cardholder CHAR(1),

    DateCommenced CHAR(10))

    DSNAME('IBMUser.Files.IN1');

 

Because Region and District are within group JZ-Key in IN1 they are not included in the generic assignment, they have to be individually assigned in this program.  The Jazz message is helpful in alerting us to this potential issue: -

COPY in1a;

COPY IN1;

PROCESS in1A;

    PRINT (IN1A.*); 

    In1.* = IN1a.*;

    #207 I Name,SalesThisMonth,SalesYTD,Cardholder,DateCommenced included in generic assignment

    In1.Region = in1a.region;

    in1.district = in1a.district;

    WRITE in1;

END PROCESS in1A;

 

EXCEPT

Use EXCEPT to exclude fields from a generic assignment.  For example

IN1.* = In1a.* EXCEPT(IN1.Region, IN1A.RDKey.District);

omits the fields Region and District from the generic assignment.  Note that you can name fields on either side of the assignment.  However if you name an unrelated field then there is no message and the irrelevant item is ignored.  Thus in the program above if you add this option to the original statement

IN1.* = In1a.* except region, district;

and then click [Check] it becomes

IN1.* = In1a.* EXCEPT(Types.Region, IN1A.RDKey.District);

#207 I RDKey.Region,Name,SalesThisMonth,SalesYTD,DateCommenced, included in generic assignment

As you see there is no message about the irrelevance of Types.Region, and RDKey.Region is included in the assignment.

Redefinitions and Generic Assignment 

When redefined fields occur within a generic reference, as in: -

DEFINE RECORD1 DATA(

    ACCOUNT NUMERIC(8),

     BANK NUMERIC(2) REDEFINES RECORD1.ACCOUNT,

     …);

DEFINE RECORD2 DATA(

    ACCOUNT NUMERIC(8),

     BANK NUMERIC(2) REDEFINES RECORD1.ACCOUNT,

     …);

then both ACCOUNT and BANK will be assigned by

RECORD1.* = RECORD2.*;

even though assignment of BANK is superfluous.

 

Fields are assigned in order of their definition position within the target record.

Tables and Subscripted References

If a field is defined as a table, i.e. with one or more dimensions, then you must refer to it with the correct number of subscripts. For example,

DEFINE D DATA(

        A SMALLINT,

        B (3) SMALLINT,

        C (3) SMALLINT,

        D(3) INTEGER,

        E (2, 3, 4) SMALLINT,

        Gr1 (2) GROUP,

                F (3, 4) SMALLINT,

                END GROUP);

Just as we can set the value of A to 1234: -

            D.A = 1234;

we can refer to elements of a table by specifying a subscript: -

            D.B(2) = 5678;

            D.A =  D.B(2);

We must give the correct number of subscripts, and so we are not permitted to write

            D.B = D.C;

to assign the whole array. Instead we use “(*)” to indicate “All of this dimension”, writing

            D.B(*) = D.C(*);  which Jazz will change to D.B(*) = D.C($IX1);

This is only valid if the arrays have exactly the same dimension, as they do here, and imply a loop like

FOR D.B(IX);

    D.B(IX) = D.C(IX);

END FOR;      

Because there is an implied loop, a statement like D.B(*) = D.C($IX1); is valid as long as an assignment from an element of D.C to an element of D.B is valid. Thus we could write

            D.D(*) = D.B($IX1);

and each SMALLINT value becomes an INTEGER value.  Similarly, we can write

            D.B(*) = D.E(1, $IX1, 1);

(here we must write $IX1 explicitly because it is not in the same position as the * in the target).

 

We can also write statements like this when the dimension of the source and target are different. Thus

DEFINE D DATA(

        B (3) SMALLINT,,

        E (2, 5, 4) SMALLINT,

           

D.B(*) = D.E(1, $IX1, 1);

the first three elements of E are assigned, ignoring elements 4 and 5. However if the dimension of E is less than the corresponding dimension of B, this is not valid.

Date Expressions

To be written