/*
 * Copyright 2020 Google LLC
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#ifndef SkSLAnalysis_DEFINED
#define SkSLAnalysis_DEFINED

#include "include/core/SkSpan.h"
#include "include/private/SkSLDefines.h"
#include "include/private/SkSLSampleUsage.h"

#include <memory>

namespace SkSL {

class ErrorReporter;
class Expression;
class ForStatement;
class FunctionDeclaration;
class FunctionDefinition;
struct LoadedModule;
struct Program;
class ProgramElement;
class ProgramUsage;
class Statement;
struct LoopUnrollInfo;
class Variable;
class VariableReference;
enum class VariableRefKind : int8_t;

/**
 * Provides utilities for analyzing SkSL statically before it's composed into a full program.
 */
struct Analysis {
    /**
     * Determines how `program` samples `child`. By default, assumes that the sample coords
     * (SK_MAIN_COORDS_BUILTIN) might be modified, so `child.eval(sampleCoords)` is treated as
     * Explicit. If writesToSampleCoords is false, treats that as PassThrough, instead.
     * If elidedSampleCoordCount is provided, the pointed to value will be incremented by the
     * number of sample calls where the above rewrite was performed.
     */
    static SampleUsage GetSampleUsage(const Program& program,
                                      const Variable& child,
                                      bool writesToSampleCoords = true,
                                      int* elidedSampleCoordCount = nullptr);

    static bool ReferencesBuiltin(const Program& program, int builtin);

    static bool ReferencesSampleCoords(const Program& program);
    static bool ReferencesFragCoords(const Program& program);

    static bool CallsSampleOutsideMain(const Program& program);

    /**
     * Computes the size of the program in a completely flattened state--loops fully unrolled,
     * function calls inlined--and rejects programs that exceed an arbitrary upper bound. This is
     * intended to prevent absurdly large programs from overwhemling SkVM. Only strict-ES2 mode is
     * supported; complex control flow is not SkVM-compatible (and this becomes the halting problem)
     */
    static bool CheckProgramUnrolledSize(const Program& program);

    /**
     * Detect an orphaned variable declaration outside of a scope, e.g. if (true) int a;. Returns
     * true if an error was reported.
     */
    static bool DetectVarDeclarationWithoutScope(const Statement& stmt,
                                                 ErrorReporter* errors = nullptr);

    static int NodeCountUpToLimit(const FunctionDefinition& function, int limit);

    /**
     * Finds unconditional exits from a switch-case. Returns true if this statement unconditionally
     * causes an exit from this switch (via continue, break or return).
     */
    static bool SwitchCaseContainsUnconditionalExit(Statement& stmt);

    /**
     * A switch-case "falls through" when it doesn't have an unconditional exit.
     */
    static bool SwitchCaseFallsThrough(Statement& stmt) {
        return !SwitchCaseContainsUnconditionalExit(stmt);
    }

    /**
     * Finds conditional exits from a switch-case. Returns true if this statement contains a
     * conditional that wraps a potential exit from the switch (via continue, break or return).
     */
    static bool SwitchCaseContainsConditionalExit(Statement& stmt);

    static std::unique_ptr<ProgramUsage> GetUsage(const Program& program);
    static std::unique_ptr<ProgramUsage> GetUsage(const LoadedModule& module);

    static bool StatementWritesToVariable(const Statement& stmt, const Variable& var);

    struct AssignmentInfo {
        VariableReference* fAssignedVar = nullptr;
    };
    static bool IsAssignable(Expression& expr, AssignmentInfo* info = nullptr,
                             ErrorReporter* errors = nullptr);

    // Updates the `refKind` field of the VariableReference at the top level of `expr`.
    // If `expr` can be assigned to (`IsAssignable`), true is returned and no errors are reported.
    // If not, false is returned. and an error is reported if `errors` is non-null.
    static bool UpdateVariableRefKind(Expression* expr, VariableRefKind kind,
                                      ErrorReporter* errors = nullptr);

    // A "trivial" expression is one where we'd feel comfortable cloning it multiple times in
    // the code, without worrying about incurring a performance penalty. Examples:
    // - true
    // - 3.14159265
    // - myIntVariable
    // - myColor.rgb
    // - myArray[123]
    // - myStruct.myField
    // - half4(0)
    //
    // Trivial-ness is stackable. Somewhat large expressions can occasionally make the cut:
    // - half4(myColor.a)
    // - myStruct.myArrayField[7].xyz
    static bool IsTrivialExpression(const Expression& expr);

    // Returns true if both expression trees are the same. Used by the optimizer to look for self-
    // assignment or self-comparison; won't necessarily catch complex cases. Rejects expressions
    // that may cause side effects.
    static bool IsSameExpressionTree(const Expression& left, const Expression& right);

