/*
 * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
package com.oracle.truffle.sl.nodes.controlflow;

import com.oracle.truffle.api.dsl.*;
import com.oracle.truffle.api.frame.*;
import com.oracle.truffle.api.nodes.*;
import com.oracle.truffle.api.source.*;
import com.oracle.truffle.api.utilities.*;
import com.oracle.truffle.sl.nodes.*;

@NodeInfo(shortName = "if", description = "The node implementing a condional statement")
public final class SLIfNode extends SLStatementNode {

    /**
     * The condition of the {@code if}. This in a {@link SLExpressionNode} because we require a
     * result value. We do not have a node type that can only return a {@code boolean} value, so
     * {@link #evaluateCondition executing the condition} can lead to a type error.
     */
    @Child private SLExpressionNode conditionNode;

    /** Statement (or {@link SLBlockNode block}) executed when the condition is true. */
    @Child private SLStatementNode thenPartNode;

    /** Statement (or {@link SLBlockNode block}) executed when the condition is false. */
    @Child private SLStatementNode elsePartNode;

    /**
     * Profiling information, collected by the interpreter, capturing whether the then-branch was
     * used (analogously for the {@link #elseTaken else-branch}). This allows the compiler to
     * generate better code for conditions that are always true or always false.
     */
    private final BranchProfile thenTaken = new BranchProfile();
    private final BranchProfile elseTaken = new BranchProfile();

    public SLIfNode(SourceSection src, SLExpressionNode conditionNode, SLStatementNode thenPartNode, SLStatementNode elsePartNode) {
        super(src);
        this.conditionNode = conditionNode;
        this.thenPartNode = thenPartNode;
        this.elsePartNode = elsePartNode;
    }

    @Override
    public void executeVoid(VirtualFrame frame) {
        if (evaluateCondition(frame)) {
            /* In the interpreter, record profiling information that the then-branch was used. */
            thenTaken.enter();
            /* Execute the then-branch. */
            thenPartNode.executeVoid(frame);
        } else {
            /* In the interpreter, record profiling information that the else-branch was used. */
            elseTaken.enter();
            /* Execute the else-branch (which is optional according to the SL syntax). */
            if (elsePartNode != null) {
                elsePartNode.executeVoid(frame);
            }
        }
    }

    private boolean evaluateCondition(VirtualFrame frame) {
        try {
            /*
             * The condition must evaluate to a boolean value, so we call the boolean-specialized
             * execute method.
             */
            return conditionNode.executeBoolean(frame);
        } catch (UnexpectedResultException ex) {
            /*
             * The condition evaluated to a non-boolean result. This is a type error in the SL
             * program. We report it with the same exception that Truffle DSL generated nodes use to
             * report type errors.
             */
            throw new UnsupportedSpecializationException(this, new Node[]{conditionNode}, ex.getResult());
        }
    }
}

@@ -2187,100 +2187,57 @@
 ing 
-whether the then-branch was%0A     * used (analogously for the %7B@link #elseTaken else-branch%7D)
+the profiling information of%0A     * the condition
 . Th
@@ -2261,23 +2261,16 @@
 piler to
-%0A     *
  generat
@@ -2306,16 +2306,23 @@
 that are
+%0A     *
  always 
@@ -2346,136 +2346,296 @@
 lse.
-%0A     */%0A    private final BranchProfile thenTaken = new BranchProfile();%0A    private final BranchProfile elseTaken = new Branch
+ Additionally the %7B@link IntegerConditionProfile%7D implementation%0A     * (as opposed to %7B@link BooleanConditionProfile%7D implementation) transmits the probability of%0A     * the condition to be true to the compiler.%0A     */%0A    private final ConditionProfile condition = new IntegerCondition
 Prof
@@ -3006,39 +3006,10 @@
     
-if (evaluateCondition(frame)) %7B
+/*
 %0A   
@@ -3006,36 +3006,32 @@
     /*%0A         
-   /
 * In the interpr
@@ -3078,63 +3078,136 @@
 the 
-then-branch was used. */%0A
+condition was executed and with%0A         * which outcome.%0A   
      
+ */%0A
        
-thenTaken.enter();
+ if (condition.profile(evaluateCondition(frame))) %7B
 %0A   
@@ -3312,137 +3312,8 @@
 e %7B%0A
-            /* In the interpreter, record profiling information that the else-branch was used. */%0A            elseTaken.enter();%0A
     

use the new IntegerConditionProfile in simple language.