utils.cpp
No OneTemporary

File Metadata

Created
Thu, Jul 9, 8:07 AM

utils.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/.
*
* aux.cpp
*
* Author: pgess <v.melnychenko@xreate.org>
*/
/**
* \file src/analysis/utils.h
* \brief Various reasoning related utilities
*/
#include "utils.h"
#include "resources.h"
#include "aux/kludges.h"
#include <boost/format.hpp>
using namespace std;
namespace xreate { namespace analysis {
typedef vector<int> InstancePacked;
std::list<Expression>
generateAllInstancesInDomain2(const ExpandedType& domainT) {
if(!domainT->isValid()) {
return {Expression()};
}
assert(domainT->__operator == TypeOperator::VARIANT);
std::list<Expression> results;
int variantId = -1;
bool flagDomainStateless = std::all_of(domainT->__operands.begin(), domainT->__operands.end(),
[](const TypeAnnotation & subdomainT) {
return !subdomainT.isValid();
});
for(const TypeAnnotation& subdomainT : domainT->__operands) {
++variantId;
if(flagDomainStateless) {
Expression result(Operator::VARIANT,{});
result.setValueDouble(variantId);
results.push_back(result);
continue;
}
std::list<Expression> subresults = generateAllInstancesInDomain2(ExpandedType(subdomainT));
for (const Expression& subresult : subresults) {
Expression result(Operator::VARIANT,{});
result.setValueDouble(variantId);
result.operands.push_back(subresult);
results.push_back(result);
}
}
return results;
}
TypeAnnotation
collapseFnGroup(const std::list<Gringo::Symbol>& symbols) {
Gringo::Symbol symbolAny = symbols.front();
size_t operandsCount = symbolAny.args().size;
TypeAnnotation resultT;
resultT.__operands.reserve(operandsCount);
for(size_t operandId = 0; operandId < operandsCount; ++operandId) {
std::list<Gringo::Symbol> column;
for(const Gringo::Symbol& row : symbols) {
column.push_back(row.args()[operandId]);
}
TypeAnnotation operandT = collapseColumn(column);
resultT.__operands.push_back(operandT);
}
if(resultT.__operands.size() == 1) {
return resultT.__operands.front();
}
if(resultT.__operands.size() > 1) {
resultT.__operator = TypeOperator::RECORD;
return resultT;
}
return resultT;
}
TypeAnnotation
collapseColumn(const std::list<Gringo::Symbol>& symbols) {
TypeAnnotation resultT;
if(!symbols.size()) return resultT;
Gringo::Symbol symbolAny = symbols.front();
switch(symbolAny.type()) {
case Gringo::SymbolType::Num:
{
return TypeAnnotation(TypePrimitive::Int);
}
case Gringo::SymbolType::Str:
{
return TypeAnnotation(TypePrimitive::String);
}
case Gringo::SymbolType::Fun:
{
map<string, list < Gringo::Symbol>> fnGroups;
for(const Gringo::Symbol& row : symbols) {
fnGroups[row.name().c_str()].push_back(row);
}
TypeAnnotation resultT;
resultT.__operands.reserve(fnGroups.size());
resultT.bindings.reserve(fnGroups.size());
for(const auto& group : fnGroups) {
if(!group.second.size()) continue;
TypeAnnotation variantT = collapseFnGroup(group.second);
Gringo::Symbol symbolAny = group.second.front();
string variantName = symbolAny.name().c_str();
resultT.fields.push_back(variantName);
resultT.__operands.push_back(variantT);
}
resultT.__operator = TypeOperator::VARIANT;
// if(resultT.__operands.size() == 1) {
// return resultT.__operands.front();
// }
return resultT;
}
case Gringo::SymbolType::Inf:
case Gringo::SymbolType::Special:
case Gringo::SymbolType::Sup:
{
break;
}
}
assert(false);
return TypeAnnotation();
}
ExpandedType
dereferenceSlaveType(ExpandedType t, const TranscendLayer* transcend) {
assert(t->__operator == TypeOperator::SLAVE);
const string& domain = t->__valueCustom;
StaticModel model = transcend->query(domain);
if(!model.size()) return ExpandedType(TypeAnnotation());
std::list<Gringo::Symbol> symbols;
for(auto row : model) {
symbols.push_back(row.second);
}
return ExpandedType(collapseFnGroup(symbols));
}
ASTSitePacked
getSite(const Expression& e, TranscendLayer* transcend){
Attachments::put<ExprId_A>(e, e);
return transcend->pack(ASTSite{e.id});
}
Expression
recognizeSite(const Gringo::Symbol& atom, const ExpandedType& schemaT, TranscendLayer* transcend)
{
if(atom.type()!=Gringo::SymbolType::Fun) return Expression();
string predicateName = atom.name().c_str();
if (predicateName != SITE_SYMBOL_PREDICATE && predicateName != SITE_ANON_PREDICATE)
return Expression();
const ASTSitePacked& siteP = TranscendLayer::parseAtom<ASTSitePacked>(atom);
const ASTSite& site = transcend->unpack(siteP);
return site.getDefinition();
}
Expression
representTransExpression(const Gringo::Symbol& atom, ExpandedType schemaT, TranscendLayer* transcend) {
const Expression siteExpr = recognizeSite(atom, schemaT, transcend);
if (siteExpr.isValid()) return siteExpr;
switch(schemaT->__operator) {
case TypeOperator::NONE:
{
switch(schemaT->__value) {
case TypePrimitive::I8:
case TypePrimitive::I32:
case TypePrimitive::I64:
case TypePrimitive::Int:
{
return Expression(Atom<Number_t>(atom.num()));
}
case TypePrimitive::String:
{
return Expression(Atom<String_t>(atom.string().c_str()));
}
case TypePrimitive::Invalid:
case TypePrimitive::Bool:
case TypePrimitive::Float:
{
assert(false);
return Expression();
}
}
break;
}
case TypeOperator::SLAVE:
{
ExpandedType contentT = dereferenceSlaveType(schemaT, transcend);
return representTransExpression(atom, contentT, transcend);
}
case TypeOperator::VARIANT:
{
map<string, int> dictVariants;
for(size_t variantId = 0; variantId < schemaT->fields.size(); ++variantId) {
dictVariants.emplace(schemaT->fields.at(variantId), variantId);
}
string predicateName = atom.name().c_str();
assert(dictVariants.count(predicateName));
size_t predicateId = dictVariants.at(predicateName);
Expression result(Operator::VARIANT,{});
result.op = Operator::VARIANT;
result.setValueDouble(predicateId);
if(!schemaT->__operands.size()) return result;
ExpandedType schemeOperands = schemaT->__operands.at(predicateId).__operator == TypeOperator::SLAVE
? dereferenceSlaveType(ExpandedType(schemaT->__operands.at(predicateId)), transcend)
: ExpandedType(schemaT->__operands.at(predicateId));
if (schemeOperands->__operator == TypeOperator::RECORD){
Expression operandsList = representTransExpression(atom, schemeOperands, transcend);
result.operands = move(operandsList.operands);
} else if(!schemeOperands->isValid()) {
assert(atom.args().size == 0);
return result;
} else {
assert(false);
}
return result;
}
case TypeOperator::RECORD:
{
const Gringo::SymSpan& operandsRaw = atom.args();
size_t opCount = operandsRaw.size;
assert(opCount == schemaT->__operands.size());
size_t operandId = 0;
std::vector<Expression> operands;
operands.reserve(opCount);
for(const TypeAnnotation operandT : schemaT->__operands) {
operands.push_back(representTransExpression(operandsRaw[operandId], ExpandedType(operandT), transcend));
++operandId;
}
Expression result(Operator::LIST,{});
result.operands = operands;
result.type = schemaT.get();
return result;
}
case TypeOperator::ARRAY:
case TypeOperator::ALIAS:
case TypeOperator::ACCESS:
case TypeOperator::REF:
case TypeOperator::VOID:
case TypeOperator::GUARD:
{
assert(false);
return Expression();
}
}
assert(false);
return Expression();
}
Expression
representVecStr(const std::vector<std::string>& srcList){
Expression dstE(Operator::LIST, {});
for(const string op: srcList){
dstE.operands.push_back(Atom<String_t>(string(op)));
}
return dstE;
}
Expression
findAnnById(unsigned annId, const ExpandedType& annT, const std::list<Expression>& annotations){
assert(annT->fields.size() > annId);
const string& annExpectedS = annT->fields.at(annId);
for(const Expression& e: annotations){
if (e.type.fields.size() <= annId) continue;
const string& annTestS = e.type.fields.at(annId);
if (annTestS == annExpectedS) return e;
}
return Expression();
}
Expression
findAnnByType(const Expression &expr, const ExpandedType &annExpectedT, AST *ast){
std::list<Expression> tagsL = kludges::getAnnotations(expr);
for (const Expression& annActualE: tagsL){
if (isSameVariantType(ast->expandType(annActualE.type), annExpectedT)){
return annActualE;
}
}
return Expression();
}
bool
isSameVariantType(const ExpandedType& a, const ExpandedType& b){
assert(a->__operator == TypeOperator::VARIANT);
assert(b->__operator == TypeOperator::VARIANT);
if (a->fields.size()!= b->fields.size()) return false;
for (size_t idx = 0; idx < a->fields.size(); ++idx){
if (a->fields.at(idx) != b->fields.at(idx)) return false;
}
return true;
}
}} //end of xreate::analysis

Event Timeline