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