Click or drag to resize

Welcome to the GrGen.NET v6.7 API documentation

This is an introduction into the Application Programming Interface of the GrGen.NET v6.7 system, i.e. the libGr and the assemblies generated from the model and rule specifications. We'll have a look at the

  • interface to the (named) graph and model
  • interface to the rules and matches
  • interface to the graph processing environment
  • interface to the graph viewer and debugger
From the input file Foo.grg the grgen.exe compiler generates the output files FooModel.cs for the model and FooActions.cs for the actions,
  • defining the exact interface
  • implementing the exact interface with generated code and code from the lgsp backend (i.e. entities from de.unika.ipd.grGen.lgsp, the libGr Search Plan Backend documentation is included for convenience, but does not define the API)
  • and implementing the generic interface from de.unika.ipd.grGen.libGr using the entities mentioned in both points above
Note Note

If you work on the API level it is helpful to keep the generated source code which normally is thrown away after it was compiled into the assemblies lgsp-FooModel.dll and lgsp-FooActions.dll. Use the -keep option when you call grgen.exe to do so.

Interface to the model and host graph

The generated FooModel.cs opens the namespace de.unika.ipd.grGen.Model_Foo containing all the generated entities. It contains for every node or edge class Bar an interface IBar, which offers C# properties giving access to the attributes, and is inheriting in the same way as specified in the model file. This builds the exact interface of the model, it is implemented by a sealed class Bar with generated code and with code from the lgsp backend. Furtheron the namespace contains a model class FooGraphModel implementing the interface de.unika.ipd.grGen.libGr.IGraphModel, which supports iteration over the entities defined in the model using further, generic(i.e. inexact) interfaces from libGr. Finally, the namespace contains a class FooGraph which defines an LGSPGraph of a model equivalent to FooGraphModel; it contains convenience functions to easily create nodes and edges of exact type in the graph. In addition, a class FooNamedGraph is available, which defines an LGSPNamedGraph of a model equivalent to FooGraphModel; the named graph offers persistent names for all its graph elements, otherwise it is identical to an LGSPGraph. The naming requires about the same memory as an unnamed graph, but under normal circumstances the named graph is the recommended one to use (and is the one which will be used if employed by the shell). The graphs require an IGlobalVariables input upon creation, you have to construct and supply an LGSPGlobalVariables object towards this goal.

Note Note

If you want to use the type-safe interface, use the interface IBar, and the CreateNodeBar-methods of FooGraph or the CreateNode-method of Bar.

If you want to use the generic interface, your entry point is the IGraphModel, with INodeModel.GetType("Bar") returning a NodeType, used in IGraph.AddNode(NodeType) returning an INode.

Interface to the rules

The generated file FooActions.cs opens the namespace de.unika.ipd.grGen.Action_Foo containing all the generated entities. It contains for every rule or test bar

  • a class Rule_bar inheriting from de.unika.ipd.grGen.lgsp.LGSPRulePattern, which contains the exact match interface IMatch_bar which defines how a match of the rule looks like, extending the generic rule-unspecific IMatch interface. Furtheron there are (but meant only for internal use): a match class Match_bar implementing the exact and inexact interface, a description of the pattern to match, and the modify methods doing the rewriting.
  • an exact action interface IAction_bar which contains the methods:
    • Match, to match the pattern in the host graph, with in-parameters corresponding to the in-parameters of the rule (name and type), returning matches of the exact type Rule_bar.IMatch_bar.
    • Modify, to modify a given match according to the rewrite specification, with out-parameters corresponding to the out-parameters of the rule.
    • Apply, to match and modify the found match, with in-parameters corresponding to the in-parameters of the rule, and with ref-parameters corresponding to the out-parameters of the rule.
Moreover the namespace contains an action class FooActions implementing the abstract class de.unika.ipd.grGen.libGr.BaseActions (in fact de.unika.ipd.grGen.lgsp.LGSPActions), which supports iteration over the entities defined in the actions using further, generic(i.e. inexact) interfaces from libGr. Additionally, at runtime it contains the instances of the actions singletons, as member bar of the exact type IAction_bar.
Note Note

If you want to use the type-safe interface, your entry point is the member bar of type IAction_bar from FooActions (or Action_bar.Instance). Actions are used with named parameters of exact types.

If you want to use the generic interface, your entry point is the method GetAction("bar") of the interface BaseActions implemented by FooActions returning an IAction. Actions are used with object-arrays for parameter passing.

Interface to the graph processing environment

The interface IGraphProcessingEnvironment implemented by the LGSPGraphProcessingEnvironment class offers all the additional functionality of GrGen.NET exceeding what is offered by the graph and the actions. It is constructed as LGSPGraphProcessingEnvironment given the graph and the actions. It offers execution of the sequences, combining actions into transformations (the former regarding control flow, the latter regarding data flow). Further on, the environment offers driver or helper objects for transaction management, deferred sequence execution, graph change recording, and emitting.

Interface to the graph viewer and debugger

The GraphViewer offers the functionality to display a graph continuously, following its changes, as well as to just render a snapshot of it. The Debugger allows you to execute sequences stepwise under debugger control (in a console window). They are contained in the graphViewerAndSequencesDebugger project; in the libGrShell project do you find the GrShell that allows you to employ GrShell-functionality from your own code (once it was generated).

Examples

