• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
13 namespace SkSL {
14 
Convert(const Context & context,int line,const Type & type,ExpressionArray args)15 std::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 
arguments_match_field_types(const ExpressionArray & args,const Type & type)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 
Make(const Context & context,int line,const Type & type,ExpressionArray args)60 std::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