1 /*
2  * Copyright 2016 Google Inc.
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 #ifndef SKSL_CONSTRUCTOR
9 #define SKSL_CONSTRUCTOR
10 
11 #include "include/core/SkSpan.h"
12 #include "src/sksl/SkSLIRGenerator.h"
13 #include "src/sksl/ir/SkSLExpression.h"
14 
15 namespace SkSL {
16 
17 /**
18  * Base class representing a constructor with unknown arguments.
19  */
20 class AnyConstructor : public Expression {
21 public:
AnyConstructor(int offset,Kind kind,const Type * type)22     AnyConstructor(int offset, Kind kind, const Type* type)
23             : INHERITED(offset, kind, type) {}
24 
25     virtual SkSpan<std::unique_ptr<Expression>> argumentSpan() = 0;
26     virtual SkSpan<const std::unique_ptr<Expression>> argumentSpan() const = 0;
27 
hasProperty(Property property)28     bool hasProperty(Property property) const override {
29         for (const std::unique_ptr<Expression>& arg : this->argumentSpan()) {
30             if (arg->hasProperty(property)) {
31                 return true;
32             }
33         }
34         return false;
35     }
36 
description()37     String description() const override {
38         String result = this->type().description() + "(";
39         const char* separator = "";
40         for (const std::unique_ptr<Expression>& arg : this->argumentSpan()) {
41             result += separator;
42             result += arg->description();
43             separator = ", ";
44         }
45         result += ")";
46         return result;
47     }
48 
componentType()49     const Type& componentType() const {
50         return this->type().componentType();
51     }
52 
isCompileTimeConstant()53     bool isCompileTimeConstant() const override {
54         for (const std::unique_ptr<Expression>& arg : this->argumentSpan()) {
55             if (!arg->isCompileTimeConstant()) {
56                 return false;
57             }
58         }
59         return true;
60     }
61 
isConstantOrUniform()62     bool isConstantOrUniform() const override {
63         for (const std::unique_ptr<Expression>& arg : this->argumentSpan()) {
64             if (!arg->isConstantOrUniform()) {
65                 return false;
66             }
67         }
68         return true;
69     }
70 
71     const Expression* getConstantSubexpression(int n) const override;
72 
73     ComparisonResult compareConstant(const Expression& other) const override;
74 
75 private:
76     std::unique_ptr<Expression> fArgument;
77 
78     using INHERITED = Expression;
79 };
80 
81 /**
82  * Base class representing a constructor that takes a single argument.
83  */
84 class SingleArgumentConstructor : public AnyConstructor {
85 public:
SingleArgumentConstructor(int offset,Kind kind,const Type * type,std::unique_ptr<Expression> argument)86     SingleArgumentConstructor(int offset, Kind kind, const Type* type,
87                               std::unique_ptr<Expression> argument)
88             : INHERITED(offset, kind, type)
89             , fArgument(std::move(argument)) {}
90 
argument()91     std::unique_ptr<Expression>& argument() {
92         return fArgument;
93     }
94 
argument()95     const std::unique_ptr<Expression>& argument() const {
96         return fArgument;
97     }
98 
argumentSpan()99     SkSpan<std::unique_ptr<Expression>> argumentSpan() final {
100         return {&fArgument, 1};
101     }
102 
argumentSpan()103     SkSpan<const std::unique_ptr<Expression>> argumentSpan() const final {
104         return {&fArgument, 1};
105     }
106 
107 private:
108     std::unique_ptr<Expression> fArgument;
109 
110     using INHERITED = AnyConstructor;
111 };
112 
113 /**
114  * Base class representing a constructor that takes an array of arguments.
115  */
116 class MultiArgumentConstructor : public AnyConstructor {
117 public:
MultiArgumentConstructor(int offset,Kind kind,const Type * type,ExpressionArray arguments)118     MultiArgumentConstructor(int offset, Kind kind, const Type* type, ExpressionArray arguments)
119             : INHERITED(offset, kind, type)
120             , fArguments(std::move(arguments)) {}
121 
arguments()122     ExpressionArray& arguments() {
123         return fArguments;
124     }
125 
arguments()126     const ExpressionArray& arguments() const {
127         return fArguments;
128     }
129 
cloneArguments()130     ExpressionArray cloneArguments() const {
131         ExpressionArray clonedArgs;
132         clonedArgs.reserve_back(this->arguments().size());
133         for (const std::unique_ptr<Expression>& arg: this->arguments()) {
134             clonedArgs.push_back(arg->clone());
135         }
136         return clonedArgs;
137     }
138 
argumentSpan()139     SkSpan<std::unique_ptr<Expression>> argumentSpan() final {
140         return {&fArguments.front(), fArguments.size()};
141     }
142 
argumentSpan()143     SkSpan<const std::unique_ptr<Expression>> argumentSpan() const final {
144         return {&fArguments.front(), fArguments.size()};
145     }
146 
147 private:
148     ExpressionArray fArguments;
149 
150     using INHERITED = AnyConstructor;
151 };
152 
153 /**
154  * Converts any GLSL constructor, such as `float2(x, y)` or `mat3x3(otherMat)` or `int[2](0, i)`, to
155  * an SkSL expression.
156  *
157  * Vector constructors must always consist of either exactly 1 scalar, or a collection of vectors
158  * and scalars totaling exactly the right number of scalar components.
159  *
160  * Matrix constructors must always consist of either exactly 1 scalar, exactly 1 matrix, or a
161  * collection of vectors and scalars totaling exactly the right number of scalar components.
162  *
163  * Array constructors must always contain the proper number of array elements (matching the Type).
164  */
165 namespace Constructor {
166     // Creates, typechecks and simplifies constructor expressions. Reports errors via the
167     // ErrorReporter. This can return null on error, so be careful. There are several different
168     // Constructor expression types; this class chooses the proper one based on context, e.g.
169     // `ConstructorCompound`, `ConstructorScalarCast`, or `ConstructorMatrixResize`.
170     std::unique_ptr<Expression> Convert(const Context& context,
171                                         int offset,
172                                         const Type& type,
173                                         ExpressionArray args);
174 };
175 
176 }  // namespace SkSL
177 
178 #endif
179