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

2750 lines
81 KiB
C++

#include "debug_printer.hpp"
#include <sstream>
namespace lsp::language::ast::debug
{
// ===== 辅助函数实现 =====
void DebugPrinter::Print(const ASTNode* node)
{
if (!node)
{
os_ << GetColor(Color::Gray) << "<null>" << GetColor(Color::Reset) << "\n";
return;
}
const_cast<ASTNode*>(node)->Accept(*this);
}
void DebugPrinter::PrintStatements(const std::vector<StatementPtr>& statements)
{
for (size_t i = 0; i < statements.size(); ++i)
{
bool is_last = (i == statements.size() - 1);
is_last_child_stack_.push_back(is_last);
PrintStatement(statements[i].get(), "", is_last);
is_last_child_stack_.pop_back();
}
}
void DebugPrinter::PrintParseResult(const ParseResult& result)
{
if (result.HasErrors())
{
os_ << GetColor(Color::BrightRed) << "Parse Errors:\n"
<< GetColor(Color::Reset);
for (const auto& error : result.errors)
{
PrintError(error);
}
os_ << "\n";
}
if (result.root)
{
Print(result.root.get());
}
}
// ===== 缩进和树形结构 =====
void DebugPrinter::PrintIndent(std::optional<bool> is_last)
{
if (!options_.use_tree_chars)
{
os_ << std::string(current_indent_, ' ');
return;
}
if (is_last.has_value())
{
// When the caller provides is_last, we treat current stack entries as ancestors.
for (size_t i = 0; i < is_last_child_stack_.size(); ++i)
{
os_ << (is_last_child_stack_[i] ? " " : "");
}
os_ << (is_last.value() ? "└─ " : "├─ ");
return;
}
// Default behavior: draw the branch for the current node itself.
if (is_last_child_stack_.empty())
return;
bool is_last_val = is_last_child_stack_.back();
for (size_t i = 0; i < is_last_child_stack_.size(); ++i)
{
if (i == is_last_child_stack_.size() - 1)
{
os_ << (is_last_val ? "└─ " : "├─ ");
}
else
{
os_ << (is_last_child_stack_[i] ? " " : "");
}
}
}
void DebugPrinter::PrintTreePrefix(bool is_last)
{
if (!options_.use_tree_chars)
{
os_ << std::string(current_indent_, ' ');
return;
}
for (size_t i = 0; i < is_last_child_stack_.size(); ++i)
{
os_ << (is_last_child_stack_[i] ? " " : "");
}
os_ << (is_last ? "└─ " : "├─ ");
}
std::string DebugPrinter::GetIndent() const
{
return std::string(current_indent_, ' ');
}
void DebugPrinter::EmitChildren(std::vector<std::function<void(bool)>>&& children)
{
size_t count = children.size();
for (size_t i = 0; i < count; ++i)
{
children[i](i == count - 1);
}
}
// ===== 颜色辅助 =====
const char* DebugPrinter::GetColor(const char* color) const
{
return options_.use_colors ? color : "";
}
void DebugPrinter::PrintColored(const std::string& text, const char* color)
{
os_ << GetColor(color) << text << GetColor(Color::Reset);
}
// ===== 节点信息输出 =====
void DebugPrinter::PrintNodeHeader(const std::string& type_name, const Location& loc)
{
PrintIndent();
PrintColored(type_name, Color::BrightCyan);
if (options_.show_location)
{
os_ << " ";
PrintLocation(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, bool is_last_child)
{
if (!source_code_)
return;
std::string snippet = GetSourceText(loc);
if (snippet.empty())
return;
snippet = TruncateString(snippet, options_.max_source_length);
snippet = EscapeString(snippet);
os_ << "\n";
PrintIndent(is_last_child);
os_ << GetColor(Color::Dim) << "Source: \"" << snippet << "\""
<< GetColor(Color::Reset) << "\n";
}
void DebugPrinter::PrintKeyValue(const std::string& key, const std::string& value, const Location& location, const char* value_color, std::optional<bool> is_last)
{
PrintIndent(is_last);
PrintColored(key + ": ", Color::Yellow);
PrintColored(value, value_color ? value_color : Color::Green);
if (options_.show_location)
{
os_ << " ";
PrintLocation(location);
}
os_ << "\n";
}
void DebugPrinter::PrintKeyValue(const std::string& key, const std::string& value, const char* value_color, std::optional<bool> is_last)
{
PrintIndent(is_last);
PrintColored(key + ": ", Color::Yellow);
PrintColored(value, value_color ? value_color : Color::Green);
os_ << "\n";
}
void DebugPrinter::PrintKeyValue(const std::string& key, int value, std::optional<bool> is_last)
{
PrintIndent(is_last);
PrintColored(key + ": ", Color::Yellow);
os_ << value << "\n";
}
void DebugPrinter::PrintKeyValue(const std::string& key, bool value, std::optional<bool> is_last)
{
PrintIndent(is_last);
PrintColored(key + ": ", Color::Yellow);
PrintColored(value ? "true" : "false", value ? Color::BrightGreen : Color::BrightRed);
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::Yellow);
}
PrintColored("<null>", Color::Gray);
os_ << "\n";
return;
}
if (!label.empty())
{
PrintIndent(is_last);
PrintColored(label + ":", Color::Yellow);
os_ << "\n";
IncreaseIndent();
// Treat label as a tree node with a single child.
is_last_child_stack_.push_back(is_last);
is_last_child_stack_.push_back(true);
const_cast<Expression*>(expr)->Accept(*this);
is_last_child_stack_.pop_back();
is_last_child_stack_.pop_back();
DecreaseIndent();
return;
}
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::Yellow);
}
PrintColored("<null>", Color::Gray);
os_ << "\n";
return;
}
if (!label.empty())
{
PrintIndent(is_last);
PrintColored(label + ":", Color::Yellow);
os_ << "\n";
IncreaseIndent();
// Treat label as a tree node with a single child.
is_last_child_stack_.push_back(is_last);
is_last_child_stack_.push_back(true);
const_cast<Statement*>(stmt)->Accept(*this);
is_last_child_stack_.pop_back();
is_last_child_stack_.pop_back();
DecreaseIndent();
return;
}
is_last_child_stack_.push_back(is_last);
const_cast<Statement*>(stmt)->Accept(*this);
is_last_child_stack_.pop_back();
}
void DebugPrinter::PrintParameter(const Parameter& param, bool is_last)
{
PrintIndent(is_last);
PrintColored("Parameter: ", Color::Cyan);
PrintColored("\"" + param.name + "\"", Color::Green);
if (param.type)
{
os_ << " : ";
PrintColored(param.type->name, Color::BrightYellow);
}
switch (param.mode)
{
case ast::ParameterMode::kNone:
break;
case ast::ParameterMode::kConst:
os_ << " " << GetColor(Color::Magenta) << "(const)" << GetColor(Color::Reset);
break;
case ast::ParameterMode::kIn:
os_ << " " << GetColor(Color::Magenta) << "(in)" << GetColor(Color::Reset);
break;
case ast::ParameterMode::kOut:
os_ << " " << GetColor(Color::Magenta) << "(out)" << GetColor(Color::Reset);
break;
case ast::ParameterMode::kVar:
os_ << " " << GetColor(Color::Magenta) << "(var)" << GetColor(Color::Reset);
break;
}
if (param.default_value)
{
os_ << " = <expr>";
}
os_ << "\n";
}
void DebugPrinter::PrintLeftHandSide(const LValue& lhs, const std::string& label, bool is_last)
{
std::visit([&](auto&& value) {
using T = std::decay_t<decltype(value)>;
if constexpr (std::is_same_v<T, std::monostate>)
{
PrintIndent(is_last);
if (!label.empty())
{
PrintColored(label + ": ", Color::Yellow);
}
PrintColored("<empty>", Color::Gray);
os_ << "\n";
}
else if constexpr (std::is_same_v<T, ExpressionPtr>)
{
PrintExpression(value.get(), label, is_last);
}
else if constexpr (std::is_same_v<T, std::unique_ptr<Identifier>> ||
std::is_same_v<T, std::unique_ptr<AttributeExpression>> ||
std::is_same_v<T, std::unique_ptr<SubscriptExpression>> ||
std::is_same_v<T, std::unique_ptr<ColumnReference>>)
{
if (!label.empty())
{
PrintIndent(is_last);
PrintColored(label + ":", Color::Yellow);
os_ << "\n";
IncreaseIndent();
// Label node wraps a single child.
is_last_child_stack_.push_back(is_last);
is_last_child_stack_.push_back(true);
if (value)
value->Accept(*this);
is_last_child_stack_.pop_back();
is_last_child_stack_.pop_back();
DecreaseIndent();
}
else
{
is_last_child_stack_.push_back(is_last);
if (value)
value->Accept(*this);
is_last_child_stack_.pop_back();
}
}
else if constexpr (std::is_same_v<T, std::unique_ptr<UnpackPattern>>)
{
if (!label.empty())
{
PrintIndent(is_last);
PrintColored(label + ":", Color::Yellow);
os_ << "\n";
IncreaseIndent();
// Label node wraps a single child.
is_last_child_stack_.push_back(is_last);
is_last_child_stack_.push_back(true);
if (value)
value->Accept(*this);
is_last_child_stack_.pop_back();
is_last_child_stack_.pop_back();
DecreaseIndent();
}
else
{
is_last_child_stack_.push_back(is_last);
if (value)
value->Accept(*this);
is_last_child_stack_.pop_back();
}
}
},
lhs);
}
// ===== 枚举值打印 =====
void DebugPrinter::PrintOperator(BinaryOperator op)
{
PrintColored(GetBinaryOperatorSymbol(op), Color::BrightMagenta);
}
void DebugPrinter::PrintOperator(AssignmentOperator op)
{
PrintColored(GetAssignmentOperatorSymbol(op), Color::BrightMagenta);
}
void DebugPrinter::PrintLiteralKind(LiteralKind kind)
{
const char* kind_str = "";
switch (kind)
{
case LiteralKind::kNumber:
kind_str = "Number";
break;
case LiteralKind::kString:
kind_str = "String";
break;
case LiteralKind::kChar:
kind_str = "Char";
break;
case LiteralKind::kBoolean:
kind_str = "Boolean";
break;
case LiteralKind::kNil:
kind_str = "Nil";
break;
case LiteralKind::kNan:
kind_str = "NaN";
break;
case LiteralKind::kInfinity:
kind_str = "Infinity";
break;
}
PrintColored(kind_str, Color::BrightYellow);
}
void DebugPrinter::PrintAccessModifier(AccessModifier modifier)
{
const char* 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;
}
PrintColored(mod_str, Color::BrightYellow);
}
void DebugPrinter::PrintMethodModifier(MethodModifier modifier)
{
const char* mod_str = "";
switch (modifier)
{
case MethodModifier::kNone:
mod_str = "none";
break;
case MethodModifier::kVirtual:
mod_str = "virtual";
break;
case MethodModifier::kOverride:
mod_str = "override";
break;
case MethodModifier::kOverload:
mod_str = "overload";
break;
}
PrintColored(mod_str, Color::BrightYellow);
}
void DebugPrinter::PrintMethodType(MethodKind kind)
{
const char* type_str = "";
switch (kind)
{
case MethodKind::kOrdinary:
type_str = "ordinary";
break;
case MethodKind::kConstructor:
type_str = "constructor";
break;
case MethodKind::kDestructor:
type_str = "destructor";
break;
case MethodKind::kOperator:
type_str = "operator";
break;
}
PrintColored(type_str, Color::BrightYellow);
}
void DebugPrinter::PrintReferenceModifier(ReferenceModifier modifier)
{
const char* mod_str = "";
switch (modifier)
{
case ReferenceModifier::kNone:
return;
case ReferenceModifier::kWeakRef:
mod_str = "weakref";
break;
case ReferenceModifier::kAutoRef:
mod_str = "autoref";
break;
}
PrintColored(mod_str, Color::Magenta);
}
void DebugPrinter::PrintConditionalCompilationType(ConditionalCompilationType type)
{
const char* type_str = "";
switch (type)
{
case ConditionalCompilationType::kIfDef:
type_str = "ifdef";
break;
case ConditionalCompilationType::kIfNDef:
type_str = "ifndef";
break;
case ConditionalCompilationType::kDefine:
type_str = "define";
break;
case ConditionalCompilationType::kUndef:
type_str = "undef";
break;
}
PrintColored(type_str, Color::BrightYellow);
}
void DebugPrinter::PrintTSSQLExpressionType(TSSQLExpressionType type)
{
const char* type_str = "";
switch (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;
}
PrintColored(type_str, Color::BrightYellow);
}
void DebugPrinter::PrintError(const ParseError& error)
{
os_ << GetColor(Color::BrightRed) << " Error: " << GetColor(Color::Reset)
<< error.message << "\n";
os_ << GetColor(Color::Gray) << " Location: ["
<< error.location.start_line << ":" << error.location.start_column << " - "
<< error.location.end_line << ":" << error.location.end_column << "]"
<< GetColor(Color::Reset) << "\n";
}
// ===== 工具函数 =====
std::string DebugPrinter::EscapeString(const std::string& str) const
{
std::string result;
for (char c : str)
{
switch (c)
{
case '\n':
result += "\\n";
break;
case '\r':
result += "\\r";
break;
case '\t':
result += "\\t";
break;
case '"':
result += "\\\"";
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 - 3) + "...";
}
std::string DebugPrinter::GetSourceText(const Location& loc) const
{
if (!source_code_)
return "";
if (loc.start_offset >= source_code_->length())
return "";
size_t length = loc.end_offset - loc.start_offset;
if (loc.start_offset + length > source_code_->length())
length = source_code_->length() - loc.start_offset;
return source_code_->substr(loc.start_offset, length);
}
std::string DebugPrinter::GetNodeKindName(NodeKind kind) const
{
switch (kind)
{
case NodeKind::kIdentifier:
return "kIdentifier";
case NodeKind::kLiteral:
return "kLiteral";
case NodeKind::kArrayExpression:
return "kArrayExpression";
case NodeKind::kParenthesizedExpression:
return "kParenthesizedExpression";
case NodeKind::kAttributeExpression:
return "kAttributeExpression";
case NodeKind::kSubscriptExpression:
return "kSubscriptExpression";
case NodeKind::kCallExpression:
return "kCallExpression";
case NodeKind::kUnaryPlusExpression:
return "kUnaryPlusExpression";
case NodeKind::kUnaryMinusExpression:
return "kUnaryMinusExpression";
case NodeKind::kPrefixIncrementExpression:
return "kPrefixIncrementExpression";
case NodeKind::kPrefixDecrementExpression:
return "kPrefixDecrementExpression";
case NodeKind::kPostfixIncrementExpression:
return "kPostfixIncrementExpression";
case NodeKind::kPostfixDecrementExpression:
return "kPostfixDecrementExpression";
case NodeKind::kLogicalNotExpression:
return "kLogicalNotExpression";
case NodeKind::kBitwiseNotExpression:
return "kBitwiseNotExpression";
case NodeKind::kDerivativeExpression:
return "kDerivativeExpression";
case NodeKind::kFunctionPointerExpression:
return "kFunctionPointerExpression";
case NodeKind::kMatrixTransposeExpression:
return "kMatrixTransposeExpression";
case NodeKind::kExprOperatorExpression:
return "kExprOperatorExpression";
case NodeKind::kBinaryExpression:
return "kBinaryExpression";
case NodeKind::kTernaryExpression:
return "kTernaryExpression";
case NodeKind::kAssignmentExpression:
return "kAssignmentExpression";
case NodeKind::kAnonymousFunctionExpression:
return "kAnonymousFunctionExpression";
case NodeKind::kNewExpression:
return "kNewExpression";
case NodeKind::kEchoExpression:
return "kEchoExpression";
case NodeKind::kRaiseExpression:
return "kRaiseExpression";
case NodeKind::kInheritedExpression:
return "kInheritedExpression";
case NodeKind::kTSSQLExpression:
return "kTSSQLExpression";
case NodeKind::kColumnReference:
return "kColumnReference";
case NodeKind::kUnpackPattern:
return "kUnpackPattern";
case NodeKind::kParameter:
return "kParameter";
case NodeKind::kVarDeclaration:
return "kVarDeclaration";
case NodeKind::kStaticDeclaration:
return "kStaticDeclaration";
case NodeKind::kGlobalDeclaration:
return "kGlobalDeclaration";
case NodeKind::kConstDeclaration:
return "kConstDeclaration";
case NodeKind::kFieldDeclaration:
return "kFieldDeclaration";
case NodeKind::kExpressionStatement:
return "kExpressionStatement";
case NodeKind::kBlockStatement:
return "kBlockStatement";
case NodeKind::kIfStatement:
return "kIfStatement";
case NodeKind::kForInStatement:
return "kForInStatement";
case NodeKind::kForToStatement:
return "kForToStatement";
case NodeKind::kWhileStatement:
return "kWhileStatement";
case NodeKind::kRepeatStatement:
return "kRepeatStatement";
case NodeKind::kCaseStatement:
return "kCaseStatement";
case NodeKind::kTryStatement:
return "kTryStatement";
case NodeKind::kBreakStatement:
return "kBreakStatement";
case NodeKind::kContinueStatement:
return "kContinueStatement";
case NodeKind::kReturnStatement:
return "kReturnStatement";
case NodeKind::kUsesStatement:
return "kUsesStatement";
case NodeKind::kFunctionDeclaration:
return "kFunctionDeclaration";
case NodeKind::kFunctionDefinition:
return "kFunctionDefinition";
case NodeKind::kMethodDeclaration:
return "kMethodDeclaration";
case NodeKind::kPropertyDeclaration:
return "kPropertyDeclaration";
case NodeKind::kClassMember:
return "kClassMember";
case NodeKind::kClassDefinition:
return "kClassDefinition";
case NodeKind::kExternalMethodDefinition:
return "kExternalMethodDefinition";
case NodeKind::kUnitDefinition:
return "kUnitDefinition";
case NodeKind::kMatrixIterationStatement:
return "kMatrixIterationStatement";
case NodeKind::kCompilerDirective:
return "kCompilerDirective";
case NodeKind::kConditionalBlock:
return "kConditionalBlock";
case NodeKind::kConditionalDirective:
return "kConditionalDirective";
case NodeKind::kTSLXBlock:
return "kTSLXBlock";
case NodeKind::kProgram:
return "kProgram";
default:
return "kUnknown";
}
}
// ===== Visitor 实现 - 基础节点 =====
void DebugPrinter::VisitProgram(Program& node)
{
PrintNodeHeader("Program", node.span);
bool has_source = options_.show_source_code && source_code_ && !GetSourceText(node.span).empty();
size_t child_count = node.statements.size();
if (has_source)
++child_count;
if (options_.show_node_kind)
++child_count;
size_t child_index = 0;
auto emit_child = [&](auto&& fn) {
bool is_last_child = ++child_index == child_count;
fn(is_last_child);
};
IncreaseIndent();
if (has_source)
{
emit_child([&](bool is_last) { PrintSourceSnippet(node.span, is_last); });
}
if (options_.show_node_kind)
{
emit_child([&](bool is_last) {
PrintKeyValue("Kind", GetNodeKindName(node.kind), node.span, nullptr, is_last);
});
}
for (const auto& stmt : node.statements)
{
emit_child([&](bool is_last) { PrintStatement(stmt.get(), "", is_last); });
}
DecreaseIndent();
}
void DebugPrinter::VisitUnitDefinition(UnitDefinition& node)
{
PrintIndent();
PrintColored("UnitDefinition: ", Color::BrightCyan);
PrintColored("\"" + node.name + "\"", Color::Green);
if (options_.show_location)
{
os_ << " ";
PrintLocation(node.location);
}
os_ << "\n";
IncreaseIndent();
std::vector<std::function<void(bool)>> children;
if (!node.interface_statements.empty())
{
children.push_back([&](bool is_last) {
PrintIndent(is_last);
PrintColored("Interface:", Color::Yellow);
os_ << "\n";
IncreaseIndent();
is_last_child_stack_.push_back(is_last);
PrintStatements(node.interface_statements);
is_last_child_stack_.pop_back();
DecreaseIndent();
});
}
if (!node.implementation_statements.empty())
{
children.push_back([&](bool is_last) {
PrintIndent(is_last);
PrintColored("Implementation:", Color::Yellow);
os_ << "\n";
IncreaseIndent();
is_last_child_stack_.push_back(is_last);
PrintStatements(node.implementation_statements);
is_last_child_stack_.pop_back();
DecreaseIndent();
});
}
if (!node.initialization_statements.empty())
{
children.push_back([&](bool is_last) {
PrintIndent(is_last);
PrintColored("Initialization:", Color::Yellow);
os_ << "\n";
IncreaseIndent();
is_last_child_stack_.push_back(is_last);
PrintStatements(node.initialization_statements);
is_last_child_stack_.pop_back();
DecreaseIndent();
});
}
if (!node.finalization_statements.empty())
{
children.push_back([&](bool is_last) {
PrintIndent(is_last);
PrintColored("Finalization:", Color::Yellow);
os_ << "\n";
IncreaseIndent();
is_last_child_stack_.push_back(is_last);
PrintStatements(node.finalization_statements);
is_last_child_stack_.pop_back();
DecreaseIndent();
});
}
EmitChildren(std::move(children));
DecreaseIndent();
}
void DebugPrinter::VisitClassDefinition(ClassDefinition& node)
{
PrintIndent();
PrintColored("ClassDefinition: ", Color::BrightCyan);
PrintColored("\"" + node.name + "\"", Color::Green);
if (options_.show_location)
{
os_ << " ";
PrintLocation(node.location);
}
os_ << "\n";
IncreaseIndent();
std::vector<std::function<void(bool)>> children;
if (!node.parent_classes.empty())
{
children.push_back([&](bool is_last) {
PrintIndent(is_last);
PrintColored("Parents:", Color::Yellow);
os_ << "\n";
IncreaseIndent();
is_last_child_stack_.push_back(is_last);
for (size_t i = 0; i < node.parent_classes.size(); ++i)
{
const auto& parent = node.parent_classes[i];
PrintIndent(i == node.parent_classes.size() - 1);
if (parent.qualifier)
{
PrintColored(*parent.qualifier + ".", Color::Magenta);
}
PrintColored(parent.name, Color::Green);
os_ << "\n";
}
is_last_child_stack_.pop_back();
DecreaseIndent();
});
}
if (node.uses)
{
children.push_back([&](bool is_last) {
is_last_child_stack_.push_back(is_last);
node.uses->Accept(*this);
is_last_child_stack_.pop_back();
});
}
if (!node.members.empty())
{
children.push_back([&](bool is_last) {
PrintIndent(is_last);
PrintColored("Members:", Color::Yellow);
os_ << "\n";
IncreaseIndent();
is_last_child_stack_.push_back(is_last);
for (size_t i = 0; i < node.members.size(); ++i)
{
is_last_child_stack_.push_back(i == node.members.size() - 1);
if (node.members[i])
node.members[i]->Accept(*this);
is_last_child_stack_.pop_back();
}
is_last_child_stack_.pop_back();
DecreaseIndent();
});
}
EmitChildren(std::move(children));
DecreaseIndent();
}
void DebugPrinter::VisitClassMember(ClassMember& node)
{
PrintIndent();
PrintColored("ClassMember", Color::BrightCyan);
if (node.access_modifier != AccessModifier::kPublic)
{
os_ << " (";
PrintAccessModifier(node.access_modifier);
os_ << ")";
}
os_ << "\n";
IncreaseIndent();
// 处理 member variant
std::visit([this](auto&& member_ptr) {
if (member_ptr)
{
is_last_child_stack_.push_back(true);
member_ptr->Accept(*this);
is_last_child_stack_.pop_back();
}
},
node.member);
DecreaseIndent();
}
void DebugPrinter::VisitMethodDeclaration(MethodDeclaration& node)
{
PrintIndent();
PrintColored("MethodDeclaration: ", Color::BrightCyan);
PrintColored("\"" + node.name + "\"", Color::Green);
if (options_.show_location)
{
os_ << " ";
PrintLocation(node.location);
}
os_ << "\n";
IncreaseIndent();
std::vector<std::function<void(bool)>> children;
if (node.modifier != MethodModifier::kNone)
{
children.push_back([&](bool is_last) {
PrintIndent(is_last);
PrintColored("Modifier: ", Color::Yellow);
PrintMethodModifier(node.modifier);
os_ << "\n";
});
}
if (node.method_kind != MethodKind::kOrdinary)
{
children.push_back([&](bool is_last) {
PrintIndent(is_last);
PrintColored("MethodKind: ", Color::Yellow);
PrintMethodType(node.method_kind);
os_ << "\n";
});
}
if (node.is_static)
{
children.push_back([&](bool is_last) { PrintKeyValue("ClassMethod", true, is_last); });
}
if (!node.parameters.empty())
{
children.push_back([&](bool is_last) {
PrintIndent(is_last);
PrintColored("Parameters:", Color::Yellow);
os_ << "\n";
IncreaseIndent();
is_last_child_stack_.push_back(is_last);
for (size_t i = 0; i < node.parameters.size(); ++i)
{
if (node.parameters[i])
{
PrintParameter(*node.parameters[i], i == node.parameters.size() - 1);
}
}
is_last_child_stack_.pop_back();
DecreaseIndent();
});
}
if (node.return_type)
{
children.push_back([&](bool is_last) { PrintKeyValue("ReturnType", node.return_type->name, nullptr, is_last); });
}
if (node.body)
{
children.push_back([&](bool is_last) { PrintStatement(node.body.get(), "Body", is_last); });
}
EmitChildren(std::move(children));
DecreaseIndent();
}
void DebugPrinter::VisitPropertyDeclaration(PropertyDeclaration& node)
{
PrintIndent();
PrintColored("PropertyDeclaration: ", Color::BrightCyan);
PrintColored("\"" + node.name + "\"", Color::Green);
if (options_.show_location)
{
os_ << " ";
PrintLocation(node.location);
}
os_ << "\n";
IncreaseIndent();
std::vector<std::function<void(bool)>> children;
if (node.type)
{
children.push_back([&](bool is_last) { PrintKeyValue("Type", node.type->name, nullptr, is_last); });
}
if (node.index)
{
children.push_back([&](bool is_last) { PrintExpression(node.index.value().get(), "Index", is_last); });
}
if (node.read_accessor)
{
children.push_back([&](bool is_last) {
PrintIndent(is_last);
PrintColored("Read: ", Color::Yellow);
PrintColored("\"" + node.read_accessor.value() + "\"", Color::Green);
if (options_.show_location && node.read_location)
{
os_ << " ";
PrintLocation(node.read_location.value());
}
os_ << "\n";
});
}
if (node.write_accessor)
{
children.push_back([&](bool is_last) {
PrintIndent(is_last);
PrintColored("Write: ", Color::Yellow);
PrintColored("\"" + node.write_accessor.value() + "\"", Color::Green);
if (options_.show_location && node.write_location)
{
os_ << " ";
PrintLocation(node.write_location.value());
}
os_ << "\n";
});
}
EmitChildren(std::move(children));
DecreaseIndent();
}
void DebugPrinter::VisitExternalMethodDefinition(ExternalMethodDefinition& node)
{
PrintIndent();
PrintColored("ExternalMethodDefinition: ", Color::BrightCyan);
PrintColored(node.owner_class.name + "::" + node.name, Color::Green);
if (options_.show_location)
{
os_ << " ";
PrintLocation(node.location);
}
os_ << "\n";
size_t child_count = 0;
if (node.modifier != MethodModifier::kNone)
++child_count;
if (node.method_kind != MethodKind::kOrdinary)
++child_count;
if (!node.parameters.empty())
++child_count;
if (node.return_type)
++child_count;
if (node.body)
++child_count;
size_t child_index = 0;
auto emit_child = [&](auto&& fn) {
bool is_last_child = ++child_index == child_count;
fn(is_last_child);
};
IncreaseIndent();
if (node.modifier != MethodModifier::kNone)
{
emit_child([&](bool is_last) {
PrintIndent(is_last);
PrintColored("Modifier: ", Color::Yellow);
PrintMethodModifier(node.modifier);
os_ << "\n";
});
}
if (node.method_kind != MethodKind::kOrdinary)
{
emit_child([&](bool is_last) {
PrintIndent(is_last);
PrintColored("MethodKind: ", Color::Yellow);
PrintMethodType(node.method_kind);
os_ << "\n";
});
}
if (!node.parameters.empty())
{
emit_child([&](bool is_last) {
PrintIndent(is_last);
PrintColored("Parameters:", Color::Yellow);
os_ << "\n";
IncreaseIndent();
for (size_t i = 0; i < node.parameters.size(); ++i)
{
if (node.parameters[i])
{
PrintParameter(*node.parameters[i], i == node.parameters.size() - 1);
}
}
DecreaseIndent();
});
}
if (node.return_type)
{
emit_child([&](bool is_last) { PrintKeyValue("ReturnType", node.return_type->name, nullptr, is_last); });
}
if (node.body)
{
emit_child([&](bool is_last) { PrintStatement(node.body.get(), "Body", is_last); });
}
DecreaseIndent();
}
// ===== 基础表达式 =====
void DebugPrinter::VisitIdentifier(Identifier& node)
{
PrintIndent();
PrintColored("Identifier: ", Color::BrightCyan);
PrintColored("\"" + node.name + "\"", Color::Green);
if (options_.show_location)
{
os_ << " ";
PrintLocation(node.location);
}
os_ << "\n";
}
void DebugPrinter::VisitLiteral(Literal& node)
{
PrintIndent();
PrintColored("Literal: ", Color::BrightCyan);
PrintColored("\"" + node.value + "\"", Color::Green);
os_ << " (";
PrintLiteralKind(node.literal_kind);
os_ << ")";
if (options_.show_location)
{
os_ << " ";
PrintLocation(node.location);
}
os_ << "\n";
}
void DebugPrinter::VisitArrayExpression(ArrayExpression& node)
{
PrintIndent();
PrintColored("ArrayExpression", Color::BrightCyan);
if (options_.show_location)
{
os_ << " ";
PrintLocation(node.span);
}
os_ << "\n";
if (!node.elements.empty())
{
IncreaseIndent();
for (size_t i = 0; i < node.elements.size(); ++i)
{
const auto& elem = node.elements[i];
bool is_last = (i == node.elements.size() - 1);
if (elem.key)
{
PrintIndent();
PrintColored("Element:", Color::Yellow);
os_ << "\n";
IncreaseIndent();
PrintExpression(elem.key->get(), "Key", false);
PrintExpression(elem.value.get(), "Value", true);
DecreaseIndent();
}
else
{
PrintExpression(elem.value.get(), "", is_last);
}
}
DecreaseIndent();
}
}
void DebugPrinter::VisitParenthesizedExpression(ParenthesizedExpression& node)
{
PrintIndent();
PrintColored("ParenthesizedExpression", Color::BrightCyan);
if (options_.show_location)
{
os_ << " ";
PrintLocation(node.span);
}
os_ << "\n";
IncreaseIndent();
for (size_t i = 0; i < node.elements.size(); ++i)
{
const auto& elem = node.elements[i];
bool is_last = (i == node.elements.size() - 1);
if (elem.key)
{
PrintIndent();
PrintColored("Element (key-value):", Color::Yellow);
os_ << "\n";
IncreaseIndent();
PrintExpression(elem.key.value().get(), "Key", false);
PrintExpression(elem.value.get(), "Value", is_last);
DecreaseIndent();
}
else
{
PrintExpression(elem.value.get(), "", is_last);
}
}
DecreaseIndent();
}
// ===== 访问表达式 =====
void DebugPrinter::VisitCallExpression(CallExpression& node)
{
PrintIndent();
PrintColored("CallExpression", Color::BrightCyan);
if (options_.show_location)
{
os_ << " ";
PrintLocation(node.span);
}
os_ << "\n";
IncreaseIndent();
PrintExpression(node.callee.get(), "Callee", node.arguments.empty());
if (!node.arguments.empty())
{
PrintIndent();
PrintColored("Arguments:", Color::Yellow);
os_ << "\n";
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];
std::string label = "Argument";
if (arg.name)
{
label += " (" + arg.name.value() + ")";
}
if (arg.mode == ast::ParameterMode::kConst)
{
label += " [const]";
}
is_last_child_stack_.push_back(is_last);
PrintExpression(arg.value.get(), label, is_last);
is_last_child_stack_.pop_back();
}
DecreaseIndent();
}
DecreaseIndent();
}
void DebugPrinter::VisitAttributeExpression(AttributeExpression& node)
{
PrintIndent();
PrintColored("AttributeExpression", Color::BrightCyan);
if (options_.show_location)
{
os_ << " ";
PrintLocation(node.span);
}
os_ << "\n";
IncreaseIndent();
PrintExpression(node.object.get(), "Object", false);
PrintExpression(node.attribute.get(), "Attribute", true);
DecreaseIndent();
}
void DebugPrinter::VisitSubscriptExpression(SubscriptExpression& node)
{
PrintIndent();
PrintColored("SubscriptExpression", Color::BrightCyan);
if (options_.show_location)
{
os_ << " ";
PrintLocation(node.span);
}
os_ << "\n";
IncreaseIndent();
PrintExpression(node.base.get(), "Base", node.indices.empty());
if (!node.indices.empty())
{
PrintIndent();
PrintColored("Indices:", Color::Yellow);
os_ << "\n";
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();
PrintColored("Index " + std::to_string(i), Color::Yellow);
if (idx.is_slice)
{
PrintColored(" (slice)", Color::Gray);
}
if (idx.is_empty_slice)
{
PrintColored(" (empty)", Color::Gray);
}
os_ << "\n";
IncreaseIndent();
if (idx.start)
{
is_last_child_stack_.push_back(false);
PrintExpression(idx.start.get(), "Start", !idx.end && !idx.step);
is_last_child_stack_.pop_back();
}
if (idx.end)
{
is_last_child_stack_.push_back(false);
PrintExpression(idx.end.get(), "End", !idx.step);
is_last_child_stack_.pop_back();
}
if (idx.step)
{
is_last_child_stack_.push_back(is_last);
PrintExpression(idx.step.get(), "Step", true);
is_last_child_stack_.pop_back();
}
DecreaseIndent();
}
DecreaseIndent();
}
DecreaseIndent();
}
// ===== 一元表达式 =====
void DebugPrinter::VisitUnaryPlusExpression(UnaryPlusExpression& node)
{
PrintIndent();
PrintColored("UnaryPlusExpression", Color::BrightCyan);
if (options_.show_location)
{
os_ << " ";
PrintLocation(node.span);
}
os_ << "\n";
IncreaseIndent();
PrintExpression(node.argument.get(), "Operand", true);
DecreaseIndent();
}
void DebugPrinter::VisitUnaryMinusExpression(UnaryMinusExpression& node)
{
PrintIndent();
PrintColored("UnaryMinusExpression", Color::BrightCyan);
if (options_.show_location)
{
os_ << " ";
PrintLocation(node.span);
}
os_ << "\n";
IncreaseIndent();
PrintExpression(node.argument.get(), "Operand", true);
DecreaseIndent();
}
void DebugPrinter::VisitPrefixIncrementExpression(PrefixIncrementExpression& node)
{
PrintIndent();
PrintColored("PrefixIncrementExpression", Color::BrightCyan);
if (options_.show_location)
{
os_ << " ";
PrintLocation(node.span);
}
os_ << "\n";
IncreaseIndent();
PrintExpression(node.argument.get(), "Operand", true);
DecreaseIndent();
}
void DebugPrinter::VisitPrefixDecrementExpression(PrefixDecrementExpression& node)
{
PrintIndent();
PrintColored("PrefixDecrementExpression", Color::BrightCyan);
if (options_.show_location)
{
os_ << " ";
PrintLocation(node.span);
}
os_ << "\n";
IncreaseIndent();
PrintExpression(node.argument.get(), "Operand", true);
DecreaseIndent();
}
void DebugPrinter::VisitPostfixIncrementExpression(PostfixIncrementExpression& node)
{
PrintIndent();
PrintColored("PostfixIncrementExpression", Color::BrightCyan);
if (options_.show_location)
{
os_ << " ";
PrintLocation(node.span);
}
os_ << "\n";
IncreaseIndent();
PrintExpression(node.argument.get(), "Operand", true);
DecreaseIndent();
}
void DebugPrinter::VisitPostfixDecrementExpression(PostfixDecrementExpression& node)
{
PrintIndent();
PrintColored("PostfixDecrementExpression", Color::BrightCyan);
if (options_.show_location)
{
os_ << " ";
PrintLocation(node.span);
}
os_ << "\n";
IncreaseIndent();
PrintExpression(node.argument.get(), "Operand", true);
DecreaseIndent();
}
void DebugPrinter::VisitLogicalNotExpression(LogicalNotExpression& node)
{
PrintIndent();
PrintColored("LogicalNotExpression", Color::BrightCyan);
if (options_.show_location)
{
os_ << " ";
PrintLocation(node.span);
}
os_ << "\n";
IncreaseIndent();
PrintExpression(node.argument.get(), "Operand", true);
DecreaseIndent();
}
void DebugPrinter::VisitBitwiseNotExpression(BitwiseNotExpression& node)
{
PrintIndent();
PrintColored("BitwiseNotExpression", Color::BrightCyan);
if (options_.show_location)
{
os_ << " ";
PrintLocation(node.span);
}
os_ << "\n";
IncreaseIndent();
PrintExpression(node.argument.get(), "Operand", true);
DecreaseIndent();
}
void DebugPrinter::VisitDerivativeExpression(DerivativeExpression& node)
{
PrintIndent();
PrintColored("DerivativeExpression", Color::BrightCyan);
if (options_.show_location)
{
os_ << " ";
PrintLocation(node.span);
}
os_ << "\n";
IncreaseIndent();
PrintExpression(node.argument.get(), "Operand", true);
DecreaseIndent();
}
void DebugPrinter::VisitFunctionPointerExpression(FunctionPointerExpression& node)
{
PrintIndent();
PrintColored("FunctionPointerExpression", Color::BrightCyan);
if (options_.show_location)
{
os_ << " ";
PrintLocation(node.span);
}
os_ << "\n";
IncreaseIndent();
PrintExpression(node.argument.get(), "Argument", true);
DecreaseIndent();
}
void DebugPrinter::VisitMatrixTransposeExpression(MatrixTransposeExpression& node)
{
PrintIndent();
PrintColored("MatrixTransposeExpression", Color::BrightCyan);
if (options_.show_location)
{
os_ << " ";
PrintLocation(node.span);
}
os_ << "\n";
IncreaseIndent();
PrintExpression(node.argument.get(), "Operand", true);
DecreaseIndent();
}
void DebugPrinter::VisitExprOperatorExpression(ExprOperatorExpression& node)
{
PrintIndent();
PrintColored("ExprOperatorExpression", Color::BrightCyan);
if (options_.show_location)
{
os_ << " ";
PrintLocation(node.span);
}
os_ << "\n";
IncreaseIndent();
PrintExpression(node.argument.get(), "Operand", true);
DecreaseIndent();
}
// ===== 二元和三元表达式 =====
void DebugPrinter::VisitBinaryExpression(BinaryExpression& node)
{
PrintIndent();
PrintColored("BinaryExpression: ", Color::BrightCyan);
PrintOperator(node.op);
if (options_.show_location)
{
os_ << " ";
PrintLocation(node.span);
}
os_ << "\n";
IncreaseIndent();
PrintExpression(node.left.get(), "Left", false);
PrintExpression(node.right.get(), "Right", true);
DecreaseIndent();
}
void DebugPrinter::VisitTernaryExpression(TernaryExpression& node)
{
PrintIndent();
PrintColored("TernaryExpression", Color::BrightCyan);
if (options_.show_location)
{
os_ << " ";
PrintLocation(node.span);
}
os_ << "\n";
IncreaseIndent();
PrintExpression(node.condition.get(), "Condition", false);
PrintExpression(node.consequence.get(), "Consequence", false);
PrintExpression(node.alternative.get(), "Alternative", true);
DecreaseIndent();
}
void DebugPrinter::VisitAssignmentExpression(AssignmentExpression& node)
{
PrintIndent();
PrintColored("AssignmentExpression: ", Color::BrightCyan);
PrintOperator(node.op);
if (options_.show_location)
{
os_ << " ";
PrintLocation(node.span);
}
os_ << "\n";
IncreaseIndent();
PrintLeftHandSide(node.left, "Left", false);
PrintExpression(node.right.get(), "Right", true);
DecreaseIndent();
}
// ===== 特殊表达式 =====
void DebugPrinter::VisitAnonymousFunctionExpression(AnonymousFunctionExpression& node)
{
PrintIndent();
PrintColored("AnonymousFunctionExpression", Color::BrightCyan);
if (node.is_static)
{
os_ << " " << GetColor(Color::Magenta) << "(static)" << GetColor(Color::Reset);
}
if (options_.show_location)
{
os_ << " ";
PrintLocation(node.span);
}
os_ << "\n";
IncreaseIndent();
std::vector<std::function<void(bool)>> children;
if (!node.parameters.empty())
{
children.push_back([&](bool is_last) {
PrintIndent(is_last);
PrintColored("Parameters:", Color::Yellow);
os_ << "\n";
IncreaseIndent();
is_last_child_stack_.push_back(is_last);
for (size_t i = 0; i < node.parameters.size(); ++i)
{
if (node.parameters[i])
{
PrintParameter(*node.parameters[i], i == node.parameters.size() - 1);
}
}
is_last_child_stack_.pop_back();
DecreaseIndent();
});
}
if (node.return_type)
{
children.push_back([&](bool is_last) { PrintKeyValue("ReturnType", node.return_type->name, nullptr, is_last); });
}
if (node.body)
{
children.push_back([&](bool is_last) { PrintStatement(node.body.get(), "Body", is_last); });
}
EmitChildren(std::move(children));
DecreaseIndent();
}
void DebugPrinter::VisitNewExpression(NewExpression& node)
{
PrintIndent();
PrintColored("NewExpression", Color::BrightCyan);
if (options_.show_location)
{
os_ << " ";
PrintLocation(node.span);
}
os_ << "\n";
if (node.target)
{
IncreaseIndent();
PrintExpression(node.target.get(), "Class", true);
DecreaseIndent();
}
}
void DebugPrinter::VisitEchoExpression(EchoExpression& node)
{
PrintIndent();
PrintColored("EchoExpression", Color::BrightCyan);
if (options_.show_location)
{
os_ << " ";
PrintLocation(node.span);
}
os_ << "\n";
if (!node.expressions.empty())
{
IncreaseIndent();
for (size_t i = 0; i < node.expressions.size(); ++i)
{
PrintExpression(node.expressions[i].get(), "", i == node.expressions.size() - 1);
}
DecreaseIndent();
}
}
void DebugPrinter::VisitRaiseExpression(RaiseExpression& node)
{
PrintIndent();
PrintColored("RaiseExpression", Color::BrightCyan);
if (options_.show_location)
{
os_ << " ";
PrintLocation(node.span);
}
os_ << "\n";
IncreaseIndent();
PrintExpression(node.exception.get(), "Exception", true);
DecreaseIndent();
}
void DebugPrinter::VisitInheritedExpression(InheritedExpression& node)
{
PrintIndent();
PrintColored("InheritedExpression", Color::BrightCyan);
if (options_.show_location)
{
os_ << " ";
PrintLocation(node.span);
}
os_ << "\n";
if (node.call)
{
IncreaseIndent();
PrintExpression(node.call.value().get(), "Call", true);
DecreaseIndent();
}
}
void DebugPrinter::VisitTSSQLExpression(TSSQLExpression& node)
{
PrintIndent();
PrintColored("TSSQLExpression: ", Color::BrightCyan);
PrintTSSQLExpressionType(node.sql_type);
if (options_.show_location)
{
os_ << " ";
PrintLocation(node.span);
}
os_ << "\n";
IncreaseIndent();
PrintIndent();
PrintColored("SQL: ", Color::Yellow);
PrintColored("\"" + EscapeString(TruncateString(node.raw_sql, 100)) + "\"", Color::Green);
os_ << "\n";
if (options_.show_location)
{
PrintIndent();
PrintColored("SQL Location: ", Color::Yellow);
PrintLocation(node.sql_location);
os_ << "\n";
}
DecreaseIndent();
}
void DebugPrinter::VisitColumnReference(ColumnReference& node)
{
PrintIndent();
PrintColored("ColumnReference", Color::BrightCyan);
if (options_.show_location)
{
os_ << " ";
PrintLocation(node.span);
}
os_ << "\n";
if (node.value)
{
IncreaseIndent();
PrintExpression(node.value.get(), "Value", true);
DecreaseIndent();
}
}
// ===== 模式 =====
void DebugPrinter::VisitParameter(Parameter& node)
{
PrintIndent();
PrintColored("Parameter: ", Color::Cyan);
PrintColored("\"" + node.name + "\"", Color::Green);
if (node.type)
{
os_ << " : ";
PrintColored(node.type->name, Color::BrightYellow);
}
switch (node.mode)
{
case ast::ParameterMode::kNone:
break;
case ast::ParameterMode::kConst:
os_ << " " << GetColor(Color::Magenta) << "(const)" << GetColor(Color::Reset);
break;
case ast::ParameterMode::kIn:
os_ << " " << GetColor(Color::Magenta) << "(in)" << GetColor(Color::Reset);
break;
case ast::ParameterMode::kOut:
os_ << " " << GetColor(Color::Magenta) << "(out)" << GetColor(Color::Reset);
break;
case ast::ParameterMode::kVar:
os_ << " " << GetColor(Color::Magenta) << "(var)" << GetColor(Color::Reset);
break;
}
if (options_.show_location)
{
os_ << " ";
PrintLocation(node.location);
}
os_ << "\n";
if (node.default_value)
{
IncreaseIndent();
PrintExpression(node.default_value->get(), "DefaultValue", true);
DecreaseIndent();
}
}
void DebugPrinter::VisitUnpackPattern(UnpackPattern& node)
{
PrintIndent();
PrintColored("UnpackPattern", Color::BrightCyan);
if (options_.show_location)
{
os_ << " ";
PrintLocation(node.span);
}
os_ << "\n";
if (!node.elements.empty())
{
IncreaseIndent();
for (size_t i = 0; i < node.elements.size(); ++i)
{
bool is_last = (i == node.elements.size() - 1);
PrintLeftHandSide(node.elements[i], "Element", is_last);
}
DecreaseIndent();
}
}
// ===== 语句 =====
void DebugPrinter::VisitExpressionStatement(ExpressionStatement& node)
{
PrintIndent();
PrintColored("ExpressionStatement", Color::BrightCyan);
if (options_.show_location)
{
os_ << " ";
PrintLocation(node.span);
}
os_ << "\n";
IncreaseIndent();
PrintExpression(node.expression.get(), "", true);
DecreaseIndent();
}
void DebugPrinter::VisitBlockStatement(BlockStatement& node)
{
PrintIndent();
PrintColored("BlockStatement", Color::BrightCyan);
if (options_.show_location)
{
os_ << " ";
PrintLocation(node.span);
}
os_ << "\n";
IncreaseIndent();
PrintStatements(node.statements);
DecreaseIndent();
}
void DebugPrinter::VisitIfStatement(IfStatement& node)
{
PrintIndent();
PrintColored("IfStatement", Color::BrightCyan);
if (options_.show_location)
{
os_ << " ";
PrintLocation(node.span);
}
os_ << "\n";
IncreaseIndent();
std::vector<std::function<void(bool)>> children;
// If/ElseIf branches
for (size_t i = 0; i < node.branches.size(); ++i)
{
const auto& branch = node.branches[i];
children.push_back([&, i](bool is_last) {
PrintIndent(is_last);
PrintColored(i == 0 ? "If Branch:" : "ElseIf Branch:", Color::Yellow);
os_ << "\n";
IncreaseIndent();
is_last_child_stack_.push_back(is_last);
std::vector<std::function<void(bool)>> branch_children;
branch_children.push_back([&](bool inner_last) { PrintExpression(branch.condition.get(), "Condition", inner_last); });
if (branch.body)
{
branch_children.push_back([&](bool inner_last) { PrintStatement(branch.body.get(), "Body", inner_last); });
}
EmitChildren(std::move(branch_children));
is_last_child_stack_.pop_back();
DecreaseIndent();
});
}
// Else branch
if (node.else_body)
{
children.push_back([&](bool is_last) {
PrintIndent(is_last);
PrintColored("Else Branch:", Color::Yellow);
os_ << "\n";
IncreaseIndent();
is_last_child_stack_.push_back(is_last);
PrintStatement(node.else_body->get(), "Body", true);
is_last_child_stack_.pop_back();
DecreaseIndent();
});
}
EmitChildren(std::move(children));
DecreaseIndent();
}
void DebugPrinter::VisitForInStatement(ForInStatement& node)
{
PrintIndent();
PrintColored("ForInStatement", Color::BrightCyan);
if (options_.show_location)
{
os_ << " ";
PrintLocation(node.span);
}
os_ << "\n";
IncreaseIndent();
std::vector<std::function<void(bool)>> children;
children.push_back([&](bool is_last) { PrintKeyValue("Key", node.key, nullptr, is_last); });
children.push_back([&](bool is_last) { PrintKeyValue("Value", node.value, nullptr, is_last); });
children.push_back([&](bool is_last) { PrintExpression(node.collection.get(), "Collection", is_last); });
if (node.body)
{
children.push_back([&](bool is_last) { PrintStatement(node.body.get(), "Body", is_last); });
}
EmitChildren(std::move(children));
DecreaseIndent();
}
void DebugPrinter::VisitForToStatement(ForToStatement& node)
{
PrintIndent();
PrintColored("ForToStatement", Color::BrightCyan);
if (options_.show_location)
{
os_ << " ";
PrintLocation(node.span);
}
os_ << "\n";
IncreaseIndent();
std::vector<std::function<void(bool)>> children;
children.push_back([&](bool is_last) { PrintKeyValue("Counter", node.counter, nullptr, is_last); });
children.push_back([&](bool is_last) { PrintKeyValue("IsDownto", node.is_downto, is_last); });
children.push_back([&](bool is_last) { PrintExpression(node.start.get(), "Start", is_last); });
children.push_back([&](bool is_last) { PrintExpression(node.end.get(), "End", is_last); });
if (node.step)
{
children.push_back([&](bool is_last) { PrintExpression(node.step.get(), "Step", is_last); });
}
if (node.body)
{
children.push_back([&](bool is_last) { PrintStatement(node.body.get(), "Body", is_last); });
}
EmitChildren(std::move(children));
DecreaseIndent();
}
void DebugPrinter::VisitWhileStatement(WhileStatement& node)
{
PrintIndent();
PrintColored("WhileStatement", Color::BrightCyan);
if (options_.show_location)
{
os_ << " ";
PrintLocation(node.span);
}
os_ << "\n";
IncreaseIndent();
std::vector<std::function<void(bool)>> children;
children.push_back([&](bool is_last) { PrintExpression(node.condition.get(), "Condition", is_last); });
if (node.body)
children.push_back([&](bool is_last) { PrintStatement(node.body.get(), "Body", is_last); });
EmitChildren(std::move(children));
DecreaseIndent();
}
void DebugPrinter::VisitRepeatStatement(RepeatStatement& node)
{
PrintIndent();
PrintColored("RepeatStatement", Color::BrightCyan);
if (options_.show_location)
{
os_ << " ";
PrintLocation(node.span);
}
os_ << "\n";
IncreaseIndent();
std::vector<std::function<void(bool)>> children;
if (!node.body.empty())
{
children.push_back([&](bool is_last) {
PrintIndent(is_last);
PrintColored("Body:", Color::Yellow);
os_ << "\n";
IncreaseIndent();
is_last_child_stack_.push_back(is_last);
for (size_t i = 0; i < node.body.size(); ++i)
{
PrintStatement(node.body[i].get(), "", i == node.body.size() - 1);
}
is_last_child_stack_.pop_back();
DecreaseIndent();
});
}
children.push_back([&](bool is_last) { PrintExpression(node.condition.get(), "Condition", is_last); });
EmitChildren(std::move(children));
DecreaseIndent();
}
void DebugPrinter::VisitCaseStatement(CaseStatement& node)
{
PrintIndent();
PrintColored("CaseStatement", Color::BrightCyan);
if (options_.show_location)
{
os_ << " ";
PrintLocation(node.span);
}
os_ << "\n";
IncreaseIndent();
std::vector<std::function<void(bool)>> children;
children.push_back([&](bool is_last) { PrintExpression(node.discriminant.get(), "Discriminant", is_last); });
for (size_t i = 0; i < node.branches.size(); ++i)
{
const auto& branch = node.branches[i];
children.push_back([&, i](bool is_last) {
PrintIndent(is_last);
PrintColored("Branch:", Color::Yellow);
os_ << "\n";
IncreaseIndent();
is_last_child_stack_.push_back(is_last);
std::vector<std::function<void(bool)>> branch_children;
branch_children.push_back([&](bool inner_last) {
PrintIndent(inner_last);
PrintColored("Values:", Color::Yellow);
os_ << "\n";
IncreaseIndent();
is_last_child_stack_.push_back(inner_last);
for (size_t j = 0; j < branch.values.size(); ++j)
{
PrintExpression(branch.values[j].get(), "", j == branch.values.size() - 1);
}
is_last_child_stack_.pop_back();
DecreaseIndent();
});
if (branch.body)
{
branch_children.push_back([&](bool inner_last) { PrintStatement(branch.body.get(), "Body", inner_last); });
}
EmitChildren(std::move(branch_children));
is_last_child_stack_.pop_back();
DecreaseIndent();
});
}
if (node.else_body)
children.push_back([&](bool is_last) { PrintStatement(node.else_body->get(), "Else", is_last); });
EmitChildren(std::move(children));
DecreaseIndent();
}
void DebugPrinter::VisitTryStatement(TryStatement& node)
{
PrintIndent();
PrintColored("TryStatement", Color::BrightCyan);
if (options_.show_location)
{
os_ << " ";
PrintLocation(node.span);
}
os_ << "\n";
IncreaseIndent();
std::vector<std::function<void(bool)>> children;
if (node.try_body)
{
children.push_back([&](bool is_last) { PrintStatement(node.try_body.get(), "Try", is_last && !node.except_body); });
}
if (node.except_body)
{
children.push_back([&](bool is_last) { PrintStatement(node.except_body.get(), "Except", is_last); });
}
EmitChildren(std::move(children));
DecreaseIndent();
}
void DebugPrinter::VisitBreakStatement(BreakStatement& node)
{
PrintIndent();
PrintColored("BreakStatement", Color::BrightCyan);
if (options_.show_location)
{
os_ << " ";
PrintLocation(node.span);
}
os_ << "\n";
}
void DebugPrinter::VisitContinueStatement(ContinueStatement& node)
{
PrintIndent();
PrintColored("ContinueStatement", Color::BrightCyan);
if (options_.show_location)
{
os_ << " ";
PrintLocation(node.span);
}
os_ << "\n";
}
void DebugPrinter::VisitReturnStatement(ReturnStatement& node)
{
PrintIndent();
PrintColored("ReturnStatement", Color::BrightCyan);
if (options_.show_location)
{
os_ << " ";
PrintLocation(node.span);
}
os_ << "\n";
if (node.value)
{
IncreaseIndent();
is_last_child_stack_.push_back(true);
PrintExpression(node.value->get(), "", true);
is_last_child_stack_.pop_back();
DecreaseIndent();
}
}
void DebugPrinter::VisitUsesStatement(UsesStatement& node)
{
PrintIndent();
PrintColored("UsesStatement", Color::BrightCyan);
if (options_.show_location)
{
os_ << " ";
PrintLocation(node.span);
}
os_ << "\n";
IncreaseIndent();
is_last_child_stack_.push_back(true);
for (size_t i = 0; i < node.units.size(); ++i)
{
PrintIndent(i == node.units.size() - 1);
PrintColored("\"" + node.units[i].name + "\"", Color::Green);
if (options_.show_location)
{
os_ << " ";
PrintLocation(node.units[i].location);
}
os_ << "\n";
}
is_last_child_stack_.pop_back();
DecreaseIndent();
}
void DebugPrinter::VisitMatrixIterationStatement(MatrixIterationStatement& node)
{
PrintIndent();
PrintColored("MatrixIterationStatement", Color::BrightCyan);
if (options_.show_location)
{
os_ << " ";
PrintLocation(node.span);
}
os_ << "\n";
IncreaseIndent();
std::vector<std::function<void(bool)>> children;
children.push_back([&](bool is_last) { PrintExpression(node.target.get(), "Target", is_last && !node.body); });
if (node.body)
children.push_back([&](bool is_last) { PrintStatement(node.body.get(), "Body", is_last); });
EmitChildren(std::move(children));
DecreaseIndent();
}
// ===== 函数和声明 =====
void DebugPrinter::VisitFunctionDefinition(FunctionDefinition& node)
{
PrintIndent();
PrintColored("FunctionDefinition: ", Color::BrightCyan);
PrintColored("\"" + node.name + "\"", Color::Green);
if (options_.show_location)
{
os_ << " ";
PrintLocation(node.location);
}
os_ << "\n";
size_t child_count = (node.parameters.empty() ? 0 : 1);
if (node.return_type)
++child_count;
if (node.body)
++child_count;
// Overload is always printed
++child_count;
size_t child_index = 0;
auto emit_child = [&](auto&& fn) {
bool is_last_child = ++child_index == child_count;
fn(is_last_child);
};
IncreaseIndent();
if (!node.parameters.empty())
{
emit_child([&](bool is_last) {
PrintIndent(is_last);
PrintColored("Parameters:", Color::Yellow);
os_ << "\n";
IncreaseIndent();
for (size_t i = 0; i < node.parameters.size(); ++i)
{
if (node.parameters[i])
{
PrintParameter(*node.parameters[i], i == node.parameters.size() - 1);
}
}
DecreaseIndent();
});
}
emit_child([&](bool is_last) {
PrintIndent(is_last);
std::string overload = node.is_overload ? "true" : "false";
PrintColored("Overload: " + overload, Color::Cyan);
os_ << "\n";
});
if (node.return_type)
{
emit_child([&](bool is_last) { PrintKeyValue("ReturnType", node.return_type->name, nullptr, is_last); });
}
if (node.body)
{
emit_child([&](bool is_last) { PrintStatement(node.body.get(), "Body", is_last); });
}
DecreaseIndent();
}
void DebugPrinter::VisitFunctionDeclaration(FunctionDeclaration& node)
{
PrintIndent();
PrintColored("FunctionDeclaration: ", Color::BrightCyan);
PrintColored("\"" + node.name + "\"", Color::Green);
if (options_.show_location)
{
os_ << " ";
PrintLocation(node.span);
}
os_ << "\n";
IncreaseIndent();
if (!node.parameters.empty())
{
PrintIndent();
PrintColored("Parameters:", Color::Yellow);
os_ << "\n";
IncreaseIndent();
for (size_t i = 0; i < node.parameters.size(); ++i)
{
if (node.parameters[i])
{
PrintParameter(*node.parameters[i], i == node.parameters.size() - 1);
}
}
DecreaseIndent();
}
if (node.return_type)
{
PrintKeyValue("ReturnType", node.return_type->name);
}
DecreaseIndent();
}
void DebugPrinter::VisitVarDeclaration(VarDeclaration& node)
{
PrintIndent();
PrintColored("VarDeclaration: ", Color::BrightCyan);
PrintColored("\"" + node.name + "\"", Color::Green);
if (options_.show_location)
{
os_ << " ";
PrintLocation(node.location);
}
os_ << "\n";
IncreaseIndent();
std::vector<std::function<void(bool)>> children;
if (node.type)
{
children.push_back([&](bool is_last) { PrintKeyValue("Type", node.type->name, nullptr, is_last); });
}
if (node.initializer)
{
children.push_back([&](bool is_last) { PrintExpression(node.initializer->get(), "InitialValue", is_last); });
}
EmitChildren(std::move(children));
DecreaseIndent();
}
void DebugPrinter::VisitStaticDeclaration(StaticDeclaration& node)
{
PrintIndent();
PrintColored("StaticDeclaration: ", Color::BrightCyan);
PrintColored("\"" + node.name + "\"", Color::Green);
if (options_.show_location)
{
os_ << " ";
PrintLocation(node.location);
}
os_ << "\n";
IncreaseIndent();
std::vector<std::function<void(bool)>> children;
if (node.type)
{
children.push_back([&](bool is_last) { PrintKeyValue("Type", node.type->name, nullptr, is_last); });
}
if (node.initializer)
{
children.push_back([&](bool is_last) { PrintExpression(node.initializer->get(), "Initializer", is_last); });
}
EmitChildren(std::move(children));
DecreaseIndent();
}
void DebugPrinter::VisitGlobalDeclaration(GlobalDeclaration& node)
{
PrintIndent();
PrintColored("GlobalDeclaration: ", Color::BrightCyan);
PrintColored("\"" + node.name + "\"", Color::Green);
if (options_.show_location)
{
os_ << " ";
PrintLocation(node.location);
}
os_ << "\n";
IncreaseIndent();
std::vector<std::function<void(bool)>> children;
if (node.type)
children.push_back([&](bool is_last) { PrintKeyValue("Type", node.type->name, nullptr, is_last); });
if (node.initializer)
children.push_back([&](bool is_last) { PrintExpression(node.initializer->get(), "Initializer", is_last); });
EmitChildren(std::move(children));
DecreaseIndent();
}
void DebugPrinter::VisitConstDeclaration(ConstDeclaration& node)
{
PrintIndent();
PrintColored("ConstDeclaration: ", Color::BrightCyan);
PrintColored("\"" + node.name + "\"", Color::Green);
if (options_.show_location)
{
os_ << " ";
PrintLocation(node.location);
}
os_ << "\n";
IncreaseIndent();
std::vector<std::function<void(bool)>> children;
if (node.type)
{
children.push_back([&](bool is_last) { PrintKeyValue("Type", node.type->name, nullptr, is_last); });
}
if (node.value)
{
children.push_back([&](bool is_last) { PrintExpression(node.value.get(), "Value", is_last); });
}
EmitChildren(std::move(children));
DecreaseIndent();
}
void DebugPrinter::VisitFieldDeclaration(FieldDeclaration& node)
{
PrintIndent();
PrintColored("FieldDeclaration: ", Color::BrightCyan);
PrintColored("\"" + node.name + "\"", Color::Green);
if (options_.show_location)
{
os_ << " ";
PrintLocation(node.location);
}
os_ << "\n";
IncreaseIndent();
std::vector<std::function<void(bool)>> children;
if (node.type)
children.push_back([&](bool is_last) { PrintKeyValue("Type", node.type->name, nullptr, is_last); });
if (node.initializer)
children.push_back([&](bool is_last) { PrintExpression(node.initializer->get(), "Initializer", is_last); });
EmitChildren(std::move(children));
DecreaseIndent();
}
// ===== 条件编译 =====
void DebugPrinter::VisitCompilerDirective(CompilerDirective& node)
{
PrintIndent();
PrintColored("CompilerDirective: ", Color::BrightCyan);
PrintColored("\"" + node.name + "\"", Color::Green);
if (node.switch_value)
{
os_ << " " << GetColor(Color::Magenta) << *node.switch_value << GetColor(Color::Reset);
}
if (options_.show_location)
{
os_ << " ";
PrintLocation(node.location);
}
os_ << "\n";
}
void DebugPrinter::VisitConditionalBlock(ConditionalBlock& node)
{
PrintIndent();
PrintColored("ConditionalBlock: ", Color::BrightCyan);
PrintConditionalCompilationType(node.type);
os_ << " " << GetColor(Color::Green) << node.name << GetColor(Color::Reset);
if (options_.show_location)
{
os_ << " ";
PrintLocation(node.location);
}
os_ << "\n";
IncreaseIndent();
if (!node.consequence.empty())
{
PrintIndent();
PrintColored("Consequence:", Color::Yellow);
os_ << "\n";
IncreaseIndent();
PrintStatements(node.consequence);
DecreaseIndent();
}
if (!node.alternative.empty())
{
PrintIndent();
PrintColored("Alternative:", Color::Yellow);
os_ << "\n";
IncreaseIndent();
PrintStatements(node.alternative);
DecreaseIndent();
}
DecreaseIndent();
}
void DebugPrinter::VisitConditionalDirective(ConditionalDirective& node)
{
PrintIndent();
PrintColored("ConditionalDirective: ", Color::BrightCyan);
PrintConditionalCompilationType(node.type);
os_ << " " << GetColor(Color::Green) << node.name << GetColor(Color::Reset);
if (options_.show_location)
{
os_ << " ";
PrintLocation(node.location);
}
os_ << "\n";
}
void DebugPrinter::VisitTSLXBlock(TSLXBlock& node)
{
PrintIndent();
PrintColored("TSLXBlock", Color::BrightCyan);
if (options_.show_location)
{
os_ << " ";
PrintLocation(node.span);
}
os_ << "\n";
// TSLXBlock 的具体内容未定义,暂时只打印节点名称
}
// ===== 便捷函数实现 =====
std::string DebugString(const ASTNode* node, const PrintOptions& opts)
{
std::ostringstream oss;
DebugPrinter printer(oss, opts);
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);
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);
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);
}
}