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
16namespace SkSL {
17
18/**
19 * A single variable declaration within a var declaration statement. For instance, the statement
20 * 'int x = 2, y[3];' is a VarDeclarations statement containing two individual VarDeclaration
21 * instances.
22 */
23struct VarDeclaration : public Statement {
24 VarDeclaration(const Variable* var,
25 std::vector<std::unique_ptr<Expression>> sizes,
26 std::unique_ptr<Expression> value)
27 : INHERITED(var->fOffset, Statement::kVarDeclaration_Kind)
28 , fVar(var)
29 , fSizes(std::move(sizes))
30 , fValue(std::move(value)) {}
31
32 int nodeCount() const override {
33 int result = 1;
34 for (const auto& s : fSizes) {
35 if (s) {
36 result += s->nodeCount();
37 }
38 }
39 if (fValue) {
40 result += fValue->nodeCount();
41 }
42 return result;
43 }
44
45 std::unique_ptr<Statement> clone() const override {
46 std::vector<std::unique_ptr<Expression>> sizesClone;
47 for (const auto& s : fSizes) {
48 if (s) {
49 sizesClone.push_back(s->clone());
50 } else {
51 sizesClone.push_back(nullptr);
52 }
53 }
54 return std::unique_ptr<Statement>(new VarDeclaration(fVar, std::move(sizesClone),
55 fValue ? fValue->clone() : nullptr));
56 }
57
58 String description() const override {
59 String result = fVar->fModifiers.description() + fVar->fType.name() + " " + fVar->fName;
60 for (const auto& size : fSizes) {
61 if (size) {
62 result += "[" + size->description() + "]";
63 } else {
64 result += "[]";
65 }
66 }
67 if (fValue) {
68 result += " = " + fValue->description();
69 }
70 return result;
71 }
72
73 const Variable* fVar;
74 std::vector<std::unique_ptr<Expression>> fSizes;
75 std::unique_ptr<Expression> fValue;
76
77 typedef Statement INHERITED;
78};
79
80/**
81 * A variable declaration statement, which may consist of one or more individual variables.
82 */
83struct VarDeclarations : public ProgramElement {
84 VarDeclarations(int offset, const Type* baseType,
85 std::vector<std::unique_ptr<VarDeclaration>> vars)
86 : INHERITED(offset, kVar_Kind)
87 , fBaseType(*baseType) {
88 for (auto& var : vars) {
89 fVars.push_back(std::unique_ptr<Statement>(var.release()));
90 }
91 }
92
93 int nodeCount() const override {
94 int result = 1;
95 for (const auto& v : fVars) {
96 result += v->nodeCount();
97 }
98 return result;
99 }
100
101 std::unique_ptr<ProgramElement> clone() const override {
102 std::vector<std::unique_ptr<VarDeclaration>> cloned;
103 for (const auto& v : fVars) {
104 cloned.push_back(std::unique_ptr<VarDeclaration>(
105 (VarDeclaration*) v->clone().release()));
106 }
107 return std::unique_ptr<ProgramElement>(new VarDeclarations(fOffset, &fBaseType,
108 std::move(cloned)));
109 }
110
111 String description() const override {
112 if (!fVars.size()) {
113 return String();
114 }
115 String result;
116 for (const auto& var : fVars) {
117 if (var->fKind != Statement::kNop_Kind) {
118 SkASSERT(var->fKind == Statement::kVarDeclaration_Kind);
119 result = ((const VarDeclaration&) *var).fVar->fModifiers.description();
120 break;
121 }
122 }
123 result += fBaseType.description() + " ";
124 String separator;
125 for (const auto& rawVar : fVars) {
126 if (rawVar->fKind == Statement::kNop_Kind) {
127 continue;
128 }
129 SkASSERT(rawVar->fKind == Statement::kVarDeclaration_Kind);
130 VarDeclaration& var = (VarDeclaration&) *rawVar;
131 result += separator;
132 separator = ", ";
133 result += var.fVar->fName;
134 if (var.fValue) {
135 result += " = " + var.fValue->description();
136 }
137 }
138 return result;
139 }
140
141 const Type& fBaseType;
142 // this *should* be a vector of unique_ptr<VarDeclaration>, but it significantly simplifies the
143 // CFG to only have to worry about unique_ptr<Statement>
144 std::vector<std::unique_ptr<Statement>> fVars;
145
146 typedef ProgramElement INHERITED;
147};
148
149} // namespace SkSL
150
151#endif
152