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

#include "include/sksl/DSLVar.h"

#include "include/sksl/DSLModifiers.h"
#include "include/sksl/DSLType.h"
#include "src/sksl/SkSLCompiler.h"
#include "src/sksl/SkSLUtil.h"
#include "src/sksl/dsl/priv/DSLWriter.h"
#include "src/sksl/ir/SkSLBinaryExpression.h"
#include "src/sksl/ir/SkSLSymbolTable.h"
#include "src/sksl/ir/SkSLVariable.h"
#include "src/sksl/ir/SkSLVariableReference.h"

namespace SkSL {

namespace dsl {

DSLVar::DSLVar(const char* name)
    : fType(kVoid_Type)
    , fRawName(name)
    , fName(name)
    , fDeclared(true) {
#if SK_SUPPORT_GPU && !defined(SKSL_STANDALONE)
    if (!strcmp(name, "sk_SampleCoord")) {
        fName = DSLWriter::CurrentEmitArgs()->fSampleCoord;
        // The actual sk_SampleCoord variable hasn't been created by GrGLSLFPFragmentBuilder yet, so
        // if we attempt to look it up in the symbol table we'll get null. As we are currently
        // converting all DSL code into strings rather than nodes, all we really need is a
        // correctly-named variable with the right type, so we just create a placeholder for it.
        // TODO(skia/11330): we'll need to fix this when switching over to nodes.
        fVar = DSLWriter::SymbolTable()->takeOwnershipOfIRNode(
                std::make_unique<SkSL::Variable>(
                        /*offset=*/-1,
                        DSLWriter::IRGenerator().fModifiers->addToPool(
                                SkSL::Modifiers(
                                        SkSL::Layout(/*flags=*/0, /*location=*/-1, /*offset=*/-1,
                                                     /*binding=*/-1, /*index=*/-1, /*set=*/-1,
                                                     SK_MAIN_COORDS_BUILTIN,
                                                     /*inputAttachmentIndex=*/-1,
                                                     Layout::kUnspecified_Primitive,
                                                     /*maxVertices=*/1, /*invocations=*/-1,
                                                     /*marker=*/"", /*when=*/"",
                                                     Layout::CType::kDefault),
                                        SkSL::Modifiers::kNo_Flag)),
                        fName,
                        DSLWriter::Context().fTypes.fFloat2.get(),
                        /*builtin=*/true,
                        SkSL::VariableStorage::kGlobal));
        return;
    }
#endif
    const SkSL::Symbol* result = (*DSLWriter::SymbolTable())[fName];
    SkASSERTF(result, "could not find '%s' in symbol table", fName);
    fVar = &result->as<SkSL::Variable>();
}

DSLVar::DSLVar(DSLType type, const char* name, DSLExpression initialValue)
    : DSLVar(DSLModifiers(), std::move(type), name, std::move(initialValue)) {}

DSLVar::DSLVar(DSLType type, DSLExpression initialValue)
    : DSLVar(type, "var", std::move(initialValue)) {}

DSLVar::DSLVar(DSLModifiers modifiers, DSLType type, DSLExpression initialValue)
    : DSLVar(modifiers, type, "var", std::move(initialValue)) {}

DSLVar::DSLVar(DSLModifiers modifiers, DSLType type, const char* name, DSLExpression initialValue)
    : fModifiers(std::move(modifiers))
    , fType(std::move(type))
    , fRawName(name)
    , fName(fType.skslType().isOpaque() ? name : DSLWriter::Name(name))
    , fInitialValue(std::move(initialValue))
    , fStorage(Variable::Storage::kLocal)
    , fDeclared(DSLWriter::Instance().fMarkVarsDeclared) {
#if SK_SUPPORT_GPU && !defined(SKSL_STANDALONE)
    if (fModifiers.fModifiers.fFlags & Modifiers::kUniform_Flag) {
        fStorage = Variable::Storage::kGlobal;
        if (DSLWriter::InFragmentProcessor()) {
            const SkSL::Type& skslType = type.skslType();
            GrSLType grslType;
            int count;
            if (skslType.isArray()) {
                SkAssertResult(SkSL::type_to_grsltype(DSLWriter::Context(),
                                                      skslType.componentType(),
                                                      &grslType));
                count = skslType.columns();
                SkASSERT(count > 0);
            } else {
                SkAssertResult(SkSL::type_to_grsltype(DSLWriter::Context(), skslType,
                                                      &grslType));
                count = 0;
            }
            const char* name;
            SkASSERT(DSLWriter::CurrentEmitArgs());
            fUniformHandle = DSLWriter::CurrentEmitArgs()->fUniformHandler->addUniformArray(
                                                                 &DSLWriter::CurrentEmitArgs()->fFp,
                                                                 kFragment_GrShaderFlag,
                                                                 grslType,
                                                                 this->name(),
                                                                 count,
                                                                 &name).toIndex();
            fName = name;
        }
        fDeclared = true;
    }
#endif // SK_SUPPORT_GPU && !defined(SKSL_STANDALONE)
}

DSLVar::~DSLVar() {
    if (!fDeclared) {
        DSLWriter::ReportError(String::printf("error: variable '%s' was destroyed without being "
                                              "declared\n", fRawName).c_str());
    }
}

DSLPossibleExpression DSLVar::operator[](DSLExpression&& index) {
    return DSLExpression(*this)[std::move(index)];
}

DSLPossibleExpression DSLVar::operator=(DSLExpression expr) {
    return DSLWriter::ConvertBinary(DSLExpression(*this).release(), SkSL::Token::Kind::TK_EQ,
                                    expr.release());
}

} // namespace dsl

} // namespace SkSL
