1904 lines
53 KiB
C++
1904 lines
53 KiB
C++
#include <sstream>
|
|
#include <cctype>
|
|
#include "./debug_printer.hpp"
|
|
|
|
namespace lsp::language::ast
|
|
{
|
|
// ===== 辅助函数实现 =====
|
|
|
|
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);
|
|
}
|
|
|
|
std::string DebugPrinter::GetIndent() const
|
|
{
|
|
return std::string(current_indent_, ' ');
|
|
}
|
|
|
|
void DebugPrinter::PrintIndent(bool is_last)
|
|
{
|
|
if (options_.use_tree_chars && current_indent_ > 0)
|
|
{
|
|
PrintTreePrefix(is_last);
|
|
}
|
|
else
|
|
{
|
|
os_ << GetIndent();
|
|
}
|
|
}
|
|
|
|
void DebugPrinter::PrintTreePrefix(bool is_last)
|
|
{
|
|
std::string prefix;
|
|
for (size_t i = 0; i < is_last_child_stack_.size(); ++i)
|
|
{
|
|
if (is_last_child_stack_[i])
|
|
{
|
|
prefix += " ";
|
|
}
|
|
else
|
|
{
|
|
prefix += "│ ";
|
|
}
|
|
}
|
|
|
|
if (is_last)
|
|
{
|
|
prefix += "└── ";
|
|
}
|
|
else
|
|
{
|
|
prefix += "├── ";
|
|
}
|
|
|
|
os_ << GetColor(Color::Gray) << prefix << GetColor(Color::Reset);
|
|
}
|
|
|
|
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:
|
|
if (c >= 32 && c < 127)
|
|
result += c;
|
|
else
|
|
{
|
|
char buf[5];
|
|
snprintf(buf, sizeof(buf), "\\x%02x", static_cast<unsigned char>(c));
|
|
result += buf;
|
|
}
|
|
}
|
|
}
|
|
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_ || source_code_->empty())
|
|
return "";
|
|
|
|
size_t start = loc.start_byte;
|
|
size_t end = loc.end_byte;
|
|
|
|
if (start >= source_code_->length() || end > source_code_->length() || start >= end)
|
|
return "";
|
|
|
|
std::string text = source_code_->substr(start, end - start);
|
|
|
|
// 移除首尾空白
|
|
size_t first = text.find_first_not_of(" \t\n\r");
|
|
if (first == std::string::npos)
|
|
return "";
|
|
size_t last = text.find_last_not_of(" \t\n\r");
|
|
text = text.substr(first, last - first + 1);
|
|
|
|
// 压缩多个空白为单个空格
|
|
bool prev_space = false;
|
|
std::string result;
|
|
for (char c : text)
|
|
{
|
|
if (std::isspace(c))
|
|
{
|
|
if (!prev_space)
|
|
result += ' ';
|
|
prev_space = true;
|
|
}
|
|
else
|
|
{
|
|
result += c;
|
|
prev_space = false;
|
|
}
|
|
}
|
|
|
|
return TruncateString(result, options_.max_source_length);
|
|
}
|
|
|
|
void DebugPrinter::PrintLocation(const Location& loc)
|
|
{
|
|
if (!options_.show_location)
|
|
return;
|
|
|
|
os_ << GetColor(Color::Gray) << "@";
|
|
os_ << loc.start_line << ":" << loc.start_column;
|
|
if (loc.end_line != loc.start_line || loc.end_column != loc.start_column)
|
|
{
|
|
os_ << "-" << loc.end_line << ":" << loc.end_column;
|
|
}
|
|
os_ << GetColor(Color::Reset);
|
|
}
|
|
|
|
void DebugPrinter::PrintSourceSnippet(const Location& loc)
|
|
{
|
|
if (!options_.show_source_code)
|
|
return;
|
|
|
|
std::string source = GetSourceText(loc);
|
|
if (!source.empty())
|
|
{
|
|
os_ << " " << GetColor(Color::Dim) << "«" << source << "»" << GetColor(Color::Reset);
|
|
}
|
|
}
|
|
|
|
void DebugPrinter::PrintNodeHeader(const std::string& type_name, const Location& loc)
|
|
{
|
|
PrintIndent();
|
|
|
|
// 打印节点类型
|
|
PrintColored(type_name, Color::BrightCyan);
|
|
|
|
// 打印位置
|
|
if (options_.show_location || options_.show_source_code)
|
|
{
|
|
os_ << " ";
|
|
PrintLocation(loc);
|
|
PrintSourceSnippet(loc);
|
|
}
|
|
|
|
os_ << "\n";
|
|
}
|
|
|
|
void DebugPrinter::PrintKeyValue(const std::string& key, const std::string& value, const char* value_color)
|
|
{
|
|
if (options_.compact_mode && value.empty())
|
|
return;
|
|
|
|
PrintIndent();
|
|
PrintColored(key + ": ", Color::Yellow);
|
|
|
|
if (value_color)
|
|
PrintColored(value, value_color);
|
|
else
|
|
os_ << value;
|
|
|
|
os_ << "\n";
|
|
}
|
|
|
|
void DebugPrinter::PrintKeyValue(const std::string& key, int value)
|
|
{
|
|
PrintIndent();
|
|
PrintColored(key + ": ", Color::Yellow);
|
|
PrintColored(std::to_string(value), Color::BrightGreen);
|
|
os_ << "\n";
|
|
}
|
|
|
|
void DebugPrinter::PrintKeyValue(const std::string& key, bool value)
|
|
{
|
|
PrintIndent();
|
|
PrintColored(key + ": ", Color::Yellow);
|
|
PrintColored(value ? "true" : "false", value ? Color::Green : Color::Red);
|
|
os_ << "\n";
|
|
}
|
|
|
|
// ===== 打印主函数 =====
|
|
|
|
void DebugPrinter::Print(const ASTNode* node)
|
|
{
|
|
if (!node)
|
|
{
|
|
os_ << GetColor(Color::Red) << "(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)
|
|
{
|
|
if (statements[i])
|
|
{
|
|
bool is_last = (i == statements.size() - 1);
|
|
if (options_.use_tree_chars)
|
|
{
|
|
is_last_child_stack_.push_back(is_last);
|
|
statements[i]->Accept(*this);
|
|
is_last_child_stack_.pop_back();
|
|
}
|
|
else
|
|
{
|
|
statements[i]->Accept(*this);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void DebugPrinter::PrintParseResult(const ParseResult& result)
|
|
{
|
|
// 打印头部
|
|
PrintColored("╔═══════════════════════════════════════════════════════════════\n", Color::BrightBlue);
|
|
PrintColored("║ ", Color::BrightBlue);
|
|
PrintColored("AST Parse Result", Color::BrightCyan);
|
|
os_ << "\n";
|
|
PrintColored("╠═══════════════════════════════════════════════════════════════\n", Color::BrightBlue);
|
|
|
|
// 打印统计信息
|
|
if (result.root)
|
|
{
|
|
PrintColored("║ ", Color::BrightBlue);
|
|
PrintColored("Statements: ", Color::Yellow);
|
|
PrintColored(std::to_string(result.root->statements.size()), Color::BrightGreen);
|
|
os_ << "\n";
|
|
}
|
|
|
|
PrintColored("║ ", Color::BrightBlue);
|
|
PrintColored("Errors: ", Color::Yellow);
|
|
if (result.errors.empty())
|
|
{
|
|
PrintColored("0", Color::Green);
|
|
os_ << " ";
|
|
PrintColored("✓", Color::BrightGreen);
|
|
}
|
|
else
|
|
{
|
|
PrintColored(std::to_string(result.errors.size()), Color::BrightRed);
|
|
os_ << " ";
|
|
PrintColored("✗", Color::BrightRed);
|
|
}
|
|
os_ << "\n";
|
|
|
|
PrintColored("╚═══════════════════════════════════════════════════════════════\n", Color::BrightBlue);
|
|
|
|
// 打印错误
|
|
if (!result.errors.empty())
|
|
{
|
|
os_ << "\n";
|
|
PrintColored("Errors:\n", Color::BrightRed);
|
|
for (const auto& error : result.errors)
|
|
{
|
|
PrintError(error);
|
|
}
|
|
os_ << "\n";
|
|
}
|
|
|
|
// 打印AST
|
|
if (result.root)
|
|
{
|
|
os_ << "\n";
|
|
PrintColored("AST Tree:\n", Color::BrightCyan);
|
|
Print(result.root.get());
|
|
}
|
|
}
|
|
|
|
void DebugPrinter::PrintError(const ParseError& error)
|
|
{
|
|
PrintIndent();
|
|
|
|
// 错误级别
|
|
const char* severity_color = Color::Red;
|
|
std::string severity_text = "ERROR";
|
|
|
|
switch (error.severity)
|
|
{
|
|
case ErrorSeverity::Warning:
|
|
severity_color = Color::Yellow;
|
|
severity_text = "WARNING";
|
|
break;
|
|
case ErrorSeverity::Fatal:
|
|
severity_color = Color::BrightRed;
|
|
severity_text = "FATAL";
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
PrintColored(severity_text, severity_color);
|
|
os_ << " ";
|
|
|
|
// 位置
|
|
PrintLocation(error.location);
|
|
os_ << " ";
|
|
|
|
// 消息
|
|
os_ << error.message << "\n";
|
|
}
|
|
|
|
void DebugPrinter::PrintExpression(const Expression* expr, const std::string& label, bool is_last)
|
|
{
|
|
if (!label.empty())
|
|
{
|
|
PrintIndent();
|
|
PrintColored(label + ":\n", Color::Yellow);
|
|
}
|
|
|
|
IncreaseIndent();
|
|
if (expr)
|
|
{
|
|
if (options_.use_tree_chars)
|
|
{
|
|
is_last_child_stack_.push_back(is_last);
|
|
const_cast<Expression*>(expr)->Accept(*this);
|
|
is_last_child_stack_.pop_back();
|
|
}
|
|
else
|
|
{
|
|
const_cast<Expression*>(expr)->Accept(*this);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (options_.use_tree_chars)
|
|
{
|
|
is_last_child_stack_.push_back(is_last);
|
|
}
|
|
PrintIndent(is_last);
|
|
PrintColored("(null)", Color::Red);
|
|
os_ << "\n";
|
|
if (options_.use_tree_chars)
|
|
{
|
|
is_last_child_stack_.pop_back();
|
|
}
|
|
}
|
|
DecreaseIndent();
|
|
}
|
|
|
|
void DebugPrinter::PrintStatement(const Statement* stmt, const std::string& label, bool is_last)
|
|
{
|
|
if (!label.empty())
|
|
{
|
|
PrintIndent();
|
|
PrintColored(label + ":\n", Color::Yellow);
|
|
}
|
|
|
|
IncreaseIndent();
|
|
if (stmt)
|
|
{
|
|
if (options_.use_tree_chars)
|
|
{
|
|
is_last_child_stack_.push_back(is_last);
|
|
const_cast<Statement*>(stmt)->Accept(*this);
|
|
is_last_child_stack_.pop_back();
|
|
}
|
|
else
|
|
{
|
|
const_cast<Statement*>(stmt)->Accept(*this);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (options_.use_tree_chars)
|
|
{
|
|
is_last_child_stack_.push_back(is_last);
|
|
}
|
|
PrintIndent(is_last);
|
|
PrintColored("(null)", Color::Red);
|
|
os_ << "\n";
|
|
if (options_.use_tree_chars)
|
|
{
|
|
is_last_child_stack_.pop_back();
|
|
}
|
|
}
|
|
DecreaseIndent();
|
|
}
|
|
|
|
void DebugPrinter::PrintSignature(const Signature& sig)
|
|
{
|
|
if (!sig.parameters.empty())
|
|
{
|
|
PrintIndent();
|
|
PrintColored("parameters", Color::Yellow);
|
|
PrintColored(" (" + std::to_string(sig.parameters.size()) + "):\n", Color::Gray);
|
|
|
|
IncreaseIndent();
|
|
for (size_t i = 0; i < sig.parameters.size(); ++i)
|
|
{
|
|
bool is_last = (i == sig.parameters.size() - 1);
|
|
if (options_.use_tree_chars)
|
|
{
|
|
is_last_child_stack_.push_back(is_last);
|
|
PrintParameter(sig.parameters[i], is_last);
|
|
is_last_child_stack_.pop_back();
|
|
}
|
|
else
|
|
{
|
|
PrintParameter(sig.parameters[i], is_last);
|
|
}
|
|
}
|
|
DecreaseIndent();
|
|
}
|
|
|
|
if (sig.return_type)
|
|
{
|
|
PrintKeyValue("return_type", *sig.return_type, Color::BrightMagenta);
|
|
}
|
|
}
|
|
|
|
void DebugPrinter::PrintParameter(const Parameter& param, bool is_last)
|
|
{
|
|
PrintIndent(is_last);
|
|
PrintColored(param.name, Color::BrightGreen);
|
|
|
|
if (param.is_var)
|
|
os_ << " " << GetColor(Color::Cyan) << "[var]" << GetColor(Color::Reset);
|
|
if (param.is_out)
|
|
os_ << " " << GetColor(Color::Cyan) << "[out]" << GetColor(Color::Reset);
|
|
|
|
if (param.type_name)
|
|
os_ << GetColor(Color::Gray) << ": " << GetColor(Color::BrightMagenta)
|
|
<< *param.type_name << GetColor(Color::Reset);
|
|
|
|
if (param.default_value)
|
|
{
|
|
os_ << " " << GetColor(Color::Gray) << "= " << GetColor(Color::Reset);
|
|
os_ << "..."; // 简化显示
|
|
}
|
|
|
|
os_ << "\n";
|
|
}
|
|
|
|
void DebugPrinter::PrintLeftHandSide(const LeftHandSide& lhs, const std::string& label, bool is_last)
|
|
{
|
|
if (!label.empty())
|
|
{
|
|
PrintIndent();
|
|
PrintColored(label + ":\n", Color::Yellow);
|
|
IncreaseIndent();
|
|
}
|
|
|
|
if (options_.use_tree_chars)
|
|
{
|
|
is_last_child_stack_.push_back(is_last);
|
|
}
|
|
|
|
std::visit([this](auto&& arg) {
|
|
using T = std::decay_t<decltype(arg)>;
|
|
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<UnpackPattern>> ||
|
|
std::is_same_v<T, std::unique_ptr<VarDeclaration>> ||
|
|
std::is_same_v<T, std::unique_ptr<StaticDeclaration>> ||
|
|
std::is_same_v<T, std::unique_ptr<GlobalDeclaration>> ||
|
|
std::is_same_v<T, std::unique_ptr<FieldDeclaration>>)
|
|
{
|
|
if (arg)
|
|
{
|
|
arg->Accept(*this);
|
|
}
|
|
else
|
|
{
|
|
PrintIndent();
|
|
PrintColored("(null)", Color::Red);
|
|
os_ << "\n";
|
|
}
|
|
}
|
|
},
|
|
lhs);
|
|
|
|
if (options_.use_tree_chars)
|
|
{
|
|
is_last_child_stack_.pop_back();
|
|
}
|
|
|
|
if (!label.empty())
|
|
{
|
|
DecreaseIndent();
|
|
}
|
|
}
|
|
|
|
// ===== 枚举打印实现 =====
|
|
|
|
void DebugPrinter::PrintOperator(BinaryOperator op)
|
|
{
|
|
PrintColored(GetBinaryOperatorSymbol(op), Color::BrightYellow);
|
|
}
|
|
|
|
void DebugPrinter::PrintOperator(UnaryOperator op)
|
|
{
|
|
const char* 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 = ".!!";
|
|
break;
|
|
case UnaryOperator::kMatrixTranspose:
|
|
symbol = "`";
|
|
break;
|
|
case UnaryOperator::kDerivative:
|
|
symbol = "!";
|
|
break;
|
|
case UnaryOperator::kExprAt:
|
|
symbol = "@";
|
|
break;
|
|
case UnaryOperator::kExprRef:
|
|
symbol = "&";
|
|
break;
|
|
}
|
|
PrintColored(symbol, Color::BrightYellow);
|
|
}
|
|
|
|
void DebugPrinter::PrintOperator(AssignmentOperator op)
|
|
{
|
|
PrintColored(GetAssignmentOperatorSymbol(op), Color::BrightYellow);
|
|
}
|
|
|
|
void DebugPrinter::PrintLiteralKind(LiteralKind kind)
|
|
{
|
|
const char* kind_str = "";
|
|
const char* color = Color::Magenta;
|
|
|
|
switch (kind)
|
|
{
|
|
case LiteralKind::kNumber:
|
|
kind_str = "number";
|
|
break;
|
|
case LiteralKind::kString:
|
|
kind_str = "string";
|
|
color = Color::Green;
|
|
break;
|
|
case LiteralKind::kBoolean:
|
|
kind_str = "boolean";
|
|
break;
|
|
case LiteralKind::kNil:
|
|
kind_str = "nil";
|
|
color = Color::Gray;
|
|
break;
|
|
case LiteralKind::kInfinity:
|
|
kind_str = "infinity";
|
|
break;
|
|
case LiteralKind::kEllipsis:
|
|
kind_str = "ellipsis";
|
|
break;
|
|
}
|
|
|
|
PrintColored(kind_str, color);
|
|
}
|
|
|
|
void DebugPrinter::PrintAccessModifier(AccessModifier modifier)
|
|
{
|
|
const char* mod_str = "";
|
|
const char* color = Color::Cyan;
|
|
|
|
switch (modifier)
|
|
{
|
|
case AccessModifier::kPublic:
|
|
mod_str = "public";
|
|
break;
|
|
case AccessModifier::kProtected:
|
|
mod_str = "protected";
|
|
color = Color::Yellow;
|
|
break;
|
|
case AccessModifier::kPrivate:
|
|
mod_str = "private";
|
|
color = Color::Red;
|
|
break;
|
|
}
|
|
|
|
PrintColored(mod_str, color);
|
|
}
|
|
|
|
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::Magenta);
|
|
}
|
|
|
|
void DebugPrinter::PrintReferenceModifier(ReferenceModifier modifier)
|
|
{
|
|
const char* mod_str = "";
|
|
|
|
switch (modifier)
|
|
{
|
|
case ReferenceModifier::kNone:
|
|
mod_str = "none";
|
|
break;
|
|
case ReferenceModifier::kWeakRef:
|
|
mod_str = "weakref";
|
|
break;
|
|
case ReferenceModifier::kAutoRef:
|
|
mod_str = "autoref";
|
|
break;
|
|
}
|
|
|
|
PrintColored(mod_str, Color::Cyan);
|
|
}
|
|
|
|
// ===== Visitor 实现 =====
|
|
|
|
void DebugPrinter::VisitProgram(Program& node)
|
|
{
|
|
PrintNodeHeader("Program", node.location);
|
|
|
|
if (!node.statements.empty())
|
|
{
|
|
IncreaseIndent();
|
|
PrintIndent();
|
|
PrintColored("statements ", Color::Yellow);
|
|
PrintColored("(" + std::to_string(node.statements.size()) + "):\n", Color::Gray);
|
|
IncreaseIndent();
|
|
PrintStatements(node.statements);
|
|
DecreaseIndent();
|
|
DecreaseIndent();
|
|
}
|
|
}
|
|
|
|
void DebugPrinter::VisitIdentifier(Identifier& node)
|
|
{
|
|
PrintNodeHeader("Identifier", node.location);
|
|
IncreaseIndent();
|
|
PrintKeyValue("name", node.name, Color::BrightGreen);
|
|
DecreaseIndent();
|
|
}
|
|
|
|
void DebugPrinter::VisitLiteral(Literal& node)
|
|
{
|
|
PrintNodeHeader("Literal", node.location);
|
|
IncreaseIndent();
|
|
|
|
PrintIndent();
|
|
PrintColored("kind: ", Color::Yellow);
|
|
PrintLiteralKind(node.literal_kind);
|
|
os_ << "\n";
|
|
|
|
PrintIndent();
|
|
PrintColored("value: ", Color::Yellow);
|
|
|
|
if (node.literal_kind == LiteralKind::kString)
|
|
{
|
|
PrintColored("\"" + EscapeString(node.value) + "\"", Color::Green);
|
|
}
|
|
else
|
|
{
|
|
PrintColored(node.value, Color::BrightGreen);
|
|
}
|
|
os_ << "\n";
|
|
|
|
DecreaseIndent();
|
|
}
|
|
|
|
void DebugPrinter::VisitBinaryExpression(BinaryExpression& node)
|
|
{
|
|
PrintNodeHeader("BinaryExpression", node.location);
|
|
IncreaseIndent();
|
|
|
|
PrintIndent();
|
|
PrintColored("operator: ", Color::Yellow);
|
|
PrintOperator(node.op);
|
|
os_ << "\n";
|
|
|
|
PrintExpression(node.left.get(), "left", false);
|
|
PrintExpression(node.right.get(), "right", true);
|
|
|
|
DecreaseIndent();
|
|
}
|
|
|
|
void DebugPrinter::VisitComparisonExpression(ComparisonExpression& node)
|
|
{
|
|
PrintNodeHeader("ComparisonExpression", node.location);
|
|
IncreaseIndent();
|
|
|
|
PrintExpression(node.left.get(), "left", false);
|
|
|
|
if (!node.comparisons.empty())
|
|
{
|
|
PrintIndent();
|
|
PrintColored("comparisons ", Color::Yellow);
|
|
PrintColored("(" + std::to_string(node.comparisons.size()) + "):\n", Color::Gray);
|
|
IncreaseIndent();
|
|
|
|
for (size_t i = 0; i < node.comparisons.size(); ++i)
|
|
{
|
|
const auto& comp = node.comparisons[i];
|
|
PrintIndent();
|
|
PrintColored("[" + std::to_string(i) + "] ", Color::Gray);
|
|
PrintOperator(comp.op);
|
|
os_ << "\n";
|
|
|
|
if (comp.right)
|
|
{
|
|
IncreaseIndent();
|
|
PrintExpression(comp.right.get());
|
|
DecreaseIndent();
|
|
}
|
|
}
|
|
DecreaseIndent();
|
|
}
|
|
|
|
DecreaseIndent();
|
|
}
|
|
|
|
void DebugPrinter::VisitUnaryExpression(UnaryExpression& node)
|
|
{
|
|
PrintNodeHeader("UnaryExpression", node.location);
|
|
IncreaseIndent();
|
|
|
|
PrintIndent();
|
|
PrintColored("operator: ", Color::Yellow);
|
|
PrintOperator(node.op);
|
|
os_ << "\n";
|
|
|
|
PrintExpression(node.argument.get(), "argument", true);
|
|
|
|
DecreaseIndent();
|
|
}
|
|
|
|
void DebugPrinter::VisitTernaryExpression(TernaryExpression& node)
|
|
{
|
|
PrintNodeHeader("TernaryExpression", node.location);
|
|
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)
|
|
{
|
|
PrintNodeHeader("CallExpression", node.location);
|
|
IncreaseIndent();
|
|
|
|
bool has_arguments = !node.arguments.empty();
|
|
PrintExpression(node.callee.get(), "callee", !has_arguments);
|
|
|
|
if (has_arguments)
|
|
{
|
|
PrintIndent();
|
|
PrintColored("arguments ", Color::Yellow);
|
|
PrintColored("(" + std::to_string(node.arguments.size()) + "):\n", Color::Gray);
|
|
|
|
IncreaseIndent();
|
|
for (size_t i = 0; i < node.arguments.size(); ++i)
|
|
{
|
|
const auto& arg = node.arguments[i];
|
|
bool is_last = (i == node.arguments.size() - 1);
|
|
|
|
if (options_.use_tree_chars)
|
|
{
|
|
is_last_child_stack_.push_back(is_last);
|
|
}
|
|
|
|
PrintIndent(is_last);
|
|
PrintColored("[" + std::to_string(i) + "]", Color::Gray);
|
|
|
|
if (arg.name)
|
|
{
|
|
os_ << " " << GetColor(Color::Yellow) << *arg.name << GetColor(Color::Reset) << ":";
|
|
}
|
|
if (arg.is_spread)
|
|
{
|
|
os_ << " " << GetColor(Color::Magenta) << "..." << GetColor(Color::Reset);
|
|
}
|
|
os_ << "\n";
|
|
|
|
if (arg.value)
|
|
{
|
|
IncreaseIndent();
|
|
arg.value->Accept(*this);
|
|
DecreaseIndent();
|
|
}
|
|
|
|
if (options_.use_tree_chars)
|
|
{
|
|
is_last_child_stack_.pop_back();
|
|
}
|
|
}
|
|
DecreaseIndent();
|
|
}
|
|
|
|
DecreaseIndent();
|
|
}
|
|
|
|
void DebugPrinter::VisitAttributeExpression(AttributeExpression& node)
|
|
{
|
|
PrintNodeHeader("AttributeExpression", node.location);
|
|
IncreaseIndent();
|
|
|
|
PrintExpression(node.object.get(), "object", false);
|
|
PrintKeyValue("attribute", node.attribute, Color::BrightGreen);
|
|
|
|
DecreaseIndent();
|
|
}
|
|
|
|
void DebugPrinter::VisitSubscriptExpression(SubscriptExpression& node)
|
|
{
|
|
PrintNodeHeader("SubscriptExpression", node.location);
|
|
IncreaseIndent();
|
|
|
|
PrintExpression(node.value.get(), "value");
|
|
|
|
if (!node.indices.empty())
|
|
{
|
|
PrintIndent();
|
|
PrintColored("indices ", Color::Yellow);
|
|
PrintColored("(" + std::to_string(node.indices.size()) + "):\n", Color::Gray);
|
|
|
|
IncreaseIndent();
|
|
for (size_t i = 0; i < node.indices.size(); ++i)
|
|
{
|
|
const auto& idx = node.indices[i];
|
|
PrintIndent();
|
|
PrintColored("[" + std::to_string(i) + "]", Color::Gray);
|
|
|
|
if (idx.is_slice)
|
|
{
|
|
os_ << " " << GetColor(Color::Cyan) << "[slice]" << GetColor(Color::Reset);
|
|
}
|
|
if (idx.is_empty_slice)
|
|
{
|
|
os_ << " " << GetColor(Color::Cyan) << "[empty]" << GetColor(Color::Reset);
|
|
}
|
|
os_ << "\n";
|
|
|
|
IncreaseIndent();
|
|
if (idx.start)
|
|
{
|
|
PrintExpression(idx.start.get(), "start");
|
|
}
|
|
if (idx.end)
|
|
{
|
|
PrintExpression(idx.end.get(), "end");
|
|
}
|
|
if (idx.step)
|
|
{
|
|
PrintExpression(idx.step.get(), "step");
|
|
}
|
|
DecreaseIndent();
|
|
}
|
|
DecreaseIndent();
|
|
}
|
|
|
|
DecreaseIndent();
|
|
}
|
|
|
|
void DebugPrinter::VisitArrayExpression(ArrayExpression& node)
|
|
{
|
|
PrintNodeHeader("ArrayExpression", node.location);
|
|
IncreaseIndent();
|
|
|
|
if (!node.elements.empty())
|
|
{
|
|
PrintIndent();
|
|
PrintColored("elements ", Color::Yellow);
|
|
PrintColored("(" + std::to_string(node.elements.size()) + "):\n", Color::Gray);
|
|
|
|
IncreaseIndent();
|
|
for (size_t i = 0; i < node.elements.size(); ++i)
|
|
{
|
|
const auto& elem = node.elements[i];
|
|
PrintIndent();
|
|
PrintColored("[" + std::to_string(i) + "]", Color::Gray);
|
|
|
|
if (elem.is_nested)
|
|
{
|
|
os_ << " " << GetColor(Color::Cyan) << "[nested]" << GetColor(Color::Reset);
|
|
}
|
|
os_ << "\n";
|
|
|
|
IncreaseIndent();
|
|
if (elem.key)
|
|
{
|
|
PrintExpression(elem.key.get(), "key");
|
|
}
|
|
if (elem.value)
|
|
{
|
|
PrintExpression(elem.value.get(), "value");
|
|
}
|
|
DecreaseIndent();
|
|
}
|
|
DecreaseIndent();
|
|
}
|
|
|
|
DecreaseIndent();
|
|
}
|
|
|
|
void DebugPrinter::VisitAnonymousFunctionExpression(AnonymousFunctionExpression& node)
|
|
{
|
|
PrintNodeHeader("AnonymousFunction", node.location);
|
|
IncreaseIndent();
|
|
|
|
PrintSignature(node.signature);
|
|
|
|
if (node.body)
|
|
{
|
|
PrintStatement(node.body.get(), "body", true);
|
|
PrintStatement(node.body.get(), "body", true);
|
|
}
|
|
|
|
DecreaseIndent();
|
|
}
|
|
|
|
void DebugPrinter::VisitPrefixIncrementExpression(PrefixIncrementExpression& node)
|
|
{
|
|
PrintNodeHeader("PrefixIncrement", node.location);
|
|
IncreaseIndent();
|
|
PrintExpression(node.argument.get(), "argument", true);
|
|
DecreaseIndent();
|
|
}
|
|
|
|
void DebugPrinter::VisitPrefixDecrementExpression(PrefixDecrementExpression& node)
|
|
{
|
|
PrintNodeHeader("PrefixDecrement", node.location);
|
|
IncreaseIndent();
|
|
PrintExpression(node.argument.get(), "argument", true);
|
|
DecreaseIndent();
|
|
}
|
|
|
|
void DebugPrinter::VisitPostfixIncrementExpression(PostfixIncrementExpression& node)
|
|
{
|
|
PrintNodeHeader("PostfixIncrement", node.location);
|
|
IncreaseIndent();
|
|
PrintExpression(node.argument.get(), "argument", true);
|
|
DecreaseIndent();
|
|
}
|
|
|
|
void DebugPrinter::VisitPostfixDecrementExpression(PostfixDecrementExpression& node)
|
|
{
|
|
PrintNodeHeader("PostfixDecrement", node.location);
|
|
IncreaseIndent();
|
|
PrintExpression(node.argument.get(), "argument", true);
|
|
DecreaseIndent();
|
|
}
|
|
|
|
void DebugPrinter::VisitFunctionPointerExpression(FunctionPointerExpression& node)
|
|
{
|
|
PrintNodeHeader("FunctionPointer", node.location);
|
|
IncreaseIndent();
|
|
PrintExpression(node.argument.get(), "argument", true);
|
|
DecreaseIndent();
|
|
}
|
|
|
|
void DebugPrinter::VisitAssignmentExpression(AssignmentExpression& node)
|
|
{
|
|
PrintNodeHeader("AssignmentExpression", node.location);
|
|
IncreaseIndent();
|
|
|
|
PrintIndent();
|
|
PrintColored("operator: ", Color::Yellow);
|
|
PrintOperator(node.op);
|
|
os_ << "\n";
|
|
|
|
PrintLeftHandSide(node.left, "left", false);
|
|
PrintExpression(node.right.get(), "right", true);
|
|
|
|
DecreaseIndent();
|
|
}
|
|
|
|
void DebugPrinter::VisitExpressionStatement(ExpressionStatement& node)
|
|
{
|
|
PrintNodeHeader("ExpressionStatement", node.location);
|
|
IncreaseIndent();
|
|
PrintExpression(node.expression.get(), "", true);
|
|
DecreaseIndent();
|
|
}
|
|
|
|
void DebugPrinter::VisitVarStatement(VarStatement& node)
|
|
{
|
|
PrintNodeHeader("VarStatement", node.location);
|
|
IncreaseIndent();
|
|
|
|
if (!node.declarations.empty())
|
|
{
|
|
PrintIndent();
|
|
PrintColored("declarations ", Color::Yellow);
|
|
PrintColored("(" + std::to_string(node.declarations.size()) + "):\n", Color::Gray);
|
|
|
|
IncreaseIndent();
|
|
for (size_t i = 0; i < node.declarations.size(); ++i)
|
|
{
|
|
bool is_last = (i == node.declarations.size() - 1);
|
|
if (node.declarations[i])
|
|
{
|
|
if (options_.use_tree_chars)
|
|
{
|
|
is_last_child_stack_.push_back(is_last);
|
|
node.declarations[i]->Accept(*this);
|
|
is_last_child_stack_.pop_back();
|
|
}
|
|
else
|
|
{
|
|
node.declarations[i]->Accept(*this);
|
|
}
|
|
}
|
|
}
|
|
DecreaseIndent();
|
|
}
|
|
|
|
DecreaseIndent();
|
|
}
|
|
|
|
void DebugPrinter::VisitStaticStatement(StaticStatement& node)
|
|
{
|
|
PrintNodeHeader("StaticStatement", node.location);
|
|
IncreaseIndent();
|
|
|
|
if (!node.declarations.empty())
|
|
{
|
|
PrintIndent();
|
|
PrintColored("declarations ", Color::Yellow);
|
|
PrintColored("(" + std::to_string(node.declarations.size()) + "):\n", Color::Gray);
|
|
|
|
IncreaseIndent();
|
|
for (size_t i = 0; i < node.declarations.size(); ++i)
|
|
{
|
|
bool is_last = (i == node.declarations.size() - 1);
|
|
if (node.declarations[i])
|
|
{
|
|
if (options_.use_tree_chars)
|
|
{
|
|
is_last_child_stack_.push_back(is_last);
|
|
node.declarations[i]->Accept(*this);
|
|
is_last_child_stack_.pop_back();
|
|
}
|
|
else
|
|
{
|
|
node.declarations[i]->Accept(*this);
|
|
}
|
|
}
|
|
}
|
|
DecreaseIndent();
|
|
}
|
|
|
|
DecreaseIndent();
|
|
}
|
|
|
|
void DebugPrinter::VisitGlobalStatement(GlobalStatement& node)
|
|
{
|
|
PrintNodeHeader("GlobalStatement", node.location);
|
|
IncreaseIndent();
|
|
|
|
if (!node.declarations.empty())
|
|
{
|
|
PrintIndent();
|
|
PrintColored("declarations ", Color::Yellow);
|
|
PrintColored("(" + std::to_string(node.declarations.size()) + "):\n", Color::Gray);
|
|
|
|
IncreaseIndent();
|
|
for (size_t i = 0; i < node.declarations.size(); ++i)
|
|
{
|
|
bool is_last = (i == node.declarations.size() - 1);
|
|
if (node.declarations[i])
|
|
{
|
|
if (options_.use_tree_chars)
|
|
{
|
|
is_last_child_stack_.push_back(is_last);
|
|
node.declarations[i]->Accept(*this);
|
|
is_last_child_stack_.pop_back();
|
|
}
|
|
else
|
|
{
|
|
node.declarations[i]->Accept(*this);
|
|
}
|
|
}
|
|
}
|
|
DecreaseIndent();
|
|
}
|
|
|
|
DecreaseIndent();
|
|
}
|
|
|
|
void DebugPrinter::VisitConstStatement(ConstStatement& node)
|
|
{
|
|
PrintNodeHeader("ConstStatement", node.location);
|
|
IncreaseIndent();
|
|
|
|
PrintKeyValue("name", node.name, Color::BrightGreen);
|
|
|
|
if (node.type_name)
|
|
{
|
|
PrintKeyValue("type", *node.type_name, Color::BrightMagenta);
|
|
}
|
|
|
|
if (node.value)
|
|
{
|
|
PrintExpression(node.value.get(), "value", true);
|
|
}
|
|
|
|
DecreaseIndent();
|
|
}
|
|
|
|
void DebugPrinter::VisitAssignmentStatement(AssignmentStatement& node)
|
|
{
|
|
PrintNodeHeader("AssignmentStatement", node.location);
|
|
IncreaseIndent();
|
|
|
|
PrintIndent();
|
|
PrintColored("operator: ", Color::Yellow);
|
|
PrintOperator(node.op);
|
|
os_ << "\n";
|
|
|
|
PrintLeftHandSide(node.left, "left", false);
|
|
PrintExpression(node.right.get(), "right", true);
|
|
|
|
DecreaseIndent();
|
|
}
|
|
|
|
void DebugPrinter::VisitBlockStatement(BlockStatement& node)
|
|
{
|
|
PrintNodeHeader("BlockStatement", node.location);
|
|
|
|
if (!node.statements.empty())
|
|
{
|
|
IncreaseIndent();
|
|
PrintStatements(node.statements);
|
|
DecreaseIndent();
|
|
}
|
|
}
|
|
|
|
void DebugPrinter::VisitIfStatement(IfStatement& node)
|
|
{
|
|
PrintNodeHeader("IfStatement", node.location);
|
|
IncreaseIndent();
|
|
|
|
if (!node.branches.empty())
|
|
{
|
|
PrintIndent();
|
|
PrintColored("branches ", Color::Yellow);
|
|
PrintColored("(" + std::to_string(node.branches.size()) + "):\n", Color::Gray);
|
|
|
|
IncreaseIndent();
|
|
for (size_t i = 0; i < node.branches.size(); ++i)
|
|
{
|
|
const auto& branch = node.branches[i];
|
|
PrintIndent();
|
|
PrintColored("[" + std::to_string(i) + "]", Color::Gray);
|
|
os_ << "\n";
|
|
|
|
IncreaseIndent();
|
|
if (branch.condition)
|
|
{
|
|
PrintExpression(branch.condition.get(), "condition");
|
|
}
|
|
if (branch.body)
|
|
{
|
|
PrintStatement(branch.body.get(), "body");
|
|
}
|
|
DecreaseIndent();
|
|
}
|
|
DecreaseIndent();
|
|
}
|
|
|
|
DecreaseIndent();
|
|
}
|
|
|
|
void DebugPrinter::VisitForInStatement(ForInStatement& node)
|
|
{
|
|
PrintNodeHeader("ForInStatement", node.location);
|
|
IncreaseIndent();
|
|
|
|
if (!node.key.empty())
|
|
{
|
|
PrintKeyValue("key", node.key, Color::BrightGreen);
|
|
}
|
|
if (!node.value.empty())
|
|
{
|
|
PrintKeyValue("value", node.value, Color::BrightGreen);
|
|
}
|
|
|
|
PrintExpression(node.collection.get(), "collection", false);
|
|
|
|
if (node.body)
|
|
{
|
|
PrintStatement(node.body.get(), "body", true);
|
|
}
|
|
|
|
DecreaseIndent();
|
|
}
|
|
|
|
void DebugPrinter::VisitForToStatement(ForToStatement& node)
|
|
{
|
|
PrintNodeHeader("ForToStatement", node.location);
|
|
IncreaseIndent();
|
|
|
|
PrintKeyValue("counter", node.counter, Color::BrightGreen);
|
|
|
|
if (node.is_downto)
|
|
{
|
|
PrintKeyValue("direction", "downto", Color::Cyan);
|
|
}
|
|
|
|
PrintExpression(node.start.get(), "start", false);
|
|
PrintExpression(node.end.get(), "end", false);
|
|
|
|
if (node.body)
|
|
{
|
|
PrintStatement(node.body.get(), "body", true);
|
|
}
|
|
|
|
DecreaseIndent();
|
|
}
|
|
|
|
void DebugPrinter::VisitWhileStatement(WhileStatement& node)
|
|
{
|
|
PrintNodeHeader("WhileStatement", node.location);
|
|
IncreaseIndent();
|
|
|
|
PrintExpression(node.condition.get(), "condition", false);
|
|
|
|
if (node.body)
|
|
{
|
|
PrintStatement(node.body.get(), "body", true);
|
|
}
|
|
|
|
DecreaseIndent();
|
|
}
|
|
|
|
void DebugPrinter::VisitRepeatStatement(RepeatStatement& node)
|
|
{
|
|
PrintNodeHeader("RepeatStatement", node.location);
|
|
IncreaseIndent();
|
|
|
|
if (!node.body.empty())
|
|
{
|
|
PrintIndent();
|
|
PrintColored("body ", Color::Yellow);
|
|
PrintColored("(" + std::to_string(node.body.size()) + "):\n", Color::Gray);
|
|
|
|
IncreaseIndent();
|
|
PrintStatements(node.body);
|
|
DecreaseIndent();
|
|
}
|
|
|
|
PrintExpression(node.condition.get(), "condition", true);
|
|
|
|
DecreaseIndent();
|
|
}
|
|
|
|
void DebugPrinter::VisitCaseStatement(CaseStatement& node)
|
|
{
|
|
PrintNodeHeader("CaseStatement", node.location);
|
|
IncreaseIndent();
|
|
|
|
PrintExpression(node.discriminant.get(), "discriminant");
|
|
|
|
if (!node.branches.empty())
|
|
{
|
|
PrintIndent();
|
|
PrintColored("branches ", Color::Yellow);
|
|
PrintColored("(" + std::to_string(node.branches.size()) + "):\n", Color::Gray);
|
|
|
|
IncreaseIndent();
|
|
for (size_t i = 0; i < node.branches.size(); ++i)
|
|
{
|
|
const auto& branch = node.branches[i];
|
|
PrintIndent();
|
|
PrintColored("[" + std::to_string(i) + "]", Color::Gray);
|
|
os_ << "\n";
|
|
|
|
IncreaseIndent();
|
|
if (!branch.values.empty())
|
|
{
|
|
PrintIndent();
|
|
PrintColored("values ", Color::Yellow);
|
|
PrintColored("(" + std::to_string(branch.values.size()) + "):\n", Color::Gray);
|
|
|
|
IncreaseIndent();
|
|
for (const auto& val : branch.values)
|
|
{
|
|
if (val)
|
|
val->Accept(*this);
|
|
}
|
|
DecreaseIndent();
|
|
}
|
|
|
|
if (branch.body)
|
|
{
|
|
PrintStatement(branch.body.get(), "body");
|
|
}
|
|
DecreaseIndent();
|
|
}
|
|
DecreaseIndent();
|
|
}
|
|
|
|
if (node.default_case)
|
|
{
|
|
PrintStatement(node.default_case.get(), "default_case");
|
|
}
|
|
|
|
DecreaseIndent();
|
|
}
|
|
|
|
void DebugPrinter::VisitTryStatement(TryStatement& node)
|
|
{
|
|
PrintNodeHeader("TryStatement", node.location);
|
|
IncreaseIndent();
|
|
|
|
if (node.try_body)
|
|
{
|
|
PrintStatement(node.try_body.get(), "try_body");
|
|
}
|
|
|
|
if (node.except_body)
|
|
{
|
|
PrintStatement(node.except_body.get(), "except_body");
|
|
}
|
|
|
|
DecreaseIndent();
|
|
}
|
|
|
|
void DebugPrinter::VisitBreakStatement(BreakStatement& node)
|
|
{
|
|
PrintNodeHeader("BreakStatement", node.location);
|
|
}
|
|
|
|
void DebugPrinter::VisitContinueStatement(ContinueStatement& node)
|
|
{
|
|
PrintNodeHeader("ContinueStatement", node.location);
|
|
}
|
|
|
|
void DebugPrinter::VisitReturnStatement(ReturnStatement& node)
|
|
{
|
|
PrintNodeHeader("ReturnStatement", node.location);
|
|
|
|
if (node.value)
|
|
{
|
|
IncreaseIndent();
|
|
PrintExpression(node.value.get(), "value", true);
|
|
DecreaseIndent();
|
|
}
|
|
}
|
|
|
|
void DebugPrinter::VisitUsesStatement(UsesStatement& node)
|
|
{
|
|
PrintNodeHeader("UsesStatement", node.location);
|
|
IncreaseIndent();
|
|
|
|
if (!node.units.empty())
|
|
{
|
|
PrintIndent();
|
|
PrintColored("units: ", Color::Yellow);
|
|
os_ << "[";
|
|
for (size_t i = 0; i < node.units.size(); ++i)
|
|
{
|
|
if (i > 0)
|
|
os_ << ", ";
|
|
PrintColored(node.units[i], Color::BrightGreen);
|
|
}
|
|
os_ << "]\n";
|
|
}
|
|
|
|
DecreaseIndent();
|
|
}
|
|
|
|
void DebugPrinter::VisitFunctionDefinition(FunctionDefinition& node)
|
|
{
|
|
PrintNodeHeader("FunctionDefinition", node.location);
|
|
IncreaseIndent();
|
|
|
|
PrintKeyValue("name", node.name, Color::BrightCyan);
|
|
|
|
if (node.is_overload)
|
|
{
|
|
PrintKeyValue("overload", true);
|
|
}
|
|
|
|
PrintSignature(node.signature);
|
|
|
|
if (node.body)
|
|
{
|
|
PrintStatement(node.body.get(), "body", true);
|
|
}
|
|
|
|
DecreaseIndent();
|
|
}
|
|
|
|
void DebugPrinter::VisitFunctionDeclaration(FunctionDeclaration& node)
|
|
{
|
|
PrintNodeHeader("FunctionDeclaration", node.location);
|
|
IncreaseIndent();
|
|
|
|
PrintKeyValue("name", node.name, Color::BrightCyan);
|
|
|
|
if (node.is_overload)
|
|
{
|
|
PrintKeyValue("overload", true);
|
|
}
|
|
|
|
PrintSignature(node.signature);
|
|
|
|
DecreaseIndent();
|
|
}
|
|
|
|
void DebugPrinter::VisitVarDeclaration(VarDeclaration& node)
|
|
{
|
|
PrintNodeHeader("VarDeclaration", node.location);
|
|
IncreaseIndent();
|
|
|
|
PrintKeyValue("name", node.name, Color::BrightGreen);
|
|
|
|
if (node.type_name)
|
|
{
|
|
PrintKeyValue("type", *node.type_name, Color::BrightMagenta);
|
|
}
|
|
|
|
if (node.initial_value)
|
|
{
|
|
PrintExpression(node.initial_value.get(), "initial_value");
|
|
}
|
|
|
|
DecreaseIndent();
|
|
}
|
|
|
|
void DebugPrinter::VisitStaticDeclaration(StaticDeclaration& node)
|
|
{
|
|
PrintNodeHeader("StaticDeclaration", node.location);
|
|
IncreaseIndent();
|
|
|
|
PrintKeyValue("name", node.name, Color::BrightGreen);
|
|
|
|
if (node.reference_modifier != ReferenceModifier::kNone)
|
|
{
|
|
PrintIndent();
|
|
PrintColored("reference: ", Color::Yellow);
|
|
PrintReferenceModifier(node.reference_modifier);
|
|
os_ << "\n";
|
|
}
|
|
|
|
if (node.type_name)
|
|
{
|
|
PrintKeyValue("type", *node.type_name, Color::BrightMagenta);
|
|
}
|
|
|
|
if (node.initial_value)
|
|
{
|
|
PrintExpression(node.initial_value.get(), "initial_value");
|
|
}
|
|
|
|
DecreaseIndent();
|
|
}
|
|
|
|
void DebugPrinter::VisitGlobalDeclaration(GlobalDeclaration& node)
|
|
{
|
|
PrintNodeHeader("GlobalDeclaration", node.location);
|
|
IncreaseIndent();
|
|
|
|
PrintKeyValue("name", node.name, Color::BrightGreen);
|
|
|
|
if (node.type_name)
|
|
{
|
|
PrintKeyValue("type", *node.type_name, Color::BrightMagenta);
|
|
}
|
|
|
|
if (node.initial_value)
|
|
{
|
|
PrintExpression(node.initial_value.get(), "initial_value");
|
|
}
|
|
|
|
DecreaseIndent();
|
|
}
|
|
|
|
void DebugPrinter::VisitFieldDeclaration(FieldDeclaration& node)
|
|
{
|
|
PrintNodeHeader("FieldDeclaration", node.location);
|
|
IncreaseIndent();
|
|
|
|
PrintKeyValue("name", node.name, Color::BrightGreen);
|
|
|
|
if (node.reference_modifier != ReferenceModifier::kNone)
|
|
{
|
|
PrintIndent();
|
|
PrintColored("reference: ", Color::Yellow);
|
|
PrintReferenceModifier(node.reference_modifier);
|
|
os_ << "\n";
|
|
}
|
|
|
|
if (node.type_name)
|
|
{
|
|
PrintKeyValue("type", *node.type_name, Color::BrightMagenta);
|
|
}
|
|
|
|
if (node.initial_value)
|
|
{
|
|
PrintExpression(node.initial_value.get(), "initial_value");
|
|
}
|
|
|
|
DecreaseIndent();
|
|
}
|
|
|
|
void DebugPrinter::VisitUnpackPattern(UnpackPattern& node)
|
|
{
|
|
PrintNodeHeader("UnpackPattern", node.location);
|
|
IncreaseIndent();
|
|
|
|
if (!node.names.empty())
|
|
{
|
|
PrintIndent();
|
|
PrintColored("names: ", Color::Yellow);
|
|
os_ << "[";
|
|
for (size_t i = 0; i < node.names.size(); ++i)
|
|
{
|
|
if (i > 0)
|
|
os_ << ", ";
|
|
PrintColored(node.names[i], Color::BrightGreen);
|
|
}
|
|
os_ << "]\n";
|
|
}
|
|
|
|
DecreaseIndent();
|
|
}
|
|
|
|
void DebugPrinter::VisitClassDefinition(ClassDefinition& node)
|
|
{
|
|
PrintNodeHeader("ClassDefinition", node.location);
|
|
IncreaseIndent();
|
|
|
|
PrintKeyValue("name", node.name, Color::BrightCyan);
|
|
|
|
if (!node.parent_classes.empty())
|
|
{
|
|
PrintIndent();
|
|
PrintColored("parents: ", Color::Yellow);
|
|
os_ << "[";
|
|
for (size_t i = 0; i < node.parent_classes.size(); ++i)
|
|
{
|
|
if (i > 0)
|
|
os_ << ", ";
|
|
PrintColored(node.parent_classes[i], Color::BrightCyan);
|
|
}
|
|
os_ << "]\n";
|
|
}
|
|
|
|
if (!node.members.empty())
|
|
{
|
|
PrintIndent();
|
|
PrintColored("members ", Color::Yellow);
|
|
PrintColored("(" + std::to_string(node.members.size()) + "):\n", Color::Gray);
|
|
|
|
IncreaseIndent();
|
|
for (const auto& member : node.members)
|
|
{
|
|
if (member)
|
|
member->Accept(*this);
|
|
}
|
|
DecreaseIndent();
|
|
}
|
|
|
|
DecreaseIndent();
|
|
}
|
|
|
|
void DebugPrinter::VisitClassMember(ClassMember& node)
|
|
{
|
|
PrintNodeHeader("ClassMember", node.location);
|
|
IncreaseIndent();
|
|
|
|
PrintIndent();
|
|
PrintColored("access: ", Color::Yellow);
|
|
PrintAccessModifier(node.access_modifier);
|
|
os_ << "\n";
|
|
|
|
std::visit([this](auto&& member) {
|
|
if (member)
|
|
{
|
|
member->Accept(*this);
|
|
}
|
|
},
|
|
node.member);
|
|
|
|
DecreaseIndent();
|
|
}
|
|
|
|
void DebugPrinter::VisitMethodDeclaration(MethodDeclaration& node)
|
|
{
|
|
PrintNodeHeader("MethodDeclaration", node.location);
|
|
IncreaseIndent();
|
|
|
|
PrintKeyValue("name", node.name, Color::BrightCyan);
|
|
|
|
if (node.method_type == MethodType::kConstructor)
|
|
{
|
|
PrintKeyValue("type", "constructor", Color::Magenta);
|
|
}
|
|
else if (node.method_type == MethodType::kDestructor)
|
|
{
|
|
PrintKeyValue("type", "destructor", Color::Magenta);
|
|
}
|
|
|
|
if (node.is_class_method)
|
|
{
|
|
PrintKeyValue("class_method", true);
|
|
}
|
|
|
|
if (node.is_operator_overload)
|
|
{
|
|
PrintKeyValue("operator", node.operator_symbol, Color::BrightYellow);
|
|
}
|
|
|
|
if (node.modifier != MethodModifier::kNone)
|
|
{
|
|
PrintIndent();
|
|
PrintColored("modifier: ", Color::Yellow);
|
|
PrintMethodModifier(node.modifier);
|
|
os_ << "\n";
|
|
}
|
|
|
|
PrintSignature(node.signature);
|
|
|
|
if (node.body)
|
|
{
|
|
PrintStatement(node.body.get(), "body", true);
|
|
}
|
|
|
|
DecreaseIndent();
|
|
}
|
|
|
|
void DebugPrinter::VisitPropertyDeclaration(PropertyDeclaration& node)
|
|
{
|
|
PrintNodeHeader("PropertyDeclaration", node.location);
|
|
IncreaseIndent();
|
|
|
|
PrintKeyValue("name", node.name, Color::BrightCyan);
|
|
|
|
if (node.type_name)
|
|
{
|
|
PrintKeyValue("type", *node.type_name, Color::BrightMagenta);
|
|
}
|
|
|
|
if (node.index_value)
|
|
{
|
|
PrintKeyValue("index", *node.index_value);
|
|
}
|
|
|
|
if (node.read_accessor)
|
|
{
|
|
PrintKeyValue("read", *node.read_accessor, Color::Green);
|
|
}
|
|
|
|
if (node.write_accessor)
|
|
{
|
|
PrintKeyValue("write", *node.write_accessor, Color::Green);
|
|
}
|
|
|
|
DecreaseIndent();
|
|
}
|
|
|
|
void DebugPrinter::VisitExternalMethodDefinition(ExternalMethodDefinition& node)
|
|
{
|
|
PrintNodeHeader("ExternalMethodDefinition", node.location);
|
|
IncreaseIndent();
|
|
|
|
PrintKeyValue("class", node.owner_class, Color::BrightCyan);
|
|
PrintKeyValue("method", node.name, Color::BrightCyan);
|
|
|
|
if (node.method_type == MethodType::kConstructor)
|
|
{
|
|
PrintKeyValue("type", "constructor", Color::Magenta);
|
|
}
|
|
else if (node.method_type == MethodType::kDestructor)
|
|
{
|
|
PrintKeyValue("type", "destructor", Color::Magenta);
|
|
}
|
|
|
|
if (node.is_class_method)
|
|
{
|
|
PrintKeyValue("class_method", true);
|
|
}
|
|
|
|
if (node.is_operator_overload)
|
|
{
|
|
PrintKeyValue("operator", node.operator_symbol, Color::BrightYellow);
|
|
}
|
|
|
|
if (node.modifier != MethodModifier::kNone)
|
|
{
|
|
PrintIndent();
|
|
PrintColored("modifier: ", Color::Yellow);
|
|
PrintMethodModifier(node.modifier);
|
|
os_ << "\n";
|
|
}
|
|
|
|
PrintSignature(node.signature);
|
|
|
|
if (node.body)
|
|
{
|
|
PrintStatement(node.body.get(), "body", true);
|
|
}
|
|
|
|
DecreaseIndent();
|
|
}
|
|
|
|
void DebugPrinter::VisitUnitDefinition(UnitDefinition& node)
|
|
{
|
|
PrintNodeHeader("UnitDefinition", node.location);
|
|
IncreaseIndent();
|
|
|
|
PrintKeyValue("name", node.name, Color::BrightCyan);
|
|
|
|
if (!node.interface_statements.empty())
|
|
{
|
|
PrintIndent();
|
|
PrintColored("interface ", Color::Yellow);
|
|
PrintColored("(" + std::to_string(node.interface_statements.size()) + "):\n", Color::Gray);
|
|
|
|
IncreaseIndent();
|
|
PrintStatements(node.interface_statements);
|
|
DecreaseIndent();
|
|
}
|
|
|
|
if (!node.implementation_statements.empty())
|
|
{
|
|
PrintIndent();
|
|
PrintColored("implementation ", Color::Yellow);
|
|
PrintColored("(" + std::to_string(node.implementation_statements.size()) + "):\n", Color::Gray);
|
|
|
|
IncreaseIndent();
|
|
PrintStatements(node.implementation_statements);
|
|
DecreaseIndent();
|
|
}
|
|
|
|
if (!node.initialization_statements.empty())
|
|
{
|
|
PrintIndent();
|
|
PrintColored("initialization ", Color::Yellow);
|
|
PrintColored("(" + std::to_string(node.initialization_statements.size()) + "):\n", Color::Gray);
|
|
|
|
IncreaseIndent();
|
|
PrintStatements(node.initialization_statements);
|
|
DecreaseIndent();
|
|
}
|
|
|
|
if (!node.finalization_statements.empty())
|
|
{
|
|
PrintIndent();
|
|
PrintColored("finalization ", Color::Yellow);
|
|
PrintColored("(" + std::to_string(node.finalization_statements.size()) + "):\n", Color::Gray);
|
|
|
|
IncreaseIndent();
|
|
PrintStatements(node.finalization_statements);
|
|
DecreaseIndent();
|
|
}
|
|
|
|
DecreaseIndent();
|
|
}
|
|
|
|
void DebugPrinter::VisitTSSQLExpression(TSSQLExpression& node)
|
|
{
|
|
PrintNodeHeader("TSSQLExpression", node.location);
|
|
IncreaseIndent();
|
|
|
|
const char* 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;
|
|
}
|
|
|
|
PrintKeyValue("sql_type", type_str, Color::BrightMagenta);
|
|
PrintKeyValue("raw_sql", node.raw_sql, Color::Green);
|
|
|
|
DecreaseIndent();
|
|
}
|
|
|
|
// ===== 便捷函数实现 =====
|
|
|
|
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);
|
|
}
|
|
}
|