Super Prev Next

System Modules

System modules are not compilation modules, in the sense that they do not have an actual definition or implementation provided in a library, or by the user. They encapsulate predefined types, constants and procedures, for which the predefined identifiers are not pervasive.

For information only, the interfaces to system modules are shown informally in this International Standard as definition modules. The required semantics cannot be obtained by interpreting these system definition modules according to the rules for separate modules as given in section 6. In particular, as predefined entities, the procedures and functions of a system module are not assignment-compatible with any procedure type. Also, types appearing as opaque types are system basic types and cannot be used to implement user-defined opaque types.

This International Standard defines five system modules, namely SYSTEM, COROUTINES, TERMINATION, EXCEPTIONS, and M2EXCEPTION.

Change: In Programming in Modula-2 the only system module is SYSTEM and this is described as a pseudo-module. Coroutine facilities have been moved from SYSTEM to the system module COROUTINES in this International Standard.


Super Prev Next

The Module SYSTEM

The system module SYSTEM provides low-level facilities for gaining access to the addresses and the underlying storage of variables, for performing address arithmetic, and for manipulating the representation of values. Programs that use these facilities may be non-portable.


Super Prev Next

The Interface to SYSTEM

The interface to SYSTEM behaves as if the following were its definition module:

    DEFINITION MODULE SYSTEM;
    
      (* Gives access to system programming facilities that are probably non portable. *)
    
      (* The constants and types define underlying properties of storage *)
    
    CONST
      BITSPERLOC = <implementation-defined constant> ;
      LOCSPERWORD = <implementation-defined constant> ;
    
    TYPE
      LOC; (* A system basic type. Values are the uninterpreted contents of the smallest
   	      addressable unit of storage *)
      ADDRESS = POINTER TO LOC;
      WORD = ARRAY [0 .. LOCSPERWORD-1] OF LOC;
    
      (* BYTE and LOCSPERBYTE are provided if appropriate for machine *)
    CONST
      LOCSPERBYTE = <implementation-defined constant> ;
    
    TYPE
      BYTE = ARRAY [0 .. LOCSPERBYTE-1] OF LOC;
    
    PROCEDURE ADDADR (addr: ADDRESS; offset: CARDINAL): ADDRESS;
      (* Returns address given by (addr + offset), or may raise an exception if this
   	 address is not valid.
      *)
    
    PROCEDURE SUBADR (addr: ADDRESS; offset: CARDINAL): ADDRESS;
      (* Returns address given by (addr - offset), or may raise an exception if this address
   	 is not valid.
      *)
    
    PROCEDURE DIFADR (addr1, addr2: ADDRESS): INTEGER;
      (* Returns the difference between addresses (addr1 - addr2), or may raise an exception
   	 if the arguments are invalid or if the address space is non-contiguous.
      *)
    
    PROCEDURE MAKEADR (val: <some type>; ... ): ADDRESS;
      (* Returns an address constructed from a list of values whose types are
   	 implementation-defined, or may raise an exception if this address is not valid.
      *)
    
    PROCEDURE ADR (VAR v: <anytype>): ADDRESS;
      (* Returns the address of variable v. *)
    
    PROCEDURE ROTATE (val: <a packedset type>; num: INTEGER): <type of first parameter>;
      (* Returns a bit sequence obtained from val by rotating up or down (left or right) by
   	 the absolute value of num. The direction is down if the sign of num is negative,
   	 otherwise the direction is up.
      *)
    
    PROCEDURE SHIFT (val: <a packedset type>; num: INTEGER): <type of first parameter>;
      (* Returns a bit sequence obtained from val by shifting up or down (left or right) by
   	 the absolute value of num, introducing zeros as necessary. The direction is down
   	 if the sign of num is negative, otherwise the direction is up.
      *)
    
    PROCEDURE CAST (<targettype>; val: <anytype>): <targettype>;
      (* CAST is a type transfer function. Given the expression denoted by val, it returns
   	 a value of the type <targettype>. An invalid value for the target value or a
   	 physical address alignment problem may raise an exception.
      *)
    
    PROCEDURE TSIZE (<type>; ... ): CARDINAL;
      (* Returns the number of LOCS used to store a value of the specified <type>. The
   	 extra parameters, if present, are used to distinguish variants in a variant record.
      *)
    
    END SYSTEM.

Declaration Semantics

The identifiers available for import from the module SYSTEM shall include the constant identifiers BITSPERLOC, and LOCSPERWORD, the type identifiers LOC, ADDRESS, and WORD, and the procedure identifiers ADDADR, SUBADR, DIFADR, MAKEADR, ADR, ROTATE, SHIFT, CAST, and TSIZE.

In addition, where appropriate for the target hardware architecture, the identifiers available for import from the module SYSTEM shall include the constant identifier LOCSPERBYTE, and the type identifier BYTE.

Note: An implementation may extend the module SYSTEM by including additional types, procedures, variables and constants appropriate to the facilities of the target hardware. The identifiers BYTE and LOCSPERBYTE are, however, reserved for use with appropriate target hardware architectures, and may not be used in SYSTEM with other meanings --- see ???.

Changes:

  1. The type LOC has been introduced as a mechanism to resolve the problem that, in many implementations of Modula-2, both BYTE and WORD occur in SYSTEM. Its introduction allows a consistent handling of both of these types, and also enables further WORD-like types to be introduced in an implementation, for example, where TSIZE(CARDINAL)6=TSIZE(INTEGER).

  2. The constants BITSPERLOC, LOCSPERWORD and LOCSPERBYTE have been introduced to denote the number of bits in a LOC, the number of LOCs in a word and the number of LOCs in a BYTE respectively.

  3. Variables of type ADDRESS are no longer expression-compatible with CARDINAL, i.e. they cannot directly occur in expressions that include arithmetic operators.

  4. The function MAKEADR has been introduced as a mechanism for constructing a value of type ADDRESS, and new functions ADDADR, SUBADR, and DIFADR have been introduced for address arithmetic, thereby obviating the necessity for assignment compatibility between ADDRESS and a whole number type.

  5. New functions ROTATE and SHIFT have been introduced to extend the bit-level manipulation operations on packedset values.

  6. The function CAST has been introduced for type transfer.


Super Prev Next

The Constants of SYSTEM

The module SYSTEM provides the constants BITSPERLOC and LOCSPERWORD. Additionally, if appropriate for the target hardware architecture, the constant LOCSPERBYTE is provided.

Declaration Semantics

The constant identifier BITSPERLOC shall denote the whole number literal value that is the number of bits used in the representation of values of the location type and other types occupying a single location.

The constant identifier LOCSPERWORD shall denote the whole number literal value that is the number of locations used in the representation of values of the type denoted by WORD and other types occupying a single word.

The constant identifier LOCSPERBYTE, if provided, shall denote the whole number literal value that is the number of locations used in the representation of values of the type denoted by BYTE and other types occupying a single byte.


Super Prev Next

The Types of SYSTEM

