diff --git a/config/default.json b/config/default.json index d52c52a..c5f1fcf 100644 --- a/config/default.json +++ b/config/default.json @@ -1,74 +1,75 @@ { "containers": { "id": { "implementations": "containers_impl", "linkedlist": "linkedlist" }, "impl": { "solid": "solid", "onthefly": "onthefly" } }, "logging": { "id": "logging" }, "function-entry": "entry", "transcend": { "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": "default", "templates": { "troubleshooting":"*", "documentation":"Modules.Doc_*:Modules_API.Doc_*:Interpretation.Doc_*:AST.Doc_*:Loop.Doc_*:LateReasoning.Doc_*:Latex.Doc_*:Polymorphs.Doc_*:Transcend.Doc_*:ASTCorrespondence.Doc_*:Virtualization.Doc_*:Exploitation.Doc_*:Communication.Doc_*:Introduction.*", "default": "*", + "universal": "Universal.*", "ast": "AST.*", "effects": "Effects.*", "basic": "Attachments.*", "compilation": "Compilation.*", "communication": "Communication.*", "cfa": "CFA.*", "containers": "Containers.*", "dfa": "DFA.*", "diagnostic": "Diagnostic.*", "dsl": "Association.*:Interpretation.*", "exploitation": "Exploitation.*", "ExpressionSerializer": "ExpressionSerializer.*", "externc": "InterfaceExternC.*", "loops": "Loop.*", "latereasoning": "LateReasoning.*", "latex": "Latex.*", "modules": "Modules.*", "polymorphs": "Polymorphs.*", "intrinsic-query": "Types.SlaveTypes*:Association.TypedQuery*", "types": "Types.*", "virtualization": "Virtualization.*", "vendorsAPI/clang": "ClangAPI.*", "vendorsAPI/xml2": "libxml2.*" } } } diff --git a/cpp/src/CMakeLists.txt b/cpp/src/CMakeLists.txt index 44d1d1c..ff23a2c 100644 --- a/cpp/src/CMakeLists.txt +++ b/cpp/src/CMakeLists.txt @@ -1,238 +1,247 @@ cmake_minimum_required(VERSION 2.8.11) project(xreate) cmake_policy(SET CMP0022 NEW) message("MODULES" ${CMAKE_MODULE_PATH}) # LLVM #====================== FIND_PACKAGE (LLVM REQUIRED) set(LLVM_VERSION ${LLVM_VERSION_MAJOR}.${LLVM_VERSION_MINOR}) message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}") message("LLVM LIB PATH:" ${LLVM_LIBRARY_DIRS}) message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}") INCLUDE_DIRECTORIES(${LLVM_INCLUDE_DIRS}) message(STATUS "INCLUDE DIR: ${LLVM_INCLUDE_DIRS}") add_definitions(${LLVM_DEFINITIONS}) message(STATUS "LLVM DEFS: " ${LLVM_DEFINITIONS}) execute_process( COMMAND llvm-config --libs OUTPUT_VARIABLE LLVM_LIBS OUTPUT_STRIP_TRAILING_WHITESPACE) message(STATUS "LLVM LIBS: " ${LLVM_LIBS}) # CLANG #====================== set(CLANG_LIBS clangCodeGen clangASTMatchers clangQuery clangTooling clangFrontend clangSerialization clangDriver clangParse clangSema clangAnalysis clangAST clangEdit clangLex clangBasic ) # POTASSCO #====================== set(CLINGO_PATH "/opt/potassco/clingo" CACHE PATH "Path to potassco sources") set(POTASSCO_INCLUDE_PATH ${CLINGO_PATH}/libgringo ${CLINGO_PATH}/libclasp ${CLINGO_PATH}/libclingo ${CLINGO_PATH}/libprogram_opts ${CLINGO_PATH}/liblp ) INCLUDE_DIRECTORIES(${POTASSCO_INCLUDE_PATH}) set(LIBCLASP_LIBS clingo clasp gringo program_opts reify lp ) message("CLASP LIBS: " ${LIBCLASP_LIBS}) # OTHER DEPENDENCIES #=========================== set(JEAYESON_INCLUDE_PATH ${CMAKE_HOME_DIRECTORY}/../vendors/jeayeson/include/ ) INCLUDE_DIRECTORIES(${JEAYESON_INCLUDE_PATH}) # COCO #=========================== set(COCO_EXECUTABLE "" CACHE PATH "Path to coco executable") set(COCO_FRAMES_PATH "" CACHE PATH "Path to coco frames") set(COCO_GRAMMAR_PATH ${CMAKE_HOME_DIRECTORY}/../grammar/) set(COCO_SOURCE_FILES_MAIN ${COCO_GRAMMAR_PATH}/main/Parser.cpp ${COCO_GRAMMAR_PATH}/main/Scanner.cpp ) set(COCO_SOURCE_FILES_MODULES ${COCO_GRAMMAR_PATH}/modules/Parser.cpp ${COCO_GRAMMAR_PATH}/modules/Scanner.cpp ) -set(COCO_SOURCE_FILES ${COCO_SOURCE_FILES_MODULES} ${COCO_SOURCE_FILES_MAIN}) +set(COCO_SOURCE_FILES_UNIVERSAL + ${COCO_GRAMMAR_PATH}/universal/Parser.cpp + ${COCO_GRAMMAR_PATH}/universal/Scanner.cpp +) + +set(COCO_SOURCE_FILES + ${COCO_SOURCE_FILES_MODULES} + ${COCO_SOURCE_FILES_MAIN} + ${COCO_SOURCE_FILES_UNIVERSAL} +) INCLUDE_DIRECTORIES(${COCO_GRAMMAR_PATH}) add_custom_command(OUTPUT ${COCO_SOURCE_FILES_MAIN} COMMAND ${COCO_GRAMMAR_PATH}/gen-grammar main ${COCO_EXECUTABLE} ${COCO_FRAMES_PATH} WORKING_DIRECTORY ${COCO_GRAMMAR_PATH} MAIN_DEPENDENCY ${COCO_GRAMMAR_PATH}/xreate.ATG ) add_custom_command(OUTPUT ${COCO_SOURCE_FILES_MODULES} COMMAND ${COCO_GRAMMAR_PATH}/gen-grammar modules ${COCO_EXECUTABLE} ${COCO_FRAMES_PATH} WORKING_DIRECTORY ${COCO_GRAMMAR_PATH} MAIN_DEPENDENCY ${COCO_GRAMMAR_PATH}/modules.ATG ) message(STATUS "COCO GRAMMAR BUILD STATUS:" ${COCO_OUTPUT}) # XREATE #====================== set(SOURCE_FILES analysis/temporalseqgraph.cpp pass/cfatemporalseqpass.cpp analysis/cfagraph.cpp pass/cfapass.cpp modules.cpp compilation/interpretation-instructions.cpp ExternLayer.cpp analysis/cfagraph.cpp compilation/latetranscend.cpp analysis/interpretation.cpp query/latex.cpp query/polymorph.cpp compilation/polymorph.cpp aux/latereasoning.cpp compilation/latex.cpp analysis/typeinference.cpp xreatemanager.cpp transcendlayer.cpp analysis/dfagraph.cpp llvmlayer.cpp pass/compilepass.cpp analysis/utils.cpp pass/dfapass.cpp compilation/targetinterpretation.cpp pass/interpretationpass.cpp ast.cpp aux/xreatemanager-decorators.cpp compilation/operators.cpp compilation/transformations.cpp compilation/transformersaturation.cpp pass/versionspass.cpp attachments.cpp compilation/containers.cpp compilation/advancedinstructions.cpp utils.cpp pass/abstractpass.cpp contextrule.cpp query/containers.cpp aux/serialization/expressionserializer.cpp ) set(XREATE_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/ ) INCLUDE_DIRECTORIES(${XREATE_INCLUDE_DIRS}) set(XREATE_PRIVATE_INCLUDE_DIRS ${XREATE_INCLUDE_DIRS} ${COCO_GRAMMAR_PATH} ${JEAYESON_INCLUDE_PATH} ${LLVM_INCLUDE_DIRS} ${POTASSCO_INCLUDE_PATH} ) add_library(${PROJECT_NAME} SHARED ${COCO_SOURCE_FILES} ${SOURCE_FILES}) target_link_libraries(${PROJECT_NAME}) target_include_directories(${PROJECT_NAME} INTERFACE ${XREATE_INCLUDE_DIRS} ${COCO_GRAMMAR_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 ${LIBCLASP_LIBS} ${CLANG_LIBS} ${LLVM_LIBS} tbb boost_system boost_filesystem ) #${CLANG_LIBS} #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/analysis/cfagraph.cpp b/cpp/src/analysis/cfagraph.cpp index 17639e3..2e24ca2 100644 --- a/cpp/src/analysis/cfagraph.cpp +++ b/cpp/src/analysis/cfagraph.cpp @@ -1,191 +1,181 @@ /* 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/. * * File: CFAGraph.cpp * Author: pgess * * Created on June 27, 2016, 2:09 PM */ /** * \file cfagraph.h * \brief Control Flow Analysis(CFA) graph representation */ #include "analysis/cfagraph.h" #include "analysis/utils.h" using namespace xreate::cfa; using namespace std; void CFAGraph::print(std::ostringstream& output) const { const std::string& atomBinding = Config::get("transcend.bindings.function"); const std::string& atomBindingScope = Config::get("transcend.bindings.scope"); output << endl << "%\t\tStatic analysis: CFA" << endl; output << __outputPrecomputed.str(); //show function tags int counterTags = 0; - std::ostringstream bufFunctionNames; - boost::format formatFunction("function(%1%)."); - boost::format formatBind(atomBinding + "(%1%, %2%)."); + boost::format formatFunction("function(\"%1%\")."); + boost::format formatBind(atomBinding + "(\"%1%\", %2%)."); for (auto function : this->__fnNodes.left) { const auto tags = this->__fnTags.equal_range(function.first); - if (tags.first == tags.second) { - //no tags - bufFunctionNames << "; " << function.second ; - continue; - } - output << formatFunction % (function.second) << std::endl; + for (const auto& tag_ : boost::make_iterator_range(tags)) { const Expression& tag = tag_.second; list tagRaw = xreate::analysis::compile(tag); assert(tagRaw.size() == 1); output << formatBind % (function.second) % (tagRaw.front()) << endl; ++counterTags; } } - if (bufFunctionNames.tellp()) { - output << formatFunction % (bufFunctionNames.str().substr(2)) << std::endl; - } - if (counterTags == 0) { output << "%no function tags at all" << endl; } //declare scopes boost::format formatScope("scope(0..%1%)."); output << formatScope % (__transcend->getScopesCount() - 1) << std::endl; //show context rules: for (auto rule : this->__contextRules) { output << ContextRule(rule.second).compile(rule.first) << std::endl; }; //show scope tags: counterTags = 0; boost::format formatScopeBind(atomBindingScope + "(%1%, %2%, strong)."); for (auto entry : this->__scopeTags) { ScopePacked scopeId = entry.first; const Expression& tag = entry.second; list tagRaw = xreate::analysis::compile(tag); assert(tagRaw.size() == 1); output << formatScopeBind % scopeId % (tagRaw.front()) << endl; ++counterTags; } if (counterTags == 0) { output << "%scope tags: no tags at all" << endl; } //parent connections //TOTEST CFG parent function - boost::format formatFunctionParent("cfa_parent(%1%, function(%2%))."); + boost::format formatFunctionParent("cfa_parent(%1%, function(\"%2%\"))."); for (const auto &relation : this->__parentFnRelation) { const string& function = this->__fnNodes.left.at(relation.right); output << formatFunctionParent % relation.left % function << endl; } //TOTEST CFG parent scope boost::format formatScopeParent("cfa_parent(%1%, scope(%2%))."); for (const auto &relation : this->__parentScopeRelation) { output << formatScopeParent % relation.first % relation.second << endl; } //call connections - boost::format formatCall("cfa_call(%1%, %2%)."); + boost::format formatCall("cfa_call(%1%, \"%2%\")."); for (const auto &relation : this->__callRelations) { const ScopePacked scopeFrom = relation.left; const string& functionTo = this->__fnNodes.left.at(relation.right); output << formatCall % (scopeFrom) % (functionTo) << endl; } //function specializations description - boost::format formatSpecializations("cfa_function_specializations(%1%, %2%)."); + boost::format formatSpecializations("cfa_function_specializations(\"%1%\", %2%)."); const list& functions = __transcend->ast->getAllFunctions(); for (auto f : functions) { if (f->guard.isValid()) { list guardRaw = xreate::analysis::compile(f->guard); assert(guardRaw.size() == 1); output << formatSpecializations % (f->getName()) % (guardRaw.front()) << endl; } } } void CFAGraph::addFunctionAnnotations(const std::string& fn, const std::map& tags) { unsigned int fid = registerNodeFunction(fn); for (auto& tag : tags) { __fnTags.emplace(fid, tag.second); } } void CFAGraph::addScopeAnnotations(const ScopePacked& scope, const std::vector& tags) { for (Expression tag : tags) { __scopeTags.emplace(scope, tag); } } void CFAGraph::addContextRules(const ScopePacked& scope, const std::vector& rules) { for (Expression rule : rules) { __contextRules.emplace(scope, rule); } } void CFAGraph::addCallConnection(const ScopePacked& callerScope, const std::string& calleeFn) { unsigned int idFuncTo = registerNodeFunction(calleeFn); __callRelations.insert(CALL_RELATIONS::value_type(callerScope, idFuncTo)); } void CFAGraph::addParentConnection(const ScopePacked& scopeEntry, const std::string& fnParent) { __parentFnRelation.insert(PARENT_FUNCTION_RELATIONS::value_type(scopeEntry, registerNodeFunction(fnParent))); } void CFAGraph::addParentConnection(const ScopePacked& scopeChild, const ScopePacked& scopeParent) { __parentScopeRelation.emplace(scopeChild, scopeParent); } unsigned int CFAGraph::registerNodeFunction(const std::string& fname) { auto pos = __fnNodes.left.insert(make_pair(__fnNodes.size(), fname)); return pos.first->first; } void CFAGraph::addScope(CodeScope* scope) { boost::format formatScopeBinding("ast_scope_binding(%1%, %2%, \"%3%\")."); ScopePacked scopeId = __transcend->pack(scope); __scopesCount = max(scopeId + 1, __scopesCount); for (int id = 0, size = scope->__bindings.size(); id < size; ++id) { __outputPrecomputed << formatScopeBinding % scopeId % id % scope->__bindings.at(id) << endl; } } diff --git a/cpp/src/analysis/dfagraph.cpp b/cpp/src/analysis/dfagraph.cpp index 7eebd53..2ced918 100644 --- a/cpp/src/analysis/dfagraph.cpp +++ b/cpp/src/analysis/dfagraph.cpp @@ -1,244 +1,244 @@ /* 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/. * * File: DFAGraph.h * Author: pgess * */ /** * \file dfagraph.h * \brief Data Flow Analysis(DFA) graph representation * */ #include "analysis/dfagraph.h" #include "analysis/utils.h" using namespace std; using namespace xreate::analysis; namespace xreate { namespace dfa { void DFACallInstance::print(std::ostringstream& output) const{ boost::format formatArgs; - boost::format formatInstance("dfa_callfn(%1%, %2%)."); + boost::format formatInstance("dfa_callfn(%1%, \"%2%\")."); switch (type) { case WEAK: formatArgs = boost::format("weak(dfa_callargs(%1%, %2%, %3%))."); break; case STRONG: formatArgs = boost::format("weak(dfa_callargs(%1%, %2%, %3%)).\ndfa_callargs(%1%, %2%, %3%)."); break; } output << formatInstance % analysis::writeSymbolNode(retActual) % fnName << endl; for(std::pair rec: args) { SymbolNode argFormal(rec.first); output << formatArgs % analysis::writeSymbolNode(retActual) % analysis::writeSymbolNode(argFormal) % analysis::writeSymbolNode(rec.second) << endl; } } void DFAGraph::addDependency(const SymbolNode& node, const SymbolNode& subnode){ __dependencies.emplace(node, subnode); if (boost::get(&node)){ __usedSymbols.insert(node); } if (boost::get(&subnode)){ __usedSymbols.insert(node); } } void DFAGraph::printDependencies(std::ostringstream& output) const{ for(const SymbolNode& root: __roots){ printDependency(output, root, root); } } void DFAGraph::printDependency(std::ostringstream& output, const SymbolNode& nodeCurrent, const SymbolNode& nodeDependent) const { auto range = __dependencies.equal_range(nodeCurrent); for (auto it = range.first; it != range.second; ++it){ if (boost::get(&it->second)){ if (!__usedSymbols.count(it->second)){ printDependency(output, it->second, nodeDependent); continue; } } boost::format formatDependency("dfa_depends(%1%, %2%)."); output << formatDependency % analysis::writeSymbolNode(nodeDependent) % analysis::writeSymbolNode(it->second) << endl; printDependency(output, it->second, it->second); } } void DFAGraph::printInplaceAnnotation(const SymbolNode& node, const Expression& expression) { // write down in-place expression tags: boost::format formatBind("bind(%1%, %2%)."); __usedSymbols.insert(node); for (const string& tag: xreate::analysis::compile(expression)) { __output << formatBind % analysis::writeSymbolNode(node) % tag << endl; } } void DFAGraph::printLateAnnotation(const SymbolNode& node, const Expression& expression, const std::list& symbols, const std::list& domains){ boost::format formatLateAnnotation("late(%1%, (%2%), (%3%), %4%):- %5%."); boost::format formatDom("%1%(%2%)"); std::list exprSerialized = xreate::analysis::compile(expression); assert(exprSerialized.size() == 1); list identSymbols, identNames, domainsSerialised; auto domainI = domains.begin(); for(auto symbol: symbols){ identSymbols.push_back(analysis::writeSymbolNode(symbol.second).str()); identNames.push_back(symbol.first); domainsSerialised.push_back((formatDom % *domainI % symbol.first).str()); ++domainI; } __output << formatLateAnnotation % analysis::writeSymbolNode(node) % boost::algorithm::join(identSymbols, ", ") % boost::algorithm::join(identNames, ", ") % exprSerialized.front() % boost::algorithm::join(domainsSerialised, "; ") << endl; } void DFAGraph::printAlias(const SymbolNode& symbFormal, const SymbolNode& symbActual){ __usedSymbols.insert(symbFormal); __usedSymbols.insert(symbActual); boost::format formatAlias("dfa_alias(%1%, %2%)."); __output << formatAlias % analysis::writeSymbolNode(symbFormal) % analysis::writeSymbolNode(symbActual) << endl; } void DFAGraph::printWeakAlias(const SymbolNode& symbFormal, const SymbolNode& symbActual){ __usedSymbols.insert(symbFormal); __usedSymbols.insert(symbActual); boost::format formatAlias("weak(dfa_alias(%1%, %2%))."); __output << formatAlias % analysis::writeSymbolNode(symbFormal) % analysis::writeSymbolNode(symbActual) << endl; } void DFAGraph::printFunctionRet(ManagedFnPtr function, const SymbolNode& symbolRet){ - boost::format formatRet("dfa_fnret(%1%, %2%)."); + boost::format formatRet("dfa_fnret(\"%1%\", %2%)."); __usedSymbols.insert(symbolRet); __output << formatRet % function->getName() % analysis::writeSymbolNode(symbolRet) << endl; __roots.insert(symbolRet); } void DFAGraph::addCallInstance(DFACallInstance&& instance){ __usedSymbols.insert(instance.retActual); for(const auto arg: instance.args){ __usedSymbols.insert(SymbolNode(arg.first)); __usedSymbols.insert(arg.second); } __callInstances.push_back(std::move(instance)); } void DFAGraph::print(std::ostringstream& output) const{ output << endl << "%\t\tStatic analysis: DFA" << endl; //Dependencies printDependencies(output); //Add generated report output << __output.str() << endl; //Call instances for(const DFACallInstance& instance: __callInstances){ instance.print(output); } output << endl; } void DFAGraph::printSymbols(TranscendLayer* transcend){ boost::format formatHint("shint(%1%, \"%2%\")."); for (const SymbolNode& node : __usedSymbols) { __output << "v(" << analysis::writeSymbolNode(node) << "). "; if (const SymbolPacked* symbol = boost::get(&node)){ __output << formatHint % analysis::writeSymbolNode(node) % transcend->getHintForPackedSymbol(*symbol); } __output << endl; } } void DFAGraph::printOperator(Operator op, std::list&& operands, int dataOpListSize){ std::string opStr; switch(op){ case Operator::MAP: opStr = "map"; break; case Operator::FOLD: opStr = "fold"; break; case Operator::LIST: opStr = "list"; break; case Operator::LIST_RANGE: opStr = "list_range"; break; case Operator::INDEX: opStr = "index"; break; default: assert(false); } std::ostringstream bufOperands; for(const SymbolNode& operand: operands){ __usedSymbols.insert(operand); bufOperands << analysis::writeSymbolNode(operand) << ", "; } if(op == Operator::LIST){ bufOperands << dataOpListSize << ", "; } boost::format formatOperator("ast_op_%1%(%2%)."); __output << (formatOperator % opStr % bufOperands.str().substr(0, bufOperands.str().size() - 2)) << endl; } }} //end of namespace xreate::dfa diff --git a/cpp/src/aux/universal.h b/cpp/src/aux/universal.h new file mode 100644 index 0000000..6468eae --- /dev/null +++ b/cpp/src/aux/universal.h @@ -0,0 +1,15 @@ +#include +#include "utils.h" +#include +#include +#include + +#define wprintf(format, ...) \ + char __buffer[100]; \ + wcstombs(__buffer, format, 100); \ + fprintf(stderr, __buffer, __VA_ARGS__) + +void +send(const std::wstring& message){ + std::cout << wstring_to_utf8(message) << std::endl; +} \ No newline at end of file diff --git a/cpp/src/aux/xreatemanager-decorators.cpp b/cpp/src/aux/xreatemanager-decorators.cpp index 2b4038d..37ec862 100644 --- a/cpp/src/aux/xreatemanager-decorators.cpp +++ b/cpp/src/aux/xreatemanager-decorators.cpp @@ -1,77 +1,77 @@ /* 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/. * * xreatemanager-decorators.cpp * * Author: pgess * Created on July 16, 2017, 4:40 PM */ /** * \file xreatemanager-decorators.h * \brief \ref xreate::XreateManager decorators to provide various functionality */ #include "aux/xreatemanager-decorators.h" #include "main/Parser.h" #include "pass/compilepass.h" #include "pass/cfapass.h" #include "pass/dfapass.h" #include "pass/interpretationpass.h" #include "pass/versionspass.h" #include "pass/cfatemporalseqpass.h" namespace xreate{ void XreateManagerDecoratorBase::initPasses() { } void XreateManagerDecoratorBase::prepareCode(std::string&& code) { - grammar::main::Scanner scanner(reinterpret_cast (code.c_str()), code.size()); - grammar::main::Parser parser(&scanner); - parser.Parse(); - assert(!parser.errors->count && "Parser errors"); + grammar::main::Scanner scanner(reinterpret_cast (code.c_str()), code.size()); + grammar::main::Parser parser(&scanner); + parser.Parse(); + assert(!parser.errors->count && "Parser errors"); - PassManager::prepare(parser.root->finalize()); + PassManager::prepare(parser.root->finalize()); } void -XreateManagerDecoratorBase::prepareCode(FILE* code) { - grammar::main::Scanner scanner(code); - grammar::main::Parser parser(&scanner); - parser.Parse(); - assert(!parser.errors->count && "Parser errors"); +XreateManagerDecoratorBase::prepareCode(FILE* code){ + grammar::main::Scanner scanner(code); + grammar::main::Parser parser(&scanner); + parser.Parse(); + assert(!parser.errors->count && "Parser errors"); - PassManager::prepare(parser.root->finalize()); + PassManager::prepare(parser.root->finalize()); } void XreateManagerDecoratorBase::analyse() { CompilePass::prepareQueries(transcend); transcend->run(); } void XreateManagerDecoratorFull::initPasses() { cfa::CFAPass* passCFG = new cfa::CFAPass(this); registerPass(new dfa::DFAPass(this), PassId::DFAPass); registerPass(passCFG, PassId::CFAPass); registerPass(new interpretation::InterpretationPass(this), PassId::InterpretationPass); registerPass(new versions::VersionsPass(this), PassId::VersionsPass); registerPass(new cfa::CFATemporalSeqPass(this), PassId::CFATemporalSeqPass); } void* XreateManagerDecoratorFull::run() { transcend->deleteReports(); std::unique_ptr compiler(new compilation::CompilePassCustomDecorators<>(this)); compiler->run(); llvm->print(); llvm->initJit(); return llvm->getFunctionPointer(compiler->getEntryFunction()); } } //namespace xreate diff --git a/cpp/src/compilation/latex.h b/cpp/src/compilation/latex.h index e35ffeb..cbb7529 100644 --- a/cpp/src/compilation/latex.h +++ b/cpp/src/compilation/latex.h @@ -1,144 +1,145 @@ /* * 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 * Created on June 23, 2018, 2:51 PM * * \file latex.h * \brief latex */ #ifndef LATEX_H #define LATEX_H #include "compilation/latetranscend.h" #include "compilation/interpretation-instructions.h" #include "query/latex.h" #include "pass/compilepass.h" #include "analysis/interpretation.h" #include "compilation/targetinterpretation.h" namespace xreate{ namespace latex{ ExpandedType -getSubjectDomain(const std::string& subject, LatexQuery* query); +getSubjectDomain(const std::string &subject, LatexQuery *query); /** \brief Latex(Late Context)-aware decorator for \ref xreate::compilation::IFunctionUnit * \extends xreate::compilation::IFunctionUnit */ template -class LatexBruteFunctionDecorator: public Parent{ +class LatexBruteFunctionDecorator : public Parent{ public: - LatexBruteFunctionDecorator(ManagedFnPtr f, CompilePass* p) - : Parent(f, p){ - __query = reinterpret_cast (Parent::pass->man->transcend->getQuery(QueryId::LatexQuery)); - } + LatexBruteFunctionDecorator(ManagedFnPtr f, CompilePass *p) + : Parent(f, p){ + __query = reinterpret_cast (Parent::pass->man->transcend->getQuery(QueryId::LatexQuery)); + } protected: - std::vector - prepareSignature(){ - std::vector&& signature = Parent::prepareSignature(); - - const Demand& demand = __query->getFnDemand(Parent::function->getName()); - signature.reserve(signature.size() + demand.size()); - - int subjectId = __query->LatexParametersOffset; - for(const std::string& subject: demand){ - const ExpandedType& subjectT = getSubjectDomain(subject, __query); - Expression bindingE; - bindingE.type = subjectT; - std::string argCaption = std::string("latex_") + subject; - Parent::function->addBinding( - Atom(std::string(argCaption)), - std::move(bindingE), - subjectId++); - - llvm::Type* subjectTRaw = Parent::pass->man->llvm->toLLVMType(subjectT); - signature.push_back(subjectTRaw); - } - - return signature; - } + std::vector + prepareSignature(){ + std::vector &&signature = Parent::prepareSignature(); + + const Demand &demand = __query->getFnDemand(Parent::function->getName()); + signature.reserve(signature.size() + demand.size()); + + int subjectId = __query->LatexParametersOffset; + for(const std::string &subject: demand){ + const ExpandedType &subjectT = getSubjectDomain(subject, __query); + Expression bindingE; + bindingE.type = subjectT; + std::string argCaption = std::string("latex_") + subject; + Parent::function->addBinding( + Atom(std::string(argCaption)), + std::move(bindingE), + subjectId++); + + llvm::Type *subjectTRaw = Parent::pass->man->llvm->toLLVMType(subjectT); + signature.push_back(subjectTRaw); + } + + return signature; + } public: - LatexQuery* __query; + LatexQuery *__query; }; /** \brief %Function invocation operator decorator to handle latex enabled functions with hidden extra arguments */ -class ExtraArgsFnInvocation: public compilation::IFnInvocation{ +class ExtraArgsFnInvocation : public compilation::IFnInvocation{ public: - ExtraArgsFnInvocation(std::vector argsLatex, compilation::IFnInvocation* parent) - : __argsLatex(argsLatex), __parent(parent){ } + ExtraArgsFnInvocation(std::vector argsLatex, compilation::IFnInvocation *parent) + : __argsLatex(argsLatex), __parent(parent){} - llvm::Value* operator()(std::vector&& args, const std::string& hintDecl = ""); + llvm::Value *operator()(std::vector &&args, const std::string &hintDecl = ""); private: - std::vector __argsLatex; - compilation::IFnInvocation* __parent; + std::vector __argsLatex; + compilation::IFnInvocation *__parent; }; /** * \brief Latex aware \ref xreate::compilation::ICodeScopeUnit decorator * \implements xreate::compilation::ICodeScopeUnit */ template -class LatexBruteScopeDecorator: public Parent{ +class LatexBruteScopeDecorator : public Parent{ public: - LatexBruteScopeDecorator(const CodeScope * const codeScope, compilation::IFunctionUnit* f, CompilePass* compilePass) - : Parent(codeScope, f, compilePass){ } - - compilation::IFnInvocation* - findFunction(const Expression& opCall){ - compilation::IFnInvocation* invocDefault = Parent::findFunction(opCall); - const std::string& calleeName = opCall.getValueString(); - LatexQuery* query = reinterpret_cast (Parent::pass->man->transcend->getQuery(QueryId::LatexQuery)); - - const Demand& fnCalleeDemand = query->getFnDemand(calleeName); - if(!fnCalleeDemand.size()) return invocDefault; - - //prepare latex arguments - std::vector argsLatex; - argsLatex.reserve(fnCalleeDemand.size()); - - for(const std::string& subject: fnCalleeDemand){ - ExpandedType subjectT = getSubjectDomain(subject, query); - llvm::Type* subjectTRaw = Parent::pass->man->llvm->toLLVMType(subjectT); - const latereasoning::LateAnnotation& decision = query->getDecision(subject, Parent::scope); - - compilation::Context ctx{this, Parent::function, Parent::pass}; - interpretation::InterpretationScope* scopeIntrpr = - Parent::pass->targetInterpretation->transformContext(ctx); - latereasoning::LateReasoningCompiler* compiler - = new latereasoning::LateReasoningCompiler(dynamic_cast(scopeIntrpr->function), ctx); - - llvm::Value* subjectRaw = compiler->compileAutoExpand( - decision, - subjectTRaw, - subject, - [&](const Gringo::Symbol & decisionRaw){ - const Expression& decisionE = interpretation::representTransExpression( - decisionRaw.args()[2], subjectT, Parent::pass->man->transcend); + LatexBruteScopeDecorator(const CodeScope *const codeScope, compilation::IFunctionUnit *f, CompilePass *compilePass) + : Parent(codeScope, f, compilePass){} + + compilation::IFnInvocation * + findFunction(const Expression &opCall){ + compilation::IFnInvocation *invocDefault = Parent::findFunction(opCall); + const std::string &calleeName = opCall.getValueString(); + LatexQuery *query = reinterpret_cast (Parent::pass->man->transcend->getQuery(QueryId::LatexQuery)); + + const Demand &fnCalleeDemand = query->getFnDemand(calleeName); + if(!fnCalleeDemand.size()) return invocDefault; + + //prepare latex arguments + std::vector argsLatex; + argsLatex.reserve(fnCalleeDemand.size()); + + for(const std::string &subject: fnCalleeDemand){ + ExpandedType subjectT = getSubjectDomain(subject, query); + llvm::Type *subjectTRaw = Parent::pass->man->llvm->toLLVMType(subjectT); + const latereasoning::LateAnnotation &decision = query->getDecision(subject, Parent::scope); + + compilation::Context ctx{this, Parent::function, Parent::pass}; + interpretation::InterpretationScope *scopeIntrpr = + Parent::pass->targetInterpretation->transformContext(ctx); + latereasoning::LateReasoningCompiler *compiler + = new latereasoning::LateReasoningCompiler( + dynamic_cast(scopeIntrpr->function), ctx); + + llvm::Value *subjectRaw = compiler->compileAutoExpand( + decision, + subjectTRaw, + subject, + [&](const Gringo::Symbol &decisionRaw){ + const Expression &decisionE = interpretation::representTransExpression( + decisionRaw.args()[2], subjectT, Parent::pass->man->transcend); Attachments::put(decisionE, subjectT); return Parent::process(decisionE, subject); - }); + }); - argsLatex.push_back(subjectRaw); - } + argsLatex.push_back(subjectRaw); + } - return new ExtraArgsFnInvocation(std::move(argsLatex), invocDefault); - } + return new ExtraArgsFnInvocation(std::move(argsLatex), invocDefault); + } }; } } //end of namespace xreate::context #endif /* LATEX_H */ diff --git a/cpp/tests/CMakeLists.txt b/cpp/tests/CMakeLists.txt index 2890e4b..188831b 100644 --- a/cpp/tests/CMakeLists.txt +++ b/cpp/tests/CMakeLists.txt @@ -1,60 +1,61 @@ cmake_minimum_required(VERSION 2.8.11) project(xreate-tests) find_package(GTest REQUIRED) INCLUDE_DIRECTORIES(${GTEST_INCLUDE_DIRS}) INCLUDE_DIRECTORIES("/usr/include/libxml2") INCLUDE_DIRECTORIES($) # TESTS #========================= FIND_PACKAGE (LLVM REQUIRED) message("LLVM_LIBRARY_DIRS: " ${LLVM_LIBRARY_DIRS}) link_directories(${LLVM_LIBRARY_DIRS}) -set (LIBCLASP_PATH ${POTASSCO_PATH}/build/debug) +set (LIBCLASP_PATH ${CLINGO_PATH}/build/debug) link_directories(${LIBCLASP_PATH}) #aux_source_directory(. TEST_FILES) set(TEST_FILES + universal.cpp introduction.cpp unit-test-example.cpp transcend-ast.cpp supplemental/docutils latetranscend.cpp cfa.cpp latex.cpp polymorph.cpp transcend.cpp virtualization.cpp exploitation.cpp effects-communication.cpp association.cpp main.cpp modules.cpp attachments.cpp ast.cpp dfa.cpp compilation.cpp ExpressionSerializer.cpp externc.cpp types.cpp #vendorsAPI/clangAPI.cpp #vendorsAPI/xml2.cpp #vendorsAPI/json.cpp containers.cpp interpretation.cpp loops.cpp #supplemental/versions-algorithm-data_dependency.cpp effects-versions.cpp ) add_executable(${PROJECT_NAME} ${TEST_FILES}) target_link_libraries(${PROJECT_NAME} xreate ${GTEST_LIBRARIES} pthread xml2 gcov) add_custom_target (coverage COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/src/code-coverage.sh WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) diff --git a/cpp/tests/ast.cpp b/cpp/tests/ast.cpp index 1a6c65a..15c70c9 100644 --- a/cpp/tests/ast.cpp +++ b/cpp/tests/ast.cpp @@ -1,254 +1,264 @@ /* Any copyright is dedicated to the Public Domain. * http://creativecommons.org/publicdomain/zero/1.0/ * * ast.cpp * * Created on: Jun 11, 2015 * Author: pgess */ #include "supplemental/docutils.h" #include "xreatemanager.h" #include "main/Parser.h" #include "supplemental/defines.h" #include "gtest/gtest.h" using namespace std; using namespace xreate; using namespace xreate::grammar::main; TEST(AST, Containers1) { FILE* input = fopen("scripts/containers/Containers_Implementation_LinkedList1.xreate", "r"); Scanner scanner(input); Parser parser(&scanner); parser.Parse(); assert(!parser.errors->count && "Parser errors"); fclose(input); } TEST(AST, InterfacesDataCFA) { XreateManager* man = XreateManager::prepare ("interface(cfa){\n" " operator map :: annotation1.\n" "}"); auto answer = man->root->__interfacesData.equal_range(CFA); EXPECT_EQ(1, std::distance(answer.first, answer.second)); Expression&& scheme = move(answer.first->second); EXPECT_EQ(Operator::MAP, scheme.op); EXPECT_EQ("annotation1", scheme.getOperands().at(0).getValueString()); } TEST(AST, syntax_recognizeIdentifiers) { XreateManager* man = XreateManager::prepare(R"Code( test= function(a:: num):: num; entry { a = b:: int. b = 8:: int. a } )Code"); } TEST(AST, syntax_operatorIndex) { XreateManager* man = XreateManager::prepare(R"Code( test= function(a:: num):: num; entry { b = a[1]. b } )Code"); } +TEST(AST, IdentHyphen1){ + XreateManager* man = XreateManager::prepare(R"Code( + my-fn = function(m-n:: num):: num; entry + { + b = m-n-1:: int. + b + } + )Code"); +} + TEST(AST, Variants_switch) { XreateManager* man = XreateManager::prepare(R"Code( Color = type variant{Blue, White, Green}. main = function:: int { x = White()::Color. switch variant(x)::int case (Green) {0} case (White) {1} case (Blue){2} } )Code"); Expression e = man->root->findFunction("main")->getEntryScope()->getBody(); ASSERT_EQ(4, e.getOperands().size()); ASSERT_EQ(3, e.blocks.size()); } TEST(AST, DISABLED_InterfacesDataDFA) { } TEST(AST, DISABLED_InterfacesDataExtern) { } TEST(AST, Doc_LiteralsAndExpressions) { XreateManager* man = XreateManager::prepare( R"Code( Record1 = type {year:: int, month:: string}. isOdd = function(x :: int) :: bool {true} test = function:: bool; entry { x1 = 5 :: int. x2 = "Nimefurahi kukujua":: string. x3 = {year = 1934, month = "april"}:: Record1. x4 = {16, 8, 3} :: [int]. x41 = [1..18]:: [int]. x5 = 8>=3:: bool. x6 = "Blue" <> "Green" :: bool. x7 = -true:: bool. colors = {"Green", "Blue"} :: [string]. color = colors[0] :: string. date = {year = 1934, month = "april"}:: Record1. year = date["year"] :: int. a = 0::int. b = 0 :: int. x7 = a - b:: int. result = isOdd(6) :: bool. true } )Code"); ASSERT_TRUE(true); } TEST(AST, Doc_CodeBlocks1) { XreateManager* man = XreateManager::prepare( getDocumentationExampleById("documentation/Syntax/syntax.xml", "CodeBlocks1")); FnNoArgs resultFn = (FnNoArgs) man->run(); int resultExpected = resultFn(); ASSERT_EQ(12, resultExpected); } TEST(AST, Doc_Functions1) { XreateManager* man = XreateManager::prepare( getDocumentationExampleById("documentation/Syntax/syntax.xml", "Functions1")); ASSERT_TRUE(true); } TEST(AST, Doc_FunctionSpecializations1) { XreateManager* man = XreateManager::prepare( getDocumentationExampleById("documentation/Syntax/syntax.xml", "FunctionSpecialization1")); ASSERT_TRUE(true); } TEST(AST, Doc_BranchStatements) { string code_IfStatement1 = getDocumentationExampleById("documentation/Syntax/syntax.xml", "IfStatement1"); string code_SwitchStatement1 = getDocumentationExampleById("documentation/Syntax/syntax.xml", "SwitchStatement1"); string code = R"Code( test = function:: int; entry { question = "Favorite color?":: string. monthNum = 2:: int. %IfStatement1 %SwitchStatement1 monthName } )Code"; replace(code, "%IfStatement1", code_IfStatement1); replace(code, "%SwitchStatement1", code_SwitchStatement1); XreateManager* man = XreateManager::prepare(move(code)); ASSERT_TRUE(true); } TEST(AST, Doc_LoopStatements) { string code_LoopStatement1 = getDocumentationExampleById("documentation/Syntax/syntax.xml", "LoopStatement1"); string code_LoopStatement2 = getDocumentationExampleById("documentation/Syntax/syntax.xml", "LoopStatement2"); string code_FoldStatement1 = getDocumentationExampleById("documentation/Syntax/syntax.xml", "FoldStatement1"); string code_MapStatement1 = getDocumentationExampleById("documentation/Syntax/syntax.xml", "MapStatement1"); string code = R"Code( test = function:: int; entry { %LoopStatement1 %LoopStatement2 %FoldStatement1 %MapStatement1 min } )Code"; replace(code, "%LoopStatement1", code_LoopStatement1); replace(code, "%LoopStatement2", code_LoopStatement2); replace(code, "%FoldStatement1", code_FoldStatement1); replace(code, "%MapStatement1", code_MapStatement1); XreateManager::prepare(move(code)); ASSERT_TRUE(true); } TEST(AST, Doc_Types){ string code = getDocumentationExampleById("documentation/Syntax/syntax.xml", "Types1"); XreateManager::prepare(move(code)); ASSERT_TRUE(true); } TEST(AST, Doc_Variants1){ string code_Variants1 = getDocumentationExampleById("documentation/Syntax/syntax.xml", "Variants1"); XreateManager::prepare(move(code_Variants1)); ASSERT_TRUE(true); } TEST(AST, Doc_VariantsSwitch1){ string code_Variants1 = getDocumentationExampleById("documentation/Syntax/syntax.xml", "VariantsSwitch1"); XreateManager::prepare(move(code_Variants1)); ASSERT_TRUE(true); } TEST(AST, Doc_RecField1){ string code_Variants1 = getDocumentationExampleById("documentation/Syntax/syntax.xml", "RecField1"); XreateManager::prepare(move(code_Variants1)); ASSERT_TRUE(true); } TEST(AST, Doc_RecUpdate1){ string code_Variants1 = getDocumentationExampleById("documentation/Syntax/syntax.xml", "RecUpdate1"); XreateManager::prepare(move(code_Variants1)); ASSERT_TRUE(true); } TEST(AST, Doc_Versions1){ string code_Variants1 = getDocumentationExampleById("documentation/Syntax/syntax.xml", "Versions1_1"); string code_Variants2 = getDocumentationExampleById("documentation/Syntax/syntax.xml", "Versions1_2"); string code = R"Code( test = function:: int; entry { y })Code"; { XreateManager* man = XreateManager::prepare(move(code_Variants1)); man->run(); delete man; ASSERT_TRUE(true); } { replace(code, "", code_Variants2); auto man = details::tier1::XreateManager::prepare(move(code)); ASSERT_DEATH(man->analyse(), ".*versions graph.*"); } } \ No newline at end of file diff --git a/cpp/tests/latex.cpp b/cpp/tests/latex.cpp index be55f08..7fea3ef 100644 --- a/cpp/tests/latex.cpp +++ b/cpp/tests/latex.cpp @@ -1,358 +1,358 @@ /* Any copyright is dedicated to the Public Domain. * http://creativecommons.org/publicdomain/zero/1.0/ * * Author: pgess * Created on June 25, 2018, 5:42 PM * * \file latex.cpp * \brief Testing of latex */ #include "xreatemanager.h" #include "pass/compilepass.h" #include "transcendlayer.h" #include "query/latex.h" #include "compilation/latex.h" #include "aux/xreatemanager-decorators.h" #include "compilation/scopedecorators.h" #include "llvmlayer.h" #include "supplemental/docutils.h" #include "supplemental/defines.h" #include #include using namespace xreate::latex; using namespace xreate::latereasoning; using namespace xreate::compilation; using namespace xreate; using namespace std; TEST(Latex, Script_NestedScopePropagation_1) { std::string program = R"CODE( import raw("scripts/cfa/context.lp"). fn = function:: int; entry { context:: test1. if(1==11)::int {2} else {3} } )CODE"; std::unique_ptr man(details::tier1::XreateManager::prepare(move(program))); CodeScope* blockTrue = man->root->findFunction("fn")->getEntryScope()->getBody().blocks.front(); auto blockTrueP = man->transcend->pack(blockTrue); boost::format formatAlias("alias(%1%, %2%)."); man->transcend->addRawScript((formatAlias % blockTrueP % "block1").str()); man->transcend->addRawScript( R"SCRIPT( success1:- bind_scope(Block1, test1, strong); alias(Block1, block1). )SCRIPT"); man->analyse(); ASSERT_EQ(1, man->transcend->query("success1").size()); } TEST(Latex, Script_DemAndDecision_1) { std::string program = R"CODE( import raw("scripts/cfa/context.lp"). a = function:: int { context:: forC(a). c() } b = function:: int { context:: forC(b). c() } c = function:: int {0} main = function:: int; entry { a() + b() } )CODE"; std::unique_ptr man(details::tier1::XreateManager::prepare(move(program))); CodeScope* blockC = man->root->findFunction("c")->getEntryScope(); auto blockCP = man->transcend->pack(blockC); boost::format formatAlias("alias(%1%, %2%)."); man->transcend->addRawScript((formatAlias % blockCP % "blockC").str()); man->transcend->addRawScript( R"SCRIPT( latex_scope_demand(BlockC, forC):- alias(BlockC, blockC). latex_registered_subjects(forC, Variant):- bind_scope(_, Variant, strong); Variant = forC(_). )SCRIPT"); man->analyse(); ASSERT_EQ(1, man->transcend->query("latex_fn_demand").size()); ASSERT_EQ(2, man->transcend->query("latex_decision").size()); } TEST(Latex, LatexQuery_getFnDemand_1){ std::string program = R"CODE( import raw("scripts/cfa/context.lp"). main = function:: int; entry { context:: alias(blockMain). 0 } )CODE"; std::unique_ptr man(details::tier1::XreateManager::prepare(move(program))); man->transcend->addRawScript( R"SCRIPT( latex_scope_demand(BlockC, forC):- bind_scope(BlockC, alias(blockMain), strong). latex_registered_subjects(forC, decisionSome). )SCRIPT"); LatexQuery* query = new LatexQuery(); man->transcend->registerQuery(query, QueryId::LatexQuery); man->analyse(); Demand demand = query->getFnDemand("main"); ASSERT_EQ(1, demand.size()); ASSERT_STREQ("forC", demand.front().c_str()); } TEST(Latex, LatexQuery_getDecision_static_1){ std::string program = R"CODE( import raw("scripts/cfa/context.lp"). a = function:: int {context::decisionSome. c()} b = function:: int {c()} c = function:: int {context:: alias(blockC). 0} )CODE"; std::unique_ptr man(details::tier1::XreateManager::prepare(move(program))); man->transcend->addRawScript( R"SCRIPT( latex_scope_demand(BlockC, forC):- bind_scope(BlockC, alias(blockC), strong). latex_registered_subjects(forC, decisionSome). )SCRIPT"); LatexQuery* query = new LatexQuery(); man->transcend->registerQuery(query, QueryId::LatexQuery); man->analyse(); LateAnnotation decisionLA = query->getDecision("forC", man->root->findFunction("a")->getEntryScope()); auto decisionGS = decisionLA.select({}, man->root, man->transcend); ASSERT_TRUE(decisionGS); decisionGS->print(cout); cout << endl; auto decisionTuple = man->transcend->parse(*decisionGS); string decision = get<2>(decisionTuple); ASSERT_STREQ("decisionSome", decision.c_str()); } TEST(Latex, Compilation_1) { std::string program = R"CODE( a = function:: int {0} main = function:: int; entry { a() } )CODE"; string script = R"SCRIPT( latex_fn_demand(%1%, subject1). latex_decision(%2%, subject1, 5). latex_registered_subjects(subject1, 1). latex_registered_subjects(subject1, 5). )SCRIPT"; typedef LatexBruteFunctionDecorator FnImpl; typedef LatexBruteScopeDecorator> ScopeImpl; std::unique_ptr man(details::tier1::XreateManager::prepare(move(program))); ScopePacked scopeMainP = man->transcend->pack(man->root->findFunction("main")->getEntryScope()); boost::format format(script); man->transcend->addRawScript((format % "a" % scopeMainP).str()); man->transcend->registerQuery(new LatexQuery(), QueryId::LatexQuery); man->analyse(); std::unique_ptr compiler(new compilation::CompilePassCustomDecorators(man.get())); compiler->run(); man->llvm->initJit(); int(*fnMain)() = (int(*)())man->llvm->getFunctionPointer(compiler->getEntryFunction()); ASSERT_EQ(0, fnMain()); } // //TEST(Latex, Full1) { // std::string program = // R"CODE( // import raw("scripts/cfa/context.lp"). // // a = function:: int // { // context:: forC(a). // c() // } // // b = function:: int // { // context:: forC(b). // c() // } // // c = function:: int {0} // // main = function:: int; entry // { // a() + b() // } // )CODE"; // // string script = // R"SCRIPT( // alias(%1%, scopeC). // latex_scope_demand(ScopeC, forC) :- alias(ScopeC, scopeC). // latex_registered_subjects(forC, forC(a)). // latex_registered_subjects(forC, forC(b)). // )SCRIPT"; // // typedef LatexBruteFunctionDecorator FnImpl; // typedef LatexBruteScopeDecorator> ScopeImpl; // // std::unique_ptr man(details::tier1::XreateManager::prepare(move(program))); // ScopePacked scopeMainP = man->transcend->pack(man->root->findFunction("main")->getEntryScope()); // auto scopeCP = man->transcend->pack(man->root->findFunction("c")->getEntryScope()); // boost::format format(script); // man->transcend->addRawScript((format %scopeCP).str()); // man->transcend->registerQuery(new LatexQuery(), QueryId::LatexQuery); // man->analyse(); // // std::unique_ptr compiler(new compilation::CompilePassCustomDecorators(man.get())); // compiler->run(); // man->llvm->print(); //} // TEST(Latex, Compilation_TransitFn1){ std::string program = R"CODE( import raw("scripts/cfa/context.lp"). branchA = function:: int { context:: sink_a. fnTransit() } branchB = function:: int { context:: sink_b. fnTransit() } fnSink = function:: int {0} fnTransit = function:: int {fnSink()} main = function:: int; entry { branchA() + branchB() } )CODE"; string script = R"SCRIPT( alias(scopeSink, %1%). latex_scope_demand(ScopeSink, sink):- alias(scopeSink, ScopeSink). latex_registered_subjects(sink, sink_a). latex_registered_subjects(sink, sink_b). )SCRIPT"; typedef LatexBruteFunctionDecorator FnImpl; typedef LatexBruteScopeDecorator> ScopeImpl; std::unique_ptr man(details::tier1::XreateManager::prepare(move(program))); CodeScope* scopeSink = man->root->findFunction("fnSink")->getEntryScope(); auto scopeSinkP = man->transcend->pack(scopeSink); ScopedSymbol argLatexSS{1, -1}; Symbol argLatexS{argLatexSS, scopeSink}; man->transcend->pack(argLatexS); boost::format format(script); man->transcend->addRawScript((format %scopeSinkP).str()); man->transcend->registerQuery(new LatexQuery(), QueryId::LatexQuery); man->analyse(); std::unique_ptr compiler(new compilation::CompilePassCustomDecorators(man.get())); compiler->run(); man->llvm->print(); man->llvm->initJit(); int(*fnMain)() = (int(*)()) man->llvm->getFunctionPointer(compiler->getEntryFunction()); int valueActual = fnMain(); ASSERT_EQ(0, valueActual); } TEST(Latex, Doc_Examples1){ std::string program = getDocumentationExampleById("documentation/Concepts/context.xml", "Examples_1"); std::unique_ptr man(details::tier1::XreateManager::prepare(move(program))); } TEST(Latex, Doc_Examples2){ std::string program = getDocumentationExampleById("documentation/Concepts/context.xml", "Examples_2"); std::unique_ptr man(details::tier1::XreateManager::prepare(move(program))); } TEST(Latex, Doc_ContextPropagation1){ std::string program =getDocumentationExampleById("documentation/Concepts/context.xml", "ContextPropagation1"); std::unique_ptr man(details::tier1::XreateManager::prepare(move(program))); } TEST(Latex, Doc_ContextPropagation2){ std::string program = getDocumentationExampleById("documentation/Concepts/context.xml", "ContextPropagation2"); std::unique_ptr man(details::tier1::XreateManager::prepare(move(program))); } TEST(Latex, Doc_Latex1){ std::string program = getDocumentationExampleById("documentation/Concepts/context.xml", "Latex1"); string script = R"SCRIPT( - latef(compute). + latef("compute"). latex_scope_demand(Scope, f_guarded(F)):- cfa_call(Scope, F); latef(F). latex_registered_subjects(f_guarded(F), Guard):- cfa_function_specializations(F, Guard); latef(F). late(TargetS, LatexParam, Guard, dfa_callguard(TargetS, Guard)):- dfa_callfn(TargetS, FnGuarded); latef(FnGuarded); latex_symbol(FnCallerBody, f_guarded(FnGuarded), LatexParam); TargetS=s(_,_, TargetScope); scope_fnbody(TargetScope, FnCallerBody); cfa_function_specializations(FnGuarded, Guard). )SCRIPT"; auto man(XreateManager::prepare(move(program))); man->transcend->addRawScript(move(script)); Fn3args fn = (Fn3args) man->run(); int resultActual = fn(1, 4, 3); ASSERT_EQ(7, resultActual); resultActual = fn(0, 4, 3); ASSERT_EQ(1, resultActual); } \ No newline at end of file diff --git a/cpp/tests/transcend-ast.cpp b/cpp/tests/transcend-ast.cpp index c8c6044..4fe628f 100644 --- a/cpp/tests/transcend-ast.cpp +++ b/cpp/tests/transcend-ast.cpp @@ -1,77 +1,77 @@ /* Any copyright is dedicated to the Public Domain. * http://creativecommons.org/publicdomain/zero/1.0/ * * AST-Transcend Correspondence Tests * * Created on: Dec 2, 2018 * Author: pgess */ #include #include "xreatemanager.h" #include "pass/dfapass.h" #include "supplemental/docutils.h" #include #include "gtest/gtest.h" using namespace xreate; using namespace std; struct TestRec { string refExample; string refOutput; PassId pass; }; std::list tests = { {"ExprAnn_1", "Output_ExprAnn_1", PassId::DFAPass}, {"CodeBlock_1", "Output_CodeBlock_1", PassId::CFAPass}, {"CodeBlockAnns_1", "Output_CodeBlockAnns_1", PassId::CFAPass}, {"CodeBlockBinds_1", "Output_CodeBlockBinds_1", PassId::CFAPass}, {"CodeBlockParents_1", "Output_CodeBlockParents_1",PassId::CFAPass}, {"Fn_1", "Output_Fn_1", PassId::CFAPass}, {"FnAnns_1", "Output_FnAnns_1", PassId::CFAPass}, {"FnSpecs_1", "Output_FnSpecs_1", PassId::CFAPass}, {"FnEntry_1", "Output_FnEntry_1", PassId::CFAPass}, {"FnResult_1", "Output_FnResult_1", PassId::CFAPass}, {"OpInvoc_1", "Output_OpInvoc_1", (PassId) 1000}, {"OpLoops_1", "Output_OpLoops_1", PassId::DFAPass} }; TEST(ASTCorrespondence, Doc_BasicTests) { for(auto test: tests) { string program = getDocumentationExampleById("documentation/Transcend/ast-api.xml", test.refExample); string outputExpected = getDocumentationExampleById("documentation/Transcend/ast-api.xml", test.refOutput); std::unique_ptr man(details::tier2::XreateManager::prepare(move(program))); switch(test.pass) { case PassId::CFAPass: man->registerPass(new cfa::CFAPass(man.get()), test.pass); break; case PassId::DFAPass: man->registerPass(new dfa::DFAPass(man.get()), test.pass); break; default: man->registerPass(new dfa::DFAPass(man.get()), PassId::DFAPass); man->registerPass(new cfa::CFAPass(man.get()), PassId::CFAPass); break; } man->registerPass(new dfa::DFAPass(man.get()), test.pass); man->executePasses(); cout << "Test: " << test.refExample << endl; testing::internal::CaptureStdout(); man->analyse(); std::string outputActual = testing::internal::GetCapturedStdout(); - //cout << outputActual << endl; + cout << outputActual << endl; //check every line independently if outputActual is multi-line string std::vector lines; boost::split(lines, outputExpected, [](char c){return c == '\n';}); for(auto line: lines) { ASSERT_NE(std::string::npos, outputActual.find(line)); } } } diff --git a/cpp/tests/transcend.cpp b/cpp/tests/transcend.cpp index 022b105..e7a53ac 100644 --- a/cpp/tests/transcend.cpp +++ b/cpp/tests/transcend.cpp @@ -1,92 +1,93 @@ /* Any copyright is dedicated to the Public Domain. * http://creativecommons.org/publicdomain/zero/1.0/ * * Author: pgess * Created on June 7, 2018, 3:35 PM * * \file transcend.cpp * \brief Transcend's tests */ #include "xreatemanager.h" #include "transcendlayer.h" #include "supplemental/docutils.h" #include using namespace xreate; using namespace std; TEST(Transcend, Parse1) { std::string script = R"Code( )Code"; std::unique_ptr man(details::tier1::XreateManager::prepare(std::move(script))); std::string scriptTranscend = R"Code( test1((1)). test2((1, 2)). )Code"; man->transcend->addRawScript(move(scriptTranscend)); man->analyse(); StaticModel solution = man->transcend->query("test1"); Gringo::Symbol symbTest1 = solution.begin()->second; auto answer1 = man->transcend->parse>(symbTest1); ASSERT_EQ(1, get<0>(answer1).size()); solution = man->transcend->query("test2"); Gringo::Symbol symbTest2 = solution.begin()->second; auto answer2 = get<0>(man->transcend->parse>(symbTest2)); ASSERT_EQ(2, answer2.size()); } TEST(Transcend, Doc_Expressions1) { string code = getDocumentationExampleById("documentation/Transcend/transcend.xml", "Expressions1"); XreateManager* man = XreateManager::prepare(move(code)); man->run(); delete man; ASSERT_TRUE(true); } TEST(Transcend, Doc_SlaveTypes1){ string code = getDocumentationExampleById("documentation/Transcend/transcend.xml", "Codeblocks1"); XreateManager::prepare(move(code)); ASSERT_TRUE(true); } TEST(Transcend, Doc_Codeblocks1) { string code = getDocumentationExampleById("documentation/Transcend/transcend.xml", "Codeblocks1"); XreateManager::prepare(move(code)); ASSERT_TRUE(true); } TEST(Transcend, Doc_Diagnostics1) { string code = getDocumentationExampleById("documentation/Transcend/transcend.xml", "Diagnostics1"); string scriptTranscend = getDocumentationExampleById("documentation/Transcend/transcend.xml", "Diagnostics1_Rules"); string scriptSupport = R"Code( scope_func_dict(S, Fn):- cfa_parent(S, function(Fn)). scope_func_dict(S1, Fn):- cfa_parent(S1, scope(S2)); scope_func_dict(S2, Fn). )Code"; auto man = XreateManager::prepare(move(code)); man->transcend->addRawScript(move(scriptTranscend)); man->transcend->addRawScript(move(scriptSupport)); testing::internal::CaptureStdout(); man->run(); delete man; std::string outputActual = testing::internal::GetCapturedStdout(); - string outputExpected = "warning(\"Visibility violation\",test,sum)"; + std::cout << outputActual << std::endl; + string outputExpected = "warning(\"Visibility violation\",\"test\",\"sum\")"; ASSERT_NE(std::string::npos, outputActual.find(outputExpected)); } \ No newline at end of file diff --git a/cpp/tests/unit-test-example.cpp b/cpp/tests/unit-test-example.cpp index 17151bb..d1b0b5b 100644 --- a/cpp/tests/unit-test-example.cpp +++ b/cpp/tests/unit-test-example.cpp @@ -1,43 +1,43 @@ #include "xreatemanager.h" //main Xreate header #include "transcendlayer.h" #include using namespace xreate; using namespace std; TEST(Example, Example1){ //Your custom transcend rules if any string rules = R"SCRIPT( - bind_func(sum, entry). + bind_func("sum", entry). )SCRIPT"; //Your custom program string example = R"CODE( //Custom code sum = function(a:: int, b:: int):: int { a + b } )CODE"; //Initialize compiler unique_ptr man(XreateManager::prepare(move(example))); //Add transcend part: man->transcend->addRawScript(move(rules)); //Define signature of your entry function: typedef int (*ENTRYFN)(int, int); //Compile the example and get a pointer to the entry function: ENTRYFN yourEntryFn = (ENTRYFN) man->run(); //Now execute function and check the result int resultActual = yourEntryFn(5, 7); int resultExpected = 5 + 7; ASSERT_EQ(resultExpected, resultActual); } diff --git a/cpp/tests/universal.cpp b/cpp/tests/universal.cpp new file mode 100644 index 0000000..f296166 --- /dev/null +++ b/cpp/tests/universal.cpp @@ -0,0 +1,22 @@ +// +// Created by pgess on 1/6/20. +// + +#include "universal/Parser.h" +#include "gtest/gtest.h" +#include + +using namespace xreate::universal; + +TEST(Universal, DISABLED_Test1) +{ + //testing::internal::CaptureStdout(); + FILE* input = fopen("/private/prg/code/xreate/design/sprint-III/universal-syntax.xreate","r"); + assert(input != nullptr); + Scanner scanner(input); + Parser parser(&scanner); + parser.Parse(); + std::string outputActual = testing::internal::GetCapturedStdout(); + //std::cout << outputActual << std::endl; + ASSERT_EQ(parser.errors->count, 0); +} \ No newline at end of file diff --git a/documentation/Transcend/ast-api.xml b/documentation/Transcend/ast-api.xml index c757ee2..aa2afbd 100644 --- a/documentation/Transcend/ast-api.xml +++ b/documentation/Transcend/ast-api.xml @@ -1,495 +1,495 @@ AST API In order to reason about program, code model is translated into form suited for processing by Transcend. Translation details are described below.
Expression Annotations: 'bind' SYNTAX: **bind**(//symbol-ref//, //annotation//) symbol-ref reference to the expression or identifier annotation expression's annotation Declares expression's annotations. Example: name="tests/transcend-ast.cpp: ASTCorrespondence.Doc_BasicTests" test = function:: int { x = 5:: int; expected(even_number). x } gets translated into: bind(s(1,-2,0),expected(even_number))
Code Block: 'scope' SYNTAX: **scope**(//scope-ref//) scope-ref reference to the code block Declares code block under its unique reference identifier. Example: name="tests/transcend-ast.cpp: ASTCorrespondence.Doc_BasicTests" test = function:: float { x = 3:: float. y = 8:: float. x + y } Translation result: scope(0)
Code Block Annotations: 'bind_scope' Pending syntax changes SYNTAX: **bind_scope**(//scope-ref//, //annotation//, strong) (1) **bind_scope**(//scope-ref//, //annotation//, weak(..)) (2) scope-ref child block's reference annotation code block's annotation Declares code block's annotations called context. There are two forms for different context' type: strong context known at compile time weak possible context, can't be decided for sure at compile time Example: name="tests/transcend-ast.cpp: ASTCorrespondence.Doc_BasicTests" test = function:: float { context:: arithmetic(fast). x = 3:: float. y = 8:: float. x + y } Translation's result: bind_scope(0,arithmetic(fast),strong)
Code Block Bindings: 'ast_scope_binding' SYNTAX: **ast_scope_binding**(//scope-ref//, //binding-id//, //binding-alias//) scope-ref code block's reference binding-id number of code block's binding binding-alias name of a binding Code blocks have zero or more bindings, i.e. Identifiers that have special meaning within the block. Predicate declares such code block's bindings. Bindings organized into ordered list. Order is conveyed by specifying binding-id for each binding-alias. Example: name="tests/transcend-ast.cpp: ASTCorrespondence.Doc_BasicTests" test = function:: int { loop ( 0 -> acc ):: int { if(acc > 10):: int {acc:: int; final} else {acc + 1} } } Translation result: ast_scope_binding(1,0,"acc")
Code Block Parents: 'cfa_parent' SYNTAX: **cfa_parent**(//scope-ref//, **scope**(//scope-parent-ref//)) scope-ref child block's reference scope-parent-ref parent block's reference Represents nested code blocks structure in terms of child-parent relation. Example: name="tests/transcend-ast.cpp: ASTCorrespondence.Doc_BasicTests" test = function:: int { x = 19:: int. if (x>5):: int {x + 1} else {x - 1} } Translation's result: cfa_parent(1, scope(0)). cfa_parent(2, scope(0)).
Function: 'function' SYNTAX: **function**(//fn-name//) fn-name function name Declares function identified by its name. Example: name="tests/transcend-ast.cpp: ASTCorrespondence.Doc_BasicTests" test = function:: int {0} Translation's result: function(test) + xml:id="Output_Fn_1">function("test")
Function's Annotations: 'bind_func' SYNTAX: **bind_func**(//fn-name//, //annotation//) fn-name function's name Declares function's annotations. Example: name="tests/transcend-ast.cpp: ASTCorrespondence.Doc_BasicTests" test = function:: int; status(obsolete) {0} Translation's result: bind_func(test,status(obsolete)) + xml:id="Output_FnAnns_1">bind_func("test",status(obsolete))
Function's Specialization: 'cfa_function_specializations' SYNTAX: **cfa_function_specializations**(//fn-name//, //guard//) fn-name name of function guard specialization guard There is a possibility to have several functions with the same name called specializations. Each specialization is uniquely determined by annotation of special kind called guard. Example: name="tests/transcend-ast.cpp: ASTCorrespondence.Doc_BasicTests" guard:: arch(amd64) { test = function:: i64 {0} } Translation's result: cfa_function_specializations(test,arch(amd64)) + xml:id="Output_FnSpecs_1">cfa_function_specializations("test",arch(amd64)) See also specializations syntax
Function's Entry: 'cfa_parent' SYNTAX: **cfa_parent**(//scope-entry-ref//, functon(//fn-name//)) scope-entry-ref function's entry code block reference fn-name function's name Each function has a single entry code block and is declared in terms of child-parent relation between entry block(which is top-level in blocks hierarchy of the given function) and the function itself. Example: name="tests/transcend-ast.cpp: ASTCorrespondence.Doc_BasicTests" test = function:: int {0} Translation's result: cfa_parent(0,function(test)) + xml:id="Output_FnEntry_1">cfa_parent(0,function("test"))
Function's Result: 'dfa_fnret' SYNTAX: **dfa_fnret**(//fn-name//, //symbol-ret-ref//) symbol-ret-ref reference to a function's return expression Specifies which expression is used to compute function's return value. Example: name="tests/transcend-ast.cpp: ASTCorrespondence.Doc_BasicTests" test = function:: int {0} Translation's result: dfa_fnret(test,s(0,-2,0)) + xml:id="Output_FnResult_1">dfa_fnret("test",s(0,-2,0))
Operations. Invocation: 'cfa_call', 'dfa_callfn', 'dfa_callargs' SYNTAX: **cfa_call**(//scope-caller-ref//, //fn-callee-name//) (1) **dfa_callfn**(//symbol-ref//, //fn-callee-name//) (2) **dfa_callargs**(//symbol-ref//, //arg-formal-name//, //arg-actual-ref//) (3) **weak**(**dfa_callargs**(//symbol-ref//, //arg-formal-name//, //arg-actual-ref//)) (4) scope-caller-ref caller's code block's reference fn-callee-name callee function name symbol-ref invocation operation reference arg-formal-name function's formal argument arg-actual-ref actual argument reference Each function invocation is transformed into several transcend facts as explained below: (1) cfa_call Specifies caller's code block and callee function name (2) dfa_callfn Declares unique reference to a particular invocation site.The reference used by other facts to supply additional information (3) dfa_callargs Declares assignment relations between actual arguments and formal arguments (4) weak(dfa_callargs) The same as form (3). Weak relation used in cases when there is no enough information at compile time. One such case is when several function specializations exist and it's impossible to say which exactly specialization is called Example: name="tests/transcend-ast.cpp: ASTCorrespondence.Doc_BasicTests" inc = function (x::int):: int { x + 1 } main = function:: int { arg = 10:: int. inc(arg) } After translation following transcend facts are present: - cfa_call(1,inc) -dfa_callfn(s(0,-2,1),inc) + cfa_call(1,"inc") +dfa_callfn(s(0,-2,1),"inc") weak(dfa_callargs(s(0,-2,1),s(1,-2,0),s(1,-2,1))) dfa_callargs(s(0,-2,1),s(1,-2,0),s(1,-2,1))
Operations. Loops **ast_op_map**(//symbol-result-ref//, //symbol-source-ref//, //loop-body-ref//) **ast_op_fold**(//symbol-result-ref//, //symbol-source-ref//, //symbol-acc-ref//, //loop-body-ref//) symbol-source-ref input list reference symbol-acc-ref accumulator reference symbol-result-ref result list reference loop-body-ref refers to a loop body expression Facts declare loop operations. Example: name="tests/transcend-ast.cpp: ASTCorrespondence.Doc_BasicTests" test = function:: int; entry { singles = {1, 2, 3}:: [int]. doubles = loop map(singles->element:: int)::[int] {2 * element}. doubles[0] } produces fact: ast_op_map(s(2,-2,0),s(1,-2,0),s(0,-2,1))
diff --git a/documentation/build.xml b/documentation/build.xml index 2f61382..4fa76c8 100644 --- a/documentation/build.xml +++ b/documentation/build.xml @@ -1,275 +1,275 @@ <?xxe-sn 2ckdfwgr1fk 2?>Installation
<?xxe-sn 2ckdfwgr1fk 7?>Build on Linux Major dependencies: gcc 7 llvm 5, clang 5 boost 1.66 coco clingo Building tested on OpenSuse Leap 15. Please change commands accordingly if using other distributions. Pull sources directly from repository: git clone --recursive http://xreate.org/diffusion/XR/xreate.git Enter into the source directory and run the following script to prepare building environment. Script will install the required system packages as well as Coco and Clingo from sources: "Enter into source directory" - тут перед directory явно нужен артикль. Гугл говорит, что определенный - the Carefully inspect scripts before run On OpenSuse Leap 15: ./installation/prepare-opensuse-leap15 That was one time operation to prepare environment. After that enter into build directory and start actual tests building: "build directory": здесь ты все-таки вначале указываешь имя объекта (build), и лишь потом родовое название (directory) cd build make After successful build you can run xreate tests: cd .. ./build/tests/xreate-tests Please pay attention that the working directory should be the repository root For consequent rebuilds after updates etc invoke cmake as follows: #working dir build cmake -DCMAKE_BUILD_TYPE=Debug \ -DBUILD_XREATE_TESTS=1 \ -DCOCO_EXECUTABLE=<FILE> \ -DCLINGO_PATH=<DIR> \ -DCOCO_FRAMES_PATH=../vendors/coco/generator/ \ -DCMAKE_CXX_COMPILER=g++ ../cpp make cmake's selected parameters: BUILD_XREATE_TESTS Determines whether to build tests COCO_EXECUTABLE Full filename of Coco executable CLINGO_PATH Installed Clingo directory "Directory of Clingo installation": может, with Clingo installation? (это если речь идет о папке, где хранятся инсталляционные файлы) Если наоборот, куда будет устанавливаться - тогда Directory for installing Clingo. Оригинальный вариант ("of Clingo installation") немного сбивает с толку.
<?xxe-sn 2coi7ojavb4 2?>Experimenting At this point the only executable produced by make is a collection of the unit tests. There are many existing unit tests located in the cpp/tests to check correctness of various compilation aspects. Unit tests are configured via the file config/default.json with the relevant settings located in the section tests. The section looks like this: "tests": { "template": "default", "templates": { "default": "*", "documentation": "Modules.Doc_*:Modules_API.Doc_*", "ast": "AST.*", ... } } Key tests.template determines which group of unit tests should be executed, while section test.templates describes all available groups. Note, that exact syntax of unit tests selection is described in the Google Tests library documentation. By modifying this configuration you can choose which tests you want to execute. In order to experiment with the compiler you need to write your own unit-tests. There are several steps to complete to add and run new unit tests: Add new file to the cpp/tests. Register test by adding its filename to the variable TEST_FILES in the test/CMakeLists.txt. Change config/default.json accordingly. Below is a bare bones example of a unit-test as a starting point to get an idea: name="tests/unit-test-example: Example.Example1", lines=15 #include "xreatemanager.h" //main Xreate header #include "transcendlayer.h" #include <gtest/gtest.h> using namespace xreate; using namespace std; TEST(Example, Example1){ //(Optional) Your custom transcend rules if any string rules = R"SCRIPT( - bind_func(sum, entry). + bind_func("sum", entry). )SCRIPT"; //Your custom program string example = R"CODE( //Custom code sum = function(a:: int, b:: int):: int { a + b } )CODE"; //Initialize compiler unique_ptr<XreateManager> man(XreateManager::prepare(move(example))); //Add transcend part: man->transcend->addRawScript(move(rules)); //Define signature of your entry function: typedef int (*ENTRYFN)(int, int); //Compile the example and get a pointer to the entry function: ENTRYFN yourEntryFn = (ENTRYFN) man->run(); //Now execute function and check the result int resultActual = yourEntryFn(5, 7); int resultExpected = 5 + 7; ASSERT_EQ(resultExpected, resultActual); } It outlines common unit test structure: defines a program and optional transcend rules(in this case to designate sum as an entry function). Then the program is compiled, executed and the result is checked against expected value. Have a look at other existing unit tests and see Internal API to know more.
diff --git a/documentation/index.xml b/documentation/index.xml index 38c577d..6bd404c 100644 --- a/documentation/index.xml +++ b/documentation/index.xml @@ -1,434 +1,434 @@ <?xxe-sn 2b06cb2u4g0 2?>Xreate Manual Xreate is an open source general purpose high level programming language designed to write efficient and safe computer programs. Here "high level" refers to the developer oriented side meaning exactly an ability to easily write, read, reuse, as well as adapt software to a constantly changing environment or business goals. In this respect, any software product can be evaluated on the basis of three dimensions: efficiency, safety, and flexibility. Unfortunately, those properties are proved to be largely contradictory, for it is manageable to write either efficient (yet unsafe) or safe (yet impractical) code, but not both. Thus, the ultimate goal of the language is to allow developers to produce code that would have all these properties at the same time. Blending features of seemingly incompatible programming paradigms is a basis of Xreate's design principles. To achieve the aforementioned design goals, Xreate consists of three distinctive layers: Brute. The lowest layer is called Brute — this is code that is intended to be actually compiled. Code on this level implements actual software functionality. It resembles the usual imperative languages' apparatus and consists of executable instructions such as arithmetic, branching, input / output, etc. Transcend. Brute alone is not enough to constitute a full-fledged language since code requires various non-executable metadata to express developer's intents, check correctness, validity and perform other types of analyses. In Xreate everything of this sort belongs to a declarative type layer called Transcend. Transcend is a logic reasoner that is appropriate to do management-type work — it analyzes, oversees and controls Brute by guiding compilation process. More precisely, everything on this level, logic or transcend facts and rules, is gathered and sent to an external logic solver to make solutions that are brought back in order to guide compilation. Unlike usual static analysis tools, Transcend directly controls compilation(see Basic Example) and able to make decisions even based on data available only at runtime(see Late Transcend) Interpretation. There is also Interpretation — the intermediate level resembling dynamically typed languages that is used as a contact point and interpreter between Brute and Transcend. See an example. On a syntactic level, Xreate is a procedural language with extensive use of annotations — arbitrary unconstrained metadata that a software developer can attach to different language constructs, variables and code blocks. Annotations are completely invisible for the compiler proper and used by Transcend more as a suggestion conveying additional information. "a different language constructs": если подразумевается "конструкции разных языков", тогда лучше "different languages' constructs". Если конструкции языка, в целом, то тогда артикль a не нужен There are several extensions already implemented to give a feeling what does this structure can be used for. Containers chapter describes that it is possible to reason about and automatically choose the most appropriate data structure's implementation depending on how it is used in the code. Look at the example below: x = [1, 2, 3]:: [int]. Container x does not have well defined implementation just yet. Only by looking how it is used throughout the code, the compiler is able to decide how exactly to store container's data. Interaction of different components and joint use of external resources is covered by Exploitation: logger = createFileLogger("/some/file"):: Logger. ... write(logger, "First log entry"). ... write(logger, "Last log entry"). Exploitation reasoning allows to determine when it is the first, last access to resources such as files, in other words, it infers access order. As a result it is possible to automatically initialize / destruct related resources. Unlike RAII, an another related technique, Exploitation is reserved to manage resources usage that spans across different parts of a program: modules, plugins, etc. Virtualization reasoning also helps to work with external resources by enabling access control if and when it is needed only. Example: openFile("/some/file"):: string; assign_sizo(zoneA). openFile("/some/file"):: string; assign_sizo(zoneB). If the compiler recognizes file access from the different zones, as in this example, it applies an appropriate virtualization strategy enough to ensure that instructions that belong to different zones do not interfere with each other. Unlike "pure", academic languages, Xreate targets safe and reliable usage of effectful computations such as IO that is covered above as well as mutable structures described in the Communication chapter. Note, that the described extensions are not part of the compiler and developers can write their own custom transcend rules to cover other aspects.
<?xxe-sn 2b06cb2u4g0 4?>Basic Example To demonstrate what Xreate is all about, basic example is given below: name="tests/introduction.cpp: Introduction.Doc_Example_1", lines=15 guard:: iAmVeryFast { div = function(a:: int, b:: int):: int { a / b } } guard:: iAmVerySafe { div = function(a:: int, b:: int):: int { if ( b == 0 ):: int { zeroDivisionErrCode() } else { a / b } } } test = function:: int; entry; iAmVerySecure { div(10, 5) } Here entry point of the program is a function test recognized so by the compiler because of annotation entry in its signature. There are also two functions with the same name div called specializations. Each specialization has a guard that defines a condition that has to be met in order to invoke this particular specialization. In the example, specializations of div have iAmVeryFast and iAmVerySafe guards, respectively. Let's say that a code author writes two specializations where the first one is a very fast division implementation, while the second one is a very safe division implementation since it checks division by zero, being "unacceptably slow" due to an extra check instruction, though. This is a basis of polymorphism — client's code test is able to work with any specialization, and the compiler must decide which one to invoke with the only hint it has — annotation iAmVerySecure in the function test's signature. "provides two specializations" - возможно, лучший вариант "designates/assigns/allocates two specializations". Или даже просто specifies/indicates. (PS заменил на specifies) "unbearably slow" - я бы заменил на более нейтральное "too slow". Unbearable - это скорее об ощущениях человека. Или, если под "unbearably" имеется в виду "недопустимо медленный", тогда - unacceptably slow. All annotations (except entry) are custom defined by developer itself. This is when Transcend comes into play. By adding a transcend rule as shown below it is possible to associate annotation iAmVerySecure with invocation of specialization guarded by iAmVerySafe: name="tests/introduction.cpp: Introduction.Doc_Example_1", lines=15 dfa_callguard(SiteInv, iAmVerySafe):- - dfa_callfn(SiteInv, div); + dfa_callfn(SiteInv, "div"); SiteInv = s(_, _, ScopeInv); cfa_parent(ScopeInv, function(FnInv)); bind_func(FnInv, iAmVerySecure). Transcend rules are written in ASP syntax — common syntax to write logic programs. This particular rule reads that for any function annotated with iAmVerySecure, certain specialization iAmVerySafe is chosen for div invocation. In this example an appropriate specialization is statically resolved, so the other specialization isn't even compiled. the, потому что их всего две. By providing custom rules it is possible to implement any polymorphism strategy, be it performed statically or dynamically. The example demonstrates basic workflow: Transcend gathers available information about a program such as annotations and using custom rules makes decisions to guide various aspects of compilation process, particularly by selecting appropriate specializations as in the above example.
<?xxe-sn 2fchdmt7vgg 2?>More Advanced Example Suppose we write a program to generate a web page consisting of several blocks(e.g. a header, a footer) constructed independently by different parts of our program. In order to organise the code, we express our intention that all blocks should be sent to a client in a very specific order: first a header, then a body and footer, as below: name="tests/exploitation.cpp: Exploitation.Doc_ExampleEov_1", lines=15 eov_expect( webpage, header, body; %we expect body to be sent after header webpage, body, footer %.. and footer after body ). This is similar to Exploitation: we are working with the external resource webpage and want to take into account an exact order of resource exploiting operations. Then, we write code like this: send("Header"):: Content; eov_checkpoint(webpage, header). We mark the operations we are interesting in as checkpoints(here header is the name of a checkpoint and webpage is the resource the checkpoint refers to) and want to know are checkpoints executed in the expected(as defined above) order. If it so happens that these blocks are constructed in the correct order in our program we may send them immediately. Otherwise, we must cache already constructed content till a whole page is generated to ensure correctness. In other words, clearly, there is an opportunity for optimizations for caching has not only memory overhead but delays response latency(time before the first block is sent) as well. We write two implementations immediate_output and cached_output each for the corresponding case: name="tests/exploitation.cpp: Exploitation.Doc_ExampleEov_1", lines=15 //type to store either sending error code or cached content Content = type variant { errcode:: int, message:: string }. //Send immediately: guard:: immediate_output { send = function(content:: string):: Content { errcode(printf("%s", content)) } } //Cache content to send it later: guard:: cached_output { send = function(content:: string):: Content { message(content) } } These implementations should be registered for the compiler to know which one to use: name="tests/exploitation.cpp: Exploitation.Doc_ExampleEov_1", lines=15 eov_analysis( success, immediate_output; fail, cached_output ). Predicate eov_analysis compares actual checkpoints execution order with the expected one and chooses either of two implementations depending on the result. This way, it is guarantied that immediate sending is chosen only if it is safe to do so to avoid unnecessary caching. Thus we can safely change and adapt our program knowing that clients always receive web page's content in the correct order by automatically employing the most efficient content delivery strategy depending on particular circumstances.
<?xxe-sn 2fs1xxghz93 -wunr7fl0rw8t?>Differences from other languages it is convenient to talk about intentions in order to outline a vast landscape of programming languages and point out the place of Xreate on it, i.e. to compare languages depending on do they allow to express a developer's intentions along with raw code that can be used on many occasions, e.g. to validate the code's correctness. Traditionally type system is used to declare intentions. At closer look, types in (imperative) statically typed languages contain inseparable combination of the following: Intentions, such as "that variable is a string". Usage patterns: a new code should play nicely with the rest of a program, e.g. if a program works with unicode, a new string variable should be also of unicode family type(even if this is not necessary for a given part of code) Platform constraints, e.g. if a platform supports wide strings natively, a new string variable should also be a wide string. In this regard, in general, statically typed languages are overconstrained, they require developers to provide more information than they intend to. This usually hinders code reuse and adaptation; to work on a new platform, software requires porting: a process of re-expressing underlying intentions once again with the new platform's constraints. On the other side, dynamically typed languages are underconstrained, since they do not allow to express all desirable intentions. This leads to disastrous inefficiency and code fragility because any errors can be caught only at runtime. As an example, OOP languages are hugely successful among other reasons because they provide classes to more finely express intentions, e.g. String, UnicodeString, Utf8String with exact behaviour being hidden in implementation details. Xreate in its turn is based on the idea to allow developers express as much or as little intentions as they want to. This is a way to reach one of the the language's goals to facilitate writing of easily reusable and adaptable software. On a syntax level, annotations are used to express intentions, e.g. string;i_dont_need(utf8)(note the modality, annotations can express boundaries, preferences, etc. ). This approach obviously leads to problems with software's performance and efficiency. For most high level languages, compilers rely on defaults to fill in unspecified by the developer gaps in the exact implementation details. Usually languages provide standard, default data structures the developer have no control over. However Xreate follows another approach: to resolve this contradiction, the compiler determines necessary implementation details not only depending on annotations, but also by looking at usage patterns along with platform properties trying to infer most efficient implementations in any given circumstances.
diff --git a/grammar/universal.ATG b/grammar/universal.ATG new file mode 100644 index 0000000..a2ac29c --- /dev/null +++ b/grammar/universal.ATG @@ -0,0 +1,60 @@ +#include "aux/universal.h" + +COMPILER Universal + +bool checkTokenAfterIdent(int key){ + if (la->kind != _ident) return false; + return scanner->Peek()->kind == key; +} + +bool checkAssignment() +{ + return checkTokenAfterIdent(_assign); +} + +CHARACTERS + letter = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz". + digit = "0123456789". + any = ANY - '"'. + cr = '\r'. + lf = '\n'. + tab = '\t'. + +TOKENS + string = '"' { any } '"'. + ident = (letter | '_') {letter | digit | '_'}. + assign = '='. + lp = '('. + rp = ')'. + tagcolon = "::". + +COMMENTS FROM "/*" TO "*/" NESTED +COMMENTS FROM "//" TO lf + +IGNORE cr + lf + tab + +PRODUCTIONS + +ArgList = lp { Expr [','] } rp. +Block = '{' '}'. + +MetaExpr = ident [MetaArgList]. +MetaArgList = lp { MetaExpr [','] } rp. +MetaExprList = {MetaExpr ';'}. + +Expr = + ident (. send(std::wstring(L"Expr: ") + t->val); .) + [ArgList] + [tagcolon MetaExprList] + {ident Block} [Block] +. + +Decl = + (IF(checkAssignment()) ident (. send(std::wstring(L"Decl: ") + t->val); .) + assign | ) + Expr +. + +Universal = {Decl ['.']} . + +END Universal. diff --git a/grammar/xreate.ATG b/grammar/xreate.ATG index abdb3f0..84ac92c 100644 --- a/grammar/xreate.ATG +++ b/grammar/xreate.ATG @@ -1,707 +1,707 @@ //TODO add ListLiteral //TODO ExprTyped: assign default(none) type #include "ast.h" #include "ExternLayer.h" #include #include #define wprintf(format, ...) \ char __buffer[100]; \ wcstombs(__buffer, format, 100); \ fprintf(stderr, __buffer, __VA_ARGS__) using namespace std; COMPILER Xreate details::inconsistent::AST* root = nullptr; // current program unit void ensureInitalizedAST(){ if (root == nullptr) root = new details::inconsistent::AST(); } struct { std::stack scopesOld; CodeScope* scope = nullptr; } context; void pushContextScope(CodeScope* scope){ context.scopesOld.push(context.scope); context.scope = scope; } void popContextScope(){ context.scope = context.scopesOld.top(); context.scopesOld.pop(); } int nextToken() { scanner->ResetPeek(); return scanner->Peek()->kind; } bool checkTokenAfterIdent(int key){ if (la->kind != _ident) return false; return nextToken() == key; } bool checkParametersList() { return la->kind == _ident && nextToken() == _lparen; } bool checkInfix() { return la->kind == _ident && nextToken() == _ident; } bool checkIndex() { return la->kind == _ident && nextToken() == _lbrack; } bool checkFuncDecl() { if (la->kind != _ident) return false; int token2 = nextToken(); int token3 = scanner->Peek()->kind; return token2 == _assign && (token3 == _function || token3 == _pre); } bool checkAssignment() { if (la->kind != _ident) return false; scanner->ResetPeek(); int token2 = scanner->Peek()->kind; if (token2 == _lcurbrack) { scanner->Peek(); int token3 = scanner->Peek()->kind; if (token3 != _rcurbrack) return false; int token4 = scanner->Peek()->kind; return token4 == _assign; } return token2 == _assign; } void recognizeIdentifier(Expression& i){ if (!context.scope->recognizeIdentifier(i)){ root->postponeIdentifier(context.scope, i); } } enum SwitchKind{SWITCH_NORMAL, SWITCH_META}; CHARACTERS letter = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz". any = ANY - '"'. digit = "0123456789". cr = '\r'. lf = '\n'. tab = '\t'. TOKENS - ident = (letter | '_') {letter | digit | '_'}. - number = (digit | '-' digit) {digit}. + ident = (letter ['-' letter] | '_') {letter ['-' letter] | digit | '_' }. + number = digit{digit}. string = '"' { any } '"'. function = "function". pre = "pre". comma = ','. period = '.'. lparen = '('. rparen = ')'. lbrack = '['. rbrack = ']'. lcurbrack = '{'. rcurbrack = '}'. equal = "==". assign = '='. implic = '-' '>'. colon = ':'. context = "context". tagcolon = "::". lse = "<=". lss = "<". gte = ">=". gtr = ">". ne1 = "!=". ne2= "<>". COMMENTS FROM "/*" TO "*/" NESTED COMMENTS FROM "//" TO lf IGNORE cr + lf + tab PRODUCTIONS Xreate = (. Function* function; ensureInitalizedAST(); .) {( //RuleDecl InterfaceData | Imprt | GuardSection | IF(checkFuncDecl()) FDecl (. root->add(function); .) | TDecl | SkipModulesSection )} (. .) . Ident = ident (. name = t->val; .). VarIdent = ident (. e = Expression(Atom(t->val)); .) [ lcurbrack ( ident (. SemErr(coco_string_create("var version as ident is not implemented yet")); .) | number (. Attachments::put(e, Atom(t->val).get()); .) ) rcurbrack ] . FDecl = (. std::wstring fname; std::wstring argName; TypeAnnotation typIn; TypeAnnotation typOut; bool flagIsPrefunct = false; Expression binding; .) Ident assign [pre (. flagIsPrefunct = true; .)] function (. f = new Function(fname); f->isPrefunction = flagIsPrefunct; CodeScope* entry = f->getEntryScope(); .) [lparen Ident tagcolon ExprAnnotations (. f->addBinding(Atom(argName), move(binding)); .) {comma Ident tagcolon ExprAnnotations (. f->addBinding(Atom (argName), move(binding));.) } rparen] [ tagcolon ( IF(flagIsPrefunct) FnTag | Type ) {';' FnTag }] BDecl (. const_cast(entry->getBody()).bindType(move(typOut));.) . GuardSection<>= (. Expression guard; Function* f; .) "guard" tagcolon MetaSimpExpr lcurbrack { FDecl (. f->guard = guard; root->add(f); .) } rcurbrack. /** * TYPES * */ TypeTerm = (. std::wstring tid; .) ("string" (. typ = TypePrimitive::String;.) | "num" (. typ = TypePrimitive::Num;.) | "int" (. typ = TypePrimitive::Int;.) | "float" (. typ = TypePrimitive::Float;.) | "bool" (. typ = TypePrimitive::Bool; .) | "i8" (. typ = TypePrimitive::I8; .) | "i32" (. typ = TypePrimitive::I32; .) | "i64" (. typ = TypePrimitive::I64; .) ). Type = (. TypeAnnotation typ2; TypePrimitive typ3; std::wstring tid; std::string field; .) ( TList | TRecord | TVariant | TSlave | TypeTerm (. typ = typ3; .) | IF (checkIndex()) Ident lbrack TypeIndex (. typ = TypeAnnotation(TypeOperator::ACCESS, {}); typ.__valueCustom = Atom(tid).get(); typ.fields.push_back(field); .) {comma TypeIndex (. typ.fields.push_back(field); .) } rbrack | Ident (. typ = TypeAnnotation(TypeOperator::CUSTOM, {}); typ.__valueCustom = Atom(tid).get(); .) [lparen Type (. typ.__operator = TypeOperator::CALL; typ.__operands.push_back(typ2); .) {comma Type (. typ.__operands.push_back(typ2); .) } rparen] | '*' (.typ = TypeAnnotation(); .) ) . TypeIndex = ( number (. name = Atom(t->val).get(); .) | string (. name = Atom(t->val).get(); .) ) . TList = (. TypeAnnotation ty; .) lbrack Type rbrack (. typ = TypeAnnotation(TypeOperator::LIST_ARRAY, {ty}); .) . TRecord = (. TypeAnnotation t; std::wstring key; size_t keyCounter=0; .) lcurbrack ( IF(checkTokenAfterIdent(_tagcolon)) Ident tagcolon Type | Type (. key = to_wstring(keyCounter++); .) ) (. typ = TypeAnnotation(TypeOperator::LIST_RECORD, {t}); typ.fields.push_back(Atom(key).get()); .) {comma ( IF(checkTokenAfterIdent(_tagcolon)) Ident tagcolon Type | Type (. key = to_wstring(keyCounter++); .) ) (. typ.__operands.push_back(t); typ.fields.push_back(Atom(key).get()); .) } rcurbrack. TVariant= (. TypeAnnotation t, typVoid; std::vector operands; std::vector> keys; std::wstring variant; .) "variant" lcurbrack Ident (. t=typVoid; .) [tagcolon Type] (. keys.push_back(Atom(variant)); operands.push_back(t); .) {comma Ident (. t=typVoid; .) [tagcolon Type] (. keys.push_back(Atom(variant)); operands.push_back(t); .) } rcurbrack (. typ = TypeAnnotation(TypeOperator::VARIANT, {}); typ.__operands = operands; typ.addFields(std::move(keys)); .) . TSlave= (. std::wstring identMaster; .) "slave" Ident (. typ = TypeAnnotation(TypeOperator::SLAVE, {}); typ.__valueCustom = Atom(identMaster).get(); .) . TDecl = (. TypeAnnotation t; std::wstring tname, arg; std::vector> args; .) Ident assign "type" [lparen Ident (. args.push_back(Atom(arg)); .) {comma Ident (. args.push_back(Atom(arg)); .) } rparen] Typeperiod (. t.addBindings(move(args)); root->add(move(t), Atom(tname)); .) . ContextDecl = (. Expression tag; .) context tagcolon MetaSimpExpr (. scope->tags.push_back(tag); .) {';' MetaSimpExpr (. scope->tags.push_back(tag); .) }. VDecl = (. std::wstring vname; Expression var, value;.) VarIdent assign ExprTyped (. Symbol identSymbol = f->addDefinition(move(var), move(value)); Attachments::put(value, identSymbol); .) . BDecl = lcurbrack (. Expression body; pushContextScope(scope); .) {(IF(checkAssignment()) VDecl period // | RuleContextDecl | ContextDeclperiod | ExprTyped (. scope->setBody(body); Attachments::put(body, Symbol{ScopedSymbol::RetSymbol, scope});.) )} rcurbrack (. popContextScope(); .) . IfDecl = (. Expression cond; ManagedScpPtr blockTrue = root->add(new CodeScope(context.scope)); ManagedScpPtr blockFalse = root->add(new CodeScope(context.scope)); .) "if" lparen Expr rparen (. e = Expression(Operator::IF, {cond}); .) tagcolon ExprAnnotations BDecl<&*blockTrue> "else" BDecl<&*blockFalse> (. e.addBlock(blockTrue); e.addBlock(blockFalse); .) . LoopDecl = (. Expression eIn, eAcc, eFilters; std::wstring varEl, varAcc, contextClass; Expression tagsEl; ManagedScpPtr block = root->add(new CodeScope(context.scope)); .) "loop" ( "map" lparen Expr implic Ident (. e = Expression(Operator::MAP, {eIn}); .) tagcolon ExprAnnotations rparen tagcolon ExprAnnotations (. e.addBindings({Atom(varEl)}); block->addBinding(Atom(varEl), move(tagsEl)); .) BDecl<&*block> (. e.addBlock(block); .) | "fold" lparen Expr implic Ident tagcolon ExprAnnotations ['|' Expr ] comma Expr implic Identrparen (. e = Expression(Operator::FOLD, {eIn, eAcc}); e.addBindings({Atom(varEl), Atom(varAcc)}); .) tagcolon ExprAnnotations (. block->addBinding(Atom(varEl), move(tagsEl)); block->addBinding(Atom(varAcc), Expression()); .) BDecl<&*block> (. e.addBlock(block); .) | lparen Expr implic Ident rparen (. e = Expression(Operator::INF, {eAcc}); e.addBindings({Atom(varAcc)}); block->addBinding(Atom(varAcc), Expression()); .) tagcolon ExprAnnotations BDecl<&*block> (. e.addBlock(block); .) ). // Switches SwitchDecl = (. TypeAnnotation typ; eSwitch = Expression(Operator::SWITCH, {}); Expression eCondition; Expression tag;.) "switch" ( SwitchVariantDecl | SwitchLateDecl | lparen ExprTyped rparen tagcolon ExprAnnotations (. eSwitch.operands.push_back(eCondition);.) CaseDecl {CaseDecl} ) . CaseDecl = (. ManagedScpPtr scope = root->add(new CodeScope(context.scope)); Expression condition; .) "case" ( IF(flagSwitchKind == SWITCH_META) lparen MetaSimpExpr rparen BDecl<&*scope> (. Expression exprCase(Operator::CASE, {}); exprCase.addTags({condition}); exprCase.addBlock(scope); outer.addArg(move(exprCase));.) | "default" BDecl<&*scope> (. Expression exprCase(Operator::CASE_DEFAULT, {}); exprCase.addBlock(scope); outer.operands.insert(++outer.operands.begin(), exprCase); .) | lparen CaseParams<&*scope> rparen (. ManagedScpPtr scopeBody = root->add(new CodeScope(&*scope)); Expression exprCase(Operator::CASE, {}); .) BDecl<&*scopeBody> (. exprCase.addBlock(scope); exprCase.addBlock(scopeBody); outer.addArg(move(exprCase)); .) ). CaseParams = (. Expression condition; Expression guard(Operator::LOGIC_AND, {}); pushContextScope(scope); .) ExprTyped (. guard.addArg(Expression(condition)); .) {comma ExprTyped (. guard.addArg(Expression(condition)); .) } (. scope->setBody(guard); popContextScope(); .) . SwitchLateDecl = (. std::wstring aliasCondition; Expression exprCondition, aliasAnns; expr = Expression(Operator::SWITCH_LATE, {}); ManagedScpPtr scope = root->add(new CodeScope(context.scope)); .) "late" lparen Expr [implic Ident] [tagcolon ExprAnnotations] rparen tagcolon ExprAnnotations BDecl<&*scope> (. expr.addArg(Expression(exprCondition)); expr.addBlock(scope); std::string alias; if(aliasCondition.empty()){ if(exprCondition.__state != Expression::IDENT){ SemErr(coco_string_create("An identifier expected in the short form")); return; } //Use exprCondition as identifier alias = exprCondition.getValueString(); } else { //Use aliasCondition alias = Atom(move(aliasCondition)).get(); } expr.addBindings({Atom(string(alias))}); scope->addBinding(Atom(move(alias)), move(aliasAnns)); .) . SwitchVariantDecl = (. Expression varTested; std::wstring varAlias; bool flagAliasFound = false; expr = Expression(Operator::SWITCH_VARIANT, {}); .) "variant" lparen Expr [implic Ident (. flagAliasFound = true; .) ] [tagcolon ExprAnnotations] rparen tagcolon ExprAnnotations (. expr.addArg(std::move(varTested)); if (flagAliasFound) { expr.addBindings({Atom(varAlias)}); } else { if(varTested.__state == Expression::IDENT){ expr.addBindings({Atom(string(varTested.getValueString()))}); } } .) CaseVariantDecl {CaseVariantDecl} . CaseVariantDecl = (. ManagedScpPtr scope = root->add(new CodeScope(context.scope)); std::wstring key; scope->addBinding(Atom(string(expr.bindings.front())), Expression()); .) "case" lparen Ident rparen (. expr.addArg(root->recognizeVariantConstructor(Atom(std::move(key)))); .) BDecl<&*scope> (. expr.addBlock(scope); .) . IntrinsicDecl= (. std::wstring name; .) "intrinsic" ( Ident< name> (. outer = Expression(Operator::CALL_INTRINSIC, {}); outer.setValue(Atom(name)); .) lparen [CalleeParams] rparen | "query" (. outer = Expression(Operator::QUERY, {}); .) ( "late" IntrinsicQueryLateDecl | lparen [CalleeParams] rparen ) ). IntrinsicQueryLateDecl = (. std::wstring predicateAlias; Expression predicateE, predicateAnns; expr = Expression(Operator::QUERY_LATE, {}); ManagedScpPtr scope = root->add(new CodeScope(context.scope)); .) lparen Expr implic Ident tagcolon ExprAnnotations rparen tagcolon ExprAnnotations BDecl<&*scope> (. expr.addArg(move(predicateE)); expr.addBindings({Atom(wstring(predicateAlias))}); scope->addBinding(Atom(move(predicateAlias)), move(predicateAnns)); expr.addBlock(scope); .) . SequenceDecl = (. sequence = Expression(); sequence.setOp(Operator::SEQUENCE); ManagedScpPtr scope = root->add(new CodeScope(context.scope)); .) "seq" BDecl<&*scope> (. sequence.blocks.push_back(&*scope); scope = root->add(new CodeScope(&*scope)); .) { (. scope = root->add(new CodeScope(&*scope)); .) BDecl<&*scope> (. sequence.blocks.push_back(&*scope); .) }. /*============================ INTERFACES ===============================*/ Imprt<> = "import" "raw" lparen string (. root->__rawImports.push_back(Atom(t->val).get()); .) rparen period. InterfaceData<> = "interface" lparen ( "dfa" rparen InterfaceDFA | "extern-c" rparen InterfaceExternC | "cfa" rparen InterfaceCFA ). InterfaceExternC<> = (. ExternData data; .) lcurbrack {IncludeExternDecl | LibExternDecl } rcurbrack (. root->addExternData(move(data)); .) . LibExternDecl = (. std::wstring pkgname, libname; .) Ident assign "library" tagcolon "pkgconfig" lparen string (. pkgname = t->val; .) rparen period (. data.addLibrary(Atom(libname), Atom(pkgname)); .) . IncludeExternDecl = (. Expression inc; .) "include" ListLiteral period (. data.addIncludeDecl(move(inc)); .) . InterfaceDFA<> = lcurbrack { InstructDecl } rcurbrack . InstructDecl = (.Operator op; Expression tag; Expression scheme; std::vector& tags = scheme.operands; tags.push_back(Expression()); /* return value */ .) "operator" InstructAlias tagcolon lparen (.scheme.setOp(op); .) [ MetaSimpExpr (. tags.push_back(tag); .) { comma MetaSimpExpr (. tags.push_back(tag); .) } ] rparen [ implic MetaSimpExpr (. tags[0] = tag; .) ] (. root->addDFAData(move(scheme)); .) period. InstructAlias = ( "map" (. op = Operator::MAP; .) | "list_range" (. op = Operator::LIST_RANGE; .) | "list" (. op = Operator::LIST; .) | "fold" (. op = Operator::FOLD; .) | "index" (. op = Operator::INDEX; .) ). InterfaceCFA<> = lcurbrack { InstructCFADecl } rcurbrack . InstructCFADecl<> = (.Operator op; Expression tag; Expression scheme; std::vector& tags = scheme.operands; .) "operator" InstructAlias tagcolon (. scheme.setOp(op); .) [ MetaSimpExpr (. tags.push_back(tag); .) { comma MetaSimpExpr (. tags.push_back(tag); .) } ] period (. root->addInterfaceData(CFA, move(scheme)); .). /*============================ METAPROGRAMMING ===============================*/ // TagsDecl = (. Expression tag; TagModifier mod = TagModifier::NONE; .) // ':' { MetaSimpExpr (. /*f.addTag(std::move(tag), mod); */ .) // }. FnTag = (. Expression tag; TagModifier mod = TagModifier::NONE; .) MetaSimpExpr ['-' TagMod] (. f->addTag(std::move(tag), mod); .). TagMod = ( "assert" (. mod = TagModifier::ASSERT; .) | "require" (. mod = TagModifier::REQUIRE; .) ). // RuleDecl<> = // "rule" tagcolon (. RuleArguments args; RuleGuards guards; DomainAnnotation typ; std::wstring arg; .) // lparen Ident tagcolon Domain (. args.add(arg, typ); .) // {comma Ident tagcolon Domain (. args.add(arg, typ); .) // } rparen // ["case" RGuard {comma RGuard}] // lcurbrack RBody rcurbrack . /* - TODO use RGuard for guards-*/ // RuleContextDecl = (.Expression eHead, eGuards, eBody; .) // "rule" "context" tagcolon MetaSimpExpr // "case" lparen MetaSimpExpr rparen // lcurbrack MetaSimpExpr rcurbrack (.scope->contextRules.push_back(Expression(Operator::CONTEXT_RULE, {eHead, eGuards, eBody})); .). // Domain = // ( // "function" (. dom = DomainAnnotation::FUNCTION; .) // | "variable" (. dom = DomainAnnotation::VARIABLE; .) // ). // RGuard= (. Expression e; .) // MetaExpr (. guards.add(std::move(e)); .). // MetaExpr= (.Operator op; Expression e2; .) // MetaExpr2 // [MetaOp MetaExpr2 (. e = Expression(op, {e, e2}); .) // ]. // MetaExpr2= // ( // lparen MetaExpr rparen // | MetaSimpExpr // ). MetaSimpExpr= (. std::wstring i1, infix; Expression e2; .) ( '-' MetaSimpExpr (. e = Expression(Operator::NEG, {e2}); .) | IF(checkParametersList()) Ident (. e = Expression(Operator::CALL, {Expression(Atom(i1))}); .) lparen [ MetaCalleeParams ] rparen | IF(checkInfix()) Ident Ident MetaSimpExpr (. e = Expression(Operator::CALL, {Expression(Atom(infix))}); e.addArg(Expression(Atom(i1))); e.addArg(std::move(e2)); .) | Ident (. e = Expression(Operator::CALL, {Atom(i1)}); .) ). MetaCalleeParams = (. Expression e2; .) MetaSimpExpr (. e.addArg(Expression(e2)); .) {comma MetaSimpExpr (. e.addArg(Expression(e2)); .) }. // RBody = // (. Expression e; std::wstring msg; .) // "warning" MetaExpr ["message" string (. msg = t->val; .) // ] (. root->add(new RuleWarning(RuleArguments(args), RuleGuards(guards), std::move(e), Atom(msg))); .) // . // MetaOp< Operator& op> = // implic (. op = Operator::IMPL; .) // . /*============================ Expressions ===============================*/ ExprAnnotations = (. TypeAnnotation typ; std::list tags; Expression tag; e.tags.clear();.) Type (. e.bindType(move(typ)); .) {';' MetaSimpExpr (. tags.push_back(tag); .) } (. e.addTags(tags); .) . ExprTyped = Expr [tagcolon ExprAnnotations]. Expr< Expression& e> (. Operator op; Expression e2; .) = ExprArithmAdd [ RelOp ExprArithmAdd (. e = Expression(op, {e, e2}); .) ]. ExprArithmAdd< Expression& e>= (. Operator op; Expression e2; .) ExprArithmMul< e> [ AddOp< op> ExprArithmAdd< e2> (. e = Expression(op, {e, e2});.) ]. ExprArithmMul< Expression& e> (. Operator op; Expression e2; .) = ExprPostfix< e> [ MulOp< op> ExprArithmMul< e2> (. e = Expression(op, {e, e2}); .) ]. ExprPostfix = Term [ (. e = Expression(Operator::INDEX, {e}); .) {lbrack CalleeParams rbrack } ]. Term< Expression& e> (. std::wstring name; e = Expression(); .) = (IF (checkParametersList()) Ident< name> (. e = Expression(Operator::CALL, {Atom(name)}); root->recognizeVariantConstructor(e); .) lparen [CalleeParams] rparen | VarIdent (. recognizeIdentifier(e); .) | ListLiteral | ListRangeLiteral | LoopDecl | IfDecl | SwitchDecl | IntrinsicDecl | SequenceDecl | number (. e = Expression(Atom(t->val)); .) | string (. e = Expression(Atom(t->val)); .) | "true" (. e = Expression(Atom(1)); e.bindType(TypePrimitive::Bool); .) | "false" (. e = Expression(Atom(0)); e.bindType(TypePrimitive::Bool); .) | "undef" (. e = Expression(Operator::UNDEF, {}); .) | '-' Term (. e = Expression(Operator::NEG, {e}); .) | lparen ExprTyped rparen ). ListLiteral = (. std::wstring key; Expression val; std::list> keys; size_t keyCounter=0; .) lcurbrack (IF(checkTokenAfterIdent(_assign)) Ident assign Expr | Expr (. key = to_wstring(keyCounter++); .) ) (. keys.push_back(Atom(key)); e = Expression(Operator::LIST, {val}); .) {comma (IF(checkTokenAfterIdent(_assign)) Ident assign Expr | Expr (. key = to_wstring(keyCounter++); .) ) (. e.addArg(Expression(val)); keys.push_back(Atom(key)); .) } rcurbrack (. e.addBindings(keys.begin(), keys.end()); .) . ListRangeLiteral = (. Expression eFrom, eTo; .) lbrack Expr ".." Expr rbrack (. e = Expression(Operator::LIST_RANGE, {eFrom, eTo}); .) . CalleeParams = (. Expression e2; .) ExprTyped (. e.addArg(Expression(e2)); .) {comma ExprTyped (. e.addArg(Expression(e2)); .) }. AddOp< Operator& op> = (. op = Operator::ADD; .) ( '+' | '-' (. op = Operator::SUB; .) ). MulOp< Operator& op> = (. op = Operator::MUL; .) ( '*' | '/' (. op = Operator::DIV; .) ). RelOp< Operator& op> = (. op = Operator::EQU; .) ( equal | (ne1 | ne2) (. op = Operator::NE; .) | lse (. op = Operator::LSE; .) | lss (. op = Operator::LSS; .) | gte (. op = Operator::GTE; .) | gtr (. op = Operator::GTR; .) ). SkipModulesSection = "module" {ANY} (lcurbrack {ANY} rcurbrack | '.'). END Xreate. diff --git a/installation/prepare-opensuse-leap15 b/installation/prepare-opensuse-leap15 index e17360a..b04d03d 100755 --- a/installation/prepare-opensuse-leap15 +++ b/installation/prepare-opensuse-leap15 @@ -1,67 +1,77 @@ #!/bin/bash # VERSIONS OF MAJOR DEPENDENCIES: # OPENSUSE LEAP 15 # LLVM: 5.0.1 # CLANG: 5.0.1 # GCC: 7.3.1 - -CLINGO_PATH=/opt/potassco/clingo -COCO_PATH=/opt/coco -CLASP_VERSION=95cc1182f SCRIPT=`realpath $0` XREATE_PATH=`dirname $SCRIPT`/.. +#Provide ABSOLUTE path +CLINGO_PATH=${XREATE_PATH}/build/vendors/clingo +COCO_PATH=${XREATE_PATH}/build/vendors/coco + +CLASP_VERSION=95cc1182f + +pause(){ + read -n1 -rsp "$1 "$'Press any key to continue or Ctrl+C to exit...\n' +} + # PREREQUISITES # sudo zypper in \ git wget unzip make \ gcc7-c++ scons bison re2c\ llvm5-devel libboost_headers1_66_0-devel \ cmake gtest tbb-devel clang5-devel \ - libxml2-devel libboost_system1_66_0-devel libboost_filesystem1_66_0-devel + libxml2-devel libbsd-devel\ + libboost_system1_66_0-devel libboost_filesystem1_66_0-devel # COCO CPP # The Compiler Generator Coco/R # http://www.ssw.uni-linz.ac.at/coco/#CPP # -mkdir $COCO_PATH +pause "Preparing Coco.." +mkdir -p $COCO_PATH cd $COCO_PATH wget http://www.ssw.uni-linz.ac.at/coco/CPP/CocoSourcesCPP.zip unzip ./CocoSourcesCPP.zip make # CLINGO # A grounder and solver for logic programs. # https://github.com/potassco/clingo # +pause "Preparing Clingo.." mkdir -p $CLINGO_PATH cd $CLINGO_PATH git clone https://github.com/potassco/clingo.git ./ &&\ git reset --hard $CLASP_VERSION git apply $XREATE_PATH/installation/docker/patches/potassco-patch-95cc11 scons configure --build-dir=debug &&\ sed -i "s/, '-fvisibility=hidden'//" build/debug.py &&\ sed -i "s/CXXFLAGS = \[\(.*\)\]/CXXFLAGS = \['-fPIC', \1\]/" build/debug.py &&\ sed -i "s/WITH_LUA = 'auto'/WITH_LUA = None/" build/debug.py &&\ sed -i "s/WITH_PYTHON = 'auto'/WITH_PYTHON = None/" build/debug.py &&\ sed -i "s/'-std=c++11'/'-std=c++14'/" build/debug.py &&\ cat build/debug.py &&\ scons --build-dir=debug # XREATE # +pause "Preparing Xreate.." cd $XREATE_PATH/vendors/jeayeson git pull ./configure mkdir ../../build cd ../../build ln -s $COCO_PATH/Copyright.frame $XREATE_PATH/vendors/coco/generator/Copyright.frame ln -s $COCO_PATH/Scanner.frame $XREATE_PATH/vendors/coco/generator/Scanner.frame mkdir $XREATE_PATH/grammar/main $XREATE_PATH/grammar/modules cmake -DCMAKE_BUILD_TYPE=Debug -DBUILD_XREATE_TESTS=1 -DCOCO_EXECUTABLE=$COCO_PATH/Coco -DCLINGO_PATH=$CLINGO_PATH -DCOCO_FRAMES_PATH=$XREATE_PATH/vendors/coco/generator/ -DCMAKE_CXX_COMPILER=g++ ../cpp diff --git a/pom.xml b/pom.xml deleted file mode 100644 index 463d822..0000000 --- a/pom.xml +++ /dev/null @@ -1,62 +0,0 @@ - - 4.0.0 - - org.xreate - xreate - 1.0-SNAPSHOT - jar - - xreate - http://maven.apache.org - - - - org.apache.maven.plugins - maven-compiler-plugin - 2.3.2 - - 1.6 - 1.6 - - - - - - UTF-8 - - - - - junit - junit - 4.10 - jar - - - org.antlr - antlr - 3.2 - - - org.antlr - antlr-runtime - 3.2 - - - com.google.guava - guava - 11.0.2 - - - javolution - javolution - 5.5.1 - - - jllvm - jllvm - 2.8 - - - diff --git a/vendors/coco/generator/Copyright.frame b/vendors/coco/generator/Copyright.frame index 708b5d5..6cac1e1 120000 --- a/vendors/coco/generator/Copyright.frame +++ b/vendors/coco/generator/Copyright.frame @@ -1 +1 @@ -/usr/share/coco-cpp/Copyright.frame \ No newline at end of file +/private/prg/code/xreate/build/vendors/coco/Copyright.frame \ No newline at end of file diff --git a/vendors/coco/generator/Scanner.frame b/vendors/coco/generator/Scanner.frame index d1ee132..2489dd2 120000 --- a/vendors/coco/generator/Scanner.frame +++ b/vendors/coco/generator/Scanner.frame @@ -1 +1 @@ -/usr/share/coco-cpp/Scanner.frame \ No newline at end of file +/private/prg/code/xreate/build/vendors/coco/Scanner.frame \ No newline at end of file