# Debugging in Yacas

##

Introduction

When writing a code segment, it is generally a good idea to separate the problem into many small functions. Not only can you then reuse these functions on other problems, but it makes debugging easier too.

For debugging a faulty function, in addition to the usual trial-and-error method and the "print everything" method, Yacas offers some trace facilities. You can try to trace applications of rules during evaluation of the function (`TraceRule()`, `TraceExp()`) or see the stack after an error has occurred (`TraceStack()`). Finally, you may want to run a debugging version of Yacas.

##

The trace facilities

The trace facilities are:

- `TraceExp` : traces the full expression, showing all calls to user- or system-defined functions, their arguments, and the return values. For complex functions this can become a long list of function calls.
- `TraceRule` : traces one single user-defined function (rule). It shows each invocation, the arguments passed in, and the returned values. This is useful for tracking the behaviour of that function in the environment it is intended to be used in.
- `TraceStack` : shows a few last function calls before an error has occurred.

The online manual pages (e.g. `?TraceStack`) have more information about the use of these functions.

An example invocation of `TraceRule` is

    In> TraceRule(x+y)2+3*5+4;

Which should then show something to the effect of

      TrEnter(2+3*5+4);
        TrEnter(2+3*5);
           TrArg(2,2);
              TrArg(3*5,15);
           TrLeave(2+3*5,17);
            TrArg(2+3*5,17);
            TrArg(4,4);
        TrLeave(2+3*5+4,21);
    Out> 21;

##

The Yacas debugger program

A debugging version of yacas comes with the distribution. The yacas debugger consists of:

- `./yacasdebug`, a separate program
- `libyacasdebug.a`, a static library that can be linked in

The debug version has to be built separately from the "production" version of Yacas (all source files have to be recompiled).

###

Why introduce a debug version?

The reason for introducing a debug version is that for a debugger it is often necessary to introduce features that make the interpreter slower. For the main kernel this is unacceptable, but for a debugging version this is defendable. It is good for testing small programs, to see where a calculation breaks. Having certain features only in the debug version keeps the release executable can be kept lean and mean, while still offering advanced debug features.

###

How to build `yacasdebug`

The yacas debugging components can be built by the command

    make debug

or, alternatively, by going into the `src/` directory and using the file `makefile.debug` to build it:

    cd src/
    make -f makefile.debug

Note the object files generated are called `*-d.o` and are suited for the normal Yacas executable. The static library `libyacasdebug.a` is built instead of the normal `libyacas.a`.

The file `makefile.debug` was written to compile under Linux, but should work on other platforms with little tweaks.

After the build the debug version of Yacas can be found in the `src/` directory.

To invoke the debugger, type

    ./yacasdebug --rootdir ../scripts/

The Yacas debugger assumes the current directory for scripts, so the `--rootdir` command line option is required.

###

What does `yacasdebug` offer?

The Yacas debugger is in development still, but already has some useful features.

When you build `yacasdebug` and run a command, it will:

- keep track of the memory allocated and freed, and show any memory leaks when you quit the program.
- show which files are loaded to read function definitions and when.
- keep a file name and line number for each object loaded from file, for debugging purposes.
- show you the stack trace when evaluation goes into an infinite recursion (equivalent of always using `TraceStack`) and print file names and line numbers for all rules.

The `libyacasdebug.a` library is used by `proteusdebugger`, a graphical front-end for debugging which is also still in development.

Future versions will have the ability to step through code and to watch local and global variables while executing, modifying them on the fly.