No OneTemporary

File Metadata

Created
Sun, Dec 22, 6:51 AM
diff --git a/config/default.json b/config/default.json
index d52c52a..5ee2fb5 100644
--- a/config/default.json
+++ b/config/default.json
@@ -1,74 +1,74 @@
{
"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": "*",
+ "default": "*-Effects.compilation_versions_1:Effects.compilation_versions_versionNext1",
"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..9dad86e 100644
--- a/cpp/src/CMakeLists.txt
+++ b/cpp/src/CMakeLists.txt
@@ -1,238 +1,223 @@
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
+ clang
)
# 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
+ ${CLINGO_PATH}/libgringo
+ ${CLINGO_PATH}/libclingo
+ ${CLINGO_PATH}/build/clasp
+ ${CLINGO_PATH}/clasp
+ ${CLINGO_PATH}/clasp/libpotassco
)
INCLUDE_DIRECTORIES(${POTASSCO_INCLUDE_PATH})
set(LIBCLASP_LIBS
clingo
clasp
+ potassco
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})
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/ExternLayer.cpp b/cpp/src/ExternLayer.cpp
index 03afa74..592462c 100644
--- a/cpp/src/ExternLayer.cpp
+++ b/cpp/src/ExternLayer.cpp
@@ -1,334 +1,334 @@
/* 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/.
*
* ExternLayer.cpp
*
* Created on: 4/21/15
* Author: pgess <v.melnychenko@xreate.org>
*/
#include "ExternLayer.h"
#include "clang/Tooling/Tooling.h"
#include "clang/Frontend/ASTUnit.h"
-#include "clang/Frontend/CodeGenOptions.h"
+#include "clang/Basic/CodeGenOptions.h"
#include "clang/ASTMatchers/ASTMatchers.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/CodeGen/ModuleBuilder.h"
#include "clang/CodeGen/CodeGenABITypes.h"
#include <llvm/Support/DynamicLibrary.h>
#include <boost/format.hpp>
#include <boost/algorithm/string/join.hpp>
#include <cstdio>
#include <iostream>
#include <clang/Frontend/CompilerInstance.h>
using namespace std;
using namespace clang;
using namespace clang::driver;
using namespace clang::tooling;
using namespace clang::ast_matchers;
using namespace llvm;
namespace xreate{
class FinderCallbackTypeDecl : public MatchFinder::MatchCallback{
public:
QualType typeResult;
virtual void
run(const MatchFinder::MatchResult &Result) {
if (const TypedefDecl * decl = Result.Nodes.getNodeAs<clang::TypedefDecl>("typename")) {
typeResult = decl->getUnderlyingType();
}
}
} ;
class FinderCallbackFunction : public MatchFinder::MatchCallback{
public:
QualType typeResult;
virtual void
run(const MatchFinder::MatchResult &Result) {
if (const FunctionDecl * decl = Result.Nodes.getNodeAs<clang::FunctionDecl>("function")) {
typeResult = decl->getType();
}
}
} ;
void
ExternData::addLibrary(Atom<Identifier_t>&& name, Atom<String_t>&& package) {
__dictLibraries.emplace(name.get(), package.get());
}
void
ExternData::addIncludeDecl(Expression&& e) {
assert(e.op == Operator::LIST);
//TODO ?? implement Expression parsing(Array of Expr as vector<string>);
for(size_t i = 0, size = e.operands.size(); i < size; ++i) {
std::string library = e.bindings.at(i);
assert(__dictLibraries.count(library));
std::string package = __dictLibraries.at(library);
Expression listHeaders = e.operands.at(i);
assert(listHeaders.op == Operator::LIST);
std::vector<std::string> headers;
std::transform(listHeaders.operands.begin(), listHeaders.operands.end(), std::inserter(headers, headers.end()),
[](const Expression & o) {
assert(o.__state == Expression::STRING);
return o.getValueString();
});
entries.emplace_back(ExternEntry{package, std::move(headers)});
}
}
void
ExternLayer::addExternalData(const std::vector<ExternEntry>& data) {
entries.insert(entries.end(), data.begin(), data.end());
}
ExternLayer::ExternLayer(LLVMLayer *llvm)
: __llvm(llvm) { }
std::vector<string>
ExternLayer::fetchPackageFlags(const ExternEntry& entry) {
std::vector<string> args;
FILE* flags = popen((string("pkg-config --cflags ") + entry.package).c_str(), "r");
size_t linesize = 0;
char* linebuf = 0;
ssize_t linelen = 0;
while ((linelen = getdelim(&linebuf, &linesize, ' ', flags)) > 0) {
if (linebuf[0] == '\n') continue;
if (linelen == 1 && linebuf[0] == ' ') continue;
//cut unwanted symbols at the end
char symbLast = linebuf[linelen - 1 ];
if (symbLast == ' ' || symbLast == '\n') linebuf[linelen - 1] = 0;
//print header for debug purposes
llvm::outs() << '<' << linebuf << "> ";
args.push_back(linebuf);
free(linebuf);
linebuf = 0;
}
pclose(flags);
return (args);
}
std::vector<string>
ExternLayer::fetchPackageLibs(const ExternEntry& entry) {
std::vector<string> libs;
FILE* flags = popen((string("pkg-config --libs ") + entry.package).c_str(), "r");
size_t linesize = 0;
char* linebuf = 0;
ssize_t linelen = 0;
while ((linelen = getdelim(&linebuf, &linesize, ' ', flags)) > 0) {
if (linebuf[0] == '\n') continue;
if (linelen == 1 && linebuf[0] == ' ') continue;
//cut unwanted symbols at the end
char symbLast = linebuf[linelen - 1 ];
if (symbLast == ' ' || symbLast == '\n') linebuf[linelen - 1] = 0;
//cut unwanted symbols at the beginning
if (linelen > 1 && linebuf[0] == '-' && linebuf[1] == 'l') {
libs.push_back(linebuf + 2);
} else {
libs.push_back(linebuf);
}
//print lib name for debug purposes
llvm::outs() << '<' << linebuf << "> ";
free(linebuf);
linebuf = 0;
}
pclose(flags);
return (libs);
}
void
ExternLayer::loadLibraries(vector<string>&& libs) {
string msgErr;
for (const string& lib : libs) {
const string& libName = string("lib") + lib + ".so";
if (!llvm::sys::DynamicLibrary::LoadLibraryPermanently(libName.c_str(), &msgErr)) {
llvm::errs() << "\n" << "Loading library " << lib << ". " << msgErr << "\n";
}
}
}
void
ExternLayer::init(const AST* root) {
addExternalData(root->__externdata);
// TODO -EXTERN01.DIP, use default include path from 'clang -xc++ -E'
list<string> code;
std::vector<string> args{
"-I/usr/include"
, "-I/usr/local/include"
, "-I/usr/lib64/clang/5.0.1/include"
// ,"-I/usr/lib/gcc/x86_64-linux-gnu/4.9/include"
// ,"-I/usr/include/x86_64-linux-gnu"
};
std::vector<string> libs;
boost::format formatInclude("#include \"%1%\"");
for(const ExternEntry& entry : entries) {
llvm::outs() << "[ExternC] Processing package: " << entry.package << "\n";
llvm::outs() << "[ExternC] args: ";
vector<string>&& args2 = fetchPackageFlags(entry);
args.insert(args.end(), args2.begin(), args2.end());
for(const string arg : args2) {
llvm::outs() << "<" << arg << "> ";
}
llvm::outs() << "\n[ExternC] libs: ";
args2 = fetchPackageLibs(entry);
for(const string arg : args2) {
llvm::outs() << "<" << arg << "> ";
}
libs.insert(libs.end(), args2.begin(), args2.end());
llvm::outs() << "\n[ExternC] headers: ";
std::transform(entry.headers.begin(), entry.headers.end(), std::inserter(code, code.begin()),
[&formatInclude](const string header ) {
string line = boost::str(formatInclude % header);
llvm::outs() << "<" << line << "> ";
return line;
});
llvm::outs() << '\n';
}
loadLibraries(move(libs));
ast = buildASTFromCodeWithArgs(boost::algorithm::join(code, "\n"), args);
__llvm->module->setDataLayout(ast->getASTContext().getTargetInfo().getDataLayout());
__clang.reset(new CompilerInstance());
__clang->createDiagnostics();
__codegen.reset(CreateLLVMCodeGen(
__clang->getDiagnostics(),
__llvm->module->getName(),
__clang->getHeaderSearchOpts(),
__clang->getPreprocessorOpts(),
clang::CodeGenOptions(),
__llvm->llvmContext
));
__codegen->Initialize(ast->getASTContext());
};
bool
ExternLayer::isPointer(const clang::QualType &t) {
const clang::Type * tInfo = t.getTypePtr();
assert(tInfo);
return tInfo->isAnyPointerType();
}
llvm::Type*
ExternLayer::toLLVMType(const clang::QualType& t) {
return CodeGen::convertTypeForMemory( __codegen->CGM(), t);
}
std::vector<std::string>
ExternLayer::getStructFields(const clang::QualType& ty) {
clang::QualType t = ty;
if (isPointer(ty)) {
const clang::PointerType* tPtr = ty->getAs<clang::PointerType>();
t = tPtr->getPointeeType();
}
assert(t.getTypePtr()->isRecordType());
const RecordType *record = t->getAsStructureType();
assert(record);
std::vector<std::string> result;
//FieldDecl* field: record->getDecl()->fields()
for (auto i = record->getDecl()->field_begin(); i != record->getDecl()->field_end(); ++i) {
result.push_back(i->getName());
}
return result;
}
bool
ExternLayer::isArrayType(const std::string& type){
clang::QualType typeRaw = lookupType(type);
if (isPointer(typeRaw)) {
const clang::PointerType* typePtr = typeRaw->getAs<clang::PointerType>();
typeRaw = typePtr->getPointeeType();
}
return typeRaw->isArrayType();
}
bool
ExternLayer::isRecordType(const std::string& type){
clang::QualType typeRaw = lookupType(type);
if (isPointer(typeRaw)) {
const clang::PointerType* typePtr = typeRaw->getAs<clang::PointerType>();
typeRaw = typePtr->getPointeeType();
}
return typeRaw->isRecordType();
}
clang::QualType
ExternLayer::lookupType(const std::string& id) {
MatchFinder finder;
FinderCallbackTypeDecl callbackTypeDecl;
auto matcherTypeDecl = typedefDecl(hasName(id)).bind("typename");
finder.addMatcher(matcherTypeDecl, &callbackTypeDecl);
finder.matchAST(ast->getASTContext());
assert(! callbackTypeDecl.typeResult.isNull());
return callbackTypeDecl.typeResult;
}
llvm::Function*
ExternLayer::lookupFunction(const std::string& name) {
if (__functions.count(name)) {
return __functions.at(name);
}
MatchFinder finder;
FinderCallbackFunction callback;
auto matcher = functionDecl(hasName(name)).bind("function");
finder.addMatcher(matcher, &callback);
finder.matchAST(ast->getASTContext());
if (callback.typeResult.isNull()) {
cout << "[External Layer] " << "Unknown function: " << name << endl;
assert(false && "Unknown external function");
}
const QualType& tyFuncQual = callback.typeResult;
llvm::Type *tyRaw = CodeGen::convertTypeForMemory(__codegen->CGM(), tyFuncQual);
llvm::FunctionType* tyRawFunc = llvm::dyn_cast<llvm::FunctionType>(tyRaw);
llvm::Function* function = llvm::Function::Create(
tyRawFunc,
llvm::GlobalValue::ExternalLinkage,
name,
__llvm->module.get());
__functions.emplace(name, function);
return function;
}
}//end of xreate namespace
diff --git a/cpp/src/ExternLayer.h b/cpp/src/ExternLayer.h
index 0bae75e..4617a6f 100644
--- a/cpp/src/ExternLayer.h
+++ b/cpp/src/ExternLayer.h
@@ -1,72 +1,71 @@
/* 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/.
*
* ExternLayer.h
*
* Created on: 4/21/15
* Author: pgess <v.melnychenko@xreate.org>
*/
/**
* \file ExternLayer.h
* \brief An external C code interaction support
*/
#ifndef XREATE_EXTERNLAYER_H
#define XREATE_EXTERNLAYER_H
#include "llvmlayer.h"
#include <vector>
#include <string>
#include <map>
#include "ast.h"
#include "clang/AST/ASTContext.h"
#include "clang/Frontend/ASTUnit.h"
-#include "clang/Frontend/CodeGenOptions.h"
#include "clang/CodeGen/CodeGenABITypes.h"
#include "clang/Lex/PreprocessorOptions.h"
namespace clang{
class CodeGenerator;
}
namespace xreate{
struct ExternData{
void addLibrary(Atom<Identifier_t>&& name, Atom<String_t>&& package);
void addIncludeDecl(Expression&& e);
std::vector<ExternEntry> entries;
std::map<std::string, std::string> __dictLibraries;
};
/** \brief A wrapper over Clang */
class ExternLayer{
public:
ExternLayer(LLVMLayer* llvm);
void init(const AST* root);
llvm::Function* lookupFunction(const std::string& name);
clang::QualType lookupType(const std::string& id);
std::vector<std::string> getStructFields(const clang::QualType& ty);
llvm::Type* toLLVMType(const clang::QualType& t);
bool isPointer(const clang::QualType& t);
bool isArrayType(const std::string& type);
bool isRecordType(const std::string& type);
static std::vector<std::string> fetchPackageFlags(const ExternEntry& entry);
static std::vector<std::string> fetchPackageLibs(const ExternEntry& entry);
private:
std::unique_ptr<clang::ASTUnit> ast;
std::unique_ptr<clang::CodeGenerator> __codegen;
std::unique_ptr<clang::CompilerInstance> __clang;
LLVMLayer* __llvm;
std::vector<ExternEntry> entries;
std::map<std::string, llvm::Function*> __functions;
void addExternalData(const std::vector<ExternEntry>& data);
void loadLibraries(std::vector<std::string>&& libs);
};
}
#endif //XREATE_EXTERNLAYER_H
diff --git a/cpp/src/analysis/interpretation.cpp b/cpp/src/analysis/interpretation.cpp
index 7c18b4e..26e5c64 100644
--- a/cpp/src/analysis/interpretation.cpp
+++ b/cpp/src/analysis/interpretation.cpp
@@ -1,269 +1,267 @@
/*
* 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 <v.melnychenko@xreate.org>
* Created on June 25, 2018, 3:25 PM
*/
#include "analysis/interpretation.h"
using namespace std;
namespace xreate{
namespace interpretation{
typedef vector<int> InstancePacked;
std::list<Expression>
generateAllInstancesInDomain2(const ExpandedType& domainT) {
if(!domainT->isValid()) {
return {Expression()};
}
assert(domainT->__operator == TypeOperator::VARIANT);
std::list<Expression> results;
int variantId = -1;
bool flagDomainStateless = std::all_of(domainT->__operands.begin(), domainT->__operands.end(),
[](const TypeAnnotation & subdomainT) {
return !subdomainT.isValid();
});
for(const TypeAnnotation& subdomainT : domainT->__operands) {
++variantId;
if(flagDomainStateless) {
Expression result(Operator::VARIANT,{});
result.setValueDouble(variantId);
results.push_back(result);
continue;
}
std::list<Expression> subresults = generateAllInstancesInDomain2(ExpandedType(subdomainT));
for (const Expression& subresult : subresults) {
Expression result(Operator::VARIANT,{});
result.setValueDouble(variantId);
result.operands.push_back(subresult);
results.push_back(result);
}
}
return results;
}
TypeAnnotation
-collapseFnGroup(const std::list<Gringo::Symbol>& symbols) {
- Gringo::Symbol symbolAny = symbols.front();
- size_t operandsCount = symbolAny.args().size;
+collapseFnGroup(const std::list<Clingo::Symbol>& symbols) {
+ Clingo::Symbol symbolAny = symbols.front();
+ size_t operandsCount = symbolAny.arguments().size();
TypeAnnotation resultT;
resultT.__operands.reserve(operandsCount);
for(size_t operandId = 0; operandId < operandsCount; ++operandId) {
- std::list<Gringo::Symbol> column;
+ std::list<Clingo::Symbol> column;
- for(const Gringo::Symbol& row : symbols) {
- column.push_back(row.args()[operandId]);
+ for(const Clingo::Symbol& row : symbols) {
+ column.push_back(row.arguments()[operandId]);
}
TypeAnnotation operandT = collapseColumn(column);
resultT.__operands.push_back(operandT);
}
if(resultT.__operands.size() == 1) {
return resultT.__operands.front();
}
if(resultT.__operands.size() > 1) {
resultT.__operator = TypeOperator::LIST_RECORD;
return resultT;
}
return resultT;
}
TypeAnnotation
-collapseColumn(const std::list<Gringo::Symbol>& symbols) {
+collapseColumn(const std::list<Clingo::Symbol>& symbols) {
TypeAnnotation resultT;
if(!symbols.size()) return resultT;
- Gringo::Symbol symbolAny = symbols.front();
+ Clingo::Symbol symbolAny = symbols.front();
switch(symbolAny.type()) {
- case Gringo::SymbolType::Num:
+ case Clingo::SymbolType::Number:
{
return TypeAnnotation(TypePrimitive::Num);
}
- case Gringo::SymbolType::Str:
+ case Clingo::SymbolType::String:
{
return TypeAnnotation(TypePrimitive::String);
}
- case Gringo::SymbolType::Fun:
+ case Clingo::SymbolType::Function:
{
- map<string, list < Gringo::Symbol>> fnGroups;
+ map<string, list < Clingo::Symbol>> fnGroups;
- for(const Gringo::Symbol& row : symbols) {
- fnGroups[row.name().c_str()].push_back(row);
+ for(const Clingo::Symbol& row : symbols) {
+ fnGroups[row.name()].push_back(row);
}
TypeAnnotation resultT;
resultT.__operands.reserve(fnGroups.size());
resultT.bindings.reserve(fnGroups.size());
for(const auto& group : fnGroups) {
if(!group.second.size()) continue;
TypeAnnotation variantT = collapseFnGroup(group.second);
- Gringo::Symbol symbolAny = group.second.front();
- string variantName = symbolAny.name().c_str();
+ Clingo::Symbol symbolAny = group.second.front();
+ string variantName(symbolAny.name());
resultT.fields.push_back(variantName);
resultT.__operands.push_back(variantT);
}
resultT.__operator = TypeOperator::VARIANT;
// if(resultT.__operands.size() == 1) {
// return resultT.__operands.front();
// }
return resultT;
}
- case Gringo::SymbolType::Inf:
- case Gringo::SymbolType::Special:
- case Gringo::SymbolType::Sup:
+ case Clingo::SymbolType::Infimum:
+ case Clingo::SymbolType::Supremum:
{
break;
}
}
assert(false);
return TypeAnnotation();
}
ExpandedType
dereferenceSlaveType(ExpandedType t, const TranscendLayer* transcend) {
assert(t->__operator == TypeOperator::SLAVE);
const string& domain = t->__valueCustom;
StaticModel model = transcend->query(domain);
if(!model.size()) return ExpandedType(TypeAnnotation());
- std::list<Gringo::Symbol> symbols;
+ std::list<Clingo::Symbol> symbols;
for(auto row : model) {
symbols.push_back(row.second);
}
return ExpandedType(collapseFnGroup(symbols));
}
Expression
-representTransExpression(const Gringo::Symbol& atom, ExpandedType schemaT, TranscendLayer* transcend) {
- atom.print(std::cout); std::cout<<endl;
+representTransExpression(const Clingo::Symbol& atom, ExpandedType schemaT, TranscendLayer* transcend) {
switch(schemaT->__operator) {
case TypeOperator::NONE:
{
switch(schemaT->__value) {
case TypePrimitive::I8:
case TypePrimitive::I32:
case TypePrimitive::I64:
case TypePrimitive::Num:
case TypePrimitive::Int:
{
- return Expression(Atom<Number_t>(atom.num()));
+ return Expression(Atom<Number_t>(atom.number()));
}
case TypePrimitive::String:
{
- return Expression(Atom<String_t>(atom.string().c_str()));
+ return Expression(Atom<String_t>(atom.string()));
}
case TypePrimitive::Invalid:
case TypePrimitive::Bool:
case TypePrimitive::Float:
{
assert(false);
return Expression();
}
}
break;
}
case TypeOperator::SLAVE:
{
ExpandedType contentT = dereferenceSlaveType(schemaT, transcend);
return representTransExpression(atom, contentT, transcend);
}
case TypeOperator::VARIANT:
{
map<string, int> dictVariants;
for(size_t variantId = 0; variantId < schemaT->fields.size(); ++variantId) {
dictVariants.emplace(schemaT->fields.at(variantId), variantId);
}
- string predicateName = atom.name().c_str();
+ string predicateName(atom.name());
assert(dictVariants.count(predicateName));
size_t predicateId = dictVariants.at(predicateName);
Expression result(Operator::VARIANT,{});
result.op = Operator::VARIANT;
result.setValueDouble(predicateId);
if(!schemaT->__operands.size()) return result;
ExpandedType contentT = schemaT->__operands.at(predicateId).__operator == TypeOperator::SLAVE
? dereferenceSlaveType(ExpandedType(schemaT->__operands.at(predicateId)), transcend)
: ExpandedType(schemaT->__operands.at(predicateId));
//edge case, content's type is LIST_NAMED:
if (contentT->__operator == TypeOperator::LIST_RECORD) {
result.operands.push_back(representTransExpression(atom, contentT, transcend));
} else if(!contentT->isValid()) {
return result;
} else {
- assert(atom.args().size);
- result.operands.push_back(representTransExpression(atom.args()[0], contentT, transcend));
+ assert(atom.arguments().size());
+ result.operands.push_back(representTransExpression(atom.arguments()[0], contentT, transcend));
}
return result;
}
case TypeOperator::LIST_RECORD:
{
- const Gringo::SymSpan& operandsRaw = atom.args();
- size_t opCount = operandsRaw.size;
+ const Clingo::SymbolSpan& operandsRaw = atom.arguments();
+ size_t opCount = operandsRaw.size();
assert(opCount == schemaT->__operands.size());
size_t operandId = 0;
std::vector<Expression> operands;
operands.reserve(opCount);
for(const TypeAnnotation operandT : schemaT->__operands) {
operands.push_back(representTransExpression(operandsRaw[operandId], ExpandedType(operandT), transcend));
++operandId;
}
Expression result(Operator::LIST,{});
result.operands = operands;
result.type = schemaT;
return result;
}
case TypeOperator::LIST_ARRAY:
case TypeOperator::CALL:
case TypeOperator::CUSTOM:
case TypeOperator::ACCESS:
case TypeOperator::LINK:
{
assert(false);
return Expression();
}
}
assert(false);
return Expression();
}
}
} //end of xreate namespace
diff --git a/cpp/src/analysis/interpretation.h b/cpp/src/analysis/interpretation.h
index 8a93e17..c00e475 100644
--- a/cpp/src/analysis/interpretation.h
+++ b/cpp/src/analysis/interpretation.h
@@ -1,45 +1,45 @@
/*
* 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 <v.melnychenko@xreate.org>
* Created on June 25, 2018, 3:24 PM
*/
/**
* \file interpretation.h
* \brief Interpretation related functions
*/
#ifndef INTERPRETATION_H
#define INTERPRETATION_H
#include "transcendlayer.h"
namespace xreate{ namespace interpretation{
/**
* \brief Converts a Transcend's fact to a Xreate's expression that can be interpreted further. Supports `query` keyword.
* @param atom Transcend's fact
* @param schemaT Type of the resulting expression
* @param transcend Transcend's instance
* @return converted Transcend' fact in form of Xreate's expression
*/
- Expression representTransExpression(const Gringo::Symbol& atom, ExpandedType schemaT, TranscendLayer* transcend);
+ Expression representTransExpression(const Clingo::Symbol& atom, ExpandedType schemaT, TranscendLayer* transcend);
/**
* \brief Expands slave type.
* @param t Slave type
* @param transcend Instance of Transcend
* @return The expanded slave type
*/
ExpandedType dereferenceSlaveType(ExpandedType t, const TranscendLayer* transcend);
- TypeAnnotation collapseColumn(const std::list<Gringo::Symbol>& symbols);
+ TypeAnnotation collapseColumn(const std::list<Clingo::Symbol>& symbols);
std::list<Expression> generateAllInstancesInDomain2(const ExpandedType& domainT);
}
}
#endif /* INTERPRETATION_H */
diff --git a/cpp/src/aux/latereasoning.cpp b/cpp/src/aux/latereasoning.cpp
index a14143e..4942490 100644
--- a/cpp/src/aux/latereasoning.cpp
+++ b/cpp/src/aux/latereasoning.cpp
@@ -1,54 +1,54 @@
/*
* 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 <v.melnychenko@xreate.org>
* Created on June 7, 2018, 6:01 PM
*/
#include "aux/latereasoning.h"
#include "analysis/interpretation.h"
#include "ast.h"
using namespace std;
namespace xreate{
namespace latereasoning{
-LateAnnotation::LateAnnotation(const Gringo::Symbol& symbolStatic) {
- guardedContent.push_back(pair<list<Gringo::Symbol>, Gringo::Symbol>({}, symbolStatic));
+LateAnnotation::LateAnnotation(const Clingo::Symbol& symbolStatic) {
+ guardedContent.push_back(pair<list<Clingo::Symbol>, Clingo::Symbol>({}, symbolStatic));
}
-boost::optional<Gringo::Symbol>
+boost::optional<Clingo::Symbol>
LateAnnotation::select(const std::list<Expression>& keys, AST* root, TranscendLayer* transcend) const {
for(const auto& entry : guardedContent) {
- const std::list<Gringo::Symbol>& guardsExpected = entry.first;
+ const std::list<Clingo::Symbol>& guardsExpected = entry.first;
auto keyPSIt = guardKeys.begin();
auto keyActualIt = keys.begin();
bool result = true;
- for(const Gringo::Symbol& guardExpectedGS : guardsExpected) {
+ for(const Clingo::Symbol& guardExpectedGS : guardsExpected) {
auto keyS = transcend->unpack(*keyPSIt);
const ExpandedType& keyT = root->getType(CodeScope::getDefinition(keyS));
const ExpandedType& keyTPlain = keyT->__operator == TypeOperator::SLAVE ?
interpretation::dereferenceSlaveType(keyT, transcend)
: keyT;
Expression guardExpectedE = interpretation::representTransExpression(
guardExpectedGS, keyTPlain, transcend);
if(!(guardExpectedE == *keyActualIt)) {
result = false;
break;
}
++keyActualIt;
++keyPSIt;
}
if(!result) continue;
return entry.second;
}
return boost::none;
}
}
}
diff --git a/cpp/src/aux/latereasoning.h b/cpp/src/aux/latereasoning.h
index e6ba460..d2e8946 100644
--- a/cpp/src/aux/latereasoning.h
+++ b/cpp/src/aux/latereasoning.h
@@ -1,91 +1,91 @@
/*
* 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 <v.melnychenko@xreate.org>
* Created on June 2, 2018, 1:08 PM
*/
/**
* \file src/aux/latereasoning.h
* \brief Late reasoning support
*/
#ifndef LATEREASONING_H
#define LATEREASONING_H
#include "transcendlayer.h"
namespace xreate{ namespace latereasoning{
/** \brief Represents Late Annotation, i.e. an annotation with late or runtime defined parameters*/
struct LateAnnotation{
LateAnnotation(){}
- LateAnnotation(const Gringo::Symbol& symbolStatic);
- std::list<std::pair<std::list<Gringo::Symbol>, Gringo::Symbol>> guardedContent;
+ LateAnnotation(const Clingo::Symbol& symbolStatic);
+ std::list<std::pair<std::list<Clingo::Symbol>, Clingo::Symbol>> guardedContent;
std::list<SymbolPacked> guardKeys;
- boost::optional<Gringo::Symbol> select(const std::list<Expression>& keys, AST* root, TranscendLayer* transcend) const;
+ boost::optional<Clingo::Symbol> select(const std::list<Expression>& keys, AST* root, TranscendLayer* transcend) const;
};
/** \brief Represents a group of all late annotations attached to a specific target */
struct LateAnnotationsGroup{
- std::unordered_map<Gringo::Symbol, LateAnnotation> annotations;
+ std::unordered_map<Clingo::Symbol, LateAnnotation> annotations;
};
-typedef std::map<Gringo::Symbol, LateAnnotation> LateModel;
+typedef std::map<Clingo::Symbol, LateAnnotation> LateModel;
/**
* \brief Decorates \ref TranscendLayer to support late annotations processing
* \extends TranscendLayer
*/
template<class Parent>
class LateReasoningTranscendDecorator: public Parent{
public:
const LateAnnotationsGroup& queryLate(const std::string& alias) const{
static LateAnnotationsGroup groupInvalid;
if(!__modelLate.count(alias)) return groupInvalid;
return __modelLate.at(alias);
}
protected:
- virtual bool processSolution(Gringo::Model const &model) override{
+ virtual bool processSolution(Clingo::Model const &model) override{
const std::string& atomLateStatement = "late";
- for(const Gringo::Symbol& atom: model.atoms(clingo_show_type_atoms)){
- std::string atomName(atom.name().c_str());
+ for(const Clingo::Symbol& atom: model.symbols(clingo_show_type_atoms)){
+ std::string atomName(atom.name());
if(atomName == atomLateStatement){
//late atom's format: (Target, (tuple of keys), (tuple of values), late-annotation)
- auto atomLate = TranscendLayer::parse<Gringo::Symbol, std::list<SymbolPacked>, std::list<Gringo::Symbol>, Gringo::Symbol>(atom);
- const std::string& atomAlias = std::get<3>(atomLate).name().c_str();
+ auto atomLate = TranscendLayer::parse<Clingo::Symbol, std::list<SymbolPacked>, std::list<Clingo::Symbol>, Clingo::Symbol>(atom);
+ std::string atomAlias(std::get<3>(atomLate).name());
addLateAtom(atomAlias, std::get<0>(atomLate),
std::get<3>(atomLate), std::get<1>(atomLate),
std::get<2>(atomLate));
}
}
return Parent::processSolution(model);
}
private:
std::map<std::string, LateAnnotationsGroup> __modelLate;
- void addLateAtom(const std::string& alias, const Gringo::Symbol& annId,
- const Gringo::Symbol& content, const std::list<SymbolPacked>& guardKeys,
- const std::list<Gringo::Symbol>& guardValues){
+ void addLateAtom(const std::string& alias, const Clingo::Symbol& annId,
+ const Clingo::Symbol& content, const std::list<SymbolPacked>& guardKeys,
+ const std::list<Clingo::Symbol>& guardValues){
LateAnnotationsGroup& group = __modelLate[alias];
LateAnnotation& annotation = group.annotations[annId];
if (annotation.guardedContent.empty()){
annotation.guardKeys = guardKeys;
}
annotation.guardedContent.push_back(std::make_pair(guardValues, content));
}
};
}} // end of xreate::latereasoning
#endif /* LATEREASONING_H */
diff --git a/cpp/src/compilation/interpretation-instructions.cpp b/cpp/src/compilation/interpretation-instructions.cpp
index f4387bd..57e9bf6 100644
--- a/cpp/src/compilation/interpretation-instructions.cpp
+++ b/cpp/src/compilation/interpretation-instructions.cpp
@@ -1,113 +1,113 @@
/*
* 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 <v.melnychenko@xreate.org>
* Created on June 15, 2018, 5:32 PM
*/
#include "compilation/interpretation-instructions.h"
#include "analysis/interpretation.h"
#include "transcendlayer.h"
#include "targets.h"
#include "aux/latereasoning.h"
#include "latetranscend.h"
#include "aux/transcend-decorators.h"
#include "compilation/targetinterpretation.h"
using namespace std;
using namespace xreate::latereasoning;
namespace xreate{
namespace interpretation{
Expression
IntrinsicQueryInstruction::process(const Expression& expression) {
AST* ast = static_cast<TargetInterpretation*> (__fnI12n->man)->ast;
TranscendLayer* transcend = static_cast<TargetInterpretation*> (__fnI12n->man)->pass->man->transcend;
ExpandedType targetT = ast->getType(expression);
assert(expression.operands.size() == 1);
assert(expression.operands.front().__state == Expression::STRING);
assert(targetT->__operator == TypeOperator::LIST_ARRAY);
std::string namePredicate = expression.operands.front().getValueString();
StaticModel model = (static_cast<TargetInterpretation*> (__fnI12n->man))->pass->man->transcend->query(namePredicate);
Expression result(Operator::LIST,{});
result.operands.reserve(model.size());
ExpandedType elementT = targetT->__operands.at(0).__operator == TypeOperator::SLAVE
? dereferenceSlaveType(ExpandedType(targetT->__operands.at(0)), transcend)
: ExpandedType(targetT->__operands.at(0));
if(model.size()) {
if (elementT->__operator == TypeOperator::LIST_RECORD) {
//edge case, content's type is LIST_NAMED:
for(const auto& row : model) {
result.operands.push_back(representTransExpression(row.second, elementT, transcend));
}
} else {
for (const auto& row : model) {
- assert(row.second.args().size);
- result.operands.push_back(representTransExpression(row.second.args()[0], elementT, transcend));
+ assert(row.second.arguments().size());
+ result.operands.push_back(representTransExpression(row.second.arguments()[0], elementT, transcend));
}
}
}
return result;
}
llvm::Value*
IntrinsicQueryInstruction::processLate(const Expression& expression, const compilation::Context& context) {
assert(expression.blocks.size());
CodeScope* body = expression.blocks.front();
PassManager* man = static_cast<TargetInterpretation*> (__fnI12n->man)->pass->man;
compilation::ICodeScopeUnit* bodyBrute = context.function->getScopeUnit(body);
llvm::Type* instructionT = man->llvm->toLLVMType(man->root->getType(expression));
Expression atomNameE = __fnI12n->getScope(context.scope->scope)->process(expression.operands.front());
assert(atomNameE.__state == Expression::STRING);
string atomName = atomNameE.getValueString();
std::string argName = expression.bindings.front();
ExpandedType argT = man->root->getType(body->getDefinition(body->getSymbol(argName)));
if (argT->__operator == TypeOperator::SLAVE){
argT = dereferenceSlaveType(argT, man->transcend);
}
auto transcend =
Decorators<LateReasoningTranscendDecoratorTag>::getInterface(man->transcend);
LateReasoningCompiler* compiler =
new latereasoning::LateReasoningCompiler(__fnI12n, context);
SymbolPacked targetSP = transcend->pack(Attachments::get<SymbolAlias>(expression));
LateAnnotationsGroup feedbackAG = transcend->queryLate(atomName);
for(const auto& feedback : feedbackAG.annotations) {
SymbolPacked targetExpectedSP = ParseImplAtom<SymbolPacked>::get(feedback.first);
if (targetExpectedSP == targetSP) {
const LateAnnotation& annotation = feedback.second;
return compiler->compileAutoExpand(annotation, instructionT, "",
- [transcend, &argT, this, body, bodyBrute, &argName](const Gringo::Symbol & atomRaw) {
+ [transcend, &argT, this, body, bodyBrute, &argName](const Clingo::Symbol & atomRaw) {
InterpretationScope* bodyI12n = __fnI12n->getScope(body);
Expression argValue;
if (argT->__operator == TypeOperator::LIST_RECORD) {
argValue = representTransExpression(atomRaw, argT, transcend);
} else {
- argValue = representTransExpression(atomRaw.args()[0], argT, transcend);
+ argValue = representTransExpression(atomRaw.arguments()[0], argT, transcend);
}
bodyI12n->overrideBindings({
{argValue, argName}});
bodyBrute->reset();
return bodyBrute->compile();
});
}
}
assert(false && "No appropriate late annotation");
return nullptr; //should not be ever reachable
}
}
} //end of xreate::interpretation
diff --git a/cpp/src/compilation/latetranscend.cpp b/cpp/src/compilation/latetranscend.cpp
index 54ce3e7..e34afa2 100644
--- a/cpp/src/compilation/latetranscend.cpp
+++ b/cpp/src/compilation/latetranscend.cpp
@@ -1,183 +1,183 @@
/*
* 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/.
*
* latereasoning.cpp
*
* Author: pgess <v.melnychenko@xreate.org>
* Created on May 26, 2018, 3:54 PM
*/
/**
* \class xreate::latereasoning::LateReasoningCompiler
* Provides Late Transcend feature. See [Late Transcend](/d/transcend/late-transcend/) for the general overview.
*/
#include "compilation/latetranscend.h"
-//#include "aux/latereasoning.h"
#include "compilation/scopedecorators.h"
#include "analysis/interpretation.h"
#include "compilation/targetinterpretation.h"
#include <vector>
+#include <numeric>
using namespace xreate::interpretation;
using namespace xreate::compilation;
using namespace std;
namespace xreate{
namespace latereasoning{
#define HINT(x) (hint.empty()? x : hint)
std::map<SymbolPacked, Expression> LateReasoningCompiler:: __dictGuardDefinitions = std::map<SymbolPacked, Expression>();
llvm::Value*
LateReasoningCompiler::processSwitchLateStatement(const Expression& expr, const std::string& hint) {
AST* root = __context.pass->man->root;
LLVMLayer* llvm = __context.pass->man->llvm;
CodeScope* scopeBody = expr.blocks.front();
Symbol guardS = Symbol{scopeBody->getSymbol(expr.bindings.front()), scopeBody};
const ExpandedType& guardT = root->getType(expr.operands.at(0));
const ExpandedType& guardTPlain = guardT->__operator == TypeOperator::SLAVE?
interpretation::dereferenceSlaveType(guardT, __context.pass->man->transcend)
: guardT;
llvm::Value * guardRaw = __context.scope->process(expr.operands.at(0));
llvm::Type* instructionT = llvm->toLLVMType(root->getType(expr));
return compileExpand(guardS, guardRaw, guardTPlain, instructionT, hint, [this, scopeBody]() {
ICodeScopeUnit* bodyUnit = this->__context.function->getScopeUnit(scopeBody);
bodyUnit->reset();
return this->__context.function->getScopeUnit(scopeBody)->compile();
});
}
llvm::Value*
LateReasoningCompiler::compileAutoExpand(const LateAnnotation& annotation,
llvm::Type* resultT,
const std::string& hint,
Handler handler) {
TranscendLayer* transcend = __context.pass->man->transcend;
AST* root = __context.pass->man->root;
const std::list<SymbolPacked>& guardKeys = annotation.guardKeys;
std::list<Symbol> guardsToExpand;
for(const SymbolPacked key : guardKeys) {
if(!__dictGuardDefinitions.count(key)) {
const Symbol& keyS = transcend->unpack(key);
InterpretationScope* keyScope = __fnI12n->getScope(keyS.scope);
if (!keyScope->isBindingDefined(keyS.identifier)) {
guardsToExpand.push_back(keyS);
}
}
}
typedef std::function < llvm::Value * () > Compiler;
Compiler programInit([handler, annotation, this]() {
std::list<Expression>&& values = findKeys(annotation.guardKeys);
auto answer = annotation.select(values, __context.pass->man->root, __context.pass->man->transcend);
assert(answer);
return handler(*answer);
});
Compiler aggregate = std::accumulate(guardsToExpand.begin(), guardsToExpand.end(),
programInit,
[this, root, transcend, &resultT, hint](Compiler program, const Symbol & key) {
const ExpandedType& keyT = root->getType(CodeScope::getDefinition(key));
const ExpandedType& keyTPlain = keyT->__operator == TypeOperator::SLAVE?
interpretation::dereferenceSlaveType(keyT, transcend)
: keyT;
return Compiler([this, key, keyTPlain, resultT, hint, program](){
llvm::Value * keyRaw = __context.scope->processSymbol(key);
return compileExpand(key, keyRaw, keyTPlain, resultT, hint, program);
});
}
);
return aggregate();
}
llvm::Value*
LateReasoningCompiler::compileExpand(const Symbol& keyS,
llvm::Value* keyRaw,
const ExpandedType& domainT,
llvm::Type* resultT,
const std::string& hint,
CompilerHandler compilerBody) {
assert(domainT->__operator == TypeOperator::VARIANT);
std::list<Expression> domInstancesList = generateAllInstancesInDomain2(domainT);
std::vector<Expression> domInstances(domInstancesList.begin(), domInstancesList.end());
const int countInstances = domInstances.size();
assert(countInstances);
TranscendLayer* transcend = __context.pass->man->transcend;
SymbolPacked keyP = transcend->pack(keyS);
LLVMLayer* llvm = __context.pass->man->llvm;
llvm::IRBuilder<>& builder = llvm->builder;
compilation::IFunctionUnit* function = __context.function;
llvm::Type* typI8 = llvm::Type::getInt8Ty(llvm->llvmContext);
llvm::Value* keyVariantRaw = builder.CreateExtractValue(keyRaw, llvm::ArrayRef<unsigned>({0}));
llvm::SwitchInst* instructionSwitch = builder.CreateSwitch(keyVariantRaw, nullptr, countInstances);
llvm::BasicBlock *blockEpilog = llvm::BasicBlock::Create(
llvm->llvmContext, "epilog", function->raw);
builder.SetInsertPoint(blockEpilog);
llvm::PHINode *ret = builder.CreatePHI(resultT, countInstances, HINT("reverse"));
llvm::BasicBlock* blockDefault = nullptr;
for (int instanceId = 0; instanceId < countInstances; ++instanceId) {
llvm::BasicBlock *blockCase = llvm::BasicBlock::Create(
llvm->llvmContext,
"case" + std::to_string(instanceId),
function->raw);
if(instanceId == 0) blockDefault = blockCase;
builder.SetInsertPoint(blockCase);
//assign guard values
const Expression& instanceE = domInstances.at(instanceId);
__dictGuardDefinitions[keyP] = instanceE;
// __fnI12n->getScope(keyS.scope)->overrideBindings({
// {instanceE, keyS.identifier}
// });
//invoke further compilation handler
llvm::Value* resultCase = compilerBody();
ret->addIncoming(resultCase, builder.GetInsertBlock());
instructionSwitch->addCase(llvm::dyn_cast<llvm::ConstantInt>(llvm::ConstantInt::get(typI8, instanceId)), blockCase);
builder.CreateBr(blockEpilog);
}
//erase guard assignment
__dictGuardDefinitions.erase(keyP);
instructionSwitch->setDefaultDest(blockDefault);
builder.SetInsertPoint(blockEpilog);
return ret;
}
std::list<Expression>
LateReasoningCompiler::findKeys(const std::list<SymbolPacked>& keys) {
TranscendLayer* transcend = __context.pass->man->transcend;
std::list<Expression> result;
InterpretationScope* scopeI12n = __fnI12n->getScope(__context.scope->scope);
std::transform(keys.begin(), keys.end(), std::inserter(result, result.end()),
[this, scopeI12n, transcend](const SymbolPacked & key) {
if (__dictGuardDefinitions.count(key)){
return __dictGuardDefinitions.at(key);
}
return scopeI12n->processSymbol(transcend->unpack(key));
});
return result;
}
}
}
diff --git a/cpp/src/compilation/latetranscend.h b/cpp/src/compilation/latetranscend.h
index a2df895..2ea6043 100644
--- a/cpp/src/compilation/latetranscend.h
+++ b/cpp/src/compilation/latetranscend.h
@@ -1,76 +1,76 @@
/*
* 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: latereasoning.h
* Author: pgess <v.melnychenko@xreate.org>
*
* Created on May 26, 2018, 3:44 PM
*/
/**
* \file latetranscend.h
* \brief Late Transcend support
*/
#ifndef CMPLLATEREASONING_H
#define CMPLLATEREASONING_H
#include "ast.h"
#include "aux/latereasoning.h"
#include "pass/compilepass.h"
#include "llvmlayer.h"
#include "transcendlayer.h"
#include "targets.h"
namespace xreate{
namespace interpretation{
class InterpretationFunction;
}
}
namespace llvm{
class Value;
}
namespace xreate{
namespace latereasoning{
typedef std::function<llvm::Value*() > CompilerHandler;
-typedef std::function<llvm::Value*(const Gringo::Symbol&) > Handler;
+typedef std::function<llvm::Value*(const Clingo::Symbol&) > Handler;
/** \brief [Late Transcend](d/transcend/late-transcend/) compilation support */
class LateReasoningCompiler{
public:
LateReasoningCompiler(interpretation::InterpretationFunction* fn,
compilation::Context ctx)
: __context(ctx), __fnI12n(fn){ }
llvm::Value* processSwitchLateStatement(const Expression& expr,
const std::string& identHint);
llvm::Value* compileAutoExpand(const LateAnnotation& annotation,
llvm::Type* resultT,
const std::string& hint,
Handler handler);
private:
compilation::Context __context;
interpretation::InterpretationFunction* __fnI12n;
static std::map<SymbolPacked, Expression> __dictGuardDefinitions;
llvm::Value* compileExpand(const Symbol& keyS,
llvm::Value* keyRaw,
const ExpandedType& domainT,
llvm::Type* resultT,
const std::string& hint,
CompilerHandler compilerBody);
std::list<Expression> findKeys(const std::list<SymbolPacked>& keys);
};
}
}
#endif /* CMPLLATEREASONING_H */
diff --git a/cpp/src/compilation/latex.cpp b/cpp/src/compilation/latex.cpp
index 9a4d11e..52cc308 100644
--- a/cpp/src/compilation/latex.cpp
+++ b/cpp/src/compilation/latex.cpp
@@ -1,36 +1,36 @@
/*
* 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 <v.melnychenko@xreate.org>
* Created on June 23, 2018, 4:33 PM
*/
/**
* \file src/compilation/latex.h
* \brief Latex(Late Context) support
*/
#include "compilation/latex.h"
#include "analysis/interpretation.h"
#include "llvmlayer.h"
namespace xreate{
namespace latex{
ExpandedType
getSubjectDomain(const std::string& subject, LatexQuery* query){
- std::list<Gringo::Symbol>&& column = query->getSubjectDomain(subject);
+ std::list<Clingo::Symbol>&& column = query->getSubjectDomain(subject);
return ExpandedType(interpretation::collapseColumn(column));
}
llvm::Value*
ExtraArgsFnInvocation::operator() (std::vector<llvm::Value *>&& args, const std::string& hintDecl) {
args.insert(args.end(), __argsLatex.begin(), __argsLatex.end());
return __parent->operator ()(std::move(args), hintDecl);
}
}
-}
\ No newline at end of file
+}
diff --git a/cpp/src/compilation/latex.h b/cpp/src/compilation/latex.h
index e35ffeb..9e63501 100644
--- a/cpp/src/compilation/latex.h
+++ b/cpp/src/compilation/latex.h
@@ -1,144 +1,144 @@
/*
* 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 <v.melnychenko@xreate.org>
* 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);
/** \brief Latex(Late Context)-aware decorator for \ref xreate::compilation::IFunctionUnit
* \extends xreate::compilation::IFunctionUnit
*/
template<class Parent>
class LatexBruteFunctionDecorator: public Parent{
public:
LatexBruteFunctionDecorator(ManagedFnPtr f, CompilePass* p)
: Parent(f, p){
__query = reinterpret_cast<LatexQuery*> (Parent::pass->man->transcend->getQuery(QueryId::LatexQuery));
}
protected:
std::vector<llvm::Type*>
prepareSignature(){
std::vector<llvm::Type*>&& 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<Identifier_t>(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;
};
/** \brief %Function invocation operator decorator to handle latex enabled functions with hidden extra arguments */
class ExtraArgsFnInvocation: public compilation::IFnInvocation{
public:
ExtraArgsFnInvocation(std::vector<llvm::Value*> argsLatex, compilation::IFnInvocation* parent)
: __argsLatex(argsLatex), __parent(parent){ }
llvm::Value* operator()(std::vector<llvm::Value *>&& args, const std::string& hintDecl = "");
private:
std::vector<llvm::Value*> __argsLatex;
compilation::IFnInvocation* __parent;
};
/**
* \brief Latex aware \ref xreate::compilation::ICodeScopeUnit decorator
* \implements xreate::compilation::ICodeScopeUnit
*/
template<class 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<LatexQuery*> (Parent::pass->man->transcend->getQuery(QueryId::LatexQuery));
const Demand& fnCalleeDemand = query->getFnDemand(calleeName);
if(!fnCalleeDemand.size()) return invocDefault;
//prepare latex arguments
std::vector<llvm::Value*> 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<interpretation::InterpretationFunction*>(scopeIntrpr->function), ctx);
llvm::Value* subjectRaw = compiler->compileAutoExpand(
decision,
subjectTRaw,
subject,
- [&](const Gringo::Symbol & decisionRaw){
+ [&](const Clingo::Symbol & decisionRaw){
const Expression& decisionE = interpretation::representTransExpression(
- decisionRaw.args()[2], subjectT, Parent::pass->man->transcend);
+ decisionRaw.arguments()[2], subjectT, Parent::pass->man->transcend);
Attachments::put<TypeInferred>(decisionE, subjectT);
return Parent::process(decisionE, subject);
});
argsLatex.push_back(subjectRaw);
}
return new ExtraArgsFnInvocation(std::move(argsLatex), invocDefault);
}
};
}
} //end of namespace xreate::context
#endif /* LATEX_H */
diff --git a/cpp/src/compilation/polymorph.cpp b/cpp/src/compilation/polymorph.cpp
index 97e654b..1ddd1ce 100644
--- a/cpp/src/compilation/polymorph.cpp
+++ b/cpp/src/compilation/polymorph.cpp
@@ -1,50 +1,50 @@
/*
* 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 <v.melnychenko@xreate.org>
* Created on July 9, 2018, 6:04 PM
*/
#include "compilation/polymorph.h"
using namespace std;
namespace xreate{
namespace polymorph{
PolymorphFnInvocation::PolymorphFnInvocation(const latereasoning::LateAnnotation& selector,
std::list<ManagedFnPtr> calleeSpecializations,
CompilePass* pass,
PolymorphQuery* query,
LLVMLayer* llvm,
latereasoning::LateReasoningCompiler* compiler)
: __selector(selector), __calleeSpecializations(calleeSpecializations),
__pass(pass), __query(query), __llvm(llvm), __compiler(compiler) { }
llvm::Value*
PolymorphFnInvocation::operator()(std::vector<llvm::Value *>&& args, const std::string& hintDecl) {
std::map<Selector, ManagedFnPtr> dictSelectors;
for(ManagedFnPtr specialization : __calleeSpecializations) {
dictSelectors.emplace(specialization->guard, specialization);
}
compilation::IFunctionUnit* specAny = __pass->getFunctionUnit(__calleeSpecializations.front());
return __compiler->compileAutoExpand(
__selector,
specAny->prepareResult(),
hintDecl,
- [this, &args, hintDecl, &dictSelectors](const Gringo::Symbol & selectorRaw) {
+ [this, &args, hintDecl, &dictSelectors](const Clingo::Symbol & selectorRaw) {
const Expression & selectorE = __query->getValue(selectorRaw);
assert(dictSelectors.count(selectorE) && "Inappropriate specialization guard");
compilation::BruteFnInvocation* invoc = new compilation::BruteFnInvocation(
__pass->getFunctionUnit(dictSelectors.at(selectorE))->compile(),
__llvm);
return invoc->operator()(move(args), hintDecl);
});
}
}
}
diff --git a/cpp/src/llvmlayer.cpp b/cpp/src/llvmlayer.cpp
index 846d96c..012bc9b 100644
--- a/cpp/src/llvmlayer.cpp
+++ b/cpp/src/llvmlayer.cpp
@@ -1,242 +1,240 @@
/* 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/.
*
* llvmlayer.cpp
*
* Author: pgess <v.melnychenko@xreate.org>
*/
/**
* \file llvmlayer.h
* \brief Bytecode generation
*/
#include "ast.h"
#include "llvmlayer.h"
#include "ExternLayer.h"
#include "llvm/ExecutionEngine/ExecutionEngine.h"
#include "llvm/ExecutionEngine/MCJIT.h"
#include "llvm/Support/TargetSelect.h"
#include <iostream>
#include <cmath>
using namespace llvm;
using namespace xreate;
using namespace std;
LLVMLayer::LLVMLayer(AST* root)
: llvmContext(),
builder(llvmContext),
ast(root),
module(new llvm::Module(root->getModuleName(), llvmContext)) {
- layerExtern = new ExternLayer(this);
- layerExtern->init(root);
+ layerExtern = new ExternLayer(this);
+ layerExtern->init(root);
+
+ InitializeNativeTarget();
+ InitializeNativeTargetAsmPrinter();
}
void*
LLVMLayer::getFunctionPointer(llvm::Function* function) {
uint64_t entryAddr = jit->getFunctionAddress(function->getName().str());
return (void*) entryAddr;
}
void
LLVMLayer::initJit() {
- std::string ErrStr;
- LLVMInitializeNativeTarget();
- llvm::InitializeNativeTargetAsmPrinter();
-
- llvm::EngineBuilder builder(std::unique_ptr<llvm::Module>(module.release()));
- jit.reset(builder
- .setEngineKind(llvm::EngineKind::JIT)
- .setErrorStr(&ErrStr)
- .setVerifyModules(true)
- .create()
- );
+ std::string errStr;
+
+ jit.reset(
+ EngineBuilder(std::unique_ptr<llvm::Module>(module.release()))
+ .setErrorStr(&errStr)
+ .setEngineKind(llvm::EngineKind::JIT)
+ .setVerifyModules(true)
+ .create()
+ );
}
void
LLVMLayer::print() {
- llvm::PassManager<llvm::Module> PM;
- PM.addPass(llvm::PrintModulePass(llvm::outs(), "banner"));
- llvm::AnalysisManager<llvm::Module> aman;
- PM.run(*module.get(), aman);
+ module->print(llvm::outs(), nullptr);
}
void
LLVMLayer::moveToGarbage(void *o) {
__garbage.push_back(o);
}
llvm::Type*
LLVMLayer::toLLVMType(const ExpandedType& ty) const {
std::map<int, llvm::StructType*> empty;
return toLLVMType(ty, empty);
}
llvm::Type*
LLVMLayer::toLLVMType(const ExpandedType& ty, std::map<int, llvm::StructType*>& conjuctions) const {
TypeAnnotation t = ty;
switch (t.__operator) {
case TypeOperator::LIST_ARRAY:
{
assert(t.__operands.size() == 1);
TypeAnnotation elTy = t.__operands.at(0);
return llvm::ArrayType::get(toLLVMType(ExpandedType(move(elTy)), conjuctions), t.__size);
}
case TypeOperator::LIST_RECORD:
{
std::vector<llvm::Type*> pack_;
pack_.reserve(t.__operands.size());
std::transform(t.__operands.begin(), t.__operands.end(), std::inserter(pack_, pack_.end()),
[this, &conjuctions](const TypeAnnotation & t) {
return toLLVMType(ExpandedType(TypeAnnotation(t)), conjuctions);
});
llvm::ArrayRef<llvm::Type*> pack(pack_);
//process recursive types:
if (conjuctions.count(t.conjuctionId)) {
auto result = conjuctions[t.conjuctionId];
result->setBody(pack, false);
return result;
}
return llvm::StructType::get(llvmContext, pack, false);
};
case TypeOperator::LINK:
{
llvm::StructType* conjuction = llvm::StructType::create(llvmContext);
int id = t.conjuctionId;
conjuctions.emplace(id, conjuction);
return conjuction;
};
case TypeOperator::CALL:
{
assert(false);
};
case TypeOperator::CUSTOM:
{
//Look in extern types
clang::QualType qt = layerExtern->lookupType(t.__valueCustom);
return layerExtern->toLLVMType(qt);
};
//DEBT omit ID field in case of single variant.
case TypeOperator::VARIANT:
{
/* Variant Type Layout:
* {
* id :: i8, Holds stored variant id
* storage:: type of biggest variant
* }
*/
uint64_t sizeStorage = 0;
llvm::Type* typStorageRaw = llvm::Type::getVoidTy(llvmContext);
for(const TypeAnnotation& subtype : t.__operands) {
llvm::Type* subtypeRaw = toLLVMType(ExpandedType(subtype), conjuctions);
if (subtypeRaw->isVoidTy()) continue;
uint64_t sizeSubtype = module->getDataLayout().getTypeStoreSize(subtypeRaw);
if (sizeSubtype > sizeStorage) {
sizeStorage = sizeSubtype;
typStorageRaw = subtypeRaw;
}
}
std::vector<llvm::Type*> layout;
layout.push_back(llvm::Type::getInt8Ty(llvmContext)); //id
const bool flagHoldsData = sizeStorage > 0;
if (flagHoldsData) {
layout.push_back(typStorageRaw); //storage
}
return llvm::StructType::get(llvmContext, llvm::ArrayRef<llvm::Type*>(layout));
}
case TypeOperator::NONE:
{
switch (t.__value) {
case TypePrimitive::I32:
case TypePrimitive::Int:
case TypePrimitive::Num:
return llvm::Type::getInt32Ty(llvmContext);
case TypePrimitive::Bool:
return llvm::Type::getInt1Ty(llvmContext);
case TypePrimitive::I8:
return llvm::Type::getInt8Ty(llvmContext);
case TypePrimitive::I64:
return llvm::Type::getInt64Ty(llvmContext);
case TypePrimitive::Float:
return llvm::Type::getDoubleTy(llvmContext);
case TypePrimitive::String:
return llvm::Type::getInt8PtrTy(llvmContext);
case TypePrimitive::Invalid:
return llvm::Type::getVoidTy(llvmContext);
default:
assert(false);
}
}
default:
assert(false);
}
assert(false);
return nullptr;
}
bool
TypeUtils::isStruct(const ExpandedType& ty) {
const TypeAnnotation& t = ty.get();
if (t.__operator == TypeOperator::LIST_RECORD) {
return true;
}
if (t.__operator != TypeOperator::CUSTOM) {
return false;
}
clang::QualType tqual = llvm->layerExtern->lookupType(t.__valueCustom);
const clang::Type * raw = tqual.getTypePtr();
// TODO skip ALL the pointers until non-pointer type found
if (raw->isStructureType()) return true;
if (!raw->isAnyPointerType()) return false;
clang::QualType pointee = raw->getPointeeType();
return pointee->isStructureType();
}
bool
TypeUtils::isPointer(const ExpandedType &ty) {
if (ty.get().__operator != TypeOperator::CUSTOM) return false;
clang::QualType qt = llvm->layerExtern->lookupType(ty.get().__valueCustom);
return llvm->layerExtern->isPointer(qt);
}
std::vector<std::string>
TypeUtils::getStructFields(const ExpandedType &t) {
return (t.get().__operator == TypeOperator::LIST_RECORD)
? t.get().fields
: llvm->layerExtern->getStructFields(
llvm->layerExtern->lookupType(t.get().__valueCustom));
}
\ No newline at end of file
diff --git a/cpp/src/modules.cpp b/cpp/src/modules.cpp
index ca196eb..bb14d7b 100644
--- a/cpp/src/modules.cpp
+++ b/cpp/src/modules.cpp
@@ -1,168 +1,162 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* modules.cpp
*
* Author: pgess <v.melnychenko@xreate.org>
* Created on July 22, 2017, 5:13 PM
*/
/**
* \file modules.h
* \brief Modules support
*/
#include "modules.h"
#include "modules/Parser.h"
#include "analysis/utils.h"
-#include <clingo/clingocontrol.hh>
+#include <clingo.hh>
#include <boost/format.hpp>
#include <regex>
#include <boost/filesystem.hpp>
#include <fstream>
using namespace std;
namespace fs = boost::filesystem;
namespace xreate { namespace modules{
void
ModuleRecord::addRequest(const Expression& request){
__requests.push_back(request);
}
void
ModuleRecord::addControllerPath(const std::string& path){
__controllers.push_back(path);
}
void
ModuleRecord::addDiscoveryPath(const std::string& path){
__discoveryPaths.push_back(path);
}
void
ModuleRecord::addProperty(const Expression& prop){
__properties.push_back(prop);
}
void
ModulesSolver::loadControllers(const ModuleRecord& module){
for (const std::string& pathController: module.__controllers){
std::fstream fileContent(pathController);
__program << fileContent.rdbuf();
}
}
void
ModulesSolver::extractProperties(const ModuleRecord& module){
const std::string atomProperty = "bind_module";
boost::format formatProperty(atomProperty + "(\"%1%\", %2%).");
for (const Expression& property: module.__properties){
std::list<std::string> reprProp = xreate::analysis::compile(property);
assert(reprProp.size()== 1);
__program << (formatProperty % module.__path % reprProp.front())
<< std::endl;
}
}
void
ModulesSolver::discoverModules(const ModuleRecord& moduleClient){
std::regex extXreate("\\.xreate$", std::regex::basic);
for(const std::string& path: moduleClient.__discoveryPaths){
for(fs::directory_entry e: fs::recursive_directory_iterator(path)) {
if (fs::is_regular_file(e.status())){
if (!std::regex_search(e.path().string(), extXreate)) continue;
FILE* script = fopen(e.path().c_str(), "r");
Scanner scanner(script);
Parser parser(&scanner);
parser.Parse();
assert(!parser.errors->count && "Discovery errors");
parser.module.__path = e.path().c_str();
extractProperties(parser.module);
fclose(script);
}
}
}
}
void
ModulesSolver::extractRequirements(const ModuleRecord& module){
const std::string atomQuery = "modules_require";
boost::format formatProperty(atomQuery + "(\"%1%\", %2%).");
for (const Expression& query: module.__requests){
std::list<std::string> reprQuery = xreate::analysis::compile(query);
assert(reprQuery.size()== 1);
__program << (formatProperty % module.__path % reprQuery.front())
<< std::endl;
}
}
void
ModulesSolver::add(const std::string& base){
__program << base;
}
void
ModulesSolver::init(const std::string& programBase, const ModuleRecord& module){
add(programBase);
extractRequirements(module);
extractProperties(module);
loadControllers(module);
discoverModules(module);
std::cout << __program.str() << std::endl;
}
std::list<std::string>
ModulesSolver::run(const ModuleRecord& module){
const std::string predicateResolution = "modules_resolution";
std::map<Expression, string> dictResolution;
- std::vector<char const *> args{"clingo", nullptr};
- DefaultGringoModule moduleDefault;
- Gringo::Scripts scriptsDefault(moduleDefault);
- ClingoLib ctl(scriptsDefault, 0, args.data(), {}, 0);
-
- ctl.add("base", {}, __program.str());
- ctl.ground({{"base", {}}}, nullptr);
- ctl.solve([&predicateResolution, this, &dictResolution, &module](Gringo::Model const &model) {
- for (Gringo::Symbol atom : model.atoms(clingo_show_type_atoms)) {
- std::cout << atom << std::endl;
- if (std::strcmp(atom.name().c_str(), predicateResolution.c_str())!=0) continue;
-
- if (atom.arity() == 2){
- auto resolution = TranscendLayer::parse<Expression, std::string>(atom);
- dictResolution.emplace(get<0>(resolution), get<1>(resolution));
- continue;
- }
-
- if (atom.arity() == 3){
- auto resolution = TranscendLayer::parse<Expression, std::string, std::string>(atom);
- if(get<2>(resolution) != module.__path) continue;
- dictResolution.emplace(get<0>(resolution), get<1>(resolution));
- continue;
- }
- assert(false && "Wrong resolution format");
- }
- return true;
- }, {});
+ Clingo::Control solver;
+ solver.add("base", {}, __program.str().c_str());
+ solver.ground({{"base", {}}}, nullptr);
+ auto solution = solver.solve();
+ for (const Clingo::Symbol& atom : solution.model().symbols(clingo_show_type_atoms)) {
+ std::cout << atom << std::endl;
+ if (std::strcmp(atom.name(), predicateResolution.c_str())!=0) continue;
+
+ if (atom.match(predicateResolution.c_str(), 2)){
+ auto resolution = TranscendLayer::parse<Expression, std::string>(atom);
+ dictResolution.emplace(get<0>(resolution), get<1>(resolution));
+ continue;
+ }
+
+ if (atom.match(predicateResolution.c_str(), 3)){
+ auto resolution = TranscendLayer::parse<Expression, std::string, std::string>(atom);
+ if(get<2>(resolution) != module.__path) continue;
+
+ dictResolution.emplace(get<0>(resolution), get<1>(resolution));
+ continue;
+ }
+ }
std::list<std::string> result;
for(const Expression& request: module.__requests){
assert(dictResolution.count(request) && "Can't find requested module");
result.push_back(dictResolution.at(request));
}
return result;
}
}} //namespace xreate::modules
diff --git a/cpp/src/pass/compilepass.cpp b/cpp/src/pass/compilepass.cpp
index 06049f2..604c267 100644
--- a/cpp/src/pass/compilepass.cpp
+++ b/cpp/src/pass/compilepass.cpp
@@ -1,788 +1,788 @@
/* 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 <v.melnychenko@xreate.org>
*
* compilepass.cpp
*/
/**
* \file compilepass.h
* \brief Main compilation routine. See \ref xreate::CompilePass
*/
#include "compilepass.h"
#include "transcendlayer.h"
#include <ast.h>
#include "llvmlayer.h"
#include "query/containers.h"
#include "compilation/containers.h"
#include "ExternLayer.h"
#include "compilation/targetinterpretation.h"
#include "pass/versionspass.h"
#include "compilation/scopedecorators.h"
#include "compilation/operators.h"
#include "compilation/latex.h"
#include "analysis/typeinference.h"
#include <boost/optional.hpp>
#include <memory>
#include <iostream>
using namespace std;
using namespace llvm;
namespace xreate{
namespace compilation{
std::string
BasicFunctionUnit::prepareName() {
AST* ast = IFunctionUnit::pass->man->root;
string name = ast->getFunctionSpecializations(IFunctionUnit::function->__name).size() > 1 ?
IFunctionUnit::function->__name + std::to_string(IFunctionUnit::function.id()) :
IFunctionUnit::function->__name;
return name;
}
std::vector<llvm::Type*>
BasicFunctionUnit::prepareSignature() {
LLVMLayer* llvm = IFunctionUnit::pass->man->llvm;
AST* ast = IFunctionUnit::pass->man->root;
CodeScope* entry = IFunctionUnit::function->__entry;
std::vector<llvm::Type*> signature;
std::transform(entry->__bindings.begin(), entry->__bindings.end(), std::inserter(signature, signature.end()),
[llvm, ast, entry](const std::string & arg)->llvm::Type* {
assert(entry->__identifiers.count(arg));
ScopedSymbol argid{entry->__identifiers.at(arg), versions::VERSION_NONE};
return llvm->toLLVMType(ast->expandType(entry->__declarations.at(argid).type));
});
return signature;
}
llvm::Type*
BasicFunctionUnit::prepareResult() {
LLVMLayer* llvm = IFunctionUnit::pass->man->llvm;
AST* ast = IFunctionUnit::pass->man->root;
CodeScope* entry = IFunctionUnit::function->__entry;
return llvm->toLLVMType(ast->expandType(entry->__declarations.at(ScopedSymbol::RetSymbol).type));
}
llvm::Function::arg_iterator
BasicFunctionUnit::prepareBindings() {
CodeScope* entry = IFunctionUnit::function->__entry;
ICodeScopeUnit* entryCompilation = IFunctionUnit::getScopeUnit(entry);
llvm::Function::arg_iterator fargsI = IFunctionUnit::raw->arg_begin();
for (std::string &arg : entry->__bindings) {
ScopedSymbol argid{entry->__identifiers[arg], versions::VERSION_NONE};
entryCompilation->bindArg(&*fargsI, argid);
fargsI->setName(arg);
++fargsI;
}
return fargsI;
}
//DEBT compiler rigidly depends on exact definition of DefaultFunctionUnit
typedef latex::LatexBruteFunctionDecorator<
compilation::BasicFunctionUnit>
BruteFunctionDefault;
ICodeScopeUnit::ICodeScopeUnit(const CodeScope * const codeScope, IFunctionUnit* f, CompilePass* compilePass)
: pass(compilePass), function(f), scope(codeScope), currentBlockRaw(nullptr) { }
llvm::Value*
BruteFnInvocation::operator()(std::vector<llvm::Value *>&& args, const std::string& hintDecl) {
llvm::Function* calleeInfo = dyn_cast<llvm::Function>(__callee);
if (calleeInfo) {
auto argsFormal = calleeInfo->args();
size_t sizeArgsF = std::distance(argsFormal.begin(), argsFormal.end());
assert(args.size() >= sizeArgsF);
assert(calleeInfo->isVarArg() || args.size() == sizeArgsF);
auto argFormal = argsFormal.begin();
for(size_t argId = 0; argId < args.size(); ++argId){
if(argFormal != argsFormal.end()){
args[argId] = typeinference::doAutomaticTypeConversion(
args.at(argId), argFormal->getType(), llvm->builder);
++argFormal;
}
}
}
//Do not name function call that returns Void.
std::string nameStatement = hintDecl;
if (calleeInfo->getReturnType()->isVoidTy()) {
nameStatement.clear();
}
return llvm->builder.CreateCall(__calleeTy, __callee, args, nameStatement);
}
//DESABLEDFEATURE implement inlining
class CallStatementInline : public IFnInvocation{
public:
CallStatementInline(IFunctionUnit* caller, IFunctionUnit* callee, LLVMLayer* l)
: __caller(caller), __callee(callee), llvm(l) { }
llvm::Value* operator()(std::vector<llvm::Value *>&& args, const std::string& hintDecl) {
//TOTEST inlining
// CodeScopeUnit* entryCompilation = outer->getScopeUnit(function->__entry);
// for(int i=0, size = args.size(); i<size; ++i) {
// entryCompilation->bindArg(args.at(i), string(entryCompilation->scope->__bindings.at(i)));
// }
//
//
// return entryCompilation->compile();
return nullptr;
}
private:
IFunctionUnit* __caller;
IFunctionUnit* __callee;
LLVMLayer* llvm;
bool
isInline() {
// Symbol ret = Symbol{0, function->__entry};
// bool flagOnTheFly = SymbolAttachments::get<IsImplementationOnTheFly>(ret, false);
//TODO consider inlining
return false;
}
} ;
BasicCodeScopeUnit::BasicCodeScopeUnit(const CodeScope * const codeScope, IFunctionUnit* f, CompilePass* compilePass)
: ICodeScopeUnit(codeScope, f, compilePass) { }
llvm::Value*
BasicCodeScopeUnit::processSymbol(const Symbol& s, std::string hintRetVar) {
Expression declaration = CodeScope::getDefinition(s);
const CodeScope* scopeExternal = s.scope;
ICodeScopeUnit* scopeBruteExternal = ICodeScopeUnit::function->getScopeUnit(scopeExternal);
assert(scopeBruteExternal->currentBlockRaw);
llvm::Value* resultRaw;
llvm::BasicBlock* blockOwn = pass->man->llvm->builder.GetInsertBlock();
if (scopeBruteExternal->currentBlockRaw == blockOwn) {
resultRaw = scopeBruteExternal->process(declaration, hintRetVar);
scopeBruteExternal->currentBlockRaw = currentBlockRaw =
pass->man->llvm->builder.GetInsertBlock();
} else {
pass->man->llvm->builder.SetInsertPoint(scopeBruteExternal->currentBlockRaw);
resultRaw = scopeBruteExternal->processSymbol(s, hintRetVar);
pass->man->llvm->builder.SetInsertPoint(blockOwn);
}
return resultRaw;
}
IFnInvocation*
BasicCodeScopeUnit::findFunction(const Expression& opCall) {
const std::string& calleeName = opCall.getValueString();
LLVMLayer* llvm = pass->man->llvm;
const std::list<ManagedFnPtr>& specializations = pass->man->root->getFunctionSpecializations(calleeName);
//if no specializations registered - check external function
if (specializations.size() == 0) {
llvm::Function* external = llvm->layerExtern->lookupFunction(calleeName);
llvm::outs() << "Debug/External function: " << calleeName;
external->getType()->print(llvm::outs(), true);
llvm::outs() << "\n";
return new BruteFnInvocation(external, llvm);
}
//There should be only one specialization without any valid guards at this point
return new BruteFnInvocation(pass->getFunctionUnit(
pass->man->root->findFunction(calleeName))->compile(),
llvm);
}
//DISABLEDFEATURE transformations
// if (pass->transformations->isAcceptable(expr)){
// return pass->transformations->transform(expr, result, ctx);
// }
llvm::Value*
BasicCodeScopeUnit::process(const Expression& expr, const std::string& hintVarDecl) {
#define DEFAULT(x) (hintVarDecl.empty()? x: hintVarDecl)
llvm::Value *left;
llvm::Value *right;
LLVMLayer& l = *pass->man->llvm;
xreate::compilation::AdvancedInstructions instructions = xreate::compilation::AdvancedInstructions({this, function, pass});
switch (expr.op) {
case Operator::SUB: case Operator::MUL:
case Operator::DIV: case Operator::EQU: case Operator::LSS:
case Operator::GTR: case Operator::NE: case Operator::LSE:
case Operator::GTE:
assert(expr.__state == Expression::COMPOUND);
assert(expr.operands.size() == 2);
left = process(expr.operands[0]);
right = process(expr.operands[1]);
break;
default:;
}
switch (expr.op) {
case Operator::ADD:
{
left = process(expr.operands[0]);
Context context{this, function, pass};
llvm::Value* resultSU = StructUpdate::add(expr.operands[0], left, expr.operands[1], context, DEFAULT("tmp_add"));
if (resultSU) return resultSU;
right = process(expr.operands[1]);
llvm::Value* resultAddPA = pointerarithmetic::PointerArithmetic::add(left, right, context, DEFAULT("tmp_add"));
if (resultAddPA) {
return resultAddPA;
}
return l.builder.CreateAdd(left, right, DEFAULT("tmp_add"));
break;
}
case Operator::SUB:
return l.builder.CreateSub(left, right, DEFAULT("tmp_sub"));
break;
case Operator::MUL:
return l.builder.CreateMul(left, right, DEFAULT("tmp_mul"));
break;
case Operator::DIV:
if (left->getType()->isIntegerTy()) return l.builder.CreateSDiv(left, right, DEFAULT("tmp_div"));
if (left->getType()->isFloatingPointTy()) return l.builder.CreateFDiv(left, right, DEFAULT("tmp_div"));
break;
case Operator::EQU: {
if (left->getType()->isIntegerTy()) return l.builder.CreateICmpEQ(left, right, DEFAULT("tmp_equ"));
if (left->getType()->isFloatingPointTy()) return l.builder.CreateFCmpOEQ(left, right, DEFAULT("tmp_equ"));
const ExpandedType& leftT = pass->man->root->getType(expr.operands[0]);
const ExpandedType& rightT = pass->man->root->getType(expr.operands[0]);
if(leftT->__operator == TypeOperator::VARIANT && rightT->__operator == TypeOperator::VARIANT){
llvm::Type* selectorT = llvm::cast<llvm::StructType>(left->getType())->getElementType(0);
llvm::Value* leftUnwapped = typeinference::doAutomaticTypeConversion(left, selectorT, l.builder);
llvm::Value* rightUnwapped = typeinference::doAutomaticTypeConversion(right, selectorT, l.builder);
return l.builder.CreateICmpEQ(leftUnwapped, rightUnwapped, DEFAULT("tmp_equ"));
}
break;
}
case Operator::NE:
return l.builder.CreateICmpNE(left, right, DEFAULT("tmp_ne"));
break;
case Operator::LSS:
return l.builder.CreateICmpSLT(left, right, DEFAULT("tmp_lss"));
break;
case Operator::LSE:
return l.builder.CreateICmpSLE(left, right, DEFAULT("tmp_lse"));
break;
case Operator::GTR:
return l.builder.CreateICmpSGT(left, right, DEFAULT("tmp_gtr"));
break;
case Operator::GTE:
return l.builder.CreateICmpSGE(left, right, DEFAULT("tmp_gte"));
break;
case Operator::NEG:
{
left = process(expr.operands[0]);
ExpandedType leftTy = pass->man->root->getType(expr.operands[0]);
if (leftTy->__value == TypePrimitive::Bool){
return l.builder.CreateNot(left, DEFAULT("tmp_not"));
} else {
return l.builder.CreateNeg(left, DEFAULT("tmp_neg"));
}
break;
}
case Operator::CALL:
{
assert(expr.__state == Expression::COMPOUND);
shared_ptr<IFnInvocation> callee(findFunction(expr));
const std::string& nameCallee = expr.getValueString();
//prepare arguments
std::vector<llvm::Value *> args;
args.reserve(expr.operands.size());
std::transform(expr.operands.begin(), expr.operands.end(), std::inserter(args, args.end()),
[this](const Expression & operand) {
return process(operand);
}
);
return (*callee)(move(args), DEFAULT("res_" + nameCallee));
}
case Operator::IF:
{
return instructions.compileIf(expr, DEFAULT("tmp_if"));
}
case Operator::SWITCH:
{
return instructions.compileSwitch(expr, DEFAULT("tmp_switch"));
}
case Operator::LOGIC_AND:
{
assert(expr.operands.size() == 1);
return process(expr.operands[0]);
}
case Operator::LIST:
{
ExpandedType exprT = l.ast->getType(expr);
bool flagIsArray;
do {
if (exprT->__operator == TypeOperator::CUSTOM){
if (l.layerExtern->isArrayType(exprT->__valueCustom)){
flagIsArray = true;
break;
}
if (l.layerExtern->isRecordType(exprT->__valueCustom)){
flagIsArray = false;
break;
}
assert(false && "Inapproriate external type");
}
if (exprT->__operator != TypeOperator::LIST_ARRAY && exprT->__operator != TypeOperator::LIST_RECORD){
assert(false && "Inapproriate type");
}
flagIsArray = exprT->__operator == TypeOperator::LIST_ARRAY;
} while(false);
if(flagIsArray){
return instructions.compileListAsSolidArray(expr, DEFAULT("tmp_list"));
}
const std::vector<string> fieldsFormal = (exprT.get().__operator == TypeOperator::CUSTOM) ?
l.layerExtern->getStructFields(l.layerExtern->lookupType(exprT.get().__valueCustom))
: exprT.get().fields;
std::map<std::string, size_t> indexFields;
for (size_t i = 0, size = fieldsFormal.size(); i < size; ++i) {
indexFields.emplace(fieldsFormal[i], i);
}
llvm::StructType* tyLiteralRaw = llvm::cast<llvm::StructType>(l.toLLVMType(exprT));
llvm::Value* record = llvm::UndefValue::get(tyLiteralRaw);
for (size_t i = 0; i < expr.operands.size(); ++i) {
const Expression& operand = expr.operands.at(i);
unsigned int fieldId = indexFields.at(expr.bindings.at(i));
llvm::Value* result = process(operand);
assert(result);
record = l.builder.CreateInsertValue(record, result, llvm::ArrayRef<unsigned>({fieldId}));
}
return record;
};
case Operator::LIST_RANGE:
{
assert(false); //no compilation phase for a range list
// return InstructionList(this).compileConstantArray(expr, l, hintRetVar);
};
case Operator::MAP:
{
assert(expr.blocks.size());
return instructions.compileMapSolidOutput(expr, DEFAULT("map"));
};
case Operator::FOLD:
{
return instructions.compileFold(expr, DEFAULT("fold"));
};
case Operator::INF:
{
return instructions.compileFoldInf(expr, DEFAULT("fold"));
};
case Operator::INDEX:
{
//TASK allow multiindex compilation
assert(expr.operands.size() == 2);
assert(expr.operands[0].__state == Expression::IDENT);
const std::string& hintIdent = expr.operands[0].getValueString();
Symbol s = Attachments::get<IdentifierSymbol>(expr.operands[0]);
const ExpandedType& t2 = pass->man->root->getType(expr.operands[0]);
llvm::Value* aggr = processSymbol(s, hintIdent);
switch (t2.get().__operator) {
case TypeOperator::LIST_RECORD: case TypeOperator::CUSTOM:
{
std::string idxField;
const Expression& idx = expr.operands.at(1);
switch (idx.__state) {
//named struct field
case Expression::STRING:
idxField = idx.getValueString();
break;
//anonymous struct field
case Expression::NUMBER:
idxField = to_string((int) idx.getValueDouble());
break;
default:
assert(false && "Wrong index for a struct");
}
return instructions.compileStructIndex(aggr, t2, idxField);
};
case TypeOperator::LIST_ARRAY:
{
std::vector<llvm::Value*> indexes;
std::transform(++expr.operands.begin(), expr.operands.end(), std::inserter(indexes, indexes.end()),
[this] (const Expression & op) {
return process(op);
}
);
return instructions.compileArrayIndex(aggr, indexes, DEFAULT(string("el_") + hintIdent));
};
default:
assert(false);
}
};
case Operator::CALL_INTRINSIC:
{
const std::string op = expr.getValueString();
if (op == "copy") {
llvm::Value* result = process(expr.getOperands().at(0));
auto decoratorVersions = Decorators<VersionsScopeDecoratorTag>::getInterface(this);
llvm::Value* storage = decoratorVersions->processIntrinsicInit(result->getType());
decoratorVersions->processIntrinsicCopy(result, storage);
return l.builder.CreateLoad(storage, hintVarDecl);
}
assert(false && "undefined intrinsic");
}
case Operator::QUERY:
case Operator::QUERY_LATE:
{
assert(false && "Should be processed by interpretation");
}
case Operator::VARIANT:
{
const ExpandedType& typVariant = pass->man->root->getType(expr);
llvm::Type* typVariantRaw = l.toLLVMType(typVariant);
llvm::Type* typIdRaw = llvm::cast<llvm::StructType>(typVariantRaw)->getElementType(0);
uint64_t id = expr.getValueDouble();
llvm::Value* variantRaw = llvm::UndefValue::get(typVariantRaw);
variantRaw = l.builder.CreateInsertValue(variantRaw, llvm::ConstantInt::get(typIdRaw, id), llvm::ArrayRef<unsigned>({0}));
const bool flagDoReference = expr.operands.size();
if (flagDoReference) {
const ExpandedType& subtyp = ExpandedType(typVariant->__operands.at(id));
llvm::Type* subtypRaw = l.toLLVMType(subtyp);
Attachments::put<TypeInferred>(expr.operands.at(0), subtyp);
llvm::Value* subtypValue = process(expr.operands.at(0));
llvm::Type* typStorageRaw = llvm::cast<llvm::StructType>(typVariantRaw)->getElementType(1);
llvm::Value* addrAsStorage = l.builder.CreateAlloca(typStorageRaw);
llvm::Value* addrAsSubtyp = l.builder.CreateBitOrPointerCast(addrAsStorage, subtypRaw->getPointerTo());
l.builder.CreateStore(subtypValue, addrAsSubtyp);
llvm::Value* storageRaw = l.builder.CreateLoad(typStorageRaw, addrAsStorage);
variantRaw = l.builder.CreateInsertValue(variantRaw, storageRaw, llvm::ArrayRef<unsigned>({1}));
}
return variantRaw;
}
case Operator::SWITCH_VARIANT:
{
return instructions.compileSwitchVariant(expr, DEFAULT("tmpswitch"));
}
case Operator::SWITCH_LATE:
{
assert(false && "Instruction's compilation should've been redirected to interpretation");
return nullptr;
}
case Operator::SEQUENCE:
{
return instructions.compileSequence(expr);
}
case Operator::UNDEF:
{
llvm::Type* typExprUndef = l.toLLVMType(typeinference::getType(expr, *pass->man->root));
return llvm::UndefValue::get(typExprUndef);
}
case Operator::INVALID:
assert(expr.__state != Expression::COMPOUND);
switch (expr.__state) {
case Expression::IDENT:
{
Symbol s = Attachments::get<IdentifierSymbol>(expr);
return processSymbol(s, expr.getValueString());
}
case Expression::NUMBER:
{
llvm::Type* typConst = l.toLLVMType(typeinference::getType(expr, *pass->man->root));
int literal = expr.getValueDouble();
if (typConst->isFloatingPointTy()) return llvm::ConstantFP::get(typConst, literal);
if (typConst->isIntegerTy()) return llvm::ConstantInt::get(typConst, literal);
assert(false && "Can't compile literal");
}
case Expression::STRING:
{
return instructions.compileConstantStringAsPChar(expr.getValueString(), DEFAULT("tmp_str"));
};
default:
{
break;
}
};
break;
default: break;
}
assert(false && "Can't compile expression");
return 0;
}
llvm::Value*
BasicCodeScopeUnit::compile(const std::string& hintBlockDecl) {
LLVMLayer* llvm = pass->man->llvm;
if (!hintBlockDecl.empty()) {
llvm::BasicBlock *block = llvm::BasicBlock::Create(llvm->llvmContext, hintBlockDecl, function->raw);
pass->man->llvm->builder.SetInsertPoint(block);
}
currentBlockRaw = pass->man->llvm->builder.GetInsertBlock();
Symbol symbScope = Symbol{ScopedSymbol::RetSymbol, scope};
return processSymbol(symbScope);
}
ICodeScopeUnit::~ICodeScopeUnit() { }
IFunctionUnit::~IFunctionUnit() { }
llvm::Function*
IFunctionUnit::compile() {
if (raw != nullptr) return raw;
LLVMLayer* llvm = pass->man->llvm;
llvm::IRBuilder<>& builder = llvm->builder;
string&& functionName = prepareName();
std::vector<llvm::Type*>&& types = prepareSignature();
llvm::Type* expectedResultType = prepareResult();
llvm::FunctionType *ft = llvm::FunctionType::get(expectedResultType, types, false);
- raw = llvm::cast<llvm::Function>(llvm->module->getOrInsertFunction(functionName, ft));
+ raw = llvm::cast<llvm::Function>(llvm->module->getOrInsertFunction(functionName, ft).getCallee());
prepareBindings();
const std::string&blockName = "entry";
llvm::BasicBlock* blockCurrent = builder.GetInsertBlock();
llvm::Value* result = getScopeUnit(function->__entry)->compile(blockName);
assert(result);
//SECTIONTAG types/convert function ret value
builder.CreateRet(typeinference::doAutomaticTypeConversion(result, expectedResultType, llvm->builder));
if (blockCurrent) {
builder.SetInsertPoint(blockCurrent);
}
llvm->moveToGarbage(ft);
return raw;
}
ICodeScopeUnit*
IFunctionUnit::getScopeUnit(const CodeScope * const scope) {
if (__scopes.count(scope)) {
auto result = __scopes.at(scope).lock();
if (result) {
return result.get();
}
}
std::shared_ptr<ICodeScopeUnit> unit(pass->buildCodeScopeUnit(scope, this));
if (scope->__parent != nullptr) {
auto parentUnit = Decorators<CachedScopeDecoratorTag>::getInterface(getScopeUnit(scope->__parent));
parentUnit->registerChildScope(unit);
} else {
__orphanedScopes.push_back(unit);
}
if (!__scopes.emplace(scope, unit).second) {
__scopes[scope] = unit;
}
return unit.get();
}
ICodeScopeUnit*
IFunctionUnit::getScopeUnit(ManagedScpPtr scope) {
return getScopeUnit(&*scope);
}
ICodeScopeUnit*
IFunctionUnit::getEntry() {
return getScopeUnit(function->getEntryScope());
}
template<>
compilation::IFunctionUnit*
CompilePassCustomDecorators<void, void>
::buildFunctionUnit(const ManagedFnPtr& function) {
return new BruteFunctionDefault(function, this);
}
template<>
compilation::ICodeScopeUnit*
CompilePassCustomDecorators<void, void>
::buildCodeScopeUnit(const CodeScope * const scope, IFunctionUnit* function) {
return new DefaultCodeScopeUnit(scope, function, this);
}
} // end of compilation
compilation::IFunctionUnit*
CompilePass::getFunctionUnit(const ManagedFnPtr& function) {
unsigned int id = function.id();
if (!functions.count(id)) {
compilation::IFunctionUnit* unit = buildFunctionUnit(function);
functions.emplace(id, unit);
return unit;
}
return functions.at(id);
}
void
CompilePass::run() {
//Initialization:
managerTransformations = new xreate::compilation::TransformationsManager();
targetInterpretation = new interpretation::TargetInterpretation(this->man->root, this);
//Determine entry function:
StaticModel model = man->transcend->query(Config::get("function-entry"));
assert(model.size() && "Error: No entry function found");
assert(model.size() == 1 && "Error: Ambiguous entry function");
string nameMain = std::get<0>(TranscendLayer::parse<std::string>(model.begin()->second));
compilation::IFunctionUnit* unitMain = getFunctionUnit(man->root->findFunction(nameMain));
//Compilation itself:
entry = unitMain->compile();
}
llvm::Function*
CompilePass::getEntryFunction() {
assert(entry);
return entry;
}
void
CompilePass::prepareQueries(TranscendLayer* transcend) {
transcend->registerQuery(new containers::Query(), QueryId::ContainersQuery);
transcend->registerQuery(new polymorph::PolymorphQuery(), QueryId::PolymorphQuery);
transcend->registerQuery(new latex::LatexQuery(), QueryId::LatexQuery);
}
} //end of namespace xreate
/**
* \class xreate::CompilePass
* \brief The owner of the compilation process. Performs fundamental compilation activities along with the xreate::compilation's routines
*
* xreate::CompilePass traverses over xreate::AST tree and produces executable code.
* The pass performs compilation using the following data sources:
* - %Attachments: the data gathered by the previous passes. See \ref xreate::Attachments.
* - Transcend solutions accessible via queries. See \ref xreate::IQuery, \ref xreate::TranscendLayer.
*
* The pass generates a bytecode by employing \ref xreate::LLVMLayer(wrapper over LLVM toolchain).
* Many compilation activities are delegated to more specific routines. Most notable delegated compilation aspects are:
* - Containers support. See \ref xreate::containers.
* - Latex compilation. See \ref xreate::latex.
* - Interpretation support. See \ref xreate::interpretation.
* - Loop saturation support. See \ref xreate::compilation::TransformationsScopeDecorator.
* - External code interaction support. See \ref xreate::ExternLayer (wrapper over Clang library).
*
* \section adaptability_sect Adaptability
* xreate::CompilePass's behaviour can be adapted in several ways:
* - %Function Decorators to alter function-level compilation. See \ref xreate::compilation::IFunctionUnit
* - Code Block Decorators to alter code block level compilation. See \ref xreate::compilation::ICodeScopeUnit.
* Default functionality defined by \ref xreate::compilation::DefaultCodeScopeUnit
* - Targets to allow more versitile extensions.
* Currently only xreate::interpretation::TargetInterpretation use Targets infrastructure. See \ref xreate::compilation::Target.
* - Altering %function invocation. See \ref xreate::compilation::IFnInvocation.
*
* Clients are free to construct a compiler instantiation with the desired decorators by using \ref xreate::compilation::CompilePassCustomDecorators.
* As a handy alias, `CompilePassCustomDecorators<void, void>` constructs the default compiler.
*
*/
diff --git a/cpp/src/query/containers.cpp b/cpp/src/query/containers.cpp
index 9bfa1a5..0e1af82 100644
--- a/cpp/src/query/containers.cpp
+++ b/cpp/src/query/containers.cpp
@@ -1,111 +1,111 @@
/* 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 <v.melnychenko@xreate.org>
*
* containers.cpp
* Created on 3/14/15.
*/
#include <transcendlayer.h>
#include "query/containers.h"
using namespace std;
using namespace xreate::containers;
using namespace xreate;
Implementation
Query::queryImplementation(xreate::Symbol const &s) {
if (Attachments::exists<Implementation>(s)) {
return Attachments::get<Implementation>(s);
}
return Implementation::create(s);
}
Query::Query() {
Attachments::init<Implementation>();
}
void
Query::init(TranscendLayer* transcend) {
if (flagDataIsLoaded) return;
//Fill implementation data for a data sources:
auto range = transcend->query(Config::get("containers.id.implementations"));
if (range.size())
for(auto atom : range) {
- auto data = TranscendLayer::parse<SymbolPacked, Gringo::Symbol>(atom.second);
+ auto data = TranscendLayer::parse<SymbolPacked, Clingo::Symbol>(atom.second);
Symbol var = transcend->unpack(get<0>(data));
- string implStr = get<1>(data).name().c_str();
+ string implStr(get<1>(data).name());
if (implStr == Config::get("containers.impl.solid")) {
auto size = TranscendLayer::parse<int>(get<1>(data));
Attachments::put<Implementation>(var,{SOLID, ImplementationRec<SOLID>
{get<0>(size)}});
} else if (implStr == Config::get("containers.impl.onthefly")) {
Attachments::put<Implementation>(var,{ON_THE_FLY, ImplementationRec<ON_THE_FLY>
{var}});
} else {
assert(false && "Unable to determine proper implementation for the symbol");
}
}
flagDataIsLoaded = true;
}
Implementation
Implementation::create(const Symbol &var) {
//TODO review implementation determination strategy
Expression varDecl = CodeScope::getDefinition(var);
switch (varDecl.op) {
case Operator::LIST_RANGE:
{
ImplementationRec<ON_THE_FLY> rec{var};
return {ON_THE_FLY, rec};
}
case Operator::LIST:
{
return {SOLID, ImplementationRec<SOLID> {varDecl.getOperands().size()}};
}
default: break;
};
ImplementationLinkedList ill(var);
if (ill) {
return ill.getImplementationData();
}
assert(false && "Unable to determine proper implementation for the symbol");
return Implementation();
}
ImplementationLinkedList::ImplementationLinkedList(const Symbol& source)
: flagIsValid(false), s(source) {
const Expression& sourceExpr = CodeScope::getDefinition(source);
if (sourceExpr.tags.count(Config::get("containers.id.linkedlist"))) {
flagIsValid = true;
Expression tagLinkedlist = sourceExpr.tags.at(Config::get("containers.id.linkedlist"));
assert(tagLinkedlist.operands.size() == 2);
fieldPointer = tagLinkedlist.operands.at(0).getValueString();
terminator = tagLinkedlist.operands.at(1);
}
}
ImplementationLinkedList::operator bool () const {
return flagIsValid;
}
Implementation
ImplementationLinkedList::getImplementationData() const {
return {ON_THE_FLY, ImplementationRec<ON_THE_FLY>{s}};
}
diff --git a/cpp/src/query/latex.cpp b/cpp/src/query/latex.cpp
index 6970cc7..4ed2485 100644
--- a/cpp/src/query/latex.cpp
+++ b/cpp/src/query/latex.cpp
@@ -1,101 +1,101 @@
/*
* 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 <v.melnychenko@xreate.org>
* Created on June 25, 2018, 12:14 PM
*
* \file latex.cpp
* \brief latex
*/
#include "query/latex.h"
#include "aux/transcend-decorators.h"
using namespace std;
using namespace xreate::latereasoning;
namespace xreate{
namespace latex{
void
LatexQuery::init(TranscendLayer* transcend) {
__transcend = transcend;
//schema: latex_fn_demand(Fn, Subject)
StaticModel data = __transcend->query("latex_fn_demand_ordered");
for(const auto& entry : data) {
string fnName, subject; size_t id;
tie(fnName, subject, id) = __transcend->parse<string, string, int>(entry.second);
__demand[fnName].resize(std::max(__demand[fnName].size(), id+1));
__demand[fnName][id] = subject;
}
//schema: latex_registered_subjects(Subject, Decision)
data = __transcend->query("latex_registered_subjects");
for(const auto& entry : data) {
string subject;
- Gringo::Symbol decision;
+ Clingo::Symbol decision;
- tie(subject, decision) = __transcend->parse<string, Gringo::Symbol>(entry.second);
+ tie(subject, decision) = __transcend->parse<string, Clingo::Symbol>(entry.second);
__domains[subject].push_back(decision);
}
//schema: latex_decision(Scope, Subject, Decision)
data = __transcend->query("latex_decision");
for(const auto& entry : data) {
ScopePacked scope;
string subject;
- Gringo::Symbol decision;
+ Clingo::Symbol decision;
- tie(scope, subject, decision) = __transcend->parse<ScopePacked, string, Gringo::Symbol>(entry.second);
+ tie(scope, subject, decision) = __transcend->parse<ScopePacked, string, Clingo::Symbol>(entry.second);
__decisions[make_pair(scope, subject)] = entry.second;
}
//schema: latex_parameters_offset(int)
//Override parameter from transcend
data = __transcend->query("latex_parameters_offset");
if(data.size()) {
LatexParametersOffset = std::get<0>(__transcend->parse<unsigned int>(data.begin()->second));
}
auto transcendLate =
Decorators<LateReasoningTranscendDecoratorTag>::getInterface(__transcend);
//Later decisions. schema: Scope, Subject, Decision
LateAnnotationsGroup group = transcendLate->queryLate("latex_decision");
for (auto entry: group.annotations) {
auto key = __transcend->parse<ScopePacked, string>(entry.first);
__decisionsLate.emplace(make_pair(get<0>(key), get<1>(key)), entry.second);
}
}
Demand
LatexQuery::getFnDemand(const std::string& fnName) {
if (!__demand.count(fnName)) return Demand();
return __demand.at(fnName);
}
latereasoning::LateAnnotation
LatexQuery::getDecision(const std::string& subject, const CodeScope* scopeCaller) {
ScopePacked scopeP = __transcend->pack(scopeCaller);
if(__decisions.count(make_pair(scopeP, subject))){
//found static decision
return LateAnnotation(__decisions.at(make_pair(scopeP, subject)));
}
return __decisionsLate.at(make_pair(scopeP, subject));
}
-std::list<Gringo::Symbol>
+std::list<Clingo::Symbol>
LatexQuery::getSubjectDomain(const std::string& subject) {
assert(__domains.count(subject));
return __domains.at(subject);
}
}
}
diff --git a/cpp/src/query/latex.h b/cpp/src/query/latex.h
index c66f39f..9f5cd09 100644
--- a/cpp/src/query/latex.h
+++ b/cpp/src/query/latex.h
@@ -1,45 +1,45 @@
/*
* 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 query/latex.h
* \brief Transcend solution on [Context](/d/concepts/context/) implementation details
*/
#ifndef LATEXQUERY_H
#define LATEXQUERY_H
#include "transcendlayer.h"
#include "aux/latereasoning.h"
#include <list>
namespace xreate{
namespace latex{
typedef std::vector<std::string> Demand;
/** \brief Queries Transcend solution on [Context](/d/concepts/context/) implementation details */
class LatexQuery: public IQuery{
public:
VNameId LatexParametersOffset = 1000; //Default value. Overriden by `latex_parameters_offset` from transcend
Demand getFnDemand(const std::string& fnName);
latereasoning::LateAnnotation getDecision(const std::string& subject, const CodeScope* scopeCaller);
- std::list<Gringo::Symbol> getSubjectDomain(const std::string& subject);
+ std::list<Clingo::Symbol> getSubjectDomain(const std::string& subject);
void init(TranscendLayer* transcend);
private:
TranscendLayer* __transcend;
std::map<std::string, Demand> __demand;
- std::map<std::pair<ScopePacked, std::string>, Gringo::Symbol> __decisions;
+ std::map<std::pair<ScopePacked, std::string>, Clingo::Symbol> __decisions;
std::map<std::pair<ScopePacked, std::string>, latereasoning::LateAnnotation> __decisionsLate;
- std::map<std::string, std::list<Gringo::Symbol>> __domains;
+ std::map<std::string, std::list<Clingo::Symbol>> __domains;
};
}
}
#endif
diff --git a/cpp/src/query/polymorph.cpp b/cpp/src/query/polymorph.cpp
index 52f6aa0..b7bf78a 100644
--- a/cpp/src/query/polymorph.cpp
+++ b/cpp/src/query/polymorph.cpp
@@ -1,71 +1,71 @@
/*
* 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: polymorph.cpp
* Author: pgess <v.melnychenko@xreate.org>
*
* Created on November 9, 2017, 12:14 PM
*/
#include "polymorph.h"
#include "aux/transcend-decorators.h"
using namespace std;
namespace xreate{
namespace polymorph{
const std::string atomPolymorph = "dfa_callguard";
void
PolymorphQuery::init(TranscendLayer* transcend) {
__transcend = transcend;
StaticModel queryResult = transcend->query(atomPolymorph);
if (queryResult.size()) {
for (auto entry : queryResult) {
- auto answer = TranscendLayer::parse<SymbolNode, Gringo::Symbol>(entry.second);
+ auto answer = TranscendLayer::parse<SymbolNode, Clingo::Symbol>(entry.second);
SymbolNode symbCaller = std::get<0>(answer);
SymbolGeneralized symbCallerUnpacked = transcend->unpack(symbCaller);
__cacheEarlyReasoning.emplace(symbCallerUnpacked, entry.second);
}
}
auto transcendLate =
Decorators<LateReasoningTranscendDecoratorTag>::getInterface(__transcend);
latereasoning::LateAnnotationsGroup group = transcendLate->queryLate(atomPolymorph);
for(auto entry : group.annotations) {
- auto targetWrapper = Gringo::Symbol::createTuple(Gringo::SymSpan{&entry.first, 1});
+ auto targetWrapper = Clingo::Function("", Clingo::SymbolSpan{&entry.first, 1});
auto targetSP = __transcend->parse<SymbolNode>(targetWrapper);
SymbolGeneralized targetS = __transcend->unpack(std::get<0>(targetSP));
__cacheLateReasoning.emplace(targetS, entry.second);
}
}
latereasoning::LateAnnotation
PolymorphQuery::get(const Expression& e) const {
SymbolGeneralized targetS = Attachments::exists<SymbolAlias>(e) ?
SymbolGeneralized(Attachments::get<SymbolAlias>(e))
: SymbolGeneralized(SymbolAnonymous{e.id});
if (__cacheEarlyReasoning.count(targetS)) {
return latereasoning::LateAnnotation(__cacheEarlyReasoning.at(targetS));
}
if (__cacheLateReasoning.count(targetS)) {
return __cacheLateReasoning.at(targetS);
}
assert(false && "Can't find a guard");
}
Expression
-PolymorphQuery::getValue(const Gringo::Symbol& symbol) const {
- auto result = __transcend->parse<Gringo::Symbol, Expression>(symbol);
+PolymorphQuery::getValue(const Clingo::Symbol& symbol) const {
+ auto result = __transcend->parse<Clingo::Symbol, Expression>(symbol);
return std::get<1>(result);
}
}
} //end of xreate::polymorph
diff --git a/cpp/src/query/polymorph.h b/cpp/src/query/polymorph.h
index 7be4f56..1baff59 100644
--- a/cpp/src/query/polymorph.h
+++ b/cpp/src/query/polymorph.h
@@ -1,42 +1,42 @@
/*
* 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: polymorph.h
* Author: pgess <v.melnychenko@xreate.org>
*
* Created on November 9, 2017, 12:14 PM
*/
/**
* \file query/polymorph.h
* \brief Transcend solution on [Polymorphism](/d/concepts/polymorphism/) implementation details
*/
#ifndef POLYMORPHQUERY_H
#define POLYMORPHQUERY_H
#include "transcendlayer.h"
#include "aux/latereasoning.h"
#include <unordered_map>
namespace xreate { namespace polymorph {
/** \brief Queries Transcend solution on [Polymorphism](/d/concepts/polymorphism/) implementation details */
class PolymorphQuery: public IQuery {
public:
latereasoning::LateAnnotation get(const Expression& e) const;
- Expression getValue(const Gringo::Symbol& s) const;
+ Expression getValue(const Clingo::Symbol& s) const;
virtual void init(TranscendLayer* transcend) override;
private:
- std::unordered_map<SymbolGeneralized, Gringo::Symbol> __cacheEarlyReasoning;
+ std::unordered_map<SymbolGeneralized, Clingo::Symbol> __cacheEarlyReasoning;
std::unordered_map<SymbolGeneralized, latereasoning::LateAnnotation> __cacheLateReasoning;
TranscendLayer* __transcend = nullptr;
};
}}//end of xreate::polymorph
#endif /* POLYMORPHQUERY_H */
diff --git a/cpp/src/transcendlayer.cpp b/cpp/src/transcendlayer.cpp
index 2ecd979..56984f9 100644
--- a/cpp/src/transcendlayer.cpp
+++ b/cpp/src/transcendlayer.cpp
@@ -1,495 +1,471 @@
/* 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 <v.melnychenko@xreate.org>
* File: transcendlayer.cpp
*/
/**
* \file transcendlayer.h
* \brief Transcend reasoning implementation
*/
#include "transcendlayer.h"
#include "analysis/utils.h"
#include "utils.h"
-#include <gringo/scripts.hh>
#include <boost/format.hpp>
#include <boost/algorithm/string/join.hpp>
#include <iostream>
#include <memory>
#include <boost/variant/detail/apply_visitor_binary.hpp>
using namespace std;
//TODO escape identifiers started with upper case symbol
namespace xreate{
bool operator==(const SymbolAnonymous& s1, const SymbolAnonymous& s2) {
return s1.id == s2.id && s1.flagIsUsed == s2.flagIsUsed;
}
struct VisitorSymbolNodeHash : public boost::static_visitor<size_t>{
std::size_t operator()(const xreate::SymbolPacked& node) const noexcept {
return 2 * (node.identifier + 3 * node.scope + 5 * std::abs(node.version));
}
std::size_t operator()(const xreate::SymbolAnonymous& node) const noexcept {
return 7 * node.id;
}
} ;
}
namespace std{
std::size_t
hash<xreate::SymbolNode>::operator()(xreate::SymbolNode const& s) const noexcept {
return boost::apply_visitor(xreate::VisitorSymbolNodeHash(), s);
}
std::size_t
hash<xreate::SymbolGeneralized>::operator()(xreate::SymbolGeneralized const& s) const noexcept {
return xreate::AttachmentsId<xreate::SymbolGeneralized>::getId(s);
}
}
namespace xreate{
void
TranscendLayer::printWarnings(std::ostream& out) {
const std::string warningTag = "warning";
auto warningsModel = query(warningTag);
if(warningsModel.size())
for(auto warning : warningsModel) {
unsigned int warningId;
- Gringo::Symbol params;
- std::tie(warningId, params) = parse<unsigned int, Gringo::Symbol>(warning.second);
+ Clingo::Symbol params;
+ std::tie(warningId, params) = parse<unsigned int, Clingo::Symbol>(warning.second);
cout << "Warning: " << __warnings.at(warningId) << " ";
- params.print(out);
out << params;
}
}
bool
-TranscendLayer::processSolution(Gringo::Model const &model) {
+TranscendLayer::processSolution(Clingo::Model const &model) {
cout << "Model: " << endl;
const string& atomBindVar = Config::get("transcend.bindings.variable");
const string& atomBindFunc = Config::get("transcend.bindings.function");
const string& atomBindScope = Config::get("transcend.bindings.scope");
- for(Gringo::Symbol atom : model.atoms(clingo_show_type_atoms)) {
- atom.print(cout);
- cout << " | " << endl;
+ for(const Clingo::Symbol& atom : model.symbols(clingo_show_type_atoms)) {
+ cout << atom << endl;
- string atomName(atom.name().c_str());
+ string atomName(atom.name());
if(atomName == atomBindVar || atomName == atomBindFunc || atomName == atomBindScope) {
- string atomAlias = std::get<1>(parse<Gringo::Symbol, Gringo::Symbol>(atom)).name().c_str();
+ string atomAlias(std::get<1>(parse<Clingo::Symbol, Clingo::Symbol>(atom)).name());
__model.emplace(atomAlias, atom);
continue;
}
__model.emplace(atomName, atom);
}
return true;
}
void
TranscendLayer::registerReport(IAnalysisReport * report) {
__reports.push_back(report);
}
void
TranscendLayer::printReports() {
for(IAnalysisReport* report : __reports) {
report->print(__partGeneral);
}
}
void
TranscendLayer::deleteReports(){
for(IAnalysisReport* report : __reports) {
delete report;
}
__reports.clear();
}
void
TranscendLayer::addRuleWarning(const RuleWarning & rule) {
//__partGeneral << rule << endl;
list<string> domains;
boost::format formatDef("%1%(%2%)");
std::transform(rule.__args.begin(), rule.__args.end(), std::inserter(domains, domains.begin()),
[&formatDef](const std::pair<std::string, DomainAnnotation> &argument) {
string domain;
switch(argument.second) {
case DomainAnnotation::FUNCTION:
domain = "function";
break;
case DomainAnnotation::VARIABLE:
domain = "variable";
break;
}
return boost::str(formatDef % domain % argument.first);
});
list<string> vars;
std::transform(rule.__args.begin(), rule.__args.end(), std::inserter(vars, vars.begin()),
[](const std::pair<std::string, DomainAnnotation> &argument) {
return argument.first.c_str();
});
list<list < string>> guardsRaw;
std::transform(rule.__guards.begin(), rule.__guards.end(), std::inserter(guardsRaw, guardsRaw.begin()),
[this](const Expression & guard) {
return xreate::analysis::compile(guard);
});
const list<string>& guards = xreate::analysis::multiplyLists(std::move(guardsRaw));
list<string> &&branches = xreate::analysis::compileNeg(rule.__condition);
boost::format formatWarning("warning(%1%, (%2%)):- %3%, %4%, %5%.");
for(const string &guardsJoined : guards)
for(const string &branch : branches) {
unsigned int hook = registerWarning(string(rule.__message));
__partGeneral << formatWarning
% (hook)
% (boost::algorithm::join(vars, ", "))
% (branch)
% (guardsJoined)
% (boost::algorithm::join(domains, ", "))
<< endl;
}
}
unsigned int
TranscendLayer::registerWarning(std::string && message) {
static int warningId = 0;
__warnings.emplace(warningId, message);
return warningId++;
}
void
TranscendLayer::involveImports() {
ostream &out = __partGeneral;
if(ast)
for(string fn : ast->__rawImports) {
std::ifstream file(fn);
if(!file) {
std::cout << "Can't process script file: " << fn << std::endl;
assert(false);
}
while(!file.eof()) {
string line;
std::getline(file, line);
out << line << endl;
}
}
}
void
TranscendLayer::addRawScript(std::string && script) {
__partGeneral << script;
}
void
TranscendLayer::run() {
involveImports();
printReports();
ostringstream program;
program << __partTags.str() << __partGeneral.str();
cout << FYEL(program.str()) << endl;
- std::vector<char const *> args{"clingo", nullptr};
- DefaultGringoModule moduleDefault;
- Gringo::Scripts scriptsDefault(moduleDefault);
-
- ClingoLib ctl(scriptsDefault, 0, args.data(), { }, 0);
-
- ctl.add("base",{}, program.str());
- ctl.ground({
- {"base",
- {}}
- }, nullptr);
-
- // solve
- Gringo::SolveResult result = ctl.solve([this](Gringo::Model const &model) {
- this->processSolution(model);
- return true;
- },
- {
- });
-
- if(result.satisfiable() == Gringo::SolveResult::Satisfiable) {
- cout << FGRN("SUCCESSFULLY") << endl;
- } else {
- cout << FRED("UNSUCCESSFULLY") << endl;
- }
+ Clingo::Control ctl;
+ ctl.add("base",{}, program.str().c_str());
+ ctl.ground({{"base",{}}}, nullptr);
+ this->processSolution(ctl.solve().model());
// invoke all query plugins to process solution
for(auto q : __queries) {
q.second->init(this);
}
}
TranscendLayer::TranscendLayer() : ast(nullptr) { }
StaticModel
TranscendLayer::query(const std::string & atom) const {
StaticModel result;
if (! __model.count(atom)) {
return result;
}
auto currentDataRange = __model.equal_range(atom);
std::copy(currentDataRange.first, currentDataRange.second, std::inserter(result, result.end()));
return result;
}
ScopePacked
TranscendLayer::pack(const CodeScope * const scope) {
auto pos = __indexScopes.emplace(scope, __indexScopes.size());
if(pos.second)
__registryScopes.push_back(scope);
return pos.first->second;
}
size_t
TranscendLayer::getScopesCount() const {
return __registryScopes.size();
}
SymbolPacked
TranscendLayer::pack(const Symbol& symbol, std::string hintSymbolName) {
SymbolPacked result(symbol.identifier.id, symbol.identifier.version, pack(symbol.scope));
__indexSymbolNameHints.emplace(result, hintSymbolName);
return result;
}
Symbol
TranscendLayer::unpack(const SymbolPacked & symbol) const {
return Symbol{ScopedSymbol
{symbol.identifier, symbol.version}, __registryScopes[symbol.scope]};
};
std::string
TranscendLayer::getHintForPackedSymbol(const SymbolPacked & symbol) {
auto result = __indexSymbolNameHints.find(symbol);
return(result == __indexSymbolNameHints.end()) ? "" : result->second;
}
IQuery *
TranscendLayer::registerQuery(IQuery *query, const QueryId & id) {
return __queries.emplace(id, query).first->second;
}
IQuery *
TranscendLayer::getQuery(const QueryId & id) {
assert(__queries.count(id) && "Undefined query");
return __queries.at(id);
}
class VisitorUnpackSymbol : public boost::static_visitor<SymbolGeneralized>{
public:
VisitorUnpackSymbol(const TranscendLayer* transcend) : __transcend(transcend) { }
SymbolGeneralized operator()(const SymbolPacked& symbol) const {
return __transcend->unpack(symbol);
}
SymbolGeneralized operator()(const SymbolAnonymous& symbol) const {
return symbol;
}
private:
const TranscendLayer* __transcend;
} ;
class VisitorPackSymbol : public boost::static_visitor<SymbolNode>{
public:
VisitorPackSymbol(TranscendLayer* transcend, const std::string& hintSymbolName)
: __transcend(transcend), __hint(hintSymbolName) { }
SymbolNode operator()(const Symbol& symbol) const {
return __transcend->pack(symbol, __hint);
}
SymbolNode operator()(const SymbolAnonymous& symbol) const {
return symbol;
}
private:
TranscendLayer* __transcend;
std::string __hint;
} ;
SymbolNode
TranscendLayer::pack(const SymbolGeneralized& symbol, const std::string & hintSymbolName) {
return boost::apply_visitor(VisitorPackSymbol(this, hintSymbolName), symbol);
}
SymbolGeneralized
TranscendLayer::unpack(const SymbolNode & symbol) const {
return boost::apply_visitor(VisitorUnpackSymbol(this), symbol);
}
bool
operator==(const SymbolPacked& s1, const SymbolPacked & s2) {
return s1.identifier == s2.identifier && s1.scope == s2.scope;
}
bool
operator<(const SymbolPacked& s1, const SymbolPacked & s2) {
return s1.scope < s2.scope || (s1.scope == s2.scope && s1.identifier < s2.identifier);
}
Expression
ParseImplAtom<Expression>
-::get(const Gringo::Symbol & atom) {
+::get(const Clingo::Symbol & atom) {
switch(atom.type()) {
- case Gringo::SymbolType::Num: return Expression(atom.num());
- case Gringo::SymbolType::Str: return Expression(Atom<String_t>(std::string(atom.string().c_str())));
+ case Clingo::SymbolType::Number: return Expression(atom.number());
+ case Clingo::SymbolType::String: return Expression(Atom<String_t>(std::string(atom.string())));
- case Gringo::SymbolType::Fun:
+ case Clingo::SymbolType::Function:
{
//FUNC
- Expression result(Operator::CALL,{Expression(Atom<Identifier_t>(std::string(atom.name().c_str())))});
- for(const Gringo::Symbol& arg : atom.args()) {
+ Expression result(Operator::CALL,{Expression(Atom<Identifier_t>(std::string(atom.name())))});
+ for(const Clingo::Symbol& arg : atom.arguments()) {
result.addArg(ParseImplAtom<Expression>::get(arg));
}
return result;
}
default:
{
assert(false);
}
}
}
int
ParseImplAtom<int>
-::get(const Gringo::Symbol & atom) {
+::get(const Clingo::Symbol & atom) {
switch(atom.type()) {
- case Gringo::SymbolType::Num: return atom.num();
+ case Clingo::SymbolType::Number: return atom.number();
default: break;
}
assert(false && "Inappropriate symbol type");
}
std::string
ParseImplAtom<std::string>
-::get(const Gringo::Symbol & atom) {
+::get(const Clingo::Symbol & atom) {
switch(atom.type()) {
- case Gringo::SymbolType::Str: return atom.string().c_str();
- case Gringo::SymbolType::Fun: return atom.name().c_str();
+ case Clingo::SymbolType::String: return atom.string();
+ case Clingo::SymbolType::Function: return atom.name();
- default: break;
+ default: break;
}
assert(false && "Inappropriate symbol type");
}
SymbolPacked
ParseImplAtom<SymbolPacked>
-::get(const Gringo::Symbol & atom) {
+::get(const Clingo::Symbol & atom) {
auto result = TranscendLayer::parse<int, int, int>(atom);
return SymbolPacked(std::get<0>(result), std::get<1>(result), std::get<2>(result));
};
-Gringo::Symbol
-ParseImplAtom<Gringo::Symbol>
-::get(const Gringo::Symbol & atom) {
+Clingo::Symbol
+ParseImplAtom<Clingo::Symbol>
+::get(const Clingo::Symbol & atom) {
return atom;
}
SymbolNode
ParseImplAtom<SymbolNode>
-::get(const Gringo::Symbol & atom) {
- assert(atom.type() == Gringo::SymbolType::Fun
+::get(const Clingo::Symbol & atom) {
+ assert(atom.type() == Clingo::SymbolType::Function
&& "Inappropriate symbol type");
- if(atom.name() == "a") {
+ if(atom.match("a", 1)) {
return SymbolAnonymous{(unsigned int) std::get<0>(TranscendLayer::parse<int>(atom))};
- } else if(atom.name() == "s") {
+ } else if(atom.match("s", 3)) {
return ParseImplAtom<SymbolPacked>::get(atom);
}
assert(false && "Wrong symbol format");
}
class VisitorSymbolId : public boost::static_visitor<unsigned int>{
public:
unsigned int operator()(const Symbol& symbol) const {
return AttachmentsId<Symbol>::getId(symbol);
}
unsigned int operator()(const SymbolAnonymous& symbol) const {
return symbol.id;
}
} ;
unsigned int
AttachmentsId<SymbolGeneralized>
::getId(const SymbolGeneralized & symbol) {
return boost::apply_visitor(VisitorSymbolId(), symbol);
}
} //end of xreate namespace
/**
* \class xreate::TranscendLayer
* \brief Logic reasoning implementation. Internally, it's a proxy to the external ASP solver [Clasp](https://potassco.org/clasp/)
*
* Performs reasoning over source codes in order to facilitate efficient compilation using results from a number of internal analyzers.
* Clients implement \ref IAnalysisReport to supply Transcend with data and implement \ref IQuery to find out resolutions.
*
* Transcend uses the following sources to build a logic program before actual reasoning is performed:
* - Raw content. Clients are free to include arbitrary ASP format data in the logic program. See \ref addRawScript().
* - External scripts. External files with ASP scripts can be appended to the logic program. See `involveImports()` (private member).
* - Diagnostic rules to produce diagnostic messages during
* compilation(warnings) or even to signal to halt compilation with errors. See \ref addRuleWarning(), \ref registerWarning().
* - Internal analyzers. The analyzer can publish logic facts and rules by implementing \ref IAnalysisReport interface.
*
* Generally, Transcend input could be loosely broke down into three categories:
* - Internally derived data. CFA, DFA, and other analyzers automatically supply the reasoner with
* useful insights about source codes, the structure and algorithms of a program.
* - User provided custom data. Analyzers extract manual developer-provided annotations from the source codes.
* - External data. External files supply reasoner with third-party data
* which relates to different aspects of a program possibly produced by external analyzers.
*
* After Transcend has gathered data from all providers and the logic program is fully constructed,
* it runs the external logic reasoner to receive back the solution.
*
* The solution from the external logic reasoner is accessible via *queries*.
* Classes which want to request data from Transcend should implement the \ref IQuery interface. See \ref IQuery descendants to find out currently available queries.
*
* \section tl_adapt Adaptability
* Decorators are used to extend %TranscendLayer functionality. The default bundle defined by \ref DefaultTranscendLayerImpl.
*
* \sa See xreate::dfa::DFAPass, xreate::cfa::CFAPass, xreate::IQuery, xreate::IAnalysisReport
*/
diff --git a/cpp/src/transcendlayer.h b/cpp/src/transcendlayer.h
index 6ad56de..495ceb5 100644
--- a/cpp/src/transcendlayer.h
+++ b/cpp/src/transcendlayer.h
@@ -1,284 +1,284 @@
/* 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 <v.melnychenko@xreate.org>
* File: transcendlayer.h
*/
#ifndef transcendLAYER_H
#define transcendLAYER_H
#include "ast.h"
#include "contextrule.h"
-#include <clingo/clingocontrol.hh>
+#include <clingo.hh>
#include <string>
#include <climits>
#include <unordered_map>
#include <boost/bimap.hpp>
#include <boost/bimap/multiset_of.hpp>
#include <boost/optional.hpp>
#include <boost/scoped_ptr.hpp>
#include <list>
#include <limits>
namespace xreate {
typedef unsigned int ScopePacked;
const ScopePacked SCOPE_ABSTRACT_GLOBAL = std::numeric_limits<ScopePacked>::max();
struct SymbolPacked {
SymbolPacked(){}
SymbolPacked(ScopedSymbol i, ScopePacked s): identifier(i.id), version(i.version), scope(s){}
SymbolPacked(VNameId symbolId, versions::VariableVersion symbolVersion, ScopePacked symbolScope)
: identifier(symbolId), version(symbolVersion), scope(symbolScope){}
VNameId identifier;
versions::VariableVersion version;
ScopePacked scope;
};
bool operator==(const SymbolPacked& s1, const SymbolPacked& s2);
bool operator<(const SymbolPacked& s1, const SymbolPacked& s2);
struct SymbolAnonymous {
unsigned int id;
bool flagIsUsed = false;
};
bool operator==(const SymbolAnonymous& s1, const SymbolAnonymous& s2);
typedef boost::variant<SymbolAnonymous, SymbolPacked> SymbolNode;
//DEBT use SymbolGeneralized communicating with Analysis rather than Symbol
typedef boost::variant<SymbolAnonymous, Symbol> SymbolGeneralized;
template<>
struct AttachmentsId<SymbolGeneralized>{
static unsigned int getId(const SymbolGeneralized& symbol);
};
} namespace std {
template<>
struct hash<xreate::SymbolNode> {
std::size_t operator()(xreate::SymbolNode const& s) const noexcept;
};
template<>
struct hash<xreate::SymbolGeneralized> {
std::size_t operator()(xreate::SymbolGeneralized const& s) const noexcept;
};
}
namespace xreate {
enum class DFGConnection {
STRONG, WEAK, PROTOTYPE
};
/** \brief Supplies \ref TranscendLayer with results of an analysis*/
class IAnalysisReport {
public:
/** \brief Composes a logic program to represent the analysis data in ASP format, and appends to a stream*/
virtual void print(std::ostringstream& output) const = 0;
virtual ~IAnalysisReport(){};
};
/** \brief Transcend solutions querying interface */
class IQuery {
public:
virtual void init(TranscendLayer* transcend) = 0;
virtual ~IQuery() {}
};
enum class QueryId {
ContainersQuery,
PolymorphQuery,
LatexQuery
};
namespace dfa{
class DFAGraph;
}
namespace cfa {
class CFAGraph;
}
-typedef std::multimap<std::string, Gringo::Symbol> StaticModel;
+typedef std::multimap<std::string, Clingo::Symbol> StaticModel;
typedef StaticModel::const_iterator StaticModelIterator;
class TranscendLayer {
friend class ContextRule;
/**\name Data Providers Management */
///@{
public:
void registerReport(IAnalysisReport* report);
void printReports();
void deleteReports();
/** \brief Appends arbitrary string to a logic program
*/
void addRawScript(std::string&& script);
private:
std::list<IAnalysisReport*> __reports;
/** Includes external text files to a *logic program* */
void involveImports();
///@}
/**\name Queries Management */
///@{
public:
/** \brief Registers a query. See xreate::IQuery */
IQuery* registerQuery(IQuery* query, const QueryId& id);
/** \brief Returns a particular query. See xreate::IQuery */
IQuery* getQuery(const QueryId& id);
template<class ...Types>
- static std::tuple<Types...> parse(const Gringo::Symbol& atom);
+ static std::tuple<Types...> parse(const Clingo::Symbol& atom);
StaticModel query(const std::string& atom) const;
size_t getScopesCount() const;
SymbolPacked pack(const Symbol& symbol, std::string hintSymbolName = "");
ScopePacked pack(const CodeScope * const scope);
Symbol unpack(const SymbolPacked& symbol) const;
SymbolNode pack(const SymbolGeneralized& symbol, const std::string& hintSymbolName);
SymbolGeneralized unpack(const SymbolNode& symbol) const;
std::string getHintForPackedSymbol(const SymbolPacked& symbol);
///@}
private:
std::map<QueryId, IQuery*> __queries;
std::map<SymbolPacked, std::string> __indexSymbolNameHints;
std::unordered_map<const CodeScope*, unsigned int> __indexScopes;
std::vector<const CodeScope*> __registryScopes;
/**\name Diagnostic */
///@{
//TODO diagnostic move over to separate provider/query
public:
/** \brief Registers diagnostic rules */
void addRuleWarning(const RuleWarning &rule);
/** \brief Registers diagnostic messages */
unsigned int registerWarning(std::string &&message);
private:
std::map<unsigned int, std::string> __warnings;
void printWarnings(std::ostream& out);
///@}
///@{
public:
TranscendLayer();
/** \brief Executes reasoning */
void run();
///@}
AST *ast;
protected:
- virtual bool processSolution(Gringo::Model const &model);
+ virtual bool processSolution(Clingo::Model const &model);
private:
StaticModel __model;
std::ostringstream __partTags;
std::ostringstream __partGeneral;
};
template<class typ>
struct ParseImplAtom {
- static typ get(const Gringo::Symbol& atom) {
- return atom.num();
+ static typ get(const Clingo::Symbol& atom) {
+ return atom.number();
}
};
template<>
struct ParseImplAtom<int> {
- static int get(const Gringo::Symbol& atom);
+ static int get(const Clingo::Symbol& atom);
};
template<>
struct ParseImplAtom<std::string> {
- static std::string get(const Gringo::Symbol& atom);
+ static std::string get(const Clingo::Symbol& atom);
};
template<>
struct ParseImplAtom<SymbolPacked> {
- static SymbolPacked get(const Gringo::Symbol& atom);
+ static SymbolPacked get(const Clingo::Symbol& atom);
};
template<>
struct ParseImplAtom<SymbolNode> {
- static SymbolNode get(const Gringo::Symbol& atom);
+ static SymbolNode get(const Clingo::Symbol& atom);
};
template<>
-struct ParseImplAtom<Gringo::Symbol> {
- static Gringo::Symbol get(const Gringo::Symbol& atom);
+struct ParseImplAtom<Clingo::Symbol> {
+ static Clingo::Symbol get(const Clingo::Symbol& atom);
};
template<class ItemType>
struct ParseImplAtom<std::list<ItemType>>{
static std::list<ItemType>
- get(const Gringo::Symbol& atom){
- bool flagIsList = (atom.type() == Gringo::SymbolType::Fun) && atom.name().empty();
+ get(const Clingo::Symbol& atom){
+ bool flagIsList = (atom.type() == Clingo::SymbolType::Function) && std::string(atom.name()).empty();
std::list<ItemType> result;
if(!flagIsList) {
//treat as degenerate case: list with a single element
result.push_back(ParseImplAtom<ItemType>::get(atom));
return result;
}
- for (const Gringo::Symbol& arg: atom.args()) {
+ for (const Clingo::Symbol& arg: atom.arguments()) {
result.push_back(ParseImplAtom<ItemType>::get(arg));
}
return result;
}
};
template<>
struct ParseImplAtom<Expression> {
- static Expression get(const Gringo::Symbol& atom);
+ static Expression get(const Clingo::Symbol& atom);
};
template<class Tuple, size_t index>
struct Parse_Impl {
- static void parse(Tuple& tup, Gringo::SymSpan::iterator arg) {
+ static void parse(Tuple& tup, Clingo::SymbolSpan::IteratorType arg) {
const size_t tupleSize = std::tuple_size<Tuple>::value;
typedef typename std::tuple_element < tupleSize - index, Tuple>::type ElType;
ElType& el = std::get < tupleSize - index > (tup);
- Gringo::Symbol atom = *arg;
+ Clingo::Symbol atom = *arg;
el = ParseImplAtom<ElType>::get(atom);
Parse_Impl<Tuple, index - 1 > ::parse(tup, ++arg);
}
};
template<class Tuple>
struct Parse_Impl<Tuple, 0> {
- static void parse(Tuple& tup, Gringo::SymSpan::iterator arg) {
+ static void parse(Tuple& tup, Clingo::SymbolSpan::IteratorType arg) {
}
};
template<class ...Types>
std::tuple<Types...>
-TranscendLayer::parse(const Gringo::Symbol& atom) {
+TranscendLayer::parse(const Clingo::Symbol& atom) {
typedef std::tuple < Types...> Tuple;
Tuple tup;
- Parse_Impl<Tuple, std::tuple_size<Tuple>::value>::parse(tup, atom.args().first);
+ Parse_Impl<Tuple, std::tuple_size<Tuple>::value>::parse(tup, atom.arguments().begin());
return tup;
}
} //end of xreate namespace
#endif
diff --git a/cpp/tests/CMakeLists.txt b/cpp/tests/CMakeLists.txt
index 2890e4b..618a5eb 100644
--- a/cpp/tests/CMakeLists.txt
+++ b/cpp/tests/CMakeLists.txt
@@ -1,60 +1,64 @@
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($<TARGET_PROPERTY:xreate,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)
-link_directories(${LIBCLASP_PATH})
+set (CLINGO_LIBS_DIR ${CLINGO_PATH}/build/bin ${CLINGO_PATH}/build/lib)
+message("CLINGO_LIBS_DIR: " ${CLINGO_LIBS_DIR})
+link_directories(${CLINGO_LIBS_DIR})
#aux_source_directory(. TEST_FILES)
set(TEST_FILES
+# vendors/clang.cpp
+ vendors/clingo.cpp
+ vendors/llvm.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/latex.cpp b/cpp/tests/latex.cpp
index be55f08..c684754 100644
--- a/cpp/tests/latex.cpp
+++ b/cpp/tests/latex.cpp
@@ -1,358 +1,357 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*
* Author: pgess <v.melnychenko@xreate.org>
* 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 <boost/format.hpp>
#include <gtest/gtest.h>
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<details::tier1::XreateManager> 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<details::tier1::XreateManager> 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<details::tier1::XreateManager> 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<details::tier1::XreateManager> 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<Gringo::Symbol, Gringo::Symbol, string>(*decisionGS);
+ cout << decisionGS.get() << endl;
+ auto decisionTuple = man->transcend->parse<Clingo::Symbol, Clingo::Symbol, string>(*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<compilation::BasicFunctionUnit> FnImpl;
typedef LatexBruteScopeDecorator<compilation::CachedScopeDecorator<compilation::BasicCodeScopeUnit>> ScopeImpl;
std::unique_ptr<details::tier1::XreateManager> 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<CompilePass> compiler(new compilation::CompilePassCustomDecorators<FnImpl, ScopeImpl>(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<compilation::BasicFunctionUnit> FnImpl;
// typedef LatexBruteScopeDecorator<compilation::CachedScopeDecorator<compilation::BasicCodeScopeUnit>> ScopeImpl;
//
// std::unique_ptr<details::tier1::XreateManager> 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<CompilePass> compiler(new compilation::CompilePassCustomDecorators<FnImpl, ScopeImpl>(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<compilation::BasicFunctionUnit> FnImpl;
typedef LatexBruteScopeDecorator<compilation::CachedScopeDecorator<compilation::BasicCodeScopeUnit>> ScopeImpl;
std::unique_ptr<details::tier1::XreateManager> 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<CompilePass> compiler(new compilation::CompilePassCustomDecorators<FnImpl, ScopeImpl>(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<details::tier1::XreateManager> man(details::tier1::XreateManager::prepare(move(program)));
}
TEST(Latex, Doc_Examples2){
std::string program = getDocumentationExampleById("documentation/Concepts/context.xml", "Examples_2");
std::unique_ptr<details::tier1::XreateManager> man(details::tier1::XreateManager::prepare(move(program)));
}
TEST(Latex, Doc_ContextPropagation1){
std::string program =getDocumentationExampleById("documentation/Concepts/context.xml", "ContextPropagation1");
std::unique_ptr<details::tier1::XreateManager> man(details::tier1::XreateManager::prepare(move(program)));
}
TEST(Latex, Doc_ContextPropagation2){
std::string program = getDocumentationExampleById("documentation/Concepts/context.xml", "ContextPropagation2");
std::unique_ptr<details::tier1::XreateManager> 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).
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/polymorph.cpp b/cpp/tests/polymorph.cpp
index 5a930bc..aa602a5 100644
--- a/cpp/tests/polymorph.cpp
+++ b/cpp/tests/polymorph.cpp
@@ -1,160 +1,159 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*
* polymorph.cpp
*
* Author: pgess <v.melnychenko@xreate.org>
* Created on October 11, 2017, 8:37 PM
*/
#include "xreatemanager.h"
#include "ast.h"
#include "transcendlayer.h"
#include "aux/latereasoning.h"
#include <list>
#include "gtest/gtest.h"
#include "query/polymorph.h"
#include "supplemental/docutils.h"
using namespace xreate;
using namespace xreate::latereasoning;
using namespace xreate::polymorph;
using namespace std;
TEST(Polymorphs, ast1) {
xreate::XreateManager* man = xreate::XreateManager::prepare(
R"CODE(
guard:: a {
test = function:: int {0}
}
guard:: b {
test = function:: int {1}
}
main = function:: int; entry { test() }
)CODE");
const std::list<ManagedFnPtr>& specs = man->root->getFunctionSpecializations("test");
ASSERT_EQ(2, specs.size());
auto itSpecs = specs.begin();
ASSERT_EQ("a", (*itSpecs)->guard.getValueString());
itSpecs++;
ASSERT_EQ("b", (*itSpecs)->guard.getValueString());
}
TEST(Polymorphs, PolymorphQuery_Static_1) {
xreate::details::tier1::XreateManager* man = xreate::details::tier1::XreateManager::prepare(
R"CODE(
import raw("scripts/dfa/polymorphism.lp").
guard:: a {
test = function:: int {0}
}
guard:: b {
test = function:: int {1}
}
main = function:: int; entry { test()::int; callguard(b); dfa_polym(ret)}
)CODE");
man->analyse();
PolymorphQuery* query = dynamic_cast<PolymorphQuery*> (man->transcend->getQuery(QueryId::PolymorphQuery));
const Expression& bodyE = man->root->findFunction("main")->getEntryScope()->getBody();
LateAnnotation decisionLA = query->get(bodyE);
ASSERT_EQ(1, decisionLA.guardedContent.size());
auto decisionOptSymb = decisionLA.select({}, man->root, man->transcend);
ASSERT_TRUE(decisionOptSymb);
-
- decisionOptSymb->print(cout);
- cout << endl;
+
+ cout << decisionOptSymb.get() << endl;
string guard = query->getValue(*decisionOptSymb).getValueString();
ASSERT_STREQ("b", guard.c_str());
}
TEST(Polymorphs, PolymorphQuery_Late_1){
xreate::details::tier1::XreateManager* man = xreate::details::tier1::XreateManager::prepare(
R"CODE(
Late = type variant{a, b}.
main = function:: int; entry{key= a():: Late; test. key::int}
)CODE");
man->transcend->addRawScript(
R"RULE(
late(S, S, a, dfa_callguard(S, a)):-
bind(S, test).
late(S, S, b, dfa_callguard(S, b)):-
bind(S, test).
)RULE");
man->analyse();
PolymorphQuery* query = dynamic_cast<PolymorphQuery*> (man->transcend->getQuery(QueryId::PolymorphQuery));
CodeScope* scopeMain = man->root->findFunction("main")->getEntryScope();
Symbol keyS = Symbol{scopeMain->getSymbol("key"), scopeMain};
Expression keyE = scopeMain->getDefinition(keyS);
latereasoning::LateAnnotation answerLA = query->get(keyE);
Expression valueB(Operator::VARIANT, {}); valueB.setValueDouble(1);
auto answerRaw = answerLA.select({valueB}, man->root, man->transcend);
ASSERT_TRUE(answerRaw);
Expression answerE = query->getValue(*answerRaw);
ASSERT_STREQ("b", answerE.getValueString().c_str());
}
TEST(Polymorphs, PSCU_1){
auto man = details::tier1::XreateManager::prepare(R"Code(
Dom = type variant {guard1, guard2}.
guard:: guard1 {
compute = function :: int
{0}
}
guard:: guard2 {
compute = function :: int
{1}
}
test = function:: int; entry
{
xLate = guard2():: Dom.
y1= switch late (xLate:: Dom; alias(xLate)):: int
{
compute():: int; guardkey(xLate)
}.
y1
}
)Code");
man->transcend->addRawScript(R"RAW(
dom(guard1; guard2).
late(Target, Key, Variant, dfa_callguard(Target, Variant)):-
bind(Target, guardkey(Alias));
bind(Key, alias(Alias));
dom(Variant).
)RAW");
man->analyse();
int (*program)() = (int (*)())man->run();
int result = program();
ASSERT_EQ(1, result);
}
TEST(Polymorphs, Doc_FnLvlPoly_1){
string example = getDocumentationExampleById("documentation/Concepts/polymorphism.xml", "FnLvlPoly_1");
auto man = XreateManager::prepare(move(example));
ASSERT_TRUE(true);
}
TEST(Polymorphs, Doc_LatePoly_1){
string example = getDocumentationExampleById("documentation/Concepts/polymorphism.xml", "LatePoly_1");
auto man = XreateManager::prepare(move(example));
ASSERT_TRUE(true);
}
\ 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 <v.melnychenko@xreate.org>
*/
#include <pass/cfapass.h>
#include "xreatemanager.h"
#include "pass/dfapass.h"
#include "supplemental/docutils.h"
#include <boost/algorithm/string.hpp>
#include "gtest/gtest.h"
using namespace xreate;
using namespace std;
struct TestRec {
string refExample;
string refOutput;
PassId pass;
};
std::list<TestRec> 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<details::tier2::XreateManager> 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<std::string> 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..176573b 100644
--- a/cpp/tests/transcend.cpp
+++ b/cpp/tests/transcend.cpp
@@ -1,92 +1,92 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*
* Author: pgess <v.melnychenko@xreate.org>
* 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 <gtest/gtest.h>
using namespace xreate;
using namespace std;
TEST(Transcend, Parse1) {
std::string script =
R"Code(
)Code";
std::unique_ptr<details::tier1::XreateManager> 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;
+ Clingo::Symbol symbTest1 = solution.begin()->second;
auto answer1 = man->transcend->parse<list<int>>(symbTest1);
ASSERT_EQ(1, get<0>(answer1).size());
solution = man->transcend->query("test2");
- Gringo::Symbol symbTest2 = solution.begin()->second;
+ Clingo::Symbol symbTest2 = solution.begin()->second;
auto answer2 = get<0>(man->transcend->parse<list<int>>(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)";
ASSERT_NE(std::string::npos, outputActual.find(outputExpected));
-}
\ No newline at end of file
+}
diff --git a/cpp/tests/vendors/llvm.cpp b/cpp/tests/vendors/llvm.cpp
new file mode 100644
index 0000000..0bcfc74
--- /dev/null
+++ b/cpp/tests/vendors/llvm.cpp
@@ -0,0 +1,47 @@
+/* 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: llvm.cpp
+ * Author: pgess <v.melnychenko@xreate.org>
+ *
+ * Created on 05/09/2020
+ */
+
+#include <llvm/Support/TargetSelect.h>
+#include <llvm/IR/Function.h>
+#include <llvm/IR/Instructions.h>
+#include <llvm/ExecutionEngine/ExecutionEngine.h>
+
+#include <gtest/gtest.h>
+
+using namespace llvm;
+typedef int (*FnNoArgs)();
+
+TEST(Vendors, LLVM_Ver9_0_1_Basic1){
+ llvm::LLVMContext context;
+ std::unique_ptr<Module> module(new Module("test", context));
+
+ InitializeNativeTarget();
+ InitializeNativeTargetAsmPrinter();
+
+ FunctionType* fnMainT = FunctionType::get(Type::getInt32Ty(context), {}, false);
+ Function* fnMain = Function::Create(fnMainT, Function::ExternalLinkage, "main", module.get());
+
+ BasicBlock *blockEntry = BasicBlock::Create(context, "entry", fnMain);
+ ReturnInst::Create(
+ context,
+ ConstantInt::get(Type::getInt32Ty(context), 0),
+ blockEntry);
+
+ module->print(llvm::outs(), nullptr);
+
+ std::string errStr;
+ ExecutionEngine *engine =
+ EngineBuilder(std::move(module))
+ .setErrorStr(&errStr)
+ .create();
+
+ FnNoArgs fnMainRaw = (FnNoArgs) engine->getFunctionAddress("main");
+ ASSERT_EQ(0, fnMainRaw());
+}
\ No newline at end of file
diff --git a/documentation/Transcend/ast-api.xml b/documentation/Transcend/ast-api.xml
index c757ee2..f76860f 100644
--- a/documentation/Transcend/ast-api.xml
+++ b/documentation/Transcend/ast-api.xml
@@ -1,495 +1,495 @@
<?xml version="1.0" encoding="UTF-8"?>
<chapter version="5.1" xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xila="http://www.w3.org/2001/XInclude/local-attributes"
xmlns:xi="http://www.w3.org/2001/XInclude"
xmlns:trans="http://docbook.org/ns/transclusion"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:m="http://www.w3.org/1998/Math/MathML"
xmlns:html="http://www.w3.org/1999/xhtml"
xmlns:db="http://docbook.org/ns/docbook">
<title>AST API</title>
<para>In order to reason about program, code model is translated into form
suited for processing by Transcend. Translation details are described
below.</para>
<section>
<title>Expression Annotations: 'bind'</title>
<synopsis>SYNTAX:
**bind**(//symbol-ref//, //annotation//)</synopsis>
<itemizedlist>
<listitem>
<para><emphasis>symbol-ref</emphasis> reference to the expression or
identifier</para>
</listitem>
<listitem>
<para><emphasis>annotation</emphasis> expression's annotation</para>
</listitem>
</itemizedlist>
<para>Declares expression's annotations.</para>
<para>Example:</para>
<programlisting xml:id="ExprAnn_1">name="tests/transcend-ast.cpp: ASTCorrespondence.Doc_BasicTests"
test = function:: int
{
x = 5:: int; expected(even_number).
x
}</programlisting>
<para>gets translated into:</para>
- <programlisting xml:id="Output_ExprAnn_1">bind(s(1,-2,0),expected(even_number)) </programlisting>
+ <programlisting xml:id="Output_ExprAnn_1">bind(s(1,-2,0),expected(even_number))</programlisting>
</section>
<section>
<title>Code Block: 'scope'</title>
<synopsis>SYNTAX:
**scope**(//scope-ref//)</synopsis>
<itemizedlist>
<listitem>
<para><emphasis>scope-ref</emphasis> reference to the code
block</para>
</listitem>
</itemizedlist>
<para>Declares code block under its unique reference identifier.</para>
<para>Example:</para>
<programlisting xml:id="CodeBlock_1">name="tests/transcend-ast.cpp: ASTCorrespondence.Doc_BasicTests"
test = function:: float
{
x = 3:: float.
y = 8:: float.
x + y
}</programlisting>
<para>Translation result: <code
xml:id="Output_CodeBlock_1">scope(0)</code></para>
</section>
<section>
<title>Code Block Annotations: 'bind_scope'</title>
<warning>
<para>Pending syntax changes</para>
</warning>
<synopsis>SYNTAX:
**bind_scope**(//scope-ref//, //annotation//, strong) (1)
**bind_scope**(//scope-ref//, //annotation//, weak(..)) (2)
</synopsis>
<itemizedlist>
<listitem>
<para><emphasis>scope-ref</emphasis> child block's reference</para>
</listitem>
<listitem>
<para><emphasis>annotation</emphasis> code block's annotation</para>
</listitem>
</itemizedlist>
<para>Declares code block's annotations called
<emphasis>context</emphasis>. There are two forms for different context'
type:</para>
<itemizedlist>
<listitem>
<para><emphasis>strong</emphasis> context known at compile time</para>
</listitem>
<listitem>
<para><emphasis>weak</emphasis> possible context, can't be decided for
sure at compile time</para>
</listitem>
</itemizedlist>
<para>Example:</para>
<programlisting xml:id="CodeBlockAnns_1">name="tests/transcend-ast.cpp: ASTCorrespondence.Doc_BasicTests"
test = function:: float
{
context:: arithmetic(fast).
x = 3:: float.
y = 8:: float.
x + y
}</programlisting>
<para>Translation's result:</para>
<programlisting xml:id="Output_CodeBlockAnns_1">bind_scope(0,arithmetic(fast),strong)</programlisting>
</section>
<section>
<title>Code Block Bindings: 'ast_scope_binding'</title>
<synopsis>SYNTAX:
**ast_scope_binding**(//scope-ref//, //binding-id//, //binding-alias//)</synopsis>
<itemizedlist>
<listitem>
<para><emphasis>scope-ref</emphasis> code block's reference</para>
</listitem>
<listitem>
<para><emphasis>binding-id</emphasis> number of code block's
binding</para>
</listitem>
<listitem>
<para><emphasis>binding-alias</emphasis> name of a binding</para>
</listitem>
</itemizedlist>
<para>Code blocks have zero or more <emphasis>bindings</emphasis>, 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 <emphasis>binding-id</emphasis> for each
<emphasis>binding-alias.</emphasis></para>
<para>Example:</para>
<programlisting xml:id="CodeBlockBinds_1">name="tests/transcend-ast.cpp: ASTCorrespondence.Doc_BasicTests"
test = function:: int
{
loop ( 0 -&gt; acc ):: int
{
if(acc &gt; 10):: int {acc:: int; final} else {acc + 1}
}
}</programlisting>
<para>Translation result: <code
xml:id="Output_CodeBlockBinds_1">ast_scope_binding(1,0,"acc")</code></para>
</section>
<section>
<title>Code Block Parents: 'cfa_parent'</title>
<synopsis>SYNTAX:
**cfa_parent**(//scope-ref//, **scope**(//scope-parent-ref//))</synopsis>
<itemizedlist>
<listitem>
<para><emphasis>scope-ref</emphasis> child block's reference</para>
</listitem>
<listitem>
<para><emphasis>scope-parent-ref</emphasis> parent block's
reference</para>
</listitem>
</itemizedlist>
<para>Represents nested code blocks structure in terms of
<emphasis>child-parent</emphasis> relation.</para>
<para>Example:</para>
<programlisting xml:id="CodeBlockParents_1">name="tests/transcend-ast.cpp: ASTCorrespondence.Doc_BasicTests"
test = function:: int
{
x = 19:: int.
if (x&gt;5):: int {x + 1} else {x - 1}
}</programlisting>
<para>Translation's result:</para>
<programlisting xml:id="Output_CodeBlockParents_1">cfa_parent(1, scope(0)).
cfa_parent(2, scope(0)).</programlisting>
</section>
<section>
<title>Function: 'function'</title>
<synopsis>SYNTAX:
**function**(//fn-name//)</synopsis>
<itemizedlist>
<listitem>
<para><emphasis>fn-name</emphasis> function name</para>
</listitem>
</itemizedlist>
<para>Declares function identified by its name.</para>
<para>Example:</para>
<programlisting xml:id="Fn_1">name="tests/transcend-ast.cpp: ASTCorrespondence.Doc_BasicTests"
test = function:: int {0}</programlisting>
<para>Translation's result: <code
xml:id="Output_Fn_1">function(test)</code></para>
</section>
<section>
<title>Function's Annotations: 'bind_func'</title>
<synopsis>SYNTAX:
**bind_func**(//fn-name//, //annotation//)</synopsis>
<itemizedlist>
<listitem>
<para><emphasis>fn-name</emphasis> function's name</para>
</listitem>
</itemizedlist>
<para>Declares function's annotations.</para>
<para>Example:</para>
<programlisting xml:id="FnAnns_1">name="tests/transcend-ast.cpp: ASTCorrespondence.Doc_BasicTests"
test = function:: int; status(obsolete) {0}</programlisting>
<para>Translation's result: <code
xml:id="Output_FnAnns_1">bind_func(test,status(obsolete))</code></para>
</section>
<section>
<title>Function's Specialization: 'cfa_function_specializations'</title>
<synopsis>SYNTAX:
**cfa_function_specializations**(//fn-name//, //guard//)</synopsis>
<itemizedlist>
<listitem>
<para><emphasis>fn-name</emphasis> name of function</para>
</listitem>
<listitem>
<para><emphasis>guard</emphasis> specialization guard</para>
</listitem>
</itemizedlist>
<para>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 <emphasis>guard</emphasis>.</para>
<para>Example:</para>
<programlisting xml:id="FnSpecs_1">name="tests/transcend-ast.cpp: ASTCorrespondence.Doc_BasicTests"
guard:: arch(amd64)
{
test = function:: i64 {0}
}</programlisting>
<para>Translation's result: <code
xml:id="Output_FnSpecs_1">cfa_function_specializations(test,arch(amd64))</code><note>
<para>See also <link
xlink:href="/d/syntax/#function-specializations">specializations
syntax</link></para>
</note></para>
</section>
<section>
<title>Function's Entry: 'cfa_parent'</title>
<synopsis>SYNTAX:
**cfa_parent**(//scope-entry-ref//, functon(//fn-name//))</synopsis>
<itemizedlist>
<listitem>
<para><emphasis>scope-entry-ref</emphasis> function's entry code block
reference</para>
</listitem>
<listitem>
<para><emphasis>fn-name</emphasis> function's name</para>
</listitem>
</itemizedlist>
<para>Each function has a single <emphasis>entry</emphasis> code block and
is declared in terms of <emphasis>child-parent</emphasis> relation between
entry block(which is top-level in blocks hierarchy of the given function)
and the function itself.</para>
<para>Example:</para>
<programlisting xml:id="FnEntry_1">name="tests/transcend-ast.cpp: ASTCorrespondence.Doc_BasicTests"
test = function:: int {0}</programlisting>
<para>Translation's result: <code
xml:id="Output_FnEntry_1">cfa_parent(0,function(test))</code></para>
</section>
<section>
<title>Function's Result: 'dfa_fnret'</title>
<synopsis>SYNTAX:
**dfa_fnret**(//fn-name//, //symbol-ret-ref//)</synopsis>
<itemizedlist>
<listitem>
<para>symbol-ret-ref reference to a function's return
expression</para>
</listitem>
</itemizedlist>
<para>Specifies which expression is used to compute function's return
value.</para>
<para>Example:</para>
<programlisting xml:id="FnResult_1">name="tests/transcend-ast.cpp: ASTCorrespondence.Doc_BasicTests"
test = function:: int {0}</programlisting>
<para>Translation's result: <code
xml:id="Output_FnResult_1">dfa_fnret(test,s(0,-2,0))</code></para>
</section>
<section>
<title>Operations. Invocation: 'cfa_call', 'dfa_callfn',
'dfa_callargs'</title>
<synopsis>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)
</synopsis>
<itemizedlist>
<listitem>
<para><emphasis>scope-caller-ref</emphasis> caller's code block's
reference</para>
</listitem>
<listitem>
<para><emphasis>fn-callee-name</emphasis> callee function name</para>
</listitem>
<listitem>
<para><emphasis>symbol-ref</emphasis> invocation operation
reference</para>
</listitem>
<listitem>
<para><emphasis>arg-formal-name</emphasis> function's formal
argument</para>
</listitem>
<listitem>
<para><emphasis>arg-actual-ref</emphasis> actual argument
reference</para>
</listitem>
</itemizedlist>
<para>Each function invocation is transformed into several transcend facts
as explained below:</para>
<informaltable>
<tgroup cols="2">
<colspec colwidth="225*"/>
<colspec colwidth="775*"/>
<tbody>
<row>
<entry>(1) <code>cfa_call</code></entry>
<entry>Specifies caller's code block and callee function
name</entry>
</row>
<row>
<entry>(2) <code>dfa_callfn</code></entry>
<entry>Declares unique reference to a particular invocation
site.The reference used by other facts to supply additional
information</entry>
</row>
<row>
<entry>(3) <code>dfa_callargs</code></entry>
<entry>Declares assignment relations between actual arguments and
formal arguments</entry>
</row>
<row>
<entry>(4) <code>weak(dfa_callargs)</code></entry>
<entry>The same as form (3). <emphasis>Weak</emphasis> 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</entry>
</row>
</tbody>
</tgroup>
</informaltable>
<para>Example:</para>
<programlisting xml:id="OpInvoc_1">name="tests/transcend-ast.cpp: ASTCorrespondence.Doc_BasicTests"
inc = function (x::int):: int
{
x + 1
}
main = function:: int
{
arg = 10:: int.
inc(arg)
}</programlisting>
<para>After translation following transcend facts are present:</para>
<programlisting xml:id="Output_OpInvoc_1">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))</programlisting>
</section>
<section>
<title>Operations. Loops</title>
<synopsis>**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//)</synopsis>
<itemizedlist>
<listitem>
<para>symbol-source-ref input list reference</para>
</listitem>
<listitem>
<para>symbol-acc-ref accumulator reference</para>
</listitem>
<listitem>
<para>symbol-result-ref result list reference</para>
</listitem>
<listitem>
<para>loop-body-ref refers to a loop body expression</para>
</listitem>
</itemizedlist>
<para>Facts declare loop operations.</para>
<para>Example:</para>
<programlisting xml:id="OpLoops_1">name="tests/transcend-ast.cpp: ASTCorrespondence.Doc_BasicTests"
test = function:: int; entry
{
singles = {1, 2, 3}:: [int].
doubles = loop map(singles-&gt;element:: int)::[int] {2 * element}.
doubles[0]
}</programlisting>
<para>produces fact: <code
xml:id="Output_OpLoops_1">ast_op_map(s(2,-2,0),s(1,-2,0),s(0,-2,1))</code></para>
</section>
</chapter>
diff --git a/vendors/coco/generator/Copyright.frame b/vendors/coco/generator/Copyright.frame
deleted file mode 120000
index 708b5d5..0000000
--- a/vendors/coco/generator/Copyright.frame
+++ /dev/null
@@ -1 +0,0 @@
-/usr/share/coco-cpp/Copyright.frame
\ No newline at end of file
diff --git a/vendors/coco/generator/Scanner.frame b/vendors/coco/generator/Scanner.frame
deleted file mode 120000
index d1ee132..0000000
--- a/vendors/coco/generator/Scanner.frame
+++ /dev/null
@@ -1 +0,0 @@
-/usr/share/coco-cpp/Scanner.frame
\ No newline at end of file

Event Timeline