tsl-devkit/lsp-server/test/test_ast/debug_printer.cpp

2098 lines
62 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include <sstream>
#include <algorithm>
#include <optional>
#include "./debug_printer.hpp"
namespace lsp::language::ast
{
// ===== 便捷函数实现 =====
std::string DebugString(const ASTNode* node, const PrintOptions& opts)
{
std::ostringstream oss;
DebugPrinter printer(oss, opts);
if (node)
{
printer.Print(node);
}
return oss.str();
}
std::string DebugString(const ParseResult& result, const PrintOptions& opts)
{
std::ostringstream oss;
DebugPrinter printer(oss, opts);
printer.PrintParseResult(result);
return oss.str();
}
void DebugPrint(const ASTNode* node, const PrintOptions& opts)
{
DebugPrinter printer(std::cout, opts);
if (node)
{
printer.Print(node);
}
}
void DebugPrint(const ParseResult& result, const PrintOptions& opts)
{
DebugPrinter printer(std::cout, opts);
printer.PrintParseResult(result);
}
void DebugPrint(const ASTNode* node, const std::string& source, const PrintOptions& opts)
{
DebugPrinter printer(std::cout, opts);
printer.SetSourceCode(&source);
if (node)
{
printer.Print(node);
}
}
void DebugPrint(const ParseResult& result, const std::string& source, const PrintOptions& opts)
{
DebugPrinter printer(std::cout, opts);
printer.SetSourceCode(&source);
printer.PrintParseResult(result);
}
// ===== DebugPrinter 主要方法 =====
void DebugPrinter::Print(const ASTNode* node)
{
if (!node)
{
os_ << GetColor(Color::Red) << "nullptr" << GetColor(Color::Reset) << "\n";
return;
}
const_cast<ASTNode*>(node)->Accept(*this);
}
void DebugPrinter::PrintStatements(const std::vector<StatementPtr>& statements)
{
if (statements.empty())
{
PrintColored("(empty)", Color::Gray);
os_ << "\n";
return;
}
for (size_t i = 0; i < statements.size(); ++i)
{
bool is_last = (i == statements.size() - 1);
PrintStatement(statements[i].get(), "", is_last);
}
}
void DebugPrinter::PrintParseResult(const ParseResult& result)
{
PrintColored("=== Parse Result ===", Color::BrightCyan);
os_ << "\n\n";
if (result.root)
{
Print(result.root.get());
}
else
{
PrintColored("No root node", Color::Red);
os_ << "\n";
}
if (!result.errors.empty())
{
os_ << "\n";
PrintColored("=== Errors ===", Color::BrightRed);
os_ << "\n";
for (const auto& error : result.errors)
{
PrintError(error);
}
}
}
// ===== 辅助方法实现 =====
void DebugPrinter::PrintIndent(std::optional<bool> is_last)
{
if (!options_.use_tree_chars)
{
os_ << std::string(current_indent_, ' ');
return;
}
// Determine actual is_last value
bool actual_is_last = false;
if (is_last.has_value())
{
// Explicitly provided - use it
actual_is_last = *is_last;
}
else if (!is_last_child_stack_.empty())
{
// Not provided - read from stack
actual_is_last = is_last_child_stack_.back();
}
// else: stack is empty and no value provided, use false (root level)
PrintTreePrefix(actual_is_last);
}
void DebugPrinter::PrintTreePrefix(bool is_last)
{
bool use_ascii = false;
#ifdef _WIN32
// Windows 环境默认使用 ASCII
use_ascii = true;
#endif
// 定义树形字符
const char* vertical = use_ascii ? "|" : "";
const char* corner = use_ascii ? "`--" : "└──";
const char* branch = use_ascii ? "|--" : "├──";
// ===== 关键修复:使用 stack 大小作为实际深度 =====
// stack 的大小代表了我们在树结构中的实际深度
// 每个元素表示该层级的父节点是否是最后一个子节点
size_t depth = is_last_child_stack_.size();
// 打印每个祖先层级的竖线或空格
for (size_t i = 0; i < depth; ++i)
{
if (is_last_child_stack_[i])
{
// 该层级的父节点是最后一个子节点,所以不需要竖线
os_ << " ";
}
else
{
// 该层级的父节点不是最后一个子节点,需要显示竖线
os_ << vertical << " ";
}
}
// 打印当前节点的分支字符(如果不是根节点)
// 根节点depth = 0不打印分支字符
if (depth > 0 || current_indent_ > 0)
{
if (is_last)
os_ << corner << " ";
else
os_ << branch << " ";
}
}
std::string DebugPrinter::GetIndent() const
{
return std::string(current_indent_, ' ');
}
const char* DebugPrinter::GetColor(const char* color) const
{
return options_.use_colors ? color : "";
}
void DebugPrinter::PrintColored(const std::string& text, const char* color)
{
if (color)
{
os_ << GetColor(color);
}
os_ << text;
if (color)
{
os_ << GetColor(Color::Reset);
}
}
void DebugPrinter::PrintNodeHeader(const std::string& type_name, const Location& loc)
{
PrintColored(type_name, Color::BrightYellow);
if (options_.show_location)
{
os_ << " ";
PrintLocation(loc);
}
if (options_.show_source_code && source_code_)
{
os_ << " ";
PrintSourceSnippet(loc);
}
os_ << "\n";
}
void DebugPrinter::PrintLocation(const Location& loc)
{
os_ << GetColor(Color::Gray) << "@"
<< loc.start_line << ":" << loc.start_column
<< "-" << loc.end_line << ":" << loc.end_column
<< GetColor(Color::Reset);
}
void DebugPrinter::PrintSourceSnippet(const Location& loc)
{
if (!source_code_ || loc.start_byte >= source_code_->length())
{
return;
}
std::string snippet = GetSourceText(loc);
snippet = TruncateString(snippet, options_.max_source_length);
snippet = EscapeString(snippet);
os_ << GetColor(Color::Cyan) << "«" << snippet << "»" << GetColor(Color::Reset);
}
void DebugPrinter::PrintKeyValue(const std::string& key, const std::string& value, const Location& location, const char* value_color)
{
PrintIndent();
PrintColored(key, Color::Green);
os_ << ": ";
PrintColored(value, value_color);
if (options_.show_location)
{
os_ << " ";
PrintLocation(location);
}
os_ << "\n";
}
void DebugPrinter::PrintKeyValue(const std::string& key, const std::string& value, const char* value_color)
{
PrintIndent();
PrintColored(key, Color::Green);
os_ << ": ";
PrintColored(value, value_color);
os_ << "\n";
}
void DebugPrinter::PrintKeyValue(const std::string& key, int value)
{
PrintIndent();
PrintColored(key, Color::Green);
os_ << ": ";
PrintColored(std::to_string(value), Color::BrightMagenta);
os_ << "\n";
}
void DebugPrinter::PrintKeyValue(const std::string& key, bool value)
{
PrintIndent();
PrintColored(key, Color::Green);
os_ << ": ";
PrintColored(value ? "true" : "false", Color::BrightMagenta);
os_ << "\n";
}
void DebugPrinter::PrintExpression(const Expression* expr, const std::string& label, bool is_last)
{
if (!expr)
{
PrintIndent(is_last);
if (!label.empty())
{
PrintColored(label, Color::Green);
os_ << ": ";
}
PrintColored("nullptr", Color::Red);
os_ << "\n";
return;
}
if (!label.empty())
{
// Print the label with proper tree characters
PrintIndent(is_last);
PrintColored(label, Color::Green);
os_ << ":\n";
// ===== 修复:只 push 一次 =====
// 标签不是树节点,不占用层级
// 我们 push is_last然后增加缩进直接 Accept
is_last_child_stack_.push_back(is_last);
IncreaseIndent();
// 直接调用 Accept不再 push
const_cast<Expression*>(expr)->Accept(*this);
DecreaseIndent();
is_last_child_stack_.pop_back();
}
else
{
// No label - just print the expression directly
// 节点自己需要知道它是否是父节点的最后子节点
is_last_child_stack_.push_back(is_last);
const_cast<Expression*>(expr)->Accept(*this);
is_last_child_stack_.pop_back();
}
}
void DebugPrinter::PrintStatement(const Statement* stmt, const std::string& label, bool is_last)
{
if (!stmt)
{
PrintIndent(is_last);
if (!label.empty())
{
PrintColored(label, Color::Green);
os_ << ": ";
}
PrintColored("nullptr", Color::Red);
os_ << "\n";
return;
}
if (!label.empty())
{
// Print the label with proper tree characters
PrintIndent(is_last);
PrintColored(label, Color::Green);
os_ << ":\n";
// ===== 修复:只 push 一次 =====
// 标签不是树节点,不占用层级
is_last_child_stack_.push_back(is_last);
IncreaseIndent();
// 直接调用 Accept不再 push
const_cast<Statement*>(stmt)->Accept(*this);
DecreaseIndent();
is_last_child_stack_.pop_back();
}
else
{
// No label - just print the statement directly
is_last_child_stack_.push_back(is_last);
const_cast<Statement*>(stmt)->Accept(*this);
is_last_child_stack_.pop_back();
}
}
void DebugPrinter::PrintSignature(const Signature& sig)
{
// ===== 修复:不再自行打印 "signature:" 标签,由调用者管理 =====
// 调用者会打印标签并管理 stack这里只负责打印 signature 的子项
bool has_params = !sig.parameters.empty();
bool has_return = sig.return_type.has_value();
if (has_params)
{
// parameters 是否是最后一个子项:取决于后面是否还有 return_type
bool params_is_last = !has_return;
PrintIndent(params_is_last);
PrintColored("parameters", Color::Green);
os_ << ":\n";
is_last_child_stack_.push_back(params_is_last);
IncreaseIndent();
for (size_t i = 0; i < sig.parameters.size(); ++i)
{
bool is_last = (i == sig.parameters.size() - 1);
PrintParameter(sig.parameters[i], is_last);
}
DecreaseIndent();
is_last_child_stack_.pop_back();
}
if (has_return)
{
PrintKeyValue("return_type", sig.return_type->name, sig.return_type->location, Color::BrightBlue);
}
}
void DebugPrinter::PrintParameter(const Parameter& param, bool is_last)
{
PrintIndent(is_last);
PrintColored("param", Color::Yellow);
os_ << " ";
PrintColored(param.name, Color::BrightCyan);
if (param.type)
{
os_ << ": ";
PrintColored(param.type->name, Color::BrightBlue);
}
if (param.is_var)
os_ << " " << GetColor(Color::Magenta) << "[var]" << GetColor(Color::Reset);
if (param.is_out)
os_ << " " << GetColor(Color::Magenta) << "[out]" << GetColor(Color::Reset);
if (options_.show_location)
{
os_ << " ";
PrintLocation(param.location);
}
os_ << "\n";
if (param.default_value)
{
is_last_child_stack_.push_back(is_last);
IncreaseIndent();
PrintExpression(param.default_value.get(), "default", true);
DecreaseIndent();
is_last_child_stack_.pop_back();
}
}
void DebugPrinter::PrintLeftHandSide(const LeftHandSide& lhs, const std::string& label, bool is_last)
{
if (!label.empty())
{
PrintIndent(is_last);
PrintColored(label, Color::Green);
os_ << ":\n";
// ===== 修复:只 push 一次 =====
is_last_child_stack_.push_back(is_last);
IncreaseIndent();
// 直接 visit不再额外 push
std::visit([this](auto&& arg) {
if (arg)
{
arg->Accept(*this);
}
else
{
PrintIndent();
PrintColored("nullptr", Color::Red);
os_ << "\n";
}
},
lhs);
DecreaseIndent();
is_last_child_stack_.pop_back();
}
else
{
// 无 label 的情况:直接 push 并 visit
is_last_child_stack_.push_back(is_last);
std::visit([this](auto&& arg) {
if (arg)
{
arg->Accept(*this);
}
else
{
PrintIndent();
PrintColored("nullptr", Color::Red);
os_ << "\n";
}
},
lhs);
is_last_child_stack_.pop_back();
}
}
void DebugPrinter::PrintOperator(BinaryOperator op)
{
os_ << GetColor(Color::BrightYellow) << GetBinaryOperatorSymbol(op) << GetColor(Color::Reset);
}
void DebugPrinter::PrintOperator(UnaryOperator op)
{
std::string symbol;
switch (op)
{
case UnaryOperator::kPlus:
symbol = "+";
break;
case UnaryOperator::kMinus:
symbol = "-";
break;
case UnaryOperator::kNot:
symbol = "not";
break;
case UnaryOperator::kBitwiseNot:
symbol = "~";
break;
case UnaryOperator::kDotNot:
symbol = ".not";
break;
case UnaryOperator::kMatrixTranspose:
symbol = "'";
break;
case UnaryOperator::kDerivative:
symbol = "";
break;
case UnaryOperator::kExprAt:
symbol = "@";
break;
case UnaryOperator::kExprRef:
symbol = "&";
break;
default:
symbol = "unknown";
break;
}
os_ << GetColor(Color::BrightYellow) << symbol << GetColor(Color::Reset);
}
void DebugPrinter::PrintOperator(AssignmentOperator op)
{
os_ << GetColor(Color::BrightYellow) << GetAssignmentOperatorSymbol(op) << GetColor(Color::Reset);
}
void DebugPrinter::PrintLiteralKind(LiteralKind kind)
{
std::string kind_str;
const char* color = Color::Cyan;
switch (kind)
{
case LiteralKind::kNumber:
kind_str = "number";
color = Color::BrightMagenta;
break;
case LiteralKind::kString:
kind_str = "string";
color = Color::BrightGreen;
break;
case LiteralKind::kBoolean:
kind_str = "boolean";
color = Color::BrightBlue;
break;
case LiteralKind::kNil:
kind_str = "nil";
color = Color::Gray;
break;
case LiteralKind::kInfinity:
kind_str = "infinity";
color = Color::BrightMagenta;
break;
case LiteralKind::kEllipsis:
kind_str = "ellipsis";
color = Color::Gray;
break;
default:
kind_str = "unknown";
break;
}
PrintColored(kind_str, color);
}
void DebugPrinter::PrintAccessModifier(AccessModifier modifier)
{
std::string mod_str;
switch (modifier)
{
case AccessModifier::kPublic:
mod_str = "public";
break;
case AccessModifier::kProtected:
mod_str = "protected";
break;
case AccessModifier::kPrivate:
mod_str = "private";
break;
default:
mod_str = "unknown";
break;
}
PrintColored(mod_str, Color::Magenta);
}
void DebugPrinter::PrintMethodModifier(MethodModifier modifier)
{
std::string mod_str;
switch (modifier)
{
case MethodModifier::kNone:
return;
case MethodModifier::kVirtual:
mod_str = "virtual";
break;
case MethodModifier::kOverride:
mod_str = "override";
break;
case MethodModifier::kOverload:
mod_str = "overload";
break;
default:
mod_str = "unknown";
break;
}
os_ << " " << GetColor(Color::Magenta) << "[" << mod_str << "]" << GetColor(Color::Reset);
}
void DebugPrinter::PrintReferenceModifier(ReferenceModifier modifier)
{
std::string mod_str;
switch (modifier)
{
case ReferenceModifier::kNone:
return;
case ReferenceModifier::kWeakRef:
mod_str = "weakref";
break;
case ReferenceModifier::kAutoRef:
mod_str = "autoref";
break;
default:
mod_str = "unknown";
break;
}
os_ << " " << GetColor(Color::Magenta) << "[" << mod_str << "]" << GetColor(Color::Reset);
}
void DebugPrinter::PrintConditionalCompilationType(ConditionalCompilationType type)
{
std::string type_str;
switch (type)
{
case ConditionalCompilationType::kIfDef:
type_str = "IFDEF";
break;
case ConditionalCompilationType::kIfNDef:
type_str = "IFNDEF";
break;
case ConditionalCompilationType::kDef:
type_str = "DEFINE";
break;
case ConditionalCompilationType::kUndef:
type_str = "UNDEF";
break;
default:
type_str = "unknown";
break;
}
PrintColored(type_str, Color::Magenta);
}
void DebugPrinter::PrintError(const ParseError& error)
{
const char* severity_color = (error.severity == ErrorSeverity::Error) ? Color::BrightRed : Color::BrightYellow;
const char* severity_str = (error.severity == ErrorSeverity::Error) ? "Error" : "Warning";
PrintColored(severity_str, severity_color);
os_ << " at ";
PrintLocation(error.location);
os_ << " in " << GetColor(Color::Yellow) << error.node_type << GetColor(Color::Reset);
os_ << ": " << error.message << "\n";
if (options_.show_source_code && source_code_)
{
os_ << " ";
PrintSourceSnippet(error.location);
os_ << "\n";
}
}
std::string DebugPrinter::EscapeString(const std::string& str) const
{
std::string result;
result.reserve(str.length());
for (char c : str)
{
switch (c)
{
case '\n':
result += "\\n";
break;
case '\r':
result += "\\r";
break;
case '\t':
result += "\\t";
break;
case '\\':
result += "\\\\";
break;
default:
result += c;
break;
}
}
return result;
}
std::string DebugPrinter::TruncateString(const std::string& str, size_t max_len) const
{
if (str.length() <= max_len)
{
return str;
}
return str.substr(0, max_len) + "...";
}
std::string DebugPrinter::GetSourceText(const Location& loc) const
{
if (!source_code_ || loc.start_byte >= source_code_->length())
{
return "";
}
size_t end = std::min(loc.end_byte, static_cast<uint32_t>(source_code_->length()));
return source_code_->substr(loc.start_byte, end - loc.start_byte);
}
// ===== Visitor 方法实现 =====
void DebugPrinter::VisitProgram(Program& node)
{
PrintIndent();
PrintNodeHeader("Program", node.span);
IncreaseIndent();
PrintStatements(node.statements);
DecreaseIndent();
}
void DebugPrinter::VisitUnitDefinition(UnitDefinition& node)
{
PrintIndent();
PrintColored("UnitDefinition", Color::BrightYellow);
os_ << " " << GetColor(Color::BrightCyan) << node.name << GetColor(Color::Reset);
if (options_.show_location)
{
os_ << " ";
PrintLocation(node.location);
}
os_ << "\n";
IncreaseIndent();
// 判断哪个是最后一个非空的子项
bool has_implementation = !node.implementation_statements.empty();
bool has_initialization = !node.initialization_statements.empty();
bool has_finalization = !node.finalization_statements.empty();
if (!node.interface_statements.empty())
{
bool is_last = !has_implementation && !has_initialization && !has_finalization;
PrintIndent(is_last);
PrintColored("interface", Color::Green);
os_ << ":\n";
is_last_child_stack_.push_back(is_last);
IncreaseIndent();
PrintStatements(node.interface_statements);
DecreaseIndent();
is_last_child_stack_.pop_back();
}
if (!node.implementation_statements.empty())
{
bool is_last = !has_initialization && !has_finalization;
PrintIndent(is_last);
PrintColored("implementation", Color::Green);
os_ << ":\n";
is_last_child_stack_.push_back(is_last);
IncreaseIndent();
PrintStatements(node.implementation_statements);
DecreaseIndent();
is_last_child_stack_.pop_back();
}
if (!node.initialization_statements.empty())
{
bool is_last = !has_finalization;
PrintIndent(is_last);
PrintColored("initialization", Color::Green);
os_ << ":\n";
is_last_child_stack_.push_back(is_last);
IncreaseIndent();
PrintStatements(node.initialization_statements);
DecreaseIndent();
is_last_child_stack_.pop_back();
}
if (!node.finalization_statements.empty())
{
PrintIndent(true); // 最后一个子项
PrintColored("finalization", Color::Green);
os_ << ":\n";
is_last_child_stack_.push_back(true);
IncreaseIndent();
PrintStatements(node.finalization_statements);
DecreaseIndent();
is_last_child_stack_.pop_back();
}
DecreaseIndent();
}
void DebugPrinter::VisitClassDefinition(ClassDefinition& node)
{
PrintIndent();
PrintColored("ClassDefinition", Color::BrightYellow);
os_ << " " << GetColor(Color::BrightCyan) << node.name << GetColor(Color::Reset);
if (options_.show_location)
{
os_ << " ";
PrintLocation(node.location);
}
os_ << "\n";
IncreaseIndent();
if (!node.parent_classes.empty())
{
PrintIndent(node.members.empty()); // is_last if no members follow
PrintColored("inherits", Color::Green);
os_ << ": ";
for (size_t i = 0; i < node.parent_classes.size(); ++i)
{
const auto& parent = node.parent_classes[i];
if (i > 0)
os_ << ", ";
if (parent.qualifier)
{
PrintColored(*parent.qualifier, Color::BrightBlue);
os_ << ".";
}
PrintColored(parent.name, Color::BrightCyan);
}
os_ << "\n";
}
if (!node.members.empty())
{
PrintIndent(true); // members is the last section
PrintColored("members", Color::Green);
os_ << ":\n";
// Push state BEFORE incrementing indent (for the members section itself)
is_last_child_stack_.push_back(false); // Will be updated in loop
IncreaseIndent();
// Print each member - update stack top instead of push/pop
for (size_t i = 0; i < node.members.size(); ++i)
{
bool is_last = (i == node.members.size() - 1);
// Update the stack top to reflect whether this member is the last one
is_last_child_stack_.back() = is_last;
node.members[i]->Accept(*this);
}
DecreaseIndent();
is_last_child_stack_.pop_back();
}
DecreaseIndent();
}
void DebugPrinter::VisitClassMember(ClassMember& node)
{
std::visit([this, &node](auto&& arg) {
if (arg)
{
bool is_last = !is_last_child_stack_.empty() ? is_last_child_stack_.back() : false;
PrintIndent(is_last);
PrintColored("[", Color::Gray);
PrintAccessModifier(node.access_modifier);
PrintColored("]", Color::Gray);
os_ << " ";
// Inline the node header without indentation
if (auto* method = dynamic_cast<MethodDeclaration*>(arg.get()))
{
PrintColored("MethodDeclaration", Color::BrightYellow);
os_ << " " << GetColor(Color::BrightCyan) << method->name << GetColor(Color::Reset);
PrintMethodModifier(method->modifier);
if (method->is_class_method)
os_ << " " << GetColor(Color::Magenta) << "[class]" << GetColor(Color::Reset);
if (method->is_operator_overload)
os_ << " " << GetColor(Color::Magenta) << "[operator]" << GetColor(Color::Reset);
if (options_.show_location)
{
os_ << " ";
PrintLocation(method->location);
}
os_ << "\n";
IncreaseIndent();
bool signature_is_last = !method->body;
is_last_child_stack_.push_back(signature_is_last);
PrintSignature(method->signature);
is_last_child_stack_.pop_back();
if (method->body)
PrintStatement(method->body.get(), "body", true);
DecreaseIndent();
}
else if (auto* field = dynamic_cast<FieldDeclaration*>(arg.get()))
{
PrintColored("FieldDeclaration", Color::Yellow);
os_ << " " << GetColor(Color::BrightCyan) << field->name << GetColor(Color::Reset);
PrintReferenceModifier(field->reference_modifier);
if (field->type)
os_ << ": " << GetColor(Color::BrightBlue) << field->type->name << GetColor(Color::Reset);
os_ << "\n";
if (field->initial_value)
{
IncreaseIndent();
PrintExpression(field->initial_value.get(), "initial_value", true);
DecreaseIndent();
}
}
else if (auto* prop = dynamic_cast<PropertyDeclaration*>(arg.get()))
{
PrintColored("PropertyDeclaration", Color::BrightYellow);
os_ << " " << GetColor(Color::BrightCyan) << prop->name << GetColor(Color::Reset);
if (options_.show_location)
{
os_ << " ";
PrintLocation(prop->location);
}
os_ << "\n";
IncreaseIndent();
if (prop->type_name)
PrintKeyValue("type", *prop->type_name, Color::BrightBlue);
if (prop->index_value)
PrintKeyValue("index", *prop->index_value);
if (prop->read_accessor)
PrintKeyValue("read", *prop->read_accessor);
if (prop->write_accessor)
PrintKeyValue("write", *prop->write_accessor);
DecreaseIndent();
}
}
},
node.member);
}
void DebugPrinter::VisitMethodDeclaration(MethodDeclaration& node)
{
PrintIndent();
PrintColored("MethodDeclaration", Color::BrightYellow);
os_ << " " << GetColor(Color::BrightCyan) << node.name << GetColor(Color::Reset);
PrintMethodModifier(node.modifier);
if (node.is_class_method)
{
os_ << " " << GetColor(Color::Magenta) << "[class]" << GetColor(Color::Reset);
}
if (node.is_operator_overload)
{
os_ << " " << GetColor(Color::Magenta) << "[operator]" << GetColor(Color::Reset);
}
if (options_.show_location)
{
os_ << " ";
PrintLocation(node.location);
}
os_ << "\n";
// ===== 修复:不需要外层 IncreaseIndent =====
bool signature_is_last = !node.body;
PrintIndent(signature_is_last);
PrintColored("signature", Color::Green);
os_ << ":\n";
is_last_child_stack_.push_back(signature_is_last);
IncreaseIndent();
PrintSignature(node.signature);
DecreaseIndent();
is_last_child_stack_.pop_back();
if (node.body)
PrintStatement(node.body.get(), "body", true);
}
void DebugPrinter::VisitPropertyDeclaration(PropertyDeclaration& node)
{
PrintIndent();
PrintColored("PropertyDeclaration", Color::BrightYellow);
os_ << " " << GetColor(Color::BrightCyan) << node.name << GetColor(Color::Reset);
if (options_.show_location)
{
os_ << " ";
PrintLocation(node.location);
}
os_ << "\n";
IncreaseIndent();
if (node.type_name)
{
PrintKeyValue("type", *node.type_name, Color::BrightBlue);
}
if (node.index_value)
{
PrintKeyValue("index", *node.index_value);
}
if (node.read_accessor)
{
PrintKeyValue("read", *node.read_accessor);
}
if (node.write_accessor)
{
PrintKeyValue("write", *node.write_accessor);
}
DecreaseIndent();
}
void DebugPrinter::VisitExternalMethodDefinition(ExternalMethodDefinition& node)
{
PrintIndent();
PrintColored("ExternalMethodDefinition", Color::BrightYellow);
os_ << " " << GetColor(Color::BrightBlue) << node.owner_class.name << GetColor(Color::Reset);
os_ << "." << GetColor(Color::BrightCyan) << node.name << GetColor(Color::Reset);
PrintMethodModifier(node.modifier);
if (node.is_class_method)
{
os_ << " " << GetColor(Color::Magenta) << "[class]" << GetColor(Color::Reset);
}
if (options_.show_location)
{
os_ << " ";
PrintLocation(node.location);
}
os_ << "\n";
// ===== 修复:不需要外层 IncreaseIndent =====
bool signature_is_last = !node.body;
PrintIndent(signature_is_last);
PrintColored("signature", Color::Green);
os_ << ":\n";
is_last_child_stack_.push_back(signature_is_last);
IncreaseIndent();
PrintSignature(node.signature);
DecreaseIndent();
is_last_child_stack_.pop_back();
if (node.body)
PrintStatement(node.body.get(), "body", true);
}
void DebugPrinter::VisitIdentifier(Identifier& node)
{
PrintIndent();
PrintColored("Identifier", Color::Yellow);
os_ << " " << GetColor(Color::BrightCyan) << node.name << GetColor(Color::Reset);
if (options_.show_location)
{
os_ << " ";
PrintLocation(node.location);
}
os_ << "\n";
}
void DebugPrinter::VisitLiteral(Literal& node)
{
PrintIndent();
PrintColored("Literal", Color::Yellow);
os_ << " [";
PrintLiteralKind(node.literal_kind);
os_ << "] " << GetColor(Color::BrightGreen) << node.name << GetColor(Color::Reset);
if (options_.show_location)
{
os_ << " ";
PrintLocation(node.location);
}
os_ << "\n";
}
void DebugPrinter::VisitBinaryExpression(BinaryExpression& node)
{
PrintIndent();
PrintColored("BinaryExpression", Color::Yellow);
os_ << " ";
PrintOperator(node.op);
os_ << "\n";
IncreaseIndent();
PrintExpression(node.left.get(), "left", false);
PrintExpression(node.right.get(), "right", true);
DecreaseIndent();
}
void DebugPrinter::VisitComparisonExpression(ComparisonExpression& node)
{
PrintIndent();
PrintColored("ComparisonExpression", Color::Yellow);
os_ << "\n";
IncreaseIndent();
PrintExpression(node.left.get(), "left", false);
for (size_t i = 0; i < node.comparisons.size(); ++i)
{
bool is_last = (i == node.comparisons.size() - 1);
const auto& comp = node.comparisons[i];
PrintIndent(is_last);
PrintColored("comparison", Color::Green);
os_ << " ";
PrintOperator(comp.op);
os_ << ":\n";
is_last_child_stack_.push_back(is_last);
IncreaseIndent();
PrintExpression(comp.right.get(), "", true);
DecreaseIndent();
is_last_child_stack_.pop_back();
}
DecreaseIndent();
}
void DebugPrinter::VisitUnaryExpression(UnaryExpression& node)
{
PrintIndent();
PrintColored("UnaryExpression", Color::Yellow);
os_ << " ";
PrintOperator(node.op);
os_ << "\n";
IncreaseIndent();
PrintExpression(node.argument.get(), "argument", true);
DecreaseIndent();
}
void DebugPrinter::VisitTernaryExpression(TernaryExpression& node)
{
PrintIndent();
PrintColored("TernaryExpression", Color::Yellow);
os_ << "\n";
IncreaseIndent();
PrintExpression(node.condition.get(), "condition", false);
PrintExpression(node.consequence.get(), "consequence", false);
PrintExpression(node.alternative.get(), "alternative", true);
DecreaseIndent();
}
void DebugPrinter::VisitCallExpression(CallExpression& node)
{
PrintIndent();
PrintColored("CallExpression", Color::Yellow);
os_ << "\n";
IncreaseIndent();
PrintExpression(node.callee.get(), "callee", false);
if (!node.arguments.empty())
{
PrintIndent(true);
PrintColored("arguments", Color::Green);
os_ << ":\n";
is_last_child_stack_.push_back(true);
IncreaseIndent();
for (size_t i = 0; i < node.arguments.size(); ++i)
{
bool is_last = (i == node.arguments.size() - 1);
const auto& arg = node.arguments[i];
PrintIndent(is_last);
if (arg.name)
{
PrintColored(*arg.name, Color::BrightCyan);
os_ << " = ";
}
os_ << "\n";
is_last_child_stack_.push_back(is_last);
IncreaseIndent();
PrintExpression(arg.value.get(), "", true);
DecreaseIndent();
is_last_child_stack_.pop_back();
}
DecreaseIndent();
is_last_child_stack_.pop_back();
}
DecreaseIndent();
}
void DebugPrinter::VisitAttributeExpression(AttributeExpression& node)
{
PrintIndent();
PrintColored("AttributeExpression", Color::Yellow);
os_ << " ." << GetColor(Color::BrightCyan) << node.name << GetColor(Color::Reset);
if (options_.show_location)
{
os_ << " ";
PrintLocation(node.location);
}
os_ << "\n";
IncreaseIndent();
PrintExpression(node.object.get(), "object", true);
DecreaseIndent();
}
void DebugPrinter::VisitSubscriptExpression(SubscriptExpression& node)
{
PrintIndent();
PrintColored("SubscriptExpression", Color::Yellow);
os_ << "\n";
IncreaseIndent();
PrintExpression(node.value.get(), "value", false);
if (!node.indices.empty())
{
PrintIndent(true);
PrintColored("indices", Color::Green);
os_ << ":\n";
is_last_child_stack_.push_back(true);
IncreaseIndent();
for (size_t i = 0; i < node.indices.size(); ++i)
{
bool is_last = (i == node.indices.size() - 1);
const auto& idx = node.indices[i];
PrintIndent(is_last);
if (idx.is_slice)
{
PrintColored("slice", Color::Magenta);
}
else
{
PrintColored("index", Color::Magenta);
}
os_ << ":\n";
is_last_child_stack_.push_back(is_last);
IncreaseIndent();
if (idx.start)
{
PrintExpression(idx.start.get(), "start", !idx.end && !idx.step);
}
if (idx.end)
{
PrintExpression(idx.end.get(), "end", !idx.step);
}
if (idx.step)
{
PrintExpression(idx.step.get(), "step", true);
}
DecreaseIndent();
is_last_child_stack_.pop_back();
}
DecreaseIndent();
is_last_child_stack_.pop_back();
}
DecreaseIndent();
}
void DebugPrinter::VisitArrayExpression(ArrayExpression& node)
{
PrintIndent();
PrintColored("ArrayExpression", Color::Yellow);
os_ << "\n";
if (node.elements.empty())
{
IncreaseIndent();
PrintIndent();
PrintColored("(empty)", Color::Gray);
os_ << "\n";
DecreaseIndent();
return;
}
IncreaseIndent();
for (size_t i = 0; i < node.elements.size(); ++i)
{
bool is_last = (i == node.elements.size() - 1);
const auto& elem = node.elements[i];
PrintIndent(is_last);
PrintColored("element", Color::Green);
if (elem.is_nested)
{
os_ << " " << GetColor(Color::Magenta) << "[nested]" << GetColor(Color::Reset);
}
os_ << ":\n";
is_last_child_stack_.push_back(is_last);
IncreaseIndent();
if (elem.key)
{
PrintExpression(elem.key.get(), "key", false);
PrintExpression(elem.value.get(), "value", true);
}
else
{
PrintExpression(elem.value.get(), "", true);
}
DecreaseIndent();
is_last_child_stack_.pop_back();
}
DecreaseIndent();
}
void DebugPrinter::VisitAnonymousFunctionExpression(AnonymousFunctionExpression& node)
{
PrintIndent();
PrintColored("AnonymousFunctionExpression", Color::Yellow);
os_ << "\n";
// ===== 修复:不需要外层 IncreaseIndent =====
bool signature_is_last = !node.body;
PrintIndent(signature_is_last);
PrintColored("signature", Color::Green);
os_ << ":\n";
is_last_child_stack_.push_back(signature_is_last);
IncreaseIndent();
PrintSignature(node.signature);
DecreaseIndent();
is_last_child_stack_.pop_back();
if (node.body)
{
PrintStatement(node.body.get(), "body", true);
}
}
void DebugPrinter::VisitPrefixIncrementExpression(PrefixIncrementExpression& node)
{
PrintIndent();
PrintColored("PrefixIncrementExpression", Color::Yellow);
os_ << " ++\n";
IncreaseIndent();
PrintExpression(node.argument.get(), "argument", true);
DecreaseIndent();
}
void DebugPrinter::VisitPrefixDecrementExpression(PrefixDecrementExpression& node)
{
PrintIndent();
PrintColored("PrefixDecrementExpression", Color::Yellow);
os_ << " --\n";
IncreaseIndent();
PrintExpression(node.argument.get(), "argument", true);
DecreaseIndent();
}
void DebugPrinter::VisitPostfixIncrementExpression(PostfixIncrementExpression& node)
{
PrintIndent();
PrintColored("PostfixIncrementExpression", Color::Yellow);
os_ << " ++\n";
IncreaseIndent();
PrintExpression(node.argument.get(), "argument", true);
DecreaseIndent();
}
void DebugPrinter::VisitPostfixDecrementExpression(PostfixDecrementExpression& node)
{
PrintIndent();
PrintColored("PostfixDecrementExpression", Color::Yellow);
os_ << " --\n";
IncreaseIndent();
PrintExpression(node.argument.get(), "argument", true);
DecreaseIndent();
}
void DebugPrinter::VisitFunctionPointerExpression(FunctionPointerExpression& node)
{
PrintIndent();
PrintColored("FunctionPointerExpression", Color::Yellow);
os_ << " @\n";
IncreaseIndent();
PrintExpression(node.argument.get(), "argument", true);
DecreaseIndent();
}
void DebugPrinter::VisitAssignmentExpression(AssignmentExpression& node)
{
PrintIndent();
PrintColored("AssignmentExpression", Color::Yellow);
os_ << " ";
PrintOperator(node.op);
os_ << "\n";
IncreaseIndent();
PrintLeftHandSide(node.left, "left", false);
PrintExpression(node.right.get(), "right", true);
DecreaseIndent();
}
void DebugPrinter::VisitExpressionStatement(ExpressionStatement& node)
{
PrintIndent();
PrintColored("ExpressionStatement", Color::BrightYellow);
os_ << "\n";
IncreaseIndent();
PrintExpression(node.expression.get(), "", true);
DecreaseIndent();
}
void DebugPrinter::VisitVarStatement(VarStatement& node)
{
PrintIndent();
PrintColored("VarStatement", Color::BrightYellow);
os_ << "\n";
IncreaseIndent();
for (size_t i = 0; i < node.declarations.size(); ++i)
{
bool is_last = (i == node.declarations.size() - 1);
is_last_child_stack_.push_back(is_last);
node.declarations[i]->Accept(*this);
is_last_child_stack_.pop_back();
}
DecreaseIndent();
}
void DebugPrinter::VisitStaticStatement(StaticStatement& node)
{
PrintIndent();
PrintColored("StaticStatement", Color::BrightYellow);
os_ << "\n";
IncreaseIndent();
for (size_t i = 0; i < node.declarations.size(); ++i)
{
bool is_last = (i == node.declarations.size() - 1);
is_last_child_stack_.push_back(is_last);
node.declarations[i]->Accept(*this);
is_last_child_stack_.pop_back();
}
DecreaseIndent();
}
void DebugPrinter::VisitGlobalStatement(GlobalStatement& node)
{
PrintIndent();
PrintColored("GlobalStatement", Color::BrightYellow);
os_ << "\n";
IncreaseIndent();
for (size_t i = 0; i < node.declarations.size(); ++i)
{
bool is_last = (i == node.declarations.size() - 1);
is_last_child_stack_.push_back(is_last);
node.declarations[i]->Accept(*this);
is_last_child_stack_.pop_back();
}
DecreaseIndent();
}
void DebugPrinter::VisitConstStatement(ConstStatement& node)
{
PrintIndent();
PrintColored("ConstStatement", Color::BrightYellow);
os_ << " " << GetColor(Color::BrightCyan) << node.name << GetColor(Color::Reset);
if (node.type_name)
{
os_ << ": " << GetColor(Color::BrightBlue) << *node.type_name << GetColor(Color::Reset);
}
os_ << "\n";
IncreaseIndent();
PrintExpression(node.value.get(), "value", true);
DecreaseIndent();
}
void DebugPrinter::VisitAssignmentStatement(AssignmentStatement& node)
{
PrintIndent();
PrintColored("AssignmentStatement", Color::BrightYellow);
os_ << " ";
PrintOperator(node.op);
os_ << "\n";
IncreaseIndent();
PrintLeftHandSide(node.left, "left", false);
PrintExpression(node.right.get(), "right", true);
DecreaseIndent();
}
void DebugPrinter::VisitBlockStatement(BlockStatement& node)
{
PrintIndent();
PrintColored("BlockStatement", Color::BrightYellow);
os_ << "\n";
IncreaseIndent();
PrintStatements(node.statements);
DecreaseIndent();
}
void DebugPrinter::VisitIfStatement(IfStatement& node)
{
PrintIndent();
PrintColored("IfStatement", Color::BrightYellow);
os_ << "\n";
IncreaseIndent();
for (size_t i = 0; i < node.branches.size(); ++i)
{
bool is_last = (i == node.branches.size() - 1);
const auto& branch = node.branches[i];
PrintIndent(is_last);
PrintColored(i == 0 ? "if" : "elif", Color::Green);
os_ << ":\n";
is_last_child_stack_.push_back(is_last);
IncreaseIndent();
PrintExpression(branch.condition.get(), "condition", false);
PrintStatement(branch.body.get(), "body", true);
DecreaseIndent();
is_last_child_stack_.pop_back();
}
DecreaseIndent();
}
void DebugPrinter::VisitForInStatement(ForInStatement& node)
{
PrintIndent();
PrintColored("ForInStatement", Color::BrightYellow);
os_ << "\n";
IncreaseIndent();
PrintIndent();
PrintColored("iterator", Color::Green);
os_ << ": ";
if (!node.key.empty())
{
PrintColored(node.key, Color::BrightCyan);
os_ << ", ";
}
PrintColored(node.value, Color::BrightCyan);
os_ << "\n";
PrintExpression(node.collection.get(), "collection", false);
PrintStatement(node.body.get(), "body", true);
DecreaseIndent();
}
void DebugPrinter::VisitForToStatement(ForToStatement& node)
{
PrintIndent();
PrintColored("ForToStatement", Color::BrightYellow);
os_ << " " << GetColor(Color::BrightCyan) << node.counter << GetColor(Color::Reset);
if (node.is_downto)
{
os_ << " " << GetColor(Color::Magenta) << "[downto]" << GetColor(Color::Reset);
}
os_ << "\n";
IncreaseIndent();
PrintExpression(node.start.get(), "start", false);
PrintExpression(node.end.get(), "end", false);
PrintStatement(node.body.get(), "body", true);
DecreaseIndent();
}
void DebugPrinter::VisitWhileStatement(WhileStatement& node)
{
PrintIndent();
PrintColored("WhileStatement", Color::BrightYellow);
os_ << "\n";
IncreaseIndent();
PrintExpression(node.condition.get(), "condition", false);
PrintStatement(node.body.get(), "body", true);
DecreaseIndent();
}
void DebugPrinter::VisitRepeatStatement(RepeatStatement& node)
{
PrintIndent();
PrintColored("RepeatStatement", Color::BrightYellow);
os_ << "\n";
IncreaseIndent();
if (!node.body.empty())
{
PrintIndent();
PrintColored("body", Color::Green);
os_ << ":\n";
IncreaseIndent();
PrintStatements(node.body);
DecreaseIndent();
}
PrintExpression(node.condition.get(), "condition", true);
DecreaseIndent();
}
void DebugPrinter::VisitCaseStatement(CaseStatement& node)
{
PrintIndent();
PrintColored("CaseStatement", Color::BrightYellow);
os_ << "\n";
IncreaseIndent();
PrintExpression(node.discriminant.get(), "discriminant", false);
if (!node.branches.empty())
{
PrintIndent(!node.default_case);
PrintColored("branches", Color::Green);
os_ << ":\n";
is_last_child_stack_.push_back(!node.default_case);
IncreaseIndent();
for (size_t i = 0; i < node.branches.size(); ++i)
{
bool is_last = (i == node.branches.size() - 1);
const auto& branch = node.branches[i];
PrintIndent(is_last);
PrintColored("case", Color::Magenta);
os_ << ":\n";
is_last_child_stack_.push_back(is_last);
IncreaseIndent();
if (!branch.values.empty())
{
PrintIndent(false);
PrintColored("values", Color::Green);
os_ << ":\n";
is_last_child_stack_.push_back(false); // values 不是最后一个body 在后面)
IncreaseIndent();
for (size_t j = 0; j < branch.values.size(); ++j)
{
bool val_is_last = (j == branch.values.size() - 1);
is_last_child_stack_.push_back(val_is_last);
PrintExpression(branch.values[j].get(), "", val_is_last);
is_last_child_stack_.pop_back();
}
DecreaseIndent();
is_last_child_stack_.pop_back();
}
PrintStatement(branch.body.get(), "body", true);
DecreaseIndent();
is_last_child_stack_.pop_back();
}
DecreaseIndent();
is_last_child_stack_.pop_back();
}
if (node.default_case)
{
PrintStatement(node.default_case.get(), "default", true);
}
DecreaseIndent();
}
void DebugPrinter::VisitTryStatement(TryStatement& node)
{
PrintIndent();
PrintColored("TryStatement", Color::BrightYellow);
os_ << "\n";
IncreaseIndent();
PrintStatement(node.try_body.get(), "try", false);
PrintStatement(node.except_body.get(), "except", true);
DecreaseIndent();
}
void DebugPrinter::VisitBreakStatement(BreakStatement&)
{
PrintIndent();
PrintColored("BreakStatement", Color::BrightYellow);
os_ << "\n";
}
void DebugPrinter::VisitContinueStatement(ContinueStatement&)
{
PrintIndent();
PrintColored("ContinueStatement", Color::BrightYellow);
os_ << "\n";
}
void DebugPrinter::VisitReturnStatement(ReturnStatement& node)
{
PrintIndent();
PrintColored("ReturnStatement", Color::BrightYellow);
os_ << "\n";
if (node.value)
{
IncreaseIndent();
PrintExpression(node.value.get(), "value", true);
DecreaseIndent();
}
}
void DebugPrinter::VisitUsesStatement(UsesStatement& node)
{
PrintIndent();
PrintColored("UsesStatement", Color::BrightYellow);
os_ << ": ";
for (size_t i = 0; i < node.units.size(); ++i)
{
if (i > 0)
os_ << ", ";
PrintColored(node.units[i], Color::BrightCyan);
}
os_ << "\n";
}
void DebugPrinter::VisitFunctionDefinition(FunctionDefinition& node)
{
PrintIndent();
PrintColored("FunctionDefinition", Color::BrightYellow);
os_ << " " << GetColor(Color::BrightCyan) << node.name << GetColor(Color::Reset);
if (node.is_overload)
{
os_ << " " << GetColor(Color::Magenta) << "[overload]" << GetColor(Color::Reset);
}
if (options_.show_location)
{
os_ << " ";
PrintLocation(node.location);
}
os_ << "\n";
// ===== 修复:不需要 IncreaseIndent缩进由 stack 管理 =====
bool signature_is_last = !node.body;
PrintIndent(signature_is_last);
PrintColored("signature", Color::Green);
os_ << ":\n";
is_last_child_stack_.push_back(signature_is_last);
IncreaseIndent(); // 这个保留,因为有对应的 push
PrintSignature(node.signature);
DecreaseIndent();
is_last_child_stack_.pop_back();
if (node.body)
PrintStatement(node.body.get(), "body", true);
}
void DebugPrinter::VisitFunctionDeclaration(FunctionDeclaration& node)
{
PrintIndent();
PrintColored("FunctionDeclaration", Color::BrightYellow);
os_ << " " << GetColor(Color::BrightCyan) << node.name << GetColor(Color::Reset);
if (node.is_overload)
{
os_ << " " << GetColor(Color::Magenta) << "[overload]" << GetColor(Color::Reset);
}
if (options_.show_location)
{
os_ << " ";
PrintLocation(node.location);
}
os_ << "\n";
// ===== 修复:不需要外层 IncreaseIndent =====
PrintIndent(true); // signature 是唯一子项
PrintColored("signature", Color::Green);
os_ << ":\n";
is_last_child_stack_.push_back(true);
IncreaseIndent();
PrintSignature(node.signature);
DecreaseIndent();
is_last_child_stack_.pop_back();
}
void DebugPrinter::VisitVarDeclaration(VarDeclaration& node)
{
PrintIndent();
PrintColored("VarDeclaration", Color::Yellow);
os_ << " " << GetColor(Color::BrightCyan) << node.name << GetColor(Color::Reset);
if (node.type)
{
os_ << ": " << GetColor(Color::BrightBlue) << node.type->name << GetColor(Color::Reset);
}
if (options_.show_location)
{
os_ << " ";
PrintLocation(node.location);
}
os_ << "\n";
if (node.initial_value)
{
IncreaseIndent();
PrintExpression(node.initial_value.get(), "initial_value", true);
DecreaseIndent();
}
}
void DebugPrinter::VisitStaticDeclaration(StaticDeclaration& node)
{
PrintIndent();
PrintColored("StaticDeclaration", Color::Yellow);
os_ << " " << GetColor(Color::BrightCyan) << node.name << GetColor(Color::Reset);
PrintReferenceModifier(node.reference_modifier);
if (node.type)
{
os_ << ": " << GetColor(Color::BrightBlue) << node.type->name << GetColor(Color::Reset);
}
if (options_.show_location)
{
os_ << " ";
PrintLocation(node.location);
}
os_ << "\n";
if (node.initial_value)
{
IncreaseIndent();
PrintExpression(node.initial_value.get(), "initial_value", true);
DecreaseIndent();
}
}
void DebugPrinter::VisitGlobalDeclaration(GlobalDeclaration& node)
{
PrintIndent();
PrintColored("GlobalDeclaration", Color::Yellow);
os_ << " " << GetColor(Color::BrightCyan) << node.name << GetColor(Color::Reset);
if (node.type)
{
os_ << ": " << GetColor(Color::BrightBlue) << node.type->name << GetColor(Color::Reset);
}
if (options_.show_location)
{
os_ << " ";
PrintLocation(node.location);
}
os_ << "\n";
if (node.initial_value)
{
IncreaseIndent();
PrintExpression(node.initial_value.get(), "initial_value", true);
DecreaseIndent();
}
}
void DebugPrinter::VisitFieldDeclaration(FieldDeclaration& node)
{
PrintIndent();
PrintColored("FieldDeclaration", Color::Yellow);
os_ << " " << GetColor(Color::BrightCyan) << node.name << GetColor(Color::Reset);
PrintReferenceModifier(node.reference_modifier);
if (node.type)
{
os_ << ": " << GetColor(Color::BrightBlue) << node.type->name << GetColor(Color::Reset);
}
os_ << "\n";
if (node.initial_value)
{
IncreaseIndent();
PrintExpression(node.initial_value.get(), "initial_value", true);
DecreaseIndent();
}
}
void DebugPrinter::VisitUnpackPattern(UnpackPattern& node)
{
PrintIndent();
PrintColored("UnpackPattern", Color::Yellow);
os_ << " [";
for (size_t i = 0; i < node.names.size(); ++i)
{
if (i > 0)
os_ << ", ";
PrintColored(node.names[i], Color::BrightCyan);
}
os_ << "]\n";
}
void DebugPrinter::VisitTSSQLExpression(TSSQLExpression& node)
{
PrintIndent();
PrintColored("TSSQLExpression", Color::Yellow);
std::string type_str;
switch (node.sql_type)
{
case TSSQLExpressionType::kSelect:
type_str = "SELECT";
break;
case TSSQLExpressionType::kSSelect:
type_str = "SSELECT";
break;
case TSSQLExpressionType::kVSelect:
type_str = "VSELECT";
break;
case TSSQLExpressionType::kMSelect:
type_str = "MSELECT";
break;
case TSSQLExpressionType::kUpdate:
type_str = "UPDATE";
break;
case TSSQLExpressionType::kDelete:
type_str = "DELETE";
break;
case TSSQLExpressionType::kInsert:
type_str = "INSERT";
break;
default:
type_str = "UNKNOWN";
break;
}
os_ << " [" << GetColor(Color::BrightBlue) << type_str << GetColor(Color::Reset) << "]\n";
IncreaseIndent();
PrintIndent();
PrintColored("sql", Color::Green);
os_ << ": " << GetColor(Color::BrightGreen) << EscapeString(node.raw_sql) << GetColor(Color::Reset) << "\n";
DecreaseIndent();
}
void DebugPrinter::VisitMatrixIterationStatement(MatrixIterationStatement& node)
{
PrintIndent();
PrintColored("MatrixIterationStatement", Color::BrightYellow);
os_ << "\n";
IncreaseIndent();
PrintExpression(node.target.get(), "target", false);
PrintStatement(node.body.get(), "body", true);
DecreaseIndent();
}
void DebugPrinter::VisitCompilerDirectiveStatement(CompilerDirectiveStatement& node)
{
PrintIndent();
PrintColored("CompilerDirectiveStatement", Color::BrightYellow);
os_ << " " << GetColor(Color::BrightCyan) << "{$" << node.name;
if (node.switch_value)
{
os_ << *node.switch_value;
}
os_ << "}" << GetColor(Color::Reset) << "\n";
}
void DebugPrinter::VisitConditionalDirectiveStatement(ConditionalDirectiveStatement& node)
{
PrintIndent();
PrintColored("ConditionalDirectiveStatement", Color::BrightYellow);
os_ << " " << GetColor(Color::BrightCyan) << "{$";
PrintConditionalCompilationType(node.type);
os_ << " " << node.name << "}" << GetColor(Color::Reset) << "\n";
}
void DebugPrinter::VisitConditionalBlockStatement(ConditionalBlockStatement& node)
{
PrintIndent();
PrintColored("ConditionalBlockStatement", Color::BrightYellow);
os_ << " " << GetColor(Color::BrightCyan) << "{$";
PrintConditionalCompilationType(node.type);
os_ << " " << node.name << "}" << GetColor(Color::Reset) << "\n";
IncreaseIndent();
if (!node.consequence.empty())
{
PrintIndent(!node.alternative.empty());
PrintColored("consequence", Color::Green);
os_ << ":\n";
is_last_child_stack_.push_back(!node.alternative.empty());
IncreaseIndent();
PrintStatements(node.consequence);
DecreaseIndent();
is_last_child_stack_.pop_back();
}
if (!node.alternative.empty())
{
PrintIndent(true);
PrintColored("alternative", Color::Green);
os_ << " " << GetColor(Color::Cyan) << "{$ELSE}" << GetColor(Color::Reset) << ":\n";
is_last_child_stack_.push_back(true);
IncreaseIndent();
PrintStatements(node.alternative);
DecreaseIndent();
is_last_child_stack_.pop_back();
}
DecreaseIndent();
}
}