#include "node.h" #include #include #include string Node::toString() const { std::ostringstream oss; if (!_label.empty()) oss << _label << " "; if (_mnemonic) oss << _mnemonic->toString() << " "; if (!_comment.empty()) oss << "." << _comment; return oss.str(); } std::string Mnemonic::toString() const { std::ostringstream oss; oss << "[OP:" << std::hex << (int)_opcode << "]"; if (_extended) oss << "+"; // Print operands for (size_t i = 0; i < _operands.size(); ++i) { if (i > 0) oss << ","; std::visit([&](auto&& arg) { using T = std::decay_t; if constexpr (std::is_same_v) { // nothing } else if constexpr (std::is_same_v) { oss << "R" << arg.num; } else if constexpr (std::is_same_v) { oss << "#" << arg.value; } else if constexpr (std::is_same_v) { oss << arg.name; if (arg.indexed) oss << ",X"; } }, _operands[i]); } return oss.str(); } string InstructionNode::toString() const { std::ostringstream oss; if (!_label.empty()) oss << _label << " "; if (_mnemonic) oss << _mnemonic->toString(); if (!_comment.empty()) oss << " ." << _comment; return oss.str(); } string CommentNode::toString() const { return "." + _comment; } string DirectiveNode::toString() const { std::ostringstream oss; if (!_label.empty()) oss << _label << " "; switch (_kind) { case DirectiveKind::START: oss << "START"; break; case DirectiveKind::END: oss << "END"; break; case DirectiveKind::BASE: oss << "BASE"; break; case DirectiveKind::NOBASE: oss << "NOBASE"; break; case DirectiveKind::EQU: oss << "EQU"; break; case DirectiveKind::ORG: oss << "ORG"; break; case DirectiveKind::LTORG: oss << "LTORG"; break; case DirectiveKind::EXTDEF: oss << "EXTDEF"; break; case DirectiveKind::EXTREF: oss << "EXTREF"; break; case DirectiveKind::CSECT: oss << "CSECT"; break; } std::visit([&](auto&& arg) { using T = std::decay_t; if constexpr (std::is_same_v) { // no arg } else if constexpr (std::is_same_v) { oss << " " << std::hex << arg; } else if constexpr (std::is_same_v) { oss << " " << arg; } else if constexpr (std::is_same_v>) { for (size_t i = 0; i < arg.size(); ++i) { if (i > 0) oss << ","; oss << arg[i]; } } }, _arg); if (!_comment.empty()) oss << " ." << _comment; return oss.str(); } string DataNode::toString() const { std::ostringstream oss; if (!_label.empty()) oss << _label << " "; switch (_kind) { case DataKind::WORD: oss << "WORD"; break; case DataKind::BYTE: oss << "BYTE"; break; case DataKind::RESW: oss << "RESW"; break; case DataKind::RESB: oss << "RESB"; break; } std::visit([&](auto&& arg) { using T = std::decay_t; if constexpr (std::is_same_v) { // no value } else if constexpr (std::is_same_v) { oss << " " << arg; } else if constexpr (std::is_same_v>) { // Try to display as string if all printable ASCII bool isPrintable = !arg.empty() && std::all_of(arg.begin(), arg.end(), [](uint8_t b) { return b >= 32 && b <= 126; }); if (isPrintable) { oss << " C'"; for (uint8_t b : arg) oss << static_cast(b); oss << "'"; } else { // Display as hex oss << " X'"; for (uint8_t b : arg) { oss << std::hex << std::setw(2) << std::setfill('0') << (int)b; } oss << "'"; } } }, _value); if (!_comment.empty()) oss << " ." << _comment; return oss.str(); }