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

#ifndef SKSL_IRNODE
#define SKSL_IRNODE

#include "include/sksl/SkSLPosition.h"
#include "src/sksl/SkSLPool.h"

#include <string>

namespace SkSL {

// The fKind field of IRNode could contain any of these values.
enum class ProgramElementKind {
    kExtension = 0,
    kFunction,
    kFunctionPrototype,
    kGlobalVar,
    kInterfaceBlock,
    kModifiers,
    kStructDefinition,

    kFirst = kExtension,
    kLast = kStructDefinition
};

enum class SymbolKind {
    kExternal = (int) ProgramElementKind::kLast + 1,
    kField,
    kFunctionDeclaration,
    kType,
    kVariable,

    kFirst = kExternal,
    kLast = kVariable
};

enum class StatementKind {
    kBlock = (int) SymbolKind::kLast + 1,
    kBreak,
    kContinue,
    kDiscard,
    kDo,
    kExpression,
    kFor,
    kIf,
    kNop,
    kReturn,
    kSwitch,
    kSwitchCase,
    kVarDeclaration,

    kFirst = kBlock,
    kLast = kVarDeclaration,
};

enum class ExpressionKind {
    kBinary = (int) StatementKind::kLast + 1,
    kChildCall,
    kConstructorArray,
    kConstructorArrayCast,
    kConstructorCompound,
    kConstructorCompoundCast,
    kConstructorDiagonalMatrix,
    kConstructorMatrixResize,
    kConstructorScalarCast,
    kConstructorSplat,
    kConstructorStruct,
    kExternalFunctionCall,
    kExternalFunctionReference,
    kFieldAccess,
    kFunctionReference,
    kFunctionCall,
    kIndex,
    kLiteral,
    kMethodReference,
    kPoison,
    kPostfix,
    kPrefix,
    kSetting,
    kSwizzle,
    kTernary,
    kTypeReference,
    kVariableReference,

    kFirst = kBinary,
    kLast = kVariableReference
};

/**
 * Represents a node in the intermediate representation (IR) tree. The IR is a fully-resolved
 * version of the program (all types determined, everything validated), ready for code generation.
 */
class IRNode : public Poolable {
public:
    virtual ~IRNode() {}

    virtual std::string description() const = 0;

    // No copy construction or assignment
    IRNode(const IRNode&) = delete;
    IRNode& operator=(const IRNode&) = delete;

    // position of this element within the program being compiled, for error reporting purposes
    Position fPosition;

    /**
     *  Use is<T> to check the type of an IRNode.
     *  e.g. replace `s.kind() == Statement::Kind::kReturn` with `s.is<ReturnStatement>()`.
     */
    template <typename T>
    bool is() const {
        return this->fKind == (int)T::kIRNodeKind;
    }

    /**
     *  Use as<T> to downcast IRNodes.
     *  e.g. replace `(ReturnStatement&) s` with `s.as<ReturnStatement>()`.
     */
    template <typename T>
    const T& as() const {
        SkASSERT(this->is<T>());
        return static_cast<const T&>(*this);
    }

    template <typename T>
    T& as() {
        SkASSERT(this->is<T>());
        return static_cast<T&>(*this);
    }

protected:
    IRNode(Position position, int kind)
        : fPosition(position)
        , fKind(kind) {}

    int fKind;
};

}  // namespace SkSL

#endif
