One of the advantages of using JVM and .NET is that if we generate sufficient debug information the execution platforms directly support source-level debugging of BETA code in their respective tools.

Below are preliminary examples of this for both .NET and JVM.

BETA.NET source level debugging

You can source level debug BETA programs compiled for .NET with both the free stand alone debuggers DbgCLR.exe (graphical) and CorDBG.exe (textual) supplied with the .NET Framework SDK as well as with the built-in debugger in Visual Studio .NET.

Debugging using Visual Studio .NET

To use Visual Studio .NET for BETA source level debugging, do this:
  1. To debug foo.exe produced from foo.bet, you first choose menu item [File->Open Solution...].
  2. In the dialog that appears, you choose Files of types: All project files and navigate to foo.exe. Double click foo.exe.
  3. Now set a breakpoint at the beginning of the program: From menu item [Debug->New Breakpoint (Ctrl-B)] specify breakpoint in Function program.Do.
  4. Now start the program using menu item [Debug->Start (F5)]. The program will now stop at the do-part of the PROGRAM fragment. You can now single step, inspect variables etc. at BETA source level.
Below is a screen shot showing a debugging session (slightly reduced size; click image to see it in full size in a separate window):
Visual Studio .NET Debugging Session
As can be seen, a breakpoint has been set in program.Do (as described above) as well as in line 12 and 17. The latter two were set using the contextual right button menu in the SuperFields.bet source window.
The breakpoint at line 12 (in the get method has been hit, and a single Step-into command has been issued, thus executing the statement x + y -> z (the maroon indication of the statement seems to be off by one - we'll check this later (:-)).
As can be seen from the red 77 in the locals window, this assignment caused the local variable named z to get the new value 77.

By default Visual Studio will only be able to find source files in the current directory. This means that when you, e.g., "step into (F11)" a method residing in a source file outside the current directory, this will behave as a "step over (F10)"!. To avoid this, you can specify the Debug Source Files property:
To access the Debug Source Files property page, right-click on your Solution in Solution Explorer and choose Properties from the shortcut menu. Expand the Common Properties folder and click the Debug Source Files page.

Additional information can be found on, e.g., Visual Studio: Debugging an Executable That Is Not Part of a Visual Studio Solution

Debugging using DbgCLR.exe

Along with the free .NET framework comes a stand alone source level debugger named DbgCLR.exe. It typically resides in C:\Program Files\Microsoft.Net\FrameworkSDK\GuiDebug\DbgCLR.exe . If you installed .NET Framework as part of Visual Studio .NET 2003 it may reside in C:\Program Files\Microsoft Visual Studio .NET 2003\SDK\v1.1\GuiDebug\DbgCLR.exe
  1. Open DbgCLR.exe by double clicking its icon in the Windows Explorer.
  2. Given that foo.bet has been compiled to foo.exe, you may now specify foo.exe in menu item [Debug->Program to debug].
  3. Now set a breakpoint at the beginning of the program: From menu item [Debug->New Breakpoint (Ctrl-B)] specify breakpoint in Function program.Do.
  4. Now start the program using menu item [Debug->Start (F5)]. The program will now stop at the do-part of the PROGRAM fragment. You can now single step, inspect variables etc. at BETA source level.
Below is a screen dump showing the same debugging session as above in Visual Studio .NET.
DbgCLR Debugging Session
Notice that DbgCLR will only be able to automatically open source files in the current directory. Thus when you "step into (F11)" a file, that does not reside in the current directory, this will behave as a step over! This can be avoided by making the other source file "known" by preopening it. If you accept saving the solution file, when the current debug session is ended, the next time you debug the same program, the previously opened source files will be known.

Addition information: CLR Debugger Solution Model.

Debugging using CorDBG.exe

There is also a command line debugger included in the .NET Framework.
It is named cordbg.exe and is normally automatically accessible from your shell (as the .NET Framework Installer will have included the path to it in your search path).

If you compiled with nbeta -d, cordbg is very useful for debugging IL code. It automatically breaks a the main entry point when run as

> cordbg foo.exe
The syntax for breaking in the Do method of class program is
(cordbg) b program::Do
You may also use cordbg for source level debug, and specify, e.g.,
(cordbg) b foo.bet:16
to make it break in line 16 of foo.bet. In this case foo should be compiled without the -d option. To get more help on using cordbg type this:
(cordbg) help

IL debugging

If you want to debug at IL level instead of BETA source level, you can compile with:

> nbeta -d foo
or (forcing total recompile):
> nbeta -s 12 -d foo

BETA.Java Source Level Debugging

Graphical debuggers for Java?

We have so far had no success in doing BETA source level debugging in any of the graphical debuggers for Java that we have tried. For a survey of our efforts see here.

Using jdb

The standard J2SE SDK version 1.4.2 includes the textual debugger called jdb.

In order to use jdb, a few observations must be made:

Since the invocation of jdb is a little cumbersom (especially the setup of the sourcepath), the BETA compiler will generate a shell script named <program name>-jdb (with .bat extension on windows), which invokes jdb on the program. Below is a session showing BETA source level debugging using this script.

A jdb session

tcsh> jbeta SuperFields.bet
tcsh> ./SuperFields-jdb
Running jdb on SuperFields:
To stop at program start issue this command: stop in beta.program.Do
Initializing jdb ...
> stop in beta.program.Do
Deferring breakpoint beta.program.Do.
It will be set after the class is loaded.
> run
run beta.program
Set uncaught java.lang.Throwable
Set deferred uncaught java.lang.Throwable
> 
VM Started: Set deferred breakpoint beta.program.Do

Breakpoint hit: "thread=Thread-1", beta.program.Do(), line=29 bci=0
29    do &SuperFieldsSub[] -> S[];

Thread-1[1] list
25      #)
26    ---program:descriptor---
27    (# S: ^SuperFieldsSub;
28       N: @integer
29 => do &SuperFieldsSub[] -> S[];
30       33 -> S.x;
31       44 -> S.y;
32       S.x -> putint;
33       newline;
34       S.y -> putint; 
Thread-1[1] stop in beta.SuperFieldsSub.get
Deferring breakpoint beta.SuperFieldsSub.get.
It will be set after the class is loaded.
main[1] cont
> Set deferred breakpoint beta.SuperFieldsSub.get
33
44

Breakpoint hit: "thread=Thread-1", beta.SuperFieldsSub.get(), line=12 bci=0
12           do x -> z;

Thread-1[1] list  
8      (# y: @integer;
9         R: ^SuperFieldsSub;
10         get: proc
11           (# z: @integer
12 =>        do x -> z;
13              z + y -> z;
14           exit z
15           #); 
16         call: proc
17           (# N: @integer; P1,P2: ^SuperFieldsSub

Thread-1[1] next
> 
Step completed: "thread=main", beta.SuperFieldsSub.get(), line=13 bci=5
13              z + y -> z;

Thread-1[1] locals
Method arguments:
Local variables:
z = 33
Thread-1[1] dump this
 this = {
    origin: instance of beta.betaenv(id=334)
    y: 44
    R: null
    beta.SuperFields.origin: instance of beta.betaenv(id=334)
    beta.SuperFields.x: 33
    beta.SuperFields.Q: null
    beta.BetaObject.comp$: null
}

Thread-1[1] where
  [1] beta.SuperFieldsSub.get (SuperFields.bet:13)
  [2] beta.program.Do (SuperFields.bet:36)
  [3] beta.Component.run (null)
Thread-1[1] clear beta.SuperFieldsSub.get
Removed: breakpoint beta.SuperFieldsSub.get
Thread-1[1] cont
> 77
77
77
77
77


The application exited
tcsh>