Code Blocks

Code Blocks in the Expression Engine behave as functions (i.e. can define a return value). These blocks consist of code lines and can use internal variables. Access to internal variables is fast and a single variable can contain any data type that a standard expression value can hold (simple types, arrays, etc.). Internal variables do not need type definitions. Every internal variable starts with an @ character and can be a combination of alphanumeric characters. The default value for all internal variables is an "Empty" value. Internal variables defined in the main code block can be used by inner code blocks or code lines sections.

Loops should be used with care, as improperly configured loops with large numbers of iterations can impact performance and be difficult to debug in certain situations.

Main code block

Main code blocks have two basic sections -- variable declarations (optional), and code lines section. Each data block internally defines a return variable with a special, well-known name - @@.

DECLARE

\\Internal variable declaration section, e.g.:

@myvariable; @mysecondVariable = 10;

BEGIN

\\Code section with code lines...

END

When the declare section is not specified, then the only available internal variable is the return value @@. The variable declaration section can define any number of internal variables. Each variable can be optionally initialized. The variable declaration line ends with a semicolon character.

@myVariable;

@myInitializedVariable = 10;

As was mentioned earlier, multiple code blocks can be used side-by-side inside an expression:

BEGIN SET @@=5; END + BEGIN SET @@=7; END

Is equivalent to

5 + 7

These examples are used to demonstrate code blocks behavior as functions and how to specify a return value inside a code block. In this example, both code blocks are independent, thus cannot share their internal variables. To be able to share variables between separate code blocks, one upper code block is necessary:

DECLARE

  @a = 5; @b = 7;

BEGIN

  SET @@= BEGIN SET @@=@a; END + BEGIN SET @@=@b; END

END

Code Lines

Each code line starts with a keyword and ends with a semicolon character.

SET Statement

This is used to set internal variables. The following is the SET syntax:

SET @variable_name = value;

Where variable_name specifies the internal variable declared in the declare section and the value can be any standard expression [combination of functions, operators and variables (internal or external)].

Examples:

SET @myvar = 10;

SET @myvar = @myvar + 1;

SET @myvar = {{my OPC Tag 1}} + {{my OPC Tag 2}};

SET @myvar = tonumber({{my OPC Tag 1}}) * @myvar2 + {{my OPC Tag 2}};

SET @myvar = IF {{my OPC Tag 1}} > 0 THEN {{my OPC Tag 1}} ELSE 0;

EXIT Statement

This command allows for a code block to exit and terminate earlier without completing other operations. It can be used as a simple EXIT command, where it makes sense in combination with an IF statement or conditional exit with WHEN part specified:

EXIT WHEN boolean_condition (expression);

or

EXIT;

The Exit command is not propagated to upper code blocks and will only affect the current code block.

Examples:

EXIT WHEN @a > 0;

IF @a > 0 THEN EXIT;

EXIT WHEN {{my data tag}} > 1 && @a < 0;

FOREACH Loop

Simple loop designed to iterate through arrays. The syntax is as follows:

FOREACH counter_variable IN array_value

LOOP

/* add code lines here */

END

where counter_variable is an internal variable, which is declared by FOREACH statement -- i.e. doesn't need to be explicitly declared beforehand. This variable is known inside the loop body only and contains a current array element. The array_value is any expression (functions, operators, etc.) that can return an array. In case it returns a simple value (non-array value), it is converted by the expression conversion mechanism to a single element array.

Looping can be stopped earlier (if needed) by an EXIT statement.

Examples:

/* simple sum function */

DECLARE

@sum = 0;

BEGIN

FOREACH @elm IN array (

{{data:Signals.RampSlow}},

{{data:Signals.RampFast}},

{{data:Signals.RandomFast}})

LOOP

SET @sum = @sum + @elm;

END

SET @@ = @sum;

END

Or without using an explicitly declared variable:

BEGIN

FOREACH @elm IN array (

{{data:Signals.RampSlow}},

{{data:Signals.RampFast}},

{{data:Signals.RandomFast}})

LOOP

SET @@ = @@ + @elm;

END

END

With Exit statement:

BEGIN

FOREACH @elm IN array (

{{data:Signals.RampSlow}},

{{data:Signals.RampFast}},

{{data:Signals.RandomFast}})

LOOP

SET @@ = @@ + @elm;

EXIT WHEN @@ > 100;

END

END

FOR Loop

The FOR loop is always looping between specified numbers and optionally allows for specifying direction and step values. Loop values (from, to, step) are read before looping starts, thus any changes to these parameters via internal variables won't take any effect to actual loop. Looping can be stopped earlier (if needed) by EXIT statement.

The syntax is as follows:

FOR counter_variable IN [REVERSE] lowest_number..highest_number [STEP value]

LOOP

/* code lines */

END

Where counter_variable is an internal variable, which is declared by FOR statement -- i.e. doesn't need to be explicitly declared. This variable is known inside the loop body only and contains current counter value. The lowest and highest numbers determine the FOR-loop range. To start looping, the lowest number must contain a lower value than the highest number. When REVERSE is specified, then it starts looping from the highest number and ends in the lowest value. STEP is followed by a numeric value that specifies the increment value used in FOR loop. The default value is 1.

Examples (without code block):

FOR @i IN 1..10

LOOP

/* values in variable @i will be: 1,2,3,4,5,6,7,8,9,10 */

@@ = @@ + @i;

END

FOR @i IN REVERSE 1..10

LOOP

/* values in variable @i will be: 10,9,8,7,6,5,4,3,2,1 */

@@ = @@ + @i;

END

FOR @i IN 1..10 STEP 3

LOOP

/* values in variable @i will be: 1,4,7,10 */

@@ = @@ + @i;

END

FOR @i IN REVERSE 1..10 STEP 3

LOOP

/* values in variable @i will be: 10,7,4,1 */

@@ = @@ + @i;

END

FOR loop can use internal/external variables in place of lowest/highest and step numbers. See full examples below:

DECLARE

@a = 0;

BEGIN

  FOR @i IN {{data:Signals.RampSlow}}..{{data:Signals.RampFast}}

LOOP

    SET @a =

IF {{data:Signals.RampSlow}} > 50

THEN @a + @i

ELSE @a - @i;     

  END

  SET @@ = @a;

END

DECLARE

@array; @a;

BEGIN

SET @@ = 0;

SET @array = array({{var_a}}, {{var_b}}, {{var_c}});

FOR @i IN 0..(len(@array) - 1)

LOOP

SET @a = getat(@array, @i);

IF @a > 0 THEN SET @@ = @@ + @a;

END

END

IF AND IFQ Statements

IF statements can be used directly in code blocks. Their behavior is very similar to IF used in standard expression text. The only difference is that THEN and ELSE values are not expressions, but either a code line or another code block. The ELSE section is optional.

The syntax is as follows:

IF Boolean_condition THEN code_block [ELSE code_block]

Examples:

BEGIN

IF {{my variable}} > 0 THENEXIT;

SET @@ = {{my variable}};

END

BEGIN

IF {{my variable}} > 0 THEN

BEGIN

SET @@ = {{my variable}};

EXIT;

END

SET @@ = "No Value";

END

CASE-WHEN-THEN Statements

CASE statements can be used directly in code blocks and their behavior is very similar to CASE statements used in standard expression text. The only difference is that THEN and ELSE values are not expressions, but either code lines or another code block. The ELSE section is optional.