diff --git a/config/default.json b/config/default.json index 28e521b..383c9d5 100644 --- a/config/default.json +++ b/config/default.json @@ -1,73 +1,73 @@ { "containers": { "id": { "implementations": "impl_fulfill_cluster", "clusters": "var_cluster", "prototypes": "proto_cluster", "linkedlist": "linkedlist" }, "impl": { "solid": "solid", "onthefly": "on_the_fly" } }, "logging": { "id": "logging" }, "function-entry": "entry", "clasp": { "bindings" : { "variable": "bind", "function": "bind_func", "scope": "bind_scope", "function_demand" : "bind_function_demand", "scope_decision": "bind_scope_decision" }, "context" : { "decisions":{ "dependent": "resolution_dependency" }, }, "nonevalue": "nonevalue", "ret": { "symbol": "retv", "tag": "ret" } }, "tests": { "template": "containers", "templates": { "default": "*-", "basic": "Basic.*", "ast": "AST.*", "cfa": "CFA.*", "dfa": "DFA.*", "compilation": "Compilation.*", - "containers": "Containers.Inference*-", + "containers": "Containers.*-", "diagnostic": "Diagnostic.*", "serializer": "ExpressionSerializer.*", "externc": "InterfaceExternC.*", "context": "ExpressionSerializer.*:Context.*", "types": "Types.*-", "log": "Logging*", "clang": "ClangAPI.*", "skip": "SkipDetection*:Adhoc_Loop_SkipDetection.*", "raw-xml": "libxml2*", "xml": "Xml.*", "installation": "Compilation.*:Sprint1.*", "exploitation": "Exploitation.*", "loops": "Loop.*", "dsl": "Interpretation.*", "adhocs": "Adhoc.*", } } } diff --git a/cpp/src/CMakeLists.txt b/cpp/src/CMakeLists.txt index 2200b02..454cdd4 100644 --- a/cpp/src/CMakeLists.txt +++ b/cpp/src/CMakeLists.txt @@ -1,217 +1,216 @@ cmake_minimum_required(VERSION 2.8.11) project(xreate) cmake_policy(SET CMP0022 NEW) # LLVM #====================== #FIND_PACKAGE (LLVM REQUIRED CONFIG PATHS PATH-TO-CMAKE-DIR NO_DEFAULT_PATH) FIND_PACKAGE (LLVM REQUIRED) set (CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake-tools") #include(PCH_GCC4_v2) set(LLVM_VERSION ${LLVM_VERSION_MAJOR}.${LLVM_VERSION_MINOR}) message ("LLVM LIB PATH:" ${LLVM_LIBRARY_DIRS}) set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}) message ("MPATH:" ${CMAKE_MODULE_PATH}) message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}") message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}") message(STATUS "INCLUDE DIR: ${LLVM_INCLUDE_DIRS}") INCLUDE_DIRECTORIES(${LLVM_INCLUDE_DIRS}) message("LLVM defs: " ${LLVM_DEFINITIONS}) add_definitions(${LLVM_DEFINITIONS}) llvm_map_components_to_libnames(LLVM_LIBS core nativecodegen native executionengine mcjit support) message("LLVM libs: " ${LLVM_LIBS}) # CLANG #====================== set(CLANG_LIBS ${LLVM_LIBRARY_DIRS}/libclangCodeGen.so ${LLVM_LIBRARY_DIRS}/libclangASTMatchers.so ${LLVM_LIBRARY_DIRS}/libclangQuery.so ${LLVM_LIBRARY_DIRS}/libclangTooling.so ${LLVM_LIBRARY_DIRS}/libclangFrontend.so ${LLVM_LIBRARY_DIRS}/libclangSerialization.so ${LLVM_LIBRARY_DIRS}/libclangDriver.so ${LLVM_LIBRARY_DIRS}/libclangParse.so ${LLVM_LIBRARY_DIRS}/libclangSema.so ${LLVM_LIBRARY_DIRS}/libclangAnalysis.so ${LLVM_LIBRARY_DIRS}/libclangAST.so ${LLVM_LIBRARY_DIRS}/libclangEdit.so ${LLVM_LIBRARY_DIRS}/libclangLex.so ${LLVM_LIBRARY_DIRS}/libclangBasic.so ) #find_package(Clang REQUIRED clangTooling libClang) message(STATUS "CLANG LIBS: " ${CLANG_LIBS}) # POTASSCO #====================== set(POTASSCO_PATH "/opt/potassco/clingo" CACHE PATH "Path to potassco sources") set(POTASSCO_INCLUDE_PATH ${POTASSCO_PATH}/libgringo ${POTASSCO_PATH}/libclasp ${POTASSCO_PATH}/libclingo ${POTASSCO_PATH}/libprogram_opts ${POTASSCO_PATH}/liblp ) INCLUDE_DIRECTORIES(${POTASSCO_INCLUDE_PATH}) set (LIBCLASP_PATH ${POTASSCO_PATH}/build/debug) set(LIBCLASP_LIBS clingo clasp gringo program_opts reify lp ) message(STATUS "CLASP LIBS: " ${LIBCLASP_LIBS}) link_directories(${LIBCLASP_PATH}) # OTHER DEPENDENCIES #=========================== set(JEAYESON_INCLUDE_PATH ${CMAKE_HOME_DIRECTORY}/../vendors/jeayeson/include/ ) INCLUDE_DIRECTORIES(${JEAYESON_INCLUDE_PATH}) # COCO #=========================== set(COCO_PATH ${CMAKE_HOME_DIRECTORY}/../coco/) set(COCO_SOURCE_FILES ${COCO_PATH}/Parser.cpp ${COCO_PATH}/Scanner.cpp) INCLUDE_DIRECTORIES(${COCO_PATH}) add_custom_command(OUTPUT ${COCO_SOURCE_FILES} COMMAND ${COCO_PATH}/gen-grammar WORKING_DIRECTORY ${COCO_PATH} MAIN_DEPENDENCY ${COCO_PATH}/xreate.ATG ) message(STATUS "COCO GRAMMAR BUILD STATUS:" ${COCO_OUTPUT}) # XREATE #====================== set(SOURCE_FILES clasplayer.cpp pass/compilepass.cpp pass/interpretationpass.cpp compilation/targetinterpretation.cpp ast.cpp ExternLayer.cpp attachments.cpp analysis/cfagraph.cpp analysis/dfagraph.cpp analysis/aux.cpp compilation/containers.cpp compilation/advanced.cpp compilation/transformations.cpp - analysis/DominatorsTreeAnalysisProvider.cpp compilation/latecontextcompiler2.cpp query/context.cpp #compilation/latecontextcompiler.cpp serialization/expressionserializer.cpp - serialization/expressionserializer2.cpp +# serialization/expressionserializer2.cpp llvmlayer.cpp utils.cpp passmanager.cpp pass/abstractpass.cpp pass/dfapass.cpp pass/cfapass.cpp pass/loggerpass.cpp pass/adhocpass.cpp query/containers.cpp contextrule.cpp #query/ptrvalid.cpp #pass/rulespass.cpp # ) set(XREATE_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/ ) INCLUDE_DIRECTORIES(${XREATE_INCLUDE_DIRS}) set(XREATE_PRIVATE_INCLUDE_DIRS ${XREATE_INCLUDE_DIRS} ${COCO_PATH} ${JEAYESON_INCLUDE_PATH} ${LLVM_INCLUDE_DIRS} ${POTASSCO_INCLUDE_PATH} ) add_library(${PROJECT_NAME} SHARED ${SOURCE_FILES} ${COCO_SOURCE_FILES}) target_link_libraries(${PROJECT_NAME} ${LIBCLASP_LIBS}) target_include_directories(${PROJECT_NAME} INTERFACE ${XREATE_INCLUDE_DIRS} ${COCO_PATH} ${JEAYESON_INCLUDE_PATH} ${LLVM_INCLUDE_DIRS} ${POTASSCO_INCLUDE_PATH} ) get_directory_property(DEFINITIONS_ALL DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} COMPILE_DEFINITIONS) message("definitions all: " ${DEFINITIONS_ALL}) target_compile_definitions(${PROJECT_NAME} INTERFACE ${DEFINITIONS_ALL}) get_directory_property(COMPILATION_OPTIONS_ALL DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} COMPILE_OPTIONS) message("compilations all: " ${COMPILATION_OPTIONS_ALL}) target_compile_options(${PROJECT_NAME} INTERFACE ${COMPILATION_OPTIONS_ALL}) SET_PROPERTY(TARGET ${PROJECT_NAME} PROPERTY INTERFACE_LINK_LIBRARIES ${LLVM_LIBS} ${CLANG_LIBS} tbb ) #set (LINK_INTERFACE_LIBRARIES "") # FUNCTION(PREPEND var prefix) # SET(listVar "") # FOREACH(f ${ARGN}) # LIST(APPEND listVar "${prefix}/${f}") # ENDFOREACH(f) # SET(${var} "${listVar}" PARENT_SCOPE) # ENDFUNCTION(PREPEND) #set(COTIRE_UNITY_SOURCE_MAXIMUM_NUMBER_OF_INCLUDES "-j4") #cotire(xreate) # MACRO (ADD_PCH_RULE _header_filename _src_list) # SET(_gch_filename "${_header_filename}.gch") # LIST(APPEND ${_src_list} ${_gch_filename}) # SET (_args ${CMAKE_CXX_FLAGS}) # LIST(APPEND _args -c ${_header_filename} -o ${_gch_filename}) # GET_DIRECTORY_PROPERTY(DIRINC INCLUDE_DIRECTORIES) # foreach (_inc ${DIRINC}) # LIST(APPEND _args "-I" ${_inc}) # endforeach(_inc ${DIRINC}) # SEPARATE_ARGUMENTS(_args) # add_custom_command(OUTPUT ${_gch_filename} # COMMAND rm -f ${_gch_filename} # COMMAND ${CMAKE_CXX_COMPILER} ${CMAKE_CXX_COMPILER_ARG1} ${_args} # DEPENDS ${_header_filename}) # ENDMACRO(ADD_PCH_RULE _header_filename _src_list) # ADD_PCH_RULE (${CMAKE_HOME_DIRECTORY}/src/ast.h SOURCE_FILES) # ADD_PCH_RULE (${CMAKE_HOME_DIRECTORY}/src/llvmlayer.h SOURCE_FILES) # ADD_PCH_RULE (${CMAKE_HOME_DIRECTORY}/src/clasplayer.h SOURCE_FILES) # ADD_PCH_RULE (${CMAKE_HOME_DIRECTORY}/src/pass/abstractpass.h SOURCE_FILES) diff --git a/cpp/src/clasplayer.cpp b/cpp/src/clasplayer.cpp index 09b2026..b171d05 100644 --- a/cpp/src/clasplayer.cpp +++ b/cpp/src/clasplayer.cpp @@ -1,313 +1,308 @@ #include "clasplayer.h" #include #include "utils.h" #include #include #include #include "analysis/aux.h" -#include "analysis/DominatorsTreeAnalysisProvider.h" #include "analysis/cfagraph.h" #include "analysis/dfagraph.h" using namespace std; //TODO escape identifiers started from upper case symbol namespace xreate { void ClaspLayer::printWarnings(std::ostream& out) { const std::string warningTag = "warning"; auto warningsRange = __model.equal_range(warningTag); for (auto warning=warningsRange.first; warning!= warningsRange.second; ++warning) { unsigned int warningId; Gringo::Symbol params; std::tie(warningId, params) = parse(warning->second); cout << "Warning: " << __warnings.at(warningId) << " "; params.print(out); out< warnings; cout << "Model: " << endl; const string& atomBindVar = Config::get("clasp.bindings.variable"); const string& atomBindFunc = Config::get("clasp.bindings.function"); const string& atomBindScope = Config::get("clasp.bindings.scope"); for (Gringo::Symbol atom : model.atoms(clingo_show_type_atoms)) { atom.print(cout); cout <<" | "<< endl; string atomName(atom.name().c_str()); if (atomName == atomBindVar || atomName == atomBindFunc || atomName == atomBindScope){ string name = std::get<1>(parse(atom)).name().c_str(); __model.emplace(move(name), move(atom)); } __model.emplace(atomName, move(atom)); } return true; } void ClaspLayer::setCFAData(xreate::analysis::CFAGraph* graph) { dataCFA.reset(graph); } void ClaspLayer::setDFAData(xreate::analysis::DFAGraph* graph){ dataDFA.reset(graph); } void ClaspLayer::addRuleWarning(const RuleWarning &rule) { //__partGeneral << rule << endl; list domains; boost::format formatDef("%1%(%2%)"); std::transform(rule.__args.begin(), rule.__args.end(), std::inserter(domains, domains.begin()), [&formatDef](const std::pair &argument) { string domain; switch (argument.second) { case DomainAnnotation::FUNCTION: domain = "function"; break; case DomainAnnotation::VARIABLE: domain = "variable"; break; } return boost::str(formatDef % domain % argument.first); }); list vars; std::transform(rule.__args.begin(), rule.__args.end(), std::inserter(vars, vars.begin()), [](const std::pair &argument) { return argument.first.c_str(); }); list> guardsRaw; std::transform(rule.__guards.begin(), rule.__guards.end(), std::inserter(guardsRaw, guardsRaw.begin()), [this](const Expression &guard) { return xreate::analysis::compile(guard); }); const list& guards = xreate::analysis::multiplyLists(std::move(guardsRaw)); list &&branches = xreate::analysis::compileNeg(rule.__condition); boost::format formatWarning("warning(%1%, (%2%)):- %3%, %4%, %5%."); for (const string &guardsJoined: guards) for (const string &branch: branches) { unsigned int hook = registerWarning(string(rule.__message)); __partGeneral << formatWarning %(hook) %(boost::algorithm::join(vars, ", ")) %(branch) %(guardsJoined) %(boost::algorithm::join(domains, ", ")) <__rawImports) { std::ifstream file(fn); if (!file) continue; while(!file.eof()){ string line; std::getline(file, line); out << line << endl; } } } void ClaspLayer::addRawScript(std::string&& script){ __partGeneral << script; } void ClaspLayer::run() { involveImports(); if (this->dataDFA){ this->dataDFA->print(__partGeneral); } if (this->dataCFA){ this->dataCFA->print(__partGeneral); } - DominatorsTreeAnalysisProvider providerDominators; - providerDominators.run(this); - providerDominators.print(__partGeneral); - ostringstream program; program << __partTags.str() << __partGeneral.str(); cout << FYEL(program.str()) << endl; std::vector 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); // solve Gringo::SolveResult result = ctl.solve([this](Gringo::Model const &model) { this->handleSolution(model); return true; }, {}); if (result.satisfiable() == Gringo::SolveResult::Satisfiable) { cout << FGRN("SUCCESSFULLY") << endl; } else { cout << FRED("UNSUCCESSFULLY") << endl; } // invoke all query plugins to process clasp data for (auto q: __queries) { q.second->init(this); } } bool ClaspLayer::checkScript(std::string&& script, std::string&& atomCheckSuccess){ //init std::vector args{"clingo", nullptr}; DefaultGringoModule moduleDefault; Gringo::Scripts scriptsDefault(moduleDefault); ClingoLib ctl(scriptsDefault, 0, args.data(), {}, 0); ctl.add("base", {}, script); ctl.ground({{"base", {}}}, nullptr); bool flagCheck = false; Gringo::SolveResult result = ctl.solve([this, &flagCheck, &atomCheckSuccess](Gringo::Model const &model) { for (Gringo::Symbol atom : model.atoms(clingo_show_type_atoms)) { atom.print(cout); cout << endl; string atomName(atom.name().c_str()); if (atomName == atomCheckSuccess){ flagCheck = true; break; }} return true; }, {}); if (!result.satisfiable()){ return false; } return flagCheck; } ClaspLayer::ClaspLayer() { } ClaspLayer::ModelFragment ClaspLayer::query(const std::string& atom) { if (! __model.count(atom)){ return boost::none; } return ModelFragment(__model.equal_range(atom)); } ScopePacked ClaspLayer::pack(CodeScope* const scope) { auto pos = __indexScopes.emplace(scope, __indexScopes.size()); if (pos.second) __registryScopes.push_back(scope); return pos.first->second; } size_t ClaspLayer::getScopesCount() const{ return __registryScopes.size(); } SymbolPacked ClaspLayer::pack(const Symbol& symbol, std::string hintSymbolName) { SymbolPacked result; result.scope = pack(symbol.scope); result.identifier = symbol.identifier; __indexSymbolNameHints.emplace(result, hintSymbolName); return result; } Symbol ClaspLayer::unpack(const SymbolPacked& symbol) { return Symbol{symbol.identifier, __registryScopes[symbol.scope]}; }; std::string ClaspLayer::getHintForPackedSymbol(const SymbolPacked& symbol){ if (!symbol.categoryTransient) { auto result = __indexSymbolNameHints.find(symbol); return (result == __indexSymbolNameHints.end())? "" : result->second; } else { return "anonym(" + to_string(symbol.identifier) + ")"; } } bool operator==(const SymbolPacked& s1, const SymbolPacked& s2) { return s1.identifier == s2.identifier && s1.scope == s2.scope; } bool operator<(const SymbolPacked& s1, const SymbolPacked& s2) { return s1.scope < s2.scope || (s1.scope == s2.scope && s1.identifier < s2.identifier); } IQuery* ClaspLayer::registerQuery(IQuery *query, const QueryId& id) { return __queries.emplace(id, query).first->second; } IQuery* ClaspLayer::getQuery(const QueryId& id){ assert(__queries.count(id) && "Undefined query"); return __queries.at(id); } } diff --git a/cpp/src/serialization/expressionserializer.cpp b/cpp/src/serialization/expressionserializer.cpp index 42b5a15..0b571ed 100644 --- a/cpp/src/serialization/expressionserializer.cpp +++ b/cpp/src/serialization/expressionserializer.cpp @@ -1,303 +1,318 @@ /* * expressionserializer.cpp * * Created on: Jan 4, 2016 * Author: pgess */ #include "serialization/expressionserializer.h" +#include +#include + #include using namespace std; //using namespace boost::bimaps; namespace xreate { struct Index { string name; size_t degree; //count of parameters unsigned char level; //level in expression tree (depth of tree layer) bool operator< (const Index other) const{ if (name != other.name) return name < other.name; if (degree != other.degree) return degree < other.degree; if (name != other.name) return level < other.level; return false; } }; class ExpressionSerializerPrivate { //boost::bimap> __registry; struct { map left; } __registry; map __range; public: void pack(const Expression& e, unsigned char level, OptionalPackedExpression& target){ if (!target) return; switch (e.op){ case Operator::NONE: { switch (e.__state) { case Expression::NUMBER: case Expression::STRING: case Expression::IDENT : { Index index; if ((e.__state == Expression::NUMBER)) index = {std::to_string(e.getValueDouble()), 0, level}; else index = {e.getValueString(), 0, level}; if (!__registry.left.count(index)){ target = boost::none; return; } size_t id = __registry.left.at(index); size_t range = __range[level]; (*target) << make_pair(id, range); return; } default: break; } break; } case Operator::CALL: { Index index{e.getValueString(), e.operands.size(), level}; if(!__registry.left.count(index)){ target = boost::none; return; } size_t id = __registry.left.at(index); size_t range = __range[level]; (*target) << make_pair(id, range); for (const Expression& operand: e.operands){ pack(operand, level+1, target); } return; } default: break; } assert(false && "Expression too complicate for serialization"); } void registerExpression(const Expression&e, unsigned char level){ switch (e.op){ case Operator::CALL: { Index index{e.getValueString(), e.operands.size(), level}; if (__registry.left.insert(make_pair(index, __range[level])).second){ __range[level]++; } for (const Expression& operand: e.operands){ registerExpression(operand, level+1); } return; } case Operator::NONE: { Index index; switch (e.__state) { case Expression::STRING: case Expression::IDENT: { index = {e.getValueString(), 0, level}; if (__registry.left.insert(make_pair(index, __range[level])).second){ __range[level]++; } return; } case Expression::NUMBER: { index = {std::to_string(e.getValueDouble()), 0, level}; if (__registry.left.insert(make_pair(index, __range[level])).second){ __range[level]++; } return; } default: break; } break; } default: break; } assert(false && "Expression too complicate for serialization"); } }; ExpressionSerializer::ExpressionSerializer() : strategy(new ExpressionSerializerPrivate()){ } ExpressionSerializer::~ExpressionSerializer() { delete strategy; } void ExpressionSerializer::registerExpression(const Expression&e){ if (e.isValid()) strategy->registerExpression(e, 0); } PackedExpression ExpressionSerializer::getId(const Expression& e){ - OptionalPackedExpression result(move(PackedExpression())); + OptionalPackedExpression result(boost::in_place()); + //move(PackedExpression()) + strategy->pack(e, 0, result); assert(result); return move(*result); } OptionalPackedExpression ExpressionSerializer::getIdOptional(const Expression& e) const{ - OptionalPackedExpression result(move(PackedExpression())); + OptionalPackedExpression result(boost::in_place()); + //move(PackedExpression()) + strategy->pack(e, 0, result); return result; } ExpressionSerializerIntegral::ExpressionSerializerIntegral():serializer(*this){} ExpressionSerializerIntegral::ExpressionSerializerIntegral(const std::vector&& expressions) : std::vector(move(expressions)), serializer(*this){ size_t id =0; for (const Expression& e: expressions){ __registry.emplace(serializer.getId(e), id++); } } size_t ExpressionSerializerIntegral::size() const{ return PARENT::size(); } size_t ExpressionSerializerIntegral::count(const Expression& e) const { return (getIdOptional(e)? 1: 0); } ExpressionSerializerIntegral::const_iterator ExpressionSerializerIntegral::begin() const { return PARENT::begin(); } ExpressionSerializerIntegral::const_iterator ExpressionSerializerIntegral::end() const { return PARENT::end(); } size_t ExpressionSerializerIntegral::getId(const Expression& e) const{ - const auto& exprPacked = serializer.getIdOptional(e); + const OptionalPackedExpression exprPacked = serializer.getIdOptional(e); assert(exprPacked); return __registry.at(*exprPacked); } boost::optional ExpressionSerializerIntegral::getIdOptional(const Expression& e) const{ - const auto& exprPacked = serializer.getIdOptional(e); + const OptionalPackedExpression exprPacked = serializer.getIdOptional(e); if (!exprPacked){ return boost::none; } return __registry.at(*exprPacked); } const Expression& ExpressionSerializerIntegral::get(size_t id) const{ return at(id); } void PackedExpression::operator<< (const std::pair& value){ static const size_t sizeSizeT = sizeof(size_t); const size_t& id = value.first; const size_t& range = value.second; int countSufficientBits = range <=1? 0 : ceil(log2(range)); if (0 < countRemainedBits && countRemainedBits < countSufficientBits) { size_t* tail = reinterpret_cast(__storage + size- sizeSizeT); (*tail) += id >> (countSufficientBits - countRemainedBits); countSufficientBits-=countRemainedBits; countRemainedBits = 0; } if (countRemainedBits == 0) { if (countSufficientBits == 0) return; char* __storageNew = new char[size+sizeSizeT]; std::memcpy (__storageNew, __storage, size); std::memset(__storageNew + size, 0, sizeSizeT); delete[] __storage; __storage = __storageNew; size += sizeSizeT; countRemainedBits = 8 * sizeSizeT; } if (countRemainedBits >= countSufficientBits) { size_t* tail = reinterpret_cast(__storage + size- sizeSizeT); (*tail) += id << (countRemainedBits - countSufficientBits); countRemainedBits -= countSufficientBits; return; } assert("Unreachable block"); } + #if BOOST_VERSION <= 105500 +PackedExpression::PackedExpression(const PackedExpression& other){ + __storage = other.__storage; + size = other.size; + countRemainedBits = other.countRemainedBits; +} + #endif + PackedExpression::PackedExpression(PackedExpression&& other){ __storage = other.__storage; size = other.size; countRemainedBits = other.countRemainedBits; other.__storage = nullptr; } bool PackedExpression::operator==(const PackedExpression& other) const{ if (size == other.size && countRemainedBits == other.countRemainedBits){ return std::memcmp(__storage, other.__storage, size) == 0 ; } return false; } bool PackedExpression::operator<(const PackedExpression& other) const{ if (size < other.size) { return true; } if (countRemainedBits < other.countRemainedBits) return true; if (size == other.size && countRemainedBits == other.countRemainedBits){ return std::memcmp(__storage, other.__storage, size) < 0 ; } return false; } bool PackedExpression::operator!=(const PackedExpression& other) const{ return ! ((*this) == other); } PackedExpression::~PackedExpression() { delete[] __storage; } //PackedExpression::PackedExpression (const PackedExpression& other) // : size(other.size), countRemainedBits(other.countRemainedBits) //{ // __storage = new char[size]; // std::memcpy (__storage, other.__storage, size); //} } /* namespace xreate */ diff --git a/cpp/src/serialization/expressionserializer.h b/cpp/src/serialization/expressionserializer.h index 9acf8c4..ad8cc66 100644 --- a/cpp/src/serialization/expressionserializer.h +++ b/cpp/src/serialization/expressionserializer.h @@ -1,103 +1,111 @@ /* * expressionserializer.h * * Created on: Jan 4, 2016 * Author: pgess */ #ifndef SRC_EXPRESSIONSERIALIZER_H_ #define SRC_EXPRESSIONSERIALIZER_H_ #include "ast.h" #include #include +#include namespace xreate { struct PackedExpression{ PackedExpression(){}; PackedExpression(PackedExpression&& other); + + #if BOOST_VERSION <= 105500 + PackedExpression (const PackedExpression&); + + #else + PackedExpression (const PackedExpression&)=delete; + #endif + ~PackedExpression(); void operator<< (const std::pair& value); char* operator*(){return __storage;} bool operator==(const PackedExpression& other) const; bool operator!=(const PackedExpression& other) const; bool operator<(const PackedExpression& other) const; private: - PackedExpression (const PackedExpression&)=delete; PackedExpression& operator=(const PackedExpression&)=delete; PackedExpression& operator=(PackedExpression&&)=delete; char* __storage = nullptr; size_t size =0; unsigned char countRemainedBits =0; }; typedef boost::optional OptionalPackedExpression; class ExpressionSerializerPrivate; class ExpressionSerializer { public: template ExpressionSerializer(const Container& source): ExpressionSerializer(){ for (const Expression& e: source) { registerExpression(e); } } template ExpressionSerializer(const Container& source, Transformer op): ExpressionSerializer(){ for (const typename Container::value_type& e: source) { registerExpression(op(e)); } } ExpressionSerializer(ExpressionSerializer&& other) : strategy(other.strategy) {other.strategy = 0; } virtual ~ExpressionSerializer(); PackedExpression getId(const Expression& e); OptionalPackedExpression getIdOptional(const Expression& e) const; private: ExpressionSerializerPrivate* strategy; void registerExpression(const Expression&e); ExpressionSerializer(); }; class ExpressionSerializerIntegral: private std::vector{ typedef std::vector PARENT; public: ExpressionSerializerIntegral(); ExpressionSerializerIntegral(const std::vector&& expressions); template ExpressionSerializerIntegral(Iterator first, Iterator last) : ExpressionSerializerIntegral(std::vector(first, last)){} ExpressionSerializerIntegral(ExpressionSerializerIntegral&& other) : PARENT(std::move(other)), __registry(std::move(other.__registry)), serializer(std::move(other.serializer)){} size_t getId(const Expression& e) const; boost::optional getIdOptional(const Expression& e) const; const Expression& get(size_t id) const; size_t size() const; size_t count(const Expression& e) const; ExpressionSerializerIntegral::const_iterator begin() const; ExpressionSerializerIntegral::const_iterator end() const; private: ExpressionSerializerIntegral(const ExpressionSerializerIntegral&)=delete; std::map __registry; ExpressionSerializer serializer; }; } /* namespace xreate */ #endif /* SRC_EXPRESSIONSERIALIZER_H_ */ diff --git a/cpp/tests/ExpressionSerializer.cpp b/cpp/tests/ExpressionSerializer.cpp deleted file mode 100644 index c5dc128..0000000 --- a/cpp/tests/ExpressionSerializer.cpp +++ /dev/null @@ -1,65 +0,0 @@ -/* - * testExpressionSerializer.cpp - * - * Created on: Jan 4, 2016 - * Author: pgess - */ - -#include "serialization/expressionserializer.h" -#include "serialization.h" -#include "ast.h" -#include "gtest/gtest.h" - -using namespace xreate; -using namespace std; - -TEST(ExpressionSerializer, pack1){ - PackedExpression x; - - x << std::make_pair(0xA1, 0x100); - size_t* storage = reinterpret_cast (*x); - ASSERT_EQ(0xA100000000000000, *storage); - - x << std::make_pair(0x23456, 0x100000); - ASSERT_EQ(0xA123456000000000, *storage); - - x << std::make_pair(0x7654321, 0x10000000); - ASSERT_EQ(0xA123456765432100, *storage); - - - x << std::make_pair(0xABBA, 0x10000); - storage = reinterpret_cast (*x); - ASSERT_EQ(0xA1234567654321AB, *storage); - ASSERT_EQ(0xBA00000000000000, *(storage+1)); -} - -TEST(ExpressionSerializer, serialize1){ - Expression a(Operator::CALL, {Expression(string("a")), Expression(string("a"))}); - Expression b(Operator::CALL, {Expression(string("a")), Expression(string("b"))}); - - ExpressionSerializer serializer(vector{a, b}); - - PackedExpression packA = serializer.getId(a); - PackedExpression packB = serializer.getId(b); - PackedExpression packA2 = serializer.getId(a); - - ASSERT_EQ(packA, packA2); - ASSERT_NE(packA, packB); -} - -TEST(ExpressionSerializer, serialize2){ - Expression a(Operator::CALL, {Expression(string("a")), Expression(string("a"))}); - Expression b(Operator::CALL, {Expression(string("a")), Expression(string("b"))}); - Expression c(Atom("c")); - - typedef ExpressionSerialization::Serializer Serializer; - Serializer serializer(vector{a, b}); - - ASSERT_EQ(2, serializer.size()); - ASSERT_EQ(1, serializer.count(a)); - ASSERT_EQ(1, serializer.count(b)); - ASSERT_EQ(0, serializer.count(c)); - - Serializer serializer2(move(serializer)); - ASSERT_EQ(1, serializer2.count(a)); -} diff --git a/cpp/tests/cfa.cpp b/cpp/tests/cfa.cpp deleted file mode 100644 index f01028c..0000000 --- a/cpp/tests/cfa.cpp +++ /dev/null @@ -1,119 +0,0 @@ -/* - * testsCFG.cpp - * - * Created on: Jul 17, 2015 - * Author: pgess - */ - -#include "passmanager.h" -#include "pass/dfapass.h" -#include "pass/cfapass.h" - -#include "analysis/DominatorsTreeAnalysisProvider.h" - -#include "gtest/gtest.h" - -#include -#include - -using namespace xreate; -using namespace std; - -TEST(CFA, testFunctionAnnotationsClasp){ - string&& program = - "f2 = function::int; annotationF2 {\n" - " 0\n" - "}\n" - "\n" - "f1 = function:: int; entry; annotationF1 {\n" - " f2() + 10\n" - "}"; - - - PassManager* man = PassManager::prepareForCode(move(program)); - man->runWithoutCompilation(); - - ClaspLayer::ModelFragment answer = man->clasp->query("annotationF1"); - int countNoneValue = 0; - if (answer) countNoneValue = std::distance(answer->first, answer->second); - EXPECT_EQ(1, countNoneValue); - - answer = man->clasp->query("annotationF2"); - countNoneValue = 0; - if (answer) countNoneValue = std::distance(answer->first, answer->second); - - EXPECT_EQ(1, countNoneValue); -} - -TEST(CFA, testLoopContextExists){ - PassManager* man = PassManager::prepareForCode ( - "interface(cfa){\n" - " operator fold:: annotation1.\n" - "}\n" - "\n" - "main = function:: int; entry {\n" - " x = [1..10]:: [int].\n" - " sum = loop fold (x->el:: int, 0->sum):: int {\n" - " el + sum + f1()\n" - " }. \n" - " sum\n" - "}" - "case context:: annotation1 {" - " f1 = function::int {\n" - " x = 0:: int. " - " x\n" - " }" - "}" - ); - - man->runWithoutCompilation(); - ClaspLayer::ModelFragment model = man->clasp->query("annotation1"); - ScopePacked scopeIdActual = std::get<0>(ClaspLayer::parse(model->first->second)); - - CodeScope* scopeEntry = man->root->findFunction("main")->getEntryScope(); - Symbol symbSum = man->root->findFunction("main")->getEntryScope()->findSymbol("sum"); - CodeScope* scopeExpected = scopeEntry->findDeclaration(symbSum).blocks.front(); - - ScopePacked scopeIdExpected = man->clasp->pack(scopeExpected); - ASSERT_EQ(scopeIdExpected, scopeIdActual); -} - -TEST(CFA, CFGRoots){ - std::string program = -R"CODE( - main = function::int{a()+ b()} - a= function::int {c1() + c2()} - b= function::int {c2()} - c1=function::int{0} - c2=function::int{0} -)CODE"; - - boost::scoped_ptr manager - (PassManager::prepareForCode(move(program))); - - manager->registerPass(new CFAPass(manager.get()) , PassId::CFGPass); - manager->executePasses(); - manager->clasp->run(); - - DominatorsTreeAnalysisProvider domProvider; - domProvider.run(manager->clasp); - - DominatorsTreeAnalysisProvider::Dominators expectedFDom= { - {0, {0, 9}} - ,{1, {1, 4}} - ,{2, {7, 8}} - ,{3, {2, 3}} - ,{4, {5, 6}} - }; - - DominatorsTreeAnalysisProvider::Dominators expectedPostDom= { - {0, {5, 6}} - ,{1, {3, 4}} - ,{2, {8, 9}} - ,{3, {1, 2}} - ,{4, {7, 10}} - }; - - ASSERT_EQ(expectedFDom, domProvider.getForwardDominators()); - ASSERT_EQ(expectedPostDom, domProvider.getPostDominators()); -} diff --git a/cpp/tests/context.cpp b/cpp/tests/context.cpp deleted file mode 100644 index 847dab1..0000000 --- a/cpp/tests/context.cpp +++ /dev/null @@ -1,495 +0,0 @@ -/* - * frame-context.cpp - * - * Created on: Dec 3, 2015 - * Author: pgess - */ - -#include "passmanager.h" -#include "query/context.h" - -#include "gtest/gtest.h" -#include -#include - -using namespace xreate; - -TEST(Context, frame_Context1){ - PassManager* man = PassManager::prepareForCode( - " import raw (\"core/control-context.lp\")\n" - " compute = function::int {\n" - " 0\n" - " }\n" - - " computeFast = function:: int {\n" - " context:: computation(fast).\n" - - " compute()\n" - " }\n" - - " computePrecisely = function:: int {\n" - " context:: computation(precise). \n" - - " compute()\n" - " }\n" - - "test = function(cmnd:: int):: int; entry {\n" - " context:: arithmetic(iee754). \n" - - " if (cmnd > 0)::int {computePrecisely()} else {computeFast()} \n" - "}\n" - ); - - ContextQuery* query = (ContextQuery*) man->clasp->registerQuery(new ContextQuery(), QueryId::ContextQuery); - man->runWithoutCompilation(); - - CodeScope* scopeTestC = man->root->findFunction("compute")->getEntryScope(); - const Domain& context = query->getContext(man->clasp->pack(scopeTestC)); - - int contextSize = context.size(); - EXPECT_EQ(1, contextSize); //arithmetic(iee754) -} - -TEST(Context, contextAsRequirementSuccessful1){ - PassManager* man = PassManager::prepareForCode( - " import raw (\"core/control-context.lp\")\n" - - " case context::safe {\n" - " funcSensitive = function::int {\n" - " 0\n" - " }}\n" - - " test = function:: int; entry {\n" - " context:: safe; test.\n" - - " funcSensitive()\n" - " }\n" - ); - - int (*main)() = (int (*)()) man->run(); - ASSERT_EQ(0, main()); -} - -TEST(Context, contextAsRequirementFailed){ - PassManager* man = PassManager::prepareForCode( - " import raw (\"core/control-context.lp\")\n" - - " case context::safe {\n" - " funcSensitive = function::int {\n" - " 0\n" - " }}\n" - - " test = function:: int; entry {\n" - " context:: non_safe; test.\n" - - " funcSensitive()\n" - " }\n" - ); - - ASSERT_DEATH(man->run(), "findFunction"); -} - -TEST(Context, ContextPropagationNested){ - PassManager* man = PassManager::prepareForCode( - " import raw (\"core/control-context.lp\")\n" - - " case context::safe {\n" - " square = function(x:: int) ::int {\n" - " x * x\n" - " }}\n" - - " test = function:: int; entry {\n" - " context:: safe; test.\n" - - " range = [1..10]:: [int]. \n" - " loop fold(range->x::int, 0->acc):: int { \n" - " acc + square(x) \n" - " } \n" - " }\n" - ); - - int (*main)() = (int (*)()) man->run(); - ASSERT_EQ(385, main()); -} - -TEST(Context, ContextPropagationNestedInterfunction){ - - PassManager* man = PassManager::prepareForCode( - " import raw (\"core/control-context.lp\")\n" - " case context::toMillimeters {\n" - " convertConcrete = function(source:: num)::num {\n" - " 10 * source \n" - " }\n" - " }\n" - - " case context::toInches {\n" - " convertConcrete = function(source:: num)::num {\n" - " 2 * source \n" - " }\n" - " }\n" - - "convert= function(source:: num):: num { \n" - "convertConcrete(source) \n" - "} \n" - - "test = function(source:: num):: num; entry {\n" - " context:: toMillimeters.\n" - " convert(1)\n" - "}\n" ); - - int (*main)(int) = (int (*)(int)) man->run(); - ASSERT_EQ(10, main(1)); -} - -TEST(Context, full_ContextBasedFunctionSpecialization){ - - PassManager* man = PassManager::prepareForCode( - " import raw (\"core/control-context.lp\")\n" - " case context::toMillimeters {\n" - " convert = function(source:: num)::num {\n" - " 10 * source \n" - " }\n" - " }\n" - - " case context::toInches {\n" - " convert = function(source:: num)::num {\n" - " 2 * source \n" - " }\n" - " }\n" - - "test = function(vrnt:: int)::int; entry {\n" - " switch(vrnt):: int\n" - " case 0 {\n" - " context:: toMillimeters.\n" - " convert(1)\n" - " }\n" - "\n" - " case 1 {\n" - " context:: toInches.\n" - " convert(1)\n" - " }\n" - " case default {0}\n" - " }" ); - - int (*main)(int) = (int (*)(int)) man->run(); - ASSERT_EQ(10, main(0)); - ASSERT_EQ(2, main(1)); -} - -//TOODO recover context loop and enable the test -TEST(Context, full_LoopContext){ - - PassManager* man = PassManager::prepareForCode( - " import raw (\"core/control-context.lp\")\n" - " case context:: a {\n" - " print = function:: string {\n" - " \"a\"\n" - " }}\n" - "\n" - " case context:: b {\n" - " print = function:: string {\n" - " \"b\"\n" - " }}\n" - "\n" - " case context:: c {\n" - " print = function:: string {\n" - " \"c\"\n" - " }}\n" - "\n" - " case context:: d {\n" - " print = function:: string {\n" - " \"d\"\n" - " }}\n" - "\n" - " start = function(command::int)::string; entry {\n" - " switch (command) :: string \n" - " case 0 {\n" - " context:: print(a); print(b); print(d).\n" - "\n" - " loop context (\"print\") {\n" - " print()\n" - " }\n" - " }\n" - "\n" - " case default {\n" - " context:: print(c).\n" - " loop context (\"print\") {\n" - " print()\n" - " }\n" - " }\n" - " }"); - - - char* (*main)(int) =(char* (*)(int)) man->run(); - ASSERT_STREQ("c", main(1)); - ASSERT_STREQ("a", main(0)); -} - -TEST(Context, full_RuleContext){ - /* - "rule context:: childs(Child)\n" - " case artefact(Item)\n" - " {\n" - " artefact_depends(Item, Child)\n" - " }"; - */ - - PassManager* man = PassManager::prepareForCode( - " import raw (\"core/control-context.lp\")\n" - " case context:: toMilli {\n" - " convert = function(length::int)::int{\n" - " 10 * length\n" - " }\n" - " }\n" - "\n" - " case context:: toCenti {\n" - " convert = function(length::int)::int{\n" - " length\n" - " }\n" - " }\n" - "\n" - " main=function::int; entry {\n" - " context:: output(milli).\n" - "\n" - " rule context::toMilli\n" - " case output(milli) {true}\n" - "\n" - " convert(1)\n" - " }" ); - - man->clasp->addRawScript("true."); - int (*entry)() = (int (*)()) man->run(); - ASSERT_EQ(10, entry()); -} - -TEST(Context, full_InheritedRuleContext){ - PassManager* man = PassManager::prepareForCode( -" import raw (\"core/control-context.lp\") \n" - -" case context:: toMilli {\n" -" convert = function(length::int)::int{\n" -" 10 * length\n" -" }\n" -" }\n" - -" case context:: toCenti {\n" -" convert = function(length::int)::int{\n" -" length\n" -" }\n" -" }\n" -"\n" - -"main = function(comm:: num)::num; entry{\n" -" rule context::X case output(X) {true}\n" -"\n" -" switch (comm)::num \n" -" case 0 {\n" -" context:: output(toMilli).\n" -" convert(1)\n" -" }\n" -" case default {\n" -" context:: output(toCenti).\n" -" convert(1)\n" -" }\n" -" }"); - - man->clasp->addRawScript("true."); - int (*entry)(int) = (int (*)(int)) man->run(); - ASSERT_EQ(10, entry(0)); - ASSERT_EQ(1, entry(1)); -} - - - -TEST(Context, full_LateContext){ - PassManager* man = PassManager::prepareForCode( - "import raw (\"core/control-context.lp\")\n" - - " convert = function(length:: num)::num{\n" - " 0\n" - " }\n" - - "case context:: milli {\n" - " convert = function(length:: num)::num{\n" - " 1000 * length\n" - " }\n" - "}\n" - "\n" - "case context:: centi {\n" - " convert = function(length:: num)::num{\n" - " 100 * length\n" - " }\n" - "}\n" - "\n" - "calculate = function(length:: num)::num {\n" - " convert(length)\n" - "}\n" - "\n" - "main = function(com:: num):: num; entry {\n" - " switch (com):: num \n" - " case 0 {\n" - " context:: milli.\n" - " calculate(1)\n" - " }\n" - "\n" - " case default{\n" - " context:: centi. \n" - " calculate(1)\n" - " }\n" - "}"); - - man->runWithoutCompilation(); - ContextQuery* queryContext = reinterpret_cast(man->clasp->getQuery(QueryId::ContextQuery)); - Expression exprSwitch = man->root->findFunction("main")->__entry->getBody(); - CodeScope* blockDefault = man->root->findFunction("main")->__entry->getBody().operands[1].blocks.front(); - ScopePacked blockDefaultId = man->clasp->pack(blockDefault); - const Domain& domDefault = queryContext->getContext(blockDefaultId); - ASSERT_EQ(1, domDefault.count(Expression(Atom("centi")))); - - std::list variants = man->root->getFunctionVariants("convert"); - for (ManagedFnPtr f: variants){ - const Expression guard = f->guardContext; - bool result = (guard.getValueString() == "centi" || guard.getValueString() == "milli" || !guard.isValid()); - ASSERT_TRUE(result); - } - - const FunctionDemand& demMain = queryContext->getFunctionDemand("main"); - ASSERT_EQ(0, demMain.size()); - - const FunctionDemand& demCalculate = queryContext->getFunctionDemand("calculate"); - ASSERT_EQ(1, demCalculate.size()); - - int (*entry)(int) = (int (*)(int)) man->run(); - ASSERT_EQ(1000, entry(0)); - ASSERT_EQ(100, entry(1)); -} - -TEST(Context, loopContextExists){ - PassManager* man = PassManager::prepareForCode ( - "import raw (\"core/control-context.lp\")\n" - - "interface(cfa){\n" - " operator fold:: annotation1.\n" - "}\n" - "\n" - "main = function:: int; entry {\n" - " x = [1..10]:: [int].\n" - " sum = loop fold (x->el:: int, 0->sum):: int {\n" - " el + sum + f1()\n" - " }. \n" - " sum\n" - "}" - "case context:: annotation1 {" - " f1 = function::int {\n" - " x = 0:: int. " - " x\n" - " }" - "}" - ); - - man->run(); -} - -TEST(Context, pathDependentContext){ - std::string program = -R"CODE( -import raw("core/control-context.lp") - -convert = function(length:: num) :: num { - 0 -} - -case context:: convert(milli, meters) { - convert = function(length:: num) :: num { - 1000 * length - } -} - -case context:: convert(centi, meters) { - convert = function(length:: num) :: num { - 100 * length - } -} - -case context:: convert(centi, kilo) { - convert = function(length:: num) :: num { - 100000 * length - } -} - -case context:: convert(milli, kilo) { - convert = function(length:: num) :: num { - 1000000 * length - } -} - -main = function(value::num, unitsInput::num, unitsOutput::num)::num; entry{ - switch (unitsInput)::num - case 0 { - test_fromMilli(value, unitsOutput) - } - case 1 { - test_fromCenti(value, unitsOutput) - } - - case default {0} -} - -test_fromCenti = function(value::num, output::num)::num{ - context:: input(centi). - - switch(output):: num - case 0 { - toMeters(value) - } - - case 1 { - toKilo(value) - } - - case default {0} -} - -test_fromMilli = function(value::num, output::num)::num{ - context:: input(milli). - - switch(output):: num - case 0 { - toMeters(value) - } - - case 1 { - toKilo(value) - } - - case default {0} -} - -toMeters = function(value::num)::num { - rule context:: convert(X, meters) case input(X) {true} - - doConvert(value) -} - -toKilo = function(value::num)::num { - rule context:: convert(X, kilo) case input(X) {true} - - doConvert(value) -} - -doConvert = function(value::num)::num{ - convert(value) -})CODE"; - - boost::scoped_ptr man(PassManager::prepareForCode(move(program))); - man->runWithoutCompilation(); - - int (*test)(int, int, int) = (int (*)(int, int, int))man->run(); - - enum {INPUT_MILLI, INPUT_CENTI}; - enum {OUTPUT_METERS, OUTPUT_KILO}; - - ASSERT_EQ(1000000, test(1, INPUT_MILLI, OUTPUT_KILO)); - ASSERT_EQ(200, test(2, INPUT_CENTI, OUTPUT_METERS)); -} - diff --git a/vendors/jeayeson b/vendors/jeayeson index bf3e2ee..20389e5 160000 --- a/vendors/jeayeson +++ b/vendors/jeayeson @@ -1 +1 @@ -Subproject commit bf3e2ee13800d0690d5ed0138ac0af6d2f353bbc +Subproject commit 20389e5ac679f08f0a268ef0886920b1ae3d2d9f