dfagraph.cpp
No OneTemporary

File Metadata

Created
Thu, Jul 9, 4:42 AM

dfagraph.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: DFAGraph.h
* Author: pgess <v.melnychenko@xreate.org>
*
*/
/**
* \file dfagraph.h
* \brief Data Flow Analysis(DFA) graph data
*
*/
#include "analysis/dfagraph.h"
#include "analysis/aux.h"
#include <list>
using namespace std;
namespace xreate {namespace dfa {
struct VisitorNodeHash : public boost::static_visitor<size_t>
{
std::size_t operator()(const xreate::SymbolPacked& node) const noexcept
{
return 2* (node.identifier + 2 * node.scope + 3 * std::abs(node.version)) + 1;
}
std::size_t operator()(const xreate::dfa::SymbolAnonymous& node) const noexcept
{
return 2 * node.id;
}
};
}}
std::size_t
hash<xreate::dfa::SymbolNode>::operator()(xreate::dfa::SymbolNode const& s) const noexcept
{
return boost::apply_visitor(xreate::dfa::VisitorNodeHash(), s);
}
namespace xreate { namespace dfa {
bool operator==(const SymbolAnonymous& s1, const SymbolAnonymous& s2){
return s1.id == s2.id && s1.flagIsUsed == s2.flagIsUsed;
}
class VisitorFormatSymbol: public boost::static_visitor<boost::format> {
public:
boost::format operator()(const SymbolPacked& node) const {
//boost::format formatSymbNamed("s(%1%, %2%, %3%)");
boost::format formatSymbNamed("s%1%%2%");
return formatSymbNamed % node.identifier /*% node.version*/ % node.scope ;
}
boost::format operator()(const SymbolAnonymous& node) const {
//boost::format formatSymbAnonymous("anon(%1%)");
boost::format formatSymbAnonymous("a%1%");
return formatSymbAnonymous % node.id;
}
};
void
DFACallInstance::print(std::ostringstream& output) const{
boost::format formatInstance("dfa_callinstance(%1%, %2%).");
boost::format formatArgs("dfa_callargs(%1%, %2%, %3%).");
boost::format formatRet("dfa_callret(%1%, %2%).");
output << formatInstance
% id % fnName
<< endl;
for(std::pair<SymbolPacked, SymbolNode> rec: args) {
SymbolNode argFormal(rec.first);
output << formatArgs
% id
% boost::apply_visitor(VisitorFormatSymbol(), argFormal)
% boost::apply_visitor(VisitorFormatSymbol(), rec.second)
<< endl;
}
output << formatRet
% id
% boost::apply_visitor(VisitorFormatSymbol(), retActual)
<< endl;
}
void
DFAGraph::addDependency(const SymbolNode& node, const SymbolNode& subnode){
__dependencies.emplace(node, subnode);
}
void
DFAGraph::printDependencies(std::ostringstream& output) const{
for(const SymbolNode& root: __roots){
printDependency(output, root, root);
}
}
void
DFAGraph::printDependency(std::ostringstream& output, const SymbolNode& nodeCurrent, const SymbolNode& nodeDependent) const {
auto range = __dependencies.equal_range(nodeCurrent);
for (auto it = range.first; it != range.second; ++it){
if (const SymbolAnonymous* symbAnon = boost::get<SymbolAnonymous>(&it->second)){
if (!__usedAnonymousSymbols.count(symbAnon->id)){
printDependency(output, it->second, nodeDependent);
continue;
}
}
boost::format formatDependency("dfa_depends(%1%, %2%).");
output << formatDependency
% boost::apply_visitor(VisitorFormatSymbol(), nodeDependent)
% boost::apply_visitor(VisitorFormatSymbol(), it->second)
<< endl;
printDependency(output, it->second, it->second);
}
}
void
DFAGraph::printInplaceAnnotations(SymbolNode node, const Expression& expression) {
// write down in-place expression tags:
boost::format formatBind("bind(%1%, %2%).");
if (expression.tags.size())
if (boost::get<SymbolAnonymous>(&node)){
markSymbolsAsUsed(vector<SymbolNode>({node}));
}
for (const pair<std::string, Expression>& tag : expression.tags) {
for (const string& tagPart: xreate::analysis::compile(tag.second)) {
__output << formatBind
% boost::apply_visitor(VisitorFormatSymbol(), node)
% tagPart
<< endl;
}
}
}
void
DFAGraph::printAlias(const SymbolNode& symbolFormal, const SymbolNode& symbActual){
boost::format formatAlias("dfa_alias(%1%, %2%).");
__output << formatAlias
% boost::apply_visitor(VisitorFormatSymbol(), symbolFormal)
% boost::apply_visitor(VisitorFormatSymbol(), symbActual)
<< endl;
}
void
DFAGraph::printFunctionRet(ManagedFnPtr function, const SymbolNode& symbolRet){
boost::format formatRet("dfa_fnret(%1%, %2%).");
__output << formatRet
% function->getName()
% boost::apply_visitor(VisitorFormatSymbol(), symbolRet)
<< endl;
__roots.insert(symbolRet);
}
void
DFAGraph::addCallInstance(DFACallInstance&& instance){
__callInstances.push_back(std::move(instance));
}
void
DFAGraph::print(std::ostringstream& output) const{
output << endl << "%\t\tStatic analysis: DFA" << endl;
//Dependencies
printDependencies(output);
//Add generated report
output << __output.str() << endl;
//Call instances
for(const DFACallInstance& instance: __callInstances){
instance.print(output);
}
output << endl;
}
void
DFAGraph::markSymbolsAsUsed(const std::vector<SymbolNode>& usedNodes){
for (const SymbolNode& node: usedNodes){
if (const SymbolAnonymous* symbol = boost::get<SymbolAnonymous>(&node)){
__usedAnonymousSymbols.insert(symbol->id);
}
}
}
bool
DFAGraph::isSymbolUsed(const SymbolNode& node) const{
if (const SymbolAnonymous* symbol = boost::get<SymbolAnonymous>(&node)){
if (!__usedAnonymousSymbols.count(symbol->id)) {return false;}
}
return true;
}
void
DFAGraph::printSymbols(ClaspLayer* clasp){
std::unordered_set<SymbolNode> symbols;
for (auto entry: __dependencies){
if (isSymbolUsed(entry.first)) {symbols.insert(entry.first);}
if (isSymbolUsed(entry.second)) {symbols.insert(entry.second);}
}
for (const SymbolNode& node : symbols) {
__output << "v(" << boost::apply_visitor(VisitorFormatSymbol(), node) << ").";
if (const SymbolPacked* symbol = boost::get<SymbolPacked>(&node)){
__output << " %" << clasp->getHintForPackedSymbol(*symbol);
}
__output << endl;
}
}
}} //end of namespace xreate::dfa

Event Timeline