The module SYSTEM provides system storage types to represent uninterpreted storage, and a type to represent logical addresses.


Super Prev Next

System Storage Types

System storage types include the location type, and types based on the location type.

Declaration Semantics

The type identifier LOC shall denote the location type. A value of this type shall correspond to the uninterpreted contents of the smallest addressable unit of storage in an implementation; the value of the call TSIZE(LOC) shall therefore be one.

Notes:

  1. The only operation directly defined on the location type is assignment.

  2. There are special rules affecting parameter compatibility for system storage types; where a formal parameter is expressed in terms of system storage types, the corresponding actual parameter may be of any type that is represented in a corresponding number of storage locations --- see System Storage Parameter Compatibility.

The type denoted by WORD shall be defined in terms of LOC as follows:

    LOCSPERWORD = <implementation-defined constant> ;
    WORD = ARRAY [0 .. LOCSPERWORD-1] OF LOC;

and the value of the call TSIZE(WORD) shall be LOCSPERWORD.

The type denoted by BYTE, if provided, shall be defined in terms of LOC as follows: if TSIZE(BYTE) = 1 then

    LOCSPERBYTE = 1;
    BYTE = LOC;

and if TSIZE(BYTE) > 1 then

    LOCSPERBYTE = <implementation-defined constant> ;
    BYTE = ARRAY [0 .. LOCSPERBYTE-1] OF LOC;

and the value of the call TSIZE(BYTE) shall be LOCSPERBYTE.


Super Prev Next

The Address Type

Declaration Semantics

The declaration:

    TYPE ADDRESS = POINTER TO LOC;

shall define the address type. Values of this type shall correspond to the logical addresses of storage locations.

Notes:

  1. The term `logical addresses' is used since it is required that the address type is assignment-compatible with all pointer types and vice-versa --- see Assignment Compatibility.

  2. A formal variable parameter of the address type is parameter-compatible with an actual variable parameter of any pointer type --- see Variable Parameter Compatibility.

  3. As well as the operations that are normally applicable to values of pointer types, the system function procedures ADDADR, SUBADR, and DIFADR allow address arithmetic to be applied to all pointer types. In the case of ADDADR and SUBADR the result type is the address type; in the case of DIFADR the result type is the signed type.

  4. Values of the address type may be used in the optional expression that follows the identifier in a variable declaration to fix the storage location of that variable; they may be constructed with the function MAKEADR --- see The Function MAKEADR.


Super Prev Next

The Functions of SYSTEM

The module SYSTEM provides function procedures for address arithmetic (ADDADR, DIFADR, and SUBADDR), for address value generation (MAKEADR and ADR), for packedset operations (ROTATE and SHIFT), for type transfer (CAST), and for determining the storage size of values of a given type (TSIZE).


Super Prev Next

Address Arithmetic Functions

The function procedures ADDADR, SUBADDR and DIFADR are provided for address arithmetic operations on values of pointer types.


Super Prev Next

The Function ADDADR

The function ADDADR can be used to construct a value of the address type by adding an offset to the value of a pointer type.

Static Semantics

A call of ADDADR shall have two actual parameters. The first parameter shall be an expression that is of a pointer type, and the second parameter shall be an expression of a type with which the unsigned type is value parameter compatible. The type of a call of ADDADR shall be the address type.

Dynamic Semantics

The value of the call ADDADR(addr, offset) shall be an address calculated by adding offset to addr in an implementation-defined manner that satisfies the properties given in Properties of the address arithmetic functions.

An exception shall be raised if addr is the nil value.

An exception may occur and may be raised if the ADDADR function increments an address out of address range.

Notes:

  1. An exception may occur, in particular, where the address space is non-contiguous.

  2. The subsequent use of a calculated address may raise an exception.

  3. Adding N to a pointer which points to a type whose size is greater than one LOC will not add N*TSIZE(typePointedTo), but will add N.


Super Prev Next

The Function SUBADR

The function SUBADR can be used to construct a value of the address type by subtracting an offset from the value of a pointer type.

Static Semantics

A call of SUBADR shall have two actual parameters. The first parameter shall be an expression that is of a pointer type, and the second parameter shall be an expression of a type with which the unsigned type is value parameter compatible. The type of a call of SUBADR shall be the address type.

Dynamic Semantics

The value of the call SUBADR(addr, offset) shall be an address calculated by subtracting offset from addr in an implementation-defined manner that satisfies the properties given in Properties of the address arithmetic functions.

An exception shall be raised if addr is the nil value.

An exception may occur and may be raised if the SUBADR function decrements an address out of address range.

Notes:

  1. An exception may occur, in particular, where the address space is non-contiguous.

  2. The subsequent use of a calculated address may raise an exception.

  3. Subtracting N from a pointer which points to a type whose size is greater than one LOC will not subtract N*TSIZE(typePointedTo), but will subtract N.


Super Prev Next

The Function DIFADR

The function DIFADR can be used to calculate the offset between two addresses, by subtracting the second address from the first.

Static Semantics

A call of DIFADR shall have two actual parameters. Both parameters shall be expressions of a pointer type. The type of a call of DIFADR shall be the signed type.

Note: The two parameters need not be expressions of the same pointer type, since the address type is compatible with all pointer types.

Dynamic Semantics

The value of the call DIFADR(addr1, addr2) shall be a signed number calculated by subtracting addr2 from addr1 in an implementation-defined manner that satisfies the properties given in Properties of the address arithmetic functions.

An exception shall occur if addr1 is the nil value or if addr2 is the nil value.

An exception may occur and may be raised if the result of the DIFADR function is out of the range of the signed type, or if the result is meaningless because the address space is non-contiguous.


Super Prev Next

Properties of the address arithmetic functions

Given the declarations VAR adr: ADDRESS; n: CARDINAL; the following shall be true of the address arithmetic func- tion procedures if an exception is not raised:

    SUBADR(ADDADR(adr,n), n) = adr
    ADDADR(SUBADR(adr,n), n) = adr
    DIFADR(ADDADR(adr,n), adr) = n
    DIFADR(adr, SUBADR(adr,n)) = n
    ADDADR(adr, 0) = adr


Super Prev Next

Address Construction and Enquiry Functions

The function procedures MAKEADR and ADR are provided for the construction and determination of address values.


Super Prev Next

The Function MAKEADR

The function MAKEADR can be used to construct a value of the address type from one or more values of implementation- defined types. The actual number and types of the parameters are not defined in this International Standard in order that implementations may offer one or more alternatives appropriate to the target architecture. On some implementations, one of the parameters might be used to distinguish between the generation of logical addresses and the generation of hardware addresses, such as apply to memory-mapped I/O.

A value constructed by MAKEADR from constant parameters can be used in the optional expression that follows the identifier in a variable declaration to fix the address of storage used for that variable --- see Variable Declarations.

Static Semantics

A call of MAKEADR shall have an implementation-defined number of actual parameters of implementation-defined types. The type of a call of MAKEADR shall be the address type.

Dynamic Semantics

The value of the call MAKEADR(val1, ... valN) shall be an implementation-defined conversion of val1, ... valN. An exception may occur and may be raised if the result is not in address range.

Note: The subsequent use of an address constructed in this way may raise an exception.


Super Prev Next

The Function ADR

The function ADR can be used to obtain the address of a variable.

Static Semantics

A call of ADR shall have one actual parameter that shall be a variable designator. The type of a call of ADR shall be the address type.

Dynamic Semantics

The value of the call ADR(v) shall be the address of the variable v such that if

    TYPE
      Val = ... ;
      PtoVal = POINTER TO Val;
    VAR
      v : Val;
      p : PtoVal;
    ...
    p := ADR(v)

then p^ and v shall designate the same variable.


Super Prev Next

Packedset Functions

The functions ROTATE and SHIFT augment the facilities provided by packedset infix operations and packedset relational operations for the bit-level manipulation of values of packedset types.


Super Prev Next

Packedset mapping

Values of a packedset type shall be considered as sequences of bits, numbered according to the ordinal values of the members of the the host type of the base type of the packedset. Bit number n is set (i.e. has the value 1) if n is an element of the packedset, and bit number n is unset or clear (has the value 0) if n is not an element of the packedset.

The bit-numbering shall be such that bit number 0 is the least significant bit in a machine register. Bit number 1 is the next least significant bit etc. Adjacent bit numbers shall be adjacent bits in the machine register.

The ordinal values of the lower and upper bounds of the interval used to define a packedset define a bit field within which bit-level operations are to be applied. An implementation may restrict the lower and upper bounds of the interval used to define a packedset --- see ???.

In shift and rotate operations on bit sequences, a move `up' by a number of bit positions will move the bit values within the bit field in the direction of increasing bit numbers; this is also described as a `left' move since bit positions of increasing significance are often shown as being laid out from right to left. Similarly, a move `down', or `right', will move the bit values within the bit field in the direction of decreasing bit numbers. In the case of shift operations, 0 bit values replace those moved away from a boundary of a bit field; in the case of rotate operations, bit values moved out of the bit field at one boundary are moved into the bit field at the other boundary.

