/*
 * 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_FIELDACCESS
#define SKSL_FIELDACCESS

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

#include <cstdint>
#include <memory>
#include <string>
#include <string_view>
#include <utility>
#include <vector>

namespace SkSL {

class Context;
class SymbolTable;

enum class FieldAccessOwnerKind : int8_t {
    kDefault,
    // this field access is to a field of an anonymous interface block (and thus, the field name
    // is actually in global scope, so only the field name needs to be written in GLSL)
    kAnonymousInterfaceBlock
};

/**
 * An expression which extracts a field from a struct, as in 'foo.bar'.
 */
class FieldAccess final : public Expression {
public:
    using OwnerKind = FieldAccessOwnerKind;

    inline static constexpr Kind kExpressionKind = Kind::kFieldAccess;

    FieldAccess(Position pos, std::unique_ptr<Expression> base, int fieldIndex,
                OwnerKind ownerKind = OwnerKind::kDefault)
    : INHERITED(pos, kExpressionKind, base->type().fields()[fieldIndex].fType)
    , fFieldIndex(fieldIndex)
    , fOwnerKind(ownerKind)
    , fBase(std::move(base)) {}

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

    // Returns a field-access expression; reports errors via ASSERT.
    static std::unique_ptr<Expression> Make(const Context& context,
                                            Position pos,
                                            std::unique_ptr<Expression> base,
                                            int fieldIndex,
                                            OwnerKind ownerKind = OwnerKind::kDefault);

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

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

    int fieldIndex() const {
        return fFieldIndex;
    }

    OwnerKind ownerKind() const {
        return fOwnerKind;
    }

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

    std::unique_ptr<Expression> clone(Position pos) const override {
        return std::make_unique<FieldAccess>(pos,
                                             this->base()->clone(),
                                             this->fieldIndex(),
                                             this->ownerKind());
    }

    std::string description() const override {
        return this->base()->description() + "." +
               std::string(this->base()->type().fields()[this->fieldIndex()].fName);
    }

private:
    int fFieldIndex;
    FieldAccessOwnerKind fOwnerKind;
    std::unique_ptr<Expression> fBase;

    using INHERITED = Expression;
};

}  // namespace SkSL

#endif
