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 "src/sksl/ir/SkSLExpression.h"
12 #include "src/sksl/ir/SkSLProgramElement.h"
13 #include "src/sksl/ir/SkSLStatement.h"
14 #include "src/sksl/ir/SkSLVariable.h"
15 
16 namespace SkSL {
17 
18 /**
19  * A single variable declaration statement. Multiple variables declared together are expanded to
20  * separate (sequential) statements. For instance, the SkSL 'int x = 2, y[3];' produces two
21  * VarDeclaration instances (wrapped in an unscoped Block).
22  */
23 class VarDeclaration final : public Statement {
24 public:
25     static constexpr Kind kStatementKind = Kind::kVarDeclaration;
26 
VarDeclaration(const Variable * var,const Type * baseType,ExpressionArray sizes,std::unique_ptr<Expression> value)27     VarDeclaration(const Variable* var,
28                    const Type* baseType,
29                    ExpressionArray sizes,
30                    std::unique_ptr<Expression> value)
31             : INHERITED(var->fOffset, kStatementKind)
32             , fVar(var)
33             , fBaseType(*baseType)
34             , fSizes(std::move(sizes))
35             , fValue(std::move(value)) {}
36 
baseType()37     const Type& baseType() const {
38         return fBaseType;
39     }
40 
var()41     const Variable& var() const {
42         return *fVar;
43     }
44 
setVar(const Variable * var)45     void setVar(const Variable* var) {
46         fVar = var;
47     }
48 
sizes()49     const ExpressionArray& sizes() const {
50         return fSizes;
51     }
52 
value()53     std::unique_ptr<Expression>& value() {
54         return fValue;
55     }
56 
value()57     const std::unique_ptr<Expression>& value() const {
58         return fValue;
59     }
60 
clone()61     std::unique_ptr<Statement> clone() const override {
62         ExpressionArray sizesClone;
63         sizesClone.reserve_back(this->sizes().count());
64         for (const std::unique_ptr<Expression>& size : this->sizes()) {
65             if (size) {
66                 sizesClone.push_back(size->clone());
67             } else {
68                 sizesClone.push_back(nullptr);
69             }
70         }
71         return std::make_unique<VarDeclaration>(&this->var(),
72                                                 &this->baseType(),
73                                                 std::move(sizesClone),
74                                                 this->value() ? this->value()->clone() : nullptr);
75     }
76 
description()77     String description() const override {
78         String result = this->var().modifiers().description() + this->baseType().description() +
79                         " " + this->var().name();
80         for (const std::unique_ptr<Expression>& size : this->sizes()) {
81             if (size) {
82                 result += "[" + size->description() + "]";
83             } else {
84                 result += "[]";
85             }
86         }
87         if (this->value()) {
88             result += " = " + this->value()->description();
89         }
90         result += ";";
91         return result;
92     }
93 
94 private:
95     const Variable* fVar;
96     const Type& fBaseType;
97     ExpressionArray fSizes;
98     std::unique_ptr<Expression> fValue;
99 
100     using INHERITED = Statement;
101 };
102 
103 /**
104  * A variable declaration appearing at global scope. A global declaration like 'int x, y;' produces
105  * two GlobalVarDeclaration elements, each containing the declaration of one variable.
106  */
107 class GlobalVarDeclaration final : public ProgramElement {
108 public:
109     static constexpr Kind kProgramElementKind = Kind::kGlobalVar;
110 
GlobalVarDeclaration(int offset,std::unique_ptr<Statement> decl)111     GlobalVarDeclaration(int offset, std::unique_ptr<Statement> decl)
112             : INHERITED(offset, kProgramElementKind)
113             , fDeclaration(std::move(decl)) {
114         SkASSERT(this->declaration()->is<VarDeclaration>());
115     }
116 
declaration()117     std::unique_ptr<Statement>& declaration() {
118         return fDeclaration;
119     }
120 
declaration()121     const std::unique_ptr<Statement>& declaration() const {
122         return fDeclaration;
123     }
124 
clone()125     std::unique_ptr<ProgramElement> clone() const override {
126         return std::make_unique<GlobalVarDeclaration>(fOffset, this->declaration()->clone());
127     }
128 
description()129     String description() const override {
130         return this->declaration()->description();
131     }
132 
133 private:
134     std::unique_ptr<Statement> fDeclaration;
135 
136     using INHERITED = ProgramElement;
137 };
138 
139 }  // namespace SkSL
140 
141 #endif
142