/** * Copyright (c) 2021 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "astDump.h" #include #include #include namespace panda::es2panda::ir { AstDumper::AstDumper(const BlockStatement *program, util::StringView sourceCode) : index_(sourceCode), indent_(0) { SerializeObject(reinterpret_cast(program)); } AstDumper::AstDumper(const ir::AstNode *node) : indent_(0), dumpNodeOnly_(true) { SerializeNode(node); } void AstDumper::SerializeNode(const ir::AstNode *node) { Wrap([this, node]() -> void { node->Dump(this); }); } void AstDumper::Add(std::initializer_list props) { AddList>(props); } void AstDumper::Add(const AstDumper::Property &prop) { Serialize(prop); } const char *AstDumper::ModifierToString(ModifierFlags flags) { if (flags & ModifierFlags::PRIVATE) { return "private"; } if (flags & ModifierFlags::PROTECTED) { return "protected"; } if (flags & ModifierFlags::PUBLIC) { return "public"; } return nullptr; } const char *AstDumper::TypeOperatorToString(TSOperatorType operatorType) { if (operatorType == TSOperatorType::KEYOF) { return "keyof"; } if (operatorType == TSOperatorType::READONLY) { return "readonly"; } if (operatorType == TSOperatorType::UNIQUE) { return "unique"; } return nullptr; } void AstDumper::Serialize(const AstDumper::Property &prop) { SerializePropKey(prop.Key()); const auto &value = prop.Value(); if (std::holds_alternative(value)) { SerializeString(std::get(value)); } else if (std::holds_alternative(value)) { SerializeString(std::get(value)); } else if (std::holds_alternative(value)) { SerializeBoolean(std::get(value)); } else if (std::holds_alternative(value)) { SerializeNumber(std::get(value)); } else if (std::holds_alternative(value)) { if (dumpNodeOnly_) { SerializeNode(std::get(value)); } else { SerializeObject(std::get(value)); } } else if (std::holds_alternative>(value)) { SerializeArray(std::get>(value)); } else if (std::holds_alternative(value)) { SerializeToken(std::get(value)); } else if (std::holds_alternative>(value)) { SerializePropList(std::get>(value)); } else if (std::holds_alternative(value)) { SerializeConstant(std::get(value)); } } void AstDumper::SerializeToken(lexer::TokenType token) { ss_ << "\"" << lexer::TokenToString(token) << "\""; } void AstDumper::SerializePropKey(const char *str) { if (dumpNodeOnly_) { return; } ss_ << std::endl; Indent(); SerializeString(str); ss_ << ": "; } void AstDumper::SerializeString(const char *str) { ss_ << "\"" << str << "\""; } void AstDumper::SerializeString(const util::StringView &str) { ss_ << "\"" << str.Utf8() << "\""; } void AstDumper::SerializeNumber(size_t number) { ss_ << number; } void AstDumper::SerializeNumber(double number) { if (std::isinf(number)) { ss_ << "\"Infinity\""; } else { ss_ << number; } } void AstDumper::SerializeBoolean(bool boolean) { ss_ << (boolean ? "true" : "false"); } void AstDumper::SerializeConstant(Property::Constant constant) { switch (constant) { case Property::Constant::PROP_NULL: { ss_ << "null"; break; } case Property::Constant::EMPTY_ARRAY: { ss_ << "[]"; break; } default: { UNREACHABLE(); } } } void AstDumper::SerializePropList(std::initializer_list props) { Wrap([this, &props]() -> void { for (const auto *it = props.begin(); it != props.end(); ++it) { Serialize(*it); if (std::next(it) != props.end()) { ss_ << ','; } } }); } void AstDumper::SerializeArray(std::vector array) { Wrap( [this, &array]() -> void { for (auto it = array.begin(); it != array.end(); ++it) { if (dumpNodeOnly_) { SerializeNode(*it); } else { ss_ << std::endl; Indent(); SerializeObject(*it); } if (std::next(it) != array.end()) { ss_ << ','; } } }, '[', ']'); } void AstDumper::SerializeObject(const ir::AstNode *object) { Wrap([this, object]() -> void { object->Dump(this); SerializeLoc(object->Range()); }); } void AstDumper::Wrap(const WrapperCb &cb, char delimStart, char delimEnd) { ss_ << delimStart; if (dumpNodeOnly_) { cb(); } else { indent_++; cb(); ss_ << std::endl; indent_--; Indent(); } ss_ << delimEnd; } void AstDumper::SerializeLoc(const lexer::SourceRange &loc) { ss_ << ','; SerializePropKey("loc"); Wrap([this, &loc]() -> void { SerializePropKey("start"); SerializeSourcePosition(loc.start); ss_ << ','; SerializePropKey("end"); SerializeSourcePosition(loc.end); }); } void AstDumper::SerializeSourcePosition(const lexer::SourcePosition &pos) { lexer::SourceLocation loc = index_.GetLocation(pos); Wrap([this, &loc]() -> void { SerializePropKey("line"); SerializeNumber(loc.line); ss_ << ','; SerializePropKey("column"); SerializeNumber(loc.col); }); } void AstDumper::Indent() { for (int32_t i = 0; i < indent_; i++) { ss_ << " "; } } } // namespace panda::es2panda::ir