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_VARDECLARATIONS 9 #define SKSL_VARDECLARATIONS 10 11 #include "include/core/SkTypes.h" 12 #include "include/private/SkSLIRNode.h" 13 #include "include/private/SkSLProgramElement.h" 14 #include "include/private/SkSLStatement.h" 15 #include "src/sksl/ir/SkSLExpression.h" 16 #include "src/sksl/ir/SkSLVariable.h" 17 18 #include <memory> 19 #include <string> 20 #include <utility> 21 22 namespace SkSL { 23 24 class Context; 25 class Position; 26 class Type; 27 28 struct Modifiers; 29 30 /** 31 * A single variable declaration statement. Multiple variables declared together are expanded to 32 * separate (sequential) statements. For instance, the SkSL 'int x = 2, y[3];' produces two 33 * VarDeclaration instances (wrapped in an unscoped Block). 34 */ 35 class VarDeclaration final : public Statement { 36 public: 37 inline static constexpr Kind kIRNodeKind = Kind::kVarDeclaration; 38 39 VarDeclaration(Variable* var, 40 const Type* baseType, 41 int arraySize, 42 std::unique_ptr<Expression> value, 43 bool isClone = false) 44 : INHERITED(var->fPosition, kIRNodeKind) 45 , fVar(var) 46 , fBaseType(*baseType) 47 , fArraySize(arraySize) 48 , fValue(std::move(value)) 49 , fIsClone(isClone) {} 50 ~VarDeclaration()51 ~VarDeclaration() override { 52 // Unhook this VarDeclaration from its associated Variable, since we're being deleted. 53 if (fVar && !fIsClone) { 54 fVar->detachDeadVarDeclaration(); 55 } 56 } 57 58 // Checks the modifiers, baseType, and storage for compatibility with one another and reports 59 // errors if needed. This method is implicitly called during Convert(), but is also explicitly 60 // called while processing interface block fields. 61 static void ErrorCheck(const Context& context, Position pos, Position modifiersPosition, 62 const Modifiers& modifiers, const Type* type, Variable::Storage storage); 63 64 // Does proper error checking and type coercion; reports errors via ErrorReporter. 65 static std::unique_ptr<Statement> Convert(const Context& context, std::unique_ptr<Variable> var, 66 std::unique_ptr<Expression> value, bool addToSymbolTable = true); 67 68 // Reports errors via ASSERT. 69 static std::unique_ptr<Statement> Make(const Context& context, 70 Variable* var, 71 const Type* baseType, 72 int arraySize, 73 std::unique_ptr<Expression> value); baseType()74 const Type& baseType() const { 75 return fBaseType; 76 } 77 var()78 Variable* var() const { 79 return fVar; 80 } 81 detachDeadVariable()82 void detachDeadVariable() { 83 fVar = nullptr; 84 } 85 arraySize()86 int arraySize() const { 87 return fArraySize; 88 } 89 value()90 std::unique_ptr<Expression>& value() { 91 return fValue; 92 } 93 value()94 const std::unique_ptr<Expression>& value() const { 95 return fValue; 96 } 97 98 std::unique_ptr<Statement> clone() const override; 99 100 std::string description() const override; 101 102 private: 103 static bool ErrorCheckAndCoerce(const Context& context, 104 const Variable& var, 105 std::unique_ptr<Expression>& value); 106 107 Variable* fVar; 108 const Type& fBaseType; 109 int fArraySize; // zero means "not an array" 110 std::unique_ptr<Expression> fValue; 111 // if this VarDeclaration is a clone, it doesn't actually own the associated variable 112 bool fIsClone; 113 114 using INHERITED = Statement; 115 }; 116 117 /** 118 * A variable declaration appearing at global scope. A global declaration like 'int x, y;' produces 119 * two GlobalVarDeclaration elements, each containing the declaration of one variable. 120 */ 121 class GlobalVarDeclaration final : public ProgramElement { 122 public: 123 inline static constexpr Kind kIRNodeKind = Kind::kGlobalVar; 124 GlobalVarDeclaration(std::unique_ptr<Statement> decl)125 GlobalVarDeclaration(std::unique_ptr<Statement> decl) 126 : INHERITED(decl->fPosition, kIRNodeKind) 127 , fDeclaration(std::move(decl)) { 128 SkASSERT(this->declaration()->is<VarDeclaration>()); 129 this->varDeclaration().var()->setGlobalVarDeclaration(this); 130 } 131 declaration()132 std::unique_ptr<Statement>& declaration() { 133 return fDeclaration; 134 } 135 declaration()136 const std::unique_ptr<Statement>& declaration() const { 137 return fDeclaration; 138 } 139 varDeclaration()140 VarDeclaration& varDeclaration() { 141 return fDeclaration->as<VarDeclaration>(); 142 } 143 varDeclaration()144 const VarDeclaration& varDeclaration() const { 145 return fDeclaration->as<VarDeclaration>(); 146 } 147 clone()148 std::unique_ptr<ProgramElement> clone() const override { 149 return std::make_unique<GlobalVarDeclaration>(this->declaration()->clone()); 150 } 151 description()152 std::string description() const override { 153 return this->declaration()->description(); 154 } 155 156 private: 157 std::unique_ptr<Statement> fDeclaration; 158 159 using INHERITED = ProgramElement; 160 }; 161 162 } // namespace SkSL 163 164 #endif 165