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