1cb93a386Sopenharmony_ci/*
2cb93a386Sopenharmony_ci * Copyright 2021 Google LLC
3cb93a386Sopenharmony_ci *
4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be
5cb93a386Sopenharmony_ci * found in the LICENSE file.
6cb93a386Sopenharmony_ci */
7cb93a386Sopenharmony_ci
8cb93a386Sopenharmony_ci#include "src/sksl/SkSLContext.h"
9cb93a386Sopenharmony_ci#include "src/sksl/ir/SkSLChildCall.h"
10cb93a386Sopenharmony_ci
11cb93a386Sopenharmony_cinamespace SkSL {
12cb93a386Sopenharmony_ci
13cb93a386Sopenharmony_cibool ChildCall::hasProperty(Property property) const {
14cb93a386Sopenharmony_ci    for (const auto& arg : this->arguments()) {
15cb93a386Sopenharmony_ci        if (arg->hasProperty(property)) {
16cb93a386Sopenharmony_ci            return true;
17cb93a386Sopenharmony_ci        }
18cb93a386Sopenharmony_ci    }
19cb93a386Sopenharmony_ci    return false;
20cb93a386Sopenharmony_ci}
21cb93a386Sopenharmony_ci
22cb93a386Sopenharmony_cistd::unique_ptr<Expression> ChildCall::clone() const {
23cb93a386Sopenharmony_ci    ExpressionArray cloned;
24cb93a386Sopenharmony_ci    cloned.reserve_back(this->arguments().size());
25cb93a386Sopenharmony_ci    for (const std::unique_ptr<Expression>& arg : this->arguments()) {
26cb93a386Sopenharmony_ci        cloned.push_back(arg->clone());
27cb93a386Sopenharmony_ci    }
28cb93a386Sopenharmony_ci    return std::make_unique<ChildCall>(fLine, &this->type(), &this->child(), std::move(cloned));
29cb93a386Sopenharmony_ci}
30cb93a386Sopenharmony_ci
31cb93a386Sopenharmony_ciString ChildCall::description() const {
32cb93a386Sopenharmony_ci    String result = String(this->child().name()) + ".eval(";
33cb93a386Sopenharmony_ci    String separator;
34cb93a386Sopenharmony_ci    for (const std::unique_ptr<Expression>& arg : this->arguments()) {
35cb93a386Sopenharmony_ci        result += separator;
36cb93a386Sopenharmony_ci        result += arg->description();
37cb93a386Sopenharmony_ci        separator = ", ";
38cb93a386Sopenharmony_ci    }
39cb93a386Sopenharmony_ci    result += ")";
40cb93a386Sopenharmony_ci    return result;
41cb93a386Sopenharmony_ci}
42cb93a386Sopenharmony_ci
43cb93a386Sopenharmony_ci[[maybe_unused]] static bool call_signature_is_valid(const Context& context,
44cb93a386Sopenharmony_ci                                                     const Variable& child,
45cb93a386Sopenharmony_ci                                                     const ExpressionArray& arguments) {
46cb93a386Sopenharmony_ci    const Type* half4 = context.fTypes.fHalf4.get();
47cb93a386Sopenharmony_ci    const Type* float2 = context.fTypes.fFloat2.get();
48cb93a386Sopenharmony_ci
49cb93a386Sopenharmony_ci    auto params = [&]() -> SkSTArray<2, const Type*> {
50cb93a386Sopenharmony_ci        switch (child.type().typeKind()) {
51cb93a386Sopenharmony_ci            case Type::TypeKind::kBlender:     return { half4, half4 };
52cb93a386Sopenharmony_ci            case Type::TypeKind::kColorFilter: return { half4 };
53cb93a386Sopenharmony_ci            case Type::TypeKind::kShader:      return { float2 };
54cb93a386Sopenharmony_ci            default:
55cb93a386Sopenharmony_ci                SkUNREACHABLE;
56cb93a386Sopenharmony_ci        }
57cb93a386Sopenharmony_ci    }();
58cb93a386Sopenharmony_ci
59cb93a386Sopenharmony_ci    if (params.size() != arguments.size()) {
60cb93a386Sopenharmony_ci        return false;
61cb93a386Sopenharmony_ci    }
62cb93a386Sopenharmony_ci    for (size_t i = 0; i < arguments.size(); i++) {
63cb93a386Sopenharmony_ci        if (arguments[i]->type() != *params[i]) {
64cb93a386Sopenharmony_ci            return false;
65cb93a386Sopenharmony_ci        }
66cb93a386Sopenharmony_ci    }
67cb93a386Sopenharmony_ci    return true;
68cb93a386Sopenharmony_ci}
69cb93a386Sopenharmony_ci
70cb93a386Sopenharmony_cistd::unique_ptr<Expression> ChildCall::Make(const Context& context,
71cb93a386Sopenharmony_ci                                            int line,
72cb93a386Sopenharmony_ci                                            const Type* returnType,
73cb93a386Sopenharmony_ci                                            const Variable& child,
74cb93a386Sopenharmony_ci                                            ExpressionArray arguments) {
75cb93a386Sopenharmony_ci    SkASSERT(call_signature_is_valid(context, child, arguments));
76cb93a386Sopenharmony_ci    return std::make_unique<ChildCall>(line, returnType, &child, std::move(arguments));
77cb93a386Sopenharmony_ci}
78cb93a386Sopenharmony_ci
79cb93a386Sopenharmony_ci}  // namespace SkSL
80