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