• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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