abstractpass.h
No OneTemporary

File Metadata

Created
Wed, Jul 8, 9:52 PM

abstractpass.h

/* 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>
*/
#ifndef ABSTRACTPASS_H
#define ABSTRACTPASS_H
#include "pass/ipass.h"
#include "xreatemanager.h"
#include "ast.h"
namespace xreate {
/** \brief Holds current position in the %AST during traverse*/
struct PassContext {
const CodeScope* scope = 0;
ManagedFnPtr function;
ManagedRulePtr rule;
std::string varDecl;
PassContext() {}
PassContext updateScope(const CodeScope* scopeNew) {
PassContext context2{*this};
context2.scope = scopeNew;
return context2;
}
~PassContext() {}
};
template<class Output>
Output
defaultValue();
template<>
void
defaultValue<void>();
/** \brief Stores processing results for the already visited nodes */
template<class Output>
class SymbolCache : private std::map<Symbol, Output> {
public:
bool isCached(const Symbol &symbol) {
return this->count(symbol);
}
Output setCachedValue(const Symbol &symbol, Output &&value) {
(*this)[symbol] = value;
return value;
}
Output getCachedValue(const Symbol &symbol) {
assert(this->count(symbol));
return this->at(symbol);
}
};
/** \brief Set of the already visited nodes */
template<>
class SymbolCache<void> : private std::set<Symbol> {
public:
bool isCached(const Symbol &symbol) {
bool result = this->count(symbol) > 0;
return result;
}
void setCachedValue(const Symbol &symbol) {
this->insert(symbol);
}
void getCachedValue(const Symbol &symbol) {
}
};
/** \brief Minimal \ref xreate::IPass implementation useful for many passes as the base class*/
template<class Output>
class AbstractPass : public IPass {
SymbolCache<Output> __visitedSymbols;
protected:
virtual Output processSymbol(const Symbol &symbol, PassContext context, const std::string &hintSymbol = "") {
if(__visitedSymbols.isCached(symbol))
return __visitedSymbols.getCachedValue(symbol);
const Expression &declaration = CodeScope::getDefinition(symbol, true);
if(declaration.isDefined()) {
PassContext context2 = context.updateScope(symbol.scope);
Output &&result = process(declaration, context2, hintSymbol);
return __visitedSymbols.setCachedValue(symbol, std::move(result));
}
return defaultValue<Output>();
}
Output processExpressionCall(const Expression &expression, PassContext context) {
const std::string &calleeName = expression.getValueString();
std::list<ManagedFnPtr> callees = man->root->getFnSpecializations(calleeName);
//Determined specialization
if(callees.size() == 1 && callees.front()) {
return processFnCall(callees.front(), context);
}
//Several specializations or External Fn
return processFnCallUncertain(calleeName, callees, context);
}
SymbolCache<Output> &getSymbolCache() {
return __visitedSymbols;
}
public:
AbstractPass(PassManager* manager)
: IPass(manager) {}
/** \brief Processes function invocation instruction */
virtual Output processFnCall(ManagedFnPtr functionCallee, PassContext context) {
return defaultValue<Output>();
}
/** \brief Processes function invocation instruction in uncertain cases
* \details Executed when it's impossible statically determine which exactly function is invoked.
*/
virtual Output processFnCallUncertain(const std::string& calleeName, const std::list<ManagedFnPtr>& candidates, PassContext context) {
return defaultValue<Output>();
}
/** \brief Processes Logic Rule */
virtual void process(ManagedRulePtr rule) {}
/** \brief Processes Function */
virtual Output process(ManagedFnPtr function) {
PassContext context;
context.function = function;
return process(function->getEntryScope(), context);
}
/** \brief Processes single CodeScope */
virtual Output process(CodeScope* scope, PassContext context, const std::string &hintBlockDecl = "") {
context.scope = scope;
return processSymbol(Symbol{ScopedSymbol::RetSymbol, scope}, context);
}
//TODO expose Symbol instead of varDecl. Required by DFAPass.
/** \brief Processes single Expression */
virtual Output process(const Expression &expression, PassContext context, const std::string &varDecl = "") {
if(expression.__state == Expression::IDENT) {
assert(context.scope);
return processSymbol(Attachments::get<IdentifierSymbol>(expression), context, expression.getValueString());
}
assert(false);
return defaultValue<Output>();
}
/** \brief Executes AST traverse */
void run() {
ManagedRulePtr rule = man->root->begin<MetaRuleAbstract>();
while(rule.isValid()) {
process(rule);
++rule;
}
ManagedFnPtr f = man->root->begin<Function>();
while(f.isValid()) {
process(f);
++f;
}
}
};
template<>
void
AbstractPass<void>::processSymbol(const Symbol &symbol, PassContext context, const std::string &hintSymbol);
template<>
void
AbstractPass<void>::process(const Expression &expression, PassContext context, const std::string &hintSymbol);
}
#endif

Event Timeline