/* * Copyright 2016 Google Inc. * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #ifndef SKSL_VARDECLARATIONS #define SKSL_VARDECLARATIONS #include "include/core/SkTypes.h" #include "src/sksl/ir/SkSLExpression.h" #include "src/sksl/ir/SkSLIRNode.h" #include "src/sksl/ir/SkSLModifierFlags.h" #include "src/sksl/ir/SkSLProgramElement.h" #include "src/sksl/ir/SkSLStatement.h" #include "src/sksl/ir/SkSLVariable.h" #include #include #include #include namespace SkSL { class Context; struct Layout; struct Modifiers; class Position; class Type; /** * A single variable declaration statement. Multiple variables declared together are expanded to * separate (sequential) statements. For instance, the SkSL 'int x = 2, y[3];' produces two * VarDeclaration instances (wrapped in an unscoped Block). */ class VarDeclaration final : public Statement { public: inline static constexpr Kind kIRNodeKind = Kind::kVarDeclaration; VarDeclaration(Variable* var, const Type* baseType, int arraySize, std::unique_ptr value) : INHERITED(var->fPosition, kIRNodeKind) , fVar(var) , fBaseType(*baseType) , fArraySize(arraySize) , fValue(std::move(value)) {} ~VarDeclaration() override { // Unhook this VarDeclaration from its associated Variable, since we're being deleted. if (fVar) { fVar->detachDeadVarDeclaration(); } } // Checks the modifiers, baseType, and storage for compatibility with one another and reports // errors if needed. This method is implicitly called during Convert(), but is also explicitly // called while processing interface block fields. static void ErrorCheck(const Context& context, Position pos, Position modifiersPosition, const Layout& layout, ModifierFlags modifierFlags, const Type* type, const Type* baseType, Variable::Storage storage); // For use when no Variable yet exists. The newly-created variable will be added to the active // symbol table. Performs proper error checking and type coercion; reports errors via // ErrorReporter. static std::unique_ptr Convert(const Context& context, Position overallPos, const Modifiers& modifiers, const Type& type, Position namePos, std::string_view name, VariableStorage storage, std::unique_ptr value); // For use when a Variable already exists. The passed-in variable will be added to the active // symbol table. Performs proper error checking and type coercion; reports errors via // ErrorReporter. static std::unique_ptr Convert(const Context& context, std::unique_ptr var, std::unique_ptr value); // The symbol table is left as-is. Reports errors via ASSERT. static std::unique_ptr Make(const Context& context, Variable* var, const Type* baseType, int arraySize, std::unique_ptr value); const Type& baseType() const { return fBaseType; } Variable* var() const { return fVar; } void detachDeadVariable() { fVar = nullptr; } int arraySize() const { return fArraySize; } std::unique_ptr& value() { return fValue; } const std::unique_ptr& value() const { return fValue; } std::string description() const override; private: static bool ErrorCheckAndCoerce(const Context& context, const Variable& var, const Type* baseType, std::unique_ptr& value); Variable* fVar; const Type& fBaseType; int fArraySize; // zero means "not an array" std::unique_ptr fValue; using INHERITED = Statement; }; /** * A variable declaration appearing at global scope. A global declaration like 'int x, y;' produces * two GlobalVarDeclaration elements, each containing the declaration of one variable. */ class GlobalVarDeclaration final : public ProgramElement { public: inline static constexpr Kind kIRNodeKind = Kind::kGlobalVar; GlobalVarDeclaration(std::unique_ptr decl) : INHERITED(decl->fPosition, kIRNodeKind) , fDeclaration(std::move(decl)) { SkASSERT(this->declaration()->is()); this->varDeclaration().var()->setGlobalVarDeclaration(this); } std::unique_ptr& declaration() { return fDeclaration; } const std::unique_ptr& declaration() const { return fDeclaration; } VarDeclaration& varDeclaration() { return fDeclaration->as(); } const VarDeclaration& varDeclaration() const { return fDeclaration->as(); } std::string description() const override { return this->declaration()->description(); } private: std::unique_ptr fDeclaration; using INHERITED = ProgramElement; }; } // namespace SkSL #endif