Skip to content

Commit

Permalink
Merge pull request #592 from leapmotion/feature-autofiltergraph
Browse files Browse the repository at this point in the history
AutoFilter network graph representation
  • Loading branch information
codemercenary committed Jun 19, 2015
2 parents 5230cff + e1cdcc6 commit a247878
Show file tree
Hide file tree
Showing 3 changed files with 140 additions and 4 deletions.
17 changes: 14 additions & 3 deletions autowiring/AutowiringDebug.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@
#pragma once
#include <string>
#include <vector>
#include <iostream>
#include <ostream>
#include <memory>

struct AutoFilterDescriptor;
class AutoPacket;
class CoreContext;

namespace autowiring {
namespace dbg {
Expand All @@ -21,9 +23,10 @@ bool IsLambda(const std::type_info& ti);
std::string ContextName(void);

/// <summary>
/// Write a string representation of the context hierarchy to 'os'
/// Write a string representation of the context hierarchy to 'os'(defaults to std::cout)
/// </summary>
void PrintContextTree(std::ostream& os = std::cout);
void PrintContextTree(void);
void PrintContextTree(std::ostream& os);

/// <returns>
/// The current packet under processing
Expand All @@ -48,6 +51,14 @@ std::string AutoFilterInfo(const char* name);
/// <param name="name">The name of the filter</param>
std::vector<std::string> ListRootDecorations(void);

/// <summary>
/// Write a DOT file representing the AutoFilter
/// </summary>
/// <param name="ctxt">Context of AutoFilter network to output. Defaults to AutoCurrentContext</param>
/// <param name="os">output stream to write DOT file</param>
void WriteAutoFilterGraph(std::ostream& os);
void WriteAutoFilterGraph(std::ostream& os, std::shared_ptr<CoreContext> ctxt);

/// <summary>
/// Initializes the Autowiring debug library
/// </summary>
Expand Down
88 changes: 87 additions & 1 deletion src/autowiring/AutowiringDebug.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include "stdafx.h"
#include "AutowiringDebug.h"
#include "Autowired.h"
#include <algorithm>
#include <iomanip>
#include <iostream>
#include <sstream>
Expand Down Expand Up @@ -43,7 +44,8 @@ static std::string DemangleWithAutoID(const std::type_info& ti) {

if (retVal.compare(0, sizeof(prefix) - 1, prefix) == 0) {
size_t off = sizeof(prefix) - 1;
retVal = retVal.substr(off, retVal.length() - off - 2);
size_t end = retVal.find_last_not_of(' ', retVal.find_last_of('>') - 1);
retVal = retVal.substr(off, end - off + 1);
}
return retVal;
}
Expand Down Expand Up @@ -91,6 +93,10 @@ void autowiring::dbg::PrintContextTree(std::ostream& os) {
PrintContextTreeRecursive(os, AutoGlobalContext());
}

void autowiring::dbg::PrintContextTree(void) {
PrintContextTreeRecursive(std::cout, AutoGlobalContext());
}

AutoPacket* autowiring::dbg::CurrentPacket(void) {
Autowired<AutoPacketFactory> factory;
if (!factory)
Expand Down Expand Up @@ -193,6 +199,86 @@ std::vector<std::string> autowiring::dbg::ListRootDecorations(void) {
return retVal;
}

void autowiring::dbg::WriteAutoFilterGraph(std::ostream& os) {
WriteAutoFilterGraph(os, AutoCurrentContext());
}

void autowiring::dbg::WriteAutoFilterGraph(std::ostream& os, std::shared_ptr<CoreContext> ctxt) {
CurrentContextPusher pshr(ctxt);
Autowired<AutoPacketFactory> factory;

// Write opening and closing parts of file. Now, we only need to write edges
os << "digraph " << autowiring::demangle(ctxt->GetSigilType()) << " {" << std::endl;
auto exit = MakeAtExit([&os]{
os << "}" << std::endl;
});

// If no factory, this is an empty network
if (!factory) {
return;
}

// Obtain all descriptors:
const std::vector<AutoFilterDescriptor> descs = factory->GetAutoFilters();

std::unordered_map<std::string, int> decorations; // demangled name to ID
std::unordered_map<std::string, int> filters; // demangled name to ID

// give each node a unique id
int idCounter = 0;

for (const auto& desc : descs) {
std::string filter = autowiring::demangle(desc.GetType());

// Assign each filter an ID
if (filters.find(filter) == filters.end()) {
filters[filter] = idCounter++;
}

auto args = desc.GetAutoFilterArguments();
for (size_t i = 0; i < desc.GetArity(); i++) {
const AutoFilterArgument& arg = args[i];

std::string decoration = DemangleWithAutoID(*arg.ti);

// Assign each decoration and ID
if (decorations.find(decoration) == decorations.end()) {
decorations[decoration] = idCounter++;
}

// Add edge
if (arg.is_input) {
os << decorations[decoration] << " -> " << filters[filter];
} else {
os << filters[filter] << " -> " << decorations[decoration];
}

// Label time shifted edges
if (arg.tshift) {
os << " [style=dotted label=\"prev=" << arg.tshift << "\"]";
}

os << std::endl;
}
}

// Label each filter with its demangled name
for (const auto& filter : filters) {
const std::string& name = filter.first;
int id = filter.second;

os << id << " [shape=box label=\""<< name << "\"];" << std::endl;
}

// Label each decoration with its demangled name
for (const auto& decoration : decorations) {
const std::string& name = decoration.first;
int id = decoration.second;

os << id << " [shape=oval label=\""<< name << "\"];" << std::endl;
}
}

void autowiring::dbg::DebugInit(void) {

}
39 changes: 39 additions & 0 deletions src/autowiring/test/AutowiringDebugTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include <autowiring/AutowiringDebug.h>
#include "TestFixtures/Decoration.hpp"
#include <algorithm>
#include <fstream>

class AutowiringDebugTest:
public testing::Test
Expand Down Expand Up @@ -86,3 +87,41 @@ TEST_F(AutowiringDebugTest, ContextPrintout) {

ASSERT_EQ(tree, output) << "Didn't print correct tree";
}

struct IntOutputer {
void AutoFilter(int& i) {
i = 4;
}
};

struct IntInFloatOut {
void AutoFilter(const int& i, float& f) {
f = static_cast<float>(i) + 3;
}
};

struct IntInFloatIn {
void AutoFilter(const int& i, const float& f) {}
};

TEST_F(AutowiringDebugTest, BasicAutoFilterGraph) {
AutoRequired<AutoPacketFactory> factory;
AutoRequired<IntOutputer> filter1;
AutoRequired<IntInFloatOut> filter2;
AutoRequired<IntInFloatIn> filter3;

*factory += [](auto_prev<float> in, std::string& out) {
out = "hello world";
};

*factory += [](double& out) { out = 3.0;};
*factory += [](double& out) { out = 4.0; };

*factory += [](const double* vals []){};

AutoCurrentContext()->Initiate();
auto packet = factory->NewPacket();

std::stringstream ss;
autowiring::dbg::WriteAutoFilterGraph(ss);
}

0 comments on commit a247878

Please sign in to comment.