wrapper.beh.html
TraversalParms{
String callBefores(Glob glob, boolean indent)(@
return callWrappers(WrapperKind.before, glob, indent, "");
@)
String callArounds(Glob glob, boolean indent, ClassName clname, TraversalMethodName mname, String args)(@
return callWrappers(WrapperKind.around, glob, indent,
Around.makeContinuation(clname, mname, glob, args));
@)
String callAfters(Glob glob, boolean indent)(@
return callWrappers(WrapperKind.after, glob, indent, "");
@)
String callWrappers(WrapperKind kind, Glob glob, boolean indent, String cont)allVisitorNames(WrapperCallGenerator);
}
WrapperCallGenerator{
init (@ return_val = ""; @)
before Visitor (@ visclname = host.get_classname(); @)
before VisitorName (@
ClassDef def = Program.prog.findClassDef(visclname);
if (def == null) {
System.err.println("Error: no such visitor class \"" + visclname + "\"");
} else if (def.hasWrapper(kind, glob)) {
return_val += (indent ? " " : " ")
+ host + "." + kind + glob.methodSuffix()
+ "(" + cont + glob.methodArgs() + ");\n";
}
@)
}
ClassDef{
(@
boolean hasWrapper(WrapperKind kind, Glob glob) {
Hashtable wrapperdict = get_wrapperdict();
if (wrapperdict == null) return false;
HostSet hostset = (HostSet) wrapperdict.get(kind);
if (hostset == null) return false;
return hostset.contains(glob);
}
Hashtable get_wrapperdict() {
return classmethods.get_wrapperdict();
}
@)
}
Program{
void buildVisitorTables()bypassing VisitorSpec via Wrapper to Glob{
(@ Hashtable wrapperdict; @)
before ClassMethods (@ wrapperdict = null; @)
(@ HostSet hostset; @)
before Wrapper (@
WrapperKind kind = host.get_kind();
// wrapperdict is a table of tables, one per wrapper kind.
if (wrapperdict == null) wrapperdict = new Hashtable();
// hostset is a set of hosts that have a wrapper of this kind.
hostset = (HostSet) wrapperdict.get(kind);
if (hostset == null) {
hostset = new HostSet();
wrapperdict.put(kind, hostset);
}
@)
before Glob (@ hostset.add(host); @)
after ClassMethods (@ host.set_wrapperdict(wrapperdict); @)
}
}
HostSet{
void add(Glob host)(@
if (host.isExact())
addExactHost(host);
else if (host.isPartNameGlob())
addPartName(host.get_partname());
else
addGlob(host);
@)
void addExactHost(Glob host)(@
if (exactHosts == null) exactHosts = new Hashtable();
exactHosts.put(host, host);
@)
void addPartName(PartName name)(@
if (partnames == null) partnames = new Hashtable();
partnames.put(name, name);
@)
void addGlob(Glob glob)(@
if (globs == null) globs = new GlobSet();
globs.addElement(glob);
@)
boolean contains(Glob glob)(@
if (exactHosts != null && exactHosts.get(glob) != null) return true;
if (partnames != null && glob instanceof PartGlob &&
partnames.get(glob.get_partname()) != null) return true;
if (globs != null && globs.match(glob)) return true;
return false;
@)
}
WrapperKind{
(@
final static Before before = new Before();
final static Around around = new Around();
final static After after = new After();
@)
}
Glob{
String methodSuffix()to{ ClassGlob, PartName, SubclassGlob, SuperclassGlob }{
before ClassGlob (@ return_val = ""; @)
before PartGlob (@ return_val = "_"; @)
before PartName (@ return_val += host; @)
before SubclassGlob (@ return_val = "_sub"; @)
before SuperclassGlob (@ return_val = "_sup"; @)
}
String methodParms()to{ ClassName, AnyClass, AnyPart }{
init (@ return_val = ""; @)
before ClassName (@ return_val += host; @)
before AnyClass (@ return_val += "Object"; @)
after ClassGlob (@ return_val += " host"; @)
after SourceGlob (@ return_val += " source, "; @)
before AnyPart (@ return_val += "String edge, "; @)
after DestGlob (@ return_val += " dest"; @)
}
String methodArgs()to{ ClassGlob, PartName, SubclassGlob, SuperclassGlob }{
before ClassGlob (@ return_val = "this"; @)
before PartGlob (@ return_val = "this, "; @)
before PartName (@ return_val += host; @)
before{ SubclassGlob, SuperclassGlob }(@ return_val = "this, this"; @)
}
}
HostSpec{
void generateWrapperCode(WrapperKind kind, Text code)to{ ClassNameExact, AnyClass, PartNameExact, AnyPart }{
before Glob (@
Program.out.print(" public void " + kind + host.methodSuffix() + "(");
if (kind instanceof Around)
Program.out.print(Around.absname + " subtraversal, ");
Program.out.println(host.methodParms() + ") {" + code + "}");
@)
}
}
Around{
(@ static final ClassName classname = ClassName.parse("__Subtraversal"); @)
(@ static final ClassName absname = ClassName.parse("AroundContinuation"); @)
static String makeContinuation(ClassName clname, TraversalMethodName name, Glob glob, String args)(@
return "new " + Around.classname
+ "(" + name.aroundName(glob, clname) + ", this, "
+ "new Object[] { " + args + " }), ";
@)
}
Program{
private void addSubtraversalClass()(@
addClassDef(ClassDef.parse(
"*notparsed* " + Around.classname + " = *extends* " + Around.absname + " {"
// get rid of this after converting TAO
+ Text.begin
+ " java.lang.reflect.Method method;\n"
+ " Object object;\n"
+ " Object args[];\n"
+ " "+Around.classname+"(java.lang.reflect.Method m, Object o, Object a[])\n"
+ " { method = m; object = o; args = a; }\n"
+ " public void apply() {\n"
+ " try {\n"
+ " method.invoke(object, args);\n"
+ " } catch (IllegalAccessException e) {\n"
+ " throw new RuntimeException(\"Internal error: \" + e);\n"
+ " } catch (IllegalArgumentException e) {\n"
+ " throw new RuntimeException(\"Internal error: \" + e);\n"
+ " } catch (java.lang.reflect.InvocationTargetException e) {\n"
+ " Throwable t = e.getTargetException();\n"
+ " java.io.StringWriter w = new java.io.StringWriter();\n"
+ " t.printStackTrace(new java.io.PrintWriter(w));\n"
/* An attempt at extracting useful information from the stack trace,
* without being redundant. Didn't work too well.
+ " String s = w.toString();\n"
+ " int i = s.indexOf(\"\\n\");\n"
+ " s = s.substring(0, s.indexOf(\"\\n\", i+1));\n"
+ " throw new RuntimeException(\""+Around.classname+" got exception:\"\n"
+ " + \"\\n\" + t + \"\\n\" + s);\n"
*/
+ " throw new RuntimeException(\""+Around.classname+" got exception:\"\n"
+ " + \"\\n\" + t + \"\\n\" + w);\n"
+ " }\n"
+ " }\n"
+ Text.end
+ "} ."));
@)
}