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