There are several examples available in the examples-api folder of the GrGen.NET-distribution:

  • How to use the graph rewrite sequences offered by the libGr on API level is shown in examples-api/BusyBeaverExample/BusyBeaverExample.cs. But normally you want to use your favourite .NET programming language for control together with the type-safe interface when working on API level.
  • How to use the visited flags on API level is shown in examples-api/VisitedExample/VisitedExample.cs.
  • How to analyze the graph and generate (hopefully) better performing matchers based on this information is shown in examples-api/BusyBeaverExample/BusyBeaverExample.cs.
  • How to compile a .grg-specification at runtime and dump a graph for visualization in .vcg format on API level is shown in examples-api/HelloMutex/HelloMutex.cs.
  • How to display a graph at API level, resp. how to communicate with yComp on API level (from your own code) is shown in examples-api/YCompExample/YCompExample.cs.
  • How to debug a sequence on API level (from your own code, in the GrGen debugger in a console window) is shown in the examples-api/DebuggerExample/DebuggerExample.cs.
  • How to employ the GrShell from API level is shown in the examples-api/ShellExample/ShellExample.cs.
  • How to use GrGen functionality from a GUI application is shown in the examples-api/ApplicationExample/ApplicationExampleForm.cs.
If you want to work with GrGen.NET at API level you should get VisualStudio or MonoDevelop and have a look at them (or the other GrGen.NET code delivered with the source distribution; have a look at the How to build section in the manual if you want to build GrGen.NET on your own). In the following are a few further examples given as starting points.

Example 1

Normally you want to use the type-safe interface of the generated code as it is much more convenient. Only if your application must get along with models and actions unknown before it is compiled you have to fall back to the generic interface. An extensive example showing how to cope with the latter is shipped with GrGen.NET in form of the GrShell. Here we'll show a short example on how to use GrGen.NET with the type-safe API; further examples are given in the examples-api folder of the GrGen.NET-distribution. We'll start with including the namespaces of the libGr and the lgsp backend shipped with GrGen.NET, plus the namespaces of our actions and models, generated from Foo.grg.

C#
using de.unika.ipd.grGen.libGr;
using de.unika.ipd.grGen.lgsp;
using de.unika.ipd.grGen.Action_Foo;
using de.unika.ipd.grGen.Model_Foo;
Then we create a graph with model bound at generation time and create actions to operate on this graph. Afterwards we create a single node of type Bar in the graph and save it to the variable b. Finally we apply the action bar(Bar x) : (Bar) to the graph with b as input receiving the output as well. The rule is taken from the actions via the member named as the action.
C#
FooGraph graph = new FooGraph(new LGSPGlobalVariables());
FooActions actions = new FooActions(graph);
Bar b = graph.CreateNodeBar();
actions.bar.Apply(graph, b, ref b); // input of type Bar, output of type Bar
We could create a named graph instead offering persistent names for its graph elements:
C#
FooNamedGraph graph = new FooNamedGraph(new LGSPGlobalVariables());

Example 2

This is an example doing mostly the same as the previous example, in a slightly more complicated way allowing for more control. Here we create the model separate from the graph, then the graph with a model not bound at generation time. We create the actions to apply on the graph, and a single node of type Bar in the graph, which we assign again to a variable b. Then we get the action from the actions and save it to an action variable bar; afterwards we use the action for finding all available matches of bar with input b -- which is different from the first version -- and remember the found matches in the matches variable with its exact type. Finally we take the first match from the matches and execute the rewrite with it. We could have inspected the nodes and edges of the match or their attributes before (using element names prefixed with node_/edge_ or attribute names to get exactly typed entities).

C#
IGraphModel model = new FooGraphModel();
LGSPGraph graph = new LGSPGraph(model, new LGSPGlobalVariables());
FooActions actions = new FooActions(graph);
Bar b = Bar.CreateNode(graph);
IAction_bar bar = Action_bar.Instance;
IMatchesExact<Rule_bar.IMatch_bar matches> = bar.Match(graph, 0, b);
bar.Modify(graph, matches.First);
We could create a named graph instead offering persistent names for its graph elements:
C#
LGSPGraph graph = new LGSPNamedGraph(model, new LGSPGlobalVariables());

Example 3

While C# allows input arguments values to be of a subtype of the declared interface parameter type (OO), it requires that the argument variables for the out parameters are of exactly the type declared (non-OO). Although a variable of a supertype would be fully sufficient -- the variable is only assigned. So for node class Bla extends Bar; and action bar(Bar x) : (Bla) from the rules file rules Foo.grg we can't use a desired target variable of type Bar as out-argument, but are forced to introduce a temporary variable of type Bla and assign this variable to the desired target variable after the call.

using de.unika.ipd.grGen.libGr;
using de.unika.ipd.grGen.lgsp;
using de.unika.ipd.grGen.Action_Foo;
using de.unika.ipd.grGen.Model_Foo;
FooGraph graph = new FooGraph(new LGSPGlobalVariables());
FooActions actions = new FooActions(graph);
Bar b = graph.CreateNodeBar();
IMatchesExact<Rule_bar.IMatch_bar> matches = actions.bar.Match(graph, 1, b);
//actions.bar.Modify(graph, matches.First, out b); // wont work, needed:
Bla bla = null; 
actions.bar.Modify(graph, matches.First, out bla);
b = bla;

Example 4

For all but the simplest transformations you'll end up constructing a graph processing environment from the graph and the actions constructed until now, executing a graph rewrite sequence on the graph processing environment:

LGSPGraphProcessingEnvironment procEnv = new LGSPGraphProcessingEnvironment(graph, actions);
procEnv.ApplyGraphRewriteSequence("<(::x)=foo && (::y)=bar(::x) | bla(::y)>");

See Also