modules.cpp
No OneTemporary

File Metadata

Created
Sat, Mar 14, 2:35 AM

modules.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/.
*
* modules.cpp
*
* Author: pgess <v.melnychenko@xreate.org>
* Created on July 22, 2017, 5:13 PM
*/
/**
* \file modules.h
* \brief Modules support
*/
#include "modules.h"
#include "modules/Parser.h"
#include "analysis/utils.h"
#include <clingo/clingocontrol.hh>
#include <boost/format.hpp>
#include <regex>
#include <boost/filesystem.hpp>
#include <fstream>
namespace fs = boost::filesystem;
namespace xreate { namespace modules{
void
ModuleRecord::addModuleQuery(const Expression& query){
__queries.push_back(query);
}
void
ModuleRecord::addControllerPath(const std::string& path){
__controllers.push_back(path);
}
void
ModuleRecord::addDiscoveryPath(const std::string& path){
__discoveries.push_back(path);
}
void
ModuleRecord::addProperty(const Expression& prop){
__properties.push_back(prop);
}
void
ModulesSolver::loadControllers(const ModuleRecord& module){
for (const std::string& pathController: module.__controllers){
std::fstream fileContent(pathController);
__program << fileContent.rdbuf();
}
}
void
ModulesSolver::extractProperties(const ModuleRecord& module){
unsigned int moduleId = __registry->getModuleHash(module.__path);
const std::string atomProperty = "bind_module";
boost::format formatProperty(atomProperty + "(%1%, %2%).");
for (const Expression& property: module.__properties){
std::list<std::string> reprProp = xreate::analysis::compile(property);
assert(reprProp.size()== 1);
__program << (formatProperty % moduleId % reprProp.front())
<< std::endl;
}
}
void
ModulesSolver::discoverModules(const ModuleRecord& moduleClient){
std::regex extXreate("\\.xreate$", std::regex::basic);
for(const std::string& path: moduleClient.__discoveries){
for(fs::directory_entry e: fs::recursive_directory_iterator(path)) {
if (fs::is_regular_file(e.status())){
if (!std::regex_search(e.path().string(), extXreate)) continue;
FILE* script = fopen(e.path().c_str(), "r");
Scanner scanner(script);
Parser parser(&scanner);
parser.Parse();
assert(!parser.errors->count && "Discovery errors");
parser.module.__path = e.path().c_str();
extractProperties(parser.module);
fclose(script);
}
}
}
}
void
ModulesSolver::extractRequirements(const ModuleRecord& module){
const std::string atomQuery = "module_require";
boost::format formatProperty(atomQuery + "(%1%, %2%).");
unsigned int moduleId = __registry->getModuleHash(module.__path);
for (const Expression& query: module.__queries){
std::list<std::string> reprQuery = xreate::analysis::compile(query);
assert(reprQuery.size()== 1);
__program << (formatProperty % moduleId % reprQuery.front())
<< std::endl;
}
}
void
ModulesSolver::add(const std::string& base){
__program << base;
}
void
ModulesSolver::init(const std::string& programBase, const ModuleRecord& module){
add(programBase);
extractRequirements(module);
extractProperties(module);
loadControllers(module);
discoverModules(module);
std::cout << __program.str() << std::endl;
}
std::list<std::string>
ModulesSolver::run(const ModuleRecord& module){
const std::string atomDecision = "module_include";
unsigned int moduleId = __registry->getModuleHash(module.__path);
std::list<std::string> result;
std::vector<char const *> args{"clingo", nullptr};
DefaultGringoModule moduleDefault;
Gringo::Scripts scriptsDefault(moduleDefault);
ClingoLib ctl(scriptsDefault, 0, args.data(), {}, 0);
ctl.add("base", {}, __program.str());
ctl.ground({{"base", {}}}, nullptr);
ctl.solve([&atomDecision, this, &result, moduleId](Gringo::Model const &model) {
for (Gringo::Symbol atom : model.atoms(clingo_show_type_atoms)) {
std::cout << atom << std::endl;
if (std::strcmp(atom.name().c_str(), atomDecision.c_str())==0){
auto rowDecision = TranscendLayer::parse<unsigned int, Gringo::Symbol>(atom);
unsigned int moduleIdActual = std::get<0>(rowDecision);
if (moduleIdActual == moduleId){
Gringo::Symbol moduleDecided = std::get<1>(rowDecision);
switch (moduleDecided.type()) {
case Gringo::SymbolType::Str:
result.push_back(moduleDecided.string().c_str());
break;
case Gringo::SymbolType::Num:
result.push_back(__registry->getModuleNameByHash(moduleDecided.num()));
break;
default: assert(false && "Inappropriate symbol type");
}
}
}
}
return true;
}, {});
return result;
}
const std::string&
ModulesRegistry::getModuleNameByHash(unsigned int hash){
auto result = __registry.right.find(hash);
assert(result != __registry.right.end());
return result->second;
}
unsigned int
ModulesRegistry::getModuleHash(const std::string& moduleName){
auto result = __registry.left.insert(Hash::left_value_type(moduleName, __registry.size()));
return result.first->second;
}
}} //namespace xreate::modules

Event Timeline