5 Execution Control

This chapter describes the various possibilities of exercising fine-grained control over the execution of programs. To do so, we'll first define at what program points thread execution can be stopped, the so-called step points.

5.1 Step Points

Step points are defined in terms of syntactic constructs in source code (in particular, debugging is not line-oriented). Many Oz constructs are designated to define step points, and in fact each such construct defines two step points: one at the entry and one at the exit. The entry point creates a new stack frame, which is popped at the corresponding exit point. When stopping at a step point, Emacs highlights the line containing it and inserts an additional mark within the line to indicate its exact position (where the precise syntactic construct begins or ends).

Constructs

The following gives a non-exhaustive list of what constructs constitute step points and how they are described in stack frames.

Definitions

The definition of a procedure, function or class constitutes a step point. The entry point is the proc, fun, or class keyword, respectively, while the exit is the end keyword. The frame description consists of the single word definition.

Applications

Procedure, function, object and method applications are step points. The entry and exit points are the opening and closing braces (or the comma in the case of a method application). The frame description mimics application syntax, displaying the procedure name (or $ if it is anonymous) and the argument values.

Conditionals

Boolean and pattern-matching conditionals are step points. The entry point is the if or case keyword (or elseif, elsecase, or catch, to be precise), the exit point the corresponding end. The frame description consists of the word conditional, followed by the value tested by the conditional, if it could be determined.

Thread Creation

Thread creation using the thread ... end construct is a step point, with the obvious entry and exit points. Thread creation frames consist of the word thread.

Installation of Exception Handlers

The try ... end construct defines step points (unless it has neither catch nor finally, in which case it is ignored), with a frame description of exception handler. The actual handling of exceptions is a step point by virtue of the fact that conditionals are step points.

Critical Sections

The lock ... end constructs are step points, with the frame description containing both the word lock and the lock itself.

Loops

The for ... end construct defines step points, with frame description loop.

5.2 Actions

Step Into

The simplest way to control the execution of a thread is to single-step, i. e., to proceed from one step point to the next. This is exactly what Step Into () does. This is the most fine-grained visualization of program execution.

Step Over

In contrast, the Step Over action (), when performed at an entry point, causes thread execution to next stop at the corresponding exit point, not stopping at any nested step points. On an exit point, it behaves exactly as Step Into does.

Action Unleash

Actually, Step Over is a special case of a more generic action, called Unleash (). It causes execution of the thread to continue until the selected stack frame is about to be popped from the stack (or until the thread has finished executing the whole stack if no stack frame is selected); this makes Step Over identical to an Unleash with the topmost frame selected. Remember you can select a stack frame by clicking on it or by walking to it using the up and down cursor keys.

Example

To illustrate the unleash action, we'll consider the following program which computes the factorial function:

local 
   fun {Fac N}
      if N < 2 then 1
      else 
         N * {Fac N-1}
      end 
   end 
in 
   {Show {Fac 5}}
end

Go and activate Step Into () a couple of times, so as to build up a bit of stack, and select Frame 5. Your Ozcar should look similar to Picture 5.1.


Picture 5.1: Before the Action ``Unleash 5''


Let's decide to immediately compute the value of {Fac 3}, in other words, continue the thread's execution until Frame 5 is about to be removed from the stack. Unleash () with Frame 5 selected does exactly this. Picture 5.2 displays the result of this action.


Picture 5.2: After the Action ``Unleash 5''


5.3 Breakpoints

Single-stepping is nice, but often somewhat inconvenient, because you may need a lot of steps until you reach the interesting section of your program. This is where breakpoints come in. Ozcar supports them in two flavours: static breakpoints and dynamic breakpoints.

5.3.1 Static Breakpoints

A static breakpoint can be defined by editing source code to contain an application {Ozcar.breakpoint} and recompiling the program (which is why they're called static). This also means that static breakpoints will persist across multiple debugging sessions.

Example

Let's take the factorial example again and assume we need to debug the base case of the recursion. We can do this with a static breakpoint as follows:

local 
   fun {Fac N}
      if N < 2 then 
         {Ozcar.breakpoint} 1
      else 
         N * {Fac N-1}
      end 
   end 
in 
   {Show {Fac 5}}
end

After feeding the code and performing the Unleash () action twice, we arrive directly at the desired program point.

5.3.2 Dynamic Breakpoints

Sometimes we'll want to insert a breakpoint in the course of a debugging session. Then we need dynamic breakpoints.

Setting Breakpoints

Dynamic breakpoints can easily be set from within Emacs: Position the cursor on the line where you want to set or reset breakpoints and press C-x space to set or C-u C-x space to delete breakpoints. Note that this will affect all entry points on the corresponding line (there may be several, or none).

Currently, there is no way to list all currently defined dynamic breakpoints.


Benjamin Lorenz and Leif Kornstaedt
Version 1.4.0 (20080702)