Did you know ... Search Documentation:
Pack callgraph -- prolog/callgraph.pl
PublicShow source

Usage

This module allows you to produce a call graph of one or more modules, where nodes (boxes) represent predicates and an edge between two predicates indicates that one (the source end) calls the other (the pointy end).

By default, node styles are used to indicate whether or not the predicate is exported (bold outline), dynamic (italic label, filled), multifile (box with diagonals in the corners). For dynamic predicates, dashed edges are used to represent operations which mutate (assert to or retract from) the predicate.

Items in the recorded database are also represented, as they consitute mutable state much like dynamic predicates. Recorded items are labelled as Key:Functor/Arity and drawn in a filled octagonal box. Dashed edges represents writing to the recorded database and ordinary solid edges represent reading.

Basic method of usage is:

  1. Load the module you want to graph.
  2. Load this module.
  3. Generate and write the module call graph to a PDF document:
    ?- module_dotpdf(ModuleName,[]).

See module_dot/2 for options that affect graph content and style, and module_dotpdf/2 for options that affect rendering.

Multi-module graphs

The predicates modules_dotpdf/3 and modules_dot/3 support graphing multiple modules. Each module is drawn inside a box (a Graphviz cluster). Items in the recorded database are outside the module system. They can optionally be collected into one cluster or into several clusters by key.

Implementation notes

NB. This is very preliminary. The intereface is not necessarily stable. The dot DCG implementation is a bit embarassing but it does the job for now.

Three parts to this:

  1. Using prolog_walk_code/1 to compile a database of inter-predicate calls into dynamic predicate edge/3.
  2. Possible transformations of graph (eg pruning).
  3. Collect information about desired modules/predicates into a Dot graph structure as defined by dotdct.pl

Types used internally

pred_head
Predicate specifier as Modue:Head where Head is a term with same name and arity of the predicate concerned.
module
Module name as an atom.
record_head
Term like Key:Term, reference to recorded database terms with Term and given Key.
node
Node name as Atom:Name/Arity.
module == atom.
functor   ---> atom/natural.
pred_head ---> module:term.
node      ---> atom:functor.
record_head ---> atom:term.
edge_spec ---> dynamic(module,pred_head,list(edge_type))
             ; recorded(edge_type,record_head).
edge_type ---> calls ; mutates ; reads ; writes.
 module_dot(+ModuleName, Opts) is det
Writes a call graph for named module as a dot file named "[ModuleName].dot". This predicate also accepts various options (some of the these types refer to the GraphViz attribute types):
prune(Prune:bool)/false
If true, then graph subtrees are removed using prune_subtrees/0.
recursive(bool)/false
If true, then looping edges are used to decorate predicates that call themselves directly. Otherwise, such direct recursion is hidden.
hide_list(list(pred_ind))/[]
A list of predicate (name/arity) to hide from the graph.
arrowhead(arrow_type)/vee
Dot arrowhead name as an atom, for all call edges.
export_style(node_style)/bold
Dot node style for exported predicates.
dynamic_shape(node_shape)/box
Dot node shape for dynamic predicates.
dynamic_style(node_style)/filled
Dot node style for dynamic predicates.
multifile_shape(node_shape)/box
Dot node shape for multifile predicates.
multifile_style(node_style)/diagonals
Dot node style for multifile predicates.
recorded_shape(node_shape)/octagon
Dot node shape for recorded facts.
recorded_style(node_style)/filled
Dot node style for recorded facts.
mutate_style(line_style)/dashed
Dot line style for edges representing mutation of a dynamic predicate.
read_style(line_style)/solid
Dot line style for edges representing readed of a recorded fact.
write_style(line_style)/dashed
Dot line style for edges representing writing of a recored fact.
font(S:string)
Font family (as a list of codes) for all labels. How these names are interpreted depends on your host operating system. On Mac OS X, I find I am able to use any font available in the "Font Book" application with the name written exactly (including spaces) as in the "Font" column. Default is "Times".
linkbase(Base:atom)
If present, each predicate node will have a URL attribute pointing to a URL formed by appending Module:Name/Arity to Base. Thus, if the output format supports links, you will be able to click on the nodes to follow the links, eg to an SWI documentation server..

Types for Dot attributes: see http://graphviz.org/Documentation.php for more details on

line_style ---> solid ; dashed ; dotted ; bold.
arrow_type ---> normal ; vee ; empty ; box ; none ; dot ; ... .
node_shape ---> box ; ellipse ; circle ; diamond ; trapezium ; parallelogram
              ; house ; square ; pentagon ; hexagon ; septagon ; octagon ; ... .
node_style ---> solid ; dashed ; dotted ; bold ; rounded
              ; diagonals ; filled ; striped ; wedged.
 module_dotpdf(+Mod, Opts) is det
Writes a call graph for module Mod as a PDF file named "[Mod].pdf". Equivalent to module_render/2 with format(pdf) option supplied.
 module_render(+Mod, Opts) is det
Writes a call graph for module Mod as a file named "<Mod>.<Fmt>" where Fmt is one of the formats supported by Graphviz and is supplied as an option As well as the options accepted by module_dot/2, this predicate also accepts:
format(atom)/pdf
Any of the formats supported by Graphviz, eg pdf, ps, svg, png etc.
method(Method:graphviz_method)/unflatten
Determines which GraphViz programs are used to render the graph. The type graphviz_method is defined as:
graphviz_method ---> dot ; neato; fdp ; sfdp ; circo ; twopi
                   ; unflatten(list(unflatten_opt))
                   ; unflatten.
unflatten_opt   ---> l(N:natural)   % -l<N>
                   ; fl(N:natural)  % -f -l<N>
                   ; c(natural).    % -c<N>

The unflatten methods filter the graph through unflatten before passing on to dot.

 modules_dot(+Modules:list(module), +Opts, +Name) is det
Mostly like module_dot/2, but takes a list of module names instead of a single module name. Output is written to a dot file named Name. It understands the same options, but in addition:
cluster_recorded(Flag:oneof([false, true, by_key]))/false
If true, then all recorded items are collected into a seperate cluster. If by_key, then all recorded items are collected multiple clusters, one for each distinct key..
 modules_dotpdf(+Modules:list(module), +Opts, +Name) is det
Equivalent to modules_render/3 with format(pdf) option supplied.
 modules_render(+Modules:list(module), +Opts, +Name) is det
Mostly like module_render/2, but takes a list of module names instead of a single module name. Output is written to a PDF file named Name. It understands the same options, but in addition:
cluster_recorded(Flag:oneof([false, true, by_key]))/false
If true, then all recorded items are collected into a seperate cluster. If by_key, then all recorded items are collected multiple clusters, one for each distinct key..