// FIXME: does not integrate with recursive session method calls: recursionEnter/Exit and also
  // recurse do not match the control flow of recursive calls, and hence runtime type monitoring
  // does not work.
  private Node translateSJRecursion(SJRecursion r, QQ qq)
        // recursionEnter inserted by node factory, but translation is finished here..
      {
    SJSessionOperationExt soe = getSJSessionOperationExt(r);

    Position pos = r.position();

    Collection<Object> mapping = new LinkedList<Object>();

    String bname = getRecursionBooleanName(soe.targetNames(), r.label());

    mapping.add(bname);
    mapping.add(bname);

    String translation = "for (boolean %s = true; %s; ) { }";
    For f = (For) qq.parseStmt(translation, mapping.toArray());

    mapping.clear();

    r = (SJRecursion) r.inits(f.inits());
    r = (SJRecursion) r.cond(f.cond());

    List stmts = new LinkedList();

    stmts.addAll(r.body().statements());

    translation = "%s = %E;";
    mapping.add(bname);
    mapping.add(((Eval) stmts.remove(0)).expr()); // Factor out constant.

    Eval e = (Eval) qq.parseStmt(translation, mapping.toArray());

    stmts.add(0, e);

    r = (SJRecursion) r.body(sjnf.Block(pos, stmts));

    /*// Appending the recursion-exit hook. // Disabled to support delegation from within recursion scopes (socket will be null on recursion-exit).
    List<Local> targets = new LinkedList<Local>(); // FIXME: should be SJLocalSockets.

    for (String sjname : soe.targetNames()) // Unicast optimisation for SJRecursionExit is done within the NodeFactory method - this pass comes after SJUnicastOptimiser.
    {
    	targets.add(sjnf.Local(pos, sjnf.Id(pos, sjname))); // Would it be bad to instead alias the recursionEnter targets?
    }

    SJRecursionExit re = sjnf.SJRecursionExit(pos, targets); // Problem: the sockets argument array is not yet filled (for other (internal) basic operations, this was done earlier by SJSessionOperationParser)...

    re = (SJRecursionExit) SJVariableParser.parseSJSessionOperation(this, re); // ...Current fix: use those routines form those earlier passes.
    re = (SJRecursionExit) SJSessionOperationParser.fixSJBasicOperationArguments(this, re);*/

    // return sjnf.Block(pos, r, sjnf.Eval(pos, re));
    return sjnf.Block(pos, r);
  }
  private Node translateSJInbranch(SJInbranch ib, QQ qq) {
    StringBuilder translation = new StringBuilder("{ ");
    Collection<Object> mapping = new LinkedList<Object>();

    String labVar = UniqueID.newID(SJ_INBRANCH_LABEL_FIELD_PREFIX);

    translation.append("%T %s = %E; ");
    mapping.add(qq.parseType(SJ_LABEL_CLASS));
    mapping.add(labVar);
    mapping.add(ib.inlabel());

    for (Iterator<SJInbranchCase> i = ib.branchCases().iterator(); i.hasNext(); ) {
      SJInbranchCase ibc = i.next();

      translation.append("if (%s.equals(%E)) { %LS } ");
      mapping.add(labVar);
      mapping.add(sjnf.StringLit(ib.position(), ibc.label().labelValue()));
      mapping.add(ibc.statements());

      if (i.hasNext()) {
        translation.append("else ");
      }
    }

    translation.append("else { throw new SJIOException(\"Unexpected inbranch label: \" + %s); }");
    mapping.add(labVar);

    // FIXME: need a final else case to better handle, if runtime monitoring is disabled,
    // non-sj-compatibility mode and in case of malicious peers.

    translation.append('}');

    return qq.parseStmt(translation.toString(), mapping.toArray());
  }