Notes:

  1. For example, the lower bound may be restricted to 0 and the upper bound to a value that is a multiple of BITSPERLOC.

  2. The restriction on the upper and lower bounds of the defining interval might apply to packedsets passed as parameters to SHIFT and ROTATE if such manipulation of only part of a machine word might be impossible.

  3. Set operations applied to packedsets are equivalent to the following bit-level operations within bit fields: + union bitwise inclusive-or operation on two bit sequences - set difference the bits of the first sequence that are not in the second * intersection bitwise and operation on two bit sequences / symmetric set difference bitwise exclusive-or operation on two bit sequences INCL(s,x) set bit x (to 1) EXCL(s,x) clear bit x (to 0) = equality are the two bit sequences equal? <> inequality are the two bit sequences different? <= subset is the first bit sequence included in the second? >= superset does the first bit sequence include the second? x IN s membership is bit number x set to 1?

  4. It is intended that packed sets be mapped on to machine register bits in such a way that in an implementation having a binary representation for CARDINAL and where, in addition, TSIZE(CARDINAL)=TSIZE(BITSET), then the following would be true.

    CAST(CARDINAL,BITSET{0}) = VAL(CARDINAL,1)

    and if v is a variable of type CARDINAL, then

    CAST(CARDINAL,SHIFT(CAST(BITSET,v),-1)) = v DIV 2

    and provided v < = MAX(CARDINAL) DIV 2, then

    CAST(CARDINAL,SHIFT(CAST(BITSET,v),1)) = v * 2


Super Prev Next

The Function ROTATE

The function ROTATE can be used to rotate a bit sequence up or down (left or right) by a specified number of positions within a bit field. The bit sequence is defined by the value of a packedset type, and the direction of rotation is down (right) if the specified number is negative; otherwise the direction is up (left).

Static Semantics

A call of ROTATE shall have two actual parameters. The first parameter shall be an expression that is of a packedset type. The second parameter shall be an expression of a type with which the signed type is value parameter compatible.

The type of a call of ROTATE shall be the type of the first parameter.

An implementation may impose restrictions on the types that are allowed as the first parameter, save that ROTATE will at least accept a value of the type BITSET --- see ??? and The Bitset Type.

Dynamic Semantics

The value of the call ROTATE(val, num) shall be a packedset whose elements are such that the offset of their ordinal values from the ordinal value of the minimum value of the base type of the packedset, is given by the offset of the ordinal values of the elements of val increased by num if it is positive, or decreased by the absolute value of num if it is negative, and scaled by the number of values in the base type.

Note: With the interpretation of a value of a packedset type as a sequence of bits, the rotate operation can be considered as a rotation of the bits upwards (leftwards), or a rotation of the bits downwards (rightwards), according to the value of the second operand, and within the bit field defined by the base type of the packedset.


Super Prev Next

The Function SHIFT

The function SHIFT can be used to shift a bit sequence up or down (left or right) by a specified number of positions within a bit field. The bit sequence is defined by the value of a packedset type, and the direction of shift is down (right) if the specified number is negative; otherwise the direction is up (left).

Static Semantics

A call of SHIFT shall have two actual parameters. The first parameter shall be an expression that is of a packedset type. The second parameter shall be an expression of a type with which the signed type is value parameter compatible.

The type of a call of SHIFT shall be the type of the first parameter.

An implementation may impose restrictions on the types that are allowed as the first parameter, save that SHIFT will at least accept a value of the type BITSET --- see ??? and The Bitset Type.

Dynamic Semantics

The value of the call SHIFT(val, num) shall be a packedset whose elements are such that the offset of their ordinal values from the ordinal value of the minimum value of the base type of the packedset, is given by the offset of the ordinal values of the elements of val increased by num if it is positive, or decreased by the absolute value of num if it is negative, provided that offset is not negative and is less than the number of values of the base type.

Note: With the interpretation of a value of type packedset as a sequence of bits, the shift operation can be considered as a zero-propagating logical-shift-up (left) operation or a logical-shift-down (right) operation, according to the value of the second operand, and within the bit field defined by the base type of the packedset.


Super Prev Next

The Function CAST

The function CAST can be used (as a type transfer function) to interpret a value of any type other than a numeric literal value as a value of another type.

Change: In Programming in Modula-2 , type transfer is effected by using a type identifier in the role of a function name, as exemplified by CARDINAL(IntExpr).

Static Semantics

A call of CAST shall have two actual parameters. The first parameter shall be a qualified identifier that denotes a type. The second shall be an expression whose type is not that of a numeric literal.

Note: The type of the expression that is the second parameter cannot be a numeric literal type, since such types do not have a defined storage size.

Dynamic Semantics

The value of the call CAST(Type, val) shall be given by a possibly unchecked conversion of val to the type Type in an implementation-defined manner satisfying the properties given below.

