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