adapmeth.beh.html
Program{
private void convertAdaptiveMethods()bypassing VisitorSpec via MethodDef to-stop{ MethodSignature, TraversalRef, TraversalSpec, ClassName_Commalist, VisitorSpec }{
(@ ClassGraph cg; @)
before ClassGraph (@ cg = host; @)
(@ ClassDef def; @)
before ClassDef (@ def = host; @)
(@ String body; @)
before MethodDef (@ body = null; @)
(@ MethodSignature sig; @)
before MethodSignature (@ sig = host; @)
(@ TraversalRef trv; TraversalDef trvdef; @)
(@ StrategyExpression strat; @)
before TraversalRef (@
trv = host;
strat = null;
trvdef = def.findTraversalDef(trv);
if (trvdef == null) {
System.err.println("Error: " + sig.get_name() + ":"
+ " No such traversal method: " + trv);
} else if (trvdef.numParms() != 1) {
System.err.println("Error: " + sig.get_name() + ":"
+ " Traversal method " + trv + " has wrong number of parameters");
trvdef = null;
}
@)
before TraversalSpec (@
// Generate a new traversal; add it to the class after we know the
// visitor classes.
String newname = "__trav_" + sig.get_name();
trv = TraversalRef.parse(newname);
strat = host.get_strat();
trvdef = null;
@)
(@ ClassName_Commalist classes; @)
before ClassName_Commalist (@ classes = host; @)
before VisitorSpec (@
// Generate a new visitor class and add it to the class graph.
String newname = "__V_" + def.get_classname() + "_" + sig.get_name();
classes = ClassName_Commalist.parse(newname);
String parts = "";
if (sig.get_parms() != null) {
Enumeration e = sig.get_parms().elements();
while (e.hasMoreElements()) {
MethodParm parm = (MethodParm) e.nextElement();
parts += "<" + parm.get_name() + "> " + parm.get_type() + " ";
}
}
JavaType ret = sig.get_returnType();
if (!ret.isVoid())
if (host.hasReturnValue())
host.setReturnType(ret);
else
parts += "<return_val> " + ret + " ";
String parents = "";
if (trvdef != null) {
// Pre-existing traversal method; make the visitor extend the
// traversal method's argument class.
parents += "*extends* " + trvdef.getVisitorClassName() + " ";
}
ClassDef visdef = ClassDef.parse("*notparsed* *visitor* "
+ newname + " = "
+ parts + parents + host + ".");
cg.addClassDef(visdef);
@)
after AdaptiveMethodBody (@
if (trvdef == null && strat != null) {
trvdef =
TraversalDef.parse("traversal " + trv
+ "(" + classes + ")"
+ "{" + strat + "; }");
trvdef.fillInVisitorNames();
def.addMethod(trvdef);
}
body = "\n";
int i = 0;
Enumeration ve = classes.elements();
boolean first = true;
String args = "";
while (ve.hasMoreElements()) {
ClassName c = (ClassName) ve.nextElement();
body += " " + c + " v" + i + " = new " + c + "();\n";
if (first) first = false; else args += ", ";
args += "v" + i;
i++;
}
if (sig.get_parms() != null) {
Enumeration pe = sig.get_parms().elements();
while (pe.hasMoreElements()) {
MethodParm parm = (MethodParm) pe.nextElement();
ParmName name = parm.get_name();
body += " v0.set_" + name + "(" + name + ");\n";
}
}
body += " " + trv.get_name() + "(" + args + ");\n";
if (!sig.get_returnType().isVoid()) {
body += " return v0.get_return_val();\n";
}
body += " ";
@)
after MethodDef (@
if (body != null)
host.set_methodbody(
VerbatimMethodBody.parse(Text.begin + body + Text.end));
@)
}
}
VisitorSpec{
boolean hasReturnValue()via ClassMethods bypassing VisitorSpec to ReturnValue{
before ReturnValue (@ return_val = true; @)
}
boolean setReturnType(JavaType t)via ClassMethods bypassing VisitorSpec to ReturnValue{
before ReturnValue (@ if (host.get_type() == null) host.set_type(t); @)
}
}
ClassDef{
TraversalDef findTraversalDef(TraversalRef ref)bypassing VisitorSpec to TraversalDef{
before TraversalDef (@
if (host.get_name().equals(ref.get_name())) return_val = host;
@)
}
}
TraversalDef{
int numParms()(@ return parms.size(); @)
ClassName getVisitorClassName()via TraversalParms to ClassName{
before ClassName (@ return_val = host; @)
}
}