dfagraph.cpp
No OneTemporary

File Metadata

Created
Mon, Dec 15, 5:58 AM

dfagraph.cpp

#include "analysis/dfagraph.h"
#include "analysis/aux.h"
#include <list>
using namespace xreate;
using namespace xreate::analysis;
using namespace std;
namespace xreate {
namespace analysis {
void
DFAGraph::print(std::ostringstream& output) const {
std::set<SymbolPacked> symbols;
output << endl << "%\t\tStatic analysis: DFA" << endl;
std::vector<std::pair<SymbolPacked, SymbolPacked>>::const_iterator i1;
std::vector<DFGConnection>::const_iterator i2;
boost::format formatDfaConnection("dfa_connection(%1%, %2%, %3%).");
for (i1 = this->__edges.begin(), i2 = this->__data.begin(); i1 != this->__edges.end(); ++i1, ++i2) {
string edgeName;
switch (*i2) {
case DFGConnection::WEAK: edgeName = "weak";
break;
case DFGConnection::STRONG: edgeName = "strong";
break;
case DFGConnection::PROTOTYPE: edgeName = "proto";
break;
}
output << formatDfaConnection
% formatSymbol(i1->first)
% formatSymbol(i1->second)
% edgeName
<< " %" << this->__clasp->getHintForPackedSymbol(i1->first) << " - " << this->__clasp->getHintForPackedSymbol(i1->second)
<< endl;
symbols.insert(i1->first);
symbols.insert(i1->second);
}
boost::format formatDfaDependency("dfa_dependency(%1%, %2%).");
for (auto i = this->__dependencies.begin(); i != this->__dependencies.end(); ++i) {
output << formatDfaDependency
% formatSymbol(i->first)
% formatSymbol(i->second)
<< " %"
<< this->__clasp->getHintForPackedSymbol(i->first) << " - "
<< this->__clasp->getHintForPackedSymbol(i->second)
<< endl;
}
boost::format formatBind("bind(%1%, %2%).");
for (const pair<SymbolPacked, Expression>& tag : this->__tags) {
for (string variant : xreate::analysis::compile(tag.second)) {
output << formatBind
% formatSymbol(tag.first)
% (variant)
<< "%" << this->__clasp->getHintForPackedSymbol(tag.first)
<< endl;
}
symbols.insert(tag.first);
}
for (const SymbolPacked& s : symbols) {
output << "v(" << formatSymbol(s) << ")."
<< " %" << this->__clasp->getHintForPackedSymbol(s)
<< endl;
}
}
class VisitorAddTag : public boost::static_visitor<> {
public:
void operator()(const SymbolPacked& symbol) {
__graph->__tags.emplace(symbol, move(__tag));
}
void operator()(SymbolTransient& symbol) {
symbol.tags.push_back(move(__tag));
}
void operator()(const SymbolInvalid& symbol) {
assert(false && "Undefined behaviour");
}
VisitorAddTag(DFAGraph * const dfagraph, Expression&& tag) :
__graph(dfagraph), __tag(tag) {
}
private:
DFAGraph * const __graph;
Expression __tag;
};
class VisitorAddLink : public boost::static_visitor<> {
public:
void operator()(const SymbolPacked& nodeFrom) {
if (!__graph->isConnected(__nodeTo, nodeFrom)) {
__graph->__edges.emplace_back(__nodeTo, nodeFrom);
__graph->__data.push_back(__link);
DFAGraph::EdgeId eid = __graph->__edges.size() - 1;
__graph->__outEdges.emplace(nodeFrom, eid);
}
}
void operator()(const SymbolTransient& symbolFrom) {
switch (__link) {
case DFGConnection::WEAK:
{
//virtual symbol to hold transient annotations
SymbolPacked symbPivot = __graph->createAnonymousSymbol(symbolFrom.scope);
__graph->addConnection(symbPivot, symbolFrom, DFGConnection::STRONG);
__graph->addConnection(__nodeTo, symbPivot, DFGConnection::WEAK);
break;
}
case DFGConnection::STRONG:
{
for (const Expression& tag : symbolFrom.tags) {
__graph->__tags.emplace(__nodeTo, tag);
}
break;
}
default:
assert(false && "Undefined behavior");
}
}
void operator()(const SymbolInvalid&) {
if (__link == DFGConnection::STRONG) return;
if (__link == DFGConnection::WEAK) return;
assert(false && "Undefined behavior");
}
VisitorAddLink(DFAGraph * const dfagraph, const SymbolPacked& nodeTo, DFGConnection link) :
__graph(dfagraph), __nodeTo(nodeTo), __link(link) {
}
private:
DFAGraph * const __graph;
SymbolPacked __nodeTo;
DFGConnection __link;
};
class VisitorGetDependencyConnection : public boost::static_visitor<list<SymbolPacked>>
{
public:
list<SymbolPacked>
operator()(const SymbolPacked & nodeFrom) {
return
{
nodeFrom
};
}
list<SymbolPacked>
operator()(const SymbolTransient & nodeFrom) {
return nodeFrom.dependencies;
}
list<SymbolPacked>
operator()(const SymbolInvalid&) {
assert(false && "Undefined behavior");
}
VisitorGetDependencyConnection(DFAGraph * const g) : graph(g) {
}
DFAGraph * const graph;
};
class VisitorSetDependencyConnection : public boost::static_visitor<> {
public:
void operator()(SymbolPacked& nodeTo) {
VisitorGetDependencyConnection visitorGetDepenencies(graph);
auto deps = boost::apply_visitor(visitorGetDepenencies, nodeFrom);
for (const SymbolPacked& dep : deps) {
graph->__dependencies.emplace(nodeTo, dep);
}
}
void operator()(SymbolTransient& nodeTo) {
VisitorGetDependencyConnection visitorGetDepenencies(graph);
auto deps = boost::apply_visitor(visitorGetDepenencies, nodeFrom);
for (const SymbolPacked& dep : deps) {
nodeTo.dependencies.push_back(dep);
}
}
void operator()(SymbolInvalid&) {
assert(false && "Undefined behavior");
}
VisitorSetDependencyConnection(DFAGraph * const g, SymbolNode s) : graph(g), nodeFrom(s) {
}
DFAGraph * const graph;
SymbolNode nodeFrom;
};
bool
DFAGraph::isConnected(const SymbolPacked& identifierTo, const SymbolPacked& identifierFrom) {
auto range = __outEdges.equal_range(identifierFrom);
for (std::multimap<SymbolPacked, EdgeId>::iterator edge = range.first; edge != range.second; ++edge) {
if (__edges[edge->second].second == identifierTo)
return true;
}
return false;
}
void
DFAGraph::addConnection(const SymbolPacked& nodeTo, const SymbolNode& nodeFrom, DFGConnection link) {
VisitorAddLink visitor(this, nodeTo, link);
boost::apply_visitor(visitor, nodeFrom);
}
void
DFAGraph::addDependencyConnection(SymbolNode& identifierTo, SymbolNode& identifierFrom) {
VisitorSetDependencyConnection visitor(this, identifierFrom);
boost::apply_visitor(visitor, identifierTo);
}
void
DFAGraph::addAnnotation(SymbolNode& node, Expression&& tag) {
VisitorAddTag visitor(this, move(tag));
boost::apply_visitor(visitor, node);
}
SymbolPacked
DFAGraph::createAnonymousSymbol(const ScopePacked& scope) {
return SymbolPacked(__countAnonymousSymbols++, scope, true);
}
}
}

Event Timeline