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