If the number of storage units that val occupies is the same as the number of storage units used by a variable of the type Type, the bit pattern representation of the result shall be the same as the bit pattern representation of val; otherwise the result and the value of val shall have the same bit pattern representation for a size that is equal to the smaller of the number of storage units.

An exception may occur and may be raised if a call of CAST causes an implementation-dependent alignment problem to occur, or if the resulting bit pattern is not a valid representation for a value of the target type.

properties

Let ARRAY [0 .. t] OF LOC correspond to Type where t = TSIZE(Type) - 1

Let ARRAY [0 .. v] OF LOC correspond to val where v = TSIZE(type of SourceExpression) - 1

The value of the call CAST(Type, val) shall be a value of type Type that when interpreted as an ARRAY [0 .. t] OF LOC has, for its first min elements, values that are the same as the first min elements of the value of val when interpreted as an ARRAY [0 .. v] OF LOC, where min is the minimum of t and v.

Note: If t > v, the values of remaining elements of the array from v+1 to t are not defined.

If a call of CAST causes an implementation-dependent alignment problem to occur, the following may result: non-mandatory-detection (invalid-alignment) handler

If the resulting bit pattern is not a valid representation for a value of the target type, the following may result: non-mandatory-detection (invalid-value) handler


Super Prev Next

The Function TSIZE

The function TSIZE can be used to ascertain the amount of storage that is used for a variable of a particular type. There are two versions of this function. The first has a type identifier as a parameter. It returns the size occupied by values of the type in terms of the smallest addressable unit of storage. This version is closely equivalent to the standard function SIZE --- see The Function SIZE. The second version has a record type identifier as the first parameter and one or more constant expressions as the remaining parameters; the values of these constant expressions must be associated with tags of variant components of that record type. It returns the size of the variant record in terms of the smallest addressable unit of storage that would be needed to store a value of the record type, with the tag fields having the values supplied in the call.

Static Semantics

The first, and possibly only parameter, shall be a qualified identifier denoting a type.

If the second and subsequent parameters are present, they shall be constant expressions, and the first parameter shall denote a record type with variant fields. The types of the constant expressions shall correspond to the types of the tag fields contained in the record type.

Note: Values may not be given for the tag fields of any record type embedded within the record type specified as the first parameter.

The type of a call of TSIZE shall be the Z-type.

Dynamic Semantics

The value of the call TSIZE(Type) shall be the size occupied by values of the type Type in terms of the smallest addressable unit of storage.

The value of the call TSIZE(Type, val ... ) shall be the size of the variant record in terms of the smallest addressable unit of storage that would be needed to store values of the record with the tag fields having the values val ....

Auxiliaries

annotations Check that the tag fields contained in a fields-list match the values given by an expression sequence.

annotations Check that the tag fields contained in a fields match the values given by an expression sequence.

annotations Check that the type of the expression in the sequence of tag values is assignment-compatible with the type of the corresponding tag component and the expression that corresponds to any tag field is a constant expression.

annotations Check the tag values in a sequence of values correspond to any tag fields in a variant component.

annotations Calculate the number of tags in a fields-list.

annotations Calculate the number of tags in a fields.

annotations Calculate the number of tags in a variant component of a record structure, selected by the value of the tag field.

annotations Calculates the number of tags in a variant component of a record structure.


Super Prev Next

The Module COROUTINES

The system module COROUTINES provides facilities for creating coroutines, for the explicit transfer of control between coroutines, and for the handling of interrupts by coroutine transfer. Programs that use the interrupt handling facilities may be non-portable since the type used to identify sources of interrupts is implementation-defined.


Super Prev Next

The Interface to COROUTINES

The interface to COROUTINES behaves as if the following were its definition module.

    DEFINITION MODULE COROUTINES;
    
    (* Facilities for coroutines and the handling of interrupts *)
    
    IMPORT SYSTEM;
    
    TYPE
    COROUTINE; (* Values of this type are created dynamically by NEWCOROUTINE
   		  and identify the coroutine in subsequent operations *)
    INTERRUPTSOURCE = <implementation-defined>;
    
    PROCEDURE NEWCOROUTINE (procBody: PROC; workspace: SYSTEM.ADDRESS; size: CARDINAL;
   			    VAR cr: COROUTINE[; initProtection: PROTECTION]);
      (* Creates a new coroutine whose body is given by procBody, and returns the identity
   	 of the coroutine in cr. workspace is a pointer to the work space allocated to
   	 the coroutine; size specifies the size of this workspace in terms of SYSTEM.LOC.
   	 initProtection is an optional parameter that specifies the initial protection
   	 level of the coroutine.
      *)
    
    PROCEDURE TRANSFER (VAR from: COROUTINE; to: COROUTINE);
      (* Returns the identity of the calling coroutine in from, and transfers control to
   	 the coroutine specified by to.
      *)
    
    PROCEDURE IOTRANSFER (VAR from: COROUTINE; to: COROUTINE);
      (* Returns the identity of the calling coroutine in from and transfers control to
   	 the coroutine specified by to. On occurrence of an interrupt, associated with the
   	 caller, control is transferred back to the caller, and the identity of the
   	 interrupted coroutine is returned in from. The calling coroutine must be
   	 associated with a source of interrupts.
      *)
    
    PROCEDURE ATTACH (source: INTERRUPTSOURCE);
      (* Associates the specified source of interrupts with the calling coroutine. *)
    
    PROCEDURE DETACH (source: INTERRUPTSOURCE);
      (* Dissociates the specified source of interrupts from the calling coroutine. *)
    
    PROCEDURE IsATTACHED (source: INTERRUPTSOURCE): BOOLEAN;
      (* Returns TRUE if and only if the specified source of interrupts is currently
   	 associated with a coroutine; otherwise returns FALSE.
      *)
    
    PROCEDURE HANDLER (source: INTERRUPTSOURCE): COROUTINE;
      (* Returns the coroutine, if any, that is associated with the source of interrupts.
   	 The result is undefined if IsATTACHED(source) = FALSE.
      *)
    
    PROCEDURE CURRENT (): COROUTINE;
      (* Returns the identity of the calling coroutine. *)
    
    PROCEDURE LISTEN (p: PROTECTION);
      (* Momentarily changes the protection of the calling coroutine to p. *)
    
    PROCEDURE PROT (): PROTECTION;
      (* Returns the protection of the calling coroutine. *)
    
    END COROUTINES.

Declaration Semantics

The identifiers available for import from the module COROUTINES shall be the type identifiers COROUTINE and INTERRUPTSOURCE, and the procedure identifiers NEWCOROUTINE, TRANSFER, IOTRANSFER, ATTACH, DETACH, IsATTACHED, HANDLER, CURRENT, LISTEN, and PROT.


Super Prev Next

The Types of COROUTINES

The module COROUTINES provides the coroutine type (denoted by COROUTINE) in terms of which coroutines are identi- fied, and the implementation-defined interrupt source type (denoted by INTERRUPTSOURCE) in terms of which sources of interrupts are identified.

