• 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 #ifndef ES2PANDA_IR_ASTDUMP_H
17 #define ES2PANDA_IR_ASTDUMP_H
18 
19 #include <ir/astNode.h>
20 #include <lexer/token/sourceLocation.h>
21 #include <lexer/token/tokenType.h>
22 #include <util/ustring.h>
23 
24 #include <sstream>
25 #include <variant>
26 
27 namespace panda::es2panda::ir {
28 
29 class AstDumper {
30 public:
31     class Nullable {
32     public:
Nullable(const ir::AstNode * node)33         explicit Nullable(const ir::AstNode *node) : node_(node) {}
34 
Node()35         const ir::AstNode *Node() const
36         {
37             return node_;
38         }
39 
40     private:
41         const ir::AstNode *node_;
42     };
43 
44     class Optional {
45     public:
46         using Val = std::variant<const char *, const ir::AstNode *, bool>;
Optional(const ir::AstNode * node)47         explicit Optional(const ir::AstNode *node) : value_(node) {}
Optional(const char * string)48         explicit Optional(const char *string) : value_(const_cast<char *>(string)) {}
Optional(bool boolean)49         explicit Optional(bool boolean) : value_(boolean) {}
50 
Value()51         const Val &Value() const
52         {
53             return value_;
54         }
55 
56     private:
57         Val value_;
58     };
59 
60     class Property {
61     public:
62         class Ignore {
63         public:
64             Ignore() = default;
65         };
66 
67         enum class Constant {
68             PROP_NULL,
69             EMPTY_ARRAY,
70         };
71 
72         using Val =
73             std::variant<const char *, lexer::TokenType, std::initializer_list<Property>, util::StringView, bool,
74                          double, const ir::AstNode *, std::vector<const ir::AstNode *>, Constant, Nullable, Ignore>;
75 
Property(const char * key,const char * string)76         Property(const char *key, const char *string) : key_(key), value_(string) {}
Property(const char * key,util::StringView str)77         Property(const char *key, util::StringView str) : key_(key), value_(str) {}
Property(const char * key,bool boolean)78         Property(const char *key, bool boolean) : key_(key), value_(boolean) {}
Property(const char * key,double number)79         Property(const char *key, double number) : key_(key), value_(number) {}
Property(const char * key,lexer::TokenType token)80         Property(const char *key, lexer::TokenType token) : key_(key), value_(token) {}
Property(const char * key,std::initializer_list<Property> props)81         Property(const char *key, std::initializer_list<Property> props) : key_(key), value_(props) {}
Property(const char * key,const ir::AstNode * node)82         Property(const char *key, const ir::AstNode *node) : key_(key), value_(const_cast<ir::AstNode *>(node)) {}
83 
Property(const char * key,Constant constant)84         Property(const char *key, Constant constant) : key_(key), value_(constant) {}
Property(const char * key,Nullable nullable)85         Property(const char *key, Nullable nullable) : key_(key)
86         {
87             if (nullable.Node()) {
88                 value_ = nullable.Node();
89             } else {
90                 value_ = Property::Constant::PROP_NULL;
91             }
92         }
93 
Property(const char * key,Optional optional)94         Property(const char *key, Optional optional) : key_(key)
95         {
96             const auto &value = optional.Value();
97             if (std::holds_alternative<const ir::AstNode *>(value) && std::get<const ir::AstNode *>(value)) {
98                 value_ = std::get<const ir::AstNode *>(value);
99                 return;
100             }
101 
102             if (std::holds_alternative<const char *>(value) && std::get<const char *>(value)) {
103                 value_ = std::get<const char *>(value);
104                 return;
105             }
106 
107             if (std::holds_alternative<bool>(value) && std::get<bool>(value)) {
108                 value_ = std::get<bool>(value);
109                 return;
110             }
111 
112             value_ = Ignore();
113         }
114 
115         template <typename T>
Property(const char * key,const ArenaVector<T> & array)116         Property(const char *key, const ArenaVector<T> &array) : key_(key)
117         {
118             if (array.empty()) {
119                 value_ = Constant::EMPTY_ARRAY;
120                 return;
121             }
122 
123             std::vector<const ir::AstNode *> nodes;
124             nodes.reserve(array.size());
125 
126             for (auto &it : array) {
127                 nodes.push_back(it);
128             }
129 
130             value_ = std::move(nodes);
131         }
132 
Key()133         const char *Key() const
134         {
135             return key_;
136         }
137 
Value()138         const Val &Value() const
139         {
140             return value_;
141         }
142 
143     private:
144         const char *key_;
145         Val value_ {false};
146     };
147 
148     explicit AstDumper(const BlockStatement *program, util::StringView sourceCode);
149     explicit AstDumper(const ir::AstNode *node);
150 
151     void SerializeNode(const ir::AstNode *node);
152 
153     void Add(std::initializer_list<Property> props);
154     void Add(const AstDumper::Property &prop);
155 
156     static const char *ModifierToString(ModifierFlags flags);
157     static const char *TypeOperatorToString(TSOperatorType operatorType);
158 
Str()159     std::string Str() const
160     {
161         return ss_.str();
162     }
163 
164 private:
165     using WrapperCb = std::function<void()>;
166 
167     template <typename T>
AddList(T props)168     void AddList(T props)
169     {
170         for (auto it = props.begin(); it != props.end();) {
171             Serialize(*it);
172 
173             do {
174                 if (++it == props.end()) {
175                     return;
176                 }
177             } while (std::holds_alternative<Property::Ignore>((*it).Value()));
178 
179             ss_ << ',';
180         }
181     }
182 
183     void Indent();
184 
185     void Serialize(const AstDumper::Property &prop);
186     void SerializePropKey(const char *str);
187     void SerializeString(const char *str);
188     void SerializeString(const util::StringView &str);
189     void SerializeNumber(size_t number);
190     void SerializeNumber(double number);
191     void SerializeBoolean(bool boolean);
192     void SerializeObject(const ir::AstNode *object);
193     void SerializeToken(lexer::TokenType token);
194     void SerializePropList(std::initializer_list<AstDumper::Property> props);
195     void SerializeConstant(Property::Constant constant);
196     void Wrap(const WrapperCb &cb, char delimStart = '{', char delimEnd = '}');
197 
198     void SerializeLoc(const lexer::SourceRange &loc);
199     void SerializeSourcePosition(const lexer::SourcePosition &pos);
200 
201     void SerializeArray(std::vector<const ir::AstNode *> array);
202 
203     lexer::LineIndex index_;
204     std::stringstream ss_;
205     int32_t indent_;
206     bool dumpNodeOnly_ = false;
207 };
208 }  // namespace panda::es2panda::ir
209 
210 #endif  // ASTDUMP_H
211