/*
 * 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 "src/sksl/SkSLConstantFolder.h"
#include "src/sksl/SkSLProgramSettings.h"
#include "src/sksl/ir/SkSLConstructorCompound.h"

#include <algorithm>
#include <numeric>

namespace SkSL {

static bool is_safe_to_eliminate(const Type& type, const Expression& arg) {
    if (type.isScalar()) {
        // A scalar "compound type" with a single scalar argument is a no-op and can be eliminated.
        // (Pedantically, this isn't a compound at all, but it's harmless to allow and simplifies
        // call sites which need to narrow a vector and may sometimes end up with a scalar.)
        SkASSERTF(arg.type().matches(type), "Creating type '%s' from '%s'",
                  type.description().c_str(), arg.type().description().c_str());
        return true;
    }
    if (type.isVector() && arg.type().matches(type)) {
        // A vector compound constructor containing a single argument of matching type can trivially
        // be eliminated.
        return true;
    }
    // This is a meaningful single-argument compound constructor (e.g. vector-from-matrix,
    // matrix-from-vector).
    return false;
}

std::unique_ptr<Expression> ConstructorCompound::Make(const Context& context,
                                                      Position pos,
                                                      const Type& type,
                                                      ExpressionArray args) {
    SkASSERT(type.isAllowedInES2(context));

    // All the arguments must have matching component type.
    SkASSERT(std::all_of(args.begin(), args.end(), [&](const std::unique_ptr<Expression>& arg) {
        const Type& argType = arg->type();
        return (argType.isScalar() || argType.isVector() || argType.isMatrix()) &&
               (argType.componentType().matches(type.componentType()));
    }));

    // The slot count of the combined argument list must match the composite type's slot count.
    SkASSERT(type.slotCount() ==
             std::accumulate(args.begin(), args.end(), /*initial value*/ (size_t)0,
                             [](size_t n, const std::unique_ptr<Expression>& arg) {
                                 return n + arg->type().slotCount();
                             }));
    // No-op compound constructors (containing a single argument of the same type) are eliminated.
    // (Even though this is a "compound constructor," we let scalars pass through here; it's
    // harmless to allow and simplifies call sites which need to narrow a vector and may sometimes
    // end up with a scalar.)
    if (args.size() == 1 && is_safe_to_eliminate(type, *args.front())) {
        args.front()->fPosition = pos;
        return std::move(args.front());
    }
    // Beyond this point, the type must be a vector or matrix.
    SkASSERT(type.isVector() || type.isMatrix());

    if (context.fConfig->fSettings.fOptimize) {
        // Find ConstructorCompounds embedded inside other ConstructorCompounds and flatten them.
        //   -  float4(float2(1, 2), 3, 4)                -->  float4(1, 2, 3, 4)
        //   -  float4(w, float3(sin(x), cos(y), tan(z))) -->  float4(w, sin(x), cos(y), tan(z))
        //   -  mat2(float2(a, b), float2(c, d))          -->  mat2(a, b, c, d)

        // See how many fields we would have if composite constructors were flattened out.
        size_t fields = 0;
        for (const std::unique_ptr<Expression>& arg : args) {
            fields += arg->is<ConstructorCompound>()
                              ? arg->as<ConstructorCompound>().arguments().size()
                              : 1;
        }

        // If we added up more fields than we're starting with, we found at least one input that can
        // be flattened out.
        if (fields > args.size()) {
            ExpressionArray flattened;
            flattened.reserve_back(fields);
            for (std::unique_ptr<Expression>& arg : args) {
                // For non-ConstructorCompound fields, move them over as-is.
                if (!arg->is<ConstructorCompound>()) {
                    flattened.push_back(std::move(arg));
                    continue;
                }
                // For ConstructorCompound fields, move over their inner arguments individually.
                ConstructorCompound& compositeCtor = arg->as<ConstructorCompound>();
                for (std::unique_ptr<Expression>& innerArg : compositeCtor.arguments()) {
                    flattened.push_back(std::move(innerArg));
                }
            }
            args = std::move(flattened);
        }
    }

    // Replace constant variables with their corresponding values, so `float2(one, two)` can
    // compile down to `float2(1.0, 2.0)` (the latter is a compile-time constant).
    for (std::unique_ptr<Expression>& arg : args) {
        arg = ConstantFolder::MakeConstantValueForVariable(pos, std::move(arg));
    }

    return std::make_unique<ConstructorCompound>(pos, type, std::move(args));
}

}  // namespace SkSL
