expand.beh.html
Program{
private void expandStaticTraversals()bypassing VisitorSpec via TraversalDef to-stop{ TraversalName, TraversalParms, StrategyGraph, PathDirective, StrategyVariable, CompoundStrategy }{
(@ ClassGraph cg; @)
before ClassGraph (@ cg = host; @)
(@ ClassDef source; ClassName clname; @)
before ClassDef (@ source = host; clname = host.get_classname(); @)
(@ TraversalName name; @)
before TraversalName (@ name = host; @)
(@ TraversalParms parms; @)
before TraversalParms (@ parms = host; @)
(@ StrategyGraph sg; @)
before StrategyExpression (@ sg = host.toGraph(clname); @)
after TraversalDef (@
Program.log.print(" Marking " + name + "...");
Program.log.flush();
if (!cg.markSubgraph(sg)) return;
Program.log.println(" expanding...");
TraversalMethodName mname = new TraversalMethodName(name);
String args = parms.collectVisitorNames();
boolean use_nodeset = sg.size() > 1;
String start_call = " public void " + name + parms + " {\n";
if (use_nodeset) {
start_call +=" java.util.BitSet startSet = new java.util.BitSet();\n";
start_call += sg.startSetCode(" ", "startSet", clname);
}
start_call += " " + mname + "(";
if (use_nodeset) {
start_call += "startSet";
if (!args.equals("")) start_call += ", ";
}
start_call += args + ");\n }\n";
source.addMethod(start_call);
Program.prog.makeTraversalMethods(mname, parms, args, use_nodeset);
@)
}
}
TraversalParms{
String collectVisitorNames()=allVisitorNames{
(@ boolean first = true; @)
init (@ return_val = ""; @)
before VisitorName (@
if (first) first = false; else return_val += ", ";
return_val += host;
@)
}
}
Program{
void makeTraversalMethods(TraversalMethodName name, TraversalParms parms, String args, boolean use_nodeset)=allEdges{
(@ TraversalParms revparms; String args_with_nodeset; @)
before Program (@
revparms = parms.reverse();
args_with_nodeset = (use_nodeset ? "nodes, " : "") + args;
@)
(@ ClassDef def; ClassName source; boolean opt; String edge_calls; @)
around ClassDef (@
if (host.isInterface()) return;
def = host;
ClassDef parent = host.get_superclass_def();
if (parent != null && !parent.is_in_trav()) parent = null;
if (host.is_in_trav()) {
/*
let v be the first visitor
outer:
If v has an around method for this class,
call/cc
else
call befores on v for this class & its parents
if v is last visitor,
for each edge e,
inner:
call befores on v for e
if v is last visitor,
traverse e
else
call inner: with next visitor
call afters on v for e
else
call outer: with next visitor
call afters on v for this class & its parents
*/
source = host.get_classname();
Glob glob = new ClassGlob(source);
// Make the before method caller.
String bef_super_call = "";
if (parent != null) {
bef_super_call = " super." + name.beforeName()
+ "(" + args + ");\n";
}
host.addBeforeMethod(name, parms,
bef_super_call + parms.callBefores(glob, false));
// Make the after method caller.
String aft_super_call = "";
if (parent != null) {
aft_super_call = " super." + name.afterName()
+ "(" + args + ");\n";
}
host.addAfterMethod(name, parms,
revparms.callAfters(glob, false) + aft_super_call);
edge_calls = "";
subtraversal.apply();
String body = host.maybeAddAroundMethod(name, parms, glob, edge_calls,
parms.callArounds(glob, false, source, name,
args_with_nodeset),
use_nodeset);
if (host.isConstructionClass()) {
body = " " + name.beforeName() + "(" + args +");\n"
+ body
+ " " + name.afterName() + "(" + args +");\n";
}
if (use_nodeset)
body = host.get_tg().intercopyEdgesCode(" ", "nodes") + body;
host.addTraversalMethod(name, parms, body, use_nodeset);
} else if (parent != null) {
// The class isn't in the traversal, but its parent is; generate
// an empty traversal method, so that the parent's method
// doesn't get inherited.
host.addTraversalMethod(name, parms, "", use_nodeset);
}
@)
before OptionalPart (@ opt = true; @)
before Part (@
if (host.is_in_trav()) {
ClassName classname = host.get_classname();
PartName partname = host.get_partname();
if (host.isDerived()) {
edge_calls += " " + classname + " " + partname
+ " = get_" + partname + "();\n";
}
if (opt) edge_calls += " if (" + partname + " != null) {\n";
Glob glob = new PartGlob(source, partname, classname);
edge_calls += parms.callBefores(glob, opt);
if (!host.isTerminal()) {
edge_calls += def.maybeAddAroundMethod(name, parms, glob,
host.callTraversalMethod(name, args, use_nodeset),
parms.callArounds(glob, opt, source, name,
args_with_nodeset),
use_nodeset);
}
edge_calls += revparms.callAfters(glob, opt);
if (opt) edge_calls += " }\n";
}
@)
after OptionalPart (@ opt = false; @)
before Superclass (@
if (host.is_in_trav() &&
Program.prog.definesClass(host.get_classname())) {
Glob glob = new SuperclassGlob(source, host.get_classname());
edge_calls += parms.callBefores(glob, false)
+ def.maybeAddAroundMethod(name, parms, glob,
host.callTraversalMethod(name, args, use_nodeset),
parms.callArounds(glob, false, source, name,
args_with_nodeset),
use_nodeset)
+ revparms.callAfters(glob, false);
}
@)
}
}
TraversalMethodName{
(@
static int trav = 0;
TraversalMethodName(TraversalName name) {
methodname = MethodName.parse(name + "_trv" + (trav++));
}
@)
protected String withSuffix(String suffix)(@
return methodname + "_" + suffix;
@)
String beforeName()(@ return withSuffix("bef"); @)
String afterName()(@ return withSuffix("aft"); @)
String aroundName(Glob glob, ClassName clname)(@
return withSuffix("aro_" + clname + glob.methodSuffix());
@)
}
ClassDef{
private String traversalMethodSignature(String name, TraversalParms parms, boolean use_nodeset)(@
String signature = " void " + name + "(";
if (use_nodeset) signature += "java.util.BitSet nodes";
Visitor_Commalist vis = parms.get_visitors();
if (vis != null) {
if (use_nodeset) signature += ", ";
signature += vis;
}
signature += ")";
return signature;
@)
void addTraversalMethod(TraversalMethodName name, TraversalParms parms, String body, boolean use_nodeset)(@
String sig = traversalMethodSignature(name.toString(), parms, use_nodeset);
addMethod(sig, body);
@)
void addBeforeMethod(TraversalMethodName name, TraversalParms parms, String body)(@
addMethod(" void " + name.beforeName() + parms, body);
@)
void addAfterMethod(TraversalMethodName name, TraversalParms parms, String body)(@
addMethod(" void " + name.afterName() + parms, body);
@)
void addAroundMethod(TraversalMethodName name, TraversalParms parms, Glob glob, String body, boolean use_nodeset)(@
ClassName clname = get_classname();
String mname = name.aroundName(glob, clname);
String sig = traversalMethodSignature(mname, parms, use_nodeset);
addMethod(sig, body);
String s = "";
s +=" static java.lang.reflect.Method " + mname + ";\n"
+ " static {\n"
+ " try {\n"
+ " " + mname + " =\n"
+ " " + clname + ".class.getDeclaredMethod(\"" + mname + "\",\n"
+ " new Class[] { ";
Enumeration e = parms.elements();
boolean first = true;
if (use_nodeset) {
s += "java.util.BitSet.class";
first = false;
}
while (e.hasMoreElements()) {
Visitor vis = (Visitor) e.nextElement();
if (first) first = false; else s += ", ";
s += vis.get_classname() + ".class";
}
s += " });\n";
s += " } catch (NoSuchMethodException e) {\n";
s += " throw new RuntimeException(e.toString());\n";
s += " }\n";
s += " }\n";
addMethod(s);
@)
String maybeAddAroundMethod(TraversalMethodName name, TraversalParms parms, Glob glob, String edge_call, String around_call, boolean use_nodeset)(@
if (around_call.equals("")) return edge_call;
// What if more than one method??
addAroundMethod(name, parms, glob, edge_call, use_nodeset);
return around_call;
@)
}
Part{
(@
String callTraversalMethod(TraversalMethodName name, String args,
boolean use_nodeset) {
if (!use_nodeset)
return " " + get_partname() + "." + name + "(" + args + ");\n";
String call =
" { java.util.BitSet newnodes = new java.util.BitSet();\n";
call += get_tg().maskCode(" ", "nodes", "newnodes");
call += " if (!newnodes.equals(new java.util.BitSet()))\n";
call += " " + get_partname() + "." + name + "(newnodes";
if (!args.equals("")) call += ", " + args;
call += "); }\n";
return call;
}
@)
}
Superclass{
(@
String callTraversalMethod(TraversalMethodName name, String args,
boolean use_nodeset) {
if (!use_nodeset)
return " super." + name + "(" + args + ");\n";
String call =
" { java.util.BitSet newnodes = new java.util.BitSet();\n";
call += get_tg().maskCode(" ", "nodes", "newnodes");
call += " if (!newnodes.equals(new java.util.BitSet()))\n";
call += " super." + name + "(newnodes";
if (!args.equals("")) call += ", " + args;
call += "); }\n";
return call;
}
@)
}