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