1 /**
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "astDump.h"
17
18 namespace panda::es2panda::ir {
19
AstDumper(const BlockStatement * program,util::StringView sourceCode)20 AstDumper::AstDumper(const BlockStatement *program, util::StringView sourceCode) : index_(sourceCode), indent_(0)
21 {
22 SerializeObject(reinterpret_cast<const ir::AstNode *>(program));
23 }
24
AstDumper(const ir::AstNode * node)25 AstDumper::AstDumper(const ir::AstNode *node) : indent_(0), dumpNodeOnly_(true)
26 {
27 SerializeNode(node);
28 }
29
SerializeNode(const ir::AstNode * node)30 void AstDumper::SerializeNode(const ir::AstNode *node)
31 {
32 Wrap([this, node]() -> void {
33 node->Dump(this);
34 });
35 }
36
Add(std::initializer_list<AstDumper::Property> props)37 void AstDumper::Add(std::initializer_list<AstDumper::Property> props)
38 {
39 AddList<std::initializer_list<AstDumper::Property>>(props);
40 }
41
Add(const AstDumper::Property & prop)42 void AstDumper::Add(const AstDumper::Property &prop)
43 {
44 Serialize(prop);
45 }
46
ModifierToString(ModifierFlags flags)47 const char *AstDumper::ModifierToString(ModifierFlags flags)
48 {
49 if (flags & ModifierFlags::PRIVATE) {
50 return "private";
51 }
52
53 if (flags & ModifierFlags::PROTECTED) {
54 return "protected";
55 }
56
57 if (flags & ModifierFlags::PUBLIC) {
58 return "public";
59 }
60
61 return nullptr;
62 }
63
TypeOperatorToString(TSOperatorType operatorType)64 const char *AstDumper::TypeOperatorToString(TSOperatorType operatorType)
65 {
66 if (operatorType == TSOperatorType::KEYOF) {
67 return "keyof";
68 }
69
70 if (operatorType == TSOperatorType::READONLY) {
71 return "readonly";
72 }
73
74 if (operatorType == TSOperatorType::UNIQUE) {
75 return "unique";
76 }
77
78 return nullptr;
79 }
80
Serialize(const AstDumper::Property & prop)81 void AstDumper::Serialize(const AstDumper::Property &prop)
82 {
83 SerializePropKey(prop.Key());
84 const auto &value = prop.Value();
85
86 if (std::holds_alternative<const char *>(value)) {
87 SerializeString(std::get<const char *>(value));
88 } else if (std::holds_alternative<util::StringView>(value)) {
89 SerializeString(std::get<util::StringView>(value));
90 } else if (std::holds_alternative<bool>(value)) {
91 SerializeBoolean(std::get<bool>(value));
92 } else if (std::holds_alternative<double>(value)) {
93 SerializeNumber(std::get<double>(value));
94 } else if (std::holds_alternative<const ir::AstNode *>(value)) {
95 if (dumpNodeOnly_) {
96 SerializeNode(std::get<const ir::AstNode *>(value));
97 } else {
98 SerializeObject(std::get<const ir::AstNode *>(value));
99 }
100 } else if (std::holds_alternative<std::vector<const ir::AstNode *>>(value)) {
101 SerializeArray(std::get<std::vector<const ir::AstNode *>>(value));
102 } else if (std::holds_alternative<lexer::TokenType>(value)) {
103 SerializeToken(std::get<lexer::TokenType>(value));
104 } else if (std::holds_alternative<std::initializer_list<Property>>(value)) {
105 SerializePropList(std::get<std::initializer_list<Property>>(value));
106 } else if (std::holds_alternative<Property::Constant>(value)) {
107 SerializeConstant(std::get<Property::Constant>(value));
108 }
109 }
110
SerializeToken(lexer::TokenType token)111 void AstDumper::SerializeToken(lexer::TokenType token)
112 {
113 ss_ << "\"" << lexer::TokenToString(token) << "\"";
114 }
115
SerializePropKey(const char * str)116 void AstDumper::SerializePropKey(const char *str)
117 {
118 if (dumpNodeOnly_) {
119 return;
120 }
121 ss_ << std::endl;
122 Indent();
123 SerializeString(str);
124 ss_ << ": ";
125 }
126
SerializeString(const char * str)127 void AstDumper::SerializeString(const char *str)
128 {
129 ss_ << "\"" << str << "\"";
130 }
131
SerializeString(const util::StringView & str)132 void AstDumper::SerializeString(const util::StringView &str)
133 {
134 ss_ << "\"" << str.Utf8() << "\"";
135 }
136
SerializeNumber(size_t number)137 void AstDumper::SerializeNumber(size_t number)
138 {
139 ss_ << number;
140 }
141
SerializeNumber(double number)142 void AstDumper::SerializeNumber(double number)
143 {
144 if (std::isinf(number)) {
145 ss_ << "\"Infinity\"";
146 } else {
147 ss_ << number;
148 }
149 }
150
SerializeBoolean(bool boolean)151 void AstDumper::SerializeBoolean(bool boolean)
152 {
153 ss_ << (boolean ? "true" : "false");
154 }
155
SerializeConstant(Property::Constant constant)156 void AstDumper::SerializeConstant(Property::Constant constant)
157 {
158 switch (constant) {
159 case Property::Constant::PROP_NULL: {
160 ss_ << "null";
161 break;
162 }
163 case Property::Constant::EMPTY_ARRAY: {
164 ss_ << "[]";
165 break;
166 }
167 default: {
168 UNREACHABLE();
169 }
170 }
171 }
172
SerializePropList(std::initializer_list<AstDumper::Property> props)173 void AstDumper::SerializePropList(std::initializer_list<AstDumper::Property> props)
174 {
175 Wrap([this, &props]() -> void {
176 for (const auto *it = props.begin(); it != props.end(); ++it) {
177 Serialize(*it);
178 if (std::next(it) != props.end()) {
179 ss_ << ',';
180 }
181 }
182 });
183 }
184
SerializeArray(std::vector<const ir::AstNode * > array)185 void AstDumper::SerializeArray(std::vector<const ir::AstNode *> array)
186 {
187 Wrap(
188 [this, &array]() -> void {
189 for (auto it = array.begin(); it != array.end(); ++it) {
190 if (dumpNodeOnly_) {
191 SerializeNode(*it);
192 } else {
193 ss_ << std::endl;
194 Indent();
195 SerializeObject(*it);
196 }
197
198 if (std::next(it) != array.end()) {
199 ss_ << ',';
200 }
201 }
202 },
203 '[', ']');
204 }
205
SerializeObject(const ir::AstNode * object)206 void AstDumper::SerializeObject(const ir::AstNode *object)
207 {
208 Wrap([this, object]() -> void {
209 object->Dump(this);
210 SerializeLoc(object->Range());
211 });
212 }
213
Wrap(const WrapperCb & cb,char delimStart,char delimEnd)214 void AstDumper::Wrap(const WrapperCb &cb, char delimStart, char delimEnd)
215 {
216 ss_ << delimStart;
217
218 if (dumpNodeOnly_) {
219 cb();
220 } else {
221 indent_++;
222 cb();
223 ss_ << std::endl;
224 indent_--;
225 Indent();
226 }
227
228 ss_ << delimEnd;
229 }
230
SerializeLoc(const lexer::SourceRange & loc)231 void AstDumper::SerializeLoc(const lexer::SourceRange &loc)
232 {
233 ss_ << ',';
234 SerializePropKey("loc");
235
236 Wrap([this, &loc]() -> void {
237 SerializePropKey("start");
238 SerializeSourcePosition(loc.start);
239 ss_ << ',';
240 SerializePropKey("end");
241 SerializeSourcePosition(loc.end);
242 });
243 }
244
SerializeSourcePosition(const lexer::SourcePosition & pos)245 void AstDumper::SerializeSourcePosition(const lexer::SourcePosition &pos)
246 {
247 lexer::SourceLocation loc = index_.GetLocation(pos);
248
249 Wrap([this, &loc]() -> void {
250 SerializePropKey("line");
251 SerializeNumber(loc.line);
252 ss_ << ',';
253 SerializePropKey("column");
254 SerializeNumber(loc.col);
255 });
256 }
257
Indent()258 void AstDumper::Indent()
259 {
260 for (int32_t i = 0; i < indent_; i++) {
261 ss_ << " ";
262 }
263 }
264
265 } // namespace panda::es2panda::ir
266