1/*
2 * Copyright 2019 Google LLC
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#include "src/sksl/SkSLASTNode.h"
9#include "src/sksl/SkSLCompiler.h"
10#include "src/sksl/SkSLString.h"
11
12namespace SkSL {
13
14#ifdef SK_DEBUG
15String ASTNode::description() const {
16 switch (fKind) {
17 case Kind::kNull: return "";
18 case Kind::kBinary:
19 return "(" + this->begin()->description() + " " +
20 Compiler::OperatorName(getToken().fKind) + " " +
21 (this->begin() + 1)->description() + ")";
22 case Kind::kBlock: {
23 String result = "{\n";
24 for (const auto& c : *this) {
25 result += c.description();
26 result += "\n";
27 }
28 result += "}";
29 return result;
30 }
31 case Kind::kBool:
32 return getBool() ? "true" : "false";
33 case Kind::kBreak:
34 return "break";
35 case Kind::kCall: {
36 auto iter = this->begin();
37 String result = iter->description();
38 result += "(";
39 const char* separator = "";
40 while (iter != this->end()) {
41 result += separator;
42 result += (iter++)->description();
43 separator = ",";
44 }
45 result += ")";
46 return result;
47 }
48 case Kind::kContinue:
49 return "continue";
50 case Kind::kDiscard:
51 return "discard";
52 case Kind::kDo:
53 return "do " + this->begin()->description() + " while (" +
54 (this->begin() + 1)->description() + ")";
55 case Kind::kEnum: {
56 String result = "enum ";
57 result += getString();
58 result += " {\n";
59 for (const auto& c : *this) {
60 result += c.description();
61 result += "\n";
62 }
63 result += "};";
64 return result;
65 }
66 case Kind::kEnumCase:
67 if (this->begin() != this->end()) {
68 return String(getString()) + " = " + this->begin()->description();
69 }
70 return getString();
71 case Kind::kExtension:
72 return "#extension " + getString();
73 case Kind::kField:
74 return this->begin()->description() + "." + getString();
75 case Kind::kFile: {
76 String result;
77 for (const auto& c : *this) {
78 result += c.description();
79 result += "\n";
80 }
81 return result;
82 }
83 case Kind::kFloat:
84 return to_string(getFloat());
85 case Kind::kFor:
86 return "for (" + this->begin()->description() + "; " +
87 (this->begin() + 1)->description() + "; " + (this->begin() + 2)->description() +
88 ") " + (this->begin() + 3)->description();
89 case Kind::kFunction: {
90 FunctionData fd = getFunctionData();
91 String result = fd.fModifiers.description();
92 if (result.size()) {
93 result += " ";
94 }
95 auto iter = this->begin();
96 result += (iter++)->description() + " " + fd.fName + "(";
97 const char* separator = "";
98 for (size_t i = 0; i < fd.fParameterCount; ++i) {
99 result += separator;
100 result += (iter++)->description();
101 separator = ", ";
102 }
103 result += ")";
104 if (iter != this->end()) {
105 result += " " + (iter++)->description();
106 SkASSERT(iter == this->end());
107 }
108 else {
109 result += ";";
110 }
111 return result;
112 }
113 case Kind::kIdentifier:
114 return getString();
115 case Kind::kIndex:
116 return this->begin()->description() + "[" + (this->begin() + 1)->description() + "]";
117 case Kind::kIf: {
118 String result;
119 if (getBool()) {
120 result = "@";
121 }
122 auto iter = this->begin();
123 result += "if (" + (iter++)->description() + ") ";
124 result += (iter++)->description();
125 if (iter != this->end()) {
126 result += " else " + (iter++)->description();
127 SkASSERT(iter == this->end());
128 }
129 return result;
130 }
131 case Kind::kInt:
132 return to_string(getInt());
133 case Kind::kInterfaceBlock: {
134 InterfaceBlockData id = getInterfaceBlockData();
135 String result = id.fModifiers.description() + " " + id.fTypeName + " {\n";
136 auto iter = this->begin();
137 for (size_t i = 0; i < id.fDeclarationCount; ++i) {
138 result += (iter++)->description() + "\n";
139 }
140 result += "} ";
141 result += id.fInstanceName;
142 for (size_t i = 0; i < id.fSizeCount; ++i) {
143 result += "[" + (iter++)->description() + "]";
144 }
145 SkASSERT(iter == this->end());
146 result += ";";
147 return result;
148 }
149 case Kind::kModifiers:
150 return getModifiers().description();
151 case Kind::kParameter: {
152 ParameterData pd = getParameterData();
153 auto iter = this->begin();
154 String result = (iter++)->description() + " " + pd.fName;
155 for (size_t i = 0; i < pd.fSizeCount; ++i) {
156 result += "[" + (iter++)->description() + "]";
157 }
158 if (iter != this->end()) {
159 result += " = " + (iter++)->description();
160 SkASSERT(iter == this->end());
161 }
162 return result;
163 }
164 case Kind::kPostfix:
165 return this->begin()->description() + Compiler::OperatorName(getToken().fKind);
166 case Kind::kPrefix:
167 return Compiler::OperatorName(getToken().fKind) + this->begin()->description();
168 case Kind::kReturn:
169 if (this->begin() != this->end()) {
170 return "return " + this->begin()->description() + ";";
171 }
172 return "return;";
173 case Kind::kSection:
174 return "@section { ... }";
175 case Kind::kSwitchCase: {
176 auto iter = this->begin();
177 String result;
178 if (*iter) {
179 result.appendf("case %s:\n", iter->description().c_str());
180 } else {
181 result = "default:\n";
182 }
183 for (++iter; iter != this->end(); ++iter) {
184 result += "\n" + iter->description();
185 }
186 return result;
187 }
188 case Kind::kSwitch: {
189 auto iter = this->begin();
190 String result;
191 if (getBool()) {
192 result = "@";
193 }
194 result += "switch (" + (iter++)->description() + ") {";
195 for (; iter != this->end(); ++iter) {
196 result += iter->description() + "\n";
197 }
198 result += "}";
199 return result;
200 }
201 case Kind::kTernary:
202 return "(" + this->begin()->description() + " ? " + (this->begin() + 1)->description() +
203 " : " + (this->begin() + 2)->description() + ")";
204 case Kind::kType:
205 return String(getTypeData().fName);
206 case Kind::kVarDeclaration: {
207 VarData vd = getVarData();
208 String result = vd.fName;
209 auto iter = this->begin();
210 for (size_t i = 0; i < vd.fSizeCount; ++i) {
211 result += "[" + (iter++)->description() + "]";
212 }
213 if (iter != this->end()) {
214 result += " = " + (iter++)->description();
215 SkASSERT(iter == this->end());
216 }
217 return result;
218 }
219 case Kind::kVarDeclarations: {
220 auto iter = this->begin();
221 String result = (iter++)->description();
222 if (result.size()) {
223 result += " ";
224 }
225 result += (iter++)->description();
226 const char* separator = " ";
227 for (; iter != this->end(); ++iter) {
228 result += separator + iter->description();
229 separator = ", ";
230 }
231 return result;
232 }
233 default:
234 SkASSERT(false);
235 return "<error>";
236 }
237}
238#endif
239
240} // namespace
241