Set-value blocks

A set-value block is an area of code in which you can set property, field, or variable values. For background on properties, see "Overview of EGL properties."

You can include a set-value block when you perform any of the following actions:

In the last two cases, you can assign values only to fields.

Programmers typically place a single set-value block at the beginning of the part contents. You can, however, have separate set-value blocks for each property or value you assign, and you can scatter them throughout the part, as long as you observe scoping rules (see Scope). For example, the set-value block in the following code turns on the handleHardIOErrors program property:
program hello
	myString STRING = "Hello, Cleveland";
	{handleHardIOErrors = YES}   // this works
	...
end
If you move the semicolon, the program gives you a validation error:
program hello
	myString STRING = "Hello, Cleveland"
	{handleHardIOErrors = YES};   // this is part of myString declaration
	...
end

The problem is that handleHardIOErrors is now in the scope of the string "Hello, Cleveland." A string has no fields to set, let alone a field named "handleHardIOErrors," so EGL cannot resolve the expression.

A set-value block has the following additional effects: The following statement creates a nullable variable whose initial value is non-null (in this case, 0):
myInt INT?{};
The following example results in a null value exception:
myList Dictionary;   // myList = null
myList.x = 23;       // illegal reference
However, the following code initializes a new dictionary variable before attempting the assignment:
myList2 Dictionary;   // myList2 = null
myList2{ x = 23 };    // myList2 now has one key, x, whose value is 23
You can use set-value blocks to initialize values in structured record variables. Consider the following example:
package com.companyb.customer;

Record StructuredRecordA
10 fullCheckNum NUM(25);
  15 bankNum NUM(9);
  15 acctNum NUM(10);
  15 checkNum NUM(6);
end

program calculate type BasicProgram

  function main()
    myRec1 StructuredRecordA 
      {fullCheckNum = 9531008501602141091001484};
    writeStdOut(myRec1.bankNum);  // 953100850
    writeStdErr(myRec1.checkNum); // 1484
  end
end
Setting the top level field also sets the substructure fields. You can also set the substructure fields individually, as in the following example:
  myRec2 StructuredRecordA {checkNum = 1485};
  writeStdOut(myRec2.fullCheckNum); // 1485

If you make multiple assignments to the same field or property in a set-value block, the last assignment takes effect. That rule also applies to fields of complex properties, which are described in "Set-value blocks in complex properties" in this topic.

Set-value blocks for elementary situations

The following rules apply in the most elementary cases:
  • Each set-value block begins with a left brace ({), includes zero or more entries separated by commas, and ends with a right brace (})
  • Each entry is in one of two formats:
    • A name/value pair such as inputRequired = yes.
    • A series of positional values (successive values assigned to successive elements of an array).

In any case, the set-value block is in the scope of the part, variable, or field being modified. The variations in syntax are best illustrated by example.

The first example shows a primitive type variable that has two properties (inputRequired and align) :
   // the scope is myVariable
   myVariable INT
   {
      inputRequired = yes,
      align = left
   };
The next example shows a DataItem part definition:
  // scope is optionEntry
  DataItem optionEntry INT
  {
      inputRequired = yes,
      align = left
  };
  end
The next example shows a variable declaration that uses the previous part as a type, then overrides one of the properties:
  // scope is menu1Option
  menu1Option optionEntry
  {
      inputRequired = no
   };
These first two assignment statements do not use a set-value block:
  myRecord02.myContent01 = "abc";
  myRecord02.myContent02 = "xyz";
This abbreviated assignment statement is equivalent to the previous two:
  myRecord02
  {
      myContent01="abc",
      myContent02="xyz"
   };

The abbreviated assignment statement is not available for fields in a structured record, and you cannot use it to set properties.

Set-value blocks for a field in a record

When you are assigning values for a field within a record variable, narrow the scope to the specific field, as follows.

Consider the following record definitions:
  record myBasicRecord03 type basicRecord
    myInt04 INT;
  end

  record myBasicRecord02 type basicRecord
    myInt03 INT;
    myRec03 myBasicRecord03;
  end

  record myBasicRecord type basicRecord  
    myInt01 INT;
    myInt02 INT;
    myRec02 myBasicRecord02;
 end
