                        IMP Signal Mechanism Definition

                Document_IMP_Signals Version 2.1.0 (2-APR-1985)

                      Draft for circulation; return to IAY

                               Copyright (c) 1984
                               Lattice Logic Ltd
                                 9 Wemyss Place
                               Edinburgh EH3 6DH

       This document is a simplified proposal for the core specification of
    the IMP signal facility; it is based on thoughts and discussions
    prompted by the first version of "Document_IMP_Signals".

       This paper makes no attempt to define the syntax and semantics of the
    event mechanism itself, leaving this to the proposed more formal
    revision of the IMP language manual, but rather concentrates on the
    three questions:

      1. What information should be contained in the global record
         describing an event?

      2. What events should be predefined by the language?

      3. How can separately compiled IMP modules cooperate via events?

    Changes to the EVENT record

       The current format of the global record accessed via the external
    EVENT record is:

          record format   EVENT FM (   -
             integer      EVENT,
                          SUB,
                          EXTRA,
             string(255)  MESSAGE  )

       This format allows some user information about the event (EXTRA and
    MESSAGE) to be propagated with the signal but is not a general facility.
    To avoid user programs having to declare extra "parallel" event
    descriptors, the EVENT record should be generalised to allow the
    procedure which signals an event to pass an arbitrary amount of
    parameter information.  Also, implementations may wish to provide
    system-specific extra information about the event.  It would be tidier
    and user programs would be more clearly marked as system-dependent if
    such information were grouped into a sub-record of EVENT.

       One concrete proposal is as follows:

       record format   SYS EVENT FM ( {is implementation defined} )

       const  integer  MAX EVENT PARAM

       record format   EVENT PARAM FM ( string(*) name S  or
                                        integer I         or
                                        long real R       or
                                        record(*) name X )

       record(EVENT PARAM FM) array Param(1:MAX EVENT PARAM)

       record format   EVENT FM (   -
          integer                EVENT,
                                 SUB,
                                 EXTRA,
          string(255)            MESSAGE,
          record(SYS EVENT FM)   SYSTEM,
          record(*) name         USER,      {extra user-defined information}
          record(EVENT PARAM FM) array PARAM(1:MAX EVENT PARAM) )

       The contents of SYSTEM would be implementation-defined but the record
    format SYS EVENT FM and the field EVENT_SYSTEM would always exist.

       The value of MAX EVENT PARAM would be implementation-dependent, but
    would always be at least (say) five.

       The USER record pointer would make the event record format
    user-extensible in arbitrary ways.  It would be used in cases where it
    was inappropriate to represent the required event parameter information
    as integer values or pointers to character string values.

       Please make suggestions for simplifying or extending the format of
    the EVENT record.

    Predefined events

       The following identifiers for events should be predefined on all
    implementations of IMP, i.e. should be part of the core library.  These
    events must be signalled by all implementations in the circumstances
    indicated.

       [ADC: The exact circumstances are not yet written down.  This will
    get done if this proposal meets with general approval.]

       Signalling or trapping events by number should be strongly
    discouraged.  Numeric equivalences are given for some identifiers for
    compatibility with previous implementations of IMP.

       constant integer PROGRAM STOP = 0
       constant integer OVERFLOW = 1
       constant integer STORE EXCEEDED = 2
       constant integer CONVERSION ERROR = 4
       constant integer ARGUMENT ERROR = 5
       constant integer RANGE ERROR = 6
       constant integer STRING RESOLUTION FAILS = 7
       constant integer UNDEFINED VALUE = 8
       constant integer INPUT ENDED = 9
       constant integer IO ERROR = 10
       constant integer JUMP OUT = 11
       constant integer USER EVENT = 12 {See next section, "modular programs"}

            [IAY requested that the numeric equivalences for the last three
         events be added; this has been done].

            [IAY: Suggest that event numbers 13..15 be 'reserved'.  Note
         that this would make some existing programs illegal].

    Events and modular programs

       Separately compiled packages of external procedures (program modules)
    may wish to use the IMP event mechanism to signal a range of error
    conditions to calling procedures.  Since event numbers must be known at
    compile-time, and there are only sixteen of them anyway, it is not
    possible to give each package its own unique event number.

       To work round this problem, a single event, USER EVENT above, is
    dedicated for use by all such packages.  A unique sub-event number must
    be claimed by a package at runtime (during its initialisation phase)

    from a central pool maintained by the IMP runtime library.  The
    package's subevent number is made available to its callers via an
    external integer variable.  The EVENT_EXTRA field is used for further
    discrimination between the various events which may be signalled by that
    package.

       The IMP runtime library procedure which dispenses subevent numbers to
    be used with the event USER EVENT would be as follows:

       integer function spec FACILITY CODE ( string(255) FAC NAME )

       [RMM: why not "FACILITY NAME"?]

       [ADC: because I think the name should indicate the returned value.  I
    myself would now prefer the name "MODULE NUMBER" or "MODULE CODE".]

       The FAC NAME supplied to FACILITY CODE is a text string which is the
    identifier of the package (e.g. "stack_manager", "I/O-Library" etc).
    The value returned by FACILITY CODE is a module number, 'n', which can
    be used later in statements of the form:

          signal USER EVENT, n, m

       Where 'm' is a number indicating one of the events detected by this
    package. 'm' defaults to zero if not specified.

       As an example, consider a small package maintaining a stack data
    structure (yawn), which can signal two error conditions: stack overflow
    and stack underflow.

       Note that as this scheme requires more runtime checking of event
    numbers by event handlers, the following code presupposes the existance
    of a core IMP library procedure RESIGNAL which will re-signal the
    current event as described by the event record.

          !
          ! Package specification  (STACK.INC)
          !
          external routine spec  INITIALISE STACK
          external routine spec  PUSH ( real X )
          external routine spec  POP  ( real name X )

          !
          ! Event identifier
          !
          external integer spec  STACK ERROR
          constant integer       STACK OVERFLOW = 1     { type of STACK ERROR }
          constant integer       STACK UNDERFLOW = 2

          end of file

          !
          ! STACK package body
          !
          !
          ! Private data objects
          !
          constant integer MAX STACK = 100
          own integer SP = 0
          own real array STACK(1:MAX STACK)

          !
          ! Externally visible data objects
          !
          external integer STACK ERROR

          !
          ! Externally visible operations
          !
          external routine INITIALISE STACK
             SP = 0
             STACK ERROR = FACILITY CODE("stack_manager")
          end

          external routine PUSH ( real X )
             SP = SP + 1
             signal USER EVENT, STACK ERROR, STACK OVERFLOW  -
                    unless 0 < SP <= MAX STACK
             STACK(SP) = X
          end

          external routine POP ( real name X )
             signal USER EVENT, STACK ERROR, STACK UNDERFLOW  -
                    unless 0 < SP <= MAX STACK
             X = STACK(SP)
             SP = SP - 1
          end

          end of file

          !
          ! Calling program (uses STACK to reverse a list of numbers)
          !
          begin
             include "STACK.INC"    { access specifications }
             real X

             on INPUT ENDED start
                begin
                   integer J
                   real VAL
                   on USER EVENT start
                      if EVENT_SUB = STACK ERROR and
                         EVENT_EXTRA = STACK UNDERFLOW start
                         return     { from begin...end block }
                      else
                         RESIGNAL   { some other sort of error -- propagates }
                      finish
                   else
                      cycle         { till stack underflows }

                         POP(VAL)
                         PRINT(VAL, 5, 3)
                         NEW LINE
                      repeat
                   finish
                end
             else
                INITIALISE STACK
                cycle               { terminates when INPUT ENDED }
                   READ(X)
                   PUSH(X)
                repeat
             finish
          end