In this post I look at how basic rewrite rules fail when dealing with side effects, as well as exploring possible solutions.

Short-Circuiting Operators

Consider the following method shortCircuit().

boolean shortCircuit(boolean cond) {
    return cond || getBoolWithSideEffects();
}

Listing 1: A short circuiting operator that may or may not trigger side effects

Currently Cornelius serializes this as if the right hand side is always executed. Instead I need to handle the short circuiting.

For instance, this would serialize to something like

(return-node 
  (|| (var cond) (invoke->peg (invoke getBoolWithSideEffects (var this) actuals heap)))
  (invoke->heap 
      (invoke getBoolWithSideEffects (var this) actuals heap)))

Listing 2: Buggy serialized output

Instead this should serialize to something like this:

(return-node 
  (|| (var cond) (invoke->peg (invoke getBoolWithSideEffects (var this) actuals heap)))
  (phi (var cond)
    (heap 0 unit)
    (invoke->heap 
      (invoke getBoolWithSideEffects (var this) actuals (heap 0 unit)))))

Commutativity

How does commutativity work here? It should actually just play out the same as in my previous post.