1 /** 2 * Copyright (c) 2021-2024 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_AST_DUMP_H 17 #define ES2PANDA_IR_AST_DUMP_H 18 19 #include "ir/astNode.h" 20 #include "lexer/token/sourceLocation.h" 21 #include "lexer/token/tokenType.h" 22 #include "lexer/token/number.h" 23 #include "util/ustring.h" 24 25 #include <sstream> 26 #include <variant> 27 28 namespace ark::es2panda::ir { 29 class AstDumper { 30 public: 31 class Nullish { 32 public: Nullish(const ir::AstNode *node)33 explicit Nullish(const ir::AstNode *node) : node_(node) {} 34 Node() const35 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 AstNode *, bool, std::vector<const AstNode *>>; 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 51 template <typename T> Optional(const ArenaVector<T> &array)52 explicit Optional(const ArenaVector<T> &array) 53 { 54 std::vector<const AstNode *> nodes; 55 nodes.reserve(array.size()); 56 57 for (auto &it : array) { 58 nodes.push_back(it); 59 } 60 61 value_ = std::move(nodes); 62 } 63 Value() const64 const Val &Value() const 65 { 66 return value_; 67 } 68 69 private: 70 Val value_; 71 }; 72 73 class Property { 74 public: 75 class Ignore { 76 public: 77 Ignore() = default; 78 }; 79 80 enum class Constant { 81 PROP_NULL, 82 PROP_UNDEFINED, 83 EMPTY_ARRAY, 84 }; 85 86 using Val = std::variant<const char *, lexer::TokenType, std::initializer_list<Property>, util::StringView, 87 bool, char16_t, lexer::Number, const ir::AstNode *, std::vector<const ir::AstNode *>, 88 Constant, Nullish, Ignore>; 89 Property(const char *key, const char *string)90 Property(const char *key, const char *string) : key_(key), value_(string) {} Property(const char *key, util::StringView str)91 Property(const char *key, util::StringView str) : key_(key), value_(str) {} Property(const char *key, bool boolean)92 Property(const char *key, bool boolean) : key_(key), value_(boolean) {} Property(const char *key, char16_t c16)93 Property(const char *key, char16_t c16) : key_(key), value_(c16) {} Property(const char *key, lexer::Number number)94 Property(const char *key, lexer::Number number) : key_(key), value_(number) {} Property(const char *key, lexer::TokenType token)95 Property(const char *key, lexer::TokenType token) : key_(key), value_(token) {} Property(const char *key, std::initializer_list<Property> props)96 Property(const char *key, std::initializer_list<Property> props) : key_(key), value_(props) {} Property(const char *key, const ir::AstNode *node)97 Property(const char *key, const ir::AstNode *node) : key_(key), value_(const_cast<ir::AstNode *>(node)) {} 98 Property(const char *key, Constant constant)99 Property(const char *key, Constant constant) : key_(key), value_(constant) {} Property(const char *key, Nullish nullish)100 Property(const char *key, Nullish nullish) : key_(key) 101 { 102 if (nullish.Node() != nullptr) { 103 value_ = nullish.Node(); 104 } else { 105 value_ = Property::Constant::PROP_NULL; 106 } 107 } 108 Property(const char *key, const Optional &optional)109 Property(const char *key, const Optional &optional) : key_(key) 110 { 111 const auto &value = optional.Value(); 112 if (std::holds_alternative<const ir::AstNode *>(value) && 113 (std::get<const ir::AstNode *>(value) != nullptr)) { 114 value_ = std::get<const ir::AstNode *>(value); 115 return; 116 } 117 118 if (std::holds_alternative<const char *>(value) && (std::get<const char *>(value) != nullptr)) { 119 value_ = std::get<const char *>(value); 120 return; 121 } 122 123 if (std::holds_alternative<bool>(value) && std::get<bool>(value)) { 124 value_ = std::get<bool>(value); 125 return; 126 } 127 128 if (std::holds_alternative<std::vector<const AstNode *>>(value)) { 129 const auto &array = std::get<std::vector<const AstNode *>>(value); 130 if (!array.empty()) { 131 value_ = array; 132 return; 133 } 134 } 135 136 value_ = Ignore(); 137 } 138 139 template <typename T> Property(const char *key, const ArenaVector<T> &array)140 Property(const char *key, const ArenaVector<T> &array) : key_(key) 141 { 142 if (array.empty()) { 143 value_ = Constant::EMPTY_ARRAY; 144 return; 145 } 146 147 std::vector<const ir::AstNode *> nodes; 148 nodes.reserve(array.size()); 149 150 for (auto &it : array) { 151 nodes.push_back(it); 152 } 153 154 value_ = std::move(nodes); 155 } 156 157 template <typename T> Property(const char *key, const ArenaVector<T> &array, const std::function<bool(AstNode *)> &filter)158 Property(const char *key, const ArenaVector<T> &array, const std::function<bool(AstNode *)> &filter) : key_(key) 159 { 160 std::vector<const ir::AstNode *> nodes; 161 nodes.reserve(array.size()); 162 163 for (auto &it : array) { 164 if (filter(it)) { 165 nodes.push_back(it); 166 } 167 } 168 169 if (nodes.empty()) { 170 value_ = Constant::EMPTY_ARRAY; 171 return; 172 } 173 174 value_ = std::move(nodes); 175 } 176 Key() const177 const char *Key() const 178 { 179 return key_; 180 } 181 Value() const182 const Val &Value() const 183 { 184 return value_; 185 } 186 187 private: 188 const char *key_; 189 Val value_ {}; 190 }; 191 192 explicit AstDumper(const ir::AstNode *node, util::StringView sourceCode = ""); 193 194 void Add(std::initializer_list<Property> props); 195 void Add(const AstDumper::Property &prop); 196 197 static const char *ModifierToString(ModifierFlags flags); 198 static const char *TypeOperatorToString(TSOperatorType operatorType); 199 Str() const200 std::string Str() const 201 { 202 return ss_.str(); 203 } 204 205 private: 206 using WrapperCb = std::function<void()>; 207 208 template <typename T> AddList(T props)209 void AddList(T props) 210 { 211 for (auto it = props.begin(); it != props.end();) { 212 Serialize(*it); 213 214 do { 215 if (++it == props.end()) { 216 return; 217 } 218 } while (std::holds_alternative<Property::Ignore>((*it).Value())); 219 220 ss_ << ','; 221 } 222 } 223 224 void Indent(); 225 226 void Serialize(const AstDumper::Property &prop); 227 void SerializePropKey(const char *str); 228 void SerializeString(const char *str); 229 void SerializeString(const util::StringView &str); 230 void SerializeNumber(size_t number); 231 void SerializeNumber(lexer::Number number); 232 void SerializeChar16(char16_t c16); 233 void SerializeBoolean(bool boolean); 234 void SerializeObject(const ir::AstNode *object); 235 void SerializeToken(lexer::TokenType token); 236 void SerializePropList(std::initializer_list<AstDumper::Property> props); 237 void SerializeConstant(Property::Constant constant); 238 void Wrap(const WrapperCb &cb, char delimStart = '{', char delimEnd = '}'); 239 240 void SerializeLoc(const lexer::SourceRange &loc); 241 void SerializeSourcePosition(const lexer::SourcePosition &pos); 242 243 void SerializeArray(std::vector<const ir::AstNode *> array); 244 245 const lexer::LineIndex index_; 246 std::stringstream ss_; 247 int32_t indent_ {}; 248 bool isSrcEmpty_ = false; 249 }; 250 } // namespace ark::es2panda::ir 251 252 #endif // AST_DUMP_H 253