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 | |
14 | #ifdef SK_DEBUG |
15 | String 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 |