• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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