dfapass.cpp
No OneTemporary

File Metadata

Created
Fri, Mar 13, 2:04 AM

dfapass.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/.
*
* Author: pgess <v.melnychenko@xreate.org>
*
* dfapass.cpp
*/
/**
* \file dfapass.h
* \brief Data Flow Analysis(DFA)
*/
//DEBT DFA represent VersionaPass in declarative form using applyDependencies
// applyDependencies(expression, context, cache, decl);
//DEBT DFA prepare static annotations and represent InterpretationPass in declarative form
// applyStaticAnnotations(expression, context, cache, decl);
//DEBT DFA Eliminate dfa schemes
#include "pass/dfapass.h"
#include "xreatemanager.h"
#include "clasplayer.h"
#include <boost/format.hpp>
#include <boost/variant/variant.hpp>
using namespace std;
namespace xreate { namespace dfa {
DFAPass::DFAPass(PassManager* manager)
: AbstractPass(manager)
, graph{new DFAGraph()}
, clasp(manager->clasp)
{}
void
DFAPass::processCallInstance(const Expression& expr, PassContext context, const SymbolNode& result){
const string &nameCalleeFunction = expr.getValueString();
//TODO implement processFnCall/Uncertain
list<ManagedFnPtr> variantsCalleeFunction = man->root->getFunctionSpecializations(nameCalleeFunction);
vector<SymbolNode> operands;
operands.reserve(expr.getOperands().size());
for (const Expression& arg: expr.getOperands()){
operands.push_back(process(arg, context));
}
graph->markSymbolsAsUsed(operands);
graph->markSymbolsAsUsed(std::vector<SymbolNode>{result});
//Set calling relations:
for (ManagedFnPtr function: variantsCalleeFunction){
CodeScope *scopeRemote = function->getEntryScope();
DFACallInstance callInstance;
callInstance.id = expr.id;
callInstance.fnName = function->getName();
std::vector<SymbolNode>::const_iterator nodeActual = operands.begin();
for (const std::string &identFormal: scopeRemote->__bindings){
const ScopedSymbol symbolFormal{scopeRemote->__identifiers.at(identFormal), versions::VERSION_NONE};
SymbolPacked symbolFormalPacked = clasp->pack(Symbol{symbolFormal, scopeRemote});
callInstance.args.push_back(std::make_pair(symbolFormalPacked, *nodeActual));
graph->addDependency(symbolFormalPacked, *nodeActual);
++nodeActual;
}
callInstance.retActual = result;
SymbolNode retFormal = SymbolNode(clasp->pack(Symbol{ScopedSymbol::RetSymbol, scopeRemote}));
graph->addDependency(result, retFormal);
graph->addCallInstance(std::move(callInstance));
}
}
void
DFAPass::processDependencies(const SymbolNode& node, const Expression& expression, PassContext context, ProcessingCache& cache){
cache.operands.reserve(expression.getOperands().size());
for (const Expression &op: expression.getOperands()) {
const SymbolNode& subnodeOperand = process(op, context);
cache.operands.push_back(subnodeOperand);
graph->addDependency(node, subnodeOperand);
}
cache.blocks.reserve(expression.blocks.size());
for (CodeScope* block : expression.blocks) {
const SymbolNode& subnodeBlock = process(block, context);
cache.blocks.push_back(subnodeBlock);
graph->addDependency(node, subnodeBlock);
}
}
SymbolNode
DFAPass::process(const Expression& expression, PassContext context, const std::string& varDecl)
{
SymbolNode result;
if (Attachments::exists<SymbolAlias>(expression))
{
Symbol varSymbol = Attachments::get<SymbolAlias>(expression);
result = clasp->pack(varSymbol, varDecl);
} else if (expression.__state == Expression::IDENT && expression.tags.size() == 0) {
Symbol varSymbol = Attachments::get<IdentifierSymbol>(expression);
result = clasp->pack(varSymbol, expression.getValueString());
} else {
result = SymbolAnonymous{expression.id};
}
graph->printInplaceAnnotations(result, expression);
switch(expression.__state){
case Expression::COMPOUND: {
switch (expression.op) {
case Operator::CALL:
processCallInstance(expression, context, result);
break;
default:
ProcessingCache cache;
processDependencies(result, expression, context, cache);
break;
}
break;
}
case Expression::IDENT: {
SymbolNode symbIdent = AbstractPass<SymbolNode>::process(expression, context, varDecl);
if (!(result == symbIdent)) {
graph->addDependency(result, symbIdent);
graph->printAlias(result, symbIdent);
}
break;
}
case Expression::NUMBER:
case Expression::STRING: {
break;
}
case Expression::INVALID:
case Expression::BINDING: {
assert(false);
break;
}
}
return result;
}
SymbolNode
DFAPass::process(CodeScope* scope, PassContext context, const std::string& hintBlockDecl){
for(const std::string& binding: scope->__bindings){
Symbol bindingSymbol{scope->getSymbol(binding), scope};
SymbolPacked bindingPacked = clasp->pack(bindingSymbol, binding);
getSymbolCache().setCachedValue(bindingSymbol, SymbolNode(bindingPacked));
}
return AbstractPass<SymbolNode>::process(scope, context, hintBlockDecl);
}
SymbolNode
DFAPass::process(ManagedFnPtr function){
SymbolNode result = AbstractPass<SymbolNode>::process(function);
graph->printFunctionRet(function, result);
return result;
}
void
DFAPass::finish(){
clasp->registerReport(graph);
//Declare symbols:
graph->printSymbols(clasp);
AbstractPass::finish();
}
} //end of namespace dfa
template<>
dfa::SymbolNode defaultValue(){
assert(false);
}
} //xreate namespace
/**
* \class xreate::dfa::DFAPass
* \details Provides DFA, important analysis for reasoning. Iterates over AST and stores collected data in DFAGraph
*/

Event Timeline