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