| 文件 | 最后提交记录 | 最后更新时间 |
|---|---|---|
| 3 年前 | ||
| 3 年前 | ||
| 3 年前 | ||
| 3 年前 | ||
| 3 年前 | ||
| 3 年前 | ||
| 3 年前 |
-
ir1-grapher This library graphs SBCL [[https://cmucl.org/docs/internals/html/The-Implicit-Continuation-Representation.html#The-Implicit-Continuation-Representation][ir1]] and outputs graphviz.
As of now, it is stil unfinished. There are a few tweaks that are needed to improve useablility, in particular, I think the rendering could be done a lot better, with subgraphs, to make it a lot more readable. Also to make it more readable, I'm planning on implementing rainbow-parens-esque arrow + label color randomization.
** How do I use it during compiler tracing? To load the system, you can call ~(asdf:load-system :ir1-grapher)~ once you have either loaded ~ir1-grapher.asd~ manually, or placed the folder inside your [[https://common-lisp.net/project/asdf/asdf/Configuring-ASDF-to-find-your-systems.html][ASDF load path]].
Because of the way it hooks in the compiler, you shouldn't actually have to do anything after loading it except turning on trace output of the compiler (SBCL), and adding ~:sb-graph~ to ~sb-c::compile-trace-targets~. Turning on the tracing can be done by calling ~(compile-file "file" :trace-file t)~, and adding ~:sb-graph~ to ~sb-c::compile-trace-targets~ can be done however you want. After compilation is done, alongside the normal trace file, SBCL is hooked into writing a series of .dot files, which contain the graphviz DOT representation of all the components compiled. If you set ~compile-progress~ to ~T~, it will print out progress information, and will tell you when and where it writes out the graphviz files.
** How do I use the system interactively? If you ran into a compiler error, and want to graph the still-in-memory code interactively, you can do so with the following functions:
*** ~(make-and-dfs object distance)~ This function takes an ir1 object ~object~, and integer ~distance~, and returns a graph object with every node up to ~distance~ hops away from ~object~ in its ~dfs-table~. Each object is tagged with a "codename", visible as a hex digit in braces at the start of each graph node.
Then, to operate on the graph interactively, you can use:
*** ~(interactively-graph graph &optional filename)~ This function takes a ~graph~ and a ~filename~, and sets the current working graph to it, and the current output file to the filename. When calling ~output~ and ~expand~, the graph will be written to ~filename~.
*** ~(output)~ This function outputs the current working graph to a string, and if ~interactively-graph~ was called with a filename, writes it to that file.
*** ~(expand codename)~ After you've rendered the graph, if you want to add a node to the ~dfs-table~ (thus expanding the amount of the in-memory objects rendered), call this function with the codename of the new object you'd like to add. Example: ~(expand "A")~.
If you passed a filename to ~interactively-graph~, this function
will then write the render to file automatically.
*** ~(unexpand codename)~ Removes the node tied to the codename from the table, meaning that it won't get its neighbours traversed when graph rendering is done.
*** ~(get-node codename)~ Returns the object tied to ~codename~ from the current interactive graph.
** And if you don't want to use ~interactively-graph~: *** ~(render-graph graph)~ Given a graph with objects in its ~dfs-table~, returns a string of the rendering of the graph in DOT.
Does the same thing as ~output~, but without using
~interactively-graph~.
*** ~(expand-codename graph codename)~ Given a graph and codename, put the node tied to ~codename~ into the ~dfs-table~ of the graph.
Does the same thing as ~expand~, but without using
~interactively-graph~.
*** ~(unexpand-codename graph codename)~ Does the same thing as ~unexpand~, but without using ~interactively-graph~.
*** ~(get-node-from-codename graph codename)~ Return the node tied to ~codename~ in ~graph~.
Does the same thing as ~node~, but without using
~interactively-graph~.
** What good is ~interactively-graph~ if I need to run ~dot~ every time the graph gets output? That's where ~render-on-change.sh~ comes in. Run ~render-on-change.sh~ with two arguments. First is the input DOT file, and second is the output SVG file. If you want to export to a different format, just modify the ~-Tsvg~ of the script.
** Help! It's saying there's a package locking error. Run ~(sb-ext:unlock-package :sb-c)~ in the REPL, or compile SBCL with ~--with-sb-devel~ (if you're doing compiler work, you should probably do this anyways). In ~src/package.lisp~, there's a ~(sb-ext:unlock-package :sb-c)~ statement, but it seems to not work as expected.
** But what if the compiler breaks your library, or I want to muck around with it? ~hooking.lisp~ contains all the code that is used to hook the compiler directly, and ~graphing.lisp~ goes from the compiler data structures to the graphviz DOT format.
Right now, I'm assuming that the only place that the compiler will ever call ~sb-c::ir2-convert~ for each component is inside ~%compile-component~, and only one time. If this becomes no longer true, then the hooking location/manner will have to be modified.
** After the ~.dot~ files get output, how do I render them? ~dot -T input.dot > output~. For example, ~dot -Tsvg trace-1-DEFUNFOO.dot > out.svg~.
** Can I see an example? Yes, look at the ~example/~ folder. It contains the dot output when running ~(compile-file "testfile" :trace-file t)~.