//
// Copyright (c) 2016 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.
//
// SplitSequenceOperator is an AST traverser that detects sequence operator expressions that
// go through further AST transformations that generate statements, and splits them so that
// possible side effects of earlier parts of the sequence operator expression are guaranteed to be
// evaluated before the latter parts of the sequence operator expression are evaluated.
//

#include "compiler/translator/SplitSequenceOperator.h"

#include "compiler/translator/IntermNode.h"
#include "compiler/translator/IntermNodePatternMatcher.h"

namespace sh
{

namespace
{

class SplitSequenceOperatorTraverser : public TLValueTrackingTraverser
{
  public:
    SplitSequenceOperatorTraverser(unsigned int patternsToSplitMask,
                                   const TSymbolTable &symbolTable,
                                   int shaderVersion);

    bool visitBinary(Visit visit, TIntermBinary *node) override;
    bool visitAggregate(Visit visit, TIntermAggregate *node) override;
    bool visitTernary(Visit visit, TIntermTernary *node) override;

    void nextIteration();
    bool foundExpressionToSplit() const { return mFoundExpressionToSplit; }

  protected:
    // Marked to true once an operation that needs to be hoisted out of the expression has been
    // found. After that, no more AST updates are performed on that traversal.
    bool mFoundExpressionToSplit;
    int mInsideSequenceOperator;

    IntermNodePatternMatcher mPatternToSplitMatcher;
};

SplitSequenceOperatorTraverser::SplitSequenceOperatorTraverser(unsigned int patternsToSplitMask,
                                                               const TSymbolTable &symbolTable,
                                                               int shaderVersion)
    : TLValueTrackingTraverser(true, false, true, symbolTable, shaderVersion),
      mFoundExpressionToSplit(false),
      mInsideSequenceOperator(0),
      mPatternToSplitMatcher(patternsToSplitMask)
{
}

void SplitSequenceOperatorTraverser::nextIteration()
{
    mFoundExpressionToSplit = false;
    mInsideSequenceOperator = 0;
    nextTemporaryIndex();
}

bool SplitSequenceOperatorTraverser::visitAggregate(Visit visit, TIntermAggregate *node)
{
    if (mFoundExpressionToSplit)
        return false;

    if (mInsideSequenceOperator > 0 && visit == PreVisit)
    {
        // Detect expressions that need to be simplified
        mFoundExpressionToSplit = mPatternToSplitMatcher.match(node, getParentNode());
        return !mFoundExpressionToSplit;
    }

    return true;
}

bool SplitSequenceOperatorTraverser::visitBinary(Visit visit, TIntermBinary *node)
{
    if (node->getOp() == EOpComma)
    {
        if (visit == PreVisit)
        {
            if (mFoundExpressionToSplit)
            {
                return false;
            }
            mInsideSequenceOperator++;
        }
        else if (visit == PostVisit)
        {
            // Split sequence operators starting from the outermost one to preserve correct
            // execution order.
            if (mFoundExpressionToSplit && mInsideSequenceOperator == 1)
            {
                // Move the left side operand into a separate statement in the parent block.
                TIntermSequence insertions;
                insertions.push_back(node->getLeft());
                insertStatementsInParentBlock(insertions);
                // Replace the comma node with its right side operand.
                queueReplacement(node, node->getRight(), OriginalNode::IS_DROPPED);
            }
            mInsideSequenceOperator--;
        }
        return true;
    }

    if (mFoundExpressionToSplit)
        return false;

    if (mInsideSequenceOperator > 0 && visit == PreVisit)
    {
        // Detect expressions that need to be simplified
        mFoundExpressionToSplit =
            mPatternToSplitMatcher.match(node, getParentNode(), isLValueRequiredHere());
        return !mFoundExpressionToSplit;
    }

    return true;
}

bool SplitSequenceOperatorTraverser::visitTernary(Visit visit, TIntermTernary *node)
{
    if (mFoundExpressionToSplit)
        return false;

    if (mInsideSequenceOperator > 0 && visit == PreVisit)
    {
        // Detect expressions that need to be simplified
        mFoundExpressionToSplit = mPatternToSplitMatcher.match(node);
        return !mFoundExpressionToSplit;
    }

    return true;
}

}  // namespace

void SplitSequenceOperator(TIntermNode *root,
                           int patternsToSplitMask,
                           unsigned int *temporaryIndex,
                           const TSymbolTable &symbolTable,
                           int shaderVersion)
{
    SplitSequenceOperatorTraverser traverser(patternsToSplitMask, symbolTable, shaderVersion);
    ASSERT(temporaryIndex != nullptr);
    traverser.useTemporaryIndex(temporaryIndex);
    // Separate one expression at a time, and reset the traverser between iterations.
    do
    {
        traverser.nextIteration();
        root->traverse(&traverser);
        if (traverser.foundExpressionToSplit())
            traverser.updateTree();
    } while (traverser.foundExpressionToSplit());
}

}  // namespace sh
