/*
 * 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/ir/SkSLConstructorComposite.h"

#include <algorithm>
#include <numeric>

namespace SkSL {

std::unique_ptr<Expression> ConstructorComposite::Make(const Context& context,
                                                       int offset,
                                                       const Type& type,
                                                       ExpressionArray args) {
    // A scalar "composite" type with a single scalar argument is a no-op and can be eliminated.
    // (Pedantically, this isn't a composite 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.)
    if (type.isScalar() && args.size() == 1 && args.front()->type() == type) {
        return std::move(args.front());
    }

    // The type must be a vector or matrix, and all the arguments must have matching component type.
    SkASSERT(type.isVector() || type.isMatrix());
    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() == 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();
                             }));

    if (context.fConfig->fSettings.fOptimize) {
        // Find ConstructorComposites embedded inside other ConstructorComposites 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<ConstructorComposite>()
                              ? arg->as<ConstructorComposite>().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-ConstructorComposite fields, move them over as-is.
                if (!arg->is<ConstructorComposite>()) {
                    flattened.push_back(std::move(arg));
                    continue;
                }
                // For ConstructorComposite fields, move over their inner arguments individually.
                ConstructorComposite& compositeCtor = arg->as<ConstructorComposite>();
                for (std::unique_ptr<Expression>& innerArg : compositeCtor.arguments()) {
                    flattened.push_back(std::move(innerArg));
                }
            }
            args = std::move(flattened);
        }
    }

    return std::make_unique<ConstructorComposite>(offset, type, std::move(args));
}

}  // namespace SkSL
