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 23namespace panda::es2panda::ir { 24 25AstDumper::AstDumper(const BlockStatement *program, util::StringView sourceCode) : index_(sourceCode), indent_(0) 26{ 27 SerializeObject(reinterpret_cast<const ir::AstNode *>(program)); 28} 29 30AstDumper::AstDumper(const ir::AstNode *node) : indent_(0), dumpNodeOnly_(true) 31{ 32 SerializeNode(node); 33} 34 35void AstDumper::SerializeNode(const ir::AstNode *node) 36{ 37 Wrap([this, node]() -> void { 38 node->Dump(this); 39 }); 40} 41 42void AstDumper::Add(std::initializer_list<AstDumper::Property> props) 43{ 44 AddList<std::initializer_list<AstDumper::Property>>(props); 45} 46 47void AstDumper::Add(const AstDumper::Property &prop) 48{ 49 Serialize(prop); 50} 51 52const 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 69const 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 86void 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 116void AstDumper::SerializeToken(lexer::TokenType token) 117{ 118 ss_ << "\"" << lexer::TokenToString(token) << "\""; 119} 120 121void 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 132void AstDumper::SerializeString(const char *str) 133{ 134 ss_ << "\"" << str << "\""; 135} 136 137void AstDumper::SerializeString(const util::StringView &str) 138{ 139 ss_ << "\"" << str.Utf8() << "\""; 140} 141 142void AstDumper::SerializeNumber(size_t number) 143{ 144 ss_ << number; 145} 146 147void AstDumper::SerializeNumber(double number) 148{ 149 if (std::isinf(number)) { 150 ss_ << "\"Infinity\""; 151 } else { 152 ss_ << number; 153 } 154} 155 156void AstDumper::SerializeBoolean(bool boolean) 157{ 158 ss_ << (boolean ? "true" : "false"); 159} 160 161void 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 178void 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 190void 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 211void AstDumper::SerializeObject(const ir::AstNode *object) 212{ 213 Wrap([this, object]() -> void { 214 object->Dump(this); 215 SerializeLoc(object->Range()); 216 }); 217} 218 219void 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 236void 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 250void 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 263void AstDumper::Indent() 264{ 265 for (int32_t i = 0; i < indent_; i++) { 266 ss_ << " "; 267 } 268} 269 270} // namespace panda::es2panda::ir 271