1/* 2 * Copyright 2021 Google LLC 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8#include "src/sksl/ir/SkSLConstructorStruct.h" 9 10#include "include/sksl/SkSLErrorReporter.h" 11#include "src/sksl/SkSLContext.h" 12 13namespace SkSL { 14 15std::unique_ptr<Expression> ConstructorStruct::Convert(const Context& context, 16 int line, 17 const Type& type, 18 ExpressionArray args) { 19 SkASSERTF(type.isStruct() && type.fields().size() > 0, "%s", type.description().c_str()); 20 21 // Check that the number of constructor arguments matches the array size. 22 if (type.fields().size() != args.size()) { 23 context.fErrors->error(line, 24 String::printf("invalid arguments to '%s' constructor " 25 "(expected %zu elements, but found %zu)", 26 type.displayName().c_str(), type.fields().size(), 27 args.size())); 28 return nullptr; 29 } 30 31 // Convert each constructor argument to the struct's field type. 32 for (int index=0; index<args.count(); ++index) { 33 std::unique_ptr<Expression>& argument = args[index]; 34 const Type::Field& field = type.fields()[index]; 35 36 argument = field.fType->coerceExpression(std::move(argument), context); 37 if (!argument) { 38 return nullptr; 39 } 40 } 41 42 return ConstructorStruct::Make(context, line, type, std::move(args)); 43} 44 45[[maybe_unused]] static bool arguments_match_field_types(const ExpressionArray& args, 46 const Type& type) { 47 SkASSERT(type.fields().size() == args.size()); 48 49 for (int index = 0; index < args.count(); ++index) { 50 const std::unique_ptr<Expression>& argument = args[index]; 51 const Type::Field& field = type.fields()[index]; 52 if (argument->type() != *field.fType) { 53 return false; 54 } 55 } 56 57 return true; 58} 59 60std::unique_ptr<Expression> ConstructorStruct::Make(const Context& context, 61 int line, 62 const Type& type, 63 ExpressionArray args) { 64 SkASSERT(type.isAllowedInES2(context)); 65 SkASSERT(arguments_match_field_types(args, type)); 66 return std::make_unique<ConstructorStruct>(line, type, std::move(args)); 67} 68 69} // namespace SkSL 70