**8.1**- VARIETY and overflow**8.1.1**- ERROR_TREATMENT**8.2**- Division and remainder**8.3**- change_variety**8.4**- and, or, not, xor**8.5**- Floating-point operations, ROUNDING_MODE**8.6**- change_bitfield_to_int, change_int_to_bitfield**8.7**- make_compound, make_nof, n_copies

The question then arises of what is meant by overflow in an operation which is meant to deliver an integer of this VARIETY - is it when the integer result is outside the range (1..10) or outside the range (0..255)? For purely pragmatic reasons, TDF chooses the latter - the result is overflowed when it is outside its representational range (0..255). If the program insists that it must be within (1..10), then it can always test for it. If the program uses the error handling mechanism and the result is outside (1..10) but still within the representational limits, then, in order for the program to be portable, then the error handling actions must in some sense be "continuous" with the normal action. This would not be the case if, for example, the value was used to index an array with bounds (1..10), but will usually be the case where the value is used in further arithmetic operations which have similar error handling. The arithmetic will continue to give the mathematically correct result provided the representational bounds are not exceeded.

The limits in a VARIETY are there to provide a guide to its representation, and not to give hard limits to its possible values. This choice is consistent with the general TDF philosophy of how exceptions are to be treated. If, for example, one wishes to do array-bound checking, then it must be done by explicit tests on the indices and jumping to some exception action if they fail. Similarly, explicit tests can be made on an integer value, provided its representational limits are not exceeded. It is unlikely that a translator could produce any more efficient code, in general, if the tests were implicit. The representational limits can be exceeded in arithmetic operations, so facilities are provided to either to ignore it , to allow one to jump to a label , or to obey a TDF exception handler if it happens.

The result of the addition has the same integer VARIETY as its parameters. If the representational bounds ofov_err: ERROR_TREATMENTarg1: EXP INTEGER(v)arg2: EXP INTEGER(v) -> EXP INTEGER(v)

The ERROR_TREATMENT , impossible, is an assertion by the producer that overflow will not occur; on its head be it if it does.

The ERROR_TREATMENTS continue and wrap give "fixup" values for the result. For continue the fixup value is undefined. For wrap, the the answer will be modulo 2 to the power of the number of bits in the representational variety.Thus, integer arithmetic with byte representational variety is done modulo 256. This just corresponds to what happens in most processors and, incidentally, the definition of C.

The ERROR_TREATMENT that one would use if one wished to jump to a label is error_jump:

A branch tolab: LABEL -> ERROR_TREATMENT

The ERROR_TREATMENT, trap(overflow) will raise a TDF exception(see section 6.3 on page 35)with ERROR_CODE overflow if overflow occurs.

. There are two different kinds of division operators (with corresponding remainder operators) defined. The operators div2 and rem2 are those generally implemented directly by processor instructions giving the sign of the remainder the same as the sign of the quotient. The other pair, div1 and rem1, is less commonly implemented in hardware, but have rather more consistent mathematical properties; here the sign of remainder is the same as the sign of divisor. Thus, div1(x, 2) is the same as shift_right(x, 1) which is only true for div2 if x is positive. The two pairs of operations give the same results if both operands have the same sign. The constructors div0 and rem0 allow the translator to choose whichever of the two forms of division is convenient - the producer is saying that he does not care which is used, as long as they are pairwise consistent. The precise definition of the divide operations is given in (S7.4).div_by_zero_error: ERROR_TREATMENTov_err: ERROR_TREATMENTarg1: EXP INTEGER(v)arg2: EXP INTEGER(v) -> EXP INTEGER(v)

If the valueov_err: ERROR_TREATMENTr: VARIETYarg1: EXP INTEGER(v) -> EXP INTEGER(r)

Conversions from integer to floating are done by float_int and from floating to integers by round_with_mode . This latter constructor has a parameter of SORT ROUNDING_MODE which effectively gives the IEEE rounding mode to be applied to the float to produce its integer result.

One can extract the real and imaginary parts of a complex FLOATING using real_part and imaginary_part. A complex FLOATING can be constructed using make_complex. Normal complex arithmetic applies to all the other FLOATING constructors except for those explicitly excluded (eg floating_abs, floating_max etc.)

The OFFSETarg1: EXP OFFSET(base, y)arg2: LIST(EXP) -> EXP COMPOUND(sz)

Constant sized array values may be constructed using make_nof, make_nof_int (see section 8.7 on page 42), and n_copies. Again, they only occur in C as constants in global definitions.

*Part of the TenDRA Web.Crown
Copyright © 1998.*