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