Page Menu
Home
Xreate
Search
Configure Global Search
Log In
Docs
Questions
Repository
Issues
Patches
Internal API
Files
F3997591
abstractpass.h
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Subscribers
None
File Metadata
Details
File Info
Storage
Attached
Created
Wed, Jul 8, 9:52 PM
Size
5 KB
Mime Type
text/x-c++
Expires
Fri, Jul 10, 9:52 PM (1 d, 10 h)
Engine
blob
Format
Raw Data
Handle
272648
Attached To
rXR Xreate
abstractpass.h
View Options
/* 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
Log In to Comment