/*
 * Copyright (C) 2019 Apple Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 * THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "config.h"
#include "WHLSLStatementBehaviorChecker.h"

#if ENABLE(WEBGPU)

#include "WHLSLBlock.h"
#include "WHLSLBreak.h"
#include "WHLSLContinue.h"
#include "WHLSLDoWhileLoop.h"
#include "WHLSLEffectfulExpressionStatement.h"
#include "WHLSLFallthrough.h"
#include "WHLSLForLoop.h"
#include "WHLSLIfStatement.h"
#include "WHLSLInferTypes.h"
#include "WHLSLProgram.h"
#include "WHLSLReturn.h"
#include "WHLSLSwitchCase.h"
#include "WHLSLSwitchStatement.h"
#include "WHLSLVariableDeclarationsStatement.h"
#include "WHLSLVisitor.h"
#include "WHLSLWhileLoop.h"
#include <cstdint>
#include <wtf/OptionSet.h>
#include <wtf/Vector.h>

namespace WebCore {

namespace WHLSL {

class StatementBehaviorChecker : public Visitor {
public:
    enum class Behavior : uint8_t {
        Return = 1 << 0,
        Break = 1 << 1,
        Continue = 1 << 2,
        Fallthrough = 1 << 3,
        Nothing = 1 << 4
    };

    OptionSet<Behavior> takeFunctionBehavior()
    {
        ASSERT(m_stack.size() == 1);
        return m_stack.takeLast();
    }

private:
    void visit(AST::Break&) override
    {
        m_stack.append({ Behavior::Break });
    }

    void visit(AST::Fallthrough&) override
    {
        m_stack.append({ Behavior::Fallthrough });
    }

    void visit(AST::Continue&) override
    {
        m_stack.append({ Behavior::Continue });
    }

    void visit(AST::Return&) override
    {
        m_stack.append({ Behavior::Return });
    }

    void visit(AST::DoWhileLoop& doWhileLoop) override
    {
        checkErrorAndVisit(doWhileLoop.body());
        if (hasError())
            return;
        auto b = m_stack.takeLast();
        b.remove(Behavior::Break);
        b.remove(Behavior::Continue);
        b.add(Behavior::Nothing);
        m_stack.append(b);
    }

    void visit(AST::ForLoop& forLoop) override
    {
        // The initialization always has a behavior of Nothing, which we already add unconditionally below,
        // so we can just ignore the initialization.

        checkErrorAndVisit(forLoop.body());
        if (hasError())
            return;
        auto b = m_stack.takeLast();
        b.remove(Behavior::Break);
        b.remove(Behavior::Continue);
        b.add(Behavior::Nothing);
        m_stack.append(b);
    }

    void visit(AST::WhileLoop& whileLoop) override
    {
        checkErrorAndVisit(whileLoop.body());
        if (hasError())
            return;
        auto b = m_stack.takeLast();
        b.remove(Behavior::Break);
        b.remove(Behavior::Continue);
        b.add(Behavior::Nothing);
        m_stack.append(b);
    }

    void visit(AST::SwitchCase& switchCase) override
    {
        Visitor::visit(switchCase);
    }

    void visit(AST::SwitchStatement& switchStatement) override
    {
        if (switchStatement.switchCases().isEmpty()) {
            m_stack.append({ Behavior::Nothing });
            return;
        }

        OptionSet<Behavior> reduction = { };
        for (auto& switchCase : switchStatement.switchCases()) {
            checkErrorAndVisit(switchCase);
            if (hasError())
                return;
            auto b = m_stack.takeLast();
            reduction = reduction | b;
        }
        if (reduction.contains(Behavior::Nothing)) {
            setError(Error("Switch statement must end in a break/fallthrough/return", switchStatement.codeLocation()));
            return;
        }
        reduction.remove(Behavior::Break);
        reduction.remove(Behavior::Fallthrough);
        reduction.add(Behavior::Nothing);
        m_stack.append(reduction);
    }

    void visit(AST::IfStatement& ifStatement) override
    {
        checkErrorAndVisit(ifStatement.body());
        if (hasError())
            return;
        auto b = m_stack.takeLast();
        OptionSet<Behavior> bPrime;
        if (ifStatement.elseBody()) {
            checkErrorAndVisit(*ifStatement.elseBody());
            if (hasError())
                return;
            bPrime = m_stack.takeLast();
        } else
            bPrime = { Behavior::Nothing };
        m_stack.append(b | bPrime);
    }

    void visit(AST::EffectfulExpressionStatement&) override
    {
        m_stack.append({ Behavior::Nothing });
    }

    void visit(AST::Block& block) override
    {
        if (block.statements().isEmpty()) {
            m_stack.append({ Behavior::Nothing });
            return;
        }

        OptionSet<Behavior> reduction = { };
        for (size_t i = 0; i < block.statements().size() - 1; ++i) {
            checkErrorAndVisit(block.statements()[i]);
            if (hasError())
                return;
            auto b = m_stack.takeLast();
            if (!b.contains(Behavior::Nothing)) {
                setError(Error("Statement inside an inner block must be reachable.", block.statements()[i]->codeLocation()));
                return;
            }
            b.remove(Behavior::Nothing);
            if (b.contains(Behavior::Fallthrough)) {
                setError(Error("Fallthrough must be the last statement in a block.", block.statements()[i]->codeLocation()));
                return;
            }
            reduction = reduction | b;
        }
        checkErrorAndVisit(block.statements()[block.statements().size() - 1]);
        if (hasError())
            return;
        auto b = m_stack.takeLast();
        m_stack.append(reduction | b);
    }

    void visit(AST::VariableDeclarationsStatement&) override
    {
        m_stack.append({ Behavior::Nothing });
    }

    Vector<OptionSet<Behavior>> m_stack;
};

Expected<void, Error> checkStatementBehavior(Program& program)
{
    StatementBehaviorChecker statementBehaviorChecker;
    for (auto& functionDefinition : program.functionDefinitions()) {
        statementBehaviorChecker.Visitor::visit(functionDefinition);
        if (statementBehaviorChecker.hasError())
            return statementBehaviorChecker.result();
        auto behavior = statementBehaviorChecker.takeFunctionBehavior();
        if (matches(functionDefinition->type(), program.intrinsics().voidType())) {
            behavior.remove(StatementBehaviorChecker::Behavior::Return);
            behavior.remove(StatementBehaviorChecker::Behavior::Nothing);
            if (behavior != OptionSet<StatementBehaviorChecker::Behavior>())
                return makeUnexpected(Error("Cannot end a void function with a break, continue, or fallthrough."));
        } else {
            if (behavior != StatementBehaviorChecker::Behavior::Return)
                return makeUnexpected(Error("Non-void functions must return a value on all code paths."));
        }
    }
    return { };
}

} // namespace WHLSL

} // namespace WebCore

#endif // ENABLE(WEBGPU)