Changes:

  1. The type PROCESS is called COROUTINE in this International Standard. The change from PROCESS to ADDRESS which occurred in the third edition of Programming in Modula-2 has not been adopted.

  2. A particular coroutine is identified by the same value of the coroutine type throughout the lifetime of that coroutine.

  3. The interrupt source type denoted by INTERRUPTSOURCE is not described in Programming in Modula-2.

Declaration Semantics

The type identifier COROUTINE shall denote the coroutine type, and the type identifier INTERRUPTSOURCE shall denote the implementation-defined interrupt source type.

The coroutine type shall be a system basic type, distinct from any other type, whose values identify a coroutine throughout the lifetime of that coroutine. The interrupt source type may be identical to a basic type or may be a predefined constructed type.

Note: In addition to use with the COROUTINES procedures NEWCOROUTINE, TRANSFER, IOTRANSFER, and CURRENT, as a system basic type, the operations of assignment and equality testing are applicable to the coroutine type --- see System Basic Types Relational Operations.

annotations Values of the coroutine type are represented by values of the type Coroutine in the formal model --- see ???. The INTERRUPTSOURCE-type is an implementation-defined type --- see Interrupt Handlers. Values of the interrupt source type are represented by values of the type Interrupt-source in the formal model --- see Interrupt Handlers.


Super Prev Next

The Procedures of COROUTINES

The module COROUTINES provides procedures for creating coroutines (NEWCOROUTINE), transferring between coroutines (TRANSFER and IOTRANSFER), for associating and dissociating interrupt sources and coroutines (ATTACH and DETACH), and for unmasking interrupts momentarily (LISTEN).


Super Prev Next

The Procedure ATTACH

The procedure ATTACH can be used to associate a coroutine with an interrupt source.

Static Semantics

A call of ATTACH shall have one actual parameter that shall be an expression that is of the interrupt source type.

Dynamic Semantics

The call ATTACH(source) shall associate the implementation-defined source of interrupts identified by source with the calling coroutine. If the source of interrupts is already associated with a coroutine, then that association shall first be broken.

Notes:

  1. More than one source of interrupts may be associated with a single coroutine.

  2. If interrupt requests are possible from the attached source, execution of the calling coroutine must first be protected from interrupts --- see Protected Modules. The protection of the calling coroutine must continue as long as interrupt requests are possible.


Super Prev Next

The Procedure DETACH

The procedure DETACH can be used to dissociate a coroutine from an interrupt source.

Static Semantics

A call of DETACH shall have one actual parameter that shall be an expression that is of the interrupt source type.

Dynamic Semantics

If the calling coroutine is associated with the source of interrupts identified by source, the call DETACH(source) shall dissociate that coroutine from that source.

Note: The call has no effect if the coroutine is not associated with source.


Super Prev Next

The Procedure IOTRANSFER

The procedure IOTRANSFER can be used to transfer control from one coroutine to another, pending an interrupt.

Static Semantics

A call of IOTRANSFER shall have two actual parameters. The first actual parameter shall designate a variable that is of the coroutine type. The second actual parameter shall be an expression that is of the coroutine type.

Change: In Programming in Modula-2, the association with the source of interrupts is made on each call of IOTRANSFER. In this International Standard, the association is made beforehand by a call or calls to ATTACH.

Dynamic Semantics

Provided that the calling coroutine is associated with a source of interrupts, the call IOTRANSFER(from,to) shall assign the identity of that coroutine to the variable from, and shall transfer control to the coroutine identified by to. An exception shall be raised if the calling coroutine is not associated with a source of interrupts.

On the granting of a subsequent interrupt, following a request from one of the sources associated with the calling coroutine, the coroutine that is then executing shall be suspended, the identity of that interrupted coroutine shall be assigned to from, and the calling coroutine shall be resumed.

Note: The coroutine that is transferred to by a call of IOTRANSFER, or one that is subsequently transferred to, must execute without protection from interrupts in order for an interrupt request to be granted.

annotations This operation models the interruption of a coroutine following an interrupt request from source. The source will be associated with a coroutine that has called IOTRANSFER. The operation is called by the coroutine that is executing when the interrupt request is granted.


Super Prev Next

The Procedure LISTEN

The procedure LISTEN can be used to alter the protection momentarily (usually lowering it so as to allow interrupt requests to be granted).

Static Semantics

A call of LISTEN shall have one parameter that is an expression that is of the protection type.

Dynamic Semantics

The call LISTEN(p) shall momentarily change the protection of the currently executing coroutine to p.

annotations If an interrupt request is granted, the effect is for a call of interrupt-occurs to be made.


Super Prev Next

The Procedure NEWCOROUTINE

The procedure NEWCOROUTINE can be used to create a new coroutine. Control can later be passed to this coroutine by calling the procedures TRANSFER or IOTRANSFER.

Static Semantics

A call of NEWCOROUTINE shall have four or five actual parameters.

The first actual parameter shall be an expression of a type with which the proc type is value-parameter-compatible.

Note: The value of the expression that is the first actual parameter in a call of NEWCOROUTINE must therefore be a parameterless procedure declared at declaration level 0.

The second actual parameter shall be an expression that is of a pointer type.

The third actual parameter shall be an expression of a type with which the unsigned type is value parameter compatible.

The fourth actual parameter shall designate a variable that is of the coroutine type.

The fifth actual parameter, if present, shall be an expression that is of the protection type.

CHANGE 1 --- In Programming in Modula-2 , no provision is made for the initial protection of a coroutine to be specified in a call of NEWCOROUTINE.

Dynamic Semantics

Provided that the value of size is not less than the minimum workspace size, the call

NEWCOROUTINE(procBody,workspace,size,cr,initProtection)

shall create a new coroutine and shall assign a value identifying the created coroutine to the variable cr. The initial protection of the coroutine shall be given by initProtection.

Provided that the value of size is not less than the minimum workspace size, the alternative call

NEWCOROUTINE(procBody,workspace,size,cr)

shall create a new coroutine and shall assign a value identifying the created coroutine to the variable cr. The initial protection of the coroutine shall be given by the current protection of the caller of NEWCOROUTINE.

The created coroutine shall be initialized in such a way that when control is first transferred to that coroutine, the procedure given by the value of procBody will be called as the body of that coroutine. The effect shall be for the caller of procBody to be in the state of normal execution with no block body as an exception handler. The effect shall also be for the caller of procBody to have a protection from interrupts given by the initial protection for the coroutine.

Change: Programming in Modula-2 does not deal with the initial protection of a new coroutine. This International Standard defines rules for determining that initial protection.

If a procedure called as the body of a coroutine attempts to return, an exception shall be raised.

Notes:

  1. If the procedure has local dynamic modules, these are finalized before the exception is raised.

  2. Since the effective caller has no exception handler, the raising of this exception is a termination event.