    // Is 'expr' a constant-expression, as defined by GLSL 1.0, section 5.10? A constant expression
    // is one of:
    //
    // - A literal value
    // - A global or local variable qualified as 'const', excluding function parameters
    // - An expression formed by an operator on operands that are constant expressions, including
    //   getting an element of a constant vector or a constant matrix, or a field of a constant
    //   structure
    // - A constructor whose arguments are all constant expressions
    //
    // GLSL (but not SkSL, yet - skbug.com/10835) also provides:
    // - A built-in function call whose arguments are all constant expressions, with the exception
    //   of the texture lookup functions
    static bool IsConstantExpression(const Expression& expr);

    // Ensures that a for-loop meets the strict requirements of The OpenGL ES Shading Language 1.00,
    // Appendix A, Section 4.
    // If the requirements are met, information about the loop's structure is returned.
    // If the requirements are not met, the problem is reported via `errors` (if not nullptr), and
    // null is returned.
    static std::unique_ptr<LoopUnrollInfo> GetLoopUnrollInfo(int offset,
                                                             const Statement* loopInitializer,
                                                             const Expression* loopTest,
                                                             const Expression* loopNext,
                                                             const Statement* loopStatement,
                                                             ErrorReporter* errors);

    static void ValidateIndexingForES2(const ProgramElement& pe, ErrorReporter& errors);

    // Detects functions that fail to return a value on at least one path.
    static bool CanExitWithoutReturningValue(const FunctionDeclaration& funcDecl,
                                             const Statement& body);

    // Searches for @if/@switch statements that didn't optimize away, or dangling
    // FunctionReference or TypeReference expressions, and reports them as errors.
    static void VerifyStaticTestsAndExpressions(const Program& program);
};

/**
 * Utility class to visit every element, statement, and expression in an SkSL program IR.
 * This is intended for simple analysis and accumulation, where custom visitation behavior is only
 * needed for a limited set of expression kinds.
 *
 * Subclasses should override visitExpression/visitStatement/visitProgramElement as needed and
 * intercept elements of interest. They can then invoke the base class's function to visit all
 * sub expressions. They can also choose not to call the base function to arrest recursion, or
 * implement custom recursion.
 *
 * The visit functions return a bool that determines how the default implementation recurses. Once
 * any visit call returns true, the default behavior stops recursing and propagates true up the
 * stack.
 */
template <typename T>
class TProgramVisitor {
public:
    virtual ~TProgramVisitor() = default;

protected:
    virtual bool visitExpression(typename T::Expression& expression);
    virtual bool visitStatement(typename T::Statement& statement);
    virtual bool visitProgramElement(typename T::ProgramElement& programElement);

    virtual bool visitExpressionPtr(typename T::UniquePtrExpression& expr) = 0;
    virtual bool visitStatementPtr(typename T::UniquePtrStatement& stmt) = 0;
};

// ProgramVisitors take const types; ProgramWriters do not.
struct ProgramVisitorTypes {
    using Program = const SkSL::Program;
    using Expression = const SkSL::Expression;
    using Statement = const SkSL::Statement;
    using ProgramElement = const SkSL::ProgramElement;
    using UniquePtrExpression = const std::unique_ptr<SkSL::Expression>;
    using UniquePtrStatement = const std::unique_ptr<SkSL::Statement>;
};

struct ProgramWriterTypes {
    using Program = SkSL::Program;
    using Expression = SkSL::Expression;
    using Statement = SkSL::Statement;
    using ProgramElement = SkSL::ProgramElement;
    using UniquePtrExpression = std::unique_ptr<SkSL::Expression>;
    using UniquePtrStatement = std::unique_ptr<SkSL::Statement>;
};

// Squelch bogus Clang warning about template vtables: https://bugs.llvm.org/show_bug.cgi?id=18733
#if defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wweak-template-vtables"
#endif
extern template class TProgramVisitor<ProgramVisitorTypes>;
extern template class TProgramVisitor<ProgramWriterTypes>;
#if defined(__clang__)
#pragma clang diagnostic pop
#endif

class ProgramVisitor : public TProgramVisitor<ProgramVisitorTypes> {
public:
    bool visit(const Program& program);

private:
    // ProgramVisitors shouldn't need access to unique_ptrs, and marking these as final should help
    // these accessors inline away. Use ProgramWriter if you need the unique_ptrs.
    bool visitExpressionPtr(const std::unique_ptr<Expression>& e) final {
        return this->visitExpression(*e);
    }
    bool visitStatementPtr(const std::unique_ptr<Statement>& s) final {
        return this->visitStatement(*s);
    }
};

class ProgramWriter : public TProgramVisitor<ProgramWriterTypes> {
public:
    // Subclass these methods if you want access to the unique_ptrs of IRNodes in a program.
    // This will allow statements or expressions to be replaced during a visit.
    bool visitExpressionPtr(std::unique_ptr<Expression>& e) override {
        return this->visitExpression(*e);
    }
    bool visitStatementPtr(std::unique_ptr<Statement>& s) override {
        return this->visitStatement(*s);
    }
};

}  // namespace SkSL

#endif
