/*
 * 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_INDEX
#define SKSL_INDEX

#include "include/sksl/SkSLPosition.h"
#include "src/sksl/ir/SkSLExpression.h"

#include <memory>
#include <string>
#include <utility>

namespace SkSL {

class Context;
class SymbolTable;
class Type;

/**
 * An expression which extracts a value from an array or matrix, as in 'm[2]'.
 */
struct IndexExpression final : public Expression {
    inline static constexpr Kind kExpressionKind = Kind::kIndex;

    IndexExpression(const Context& context, Position pos, std::unique_ptr<Expression> base,
                    std::unique_ptr<Expression> index)
        : INHERITED(pos, kExpressionKind, &IndexType(context, base->type()))
        , fBase(std::move(base))
        , fIndex(std::move(index)) {}

    // Returns a simplified index-expression; reports errors via the ErrorReporter.
    static std::unique_ptr<Expression> Convert(const Context& context,
                                               SymbolTable& symbolTable,
                                               Position pos,
                                               std::unique_ptr<Expression> base,
                                               std::unique_ptr<Expression> index);

    // Returns a simplified index-expression; reports errors via ASSERT.
    static std::unique_ptr<Expression> Make(const Context& context,
                                            Position pos,
                                            std::unique_ptr<Expression> base,
                                            std::unique_ptr<Expression> index);

    /**
     * Given a type, returns the type that will result from extracting an array value from it.
     */
    static const Type& IndexType(const Context& context, const Type& type);

    std::unique_ptr<Expression>& base() {
        return fBase;
    }

    const std::unique_ptr<Expression>& base() const {
        return fBase;
    }

    std::unique_ptr<Expression>& index() {
        return fIndex;
    }

    const std::unique_ptr<Expression>& index() const {
        return fIndex;
    }

    bool hasProperty(Property property) const override {
        return this->base()->hasProperty(property) || this->index()->hasProperty(property);
    }

    std::unique_ptr<Expression> clone(Position pos) const override {
        return std::unique_ptr<Expression>(new IndexExpression(pos, this->base()->clone(),
                                                               this->index()->clone(),
                                                               &this->type()));
    }

    std::string description() const override {
        return this->base()->description() + "[" + this->index()->description() + "]";
    }

    using INHERITED = Expression;

private:
    IndexExpression(Position pos, std::unique_ptr<Expression> base,
                    std::unique_ptr<Expression> index, const Type* type)
        : INHERITED(pos, Kind::kIndex, type)
        , fBase(std::move(base))
        , fIndex(std::move(index)) {}

    std::unique_ptr<Expression> fBase;
    std::unique_ptr<Expression> fIndex;
};

}  // namespace SkSL

#endif
