package som.interpreter.nodes.specialized;

import som.interpreter.nodes.BinaryMessageNode;
import som.vm.Universe;
import som.vmobjects.SAbstractObject;
import som.vmobjects.SBlock;
import som.vmobjects.SMethod;
import som.vmobjects.SObject;
import som.vmobjects.SSymbol;

import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.frame.VirtualFrame;


public abstract class IfFalseMessageNode extends BinaryMessageNode  {
  public IfFalseMessageNode(final SSymbol selector, final Universe universe) { super(selector, universe); }
  public IfFalseMessageNode(final IfFalseMessageNode node) { this(node.selector, node.universe); }

  /**
   * This is the case were we got a block as the argument. Need to actually
   * evaluate it.
   */
  @Specialization(order = 1)
  public SAbstractObject doIfFalse(final VirtualFrame frame,
      final boolean receiver, final SBlock argument) {
    if (!receiver) {
      SMethod blockMethod = argument.getMethod();
      SBlock b = universe.newBlock(blockMethod, frame.materialize(), 1);
      return blockMethod.invoke(frame.pack(), b, noArgs);
    } else {
      return universe.nilObject;
    }
  }

  @Specialization(guards = "isBooleanReceiver", order = 2)
  public SAbstractObject doIfFalse(final VirtualFrame frame,
      final SObject receiver, final SBlock argument) {
    return doIfFalse(frame, receiver == universe.falseObject, argument);
  }

  /**
   * The argument in this case is an expression and can be returned directly.
   */
  @Specialization(order = 10)
  public SAbstractObject doIfFalse(final VirtualFrame frame,
      final boolean receiver, final SAbstractObject argument) {
    if (!receiver) {
      return argument;
    } else {
      return universe.nilObject;
    }
  }


  @Specialization(guards = "isBooleanReceiver", order = 11)
  public SAbstractObject doIfFalse(final VirtualFrame frame,
      final SObject receiver, final SAbstractObject argument) {
    return doIfFalse(frame, receiver == universe.falseObject, argument);
  }
}

@@ -1324,32 +1324,129 @@
 ock argument) %7B%0A
+    // additional %60not%60/! because doIfFalse is implemented to take a boolean and check for false%0A
     return doIfF
@@ -1449,32 +1449,34 @@
 oIfFalse(frame, 
+!(
 receiver == univ
@@ -1483,32 +1483,33 @@
 erse.falseObject
+)
 , argument);%0A  %7D

Fix bug in IfFalse node