#INCLUDE "course.module"

PROC casting.occ (CHAN BYTE keyboard?, screen!, error!)

  --{{{  COMMENT documentation
  -->
  --> Infix operators in occam demand the same type (i.e. base type and
  --> precision) for both its operands.  Assignment, communication and
  --> parameter passing are equally strict: the type and precision of the
  --> variable (or parameter) receiving the data (or argument) must match
  --> what is being supplied.  THERE IS NO AUTOMATIC CASTING BETWEEN TYPES.
  -->
  --> Hence:
  -->
  -->   INT a:
  -->   REAL32 x:
  -->   SEQ
  -->     a := 42      -- this line is OK
  -->     x := 42.0    -- this line is OK
  -->     x := 42      -- this line will not compile
  -->     a := x       -- this line will not compile
  -->     x := a       -- this line will not compile
  -->     x := 2*x     -- this line will not compile
  -->     x := 2.0*x   -- this line is OK
  -->
  --> CASTING BETWEEN TYPES AND PRECISIONS MUST BE EXPLICITLY SPECIFIED.
  -->
  --> We can cast any primitive type to any other primitive by using
  --> the target type name as a prefix operator.  For those casts that may
  --> lose precision, we must say how the least significant bit is to be
  --> resolved (wither by ROUNDing or TRUNCation).  This is done by qualifying
  --> the type-name-prefix-operator with either ROUND or TRUNC.
  -->
  --}}}

  BOOL a:
  BYTE b:
  INT16 i16:
  INT32 i32:
  INT64 i64:
  INT i:
  REAL32 r32:
  REAL64 r64:

  SEQ

    a := TRUE

    b := (BYTE a) + 42
    i16 := INT16 b
    i32 := INT32 i16
    i := INT i32
    i64 := INT64 i
    r32 := REAL32 ROUND i16   -- rounds least significant bit to nearest
    r32 := REAL32 TRUNC i16   -- rounds least significant bit towards zero
    r32 := REAL32 ROUND i     -- rounds least significant bit to nearest
    r32 := REAL32 TRUNC i     -- rounds least significant bit towards zero
    r64 := REAL64 r32         -- no need for rounding

    r32 := REAL32 ROUND r64   -- rounds least significant bit to nearest
    r32 := REAL32 TRUNC r64   -- rounds least significant bit towards zero
    i64 := INT64 ROUND r32    -- rounds to nearest whole number
    i64 := INT64 TRUNC r32    -- rounds towards zero
    i := INT i64
    i32 := INT32 ROUND r64    -- rounds to nearest whole number
    i32 := INT32 TRUNC r64    -- rounds towards zero
    i16 := INT16 i
    b := BYTE i16
    a := BOOL (b - 42)

    IF
      a
        out.string ("OK!*c*n", 0, screen!)
      NOT a
        out.string ("ERROR!*c*n", 0, screen!)

    --{{{  COMMENT Warning
    -->
    --> Warning: if the result of an attempted cast lies outside the legal
    --> range of values for the target type, there will be a run-time error:
    -->
    -->   BYTE b:
    -->   INT i:
    -->   SEQ
    -->     b := 180
    -->     i := INT b
    -->     b := BYTE i   -- this executes OK (but changes nothing - b is still 180)
    -->     i := 2*i
    -->     b := BYTE i   -- this will cause a run-time error
    -->
    --}}}

:
