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