/*
 * 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 "src/sksl/dsl/priv/DSLWriter.h"

#include "include/core/SkTypes.h"
#include "include/private/SkSLDefines.h"
#include "include/private/SkSLProgramElement.h"
#include "include/private/SkSLStatement.h"
#include "include/sksl/DSLCore.h"
#include "include/sksl/DSLExpression.h"
#include "include/sksl/DSLModifiers.h"
#include "include/sksl/DSLStatement.h"
#include "include/sksl/DSLSymbols.h"
#include "include/sksl/DSLType.h"
#include "include/sksl/DSLVar.h"
#include "include/sksl/SkSLPosition.h"
#include "src/sksl/SkSLMangler.h"
#include "src/sksl/SkSLModifiersPool.h"
#include "src/sksl/SkSLProgramSettings.h"
#include "src/sksl/SkSLThreadContext.h"
#include "src/sksl/ir/SkSLBlock.h"
#include "src/sksl/ir/SkSLExpression.h"
#include "src/sksl/ir/SkSLNop.h"
#include "src/sksl/ir/SkSLType.h"
#include "src/sksl/ir/SkSLVarDeclarations.h"
#include "src/sksl/ir/SkSLVariable.h"

#include <string>
#include <type_traits>
#include <utility>
#include <vector>

namespace SkSL {

namespace dsl {

bool DSLWriter::ManglingEnabled() {
    return ThreadContext::Instance().fSettings.fDSLMangling;
}

std::string_view DSLWriter::Name(std::string_view name) {
    if (ManglingEnabled()) {
        const std::string* s = ThreadContext::SymbolTable()->takeOwnershipOfString(
                ThreadContext::Instance().fMangler.uniqueName(name,
                    ThreadContext::SymbolTable().get()));
        return s->c_str();
    }
    return name;
}

const SkSL::Variable* DSLWriter::Var(DSLVarBase& var) {
    // fInitialized is true if we have attempted to create a var, whether or not we actually
    // succeeded. If it's true, we don't want to try again, to avoid reporting the same error
    // multiple times.
    if (!var.fInitialized) {
        // We haven't even attempted to create a var yet, so fVar ought to be null
        SkASSERT(!var.fVar);
        var.fInitialized = true;
        if (var.storage() != SkSL::VariableStorage::kParameter) {
            const SkSL::Type* baseType = &var.fType.skslType();
            if (baseType->isArray()) {
                baseType = &baseType->componentType();
            }
        }
        std::unique_ptr<SkSL::Variable> skslvar = SkSL::Variable::Convert(ThreadContext::Context(),
                var.fPosition, var.fModifiers.fPosition, var.fModifiers.fModifiers,
                &var.fType.skslType(), var.fNamePosition, var.fName, /*isArray=*/false,
                /*arraySize=*/nullptr, var.storage());
        SkSL::Variable* varPtr = skslvar.get();
        if (var.storage() != SkSL::VariableStorage::kParameter) {
            var.fDeclaration = VarDeclaration::Convert(ThreadContext::Context(), std::move(skslvar),
                    var.fInitialValue.releaseIfPossible(), /*addToSymbolTable=*/false);
            if (var.fDeclaration) {
                var.fVar = varPtr;
                var.fInitialized = true;
            }
        }
        ThreadContext::ReportErrors(var.fPosition);
    }
    return var.fVar;
}

std::unique_ptr<SkSL::Variable> DSLWriter::CreateParameterVar(DSLParameter& var) {
    // This should only be called on undeclared parameter variables, but we allow the creation to go
    // ahead regardless so we don't have to worry about null pointers potentially sneaking in and
    // breaking things. DSLFunction is responsible for reporting errors for invalid parameters.
    return SkSL::Variable::Convert(ThreadContext::Context(), var.fPosition,
            var.fModifiers.fPosition, var.fModifiers.fModifiers, &var.fType.skslType(),
            var.fNamePosition, var.fName, /*isArray=*/false, /*arraySize=*/nullptr, var.storage());
}

std::unique_ptr<SkSL::Statement> DSLWriter::Declaration(DSLVarBase& var) {
    Var(var);
    if (!var.fDeclaration) {
        // We should have already reported an error before ending up here, just clean up the
        // initial value so it doesn't assert and return a nop.
        var.fInitialValue.releaseIfPossible();
        return SkSL::Nop::Make();
    }
    return std::move(var.fDeclaration);
}

void DSLWriter::MarkDeclared(DSLVarBase& var) {
    SkASSERT(!var.fDeclared);
    var.fDeclared = true;
}

bool DSLWriter::MarkVarsDeclared() {
    return ThreadContext::Instance().fSettings.fDSLMarkVarsDeclared;
}

void DSLWriter::AddVarDeclaration(DSLStatement& existing, DSLVar& additional) {
    if (existing.fStatement->is<Block>()) {
        SkSL::Block& block = existing.fStatement->as<Block>();
        SkASSERT(!block.isScope());
        block.children().push_back(Declare(additional).release());
    } else if (existing.fStatement->is<VarDeclaration>()) {
        Position pos = existing.fStatement->fPosition;
        StatementArray stmts;
        stmts.reserve_back(2);
        stmts.push_back(std::move(existing.fStatement));
        stmts.push_back(Declare(additional).release());
        existing.fStatement = SkSL::Block::Make(pos, std::move(stmts),
                                                Block::Kind::kCompoundStatement);
    } else if (existing.fStatement->isEmpty()) {
        // If the variable declaration generated an error, we can end up with a Nop statement here.
        existing.fStatement = Declare(additional).release();
    }
}

#if !defined(SKSL_STANDALONE) && SK_SUPPORT_GPU
GrGLSLUniformHandler::UniformHandle DSLWriter::VarUniformHandle(const DSLGlobalVar& var) {
    return GrGLSLUniformHandler::UniformHandle(var.fUniformHandle);
}
#endif

void DSLWriter::Reset() {
    dsl::PopSymbolTable();
    dsl::PushSymbolTable();
    ThreadContext::ProgramElements().clear();
    ThreadContext::GetModifiersPool()->clear();
}

} // namespace dsl

} // namespace SkSL
