Handling a Division by Zero Exception - LucPrestin/Hidden-Modularity GitHub Wiki
Description
Handling exceptions is an essential part of robust programming. At the same time, throwing and catching exceptions is a complex part of the system. To reduce as much complexity as possible, in order to still be able to keep track of the whole, the handling of a division by zero is a good starting point.
Code
^ TDBCursor traceForBlock: [
[2 / 0] on: ZeroDivide do: [:ex | ex resume: 0]
]
Hypotheses
- The handling of division by zero is quite strongly confined to the context of numbers. Accordingly, we expect few involved classes. Most notably, the exception itself, the method context likely to be used for tracking, and the numbers themselves.
on:do:
sets a marker on the stack to know whether an exception has already been handled. This should also be visible in the trace.
Evaluation
Node size based on incoming and outgoing edges | Node size additionally under consideration of edge weights |
Hypothesis 1: classes involved
Broadly speaking, the hypothesis seems to be correct. There are a few classes involved, the largest of which belong to the exception control flow or are numbers. Unexpected is the UndefinedObject
here.
Hypothese 2: Stack Marker
No meaningful statement can be made here based on the Communicator Graph. It has no explicit class that encapsulates the access to the stack. We could get a more detailed impression of this via the Communicator Method Category Graph:
Communicator Graph | Communicator Method Category Graph |
Among other things, there is a category Context: private-exceptions
. If we have a look over in Squeak we will find the method Context>>handleSignal:
with the following content:
handleSignal: exception
"Sent to handler (on:do:) contexts only.
Execute the handler action block"
| val |
<primitive: 199> "just a marker, fail and execute the following"
exception privHandlerContext: self contextTag.
self deactivateHandler. "Prevent re-entering the action block, unless it is explicitely rearmed"
val := [self fireHandlerActionForSignal: exception] ensure: [self reactivateHandler].
self return: val "return from self if not otherwise directed in handle block"
This is where the pieces come together. First, the method comment indicates that it is specifically a method for on:do:
, which is what we were looking for. Then the next comment marks a primitive that sets a marker. This could be the marker we are looking for.
Even though we couldn't see the marker directly, the Communicator Method Category Graph still put us on the right track.