Clarification: Programming in Modula-2 states that a program terminates when control reaches the end of a proce- dure which is the body of a coroutine. This International Standard requires that an unhandled exception is raised on any attempt to return to the effective caller of the body of a dynamically created coroutine.

The storage for a variable occupying a number of locations given by the value of size and having an address given by the value of workspace shall be given to the coroutine as its workspace. The use made of this workspace shall be implementation-dependent.

The minimum workspace size shall be implementation-defined. An exception shall be raised if the value of size is smaller than the minimum workspace size.

Notes:

  1. In addition to coroutines created by NEWCOROUTINE, there is an original coroutine, or main coroutine, by which the static modules of the program are initialized. The initial protection of the main coroutine is implementation-defined and the workspace is supplied by the implementation.

  2. The creation of a coroutine does not cause a transfer of control.

  3. To ensure that no interrupts are allowed on the initial transfer to a coroutine, it is not sufficient for the procedure given as the value of the procBody parameter in a call of NEWCOROUTINE to be a protected procedure with a protection of UNINTERRUPTIBLE. That protection will only be established when the procedure is called (automatically) in the new coroutine.

  4. A call of NEWCOROUTINE does not check if the given workspace overlaps with that of other coroutines; provided that a variable remains in existence until the end of program execution, the storage for that variable may be given to a coroutine for use as its workspace.

  5. The giving of coroutine workspace allows the possibility of aliasing. By accessing the workspace through the variable whose storage is given in the call of NEWCOROUTINE it may be possible for a program to alter the values of coroutine variables or to affect control information such as procedure return addresses. Two consequences that follow are: a) Since the use of coroutine workspace is implementation-dependent, no meaning is given to such a program by this International Standard. b) Depending on the implementation, it may not be possible to perform a static check that a for loop control variable in a coroutine is not threatened in this way.

  6. Workspace overflow is checked during coroutine execution. The check may be carried out when a procedure is activated when storage is allocated for its local variables (see Operations to Allocate and Deallocate Storage)


Super Prev Next

The Procedure TRANSFER

The procedure TRANSFER can be used to transfer control from one coroutine to another.

Static Semantics

A call of TRANSFER shall have two actual parameters. The first actual parameter shall designate a variable that is of the coroutine type. The second actual parameter shall be an expression that is of the coroutine type.

Dynamic Semantics

The call TRANSFER(from,to) shall assign the identity of the calling coroutine to the variable from, and shall transfer control to the coroutine identified by to.

Note: If at the end of its previous execution (if any) the coroutine identified by to had transferred control to another by a call of IOTRANSFER, it will appear as if an interrupt has occurred.


Super Prev Next

The Functions of COROUTINES

The module COROUTINES provides functions for determining the identity of the current coroutine (CURRENT), the protection of the current coroutine (PROT), and for determining whether and which interrupt sources are associated with coroutines (HANDLER and IsATTACHED).


Super Prev Next

The Function HANDLER

The function HANDLER can be used to identify which coroutine is attached to a specified interrupt source.

Static Semantics

A call of HANDLER shall have one actual parameter that is an expression that is of the interrupt source type. The type of a call of HANDLER shall be the coroutine type.

Dynamic Semantics

The value of the call HANDLER(source) shall be the identity of the coroutine, if any, that is associated with the source of interrupts given by source. An exception shall occur and may be raised if that source is not currently associated with any coroutine.


Super Prev Next

The Function IsATTACHED

The function IsATTACHED can be used to determine whether a coroutine is attached to a specified interrupt source.

Static Semantics

A call of IsATTACHED shall have one actual parameter that is an expression that is of the interrupt source type. The type of a call of IsATTACHED shall be the coroutine type.

Dynamic Semantics

The value of the call IsATTACHED(source) shall be true if any coroutine is associated with the source of interrupts denoted by source, and false otherwise.


Super Prev Next

The Function CURRENT

The function CURRENT can be used to determine the identity of the currently executing coroutine.

Static Semantics

A call of CURRENT shall have no actual parameters. The type of a call of CURRENT shall be the coroutine type.

Dynamic Semantics

The value of the call CURRENT() shall be the identity of the calling coroutine.


Super Prev Next

The Function PROT

The function PROT can be used to obtain the protection of the currently executing coroutine, that is, the extent to which interrupts are currently masked.

Static Semantics

A call of PROT shall have no actual parameters. The type of a call of PROT shall be the protection type.

Dynamic Semantics

The value of the call PROT() shall be the value of the current protection against interrupts.


Super Prev Next

The Module EXCEPTIONS

The system module EXCEPTIONS provides low-level facilities for identifying the source of user-defined exceptions, for reporting their occurrence, and for making enquiries concerning the execution state of the current coroutine.

User-defined exceptions are identified uniquely by an exception source/number pair. When the source of a user-defined exception is a separate module, that module may encapsulate the exception source value, thus preventing the defined exceptions of the module from being raised directly by other sources. The exception number may also be mapped to values of an enumeration type defined by the module. An example of the use of these facilities is given in The Use of EXCEPTIONS.


Super Prev Next

The Interface to EXCEPTIONS

The interface to EXCEPTIONS behaves as if the following were its definition module.

    DEFINITION MODULE EXCEPTIONS;
    
    (* Provides facilities for raising user exceptions
    and for making enquiries concerning the current execution state.
    *)
    
    TYPE
      ExceptionSource;		 (* values of this type are used within library modules to
  				    identify the source of raised exceptions *)
      ExceptionNumber = CARDINAL;
    
    PROCEDURE AllocateSource (VAR newSource: ExceptionSource);
      (* Allocates a unique value of type ExceptionSource *)
    
    PROCEDURE RAISE (source: ExceptionSource; number: ExceptionNumber; message: ARRAY OF CHAR);
      (* Associates the given values of source, number and message with the current context
   	 and raises an exception.
      *)
    
    PROCEDURE CurrentNumber (source: ExceptionSource): ExceptionNumber;
      (* If the current coroutine is in the exceptional execution state because of the raising
   	 of an exception from source, returns the corresponding number, and otherwise
   	 raises an exception.
      *)
    
    PROCEDURE GetMessage (VAR text: ARRAY OF CHAR);
      (* If the current coroutine is in the exceptional execution state, returns the possibly
  	  truncated string associated with the current context.
   	 Otherwise, in normal execution state, returns the empty string.
      *)
    
    PROCEDURE IsCurrentSource (source: ExceptionSource): BOOLEAN;
      (* If the current coroutine is in the exceptional execution state because of the raising
   	 of an exception from source, returns TRUE, and otherwise returns FALSE.
      *)
    
    PROCEDURE IsExceptionalExecution (): BOOLEAN;
      (* If the current coroutine is in the exceptional execution state because of the raising
   	 of an exception, returns TRUE, and otherwise returns FALSE.
      *)
    
    END EXCEPTIONS.

Declaration Semantics

The identifiers available for import from the module EXCEPTIONS shall be the type identifiers ExceptionSource and ExceptionNumber, and the procedure identifiers AllocateSource, RAISE, CurrentNumber, GetMessage, IsCurrentSource, and IsExceptionalExecution.


