/** * 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. */ #ifndef ES2PANDA_IR_ASTDUMP_H #define ES2PANDA_IR_ASTDUMP_H #include #include #include #include #include #include namespace panda::es2panda::ir { class AstDumper { public: class Nullable { public: explicit Nullable(const ir::AstNode *node) : node_(node) {} const ir::AstNode *Node() const { return node_; } private: const ir::AstNode *node_; }; class Optional { public: using Val = std::variant; explicit Optional(const ir::AstNode *node) : value_(node) {} explicit Optional(const char *string) : value_(const_cast(string)) {} explicit Optional(bool boolean) : value_(boolean) {} const Val &Value() const { return value_; } private: Val value_; }; class Property { public: class Ignore { public: Ignore() = default; }; enum class Constant { PROP_NULL, EMPTY_ARRAY, }; using Val = std::variant, util::StringView, bool, double, const ir::AstNode *, std::vector, Constant, Nullable, Ignore>; Property(const char *key, const char *string) : key_(key), value_(string) {} Property(const char *key, util::StringView str) : key_(key), value_(str) {} Property(const char *key, bool boolean) : key_(key), value_(boolean) {} Property(const char *key, double number) : key_(key), value_(number) {} Property(const char *key, lexer::TokenType token) : key_(key), value_(token) {} Property(const char *key, std::initializer_list props) : key_(key), value_(props) {} Property(const char *key, const ir::AstNode *node) : key_(key), value_(const_cast(node)) {} Property(const char *key, Constant constant) : key_(key), value_(constant) {} Property(const char *key, Nullable nullable) : key_(key) { if (nullable.Node()) { value_ = nullable.Node(); } else { value_ = Property::Constant::PROP_NULL; } } Property(const char *key, Optional optional) : key_(key) { const auto &value = optional.Value(); if (std::holds_alternative(value) && std::get(value)) { value_ = std::get(value); return; } if (std::holds_alternative(value) && std::get(value)) { value_ = std::get(value); return; } if (std::holds_alternative(value) && std::get(value)) { value_ = std::get(value); return; } value_ = Ignore(); } template Property(const char *key, const ArenaVector &array) : key_(key) { if (array.empty()) { value_ = Constant::EMPTY_ARRAY; return; } std::vector nodes; nodes.reserve(array.size()); for (auto &it : array) { nodes.push_back(it); } value_ = std::move(nodes); } const char *Key() const { return key_; } const Val &Value() const { return value_; } private: const char *key_; Val value_ {false}; }; explicit AstDumper(const BlockStatement *program, util::StringView sourceCode); explicit AstDumper(const ir::AstNode *node); void SerializeNode(const ir::AstNode *node); void Add(std::initializer_list props); void Add(const AstDumper::Property &prop); static const char *ModifierToString(ModifierFlags flags); static const char *TypeOperatorToString(TSOperatorType operatorType); std::string Str() const { return ss_.str(); } private: using WrapperCb = std::function; template void AddList(T props) { for (auto it = props.begin(); it != props.end();) { Serialize(*it); do { if (++it == props.end()) { return; } } while (std::holds_alternative((*it).Value())); ss_ << ','; } } void Indent(); void Serialize(const AstDumper::Property &prop); void SerializePropKey(const char *str); void SerializeString(const char *str); void SerializeString(const util::StringView &str); void SerializeNumber(size_t number); void SerializeNumber(double number); void SerializeBoolean(bool boolean); void SerializeObject(const ir::AstNode *object); void SerializeToken(lexer::TokenType token); void SerializePropList(std::initializer_list props); void SerializeConstant(Property::Constant constant); void Wrap(const WrapperCb &cb, char delimStart = '{', char delimEnd = '}'); void SerializeLoc(const lexer::SourceRange &loc); void SerializeSourcePosition(const lexer::SourcePosition &pos); void SerializeArray(std::vector array); lexer::LineIndex index_; std::stringstream ss_; int32_t indent_; bool dumpNodeOnly_ = false; }; } // namespace panda::es2panda::ir #endif // ASTDUMP_H