/*
 * 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 "src/sksl/SkSLUtil.h"
#include "src/sksl/ir/SkSLExpression.h"

namespace SkSL {

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