Super Prev Next

The Types of EXCEPTIONS

The module EXCEPTIONS provides the exception source type (denoted by ExceptionSource) in terms of which the sources of user-defined exceptions are identified, and the exception number type (denoted by ExceptionNumber) in terms of which exceptions from a particular source are identified.

Declaration Semantics

The type identifier ExceptionSource shall denote the exception source type, and the type identifier ExceptionNumber shall denote the whole number type.

Note: In addition to use with the EXCEPTIONS procedures AllocateSource, RAISE, CurrentNumber, and IsCurrentSource, as a system basic type, the operations of assignment and equality testing are applicable to the ex- ception source type --- see System Basic Types Relational Operations.

annotations Values of the exception source type are represented by values of the type Exception-source in the formal model --- see Exceptions.


Super Prev Next

The Procedures of EXCEPTIONS

The module EXCEPTIONS provides procedures for allocating a unique value of the exception source type (AllocateSource), raising a user-defined exception (RAISE), and obtaining the message associated with the current exception context (GetMessage).


Super Prev Next

The Procedure AllocateSource

The procedure AllocateSource can be used as a server for previously unallocated values of the type ExceptionSource. Values of this type are used to identify a source of exceptions, such as a library module, when an exception is raised with the procedure RAISE. The procedure is normally called once during initialization of a separate module, and the resulting value is then used in all calls of RAISE for exceptions that may be handled by clients of the module.

Static Semantics

A call of AllocateSource shall have one actual parameter which shall be a variable that is of the exception source type.

Dynamic Semantics

The call AllocateSource(newSource) shall allocate a value of the exception source type that is unique within the program and shall assign this value to the variable newSource. If a unique value cannot be allocated, an exception shall be raised.


Super Prev Next

The Procedure RAISE

The procedure RAISE can be used by a specified source to raise a user-defined exception.

The effect of raising an exception is the same for exceptions raised by the language implementation as for exceptions raised by explicit use of the procedure RAISE --- see Language Exceptions. Thus the raising of a user-defined exception is a termination event (see Program Termination) unless the exception is handled by an exception body (see Block Bodies and Exception Handling).

Static Semantics

A call of RAISE shall have three actual parameters. The first actual parameter shall be an expression that is of the exception source type, the second actual parameter shall be an expression of a type with which the unsigned type is value parameter compatible, and the third actual parameter shall be an expression of a type with which an open array of CHAR is value parameter compatible.

Dynamic Semantics

The call of RAISE(source, number, message) shall set the current exception source to the value of source, the current exception number to the value of number, and the current exception message to the value of message interpreted as a character string and limited to an implementation-defined length.


Super Prev Next

The Procedure GetMessage

The procedure GetMessage can be used to obtain the message passed when an exception is raised. This may give further information about the nature of the exception for use by the program, or in the construction of other messages.

Static Semantics

A call of GetMessage shall have one actual parameter which shall be an array variable having components of the character type.

Dynamic Semantics

The call GetMessage(text) shall assign a string value to the variable text. If the calling coroutine is in the state of exceptional execution, the string value shall be formed from the message stored when the corresponding exception was raised, but with a length limited by the capacity of text.


Super Prev Next

The Functions of EXCEPTIONS

The module EXCEPTIONS provides functions for determining the exception number for the current user-defined excep- tion (CurrentNumber), whether a user-defined exception has been raised by a given source (IsCurrentSource), and whether the execution state is that of exceptional execution (IsExceptionalExecution).


Super Prev Next

The Function CurrentNumber

The function CurrentNumber can be used to obtain the exception number for the current user-defined exception that has been raised.

Static Semantics

A call of CurrentNumber shall have one actual parameter which shall be an expression of the exception source type. The type of a call of CurrentNumber shall be the unsigned type.

Dynamic Semantics

If the calling coroutine is in the state of exceptional execution because of the raising of a user-defined exception from source, the value of the call CurrentNumber(source) shall be the number that is associated with the raised exception; otherwise an exception shall be raised.


Super Prev Next

The Function IsCurrentSource

The function IsCurrentSource can be used to test whether the calling coroutine is in the state of exceptional execution because of the raising of a user-defined exception from a specified source.

Static Semantics

A call of IsCurrentSource shall have one actual parameter which shall be an expression of the exception source type. The type of a call of IsCurrentSource shall be the Boolean type.

Dynamic Semantics

If the calling coroutine is in the state of exceptional execution because of the raising of a user-defined exception from source, the value of the call IsCurrentSource(source) shall be true ; otherwise the value shall be false .


Super Prev Next

The Function IsExceptionalExecution

The function IsExceptionalExecution can be used to test whether the calling coroutine is in the state of exceptional execution.

Static Semantics

A call of IsExceptionalExecution shall have no actual parameters. The type of a call of IsExceptionalExecution shall be the Boolean type.

Dynamic Semantics

If the calling coroutine is in the state of exceptional execution, the value of the call IsExceptionalExecution() shall be true ; otherwise the value shall be false .


Super Prev Next

The Use of EXCEPTIONS

The example given below shows the use of EXCEPTIONS in the implementation of a separate module that provides facilities to allow a general user-defined exception to be raised and identified.

Example: A general user exception separate module.

    DEFINITION MODULE GeneralUserExceptions;

    (* Provides facilities for general user-defined exceptions *)

    TYPE
      GeneralExceptions = (problem, disaster);

    PROCEDURE RaiseGeneralException (exception: GeneralExceptions; text: ARRAY OF CHAR);
      (* Raises exception using text as the associated message *)

    PROCEDURE IsGeneralException (): BOOLEAN;
      (* Returns TRUE if the current coroutine is in the exceptional execution state
         because of the raising of an exception from GeneralExceptions;
         otherwise returns FALSE.
      *)

    PROCEDURE GeneralException(): GeneralExceptions;
      (* If the current coroutine is in the exceptional execution state because of the
         raising of an exception from GeneralExceptions, returns the corresponding
         enumeration value, and otherwise raises an exception.
      *)
    
    END GeneralUserExceptions.

    
    IMPLEMENTATION MODULE GeneralUserExceptions;

    IMPORT EXCEPTIONS;
    
    VAR
      generalSource: EXCEPTIONS.ExceptionSource;
    
    PROCEDURE RaiseGeneralException (exception: GeneralExceptions; text: ARRAY OF CHAR);
      BEGIN
        EXCEPTIONS.RAISE(generalSource, ORD(exception), text)
      END RaiseGeneralException;

    PROCEDURE IsGeneralException (): BOOLEAN;
      BEGIN
        RETURN EXCEPTIONS.IsCurrentSource(generalSource)
      END IsGeneralException;
    
    PROCEDURE GeneralException(): GeneralExceptions;
      BEGIN
        RETURN VAL(GeneralExceptions, EXCEPTIONS.CurrentNumber(generalSource))
      END GeneralException;

    BEGIN
      EXCEPTIONS.AllocateSource(generalSource)
    END GeneralUserExceptions.


