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