Skip to content

Commit

Permalink
Merge pull request #24 from elegios/debug-section
Browse files Browse the repository at this point in the history
Add a how-to section on debugging
  • Loading branch information
elegios authored May 31, 2024
2 parents fdeee6a + 3e5e375 commit d90d396
Show file tree
Hide file tree
Showing 3 changed files with 102 additions and 0 deletions.
1 change: 1 addition & 0 deletions docs/how-to-guides/debugging/_category_.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
label: 'Debugging'
58 changes: 58 additions & 0 deletions docs/how-to-guides/debugging/debug-json.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# Examining large ASTs as JSON

Sometimes the ASTs you wish to examine are too large for the various
`--debug-*` flags to be viable, or you want the ability to
programmatically explore it outside the compiler.

This can be achieved using `mexpr/json-debug.mc`, which is a small
library in the standard library. Usage centers around a few functions
like `exprToJson`, `typeToJson`, etc., To use these functions you need
include `mexpr/json-debug.mc` and `use` the `MExprToJson` language
fragment:

```mc
-- Add this include to the file
include "mexpr/json-debug.mc"
-- Later:
let ast = /- Some code producing an AST to examine -/ in
printLn (json2string (use MExprToJson in exprToJson ast));
-- ... more code that keeps processing the AST ...
```

:::note

If you are working with an extended language, e.g., in `miking-dppl`,
then you will need to create a new language fragment that implements
the corresponding `sem`s (`exprToJson` for constructors in `Expr`,
etc.). See `stdlib/mexpr/json-debug.mc` for examples.

:::

When run, this code will typically print a *very* large json object,
thus it's typically useful to redirect the output to a file for later
processing:

```bash
# Assuming the above code has been added somewhere in the main `mi` compiler:
mi compile test.mc > debug.json
```

Some useful tools to explore this data are [jless](https://jless.io/)
and [jq](https://jqlang.github.io/jq/).

:::tip

When looking at data from a program that prints both json-encoded data
and arbitrary strings (e.g., an edited `mi` compiler) it might be
useful to pre-process the output first:

```bash
# Filter out non-json lines
jq -R 'try fromjson' < debug.json | jless

# Reformat all non-json lines as strings with `-> ` added at the start
jq -R '. as $line | try fromjson catch ("-> " + $line)' < debug.json | jless
```

:::
43 changes: 43 additions & 0 deletions docs/how-to-guides/debugging/ocaml-stacktraces.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# Getting stack traces when using the OCaml backend

There are two primary ways to get stack traces from a program compiled
with the OCaml backend. Note that regardless of the method used most
functions will have mangled names, i.e., they differ somewhat from the
source code, but the connection is typically quite clear
nonetheless. For example, a function `typeCheckExpr` in a language
fragment `ExtMCore` might become something like
`camlDune__exe__Program__v_vExtMCore_typeCheckExpr_142839`.

First, the `OCAMLRUNPARAM` environment flag can be set to `b` to
instruct the OCaml runtime to emit a backtrace when it encounters an
exception:

```bash
OCAMLRUNPARAM=b ./program
```

Second, the program can be run using a debugger such as `gdb`:

```bash
gdb ./program

# Once inside gdb:
run <program args>

# Use `bt` to get a backtrace when the program has crashed or been interrupted:
bt
```

:::tip

If the program prints an error and exits explicitly (e.g., via `exit
1`) rather than throwing an exception and crashing `gdb` can still
extract a backtrace by adding a breakpoint to `exit`:

```bash
# Inside gdb, before running the program:
break exit
# Then run as usual, the program will break just before exiting, at which point you can run `bt`
```

:::

0 comments on commit d90d396

Please sign in to comment.