Super Prev Next

The Module TERMINATION

The system module TERMINATION provides facilities for a program to enquire whether a termination event has occurred --- see Program Termination.


Super Prev Next

The Interface to TERMINATION

The interface to TERMINATION behaves as if the following were its definition module.

    DEFINITION MODULE TERMINATION;
    
    (* Provides facilities for enquiries concerning the occurrence of termination events. *)
    
    PROCEDURE IsTerminating (): BOOLEAN ;
      (* Returns TRUE if any coroutine has started program termination and FALSE otherwise. *)
    
    PROCEDURE HasHalted (): BOOLEAN ;
      (* Returns TRUE if a call to HALT has been made and FALSE otherwise. *)
    
    END TERMINATION.

Declaration Semantics

The identifiers available for import from the module TERMINATION shall be the procedure identifiers IsTerminating, and HasHalted.


Super Prev Next

The Functions of TERMINATION

The module TERMINATION provides the function procedures IsTerminating and HasHalted for enquiries concerning the occurrence of termination events.


Super Prev Next

The Function IsTerminating

The function IsTerminating can be used to determine whether any coroutine has started program termination.

Static Semantics

A call of IsTerminating shall have no parameters. The type of a call of IsTerminating shall be the Boolean type.

Dynamic Semantics

The value of the call IsTerminating() shall be true if any coroutine has started program termination and shall be false otherwise.


Super Prev Next

The Function HasHalted

The function HasHalted can be used to determine whether a call has been made to HALT.

Static Semantics

A call of HasHalted shall have no parameters. The type of a call of HasHalted shall be the Boolean type.

Dynamic Semantics

The value of the call HasHalted() shall be true if a call to HALT has been made and shall be false otherwise.


Super Prev Next

The Module M2EXCEPTION

The system module M2EXCEPTION provides facilities for identifying language exceptions that have been raised.

The language (which includes the system modules) is regarded as one source of exceptions. Similar facilities are defined by library modules that are sources of user-defined exceptions --- see, for example, ???.


Super Prev Next

The Interface to M2EXCEPTION

The interface to M2EXCEPTION behaves as if the following were its definition module.

    DEFINITION MODULE M2EXCEPTION;
    
    (* Provides facilities for identifying language exceptions *)
    
    TYPE
      M2Exceptions =
        (indexException, rangeException, caseSelectException, invalidLocation,
    	 functionException, wholeValueException, wholeDivException, realValueException,
    	 realDivException, complexValueException, complexDivException, protException,
    	 sysException, coException, exException
        );
    
    PROCEDURE M2Exception (): M2Exceptions;
      (* If the current coroutine is in the exceptional execution state because of the raising
   	 of a language exception, returns the corresponding enumeration value, and otherwise
   	 raises an exception.
      *)
    
    PROCEDURE IsM2Exception (): BOOLEAN;
      (* If the current coroutine is in the exceptional execution state because of the raising
   	 of a language exception, returns TRUE, and otherwise returns FALSE.
      *)
    
    END M2EXCEPTION.

Declaration Semantics

The identifiers available for import from the module M2EXCEPTION shall be the enumeration type identifier M2Exceptions, the corresponding enumeration value identifiers, and the procedure identifiers M2Exception and IsM2Exception.


Super Prev Next

The Types of M2EXCEPTION

The module M2EXCEPTION provides the m2exceptions enumeration type (denoted by M2Exceptions) in terms of which the language exceptions are raised. The enumeration values represent aggregations of the exceptions detected by the formal model --- see Aggregation and Raising of Language Exceptions.

Declaration Semantics

The type identifier M2Exceptions shall denote the m2exceptions type which shall be an enumeration type correspond- ing to the following enumeration:

    (indexException,	 rangeException,	 caseSelectException,	 invalidLocation,
    functionException,	 wholeValueException,	 wholeDivException,	 realValueException,
    realDivException,	 complexValueException,	 complexDivException,	 protException,
    sysException,	 coException,		 exException
    );

annotations Values of the m2exceptions type are represented by values of the type Exception-value in the formal model --- see Exceptions.


Super Prev Next

The Functions of M2EXCEPTION

The module M2EXCEPTION provides the function procedures M2Exception and IsM2Exception for enquiries concerning language exceptions.


Super Prev Next

The Function M2Exception

The function M2Exception can be used to determine the language exception that has been raised.

Static Semantics

A call of M2Exception shall have no actual parameters. The type of a call of M2Exception shall be the m2exceptions type.

Dynamic Semantics

If the calling coroutine is in state of exceptional execution because of the raising of a language exeption, the value of the call M2Exception() shall be the value of type M2Exceptions that is associated with the raised exception; otherwise an exception shall be raised.


Super Prev Next

The Function IsM2Exception

The function IsM2Exception can be used to test whether the calling coroutine is in the state of exceptional execution because of the raising of a language exception.

Static Semantics

A call of IsM2Exception shall have no parameters. The type of a call of IsM2Exception shall be the Boolean type.

Dynamic Semantics

If the calling coroutine is in the state of exceptional execution because of the raising of a language exception, the value of the call IsM2Exception() shall be true ; otherwise the value shall be false .


Super Prev Next

Language Exceptions

The exceptions defined by the dynamic semantics of the language, which includes the system modules, are categorized into those which an implementation is required to detect and those which an implementation is not required to detect. Detected exceptions are raised by the implementation and constitute a termination event (see Program Termination) unless the exception is handled by an exception body (see Block Bodies and Exception Handling). Exceptions that are distinguished in the dynamic semantics are aggregated into a smaller number of identified exceptions for the purposes of exception handling.

An implementation must define which of the exceptions whose detection is not required are in fact detected in some or all circumstances. It need not define the circumstances in which such exceptions are detected. If such an exception occurs, but is not detected, this International Standard gives no meaning to the program --- see ???.


Super Prev Next

Exceptions whose detection is required

Dynamic Semantics

annotations Construct an appropriate message based on the exception and the current state, and construct an exception context in which to raise the exception.


Super Prev Next

Exceptions whose detection is not required

Dynamic Semantics

annotations If the exception is detected by the implementation, construct an appropriate message based on the exception, the environment and the current state, and construct an exception context in which to raise the exception. Otherwise, the behaviour is implementation-dependent.

annotations The result is true if the exception is actually detected and otherwise false .


Super Prev Next

Messages Associated with Language Exceptions

Dynamic Semantics

The character string associated with each of the exceptions that may be raised as specified in Chapters The Language and System Modules shall be implementation-defined.

Note: The character string associated with a raised exception may be accessed using the GetMessage procedure --- see The Procedure GetMessage.

annotations Using the exception and the current state, construct an appropriate message for a language exception context.


Super Prev Next

Aggregation and Raising of Language Exceptions

annotations Build a language exception context from: an enumeration value defined by the mapping exception-value ; and the message. Raise an exception that has the exception context.