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