Errors and debugging

Exceptions are Python exceptions. Tracebacks show Koskari source lines.

Where an error comes from

Is there a SyntaxError and a runtime error, as in Python?

Yes, with a third between them. A reader error, ReaderSyntaxError, means the text could not be read: unbalanced parentheses, a bad block. A compile error, CompilerError and its subclasses, means the form read but its shape is wrong for the special form at its head. Neither has run anything. A runtime error is a Python exception raised while running, from your code or from a library you called.

>>> ( 1 2 ]

is a reader error,

>>> (var)

is a compile error, and

>>> (/ 1 0)

raises ZeroDivisionError.

Handling

Python

try:
    risky()
except ValueError as e:
    handle(e)
else:
    on_success()
finally:
    cleanup()

Koskari

try:
  (risky)
except [ValueError as: e]:
  (handle e)
else:
  (on-success)
finally:
  (cleanup)

Python

try:
    risky()
except:
    handle_anything()

Koskari

try:
  (risky)
except:
  (handle-anything)

Is try a statement?

An expression. Its value is the body’s value, or the handler’s when one ran, so var result: try: ... is a common shape.

Python

raise ValueError("bad input")
raise

Koskari

raise (ValueError "bad input")
raise

Tracebacks

What does a traceback show?

Koskari frames with their source lines, interleaved with Python frames where the call crossed into Python, the way a C extension appears in a Python stack. The REPL trims its own frames; --repl-full-trace shows them.

Does a handler see those frames?

Yes. Inside an except clause, e.__traceback__ holds an entry for every Koskari frame the exception crossed and for the frame of the handler, at the line that was executing, so traceback.format_exc(), logging.exception(...) and raise Other() from e show Koskari source lines. An exception that escapes to Python carries the same entries.

Finding the problem

What is the order of attack?

  1. Read the exception class and the first message line.

  2. Reproduce with one form at the REPL before touching the file.

  3. For a macro surprise, (macroexpand-1 'form) shows one step of expansion.

  4. (help name) shows what a name is bound to and its documentation.

Python

print("here", x, x.value)

Koskari

print "here" x x.value

Run it

At the REPL:

>>> try:
...   (/ 1 0)
... except [ZeroDivisionError]:
...   "caught"
"caught"

The exception classes for each phase are in the Error guide.