This package includes basic recursive data structures make up of
intermediate representation (IR) nodes: trees and graphs. The classes
differ in whether edges are represented explicitly as nodes
themselves, whether edges can be traversed in either direction,
whether each node has a unique parent and whether nodes have operators
which determine the number of children. The name may include the
following terms:
- Edge
- Edges are explicitly represented with IR nodes.
In this case it is possible to define attributes on edges.
- Symmetric
- Edges can be traversed in either direction.
Otherwise the structure can only be traversed in
the direction of the edges.
- Tree
- Each node has at most one parent (always symmetric as well)
- Syntax
- Each node has an operator.
Not all combinations are implemented.
The classes provide methods to add new nodes to the data structure
and to attach these nodes in particular places. When a node is added
to a structure, the number of children is specified. For a graph, the
children of a node are the nodes that can be reached by following one
directed edge. The parents are those nodes for which this node is a
child. The number of parents is also specified when the node is added
to the data structure. In some cases, the number of children or
parents may be specified by the client with an integer parameter, num:
- num < 0
- the number is varying, starting with the one's
complement (~num) elements (-1 means none, -2 means
one etc).
- num = 0
- none are permitted.
- num > 0
- a fixed number are permitted.
At the beginning each is undefined,
requesting it raises the
{@link fluid.ir.SlotUndefinedException}
exception.
In other cases, the number is determined in a different way.
For example, trees have only one place for a parent, and syntax trees
get the number of children from the operator.
Trees and graphs may be immutable, mutable or versioned; the
constructor takes a {@link fluid.ir.SlotFactory} that specifies
what kind of slots to use.
This package provides interfaces as well as classes. The
interfaces should be used by clients that only need to traverse and
not add or modify structure. Here is a list of classes and the
corresponding interfaces:
- {@link fluid.tree.Digraph}
- {@link fluid.tree.DigraphInterface}
- {@link fluid.tree.EdgeDigraph}
- {@link fluid.tree.EdgeDigraphInterface}
- {@link fluid.tree.SymmetricDigraph}
-
{@link fluid.tree.SymmetricDigraphInterface}
- {@link fluid.tree.SymmetricEdgeDigraph}
-
{@link fluid.tree.SymmetricEdgeDigraphInterface}
- {@link fluid.tree.Tree}
- {@link fluid.tree.TreeInterface}
Additionally there is an interface {@link fluid.tree.GraphLabel} for
classes where each node has a label. The class
{@link fluid.tree.SyntaxTree} implements this interface.
The nodes of a structure can be enumerated in at least two ways
using classes in this package
- {@link fluid.tree.DepthFirstSearch}
- Starting from a particular node,
this node is returned and then the children are traversed.
If a node has already been traversed it is skipped, thus
ensuring termination.
- {@link fluid.tree.ConnectedNodes}
- (for symmetric structures only)
Starting from a particular node, return it and then all nodes
connected to it recursively. Again, if a node has already
been visited, it is skipped.
There is currently no way to enumerate all the nodes entered
into a structure. This capability would be incompatible with garbage
collecting unconnected nodes.
These classes can be listened to using the
method Digraph#addDigraphListener. There are
a large variety of different events below {@link fluid.tree.DigraphEvent}
that can be generated:
- {@link fluid.tree.NodeEvent}
- Events about nodes.
- {@link fluid.tree.NewNodeEvent}
- a node is added to graph
- {@link fluid.tree.ChildEvent}
- children changed:
- {@link fluid.tree.NewChildEvent}
- a new child is added
- {@link fluid.tree.RemoveChildEvent}
- a child is removed
- {@link fluid.tree.ChangedChildEvent}
- a
child is changed from one node to another
- {@link fluid.tree.ParentEvent}
- parents changed:
- {@link fluid.tree.NewParentEvent}
- a new parent is added
- {@link fluid.tree.RemoveParentEvent}
- a parent is removed
- {@link fluid.tree.ChangedParentEvent}
- a
parent is changed from one node to another
(Currently, this event is not generated).
- {@link fluid.tree.NodeEdgeEvent}
- a node's (reified)
incoming or outgoing edges change:
- {@link fluid.tree.ChildEdgeEvent}
- outgoing edges changed:
- {@link fluid.tree.NewChildEdgeEvent}
- a new
outgoing edge is added
- {@link fluid.tree.RemoveChildEdgeEvent}
- an outgoing
edge is removed
- {@link fluid.tree.ChangedChildEdgeEvent}
- an
outgoing edge is changed from one edge to
another
- {@link fluid.tree.ParentEvent}
- incoming edges changed:
- {@link fluid.tree.NewParentEdgeEvent}
- a new
incoming edge is added
- {@link fluid.tree.RemoveParentEdgeEvent}
- an incoming
edge is removed
- {@link fluid.tree.ChangedParentEdgeEvent}
- an incoming
edge is changed from one edge to another
(Currently, this event is not generated).
- {@link fluid.tree.RemoveChildrenEvent}
- all children
of the node are removed.
- {@link fluid.tree.RemoveParentsEvent}
- all parents of
the node are removed.
- {@link fluid.tree.EdgeEvent}
- Events about (reified) edges:
- {@link fluid.tree.NewEdgeEvent}
- A new edge is
added to the graph.
- {@link fluid.tree.EdgeNodeEvent}
- An edge gets
a new source or sink:
- {@link fluid.tree.SourceEvent}
- events about
changing sources:
- {@link fluid.tree.NewSourceEvent}
- the
source is defined
- {@link fluid.tree.ChangedSourceEvent}
- a
source is changed from one node to another
(Currently, this event is not generated).
- {@link fluid.tree.SinkEvent}
- events about changing sinks:
- {@link fluid.tree.NewSinkEvent}
- the
sink is defined
- {@link fluid.tree.ChangedSinkEvent}
- a
sink is changed from one node to another
The classes provide a way to create delegating versions of
themselves. Each class can be asked to express itself in the form of
derived attributes, and each class has a constructor which takes
attributes to which to delegate graph methods. In other words, one
can create (say) a directed graph, get this graph in the form of a
``children'' attribute and then create a directed graph which implements
methods by acting upon the attributes you give it. In this way one
gets a copy of the previous graph. It is interesting because one may
use wrappers around the attributes that are being used to express the
graph methods. The fit isn't complete; they are some operations that
cannot be expressed as slot accesses; these are indicated in the
known bugs section of each class.