Type conversion: Integer to integer

The programming language Chora supports six different data types to represent integer operands. We distinguish between signed and unsigned data types, each with 8-, 16-, 32- or 64-bit precision. In order to convert an operand between the diverse integer data types, a set of adequate integer conversion operators is available.

Syntax

(int64)integer‑operandorint64(integer‑operand)

(int32)integer‑operandorint32(integer‑operand)

(int16)integer‑operandorint16(integer‑operand)

(int8)integer‑operandorint8(integer‑operand)

(uint64)integer‑operandoruint64(integer‑operand)

(uint32)integer‑operandoruint32(integer‑operand)

(uint16)integer‑operandoruint16(integer‑operand)

(uint8)integer‑operandoruint8(integer‑operand)

Discussion

The integer conversion operator converts the given integer operand to another signed or unsigned integer data type. Generally, the conversion to a compatible data type with the same or greater rank than the of the original operand do not change the operand value or its representation. Please note, the conversion to a higher rank extends the value in the operand by additional 0 (zero) bits if the value was positive or 1 (one) bits if it was negative:

var int16 a1 = -1251;  // hex 0xFB1D
var int16 a2 = -125;   // hex 0xFF83
var int16 a3 =  1369;  // hex 0x0559

var int32 b1 = (int32)a1;  // b1 = -1251 (hex 0xFFFFF4E3)
var int32 b2 = (int32)a2;  // b2 = -125  (hex 0xFFFFFF83)
var int32 b3 = (int32)a3;  // b3 =  1369 (hex 0x00000559)

Depending on the operand original content, the conversion may lead to the loss of information provided in it. Precisely, the conversion to a data type with lower rank or the conversion between signed and unsigned data types result in the operand highest bits being truncated or reinterpreted.

In simple terms, if the value stored originally in an operand doesn't fit in the destination data type, the value resulting from the conversion will differ from the expected value. In the following example you see two 16-bit signed integer operands. While the value in the operand a1 is small enough to be converted in the lower int8 data type, the value in operand a2 doesn't fit in it and its conversion loses information resulting in a completely different value:

var int16 a1 = -125;   // hex 0xFF83
var int16 a2 = -1251;  // hex 0xFB1D

var int8  b1 = (int8)a1;  // b1 = -125 (hex 0x83)
var int8  b2 = (int8)a2;  // b2 =  29  (hex 0x1D)

Similarly, trying to convert a negative number in an unsigned integer data type will result again in an erroneous value. In the following example you see two 16-bit signed integer operands. While the value in the operand a1 is positive and can be converted in the uint32 data type, the value in the operand a2 is negative and its conversion causes the information being misinterpreted:

var int16  a1 =  1251;  // hex 0x04E3
var int16  a2 = -125;   // hex 0xFF83

var uint32 b1 = (uint32)a1;  // b1 = 1251       (hex 0x000004E3)
var uint32 b2 = (uint32)a2;  // b2 = 4294967171 (hex 0xFFFFFF83)

Explicit conversion

With the explicit conversion operator you specify explicitly how an operand should be treated within the implemented expression. Chora supports two equivalent notation variants how you can apply the conversion operators. In the first variant the destination data type is specified between a pair of (...) (parentheses). The second notation variant corresponds to a constructor invocation of the respective destination data type:

var int32 a = 1369;
var int32 b = 1251;

// Notation 1
var int16 c1 = (int16)( a + b );

// Notation 2
var int16 c2 = int16( a + b );

trace c1 == c2; // true

The explicit type conversion is performed with the above described side effects. Applying the conversion on an operand not fitting the destination data type will thus result in the original operand value being truncated or its sign being lost. Since you apply the operation consciously, the Chora compiler will not report any warning nor error in such case.

Implicit conversion

Wherever it is not ambiguous, the Chora compiler applies the necessary type conversion implicitly. This is usually the case when you assign the result of an expression to e.g. a variable or you pass it as parameter in a method invocation. In such cases the Chora compiler can derive from the destination operand the corresponding data type and decide whether or not to convert the expression. For example, the following assignment implies the conversion to uint8 data type since the destination operand is the red instant property declared with uint8 as data type:

var int32 a   = 167;
var color clr = #00000000;

// Apply an implicit conversion from 'int32' to 'uint8'
clr.red = a;  // clr.red = 167

If the applied implicit type conversion has potential side effects, the Chora compiler will report a warning giving you a chance to review the affected expression. To avoid the warning you can extend the expression by an additional explicit type conversion operator:

Integer promotion

Integer types smaller than int32 (32-bit signed integer) are automatically promoted to int32 when an operation (e.g. an addition) is performed on them. Since int32 is a superset of all smaller integer data types (except the uint32), the operation is legal without fearing any side effects. For example:

var uint8 a = 167;
var int32 b = 1369;

// 'a' is converted in 'int32' and the addition
// is performed with signed 32-bit precision.
var int32 c = a + b;  // c = 1536

If the operation evaluates an int64 operand, all other involved and smaller integer operands are automatically promoted to int64 and the entire operation results in a signed 64-bit integer value. For example:

var int64  a = -125113691469;
var uint32 b =  167;

// 'b' is converted in 'int64' and the addition
// is performed with signed 64-bit precision.
var int64 c = a + b;  // c = -125113691302

When mixing an uint32 or uint64 operand with a signed integer, the signed operand is converted implicitly in the corresponding uint32 or uint64 data type. This implicit type conversion is performed with the above described side effects. The resulting data type of the entire operation is consequently uint32 or uint64. For example:

var int32  a = -1251;
var uint32 b =  167;

// 'a' is converted in 'uint32' and the addition
// is performed with unsigned 32-bit precision.
var uint32 c = a + b;  // c = 4294964618

By using the explicit type conversion operators you can control the operation more precisely. Knowing, that the value in the uint32 operand will never become to big for an int32 data type, you can convert the uint32 in int32 and perform a signed integer addition:

var int32  a = -1251;
var uint32 b =  167;

// 'b' is converted in 'int32' and the addition
// is performed with signed 32-bit precision.
var int32 c = a + int32( b );  // c = -1084