//
// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// UnfoldShortCircuit is an AST traverser to output short-circuiting operators as if-else statements.
// The results are assigned to s# temporaries, which are used by the main translator instead of
// the original expression.
//

#include "compiler/UnfoldShortCircuit.h"

#include "compiler/InfoSink.h"
#include "compiler/OutputHLSL.h"

namespace sh
{
UnfoldShortCircuit::UnfoldShortCircuit(TParseContext &context, OutputHLSL *outputHLSL) : mContext(context), mOutputHLSL(outputHLSL)
{
    mTemporaryIndex = 0;
}

void UnfoldShortCircuit::traverse(TIntermNode *node)
{
    int rewindIndex = mTemporaryIndex;
    node->traverse(this);
    mTemporaryIndex = rewindIndex;
}

bool UnfoldShortCircuit::visitBinary(Visit visit, TIntermBinary *node)
{
    TInfoSinkBase &out = mOutputHLSL->getBodyStream();

    switch (node->getOp())
    {
      case EOpLogicalOr:
        // "x || y" is equivalent to "x ? true : y", which unfolds to "bool s; if(x) s = true; else s = y;",
        // and then further simplifies down to "bool s = x; if(!s) s = y;".
        {
            int i = mTemporaryIndex;

            out << "bool s" << i << ";\n";

            out << "{\n";

            mTemporaryIndex = i + 1;
            node->getLeft()->traverse(this);
            out << "s" << i << " = ";
            mTemporaryIndex = i + 1;
            node->getLeft()->traverse(mOutputHLSL);
            out << ";\n";
            out << "if(!s" << i << ")\n"
                   "{\n";
            mTemporaryIndex = i + 1;
            node->getRight()->traverse(this);
            out << "    s" << i << " = ";
            mTemporaryIndex = i + 1;
            node->getRight()->traverse(mOutputHLSL);
            out << ";\n"
                   "}\n";

            out << "}\n";

            mTemporaryIndex = i + 1;
        }
        return false;
      case EOpLogicalAnd:
        // "x && y" is equivalent to "x ? y : false", which unfolds to "bool s; if(x) s = y; else s = false;",
        // and then further simplifies down to "bool s = x; if(s) s = y;".
        {
            int i = mTemporaryIndex;

            out << "bool s" << i << ";\n";

            out << "{\n";

            mTemporaryIndex = i + 1;
            node->getLeft()->traverse(this);
            out << "s" << i << " = ";
            mTemporaryIndex = i + 1;
            node->getLeft()->traverse(mOutputHLSL);
            out << ";\n";
            out << "if(s" << i << ")\n"
                   "{\n";
            mTemporaryIndex = i + 1;
            node->getRight()->traverse(this);
            out << "    s" << i << " = ";
            mTemporaryIndex = i + 1;
            node->getRight()->traverse(mOutputHLSL);
            out << ";\n"
                   "}\n";

            out << "}\n";

            mTemporaryIndex = i + 1;
        }
        return false;
      default:
        return true;
    }
}

bool UnfoldShortCircuit::visitSelection(Visit visit, TIntermSelection *node)
{
    TInfoSinkBase &out = mOutputHLSL->getBodyStream();

    // Unfold "b ? x : y" into "type s; if(b) s = x; else s = y;"
    if (node->usesTernaryOperator())
    {
        int i = mTemporaryIndex;

        out << mOutputHLSL->typeString(node->getType()) << " s" << i << ";\n";

        out << "{\n";

        mTemporaryIndex = i + 1;
        node->getCondition()->traverse(this);
        out << "if(";
        mTemporaryIndex = i + 1;
        node->getCondition()->traverse(mOutputHLSL);
        out << ")\n"
               "{\n";
        mTemporaryIndex = i + 1;
        node->getTrueBlock()->traverse(this);
        out << "    s" << i << " = ";
        mTemporaryIndex = i + 1;
        node->getTrueBlock()->traverse(mOutputHLSL);
        out << ";\n"
               "}\n"
               "else\n"
               "{\n";
        mTemporaryIndex = i + 1;
        node->getFalseBlock()->traverse(this);
        out << "    s" << i << " = ";
        mTemporaryIndex = i + 1;
        node->getFalseBlock()->traverse(mOutputHLSL);
        out << ";\n"
               "}\n";

        out << "}\n";

        mTemporaryIndex = i + 1;
    }

    return false;
}

bool UnfoldShortCircuit::visitLoop(Visit visit, TIntermLoop *node)
{
    int rewindIndex = mTemporaryIndex;

    if (node->getInit())
    {
        node->getInit()->traverse(this);
    }
    
    if (node->getCondition())
    {
        node->getCondition()->traverse(this);
    }

    if (node->getExpression())
    {
        node->getExpression()->traverse(this);
    }

    mTemporaryIndex = rewindIndex;

    return false;
}

int UnfoldShortCircuit::getNextTemporaryIndex()
{
    return mTemporaryIndex++;
}
}
