Typing of expressions

logi.CAD 3 →types →expressions and →assignments according to the following rules:

  • The data type of the →variable to store the result of the →overloaded function influences the data type of the result of the function or operation. This rule does not correspond to the specifications within the →IEC-standard.

    Examples
    VAR
    int1, int2, int3 : INT := 32767;
    dint1 : DINT := 32767;
    ResultInt1 : INT;
    ResultDint1, ResultDint2 : DINT;
    END_VAR
     
    ResultInt1 := int1 + int2; (* The addition is performed as an INT-operation. *)
    ResultDint1 := int1 + int2; (* In contrast to the IEC-standard: 'int1' and 'int2' are converted to DINT. The addition is performed as an DINT-operation and assigned to 'ResultDint1'. *)
    ResultDint2 := dint1 + int3; (* 'int3' is converted to DINT. The addition is performed as a DINT addition. *)
  • If the expressions do not include any concrete data type, typing is influenced by the data type of the variable to store the result of the overloaded function. This addon rule is an implementer-specific realization because the IEC-standard does not specify any on this.

    Examples
    VAR
    ResultDintA, ResultDintB, ResultDintC : DINT;
    sint1 : SINT := 127;
    END_VAR
     
    ResultDintA := 127 + 127; (* The addition is performed as an DINT-operation because there is no other concrete data type. *)
    ResultDintB := 127 + SINT#127; (* 'SINT#127' is converted to DINT. The addition is performed as an DINT-operation and assigned to 'ResultDintB'. *)
    ResultDintC := 127 + sint1; (* 'sint1' is converted to DINT. The addition is performed as an DINT-operation and assigned to 'ResultDintC'.*)
  • In case of a →call that is using inputs, outputs and/or a return value with the same →generic data type, logi.CAD 3 types all of these inputs, outputs and the return value of the call – even if only one of these elements is connected to a concrete data type.

    Examples
    VAR
    Var1, OUT1 : INT;
    iForceMrk1 : FORCEMRK;
    END_VAR
     
    Var1 := ADD(IN1 := 1, IN2 := 3);
    (* The inputs and the return value of 'ADD' are using the same generic data type. As the INT variable 'Var1' is assigned to the call of 'ADD' (in particular to the return value of 'ADD'), the call is typed with 'INT'. Subsequently, the inputs of 'ADD' are typed with 'INT' as well. *)
     
    iForceMrk1(IN := 3, OUT => OUT1);
    (* The input and the output of 'FORCEMRK' are using the same generic data type. As output 'OUT' of 'iForceMrk1' is assigned to the INT variable 'OUT1', the call is typed with 'INT'. Subsequently, the input of 'iForceMrk1' is typed with 'INT' as well. *)

    If a →user-defined data type is used for typing, logi.CAD 3 uses the →base type. This rule is of importance, if an →Initial value is defined within the user-defined data type – in this case the initial value of the data type is not used but the initial value of the base type.
    Compare: In case of an →array data type (incl. an ARRAY declaration of a variable) or a →structured data type, the user-defined data type is the base type.

    Examples
    TYPE
    MyInt : INT := 6;
    MyStruct : Struct
    Elem1 : MyInt;
    END_STRUCT;
    MyArray : Array [1..1] OF MyInt := [99];
    END_TYPE
     
    FUNCTION_BLOCK myFB
    VAR
    outDerived : MyInt;
    outArray1 : MyArray;
    outArray2 : Array [1..1] OF MyInt;
    outStruct : MyStruct;
    iForceMrk1, iForceMrk2, iForceMrk3, iForceMrk4 : FORCEMRK;
    END_VAR
     
    iForceMrk1(OUT => outDerived);
    (* 'OUT' gets value '0' because initial value '0' of 'INT' is used. Here the base type is 'INT'. *)
    (* The initial value '6' of 'MyInt' is NOT used. *)
    iForceMrk2(OUT => outArray1);
    iForceMrk3(OUT => outArray2);
    iForceMrk4(OUT => outStruct);
    (* Each element of output 'OUT' gets value '6' because initial value '6' of 'MyINT' is used. *)
    (* Here the base type of each element is 'MyInt* while the base type of 'OUT' is 'ARRAY [...] OF' or 'STRUCT'. *)
    END_FUNCTION_BLOCK
  • In 2 or more calls are connected with each other and their connected inputs, outputs and/or the connected return value are of a generic data type (but the others are of a concrete data type), logi.CAD 3 types all of these inputs, outputs and the return value of the call by using the lowest common data type.
    Example: The return value of the PACK block is of the generic data type ANY_ELEMENTARY and the inputs are of the concrete data type BYTE, the input of the TO_DINT block is also of the generic data type ANY_ELEMENTARY and the return value is of the concrete data type DINT. In case of the following code, the return value of PACK and the input of TO_DINT are typed with BOOL (BOOL is the lowest common data type of ANY_ALEMENTARY).

    Example
    VAR
    Var1 : DINT;
    ByteVar1 : BYTE:= 16#AB;
    END_VAR
     
    Var1 := TO_DINT(PACK(ByteVar1, ByteVar1)); (* 'Var1' evaluates to value '1'. This is not a value expected from 'PACK', but the correct result due to the typing. *)

    Do not nest the calls in order to avoid the typing using to the lowest common data type.
    Workaround 1: Declare an auxiliary variable. Assign one call to this auxiliary variable. Assign this auxiliary variable as parameter for the other call.

    Example for workaround 1
    VAR
    Var1 : DINT;
    ByteVar1 : BYTE := 16#AB;
    HelperVar : DINT; (* the auxiliary variable *)
    END_VAR
     
    HelperVar := PACK(ByteVar1, ByteVar1);
    Var1 := TO_DINT(HelperVar); (* 'Var1' evaluates to value '43947'. This a value as expected from 'PACK' *)

    Workaround 2: Create a user-defined POU (e.g. a function). Assign one call of the blocks (in the following example: PACK) to the result value of the function. Call the function as parameter of the other block (then: DINT).

    Example for workaround 2
    FUNCTION myFun1 : DWORD
    VAR
    ByteVar1 : BYTE:= 16#AB;
    END_VAR
     
    myFun1 := PACK(ByteVar1, ByteVar1); (* 'PACK' is assigned to the return value of function 'myFun1'. *)
    END_FUNCTION
     
    FUNCTION_BLOCK myFB2
    VAR
    Var1 : DINT;
    END_VAR
    Var1 := TO_DINT(IN:=myFun1()); (* 'Var1' evaluates to value '43947'. This a value as expected from 'PACK'. *)
    END_FUNCTION_BLOCK