transcendtarget.cpp
No OneTemporary

File Metadata

Created
Wed, Jul 8, 1:15 PM

transcendtarget.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>
* Created on: Jan, 2020
*/
#include "transcendtarget.h"
#include "analysis/utils.h"
#include "analysis/resources.h"
#include <boost/format.hpp>
#include <boost/algorithm/string/join.hpp>
using namespace std;
namespace xreate{
void
TranscendPass::process(ManagedFnPtr function){
boost::format formatFn(analysis::FUNCTION_PREDICATE_TPL);
boost::format formatFnAnn(analysis::FUNCTION_ANN_PREDICATE_TPL);
__output << endl << analysis::TRANSCEND_PASS_SECTION << endl;
__output << formatFn
% (function->getName())
<< "." << std::endl;
for(const auto &tagRec: function->getTags()){
const Expression &tag = tagRec.second;
TranscendScope* scopeTr = getRootScope();
list<string> definitions;
const string& partTagRaw = scopeTr->compile(tag, definitions);
TranscendScope::rule(__output,
boost::str(formatFnAnn
% (function->getName())
% (partTagRaw)),
definitions);
__output << endl;
}
return Parent::process(function);
}
void
TranscendPass::process(CodeScope* scope, PassContext context, const std::string &hintBlockDecl) {
TranscendLayer* transcend = man->transcend;
boost::format formatScopeAnn(analysis::SCOPE_ANN_PREDICATE_TPL);
ScopePacked scopeId = transcend->pack(scope);
TranscendScope* scopeTr = getScope(scope);
for (const auto& tag : scope->tags){
list<string> definitions;
const string& partTagRaw = scopeTr->compile(tag, definitions);
TranscendScope::rule(__output,
boost::str(formatScopeAnn
% scopeId
% (partTagRaw)),
definitions);
__output << endl;
}
return Parent::process(scope, context, hintBlockDecl);
}
void
TranscendPass::process(const Expression &expression, PassContext context, const std::string &varDecl){
boost::format formatVarAnn(analysis::VAR_ANN_PREDICATE_TPL);
TranscendLayer* transcend = man->transcend;
TranscendScope* scopeTr = getScope(context.scope);
for (const auto& tag: expression.tags){
list<string> body;
const string& head = scopeTr->compile(tag.second, body);
TranscendScope::rule(__output,
boost::str(formatVarAnn
% Parent::man->transcend->pack(ASTSite{expression.id}).str()
% head), body);
}
return Parent::process(expression, context, varDecl);
}
TranscendScope*
TranscendPass::getScope(const CodeScope * const scope){
if(__scopes.count(scope)){
return __scopes.at(scope);
}
TranscendScope* unit(new TranscendScope(scope, this));
__scopes[scope] = unit;
return unit;
}
void
TranscendPass::finish(){
Parent::man->transcend->addRawScript(__output.str());
}
std::string
TranscendScope::compile(const Expression &e, std::list<std::string>& definitions){
switch(e.__state){
case Expression::COMPOUND: {
switch (e.op){
case Operator::VARIANT: {
const string& predicate = escapePredicate(string(e.getValueString()));
if(!e.operands.size()){
return predicate;
}
list<string> operands;
std::transform(e.operands.begin(), e.operands.end(), std::inserter(operands, operands.begin()),
[this, &definitions](const Expression &e) {
return this->compile(e, definitions);
});
return boost::str(
boost::format("%1%(%2%)")
% predicate
% boost::algorithm::join(operands, ", "));
}
default: {
return analysis::getSite(e, __pass->man->transcend).str();
}
}
}
case Expression::NUMBER: {
return to_string((unsigned int)e.getValueDouble());
break;
}
case Expression::STRING: {
return boost::str(boost::format("\"%1%\"") % e.getValueString());
}
case Expression::IDENT: {
Symbol s = Attachments::get<IdentifierSymbol>(e);
const string& identSafe = escapeVar(string(e.getValueString()));
const Expression& symbDefinition = CodeScope::getDefinition(s);
definitions.push_back(boost::str(boost::format("%1% = %2%")
% identSafe
% compile(symbDefinition, definitions)
));
return identSafe;
}
case Expression::INVALID: case Expression::BINDING: assert(false);
}
assert(false);
return "";
}
std::string
TranscendScope::escapeVar(std::string&& var){
assert(var.size());
var[0] = std::toupper(var[0]);
return var;
}
std::string
TranscendScope::escapePredicate(std::string&& pred){
assert(pred.size());
pred[0] = std::tolower(pred[0]);
return pred;
}
void
TranscendScope::rule(std::ostringstream& output, const std::string& head, const std::list<std::string>& body){
output << head;
const string& partBody = boost::join(body, ";");
if (!partBody.empty()){
output << " :- " << partBody;
}
output << ".";
}
}

Event Timeline