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 VarDeclaration(Variable * var,const Type * baseType,int arraySize,std::unique_ptr<Expression> value)41 VarDeclaration(Variable* var, 42 const Type* baseType, 43 int arraySize, 44 std::unique_ptr<Expression> value) 45 : INHERITED(var->fPosition, kIRNodeKind) 46 , fVar(var) 47 , fBaseType(*baseType) 48 , fArraySize(arraySize) 49 , fValue(std::move(value)) {} 50 ~VarDeclaration()51 ~VarDeclaration() override { 52 // Unhook this VarDeclaration from its associated Variable, since we're being deleted. 53 if (fVar) { 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 Layout& layout, ModifierFlags modifierFlags, const Type* type, 63 const Type* baseType, Variable::Storage storage); 64 65 // For use when no Variable yet exists. The newly-created variable will be added to the active 66 // symbol table. Performs proper error checking and type coercion; reports errors via 67 // ErrorReporter. 68 static std::unique_ptr<VarDeclaration> Convert(const Context& context, 69 Position overallPos, 70 const Modifiers& modifiers, 71 const Type& type, 72 Position namePos, 73 std::string_view name, 74 VariableStorage storage, 75 std::unique_ptr<Expression> value); 76 77 // For use when a Variable already exists. The passed-in variable will be added to the active 78 // symbol table. Performs proper error checking and type coercion; reports errors via 79 // ErrorReporter. 80 static std::unique_ptr<VarDeclaration> Convert(const Context& context, 81 std::unique_ptr<Variable> var, 82 std::unique_ptr<Expression> value); 83 84 // The symbol table is left as-is. Reports errors via ASSERT. 85 static std::unique_ptr<VarDeclaration> Make(const Context& context, 86 Variable* var, 87 const Type* baseType, 88 int arraySize, 89 std::unique_ptr<Expression> value); baseType()90 const Type& baseType() const { 91 return fBaseType; 92 } 93 var()94 Variable* var() const { 95 return fVar; 96 } 97 detachDeadVariable()98 void detachDeadVariable() { 99 fVar = nullptr; 100 } 101 arraySize()102 int arraySize() const { 103 return fArraySize; 104 } 105 value()106 std::unique_ptr<Expression>& value() { 107 return fValue; 108 } 109 value()110 const std::unique_ptr<Expression>& value() const { 111 return fValue; 112 } 113 114 std::string description() const override; 115 116 private: 117 static bool ErrorCheckAndCoerce(const Context& context, 118 const Variable& var, 119 const Type* baseType, 120 std::unique_ptr<Expression>& value); 121 122 Variable* fVar; 123 const Type& fBaseType; 124 int fArraySize; // zero means "not an array" 125 std::unique_ptr<Expression> fValue; 126 127 using INHERITED = Statement; 128 }; 129 130 /** 131 * A variable declaration appearing at global scope. A global declaration like 'int x, y;' produces 132 * two GlobalVarDeclaration elements, each containing the declaration of one variable. 133 */ 134 class GlobalVarDeclaration final : public ProgramElement { 135 public: 136 inline static constexpr Kind kIRNodeKind = Kind::kGlobalVar; 137 GlobalVarDeclaration(std::unique_ptr<Statement> decl)138 GlobalVarDeclaration(std::unique_ptr<Statement> decl) 139 : INHERITED(decl->fPosition, kIRNodeKind) 140 , fDeclaration(std::move(decl)) { 141 SkASSERT(this->declaration()->is<VarDeclaration>()); 142 this->varDeclaration().var()->setGlobalVarDeclaration(this); 143 } 144 declaration()145 std::unique_ptr<Statement>& declaration() { 146 return fDeclaration; 147 } 148 declaration()149 const std::unique_ptr<Statement>& declaration() const { 150 return fDeclaration; 151 } 152 varDeclaration()153 VarDeclaration& varDeclaration() { 154 return fDeclaration->as<VarDeclaration>(); 155 } 156 varDeclaration()157 const VarDeclaration& varDeclaration() const { 158 return fDeclaration->as<VarDeclaration>(); 159 } 160 description()161 std::string description() const override { 162 return this->declaration()->description(); 163 } 164 165 private: 166 std::unique_ptr<Statement> fDeclaration; 167 168 using INHERITED = ProgramElement; 169 }; 170 171 } // namespace SkSL 172 173 #endif 174