Previous Table of Contents Next


6.2.9. Debugging Facilities

6.2.9.1. Diagnostic Output

The first thing most programmers do when faced with a problem in a program is to add diagnostic output. In Icon, this takes the form of write() expressions. However, write() can handle only values that are strings or convertible to strings.

For other kinds of values, the function image(x) is particularly useful. It produces a string representation of x for all types of values. In addition, the type can be determined from the value image() produces.

For numeric values, image() simply produces a string showing the value. For example,

    write(image(137))

writes 137 and

    write(image(–23.3))

writes –23.3.

For strings and csets, image() produces the value with enclosing double and single quotation marks, respectively. For example,

    write(image(“Hello world”))

writes “Hello world”, and

    write(image(‘aeiou’))

writes ‘aeiou’. Because image() encloses strings and csets in quotation marks, such values can be told from other values with corresponding characters. For example,

    write(image(“137”))

writes “137”, not 137.

For structure types, image() produces a string with the type name, the serial number of the structure, and its size. The form of the string produced is illustrated by

    write([2, 3, 5, 7, 11, 13])

which writes list_21(6), assuming this is the twenty-first list created during program execution.

Some values produced by image() are in the form of keywords that produce the value. For example,

    write(image())

writes &null.

6.2.9.2. Error Messages

Icon detects errors, according to the phases of program processing:

  Preprocessing
  Compilation
  Linking
  Execution

An error produces a message, which is written to standard error output. An error in one phase prevents program processing from proceeding to the next phase.

Preprocessor Errors

Preprocessor error messages are largely self-explanatory. For example, in

    $define “constants.icn”

if the file constants.icn does not exist, the error message is

    $include: invalid file name

Syntax Errors

Syntax errors are detected during compilation. Some error messages are self-explanatory, such as

    invalid context for next

which simply means that a next expression occurs in a context in which there is no enclosing loop.

Other error messages are less informative, largely because an expression that is valid at the time it occurs may become invalid at a later point in the program, at which time the source of the error is no longer known. An example is

    procedure parse()                                       # 1
        every 1 to count do                                 # 2
          s := goal                                         # 3
        repeat {                                            # 4
          if not upto(&ucase,s) then break                  # 5
          if not(s ? replace(!xlist)) then break next       # 6
          until s ?:= replace(?xlist)                       # 7
          }                                                 # 8
        write(s)                                            # 9
        }                                                   # 10
    end                                                     # 11

Here, the error is a missing left (opening) brace following the do on line 2. The subsequent code is syntactically correct until the end of the procedure is reached. At that point, the message

    … Line 10 # “}”: missing semicolon or operator

occurs.

The use of a consistent indentation style not only makes it easier to find the source of such errors but also to avoid them in the first place.

Linking Errors

Only one error message can occur during linking:

    inconsistent redeclaration

This error occurs if two procedures have the same name, a procedure and a record have the same name, and so on. (It is legal to have a global declaration name that is the same as the name of a procedure or record.)

Runtime Errors

Many errors manifest themselves as errors during program execution. When such a runtime error occurs, there is an error message, a traceback of the procedure calls leading to the place of the error, and the offending expression. Runtime error messages are numbered and divided into categories, depending on the nature of the error.

Error messages with 100 numbers indicate an invalid type or form. An example is

    103 string expected

Error messages with 200 numbers indicate an invalid value or computation, as in

    201  division by zero

Error messages with 300 numbers indicate a capacity has been exceeded. An example is

    301  evaluation stack overflow

This error usually results from excessively deep recursion in procedure calls.

An example of error reporting and the traceback as the result of a runtime error is

    Run-time error 106
    File recorder.icn; Line 32
    procedure or integer expected
    offending value: &null
    Traceback:
       main()
       &null(“Summary information …”) from line 32 in recorder.icn

Such error termination messages generally are self-explanatory. For example, the error that resulted in the preceding output occurred in the main procedure. The offending expression was an invocation, but instead of a function, procedure, or integer, there was an attempt to apply the null value. This often is the result of a misspelling. In the program in which this error occurred, two letters were transposed, resulting in wirte instead of write.


Previous Table of Contents Next