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#include "astDump.h" 17 18#include "ir/astNode.h" 19#include "util/helpers.h" 20 21#include <cmath> 22#include <iostream> 23 24namespace ark::es2panda::ir { 25AstDumper::AstDumper(const ir::AstNode *node, util::StringView sourceCode) : index_(sourceCode) 26{ 27 isSrcEmpty_ = sourceCode.Empty(); 28 SerializeObject(node); 29} 30 31void AstDumper::Add(std::initializer_list<AstDumper::Property> props) 32{ 33 AddList<std::initializer_list<AstDumper::Property>>(props); 34} 35 36void AstDumper::Add(const AstDumper::Property &prop) 37{ 38 Serialize(prop); 39} 40 41const char *AstDumper::ModifierToString(ModifierFlags flags) 42{ 43 if ((flags & ModifierFlags::INTERNAL) != 0) { 44 return "internal"; 45 } 46 47 if ((flags & ModifierFlags::PRIVATE) != 0) { 48 return "private"; 49 } 50 51 if ((flags & ModifierFlags::PROTECTED) != 0) { 52 return "protected"; 53 } 54 55 if ((flags & ModifierFlags::PUBLIC) != 0) { 56 return "public"; 57 } 58 59 return nullptr; 60} 61 62const char *AstDumper::TypeOperatorToString(TSOperatorType operatorType) 63{ 64 if (operatorType == TSOperatorType::KEYOF) { 65 return "keyof"; 66 } 67 68 if (operatorType == TSOperatorType::READONLY) { 69 return "readonly"; 70 } 71 72 if (operatorType == TSOperatorType::UNIQUE) { 73 return "unique"; 74 } 75 76 return nullptr; 77} 78 79void AstDumper::Serialize(const AstDumper::Property &prop) 80{ 81 SerializePropKey(prop.Key()); 82 const auto &value = prop.Value(); 83 84 if (std::holds_alternative<const char *>(value)) { 85 SerializeString(std::get<const char *>(value)); 86 } else if (std::holds_alternative<util::StringView>(value)) { 87 SerializeString(std::get<util::StringView>(value)); 88 } else if (std::holds_alternative<bool>(value)) { 89 SerializeBoolean(std::get<bool>(value)); 90 } else if (std::holds_alternative<lexer::Number>(value)) { 91 SerializeNumber(std::get<lexer::Number>(value)); 92 } else if (std::holds_alternative<char16_t>(value)) { 93 SerializeChar16(std::get<char16_t>(value)); 94 } else if (std::holds_alternative<const ir::AstNode *>(value)) { 95 SerializeObject(std::get<const ir::AstNode *>(value)); 96 } else if (std::holds_alternative<std::vector<const ir::AstNode *>>(value)) { 97 SerializeArray(std::get<std::vector<const ir::AstNode *>>(value)); 98 } else if (std::holds_alternative<lexer::TokenType>(value)) { 99 SerializeToken(std::get<lexer::TokenType>(value)); 100 } else if (std::holds_alternative<std::initializer_list<Property>>(value)) { 101 SerializePropList(std::get<std::initializer_list<Property>>(value)); 102 } else if (std::holds_alternative<Property::Constant>(value)) { 103 SerializeConstant(std::get<Property::Constant>(value)); 104 } 105} 106 107void AstDumper::SerializeToken(lexer::TokenType token) 108{ 109 ss_ << "\"" << lexer::TokenToString(token) << "\""; 110} 111 112void AstDumper::SerializePropKey(const char *str) 113{ 114 ss_ << std::endl; 115 Indent(); 116 SerializeString(str); 117 ss_ << ": "; 118} 119 120void AstDumper::SerializeString(const char *str) 121{ 122 ss_ << "\"" << str << "\""; 123} 124 125void AstDumper::SerializeString(const util::StringView &str) 126{ 127 ss_ << "\"" << str.Utf8() << "\""; 128} 129 130void AstDumper::SerializeNumber(size_t number) 131{ 132 ss_ << number; 133} 134 135void AstDumper::SerializeNumber(lexer::Number number) 136{ 137 if (number.IsInt()) { 138 ss_ << number.GetInt(); 139 } else if (number.IsLong()) { 140 ss_ << number.GetLong(); 141 } else if (number.IsFloat()) { 142 if (std::isinf(number.GetFloat())) { 143 ss_ << "\"Infinity\""; 144 } else { 145 ss_ << number.GetFloat(); 146 } 147 } else { 148 if (std::isinf(number.GetDouble())) { 149 ss_ << "\"Infinity\""; 150 } else { 151 ss_ << number.GetDouble(); 152 } 153 } 154} 155 156void AstDumper::SerializeChar16(char16_t c16) 157{ 158 SerializeString(util::Helpers::UTF16toUTF8(c16).c_str()); 159} 160 161void AstDumper::SerializeBoolean(bool boolean) 162{ 163 ss_ << (boolean ? "true" : "false"); 164} 165 166void AstDumper::SerializeConstant(Property::Constant constant) 167{ 168 switch (constant) { 169 case Property::Constant::PROP_NULL: { 170 ss_ << "null"; 171 break; 172 } 173 case Property::Constant::PROP_UNDEFINED: { 174 ss_ << "undefined"; 175 break; 176 } 177 case Property::Constant::EMPTY_ARRAY: { 178 ss_ << "[]"; 179 break; 180 } 181 default: { 182 UNREACHABLE(); 183 } 184 } 185} 186 187void AstDumper::SerializePropList(std::initializer_list<AstDumper::Property> props) 188{ 189 Wrap([this, &props]() -> void { 190 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) 191 for (const auto *it = props.begin(); it != props.end(); ++it) { 192 Serialize(*it); 193 if (std::next(it) != props.end()) { 194 ss_ << ','; 195 } 196 } 197 }); 198} 199 200void AstDumper::SerializeArray(std::vector<const ir::AstNode *> array) 201{ 202 Wrap( 203 [this, &array]() -> void { 204 for (auto it = array.begin(); it != array.end(); ++it) { 205 ss_ << std::endl; 206 Indent(); 207 208 SerializeObject(*it); 209 210 if (std::next(it) != array.end()) { 211 ss_ << ','; 212 } 213 } 214 }, 215 '[', ']'); 216} 217 218void AstDumper::SerializeObject(const ir::AstNode *object) 219{ 220 Wrap([this, object]() -> void { 221 object->Dump(this); 222 if (!isSrcEmpty_) { 223 SerializeLoc(object->Range()); 224 } 225 }); 226} 227 228void AstDumper::Wrap(const WrapperCb &cb, char delimStart, char delimEnd) 229{ 230 ss_ << delimStart; 231 indent_++; 232 233 cb(); 234 ss_ << std::endl; 235 indent_--; 236 Indent(); 237 ss_ << delimEnd; 238} 239 240void AstDumper::SerializeLoc(const lexer::SourceRange &loc) 241{ 242 ss_ << ','; 243 SerializePropKey("loc"); 244 245 Wrap([this, &loc]() -> void { 246 SerializePropKey("start"); 247 SerializeSourcePosition(loc.start); 248 ss_ << ','; 249 SerializePropKey("end"); 250 SerializeSourcePosition(loc.end); 251 }); 252} 253 254void AstDumper::SerializeSourcePosition(const lexer::SourcePosition &pos) 255{ 256 lexer::SourceLocation loc = index_.GetLocation(pos); 257 258 Wrap([this, &loc]() -> void { 259 SerializePropKey("line"); 260 SerializeNumber(loc.line); 261 ss_ << ','; 262 SerializePropKey("column"); 263 SerializeNumber(loc.col); 264 }); 265} 266 267void AstDumper::Indent() 268{ 269 for (int32_t i = 0; i < indent_; i++) { 270 ss_ << " "; 271 } 272} 273} // namespace ark::es2panda::ir 274