dfgpass.cpp
No OneTemporary

File Metadata

Created
Thu, Jul 9, 12:29 AM

dfgpass.cpp

#include "dfgpass.h"
#include "passmanager.h"
#include "clasplayer.h"
#include <boost/format.hpp>
using namespace std;
namespace xreate{
DFGPass::DFGPass(PassManager* manager)
: AbstractPass(manager), clasp(man->clasp)
{}
SymbolNode
DFGPass::process(CodeScope* scope, PassContext context, const std::string& hintBlockDecl){
/*
if (SymbolTransient* symbT = boost::get<SymbolTransient>(&symbolRet)){
std::vector<Tag> tags;
tags.reserve(symbT->tags.size());
const std::string stmntRetTag = Config::get("clasp.ret.tag");
std::transform(symbT->tags.begin(), symbT->tags.end(), std::inserter(tags, tags.begin()),
[&stmntRetTag](const Expression& e) {
Expression tag(Operator::CALL, {Atom<Identifier_t>(string(stmntRetTag)), e});
return Tag{e, TagModifier::NONE};
});
clasp->cfagraph.addFunctionAnnotations(function->getName(), tags);
}
*/
const SymbolNode& retActual = AbstractPass::process(scope, context, hintBlockDecl);
const SymbolPacked& retFormal{0, clasp->pack(scope)};
__context.graph.addConnection(retFormal, retActual, DFGConnection::ALIAS);
return retFormal;
}
SymbolNode
DFGPass::process(const Expression& expression, PassContext context, const std::string& decl)
{
// write down adhoc expression tags:
if (expression.tags.size() && decl.length()) {
for (pair<std::string, Expression> tag: expression.tags) {
SymbolNode nodeThis = clasp->pack(context.scope->findSymbol(decl), context.function->getName() + ":" + decl);
__context.graph.addAnnotation(nodeThis, Expression(tag.second));
}
}
switch(expression.__state) {
case Expression::IDENT: {
const string& ident = expression.getValueString();
SymbolNode nodeFrom = AbstractPass::process(expression, context, decl);
SymbolPacked nodeTo = clasp->pack(context.scope->findSymbol(ident), context.function->getName() + ":" + ident);
__context.graph.addConnection(nodeTo, nodeFrom, DFGConnection::ALIAS);
return nodeTo;
}
default: break;
}
//TODO Null ad hoc DFG implementation
// if (expression.isNone()){
// return SymbolTransient{{Atom<Identifier_t>(Config::get("clasp.nonevalue"))}};
// }
switch(expression.op) {
case Operator::CALL: {
const string &name = expression.getValueString();
std::vector<SymbolNode> operands;
operands.reserve(expression.getOperands().size());
for (const Expression &op: expression.getOperands()) {
operands.push_back(process(op, context));
}
//TODO implement processFnCall/Uncertain
list<ManagedFnPtr> functions = man->root->getFunctionVariants(name);
if (functions.size()!=1) return SymbolInvalid();
ManagedFnPtr function= functions.front();
// set calling relations:
CodeScope *scopeRemote = function->getEntryScope();
std::vector<SymbolNode>::iterator nodeActual = operands.begin();
for (const std::string &identFormal: scopeRemote->__args) {
const Symbol &symbolFormal = scopeRemote->findSymbol(identFormal);
__context.graph.addConnection(clasp->pack(symbolFormal, name + ":" + identFormal), *nodeActual, DFGConnection::OPT);
++nodeActual;
}
//TODO need SymbolTransient::connection mark in order to represent OPT connection
return clasp->pack(Symbol{0, scopeRemote}, name + ": *retv");
}
default: break;
}
SymbolNode result = AbstractPass::process(expression, context, decl);
if (expression.__state != Expression::COMPOUND){
return result;
}
std::vector<SymbolNode> operands;
if (__signatures.count(expression.op)) {
const Expression &scheme = __signatures.at(expression.op);
operands.reserve(expression.getOperands().size());
if (expression.op == Operator::CALL || expression.op == Operator::INDEX){
string caption = expression.getValueString();
operands.push_back(process(Expression(move(caption)), context, ""));
}
for (const Expression &op: expression.getOperands()) {
operands.push_back(process(op, context));
}
std::vector<SymbolNode>::iterator arg = operands.begin();
std::vector<Expression>::const_iterator tag = ++scheme.getOperands().begin();
while (tag != scheme.getOperands().end()) {
if (tag->__state != Expression::INVALID) {
__context.graph.addAnnotation(*arg, Expression(*tag));
}
++arg; ++tag;
}
Expression retTag = *scheme.getOperands().begin();
if (retTag.__state != Expression::INVALID) {
__context.graph.addAnnotation(result, move(retTag));
}
}
// adhoc for MAP case, TODO reorganize code in more clear manner
if (expression.op == Operator::MAP) {
SymbolNode nodeFrom;
if (operands.size()) {
nodeFrom = operands.at(0);
} else {
nodeFrom = process(expression.getOperands().at(0), context);
}
assert(!decl.empty());
SymbolPacked nodeTo = clasp->pack(context.scope->findSymbol(decl), context.function->getName() + ":" + decl);
SymbolPacked* nodeFromPacked = boost::get<SymbolPacked>(&nodeFrom);
assert(nodeFromPacked);
__context.graph.addConnection(move(nodeTo), *nodeFromPacked, DFGConnection::PROTO);
}
return result;
}
void
DFGPass::run()
{
init();
return AbstractPass::run();
}
void
DFGPass::init()
{
for (const Expression& scheme: man->root->__dfadata)
{
__signatures.emplace(scheme.op, scheme);
}
}
void DFGPass::finish()
{
man->clasp->addDFAData(move(__context.graph));
}
template<>
SymbolNode defaultValue(){return SymbolInvalid();};
}

Event Timeline