Condition Processing
A Condition in SMI++ is a Boolean expression composed of a combination of Boolean operators {and, or, not}, brackets { ( , ) } and Boolean statements.
In SMI++ these Boolean statements are so called Simple Conditions (SC) and are of the following 4 types:
type1 | ( 'object-name' in_state 'state-name' ) |
type2 | ( all_in 'objectset-name'
in_state 'state-name' ) or (any_in 'objectset-name' in_state 'state-name' ) |
type3 | ( 'objectset-name' is_empty ) |
type4 | ( 'item1' relational-operator
'item2' ) NB: this type is used for testing values of parameters. See details bellow. |
NB: more advanced use for experts of 'object-name' and 'objectset-name' in type1, type2 and type3, see Variable Elements in SML
NB: in the above one can also have not_in_state instead of in_state and not_empty instead of empty
A condition is translated (decomposed) by SMI Translator in the following way: all the Simple Conditions (SC) are extracted and a series of elementary Boolean operations or Condition Instructions (CI), which are either binary or unary, is generated. At run time, firstly all the SCs are evaluated and then the series of CIs is then evaluated from the beginning to the end with the result of the last CI being the overall desired answer. There are 3 possible forms of these CIs:
- operand1 and operand2
- operand1 or operand2
- not operand1
where operand1(operand2) is either result of evaluation of one of the SCs or one of the previous CIs.
Example:
( ( A in_state ERROR ) or (B in_state ERROR) ) and ( LHC in_state PHYSICS)
The following simple conditions are extracted:
SC1:( A in_state ERROR ); SC2:(B in_state ERROR); SC3: ( LHC in_state PHYSICS)
and the series of CI generated:
CI1 : result-of-SC1 or result-of-SC2
CI2 : result-of-CI1 and result-of-SC3
In 'normal' circumstances the result of evaluation of SC as well as CI is either TRUE or FALSE.
The complication arises when one or more simple conditions of type2 refer to empty set. We adopted rather ad-hoc way of dealing with this situation:
In addition to the two values TRUE and FALSE, we introduced yet another value which we call GHOST and define it as follows:
When simple condition of type2 refers to empty set, it's value is by definition GHOST.
For evaluation of CI we adopted the following rules:
- 'normal-value' or GHOST = 'normal-value'
- GHOST or 'normal-value' = 'normal-value
- GHOST or GHOST = GHOST
- 'normal-value' and GHOST = normal-value
- GHOST and normal-value = normal-value
- GHOST and GHOST = GHOST
- not GHOST = GHOST
In most common situations, it works like if the simple conditions referring to empty sets were not present. This is probably what one would like to do. The problem is when the overall result is GHOST. In this case we replace this result with FALSE. In case of when instructions this is exactly what is required. In case of if instructions it is not ideal because it will cause execution of else part of if (if any) without any justification. Obviously the better thing would have been to ignore the if instruction altogether.
Simple Condition Type4
Format:
( item1 relational-operator item2 )
Where:
- item1(2)
- are indiValues as described in indiValue
- relational-operator is one of the following:
- < less than
- > greater than
- <= less than or equal to
- >= greater than or equal to
- == equal to
- <> not equal to
Generally, the comparison is done only between items representing values of the same type. If items do not represent values of the same type, then this can be achieved by type casting of one of them or both. See below.
Item Type Casting and Type Mixing
Format:
(cast-indicator)item
Where
- item
- is as described above
- cast-indicator is one of the following:
- string, int, float
example: (int)run-type
In this example run-type is a name of parameter that has been declared as string and this way it's value is temporarily cast into integer. And therefore can be compared with other integer values.
Restrictions
There are two basic restrictions which are imposed already at translation stage:
- Casting item representing constant value e.g. (float)3
- Casting item representing string value into floating point value
In addition, at running (State Manager) stage:
- Casting item representing string value into integer when the string can not be interpreted as such.
When type casting is used, then Translator insists that both items (after casting) are of the same type
When type casting is not used and the items represent values of different types, then Translator will attempt its own type casting and will produce warnings (and possibly errors) in the process :
- If one of the items represents string value and the other represents floating-point value then Translator will produce fatal error.
- If one of the items represents integer value and the other represents floating-point value then the item representing integer value is casted to floating point.
- If one of the items represents integer value and the other represents string value then the item representing string value is type cast to integer. Later, when State Manager is running and the actual string value can not be interpreted as such, the condition evaluates to GHOST and State Manager generates a warning message. In this case such simple condition is handled in the same way as type2 condition referring to empty set. See above.