#include "resolving_output.h"
#include "cbc/isa_disasm.h"
#include "engine/engine.h"
#include "engine/field_layout.h"
#include "engine/identifiers.h"
#include "engine/method_table.h"
#include "engine/symlevel/code.h"
#include "engine/symlevel/definitions.h"
#include "engine/symlevel/io/file_id.h"
#include "engine/symlevel/reader.h"
#include "engine/terms.h"
#include "resolution/resolution.h"
namespace Stream {
ResolvingOutput::ResolvingOutput(Engine::Session& session, Stream::Output& out)
: session(session),
holder(Indented(out, 0))
{}
template <typename T> ResolvingOutput& operator<<(ResolvingOutput& out, std::optional<T> opt)
{
if (opt.has_value()) {
out << *opt;
} else {
out << "<none>";
}
return out;
}
ResolvingOutput& ResolvingOutput::operator<<(Engine::Term term) { return *this << term.GetName(session); }
ResolvingOutput& ResolvingOutput::operator<<(Detailed<Engine::RefIdentifier<Engine::Term>> term)
{
return *this << Engine::TermManager::Resolve(session, term.value);
}
ResolvingOutput& ResolvingOutput::operator<<(Engine::GlobalTerm term) { return *this << Engine::Term(term); }
ResolvingOutput& ResolvingOutput::operator<<(Engine::LocalTerm term) { return *this << Engine::Term(term); }
ResolvingOutput& ResolvingOutput::operator<<(IO::FileId fileId) { return *this << fileId.id; }
ResolvingOutput& ResolvingOutput::operator<<(Symlevel::FieldDefinition const& fd)
{
auto& out = *this;
auto ftype = Detailed(fd.FieldType());
auto name = StringOf(fd.GetName());
out << Detailed(fd.Flags()) << " " << Detailed(fd.FieldType()) << " " << name;
return out;
}
ResolvingOutput& ResolvingOutput::operator<<(NoResolve<Symlevel::FieldDefinition> nr)
{
auto& out = *this;
auto& fd = nr.value;
auto ftype = fd.FieldType();
auto name = fd.GetName();
out << Detailed(fd.Flags()) << ". field type: " << ftype << ". name: " << name;
return out;
}
ResolvingOutput& ResolvingOutput::operator<<(Full<Symlevel::MethodDefinition> full)
{
auto& md = full.value;
auto& out = *this;
auto resolver = Resolution::Resolver(session, md.GetIdentifier());
auto name = Detailed(md.Name());
out << name << Detailed(md.Signature()) << " ";
Region("", [&] {
out << "flags: " << Detailed(md.GetFlags()) << endl;
if (auto sourceFileOpt = md.SourceFile()) {
out << "source file: " << StringOf(*sourceFileOpt) << endl;
}
if (auto sourceFullOpt = md.SourceFullName()) {
out << "source full name: " << StringOf(*sourceFullOpt) << endl;
}
if (auto linkageOpt = md.LinkageName()) {
out << "linkage name: " << StringOf(*linkageOpt) << endl;
}
if (auto codeOpt = md.MethodCode()) {
Region("code", [&]() {
auto code = Symlevel::Code::Parse(session, md.FileId(), codeOpt->GetOffset());
Cbc::Disasm(ResolvingOutput::out, code, &resolver);
});
}
});
return out;
}
ResolvingOutput& ResolvingOutput::operator<<(Symlevel::MethodDefinition const& md)
{
auto& out = *this;
auto name = Detailed(md.Name());
out << name << Detailed(md.Signature());
return out;
}
ResolvingOutput& ResolvingOutput::operator<<(NoResolve<Symlevel::MethodDefinition> nr)
{
auto& out = *this;
auto& md = nr.value;
out << "name: " << md.Name().GetOffset() << ". sig: " << md.Signature();
return out;
}
ResolvingOutput& ResolvingOutput::operator<<(NoResolve<Symlevel::TypeDefinition> nr)
{
auto& out = *this;
auto& td = nr.value;
Region("method name: " + std::to_string(td.GetName().GetOffset()), [&]() {
out << "super: " << td.GetSuperType() << endl;
Region("fields", [&]() {
td.GetFields().ForEach(session, [&](auto& def) { out << NoResolve(def.Identifier()) << endl; });
});
Region("methods", [&]() {
td.GetMethods().ForEach(session, [&](auto& def) { out << NoResolve(def.GetIdentifier()); });
});
Region("virtual methods", [&]() {
auto vms = td.GetVirtualMethods();
for (auto ident : vms.Values(session)) {
out << NoResolve(ident);
}
});
});
return out;
}
ResolvingOutput& ResolvingOutput::TypeDefinition(Symlevel::TypeDefinition const& td, bool full)
{
auto& out = *this;
Region(StringOf(td.GetName()), [&]() {
out << "super: " << Detailed(td.GetSuperType()) << endl;
Region("fields", [&]() {
td.GetFields().ForEach(session, [&](auto& def) { out << Detailed(def.Identifier()) << endl; });
});
Region("instance fields", [&]() {
for (auto def : td.GetInstanceFields().Values(session)) {
out << Detailed(def) << endl;
}
});
Region("methods", [&]() {
td.GetMethods().ForEach(session, [&](auto& def) {
if (full) {
out << Full(def.GetIdentifier());
} else {
out << Detailed(def.GetIdentifier());
}
});
});
Region("virtual methods", [&]() {
auto vms = td.GetVirtualMethods();
for (auto ident : vms.Values(session)) {
if (full) {
out << Full(ident);
} else {
out << Detailed(ident);
}
}
});
});
return out;
}
ResolvingOutput& ResolvingOutput::operator<<(Full<Symlevel::TypeDefinition> full)
{
return TypeDefinition(full.value, true);
}
ResolvingOutput& ResolvingOutput::operator<<(Symlevel::TypeDefinition const& td) { return TypeDefinition(td, false); }
ResolvingOutput& ResolvingOutput::operator<<(Engine::MethodTable const& mt)
{
auto& out = *this;
out << "method table:" << endl;
out << " classes:" << endl;
auto writeEntry = [&](Engine::MethodTableEntry& entry) {
auto def = Symlevel::Reader::Read(session, entry.method);
out << " " << entry.methodNum << ": ";
out << Detailed(def.Name()) << Detailed(def.Signature());
out << ", from: " << entry.genericContext << endl;
};
auto writeTable = [&](Engine::MethodSubTable& st) {
out << " " << st.DeclaringType();
out << " [" << st.StartPos() << ", " << st.EndPos() << "]:" << endl;
for (auto entry : st.Entries()) {
writeEntry(entry);
}
};
for (auto st : mt.Classes()) {
writeTable(st);
}
out << " interfaces:" << endl;
for (auto st : mt.Interfaces()) {
writeTable(st);
}
return out;
}
ResolvingOutput& ResolvingOutput::operator<<(Engine::FieldLayout const& layout)
{
auto& stream = *this;
stream << "field layout:" << endl;
out.SetIndent(out.GetIndent() + 2);
stream << "size: " << layout->desc.size << endl;
stream << "alignment: " << layout->desc.alignment << endl;
for (auto& f : layout->fields) {
auto def = Symlevel::Reader::Read(session, f.definition);
stream << Detailed(def.GetName()) << ": " << f.fieldType << " - " << f.offset << endl;
}
out.SetIndent(out.GetIndent() - 2);
return stream;
}
template <typename T> void ResolvingOutput::Region(T name, std::function<void()> f)
{
*this << name << " {" << endl;
out.SetIndent(out.GetIndent() + 2);
f();
out.SetIndent(out.GetIndent() - 2);
*this << "}" << endl;
}
Symlevel::String ResolvingOutput::StringOf(Symlevel::Offset<Symlevel::String> str, IO::FileId fid)
{
return Symlevel::String::Parse(session, fid, str);
}
Symlevel::String ResolvingOutput::StringOf(Engine::Identifier<Symlevel::String> str)
{
return Symlevel::String::Parse(session, str);
}
}