Page Menu
Home
Xreate
Search
Configure Global Search
Log In
Docs
Questions
Repository
Issues
Patches
Internal API
Files
F2718296
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Subscribers
None
File Metadata
Details
File Info
Storage
Attached
Created
Sun, Feb 15, 11:41 PM
Size
14 KB
Mime Type
text/x-diff
Expires
Tue, Feb 17, 11:41 PM (1 d, 19 h)
Engine
blob
Format
Raw Data
Handle
237837
Attached To
rXR Xreate
View Options
diff --git a/cpp/src/modules.cpp b/cpp/src/modules.cpp
index 5866c8a..c5e87fe 100644
--- a/cpp/src/modules.cpp
+++ b/cpp/src/modules.cpp
@@ -1,164 +1,175 @@
/*
* modules.cpp
*
* Author: pgess <v.melnychenko@xreate.org>
* Created on July 22, 2017, 5:13 PM
*/
#include "modules.h"
#include "modules/Parser.h"
#include "analysis/aux.h"
#include <clingo/clingocontrol.hh>
#include <boost/format.hpp>
#include <regex>
#include <boost/filesystem.hpp>
#include <fstream>
namespace fs = boost::filesystem;
namespace xreate {
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");
grammar::modules::Scanner scanner(script);
grammar::modules::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)) {
- atom.print(std::cout);
+ std::cout << atom << std::endl;
if (std::strcmp(atom.name().c_str(), atomDecision.c_str())==0){
- auto rowDecision = ClaspLayer::parse<unsigned int, unsigned int>(atom);
+ auto rowDecision = ClaspLayer::parse<unsigned int, Gringo::Symbol>(atom);
unsigned int moduleIdActual = std::get<0>(rowDecision);
if (moduleIdActual == moduleId){
- result.push_back(__registry->getModuleNameByHash(std::get<1>(rowDecision)));
+ 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
diff --git a/cpp/tests/modules.cpp b/cpp/tests/modules.cpp
index 10c1ead..d8e76b1 100644
--- a/cpp/tests/modules.cpp
+++ b/cpp/tests/modules.cpp
@@ -1,271 +1,320 @@
/*
* modules.cpp
*
* Author: pgess <v.melnychenko@xreate.org>
* Created on June 18, 2017, 8:25 PM
*/
class Modules_AST2_Test;
class Modules_Discovery1_Test;
class Modules_Solve1_Test;
#define FRIENDS_MODULES_TESTS \
friend class ::Modules_AST2_Test; \
friend class ::Modules_Discovery1_Test; \
friend class ::Modules_Solve1_Test;
#include "modules.h"
#include "misc/xreatemanager-decorators.h"
#include "misc/xreatemanager-modules.h"
#include "xreatemanager.h"
#include "modules/Parser.h"
#include "gtest/gtest.h"
#include <boost/filesystem.hpp>
#include <regex>
#include <clingo/clingocontrol.hh>
namespace fs = boost::filesystem;
using namespace std;
using namespace xreate::grammar::modules;
TEST(Modules, AST1) {
FILE* input = fopen("scripts/dsl/regexp.xreate","r");
assert(input != nullptr);
Scanner scanner(input);
Parser parser(&scanner);
parser.Parse();
ASSERT_EQ(parser.errors->count, 0);
}
TEST(Modules, AST2){
string code = R"Code(
module {
name(test1).
status(untested).
require provides(logging).
include controller("/tmp/test-controller.ls").
discover("/tmp/root/").
}
)Code";
Scanner scanner(reinterpret_cast<const unsigned char*>(code.c_str()), code.size());
Parser parser(&scanner);
parser.Parse();
xreate::ModuleRecord module = parser.module;
ASSERT_EQ(2, module.__properties.size());
ASSERT_EQ("name", module.__properties.front().getValueString());
ASSERT_EQ("status", module.__properties.back().getValueString());
ASSERT_EQ(1, module.__queries.size());
ASSERT_EQ("provides", module.__queries.front().getValueString());
ASSERT_EQ(1, module.__controllers.size());
ASSERT_EQ("/tmp/test-controller.ls", module.__controllers.front());
ASSERT_EQ(1, module.__discoveries.size());
ASSERT_EQ("/tmp/root/", module.__discoveries.front());
}
TEST(Modules, Discovery1){
const std::string dirModulesRoot = "/tmp/testModulesDiscovery1_t54723/";
string codeA =
R"Code(module {
name(testA).
status(needToTestMore).
})Code";
string codeB =
R"Code(module {
name(testB).
status(needToTestEvenMore).
})Code";
string codeMain = string("module{discover \"") + dirModulesRoot + "\".}";
fs::create_directories(dirModulesRoot);
fs::ofstream fileA(dirModulesRoot + "a.xreate");
fileA << codeA;
fileA.close();
fs::ofstream fileB(dirModulesRoot + "b.xreate");
fileB << codeB;
fileB.close();
Scanner scanner(reinterpret_cast<const unsigned char*>(codeMain.c_str()), codeMain.size());
Parser parser(&scanner);
parser.Parse();
xreate::ModulesRegistry registry;
xreate::ModulesSolver solver(®istry);
solver.discoverModules(parser.module);
fs::remove_all(dirModulesRoot);
std::string output = solver.__program.str();
cout << output << endl;
ASSERT_NE(string::npos, output.find("bind_module(0, name(testA))."));
ASSERT_NE(string::npos, output.find("bind_module(1, status(needToTestEvenMore))."));
}
TEST(Modules, Requests1){
}
TEST(Modules, Solve1){
const std::string dirModulesRoot = "/tmp/testModulesDiscovery1_t54724/";
string codeA =
R"Code(module {
name(testA).
provide(superService).
status(needToTestMore).
})Code";
string codeB =
R"Code(module {
name(testB).
provide(superService).
status(needToTestEvenMore).
})Code";
string codeMain =
R"Code(module {
discover("/tmp/testModulesDiscovery1_t54724/")
include controller ("/tmp/testModulesDiscovery1_t54724/controller")
require (superService)
})Code";
string codeController =
R"Code(
status_score(0, needToTestEvenMore).
status_score(1, needToTestMore).
module_include_candidate(X, Y, Request):-
module_require(X, Request); bind_module(Y, provide(Request)).
module_include_winner(X, Request, MaxScore) :-
MaxScore = #max{Score: module_include_candidate(X, Y, Request), bind_module(Y, status(Status)), status_score(Score, Status)};
module_require(X, Request).
module_include(X, Y) :-
module_include_winner(X, Request, MaxScore);
bind_module(Y, provide(Request));
bind_module(Y, status(Status));
status_score(MaxScore, Status).
)Code";
fs::create_directories(dirModulesRoot);
fs::ofstream fileA(dirModulesRoot + "a.xreate");
fileA << codeA;
fileA.close();
fs::ofstream fileB(dirModulesRoot + "b.xreate");
fileB << codeB;
fileB.close();
fs::ofstream fileController(dirModulesRoot + "controller");
fileController << codeController;
fileController.close();
Scanner scanner(reinterpret_cast<const unsigned char*>(codeMain.c_str()), codeMain.size());
Parser parser(&scanner);
parser.Parse();
xreate::ModulesRegistry registry;
xreate::ModulesSolver solver(®istry);
solver.init("", parser.module);
fs::remove_all(dirModulesRoot);
cout << solver.__program.str() << endl;
std::list<std::string> modulesRequired = solver.run(parser.module);
ASSERT_EQ(1, modulesRequired.size());
string moduleActualRequired = modulesRequired.front();
string moduleExpected = dirModulesRoot + "a.xreate";
ASSERT_EQ(moduleExpected, moduleActualRequired);
}
TEST(Modules, Compilation1){
const std::string dirModulesRoot = "/tmp/testModulesDiscovery1_t54725/";
string codeMain =
R"Code(
module {
discover("/tmp/testModulesDiscovery1_t54725/")
include controller("/tmp/testModulesDiscovery1_t54725/controller")
require (superService)
}
test = function:: int; entry {
getYourNumber()
}
)Code";
string codeA =
R"Code(module {
name(testA).
provide(superService).
status(needToTestEvenMore).
}
getYourNumber= function:: int {0}
)Code";
string codeB =
R"Code(module {
name(testB).
provide(superService).
status(needToTestMore).
}
getYourNumber= function:: int {1}
)Code";
string codeController =
R"Code(
status_score(0, needToTestEvenMore).
status_score(1, needToTestMore).
module_include_candidate(X, Y, Request):-
module_require(X, Request); bind_module(Y, provide(Request)).
module_include_winner(X, Request, MaxScore) :-
MaxScore = #max{Score: module_include_candidate(X, Y, Request), bind_module(Y, status(Status)), status_score(Score, Status)};
module_require(X, Request).
module_include(X, Y) :-
module_include_winner(X, Request, MaxScore);
bind_module(Y, provide(Request));
bind_module(Y, status(Status));
status_score(MaxScore, Status).
)Code";
fs::create_directories(dirModulesRoot);
fs::ofstream fileA(dirModulesRoot + "a.xreate");
fileA << codeA;
fileA.close();
fs::ofstream fileB(dirModulesRoot + "b.xreate");
fileB << codeB;
fileB.close();
fs::ofstream fileController(dirModulesRoot + "controller");
fileController << codeController;
fileController.close();
auto man = new XreateManagerImpl<XreateManagerDecoratorModules<XreateManagerDecoratorFull>>();
man->prepareCode(std::move(codeMain));
fs::remove_all(dirModulesRoot);
int (*funcMain)() = (int (*)()) man->run();
int result = funcMain();
ASSERT_EQ(1, result);
}
+
+TEST(Modules, Compilation_AssignModulePath1){
+ const std::string dirModulesRoot = "/tmp/testModulesDiscovery1_t54725/";
+ string codeMain =
+R"Code(
+module {
+ discover("/tmp/testModulesDiscovery1_t54725/")
+ include controller("/tmp/testModulesDiscovery1_t54725/controller")
+
+ require (superService)
+}
+
+test = function:: int; entry {
+ getYourNumber()
+}
+)Code";
+
+ string codeA =
+R"Code(module {
+ name(testA).
+ provide(superService).
+ status(needToTestEvenMore).
+}
+
+getYourNumber= function:: int {0}
+)Code";
+
+ string codeController =
+R"Code(
+module_include(X, "/tmp/testModulesDiscovery1_t54725/a.xreate") :- module_require(X, superService).
+)Code";
+
+ fs::create_directories(dirModulesRoot);
+ fs::ofstream fileA(dirModulesRoot + "a.xreate");
+ fileA << codeA;
+ fileA.close();
+
+ fs::ofstream fileController(dirModulesRoot + "controller");
+ fileController << codeController;
+ fileController.close();
+
+ auto man = new XreateManagerImpl<XreateManagerDecoratorModules<XreateManagerDecoratorFull>>();
+ man->prepareCode(std::move(codeMain));
+ fs::remove_all(dirModulesRoot);
+
+ int (*funcMain)() = (int (*)()) man->run();
+ int result = funcMain();
+ ASSERT_EQ(0, result);
+}
\ No newline at end of file
Event Timeline
Log In to Comment