Program: 59784
Project: 59784
Buggy source:
/** 
 * Try to inline the body of a block (a ()->T lambda), for use as a block body in target code. If successful, a string containing the generated code is returned, otherwise null. Inlining succeeds if the term   {@link #derefToLambda dereferences to a lambda}, or failing that if the fallbackToCall param is true, in which case a single statement containing a call to the lambda is returned. So given a block <pre><code> f = { a(1); b(2); c(3) } </code></pre> then in the former case the returned string will amount to <pre><code> "a(1); b(2); c(3)" </code></pre> and in the latter case <pre><code> "f()" </code></pre> The fallback allows us to inline control flow even when arguments can't be dereferenced to lambda literals, eg <pre><code> if(c, t, f) => if (c) { t(); } else { f(); } </code></pre> ...which empirically seems worth it. Note that as implied by the "Stmts" in the name, we are implicitly generating code to be used in a non-expression context. This means that we don't need to return the block's result value, only execute the expression that produces it.
 */
static String formatBlockStmts(final StatementFormatter fmt,final Term block,final boolean fallbackToCall){
  final Loc loc=block.getLoc();
  final Type type=block.getType();
  final Type resultType=Types.funResult(type);
  final String call;
{
    if (fallbackToCall) {
      final Term body=new ApplyTerm(loc,block,TupleTerm.UNIT);
      body.setType(resultType);
      call=fmt.formatTermAs(body,resultType);
    }
 else {
      fmt.formatTermAs(block,block.getType());
      call=null;
    }
  }
  final LambdaTerm blockDeref=derefToLambda(block);
  if (blockDeref == null)   return call;
  final ArrayList<String> bodyStmts=new ArrayList<String>();
  for (  final Statement statement : blockDeref.getNonResultStatements())   bodyStmts.add(fmt.formatInLambdaStatement(statement));
  final UnboundTerm result=blockDeref.getResultStatement();
  if (!result.getValue().equals(TupleTerm.UNIT))   bodyStmts.add(fmt.formatInLambdaStatement(result));
  return StringUtils.join(bodyStmts,"String_Node_Str");
}

Fixed version (ground truth):
/** 
 * Try to inline the body of a block-typed term (a ()->T lambda), for use as a block body in target code. If successful, a string containing the generated code is returned, otherwise null. Inlining succeeds if the term   {@link #derefToLambda dereferences toa lambda}, or failing that if the fallbackToCall param is true and the term   {@link #isImmediate is immediate}, meaning that obtaining its value involves no computation*. In this case a single statement containing a call to the lambda is returned. (The term must be immediate because use-cases may place the returned call in conditional code, which would alter the semantics of the original if there were computation involved.) So given a block <pre><code> f = { a(1); b(2); c(3) } </code></pre> then in the former case the returned string will amount to <pre><code> "a(1); b(2); c(3)" </code></pre> and in the latter case <pre><code> "f()" </code></pre> The fallback allows us to inline control flow even when arguments can't be statically dereferenced to lambda literals, eg <pre><code> if(c, t, f) => if (c) { t(); } else { f(); } </code></pre> ...which empirically seems worth it. Note that as implied by the "Stmts" in the name, we are implicitly generating code to be used in a non-expression context. This means that we don't need to return the block's result value, only execute the expression that produces it.
 */
static String formatBlockStmts(final StatementFormatter fmt,final Term block,final boolean fallbackToCall){
  final Loc loc=block.getLoc();
  final Type type=block.getType();
  final Type resultType=Types.funResult(type);
  final String call;
{
    if (fallbackToCall && isImmediate(block)) {
      final Term body=new ApplyTerm(loc,block,TupleTerm.UNIT);
      body.setType(resultType);
      call=fmt.formatTermAs(body,resultType);
    }
 else {
      fmt.formatTermAs(block,block.getType());
      call=null;
    }
  }
  final LambdaTerm blockDeref=derefToLambda(block);
  if (blockDeref == null)   return call;
  final ArrayList<String> bodyStmts=new ArrayList<String>();
  for (  final Statement statement : blockDeref.getNonResultStatements())   bodyStmts.add(fmt.formatInLambdaStatement(statement));
  final UnboundTerm result=blockDeref.getResultStatement();
  if (!result.getValue().equals(TupleTerm.UNIT))   bodyStmts.add(fmt.formatInLambdaStatement(result));
  return StringUtils.join(bodyStmts,"String_Node_Str");
}