temporalseqgraph.cpp
No OneTemporary

File Metadata

Created
Thu, Jul 9, 2:34 AM

temporalseqgraph.cpp

/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* File: temporalseqgraph.cpp
* Author: pgess
*
* Created on February 4, 2019, 4:51 PM
*/
#include "temporalseqgraph.h"
using namespace xreate::cfa;
using namespace std;
namespace std {
bool operator<(const xreate::cfa::TemporalNode& x, const xreate::cfa::TemporalNode& y) {
if(x.scope != y.scope) return x.scope < y.scope;
return x.mark < y.mark;
}
};
TemporalSeqGraph::TemporalSeqGraph(TranscendLayer* transcend)
: __transcend(transcend) { }
void
TemporalSeqGraph::addSubScopes(const CodeScope* scopeIn, const std::list<CodeScope*>& scopesChild) {
auto socket = addSocket(scopeIn, TemporalOperator::AND);
for(auto scopeChild : scopesChild) {
TemporalNode nodeChild = TemporalNode{__transcend->pack(scopeChild), TemporalOperator::SCOPE};
connect(socket.first, nodeChild);
connect(nodeChild, socket.second);
}
}
void
TemporalSeqGraph::addBranchScopes(const CodeScope* scopeIn, const std::list<CodeScope*>& scopesChild) {
auto socket = addSocket(scopeIn, TemporalOperator::AND);
TemporalNode toNode{__idNextVacant++, TemporalOperator::OR};
connect(toNode, socket.second);
for(auto scopeChild : scopesChild) {
TemporalNode nodeChild = TemporalNode{__transcend->pack(scopeChild), TemporalOperator::SCOPE};
connect(socket.first, nodeChild);
connect(nodeChild, toNode);
}
}
std::pair<TemporalNode, TemporalNode>
TemporalSeqGraph::addSocket(const CodeScope* scopeIn, TemporalOperator mark) {
TemporalNode nodeFrom;
TemporalNode nodeIn = TemporalNode{__transcend->pack(scopeIn), TemporalOperator::SCOPE};
auto rangeInward = graph.right.equal_range(nodeIn);
size_t sizeInward = std::distance(rangeInward.first, rangeInward.second);
if (sizeInward == 1) {
//if scope has single inward connection
nodeFrom = rangeInward.first->second;
} else if (sizeInward > 1) {
//if scope has multy inward con:
nodeFrom = insertBefore(nodeIn, EMPTY);
} else {
//no inward connections:
nodeFrom = insertBefore(nodeIn, EMPTY);
}
TemporalNode nodeTo = insertAfter(nodeIn, mark);
return {nodeFrom, nodeTo};
}
Socket
TemporalSeqGraph::getFnSocket(ManagedFnPtr calleeFn) {
if(__cacheFnSockets.count(calleeFn)) {
return __cacheFnSockets.at(calleeFn);
}
TemporalNode fromNode{__idNextVacant++, TemporalOperator::EMPTY};
TemporalNode toNode{__idNextVacant++, TemporalOperator::EMPTY};
Socket fnSock = make_pair(fromNode, toNode);
__cacheFnSockets.emplace(calleeFn, fnSock);
return fnSock;
}
Socket
TemporalSeqGraph::getUncertainFnSocket(const std::string& calleeName, const std::list<ManagedFnPtr>& candidates) {
if(__cacheUncertainFnSockets.count(calleeName)) {
return __cacheUncertainFnSockets.at(calleeName);
}
Socket fnSock;
if(candidates.size() == 0) {
//External Function
TemporalNode node{__idNextVacant++, TemporalOperator::EMPTY};
fnSock = make_pair(node, node);
} else {
//Multiple specializations
TemporalNode fromNode{__idNextVacant++, TemporalOperator::EMPTY};
TemporalNode toNode{__idNextVacant++, TemporalOperator::OR};
fnSock = make_pair(fromNode, toNode);
for (const ManagedFnPtr& candidate : candidates) {
Socket candidateSock = getFnSocket(candidate);
connect(fromNode, candidateSock.first);
connect(candidateSock.second, toNode);
}
}
__cacheUncertainFnSockets.emplace(calleeName, fnSock);
return fnSock;
}
TemporalNode
TemporalSeqGraph::insertBefore(TemporalNode node, TemporalOperator mark) {
TemporalNode nodeNew{__idNextVacant++, mark};
auto nodesInRange = graph.right.equal_range(node);
list<TemporalNode> nodesIn;
for(auto nodeInIt = nodesInRange.first; nodeInIt != nodesInRange.second; ++nodeInIt) {
nodesIn.push_back(nodeInIt->second);
}
graph.right.erase(node);
for(auto nodeIn : nodesIn) {
connect(nodeIn, nodeNew);
}
connect(nodeNew, node);
return nodeNew;
}
TemporalNode
TemporalSeqGraph::insertAfter(TemporalNode node, TemporalOperator mark) {
TemporalNode nodeNew{__idNextVacant++, mark};
auto nodesOutRange = graph.left.equal_range(node);
list<TemporalNode> nodesOut;
for(auto nodeOutIt = nodesOutRange.first; nodeOutIt != nodesOutRange.second; ++nodeOutIt) {
nodesOut.push_back(nodeOutIt->second);
}
graph.left.erase(node);
for(auto nodeOut : nodesOut) {
connect(nodeNew, nodeOut);
}
connect(node, nodeNew);
return nodeNew;
}
void
TemporalSeqGraph::connect(TemporalNode nodeFrom, TemporalNode nodeTo) {
graph.insert(Graph::value_type(nodeFrom, nodeTo));
}
void
TemporalSeqGraph::connectGuarded(const Socket& from, const Socket& to) {
unsigned int guard = __guardNextVacant++;
graphGuarded.emplace(from.first, make_pair(to.first, TemporalGuard{TemporalGuard::IN, guard}));
graphGuarded.emplace(to.second, make_pair(from.second, TemporalGuard{TemporalGuard::OUT, guard}));
}
void
TemporalSeqGraph::print(std::ostringstream &output) const {
for (auto entry : graph) {
output
<< "cfa_seq("
<< entry.left << ", "
<< entry.right << ").\n";
}
for (auto entry : graphGuarded) {
output
<< "cfa_seq_guarded("
<< entry.first << ", "
<< entry.second.first << ", "
<< (entry.second.second.mark == TemporalGuard::IN ? "in(" : "out(")
<< entry.second.second.id << ")).\n";
}
}
bool TemporalSeqGraph::isOrdered(const ScopePacked& scopeAfter, const ScopePacked& scopeBefore) const {
set<TemporalNode> visitedNodes;
return isOrdered(TemporalNode{scopeAfter, TemporalOperator::SCOPE},
TemporalNode{scopeBefore, TemporalOperator::SCOPE},
visitedNodes);
}
bool
TemporalSeqGraph::isOrdered(const TemporalNode& nodeAfter, const TemporalNode& nodeBefore, set<TemporalNode>& visitedNodes) const {
if (nodeAfter.scope == nodeBefore.scope && nodeAfter.mark == nodeBefore.mark) return true;
if (visitedNodes.count(nodeAfter)) return false;
visitedNodes.insert(nodeAfter);
auto frontierList = graph.right.equal_range(nodeAfter);
for(auto frontierIt = frontierList.first; frontierIt != frontierList.second; ++frontierIt) {
if(isOrdered(frontierIt->second, nodeBefore, visitedNodes)) return true;
}
return false;
}
namespace xreate {
namespace cfa {
static string dictNodes[] = {"scope", "empty", "and", "or"};
std::ostream&
operator << (std::ostream& output, const TemporalNode& node) {
string op = dictNodes[node.mark];
output << op << "(" << node.scope << ")";
return output;
}
}}

Event Timeline