blob: c758a6b618604fbf3a3dc95120f607013352dc87 [file] [log] [blame]
/*
* 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/SkSLConstructorStruct.h"
#include "include/core/SkTypes.h"
#include "include/private/SkSLString.h"
#include "include/private/SkTArray.h"
#include "include/sksl/SkSLErrorReporter.h"
#include "src/sksl/SkSLContext.h"
#include "src/sksl/ir/SkSLType.h"
#include <string>
#include <vector>
namespace SkSL {
std::unique_ptr<Expression> ConstructorStruct::Convert(const Context& context,
Position pos,
const Type& type,
ExpressionArray args) {
SkASSERTF(type.isStruct() && type.fields().size() > 0, "%s", type.description().c_str());
// Check that the number of constructor arguments matches the array size.
if (type.fields().size() != args.size()) {
context.fErrors->error(pos,
String::printf("invalid arguments to '%s' constructor "
"(expected %zu elements, but found %zu)",
type.displayName().c_str(), type.fields().size(),
args.size()));
return nullptr;
}
// Convert each constructor argument to the struct's field type.
for (int index=0; index<args.count(); ++index) {
std::unique_ptr<Expression>& argument = args[index];
const Type::Field& field = type.fields()[index];
argument = field.fType->coerceExpression(std::move(argument), context);
if (!argument) {
return nullptr;
}
}
return ConstructorStruct::Make(context, pos, type, std::move(args));
}
[[maybe_unused]] static bool arguments_match_field_types(const ExpressionArray& args,
const Type& type) {
SkASSERT(type.fields().size() == args.size());
for (int index = 0; index < args.count(); ++index) {
const std::unique_ptr<Expression>& argument = args[index];
const Type::Field& field = type.fields()[index];
if (!argument->type().matches(*field.fType)) {
return false;
}
}
return true;
}
std::unique_ptr<Expression> ConstructorStruct::Make(const Context& context,
Position pos,
const Type& type,
ExpressionArray args) {
SkASSERT(type.isAllowedInES2(context));
SkASSERT(arguments_match_field_types(args, type));
return std::make_unique<ConstructorStruct>(pos, type, std::move(args));
}
} // namespace SkSL