You can assign a property value for any field using the following steps:
  • Create a set-value block for the record
  • Embed a series of field names to narrow the scope
  • Create a field-specific set-value block

The syntax for assigning a property value can take any of the forms shown in the following examples, which apply to the field myInt04:

  // dotted syntax
  myRecB myBasicRecord 
  { 
    myRec02.myRec03.myInt04{ align = left } 
  };

  // bracket syntax
  // You cannot use this syntax to affect
  // fields in fixed structures
  myRecC myBasicRecord 
  { 
    myRec02["myRec03"]["myInt04"]{ align = left } 
  };

  // brace syntax 
  myRecA myBasicRecord 
  { 
    myRec02 {myRec03 { myInt04 { align = left }}}
  };
Even in complex cases, use a comma to separate entries in a set-value block. You must consider the level at which a given block is nested:
  // dotted syntax
  myRecB myBasicRecord 
  { 
    myInt01 = 4,
    myInt02 = 5,
    myRec02.myRec03.myInt04{ align = left }, 
    myRec02.myInt03 = 6
  };

  // bracket syntax
  myRecC myBasicRecord 
  { 
    myInt01 = 4,
    myInt02 = 5,
    myRec02["myRec03"]["myInt04"]{ align = left }, 
    myRec02["myInt03"] = 6
  };

  // brace syntax; 
  // but this usage is much harder to maintain
  myRecA myBasicRecord 
  { 
    myInt01 = 4,
    myInt02 = 5,
    myRec02 
      {
        myRec03 
          { myInt04 
            { action = label5 }},
        myInt03 = 6
      }
  };

Use of "this" in set-value blocks

In a variable declaration or assignment statement, you can have a container (such as an SQL record) that includes a field (such as keyItems) that has the same name as a record property. To refer to your field rather than to the property, use the keyword this, which establishes the scope as being the declaration in which the set-value block resides.

Consider the following record definition:
  Record ExampleRecord type SQLRecord
    { tableNames = [["myTable"]],
      keyItems = [myKey] }
    myKey CHAR(10);
    myOtherKey CHAR(10);
    keyItems CHAR(60);
  end 
The following record declaration first sets a value for the property keyItems, then sets a value for the field of the same name:
  myRecord ExampleRecord 
  { 
     keyItems = [myOtherKey],
     this.keyItems = "abc"
  };

For an example in an array declaration, see "Additional set-value block examples."

Set-value blocks in complex properties

EGL includes a number of complex properties whose names conventionally begin with an @ sign. Complex properties have properties (called property fields) of their own, with values assigned in a subsidiary set-value block. The following example shows the @xml complex property, used with service variable declarations:
  myService ExampleServicePart 
  { @xml
    {name="myService",
     namespace="http://www.customerpackage.companyb.commy.useful.service"}
  };

Additional set-value block examples

The examples use the following record definitions:
  Record Point
    x INT;
    y INT;
  end

  Record Rectangle
    topLeft Point;
    bottomRight Point;
  end
The following code is valid:
  Function test()
    screen Rectangle
    {
      topLeft{x=1, y=1},
      bottomRight{x=80, y=24}
    };
  
    // change x, y in code, using a statement 
    // that is equivalent to the following code:
    //   screen.topLeft.x = 1;
    //   screen.topLeft.y = 2;
    screen.topLeft{x=1, y=2};
  end
Next, initialize a dynamic array of Point elements in the same function:
  pts Point[2]
  {
    this[1]{x=1, y=2},
    this[2]{x=2, y=3}
  };
Set the value of each element that is now in the array, then set the first element to a different value:
  pts{ x=1, y=1 };
  pts[1]{x=10, y=20};

The keyword this has a different meaning outside of a set-value block (see The "this" keyword). In any case, the use of pts[1] here is not ambiguous, so no such distinction is necessary.

Next, consider another dynamic array of type Point:
  points Point[];
The following two assignments throw NullValueExceptions because the array is not initialized. Arrays have null initial values because they are reference types (see Reference variables):
  points{x=1, y=1};
  points[1]{x=10, y=20};
After you initialize the array, you can add elements to the array, then use a single statement to set values in all elements:
  points{};
  points.resize(2);
  points{x=1, y=1};

Feedback