/*
 * Copyright 2021 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/DSLFunction.h"

#include "include/sksl/DSLVar.h"
#include "src/sksl/SkSLAnalysis.h"
#include "src/sksl/SkSLCompiler.h"
#include "src/sksl/SkSLIRGenerator.h"
#include "src/sksl/dsl/priv/DSLWriter.h"
#include "src/sksl/ir/SkSLReturnStatement.h"

namespace SkSL {

namespace dsl {

void DSLFunction::init(const DSLType& returnType, const char* name,
                       std::vector<DSLVar*> params) {
    std::vector<const Variable*> paramVars;
    paramVars.reserve(params.size());
    bool isMain = !strcmp(name, "main");
    auto typeIsValidForColor = [&](const SkSL::Type& type) {
        return type == *DSLWriter::Context().fTypes.fHalf4 ||
               type == *DSLWriter::Context().fTypes.fFloat4;
    };
    for (DSLVar* param : params) {
        // This counts as declaring the variable; make sure it hasn't been previously declared and
        // then kill its pending declaration statement. Otherwise the statement will hang around
        // until after the Var is destroyed, which is probably after the End() call and therefore
        // after the Pool's destruction. Freeing a pooled object after the Pool's destruction is a
        // Bad Thing.
        if (param->fDeclared) {
            DSLWriter::ReportError("error: using an already-declared variable as a function "
                                   "parameter\n");
        }
        if (param->fInitialValue.release()) {
            DSLWriter::ReportError("error: variables used as function parameters cannot have "
                                   "initial values\n");
        }
        param->fDeclared = true;
        param->fStorage = SkSL::VariableStorage::kParameter;
        if (paramVars.empty()) {
            SkSL::ProgramKind kind = DSLWriter::Context().fConfig->fKind;
            if (isMain && (kind == ProgramKind::kRuntimeColorFilter ||
                           kind == ProgramKind::kRuntimeShader ||
                           kind == ProgramKind::kFragmentProcessor)) {
                const SkSL::Type& type = param->fType.skslType();
                // We verify that the signature is fully correct later. For now, if this is an .fp
                // or runtime effect of any flavor, a float2 param is supposed to be the coords, and
                // a half4/float parameter is supposed to be the input color:
                if (type == *DSLWriter::Context().fTypes.fFloat2) {
                    param->fModifiers.fModifiers.fLayout.fBuiltin = SK_MAIN_COORDS_BUILTIN;
                } else if (typeIsValidForColor(type)) {
                    param->fModifiers.fModifiers.fLayout.fBuiltin = SK_INPUT_COLOR_BUILTIN;
                }
            }
        }
        paramVars.push_back(&DSLWriter::Var(*param));
        param->fDeclaration = nullptr;
    }
    SkSL::SymbolTable& symbols = *DSLWriter::SymbolTable();
    fDecl = symbols.add(std::make_unique<SkSL::FunctionDeclaration>(
                                             /*offset=*/-1,
                                             DSLWriter::Modifiers(SkSL::Modifiers()),
                                             isMain ? name : DSLWriter::Name(name),
                                             std::move(paramVars), fReturnType,
                                             /*builtin=*/false));
}

void DSLFunction::define(DSLBlock block) {
    SkASSERT(fDecl);
    SkASSERTF(!fDecl->definition(), "function '%s' already defined", fDecl->description().c_str());
    std::unique_ptr<Statement> body = block.release();
    DSLWriter::IRGenerator().finalizeFunction(*fDecl, body.get());
    auto function = std::make_unique<SkSL::FunctionDefinition>(/*offset=*/-1, fDecl,
                                                               /*builtin=*/false, std::move(body));
    if (DSLWriter::Compiler().errorCount()) {
        DSLWriter::ReportError(DSLWriter::Compiler().errorText(/*showCount=*/false).c_str());
        DSLWriter::Compiler().setErrorCount(0);
        SkASSERT(!DSLWriter::Compiler().errorCount());
    }
    fDecl->fDefinition = function.get();
    DSLWriter::ProgramElements().push_back(std::move(function));
}

DSLExpression DSLFunction::call(SkTArray<DSLExpression> args) {
    ExpressionArray released;
    released.reserve_back(args.size());
    for (DSLExpression& arg : args) {
        released.push_back(arg.release());
    }
    return DSLWriter::Call(*fDecl, std::move(released));
}

} // namespace dsl

} // namespace SkSL
