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; @)
	}
}