No OneTemporary

File Metadata

Created
Sun, Feb 15, 5:10 PM
This file is larger than 256 KB, so syntax highlighting was skipped.
diff --git a/cpp/src/CMakeLists.txt b/cpp/src/CMakeLists.txt
index 62be4db..44d1d1c 100644
--- a/cpp/src/CMakeLists.txt
+++ b/cpp/src/CMakeLists.txt
@@ -1,238 +1,238 @@
cmake_minimum_required(VERSION 2.8.11)
project(xreate)
cmake_policy(SET CMP0022 NEW)
message("MODULES" ${CMAKE_MODULE_PATH})
# LLVM
#======================
FIND_PACKAGE (LLVM REQUIRED)
set(LLVM_VERSION ${LLVM_VERSION_MAJOR}.${LLVM_VERSION_MINOR})
message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}")
message("LLVM LIB PATH:" ${LLVM_LIBRARY_DIRS})
message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}")
INCLUDE_DIRECTORIES(${LLVM_INCLUDE_DIRS})
message(STATUS "INCLUDE DIR: ${LLVM_INCLUDE_DIRS}")
add_definitions(${LLVM_DEFINITIONS})
message(STATUS "LLVM DEFS: " ${LLVM_DEFINITIONS})
execute_process(
COMMAND llvm-config --libs
OUTPUT_VARIABLE LLVM_LIBS
OUTPUT_STRIP_TRAILING_WHITESPACE)
message(STATUS "LLVM LIBS: " ${LLVM_LIBS})
# CLANG
#======================
set(CLANG_LIBS
clangCodeGen
clangASTMatchers
clangQuery
clangTooling
clangFrontend
clangSerialization
clangDriver
clangParse
clangSema
clangAnalysis
clangAST
clangEdit
clangLex
clangBasic
)
# POTASSCO
#======================
set(CLINGO_PATH "/opt/potassco/clingo" CACHE PATH "Path to potassco sources")
set(POTASSCO_INCLUDE_PATH
${CLINGO_PATH}/libgringo
${CLINGO_PATH}/libclasp
${CLINGO_PATH}/libclingo
${CLINGO_PATH}/libprogram_opts
${CLINGO_PATH}/liblp
)
INCLUDE_DIRECTORIES(${POTASSCO_INCLUDE_PATH})
set(LIBCLASP_LIBS
clingo
clasp
gringo
program_opts
reify
lp
)
message("CLASP LIBS: " ${LIBCLASP_LIBS})
# OTHER DEPENDENCIES
#===========================
set(JEAYESON_INCLUDE_PATH
${CMAKE_HOME_DIRECTORY}/../vendors/jeayeson/include/
)
INCLUDE_DIRECTORIES(${JEAYESON_INCLUDE_PATH})
# COCO
#===========================
set(COCO_EXECUTABLE "" CACHE PATH "Path to coco executable")
set(COCO_FRAMES_PATH "" CACHE PATH "Path to coco frames")
set(COCO_GRAMMAR_PATH ${CMAKE_HOME_DIRECTORY}/../grammar/)
set(COCO_SOURCE_FILES_MAIN
${COCO_GRAMMAR_PATH}/main/Parser.cpp
${COCO_GRAMMAR_PATH}/main/Scanner.cpp
)
set(COCO_SOURCE_FILES_MODULES
${COCO_GRAMMAR_PATH}/modules/Parser.cpp
${COCO_GRAMMAR_PATH}/modules/Scanner.cpp
)
set(COCO_SOURCE_FILES ${COCO_SOURCE_FILES_MODULES} ${COCO_SOURCE_FILES_MAIN})
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/latereasoning.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 81991bb..03afa74 100644
--- a/cpp/src/ExternLayer.cpp
+++ b/cpp/src/ExternLayer.cpp
@@ -1,337 +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>
- *
- * \file ExternLayer.h
- * \brief Support of external C code. Wrapper over Clang
*/
#include "ExternLayer.h"
#include "clang/Tooling/Tooling.h"
#include "clang/Frontend/ASTUnit.h"
#include "clang/Frontend/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 d0f0c33..0bae75e 100644
--- a/cpp/src/ExternLayer.h
+++ b/cpp/src/ExternLayer.h
@@ -1,67 +1,72 @@
/* 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/cfagraph.cpp b/cpp/src/analysis/cfagraph.cpp
index ef0c679..17639e3 100644
--- a/cpp/src/analysis/cfagraph.cpp
+++ b/cpp/src/analysis/cfagraph.cpp
@@ -1,191 +1,191 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* File: CFAGraph.cpp
* Author: pgess <v.melnychenko@xreate.org>
*
* Created on June 27, 2016, 2:09 PM
*/
/**
- * \file cfagraph.h
- * \brief Control Flow Analysis(CFA) graph data
+ * \file cfagraph.h
+ * \brief Control Flow Analysis(CFA) graph representation
*/
#include "analysis/cfagraph.h"
#include "analysis/utils.h"
using namespace xreate::cfa;
using namespace std;
void
CFAGraph::print(std::ostringstream& output) const {
const std::string& atomBinding = Config::get("transcend.bindings.function");
const std::string& atomBindingScope = Config::get("transcend.bindings.scope");
output << endl << "%\t\tStatic analysis: CFA" << endl;
output << __outputPrecomputed.str();
//show function tags
int counterTags = 0;
std::ostringstream bufFunctionNames;
boost::format formatFunction("function(%1%).");
boost::format formatBind(atomBinding + "(%1%, %2%).");
for (auto function : this->__fnNodes.left) {
const auto tags = this->__fnTags.equal_range(function.first);
if (tags.first == tags.second) {
//no tags
bufFunctionNames << "; " << function.second ;
continue;
}
output << formatFunction % (function.second) << std::endl;
for (const auto& tag_ : boost::make_iterator_range(tags)) {
const Expression& tag = tag_.second;
list<string> tagRaw = xreate::analysis::compile(tag);
assert(tagRaw.size() == 1);
output << formatBind
% (function.second)
% (tagRaw.front())
<< endl;
++counterTags;
}
}
if (bufFunctionNames.tellp()) {
output << formatFunction % (bufFunctionNames.str().substr(2)) << std::endl;
}
if (counterTags == 0) {
output << "%no function tags at all" << endl;
}
//declare scopes
boost::format formatScope("scope(0..%1%).");
output << formatScope % (__transcend->getScopesCount() - 1) << std::endl;
//show context rules:
for (auto rule : this->__contextRules) {
output << ContextRule(rule.second).compile(rule.first) << std::endl;
};
//show scope tags:
counterTags = 0;
boost::format formatScopeBind(atomBindingScope + "(%1%, %2%, strong).");
for (auto entry : this->__scopeTags) {
ScopePacked scopeId = entry.first;
const Expression& tag = entry.second;
list<string> tagRaw = xreate::analysis::compile(tag);
assert(tagRaw.size() == 1);
output << formatScopeBind % scopeId % (tagRaw.front()) << endl;
++counterTags;
}
if (counterTags == 0) {
output << "%scope tags: no tags at all" << endl;
}
//parent connections
//TOTEST CFG parent function
boost::format formatFunctionParent("cfa_parent(%1%, function(%2%)).");
for (const auto &relation : this->__parentFnRelation) {
const string& function = this->__fnNodes.left.at(relation.right);
output << formatFunctionParent % relation.left % function << endl;
}
//TOTEST CFG parent scope
boost::format formatScopeParent("cfa_parent(%1%, scope(%2%)).");
for (const auto &relation : this->__parentScopeRelation) {
output << formatScopeParent % relation.first % relation.second << endl;
}
//call connections
boost::format formatCall("cfa_call(%1%, %2%).");
for (const auto &relation : this->__callRelations) {
const ScopePacked scopeFrom = relation.left;
const string& functionTo = this->__fnNodes.left.at(relation.right);
output << formatCall % (scopeFrom) % (functionTo) << endl;
}
//function specializations description
boost::format formatSpecializations("cfa_function_specializations(%1%, %2%).");
const list<ManagedFnPtr>& functions = __transcend->ast->getAllFunctions();
for (auto f : functions) {
if (f->guard.isValid()) {
list<string> guardRaw = xreate::analysis::compile(f->guard);
assert(guardRaw.size() == 1);
output << formatSpecializations % (f->getName()) % (guardRaw.front()) << endl;
}
}
}
void
CFAGraph::addFunctionAnnotations(const std::string& fn, const std::map<std::string, Expression>& tags) {
unsigned int fid = registerNodeFunction(fn);
for (auto& tag : tags) {
__fnTags.emplace(fid, tag.second);
}
}
void
CFAGraph::addScopeAnnotations(const ScopePacked& scope, const std::vector<Expression>& tags) {
for (Expression tag : tags) {
__scopeTags.emplace(scope, tag);
}
}
void
CFAGraph::addContextRules(const ScopePacked& scope, const std::vector<Expression>& rules) {
for (Expression rule : rules) {
__contextRules.emplace(scope, rule);
}
}
void
CFAGraph::addCallConnection(const ScopePacked& callerScope, const std::string& calleeFn) {
unsigned int idFuncTo = registerNodeFunction(calleeFn);
__callRelations.insert(CALL_RELATIONS::value_type(callerScope, idFuncTo));
}
void
CFAGraph::addParentConnection(const ScopePacked& scopeEntry, const std::string& fnParent) {
__parentFnRelation.insert(PARENT_FUNCTION_RELATIONS::value_type(scopeEntry, registerNodeFunction(fnParent)));
}
void
CFAGraph::addParentConnection(const ScopePacked& scopeChild, const ScopePacked& scopeParent) {
__parentScopeRelation.emplace(scopeChild, scopeParent);
}
unsigned int
CFAGraph::registerNodeFunction(const std::string& fname) {
auto pos = __fnNodes.left.insert(make_pair(__fnNodes.size(), fname));
return pos.first->first;
}
void
CFAGraph::addScope(CodeScope* scope) {
boost::format formatScopeBinding("ast_scope_binding(%1%, %2%, \"%3%\").");
ScopePacked scopeId = __transcend->pack(scope);
__scopesCount = max(scopeId + 1, __scopesCount);
for (int id = 0, size = scope->__bindings.size(); id < size; ++id) {
__outputPrecomputed << formatScopeBinding
% scopeId
% id
% scope->__bindings.at(id)
<< endl;
}
}
diff --git a/cpp/src/analysis/cfagraph.h b/cpp/src/analysis/cfagraph.h
index 543731a..0f5fb0d 100644
--- a/cpp/src/analysis/cfagraph.h
+++ b/cpp/src/analysis/cfagraph.h
@@ -1,66 +1,67 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* File: CFAGraph.h
* Author: pgess <v.melnychenko@xreate.org>
*
* Created on June 27, 2016, 2:09 PM
*/
#ifndef CFAGRAPH_H
#define CFAGRAPH_H
#include "transcendlayer.h"
namespace xreate{
namespace cfa{
-/** \brief Represents CFA analysis data produced by CFAPass */
+/** \brief Represents CFA analysis data produced by CFAPass
+ */
class CFAGraph: public IAnalysisReport{
friend class TemporalSeqGraph;
public:
typedef boost::bimap<ScopePacked, boost::bimaps::multiset_of<unsigned int>> PARENT_FUNCTION_RELATIONS;
PARENT_FUNCTION_RELATIONS __parentFnRelation;
std::map<ScopePacked, ScopePacked> __parentScopeRelation;
typedef boost::bimap<
boost::bimaps::multiset_of<ScopePacked>,
boost::bimaps::multiset_of<unsigned int>,
boost::bimaps::set_of_relation<>
> CALL_RELATIONS;
CALL_RELATIONS __callRelations;
boost::bimap<unsigned int, std::string> __fnNodes;
std::multimap<unsigned int, Expression> __fnTags;
std::multimap<ScopePacked, Expression> __scopeTags;
std::multimap<ScopePacked, ContextRule> __contextRules;
unsigned int __scopesCount = 0;
void print(std::ostringstream &output) const override;
CFAGraph(TranscendLayer* engine): __transcend(engine){ }
void addFunctionAnnotations(const std::string &fn, const std::map<std::string, Expression> &tags);
void addScopeAnnotations(const ScopePacked &scope, const std::vector<Expression> &tags);
void addContextRules(const ScopePacked &scope, const std::vector<Expression> &rules);
void addCallConnection(const ScopePacked &callerScope, const std::string &calleeFn);
void addParentConnection(const ScopePacked &scopeEntry, const std::string &fnParent);
void addParentConnection(const ScopePacked &scopeChild, const ScopePacked &scopeParent);
void addScope(CodeScope* scope);
private:
TranscendLayer* __transcend;
std::ostringstream __outputPrecomputed;
unsigned int registerNodeFunction(const std::string &fname);
};
}
} //end of namespace xreate::cfa
#endif /* CFAGRAPH_H */
diff --git a/cpp/src/analysis/dfagraph.cpp b/cpp/src/analysis/dfagraph.cpp
index aabc49a..7eebd53 100644
--- a/cpp/src/analysis/dfagraph.cpp
+++ b/cpp/src/analysis/dfagraph.cpp
@@ -1,244 +1,244 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* File: DFAGraph.h
* Author: pgess <v.melnychenko@xreate.org>
*
*/
/**
* \file dfagraph.h
- * \brief Data Flow Analysis(DFA) graph data
+ * \brief Data Flow Analysis(DFA) graph representation
*
*/
#include "analysis/dfagraph.h"
#include "analysis/utils.h"
using namespace std;
using namespace xreate::analysis;
namespace xreate { namespace dfa {
void
DFACallInstance::print(std::ostringstream& output) const{
boost::format formatArgs;
boost::format formatInstance("dfa_callfn(%1%, %2%).");
switch (type) {
case WEAK:
formatArgs = boost::format("weak(dfa_callargs(%1%, %2%, %3%)).");
break;
case STRONG:
formatArgs = boost::format("weak(dfa_callargs(%1%, %2%, %3%)).\ndfa_callargs(%1%, %2%, %3%).");
break;
}
output << formatInstance
% analysis::writeSymbolNode(retActual)
% fnName
<< endl;
for(std::pair<SymbolPacked, SymbolNode> rec: args) {
SymbolNode argFormal(rec.first);
output << formatArgs
% analysis::writeSymbolNode(retActual)
% analysis::writeSymbolNode(argFormal)
% analysis::writeSymbolNode(rec.second)
<< endl;
}
}
void
DFAGraph::addDependency(const SymbolNode& node, const SymbolNode& subnode){
__dependencies.emplace(node, subnode);
if (boost::get<SymbolPacked>(&node)){
__usedSymbols.insert(node);
}
if (boost::get<SymbolPacked>(&subnode)){
__usedSymbols.insert(node);
}
}
void
DFAGraph::printDependencies(std::ostringstream& output) const{
for(const SymbolNode& root: __roots){
printDependency(output, root, root);
}
}
void
DFAGraph::printDependency(std::ostringstream& output, const SymbolNode& nodeCurrent, const SymbolNode& nodeDependent) const {
auto range = __dependencies.equal_range(nodeCurrent);
for (auto it = range.first; it != range.second; ++it){
if (boost::get<SymbolAnonymous>(&it->second)){
if (!__usedSymbols.count(it->second)){
printDependency(output, it->second, nodeDependent);
continue;
}
}
boost::format formatDependency("dfa_depends(%1%, %2%).");
output << formatDependency
% analysis::writeSymbolNode(nodeDependent)
% analysis::writeSymbolNode(it->second)
<< endl;
printDependency(output, it->second, it->second);
}
}
void
DFAGraph::printInplaceAnnotation(const SymbolNode& node, const Expression& expression) {
// write down in-place expression tags:
boost::format formatBind("bind(%1%, %2%).");
__usedSymbols.insert(node);
for (const string& tag: xreate::analysis::compile(expression)) {
__output << formatBind
% analysis::writeSymbolNode(node)
% tag
<< endl;
}
}
void
DFAGraph::printLateAnnotation(const SymbolNode& node,
const Expression& expression,
const std::list<latereasoning::LateParameter>& symbols,
const std::list<std::string>& domains){
boost::format formatLateAnnotation("late(%1%, (%2%), (%3%), %4%):- %5%.");
boost::format formatDom("%1%(%2%)");
std::list<std::string> exprSerialized = xreate::analysis::compile(expression);
assert(exprSerialized.size() == 1);
list<string> identSymbols, identNames, domainsSerialised;
auto domainI = domains.begin();
for(auto symbol: symbols){
identSymbols.push_back(analysis::writeSymbolNode(symbol.second).str());
identNames.push_back(symbol.first);
domainsSerialised.push_back((formatDom % *domainI % symbol.first).str());
++domainI;
}
__output << formatLateAnnotation
% analysis::writeSymbolNode(node)
% boost::algorithm::join(identSymbols, ", ")
% boost::algorithm::join(identNames, ", ")
% exprSerialized.front()
% boost::algorithm::join(domainsSerialised, "; ")
<< endl;
}
void
DFAGraph::printAlias(const SymbolNode& symbFormal, const SymbolNode& symbActual){
__usedSymbols.insert(symbFormal); __usedSymbols.insert(symbActual);
boost::format formatAlias("dfa_alias(%1%, %2%).");
__output << formatAlias
% analysis::writeSymbolNode(symbFormal)
% analysis::writeSymbolNode(symbActual)
<< endl;
}
void
DFAGraph::printWeakAlias(const SymbolNode& symbFormal, const SymbolNode& symbActual){
__usedSymbols.insert(symbFormal); __usedSymbols.insert(symbActual);
boost::format formatAlias("weak(dfa_alias(%1%, %2%)).");
__output << formatAlias
% analysis::writeSymbolNode(symbFormal)
% analysis::writeSymbolNode(symbActual)
<< endl;
}
void
DFAGraph::printFunctionRet(ManagedFnPtr function, const SymbolNode& symbolRet){
boost::format formatRet("dfa_fnret(%1%, %2%).");
__usedSymbols.insert(symbolRet);
__output << formatRet
% function->getName()
% analysis::writeSymbolNode(symbolRet)
<< endl;
__roots.insert(symbolRet);
}
void
DFAGraph::addCallInstance(DFACallInstance&& instance){
__usedSymbols.insert(instance.retActual);
for(const auto arg: instance.args){
__usedSymbols.insert(SymbolNode(arg.first));
__usedSymbols.insert(arg.second);
}
__callInstances.push_back(std::move(instance));
}
void
DFAGraph::print(std::ostringstream& output) const{
output << endl << "%\t\tStatic analysis: DFA" << endl;
//Dependencies
printDependencies(output);
//Add generated report
output << __output.str() << endl;
//Call instances
for(const DFACallInstance& instance: __callInstances){
instance.print(output);
}
output << endl;
}
void
DFAGraph::printSymbols(TranscendLayer* transcend){
boost::format formatHint("shint(%1%, \"%2%\").");
for (const SymbolNode& node : __usedSymbols) {
__output << "v(" << analysis::writeSymbolNode(node) << "). ";
if (const SymbolPacked* symbol = boost::get<SymbolPacked>(&node)){
__output << formatHint % analysis::writeSymbolNode(node) % transcend->getHintForPackedSymbol(*symbol);
}
__output << endl;
}
}
void
DFAGraph::printOperator(Operator op, std::list<SymbolNode>&& operands, int dataOpListSize){
std::string opStr;
switch(op){
case Operator::MAP: opStr = "map"; break;
case Operator::FOLD: opStr = "fold"; break;
case Operator::LIST: opStr = "list"; break;
case Operator::LIST_RANGE: opStr = "list_range"; break;
case Operator::INDEX: opStr = "index"; break;
default: assert(false);
}
std::ostringstream bufOperands;
for(const SymbolNode& operand: operands){
__usedSymbols.insert(operand);
bufOperands << analysis::writeSymbolNode(operand) << ", ";
}
if(op == Operator::LIST){
bufOperands << dataOpListSize << ", ";
}
boost::format formatOperator("ast_op_%1%(%2%).");
__output << (formatOperator % opStr % bufOperands.str().substr(0, bufOperands.str().size() - 2)) << endl;
}
}} //end of namespace xreate::dfa
diff --git a/cpp/src/analysis/dfagraph.h b/cpp/src/analysis/dfagraph.h
index d8817b0..c1ec4db 100644
--- a/cpp/src/analysis/dfagraph.h
+++ b/cpp/src/analysis/dfagraph.h
@@ -1,66 +1,66 @@
/* 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: dfa.h
* Author: pgess <v.melnychenko@xreate.org>
*
* Created on June 27, 2016, 1:50 PM
*/
#ifndef DFA_H
#define DFA_H
#include "transcendlayer.h"
#include <unordered_set>
namespace xreate { namespace latereasoning {
typedef std::pair<std::string, SymbolPacked> LateParameter;
}}
namespace xreate {namespace dfa {
enum DFACallInstanceType {
STRONG, WEAK
};
class DFACallInstance {
public:
std::string fnName;
std::vector<std::pair<SymbolPacked, SymbolNode>> args;
SymbolNode retActual;
DFACallInstanceType type;
void print(std::ostringstream& output) const;
};
-/** \brief Holds DFA Analysis report produced by DFAPass */
+/** \brief Represents DFA Analysis report produced by DFAPass */
class DFAGraph : public IAnalysisReport {
public:
// DFAGraph(TranscendLayer* engine): __transcend(engine){}
virtual void print(std::ostringstream& output) const override;
void addCallInstance(DFACallInstance && instance);
void addDependency(const SymbolNode& node, const SymbolNode& subnodeBlock);
void printInplaceAnnotation(const SymbolNode& node, const Expression& expression);
void printLateAnnotation(const SymbolNode& node, const Expression& expression,
const std::list<latereasoning::LateParameter>& symbols,
const std::list<std::string>& domains);
void printAlias(const SymbolNode& symbFormal, const SymbolNode& symbActual);
void printWeakAlias(const SymbolNode& symbFormal, const SymbolNode& symbActual);
void printFunctionRet(ManagedFnPtr function, const SymbolNode& symbolRet);
void printDependencies(std::ostringstream& output) const;
void printSymbols(TranscendLayer* transcend);
void printOperator(Operator, std::list<SymbolNode>&& operands, int dataOpListSize = 0);
private:
mutable std::ostringstream __output;
std::list<DFACallInstance> __callInstances;
std::unordered_multimap<SymbolNode, SymbolNode> __dependencies;
std::unordered_set<SymbolNode> __usedSymbols;
std::unordered_set<SymbolNode> __roots;
void printDependency(std::ostringstream& output, const SymbolNode& nodeCurrent, const SymbolNode& nodeDependent) const;
};
}} // end of namespace xreate::dfa
#endif /* DFA_H */
diff --git a/cpp/src/analysis/interpretation.cpp b/cpp/src/analysis/interpretation.cpp
index b841a8e..7c18b4e 100644
--- a/cpp/src/analysis/interpretation.cpp
+++ b/cpp/src/analysis/interpretation.cpp
@@ -1,274 +1,269 @@
/*
* 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
- *
- * \file interpretation.cpp
- * \brief interpretation
*/
#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;
TypeAnnotation resultT;
resultT.__operands.reserve(operandsCount);
for(size_t operandId = 0; operandId < operandsCount; ++operandId) {
std::list<Gringo::Symbol> column;
for(const Gringo::Symbol& row : symbols) {
column.push_back(row.args()[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) {
TypeAnnotation resultT;
if(!symbols.size()) return resultT;
Gringo::Symbol symbolAny = symbols.front();
switch(symbolAny.type()) {
case Gringo::SymbolType::Num:
{
return TypeAnnotation(TypePrimitive::Num);
}
case Gringo::SymbolType::Str:
{
return TypeAnnotation(TypePrimitive::String);
}
case Gringo::SymbolType::Fun:
{
map<string, list < Gringo::Symbol>> fnGroups;
for(const Gringo::Symbol& row : symbols) {
fnGroups[row.name().c_str()].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();
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:
{
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;
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;
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()));
}
case TypePrimitive::String:
{
return Expression(Atom<String_t>(atom.string().c_str()));
}
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();
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));
}
return result;
}
case TypeOperator::LIST_RECORD:
{
const Gringo::SymSpan& operandsRaw = atom.args();
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 7716eb8..8a93e17 100644
--- a/cpp/src/analysis/interpretation.h
+++ b/cpp/src/analysis/interpretation.h
@@ -1,31 +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
+ */
+
+/**
+ * \file interpretation.h
+ * \brief Interpretation related functions
*/
#ifndef INTERPRETATION_H
#define INTERPRETATION_H
#include "transcendlayer.h"
-namespace xreate{
-namespace interpretation{
+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);
-TypeAnnotation collapseColumn(const std::list<Gringo::Symbol>& symbols);
-ExpandedType dereferenceSlaveType(ExpandedType t, const TranscendLayer* transcend);
-Expression representTransExpression(const Gringo::Symbol& atom, ExpandedType schemaT, TranscendLayer* transcend);
-std::list<Expression> generateAllInstancesInDomain2(const ExpandedType& domainT);
+ /**
+ * \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);
+ std::list<Expression> generateAllInstancesInDomain2(const ExpandedType& domainT);
}
}
#endif /* INTERPRETATION_H */
diff --git a/cpp/src/analysis/temporalseqgraph.h b/cpp/src/analysis/temporalseqgraph.h
index c3672ec..14b88ec 100644
--- a/cpp/src/analysis/temporalseqgraph.h
+++ b/cpp/src/analysis/temporalseqgraph.h
@@ -1,77 +1,85 @@
/* 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: temporalseqgraph.h
* Author: pgess
*
* Created on February 4, 2019, 4:51 PM
*/
+/**
+ * \file temporalseqgraph.h
+ * \brief Execution Order Graph representation
+ */
+
#ifndef TEMPORALSEQGRAPH_H
#define TEMPORALSEQGRAPH_H
#include "transcendlayer.h"
namespace xreate{ namespace cfa{
enum TemporalOperator {SCOPE, EMPTY, AND, OR};
struct TemporalNode{
ScopePacked scope;
TemporalOperator mark;
friend std::ostream& operator << (std::ostream& output, const TemporalNode& node);
bool operator==(const TemporalNode& other) const
{ return other.scope == scope && other.mark == mark; }
};
struct TemporalGuard{
enum{IN, OUT} mark;
unsigned int id;
};
typedef std::pair<TemporalNode, TemporalNode> Socket;
}} namespace std {
bool operator<(const xreate::cfa::TemporalNode& x, const xreate::cfa::TemporalNode& y);
} namespace xreate {namespace cfa {
-
+
+/**
+ * \brief Execution order graph representation. Produced by CFATemporalSeqPass
+ */
class TemporalSeqGraph: public IAnalysisReport{
typedef boost::bimap<
boost::bimaps::multiset_of<TemporalNode>,
boost::bimaps::multiset_of<TemporalNode>> Graph;
public:
TemporalSeqGraph(TranscendLayer* transcend);
void addSubScopes(const CodeScope*, const std::list<CodeScope*>&);
void addBranchScopes(const CodeScope*, const std::list<CodeScope*>&);
Socket addSocket(const CodeScope*, TemporalOperator mark);
TemporalNode insertBefore(TemporalNode node, TemporalOperator mark);
TemporalNode insertAfter(TemporalNode node, TemporalOperator mark);
void connect(TemporalNode, TemporalNode);
void connectGuarded(const Socket& from, const Socket& to);
Socket getFnSocket(ManagedFnPtr calleeFn);
Socket getUncertainFnSocket(const std::string& calleeName, const std::list<ManagedFnPtr>& candidates);
bool isOrdered(const ScopePacked& scopeAfter, const ScopePacked& scopeBefore) const;
bool isOrdered(const TemporalNode& nodeAfter, const TemporalNode& nodeBefore, std::set<TemporalNode>&) const;
void print(std::ostringstream &output) const override;
private:
Graph graph;
std::multimap<TemporalNode, std::pair<TemporalNode, TemporalGuard>> graphGuarded;
ScopePacked __idNextVacant = 0;
unsigned int __guardNextVacant = 0;
TranscendLayer* __transcend;
std::map<ManagedFnPtr, Socket> __cacheFnSockets;
std::map<std::string, Socket> __cacheUncertainFnSockets;
};
}
} //end of namespace xreate::cfa
#endif /* TEMPORALSEQGRAPH_H */
diff --git a/cpp/src/analysis/typeinference.cpp b/cpp/src/analysis/typeinference.cpp
index 3583aca..c6d2b5a 100644
--- a/cpp/src/analysis/typeinference.cpp
+++ b/cpp/src/analysis/typeinference.cpp
@@ -1,87 +1,98 @@
/* 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/.
*
* typeinference.cpp
*
* Author: pgess <v.melnychenko@xreate.org>
* Created on April 16, 2017, 10:13 AM
*/
/**
* \file typeinference.h
* \brief Type inference analysis
*/
#include "typeinference.h"
#include "llvmlayer.h"
#include "transcendlayer.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/DerivedTypes.h"
using namespace std;
namespace xreate{
namespace typeinference{
//TODO type conversion:
//a) automatically expand types int -> bigger int; int -> floating
//b) detect exact type of `num` based on max used numeral / function type
//c) warning if need to truncate (allow/dissallow based on annotations)
-
+
llvm::Value*
doAutomaticTypeConversion(llvm::Value* source, llvm::Type* tyTarget, llvm::IRBuilder<>& builder) {
if(tyTarget->isIntegerTy() && source->getType()->isIntegerTy()) {
llvm::IntegerType* tyTargetInt = llvm::dyn_cast<llvm::IntegerType>(tyTarget);
llvm::IntegerType* tySourceInt = llvm::dyn_cast<llvm::IntegerType>(source->getType());
if(tyTargetInt->getBitWidth() < tySourceInt->getBitWidth()) {
return builder.CreateCast(llvm::Instruction::Trunc, source, tyTarget);
}
if(tyTargetInt->getBitWidth() > tySourceInt->getBitWidth()) {
return builder.CreateCast(llvm::Instruction::SExt, source, tyTarget);
}
}
if(source->getType()->isIntegerTy() && tyTarget->isFloatingPointTy()) {
return builder.CreateCast(llvm::Instruction::SIToFP, source, tyTarget);
}
if (source->getType()->isStructTy() && tyTarget->isIntegerTy()){
llvm::StructType* sourceST = llvm::cast<llvm::StructType>(source->getType());
if(sourceST->getNumElements() == 1) {
llvm::Value* sourceElRaw = builder.CreateExtractValue(source, llvm::ArrayRef<unsigned>({0}));
return doAutomaticTypeConversion(sourceElRaw, tyTarget, builder);
}
}
return source;
}
+/**
+ * \brief Performs basic type inference to deduce the type of the given expression
+ *
+ * Tries several strategies in the following order:
+ * - Looks at expression's type if it has one.
+ * - Looks at Attachment<TypeInferred> if it has one. This allows assign expression's type by analyses done elsewhere.
+ * - For a number literal assumes i32.
+ *
+ * \param expression Infers the given expression's type.
+ * \param ast AST instance.
+ */
ExpandedType
getType(const Expression& expression, const AST& ast) {
if(expression.type.isValid()) {
return ast.expandType(expression.type);
}
if(expression.__state == Expression::IDENT) {
Symbol s = Attachments::get<IdentifierSymbol>(expression);
return getType(CodeScope::getDefinition(s), ast);
}
if(Attachments::exists<TypeInferred>(expression)) {
return Attachments::get<TypeInferred>(expression);
}
if(expression.__state == Expression::NUMBER) {
return ExpandedType(TypeAnnotation(TypePrimitive::I32));
}
assert(false && "Type can't be determined for an expression");
}
}
} //end of namespace xreate::typeinference
diff --git a/cpp/src/analysis/typeinference.h b/cpp/src/analysis/typeinference.h
index df6ce78..1990995 100644
--- a/cpp/src/analysis/typeinference.h
+++ b/cpp/src/analysis/typeinference.h
@@ -1,31 +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/.
*
* File: typeinference.h
* Author: pgess <v.melnychenko@xreate.org>
*
* Created on April 16, 2017, 10:17 AM
*/
#ifndef TYPEINFERENCE_H
#define TYPEINFERENCE_H
#include "ast.h"
#include "llvm/IR/IRBuilder.h"
namespace llvm{
class Value;
class Type;
};
-namespace xreate{
-namespace typeinference{
+namespace xreate{ namespace typeinference{
+/**
+ * \brief Casts the given variable to the given type
+ * \param source The variable that needs casting
+ * \param tyTarget The type to cast to
+ * \param builder Instance of llvm's IRBuilder
+ */
llvm::Value* doAutomaticTypeConversion(llvm::Value* source, llvm::Type* tyTarget, llvm::IRBuilder<>& builder);
ExpandedType getType(const Expression& expression, const AST& ast);
}
}//namespace xreate::typeinference
#endif /* TYPEINFERENCE_H */
diff --git a/cpp/src/analysis/utils.cpp b/cpp/src/analysis/utils.cpp
index 471e24d..1d8df75 100644
--- a/cpp/src/analysis/utils.cpp
+++ b/cpp/src/analysis/utils.cpp
@@ -1,159 +1,159 @@
/* 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/.
*
* aux.cpp
*
* Author: pgess <v.melnychenko@xreate.org>
*/
/**
- * \file aux.h
- * \brief Data representation in ASP format ready for use by reasoner
+ * \file src/analysis/utils.h
+ * \brief Various reasoning related utilities
*/
#include "utils.h"
#include <boost/format.hpp>
-namespace xreate { namespace analysis {
-
using namespace std;
-list<string>
-multiplyLists(list<list<string>> &&lists) {
- typedef list<string> StringList;
- assert(lists.size());
- StringList result(*lists.begin());
- lists.pop_front();
-
- boost::format concat("%s, %s");
- for (StringList &list: lists) {
- StringList::const_iterator end = result.end();
- for (StringList::iterator expr1I = result.begin(); expr1I != end; ++expr1I) {
- if (list.size() == 0) continue;
-
- StringList::const_iterator expr2I = list.begin();
- for (int expr2No = 0, size = list.size() - 1; expr2No < size; ++expr2No, ++expr1I)
- result.push_back(str(concat %(*expr1I) %(*expr2I)));
-
- *expr1I = str(concat %(*expr1I) %(*expr2I));
- }
- }
-
- return result;
-}
+namespace xreate { namespace analysis {
std::list<std::string>
compile(const Expression &e){
list<string> result;
switch (e.op) {
case Operator::CALL: {
if(!e.operands.size()){
result.push_back(e.getValueString());
break;
}
std::list<list<string>> operands;
std::transform(e.operands.begin(), e.operands.end(), std::inserter(operands, operands.begin()),
[](const Expression &e) {
return compile(e);
});
list<string> &&operands_ = multiplyLists(std::move(operands));
result.push_back(boost::str(boost::format("%1%(%2%)") % (e.getValueString()) % (boost::algorithm::join(operands_, ", "))));
break;
}
case Operator::NEG: {
assert(e.operands.size() == 1);
const Expression &op = e.operands.at(0);
list<string> &&rawOp = compile(op);
assert(rawOp.size() == 1);
result.push_back((boost::format("not %1%")%(rawOp.front())).str());
break;
};
case Operator::INVALID: {
switch (e.__state) {
case Expression::IDENT:
result.push_back(e.getValueString());
break;
case Expression::NUMBER:
result.push_back(to_string(e.getValueDouble()));
break;
default:
assert(true);
}
break;
}
default: break;
}
assert(result.size());
return result;
}
+list<string>
+multiplyLists(list<list<string>> &&lists) {
+ typedef list<string> StringList;
+ assert(lists.size());
+ StringList result(*lists.begin());
+ lists.pop_front();
+
+ boost::format concat("%s, %s");
+ for (StringList &list: lists) {
+ StringList::const_iterator end = result.end();
+ for (StringList::iterator expr1I = result.begin(); expr1I != end; ++expr1I) {
+ if (list.size() == 0) continue;
+
+ StringList::const_iterator expr2I = list.begin();
+ for (int expr2No = 0, size = list.size() - 1; expr2No < size; ++expr2No, ++expr1I)
+ result.push_back(str(concat %(*expr1I) %(*expr2I)));
+
+ *expr1I = str(concat %(*expr1I) %(*expr2I));
+ }
+ }
+
+ return result;
+}
+
std::list<std::string>
compileNeg(const Expression &e){
list<string> result;
switch (e.op) {
case Operator::IMPL: {
assert(e.__state == Expression::COMPOUND);
assert(e.operands.size() == 2);
list<string> operands1 = compile(e.operands.at(0));
list<string> operands2 = compile(e.operands.at(1));
boost::format formatNeg("%1%, not %2%");
for (const auto &op1: operands1)
for (const auto &op2: operands2) {
result.push_back(boost::str(formatNeg %(op1) % (op2)));
}
break;
}
case Operator::NEG: {
assert(e.operands.size() == 1);
const Expression &op = e.operands.at(0);
list<string> &&rawOp = compile(op);
assert(rawOp.size() == 1);
result.push_back(rawOp.front());
break;
};
default:
assert(true);
}
return result;
}
//NOTE: Any changes should be reflected in ParseImplAtom<SymbolPacked>,
// ParseImplAtom<SymbolNode>
class VisitorFormatSymbol: public boost::static_visitor<boost::format> {
public:
boost::format operator()(const SymbolPacked& node) const {
boost::format formatSymbNamed("s(%1%,%2%,%3%)");
return formatSymbNamed % node.identifier % node.version % node.scope ;
}
boost::format operator()(const SymbolAnonymous& node) const {
boost::format formatSymbAnonymous("a(%1%)");
return formatSymbAnonymous % node.id;
}
};
boost::format writeSymbolNode(const SymbolNode& symbol){
return boost::apply_visitor(VisitorFormatSymbol(), symbol);
}
}} //end of xreate::analysis
diff --git a/cpp/src/analysis/utils.h b/cpp/src/analysis/utils.h
index 70c2dc1..82c325b 100644
--- a/cpp/src/analysis/utils.h
+++ b/cpp/src/analysis/utils.h
@@ -1,31 +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/.
*
* File: aux.h
* Author: pgess <v.melnychenko@xreate.org>
*
* Created on June 26, 2016, 6:49 PM
*/
#ifndef AUX_H
#define AUX_H
#include "ast.h"
#include "transcendlayer.h"
#include <list>
#include <boost/format.hpp>
namespace xreate { namespace analysis {
+/**
+ * \brief Compiles Xreate expression into ASP format recognizable by an external ASP solver.
+ * @param e expression
+ * @return textual expression's representation in an ASP format.
+ */
std::list<std::string> compile(const Expression &e);
std::list<std::string> compileNeg(const Expression &e);
std::list<std::string> multiplyLists(std::list<std::list<std::string>> &&lists);
boost::format writeSymbolNode(const SymbolNode& symbol);
}} //end of xreate::analysis
#endif /* AUX_H */
diff --git a/cpp/src/ast.cpp b/cpp/src/ast.cpp
index 8b1cf6a..2c24707 100644
--- a/cpp/src/ast.cpp
+++ b/cpp/src/ast.cpp
@@ -1,977 +1,971 @@
/* 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: ast.cpp
*/
-/**
- * \file ast.h
- * \brief Syntax Tree and related code
- *
- * \sa xreate::AST
- */
-
#include "ast.h"
#include "ExternLayer.h"
#include "analysis/typeinference.h"
#include <stdexcept>
#include <iostream>
//TODO BDecl. forbid multiple body declaration (ExprTyped)
namespace std {
std::size_t
hash<xreate::ScopedSymbol>::operator()(xreate::ScopedSymbol const& s) const {
return s.id ^ (s.version << 2);
}
bool
equal_to<xreate::ScopedSymbol>::operator()(const xreate::ScopedSymbol& __x, const xreate::ScopedSymbol& __y) const {
return __x.id == __y.id && __x.version == __y.version;
}
size_t
hash<xreate::Symbol>::operator()(xreate::Symbol const& s) const {
return hash<xreate::ScopedSymbol>()(s.identifier) ^ ((long int) s.scope << 1);
}
bool
equal_to<xreate::Symbol>::operator()(const xreate::Symbol& __x, const xreate::Symbol& __y) const {
return __x == __y;
};
}
using namespace std;
namespace xreate {
Atom<Identifier_t>::Atom(const std::wstring& value) {
__value = wstring_to_utf8(value);
}
Atom<Identifier_t>::Atom(std::string && name) : __value(name) {
}
const std::string&
Atom<Identifier_t>::get() const {
return __value;
}
Atom<Number_t>::Atom(wchar_t* value) {
//DEBT reconsider number literal recognition
__value = wcstol(value, 0, 10);
}
Atom<Number_t>::Atom(int value)
: __value(value) {
}
double
Atom<Number_t>::get()const {
return __value;
}
Atom<String_t>::Atom(const std::wstring& value) {
assert(value.size() >= 2);
__value = wstring_to_utf8(value.substr(1, value.size() - 2));
}
Atom<String_t>::Atom(std::string && name) : __value(name) {}
const std::string&
Atom<String_t>::get() const {
return __value;
}
+/** \brief xreate::Expression static information*/
class ExpressionHints {
public:
static bool
isStringValueValid(const Expression& e) {
switch (e.__state) {
case Expression::INVALID:
assert(false);
case Expression::IDENT:
case Expression::STRING:
return true;
case Expression::NUMBER:
case Expression::BINDING:
return false;
case Expression::COMPOUND:
{
switch (e.op) {
case Operator::CALL:
return true;
default: return false;
}
}
}
return false;
}
static bool
isDoubleValueValid(const Expression& e) {
switch (e.__state) {
case Expression::NUMBER:
return true;
case Expression::INVALID:
assert(false);
case Expression::IDENT:
case Expression::STRING:
case Expression::BINDING:
return false;
case Expression::COMPOUND: {
switch (e.op) {
case Operator::VARIANT:
return true;
default: return false;
}
}
}
return false;
}
};
class TypesResolver {
private:
const AST* ast;
std::map<std::string, TypeAnnotation> scope;
std::map<TypeAnnotation, int> signatures;
ExpandedType expandType(const TypeAnnotation &t, const std::vector<TypeAnnotation> &args = std::vector<TypeAnnotation>()) {
return TypesResolver(ast, scope, signatures)(t, args);
}
std::vector<TypeAnnotation>
expandOperands(const std::vector<TypeAnnotation>& operands) {
std::vector<TypeAnnotation> pack;
pack.reserve(operands.size());
std::transform(operands.begin(), operands.end(), std::inserter(pack, pack.end()),
[this](const TypeAnnotation & t) {
return expandType(t);
});
return pack;
}
public:
TypesResolver(const AST* root, const std::map<std::string, TypeAnnotation>& scopeOuter = std::map<std::string, TypeAnnotation>(),
std::map<TypeAnnotation, int> signaturesOuter = std::map<TypeAnnotation, int>())
: ast(root), scope(scopeOuter), signatures(signaturesOuter) {
}
ExpandedType
operator()(const TypeAnnotation &t, const std::vector<TypeAnnotation> &args = std::vector<TypeAnnotation>()) {
//assert(args.size() == t.bindings.size()); // invalid number of arguments
for (size_t i = 0; i < args.size(); ++i) {
scope[t.bindings.at(i)] = args.at(i);
}
switch (t.__operator) {
case TypeOperator::LIST_ARRAY:
{
assert(t.__operands.size() == 1);
Expanded<TypeAnnotation> elTy = expandType(t.__operands.at(0));
return ExpandedType(TypeAnnotation(tag_array, elTy, 0));
}
case TypeOperator::LIST_RECORD:
{
std::vector<TypeAnnotation>&& packOperands = expandOperands(t.__operands);
auto typNew = TypeAnnotation(TypeOperator::LIST_RECORD, move(packOperands));
typNew.fields = t.fields;
return ExpandedType(move(typNew));
};
case TypeOperator::VARIANT:
{
std::vector<TypeAnnotation>&& packOperands = expandOperands(t.__operands);
auto typNew = TypeAnnotation(TypeOperator::VARIANT, move(packOperands));
typNew.fields = t.fields;
return ExpandedType(move(typNew));
};
case TypeOperator::CALL:
{
std::string alias = t.__valueCustom;
//find in local scope:
TypeAnnotation ty;
if (scope.count(alias)) {
ty = scope.at(alias);
} else if (ast->__indexTypeAliases.count(alias)) {
ty = ast->__indexTypeAliases.at(alias);
} else {
assert(false && "Undefined or external type");
}
std::vector<TypeAnnotation>&& operands = expandOperands(t.__operands);
TypeAnnotation signature(TypeOperator::CALL, move(operands));
signature.__valueCustom = alias;
if (signatures.count(signature)) {
auto link = TypeAnnotation(TypeOperator::LINK,{});
link.conjuctionId = signatures.at(signature);
return ExpandedType(move(link));
}
int cid = signatures.size();
signatures[signature] = cid;
TypeAnnotation tyResult = expandType(ty, operands);
tyResult.conjuctionId = cid;
return ExpandedType(move(tyResult));
};
case TypeOperator::CUSTOM:
{
if (signatures.count(t)) {
return ExpandedType(TypeAnnotation(TypeOperator::LINK, {t}));
}
signatures.emplace(t, signatures.size());
std::string alias = t.__valueCustom;
//find in local scope:
if (scope.count(alias)) {
return expandType(scope.at(alias));
}
//find in general scope:
if (ast->__indexTypeAliases.count(alias)) {
return expandType(ast->__indexTypeAliases.at(t.__valueCustom));
}
//if type is unknown keep it as is.
return ExpandedType(TypeAnnotation(t));
};
case TypeOperator::ACCESS:
{
std::string alias = t.__valueCustom;
ExpandedType tyAlias = ExpandedType(TypeAnnotation());
//Find in local scope:
if (scope.count(alias)) {
tyAlias = expandType(scope.at(alias));
//Find in global scope:
} else if ((ast->__indexTypeAliases.count(alias))) {
tyAlias = expandType(ast->__indexTypeAliases.at(alias));
} else {
assert(false && "Undefined or external type");
}
assert(tyAlias->__operator == TypeOperator::LIST_RECORD);
for (const string& field : t.fields) {
auto fieldIt = std::find(tyAlias->fields.begin(), tyAlias->fields.end(), field);
assert(fieldIt != tyAlias->fields.end() && "unknown field");
int fieldId = fieldIt - tyAlias->fields.begin();
tyAlias = expandType(tyAlias->__operands.at(fieldId));
}
return tyAlias;
}
case TypeOperator::NONE:
{
return ExpandedType(TypeAnnotation(t));
}
case TypeOperator::SLAVE:
{
return ExpandedType(t);
}
default:
assert(false);
}
assert(false);
return ExpandedType(TypeAnnotation());
}
};
TypeAnnotation::TypeAnnotation()
: __operator(TypeOperator::NONE), __value(TypePrimitive::Invalid) {
}
TypeAnnotation::TypeAnnotation(TypePrimitive typ)
: __value(typ) {
}
TypeAnnotation::TypeAnnotation(TypeOperator op, std::initializer_list<TypeAnnotation> operands)
: __operator(op), __operands(operands) {
}
TypeAnnotation::TypeAnnotation(TypeOperator op, std::vector<TypeAnnotation>&& operands)
: __operator(op), __operands(operands) {
}
TypeAnnotation::TypeAnnotation(llvm_array_tag, TypeAnnotation typ, int size)
: TypeAnnotation(TypeOperator::LIST_ARRAY,{typ}) {
__size = size;
}
bool
TypeAnnotation::isValid() const {
return !(__value == TypePrimitive::Invalid && __operator == TypeOperator::NONE);
}
bool
TypeAnnotation::operator<(const TypeAnnotation& t) const {
if (__operator != t.__operator) return __operator < t.__operator;
if (__operator == TypeOperator::NONE)
return __value < t.__value;
if (__operator == TypeOperator::CALL || __operator == TypeOperator::CUSTOM || __operator == TypeOperator::ACCESS) {
if (__valueCustom != t.__valueCustom)
return __valueCustom < t.__valueCustom;
}
return __operands < t.__operands;
}
/*
TypeAnnotation (struct_tag, std::initializer_list<TypeAnnotation>)
{}
*/
void
TypeAnnotation::addBindings(std::vector<Atom<Identifier_t>>&& params) {
bindings.reserve(bindings.size() + params.size());
std::transform(params.begin(), params.end(), std::inserter(bindings, bindings.end()),
[](const Atom<Identifier_t>& ident) {
return ident.get(); });
}
void
TypeAnnotation::addFields(std::vector<Atom<Identifier_t>>&& listFields) {
fields.reserve(fields.size() + listFields.size());
std::transform(listFields.begin(), listFields.end(), std::inserter(fields, fields.end()),
[](const Atom<Identifier_t>& ident) {
return ident.get(); });
}
unsigned int Expression::nextVacantId = 0;
Expression::Expression(const Atom<Number_t>& number)
: Expression() {
__state = NUMBER;
op = Operator::INVALID;
__valueD = number.get();
}
Expression::Expression(const Atom<String_t>& a)
: Expression() {
__state = STRING;
op = Operator::INVALID;
__valueS = a.get();
}
Expression::Expression(const Atom<Identifier_t> &ident)
: Expression() {
__state = IDENT;
op = Operator::INVALID;
__valueS = ident.get();
}
Expression::Expression(const Operator &oprt, std::initializer_list<Expression> params)
: Expression() {
__state = COMPOUND;
op = oprt;
if (op == Operator::CALL) {
assert(params.size() > 0);
Expression arg = *params.begin();
assert(arg.__state == Expression::IDENT);
__valueS = std::move(arg.__valueS);
operands.insert(operands.end(), params.begin() + 1, params.end());
return;
}
operands.insert(operands.end(), params.begin(), params.end());
}
void
Expression::setOp(Operator oprt) {
op = oprt;
switch (op) {
case Operator::INVALID:
__state = INVALID;
break;
default:
__state = COMPOUND;
break;
}
}
void
Expression::addArg(Expression &&arg) {
operands.push_back(arg);
}
void
Expression::addTags(const std::list<Expression> tags) const {
std::transform(tags.begin(), tags.end(), std::inserter(this->tags, this->tags.end()),
[](const Expression & tag) {
return make_pair(tag.getValueString(), tag);
});
}
void
Expression::addBindings(std::initializer_list<Atom<Identifier_t>> params) {
addBindings(params.begin(), params.end());
}
void
Expression::bindType(TypeAnnotation t) {
type = move(t);
}
void
Expression::addBlock(ManagedScpPtr scope) {
blocks.push_back(scope.operator->());
}
const std::vector<Expression>&
Expression::getOperands() const {
return operands;
}
double
Expression::getValueDouble() const {
return __valueD;
}
const std::string&
Expression::getValueString() const {
return __valueS;
}
void
Expression::setValue(const Atom<Identifier_t>&& v) {
__valueS = v.get();
}
void Expression::setValueDouble(double value) {
__valueD = value;
}
bool
Expression::isValid() const {
return (__state != INVALID);
}
bool
Expression::isDefined() const {
return (__state != BINDING && __state != INVALID);
}
Expression::Expression()
: __state(INVALID), op(Operator::INVALID), id(nextVacantId++) {
}
namespace details { namespace inconsistent {
AST::AST() {
Attachments::init<versions::VariableVersion>();
Attachments::init<IdentifierSymbol>();
Attachments::init<SymbolAlias>();
Attachments::init<TypeInferred>();
}
void
AST::addInterfaceData(const ASTInterface& interface, Expression&& data) {
__interfacesData.emplace(interface, move(data));
}
void
AST::addDFAData(Expression &&data) {
__dfadata.push_back(data);
}
void
AST::addExternData(ExternData &&data) {
__externdata.insert(__externdata.end(), data.entries.begin(), data.entries.end());
}
void
AST::add(Function* f) {
__functions.push_back(f);
__indexFunctions.emplace(f->getName(), __functions.size() - 1);
}
void
AST::add(MetaRuleAbstract *r) {
__rules.push_back(r);
}
void
AST::add(TypeAnnotation t, Atom<Identifier_t> alias) {
if (t.__operator == TypeOperator::VARIANT) {
for (int i = 0, size = t.fields.size(); i < size; ++i) {
__dictVariants.emplace(t.fields[i], make_pair(t, i));
}
}
__indexTypeAliases.emplace(alias.get(), move(t));
}
ManagedScpPtr
AST::add(CodeScope* scope) {
this->__scopes.push_back(scope);
return ManagedScpPtr(this->__scopes.size() - 1, &this->__scopes);
}
std::string
AST::getModuleName() {
const std::string name = "moduleTest";
return name;
}
ManagedPtr<Function>
AST::findFunction(const std::string& name) {
int count = __indexFunctions.count(name);
if (!count) {
return ManagedFnPtr::Invalid();
}
assert(count == 1);
auto range = __indexFunctions.equal_range(name);
return ManagedPtr<Function>(range.first->second, &this->__functions);
}
std::list<ManagedFnPtr>
AST::getAllFunctions() const {
const size_t size = __functions.size();
std::list<ManagedFnPtr> result;
for (size_t i = 0; i < size; ++i) {
result.push_back(ManagedFnPtr(i, &this->__functions));
}
return result;
}
//TASK select default specializations
std::list<ManagedFnPtr>
AST::getFunctionSpecializations(const std::string& fnName) const {
auto functions = __indexFunctions.equal_range(fnName);
std::list<ManagedFnPtr> result;
std::transform(functions.first, functions.second, inserter(result, result.end()),
[this](auto f) {
return ManagedFnPtr(f.second, &this->__functions);
});
return result;
}
template<>
ManagedPtr<Function>
AST::begin<Function>() {
return ManagedPtr<Function>(0, &this->__functions);
}
template<>
ManagedPtr<CodeScope>
AST::begin<CodeScope>() {
return ManagedPtr<CodeScope>(0, &this->__scopes);
}
template<>
ManagedPtr<MetaRuleAbstract>
AST::begin<MetaRuleAbstract>() {
return ManagedPtr<MetaRuleAbstract>(0, &this->__rules);
}
void
AST::recognizeVariantConstructor(Expression& function) {
assert(function.op == Operator::CALL);
std::string variant = function.getValueString();
if (!__dictVariants.count(variant)) {
return;
}
auto record = __dictVariants.at(variant);
const TypeAnnotation& typ = record.first;
function.op = Operator::VARIANT;
function.setValueDouble(record.second);
function.type = typ;
}
Atom<Number_t>
AST::recognizeVariantConstructor(Atom<Identifier_t> ident) {
std::string variant = ident.get();
assert(__dictVariants.count(variant) && "Can't recognize variant constructor");
auto record = __dictVariants.at(variant);
return Atom<Number_t>(record.second);
}
void
AST::postponeIdentifier(CodeScope* scope, const Expression& id) {
bucketUnrecognizedIdentifiers.emplace(scope, id);
}
void
AST::recognizePostponedIdentifiers() {
for (const auto& identifier : bucketUnrecognizedIdentifiers) {
if (!identifier.first->recognizeIdentifier(identifier.second)) {
//exception: Ident not found
std::cout << "Unknown symbol: " << identifier.second.getValueString() << std::endl;
assert(false && "Symbol not found");
}
}
}
xreate::AST*
AST::finalize() {
//all finalization steps:
recognizePostponedIdentifiers();
return reinterpret_cast<xreate::AST*> (this);
}
} } //namespace details::incomplete
Expanded<TypeAnnotation>
AST::findType(const std::string& name) {
// find in general scope:
if (__indexTypeAliases.count(name))
return expandType(__indexTypeAliases.at(name));
//if type is unknown keep it as is.
TypeAnnotation t(TypeOperator::CUSTOM,{});
t.__valueCustom = name;
return ExpandedType(move(t));
}
Expanded<TypeAnnotation>
AST::expandType(const TypeAnnotation &t) const {
return TypesResolver(this)(t);
}
ExpandedType
AST::getType(const Expression& expression) {
return typeinference::getType(expression, *this);
}
Function::Function(const Atom<Identifier_t>& name)
: __entry(new CodeScope(0)) {
__name = name.get();
}
void
Function::addTag(Expression&& tag, const TagModifier mod) {
string name = tag.getValueString();
__tags.emplace(move(name), move(tag));
}
const std::map<std::string, Expression>&
Function::getTags() const {
return __tags;
}
CodeScope*
Function::getEntryScope() const {
return __entry;
}
void
Function::addBinding(Atom <Identifier_t>&& name, Expression&& argument, const VNameId hintBindingId) {
__entry->addBinding(move(name), move(argument), hintBindingId);
}
const std::string&
Function::getName() const {
return __name;
}
ScopedSymbol
CodeScope::registerIdentifier(const Expression& identifier, const VNameId hintBindingId) {
versions::VariableVersion version = Attachments::get<versions::VariableVersion>(identifier, versions::VERSION_NONE);
auto result = __identifiers.emplace(identifier.getValueString(), hintBindingId? hintBindingId: __identifiers.size() + 1);
return { result.first->second, version };
}
bool
CodeScope::recognizeIdentifier(const Expression& identifier) const {
versions::VariableVersion version = Attachments::get<versions::VariableVersion>(identifier, versions::VERSION_NONE);
const std::string& name = identifier.getValueString();
//search identifier in the current block
if (__identifiers.count(name)) {
VNameId id = __identifiers.at(name);
Symbol s;
s.identifier = ScopedSymbol{id, version};
s.scope = const_cast<CodeScope*> (this);
Attachments::put<IdentifierSymbol>(identifier, s);
return true;
}
//search in the parent scope
if (__parent) {
return __parent->recognizeIdentifier(identifier);
}
return false;
}
ScopedSymbol
CodeScope::getSymbol(const std::string& alias) {
assert(__identifiers.count(alias));
VNameId id = __identifiers.at(alias);
return {id, versions::VERSION_NONE };
}
void
CodeScope::addBinding(Expression&& var, Expression&& argument, const VNameId hintBindingId) {
argument.__state = Expression::BINDING;
__bindings.push_back(var.getValueString());
ScopedSymbol binding = registerIdentifier(var, hintBindingId);
__declarations[binding] = move(argument);
}
Symbol
CodeScope::addDefinition(Expression&& var, Expression&& body) {
ScopedSymbol s = registerIdentifier(var);
__declarations[s] = move(body);
return Symbol{s, this};
}
CodeScope::CodeScope(CodeScope* parent)
: __parent(parent) {
}
CodeScope::~CodeScope() {
}
void
CodeScope::setBody(const Expression &body) {
assert(__declarations.count(ScopedSymbol::RetSymbol)==0 && "Attempt to reassign scope body");
__declarations[ScopedSymbol::RetSymbol] = body;
}
const Expression&
CodeScope::getBody() const{
return __declarations.at(ScopedSymbol::RetSymbol);
}
const Expression&
CodeScope::getDefinition(const Symbol& symbol, bool flagAllowUndefined){
const CodeScope* self = symbol.scope;
return self->getDefinition(symbol.identifier, flagAllowUndefined);
}
const Expression&
CodeScope::getDefinition(const ScopedSymbol& symbol, bool flagAllowUndefined) const{
static Expression expressionInvalid;
if (!__declarations.count(symbol)){
if (flagAllowUndefined) return expressionInvalid;
assert(false && "Symbol's declaration not found");
}
return __declarations.at(symbol);
}
void
RuleArguments::add(const Atom<Identifier_t> &arg, DomainAnnotation typ) {
emplace_back(arg.get(), typ);
}
void
RuleGuards::add(Expression&& e) {
push_back(e);
}
MetaRuleAbstract::
MetaRuleAbstract(RuleArguments&& args, RuleGuards&& guards)
: __args(std::move(args)), __guards(std::move(guards)) {
}
MetaRuleAbstract::~MetaRuleAbstract() {
}
RuleWarning::
RuleWarning(RuleArguments&& args, RuleGuards&& guards, Expression&& condition, Atom<String_t>&& message)
: MetaRuleAbstract(std::move(args), std::move(guards)), __message(message.get()), __condition(condition) {
}
RuleWarning::~RuleWarning() {
}
void
RuleWarning::compile(TranscendLayer& layer) {
//TODO restore addRuleWarning
//layer.addRuleWarning(*this);
}
bool operator<(const ScopedSymbol& s1, const ScopedSymbol& s2) {
return (s1.id < s2.id) || (s1.id == s2.id && s1.version < s2.version);
}
bool operator==(const ScopedSymbol& s1, const ScopedSymbol& s2) {
return (s1.id == s2.id) && (s1.version == s2.version);
}
bool operator<(const Symbol& s1, const Symbol& s2) {
return (s1.scope < s2.scope) || (s1.scope == s2.scope && s1.identifier < s2.identifier);
}
bool operator==(const Symbol& s1, const Symbol& s2) {
return (s1.scope == s2.scope) && (s1.identifier == s2.identifier);
}
bool operator<(const Expression&a, const Expression&b) {
if (a.__state != b.__state) return a.__state < b.__state;
assert(a.__state != Expression::INVALID);
switch (a.__state) {
case Expression::IDENT:
case Expression::STRING:
return a.getValueString() < b.getValueString();
case Expression::NUMBER:
return a.getValueDouble() < b.getValueDouble();
case Expression::COMPOUND:
{
assert(a.blocks.size() == 0);
assert(b.blocks.size() == 0);
if (a.op != b.op) {
return a.op < b.op;
}
bool flagAValid = ExpressionHints::isStringValueValid(a);
bool flagBValid = ExpressionHints::isStringValueValid(b);
if (flagAValid != flagBValid) {
return flagAValid < flagBValid;
}
if (flagAValid) {
if (a.getValueString() != b.getValueString()) {
return a.getValueString() < b.getValueString();
}
}
flagAValid = ExpressionHints::isDoubleValueValid(a);
flagBValid = ExpressionHints::isDoubleValueValid(b);
if (flagAValid != flagBValid) {
return flagAValid < flagBValid;
}
if (flagAValid) {
if (a.getValueDouble() != b.getValueDouble()) {
return a.getValueDouble() < b.getValueDouble();
}
}
if (a.operands.size() != b.operands.size()) {
return (a.operands.size() < b.operands.size());
}
for (size_t i = 0; i < a.operands.size(); ++i) {
bool result = a.operands[i] < b.operands[i];
if (result) return true;
}
return false;
}
case Expression::BINDING:
case Expression::INVALID:
assert(false);
}
return false;
}
bool
Expression::operator==(const Expression& other) const {
if (this->__state != other.__state) return false;
if (ExpressionHints::isStringValueValid(*this)) {
if (this->__valueS != other.__valueS) return false;
}
if (ExpressionHints::isDoubleValueValid(*this)) {
if (this->__valueD != other.__valueD) return false;
}
if (this->__state != Expression::COMPOUND) {
return true;
}
if (this->op != other.op) {
return false;
}
if (this->operands.size() != other.operands.size()) {
return false;
}
for (size_t i = 0; i<this->operands.size(); ++i) {
if (!(this->operands[i] == other.operands[i])) return false;
}
assert(!this->blocks.size());
assert(!other.blocks.size());
return true;
}
const ScopedSymbol
ScopedSymbol::RetSymbol = ScopedSymbol{0, versions::VERSION_NONE};
} //end of namespace xreate
diff --git a/cpp/src/ast.h b/cpp/src/ast.h
index 59bdb5b..5fee1f6 100644
--- a/cpp/src/ast.h
+++ b/cpp/src/ast.h
@@ -1,740 +1,745 @@
/* 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: ast.h
*/
+/**
+ * \file ast.h
+ * \brief A syntax tree representation and related code
+ *
+ * \sa xreate::AST
+ */
+
#ifndef AST_H
#define AST_H
#include "attachments.h"
#include <vector>
#include <stdlib.h>
#include <string>
#include <list>
#include <unordered_map>
#include <unordered_set>
#include <climits>
#include "utils.h"
#include <algorithm>
namespace llvm {
class Value;
}
namespace xreate {
struct ScopedSymbol;
struct Symbol;
}
namespace std {
template<>
struct hash<xreate::ScopedSymbol> {
std::size_t operator()(xreate::ScopedSymbol const& s) const;
};
template<>
struct equal_to<xreate::ScopedSymbol> {
bool operator()(const xreate::ScopedSymbol& __x, const xreate::ScopedSymbol& __y) const;
};
template<>
struct hash<xreate::Symbol> {
size_t operator()(xreate::Symbol const& s) const;
};
template<>
struct equal_to<xreate::Symbol> {
bool operator()(const xreate::Symbol& __x, const xreate::Symbol& __y) const;
};
}
namespace xreate {
struct String_t {
};
struct Identifier_t {
};
struct Number_t {
};
struct Type_t {
};
template<typename A>
class Atom {
};
//DEBT store line:col for all atoms/identifiers
template<> class
Atom<Identifier_t> {
public:
Atom(const std::wstring& value);
Atom(std::string && name);
const std::string& get() const;
private:
std::string __value;
};
template<>
class Atom<Number_t> {
public:
Atom(wchar_t* value);
Atom(int value);
double get()const;
private:
double __value;
};
template<>
class Atom<String_t> {
public:
Atom(const std::wstring& value);
Atom(std::string && name);
const std::string& get() const;
private:
std::string __value;
};
enum class TypePrimitive {
Invalid, Bool, I8, I32, I64, Num, Int, Float, String
};
enum class TypeOperator {
NONE, CALL, CUSTOM, VARIANT, LIST_ARRAY, LIST_RECORD, ACCESS, LINK, SLAVE
};
struct llvm_array_tag {
};
struct struct_tag {
};
const llvm_array_tag tag_array = llvm_array_tag();
const struct_tag tag_struct = struct_tag();
/**
- * \brief Represents type to support type system
+ * \brief A type representation to support type system
*
- * This class represents type in denormalized form, i.e. without arguments and aliases substitution
+ * The class represents type in a denormalized form, i.e. with no arguments and aliases substitution
* \sa AST::expandType()
*/
class TypeAnnotation {
public:
TypeAnnotation();
TypeAnnotation(const Atom<Type_t>& typ);
TypeAnnotation(TypePrimitive typ);
TypeAnnotation(llvm_array_tag, TypeAnnotation typ, int size);
TypeAnnotation(TypeOperator op, std::initializer_list<TypeAnnotation> operands);
TypeAnnotation(TypeOperator op, std::vector<TypeAnnotation>&& operands);
void addBindings(std::vector<Atom<Identifier_t>>&& params);
void addFields(std::vector<Atom<Identifier_t>>&& listFields);
bool operator<(const TypeAnnotation& t) const;
// TypeAnnotation (struct_tag, std::initializer_list<TypePrimitive>);
bool isValid() const;
TypeOperator __operator = TypeOperator::NONE;
std::vector<TypeAnnotation> __operands;
TypePrimitive __value;
std::string __valueCustom;
int conjuctionId = -1; //conjunction point id (relevant for recursive types)
uint64_t __size = 0;
std::vector<std::string> fields;
std::vector<std::string> bindings;
private:
};
enum class Operator {
INVALID, UNDEF, ADD, SUB, MUL, DIV,
EQU, NE, NEG, LSS,
LSE, GTR, GTE, LIST,
LIST_RANGE,
CALL, CALL_INTRINSIC, QUERY, QUERY_LATE,
IMPL/* implication */, MAP,
FOLD, INF, INDEX,
IF, SWITCH, SWITCH_VARIANT, SWITCH_LATE,
CASE, CASE_DEFAULT, LOGIC_AND,
CONTEXT_RULE, VARIANT, SEQUENCE
};
class Function;
class AST;
class CodeScope;
class MetaRuleAbstract;
typedef ManagedPtr<Function> ManagedFnPtr;
typedef ManagedPtr<CodeScope> ManagedScpPtr;
typedef ManagedPtr<MetaRuleAbstract> ManagedRulePtr;
const ManagedScpPtr NO_SCOPE = ManagedScpPtr(UINT_MAX, 0);
/**
- * \brief Represents every instruction in Xreate's syntax tree
- * \attention In case of any changes update xreate::ExpressionHints auxiliary helper as well
+ * \brief AST node to represent a single instruction or an annotation
+ * \attention In case of any changes update \ref xreate::ExpressionHints auxiliary helper as well
*
- * Expression is generic building block of syntax tree able to hold node data
- * as well as child nodes as operands. Not only instructions use expression for representation in syntax tree
- * but annotation as well.
+ * %Expression is a generic building block of syntax tree which is able to hold node data
+ * along with child nodes as operands.
*
- * Additionally, `types` as a special kind of annotations use Expression-like data structure TypeAnnotation
+ * \note For types the %expression-like data structure \ref TypeAnnotation is used rather than Expression itself.
* \sa xreate::AST, xreate::TypeAnnotation
*/
-//
struct Expression {
friend class CodeScope;
friend class TranscendLayer;
friend class CFAPass;
friend class ExpressionHints;
Expression(const Operator &oprt, std::initializer_list<Expression> params);
Expression(const Atom<Identifier_t>& ident);
Expression(const Atom<Number_t>& number);
Expression(const Atom<String_t>& a);
Expression();
void setOp(Operator oprt);
void addArg(Expression&& arg);
void addBindings(std::initializer_list<Atom<Identifier_t>> params);
void bindType(TypeAnnotation t);
template<class InputIt>
void addBindings(InputIt paramsBegin, InputIt paramsEnd);
void addTags(const std::list<Expression> tags) const;
void addBlock(ManagedScpPtr scope);
const std::vector<Expression>& getOperands() const;
double getValueDouble() const;
void setValueDouble(double value);
const std::string& getValueString() const;
void setValue(const Atom<Identifier_t>&& v);
bool isValid() const;
bool isDefined() const;
bool operator==(const Expression& other) const;
/**
* \brief is it string, number, compound operation and so on
*/
enum {
INVALID, COMPOUND, IDENT, NUMBER, STRING, BINDING
} __state = INVALID;
/**
* \brief Valid for compound State. Holds type of compound operator
*/
Operator op;
/**
* \brief Unique id to identify expression within syntax tree
*/
unsigned int id;
/**
* \brief Exact meaning depends on particular instruction
* \details As an example, named lists/structs hold field names in bindings
*/
std::vector<std::string> bindings;
std::map<std::string, size_t> __indexBindings;
/**
* \brief Holds child instructions as arguments
*/
std::vector<Expression> operands;
/**
* \brief Holds type of instruction's result
*/
TypeAnnotation type;
/**
* \brief Holds additional annotations
*/
mutable std::map<std::string, Expression> tags;
/**
* \brief Child code blocks
* \details For example, If statement holds TRUE-branch as first and FALSE-branch as second block here
*/
std::list<CodeScope*> blocks;
private:
std::string __valueS;
double __valueD;
static unsigned int nextVacantId;
};
bool operator<(const Expression&, const Expression&);
template<class InputIt>
void Expression::addBindings(InputIt paramsBegin, InputIt paramsEnd) {
size_t index = bindings.size();
std::transform(paramsBegin, paramsEnd, std::inserter(bindings, bindings.end()),
[&index, this] (const Atom<Identifier_t> atom) {
std::string key = atom.get();
this->__indexBindings[key] = index++;
return key;
});
}
typedef std::list<Expression> ExpressionList;
enum class TagModifier {
NONE, ASSERT, REQUIRE
};
enum class DomainAnnotation {
FUNCTION, VARIABLE
};
class RuleArguments : public std::vector<std::pair<std::string, DomainAnnotation>>
{
public:
void add(const Atom<Identifier_t>& name, DomainAnnotation typ);
};
class RuleGuards : public std::vector<Expression> {
public:
void add(Expression&& e);
};
class TranscendLayer;
class LLVMLayer;
class MetaRuleAbstract {
public:
MetaRuleAbstract(RuleArguments&& args, RuleGuards&& guards);
virtual ~MetaRuleAbstract();
virtual void compile(TranscendLayer& layer) = 0;
protected:
RuleArguments __args;
RuleGuards __guards;
};
class RuleWarning : public MetaRuleAbstract {
friend class TranscendLayer;
public:
RuleWarning(RuleArguments&& args, RuleGuards&& guards, Expression&& condition, Atom<String_t>&& message);
virtual void compile(TranscendLayer& layer);
~RuleWarning();
private:
std::string __message;
Expression __condition;
};
typedef unsigned int VNameId;
namespace versions {
typedef int VariableVersion;
const VariableVersion VERSION_NONE = -2;
const VariableVersion VERSION_INIT = 0;
}
template<>
struct AttachmentsDict<versions::VariableVersion> {
typedef versions::VariableVersion Data;
static const unsigned int key = 6;
};
struct ScopedSymbol {
VNameId id;
versions::VariableVersion version;
static const ScopedSymbol RetSymbol;
};
struct Symbol {
ScopedSymbol identifier;
const CodeScope * scope;
};
struct IdentifierSymbol{};
struct SymbolAlias{};
template<>
struct AttachmentsDict<IdentifierSymbol> {
typedef Symbol Data;
static const unsigned int key = 7;
};
template<>
struct AttachmentsDict<SymbolAlias> {
typedef Symbol Data;
static const unsigned int key = 9;
};
typedef std::pair<Expression, TagModifier> Tag;
bool operator<(const ScopedSymbol& s1, const ScopedSymbol& s2);
bool operator==(const ScopedSymbol& s1, const ScopedSymbol& s2);
bool operator<(const Symbol& s1, const Symbol& s2);
bool operator==(const Symbol& s1, const Symbol& s2);
/**
- * \brief Represents code block and single scope of visibility
+ * \brief AST node to represent a single code block/a scope of visibility
*
- * Holds single expression as a *body* and set of variable assignments(declarations) used in body's expression
+ * Holds a single expression as a `body` along with set of variable assignments(declarations) used in body's expression.
* \sa xreate::AST
*/
class CodeScope {
friend class Function;
friend class PassManager;
public:
CodeScope(CodeScope* parent = 0);
~CodeScope();
/** \brief Set expression as a body */
void setBody(const Expression& body);
/** \brief Returns current code scope body */
const Expression& getBody() const;
/** \brief Adds variable definition to be used in body as well as in other declarations */
Symbol addDefinition(Expression&& var, Expression&& body);
/** \brief Returns symbols' definition */
static const Expression& getDefinition(const Symbol& symbol, bool flagAllowUndefined = false);
const Expression& getDefinition(const ScopedSymbol& symbol, bool flagAllowUndefined = false) const;
/** \brief Adds variable defined elsewhere */
void addBinding(Expression&& var, Expression&& argument, const VNameId hintBindingId = 0);
std::vector<std::string> __bindings;
std::map<std::string, VNameId> __identifiers;
CodeScope* __parent;
//TODO move __definitions to SymbolsAttachments data
//NOTE: definition of return type has index 0
std::unordered_map<ScopedSymbol, Expression> __declarations;
std::vector<Expression> tags;
std::vector<Expression> contextRules;
private:
ScopedSymbol registerIdentifier(const Expression& identifier, const VNameId hintBindingId = 0);
public:
bool recognizeIdentifier(const Expression& identifier) const;
ScopedSymbol getSymbol(const std::string& alias);
};
/**
- * \brief Represents single function in Xreate's syntax tree
+ * \brief AST node to represent a single function
*
- * Holds an entry code scope and `guardContext` required for function to operate
+ * Holds an `__entry` entry code scope along with `guard` to denote the different specializations.
* \sa xreate::AST
*/
class Function {
friend class Expression;
friend class CodeScope;
friend class AST;
public:
Function(const Atom<Identifier_t>& name);
/**
* \brief Adds function arguments
*/
void addBinding(Atom <Identifier_t>&& name, Expression&& argument, const VNameId hintBindingId=0);
/**
* \brief Adds additional function annotations
*/
void addTag(Expression&& tag, const TagModifier mod);
const std::string& getName() const;
const std::map<std::string, Expression>& getTags() const;
CodeScope* getEntryScope() const;
CodeScope* __entry;
std::string __name;
bool isPrefunction = false; //SECTIONTAG adhoc Function::isPrefunction flag
Expression guard;
+
private:
-
std::map<std::string, Expression> __tags;
};
class ExternData;
struct ExternEntry {
std::string package;
std::vector<std::string> headers;
};
typedef Expanded<TypeAnnotation> ExpandedType;
struct TypeInferred{};
template<>
struct AttachmentsDict<TypeInferred> {
typedef ExpandedType Data;
static const unsigned int key = 11;
};
enum ASTInterface {
CFA, DFA, Extern, Adhoc
};
struct FunctionSpecialization {
std::string guard;
size_t id;
};
struct FunctionSpecializationQuery {
std::unordered_set<std::string> context;
};
template<>
struct AttachmentsId<Expression>{
static unsigned int getId(const Expression& expression){
return expression.id;
}
};
template<>
struct AttachmentsId<Symbol>{
static unsigned int getId(const Symbol& s){
return s.scope->__declarations.at(s.identifier).id;
}
};
template<>
struct AttachmentsId<ManagedFnPtr>{
static unsigned int getId(const ManagedFnPtr& f){
const Symbol symbolFunction{ScopedSymbol::RetSymbol, f->getEntryScope()};
return AttachmentsId<Symbol>::getId(symbolFunction);
}
};
template<>
struct AttachmentsId<CodeScope*>{
static unsigned int getId(const CodeScope* scope){
const Symbol symbolScope{ScopedSymbol::RetSymbol, scope};
return AttachmentsId<Symbol>::getId(symbolScope);
}
};
template<>
struct AttachmentsId<unsigned int>{
static unsigned int getId(const unsigned int id){
return id;
}
};
class TypesResolver;
namespace details { namespace inconsistent {
- /**
- * \brief Syntax tree under construction in inconsistent form
- *
- * Represents Syntax Tree under construction(**inconsistent state**).
- * \attention Clients should use rather xreate::AST unless client's code explicitly works with Syntax Tree during construction.
- *
- * Typically instance only created by xreate::XreateManager and filled in by Parser
- * \sa xreate::XreateManager::prepare(std::string&&)
- */
+/**
+ * \brief AST in an inconsistent form during construction
+ *
+ * Represents AST under construction(**inconsistent state**).
+ * \attention Clients should use rather xreate::AST unless client's code explicitly works with Syntax Tree during construction.
+ *
+ * Typically an instance is created by xreate::XreateManager only and filled out by the parser
+ * \sa xreate::XreateManager::prepare(std::string&&)
+ */
class AST {
friend class xreate::TypesResolver;
public:
AST();
/**
* \brief Adds new function to AST
* \param f Function to register
*/
void add(Function* f);
/**
* \brief Adds new declarative rule to AST
* \param r Declarative Rule
*/
void add(MetaRuleAbstract* r);
/** \brief Registers new code block */
ManagedScpPtr add(CodeScope* scope);
/**
* \brief Add new type to AST
* @param t Type definition
* @param alias Typer name
*/
void add(TypeAnnotation t, Atom<Identifier_t> alias);
/** \brief Current module's name */
std::string getModuleName();
/**
* \brief Looks for function with given name
* \param name Function name to find
* \note Requires that only one function exists under given name
* \return Found function
*/
ManagedPtr<Function> findFunction(const std::string& name);
/** \brief Returns all function in AST */
std::list<ManagedFnPtr> getAllFunctions() const;
/**
* \brief Returns all specializations of a function with a given name
* \param fnName function to find
* \return list of found function specializations
*/
std::list<ManagedFnPtr> getFunctionSpecializations(const std::string& fnName) const;
/**
* \return First element in Functions/Scopes/Rules list depending on template parameter
* \tparam Target either Function or CodeScope or MetaRuleAbstract
*/
template<class Target>
ManagedPtr<Target> begin();
/**
* \brief Performs all necessary steps after AST is built
*
- * Performs all finzalisation steps and move AST into consistent state represented by xreate::AST
+ * Performs all finalization steps and moves AST into consistent state represented by xreate::AST
* \sa xreate::AST
* \return AST in consistent state
*/
xreate::AST* finalize();
typedef std::multimap<std::string, unsigned int> FUNCTIONS_REGISTRY;
std::vector<ExternEntry> __externdata;
std::list<Expression> __dfadata; //TODO move to more appropriate place
std::list<std::string> __rawImports; //TODO move to more appropriate place
std::multimap<ASTInterface, Expression> __interfacesData; //TODO CFA data here.
private:
std::vector<MetaRuleAbstract*> __rules;
std::vector<Function*> __functions;
std::vector<CodeScope*> __scopes;
FUNCTIONS_REGISTRY __indexFunctions;
protected:
std::map<std::string, TypeAnnotation> __indexTypeAliases;
public:
/**
* \brief Stores DFA scheme for later use by DFA Pass
*
- * Treats expression as a DFA scheme and feeds to a DFA Pass later
- * \paramn Expression DFA Scheme
+ * Treats expression as a DFA scheme and feeds to the DFA Pass later
+ * \param data DFA Scheme
* \sa xreate::DFAPass
*/
void addDFAData(Expression&& data);
/** \brief Stores data for later use by xreate::ExternLayer */
void addExternData(ExternData&& data);
/**
* \brief Generalized function to store particular data for later use by particular pass
* \param interface Particular Interface
* \param data Particular data
*/
void addInterfaceData(const ASTInterface& interface, Expression&& data);
/**\name Symbols Recognition */
///@{
public:
//TODO revisit enums/variants, move to codescope
/**
* \brief Tries to find out whether expression is Variant constructor
*/
void recognizeVariantConstructor(Expression& function);
Atom<Number_t> recognizeVariantConstructor(Atom<Identifier_t> ident);
private:
std::map<std::string, std::pair<TypeAnnotation, int>> __dictVariants;
public:
std::set<std::pair<CodeScope*, Expression>> bucketUnrecognizedIdentifiers;
public:
/**
* \brief Postpones unrecognized identifier for future second round of recognition
* \param scope Code block identifier is encountered
* \param id Identifier
*/
void postponeIdentifier(CodeScope* scope, const Expression& id);
/** \brief Second round of identifiers recognition done right after AST is fully constructed */
void recognizePostponedIdentifiers();
///@}
};
template<>
ManagedPtr<Function>
AST::begin<Function>();
template<>
ManagedPtr<CodeScope>
AST::begin<CodeScope>();
template<>
ManagedPtr<MetaRuleAbstract>
AST::begin<MetaRuleAbstract>();
} } // namespace details::incomplete
/**
- * \brief Xreate's Syntax Tree in consistent state
+ * \brief AST in a consistent state
*
- * Syntax Tree has two mutually exclusive possible states:
- * - inconsistent state while AST is under construction. Represented by xreate::details::inconsistent::AST
- * - consistent state when AST is built and finalize() is done.
+ * AST has two mutually exclusive possible states:
+ * - an inconsistent state while AST is under construction. Represented by xreate::details::inconsistent::AST
+ * - a consistent state when AST is built and finalize() is invoked.
*
- * This class represents consistent state and should be used everywhere unless client's code explicitly works with AST under construction.
- * Consistent AST enables access to additional functions(currently related to type management).
+ * This class represents a consistent state and should be used by clients unless client's code explicitly works with AST under construction.
+ * Consistent AST enables access to additional functions(such as type management).
* \sa xreate::details::inconsistent::AST
*/
class AST : public details::inconsistent::AST {
public:
AST() : details::inconsistent::AST() {}
/**
* \brief Computes fully expanded form of type by substituting all arguments and aliases
* \param t Type to expand
* \return Expdanded or normal form of type
* \sa TypeAnnotation
*/
ExpandedType expandType(const TypeAnnotation &t) const;
/**
* Searches type by given name
* \param name Typename to search
* \return Expanded or normal form of desired type
* \note if type name is not found returns new undefined type with this name
*/
ExpandedType findType(const std::string& name);
/**
* Invokes Type Inference Analysis to find out expanded(normal) form expressions's type
* \sa typeinference.h
* \param expression
* \return Type of expression
*/
ExpandedType getType(const Expression& expression);
};
}
#endif // AST_H
diff --git a/cpp/src/attachments.cpp b/cpp/src/attachments.cpp
index a9f19f3..2113cf4 100644
--- a/cpp/src/attachments.cpp
+++ b/cpp/src/attachments.cpp
@@ -1,20 +1,15 @@
/* 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: attachments.cpp
* Date: 3/15/15
*/
-/**
- * \file attachments.h
- * \brief Attachments support: mechanism to attach additional data to AST nodes
- */
-
#include "attachments.h"
using namespace xreate;
std::vector<void*>
Attachments::__storage = std::vector<void*>();
diff --git a/cpp/src/attachments.h b/cpp/src/attachments.h
index a9bc42b..8ef3663 100644
--- a/cpp/src/attachments.h
+++ b/cpp/src/attachments.h
@@ -1,179 +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/.
*
* Author: pgess <v.melnychenko@xreate.org>
* File: attachments.h
* Date: 3/15/15
*/
+/**
+ * \file attachments.h
+ * \brief The attachments support: a mechanism to attach additional data to AST nodes
+ */
+
#ifndef _XREATE_ATTACHMENTS_H_
#define _XREATE_ATTACHMENTS_H_
#include <unordered_map>
#include <vector>
#include <assert.h>
#include <type_traits>
namespace xreate
{
- //Attachments dictionary
+ /** \brief Attachments dictionary */
template<class Tag>
struct AttachmentsDict
{
// typedef void Data;
// static const unsigned int key (next vacant id - 12);
// Defined attachments:
//-----------------------------------------------------
// 1 containers::Implementation
// 3 interpretation::InterpretationData
// 5 interpretation::FunctionInterpretationData
// 6 VariableVersion
// 7 IdentifierSymbol
// 8 versions::VersionImposedDependency
// 9 SymbolAlias
// 11 TypeInferred
};
template<class Object>
struct AttachmentsId{
//static unsigned int getId(const Object& object);
};
-
template<class Data>
class IAttachmentsContainer{
protected:
virtual bool __exists(const unsigned int object)=0;
virtual Data& __get(const unsigned int object)=0;
virtual void __put(const unsigned int object, Data data)=0;
public:
template<class Id>
bool exists(const Id& object){
unsigned int id = AttachmentsId<Id>::getId(object);
return __exists(id);
}
template<class Id>
Data& get(const Id& object){
unsigned int id = AttachmentsId<Id>::getId(object);
return __get(id);
}
template<class Id>
Data get(const Id& object, const Data& dataDefault){
unsigned int id = AttachmentsId<Id>::getId(object);
if (! __exists(id)){
return dataDefault;
}
return __get(id);
}
template<class Id>
void put(const Id& object, Data data){
unsigned int id = AttachmentsId<Id>::getId(object);
__put(id, data);
}
virtual ~IAttachmentsContainer(){};
};
template<class Data>
class AttachmentsContainerDefault: public IAttachmentsContainer<Data>{
private:
std::unordered_map<unsigned int, Data> __data;
virtual bool __exists(const unsigned int id){
return __data.count(id);
}
virtual Data& __get(const unsigned int id){
return __data.at(id);
}
virtual void __put(const unsigned int id, Data data){
auto result = __data.emplace(id, data);
assert(result.second);
}
public:
std::unordered_map<unsigned int, Data>& getRawStorage() {
return __data;
}
};
-
+/** \brief Implements %AST attachments mechanism to facilitate data sharing among different analyzers and compilation phases */
class Attachments{
private:
static std::vector<void*> __storage;
template<class Tag>
using Data = typename AttachmentsDict<Tag>::Data;
public:
template<class Tag, class Id>
static bool exists(const Id& object) {
assert(AttachmentsDict<Tag>::key < __storage.size());
assert(__storage.at(AttachmentsDict<Tag>::key));
IAttachmentsContainer<Data<Tag>>* self = reinterpret_cast<IAttachmentsContainer<Data<Tag>>*>(__storage.at(AttachmentsDict<Tag>::key));
return self->exists(object);
}
template<class Tag, class Id>
static Data<Tag>& get(const Id& object){
assert(AttachmentsDict<Tag>::key < __storage.size());
assert(__storage.at(AttachmentsDict<Tag>::key));
IAttachmentsContainer<Data<Tag>>* self = reinterpret_cast<IAttachmentsContainer<Data<Tag>>*>(__storage.at(AttachmentsDict<Tag>::key));
return self->get(object);
}
template<class Tag, class Id>
static Data<Tag> get(const Id& object, const Data<Tag>& dataDefault){
assert(AttachmentsDict<Tag>::key < __storage.size());
assert(__storage.at(AttachmentsDict<Tag>::key));
IAttachmentsContainer<Data<Tag>>* self = reinterpret_cast<IAttachmentsContainer<Data<Tag>>*>(__storage.at(AttachmentsDict<Tag>::key));
return self->get(object, dataDefault);
}
template<class Tag, class Id>
static void put(const Id& object, Data<Tag> data){
assert(AttachmentsDict<Tag>::key < __storage.size());
assert(__storage.at(AttachmentsDict<Tag>::key));
IAttachmentsContainer<Data<Tag>>* self = reinterpret_cast<IAttachmentsContainer<Data<Tag>>*>(__storage.at(AttachmentsDict<Tag>::key));
self->put(object, data);
}
template<class Tag>
static void init(){
unsigned int keyStorage = AttachmentsDict<Tag>::key;
if (keyStorage+1 > __storage.size()){
__storage.resize(keyStorage + 1, nullptr);
}
__storage[keyStorage] = new AttachmentsContainerDefault<Data<Tag>>();
}
template<class Tag>
static void init(IAttachmentsContainer<Data<Tag>>* container){
unsigned int keyStorage = AttachmentsDict<Tag>::key;
if (keyStorage+1 > __storage.size()){
__storage.resize(keyStorage + 1, nullptr);
}
__storage[keyStorage] = container;
}
};
}
#endif //_XREATE_ATTACHMENTS_H_
diff --git a/cpp/src/aux/latereasoning.cpp b/cpp/src/aux/latereasoning.cpp
index c70ef88..a14143e 100644
--- a/cpp/src/aux/latereasoning.cpp
+++ b/cpp/src/aux/latereasoning.cpp
@@ -1,57 +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
- *
- * \file latereasoning.cpp
- * \brief Late reasoninf support
*/
-
+
#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));
}
boost::optional<Gringo::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;
auto keyPSIt = guardKeys.begin();
auto keyActualIt = keys.begin();
bool result = true;
for(const Gringo::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 a20dbe1..e6ba460 100644
--- a/cpp/src/aux/latereasoning.h
+++ b/cpp/src/aux/latereasoning.h
@@ -1,84 +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/.
*
- * \file latereasoning.h
- * \brief Late reasoning support
- *
* 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;
std::list<SymbolPacked> guardKeys;
boost::optional<Gringo::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;
};
typedef std::map<Gringo::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{
const std::string& atomLateStatement = "late";
for(const Gringo::Symbol& atom: model.atoms(clingo_show_type_atoms)){
std::string atomName(atom.name().c_str());
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();
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){
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/aux/transcend-decorators.h b/cpp/src/aux/transcend-decorators.h
index 321b66c..018e790 100644
--- a/cpp/src/aux/transcend-decorators.h
+++ b/cpp/src/aux/transcend-decorators.h
@@ -1,34 +1,38 @@
/*
* 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:47 PM
- *
+ */
+
+/**
* \file transcend-decorators.h
- * \brief TranscendLevel decorators management
+ * \brief \ref xreate::TranscendLayer decorators management
*/
#include "transcendlayer.h"
#include "aux/latereasoning.h"
#ifndef TRANSCEND_DECORATORS_H
#define TRANSCEND_DECORATORS_H
namespace xreate {
+ /**
+ * \brief Default \ref xreate::TranscendLayer functionality
+ * \extends xreate::TranscendLayer
+ */
typedef latereasoning::LateReasoningTranscendDecorator<TranscendLayer>
DefaultTranscendLayerImpl;
struct LateReasoningTranscendDecoratorTag;
template<>
struct DecoratorsDict<LateReasoningTranscendDecoratorTag>{
typedef latereasoning::LateReasoningTranscendDecorator<TranscendLayer> result;
};
}
#endif /* TRANSCEND_DECORATORS_H */
diff --git a/cpp/src/aux/xreatemanager-decorators.h b/cpp/src/aux/xreatemanager-decorators.h
index d1cfe71..e8bc213 100644
--- a/cpp/src/aux/xreatemanager-decorators.h
+++ b/cpp/src/aux/xreatemanager-decorators.h
@@ -1,38 +1,40 @@
/* 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: xreatemanager-decorators.h
* Author: pgess <v.melnychenko@xreate.org>
*
* Created on July 16, 2017, 4:37 PM
*/
#ifndef XREATEMANAGER_DECORATORS_H
#define XREATEMANAGER_DECORATORS_H
#include "xreatemanager.h"
namespace xreate{
+/** \brief Simple \ref xm_adapt "XreateManager's" backend intended for inheritance, does not provide much functionality. */
class XreateManagerDecoratorBase: public details::tier2::XreateManager{
public:
virtual void initPasses() override;
virtual void analyse();
virtual void* run(){};
public:
virtual void prepareCode(std::string&& code);
virtual void prepareCode(FILE* code);
};
+/** \brief \ref xm_adapt "XreateManager's" backend intended to initialize all builtin passes. */
class XreateManagerDecoratorFull: public XreateManagerDecoratorBase{
public:
virtual void initPasses() override;
void* run();
};
}
#endif /* XREATEMANAGER_DECORATORS_H */
diff --git a/cpp/src/aux/xreatemanager-modules.h b/cpp/src/aux/xreatemanager-modules.h
index 003d780..f47ca72 100644
--- a/cpp/src/aux/xreatemanager-modules.h
+++ b/cpp/src/aux/xreatemanager-modules.h
@@ -1,124 +1,124 @@
/* 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: PassManagerModular.h
* Author: pgess <v.melnychenko@xreate.org>
*
* Created on June 22, 2017, 5:32 PM
*/
/**
* \file xreatemanager-modules.h
- * \brief XreateManager's decorator to support [Modules](/w/concepts/modules/).
+ * \brief XreateManager's decorator to support [Modules](/d/syntax/modules/).
*/
#ifndef PASSMANAGERMODULAR_H
#define PASSMANAGERMODULAR_H
#include "ast.h"
#include "modules.h"
#include "modules/Parser.h"
#include "main/Parser.h"
namespace xreate{namespace modules {
template<class Parent>
-/** \brief PassManager decorator to add [Modules Concept](/w/concepts/modules/) support
+/** \brief XreateManager decorator to support [Modules](/d/syntax/modules/).
*
- * Scanning of source file looking for other modules requirements.
- * Finds and connects other modules to satisfy module's requirements
- *
- * \sa ModulesSolver, ModulesRegistry, ModuleRecord
+ * Scans source code looking for other modules requirements.
+ * Finds and connects other modules to satisfy a current module's requirements
+ * \extends XreateManager
+ * \sa ModulesSolver, ModuleRecord
*/
class XreateManagerDecoratorModules: public Parent{
public:
XreateManagerDecoratorModules(){}
void prepareCode(std::string&& code) override {
Scanner scannerModules(reinterpret_cast<const unsigned char*>(code.c_str()), code.size());
std::list<std::string> listIncludedFiles;
parseModulesGrammar(scannerModules, listIncludedFiles);
grammar::main::Scanner scannerMain(reinterpret_cast<const unsigned char*>(code.c_str()), code.size());
parseMainGrammar(scannerMain, listIncludedFiles);
}
void prepareCode(FILE* code) override {
Scanner scannerModules(code);
std::list<std::string> listIncludedFiles;
parseModulesGrammar(scannerModules, listIncludedFiles);
grammar::main::Scanner scannerMain(code);
parseMainGrammar(scannerMain, listIncludedFiles);
}
private:
void parseModulesGrammar(Scanner& scanner, std::list<std::string>& listIncludedFiles){
ModulesSolver solver;
Parser parser(&scanner);
parser.Parse();
parser.module.__path = "";
solver.init("", parser.module);
std::list<std::string> modulesExternal = solver.run(parser.module);
std::string programBase = solver.__program.str();
for (const std::string module: modulesExternal){
parseModulesGrammar(module, programBase, listIncludedFiles);
}
}
void parseModulesGrammar(const std::string& path, std::string base, std::list<std::string>& listIncludedFiles){
FILE* input = fopen(path.c_str(), "r");
assert(input != nullptr);
Scanner scanner(input);
Parser parser(&scanner);
parser.Parse();
parser.module.__path = path;
fclose(input);
ModulesSolver solver;
solver.init(base, parser.module);
std::list<std::string>&& modulesExternal = solver.run(parser.module);
std::string programBase = solver.__program.str();
for (const std::string module: modulesExternal){
parseModulesGrammar(module, programBase, listIncludedFiles);
}
listIncludedFiles.push_back(path);
}
void parseMainGrammar(grammar::main::Scanner& scanner, std::list<std::string>& listIncludedFiles){
details::inconsistent::AST* ast = new AST;
grammar::main::Parser parser(&scanner);
parser.root = ast;
parser.Parse();
assert(!parser.errors->count && "Parser errors");
for (auto file: listIncludedFiles){
FILE* fileContent = fopen(file.c_str(), "r");
grammar::main::Scanner scanner(fileContent);
grammar::main::Parser parser(&scanner);
parser.root = ast;
parser.Parse();
fclose(fileContent);
assert(!parser.errors->count && "Parser errors");
}
PassManager::prepare(ast->finalize());
}
};
}} //end namespace xreate::modules
#endif /* PASSMANAGERMODULAR_H */
diff --git a/cpp/src/compilation/advancedinstructions.cpp b/cpp/src/compilation/advancedinstructions.cpp
index 787126c..b6ca440 100644
--- a/cpp/src/compilation/advancedinstructions.cpp
+++ b/cpp/src/compilation/advancedinstructions.cpp
@@ -1,470 +1,465 @@
/* 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: InstructionsAdvanced.cpp
* Author: pgess <v.melnychenko@xreate.org>
*
* Created on June 26, 2016, 6:00 PM
*/
-/**
- * \file advanced.h
- * \brief Compilation of statements that require more than one LLVM instruction
- */
-
#include "analysis/typeinference.h"
#include "compilation/advancedinstructions.h"
#include "compilation/containers.h"
#include "compilation/transformersaturation.h"
#include "query/containers.h"
#include "llvmlayer.h"
#include "ast.h"
using namespace std;
using namespace llvm;
using namespace xreate;
using namespace xreate::containers;
using namespace xreate::compilation;
#define NAME(x) (hintRetVar.empty()? x : hintRetVar)
#define UNUSED(x) (void)(x)
#define EXPAND_CONTEXT \
LLVMLayer* llvm = context.pass->man->llvm; \
compilation::ICodeScopeUnit* scope = context.scope; \
compilation::IFunctionUnit* function = context.function;
AdvancedInstructions::AdvancedInstructions(compilation::Context ctx)
: context(ctx), tyNum(static_cast<llvm::IntegerType*> (ctx.pass->man->llvm->toLLVMType(ExpandedType(TypeAnnotation(TypePrimitive::Num))))) {
}
llvm::Value*
AdvancedInstructions::compileMapSolidOutput(const Expression &expr, const std::string hintRetVar) {
EXPAND_CONTEXT UNUSED(scope);
//initialization
Symbol symbolIn = Attachments::get<IdentifierSymbol>(expr.getOperands()[0]);
ImplementationRec<SOLID> implIn = containers::Query::queryImplementation(symbolIn).extract<SOLID>(); // impl of input list
size_t size = implIn.size;
CodeScope* scopeLoop = expr.blocks.front();
std::string varEl = scopeLoop->__bindings[0];
Iterator* it = Iterator::create(context, symbolIn);
llvm::Value *rangeFrom = it->begin();
llvm::Value *rangeTo = it->end();
//definitions
ArrayType* tyNumArray = (ArrayType*) (llvm->toLLVMType(ExpandedType(TypeAnnotation(tag_array, TypePrimitive::Num, size))));
llvm::IRBuilder<> &builder = llvm->builder;
llvm::BasicBlock *blockLoop = llvm::BasicBlock::Create(llvm->llvmContext, "loop", function->raw);
llvm::BasicBlock *blockBeforeLoop = builder.GetInsertBlock();
llvm::BasicBlock *blockAfterLoop = llvm::BasicBlock::Create(llvm->llvmContext, "postloop", function->raw);
Value* dataOut = llvm->builder.CreateAlloca(tyNumArray, ConstantInt::get(tyNum, size), NAME("map"));
// * initial check
Value* condBefore = builder.CreateICmpSLE(rangeFrom, rangeTo);
builder.CreateCondBr(condBefore, blockLoop, blockAfterLoop);
// create PHI:
builder.SetInsertPoint(blockLoop);
llvm::PHINode *stateLoop = builder.CreatePHI(tyNum, 2, "mapIt");
stateLoop->addIncoming(rangeFrom, blockBeforeLoop);
// loop body:
Value* elIn = it->get(stateLoop, varEl);
compilation::ICodeScopeUnit* scopeLoopUnit = function->getScopeUnit(scopeLoop);
scopeLoopUnit->bindArg(elIn, move(varEl));
Value* elOut = scopeLoopUnit->compile();
Value *pElOut = builder.CreateGEP(dataOut, ArrayRef<Value *>(std::vector<Value*>{ConstantInt::get(tyNum, 0), stateLoop}));
builder.CreateStore(elOut, pElOut);
//next iteration preparing
Value *stateLoopNext = builder.CreateAdd(stateLoop, llvm::ConstantInt::get(tyNum, 1));
stateLoop->addIncoming(stateLoopNext, builder.GetInsertBlock());
//next iteration checks:
Value* condAfter = builder.CreateICmpSLE(stateLoopNext, rangeTo);
builder.CreateCondBr(condAfter, blockLoop, blockAfterLoop);
//finalization:
builder.SetInsertPoint(blockAfterLoop);
return dataOut;
}
Value*
AdvancedInstructions::compileArrayIndex(llvm::Value* aggregate, std::vector<llvm::Value *> indexes, std::string hintRetVar) {
EXPAND_CONTEXT UNUSED(function); UNUSED(scope);
indexes.insert(indexes.begin(), llvm::ConstantInt::get(tyNum, 0));
llvm::Value *pEl = llvm->builder.CreateGEP(aggregate, llvm::ArrayRef<llvm::Value *>(indexes));
return llvm->builder.CreateLoad(pEl, NAME("el"));
}
Value*
AdvancedInstructions::compileStructIndex(llvm::Value* aggregate, const ExpandedType& t, const std::string& idx) {
EXPAND_CONTEXT UNUSED(scope); UNUSED(function);
TypeUtils types(llvm);
std::vector<std::string>&& fields = types.getStructFields(t);
for (unsigned i = 0, size = fields.size(); i < size; ++i) {
if (fields.at(i) == idx) {
//dereference pointer
if (types.isPointer(t)) {
llvm::Value* addr = llvm->builder.CreateConstGEP2_32(nullptr, aggregate, 0, i);
return llvm->builder.CreateLoad(addr);
}
return llvm->builder.CreateExtractValue(aggregate, llvm::ArrayRef<unsigned>{i});
}
}
assert(false && "not found required struct field");
return nullptr;
}
llvm::Value*
AdvancedInstructions::compileFold(const Expression& fold, const std::string& hintRetVar) {
EXPAND_CONTEXT
assert(fold.op == Operator::FOLD);
//initialization:
Symbol varInSymbol = Attachments::get<IdentifierSymbol>(fold.getOperands()[0]);
Implementation info = Query::queryImplementation(varInSymbol);
Iterator* it = Iterator::create(context, varInSymbol);
llvm::Value* rangeBegin = it->begin();
llvm::Value* rangeEnd = it->end();
llvm::Value* accumInit = scope->process(fold.getOperands()[1]);
std::string varIn = fold.getOperands()[0].getValueString();
std::string varAccum = fold.bindings[1];
std::string varEl = fold.bindings[0];
llvm::BasicBlock *blockBeforeLoop = llvm->builder.GetInsertBlock();
std::unique_ptr<TransformerSaturation> transformerSaturation(new TransformerSaturation(blockBeforeLoop, context.pass->managerTransformations));
llvm::BasicBlock *blockLoop = llvm::BasicBlock::Create(llvm->llvmContext, "fold", function->raw);
llvm::BasicBlock *blockLoopBody = llvm::BasicBlock::Create(llvm->llvmContext, "fold_body", function->raw);
llvm::BasicBlock *blockAfterLoop = llvm::BasicBlock::Create(llvm->llvmContext, "fold_after", function->raw);
llvm::BasicBlock *blockNext = llvm::BasicBlock::Create(llvm->llvmContext, "fold_next", function->raw);
llvm->builder.CreateBr(blockLoop);
// * create phi
llvm->builder.SetInsertPoint(blockLoop);
llvm::PHINode *accum = llvm->builder.CreatePHI(accumInit->getType(), 2, varAccum);
accum->addIncoming(accumInit, blockBeforeLoop);
llvm::PHINode *itLoop = llvm->builder.CreatePHI(rangeBegin->getType(), 2, "foldIt");
itLoop->addIncoming(rangeBegin, blockBeforeLoop);
// * loop checks
Value* condRange = llvm->builder.CreateICmpNE(itLoop, rangeEnd);
llvm->builder.CreateCondBr(condRange, blockLoopBody, blockAfterLoop);
// * loop body
llvm->builder.SetInsertPoint(blockLoopBody);
CodeScope* scopeLoop = fold.blocks.front();
compilation::ICodeScopeUnit* loopUnit = function->getScopeUnit(scopeLoop);
Value* elIn = it->get(itLoop);
loopUnit->bindArg(accum, move(varAccum));
loopUnit->bindArg(elIn, move(varEl));
Value* accumNext = loopUnit->compile();
// * Loop saturation checks
bool flagSaturationTriggered = transformerSaturation->insertSaturationChecks(blockNext, blockAfterLoop, context);
llvm::BasicBlock* blockSaturation = llvm->builder.GetInsertBlock();
if (!flagSaturationTriggered){
llvm->builder.CreateBr(blockNext);
}
// * computing next iteration state
llvm->builder.SetInsertPoint(blockNext);
Value *itLoopNext = it->advance(itLoop);
accum->addIncoming(accumNext, llvm->builder.GetInsertBlock());
itLoop->addIncoming(itLoopNext, llvm->builder.GetInsertBlock());
llvm->builder.CreateBr(blockLoop);
// * finalization:
llvm->builder.SetInsertPoint(blockAfterLoop);
if (!flagSaturationTriggered){
return accum;
}
llvm::PHINode* result = llvm->builder.CreatePHI(accumInit->getType(), 2);
result->addIncoming(accum, blockLoop);
result->addIncoming(accumNext, blockSaturation);
return result;
}
llvm::Value*
AdvancedInstructions::compileFoldInf(const Expression& fold, const std::string& hintRetVar) {
EXPAND_CONTEXT
assert(fold.op == Operator::INF);
std::string accumName = fold.bindings[0];
llvm::Value* accumInit = scope->process(fold.getOperands()[0]);
llvm::BasicBlock *blockBeforeLoop = llvm->builder.GetInsertBlock();
llvm::BasicBlock *blockLoop = llvm::BasicBlock::Create(llvm->llvmContext, "foldinf", function->raw);
llvm::BasicBlock *blockNext = llvm::BasicBlock::Create(llvm->llvmContext, "foldinf_next", function->raw);
llvm::BasicBlock *blockAfterLoop = llvm::BasicBlock::Create(llvm->llvmContext, "foldinf_post", function->raw);
std::unique_ptr<TransformerSaturation> transformerSaturation(new TransformerSaturation(blockBeforeLoop, context.pass->managerTransformations));
llvm->builder.CreateBr(blockLoop);
// * create phi
llvm->builder.SetInsertPoint(blockLoop);
llvm::PHINode *accum = llvm->builder.CreatePHI(accumInit->getType(), 2, accumName);
accum->addIncoming(accumInit, blockBeforeLoop);
// * loop body
CodeScope* scopeLoop = fold.blocks.front();
compilation::ICodeScopeUnit* unitLoop = function->getScopeUnit(scopeLoop);
unitLoop->bindArg(accum, move(accumName));
Value* accumNext = unitLoop->compile();
// * Loop saturation checks
bool flagSaturationTriggered = transformerSaturation->insertSaturationChecks(blockNext, blockAfterLoop, context);
assert(flagSaturationTriggered);
// * computing next iteration state
llvm->builder.SetInsertPoint(blockNext);
accum->addIncoming(accumNext, llvm->builder.GetInsertBlock());
llvm->builder.CreateBr(blockLoop);
// finalization:
llvm->builder.SetInsertPoint(blockAfterLoop);
return accumNext;
}
llvm::Value*
AdvancedInstructions::compileIf(const Expression& exprIf, const std::string& hintRetVar) {
EXPAND_CONTEXT
const Expression& condExpr = exprIf.getOperands()[0];
llvm::IRBuilder<>& builder = llvm->builder;
assert(builder.GetInsertBlock() == scope->currentBlockRaw);
//initialization:
llvm::BasicBlock *blockEpilog = llvm::BasicBlock::Create(llvm->llvmContext, "ifAfter", function->raw);
llvm::BasicBlock *blockTrue = llvm::BasicBlock::Create(llvm->llvmContext, "ifTrue", function->raw);
llvm::BasicBlock *blockFalse = llvm::BasicBlock::Create(llvm->llvmContext, "ifFalse", function->raw);
llvm::Value* cond = scope->process(condExpr);
builder.SetInsertPoint(blockTrue);
CodeScope* scopeTrue = exprIf.blocks.front();
llvm::Value* resultTrue = function->getScopeUnit(scopeTrue)->compile();
llvm::BasicBlock * blockTrueEnd = builder.GetInsertBlock();
builder.CreateBr(blockEpilog);
builder.SetInsertPoint(blockFalse);
CodeScope* scopeFalse = exprIf.blocks.back();
llvm::Value* resultFalse = function->getScopeUnit(scopeFalse)->compile();
llvm::BasicBlock * blockFalseEnd = builder.GetInsertBlock();
builder.CreateBr(blockEpilog);
builder.SetInsertPoint(scope->currentBlockRaw);
llvm->builder.CreateCondBr(cond, blockTrue, blockFalse);
builder.SetInsertPoint(blockEpilog);
llvm::PHINode *ret = builder.CreatePHI(resultTrue->getType(), 2, NAME("if"));
ret->addIncoming(resultTrue, blockTrueEnd);
ret->addIncoming(resultFalse, blockFalseEnd);
return ret;
}
//TODO Switch: default variant no needed when all possible conditions are considered
llvm::Value*
AdvancedInstructions::compileSwitch(const Expression& exprSwitch, const std::string& hintRetVar) {
EXPAND_CONTEXT UNUSED(function);
AST* root = context.pass->man->root;
llvm::IRBuilder<>& builder = llvm->builder;
assert(exprSwitch.operands.size() >= 2);
assert(exprSwitch.operands[1].op == Operator::CASE_DEFAULT && "No default case in Switch Statement");
int countCases = exprSwitch.operands.size() - 1;
llvm::BasicBlock* blockProlog = builder.GetInsertBlock();
llvm::BasicBlock *blockEpilog = llvm::BasicBlock::Create(llvm->llvmContext, "switchAfter", function->raw);
builder.SetInsertPoint(blockEpilog);
llvm::Type* exprSwitchType = llvm->toLLVMType(root->getType(exprSwitch));
llvm::PHINode *ret = builder.CreatePHI(exprSwitchType, countCases, NAME("switch"));
llvm::Type* typI8 = llvm::Type::getInt8Ty(llvm->llvmContext);
builder.SetInsertPoint(blockProlog);
llvm::Value * conditionSwitch = scope->process(exprSwitch.operands[0]);
llvm::BasicBlock *blockDefault = llvm::BasicBlock::Create(llvm->llvmContext, "caseDefault", function->raw);
llvm::SwitchInst * instructionSwitch = builder.CreateSwitch(
typeinference::doAutomaticTypeConversion(conditionSwitch, typI8, builder),
blockDefault,
countCases);
for (int size = exprSwitch.operands.size(), i = 2; i < size; ++i) {
llvm::BasicBlock *blockCase = llvm::BasicBlock::Create(llvm->llvmContext, "case" + std::to_string(i), function->raw);
llvm::Value* condCase = function->getScopeUnit(exprSwitch.operands[i].blocks.front())->compile();
builder.SetInsertPoint(blockCase);
llvm::Value* resultCase = function->getScopeUnit(exprSwitch.operands[i].blocks.back())->compile();
builder.CreateBr(blockEpilog);
ret->addIncoming(resultCase, builder.GetInsertBlock());
builder.SetInsertPoint(blockProlog);
instructionSwitch->addCase(
dyn_cast<llvm::ConstantInt>(
typeinference::doAutomaticTypeConversion(condCase, typI8, builder)),
blockCase);
}
//compile default block:
builder.SetInsertPoint(blockDefault);
CodeScope* scopeDefault = exprSwitch.operands[1].blocks.front();
llvm::Value* resultDefault = function->getScopeUnit(scopeDefault)->compile();
builder.CreateBr(blockEpilog);
ret->addIncoming(resultDefault, builder.GetInsertBlock());
builder.SetInsertPoint(blockEpilog);
return ret;
}
llvm::Value*
AdvancedInstructions::compileSwitchVariant(const Expression& exprSwitch, const std::string& hintRetVar) {
EXPAND_CONTEXT UNUSED(function);
AST* root = context.pass->man->root;
llvm::IRBuilder<>& builder = llvm->builder;
llvm::Type* typI8= llvm::Type::getInt8Ty(llvm->llvmContext);
const ExpandedType& typVariant = root->getType(exprSwitch.operands.at(0));
llvm::Type* typVariantRaw = llvm->toLLVMType(typVariant);
assert(typVariant->__operands.size() == exprSwitch.operands.size() - 1 && "Ill-formed Switch Variant");
int casesCount = exprSwitch.operands.size();
llvm::BasicBlock* blockProlog = builder.GetInsertBlock();
llvm::BasicBlock *blockEpilog = llvm::BasicBlock::Create(llvm->llvmContext, "switchAfter", function->raw);
builder.SetInsertPoint(blockEpilog);
llvm::Type* resultType = llvm->toLLVMType(root->getType(exprSwitch));
llvm::PHINode *ret = builder.CreatePHI(resultType, casesCount, NAME("switch"));
builder.SetInsertPoint(blockProlog);
llvm::Value * conditionSwitchRaw = scope->process(exprSwitch.operands.at(0));
llvm::Value* idRaw = builder.CreateExtractValue(conditionSwitchRaw, llvm::ArrayRef<unsigned>({0}));
//Dereference preparation
const bool flagPrepareDerefence = std::any_of(typVariant->__operands.begin(), typVariant->__operands.end(), [](const TypeAnnotation& op){
return op.isValid();
});
llvm::Value* addrAsStorage = nullptr;
if (flagPrepareDerefence){
assert(exprSwitch.bindings.size() && "Switch condition alias not found");
llvm::Type* typStorageRaw = llvm::cast<llvm::StructType>(typVariantRaw)->getElementType(1);
llvm::Value* storageRaw = builder.CreateExtractValue(conditionSwitchRaw, llvm::ArrayRef<unsigned>({1}));
addrAsStorage = llvm->builder.CreateAlloca(typStorageRaw);
llvm->builder.CreateStore(storageRaw, addrAsStorage);
}
llvm::SwitchInst * instructionSwitch = builder.CreateSwitch(idRaw, nullptr, casesCount);
llvm::BasicBlock* blockDefaultUndefined;
std::list<CodeScope*>::const_iterator scopeCaseIt = exprSwitch.blocks.begin();
for (int instancesSize = exprSwitch.operands.size()-1, instId = 0; instId < instancesSize; ++instId) {
llvm::BasicBlock *blockCase = llvm::BasicBlock::Create(llvm->llvmContext, "case" + std::to_string(instId), function->raw);
builder.SetInsertPoint(blockCase);
ICodeScopeUnit* unitCase = function->getScopeUnit(*scopeCaseIt);
const ExpandedType& instType = ExpandedType(typVariant->__operands.at(instId));
//Actual variant derefence
if (instType->isValid()) {
string identCondition = exprSwitch.bindings.front();
llvm::Type* instTypeRaw = llvm->toLLVMType(instType);
llvm::Value* addrAsInst = llvm->builder.CreateBitOrPointerCast(addrAsStorage, instTypeRaw->getPointerTo());
llvm::Value* instRaw = llvm->builder.CreateLoad(instTypeRaw, addrAsInst);
const Symbol& identSymb = unitCase->bindArg(instRaw, move(identCondition));
Attachments::put<TypeInferred>(identSymb, instType);
}
llvm::Value* resultCase = function->getScopeUnit(*scopeCaseIt)->compile();
builder.CreateBr(blockEpilog);
ret->addIncoming(resultCase, blockDefaultUndefined = builder.GetInsertBlock());
builder.SetInsertPoint(blockProlog);
instructionSwitch->addCase(dyn_cast<llvm::ConstantInt>(llvm::ConstantInt::get(typI8, exprSwitch.operands.at(instId+1).getValueDouble())), blockCase);
++scopeCaseIt;
}
instructionSwitch->setDefaultDest(blockDefaultUndefined);
builder.SetInsertPoint(blockEpilog);
return ret;
}
//TODO recognize cases to make const arrays/stored in global mem/stack alloced.
llvm::Value*
AdvancedInstructions::compileListAsSolidArray(const Expression &expr, const std::string& hintRetVar) {
EXPAND_CONTEXT UNUSED(scope); UNUSED(function);
AST* root = context.pass->man->root;
const size_t& length = expr.getOperands().size();
const Expression& expression = expr;
llvm::Value* zero = ConstantInt::get(tyNum, 0);
llvm::Value* one = ConstantInt::get(tyNum, 1);
ExpandedType typAggrExpanded = root->getType(expression);
assert(typAggrExpanded->__operator == TypeOperator::LIST_ARRAY);
llvm::Type* typEl = llvm->toLLVMType(ExpandedType(typAggrExpanded->__operands[0]));
ArrayType* typAggr = (ArrayType*) llvm::ArrayType::get(typEl, length);
llvm::Value* list = llvm->builder.CreateAlloca(typAggr, ConstantInt::get(Type::getInt32Ty(llvm->llvmContext), length, false), hintRetVar);
const std::vector<Expression>& operands = expression.getOperands();
llvm::Value* addrOperand = llvm->builder.CreateGEP(typAggr, list, ArrayRef<Value *>(std::vector<Value*>{zero, zero}));
llvm->builder.CreateStore(scope->process(operands.front()), addrOperand) ;
for (auto i=++operands.begin(); i!=operands.end(); ++i){
addrOperand = llvm->builder.CreateGEP(typEl, addrOperand, ArrayRef<Value *>(std::vector<Value*>{one}));
llvm->builder.CreateStore(scope->process(*i), addrOperand) ;
}
return list;
// Value* listDest = l.builder.CreateAlloca(typList, ConstantInt::get(typI32, __size), *hintRetVar);
// l.buil1der.CreateMemCpy(listDest, listSource, __size, 16);
}
llvm::Value*
AdvancedInstructions::compileConstantStringAsPChar(const string& data, const std::string& hintRetVar) {
EXPAND_CONTEXT UNUSED(function); UNUSED(scope);
Type* typPchar = PointerType::getUnqual(Type::getInt8Ty(llvm->llvmContext));
//ArrayType* typStr = (ArrayType*) (llvm->toLLVMType(ExpandedType(TypeAnnotation(tag_array, TypePrimitive::I8, size+1))));
/*
std::vector<Constant *> chars;
chars.reserve(size+1);
for (size_t i=0; i< size; ++i){
chars[i] = ConstantInt::get(typI8, (unsigned char) data[i]);
}
chars[size] = ConstantInt::get(typI8, 0);
*/
Value* rawData = ConstantDataArray::getString(llvm->llvmContext, data);
Value* rawPtrData = llvm->builder.CreateAlloca(rawData->getType(), ConstantInt::get(Type::getInt32Ty(llvm->llvmContext), 1, false));
llvm->builder.CreateStore(rawData, rawPtrData);
return llvm->builder.CreateCast(llvm::Instruction::BitCast, rawPtrData, typPchar, hintRetVar);
}
llvm::Value*
AdvancedInstructions::compileSequence(const Expression &expr){
EXPAND_CONTEXT UNUSED(scope); UNUSED(llvm);
llvm::Value* result;
for(CodeScope* scope: expr.blocks){
result = function->getScopeUnit(scope)->compile();
}
return result;
}
diff --git a/cpp/src/compilation/advancedinstructions.h b/cpp/src/compilation/advancedinstructions.h
index 7b0fbfb..4826c2f 100644
--- a/cpp/src/compilation/advancedinstructions.h
+++ b/cpp/src/compilation/advancedinstructions.h
@@ -1,52 +1,79 @@
/* 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: AdvancedInstructions.h
* Author: pgess <v.melnychenko@xreate.org>
*
* Created on June 26, 2016, 6:00 PM
*/
+/**
+ * \file advancedinstructions.h
+ * \brief Compound statements compilation
+ */
+
#ifndef INSTRUCTIONSADVANCED_H
#define INSTRUCTIONSADVANCED_H
#include "ast.h"
#include "llvmlayer.h"
#include "pass/compilepass.h"
#include <vector>
namespace xreate {
namespace compilation {
+ /** \brief Advanced compilation primitives */
class AdvancedInstructions {
public:
AdvancedInstructions(compilation::Context ctx);
+
+ /** \brief Array subscript access operator compilation*/
llvm::Value* compileArrayIndex(llvm::Value* aggregate, std::vector<llvm::Value *> indexes, std::string ident = "");
+
+ /** \brief Struct field access operator compilation*/
llvm::Value* compileStructIndex(llvm::Value* aggregate, const ExpandedType& t, const std::string& idx);
/*
* - map Computation -> Llvm_Array: Prohibited, we do not know a result size
* - map Llvm_Array -> Computation: considered in `compileGetElement`
* - map Llvm_Array -> Llvm_Array considered by this method
*/
+
+ /** \brief `loop map` statement compilation*/
llvm::Value* compileMapSolidOutput(const Expression &expr, const std::string hintRetVar = "");
+
+ /** \brief `loop fold` statement compilation*/
llvm::Value* compileFold(const Expression& fold, const std::string& ident="");
+
+ /** \brief `loop` statement compilation*/
llvm::Value* compileFoldInf(const Expression& fold, const std::string& ident="");
+ /** \brief `if` statement compilation*/
llvm::Value* compileIf(const Expression& exprIf, const std::string& ident);
+
+ /** \brief `switch` statement compilation*/
llvm::Value* compileSwitch(const Expression& exprSwitch, const std::string& hintRetVar);
+
+ /** \brief `switch` statement compilation*/
llvm::Value* compileSwitchVariant(const Expression& exprSwitch, const std::string& hintRetVar);
+
+ /** \brief `switch variant` statement compilation*/
llvm::Value* compileConstantStringAsPChar(const std::string &data, const std::string& hintRetVar);
+
+ /** \brief Contiguous memory list implementation*/
llvm::Value* compileListAsSolidArray(const Expression &expr, const std::string& hintRetVar);
+
+ /** \brief `seq` statement compilation */
llvm::Value* compileSequence(const Expression &expr);
private:
compilation::Context context;
llvm::IntegerType* const tyNum;
};
}}
#endif /* INSTRUCTIONSADVANCED_H */
diff --git a/cpp/src/compilation/containers.cpp b/cpp/src/compilation/containers.cpp
index ae85604..eb6c3f5 100644
--- a/cpp/src/compilation/containers.cpp
+++ b/cpp/src/compilation/containers.cpp
@@ -1,206 +1,208 @@
/* 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: containers.cpp
* Author: pgess <v.melnychenko@xreate.org>
- *
+ */
+
+/**
* \file compilation/containers.h
- * \brief Containers compilation support. See more [details on Containers](/w/concepts/containers)
+ * \brief Containers compilation support. See [Containers](/d/concepts/containers/) in the Xreate's documentation.
*/
#include "compilation/containers.h"
using namespace std;
using namespace llvm;
using namespace xreate;
using namespace xreate::containers;
Iterator*
Iterator::create(xreate::compilation::Context context, const xreate::Symbol& var){
const Implementation& data = Query::queryImplementation(var);
switch(data.impl){
case ON_THE_FLY:
return new IteratorForward<ON_THE_FLY>(context, var, data.extract<ON_THE_FLY>());
case SOLID:
return new IteratorForward<SOLID>(context, var, data.extract<SOLID>());
default: assert(true);
}
assert(false && "Unknown declaration");
return nullptr;
}
llvm::Value*
IteratorForward<ON_THE_FLY>::begin() {
switch(sourceDecl.op) {
case xreate::Operator::LIST:
{
sourceRawType = llvm::Type::getInt32Ty(llvm->llvmContext);
return llvm::ConstantInt::get(Type::getInt32Ty(llvm->llvmContext), 0);
};
case xreate::Operator::LIST_RANGE:{
assert(sourceDecl.operands.size()==2);
llvm::Value* result = sourceUnit->process(sourceDecl.operands.at(0));
sourceRawType = result->getType();
return result;
};
default: break;
}
if (linkedlist){
llvm::Value* result = sourceUnit->process(sourceDecl);
sourceRawType = result->getType();
return result;
}
assert(false);
}
llvm::Value*
IteratorForward<ON_THE_FLY>::end(){
switch(sourceDecl.op) {
case xreate::Operator::LIST: {
size_t idLast = sourceDecl.operands.size() - 1;
return ConstantInt::get(sourceRawType, idLast);
}
case xreate::Operator::LIST_RANGE: {
assert(sourceDecl.operands.size() == 2);
llvm::Value* valueEndOfRange = sourceUnit->process(sourceDecl.operands.at(1));
llvm::Value* valueConstOne = llvm::ConstantInt::get(llvm::Type::getInt32Ty(llvm->llvmContext), 1);
return llvm->builder.CreateAdd(valueEndOfRange, valueConstOne);
};
default: break;
}
//return null pointer
if (linkedlist){
return ConstantPointerNull::getNullValue(sourceRawType);
}
assert(false && "Unknown declaration");
return nullptr;
}
llvm::Value*
IteratorForward<ON_THE_FLY>::get(Value* index,const std::string& hintRetVar){
const Expression& currentDecl = CodeScope::getDefinition(current);
switch (currentDecl.op) {
case xreate::Operator::LIST: {
//TODO re check is it right scope(source) to compile currentDecl. Provide unittests.
llvm::Value* currentValue = sourceUnit->processSymbol(current);
return xreate::compilation::AdvancedInstructions(context).compileArrayIndex(currentValue, std::vector<Value *>{index});
};
case xreate::Operator::LIST_RANGE: {
return index;
};
case xreate::Operator::MAP: {
assert(currentDecl.getOperands().size()==1);
assert(currentDecl.bindings.size());
assert(currentDecl.blocks.size());
CodeScope* scopeLoop = currentDecl.blocks.front();
std::string varEl = currentDecl.bindings[0];
const Symbol& symbIn = Attachments::get<IdentifierSymbol>(currentDecl.getOperands()[0]);
auto it = std::unique_ptr<Iterator>(Iterator::create(context, symbIn));
Value* elIn = it->get(index, varEl);
compilation::ICodeScopeUnit* unitLoop = function->getScopeUnit(scopeLoop);
unitLoop->bindArg(elIn, std::move(varEl));
return unitLoop->compile();
}
case xreate::Operator::INVALID: {
//TODO review iterator determination strategy for case of Expression::BINDING
assert(currentDecl.__state==Expression::IDENT);
const Symbol& symbIn = Attachments::get<IdentifierSymbol>(currentDecl);
auto it = std::unique_ptr<Iterator>(Iterator::create(context, symbIn));
return it->get(index);
};
default: break;
}
if (linkedlist){
return index;
}
assert(false && "Unknown declaration");
return nullptr;
}
llvm::Value*
IteratorForward<ON_THE_FLY>::advance(Value* index, const std::string& hintRetVar){
switch(sourceDecl.op)
{
case xreate::Operator::LIST:
case xreate::Operator::LIST_RANGE:
return llvm->builder.CreateAdd(index, llvm::ConstantInt::get(llvm::Type::getInt32Ty(llvm->llvmContext), 1), hintRetVar);
default: break;
}
if (linkedlist){
ExpandedType tySource = llvm->ast->getType(CodeScope::getDefinition(source));
assert(tySource->__operator == TypeOperator::LIST_ARRAY && "Linked list implementation has to have ARRAY type");
assert(tySource->__operands.size());
return xreate::compilation::AdvancedInstructions(context).compileStructIndex(index, ExpandedType(TypeAnnotation(tySource->__operands.at(0))), linkedlist.fieldPointer);
}
assert(false && "Unknown declaration");
return nullptr;
}
//const ImplementationRec<ON_THE_FLY>& implementation
IteratorForward<SOLID>::IteratorForward(const compilation::Context& ctx, const xreate::Symbol& symbolContainer, const ImplementationRec<SOLID>& implementation)
: Iterator(), __length(implementation.size), llvm(ctx.pass->man->llvm)
{
__container = ctx.function->getScopeUnit(symbolContainer.scope)->processSymbol(symbolContainer);
}
llvm::Value*
IteratorForward<SOLID>::begin(){
//0
return llvm::ConstantInt::get(llvm::Type::getInt32Ty(llvm->llvmContext), 0);
}
llvm::Value*
IteratorForward<SOLID>::end(){
//length
return llvm::ConstantInt::get(llvm::Type::getInt32Ty(llvm->llvmContext), __length);
}
llvm::Value*
IteratorForward<SOLID>::get(llvm::Value* index,const std::string& hintRetVar){
//GEP[index]]
llvm::Type* tyNum = llvm::Type::getInt32Ty(llvm->llvmContext);
llvm::Value* pResult = llvm->builder.CreateGEP(__container, ArrayRef<Value *>(std::vector<Value*>{ConstantInt::get(tyNum, 0), index}));
return llvm->builder.CreateLoad(pResult, hintRetVar);
}
llvm::Value*
IteratorForward<SOLID>::advance(llvm::Value* index, const std::string& hintRetVar){
//index + 1
llvm::Type* tyNum = llvm::Type::getInt32Ty(llvm->llvmContext);
return llvm->builder.CreateAdd(index, llvm::ConstantInt::get(tyNum, 1), hintRetVar);
}
diff --git a/cpp/src/compilation/containers.h b/cpp/src/compilation/containers.h
index bd8a4fc..893b387 100644
--- a/cpp/src/compilation/containers.h
+++ b/cpp/src/compilation/containers.h
@@ -1,96 +1,100 @@
/* 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: containers.h
* Author: pgess <v.melnychenko@xreate.org>
*/
#ifndef CODEINSTRUCTIONS_H
#define CODEINSTRUCTIONS_H
#include "ast.h"
#include "llvmlayer.h"
#include "pass/compilepass.h"
#include "compilation/advancedinstructions.h"
#include "query/containers.h"
namespace xreate {
namespace containers {
using namespace llvm;
-/** \brief Factory to create relevant iterator based on solution
- * provided by xreate::containers::Query
+/**
+ * \brief A factory to create a concrete iterator based on the solution provided by xreate::containers::Query
* \sa xreate::containers::Query
*/
class Iterator{
public :
virtual llvm::Value* begin() =0;
virtual llvm::Value* end() = 0;
virtual llvm::Value* get(llvm::Value* index,const std::string& hintRetVar="") = 0;
virtual llvm::Value* advance(llvm::Value* index, const std::string& hintRetVar="")=0;
virtual ~Iterator(){};
static Iterator* create(xreate::compilation::Context context, const xreate::Symbol& var);
};
template<ImplementationType I>
class IteratorForward;
-/** \brief Possible container implementation. Represents computation on the fly
+/** \brief The lazy container implementation.
+ *
+ * Represents computation on the fly.
* \sa xreate::containers::Iterator, \sa xreate::containers::Query
*/
template<>
class IteratorForward<ON_THE_FLY> : public Iterator {
private:
LLVMLayer* llvm;
const xreate::Symbol current;
const Symbol source;
const ImplementationLinkedList linkedlist;
const CodeScope* const sourceScope;
//TODO initialize and mark as const (three fields)
compilation::ICodeScopeUnit* sourceUnit;
compilation::IFunctionUnit* function; //TODO is used somewhere?
const Expression& sourceDecl;
compilation::Context context;
llvm::Type* sourceRawType =nullptr;
public:
IteratorForward(const compilation::Context& ctx, const xreate::Symbol& s, const ImplementationRec<ON_THE_FLY>& implementation)
: llvm(ctx.pass->man->llvm),
current(s),
source(implementation.source),
linkedlist(source),
sourceScope(source.scope),
sourceUnit(ctx.function->getScopeUnit(source.scope)),
sourceDecl(CodeScope::getDefinition(source)),
context(ctx)
{}
llvm::Value* begin() override;
llvm::Value* end() override;
llvm::Value* get(llvm::Value* index,const std::string& hintRetVar="") override;
llvm::Value* advance(llvm::Value* index, const std::string& hintRetVar="") override;
};
-/** \brief Possible container implementation. Represents contiguous in memory(array) implementation
+/** \brief The contiguous container implementation.
+ *
+ * Represents contiguous in memory(array) implementation.
* \sa xreate::containers::Iterator, \sa xreate::containers::Query
*/
template<>
class IteratorForward<SOLID>: public Iterator{
size_t __length;
llvm::Value* __container;
LLVMLayer* llvm;
public:
IteratorForward(const compilation::Context& ctx, const xreate::Symbol& symbolContainer, const ImplementationRec<SOLID>& implementation);
llvm::Value* begin() override;
llvm::Value* end() override;
llvm::Value* get(llvm::Value* index,const std::string& hintRetVar="") override;
llvm::Value* advance(llvm::Value* index, const std::string& hintRetVar="") override;
};
}}
#endif //CODEINSTRUCTIONS_H
diff --git a/cpp/src/compilation/interpretation-instructions.cpp b/cpp/src/compilation/interpretation-instructions.cpp
index 5ad4ffb..f4387bd 100644
--- a/cpp/src/compilation/interpretation-instructions.cpp
+++ b/cpp/src/compilation/interpretation-instructions.cpp
@@ -1,116 +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 "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));
}
}
}
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) {
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);
}
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/interpretation-instructions.h b/cpp/src/compilation/interpretation-instructions.h
index 284b094..951fa0e 100644
--- a/cpp/src/compilation/interpretation-instructions.h
+++ b/cpp/src/compilation/interpretation-instructions.h
@@ -1,46 +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 June 15, 2018, 5:28 PM
- *
+ */
+
+/**
* \file interpretation-instructions.h
- * \brief Additional intepretation statements
+ * \brief The interpretation related statements
*/
#ifndef INTERPRETATION_INSTRUCTIONS_H
#define INTERPRETATION_INSTRUCTIONS_H
#include "ast.h"
namespace xreate{
namespace compilation{
class Context;
}
}
namespace xreate{
namespace interpretation{
class InterpretationFunction;
+/** \brief `intrinsic query` statement */
class IntrinsicQueryInstruction{
public:
-
IntrinsicQueryInstruction(InterpretationFunction* fn): __fnI12n(fn){ }
+
+ /** \brief Processes `intrinsic query` instruction */
Expression process(const Expression& expression);
+
+ /** \brief Processes `intrinsic query late` instruction */
llvm::Value* processLate(const Expression& expression, const compilation::Context& context);
private:
InterpretationFunction* __fnI12n;
};
}
} //end of xreate::interpretation
#endif /* INTERPRETATION_INSTRUCTIONS_H */
diff --git a/cpp/src/compilation/latereasoning.cpp b/cpp/src/compilation/latetranscend.cpp
similarity index 97%
rename from cpp/src/compilation/latereasoning.cpp
rename to cpp/src/compilation/latetranscend.cpp
index 4b32156..54ce3e7 100644
--- a/cpp/src/compilation/latereasoning.cpp
+++ b/cpp/src/compilation/latetranscend.cpp
@@ -1,179 +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
*/
-#include "compilation/latereasoning.h"
+/**
+ * \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>
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/latereasoning.h b/cpp/src/compilation/latetranscend.h
similarity index 93%
rename from cpp/src/compilation/latereasoning.h
rename to cpp/src/compilation/latetranscend.h
index 7dc6d59..a2df895 100644
--- a/cpp/src/compilation/latereasoning.h
+++ b/cpp/src/compilation/latetranscend.h
@@ -1,72 +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;
+/** \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 b853fd8..9a4d11e 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 latex.cpp
- * \brief latex
+ */
+
+/**
+ * \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);
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 339b82e..e35ffeb 100644
--- a/cpp/src/compilation/latex.h
+++ b/cpp/src/compilation/latex.h
@@ -1,140 +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/latereasoning.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)-enabled decorator for IFunctionUnit
- * \extends IFunctionUnit
+/** \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 Expression& decisionE = interpretation::representTransExpression(
decisionRaw.args()[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/operators.cpp b/cpp/src/compilation/operators.cpp
index 5ad1983..087b766 100644
--- a/cpp/src/compilation/operators.cpp
+++ b/cpp/src/compilation/operators.cpp
@@ -1,75 +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/.
*
* operators.cpp
*
* Author: pgess <v.melnychenko@xreate.org>
* Created on April 8, 2017, 1:35 PM
*/
-/**
- * \file operators.h
- * \brief Helpers to compile various operators
- */
-
#include "operators.h"
#include "llvmlayer.h"
#include "ExternLayer.h"
#include <vector>
using namespace llvm;
using namespace std;
namespace xreate {
namespace pointerarithmetic {
+
llvm::Value*
PointerArithmetic::add(llvm::Value *left, llvm::Value *right, compilation::Context context, const std::string& hintVarDecl){
LLVMLayer* llvm = context.pass->man->llvm;
if (left->getType()->isPointerTy() && right->getType()->isIntegerTy()){
std::vector<llvm::Value*> indexes{right};
//{llvm::ConstantInt::get(llvm::Type::getInt32Ty(llvm::getGlobalContext()), 0)};
//indexes.push_back(right);
return llvm->builder.CreateGEP(left, llvm::ArrayRef<llvm::Value*>(indexes), hintVarDecl);
}
return nullptr;
}
}//end of pointgerarithmetic namespace
llvm::Value*
StructUpdate::add(const Expression& left, llvm::Value *leftRaw, const Expression& right, compilation::Context context, const std::string& hintVarDecl){\
if (!(right.__state == Expression::COMPOUND && right.op == Operator::LIST)){
return nullptr;
}
PassManager* man = context.pass->man;
ExpandedType tyOperandLeft = man->root->getType(left);
const std::vector<string> fieldsFormal = (tyOperandLeft.get().__operator == TypeOperator::CUSTOM)?
man->llvm->layerExtern->getStructFields(man->llvm->layerExtern->lookupType(tyOperandLeft.get().__valueCustom))
: tyOperandLeft.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::Value* result = leftRaw;
for (size_t i=0; i<right.operands.size(); ++i){
const Expression& value = right.operands.at(i);
llvm::Value* valueRaw = context.scope->process(value, right.bindings.at(i));
unsigned int fieldId = indexFields.at(right.bindings.at(i));
result = man->llvm->builder.CreateInsertValue(result, valueRaw, llvm::ArrayRef<unsigned>({fieldId}));
}
return result;
}
} //end of xreate namespace
diff --git a/cpp/src/compilation/operators.h b/cpp/src/compilation/operators.h
index d465944..51a0448 100644
--- a/cpp/src/compilation/operators.h
+++ b/cpp/src/compilation/operators.h
@@ -1,36 +1,46 @@
/* 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: operators.h
* Author: pgess <v.melnychenko@xreate.org>
*
* Created on April 8, 2017, 1:33 PM
*/
+/**
+ * \file operators.h
+ * \brief Helpers to compile various operators
+ */
+
#ifndef OPERATORS_H
#define OPERATORS_H
#include "pass/compilepass.h"
-namespace llvm {
- class Value;
+namespace llvm{
+ class Value;
}
-namespace xreate {
-
-namespace pointerarithmetic {
- class PointerArithmetic {
- public:
- static llvm::Value* add(llvm::Value *left, llvm::Value *right, compilation::Context context, const std::string& hintVarDecl);
- };
-} //end of pointerarithmetic namespace
+namespace xreate{ namespace pointerarithmetic{
-class StructUpdate {
+/** \brief Pointer arithmetic operators */
+class PointerArithmetic{
public:
- static llvm::Value* add(const Expression& left, llvm::Value *leftRaw, const Expression& right, compilation::Context context, const std::string& hintVarDecl);
+
+ /** \brief Pointer arithmetic operator */
+ static llvm::Value* add(llvm::Value *left, llvm::Value *right, compilation::Context context, const std::string& hintVarDecl);
};
+} //end of pointerarithmetic namespace
+
+/** \brief Struct update operators */
+class StructUpdate{
+public:
+
+ /** \brief Struct update operator */
+ static llvm::Value* add(const Expression& left, llvm::Value *leftRaw, const Expression& right, compilation::Context context, const std::string& hintVarDecl);
+} ;
} //namespace xreate
#endif /* OPERATORS_H */
diff --git a/cpp/src/compilation/polymorph.cpp b/cpp/src/compilation/polymorph.cpp
index 5d07277..97e654b 100644
--- a/cpp/src/compilation/polymorph.cpp
+++ b/cpp/src/compilation/polymorph.cpp
@@ -1,53 +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
- *
- * \file polymorph.cpp
- * \brief polymorph
*/
#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) {
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/compilation/polymorph.h b/cpp/src/compilation/polymorph.h
index def1bc1..71194d6 100644
--- a/cpp/src/compilation/polymorph.h
+++ b/cpp/src/compilation/polymorph.h
@@ -1,96 +1,103 @@
/*
* 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: polymorphcompiler.h
* Author: pgess <v.melnychenko@xreate.org>
*
* Created on October 7, 2017
*/
+/**
+ * \file src/compilation/polymorph.h
+ * \brief Polymorphism-aware compilation routines
+ */
+
#ifndef POLYMORPHCOMPILER_H
#define POLYMORPHCOMPILER_H
#include "pass/compilepass.h"
#include "query/polymorph.h"
-#include "compilation/latereasoning.h"
+#include "compilation/latetranscend.h"
#include "compilation/targetinterpretation.h"
namespace xreate{
namespace polymorph{
typedef Expression Selector;
+/** \brief An instance of \ref compilation::IFnInvocation to manage polymorphic functions invocation*/
class PolymorphFnInvocation: public compilation::IFnInvocation{
public:
- PolymorphFnInvocation(const latereasoning::LateAnnotation& selector,
- std::list<ManagedFnPtr> calleeSpecializations,
- CompilePass* pass,
- PolymorphQuery* query,
- LLVMLayer* llvm,
- latereasoning::LateReasoningCompiler* compiler);
+ PolymorphFnInvocation(const latereasoning::LateAnnotation& selector,
+ std::list<ManagedFnPtr> calleeSpecializations,
+ CompilePass* pass,
+ PolymorphQuery* query,
+ LLVMLayer* llvm,
+ latereasoning::LateReasoningCompiler* compiler);
- llvm::Value* operator()(std::vector<llvm::Value *>&& args, const std::string& hintDecl = "");
+ llvm::Value* operator()(std::vector<llvm::Value *>&& args, const std::string& hintDecl = "");
private:
- latereasoning::LateAnnotation __selector;
- std::list<ManagedFnPtr> __calleeSpecializations;
-
- CompilePass* __pass;
- PolymorphQuery* __query;
- LLVMLayer* __llvm;
- latereasoning::LateReasoningCompiler* __compiler;
-};
-
+ latereasoning::LateAnnotation __selector;
+ std::list<ManagedFnPtr> __calleeSpecializations;
+
+ CompilePass* __pass;
+ PolymorphQuery* __query;
+ LLVMLayer* __llvm;
+ latereasoning::LateReasoningCompiler* __compiler;
+} ;
+
+/**
+ * \brief Polymorphism aware \ref xreate::compilation::ICodeScopeUnit decorator
+ * \implements xreate::compilation::ICodeScopeUnit
+ */
template <class Parent>
class PolymorphCodeScopeUnit: public Parent{
public:
-
- PolymorphCodeScopeUnit(const CodeScope * const codeScope,
- compilation::IFunctionUnit* f,
- CompilePass* compilePass)
- : Parent(codeScope, f, compilePass){ }
+ PolymorphCodeScopeUnit(const CodeScope * const codeScope,
+ compilation::IFunctionUnit* f,
+ CompilePass* compilePass)
+ : Parent(codeScope, f, compilePass){ }
protected:
+ compilation::IFnInvocation*
+ findFunction(const Expression& opCall) override{
+ // //Check does invocation require guards satisfaction
+ const std::string& nameCallee = opCall.getValueString();
+ const std::list<ManagedFnPtr>& specializations =
+ Parent::pass->man->root->getFunctionSpecializations(nameCallee);
+
+ //Extern function
+ if(specializations.size() == 0){
+ return Parent::findFunction(opCall);
+ }
- compilation::IFnInvocation*
- findFunction(const Expression& opCall) override{
-// //Check does invocation require guards satisfaction
- const std::string& nameCallee = opCall.getValueString();
- const std::list<ManagedFnPtr>& specializations =
- Parent::pass->man->root->getFunctionSpecializations(nameCallee);
-
- //Extern function
- if(specializations.size() == 0){
- return Parent::findFunction(opCall);
- }
-
- //No other specializations. Check if it has no guard
- if(specializations.size() == 1){
- if(!specializations.front()->guard.isValid()){
- return Parent::findFunction(opCall);
- }
- }
-
- //Several specializations
- PolymorphQuery* query = dynamic_cast<PolymorphQuery*> (
- Parent::pass->man->transcend->getQuery(QueryId::PolymorphQuery));
- const latereasoning::LateAnnotation& selector = query->get(opCall);
-
- 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);
-
- return new PolymorphFnInvocation(selector, specializations, Parent::pass,
- query, Parent::pass->man->llvm, compiler);
+ //No other specializations. Check if it has no guard
+ if(specializations.size() == 1){
+ if(!specializations.front()->guard.isValid()){
+ return Parent::findFunction(opCall);
+ }
}
-};
+
+ //Several specializations
+ PolymorphQuery* query = dynamic_cast<PolymorphQuery*> (
+ Parent::pass->man->transcend->getQuery(QueryId::PolymorphQuery));
+ const latereasoning::LateAnnotation& selector = query->get(opCall);
+
+ 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);
+
+ return new PolymorphFnInvocation(selector, specializations, Parent::pass,
+ query, Parent::pass->man->llvm, compiler);
+ }
+} ;
}
} //end of xreate::polymorph
#endif /* POLYMORPHCOMPILER_H */
diff --git a/cpp/src/compilation/scopedecorators.h b/cpp/src/compilation/scopedecorators.h
index cf26986..b84b9ae 100644
--- a/cpp/src/compilation/scopedecorators.h
+++ b/cpp/src/compilation/scopedecorators.h
@@ -1,183 +1,188 @@
/* 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: scopedecorators.h
* Author: pgess <v.melnychenko@xreate.org>
*
* Created on February 24, 2017, 11:35 AM
*/
/**
* \file scopedecorators.h
* \brief Basic code block compilation xreate::compilation::ICodeScopeUnit decorators
*/
#ifndef SCOPEDECORATORS_H
#define SCOPEDECORATORS_H
#include "ast.h"
#include "compilation/targetinterpretation.h"
#include "compilation/versions.h"
#include "compilation/transformations.h"
#include "compilation/polymorph.h"
#include "compilation/latex.h"
#include "analysis/typeinference.h"
#include <list>
namespace xreate {
class CompilePass;
namespace compilation {
class ICodeScopeUnit;
class IFunctionUnit;
-/**\brief Caching ability for code scope compilation
+/**\brief Provides caching ability for code scope compilation
* \extends xreate::compilation::ICodeScopeUnit
*/
template<class Parent>
class CachedScopeDecorator: public Parent{
typedef CachedScopeDecorator<Parent> SELF;
public:
CachedScopeDecorator(const CodeScope* const codeScope, IFunctionUnit* f, CompilePass* compilePass): Parent(codeScope, f, compilePass){}
Symbol bindArg(llvm::Value* value, std::string&& alias)
{
//ensure existence of an alias
assert(Parent::scope->__identifiers.count(alias));
//memorize new value for an alias
ScopedSymbol id{Parent::scope->__identifiers.at(alias), versions::VERSION_NONE};
__rawVars[id] = value;
return Symbol{id, Parent::scope};
}
void bindArg(llvm::Value* value, const ScopedSymbol& s) {
__rawVars[s] = value;
}
llvm::Value* compile(const std::string& hintBlockDecl="") override{
if (__rawVars.count(ScopedSymbol::RetSymbol)){
return __rawVars[ScopedSymbol::RetSymbol];
}
return Parent::compile(hintBlockDecl);
}
llvm::Value*
processSymbol(const Symbol& s, std::string hintRetVar) override{
const CodeScope* scope = s.scope;
SELF* self = dynamic_cast<SELF*>(Parent::function->getScopeUnit(scope));
if (self->__rawVars.count(s.identifier)){
return self->__rawVars[s.identifier];
}
//Declaration could be overriden
/*
Expression declaration = CodeScope::getDefinition(s, true);
if (!declaration.isDefined()){
assert(__declarationsOverriden.count(s.identifier));
declaration = __declarationsOverriden[s.identifier];
} else {
(false); //in case of binding there should be raws provided.
}
}
*/
llvm::Value* resultRaw = Parent::processSymbol(s, hintRetVar);
self->__rawVars.emplace(s.identifier, resultRaw);
return resultRaw;
}
void
overrideDeclarations(std::list<std::pair<Symbol, Expression>> bindings){
reset();
for (auto entry: bindings){
SELF* self = dynamic_cast<SELF*>(Parent::function->getScopeUnit(entry.first.scope));
assert(self == this);
self->__declarationsOverriden.emplace(entry.first.identifier, entry.second);
}
}
void registerChildScope(std::shared_ptr<ICodeScopeUnit> scope){
__childScopes.push_back(scope);
}
void reset(){
__rawVars.clear();
__declarationsOverriden.clear();
__childScopes.clear();
}
private:
std::unordered_map<ScopedSymbol, Expression> __declarationsOverriden;
std::unordered_map<ScopedSymbol,llvm::Value*> __rawVars;
std::list<std::shared_ptr<ICodeScopeUnit>> __childScopes;
};
+/** \brief Provides automatic type conversion
+ * \extends xreate::compilation::ICodeScopeUnit
+ */
template<class Parent>
class TypeConversionScopeDecorator: public Parent {
public:
TypeConversionScopeDecorator(const CodeScope* const codeScope, IFunctionUnit* f, CompilePass* compilePass): Parent(codeScope, f, compilePass){}
llvm::Value* process(const Expression& expr, const std::string& hintVarDecl="") override {
llvm::Value* resultR = Parent::process(expr, hintVarDecl);
if(!expr.type.isValid()) {
return resultR;
}
ExpandedType exprT = Parent::pass->man->root->getType(expr);
llvm::Type* exprTR = Parent::pass->man->llvm->toLLVMType(exprT);
return typeinference::doAutomaticTypeConversion(resultR, exprTR, Parent::pass->man->llvm->builder);
}
};
-/**\brief Default code scope compilation functionality*/
+/**\brief The default code scope compilation implementation
+ * \extends xreate::compilation::ICodeScopeUnit
+ */
typedef CachedScopeDecorator<
TypeConversionScopeDecorator<
latex::LatexBruteScopeDecorator<
polymorph::PolymorphCodeScopeUnit<
compilation::TransformationsScopeDecorator<
interpretation::InterpretationScopeDecorator<
versions::VersionsScopeDecorator<compilation::BasicCodeScopeUnit>>>>>>>
DefaultCodeScopeUnit;
} //end of compilation namespace
struct CachedScopeDecoratorTag;
struct VersionsScopeDecoratorTag;
template<>
struct DecoratorsDict<CachedScopeDecoratorTag>{
typedef compilation::CachedScopeDecorator<
compilation::TypeConversionScopeDecorator<
latex::LatexBruteScopeDecorator<
polymorph::PolymorphCodeScopeUnit<
compilation::TransformationsScopeDecorator<
interpretation::InterpretationScopeDecorator<
versions::VersionsScopeDecorator<compilation::BasicCodeScopeUnit>>>>>>>
result;
};
template<>
struct DecoratorsDict<VersionsScopeDecoratorTag>{
typedef versions::VersionsScopeDecorator<
compilation::BasicCodeScopeUnit> result;
};
} //end of xreate
#endif /* SCOPEDECORATORS_H */
diff --git a/cpp/src/compilation/targetinterpretation.cpp b/cpp/src/compilation/targetinterpretation.cpp
index 4f4555a..f22ebc1 100644
--- a/cpp/src/compilation/targetinterpretation.cpp
+++ b/cpp/src/compilation/targetinterpretation.cpp
@@ -1,627 +1,626 @@
/* 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: targetinterpretation.cpp
* Author: pgess <v.melnychenko@xreate.org>
*
* Created on June 29, 2016, 6:45 PM
*/
/**
* \file targetinterpretation.h
- * \brief Interpretation support. See more [details on Interpretation](/w/concepts/dsl/)
+ * \brief Interpretation support. See more details on [Interpretation](/d/concepts/interpretation/)
*/
#include "compilation/targetinterpretation.h"
#include "pass/interpretationpass.h"
#include "analysis/typeinference.h"
#include "llvmlayer.h"
#include "compilation/scopedecorators.h"
#include "compilation/interpretation-instructions.h"
#include <boost/scoped_ptr.hpp>
#include <iostream>
#include <csignal>
using namespace std;
using namespace xreate::compilation;
namespace xreate{
namespace interpretation{
const Expression EXPRESSION_FALSE = Expression(Atom<Number_t>(0));
const Expression EXPRESSION_TRUE = Expression(Atom<Number_t>(1));
CodeScope*
InterpretationScope::processOperatorIf(const Expression& expression) {
const Expression& exprCondition = process(expression.getOperands()[0]);
if (exprCondition == EXPRESSION_TRUE) {
return expression.blocks.front();
}
return expression.blocks.back();
}
CodeScope*
InterpretationScope::processOperatorSwitch(const Expression& expression) {
const Expression& exprCondition = process(expression.operands[0]);
bool flagHasDefault = expression.operands[1].op == Operator::CASE_DEFAULT;
//TODO check that one and only one case variant is appropriate
for (size_t size = expression.operands.size(), i = flagHasDefault ? 2 : 1; i < size; ++i) {
const Expression& exprCase = process(expression.operands[i]);
if (function->getScope((const CodeScope*) exprCase.blocks.front())->processScope() == exprCondition) {
return exprCase.blocks.back();
}
}
if (flagHasDefault) {
const Expression& exprCaseDefault = expression.operands[1];
return exprCaseDefault.blocks.front();
}
assert(false && "Switch has no appropriate variant");
return nullptr;
}
CodeScope*
InterpretationScope::processOperatorSwitchVariant(const Expression& expression) {
const Expression& condition = process(expression.operands.at(0));
assert(condition.op == Operator::VARIANT);
const string& identCondition = expression.bindings.front();
Expression opExpected(Atom<Number_t>(condition.getValueDouble()));
auto itFoundValue = std::find(++expression.operands.begin(), expression.operands.end(), opExpected);
assert(itFoundValue != expression.operands.end());
int indexBlock = itFoundValue - expression.operands.begin() - 1;
auto blockFound = expression.blocks.begin();
std::advance(blockFound, indexBlock);
InterpretationScope* scopeI12n = function->getScope(*blockFound);
if(condition.operands.size()) {
const Expression& value = condition.operands.at(0);
scopeI12n->overrideBindings({
{value, identCondition}
});
}
return *blockFound;
}
llvm::Value*
InterpretationScope::processLate(const InterpretationOperator& op, const Expression& expression, const Context& context) {
switch(op) {
case IF_INTERPRET_CONDITION:
{
CodeScope* scopeResult = processOperatorIf(expression);
llvm::Value* result = context.function->getScopeUnit(scopeResult)->compile();
return result;
}
case SWITCH_INTERPRET_CONDITION:
{
CodeScope* scopeResult = processOperatorSwitch(expression);
llvm::Value* result = context.function->getScopeUnit(scopeResult)->compile();
return result;
}
case SWITCH_VARIANT:
{
CodeScope* scopeResult = processOperatorSwitchVariant(expression);
const Expression& condition = expression.operands.at(0);
const Expression& valueCondition = process(condition);
const string identCondition = expression.bindings.front();
auto scopeCompilation = Decorators<CachedScopeDecoratorTag>::getInterface(context.function->getScopeUnit(scopeResult));
if(valueCondition.operands.size()) {
//override value
Symbol symbCondition{ScopedSymbol{scopeResult->__identifiers.at(identCondition), versions::VERSION_NONE}, scopeResult};
scopeCompilation->overrideDeclarations({
{symbCondition, Expression(valueCondition.operands.at(0))}}
);
//set correct type for binding:
TypeAnnotation typeVariant = typeinference::getType(condition, *function->man->ast);
int conditionIndex = valueCondition.getValueDouble();
ScopedSymbol symbolInternal = scopeResult->getSymbol(identCondition);
scopeResult->__declarations[symbolInternal].bindType(typeVariant.__operands.at(conditionIndex));
}
llvm::Value* result = context.function->getScopeUnit(scopeResult)->compile();
return result;
}
case SWITCH_LATE:
{
latereasoning::LateReasoningCompiler compiler(dynamic_cast<InterpretationFunction*>(this->function), context);
return compiler.processSwitchLateStatement(expression, "");
}
case FOLD_INTERPRET_INPUT:
{
//initialization
const Expression& exprInput = process(expression.getOperands()[0]);
assert(exprInput.op == Operator::LIST);
CodeScope* scopeBody = expression.blocks.front();
const string& nameEl = expression.bindings[0];
Symbol symbEl{ScopedSymbol{scopeBody->__identifiers.at(nameEl), versions::VERSION_NONE}, scopeBody};
const std::string& idAccum = expression.bindings[1];
llvm::Value* rawAccum = context.scope->process(expression.getOperands()[1]);
InterpretationScope* intrBody = function->getScope(scopeBody);
auto unitBody = Decorators<CachedScopeDecoratorTag>::getInterface(context.function->getScopeUnit(scopeBody));
const std::vector<Expression> elementsInput = exprInput.getOperands();
for(size_t i = 0; i < elementsInput.size(); ++i) {
const Expression& exprElement = elementsInput[i];
intrBody->overrideBindings({
{exprElement, nameEl}
});
unitBody->overrideDeclarations({
{symbEl, exprElement}
}); //resets unitBody
unitBody->bindArg(rawAccum, string(idAccum));
rawAccum = unitBody->compile();
}
return rawAccum;
}
// case FOLD_INF_INTERPRET_INOUT:
// {
// }
//TODO refactor as InterpretationCallStatement class
case CALL_INTERPRET_PARTIAL:
{
const std::string &calleeName = expression.getValueString();
ICodeScopeUnit* scopeUnitSelf = context.scope;
ManagedFnPtr callee = this->function->man->ast->findFunction(calleeName);
const FunctionInterpretationData& calleeData = FunctionInterpretationHelper::getSignature(callee);
std::vector<llvm::Value *> argsActual;
PIFSignature sig;
sig.declaration = callee;
for(size_t no = 0, size = expression.operands.size(); no < size; ++no) {
const Expression& op = expression.operands[no];
if (calleeData.signature.at(no) == INTR_ONLY) {
sig.bindings.push_back(process(op));
continue;
}
argsActual.push_back(scopeUnitSelf->process(op));
}
TargetInterpretation* man = dynamic_cast<TargetInterpretation*> (this->function->man);
PIFunction* pifunction = man->getFunction(move(sig));
llvm::Function* raw = pifunction->compile();
boost::scoped_ptr<BruteFnInvocation> statement(new BruteFnInvocation(raw, man->pass->man->llvm));
return (*statement)(move(argsActual));
}
case QUERY_LATE:
{
return IntrinsicQueryInstruction(
dynamic_cast<InterpretationFunction*>(this->function))
.processLate(expression, context);
}
default: break;
}
assert(false && "Unknown late interpretation operator");
return nullptr;
}
llvm::Value*
InterpretationScope::compile(const Expression& expression, const Context& context) {
const InterpretationData& data = Attachments::get<InterpretationData>(expression);
if (data.op != InterpretationOperator::NONE) {
return processLate(data.op, expression, context);
}
Expression result = process(expression);
return context.scope->process(result);
}
Expression
InterpretationScope::process(const Expression& expression) {
#ifndef NDEBUG
if (expression.tags.count("bpoint")) {
std::raise(SIGINT);
}
#endif
PassManager* man = (static_cast<TargetInterpretation*> (function->man))->pass->man;
switch (expression.__state) {
case Expression::INVALID:
assert(false);
case Expression::NUMBER:
case Expression::STRING:
return expression;
case Expression::IDENT:
{
Symbol s = Attachments::get<IdentifierSymbol>(expression);
return Parent::processSymbol(s);
}
case Expression::COMPOUND:
break;
default: assert(false);
}
switch (expression.op) {
case Operator::EQU:
{
const Expression& left = process(expression.operands[0]);
const Expression& right = process(expression.operands[1]);
if (left == right) return EXPRESSION_TRUE;
return EXPRESSION_FALSE;
}
case Operator::NE:
{
const Expression& left = process(expression.operands[0]);
const Expression& right = process(expression.operands[1]);
if (left == right) return EXPRESSION_FALSE;
return EXPRESSION_TRUE;
}
case Operator::LOGIC_AND:
{
assert(expression.operands.size() == 1);
return process (expression.operands[0]);
}
// case Operator::LOGIC_OR:
case Operator::CALL:
{
const std::string &fnName = expression.getValueString();
ManagedFnPtr fnAst = this->function->man->ast->findFunction(fnName);
InterpretationFunction* fnUnit = this->function->man->getFunction(fnAst);
vector<Expression> args;
args.reserve(expression.getOperands().size());
for(size_t i = 0, size = expression.getOperands().size(); i < size; ++i) {
args.push_back(process(expression.getOperands()[i]));
}
return fnUnit->process(args);
}
case Operator::CALL_INTRINSIC:
{
assert(false && "Unknown intrinsic");
}
case Operator::QUERY:
{
return IntrinsicQueryInstruction(dynamic_cast<InterpretationFunction*>(this->function))
.process(expression);
}
case Operator::QUERY_LATE:
{
assert(false && "Can't be interpretated");
return Expression();
}
case Operator::IF:
{
CodeScope* scopeResult = processOperatorIf(expression);
return function->getScope(scopeResult)->processScope();
}
case Operator::SWITCH:
{
CodeScope* scopeResult = processOperatorSwitch(expression);
return function->getScope(scopeResult)->processScope();
}
case Operator::SWITCH_VARIANT:
{
CodeScope* scopeResult = processOperatorSwitchVariant(expression);
return function->getScope(scopeResult)->processScope();
}
case Operator::VARIANT:
{
if(!expression.operands.size()) return expression;
Expression variantData = process(expression.operands[0]);
Expression result{Operator::VARIANT, {variantData}};
result.setValueDouble(expression.getValueDouble());
return result;
}
case Operator::INDEX:
{
Expression exprData = process(expression.operands[0]);
for (size_t keyId = 1; keyId < expression.operands.size(); ++keyId) {
const Expression& exprKey = process(expression.operands[keyId]);
if (exprKey.__state == Expression::STRING) {
const string& key = exprKey.getValueString();
assert(exprData.__indexBindings.count(key));
size_t idxKey = exprData.__indexBindings.at(key);
exprData = Expression(exprData.operands.at(idxKey));
continue;
}
if (exprKey.__state == Expression::NUMBER) {
int key = exprKey.getValueDouble();
exprData = Expression(exprData.operands[key]);
continue;
}
assert(false && "Inappropriate key");
}
return exprData;
}
case Operator::FOLD:
{
const Expression& exprInput = process(expression.getOperands()[0]);
const Expression& exprInit = process(expression.getOperands()[1]);
const std::string& argEl = expression.bindings[0];
const std::string& argAccum = expression.bindings[1];
InterpretationScope* body = function->getScope(expression.blocks.front());
Expression accum = exprInit;
for(size_t size = exprInput.getOperands().size(), i = 0; i < size; ++i) {
body->overrideBindings({
{exprInput.getOperands()[i], argEl},
{accum, argAccum}
});
accum = body->processScope();
}
return accum;
}
case Operator::LIST:
case Operator::LIST_RANGE:
{
Expression result(expression.op,{});
result.operands.resize(expression.operands.size());
result.bindings = expression.bindings;
result.__indexBindings = expression.__indexBindings;
int keyId = 0;
for(const Expression& opCurrent : expression.operands) {
result.operands[keyId++] = process(opCurrent);
}
return result;
}
// case Operator::MAP: {
// break;
// }
default: break;
}
return expression;
}
InterpretationFunction*
TargetInterpretation::getFunction(IFunctionUnit* unit) {
if (__dictFunctionsByUnit.count(unit)) {
return __dictFunctionsByUnit.at(unit);
}
InterpretationFunction* f = new InterpretationFunction(unit->function, this);
__dictFunctionsByUnit.emplace(unit, f);
assert(__functions.emplace(unit->function.id(), f).second);
return f;
}
PIFunction*
TargetInterpretation::getFunction(PIFSignature&& sig) {
auto f = __pifunctions.find(sig);
if (f != __pifunctions.end()) {
return f->second;
}
PIFunction* result = new PIFunction(PIFSignature(sig), __pifunctions.size(), this);
__pifunctions.emplace(move(sig), result);
assert(__dictFunctionsByUnit.emplace(result->functionUnit, result).second);
return result;
}
InterpretationScope*
TargetInterpretation::transformContext(const Context& c) {
return this->getFunction(c.function)->getScope(c.scope->scope);
}
llvm::Value*
TargetInterpretation::compile(const Expression& expression, const Context& ctx) {
return transformContext(ctx)->compile(expression, ctx);
}
InterpretationFunction::InterpretationFunction(const ManagedFnPtr& function, Target<TargetInterpretation>* target)
: Function<TargetInterpretation>(function, target) { }
Expression
InterpretationFunction::process(const std::vector<Expression>& args) {
InterpretationScope* body = getScope(__function->__entry);
list<pair<Expression, string>> bindings;
for(size_t i = 0, size = args.size(); i < size; ++i) {
bindings.push_back(make_pair(args.at(i), body->scope->__bindings.at(i)));
}
body->overrideBindings(bindings);
return body->processScope();
}
// Partial function interpretation
typedef BasicFunctionUnit PIFunctionUnitParent;
class PIFunctionUnit : public PIFunctionUnitParent{
public:
PIFunctionUnit(ManagedFnPtr f, std::set<size_t>&& arguments, size_t id, CompilePass* p)
: PIFunctionUnitParent(f, p), argumentsActual(move(arguments)), __id(id) { }
protected:
std::vector<llvm::Type*>
prepareSignature() override {
LLVMLayer* llvm = PIFunctionUnitParent::pass->man->llvm;
AST* ast = PIFunctionUnitParent::pass->man->root;
CodeScope* entry = PIFunctionUnitParent::function->__entry;
std::vector<llvm::Type*> signature;
for(size_t no : argumentsActual) {
VNameId argId = entry->__identifiers.at(entry->__bindings.at(no));
ScopedSymbol arg{argId, versions::VERSION_NONE};
signature.push_back(llvm->toLLVMType(ast->expandType(entry->__declarations.at(arg).type)));
}
return signature;
}
llvm::Function::arg_iterator
prepareBindings() override{
CodeScope* entry = PIFunctionUnitParent::function->__entry;
ICodeScopeUnit* entryCompilation = PIFunctionUnitParent::getScopeUnit(entry);
llvm::Function::arg_iterator fargsI = PIFunctionUnitParent::raw->arg_begin();
for(size_t no : argumentsActual) {
ScopedSymbol arg{entry->__identifiers.at(entry->__bindings.at(no)), versions::VERSION_NONE};
entryCompilation->bindArg(&*fargsI, arg);
fargsI->setName(entry->__bindings.at(no));
++fargsI;
}
return fargsI;
}
virtual std::string
prepareName() override {
return PIFunctionUnitParent::prepareName() + "_" + std::to_string(__id);
}
private:
std::set<size_t> argumentsActual;
size_t __id;
} ;
PIFunction::PIFunction(PIFSignature&& sig, size_t id, TargetInterpretation* target)
: InterpretationFunction(sig.declaration, target), signatureInstance(move(sig)) {
const FunctionInterpretationData& functionData = FunctionInterpretationHelper::getSignature(signatureInstance.declaration);
std::set<size_t> argumentsActual;
for (size_t no = 0, size = functionData.signature.size(); no < size; ++no) {
if (functionData.signature.at(no) != INTR_ONLY) {
argumentsActual.insert(no);
}
}
functionUnit = new PIFunctionUnit(signatureInstance.declaration, move(argumentsActual), id, target->pass);
CodeScope* entry = signatureInstance.declaration->__entry;
auto entryUnit = Decorators<CachedScopeDecoratorTag>::getInterface<>(functionUnit->getEntry());
InterpretationScope* entryIntrp = InterpretationFunction::getScope(entry);
list<pair<Expression, std::string>> bindingsPartial;
list<pair<Symbol, Expression>> declsPartial;
for(size_t no = 0, sigNo = 0, size = entry->__bindings.size(); no < size; ++no) {
if(functionData.signature.at(no) == INTR_ONLY) {
bindingsPartial.push_back({signatureInstance.bindings[sigNo], entry->__bindings[no]});
VNameId argId = entry->__identifiers.at(entry->__bindings[no]);
Symbol argSymbol{ScopedSymbol
{argId, versions::VERSION_NONE}, entry};
declsPartial.push_back({argSymbol, signatureInstance.bindings[sigNo]});
++sigNo;
}
}
entryIntrp->overrideBindings(bindingsPartial);
entryUnit->overrideDeclarations(declsPartial);
}
llvm::Function*
PIFunction::compile() {
llvm::Function* raw = functionUnit->compile();
return raw;
}
bool operator<(const PIFSignature& lhs, const PIFSignature& rhs) {
if (lhs.declaration.id() != rhs.declaration.id()) {
return lhs.declaration.id() < rhs.declaration.id();
}
return lhs.bindings < rhs.bindings;
}
bool operator<(const PIFSignature& lhs, PIFunction * const rhs) {
return lhs < rhs->signatureInstance;
}
bool operator<(PIFunction * const lhs, const PIFSignature& rhs) {
return lhs->signatureInstance < rhs;
}
}
}
/** \class xreate::interpretation::InterpretationFunction
*
* Holds list of xreate::interpretation::InterpretationScope 's focused on interpretation of individual code scopes
*
- * There is particulat subclass PIFunction intended to represent partially interpreted functions
+ * There is particulat subclass PIFunction intended to represent partially interpreted functions.
*\sa TargetInterpretation, [Interpretation Concept](/w/concepts/dfa)
*/
+
/** \class xreate::interpretation::TargetInterpretation
*
- * Executed during compilation and intented to preprocess eligible parts of code.
- * Established on [Targets Infrastructure](\ref compilation::Target)
+ * TargetInterpretation is executed during compilation and is intended to preprocess eligible for interpretation parts of a source code.
*
- * Holds list of InterpretationFunction / PIFunction to represent interpretation process for individual functions
+ * Keeps a list of InterpretationFunction / PIFunction that represent interpretation for an individual functions.
*
- * In order to be activated during compilation process there is
- * InterpretationScopeDecorator implementation of ICodeScopeUnit
- * \sa InterpretationPass, compilation::Target, [Interpretation Concept](/w/concepts/dfa)
+ * There is \ref InterpretationScopeDecorator that embeds interpretation to an overall compilation process.
+ * \sa InterpretationPass, compilation::Target, [Interpretation Concept](/d/concepts/interpretation/)
*
*/
diff --git a/cpp/src/compilation/targetinterpretation.h b/cpp/src/compilation/targetinterpretation.h
index 867b2f4..8ff000b 100644
--- a/cpp/src/compilation/targetinterpretation.h
+++ b/cpp/src/compilation/targetinterpretation.h
@@ -1,130 +1,133 @@
/* 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: targetstatic.h
* Author: pgess <v.melnychenko@xreate.org>
*
* Created on July 2, 2016, 1:25 PM
*/
#ifndef TARGETSTATIC_H
#define TARGETSTATIC_H
#include "ast.h"
#include "pass/compilepass.h"
#include "compilation/targets.h"
#include "pass/interpretationpass.h"
#include "transcendlayer.h"
namespace xreate{ namespace interpretation{
class TargetInterpretation;
class InterpretationScope;
class InterpretationFunction;
}}
namespace xreate{ namespace compilation{
template <>
struct TargetInfo<interpretation::TargetInterpretation> {
typedef Expression Result;
typedef interpretation::InterpretationScope Scope;
typedef interpretation::InterpretationFunction Function;
};
}}
namespace xreate{ namespace interpretation{
- /** \brief Encapsulates interpretation of a single Code Scope */
+/** \brief Encapsulates interpretation of a single code scope */
class InterpretationScope: public compilation::Scope<TargetInterpretation>{
typedef Scope<TargetInterpretation> Parent;
public:
InterpretationScope(const CodeScope* scope, compilation::Function<TargetInterpretation>* f): Parent(scope, f) {}
Expression process(const Expression& expression) override;
llvm::Value* compile(const Expression& expression, const compilation::Context& context);
private:
llvm::Value* processLate(const InterpretationOperator& op, const Expression& expression, const compilation::Context& context);
//llvm::Value* compilePartialFnCall(const Expression& expression, const Context& context);
CodeScope* processOperatorIf(const Expression& expression);
CodeScope* processOperatorSwitch(const Expression& expression);
CodeScope* processOperatorSwitchVariant(const Expression& expression);
};
-/** \brief Encapsulates interpretation of a single %Function */
+/** \brief Encapsulates interpretation of a single function */
class InterpretationFunction: public compilation::Function<TargetInterpretation>{
public:
InterpretationFunction(const ManagedFnPtr& function, compilation::Target<TargetInterpretation>* target);
Expression process(const std::vector<Expression>& args);
};
/** \brief Signature of a partially interpreted function */
struct PIFSignature{
ManagedFnPtr declaration;
std::vector<Expression> bindings;
};
class PIFunctionUnit;
-/** \brief Partially interpreted function */
+/** \brief Encapsulates partially interpreted function */
class PIFunction: public InterpretationFunction{
public:
PIFunctionUnit* functionUnit;
PIFSignature signatureInstance;
PIFunction(PIFSignature&& sig, size_t id, TargetInterpretation* target);
llvm::Function* compile();
};
bool operator<(const PIFSignature& lhs, PIFunction* const rhs);
bool operator<(PIFunction* const lhs, const PIFSignature& rhs);
-/** \brief Encapsulates actual [Interpretation](/w/concepts/dfa) based on InterpretationPass analysis results */
+/** \brief Encapsulates interpretation process based on analysis results from \ref InterpretationPass
+ * \extends compilation::Target
+ * \sa InterpretationPass
+ */
class TargetInterpretation: public compilation::Target<TargetInterpretation>{
public:
TargetInterpretation(AST* root, CompilePass* passCompilation): Target<TargetInterpretation>(root), pass(passCompilation){}
//target:
public:
InterpretationFunction* getFunction(compilation::IFunctionUnit* unit);
PIFunction* getFunction(PIFSignature&& sig);
private:
std::map<PIFSignature, PIFunction*> __pifunctions;
std::map<compilation::IFunctionUnit*, InterpretationFunction*> __dictFunctionsByUnit;
//self:
public:
CompilePass* pass;
llvm::Value* compile(const Expression& expression, const compilation::Context& ctx);
InterpretationScope* transformContext(const compilation::Context& c);
private:
};
/**\brief Interpretation-aware Code Scope decorator
* \extends xreate::compilation::ICodeScopeUnit
*/
template<class Parent>
class InterpretationScopeDecorator: public Parent{
public:
InterpretationScopeDecorator(const CodeScope* const codeScope, compilation::IFunctionUnit* f, CompilePass* compilePass): Parent(codeScope, f, compilePass){}
virtual llvm::Value* process(const Expression& expr, const std::string& hintVarDecl){
const InterpretationData& data = Attachments::get<InterpretationData>(expr, {ANY, NONE});
bool flagInterpretationEligible = (data.resolution == INTR_ONLY || data.op != InterpretationOperator::NONE);
if (flagInterpretationEligible){
compilation::Context ctx{this, this->function, this->pass};
return Parent::pass->targetInterpretation->compile(expr, ctx);
}
return Parent::process(expr, hintVarDecl);
}
};
}} //end of xreate:: interpretation
#endif /* TARGETSTATIC_H */
\ No newline at end of file
diff --git a/cpp/src/compilation/transformersaturation.h b/cpp/src/compilation/transformersaturation.h
index bb370a1..478956b 100644
--- a/cpp/src/compilation/transformersaturation.h
+++ b/cpp/src/compilation/transformersaturation.h
@@ -1,45 +1,46 @@
/* 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: transformersaturation.h
* Author: pgess <v.melnychenko@xreate.org>
*
* Created on March 25, 2017, 9:59 PM
*/
#ifndef TRANSFORMERSATURATION_H
#define TRANSFORMERSATURATION_H
#include "transformations.h"
namespace xreate { namespace compilation {
+/** \brief Loop saturation support */
class TransformerSaturation: public Transformer{
public:
TransformerSaturation(llvm::BasicBlock* allocationBlock, TransformationsManager* manager);
~TransformerSaturation();
llvm::Value* transform(const Expression& expression, llvm::Value* raw, const Context& ctx) override;
void processBreak(const Context& ctx);
void allocateFlag(const Context& ctx);
bool insertSaturationChecks(llvm::BasicBlock* blockContinue, llvm::BasicBlock* blockExit, const Context& ctx);
private:
TransformationsManager* man;
TransformerSaturation* oldInstance = nullptr;
llvm::BasicBlock* blockAllocation;
llvm::Value* flagSaturation = nullptr;
};
template <>
struct TransformerInfo<TransformerSaturation> {
static const unsigned int id = 0;
};
} }
#endif /* TRANSFORMERSATURATION_H */
diff --git a/cpp/src/compilation/versions.h b/cpp/src/compilation/versions.h
index 3aeaab5..a45dcbe 100644
--- a/cpp/src/compilation/versions.h
+++ b/cpp/src/compilation/versions.h
@@ -1,155 +1,124 @@
/* 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/.
*
* versions.cpp
*
* Author: pgess <v.melnychenko@xreate.org>
* Created on January 21, 2017, 1:24 PM
*/
/**
- * \file
- * \brief CodeScope's Decorator to support Versions
+ * \file versions.h
+ * \brief Versions-aware compilation support
*/
#include "pass/versionspass.h"
#include "pass/compilepass.h"
#include "llvmlayer.h"
namespace xreate {
class CompilePass;
namespace compilation {
class ICodeScopeUnit;
class IFunctionUnit;
}
namespace versions{
-/**\brief Enables compilation of code with versioned variables
- * \details Dictates order of computation determined by VersionsPass
+/**\brief Versioned variables code scope level compilation support
+ *
+ * Decorates \ref xreate::compilation::ICodeScopeUnit to enable versioned variables compilation.
+ * An order of variables computation is determined by \ref VersionsPass.
* \extends xreate::compilation::ICodeScopeUnit
* \sa VersionsPass, VersionsGraph
*/
template<class Parent>
class VersionsScopeDecorator: public Parent{
typedef VersionsScopeDecorator<Parent> SELF;
public:
VersionsScopeDecorator(const CodeScope* const codeScope, compilation::IFunctionUnit* f, CompilePass* compilePass): Parent(codeScope, f, compilePass){}
virtual llvm::Value* processSymbol(const Symbol& s, std::string hintSymbol=""){
if (Attachments::exists<VersionImposedDependency>(s)){
const std::list<Symbol> dependencies = Attachments::get<VersionImposedDependency>(s);
for(const Symbol& symbolDependent: dependencies){
processSymbol(symbolDependent);
}
}
llvm::Value* result = Parent::processSymbol(s, hintSymbol);
if (s.identifier.version == VERSION_INIT){
llvm::Value* storage = SELF::processIntrinsicInit(result->getType(), hintSymbol);
setSymbolStorage(s, storage);
processIntrinsicCopy(result, storage);
return compilation::ICodeScopeUnit::pass->man->llvm->builder.CreateLoad(storage);
} else if (s.identifier.version != VERSION_NONE){
Symbol symbolInitVersion = getSymbolInitVersion(s);
llvm::Value* storage = getSymbolStorage(symbolInitVersion);
processIntrinsicCopy(result, storage);
return compilation::ICodeScopeUnit::pass->man->llvm->builder.CreateLoad(storage);
}
return result;
}
llvm::Value*
processIntrinsicInit(llvm::Type* typeStorage, const std::string& hintVarDecl=""){
LLVMLayer* llvm = compilation::ICodeScopeUnit::pass->man->llvm;
llvm::IntegerType* tyInt = llvm::Type::getInt32Ty(llvm->llvmContext);
llvm::ConstantInt* constOne = llvm::ConstantInt::get(tyInt, 1, false);
return llvm->builder.CreateAlloca(typeStorage, constOne, hintVarDecl);
}
void
processIntrinsicCopy(llvm::Value* value, llvm::Value* storage){
compilation::ICodeScopeUnit::pass->man->llvm->builder.CreateStore(value, storage);
}
private:
std::map<Symbol, llvm::Value*> __symbolStorage;
static Symbol
getSymbolInitVersion(const Symbol& s){
return Symbol{ScopedSymbol{s.identifier.id, VERSION_INIT}, s.scope};
}
llvm::Value*
getSymbolStorage(const Symbol& s){
return __symbolStorage.at(s);
}
void setSymbolStorage(const Symbol& s, llvm::Value* storage){
__symbolStorage[s] = storage;
}
};
+/**
+ * \brief A Versions-aware function level decorator. Not used currently.
+ */
template<class Parent>
class VersionedFunctionDecorator : public Parent {
public:
VersionedFunctionDecorator(ManagedFnPtr f, CompilePass* p)
: Parent(f, p){}
protected:
std::vector<llvm::Type*> prepareArguments() {
std::vector<llvm::Type*>&& arguments = Parent::prepareArguments();
return arguments;
}
};
-} } //end of namespace xreate::versions
-
-// llvm::Value*
-// processIntrinsicInitAndCopy(){
-//
-// }
-
-//llvm::Value*
-//process(const Expression& expr, const std::string& hintVarDecl){
-// case Operator::CALL_INTRINSIC: {
-// enum INRINSIC{INIT, COPY};
-//
-// const ExpandedType& typSymbol = pass->man->root->expandType(expr.type);
-//
-// INTRINSIC op = (INTRINSIC) expr.getValueDouble();
-//
-// switch (op){
-// case INIT: {
-// llvm::Type* typSymbolRaw = l.toLLVMType(typSymbol);
-//
-//
-// return storage;
-// }
-//
-// case COPY: {
-// llvm::Type* typSymbolRaw = l.toLLVMType(typSymbol);
-// llvm::value* valueOriginal = process(expr.getOperands()[0], hintVarDecl);
-// llvm::Value* storage = l.builder.CreateAlloca(typSymbolRaw, constOne, hintVarDecl);
-// llvm::Value* valueCopy = l.builder.CreateStore(valueOriginal, storage);
-//
-// return valueCopy;
-// }
-// }
-// return;
-// }
-//}
-//};
+} } //end of namespace xreate::versions
\ No newline at end of file
diff --git a/cpp/src/llvmlayer.cpp b/cpp/src/llvmlayer.cpp
index 6cca735..846d96c 100644
--- a/cpp/src/llvmlayer.cpp
+++ b/cpp/src/llvmlayer.cpp
@@ -1,244 +1,242 @@
/* 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 Wrapper over LLVM
+ * \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);
}
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()
);
}
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);
}
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/llvmlayer.h b/cpp/src/llvmlayer.h
index 900bb0d..ab6938d 100644
--- a/cpp/src/llvmlayer.h
+++ b/cpp/src/llvmlayer.h
@@ -1,69 +1,70 @@
/* 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.h
*
* Author: pgess <v.melnychenko@xreate.org>
*/
#ifndef LLVMLAYER_H
#define LLVMLAYER_H
#include "llvm/IR/Module.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/PassManager.h"
#include "llvm/IR/CallingConv.h"
#include "llvm/IR/Verifier.h"
#include "llvm/IR/IRPrintingPasses.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/ExecutionEngine/ExecutionEngine.h"
#include "utils.h"
namespace xreate {
class AST;
class ExternLayer;
class TypeAnnotation;
+/** \brief A wrapper over LLVM toolchain to generate and execute bytecode */
class LLVMLayer {
public:
LLVMLayer(AST* rootAST);
mutable llvm::LLVMContext llvmContext;
llvm::IRBuilder<> builder;
AST *ast = 0;
ExternLayer *layerExtern =0;
std::unique_ptr<llvm::Module> module;
std::unique_ptr<llvm::ExecutionEngine> jit;
void moveToGarbage(void *o);
llvm::Type* toLLVMType(const Expanded<TypeAnnotation>& ty) const;
void print();
void* getFunctionPointer(llvm::Function* function);
void initJit();
private:
llvm::Type* toLLVMType(const Expanded<TypeAnnotation>& ty, std::map<int, llvm::StructType*>& conjunctions) const;
std::vector<void *> __garbage;
};
struct TypeUtils {
bool isStruct(const Expanded<TypeAnnotation>& ty);
bool isPointer(const Expanded<TypeAnnotation>& ty);
std::vector<std::string> getStructFields(const Expanded<TypeAnnotation>& t);
TypeUtils(LLVMLayer*llvmlayer)
: llvm(llvmlayer){}
private:
LLVMLayer* llvm;
};
}
#endif // LLVMLAYER_H
diff --git a/cpp/src/modules.h b/cpp/src/modules.h
index 3be3aaa..fbc4ee9 100644
--- a/cpp/src/modules.h
+++ b/cpp/src/modules.h
@@ -1,76 +1,78 @@
/* 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: modules.h
* Author: pgess <v.melnychenko@xreate.org>
*
* Created on July 22, 2017, 5:11 PM
*/
#ifndef MODULES_H
#define MODULES_H
#include "ast.h"
#include <boost/bimap.hpp>
#ifndef FRIENDS_MODULES_TESTS
#define FRIENDS_MODULES_TESTS
#endif
namespace xreate { namespace modules{
class ModulesSolver;
-/**\brief Holds information related to an individual module
+/**
+ * \brief An individual module specific information
* \sa XreateManagerDecoratorModules, ModulesSolver, ModulesRegistry
*/
class ModuleRecord {
FRIENDS_MODULES_TESTS
friend class ModulesSolver;
public:
void addRequest(const Expression& request);
void addControllerPath(const std::string& path);
void addDiscoveryPath(const std::string& path);
void addProperty(const Expression& prop);
private:
std::list<Expression> __requests;
std::list<std::string> __controllers;
std::list<std::string> __discoveryPaths;
std::list<Expression> __properties;
public:
std::string __path;
};
-/** \brief Resolves module's requrements
+/**
+ * \brief A module's requirements resolver
* \sa XreateManagerDecoratorModules, ModuleRecord
*/
class ModulesSolver{
FRIENDS_MODULES_TESTS
public:
ModulesSolver(){}
/** \brief Loads content of *controllers* into logic program for resolution */
void loadControllers(const ModuleRecord& module);
/** \brief Discovers specified path for existing modules and stores found modules' properties */
void discoverModules(const ModuleRecord& moduleClient);
void extractProperties(const ModuleRecord& module);
void extractRequirements(const ModuleRecord& module);
void add(const std::string& base);
void init(const std::string& programBase, const ModuleRecord& module);
std::list<std::string> run(const ModuleRecord& module);
public:
std::ostringstream __program;
};
}} //end namespace xreate::modules
#endif /* MODULES_H */
diff --git a/cpp/src/pass/abstractpass.cpp b/cpp/src/pass/abstractpass.cpp
index 9cc6285..26b3195 100644
--- a/cpp/src/pass/abstractpass.cpp
+++ b/cpp/src/pass/abstractpass.cpp
@@ -1,103 +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>
*/
/**
* \file abstractpass.h
* \brief Infrastructure to iterate over AST to facilitate analysis and compilation.
*/
#include "abstractpass.h"
#include "attachments.h"
#include "xreatemanager.h"
using namespace std;
namespace xreate {
template<>
void defaultValue<void>(){}
void IPass::finish(){}
IPass::IPass(PassManager *manager)
: man(manager) {
}
template<>
void
AbstractPass<void>::processSymbol(const Symbol& symbol, PassContext context, const std::string& hintSymbol)
{
if (__visitedSymbols.isCached(symbol))
return;
__visitedSymbols.setCachedValue(symbol);
const Expression& declaration = CodeScope::getDefinition(symbol, true);
if (declaration.isDefined()){
PassContext context2 = context.updateScope(symbol.scope);
process(declaration, context2, hintSymbol);
}
}
template<>
void
AbstractPass<void>::process(const Expression& expression, PassContext context, const std::string& varDecl){
if (expression.__state == Expression::COMPOUND){
for (const Expression &op: expression.getOperands()) {
process(op, context);
}
for (CodeScope* scope: expression.blocks) {
process(scope, context);
}
if (expression.op == Operator::CALL){
processExpressionCall(expression, context);
}
return;
}
if (expression.__state == Expression::IDENT){
assert(context.scope);
processSymbol(Attachments::get<IdentifierSymbol>(expression), context, expression.getValueString());
}
}
}
/**
* \class xreate::IPass
*
- * Each pass has to have IPass interface to be controllable by XreateManager.
- * However in most cases users should inherit minimal useful implementation xreate::AbstractPass
+ * An each pass has to have IPass interface to be controllable by \ref XreateManager.
+ * However in most cases users should inherit minimal useful implementation \ref xreate::AbstractPass
*
- * \note It's usually expected that custom Pass publish processing results by one of the following means:
- * - xreate::Attachments for communicating with other Passes
- * - IAnalysisReport to feed xreate::TranscendLayer solver
+ * \note It's usually expected that a custom pass publishes processing results by one of the following means:
+ * - xreate::Attachments for communicating with other passes
+ * - IAnalysisReport to prepare date for the \ref xreate::TranscendLayer solver
*
* \sa xreate::XreateManager, xreate::AbstractPass
*/
/**
* \class xreate::AbstractPass
*
- * Iterates over %AST and provides functions to alter processing of particular %AST nodes.
- * Thus client should not re-implement every possible node processing
- * and it's enough to focus only on relevant nodes.
+ * The class traverses the %AST in a minimally useful manner sparing clients from processing an every possible node manually.
+ * This way clients able to focus only on relevant nodes processing.
*
- * Template parameter `Output` specify type of node processing result data.
+ * The `Output` template parameter specifies the type of node processing result data.
*
- * Automatically caches already visited nodes
- *
- * \note It's usually expected that custom Pass publish processing results by one of the following means:
- * - xreate::Attachments for communicating with other Passes
- * - IAnalysisReport to feed xreate::TranscendLayer solver
+ * \note Automatically caches already visited nodes
*
+ * \note It's usually expected that a custom pass publishes processing results by one of the following means:
+ * - \ref xreate::Attachments for communicating with other passes
+ * - IAnalysisReport to prepare date for the \ref xreate::TranscendLayer solver
*
* \sa xreate::XreateManager, xreate::IPass, xreate::AST
*/
diff --git a/cpp/src/pass/abstractpass.h b/cpp/src/pass/abstractpass.h
index 77e1f0b..ea44e23 100644
--- a/cpp/src/pass/abstractpass.h
+++ b/cpp/src/pass/abstractpass.h
@@ -1,205 +1,206 @@
/* 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>
*/
#ifndef ABSTRACTPASS_H
#define ABSTRACTPASS_H
#include "ast.h"
#include "xreatemanager.h"
#include<iostream>
namespace xreate {
-/** \brief Holds current position in %AST while traversing*/
+
+/** \brief Holds current position in the %AST during traverse*/
struct PassContext {
const CodeScope* scope = 0;
ManagedFnPtr function;
ManagedRulePtr rule;
std::string varDecl;
PassContext() {}
PassContext updateScope(const CodeScope* scopeNew) {
PassContext context2{*this};
context2.scope = scopeNew;
return context2;
}
~PassContext() {}
};
-/** \brief Base class for all passes to inherit */
+/** \brief Interface for all passes to inherit. \ref xreate::PassManager holds a collection of passes to execute */
class IPass {
public:
IPass(PassManager* manager);
virtual ~IPass() {}
/** \brief Executes pass */
virtual void run() = 0;
/** \brief Finalizes pass. Empty by default*/
virtual void finish();
PassManager* man;
};
template<class Output>
Output
defaultValue();
template<>
void
defaultValue<void>();
-/** \brief Stores processing results for already visited nodes */
+/** \brief Stores processing results for the already visited nodes */
template<class Output>
class SymbolCache : private std::map<Symbol, Output> {
public:
bool isCached(const Symbol &symbol) {
return this->count(symbol);
}
Output setCachedValue(const Symbol &symbol, Output &&value) {
(*this)[symbol] = value;
return value;
}
Output getCachedValue(const Symbol &symbol) {
assert(this->count(symbol));
return this->at(symbol);
}
};
-/** \brief Set of already visited nodes */
+/** \brief Set of the already visited nodes */
template<>
class SymbolCache<void> : private std::set<Symbol> {
public:
bool isCached(const Symbol &symbol) {
bool result = this->count(symbol) > 0;
return result;
}
void setCachedValue(const Symbol &symbol) {
this->insert(symbol);
}
void getCachedValue(const Symbol &symbol) {
}
};
-/** \brief Minimal useful IPass implementation*/
+/** \brief Minimal \ref xreate::IPass implementation useful for many passes as the base class*/
template<class Output>
class AbstractPass : public IPass {
SymbolCache<Output> __visitedSymbols;
protected:
virtual Output processSymbol(const Symbol &symbol, PassContext context, const std::string &hintSymbol = "") {
if(__visitedSymbols.isCached(symbol))
return __visitedSymbols.getCachedValue(symbol);
const Expression &declaration = CodeScope::getDefinition(symbol, true);
if(declaration.isDefined()) {
PassContext context2 = context.updateScope(symbol.scope);
Output &&result = process(declaration, context2, hintSymbol);
return __visitedSymbols.setCachedValue(symbol, std::move(result));
}
return defaultValue<Output>();
}
Output processExpressionCall(const Expression &expression, PassContext context) {
const std::string &calleeName = expression.getValueString();
std::list<ManagedFnPtr> callees = man->root->getFunctionSpecializations(calleeName);
//Determined specialization
if(callees.size() == 1 && callees.front()) {
return processFnCall(callees.front(), context);
}
//Several specializations or External Fn
return processFnCallUncertain(calleeName, callees, context);
}
SymbolCache<Output> &getSymbolCache() {
return __visitedSymbols;
}
public:
AbstractPass(PassManager* manager)
: IPass(manager) {}
/** \brief Processes function invocation instruction */
virtual Output processFnCall(ManagedFnPtr functionCallee, PassContext context) {
return defaultValue<Output>();
}
/** \brief Processes function invocation instruction in uncertain cases
* \details Executed when it's impossible statically determine which exactly function is invoked.
*/
virtual Output processFnCallUncertain(const std::string& calleeName, const std::list<ManagedFnPtr>& candidates, PassContext context) {
return defaultValue<Output>();
}
/** \brief Processes Logic Rule */
virtual void process(ManagedRulePtr rule) {}
/** \brief Processes Function */
virtual Output process(ManagedFnPtr function) {
PassContext context;
context.function = function;
return process(function->getEntryScope(), context);
}
/** \brief Processes single CodeScope */
virtual Output process(CodeScope* scope, PassContext context, const std::string &hintBlockDecl = "") {
context.scope = scope;
return processSymbol(Symbol{ScopedSymbol::RetSymbol, scope}, context);
}
//TODO expose Symbol instead of varDecl. Required by DFAPass.
/** \brief Processes single Expression */
virtual Output process(const Expression &expression, PassContext context, const std::string &varDecl = "") {
if(expression.__state == Expression::IDENT) {
assert(context.scope);
return processSymbol(Attachments::get<IdentifierSymbol>(expression), context, expression.getValueString());
}
assert(false);
return defaultValue<Output>();
}
/** \brief Executes AST traverse */
void run() {
ManagedRulePtr rule = man->root->begin<MetaRuleAbstract>();
while(rule.isValid()) {
process(rule);
++rule;
}
ManagedFnPtr f = man->root->begin<Function>();
while(f.isValid()) {
process(f);
++f;
}
}
};
template<>
void
AbstractPass<void>::processSymbol(const Symbol &symbol, PassContext context, const std::string &hintSymbol);
template<>
void
AbstractPass<void>::process(const Expression &expression, PassContext context, const std::string &hintSymbol);
}
#endif
diff --git a/cpp/src/pass/cfapass.cpp b/cpp/src/pass/cfapass.cpp
index 3756331..5361c4f 100644
--- a/cpp/src/pass/cfapass.cpp
+++ b/cpp/src/pass/cfapass.cpp
@@ -1,124 +1,125 @@
/* 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/.
*
* cfapass.cpp
*
* Author: pgess <v.melnychenko@xreate.org>
*/
/**
* \file cfapass.h
* \brief Control Flow Analysis(CFA)
*/
#include "pass/cfapass.h"
#include "analysis/cfagraph.h"
#include <boost/range/iterator_range_core.hpp>
using namespace std;
namespace xreate {
namespace cfa {
void
CFAPass::initSignatures() {
auto range = man->root->__interfacesData.equal_range(CFA);
for(auto i = range.first; i != range.second; ++i) {
__signatures.emplace(i->second.op, i->second);
}
}
void
CFAPass::run() {
initSignatures();
return AbstractPass::run();
}
void
CFAPass::finish() {
man->transcend->registerReport(__context.graph);
return AbstractPass::finish();
}
void
CFAPass::processFnCall(ManagedFnPtr function, PassContext context) {
TranscendLayer* transcend = man->transcend;
__context.graph->addCallConnection(transcend->pack(context.scope), function->getName());
return AbstractPass::processFnCall(function, context);
}
void
CFAPass::processFnCallUncertain(const std::string& calleeName, const std::list<ManagedFnPtr>& candidates, PassContext context) {
TranscendLayer* transcend = man->transcend;
__context.graph->addCallConnection(transcend->pack(context.scope), calleeName);
return AbstractPass::processFnCallUncertain(calleeName, candidates, context);
}
void
CFAPass::process(CodeScope* scope, PassContext context, const std::string &hintBlockDecl) {
TranscendLayer* transcend = man->transcend;
const CodeScope* scopeParent = context.scope;
ScopePacked scopeId = transcend->pack(scope);
__context.graph->addScope(scope);
//Parent Relations
if(scopeParent) {
__context.graph->addParentConnection(scopeId, transcend->pack(scopeParent));
} else {
__context.graph->addParentConnection(scopeId, context.function->getName());
}
//TOTEST scope annotations
//SECTIONTAG context gather scope annotations
__context.graph->addScopeAnnotations(scopeId, scope->tags);
__context.graph->addContextRules(scopeId, scope->contextRules);
return AbstractPass::process(scope, context, hintBlockDecl);
}
//TOTEST scope annotations via scheme
void
CFAPass::process(const Expression &expression, PassContext context, const std::string &varDecl) {
TranscendLayer* transcend = man->transcend;
if(expression.__state == Expression::COMPOUND) {
Operator op = expression.op;
if(__signatures.count(op)) {
assert(expression.blocks.size());
for(const auto &scheme : boost::make_iterator_range(__signatures.equal_range(expression.op))) {
__context.graph->addScopeAnnotations(transcend->pack(expression.blocks.front()), scheme.second.getOperands());
}
}
}
return AbstractPass::process(expression, context, varDecl);
}
void
CFAPass::process(ManagedFnPtr function) {
__context.graph->addFunctionAnnotations(function->getName(), function->getTags());
return AbstractPass::process(function);
}
CFAPass::CFAPass(PassManager* manager)
: AbstractPass(manager), __context{new CFAGraph(manager->transcend)}
{
}
}
}
/**
* \class xreate::cfa::CFAPass
- * \details Provides CFA, important analysis for reasoning. Iterates over AST and stores collected data in CFAGraph
+ *
+ * Provides %CFA, an important analysis for the reasoning. Traverses over AST and stores the collected data in \ref xreate::cfa::CFAGraph.
*/
diff --git a/cpp/src/pass/cfapass.h b/cpp/src/pass/cfapass.h
index b4ee3c8..2c3bc3c 100644
--- a/cpp/src/pass/cfapass.h
+++ b/cpp/src/pass/cfapass.h
@@ -1,51 +1,51 @@
/* 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>
*
* cfapass.cpp
* Control Flow Graph building pass
*/
#ifndef CFGPASS_H
#define CFGPASS_H
#include "xreatemanager.h"
#include "transcendlayer.h"
#include "abstractpass.h"
#include "analysis/cfagraph.h"
namespace xreate{namespace cfa {
class CFAGraph;
-/** \brief Control Flow Analysis Pass(%CFA)*/
+/** \brief %CFA(Control Flow Analysis) implementation */
class CFAPass : public AbstractPass<void>{
public:
void process(ManagedFnPtr function) override;
void processFnCall(ManagedFnPtr function, PassContext context) override;
void processFnCallUncertain(const std::string& calleeName, const std::list<ManagedFnPtr>& candidates, PassContext context) override;
void process(CodeScope* scope, PassContext context, const std::string& hintBlockDecl="") override;
void process(const Expression& expression, PassContext context, const std::string& varDecl="") override;
CFAPass(PassManager* manager);
void finish() override;
void run() override;
const CFAGraph* getReport() const {return __context.graph; }
protected:
struct {
CFAGraph* graph;
} __context;
std::multimap<Operator, Expression> __signatures; //CFA data for particular operators
void initSignatures();
};
}} //end of namespace xreate::cfa
#endif // CFGPASS_H
diff --git a/cpp/src/pass/cfatemporalseqpass.cpp b/cpp/src/pass/cfatemporalseqpass.cpp
index 9710e61..9ecca90 100644
--- a/cpp/src/pass/cfatemporalseqpass.cpp
+++ b/cpp/src/pass/cfatemporalseqpass.cpp
@@ -1,125 +1,120 @@
/* 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: cfatemporalseqpass.cpp
* Author: pgess
*
* Created on February 4, 2019, 4:43 PM
*/
-/**
- * \file cfatemporalseqpass.h
- * \brief Context Blocks' compilation order analysis.
- */
-
#include "pass/cfatemporalseqpass.h"
#include "analysis/temporalseqgraph.h"
using namespace xreate::cfa;
using namespace std;
namespace xreate {
template<>
cfa::Socket defaultValue<cfa::Socket>() {
const cfa::TemporalNode invalidNode{(ScopePacked) - 1, cfa::TemporalOperator::EMPTY};
return make_pair(invalidNode, invalidNode);
};
}
CFATemporalSeqPass::CFATemporalSeqPass(PassManager* manager)
: AbstractPass(manager), __graph(new TemporalSeqGraph(manager->transcend)) { }
void
CFATemporalSeqPass::finish() {
man->transcend->registerReport(__graph);
return AbstractPass::finish();
}
void
CFATemporalSeqPass::process(
const Expression &expression,
PassContext context,
const std::string &varDecl) {
TranscendLayer* transcend = man->transcend;
if(expression.__state == Expression::COMPOUND) {
Operator op = expression.op;
switch(op) {
case Operator::QUERY_LATE:
case Operator::MAP:
case Operator::FOLD:
case Operator::INF:
{
__graph->addSubScopes(context.scope,
expression.blocks);
break;
}
case Operator::IF:
case Operator::SWITCH:
case Operator::SWITCH_LATE:
case Operator::SWITCH_VARIANT:
{
__graph->addBranchScopes(context.scope,
expression.blocks);
break;
}
case Operator::SEQUENCE:
{
auto socket = __graph->addSocket(context.scope, TemporalOperator::AND);
auto nodeFrom = socket.first;
for(auto scopeIt = expression.blocks.begin(); scopeIt != expression.blocks.end(); ++scopeIt) {
ScopePacked scope = transcend->pack(*scopeIt);
TemporalNode node{scope, TemporalOperator::SCOPE};
__graph->connect(nodeFrom, node);
nodeFrom = node;
}
__graph->connect(nodeFrom, socket.second);
}
default:
break;
}
}
return Parent::process(expression, context, varDecl);
}
void
CFATemporalSeqPass::processFnCall(ManagedFnPtr functionCallee, PassContext context) {
auto callerSock = __graph->addSocket(context.scope, TemporalOperator::AND);
auto calleeSock = __graph->getFnSocket(functionCallee);
__graph->connectGuarded(callerSock, calleeSock);
}
void
CFATemporalSeqPass::processFnCallUncertain(const std::string& calleeName, const std::list<ManagedFnPtr>& candidates, PassContext context) {
auto callerSock = __graph->addSocket(context.scope, TemporalOperator::AND);
auto calleeSock = __graph->getUncertainFnSocket(calleeName, candidates);
__graph->connectGuarded(callerSock, calleeSock);
}
void
CFATemporalSeqPass::process(ManagedFnPtr function) {
TranscendLayer* transcend = man->transcend;
Socket fnSocket = __graph->getFnSocket(function);
TemporalNode entryNode{
transcend->pack(function->getEntryScope()),
TemporalOperator::SCOPE
};
__graph->connect(fnSocket.first, entryNode);
__graph->connect(entryNode, fnSocket.second);
return Parent::process(function);
}
\ No newline at end of file
diff --git a/cpp/src/pass/cfatemporalseqpass.h b/cpp/src/pass/cfatemporalseqpass.h
index c5d15e6..95a1dc2 100644
--- a/cpp/src/pass/cfatemporalseqpass.h
+++ b/cpp/src/pass/cfatemporalseqpass.h
@@ -1,41 +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: cfatemporalseqpass.h
* Author: pgess
*
* Created on February 4, 2019, 4:43 PM
*/
+/**
+ * \file cfatemporalseqpass.h
+ * \brief Code blocks execution order analysis
+ */
+
#ifndef CFATEMPORALSEQPASS_H
#define CFATEMPORALSEQPASS_H
#include "xreatemanager.h"
#include "abstractpass.h"
namespace xreate{namespace cfa {
class TemporalSeqGraph;
+/** \brief Code blocks execution order analysis. The results are stored in the \ref xreate::cfa::TemporalSeqGraph graph */
class CFATemporalSeqPass: public AbstractPass<void>{
typedef AbstractPass<void> Parent;
public:
CFATemporalSeqPass(PassManager* manager);
void processFnCall(ManagedFnPtr functionCallee, PassContext context) override;
void processFnCallUncertain(const std::string& calleeName, const std::list<ManagedFnPtr>& candidates, PassContext context) override;
void process(const Expression& expression, PassContext context, const std::string& varDecl="") override;
void process(ManagedFnPtr function) override;
const TemporalSeqGraph* getReport() const {return __graph; }
void finish() override;
private:
TemporalSeqGraph* __graph;
};
}} //end of namespace xreate::cfa
#endif /* CFATEMPORALSEQPASS_H */
diff --git a/cpp/src/pass/compilepass.cpp b/cpp/src/pass/compilepass.cpp
index 7cf3994..55384ef 100644
--- a/cpp/src/pass/compilepass.cpp
+++ b/cpp/src/pass/compilepass.cpp
@@ -1,775 +1,780 @@
/* 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 Compilation pass
+ * \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]);
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));
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 Encapsulates all compilation activities
+ * \brief The owner of the compilation process. Performs fundamental compilation activities along with the xreate::compilation's routines
*
- * xreate::CompilePass iterates over xreate::AST tree and produces executable code fed by data(via xreate::Attachments) gathered by previous passes as well as data via queries(xreate::IQuery) from xreate:TranscendLayer reasoner.
- * Compilation's done using xreate::LLVMLayer(wrapper over LLVM toolchain) and based on following aspects:
- * - Containers support. See \ref compilation/containers.h
- * - Late Conext compilation. See xreate::context::LateContextCompiler2
- * - Interpretation support. See xreate::interpretation::TargetInterpretation
- * - Loop saturation support. See xreate::compilation::TransformerSaturation
- * - External Code access. See xreate::ExternLayer(wrapper over Clang library)
+ * 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 architecture provides adaptability by employing:
- * - %Function Decorators to alter function-level compilation. See xreate::compilation::IFunctionUnit
- * - Code Block Decorators to alter code block level compilation. See xreate::compilation::ICodeScopeUnit
- * Default functionality defined by \ref xreate::compilation::DefaultCodeScopeUnit
+ * 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 xreate::compilation::Target
- * - %Altering Function invocation. xreate::compilation::ICallStatement
+ * Currently only xreate::interpretation::TargetInterpretation use Targets infrastructure. See \ref xreate::compilation::Target.
+ * - Altering %function invocation. See \ref xreate::compilation::IFnInvocation.
*
- * Client able to construct compiler with desired decorators using xreate::compilation::CompilePassCustomDecorators.
- * As a handy alias, `CompilePassCustomDecorators<void, void>` constructs default compiler
+ * 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/pass/compilepass.h b/cpp/src/pass/compilepass.h
index 7853fb8..dc4aba2 100644
--- a/cpp/src/pass/compilepass.h
+++ b/cpp/src/pass/compilepass.h
@@ -1,208 +1,210 @@
/* 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.h
*/
#ifndef COMPILEPASS_H
#define COMPILEPASS_H
#include "abstractpass.h"
#include "llvm/IR/Function.h"
namespace xreate {
class TranscendLayer;
class CompilePass;
class LLVMLayer;
namespace interpretation{
class TargetInterpretation;
}
}
namespace xreate { namespace compilation {
class ICodeScopeUnit;
class IFunctionUnit;
class TransformationsManager;
/** \brief Holds current position in %AST while traversing*/
struct Context{
ICodeScopeUnit* scope;
IFunctionUnit* function;
CompilePass* pass;
};
-/** \brief Interface to specify custom way of function invocation
- * \details Default implementation is xreate::compilation::RawFnInvocation
+/** \brief Interface for custom function invocation operation compilation
+ * \details Default implementation is xreate::compilation::BruteFnInvocation
*/
class IFnInvocation {
public:
- /** \brief Returns result of custom function invocation for given arguments*/
+ /** \brief Returns result of custom function invocation for the given arguments*/
virtual llvm::Value* operator() (std::vector<llvm::Value *>&& args, const std::string& hintDecl="") = 0;
};
/** \brief Default IFnInvocation implementation */
class BruteFnInvocation: public IFnInvocation{
public:
BruteFnInvocation(llvm::Function* callee, LLVMLayer* l)
: __callee(callee), __calleeTy(callee->getFunctionType()), llvm(l) {}
BruteFnInvocation(llvm::Value* callee, llvm::FunctionType* ty, LLVMLayer* l)
: __callee(callee), __calleeTy(ty), llvm(l) {}
/** \brief Makes type conversions and returns LLVM call statement with given arguments*/
llvm::Value* operator() (std::vector<llvm::Value *>&& args, const std::string& hintDecl="");
protected:
llvm::Value* __callee;
llvm::FunctionType* __calleeTy;
LLVMLayer* llvm;
};
/** \brief Interface to allow modification of CodeScope compilation
* \details Default implementation defined in xreate::compilation::DefaultCodeScopeUnit
*/
class ICodeScopeUnit{
public:
CompilePass* const pass;
IFunctionUnit* const function;
const CodeScope* const scope;
llvm::BasicBlock* currentBlockRaw;
ICodeScopeUnit(const CodeScope* const codeScope, IFunctionUnit* f, CompilePass* compilePass);
virtual ~ICodeScopeUnit();
virtual llvm::Value* compile(const std::string& hintBlockDecl="")=0;
virtual llvm::Value* processSymbol(const Symbol& s, std::string hintRetVar="")=0;
virtual llvm::Value* process(const Expression& expr, const std::string& hintVarDecl="")=0;
virtual Symbol bindArg(llvm::Value* value, std::string&& alias)=0;
virtual void bindArg(llvm::Value* value, const ScopedSymbol& s)=0;
virtual void reset() = 0;
protected:
+
+ /** \brief For subclasses to implement this method to define a function name resolution*/
virtual IFnInvocation* findFunction(const Expression& opCall)=0;
};
/** \brief Minimal useful ICodeScopeUnit implementation suited for inheritance */
class BasicCodeScopeUnit: public ICodeScopeUnit{
public:
BasicCodeScopeUnit(const CodeScope* const codeScope, IFunctionUnit* f, CompilePass* compilePass);
llvm::Value* processSymbol(const Symbol& s, std::string hintRetVar="") override;
llvm::Value* process(const Expression& expr, const std::string& hintVarDecl="") override;
llvm::Value* compile(const std::string& hintBlockDecl="") override;
protected:
IFnInvocation* findFunction(const Expression& opCall) override;
};
/** \brief Interface to specify compilation of %Function */
class IFunctionUnit{
public:
IFunctionUnit(ManagedFnPtr f, CompilePass* p): function(f), pass(p) {}
virtual ~IFunctionUnit();
llvm::Function* compile();
ICodeScopeUnit* getEntry();
ICodeScopeUnit* getScopeUnit(const CodeScope * const scope);
ICodeScopeUnit* getScopeUnit(ManagedScpPtr scope);
virtual llvm::Type* prepareResult() = 0;
ManagedFnPtr function;
llvm::Function* raw = nullptr;
protected:
CompilePass* pass=nullptr;
virtual std::string prepareName() = 0;
virtual std::vector<llvm::Type*> prepareSignature() = 0;
virtual llvm::Function::arg_iterator prepareBindings() = 0;
private:
std::map<const CodeScope * const, std::weak_ptr<ICodeScopeUnit>> __scopes;
std::list<std::shared_ptr<ICodeScopeUnit>> __orphanedScopes;
};
/** \brief Minimal useful IFunctionUnit implementation suited for inheritance */
class BasicFunctionUnit: public IFunctionUnit{
public:
BasicFunctionUnit(ManagedFnPtr f, CompilePass* p)
: IFunctionUnit(f, p) {}
protected:
std::string prepareName() override;
virtual std::vector<llvm::Type*> prepareSignature() override;
virtual llvm::Type* prepareResult() override;
virtual llvm::Function::arg_iterator prepareBindings() override;
};
} // end of namespace compilation
class CompilePass : public AbstractPass<void> {
friend class compilation::BasicCodeScopeUnit;
friend class compilation::IFunctionUnit;
public:
compilation::TransformationsManager* managerTransformations;
interpretation::TargetInterpretation* targetInterpretation;
CompilePass(PassManager* manager): AbstractPass<void>(manager) {}
/** \brief Executes compilation process */
void run() override;
/**\brief Returns compiled specified %Function
* \details Executes function compilation or read cache if it's already done
*/
compilation::IFunctionUnit* getFunctionUnit(const ManagedFnPtr& function);
/**\brief Returns compiled main(entry) %Function in program */
llvm::Function* getEntryFunction();
/** \brief Initializes queries required by compiler. See xreate::IQuery, xreate::TranscendLayer */
static void prepareQueries(TranscendLayer* transcend);
protected:
virtual compilation::IFunctionUnit* buildFunctionUnit(const ManagedFnPtr& function)=0;
virtual compilation::ICodeScopeUnit* buildCodeScopeUnit(const CodeScope* const scope, compilation::IFunctionUnit* function)=0;
private:
//TODO free `functions` in destructor
std::map<unsigned int, compilation::IFunctionUnit*> functions;
llvm::Function* entry = 0;
};
namespace compilation{
/** \brief Constructs compiler with desired %Function and %Code Scope decorators. See adaptability in xreate::CompilePass*/
template<class FUNCTION_DECORATOR=void, class SCOPE_DECORATOR=void>
class CompilePassCustomDecorators: public ::xreate::CompilePass{
public:
CompilePassCustomDecorators(PassManager* manager): ::xreate::CompilePass(manager) {}
virtual compilation::IFunctionUnit* buildFunctionUnit(const ManagedFnPtr& function) override{
return new FUNCTION_DECORATOR(function, this);
}
virtual compilation::ICodeScopeUnit* buildCodeScopeUnit(const CodeScope* const scope, IFunctionUnit* function) override{
return new SCOPE_DECORATOR(scope, function, this);
}
};
template<>
compilation::IFunctionUnit*
CompilePassCustomDecorators<void, void>::buildFunctionUnit(const ManagedFnPtr& function);
template<>
compilation::ICodeScopeUnit*
CompilePassCustomDecorators<void, void>::buildCodeScopeUnit(const CodeScope* const scope, IFunctionUnit* function);
}} //end of namespace xreate::compilation
#endif // COMPILEPASS_H
diff --git a/cpp/src/pass/dfapass.cpp b/cpp/src/pass/dfapass.cpp
index de02dc1..e4adedc 100644
--- a/cpp/src/pass/dfapass.cpp
+++ b/cpp/src/pass/dfapass.cpp
@@ -1,266 +1,266 @@
/* 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>
*
* dfapass.cpp
*/
/**
* \file dfapass.h
- * \brief Data Flow Analysis(DFA)
+ * \brief Data Flow Analysis
*/
//DEBT DFA represent VersionaPass in declarative form using applyDependencies
// applyDependencies(expression, context, cache, decl);
//DEBT DFA prepare static annotations and represent InterpretationPass in declarative form
// applyStaticAnnotations(expression, context, cache, decl);
//DEBT DFA Eliminate dfa schemes
#include "pass/dfapass.h"
#include "xreatemanager.h"
#include "transcendlayer.h"
#include <boost/format.hpp>
#include <boost/variant/variant.hpp>
using namespace std;
namespace xreate {namespace dfa {
DFAPass::DFAPass(PassManager* manager)
: AbstractPass(manager)
, graph{new DFAGraph()}
, transcend(manager->transcend) { }
void
DFAPass::processCallInstance(const Expression& expr, PassContext context, const SymbolNode& result) {
const string &nameCalleeFunction=expr.getValueString();
//TODO implement processFnCall/Uncertain
list<ManagedFnPtr> variantsCalleeFunction=man->root->getFunctionSpecializations(nameCalleeFunction);
vector<SymbolNode> operands;
operands.reserve(expr.getOperands().size());
for(const Expression& arg : expr.getOperands()) {
operands.push_back(process(arg, context));
}
//Set calling relations:
DFACallInstanceType type=variantsCalleeFunction.size()>1?WEAK:STRONG;
for(ManagedFnPtr function : variantsCalleeFunction) {
CodeScope *scopeRemote=function->getEntryScope();
DFACallInstance callInstance;
callInstance.fnName=function->getName();
callInstance.type=type;
std::vector<SymbolNode>::const_iterator nodeActual=operands.begin();
for(const std::string &identFormal : scopeRemote->__bindings) {
const ScopedSymbol symbolFormal{scopeRemote->__identifiers.at(identFormal), versions::VERSION_NONE};
SymbolPacked symbolFormalPacked=transcend->pack(Symbol{symbolFormal, scopeRemote}, nameCalleeFunction+":"+identFormal);
callInstance.args.push_back(std::make_pair(symbolFormalPacked, *nodeActual));
++nodeActual;
}
callInstance.retActual=result;
SymbolNode retFormal=SymbolNode(transcend->pack(Symbol{ScopedSymbol::RetSymbol, scopeRemote}, nameCalleeFunction+":[ret]"));
graph->addCallInstance(std::move(callInstance));
}
}
void
DFAPass::processDependencies(const SymbolNode& node, const Expression& expression, PassContext context, ProcessingCache& cache) {
cache.operands.reserve(expression.getOperands().size());
for(const Expression &op : expression.getOperands()) {
const SymbolNode& subnodeOperand=process(op, context);
cache.operands.push_back(subnodeOperand);
graph->addDependency(node, subnodeOperand);
}
cache.blocks.reserve(expression.blocks.size());
for(CodeScope* block : expression.blocks) {
const SymbolNode& subnodeBlock=process(block, context);
cache.blocks.push_back(subnodeBlock);
graph->addDependency(node, subnodeBlock);
}
}
void
DFAPass::processAnnotations(const Expression& expression, PassContext context, const SymbolNode& ident){
for (const pair<std::string, Expression>& tag : expression.tags){
graph->printInplaceAnnotation(ident, tag.second);
}
}
SymbolNode
DFAPass::process(const Expression& expression, PassContext context, const std::string& varDecl) {
SymbolNode result;
if(Attachments::exists<SymbolAlias>(expression)){
Symbol varSymbol=Attachments::get<SymbolAlias>(expression);
result=transcend->pack(varSymbol, varDecl);
} else if(expression.__state==Expression::IDENT&&expression.tags.size()==0){
Symbol varSymbol=Attachments::get<IdentifierSymbol>(expression);
result=transcend->pack(varSymbol, expression.getValueString());
} else {
result=SymbolAnonymous{expression.id};
}
processAnnotations(expression, context, result);
ProcessingCache cache;
switch(expression.__state) {
case Expression::COMPOUND: {
switch(expression.op) {
case Operator::CALL: {
processCallInstance(expression, context, result);
break;
}
case Operator::IF: {
const SymbolNode& scopeA=process(expression.blocks.front(), context, "ifTrue" + std::to_string(expression.id));
const SymbolNode& scopeB=process(expression.blocks.back(), context, "ifFalse" + std::to_string(expression.id));
const SymbolNode& condition=process(expression.operands.at(0), context);
graph->addDependency(result, scopeA);
graph->addDependency(result, scopeB);
graph->addDependency(result, condition);
graph->printWeakAlias(result, scopeA);
graph->printWeakAlias(result, scopeB);
break;
}
case Operator::SWITCH:
case Operator::SWITCH_VARIANT: {
for(CodeScope* block : expression.blocks) {
const SymbolNode& subnodeBlock=process(block, context, "case"+to_string(block->getBody().id));
graph->addDependency(result, subnodeBlock);
graph->printWeakAlias(result, subnodeBlock);
}
const SymbolNode& condition=process(expression.operands.at(0), context);
graph->addDependency(result, condition);
break;
}
case Operator::MAP:
processDependencies(result, expression, context, cache);
graph->printOperator(Operator::MAP, {result, cache.operands.at(0), cache.blocks.at(0)});
break;
case Operator::FOLD:
processDependencies(result, expression, context, cache);
graph->printOperator(Operator::FOLD, {result, cache.operands.at(0), cache.operands.at(1), cache.blocks.at(0)});
break;
case Operator::LIST:
processDependencies(result, expression, context, cache);
graph->printOperator(Operator::LIST, {result}, expression.getOperands().size());
break;
case Operator::LIST_RANGE:
processDependencies(result, expression, context, cache);
graph->printOperator(Operator::LIST_RANGE, {result});
break;
case Operator::INDEX:
processDependencies(result, expression, context, cache);
graph->printOperator(Operator::INDEX, {result, cache.operands.at(0), cache.operands.at(1)});
break;
default: {
processDependencies(result, expression, context, cache);
break;
}
}
break;
}
case Expression::IDENT: {
SymbolNode symbIdent=AbstractPass<SymbolNode>::process(expression, context, varDecl);
if(!(result==symbIdent)){
graph->addDependency(result, symbIdent);
graph->printAlias(result, symbIdent);
}
break;
}
case Expression::NUMBER:
case Expression::STRING: {
break;
}
case Expression::INVALID:
case Expression::BINDING: {
assert(false);
break;
}
}
return result;
}
SymbolNode
DFAPass::process(CodeScope* scope, PassContext context, const std::string& hintBlockDecl) {
if (!hintBlockDecl.empty()) {
Symbol symbRet{ScopedSymbol::RetSymbol, scope};
transcend->pack(symbRet, hintBlockDecl + ":[ret]");
}
for(const std::string& binding : scope->__bindings) {
Symbol bindingSymb{scope->getSymbol(binding), scope};
SymbolPacked bindingSymbP=transcend->pack(bindingSymb, binding);
getSymbolCache().setCachedValue(bindingSymb, SymbolNode(bindingSymbP));
processAnnotations(scope->getDefinition(bindingSymb), context, SymbolNode(bindingSymbP));
}
return AbstractPass<SymbolNode>::process(scope, context, hintBlockDecl);
}
SymbolNode
DFAPass::process(ManagedFnPtr function) {
transcend->pack(Symbol{ScopedSymbol::RetSymbol, function->getEntryScope()}, function->getName()+to_string(function.id())+":[ret]");
SymbolNode result=AbstractPass<SymbolNode>::process(function);
graph->printFunctionRet(function, result);
return result;
}
void
DFAPass::finish() {
transcend->registerReport(graph);
//Declare symbols:
graph->printSymbols(transcend);
AbstractPass::finish();
}
} //end of namespace dfa
template<>
SymbolNode
defaultValue() {
assert(false);
}
} //end of xreate namespace
/**
* \class xreate::dfa::DFAPass
- * \details Provides DFA, important analysis for reasoning. Iterates over AST and stores collected data in DFAGraph
+ * \details Provides DFA, an important analysis for the reasoning. Traverses over AST and stores the collected data in the \ref xreate::dfa::DFAGraph
*/
diff --git a/cpp/src/pass/dfapass.h b/cpp/src/pass/dfapass.h
index 0626a26..f27f6b5 100644
--- a/cpp/src/pass/dfapass.h
+++ b/cpp/src/pass/dfapass.h
@@ -1,52 +1,52 @@
/* 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>
*
* dfapass.h
* Data Flow Graph building pass
*/
#ifndef DFGPASS_H
#define DFGPASS_H
#include "abstractpass.h"
#include "analysis/dfagraph.h"
namespace xreate {
class TranscendLayer;
}
namespace xreate { namespace dfa {
struct ProcessingCache {
std::vector<SymbolNode> operands;
std::vector<SymbolNode> blocks;
};
-/** \brief Data Flow Analysis Pass(%DFA) */
+/** \brief Data Flow Analysis Pass */
class DFAPass: public AbstractPass<SymbolNode> {
public:
DFAPass(PassManager* manager);
protected:
virtual void processAnnotations(const Expression& expression, PassContext context, const SymbolNode& ident);
virtual SymbolNode process(const Expression& expression, PassContext context, const std::string& varDecl="") override;
virtual SymbolNode process(CodeScope* scope, PassContext context, const std::string& hintBlockDecl="") override;
virtual SymbolNode process(ManagedFnPtr function) override;
void init();
void finish() override;
DFAGraph* graph;
TranscendLayer* transcend;
private:
void processCallInstance(const Expression& expr, PassContext context, const SymbolNode& result);
void processDependencies(const SymbolNode& node, const Expression& expression, PassContext context, ProcessingCache& cache);
};
}} //end of xreate::dfa namespace
#endif
diff --git a/cpp/src/pass/interpretationpass.cpp b/cpp/src/pass/interpretationpass.cpp
index 9143ecb..e4b1265 100644
--- a/cpp/src/pass/interpretationpass.cpp
+++ b/cpp/src/pass/interpretationpass.cpp
@@ -1,554 +1,554 @@
/* 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: interpretationpass.cpp
* Author: pgess <v.melnychenko@xreate.org>
*
* Created on July 5, 2016, 5:21 PM
*/
/**
* \file interpretationpass.h
- * \brief Interpretation analysis: determines what parts of code could be interpreted
+ * \brief Interpretation analysis: determines what parts of a code could be interpreted
*/
#include "pass/interpretationpass.h"
#include <compilation/targetinterpretation.h>
#include <bits/stl_vector.h>
#include "ast.h"
//DEBT implement InterpretationPass purely in transcend
//DEBT represent InterpretationPass as general type inference
using namespace std;
namespace xreate {
template<>
interpretation::InterpretationResolution
defaultValue<interpretation::InterpretationResolution>() {
return interpretation::CMPL_ONLY;
}
namespace interpretation {
enum InterpretationQuery {
QUERY_INTR_ONLY, QUERY_CMPL_ONLY
};
namespace details {
template<InterpretationQuery FLAG_REQUIRED>
bool
checkConstraints(InterpretationResolution flag) {
return( (flag==INTR_ONLY&&FLAG_REQUIRED==QUERY_INTR_ONLY)
||(flag==CMPL_ONLY&&FLAG_REQUIRED==QUERY_CMPL_ONLY));
}
InterpretationResolution
recognizeTags(const map<std::string, Expression>& tags) {
auto i=tags.find("i12n");
if(i==tags.end()){
return ANY;
}
assert(i->second.op==Operator::CALL);
const string& cmd=i->second.operands.at(0).getValueString();
//TODO make consistent names of annotation and resolution
if(cmd=="on"){
return INTR_ONLY;
} else if(cmd=="off"){
return CMPL_ONLY;
}
return ANY;
}
}
InterpretationResolution
unify(InterpretationResolution flag) {
return flag;
}
template<typename FLAG_A, typename FLAG_B, typename... FLAGS>
InterpretationResolution
unify(FLAG_A flagA, FLAG_B flagB, FLAGS... flags) {
if(flagA==ANY){
return unify(flagB, flags...);
}
if(flagB==ANY){
return unify(flagA, flags...);
}
assert(flagA==flagB);
return flagA;
}
template<InterpretationQuery FLAG_REQUIRED>
bool
checkConstraints(std::vector<InterpretationResolution>&& flags) {
assert(flags.size());
InterpretationResolution flag=flags.front();
return details::checkConstraints<FLAG_REQUIRED>(flag);
}
template<InterpretationQuery FLAG_REQUIRED_A, InterpretationQuery FLAG_REQUIRED_B, InterpretationQuery... FLAGS>
bool
checkConstraints(std::vector<InterpretationResolution>&& flags) {
assert(flags.size());
InterpretationResolution flag=flags.front();
flags.pop_back();
if(details::checkConstraints<FLAG_REQUIRED_A>(flag)){
return checkConstraints<FLAG_REQUIRED_B, FLAGS...>(move(flags));
}
return false;
}
bool
InterpretationData::isDefault() const {
return(resolution==ANY&&op==NONE);
}
void
recognizeTags(const Expression& e) {
InterpretationData tag{details::recognizeTags(e.tags), NONE};
if(!tag.isDefault())
Attachments::put<InterpretationData>(e, tag);
}
InterpretationResolution
recognizeTags(const ManagedFnPtr& f) {
return details::recognizeTags(f->getTags());
}
InterpretationPass::InterpretationPass(PassManager* manager)
: AbstractPass(manager) {
Attachments::init<FunctionInterpretationData>();
Attachments::init<InterpretationData>();
}
void
InterpretationPass::run() {
ManagedFnPtr f=man->root->begin<Function>();
auto& visitedSymbols=getSymbolCache();
while(f.isValid()) {
const Symbol&symbolFunction{ScopedSymbol::RetSymbol, f->getEntryScope()};
if(!visitedSymbols.isCached(symbolFunction)){
visitedSymbols.setCachedValue(symbolFunction, process(f));
}
++f;
}
}
InterpretationResolution
InterpretationPass::process(const Expression& expression, PassContext context, const std::string& decl) {
recognizeTags(expression);
InterpretationResolution resolution=ANY;
InterpretationOperator opNo=NONE;
switch(expression.__state) {
case Expression::NUMBER:
case Expression::STRING:
{
break;
}
case Expression::IDENT:
{
resolution=Parent::processSymbol(Attachments::get<IdentifierSymbol>(expression), context);
break;
}
case Expression::COMPOUND:
break;
default:
{
resolution=CMPL_ONLY;
break;
}
}
if(expression.__state==Expression::COMPOUND)
switch(expression.op) {
case Operator::EQU:
case Operator::NE:
{
InterpretationResolution left=process(expression.operands[0], context);
InterpretationResolution right=process(expression.operands[1], context);
resolution=unify(left, right);
break;
}
case Operator::LOGIC_AND:
{
assert(expression.operands.size()==1);
resolution=process(expression.operands[0], context);
break;
}
case Operator::CALL:
{
size_t sizeOperands = expression.operands.size();
std::vector<InterpretationResolution> operands;
operands.reserve(sizeOperands);
for(size_t opNo=0; opNo<sizeOperands; ++opNo) {
const Expression &operand=expression.operands[opNo];
operands.push_back(process(operand, context));
}
//TODO cope with static/dynamic context
//TODO BUG here: if several variants they all are processed as CMPL regardless of signature
list<ManagedFnPtr> callees=man->root->getFunctionSpecializations(expression.getValueString());
if(callees.size()!=1){
resolution=CMPL_ONLY;
break;
}
ManagedFnPtr callee=callees.front();
const Symbol& symbCalleeFunc{ScopedSymbol::RetSymbol, callee->getEntryScope()};
//recursion-aware processing:
// - skip self recursion
const Symbol&symbSelfFunc{ScopedSymbol::RetSymbol, context.function->getEntryScope()};
if(!(symbSelfFunc==symbCalleeFunc)){
InterpretationResolution resCallee=processFnCall(callee, context);
assert(resCallee!=FUNC_POSTPONED&&"Indirect recursion detected: can't decide on interpretation resolution");
resolution=unify(resolution, resCallee);
}
//check arguments compatibility
const FunctionInterpretationData& calleeSignature=FunctionInterpretationHelper::getSignature(callee);
for(size_t opNo=0; opNo<sizeOperands; ++opNo){
InterpretationResolution argActual=operands.at(opNo);
InterpretationResolution argExpected=calleeSignature.signature[opNo];
//TODO use args unification result to properly process function call
unify(argActual, argExpected);
}
if(FunctionInterpretationHelper::needPartialInterpretation(callee)){
opNo=CALL_INTERPRET_PARTIAL;
}
break;
}
case Operator::CALL_INTRINSIC:
{
resolution=CMPL_ONLY;
break;
}
case Operator::QUERY:
{
resolution=INTR_ONLY;
break;
}
case Operator::QUERY_LATE:
{
InterpretationResolution predicate=process(expression.operands[0], context);
unify(predicate, INTR_ONLY);
CodeScope* exprBody=expression.blocks.front();
const std::string& argName=expression.bindings[0];
Symbol argS = {
ScopedSymbol{exprBody->__identifiers.at(argName), versions::VERSION_NONE},
exprBody
};
getSymbolCache().setCachedValue(argS, INTR_ONLY);
Parent::process(expression.blocks.front(), context);
resolution = CMPL_ONLY;
opNo=QUERY_LATE;
break;
}
case Operator::SWITCH_LATE:
{
resolution = CMPL_ONLY;
opNo = SWITCH_LATE;
break;
}
case Operator::IF:
{
InterpretationResolution flagCondition=process(expression.getOperands()[0], context);
InterpretationResolution flagScope1=Parent::process(expression.blocks.front(), context);
InterpretationResolution flagScope2=Parent::process(expression.blocks.back(), context);
//special case: IF_INTERPRET_CONDITION
if(checkConstraints<QUERY_INTR_ONLY>({flagCondition})){
opNo=IF_INTERPRET_CONDITION;
flagCondition=ANY;
}
resolution=unify(flagCondition, flagScope1, flagScope2);
break;
}
case Operator::FOLD:
{
InterpretationResolution flagInput=process(expression.getOperands()[0], context);
InterpretationResolution flagAccumInit=process(expression.getOperands()[1], context);
CodeScope* scopeBody=expression.blocks.front();
const std::string& nameEl=expression.bindings[0];
Symbol symbEl{ScopedSymbol
{scopeBody->__identifiers.at(nameEl), versions::VERSION_NONE}, scopeBody};
getSymbolCache().setCachedValue(symbEl, InterpretationResolution(flagInput));
const std::string& nameAccum=expression.bindings[1];
Symbol symbAccum{ScopedSymbol
{scopeBody->__identifiers.at(nameAccum), versions::VERSION_NONE}, scopeBody};
getSymbolCache().setCachedValue(symbAccum, InterpretationResolution(flagAccumInit));
InterpretationResolution flagBody=Parent::process(expression.blocks.front(), context);
//special case: FOLD_INTERPRET_INPUT
if(checkConstraints<QUERY_INTR_ONLY>({flagInput})){
opNo=FOLD_INTERPRET_INPUT;
flagInput=ANY;
}
resolution=unify(flagInput, flagAccumInit, flagBody);
break;
}
case Operator::INDEX:
{
for(const Expression &opNo : expression.getOperands()) {
resolution=unify(resolution, process(opNo, context));
}
break;
}
case Operator::SWITCH:
{
InterpretationResolution flagCondition=process(expression.operands[0], context);
bool hasDefaultCase=expression.operands[1].op==Operator::CASE_DEFAULT;
//determine conditions resolution
InterpretationResolution flagHeaders=flagCondition;
for(size_t size=expression.operands.size(), i=hasDefaultCase?2:1; i<size; ++i) {
const Expression& exprCase=expression.operands[i];
flagHeaders=unify(flagHeaders, Parent::process(exprCase.blocks.front(), context));
}
if(checkConstraints<QUERY_INTR_ONLY>({flagHeaders})){
opNo=SWITCH_INTERPRET_CONDITION;
flagHeaders=ANY;
}
//determine body resolutions
resolution=flagHeaders;
for(size_t size=expression.operands.size(), i=1; i<size; ++i) {
const Expression& exprCase=expression.operands[i];
resolution=unify(resolution, Parent::process(exprCase.blocks.back(), context));
}
break;
}
case Operator::SWITCH_VARIANT:
{
InterpretationResolution resolutionCondition=process(expression.operands.at(0), context);
resolution=resolutionCondition;
if(checkConstraints<QUERY_INTR_ONLY>({resolution})){
opNo=SWITCH_VARIANT;
resolution=ANY;
}
const string identCondition=expression.bindings.front();
for(auto scope : expression.blocks) {
//set binding resolution
ScopedSymbol symbolInternal=scope->getSymbol(identCondition);
getSymbolCache().setCachedValue(Symbol{symbolInternal, scope}, InterpretationResolution(resolutionCondition));
resolution=unify(resolution, Parent::process(scope, context));
}
for(auto scope : expression.blocks) {
resolution=unify(resolution, Parent::process(scope, context));
}
break;
}
case Operator::LIST:
{
for(const Expression &opNo : expression.getOperands()) {
resolution=unify(resolution, process(opNo, context));
}
break;
}
case Operator::VARIANT:
{
if(expression.getOperands().size()){
resolution=process(expression.getOperands().front(), context);
} else {
resolution=ANY;
}
break;
}
default:
{
resolution=CMPL_ONLY;
for(const Expression &opNo : expression.getOperands()) {
process(opNo, context);
}
for(CodeScope* scope : expression.blocks) {
Parent::process(scope, context);
}
break;
}
}
InterpretationData dataExpected=
Attachments::get<InterpretationData>(expression,{ANY, NONE});
resolution=unify(resolution, dataExpected.resolution);
if(resolution!=dataExpected.resolution || opNo != dataExpected.op ){
Attachments::put<InterpretationData>(expression,{resolution, opNo});
}
return resolution;
}
InterpretationResolution
InterpretationPass::processFnCall(ManagedFnPtr function, PassContext context) {
return process(function);
}
InterpretationResolution
InterpretationPass::process(ManagedFnPtr function) {
CodeScope* entry=function->getEntryScope();
std::vector<std::string> arguments=entry->__bindings;
const Symbol&symbSelfFunc{ScopedSymbol::RetSymbol, function->getEntryScope()};
auto& cache=getSymbolCache();
if(cache.isCached(symbSelfFunc))
return cache.getCachedValue(symbSelfFunc);
const FunctionInterpretationData& fnSignature=FunctionInterpretationHelper::getSignature(function);
InterpretationResolution fnResolutionExpected=details::recognizeTags(function->getTags());
//mark preliminary function resolution as expected
if(fnResolutionExpected!=ANY){
cache.setCachedValue(symbSelfFunc, move(fnResolutionExpected));
} else {
// - in order to recognize indirect recursion mark this function resolution as POSTPONED
cache.setCachedValue(symbSelfFunc, FUNC_POSTPONED);
}
//set resolution for function arguments as expected
for(int argNo=0, size=arguments.size(); argNo<size; ++argNo) {
Symbol symbArg{ScopedSymbol
{entry->__identifiers.at(arguments[argNo]), versions::VERSION_NONE}, entry};
cache.setCachedValue(symbArg, InterpretationResolution(fnSignature.signature[argNo]));
}
PassContext context;
context.function=function;
context.scope=entry;
InterpretationResolution resActual=process(CodeScope::getDefinition(symbSelfFunc), context);
resActual=unify(resActual, fnResolutionExpected);
return cache.setCachedValue(symbSelfFunc, move(resActual));
}
const FunctionInterpretationData
FunctionInterpretationHelper::getSignature(ManagedFnPtr function) {
if(Attachments::exists<FunctionInterpretationData>(function)){
return Attachments::get<FunctionInterpretationData>(function);
}
FunctionInterpretationData&& data=recognizeSignature(function);
Attachments::put<FunctionInterpretationData>(function, data);
return data;
}
FunctionInterpretationData
FunctionInterpretationHelper::recognizeSignature(ManagedFnPtr function) {
CodeScope* entry=function->__entry;
FunctionInterpretationData result;
result.signature.reserve(entry->__bindings.size());
bool flagPartialInterpretation=false;
for(size_t no=0, size=entry->__bindings.size(); no<size; ++no) {
const std::string& argName=entry->__bindings[no];
Symbol symbArg{ScopedSymbol
{entry->__identifiers.at(argName), versions::VERSION_NONE}, entry};
const Expression& arg=CodeScope::getDefinition(symbArg);
InterpretationResolution argResolution=details::recognizeTags(arg.tags);
flagPartialInterpretation|=(argResolution==INTR_ONLY);
result.signature.push_back(argResolution);
}
result.flagPartialInterpretation=flagPartialInterpretation;
return result;
}
bool
FunctionInterpretationHelper::needPartialInterpretation(ManagedFnPtr function) {
const FunctionInterpretationData& data=getSignature(function);
return data.flagPartialInterpretation;
}
}
} //end of namespace xreate::interpretation
/** \class xreate::interpretation::InterpretationPass
*
- * Encapsulates *Interpretation Analysis* to support [Interpretation Concept](/w/concepts/dfa)
+ * The class encapsulates *Interpretation Analysis* to support [Interpretation](/d/concepts/interpretation/).
*
- * Recognizes program functions, expressions, instructions eligible for interpretation
- * and stores output in Attachments<FunctionInterpretationData> and Attachments<InterpretationData>
+ * It recognizes program functions, expressions, instructions eligible for interpretation
+ * and stores the output in \ref Attachments<FunctionInterpretationData> and \ref Attachments<InterpretationData>
*
- * There are number of instructions currently able to be interpreted:
+ * There are number of instructions currently eligible for interpretation:
* - Basic literals: numbers and strings
* - Compounds: lists, structs, variants
* - Non-versioned identifiers
* - Comparison and logic operators
* - %Function calls
* - `query` intrinsic function calls
* - Branching: `if`, `loop fold`, `switch`, `switch variant` statements
*
- * Some of those instructions are eligibile for *late interpretation* to allow coupling
+ * Some of these instructions are eligible also for *late interpretation* to allow coupling
* of compiled instructions with interpreted ones, those are:
* - Partial function calls
* - Branching: `if`, `loop fold`, `switch`, `switch variant` statements
*
- * \sa xreate::interpretation::TargetInterpretation, [Interpretation Concept](/w/concepts/dfa)
+ * \sa xreate::interpretation::TargetInterpretation, [Interpretation Concept](/d/concepts/interpretation/)
*/
diff --git a/cpp/src/pass/interpretationpass.h b/cpp/src/pass/interpretationpass.h
index 1f47aa2..22702bf 100644
--- a/cpp/src/pass/interpretationpass.h
+++ b/cpp/src/pass/interpretationpass.h
@@ -1,96 +1,96 @@
/* 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: interpretationpass.h
* Author: pgess <v.melnychenko@xreate.org>
*
* Created on July 5, 2016, 5:21 PM
*/
#ifndef INTERPRETATIONPASS_H
#define INTERPRETATIONPASS_H
#include "abstractpass.h"
#include <map>
#ifndef FRIENDS_INTERPRETATION_TESTS
#define FRIENDS_INTERPRETATION_TESTS
#endif
//TODO refactor interpretation. Get rid of InterpretationOperator, put only one operator - Hybrid/Late.
namespace xreate{ namespace interpretation{
enum InterpretationResolution{ANY, INTR_ONLY, CMPL_ONLY, FUNC_POSTPONED};
enum InterpretationOperator{
NONE, IF_INTERPRET_CONDITION, FOLD_INTERPRET_INPUT, QUERY_LATE,
SWITCH_INTERPRET_CONDITION, SWITCH_VARIANT, SWITCH_LATE,
CALL_INTERPRET_PARTIAL
};
struct InterpretationData{
InterpretationResolution resolution;
InterpretationOperator op;
bool isDefault() const;
};
struct FunctionInterpretationData{
typedef std::vector<InterpretationResolution> Signature;
Signature signature;
bool flagPartialInterpretation;
};
class FunctionInterpretationHelper {
public:
static const FunctionInterpretationData
getSignature(ManagedFnPtr function);
static bool needPartialInterpretation(ManagedFnPtr function);
private:
static FunctionInterpretationData recognizeSignature(ManagedFnPtr function);
};
-/** \brief Determines parts of program eligible for Interpretation. */
+/** \brief Provides the interpretation analysis. Determines parts of a program eligible for Interpretation by \ref xreate::interpretation::TargetInterpretation */
class InterpretationPass: public AbstractPass<InterpretationResolution> {
typedef AbstractPass<InterpretationResolution> Parent;
public:
InterpretationResolution process(const Expression& expression, PassContext context, const std::string& varDecl="") override;
InterpretationResolution process(ManagedFnPtr function);
InterpretationResolution processFnCall(ManagedFnPtr function, PassContext context);
InterpretationPass(PassManager* manager);
void run();
};
namespace details {
InterpretationResolution recognizeTags(const std::map<std::string, Expression>& tags);
}
} //end of namespace interpretation
template<>
interpretation::InterpretationResolution
defaultValue<interpretation::InterpretationResolution>();
template<>
struct AttachmentsDict<interpretation::FunctionInterpretationData>
{
typedef interpretation::FunctionInterpretationData Data;
static const unsigned int key = 5;
};
template<>
struct AttachmentsDict<interpretation::InterpretationData>
{
typedef interpretation::InterpretationData Data;
static const unsigned int key = 3;
};
} //end of namespace xreate
#endif /* INTERPRETATIONPASS_H */
diff --git a/cpp/src/pass/latereasoningpass.h b/cpp/src/pass/latereasoningpass.h
index 3d293b1..a048aca 100644
--- a/cpp/src/pass/latereasoningpass.h
+++ b/cpp/src/pass/latereasoningpass.h
@@ -1,188 +1,194 @@
/*
* 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, 7:20 PM
- *
+ */
+
+/**
* \file latereasoningpass.h
- * \brief latereasoningpass
+ * \brief Late Transcend Support
*/
+
#ifndef LATEREASONINGPASS_H
#define LATEREASONINGPASS_H
#include "pass/dfapass.h"
namespace xreate { namespace latereasoning {
+/** \brief Keeps track of defined late transcend parameters */
class LateReasoningScope{
public:
LateReasoningScope(LateReasoningScope* parent): __parent(parent){ }
boost::optional<LateParameter>
recognizeIdentifier(const std::string& identifier){
//Search identifier in the current scope
if(__identifiers.count(identifier)){
return make_pair(identifier, __identifiers.at(identifier));
}
//Search in the parent scope
if(__parent){
return __parent->recognizeIdentifier(identifier);
}
return boost::none;
}
void
addIdentifier(std::string idenName, const SymbolPacked& identSymbol){
__identifiers.emplace(idenName, identSymbol);
}
private:
std::map<std::string, SymbolPacked> __identifiers;
LateReasoningScope *__parent;
};
/**
- * \note Limitation: Produces late annotation with target as a symbol to which annotation is attached
+ * \brief Decorates \ref dfa::DFAPass to recognize and extract late annotations
+ * \extends xreate::dfa::DFAPass
+ * \note Limitation: Produces late annotation with the symbol the annotation is attached to being a target
*/
template<class Parent>
class LateReasoningDFAPassDecorator: public Parent{
public:
LateReasoningDFAPassDecorator(PassManager* manager): Parent(manager){ }
void
registerLateScope(CodeScope* scope, LateReasoningScope* scopeLate){
__dictScopes.emplace(scope, scopeLate);
}
private:
LateReasoningScope*
liftScope(const CodeScope* scope){
while(scope){
if(__dictScopes.count(scope)) return __dictScopes.at(scope);
scope = scope->__parent;
}
return nullptr;
}
std::list<LateParameter>
recognizeLateParameters(const Expression& expression, LateReasoningScope* scope){
std::list<LateParameter> result;
switch(expression.op){
case Operator::CALL:
{
for(const auto& op: expression.operands){
std::list<LateParameter> opResult = recognizeLateParameters(op, scope);
result.insert(result.end(), opResult.begin(), opResult.end());
}
if(!expression.operands.size()){
if(auto symbolRecognized = scope->recognizeIdentifier(expression.getValueString())){
result.push_back(*symbolRecognized);
}
}
break;
}
case Operator::NEG:
{
assert(expression.operands.size() == 1);
const Expression &op = expression.operands.at(0);
std::list<LateParameter> opResult = recognizeLateParameters(op, scope);
result.insert(result.end(), opResult.begin(), opResult.end());
};
case Operator::INVALID:
{
switch(expression.__state){
case Expression::NUMBER:
break;
default:
assert(true);
}
break;
}
default: break;
}
return result;
}
protected:
virtual SymbolNode process(const Expression& expression, PassContext context, const std::string& varDecl="") override{
if(expression.__state == Expression::COMPOUND && expression.op == Operator::SWITCH_LATE){
//Reserve late scope:
LateReasoningScope* scopeLate = new LateReasoningScope(liftScope(context.scope));
CodeScope* scopeBody = expression.blocks.front();
registerLateScope(scopeBody, scopeLate);
for(const std::string& identLate: expression.bindings){
ScopedSymbol identLateS = scopeBody->getSymbol(identLate);
SymbolPacked identLateSP = Parent::man->transcend->pack(Symbol{identLateS, scopeBody});
scopeLate->addIdentifier(identLate, identLateSP); //Assign late identifiers
//Assign type(if isn't provided by user)
Expression identE = scopeBody->getDefinition(identLateS);
if (!identE.type.isValid()){
Expression sourceE = expression.getOperands().at(0);
Attachments::put<TypeInferred>(Symbol{identLateS, scopeBody}, Parent::man->root->getType(sourceE));
}
}
}
return Parent::process(expression, context, varDecl);
}
virtual void
processAnnotations(const Expression& expression,
PassContext context,
const SymbolNode& ident){
LateReasoningScope* scopeLate = liftScope(context.scope);
if(!expression.tags.size()) {return Parent::processAnnotations(expression, context, ident);}
if(!scopeLate) {return Parent::processAnnotations(expression, context, ident);}
for(const std::pair<std::string, Expression>& tag: expression.tags){
std::list<LateParameter> argsLate = recognizeLateParameters(tag.second, scopeLate);
if(!argsLate.size()){
//Standard compilation
Parent::graph->printInplaceAnnotation(ident, tag.second);
} else{
//Late compilation
std::list<std::string> domains;
for(const auto& arg: argsLate){
Symbol symbolUnpacked = Parent::man->transcend->unpack(arg.second);
ExpandedType typSymbol = Parent::man->root->getType(CodeScope::getDefinition(symbolUnpacked));
assert(typSymbol->__operator == TypeOperator::SLAVE);
domains.push_back(typSymbol->__valueCustom);
}
Parent::graph->printLateAnnotation(ident, tag.second, argsLate, domains);
}
}
}
private:
std::unordered_map<const CodeScope*, LateReasoningScope*> __dictScopes;
};
}}
#endif /* LATEREASONINGPASS_H */
diff --git a/cpp/src/pass/versionspass.cpp b/cpp/src/pass/versionspass.cpp
index 8129686..9a511f2 100644
--- a/cpp/src/pass/versionspass.cpp
+++ b/cpp/src/pass/versionspass.cpp
@@ -1,376 +1,380 @@
/* 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/.
*
* versionspass.cpp
*
* Author: pgess <v.melnychenko@xreate.org>
* Created on January 4, 2017, 3:13 PM
*/
-/** \class xreate::versions::VersionsPass
- * Has two parts:
- * - Validates correctness of versioned variables with regard to variables lifespan
- * - Determines versioned variables computation order
- * \sa VersionsScopeDecorator, VersionsGraph, [Versions Concept](/w/concepts/versions)
- */
-
#include <boost/optional/optional.hpp>
#include "pass/versionspass.h"
namespace std{
std::size_t
hash<xreate::versions::SymbolOrPlaceholder>::operator()(xreate::versions::SymbolOrPlaceholder const& s) const
{return std::hash<xreate::Symbol>()(s.symbol) + (s.flagEndOfLifePlaceholder? 9849 : 1);}
bool
equal_to<xreate::versions::SymbolOrPlaceholder>::operator()(const xreate::versions::SymbolOrPlaceholder& __x, const xreate::versions::SymbolOrPlaceholder& __y) const
{ return __x.flagEndOfLifePlaceholder == __y.flagEndOfLifePlaceholder && __x.symbol == __y.symbol; }
}
using namespace std;
namespace xreate {
template<>
std::list<Symbol>
defaultValue<std::list<Symbol>>(){
return std::list<Symbol>();
};
}
namespace xreate{ namespace versions{
inline std::string
printSymbol(const SymbolOrPlaceholder& s){
switch(s.flagEndOfLifePlaceholder){
case SYMBOL: return string("(") + std::to_string(s.symbol.identifier.id) + ", "+ std::to_string(s.symbol.identifier.version) + ")";
case PLACEHOLDER: return string("(") + std::to_string(s.symbol.identifier.id) + ", "+ std::to_string(s.symbol.identifier.version) + ")+";
}
return "";
}
void
VersionsGraph::__debug_print(std::ostream& output) const{
for(auto entry: __inferiors){
output << printSymbol(entry.second) << " <-" << printSymbol(entry.first) << "\n";
}
}
void
VersionsGraph::defineEndOfLife(const Symbol& symbol, const Symbol& symbolSuccessor){
if(__dictSuccessors.count(symbol)){
assert("No version branches allowed yet" && false);
}
const SymbolOrPlaceholder& placeholder = getEndOfLife(symbol);
auto inferiorsDeferred = __inferiors.equal_range(placeholder);
std::unordered_multimap<SymbolOrPlaceholder, SymbolOrPlaceholder> inferiorsReassigned;
for (const auto& inf: boost::make_iterator_range(inferiorsDeferred)){
inferiorsReassigned.emplace(SymbolOrPlaceholder{SYMBOL, symbolSuccessor}, inf.second);
}
__inferiors.erase(placeholder);
__inferiors.insert(inferiorsReassigned.begin(), inferiorsReassigned.end());
__inferiors.emplace(SymbolOrPlaceholder{SYMBOL, symbolSuccessor}, SymbolOrPlaceholder{SYMBOL, symbol});
__dictSuccessors.emplace(symbol, symbolSuccessor);
}
SymbolOrPlaceholder
VersionsGraph::getEndOfLife(const Symbol& s){
if (__dictSuccessors.count(s)){
return SymbolOrPlaceholder{SYMBOL, __dictSuccessors.at(s)}; }
return SymbolOrPlaceholder{PLACEHOLDER, s};
}
void
VersionsGraph::applyNatualDependencies(const Symbol& symbol, const std::list<Symbol>& dependencies){
for (const Symbol& right: dependencies){
__inferiorsNatural.emplace(symbol, right);
}
}
void
VersionsGraph::applyDependentEndOfLife(const SymbolOrPlaceholder& symbol, const list<Symbol>& dependencies){
for (const Symbol& right: dependencies){
auto rightEOF = getEndOfLife(right);
__inferiors.emplace(rightEOF, symbol);
}
}
bool
VersionsGraph::tryEliminateEofAliases(const std::list<SymbolOrPlaceholder>& aliases){
if (aliases.size()==1){
return true;
}
boost::optional<Symbol> symbolActualEoF;
for(const SymbolOrPlaceholder alias: aliases){
switch(alias.flagEndOfLifePlaceholder){
case SYMBOL:
if(symbolActualEoF){
return false;
}
symbolActualEoF = alias.symbol;
break;
case PLACEHOLDER:
continue;
}
}
if(!symbolActualEoF){
return false;
}
for(const SymbolOrPlaceholder alias: aliases){
switch(alias.flagEndOfLifePlaceholder){
case SYMBOL:
continue;
case PLACEHOLDER:
defineEndOfLife(alias.symbol, symbolActualEoF.get());
break;
}
}
return true;
}
std::list<SymbolOrPlaceholder>
VersionsGraph::extractCycle(const Path& path, const SymbolOrPlaceholder& symbolBeginning){
unsigned int posBeginning = path.at(symbolBeginning);
std::list<SymbolOrPlaceholder> result;
auto i=path.begin();
while(true){
i = std::find_if(i, path.end(), [&posBeginning](const auto& el){return el.second >=posBeginning;});
if (i!= path.end()){
result.push_back(i->first);
++i;
} else {break; }
}
return result;
}
bool
VersionsGraph::validateCycles(const SymbolOrPlaceholder& s,
std::unordered_multimap<SymbolOrPlaceholder, SymbolOrPlaceholder>& graph,
std::unordered_set<SymbolOrPlaceholder>& symbolsVisited,
Path& path)
{
if (symbolsVisited.count(s)) return true;
symbolsVisited.insert(s);
path.emplace(s, path.size());
if (graph.count(s)){
//iterate over imposed dependencies
auto candidates = graph.equal_range(s);
for (auto candidate = candidates.first; candidate != candidates.second; ++candidate){
if (path.count(candidate->second)) {
std::list<SymbolOrPlaceholder> cycle = extractCycle(path, candidate->second);
if (!tryEliminateEofAliases(cycle)) return false;
continue;
}
if(!validateCycles(candidate->second, graph, symbolsVisited, path)) return false;
}
}
//iterate over natural dependencies
if (s.flagEndOfLifePlaceholder == SYMBOL) {
auto candidates = __inferiorsNatural.equal_range(s.symbol);
for (auto candidate = candidates.first; candidate != candidates.second; ++candidate){
if (path.count(SymbolOrPlaceholder{SYMBOL, candidate->second})){
return false;
}
if(!validateCycles(SymbolOrPlaceholder{SYMBOL,candidate->second}, graph, symbolsVisited, path)) return false;
}
}
//check previous version
if (s.flagEndOfLifePlaceholder == PLACEHOLDER){
const Symbol& candidate = s.symbol;
if (path.count(SymbolOrPlaceholder{SYMBOL, candidate})){
std::list<SymbolOrPlaceholder> cycle = extractCycle(path, SymbolOrPlaceholder{SYMBOL, candidate});
if (!tryEliminateEofAliases(cycle)) return false;
}
if(!validateCycles(SymbolOrPlaceholder{SYMBOL,candidate}, graph, symbolsVisited, path)) return false;
}
path.erase(s);
return true;
}
bool
VersionsGraph::validateCycles(){
std::unordered_set<SymbolOrPlaceholder> symbolsVisited;
Path path;
std::unordered_multimap<SymbolOrPlaceholder, SymbolOrPlaceholder> graph(__inferiors);
std::unordered_multimap<SymbolOrPlaceholder, SymbolOrPlaceholder>::const_iterator s;
for (s = graph.begin(); s != graph.end(); ++s){
if(!validateCycles(s->first, graph, symbolsVisited, path)) return false;
}
return true;
}
bool
VersionsGraph::validate(){
return validateCycles();
}
std::list<Symbol>
VersionsGraph::expandPlaceholder(const SymbolOrPlaceholder& symbol, const Symbol& symbolPrev) const{
std::list<Symbol> result;
switch (symbol.flagEndOfLifePlaceholder){
case SYMBOL:
//skip self-loops
if (symbol.symbol == symbolPrev) return {};
return {symbol.symbol};
case PLACEHOLDER:
for (const auto& entry: boost::make_iterator_range(__inferiors.equal_range(symbol))){
list<Symbol>&& childResult = expandPlaceholder(entry.second, symbolPrev);
result.insert(result.end(), childResult.begin(), childResult.end());
}
if (__dictSuccessors.count(symbol.symbol)){
Symbol knownSuccessor = __dictSuccessors.at(symbol.symbol);
//skip alias loop
if (knownSuccessor == symbolPrev) return {};
for (const auto& entry: boost::make_iterator_range(__inferiors.equal_range(SymbolOrPlaceholder{SYMBOL, knownSuccessor}))){
list<Symbol>&& childResult = expandPlaceholder(entry.second, knownSuccessor);
result.insert(result.end(), childResult.begin(), childResult.end());
}
}
break;
}
return result;
}
AttachmentsContainerDefault<std::list<Symbol>>*
VersionsGraph::representAsAttachments() const {
AttachmentsContainerDefault<std::list<Symbol>>* container = new AttachmentsContainerDefault<std::list<Symbol>>();
std::map<Symbol, std::list<Symbol>> containerData;
for(const auto& entry: __inferiors){
if(entry.first.flagEndOfLifePlaceholder == PLACEHOLDER) continue;
list<Symbol>& infs = containerData[entry.first.symbol];
list<Symbol>&& infsExpanded = expandPlaceholder(entry.second, entry.first.symbol);
infs.insert(infs.begin(), infsExpanded.begin(), infsExpanded.end());
}
for(const auto& entry: containerData){
container->put(entry.first, entry.second);
}
return container;
}
std::list<Symbol>
VersionsPass::process(const Expression& expression, PassContext context, const std::string& hintSymbol){
if (expression.__state == Expression::COMPOUND){
std::list<Symbol> resultDependencies;
for (const Expression &op: expression.getOperands()) {
std::list<Symbol> deps = process(op, context);
resultDependencies.insert(resultDependencies.end(), deps.begin(), deps.end());
}
for (CodeScope* scope: expression.blocks) {
std::list<Symbol> deps = Parent::process(scope, context);
resultDependencies.insert(resultDependencies.end(), deps.begin(), deps.end());
}
return resultDependencies;
}
if (expression.__state == Expression::IDENT){
const Symbol symb = Attachments::get<IdentifierSymbol>(expression);
return processSymbol(symb, context, expression.getValueString());
}
return {};
}
//TODO versions, check (declaration.isDefined()) before processing declaration
list<Symbol>
VersionsPass::processSymbol(const Symbol& symbol, PassContext context, const std::string& hintSymbol){
list<Symbol> result{symbol};
if (__symbolsVisited.exists(symbol)){
return result;
}
enum {MODE_ALIAS, MODE_COPY } mode = MODE_ALIAS;
const Expression& declaration = CodeScope::getDefinition(symbol);
if (declaration.op == Operator::CALL_INTRINSIC){
if (declaration.getValueString() == "copy"){
mode = MODE_COPY;
}
}
if (symbol.identifier.version != VERSION_NONE){
mode = MODE_COPY;
if (symbol.identifier.version > 0){
Symbol versionPrev = Symbol{ScopedSymbol{symbol.identifier.id, symbol.identifier.version-1}, symbol.scope};
__graph.defineEndOfLife(versionPrev, symbol);
}
}
PassContext context2 = context.updateScope(symbol.scope);
std::list<Symbol> dependencies = process(declaration, context2, hintSymbol);
switch (mode) {
case MODE_COPY: __graph.applyDependentEndOfLife(SymbolOrPlaceholder{SYMBOL, symbol}, dependencies); break;
case MODE_ALIAS: __graph.applyDependentEndOfLife(__graph.getEndOfLife(symbol), dependencies); break;
}
__graph.applyNatualDependencies(symbol, dependencies);
__symbolsVisited.put(symbol, true);
return list<Symbol>{symbol};
}
VersionsGraph&
VersionsPass::getResultGraph(){
return __graph;
}
void
VersionsPass::finish(){
assert(__graph.validate() && "Can't validate versions graph");
Attachments::init<VersionImposedDependency>(__graph.representAsAttachments());
}
}} //end of namespace xreate::versions
+
+
+/**
+ * \class xreate::versions::VersionsPass
+ *
+ * Consists of two parts:
+ * - Validates correctness of versioned variables usage with regard to the variables lifespans.
+ * - Determines versioned variables computation order.
+ *
+ * \sa VersionsScopeDecorator, VersionsGraph, [Versions Explanation](/d/concepts/versions)
+ */
\ No newline at end of file
diff --git a/cpp/src/pass/versionspass.h b/cpp/src/pass/versionspass.h
index 2ce01b6..103d801 100644
--- a/cpp/src/pass/versionspass.h
+++ b/cpp/src/pass/versionspass.h
@@ -1,119 +1,120 @@
/* 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: versionspass.h
* Author: v.melnychenko@xreate.org
*
* Created on January 4, 2017, 3:09 PM
*/
/**
* \file versionspass.h
- * \brief Versions analysis: validates versioned variables' usage and lifespan
+ * \brief The versions analysis pass
*/
#ifndef VERSIONSPASS_H
#define VERSIONSPASS_H
#include "pass/abstractpass.h"
#include <list>
#include <functional>
namespace xreate { namespace versions {
struct SymbolOrPlaceholder;
}}
namespace std {
template<>
struct hash<xreate::versions::SymbolOrPlaceholder>{
std::size_t operator()(xreate::versions::SymbolOrPlaceholder const& s) const;
};
template<>
struct equal_to<xreate::versions::SymbolOrPlaceholder>{
bool operator()(const xreate::versions::SymbolOrPlaceholder& __x, const xreate::versions::SymbolOrPlaceholder& __y) const;
};
}
namespace xreate { namespace versions {
enum PlaceholderFlag {SYMBOL, PLACEHOLDER};
struct SymbolOrPlaceholder {
PlaceholderFlag flagEndOfLifePlaceholder;
Symbol symbol;
};
struct VersionImposedDependency{};
-/** \brief Represents results of Versions Analysis
+/**
+ * \brief Represents the results of the versions analysis provided by \ref VersionsPass
* \sa VersionsPass
*/
class VersionsGraph{
public:
//processing API:
void applyNatualDependencies(const Symbol& symbol, const std::list<Symbol>& dependencies);
void applyDependentEndOfLife(const SymbolOrPlaceholder& symbol, const std::list<Symbol>& dependencies);
void defineEndOfLife(const Symbol& symbol, const Symbol& symbolSuccessor);
SymbolOrPlaceholder getEndOfLife(const Symbol& s);
bool validate();
//examination API:
AttachmentsContainerDefault<std::list<Symbol>>* representAsAttachments() const;
void __debug_print(std::ostream& output) const;
private:
typedef std::unordered_map<SymbolOrPlaceholder, unsigned int> Path;
std::unordered_multimap<Symbol, Symbol> __inferiorsNatural;
std::unordered_multimap<SymbolOrPlaceholder, SymbolOrPlaceholder> __inferiors;
std::unordered_map<Symbol, Symbol> __dictSuccessors;
std::list<Symbol> expandPlaceholder(const SymbolOrPlaceholder& symbol, const Symbol& symbolPrev) const;
std::list<SymbolOrPlaceholder> extractCycle(const Path& path, const SymbolOrPlaceholder& symbolBeginning);
bool tryEliminateEofAliases(const std::list<SymbolOrPlaceholder>& aliases);
bool validateCycles();
bool validateCycles(const SymbolOrPlaceholder& s,
std::unordered_multimap<SymbolOrPlaceholder, SymbolOrPlaceholder>& graph,
std::unordered_set<SymbolOrPlaceholder>& symbolsVisited,
Path& path);
};
-/** \brief Provides Versions Analysis and stores results in VersionsGraph */
+/** \brief Implements the versions analysis and stores the results in \ref VersionsGraph */
class VersionsPass: public AbstractPass<std::list<Symbol>> {
typedef AbstractPass<std::list<Symbol>> Parent;
public:
VersionsPass(PassManager* manager): AbstractPass<std::list<Symbol>>(manager){}
std::list<Symbol> process(const Expression& expression, PassContext context, const std::string& hintSymbol="") override;
VersionsGraph& getResultGraph();
virtual void finish();
protected:
std::list<Symbol> processSymbol(const Symbol& symbol, PassContext context, const std::string& hintSymbol="") override;
private:
VersionsGraph __graph;
AttachmentsContainerDefault<bool> __symbolsVisited;
};
}} //end of xreate::versions
namespace xreate{
template<>
std::list<Symbol>
defaultValue<std::list<Symbol>>();
template<>
struct AttachmentsDict<versions::VersionImposedDependency>
{
typedef std::list<Symbol> Data;
static const unsigned int key = 8;
};
}
#endif /* VERSIONSPASS_H */
diff --git a/cpp/src/query/containers.cpp b/cpp/src/query/containers.cpp
index a95fe9c..9bfa1a5 100644
--- a/cpp/src/query/containers.cpp
+++ b/cpp/src/query/containers.cpp
@@ -1,116 +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.
*/
-/**
- * \file query/containers.h
- * \brief Represents reasoner's solution on [Container implementations](/w/concepts/containers)
- */
-
#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);
Symbol var = transcend->unpack(get<0>(data));
string implStr = get<1>(data).name().c_str();
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/containers.h b/cpp/src/query/containers.h
index ab8de85..e95cc7d 100644
--- a/cpp/src/query/containers.h
+++ b/cpp/src/query/containers.h
@@ -1,92 +1,96 @@
/* 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.h
* Created on 3/14/15.
*/
+/**
+ * \file query/containers.h
+ * \brief Transcend solutions on [Containers](/w/concepts/containers) implementation details
+ */
+
#ifndef _XREATE_CONTAINERSQUERY_H_
#define _XREATE_CONTAINERSQUERY_H_
#include "xreatemanager.h"
#include "transcendlayer.h"
#include <boost/variant.hpp>
namespace xreate {
namespace containers {
enum ImplementationType {SOLID, ON_THE_FLY, LINKED_LIST};
template<ImplementationType I>
struct ImplementationRec;
template<>
struct ImplementationRec<SOLID> {
size_t size;
};
template<>
struct ImplementationRec<ON_THE_FLY>{
Symbol source;
};
struct Implementation;
struct ImplementationLinkedList {
bool flagIsValid;
std::string fieldPointer;
Expression terminator;
ImplementationLinkedList(const Symbol& source);
operator bool() const;
Implementation getImplementationData() const;
private:
Symbol s;
};
struct Implementation {
typedef boost::variant<ImplementationRec<SOLID>, ImplementationRec<ON_THE_FLY>> Variant;
ImplementationType impl;
Variant data;
static Implementation create(const Symbol &var);
static Implementation create(const Symbol& var, const std::string &implSerialized);
template<ImplementationType I>
const ImplementationRec<I>& extract() const{
const ImplementationRec<I>& rec = boost::get<ImplementationRec<I>>(data);
return rec;
}
};
- /** \brief Extracts solution about container implementation
+ /**
+ * \brief Queries Transcend solutions on containers implementation details
* \sa xreate::containers::Iterator
*/
class Query : public xreate::IQuery {
public:
static Implementation queryImplementation(xreate::Symbol const &s);
void init(TranscendLayer* transcend);
Query();
~Query(){}
private:
bool flagDataIsLoaded = false;
PassManager *man;
};
-
-
}
template<>
struct AttachmentsDict<containers::Implementation> {
typedef containers::Implementation Data;
static const unsigned int key = 1;
};
}
#endif //_XREATE_CONTAINERSQUERY_H_
diff --git a/cpp/src/query/latex.h b/cpp/src/query/latex.h
index 42e5d9e..c66f39f 100644
--- a/cpp/src/query/latex.h
+++ b/cpp/src/query/latex.h
@@ -1,46 +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/context.h
- * \brief Represents reasoner's solution on [Context](/w/concepts/context)
- *
- * \class xreate::latex::LatexQuery
+ * \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);
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>, latereasoning::LateAnnotation> __decisionsLate;
std::map<std::string, std::list<Gringo::Symbol>> __domains;
};
}
}
#endif
diff --git a/cpp/src/query/polymorph.h b/cpp/src/query/polymorph.h
index f708fe6..7be4f56 100644
--- a/cpp/src/query/polymorph.h
+++ b/cpp/src/query/polymorph.h
@@ -1,35 +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;
virtual void init(TranscendLayer* transcend) override;
private:
std::unordered_map<SymbolGeneralized, Gringo::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 adfda07..2ecd979 100644
--- a/cpp/src/transcendlayer.cpp
+++ b/cpp/src/transcendlayer.cpp
@@ -1,501 +1,495 @@
/* 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 Reasoner. Wrapper over the external Clasp reasoner library
+ * \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);
cout << "Warning: " << __warnings.at(warningId) << " ";
params.print(out);
out << params;
}
}
bool
TranscendLayer::processSolution(Gringo::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;
string atomName(atom.name().c_str());
if(atomName == atomBindVar || atomName == atomBindFunc || atomName == atomBindScope) {
string atomAlias = std::get<1>(parse<Gringo::Symbol, Gringo::Symbol>(atom)).name().c_str();
__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;
}
// 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) {
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 Gringo::SymbolType::Fun:
{
//FUNC
Expression result(Operator::CALL,{Expression(Atom<Identifier_t>(std::string(atom.name().c_str())))});
for(const Gringo::Symbol& arg : atom.args()) {
result.addArg(ParseImplAtom<Expression>::get(arg));
}
return result;
}
default:
{
assert(false);
}
}
}
int
ParseImplAtom<int>
::get(const Gringo::Symbol & atom) {
switch(atom.type()) {
case Gringo::SymbolType::Num: return atom.num();
default: break;
}
assert(false && "Inappropriate symbol type");
}
std::string
ParseImplAtom<std::string>
::get(const Gringo::Symbol & atom) {
switch(atom.type()) {
case Gringo::SymbolType::Str: return atom.string().c_str();
case Gringo::SymbolType::Fun: return atom.name().c_str();
default: break;
}
assert(false && "Inappropriate symbol type");
}
SymbolPacked
ParseImplAtom<SymbolPacked>
::get(const Gringo::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) {
return atom;
}
SymbolNode
ParseImplAtom<SymbolNode>
::get(const Gringo::Symbol & atom) {
assert(atom.type() == Gringo::SymbolType::Fun
&& "Inappropriate symbol type");
if(atom.name() == "a") {
return SymbolAnonymous{(unsigned int) std::get<0>(TranscendLayer::parse<int>(atom))};
} else if(atom.name() == "s") {
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 Reasoning and logic Solver.
+ * \brief Logic reasoning implementation. Internally, it's a proxy to the external ASP solver [Clasp](https://potassco.org/clasp/)
*
- * Wraps external brilliant fantastic tool [Clasp solver](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.
*
- * For building *logic program* for reasoning TranscendLayer takes input from:
- * - Raw scripts. Client could append arbitrary ASP script to _logic program_. \ref addRawScript()
- * - Includes. There is possibility to specify external files with ASP scripts
- * to append to _logic program_. \ref involveImports() (private member)
- * - Diagnostic rules. Rules that produce diagnostic messages during
- * compilation(warnings) or even able to halt compilation with errors.
- * addRuleWarning(), \ref registerWarning()
- * - DFA data. \ref setDFAData()
- * - CFA data. \ref setCFAData()
- * - Dominators Analysis. See xreate::dominators::DominatorsAnalysisProvider.
- * Executed by \ref run()
- * - Context rules. See xreate::ContextRule and general [Context Explanation](/w/concepts/context)
+ * 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.
*
- * Data sources implement xreate::IAnalysisReport. Generally, input could be loosely divided into three categories:
- * - *Internally derived* data. CFA, DFA, Dominators analyses *automatically* feed reasoner by
- * useful insights about data, structure and algorithms of a program
- * - *User provided* data. CFA, DFA, Diagnostic/Context rules feed reasoner by
- * annotations Developer specifically provides manually
- * - *External* data. Raw scripts and includes feed reasoner with third-party data
- * related to a 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.
*
- * Once TranscendLayer got input from all providers and logic program is fully constructed
- * it runs external Clasp reasoner and receives back desired solutions.
- *
- * Output of the external Clasp reasoner is recognized and accessed via *queries*.
- * IQuery represents an interface between reasoner's output and rest of Xreate.
- * Each query inherits xreate::IQuery interface. Currently there are queries as follows:
- * - xreate::containers::Query to catch solutions regarding Containers implementation. See [Containers Explanation](/w/concepts/containers)
- * - xreate::context::ContextQuery to catch solution regarding Context. See [Context Explanation](/w/concepts/context)
- *
- * \sa See xreate::dfa::DFAPass, xreate::cfa::CFAPass, xreate::IQuery, xreate::IAnalysisReport, xreate::dominators::DominatorsAnalysisProvider
+ * \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 e0051bb..6ad56de 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 <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 Designated to mark analysis results that can be composed as *logic program* */
+/** \brief Supplies \ref TranscendLayer with results of an analysis*/
class IAnalysisReport {
public:
- /** \brief Composes *logic program* based on analysis data into ASP format and appends to a stream*/
+ /** \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 Logic program query interface */
+/** \brief Transcend solutions querying interface */
class IQuery {
public:
- virtual void init(TranscendLayer* transcend) = 0;
- virtual ~IQuery() {}
+ virtual void init(TranscendLayer* transcend) = 0;
+ virtual ~IQuery() {}
};
enum class QueryId {
- ContainersQuery,
- PolymorphQuery,
- LatexQuery
+ ContainersQuery,
+ PolymorphQuery,
+ LatexQuery
};
namespace dfa{
- class DFAGraph;
+ class DFAGraph;
}
namespace cfa {
- class CFAGraph;
+ class CFAGraph;
}
typedef std::multimap<std::string, Gringo::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 *logic program*
+ /** \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 Adds query. See xreate::IQuery */
+ /** \brief Registers a query. See xreate::IQuery */
IQuery* registerQuery(IQuery* query, const QueryId& id);
- /** \brief Returns particular query. See xreate::IQuery */
+ /** \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);
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 Adds diagnostic rule */
+ /** \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);
private:
StaticModel __model;
std::ostringstream __partTags;
std::ostringstream __partGeneral;
};
template<class typ>
struct ParseImplAtom {
static typ get(const Gringo::Symbol& atom) {
return atom.num();
}
};
template<>
struct ParseImplAtom<int> {
static int get(const Gringo::Symbol& atom);
};
template<>
struct ParseImplAtom<std::string> {
static std::string get(const Gringo::Symbol& atom);
};
template<>
struct ParseImplAtom<SymbolPacked> {
static SymbolPacked get(const Gringo::Symbol& atom);
};
template<>
struct ParseImplAtom<SymbolNode> {
static SymbolNode get(const Gringo::Symbol& atom);
};
template<>
struct ParseImplAtom<Gringo::Symbol> {
static Gringo::Symbol get(const Gringo::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();
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()) {
result.push_back(ParseImplAtom<ItemType>::get(arg));
}
return result;
}
};
template<>
struct ParseImplAtom<Expression> {
static Expression get(const Gringo::Symbol& atom);
};
template<class Tuple, size_t index>
struct Parse_Impl {
static void parse(Tuple& tup, Gringo::SymSpan::iterator 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;
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) {
}
};
template<class ...Types>
std::tuple<Types...>
TranscendLayer::parse(const Gringo::Symbol& atom) {
typedef std::tuple < Types...> Tuple;
Tuple tup;
Parse_Impl<Tuple, std::tuple_size<Tuple>::value>::parse(tup, atom.args().first);
return tup;
}
} //end of xreate namespace
#endif
diff --git a/cpp/src/utils.cpp b/cpp/src/utils.cpp
index b138bff..a901e38 100644
--- a/cpp/src/utils.cpp
+++ b/cpp/src/utils.cpp
@@ -1,38 +1,38 @@
/* 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/.
*
* utils.cpp
*
* Author: pgess <v.melnychenko@xreate.org>
*/
/**
- * \file utils.h
+ * \file cpp/src/utils.h
* \brief Auxiliary code
*/
#include "utils.h"
#include <boost/locale/encoding_utf.hpp>
using namespace xreate;
Config Config::__self = Config();
Config::Config()
: __storage{json_file{ "config/default.json" }}
{}
using boost::locale::conv::utf_to_utf;
std::wstring
utf8_to_wstring(const std::string& str)
{
return utf_to_utf<wchar_t>(str.c_str(), str.c_str() + str.size());
}
std::string
wstring_to_utf8(const std::wstring& str)
{
return utf_to_utf<char>(str.c_str(), str.c_str() + str.size());
}
diff --git a/cpp/src/xreatemanager.cpp b/cpp/src/xreatemanager.cpp
index fe81268..974bdc4 100644
--- a/cpp/src/xreatemanager.cpp
+++ b/cpp/src/xreatemanager.cpp
@@ -1,156 +1,151 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* xreatemanager.cpp
*
* Author: pgess <v.melnychenko@xreate.org>
* Created on July 3, 2017, 6:03 PM
*/
#include "xreatemanager.h"
#include "pass/abstractpass.h"
#include "aux/transcend-decorators.h"
#include "aux/xreatemanager-decorators.h"
#include "llvmlayer.h"
#include <assert.h>
#include <list>
namespace xreate {
void
PassManager::registerPass(IPass* pass, const PassId& id, IPass* parent)
{
__passes.emplace(id, pass);
__passDependencies.emplace(parent, pass);
}
IPass*
PassManager::getPassById(const PassId& id){
assert(__passes.count(id));
return __passes[id];
}
bool
PassManager::isPassRegistered(const PassId& id){
return __passes.count(id);
}
void
PassManager::executePasses(){
std::list<IPass*> passes{nullptr};
while (passes.size()){
IPass* parent = passes.front();
auto range = __passDependencies.equal_range(parent);
for (auto i=range.first; i!=range.second; ++i){
IPass* pass = i->second;
pass->run();
pass->finish();
passes.push_back(pass);
}
passes.pop_front();
}
}
void
PassManager::prepare(AST* ast){
root = ast;
transcend = new DefaultTranscendLayerImpl();
transcend->ast = ast;
llvm = new LLVMLayer(ast);
}
PassManager::~PassManager(){}
typedef XreateManagerDecoratorFull XreateManagerDecoratorDefault;
namespace details{ namespace tier2{
XreateManager*
XreateManager::prepare(std::string&& code){
auto man = new XreateManagerImpl<XreateManagerDecoratorDefault>;
man->prepareCode(std::move(code));
return man;
}
XreateManager*
XreateManager::prepare(FILE* code){
auto man = new XreateManagerImpl<XreateManagerDecoratorDefault>;
man->prepareCode(code);
return man;
}
}}
namespace details { namespace tier1 {
XreateManager*
XreateManager::prepare(std::string&& code){
auto man = new XreateManagerImpl<XreateManagerDecoratorDefault>;
man->prepareCode(std::move(code));
return man;
}
XreateManager*
XreateManager::prepare(FILE* code){
auto man = new XreateManagerImpl<XreateManagerDecoratorDefault>;
man->prepareCode(code);
return man;
}
}}
-/**
- * \class xreate::XreateManager
- * \brief Entry point of Xreate API
- *
- * Manages whole Xreate's internal workflow. There are 4 distinctive stages covered by XreateManager:
- * - initPasses() To init passes
- * - executePasses() To execute passes
- * - analyse() To run reasoner
- * - run() To run compiler
- *
- * For adaptability manager comes with several *Frontends*:
- * - xreate::details::tier2::XreateManager has all stages accessible by client for full control
- * - xreate::details::tier1::XreateManager has only analyse() and run(), where analyse() combines execution of all previous stages
- * - xreate::XreateManager has only run() to combine all stages for convenient use
- *
- * Moreover there are *Backends*:
- * - xreate::XreateManagerDecoratorBase Simple backend intended for inheritance without much functionality
- * - XreateManagerDecoratorFull Backend intended to initialize all builtin passes
- *
- * Thus, client's code could combine desired frontend and desired backend as see fit.
- * Default xreate::XreateManager connects full backend to init all builtin passes
- * to a simplest frontend with only run() available to execute all stages at once
- */
-
-/**
- *\brief Constructs XreateManager for a given code
- */
XreateManager*
XreateManager::prepare(std::string&& code) {
auto man = new XreateManagerImpl<XreateManagerDecoratorDefault>;
man->prepareCode(std::move(code));
return man;
}
-/**
- *\brief Constructs XreateManager for a given script file
- */
XreateManager*
XreateManager::prepare(FILE* code){
auto man = new XreateManagerImpl<XreateManagerDecoratorDefault>;
man->prepareCode(code);
return man;
}
}
+
+/**
+ * \class xreate::XreateManager
+ * \brief Entry point of Xreate API
+ *
+ * Manages whole Xreate compiler's internal workflow. There are 4 distinctive stages managed by XreateManager:
+ * - `initPasses()` To init passes.
+ * - `executePasses()` To execute passes.
+ * - `analyse()` To run the reasoner.
+ * - `run()` To run the compiler.
+ *
+ * * \section xm_adapt Adaptability
+ * For adaptability reasons XreateManager comes with several *frontends*:
+ * - `xreate::details::tier2::XreateManager` exposes all the stages to clients for full control.
+ * - `xreate::details::tier1::XreateManager` exposes `analyse()` along with `run()`, where `analyse()` combines execution of all previous stages.
+ * - `xreate::XreateManager` exposes `run()` only which properly initializes and executes all the stages for convenient use.
+ *
+ * Besides, there are also *backends* as follows:
+ * - \ref XreateManagerDecoratorBase Simple backend intended for inheritance, does not provide much functionality.
+ * - \ref XreateManagerDecoratorFull Backend intended to initialize all builtin passes.
+ *
+ * Thus, client could combine a desired frontend along with a desired backend as it sees fit.
+ * Default xreate::XreateManager wraps around the full backend to init all builtin passes, and
+ * the simplest frontend with the only `run()` exposed to execute all stages at once.
+ */
\ No newline at end of file
diff --git a/cpp/src/xreatemanager.h b/cpp/src/xreatemanager.h
index 19919de..1d2f8ad 100644
--- a/cpp/src/xreatemanager.h
+++ b/cpp/src/xreatemanager.h
@@ -1,141 +1,145 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* xreatemanager.h
*
* Author: pgess <v.melnychenko@xreate.org>
* Created on July 3, 2017, 6:03 PM
*/
/**
* \file
- * \brief Entry point of Xreate API.
- *
+ * \brief The entry point of Xreate API.
*/
#ifndef PASSMANAGER_H
#define PASSMANAGER_H
#include <string>
#include <map>
//stdio external
struct _IO_FILE;
typedef struct _IO_FILE FILE;
namespace xreate { namespace grammar { namespace main {
class Scanner;
}}}
namespace xreate {
class IPass;
class TranscendLayer;
class LLVMLayer;
class AST;
enum class PassId {
CFAPass, CFATemporalSeqPass,
CompilePass,
DFAPass,
EnvironmentTestsPass,
LoggerPass,
RulesPass,
InterpretationPass,
VersionsPass
};
/**
* \class PassManager
- * \brief Base class to control passes
+ * \brief The base class to control passes
*/
class PassManager{
public:
void prepare(AST* ast);
void registerPass(IPass* pass, const PassId& id, IPass* prerequisite=nullptr);
IPass* getPassById(const PassId& id);
bool isPassRegistered(const PassId& id);
void executePasses();
virtual ~PassManager();
TranscendLayer* transcend;
LLVMLayer* llvm;
AST* root;
private:
std::map<PassId, IPass*> __passes;
std::multimap<IPass*, IPass*> __passDependencies;
};
namespace details{ namespace tier2{
class XreateManager: public virtual PassManager{
public:
virtual ~XreateManager(){};
virtual void initPasses()=0;
// virtual void executePasses()=0;
virtual void analyse()=0;
virtual void* run()=0;
static XreateManager* prepare(std::string&& code);
static XreateManager* prepare(FILE* code);
};
template<class Decorator>
class XreateManagerImpl: public Decorator {
public:
};
}} //namespace details::tier2
namespace details{ namespace tier1{
class XreateManager: public virtual PassManager{
public:
virtual void analyse()=0;
virtual void* run()=0;
static XreateManager* prepare(std::string&& code);
static XreateManager* prepare(FILE* code);
};
template<class Decorator>
class XreateManagerImpl: public XreateManager, public details::tier2::XreateManagerImpl<Decorator> {
typedef details::tier2::XreateManagerImpl<Decorator> PARENT;
public:
void analyse(){
PARENT::initPasses();
PARENT::executePasses();
PARENT::analyse();
}
void* run(){
return PARENT::run();
}
};
}} //namespace details::tier1
class XreateManager: public virtual PassManager{
public:
+
+ /** \brief Consequently executes all compilation and code execution phases */
virtual void* run()=0;
+ /** \brief Constructs XreateManager for a given code */
static XreateManager* prepare(std::string&& code);
+
+ /** \brief Constructs XreateManager for a given script file */
static XreateManager* prepare(FILE* code);
};
template<class Decorator>
class XreateManagerImpl: public XreateManager, public details::tier1::XreateManagerImpl<Decorator>{
typedef details::tier1::XreateManagerImpl<Decorator> PARENT;
public:
void* run(){
PARENT::analyse();
return PARENT::run();
}
};
} //namespace xreate
#endif
diff --git a/cpp/tests/unit-test-example.cpp b/cpp/tests/unit-test-example.cpp
new file mode 100644
index 0000000..17151bb
--- /dev/null
+++ b/cpp/tests/unit-test-example.cpp
@@ -0,0 +1,43 @@
+#include "xreatemanager.h" //main Xreate header
+#include "transcendlayer.h"
+#include <gtest/gtest.h>
+
+using namespace xreate;
+using namespace std;
+
+TEST(Example, Example1){
+ //Your custom transcend rules if any
+ string rules =
+ R"SCRIPT(
+ bind_func(sum, entry).
+ )SCRIPT";
+
+ //Your custom program
+ string example =
+ R"CODE(
+ //Custom code
+
+ sum = function(a:: int, b:: int):: int
+ {
+ a + b
+ }
+ )CODE";
+
+ //Initialize compiler
+ unique_ptr<XreateManager> man(XreateManager::prepare(move(example)));
+
+ //Add transcend part:
+ man->transcend->addRawScript(move(rules));
+
+ //Define signature of your entry function:
+ typedef int (*ENTRYFN)(int, int);
+
+ //Compile the example and get a pointer to the entry function:
+ ENTRYFN yourEntryFn = (ENTRYFN) man->run();
+
+ //Now execute function and check the result
+ int resultActual = yourEntryFn(5, 7);
+ int resultExpected = 5 + 7;
+
+ ASSERT_EQ(resultExpected, resultActual);
+}
diff --git a/documentation-api/XreateDoxyfile b/documentation-api/XreateDoxyfile
index b6264fb..512fdab 100644
--- a/documentation-api/XreateDoxyfile
+++ b/documentation-api/XreateDoxyfile
@@ -1,2406 +1,2406 @@
# Doxyfile 1.8.11
# This file describes the settings to be used by the documentation system
# doxygen (www.doxygen.org) for a project.
#
# All text after a double hash (##) is considered a comment and is placed in
# front of the TAG it is preceding.
#
# All text after a single hash (#) is considered a comment and will be ignored.
# The format is:
# TAG = value [value, ...]
# For lists, items can also be appended using:
# TAG += value [value, ...]
# Values that contain spaces should be placed between quotes (\" \").
#---------------------------------------------------------------------------
# Project related configuration options
#---------------------------------------------------------------------------
# This tag specifies the encoding used for all characters in the config file
# that follow. The default is UTF-8 which is also the encoding used for all text
# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv
# built into libc) for the transcoding. See http://www.gnu.org/software/libiconv
# for the list of possible encodings.
# The default value is: UTF-8.
DOXYFILE_ENCODING = UTF-8
# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by
# double-quotes, unless you are using Doxywizard) that should identify the
# project for which the documentation is generated. This name is used in the
# title of most generated pages and in a few other places.
# The default value is: My Project.
PROJECT_NAME = "Xreate"
# The PROJECT_NUMBER tag can be used to enter a project or revision number. This
# could be handy for archiving the generated documentation or if some version
# control system is used.
PROJECT_NUMBER =
# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a
# quick idea about the purpose of the project. Keep the description short.
-PROJECT_BRIEF = "Xreate programming language"
+PROJECT_BRIEF = "The Xreate programming language"
# With the PROJECT_LOGO tag one can specify a logo or an icon that is included
# in the documentation. The maximum height of the logo should not exceed 55
# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy
# the logo to the output directory.
PROJECT_LOGO =
# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path
# into which the generated documentation will be written. If a relative path is
# entered, it will be relative to the location where doxygen was started. If
# left blank the current directory will be used.
-OUTPUT_DIRECTORY = "/tmp/xreate-documentation-api"
+OUTPUT_DIRECTORY = "tmp-generated-doc-api"
# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub-
# directories (in 2 levels) under the output directory of each output format and
# will distribute the generated files over these directories. Enabling this
# option can be useful when feeding doxygen a huge amount of source files, where
# putting all generated files in the same directory would otherwise causes
# performance problems for the file system.
# The default value is: NO.
CREATE_SUBDIRS = NO
# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII
# characters to appear in the names of generated files. If set to NO, non-ASCII
# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode
# U+3044.
# The default value is: NO.
ALLOW_UNICODE_NAMES = NO
# The OUTPUT_LANGUAGE tag is used to specify the language in which all
# documentation generated by doxygen is written. Doxygen will use this
# information to generate all constant output in the proper language.
# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese,
# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States),
# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian,
# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages),
# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian,
# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian,
# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish,
# Ukrainian and Vietnamese.
# The default value is: English.
OUTPUT_LANGUAGE = English
# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member
# descriptions after the members that are listed in the file and class
# documentation (similar to Javadoc). Set to NO to disable this.
# The default value is: YES.
BRIEF_MEMBER_DESC = YES
# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief
# description of a member or function before the detailed description
#
# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
# brief descriptions will be completely suppressed.
# The default value is: YES.
REPEAT_BRIEF = YES
# This tag implements a quasi-intelligent brief description abbreviator that is
# used to form the text in various listings. Each string in this list, if found
# as the leading text of the brief description, will be stripped from the text
# and the result, after processing the whole list, is used as the annotated
# text. Otherwise, the brief description is used as-is. If left blank, the
# following values are used ($name is automatically replaced with the name of
# the entity):The $name class, The $name widget, The $name file, is, provides,
# specifies, contains, represents, a, an and the.
ABBREVIATE_BRIEF =
# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
# doxygen will generate a detailed section even if there is only a brief
# description.
# The default value is: NO.
ALWAYS_DETAILED_SEC = NO
# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
# inherited members of a class in the documentation of that class as if those
# members were ordinary class members. Constructors, destructors and assignment
# operators of the base classes will not be shown.
# The default value is: NO.
INLINE_INHERITED_MEMB = NO
# If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path
# before files name in the file list and in the header files. If set to NO the
# shortest path that makes the file name unique will be used
# The default value is: YES.
FULL_PATH_NAMES = YES
# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path.
# Stripping is only done if one of the specified strings matches the left-hand
# part of the path. The tag can be used to show relative paths in the file list.
# If left blank the directory from which doxygen is run is used as the path to
# strip.
#
# Note that you can specify absolute paths here, but also relative paths, which
# will be relative from the directory where doxygen is started.
# This tag requires that the tag FULL_PATH_NAMES is set to YES.
STRIP_FROM_PATH = ../
# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the
# path mentioned in the documentation of a class, which tells the reader which
# header file to include in order to use a class. If left blank only the name of
# the header file containing the class definition is used. Otherwise one should
# specify the list of include paths that are normally passed to the compiler
# using the -I flag.
STRIP_FROM_INC_PATH =
# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but
# less readable) file names. This can be useful is your file systems doesn't
# support long names like on DOS, Mac, or CD-ROM.
# The default value is: NO.
SHORT_NAMES = NO
# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the
# first line (until the first dot) of a Javadoc-style comment as the brief
# description. If set to NO, the Javadoc-style will behave just like regular Qt-
# style comments (thus requiring an explicit @brief command for a brief
# description.)
# The default value is: NO.
JAVADOC_AUTOBRIEF = NO
# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first
# line (until the first dot) of a Qt-style comment as the brief description. If
# set to NO, the Qt-style will behave just like regular Qt-style comments (thus
# requiring an explicit \brief command for a brief description.)
# The default value is: NO.
QT_AUTOBRIEF = NO
# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a
# multi-line C++ special comment block (i.e. a block of //! or /// comments) as
# a brief description. This used to be the default behavior. The new default is
# to treat a multi-line C++ comment block as a detailed description. Set this
# tag to YES if you prefer the old behavior instead.
#
# Note that setting this tag to YES also means that rational rose comments are
# not recognized any more.
# The default value is: NO.
MULTILINE_CPP_IS_BRIEF = NO
# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the
# documentation from any documented member that it re-implements.
# The default value is: YES.
INHERIT_DOCS = YES
# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new
# page for each member. If set to NO, the documentation of a member will be part
# of the file/class/namespace that contains it.
# The default value is: NO.
SEPARATE_MEMBER_PAGES = NO
# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen
# uses this value to replace tabs by spaces in code fragments.
# Minimum value: 1, maximum value: 16, default value: 4.
TAB_SIZE = 4
# This tag can be used to specify a number of aliases that act as commands in
# the documentation. An alias has the form:
# name=value
# For example adding
# "sideeffect=@par Side Effects:\n"
# will allow you to put the command \sideeffect (or @sideeffect) in the
# documentation, which will result in a user-defined paragraph with heading
# "Side Effects:". You can put \n's in the value part of an alias to insert
# newlines.
ALIASES =
# This tag can be used to specify a number of word-keyword mappings (TCL only).
# A mapping has the form "name=value". For example adding "class=itcl::class"
# will allow you to use the command class in the itcl::class meaning.
TCL_SUBST =
# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
# only. Doxygen will then generate output that is more tailored for C. For
# instance, some of the names that are used will be different. The list of all
# members will be omitted, etc.
# The default value is: NO.
OPTIMIZE_OUTPUT_FOR_C = NO
# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or
# Python sources only. Doxygen will then generate output that is more tailored
# for that language. For instance, namespaces will be presented as packages,
# qualified scopes will look different, etc.
# The default value is: NO.
OPTIMIZE_OUTPUT_JAVA = NO
# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
# sources. Doxygen will then generate output that is tailored for Fortran.
# The default value is: NO.
OPTIMIZE_FOR_FORTRAN = NO
# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
# sources. Doxygen will then generate output that is tailored for VHDL.
# The default value is: NO.
OPTIMIZE_OUTPUT_VHDL = NO
# Doxygen selects the parser to use depending on the extension of the files it
# parses. With this tag you can assign which parser to use for a given
# extension. Doxygen has a built-in mapping, but you can override or extend it
# using this tag. The format is ext=language, where ext is a file extension, and
# language is one of the parsers supported by doxygen: IDL, Java, Javascript,
# C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran:
# FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran:
# Fortran. In the later case the parser tries to guess whether the code is fixed
# or free formatted code, this is the default for Fortran type files), VHDL. For
# instance to make doxygen treat .inc files as Fortran files (default is PHP),
# and .f files as C (default is Fortran), use: inc=Fortran f=C.
#
# Note: For files without extension you can use no_extension as a placeholder.
#
# Note that for custom extensions you also need to set FILE_PATTERNS otherwise
# the files are not read by doxygen.
EXTENSION_MAPPING =
# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments
# according to the Markdown format, which allows for more readable
# documentation. See http://daringfireball.net/projects/markdown/ for details.
# The output of markdown processing is further processed by doxygen, so you can
# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in
# case of backward compatibilities issues.
# The default value is: YES.
MARKDOWN_SUPPORT = YES
# When enabled doxygen tries to link words that correspond to documented
# classes, or namespaces to their corresponding documentation. Such a link can
# be prevented in individual cases by putting a % sign in front of the word or
# globally by setting AUTOLINK_SUPPORT to NO.
# The default value is: YES.
AUTOLINK_SUPPORT = YES
# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
# to include (a tag file for) the STL sources as input, then you should set this
# tag to YES in order to let doxygen match functions declarations and
# definitions whose arguments contain STL classes (e.g. func(std::string);
# versus func(std::string) {}). This also make the inheritance and collaboration
# diagrams that involve STL classes more complete and accurate.
# The default value is: NO.
BUILTIN_STL_SUPPORT = YES
# If you use Microsoft's C++/CLI language, you should set this option to YES to
# enable parsing support.
# The default value is: NO.
CPP_CLI_SUPPORT = NO
# Set the SIP_SUPPORT tag to YES if your project consists of sip (see:
# http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen
# will parse them like normal C++ but will assume all classes use public instead
# of private inheritance when no explicit protection keyword is present.
# The default value is: NO.
SIP_SUPPORT = NO
# For Microsoft's IDL there are propget and propput attributes to indicate
# getter and setter methods for a property. Setting this option to YES will make
# doxygen to replace the get and set methods by a property in the documentation.
# This will only work if the methods are indeed getting or setting a simple
# type. If this is not the case, or you want to show the methods anyway, you
# should set this option to NO.
# The default value is: YES.
IDL_PROPERTY_SUPPORT = YES
# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
# tag is set to YES then doxygen will reuse the documentation of the first
# member in the group (if any) for the other members of the group. By default
# all members of a group must be documented explicitly.
# The default value is: NO.
DISTRIBUTE_GROUP_DOC = NO
# If one adds a struct or class to a group and this option is enabled, then also
# any nested class or struct is added to the same group. By default this option
# is disabled and one has to add nested compounds explicitly via \ingroup.
# The default value is: NO.
GROUP_NESTED_COMPOUNDS = NO
# Set the SUBGROUPING tag to YES to allow class member groups of the same type
# (for instance a group of public functions) to be put as a subgroup of that
# type (e.g. under the Public Functions section). Set it to NO to prevent
# subgrouping. Alternatively, this can be done per class using the
# \nosubgrouping command.
# The default value is: YES.
SUBGROUPING = YES
# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions
# are shown inside the group in which they are included (e.g. using \ingroup)
# instead of on a separate page (for HTML and Man pages) or section (for LaTeX
# and RTF).
#
# Note that this feature does not work in combination with
# SEPARATE_MEMBER_PAGES.
# The default value is: NO.
INLINE_GROUPED_CLASSES = NO
# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions
# with only public data fields or simple typedef fields will be shown inline in
# the documentation of the scope in which they are defined (i.e. file,
# namespace, or group documentation), provided this scope is documented. If set
# to NO, structs, classes, and unions are shown on a separate page (for HTML and
# Man pages) or section (for LaTeX and RTF).
# The default value is: NO.
INLINE_SIMPLE_STRUCTS = NO
# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or
# enum is documented as struct, union, or enum with the name of the typedef. So
# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
# with name TypeT. When disabled the typedef will appear as a member of a file,
# namespace, or class. And the struct will be named TypeS. This can typically be
# useful for C code in case the coding convention dictates that all compound
# types are typedef'ed and only the typedef is referenced, never the tag name.
# The default value is: NO.
TYPEDEF_HIDES_STRUCT = NO
# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This
# cache is used to resolve symbols given their name and scope. Since this can be
# an expensive process and often the same symbol appears multiple times in the
# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small
# doxygen will become slower. If the cache is too large, memory is wasted. The
# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range
# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536
# symbols. At the end of a run doxygen will report the cache usage and suggest
# the optimal cache size from a speed point of view.
# Minimum value: 0, maximum value: 9, default value: 0.
LOOKUP_CACHE_SIZE = 0
#---------------------------------------------------------------------------
# Build related configuration options
#---------------------------------------------------------------------------
# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in
# documentation are documented, even if no documentation was available. Private
# class members and static file members will be hidden unless the
# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES.
# Note: This will also disable the warnings about undocumented members that are
# normally produced when WARNINGS is set to YES.
# The default value is: NO.
EXTRACT_ALL = NO
# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will
# be included in the documentation.
# The default value is: NO.
EXTRACT_PRIVATE = NO
# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal
# scope will be included in the documentation.
# The default value is: NO.
EXTRACT_PACKAGE = NO
# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be
# included in the documentation.
# The default value is: NO.
EXTRACT_STATIC = YES
# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined
# locally in source files will be included in the documentation. If set to NO,
# only classes defined in header files are included. Does not have any effect
# for Java sources.
# The default value is: YES.
EXTRACT_LOCAL_CLASSES = YES
# This flag is only useful for Objective-C code. If set to YES, local methods,
# which are defined in the implementation section but not in the interface are
# included in the documentation. If set to NO, only methods in the interface are
# included.
# The default value is: NO.
EXTRACT_LOCAL_METHODS = NO
# If this flag is set to YES, the members of anonymous namespaces will be
# extracted and appear in the documentation as a namespace called
# 'anonymous_namespace{file}', where file will be replaced with the base name of
# the file that contains the anonymous namespace. By default anonymous namespace
# are hidden.
# The default value is: NO.
EXTRACT_ANON_NSPACES = NO
# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all
# undocumented members inside documented classes or files. If set to NO these
# members will be included in the various overviews, but no documentation
# section is generated. This option has no effect if EXTRACT_ALL is enabled.
# The default value is: NO.
HIDE_UNDOC_MEMBERS = YES
# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all
# undocumented classes that are normally visible in the class hierarchy. If set
# to NO, these classes will be included in the various overviews. This option
# has no effect if EXTRACT_ALL is enabled.
# The default value is: NO.
HIDE_UNDOC_CLASSES = YES
# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend
# (class|struct|union) declarations. If set to NO, these declarations will be
# included in the documentation.
# The default value is: NO.
HIDE_FRIEND_COMPOUNDS = YES
# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any
# documentation blocks found inside the body of a function. If set to NO, these
# blocks will be appended to the function's detailed documentation block.
# The default value is: NO.
HIDE_IN_BODY_DOCS = NO
# The INTERNAL_DOCS tag determines if documentation that is typed after a
# \internal command is included. If the tag is set to NO then the documentation
# will be excluded. Set it to YES to include the internal documentation.
# The default value is: NO.
INTERNAL_DOCS = NO
# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file
# names in lower-case letters. If set to YES, upper-case letters are also
# allowed. This is useful if you have classes or files whose names only differ
# in case and if your file system supports case sensitive file names. Windows
# and Mac users are advised to set this option to NO.
# The default value is: system dependent.
CASE_SENSE_NAMES = YES
# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with
# their full class and namespace scopes in the documentation. If set to YES, the
# scope will be hidden.
# The default value is: NO.
HIDE_SCOPE_NAMES = YES
# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will
# append additional text to a page's title, such as Class Reference. If set to
# YES the compound reference will be hidden.
# The default value is: NO.
HIDE_COMPOUND_REFERENCE= NO
# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of
# the files that are included by a file in the documentation of that file.
# The default value is: YES.
SHOW_INCLUDE_FILES = YES
# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each
# grouped member an include statement to the documentation, telling the reader
# which file to include in order to use the member.
# The default value is: NO.
SHOW_GROUPED_MEMB_INC = NO
# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include
# files with double quotes in the documentation rather than with sharp brackets.
# The default value is: NO.
FORCE_LOCAL_INCLUDES = NO
# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the
# documentation for inline members.
# The default value is: YES.
INLINE_INFO = YES
# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the
# (detailed) documentation of file and class members alphabetically by member
# name. If set to NO, the members will appear in declaration order.
# The default value is: YES.
SORT_MEMBER_DOCS = YES
# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief
# descriptions of file, namespace and class members alphabetically by member
# name. If set to NO, the members will appear in declaration order. Note that
# this will also influence the order of the classes in the class list.
# The default value is: NO.
SORT_BRIEF_DOCS = NO
# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the
# (brief and detailed) documentation of class members so that constructors and
# destructors are listed first. If set to NO the constructors will appear in the
# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS.
# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief
# member documentation.
# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting
# detailed member documentation.
# The default value is: NO.
SORT_MEMBERS_CTORS_1ST = NO
# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy
# of group names into alphabetical order. If set to NO the group names will
# appear in their defined order.
# The default value is: NO.
SORT_GROUP_NAMES = NO
# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by
# fully-qualified names, including namespaces. If set to NO, the class list will
# be sorted only by class name, not including the namespace part.
# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
# Note: This option applies only to the class list, not to the alphabetical
# list.
# The default value is: NO.
SORT_BY_SCOPE_NAME = NO
# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper
# type resolution of all parameters of a function it will reject a match between
# the prototype and the implementation of a member function even if there is
# only one candidate or it is obvious which candidate to choose by doing a
# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still
# accept a match between prototype and implementation in such cases.
# The default value is: NO.
STRICT_PROTO_MATCHING = NO
# The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo
# list. This list is created by putting \todo commands in the documentation.
# The default value is: YES.
GENERATE_TODOLIST = YES
# The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test
# list. This list is created by putting \test commands in the documentation.
# The default value is: YES.
GENERATE_TESTLIST = YES
# The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug
# list. This list is created by putting \bug commands in the documentation.
# The default value is: YES.
GENERATE_BUGLIST = YES
# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO)
# the deprecated list. This list is created by putting \deprecated commands in
# the documentation.
# The default value is: YES.
GENERATE_DEPRECATEDLIST= YES
# The ENABLED_SECTIONS tag can be used to enable conditional documentation
# sections, marked by \if <section_label> ... \endif and \cond <section_label>
# ... \endcond blocks.
ENABLED_SECTIONS =
# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the
# initial value of a variable or macro / define can have for it to appear in the
# documentation. If the initializer consists of more lines than specified here
# it will be hidden. Use a value of 0 to hide initializers completely. The
# appearance of the value of individual variables and macros / defines can be
# controlled using \showinitializer or \hideinitializer command in the
# documentation regardless of this setting.
# Minimum value: 0, maximum value: 10000, default value: 30.
MAX_INITIALIZER_LINES = 30
# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at
# the bottom of the documentation of classes and structs. If set to YES, the
# list will mention the files that were used to generate the documentation.
# The default value is: YES.
SHOW_USED_FILES = YES
# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This
# will remove the Files entry from the Quick Index and from the Folder Tree View
# (if specified).
# The default value is: YES.
SHOW_FILES = YES
# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces
# page. This will remove the Namespaces entry from the Quick Index and from the
# Folder Tree View (if specified).
# The default value is: YES.
SHOW_NAMESPACES = YES
# The FILE_VERSION_FILTER tag can be used to specify a program or script that
# doxygen should invoke to get the current version for each file (typically from
# the version control system). Doxygen will invoke the program by executing (via
# popen()) the command command input-file, where command is the value of the
# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided
# by doxygen. Whatever the program writes to standard output is used as the file
# version. For an example see the documentation.
FILE_VERSION_FILTER =
# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
# by doxygen. The layout file controls the global structure of the generated
# output files in an output format independent way. To create the layout file
# that represents doxygen's defaults, run doxygen with the -l option. You can
# optionally specify a file name after the option, if omitted DoxygenLayout.xml
# will be used as the name of the layout file.
#
# Note that if you run doxygen from a directory containing a file called
# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE
# tag is left empty.
LAYOUT_FILE = XreateDoxygenLayout.xml
# The CITE_BIB_FILES tag can be used to specify one or more bib files containing
# the reference definitions. This must be a list of .bib files. The .bib
# extension is automatically appended if omitted. This requires the bibtex tool
# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info.
# For LaTeX the style of the bibliography can be controlled using
# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the
# search path. See also \cite for info how to create references.
CITE_BIB_FILES =
#---------------------------------------------------------------------------
# Configuration options related to warning and progress messages
#---------------------------------------------------------------------------
# The QUIET tag can be used to turn on/off the messages that are generated to
# standard output by doxygen. If QUIET is set to YES this implies that the
# messages are off.
# The default value is: NO.
-QUIET = NO
+QUIET = YES
# The WARNINGS tag can be used to turn on/off the warning messages that are
# generated to standard error (stderr) by doxygen. If WARNINGS is set to YES
# this implies that the warnings are on.
#
# Tip: Turn warnings on while writing the documentation.
# The default value is: YES.
WARNINGS = YES
# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate
# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag
# will automatically be disabled.
# The default value is: YES.
WARN_IF_UNDOCUMENTED = YES
# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for
# potential errors in the documentation, such as not documenting some parameters
# in a documented function, or documenting parameters that don't exist or using
# markup commands wrongly.
# The default value is: YES.
WARN_IF_DOC_ERROR = YES
# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that
# are documented, but have no documentation for their parameters or return
# value. If set to NO, doxygen will only warn about wrong or incomplete
# parameter documentation, but not about the absence of documentation.
# The default value is: NO.
WARN_NO_PARAMDOC = NO
# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when
# a warning is encountered.
# The default value is: NO.
WARN_AS_ERROR = NO
# The WARN_FORMAT tag determines the format of the warning messages that doxygen
# can produce. The string should contain the $file, $line, and $text tags, which
# will be replaced by the file and line number from which the warning originated
# and the warning text. Optionally the format may contain $version, which will
# be replaced by the version of the file (if it could be obtained via
# FILE_VERSION_FILTER)
# The default value is: $file:$line: $text.
WARN_FORMAT = "$file:$line: $text"
# The WARN_LOGFILE tag can be used to specify a file to which warning and error
# messages should be written. If left blank the output is written to standard
# error (stderr).
WARN_LOGFILE =
#---------------------------------------------------------------------------
# Configuration options related to the input files
#---------------------------------------------------------------------------
# The INPUT tag is used to specify the files and/or directories that contain
# documented source files. You may enter file names like myfile.cpp or
# directories like /usr/src/myproject. Separate the files or directories with
# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
# Note: If this tag is empty the current directory is searched.
INPUT = ../cpp/src ./
# This tag can be used to specify the character encoding of the source files
# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
# libiconv (or the iconv built into libc) for the transcoding. See the libiconv
# documentation (see: http://www.gnu.org/software/libiconv) for the list of
# possible encodings.
# The default value is: UTF-8.
INPUT_ENCODING = UTF-8
# If the value of the INPUT tag contains directories, you can use the
# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and
# *.h) to filter out the source-files in the directories.
#
# Note that for custom extensions or not directly supported extensions you also
# need to set EXTENSION_MAPPING for the extension otherwise the files are not
# read by doxygen.
#
# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp,
# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h,
# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc,
# *.m, *.markdown, *.md, *.mm, *.dox, *.py, *.pyw, *.f90, *.f, *.for, *.tcl,
# *.vhd, *.vhdl, *.ucf, *.qsf, *.as and *.js.
FILE_PATTERNS = *.cpp *.h *.dox
# The RECURSIVE tag can be used to specify whether or not subdirectories should
# be searched for input files as well.
# The default value is: NO.
RECURSIVE = YES
# The EXCLUDE tag can be used to specify files and/or directories that should be
# excluded from the INPUT source files. This way you can easily exclude a
# subdirectory from a directory tree whose root is specified with the INPUT tag.
#
# Note that relative paths are relative to the directory from which doxygen is
# run.
EXCLUDE =
# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
# directories that are symbolic links (a Unix file system feature) are excluded
# from the input.
# The default value is: NO.
EXCLUDE_SYMLINKS = NO
# If the value of the INPUT tag contains directories, you can use the
# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
# certain files from those directories.
#
# Note that the wildcards are matched against the file with absolute path, so to
# exclude all test directories for example use the pattern */test/*
EXCLUDE_PATTERNS =
# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
# (namespaces, classes, functions, etc.) that should be excluded from the
# output. The symbol name can be a fully qualified name, a word, or if the
# wildcard * is used, a substring. Examples: ANamespace, AClass,
# AClass::ANamespace, ANamespace::*Test
#
# Note that the wildcards are matched against the file with absolute path, so to
# exclude all test directories use the pattern */test/*
EXCLUDE_SYMBOLS =
# The EXAMPLE_PATH tag can be used to specify one or more files or directories
# that contain example code fragments that are included (see the \include
# command).
EXAMPLE_PATH =
# If the value of the EXAMPLE_PATH tag contains directories, you can use the
# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and
# *.h) to filter out the source-files in the directories. If left blank all
# files are included.
EXAMPLE_PATTERNS =
# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
# searched for input files to be used with the \include or \dontinclude commands
# irrespective of the value of the RECURSIVE tag.
# The default value is: NO.
EXAMPLE_RECURSIVE = NO
# The IMAGE_PATH tag can be used to specify one or more files or directories
# that contain images that are to be included in the documentation (see the
# \image command).
IMAGE_PATH =
# The INPUT_FILTER tag can be used to specify a program that doxygen should
# invoke to filter for each input file. Doxygen will invoke the filter program
# by executing (via popen()) the command:
#
# <filter> <input-file>
#
# where <filter> is the value of the INPUT_FILTER tag, and <input-file> is the
# name of an input file. Doxygen will then use the output that the filter
# program writes to standard output. If FILTER_PATTERNS is specified, this tag
# will be ignored.
#
# Note that the filter must not add or remove lines; it is applied before the
# code is scanned, but not when the output code is generated. If lines are added
# or removed, the anchors will not be placed correctly.
#
# Note that for custom extensions or not directly supported extensions you also
# need to set EXTENSION_MAPPING for the extension otherwise the files are not
# properly processed by doxygen.
INPUT_FILTER =
# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
# basis. Doxygen will compare the file name with each pattern and apply the
# filter if there is a match. The filters are a list of the form: pattern=filter
# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how
# filters are used. If the FILTER_PATTERNS tag is empty or if none of the
# patterns match the file name, INPUT_FILTER is applied.
#
# Note that for custom extensions or not directly supported extensions you also
# need to set EXTENSION_MAPPING for the extension otherwise the files are not
# properly processed by doxygen.
FILTER_PATTERNS =
# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
# INPUT_FILTER) will also be used to filter the input files that are used for
# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES).
# The default value is: NO.
FILTER_SOURCE_FILES = NO
# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file
# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and
# it is also possible to disable source filtering for a specific pattern using
# *.ext= (so without naming a filter).
# This tag requires that the tag FILTER_SOURCE_FILES is set to YES.
FILTER_SOURCE_PATTERNS =
# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that
# is part of the input, its contents will be placed on the main page
# (index.html). This can be useful if you have a project on for instance GitHub
# and want to reuse the introduction page also for the doxygen output.
USE_MDFILE_AS_MAINPAGE =
#---------------------------------------------------------------------------
# Configuration options related to source browsing
#---------------------------------------------------------------------------
# If the SOURCE_BROWSER tag is set to YES then a list of source files will be
# generated. Documented entities will be cross-referenced with these sources.
#
# Note: To get rid of all source code in the generated output, make sure that
# also VERBATIM_HEADERS is set to NO.
# The default value is: NO.
SOURCE_BROWSER = NO
# Setting the INLINE_SOURCES tag to YES will include the body of functions,
# classes and enums directly into the documentation.
# The default value is: NO.
INLINE_SOURCES = NO
# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any
# special comment blocks from generated source code fragments. Normal C, C++ and
# Fortran comments will always remain visible.
# The default value is: YES.
STRIP_CODE_COMMENTS = YES
# If the REFERENCED_BY_RELATION tag is set to YES then for each documented
# function all documented functions referencing it will be listed.
# The default value is: NO.
REFERENCED_BY_RELATION = NO
# If the REFERENCES_RELATION tag is set to YES then for each documented function
# all documented entities called/used by that function will be listed.
# The default value is: NO.
REFERENCES_RELATION = NO
# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set
# to YES then the hyperlinks from functions in REFERENCES_RELATION and
# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will
# link to the documentation.
# The default value is: YES.
REFERENCES_LINK_SOURCE = YES
# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the
# source code will show a tooltip with additional information such as prototype,
# brief description and links to the definition and documentation. Since this
# will make the HTML file larger and loading of large files a bit slower, you
# can opt to disable this feature.
# The default value is: YES.
# This tag requires that the tag SOURCE_BROWSER is set to YES.
SOURCE_TOOLTIPS = YES
# If the USE_HTAGS tag is set to YES then the references to source code will
# point to the HTML generated by the htags(1) tool instead of doxygen built-in
# source browser. The htags tool is part of GNU's global source tagging system
# (see http://www.gnu.org/software/global/global.html). You will need version
# 4.8.6 or higher.
#
# To use it do the following:
# - Install the latest version of global
# - Enable SOURCE_BROWSER and USE_HTAGS in the config file
# - Make sure the INPUT points to the root of the source tree
# - Run doxygen as normal
#
# Doxygen will invoke htags (and that will in turn invoke gtags), so these
# tools must be available from the command line (i.e. in the search path).
#
# The result: instead of the source browser generated by doxygen, the links to
# source code will now point to the output of htags.
# The default value is: NO.
# This tag requires that the tag SOURCE_BROWSER is set to YES.
USE_HTAGS = NO
# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a
# verbatim copy of the header file for each class for which an include is
# specified. Set to NO to disable this.
# See also: Section \class.
# The default value is: YES.
VERBATIM_HEADERS = NO
#---------------------------------------------------------------------------
# Configuration options related to the alphabetical class index
#---------------------------------------------------------------------------
# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all
# compounds will be generated. Enable this if the project contains a lot of
# classes, structs, unions or interfaces.
# The default value is: YES.
ALPHABETICAL_INDEX = YES
# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in
# which the alphabetical index list will be split.
# Minimum value: 1, maximum value: 20, default value: 5.
# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
COLS_IN_ALPHA_INDEX = 5
# In case all classes in a project start with a common prefix, all classes will
# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag
# can be used to specify a prefix (or a list of prefixes) that should be ignored
# while generating the index headers.
# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
IGNORE_PREFIX =
#---------------------------------------------------------------------------
# Configuration options related to the HTML output
#---------------------------------------------------------------------------
# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output
# The default value is: YES.
GENERATE_HTML = YES
# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a
# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
# it.
# The default directory is: html.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_OUTPUT = html
# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each
# generated HTML page (for example: .htm, .php, .asp).
# The default value is: .html.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_FILE_EXTENSION = .html
# The HTML_HEADER tag can be used to specify a user-defined HTML header file for
# each generated HTML page. If the tag is left blank doxygen will generate a
# standard header.
#
# To get valid HTML the header file that includes any scripts and style sheets
# that doxygen needs, which is dependent on the configuration options used (e.g.
# the setting GENERATE_TREEVIEW). It is highly recommended to start with a
# default header using
# doxygen -w html new_header.html new_footer.html new_stylesheet.css
# YourConfigFile
# and then modify the file new_header.html. See also section "Doxygen usage"
# for information on how to generate the default header that doxygen normally
# uses.
# Note: The header is subject to change so you typically have to regenerate the
# default header when upgrading to a newer version of doxygen. For a description
# of the possible markers and block names see the documentation.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_HEADER =
# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each
# generated HTML page. If the tag is left blank doxygen will generate a standard
# footer. See HTML_HEADER for more information on how to generate a default
# footer and what special commands can be used inside the footer. See also
# section "Doxygen usage" for information on how to generate the default footer
# that doxygen normally uses.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_FOOTER =
# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style
# sheet that is used by each HTML page. It can be used to fine-tune the look of
# the HTML output. If left blank doxygen will generate a default style sheet.
# See also section "Doxygen usage" for information on how to generate the style
# sheet that doxygen normally uses.
# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as
# it is more robust and this tag (HTML_STYLESHEET) will in the future become
# obsolete.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_STYLESHEET =
# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined
# cascading style sheets that are included after the standard style sheets
# created by doxygen. Using this option one can overrule certain style aspects.
# This is preferred over using HTML_STYLESHEET since it does not replace the
# standard style sheet and is therefore more robust against future updates.
# Doxygen will copy the style sheet files to the output directory.
# Note: The order of the extra style sheet files is of importance (e.g. the last
# style sheet in the list overrules the setting of the previous ones in the
# list). For an example see the documentation.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_EXTRA_STYLESHEET =
# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
# other source files which should be copied to the HTML output directory. Note
# that these files will be copied to the base HTML output directory. Use the
# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these
# files. In the HTML_STYLESHEET file, use the file name only. Also note that the
# files will be copied as-is; there are no commands or markers available.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_EXTRA_FILES =
# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
# will adjust the colors in the style sheet and background images according to
# this color. Hue is specified as an angle on a colorwheel, see
# http://en.wikipedia.org/wiki/Hue for more information. For instance the value
# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300
# purple, and 360 is red again.
# Minimum value: 0, maximum value: 359, default value: 220.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_COLORSTYLE_HUE = 220
# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors
# in the HTML output. For a value of 0 the output will use grayscales only. A
# value of 255 will produce the most vivid colors.
# Minimum value: 0, maximum value: 255, default value: 100.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_COLORSTYLE_SAT = 100
# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the
# luminance component of the colors in the HTML output. Values below 100
# gradually make the output lighter, whereas values above 100 make the output
# darker. The value divided by 100 is the actual gamma applied, so 80 represents
# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not
# change the gamma.
# Minimum value: 40, maximum value: 240, default value: 80.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_COLORSTYLE_GAMMA = 80
# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
# page will contain the date and time when the page was generated. Setting this
# to YES can help to show when doxygen was last run and thus if the
# documentation is up to date.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_TIMESTAMP = NO
# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
# documentation will contain sections that can be hidden and shown after the
# page has loaded.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_DYNAMIC_SECTIONS = NO
# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries
# shown in the various tree structured indices initially; the user can expand
# and collapse entries dynamically later on. Doxygen will expand the tree to
# such a level that at most the specified number of entries are visible (unless
# a fully collapsed tree already exceeds this amount). So setting the number of
# entries 1 will produce a full collapsed tree by default. 0 is a special value
# representing an infinite number of entries and will result in a full expanded
# tree by default.
# Minimum value: 0, maximum value: 9999, default value: 100.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_INDEX_NUM_ENTRIES = 100
# If the GENERATE_DOCSET tag is set to YES, additional index files will be
# generated that can be used as input for Apple's Xcode 3 integrated development
# environment (see: http://developer.apple.com/tools/xcode/), introduced with
# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a
# Makefile in the HTML output directory. Running make will produce the docset in
# that directory and running make install will install the docset in
# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at
# startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html
# for more information.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
GENERATE_DOCSET = NO
# This tag determines the name of the docset feed. A documentation feed provides
# an umbrella under which multiple documentation sets from a single provider
# (such as a company or product suite) can be grouped.
# The default value is: Doxygen generated docs.
# This tag requires that the tag GENERATE_DOCSET is set to YES.
DOCSET_FEEDNAME = "Doxygen generated docs"
# This tag specifies a string that should uniquely identify the documentation
# set bundle. This should be a reverse domain-name style string, e.g.
# com.mycompany.MyDocSet. Doxygen will append .docset to the name.
# The default value is: org.doxygen.Project.
# This tag requires that the tag GENERATE_DOCSET is set to YES.
DOCSET_BUNDLE_ID = org.doxygen.Project
# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify
# the documentation publisher. This should be a reverse domain-name style
# string, e.g. com.mycompany.MyDocSet.documentation.
# The default value is: org.doxygen.Publisher.
# This tag requires that the tag GENERATE_DOCSET is set to YES.
DOCSET_PUBLISHER_ID = org.doxygen.Publisher
# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher.
# The default value is: Publisher.
# This tag requires that the tag GENERATE_DOCSET is set to YES.
DOCSET_PUBLISHER_NAME = Publisher
# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three
# additional HTML index files: index.hhp, index.hhc, and index.hhk. The
# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop
# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on
# Windows.
#
# The HTML Help Workshop contains a compiler that can convert all HTML output
# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML
# files are now used as the Windows 98 help format, and will replace the old
# Windows help format (.hlp) on all Windows platforms in the future. Compressed
# HTML files also contain an index, a table of contents, and you can search for
# words in the documentation. The HTML workshop also contains a viewer for
# compressed HTML files.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
GENERATE_HTMLHELP = NO
# The CHM_FILE tag can be used to specify the file name of the resulting .chm
# file. You can add a path in front of the file if the result should not be
# written to the html output directory.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
CHM_FILE =
# The HHC_LOCATION tag can be used to specify the location (absolute path
# including file name) of the HTML help compiler (hhc.exe). If non-empty,
# doxygen will try to run the HTML help compiler on the generated index.hhp.
# The file has to be specified with full path.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
HHC_LOCATION =
# The GENERATE_CHI flag controls if a separate .chi index file is generated
# (YES) or that it should be included in the master .chm file (NO).
# The default value is: NO.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
GENERATE_CHI = NO
# The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc)
# and project file content.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
CHM_INDEX_ENCODING =
# The BINARY_TOC flag controls whether a binary table of contents is generated
# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it
# enables the Previous and Next buttons.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
BINARY_TOC = NO
# The TOC_EXPAND flag can be set to YES to add extra items for group members to
# the table of contents of the HTML help documentation and to the tree view.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
TOC_EXPAND = NO
# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and
# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that
# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help
# (.qch) of the generated HTML documentation.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
GENERATE_QHP = NO
# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify
# the file name of the resulting .qch file. The path specified is relative to
# the HTML output folder.
# This tag requires that the tag GENERATE_QHP is set to YES.
QCH_FILE =
# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help
# Project output. For more information please see Qt Help Project / Namespace
# (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace).
# The default value is: org.doxygen.Project.
# This tag requires that the tag GENERATE_QHP is set to YES.
QHP_NAMESPACE = org.doxygen.Project
# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt
# Help Project output. For more information please see Qt Help Project / Virtual
# Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual-
# folders).
# The default value is: doc.
# This tag requires that the tag GENERATE_QHP is set to YES.
QHP_VIRTUAL_FOLDER = doc
# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom
# filter to add. For more information please see Qt Help Project / Custom
# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
# filters).
# This tag requires that the tag GENERATE_QHP is set to YES.
QHP_CUST_FILTER_NAME =
# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the
# custom filter to add. For more information please see Qt Help Project / Custom
# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
# filters).
# This tag requires that the tag GENERATE_QHP is set to YES.
QHP_CUST_FILTER_ATTRS =
# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
# project's filter section matches. Qt Help Project / Filter Attributes (see:
# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes).
# This tag requires that the tag GENERATE_QHP is set to YES.
QHP_SECT_FILTER_ATTRS =
# The QHG_LOCATION tag can be used to specify the location of Qt's
# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the
# generated .qhp file.
# This tag requires that the tag GENERATE_QHP is set to YES.
QHG_LOCATION =
# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be
# generated, together with the HTML files, they form an Eclipse help plugin. To
# install this plugin and make it available under the help contents menu in
# Eclipse, the contents of the directory containing the HTML and XML files needs
# to be copied into the plugins directory of eclipse. The name of the directory
# within the plugins directory should be the same as the ECLIPSE_DOC_ID value.
# After copying Eclipse needs to be restarted before the help appears.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
GENERATE_ECLIPSEHELP = NO
# A unique identifier for the Eclipse help plugin. When installing the plugin
# the directory name containing the HTML and XML files should also have this
# name. Each documentation set should have its own identifier.
# The default value is: org.doxygen.Project.
# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES.
ECLIPSE_DOC_ID = org.doxygen.Project
# If you want full control over the layout of the generated HTML pages it might
# be necessary to disable the index and replace it with your own. The
# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top
# of each HTML page. A value of NO enables the index and the value YES disables
# it. Since the tabs in the index contain the same information as the navigation
# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
DISABLE_INDEX = NO
# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
# structure should be generated to display hierarchical information. If the tag
# value is set to YES, a side panel will be generated containing a tree-like
# index structure (just like the one that is generated for HTML Help). For this
# to work a browser that supports JavaScript, DHTML, CSS and frames is required
# (i.e. any modern browser). Windows users are probably better off using the
# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can
# further fine-tune the look of the index. As an example, the default style
# sheet generated by doxygen has an example that shows how to put an image at
# the root of the tree instead of the PROJECT_NAME. Since the tree basically has
# the same information as the tab index, you could consider setting
# DISABLE_INDEX to YES when enabling this option.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
GENERATE_TREEVIEW = NO
# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that
# doxygen will group on one line in the generated HTML documentation.
#
# Note that a value of 0 will completely suppress the enum values from appearing
# in the overview section.
# Minimum value: 0, maximum value: 20, default value: 4.
# This tag requires that the tag GENERATE_HTML is set to YES.
ENUM_VALUES_PER_LINE = 4
# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used
# to set the initial width (in pixels) of the frame in which the tree is shown.
# Minimum value: 0, maximum value: 1500, default value: 250.
# This tag requires that the tag GENERATE_HTML is set to YES.
TREEVIEW_WIDTH = 250
# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to
# external symbols imported via tag files in a separate window.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
EXT_LINKS_IN_WINDOW = NO
# Use this tag to change the font size of LaTeX formulas included as images in
# the HTML documentation. When you change the font size after a successful
# doxygen run you need to manually remove any form_*.png images from the HTML
# output directory to force them to be regenerated.
# Minimum value: 8, maximum value: 50, default value: 10.
# This tag requires that the tag GENERATE_HTML is set to YES.
FORMULA_FONTSIZE = 10
# Use the FORMULA_TRANPARENT tag to determine whether or not the images
# generated for formulas are transparent PNGs. Transparent PNGs are not
# supported properly for IE 6.0, but are supported on all modern browsers.
#
# Note that when changing this option you need to delete any form_*.png files in
# the HTML output directory before the changes have effect.
# The default value is: YES.
# This tag requires that the tag GENERATE_HTML is set to YES.
FORMULA_TRANSPARENT = YES
# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see
# http://www.mathjax.org) which uses client side Javascript for the rendering
# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX
# installed or if you want to formulas look prettier in the HTML output. When
# enabled you may also need to install MathJax separately and configure the path
# to it using the MATHJAX_RELPATH option.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
USE_MATHJAX = NO
# When MathJax is enabled you can set the default output format to be used for
# the MathJax output. See the MathJax site (see:
# http://docs.mathjax.org/en/latest/output.html) for more details.
# Possible values are: HTML-CSS (which is slower, but has the best
# compatibility), NativeMML (i.e. MathML) and SVG.
# The default value is: HTML-CSS.
# This tag requires that the tag USE_MATHJAX is set to YES.
MATHJAX_FORMAT = HTML-CSS
# When MathJax is enabled you need to specify the location relative to the HTML
# output directory using the MATHJAX_RELPATH option. The destination directory
# should contain the MathJax.js script. For instance, if the mathjax directory
# is located at the same level as the HTML output directory, then
# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax
# Content Delivery Network so you can quickly see the result without installing
# MathJax. However, it is strongly recommended to install a local copy of
# MathJax from http://www.mathjax.org before deployment.
# The default value is: http://cdn.mathjax.org/mathjax/latest.
# This tag requires that the tag USE_MATHJAX is set to YES.
MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest
# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax
# extension names that should be enabled during MathJax rendering. For example
# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols
# This tag requires that the tag USE_MATHJAX is set to YES.
MATHJAX_EXTENSIONS =
# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces
# of code that will be used on startup of the MathJax code. See the MathJax site
# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an
# example see the documentation.
# This tag requires that the tag USE_MATHJAX is set to YES.
MATHJAX_CODEFILE =
# When the SEARCHENGINE tag is enabled doxygen will generate a search box for
# the HTML output. The underlying search engine uses javascript and DHTML and
# should work on any modern browser. Note that when using HTML help
# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET)
# there is already a search function so this one should typically be disabled.
# For large projects the javascript based search engine can be slow, then
# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to
# search using the keyboard; to jump to the search box use <access key> + S
# (what the <access key> is depends on the OS and browser, but it is typically
# <CTRL>, <ALT>/<option>, or both). Inside the search box use the <cursor down
# key> to jump into the search results window, the results can be navigated
# using the <cursor keys>. Press <Enter> to select an item or <escape> to cancel
# the search. The filter options can be selected when the cursor is inside the
# search box by pressing <Shift>+<cursor down>. Also here use the <cursor keys>
# to select a filter and <Enter> or <escape> to activate or cancel the filter
# option.
# The default value is: YES.
# This tag requires that the tag GENERATE_HTML is set to YES.
SEARCHENGINE = YES
# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
# implemented using a web server instead of a web client using Javascript. There
# are two flavors of web server based searching depending on the EXTERNAL_SEARCH
# setting. When disabled, doxygen will generate a PHP script for searching and
# an index file used by the script. When EXTERNAL_SEARCH is enabled the indexing
# and searching needs to be provided by external tools. See the section
# "External Indexing and Searching" for details.
# The default value is: NO.
# This tag requires that the tag SEARCHENGINE is set to YES.
SERVER_BASED_SEARCH = NO
# When EXTERNAL_SEARCH tag is enabled doxygen will no longer generate the PHP
# script for searching. Instead the search results are written to an XML file
# which needs to be processed by an external indexer. Doxygen will invoke an
# external search engine pointed to by the SEARCHENGINE_URL option to obtain the
# search results.
#
# Doxygen ships with an example indexer (doxyindexer) and search engine
# (doxysearch.cgi) which are based on the open source search engine library
# Xapian (see: http://xapian.org/).
#
# See the section "External Indexing and Searching" for details.
# The default value is: NO.
# This tag requires that the tag SEARCHENGINE is set to YES.
EXTERNAL_SEARCH = NO
# The SEARCHENGINE_URL should point to a search engine hosted by a web server
# which will return the search results when EXTERNAL_SEARCH is enabled.
#
# Doxygen ships with an example indexer (doxyindexer) and search engine
# (doxysearch.cgi) which are based on the open source search engine library
# Xapian (see: http://xapian.org/). See the section "External Indexing and
# Searching" for details.
# This tag requires that the tag SEARCHENGINE is set to YES.
SEARCHENGINE_URL =
# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed
# search data is written to a file for indexing by an external tool. With the
# SEARCHDATA_FILE tag the name of this file can be specified.
# The default file is: searchdata.xml.
# This tag requires that the tag SEARCHENGINE is set to YES.
SEARCHDATA_FILE = searchdata.xml
# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the
# EXTERNAL_SEARCH_ID tag can be used as an identifier for the project. This is
# useful in combination with EXTRA_SEARCH_MAPPINGS to search through multiple
# projects and redirect the results back to the right project.
# This tag requires that the tag SEARCHENGINE is set to YES.
EXTERNAL_SEARCH_ID =
# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen
# projects other than the one defined by this configuration file, but that are
# all added to the same external search index. Each project needs to have a
# unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id of
# to a relative location where the documentation can be found. The format is:
# EXTRA_SEARCH_MAPPINGS = tagname1=loc1 tagname2=loc2 ...
# This tag requires that the tag SEARCHENGINE is set to YES.
EXTRA_SEARCH_MAPPINGS =
#---------------------------------------------------------------------------
# Configuration options related to the LaTeX output
#---------------------------------------------------------------------------
# If the GENERATE_LATEX tag is set to YES, doxygen will generate LaTeX output.
# The default value is: YES.
GENERATE_LATEX = NO
# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. If a
# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
# it.
# The default directory is: latex.
# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_OUTPUT = latex
# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
# invoked.
#
# Note that when enabling USE_PDFLATEX this option is only used for generating
# bitmaps for formulas in the HTML output, but not in the Makefile that is
# written to the output directory.
# The default file is: latex.
# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_CMD_NAME = latex
# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to generate
# index for LaTeX.
# The default file is: makeindex.
# This tag requires that the tag GENERATE_LATEX is set to YES.
MAKEINDEX_CMD_NAME = makeindex
# If the COMPACT_LATEX tag is set to YES, doxygen generates more compact LaTeX
# documents. This may be useful for small projects and may help to save some
# trees in general.
# The default value is: NO.
# This tag requires that the tag GENERATE_LATEX is set to YES.
COMPACT_LATEX = NO
# The PAPER_TYPE tag can be used to set the paper type that is used by the
# printer.
# Possible values are: a4 (210 x 297 mm), letter (8.5 x 11 inches), legal (8.5 x
# 14 inches) and executive (7.25 x 10.5 inches).
# The default value is: a4.
# This tag requires that the tag GENERATE_LATEX is set to YES.
PAPER_TYPE = a4
# The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names
# that should be included in the LaTeX output. The package can be specified just
# by its name or with the correct syntax as to be used with the LaTeX
# \usepackage command. To get the times font for instance you can specify :
# EXTRA_PACKAGES=times or EXTRA_PACKAGES={times}
# To use the option intlimits with the amsmath package you can specify:
# EXTRA_PACKAGES=[intlimits]{amsmath}
# If left blank no extra packages will be included.
# This tag requires that the tag GENERATE_LATEX is set to YES.
EXTRA_PACKAGES =
# The LATEX_HEADER tag can be used to specify a personal LaTeX header for the
# generated LaTeX document. The header should contain everything until the first
# chapter. If it is left blank doxygen will generate a standard header. See
# section "Doxygen usage" for information on how to let doxygen write the
# default header to a separate file.
#
# Note: Only use a user-defined header if you know what you are doing! The
# following commands have a special meaning inside the header: $title,
# $datetime, $date, $doxygenversion, $projectname, $projectnumber,
# $projectbrief, $projectlogo. Doxygen will replace $title with the empty
# string, for the replacement values of the other commands the user is referred
# to HTML_HEADER.
# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_HEADER =
# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the
# generated LaTeX document. The footer should contain everything after the last
# chapter. If it is left blank doxygen will generate a standard footer. See
# LATEX_HEADER for more information on how to generate a default footer and what
# special commands can be used inside the footer.
#
# Note: Only use a user-defined footer if you know what you are doing!
# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_FOOTER =
# The LATEX_EXTRA_STYLESHEET tag can be used to specify additional user-defined
# LaTeX style sheets that are included after the standard style sheets created
# by doxygen. Using this option one can overrule certain style aspects. Doxygen
# will copy the style sheet files to the output directory.
# Note: The order of the extra style sheet files is of importance (e.g. the last
# style sheet in the list overrules the setting of the previous ones in the
# list).
# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_EXTRA_STYLESHEET =
# The LATEX_EXTRA_FILES tag can be used to specify one or more extra images or
# other source files which should be copied to the LATEX_OUTPUT output
# directory. Note that the files will be copied as-is; there are no commands or
# markers available.
# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_EXTRA_FILES =
# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated is
# prepared for conversion to PDF (using ps2pdf or pdflatex). The PDF file will
# contain links (just like the HTML output) instead of page references. This
# makes the output suitable for online browsing using a PDF viewer.
# The default value is: YES.
# This tag requires that the tag GENERATE_LATEX is set to YES.
PDF_HYPERLINKS = YES
# If the USE_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate
# the PDF file directly from the LaTeX files. Set this option to YES, to get a
# higher quality PDF documentation.
# The default value is: YES.
# This tag requires that the tag GENERATE_LATEX is set to YES.
USE_PDFLATEX = YES
# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \batchmode
# command to the generated LaTeX files. This will instruct LaTeX to keep running
# if errors occur, instead of asking the user for help. This option is also used
# when generating formulas in HTML.
# The default value is: NO.
# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_BATCHMODE = NO
# If the LATEX_HIDE_INDICES tag is set to YES then doxygen will not include the
# index chapters (such as File Index, Compound Index, etc.) in the output.
# The default value is: NO.
# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_HIDE_INDICES = NO
# If the LATEX_SOURCE_CODE tag is set to YES then doxygen will include source
# code with syntax highlighting in the LaTeX output.
#
# Note that which sources are shown also depends on other settings such as
# SOURCE_BROWSER.
# The default value is: NO.
# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_SOURCE_CODE = NO
# The LATEX_BIB_STYLE tag can be used to specify the style to use for the
# bibliography, e.g. plainnat, or ieeetr. See
# http://en.wikipedia.org/wiki/BibTeX and \cite for more info.
# The default value is: plain.
# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_BIB_STYLE = plain
# If the LATEX_TIMESTAMP tag is set to YES then the footer of each generated
# page will contain the date and time when the page was generated. Setting this
# to NO can help when comparing the output of multiple runs.
# The default value is: NO.
# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_TIMESTAMP = NO
#---------------------------------------------------------------------------
# Configuration options related to the RTF output
#---------------------------------------------------------------------------
# If the GENERATE_RTF tag is set to YES, doxygen will generate RTF output. The
# RTF output is optimized for Word 97 and may not look too pretty with other RTF
# readers/editors.
# The default value is: NO.
GENERATE_RTF = NO
# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. If a
# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
# it.
# The default directory is: rtf.
# This tag requires that the tag GENERATE_RTF is set to YES.
RTF_OUTPUT = rtf
# If the COMPACT_RTF tag is set to YES, doxygen generates more compact RTF
# documents. This may be useful for small projects and may help to save some
# trees in general.
# The default value is: NO.
# This tag requires that the tag GENERATE_RTF is set to YES.
COMPACT_RTF = NO
# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated will
# contain hyperlink fields. The RTF file will contain links (just like the HTML
# output) instead of page references. This makes the output suitable for online
# browsing using Word or some other Word compatible readers that support those
# fields.
#
# Note: WordPad (write) and others do not support links.
# The default value is: NO.
# This tag requires that the tag GENERATE_RTF is set to YES.
RTF_HYPERLINKS = NO
# Load stylesheet definitions from file. Syntax is similar to doxygen's config
# file, i.e. a series of assignments. You only have to provide replacements,
# missing definitions are set to their default value.
#
# See also section "Doxygen usage" for information on how to generate the
# default style sheet that doxygen normally uses.
# This tag requires that the tag GENERATE_RTF is set to YES.
RTF_STYLESHEET_FILE =
# Set optional variables used in the generation of an RTF document. Syntax is
# similar to doxygen's config file. A template extensions file can be generated
# using doxygen -e rtf extensionFile.
# This tag requires that the tag GENERATE_RTF is set to YES.
RTF_EXTENSIONS_FILE =
# If the RTF_SOURCE_CODE tag is set to YES then doxygen will include source code
# with syntax highlighting in the RTF output.
#
# Note that which sources are shown also depends on other settings such as
# SOURCE_BROWSER.
# The default value is: NO.
# This tag requires that the tag GENERATE_RTF is set to YES.
RTF_SOURCE_CODE = NO
#---------------------------------------------------------------------------
# Configuration options related to the man page output
#---------------------------------------------------------------------------
# If the GENERATE_MAN tag is set to YES, doxygen will generate man pages for
# classes and files.
# The default value is: NO.
GENERATE_MAN = NO
# The MAN_OUTPUT tag is used to specify where the man pages will be put. If a
# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
# it. A directory man3 will be created inside the directory specified by
# MAN_OUTPUT.
# The default directory is: man.
# This tag requires that the tag GENERATE_MAN is set to YES.
MAN_OUTPUT = man
# The MAN_EXTENSION tag determines the extension that is added to the generated
# man pages. In case the manual section does not start with a number, the number
# 3 is prepended. The dot (.) at the beginning of the MAN_EXTENSION tag is
# optional.
# The default value is: .3.
# This tag requires that the tag GENERATE_MAN is set to YES.
MAN_EXTENSION = .3
# The MAN_SUBDIR tag determines the name of the directory created within
# MAN_OUTPUT in which the man pages are placed. If defaults to man followed by
# MAN_EXTENSION with the initial . removed.
# This tag requires that the tag GENERATE_MAN is set to YES.
MAN_SUBDIR =
# If the MAN_LINKS tag is set to YES and doxygen generates man output, then it
# will generate one additional man file for each entity documented in the real
# man page(s). These additional files only source the real man page, but without
# them the man command would be unable to find the correct page.
# The default value is: NO.
# This tag requires that the tag GENERATE_MAN is set to YES.
MAN_LINKS = NO
#---------------------------------------------------------------------------
# Configuration options related to the XML output
#---------------------------------------------------------------------------
# If the GENERATE_XML tag is set to YES, doxygen will generate an XML file that
# captures the structure of the code including all documentation.
# The default value is: NO.
-GENERATE_XML = YES
+GENERATE_XML = NO
# The XML_OUTPUT tag is used to specify where the XML pages will be put. If a
# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
# it.
# The default directory is: xml.
# This tag requires that the tag GENERATE_XML is set to YES.
XML_OUTPUT = xml
# If the XML_PROGRAMLISTING tag is set to YES, doxygen will dump the program
# listings (including syntax highlighting and cross-referencing information) to
# the XML output. Note that enabling this will significantly increase the size
# of the XML output.
# The default value is: YES.
# This tag requires that the tag GENERATE_XML is set to YES.
XML_PROGRAMLISTING = YES
#---------------------------------------------------------------------------
# Configuration options related to the DOCBOOK output
#---------------------------------------------------------------------------
# If the GENERATE_DOCBOOK tag is set to YES, doxygen will generate Docbook files
# that can be used to generate PDF.
# The default value is: NO.
GENERATE_DOCBOOK = NO
# The DOCBOOK_OUTPUT tag is used to specify where the Docbook pages will be put.
# If a relative path is entered the value of OUTPUT_DIRECTORY will be put in
# front of it.
# The default directory is: docbook.
# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
DOCBOOK_OUTPUT = docbook
# If the DOCBOOK_PROGRAMLISTING tag is set to YES, doxygen will include the
# program listings (including syntax highlighting and cross-referencing
# information) to the DOCBOOK output. Note that enabling this will significantly
# increase the size of the DOCBOOK output.
# The default value is: NO.
# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
DOCBOOK_PROGRAMLISTING = NO
#---------------------------------------------------------------------------
# Configuration options for the AutoGen Definitions output
#---------------------------------------------------------------------------
# If the GENERATE_AUTOGEN_DEF tag is set to YES, doxygen will generate an
# AutoGen Definitions (see http://autogen.sf.net) file that captures the
# structure of the code including all documentation. Note that this feature is
# still experimental and incomplete at the moment.
# The default value is: NO.
GENERATE_AUTOGEN_DEF = NO
#---------------------------------------------------------------------------
# Configuration options related to the Perl module output
#---------------------------------------------------------------------------
# If the GENERATE_PERLMOD tag is set to YES, doxygen will generate a Perl module
# file that captures the structure of the code including all documentation.
#
# Note that this feature is still experimental and incomplete at the moment.
# The default value is: NO.
GENERATE_PERLMOD = NO
# If the PERLMOD_LATEX tag is set to YES, doxygen will generate the necessary
# Makefile rules, Perl scripts and LaTeX code to be able to generate PDF and DVI
# output from the Perl module output.
# The default value is: NO.
# This tag requires that the tag GENERATE_PERLMOD is set to YES.
PERLMOD_LATEX = NO
# If the PERLMOD_PRETTY tag is set to YES, the Perl module output will be nicely
# formatted so it can be parsed by a human reader. This is useful if you want to
# understand what is going on. On the other hand, if this tag is set to NO, the
# size of the Perl module output will be much smaller and Perl will parse it
# just the same.
# The default value is: YES.
# This tag requires that the tag GENERATE_PERLMOD is set to YES.
PERLMOD_PRETTY = YES
# The names of the make variables in the generated doxyrules.make file are
# prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. This is useful
# so different doxyrules.make files included by the same Makefile don't
# overwrite each other's variables.
# This tag requires that the tag GENERATE_PERLMOD is set to YES.
PERLMOD_MAKEVAR_PREFIX =
#---------------------------------------------------------------------------
# Configuration options related to the preprocessor
#---------------------------------------------------------------------------
# If the ENABLE_PREPROCESSING tag is set to YES, doxygen will evaluate all
# C-preprocessor directives found in the sources and include files.
# The default value is: YES.
ENABLE_PREPROCESSING = YES
# If the MACRO_EXPANSION tag is set to YES, doxygen will expand all macro names
# in the source code. If set to NO, only conditional compilation will be
# performed. Macro expansion can be done in a controlled way by setting
# EXPAND_ONLY_PREDEF to YES.
# The default value is: NO.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
MACRO_EXPANSION = NO
# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES then
# the macro expansion is limited to the macros specified with the PREDEFINED and
# EXPAND_AS_DEFINED tags.
# The default value is: NO.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
EXPAND_ONLY_PREDEF = NO
# If the SEARCH_INCLUDES tag is set to YES, the include files in the
# INCLUDE_PATH will be searched if a #include is found.
# The default value is: YES.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
SEARCH_INCLUDES = YES
# The INCLUDE_PATH tag can be used to specify one or more directories that
# contain include files that are not input files but should be processed by the
# preprocessor.
# This tag requires that the tag SEARCH_INCLUDES is set to YES.
INCLUDE_PATH =
# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
# patterns (like *.h and *.hpp) to filter out the header-files in the
# directories. If left blank, the patterns specified with FILE_PATTERNS will be
# used.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
INCLUDE_FILE_PATTERNS =
# The PREDEFINED tag can be used to specify one or more macro names that are
# defined before the preprocessor is started (similar to the -D option of e.g.
# gcc). The argument of the tag is a list of macros of the form: name or
# name=definition (no spaces). If the definition and the "=" are omitted, "=1"
# is assumed. To prevent a macro definition from being undefined via #undef or
# recursively expanded use the := operator instead of the = operator.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
PREDEFINED =
# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
# tag can be used to specify a list of macro names that should be expanded. The
# macro definition that is found in the sources will be used. Use the PREDEFINED
# tag if you want to use a different macro definition that overrules the
# definition found in the source code.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
EXPAND_AS_DEFINED =
# If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will
# remove all references to function-like macros that are alone on a line, have
# an all uppercase name, and do not end with a semicolon. Such function macros
# are typically used for boiler-plate code, and will confuse the parser if not
# removed.
# The default value is: YES.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
SKIP_FUNCTION_MACROS = YES
#---------------------------------------------------------------------------
# Configuration options related to external references
#---------------------------------------------------------------------------
# The TAGFILES tag can be used to specify one or more tag files. For each tag
# file the location of the external documentation should be added. The format of
# a tag file without this location is as follows:
# TAGFILES = file1 file2 ...
# Adding location for the tag files is done as follows:
# TAGFILES = file1=loc1 "file2 = loc2" ...
# where loc1 and loc2 can be relative or absolute paths or URLs. See the
# section "Linking to external documentation" for more information about the use
# of tag files.
# Note: Each tag file must have a unique name (where the name does NOT include
# the path). If a tag file is not located in the directory in which doxygen is
# run, you must also specify the path to the tagfile here.
TAGFILES =
# When a file name is specified after GENERATE_TAGFILE, doxygen will create a
# tag file that is based on the input files it reads. See section "Linking to
# external documentation" for more information about the usage of tag files.
GENERATE_TAGFILE =
# If the ALLEXTERNALS tag is set to YES, all external class will be listed in
# the class index. If set to NO, only the inherited external classes will be
# listed.
# The default value is: NO.
ALLEXTERNALS = NO
# If the EXTERNAL_GROUPS tag is set to YES, all external groups will be listed
# in the modules index. If set to NO, only the current project's groups will be
# listed.
# The default value is: YES.
EXTERNAL_GROUPS = YES
# If the EXTERNAL_PAGES tag is set to YES, all external pages will be listed in
# the related pages index. If set to NO, only the current project's pages will
# be listed.
# The default value is: YES.
EXTERNAL_PAGES = YES
# The PERL_PATH should be the absolute path and name of the perl script
# interpreter (i.e. the result of 'which perl').
# The default file (with absolute path) is: /usr/bin/perl.
PERL_PATH = /usr/bin/perl
#---------------------------------------------------------------------------
# Configuration options related to the dot tool
#---------------------------------------------------------------------------
# If the CLASS_DIAGRAMS tag is set to YES, doxygen will generate a class diagram
# (in HTML and LaTeX) for classes with base or super classes. Setting the tag to
# NO turns the diagrams off. Note that this option also works with HAVE_DOT
# disabled, but it is recommended to install and use dot, since it yields more
# powerful graphs.
# The default value is: YES.
CLASS_DIAGRAMS = YES
# You can define message sequence charts within doxygen comments using the \msc
# command. Doxygen will then run the mscgen tool (see:
# http://www.mcternan.me.uk/mscgen/)) to produce the chart and insert it in the
# documentation. The MSCGEN_PATH tag allows you to specify the directory where
# the mscgen tool resides. If left empty the tool is assumed to be found in the
# default search path.
MSCGEN_PATH =
# You can include diagrams made with dia in doxygen documentation. Doxygen will
# then run dia to produce the diagram and insert it in the documentation. The
# DIA_PATH tag allows you to specify the directory where the dia binary resides.
# If left empty dia is assumed to be found in the default search path.
DIA_PATH =
# If set to YES the inheritance and collaboration graphs will hide inheritance
# and usage relations if the target is undocumented or is not a class.
# The default value is: YES.
HIDE_UNDOC_RELATIONS = YES
# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
# available from the path. This tool is part of Graphviz (see:
# http://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent
# Bell Labs. The other options in this section have no effect if this option is
# set to NO
# The default value is: NO.
HAVE_DOT = NO
# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is allowed
# to run in parallel. When set to 0 doxygen will base this on the number of
# processors available in the system. You can set it explicitly to a value
# larger than 0 to get control over the balance between CPU load and processing
# speed.
# Minimum value: 0, maximum value: 32, default value: 0.
# This tag requires that the tag HAVE_DOT is set to YES.
DOT_NUM_THREADS = 0
# When you want a differently looking font in the dot files that doxygen
# generates you can specify the font name using DOT_FONTNAME. You need to make
# sure dot is able to find the font, which can be done by putting it in a
# standard location or by setting the DOTFONTPATH environment variable or by
# setting DOT_FONTPATH to the directory containing the font.
# The default value is: Helvetica.
# This tag requires that the tag HAVE_DOT is set to YES.
DOT_FONTNAME = Helvetica
# The DOT_FONTSIZE tag can be used to set the size (in points) of the font of
# dot graphs.
# Minimum value: 4, maximum value: 24, default value: 10.
# This tag requires that the tag HAVE_DOT is set to YES.
DOT_FONTSIZE = 10
# By default doxygen will tell dot to use the default font as specified with
# DOT_FONTNAME. If you specify a different font using DOT_FONTNAME you can set
# the path where dot can find it using this tag.
# This tag requires that the tag HAVE_DOT is set to YES.
DOT_FONTPATH =
# If the CLASS_GRAPH tag is set to YES then doxygen will generate a graph for
# each documented class showing the direct and indirect inheritance relations.
# Setting this tag to YES will force the CLASS_DIAGRAMS tag to NO.
# The default value is: YES.
# This tag requires that the tag HAVE_DOT is set to YES.
CLASS_GRAPH = YES
# If the COLLABORATION_GRAPH tag is set to YES then doxygen will generate a
# graph for each documented class showing the direct and indirect implementation
# dependencies (inheritance, containment, and class references variables) of the
# class with other documented classes.
# The default value is: YES.
# This tag requires that the tag HAVE_DOT is set to YES.
COLLABORATION_GRAPH = YES
# If the GROUP_GRAPHS tag is set to YES then doxygen will generate a graph for
# groups, showing the direct groups dependencies.
# The default value is: YES.
# This tag requires that the tag HAVE_DOT is set to YES.
GROUP_GRAPHS = YES
# If the UML_LOOK tag is set to YES, doxygen will generate inheritance and
# collaboration diagrams in a style similar to the OMG's Unified Modeling
# Language.
# The default value is: NO.
# This tag requires that the tag HAVE_DOT is set to YES.
UML_LOOK = NO
# If the UML_LOOK tag is enabled, the fields and methods are shown inside the
# class node. If there are many fields or methods and many nodes the graph may
# become too big to be useful. The UML_LIMIT_NUM_FIELDS threshold limits the
# number of items for each type to make the size more manageable. Set this to 0
# for no limit. Note that the threshold may be exceeded by 50% before the limit
# is enforced. So when you set the threshold to 10, up to 15 fields may appear,
# but if the number exceeds 15, the total amount of fields shown is limited to
# 10.
# Minimum value: 0, maximum value: 100, default value: 10.
# This tag requires that the tag HAVE_DOT is set to YES.
UML_LIMIT_NUM_FIELDS = 10
# If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and
# collaboration graphs will show the relations between templates and their
# instances.
# The default value is: NO.
# This tag requires that the tag HAVE_DOT is set to YES.
TEMPLATE_RELATIONS = NO
# If the INCLUDE_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are set to
# YES then doxygen will generate a graph for each documented file showing the
# direct and indirect include dependencies of the file with other documented
# files.
# The default value is: YES.
# This tag requires that the tag HAVE_DOT is set to YES.
INCLUDE_GRAPH = YES
# If the INCLUDED_BY_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are
# set to YES then doxygen will generate a graph for each documented file showing
# the direct and indirect include dependencies of the file with other documented
# files.
# The default value is: YES.
# This tag requires that the tag HAVE_DOT is set to YES.
INCLUDED_BY_GRAPH = YES
# If the CALL_GRAPH tag is set to YES then doxygen will generate a call
# dependency graph for every global function or class method.
#
# Note that enabling this option will significantly increase the time of a run.
# So in most cases it will be better to enable call graphs for selected
# functions only using the \callgraph command. Disabling a call graph can be
# accomplished by means of the command \hidecallgraph.
# The default value is: NO.
# This tag requires that the tag HAVE_DOT is set to YES.
CALL_GRAPH = NO
# If the CALLER_GRAPH tag is set to YES then doxygen will generate a caller
# dependency graph for every global function or class method.
#
# Note that enabling this option will significantly increase the time of a run.
# So in most cases it will be better to enable caller graphs for selected
# functions only using the \callergraph command. Disabling a caller graph can be
# accomplished by means of the command \hidecallergraph.
# The default value is: NO.
# This tag requires that the tag HAVE_DOT is set to YES.
CALLER_GRAPH = NO
# If the GRAPHICAL_HIERARCHY tag is set to YES then doxygen will graphical
# hierarchy of all classes instead of a textual one.
# The default value is: YES.
# This tag requires that the tag HAVE_DOT is set to YES.
GRAPHICAL_HIERARCHY = YES
# If the DIRECTORY_GRAPH tag is set to YES then doxygen will show the
# dependencies a directory has on other directories in a graphical way. The
# dependency relations are determined by the #include relations between the
# files in the directories.
# The default value is: YES.
# This tag requires that the tag HAVE_DOT is set to YES.
DIRECTORY_GRAPH = YES
# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
# generated by dot. For an explanation of the image formats see the section
# output formats in the documentation of the dot tool (Graphviz (see:
# http://www.graphviz.org/)).
# Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order
# to make the SVG files visible in IE 9+ (other browsers do not have this
# requirement).
# Possible values are: png, jpg, gif, svg, png:gd, png:gd:gd, png:cairo,
# png:cairo:gd, png:cairo:cairo, png:cairo:gdiplus, png:gdiplus and
# png:gdiplus:gdiplus.
# The default value is: png.
# This tag requires that the tag HAVE_DOT is set to YES.
DOT_IMAGE_FORMAT = png
# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to
# enable generation of interactive SVG images that allow zooming and panning.
#
# Note that this requires a modern browser other than Internet Explorer. Tested
# and working are Firefox, Chrome, Safari, and Opera.
# Note: For IE 9+ you need to set HTML_FILE_EXTENSION to xhtml in order to make
# the SVG files visible. Older versions of IE do not have SVG support.
# The default value is: NO.
# This tag requires that the tag HAVE_DOT is set to YES.
INTERACTIVE_SVG = NO
# The DOT_PATH tag can be used to specify the path where the dot tool can be
# found. If left blank, it is assumed the dot tool can be found in the path.
# This tag requires that the tag HAVE_DOT is set to YES.
DOT_PATH =
# The DOTFILE_DIRS tag can be used to specify one or more directories that
# contain dot files that are included in the documentation (see the \dotfile
# command).
# This tag requires that the tag HAVE_DOT is set to YES.
DOTFILE_DIRS =
# The MSCFILE_DIRS tag can be used to specify one or more directories that
# contain msc files that are included in the documentation (see the \mscfile
# command).
MSCFILE_DIRS =
# The DIAFILE_DIRS tag can be used to specify one or more directories that
# contain dia files that are included in the documentation (see the \diafile
# command).
DIAFILE_DIRS =
# When using plantuml, the PLANTUML_JAR_PATH tag should be used to specify the
# path where java can find the plantuml.jar file. If left blank, it is assumed
# PlantUML is not used or called during a preprocessing step. Doxygen will
# generate a warning when it encounters a \startuml command in this case and
# will not generate output for the diagram.
PLANTUML_JAR_PATH =
# When using plantuml, the specified paths are searched for files specified by
# the !include statement in a plantuml block.
PLANTUML_INCLUDE_PATH =
# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes
# that will be shown in the graph. If the number of nodes in a graph becomes
# larger than this value, doxygen will truncate the graph, which is visualized
# by representing a node as a red box. Note that doxygen if the number of direct
# children of the root node in a graph is already larger than
# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note that
# the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
# Minimum value: 0, maximum value: 10000, default value: 50.
# This tag requires that the tag HAVE_DOT is set to YES.
DOT_GRAPH_MAX_NODES = 50
# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the graphs
# generated by dot. A depth value of 3 means that only nodes reachable from the
# root by following a path via at most 3 edges will be shown. Nodes that lay
# further from the root node will be omitted. Note that setting this option to 1
# or 2 may greatly reduce the computation time needed for large code bases. Also
# note that the size of a graph can be further restricted by
# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
# Minimum value: 0, maximum value: 1000, default value: 0.
# This tag requires that the tag HAVE_DOT is set to YES.
MAX_DOT_GRAPH_DEPTH = 0
# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
# background. This is disabled by default, because dot on Windows does not seem
# to support this out of the box.
#
# Warning: Depending on the platform used, enabling this option may lead to
# badly anti-aliased labels on the edges of a graph (i.e. they become hard to
# read).
# The default value is: NO.
# This tag requires that the tag HAVE_DOT is set to YES.
DOT_TRANSPARENT = NO
# Set the DOT_MULTI_TARGETS tag to YES to allow dot to generate multiple output
# files in one run (i.e. multiple -o and -T options on the command line). This
# makes dot run faster, but since only newer versions of dot (>1.8.10) support
# this, this feature is disabled by default.
# The default value is: NO.
# This tag requires that the tag HAVE_DOT is set to YES.
DOT_MULTI_TARGETS = NO
# If the GENERATE_LEGEND tag is set to YES doxygen will generate a legend page
# explaining the meaning of the various boxes and arrows in the dot generated
# graphs.
# The default value is: YES.
# This tag requires that the tag HAVE_DOT is set to YES.
GENERATE_LEGEND = YES
# If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate dot
# files that are used to generate the various graphs.
# The default value is: YES.
# This tag requires that the tag HAVE_DOT is set to YES.
DOT_CLEANUP = YES
diff --git a/documentation-api/communicaton.graphml b/documentation-api/diagrams/communicaton.graphml
similarity index 100%
rename from documentation-api/communicaton.graphml
rename to documentation-api/diagrams/communicaton.graphml
diff --git a/documentation-api/containers.graphml b/documentation-api/diagrams/containers.graphml
similarity index 100%
rename from documentation-api/containers.graphml
rename to documentation-api/diagrams/containers.graphml
diff --git a/documentation-api/exploitation.graphml b/documentation-api/diagrams/exploitation.graphml
similarity index 100%
rename from documentation-api/exploitation.graphml
rename to documentation-api/diagrams/exploitation.graphml
diff --git a/documentation-api/interpretation.graphml b/documentation-api/diagrams/interpretation.graphml
similarity index 100%
rename from documentation-api/interpretation.graphml
rename to documentation-api/diagrams/interpretation.graphml
diff --git a/documentation-api/latetranscend.graphml b/documentation-api/diagrams/latetranscend.graphml
similarity index 99%
rename from documentation-api/latetranscend.graphml
rename to documentation-api/diagrams/latetranscend.graphml
index 808e3a4..85ad3eb 100644
--- a/documentation-api/latetranscend.graphml
+++ b/documentation-api/diagrams/latetranscend.graphml
@@ -1,550 +1,550 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<graphml xmlns="http://graphml.graphdrawing.org/xmlns" xmlns:java="http://www.yworks.com/xml/yfiles-common/1.0/java" xmlns:sys="http://www.yworks.com/xml/yfiles-common/markup/primitives/2.0" xmlns:x="http://www.yworks.com/xml/yfiles-common/markup/2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:y="http://www.yworks.com/xml/graphml" xmlns:yed="http://www.yworks.com/xml/yed/3" xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns http://www.yworks.com/xml/schema/graphml/1.1/ygraphml.xsd">
<!--Created by yEd 3.18.1-->
<key attr.name="Description" attr.type="string" for="graph" id="d0"/>
<key for="port" id="d1" yfiles.type="portgraphics"/>
<key for="port" id="d2" yfiles.type="portgeometry"/>
<key for="port" id="d3" yfiles.type="portuserdata"/>
<key attr.name="Property 1" attr.type="string" for="node" id="d4">
<default xml:space="preserve"/>
</key>
<key attr.name="url" attr.type="string" for="node" id="d5"/>
<key attr.name="description" attr.type="string" for="node" id="d6"/>
<key for="node" id="d7" yfiles.type="nodegraphics"/>
<key for="graphml" id="d8" yfiles.type="resources"/>
<key attr.name="url" attr.type="string" for="edge" id="d9"/>
<key attr.name="description" attr.type="string" for="edge" id="d10"/>
<key for="edge" id="d11" yfiles.type="edgegraphics"/>
<graph edgedefault="directed" id="G">
<data key="d0" xml:space="preserve"/>
<node id="n0" yfiles.foldertype="group">
<data key="d7">
<y:TableNode configuration="YED_TABLE_NODE">
- <y:Geometry height="500.24892252285287" width="1181.2763671875" x="150.0" y="-350.5"/>
+ <y:Geometry height="487.76064127285287" width="1181.2763671875" x="150.0" y="-338.01171875"/>
<y:Fill color="#ECF5FF" color2="#0042F440" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="15" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="20.7578125" horizontalTextPosition="center" iconTextGap="4" modelName="internal" modelPosition="t" textColor="#000000" verticalTextPosition="bottom" visible="true" width="169.08056640625" x="506.097900390625" xml:space="preserve" y="4.0">Late Transcend Diagram</y:NodeLabel>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.40625" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="30.677734375" x="149.2061328125003" xml:space="preserve" y="33.0">Pass<y:LabelModel><y:ColumnNodeLabelModel offset="3.0"/></y:LabelModel><y:ModelParameter><y:ColumnNodeLabelModelParameter id="column_0" inside="true" verticalPosition="0.0"/></y:ModelParameter></y:NodeLabel>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.40625" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="74.7109375" x="519.7477148437504" xml:space="preserve" y="33.0">Interpretation<y:LabelModel><y:ColumnNodeLabelModel offset="3.0"/></y:LabelModel><y:ModelParameter><y:ColumnNodeLabelModelParameter id="column_1" inside="true" verticalPosition="0.0"/></y:ModelParameter></y:NodeLabel>
- <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" hasText="false" height="4.0" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="4.0" x="588.63818359375" y="248.12446126142643">
+ <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" hasText="false" height="4.0" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="4.0" x="588.63818359375" y="241.88032063642643">
<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.40625" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="60.6953125" x="952.8487109375001" xml:space="preserve" y="33.0">Transcend<y:LabelModel><y:ColumnNodeLabelModel offset="3.0"/></y:LabelModel><y:ModelParameter><y:ColumnNodeLabelModelParameter id="column_2" inside="true" verticalPosition="0.0"/></y:ModelParameter></y:NodeLabel>
<y:StyleProperties>
<y:Property class="java.awt.Color" name="yed.table.section.color" value="#7192b2"/>
<y:Property class="java.lang.Double" name="yed.table.header.height" value="24.0"/>
<y:Property class="java.awt.Color" name="yed.table.lane.color.main" value="#c4d7ed"/>
<y:Property class="java.awt.Color" name="yed.table.lane.color.alternating" value="#abc8e2"/>
<y:Property class="java.awt.Color" name="yed.table.header.color.alternating" value="#abc8e2"/>
<y:Property class="java.lang.String" name="yed.table.lane.style" value="lane.style.columns"/>
<y:Property class="java.awt.Color" name="yed.table.header.color.main" value="#c4d7ed"/>
</y:StyleProperties>
<y:State autoResize="true" closed="false" closedHeight="80.0" closedWidth="100.0"/>
<y:Insets bottom="0" bottomF="0.0" left="0" leftF="0.0" right="0" rightF="0.0" top="0" topF="0.0"/>
<y:BorderInsets bottom="67" bottomF="66.74892252285287" left="0" leftF="0.0" right="48" rightF="48.0" top="0" topF="0.0"/>
<y:Table autoResizeTable="true" defaultColumnWidth="120.0" defaultMinimumColumnWidth="80.0" defaultMinimumRowHeight="50.0" defaultRowHeight="80.0">
<y:DefaultColumnInsets bottom="0.0" left="0.0" right="0.0" top="24.0"/>
<y:DefaultRowInsets bottom="0.0" left="0.0" right="0.0" top="0.0"/>
<y:Insets bottom="0.0" left="0.0" right="0.0" top="30.0"/>
<y:Columns>
<y:Column id="column_0" minimumWidth="80.0" width="329.0900000000006">
<y:Insets bottom="0.0" left="0.0" right="0.0" top="24.0"/>
</y:Column>
<y:Column id="column_1" minimumWidth="80.0" width="456.02636718749966">
<y:Insets bottom="0.0" left="0.0" right="0.0" top="24.0"/>
</y:Column>
<y:Column id="column_2" minimumWidth="80.0" width="396.15999999999974">
<y:Insets bottom="0.0" left="0.0" right="0.0" top="24.0"/>
</y:Column>
</y:Columns>
<y:Rows>
- <y:Row height="446.24892252285287" id="row_0" minimumHeight="50.0">
+ <y:Row height="433.76064127285287" id="row_0" minimumHeight="50.0">
<y:Insets bottom="0.0" left="0.0" right="0.0" top="0.0"/>
</y:Row>
</y:Rows>
</y:Table>
</y:TableNode>
</data>
<graph edgedefault="directed" id="n0:">
<node id="n0::n0">
<data key="d5" xml:space="preserve"/>
<data key="d7">
<y:UMLClassNode>
<y:Geometry height="75.0" width="111.0" x="169.5" y="-137.5"/>
<y:Fill color="#FFCC00" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="33.046875" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="97.18359375" x="6.908203125" xml:space="preserve" y="25.40625">LateReasoning
Scope<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="-0.03703090122767855" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.40625" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="36.68359375" x="37.158203125" xml:space="preserve" y="28.796875">fvffdfd<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="30.8125" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="51.35546875" x="29.822265625" xml:space="preserve" y="22.09375">vdffldkjfd
fdfdfd<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
<y:UML clipContent="true" constraint="" hasDetailsColor="false" omitDetails="false" stereotype="pass" use3DEffect="true">
<y:AttributeLabel xml:space="preserve"/>
<y:MethodLabel xml:space="preserve"/>
</y:UML>
</y:UMLClassNode>
</data>
</node>
<node id="n0::n1">
<data key="d5" xml:space="preserve"/>
<data key="d7">
<y:UMLClassNode>
<y:Geometry height="145.7890625" width="119.3984375" x="340.30078125" y="-172.89453125"/>
<y:Fill color="#FFCC00" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="47.5703125" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="97.18359375" x="11.107421875" xml:space="preserve" y="25.40625">LateReasoning
DFAPass
Decorator<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="-0.03703090122767855" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.40625" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="36.68359375" x="41.357421875" xml:space="preserve" y="64.19140625">fvffdfd<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="30.8125" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="51.35546875" x="34.021484375" xml:space="preserve" y="57.48828125">vdffldkjfd
fdfdfd<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
<y:UML clipContent="true" constraint="" hasDetailsColor="false" omitDetails="false" stereotype="pass" use3DEffect="true">
<y:AttributeLabel xml:space="preserve"/>
<y:MethodLabel xml:space="preserve">registerLateScope
processAnnotations</y:MethodLabel>
</y:UML>
</y:UMLClassNode>
</data>
</node>
<node id="n0::n2">
<data key="d5" xml:space="preserve"/>
<data key="d7">
<y:UMLClassNode>
- <y:Geometry height="34.0" width="100.0" x="350.0" y="-267.0"/>
+ <y:Geometry height="34.0" width="100.0" x="350.0" y="-279.48828125"/>
<y:Fill color="#CCCCCC" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="18.5234375" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="61.078125" x="19.4609375" xml:space="preserve" y="3.0">DFAPass<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="-0.03703090122767855" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
<y:UML clipContent="true" constraint="" hasDetailsColor="false" omitDetails="false" stereotype="" use3DEffect="true">
<y:AttributeLabel xml:space="preserve"/>
<y:MethodLabel xml:space="preserve"/>
</y:UML>
</y:UMLClassNode>
</data>
</node>
<node id="n0::n3">
<data key="d5" xml:space="preserve"/>
<data key="d7">
<y:UMLClassNode>
<y:Geometry height="28.0" width="100.0" x="150.0" y="-39.0"/>
<y:Fill color="#CCCCCC" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="18.5234375" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="79.12451171875" x="10.437744140625" xml:space="preserve" y="3.0">ICodeScope<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="-0.03703090122767855" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
<y:UML clipContent="true" constraint="" hasDetailsColor="false" omitDetails="false" stereotype="" use3DEffect="true">
<y:AttributeLabel xml:space="preserve"/>
<y:MethodLabel xml:space="preserve"/>
</y:UML>
</y:UMLClassNode>
</data>
</node>
<node id="n0::n4">
<data key="d5" xml:space="preserve"/>
<data key="d7">
<y:UMLClassNode>
<y:Geometry height="66.0" width="100.0" x="175.0" y="17.0"/>
<y:Fill color="#FFCC00" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="18.5234375" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="94.3271484375" x="2.83642578125" xml:space="preserve" y="25.40625">LateParameter<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="-0.03703090122767855" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
<y:UML clipContent="true" constraint="" hasDetailsColor="false" omitDetails="false" stereotype="analysis" use3DEffect="true">
<y:AttributeLabel xml:space="preserve"/>
<y:MethodLabel xml:space="preserve"/>
</y:UML>
</y:UMLClassNode>
</data>
</node>
<node id="n0::n5">
<data key="d5" xml:space="preserve"/>
<data key="d7">
<y:UMLClassNode>
<y:Geometry height="28.0" width="100.0" x="350.0" y="11.0"/>
<y:Fill color="#CCCCCC" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="18.5234375" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="69.0" x="15.5" xml:space="preserve" y="3.0">DFAGraph<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="-0.03703090122767855" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
<y:UML clipContent="true" constraint="" hasDetailsColor="false" omitDetails="false" stereotype="" use3DEffect="true">
<y:AttributeLabel xml:space="preserve"/>
<y:MethodLabel xml:space="preserve"/>
</y:UML>
</y:UMLClassNode>
</data>
</node>
<node id="n0::n6">
<data key="d5" xml:space="preserve"/>
<data key="d7">
<y:UMLClassNode>
<y:Geometry height="131.671875" width="169.4140625" x="615.29296875" y="-190.8359375"/>
<y:Fill color="#FFCC00" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="33.046875" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="97.18359375" x="36.115234375" xml:space="preserve" y="25.40625">LateReasoning
Compiler<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="-0.03703090122767855" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
<y:UML clipContent="true" constraint="" hasDetailsColor="false" omitDetails="false" stereotype="compilation" use3DEffect="true">
<y:AttributeLabel xml:space="preserve"/>
<y:MethodLabel xml:space="preserve">processSwitchLateStatement
compileAutoExpand
findKeys</y:MethodLabel>
</y:UML>
</y:UMLClassNode>
</data>
</node>
<node id="n0::n7">
<data key="d5" xml:space="preserve"/>
<data key="d7">
<y:UMLClassNode>
<y:Geometry height="130.3828125" width="107.18359375" x="1021.408203125" y="-190.19140625"/>
<y:Fill color="#FFCC00" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="47.5703125" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="97.18359375" x="5.0" xml:space="preserve" y="25.40625">LateReasoning
Transcend
Decorator<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="-0.03703090122767855" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
<y:UML clipContent="true" constraint="" hasDetailsColor="false" omitDetails="false" stereotype="aux" use3DEffect="true">
<y:AttributeLabel xml:space="preserve"/>
<y:MethodLabel xml:space="preserve">queryLate
processSolution</y:MethodLabel>
</y:UML>
</y:UMLClassNode>
</data>
</node>
<node id="n0::n8">
<data key="d5" xml:space="preserve"/>
<data key="d7">
<y:UMLClassNode>
- <y:Geometry height="43.0" width="100.0" x="1025.0" y="-296.5"/>
+ <y:Geometry height="43.0" width="100.0" x="1025.0" y="-283.98828125"/>
<y:Fill color="#CCCCCC" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="33.046875" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="69.74267578125" x="15.128662109375" xml:space="preserve" y="3.0">Transcend
Layer<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="-0.03703090122767855" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
<y:UML clipContent="true" constraint="" hasDetailsColor="false" omitDetails="false" stereotype="" use3DEffect="true">
<y:AttributeLabel xml:space="preserve"/>
<y:MethodLabel xml:space="preserve"/>
</y:UML>
</y:UMLClassNode>
</data>
</node>
<node id="n0::n9">
<data key="d5" xml:space="preserve"/>
<data key="d7">
<y:UMLClassNode>
<y:Geometry height="95.859375" width="116.552734375" x="1166.7236328125" y="-172.9296875"/>
<y:Fill color="#FFCC00" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="33.046875" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="106.552734375" x="5.0" xml:space="preserve" y="25.40625">LateAnnotations
Group<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="-0.03703090122767855" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
<y:UML clipContent="true" constraint="" hasDetailsColor="false" omitDetails="false" stereotype="aux" use3DEffect="true">
<y:AttributeLabel xml:space="preserve"/>
<y:MethodLabel xml:space="preserve">select()</y:MethodLabel>
</y:UML>
</y:UMLClassNode>
</data>
</node>
<node id="n0::n10">
<data key="d5" xml:space="preserve"/>
<data key="d7">
<y:UMLClassNode>
<y:Geometry height="61.0" width="100.0" x="1175.0" y="-30.5"/>
<y:Fill color="#FFCC00" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="33.046875" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="72.5927734375" x="13.70361328125" xml:space="preserve" y="25.40625">Late
Annotation<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="-0.03703090122767855" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
<y:UML clipContent="true" constraint="" hasDetailsColor="false" omitDetails="false" stereotype="aux" use3DEffect="true">
<y:AttributeLabel xml:space="preserve"/>
<y:MethodLabel xml:space="preserve"/>
</y:UML>
</y:UMLClassNode>
</data>
</node>
<node id="n0::n11">
<data key="d7">
<y:GenericNode configuration="com.yworks.flowchart.cloud">
<y:Geometry height="40.8125" width="70.6953125" x="1039.65234375" y="29.59375"/>
<y:Fill color="#E8EEF7" color2="#B7C9E3" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="30.8125" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="60.6953125" x="5.0" xml:space="preserve" y="5.0">Transcend
program<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
</y:GenericNode>
</data>
</node>
<node id="n0::n12">
<data key="d7">
<y:ShapeNode>
<y:Geometry height="46.57249999999999" width="61.377578124999985" x="269.3112109375" y="-248.28625"/>
<y:Fill color="#00FFFF" transparent="false"/>
<y:BorderStyle color="#000000" raised="false" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="30.8125" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="52.017578125" x="4.680000000000007" xml:space="preserve" y="7.8799999999999955">DFA
PassDec<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
<y:Shape type="star8"/>
</y:ShapeNode>
</data>
</node>
<node id="n0::n13">
<data key="d5" xml:space="preserve"/>
<data key="d7">
<y:UMLClassNode>
- <y:Geometry height="43.046875" width="97.78271484375" x="651.108642578125" y="-271.5234375"/>
+ <y:Geometry height="43.046875" width="97.78271484375" x="651.108642578125" y="-284.01171875"/>
<y:Fill color="#C0C0C0" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="33.046875" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="87.78271484375" x="5.0" xml:space="preserve" y="3.0">Interpretation
Scope<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
<y:UML clipContent="true" constraint="" hasDetailsColor="false" omitDetails="false" stereotype="" use3DEffect="true">
<y:AttributeLabel xml:space="preserve"/>
<y:MethodLabel xml:space="preserve"/>
</y:UML>
</y:UMLClassNode>
</data>
</node>
<node id="n0::n14">
<data key="d7">
<y:ShapeNode>
<y:Geometry height="53.00758629441623" width="53.52207177982234" x="948.2389641100888" y="-251.5037931472081"/>
<y:Fill color="#00FFFF" transparent="false"/>
<y:BorderStyle color="#000000" raised="false" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="44.21875" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="34.673828125" x="9.424121827411227" xml:space="preserve" y="4.394418147208114">LR
Trans
Dec<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
<y:Shape type="star8"/>
</y:ShapeNode>
</data>
</node>
</graph>
</node>
<node id="n1">
<data key="d5" xml:space="preserve"/>
<data key="d7">
<y:UMLClassNode>
<y:Geometry height="46.57249999999999" width="63.841796875" x="1268.0791015625" y="201.71375"/>
<y:Fill color="#C0C0C0" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="33.046875" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="53.841796875" x="5.0" xml:space="preserve" y="3.0">AST
getType<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="-0.03703090122767855" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.40625" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="36.68359375" x="13.5791015625" xml:space="preserve" y="14.583124999999995">fvffdfd<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="30.8125" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="51.35546875" x="6.2431640625" xml:space="preserve" y="7.8799999999999955">vdffldkjfd
fdfdfd<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
<y:UML clipContent="true" constraint="" hasDetailsColor="false" omitDetails="false" stereotype="" use3DEffect="true">
<y:AttributeLabel xml:space="preserve"/>
<y:MethodLabel xml:space="preserve"/>
</y:UML>
</y:UMLClassNode>
</data>
</node>
<node id="n2">
<data key="d5" xml:space="preserve"/>
<data key="d7">
<y:UMLClassNode>
<y:Geometry height="28.0" width="152.0234375" x="1116.0556640625" y="161.0"/>
<y:Fill color="#C0C0C0" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="18.5234375" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="142.0234375" x="5.0" xml:space="preserve" y="3.0">dereferenceSlaveType<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
<y:UML clipContent="true" constraint="" hasDetailsColor="false" omitDetails="false" stereotype="" use3DEffect="true">
<y:AttributeLabel xml:space="preserve"/>
<y:MethodLabel xml:space="preserve"/>
</y:UML>
</y:UMLClassNode>
</data>
</node>
<edge id="n0::e0" source="n0::n5" target="n0::n4">
<data key="d9" xml:space="preserve"/>
<data key="d11">
<y:PolyLineEdge>
<y:Path sx="-32.4930059982301" sy="-0.8679073476494636" tx="0.0" ty="0.0">
<y:Point x="375.0" y="50.0"/>
</y:Path>
<y:LineStyle color="#000000" type="dashed" width="1.0"/>
<y:Arrows source="none" target="plain"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="n0::e1" source="n0::n0" target="n0::n4">
<data key="d9" xml:space="preserve"/>
<data key="d11">
<y:PolyLineEdge>
<y:Path sx="-8.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="dashed" width="1.0"/>
<y:Arrows source="none" target="plain"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="n0::e2" source="n0::n0" target="n0::n3">
<data key="d9" xml:space="preserve"/>
<data key="d11">
<y:PolyLineEdge>
<y:Path sx="-28.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="none"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="n0::e3" source="n0::n1" target="n0::n0">
<data key="d9" xml:space="preserve"/>
<data key="d11">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="diamond" target="none"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="n0::e4" source="n0::n1" target="n0::n2">
<data key="d9" xml:space="preserve"/>
<data key="d11">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="white_delta"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="n0::e5" source="n0::n7" target="n0::n9">
<data key="d9" xml:space="preserve"/>
<data key="d11">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0">
<y:Point x="1150.0" y="-125.0"/>
<y:Point x="1150.0" y="-125.0"/>
</y:Path>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="diamond" target="none"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="n0::e6" source="n0::n9" target="n0::n10">
<data key="d9" xml:space="preserve"/>
<data key="d11">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0">
<y:Point x="1225.0" y="-50.0"/>
<y:Point x="1225.0" y="-50.0"/>
</y:Path>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="diamond" target="none"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="n0::e7" source="n0::n7" target="n0::n8">
<data key="d9" xml:space="preserve"/>
<data key="d11">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0">
<y:Point x="1075.0" y="-200.0"/>
<y:Point x="1075.0" y="-200.0"/>
</y:Path>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="white_delta"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="n0::e8" source="n0::n5" target="n0::n11">
<data key="d11">
<y:GenericEdge configuration="com.yworks.edge.framed">
<y:Path sx="0.055000000000063665" sy="3.253818237304529" tx="0.0" ty="0.0">
<y:Point x="400.05500000000006" y="50.0"/>
</y:Path>
<y:LineStyle color="#000000" type="line" width="3.0"/>
<y:Arrows source="none" target="standard"/>
</y:GenericEdge>
</data>
</edge>
<edge id="n0::e9" source="n0::n11" target="n0::n7">
<data key="d11">
<y:GenericEdge configuration="com.yworks.edge.framed">
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="line" width="3.0"/>
<y:Arrows source="none" target="standard"/>
</y:GenericEdge>
</data>
</edge>
<edge id="n0::e10" source="n0::n6" target="n0::n10">
<data key="d9" xml:space="preserve"/>
<data key="d11">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0">
<y:Point x="700.0" y="0.0"/>
</y:Path>
<y:LineStyle color="#000000" type="dashed" width="1.0"/>
<y:Arrows source="none" target="plain"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="n0::e11" source="n0::n6" target="n0::n13">
<data key="d9" xml:space="preserve"/>
<data key="d11">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="white_diamond" target="none"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="n0::e12" source="n0::n1" target="n0::n5">
<data key="d9" xml:space="preserve"/>
<data key="d11">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="dashed" width="1.0"/>
<y:Arrows source="none" target="plain"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="n0::e13" source="n0::n12" target="n0::n1">
<data key="d9" xml:space="preserve"/>
<data key="d11">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="dashed" width="1.0"/>
<y:Arrows source="none" target="plain"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="n0::e14" source="n0::n14" target="n0::n7">
<data key="d9" xml:space="preserve"/>
<data key="d11">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="dashed" width="1.0"/>
<y:Arrows source="none" target="plain"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e0" source="n0::n10" target="n1">
<data key="d9" xml:space="preserve"/>
<data key="d11">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0">
<y:Point x="1225.0" y="225.0"/>
</y:Path>
<y:LineStyle color="#000000" type="dashed" width="1.0"/>
<y:Arrows source="none" target="plain"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e1" source="n0::n10" target="n2">
<data key="d9" xml:space="preserve"/>
<data key="d11">
<y:PolyLineEdge>
<y:Path sx="-34.93826341837166" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="dashed" width="1.0"/>
<y:Arrows source="none" target="plain"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
</graph>
<data key="d8">
<y:Resources/>
</data>
</graphml>
diff --git a/documentation-api/latex.graphml b/documentation-api/diagrams/latex.graphml
similarity index 100%
rename from documentation-api/latex.graphml
rename to documentation-api/diagrams/latex.graphml
diff --git a/documentation-api/modules.graphml b/documentation-api/diagrams/modules.graphml
similarity index 100%
rename from documentation-api/modules.graphml
rename to documentation-api/diagrams/modules.graphml
diff --git a/documentation-api/polymorphism.graphml b/documentation-api/diagrams/polymorphism.graphml
similarity index 100%
rename from documentation-api/polymorphism.graphml
rename to documentation-api/diagrams/polymorphism.graphml
diff --git a/documentation-api/doxygenctl b/documentation-api/doxygenctl
index 91b6440..6a988d1 100755
--- a/documentation-api/doxygenctl
+++ b/documentation-api/doxygenctl
@@ -1,13 +1,20 @@
+#!/bin/bash
+
+SCRIPT=`realpath $0`
+DIR=`dirname $SCRIPT`
+
generate () {
+ echo ${DIR}
+ cd ${DIR}
doxygen ./XreateDoxyfile
}
transfer() {
- scp -P24 -r /tmp/xreate-documentation/html/ xreate@xreate.org:/opt/xreate-documentation-api/
+ scp -P24 -r ${DIR}/tmp-generated-doc-api/html/ xreate@xreate.org:/opt/xreate-documentation-api/
}
case $1 in
local) generate ;;
remote) generate && transfer ;;
*) echo "usage: local | remote ";;
esac
diff --git a/documentation-api/folders.dox b/documentation-api/folders.dox
index 1df879e..cb62da9 100644
--- a/documentation-api/folders.dox
+++ b/documentation-api/folders.dox
@@ -1,16 +1,21 @@
/**
* \dir analysis
* \brief Data structures and providers for analysis step. Everything that depends on Clasp reasoner's API.
*
* \dir aux
* \brief Auxiliary files
*
* \dir compilation
* \brief Code related to compilation step. Everything that depends on compiler toolchain LLVM internals
*
* \dir pass
* \brief Various passes to gather data and perforrm analysis and compilation
*
* \dir query
* \brief Code for exrtacting solutions from reasoner output and influence compilation
+ *
+ * \dir pass
+ * \brief Various passes to gather data and perforrm analysis and compilation
+ *
*/
+
diff --git a/documentation-api/namespaces.dox b/documentation-api/namespaces.dox
new file mode 100644
index 0000000..1de792c
--- /dev/null
+++ b/documentation-api/namespaces.dox
@@ -0,0 +1,44 @@
+/**
+ * \namespace xreate
+ * \brief Aww
+ *
+ * \namespace xreate::cfa
+ * \brief The CFA(Control Flow Analysis) related functionality
+ *
+ * \namespace xreate::dfa
+ * \brief The DFA(Data Flow Analysis) related functionality
+ *
+ * \namespace xreate::interpretation
+ * \brief Interpretation support
+ *
+ * \namespace xreate::typeinference
+ * \brief Type inference support
+ *
+ * \namespace xreate::analysis
+ * \brief The analysis' internal routines
+ *
+ * \namespace xreate::pointerarithmetic
+ * \brief Pointer arithemitic support
+ *
+ * \namespace xreate::compilation
+ * \brief The compilation internals used by \ref CompilePass
+ *
+ * \namespace xreate::polymorph
+ * \brief Polymorphism support
+ *
+ * \namespace xreate::latex
+ * \brief Latex(Late Context) support
+ *
+ * \namespace xreate::latereasoning
+ * \brief Late Transcend support
+ *
+ * \namespace xreate::versions
+ * \brief Versioned variables support. See the [explanation](/d/concepts/versions/)
+ *
+ * \namespace xreate::containers
+ * \brief Containers support. See [the explanation](/d/concepts/containers/)
+ *
+ * \namespace xreate::modules
+ * \brief Modules support
+ *
+*/
diff --git a/documentation-api/overview.dox b/documentation-api/overview.dox
index 99d2bb3..750ed0f 100644
--- a/documentation-api/overview.dox
+++ b/documentation-api/overview.dox
@@ -1,73 +1,68 @@
/**
- * \mainpage Xreate Internals
+ * \mainpage Xreate Compiler Internals
+ * \section overview_sect Overview
* \tableofcontents
- * \attention For installation and examples see [Instruction: First Steps](/w/instructions/first=steps).
+ * In a nutshell, \ref xreate::XreateManager is the entry point of the Xreate compiler API for clients to start off by instantiating it.
*
- * In a nutshell, xreate::XreateManager is an entry point of Xreate API and clients should start off by instantiating it.
- *
- * xreate::XreateManager is convenient wrapper to control all internal work-flow consisting of steps as follows:
- * - Parsing
- * - Intermediate Passes
- * - Reasoning
- * - Compilation
+ * \ref xreate::XreateManager's responsibility is a control over internal compiler's workflow consisting of steps as follows:
+ * - Parsing.
+ * - Internal passes and analyses.
+ * - Reasoning.
+ * - Bytecode generation.
*
+ * \section install_sect Build and run
+ * For build instructions and examples see [Build and Run](/d/build/).
+ *
* \section grammar_sect Grammar
- * Xreate's grammar located in two files in COCO parser generator's format
- * - `/grammar/xreate.ATG` : main Xreate's grammar file
- * - `/grammar/modules.ATG` : additional grammar to support modules management. See xreate::modules::XreateManagerDecoratorModules and [Modules Explanation](/w/concepts/modules/) for details
+ * The Xreate grammar located in two files in a [COCO](http://www.ssw.uni-linz.ac.at/Coco/) parser generator's format:
+ * - `/grammar/xreate.ATG` : main Xreate grammar file.
+ * - `/grammar/modules.ATG`: modules management grammar. See \ref xreate::modules and [Modules Explanation](/d/syntax/modules/) for details.
+
* \section parsing_sect Parsing
- * xreate::AST represents Xreate's syntax tree. It's produced by `Scanner` and `Parser` themselves generated by external tool Coco Parser Generator
+ * \ref xreate::AST represents the Xreate's syntax tree. It's produced by `Scanner` and `Parser` themselves generated by the Coco generator.
*
- * \section var_passes_sect Intermediate Passes
- * Once xreate::AST is built, xreate::XreateManager runs number of passes as a preparation
- * for *reasoning*(xreate::TranscendLayer) and *compilation*(xreate::CompilePass).
+ * \section var_passes_sect Internal passes
+ * Once \ref xreate::AST is built, \ref xreate::XreateManager runs number of passes as a preparation
+ * for *reasoning* (see \ref xreate::TranscendLayer) and *compilation* (see \ref xreate::CompilePass).
*
- * There is xreate::Attachments to address need of communication between various passes and stages.
+ * There is \ref xreate::Attachments to address a need of communication between various passes and stages.
+ * Passes may store additional pieces of information as AST node attachments for future use by consequent passes.
+ * Ultimately, all accumulated this way data is used to facilitate, enhance and refine the compilation process.
*
- * Currently there are following passes:
- * - xreate::cfa::CFAPass to perform Control Flow Analysis(CFA). Analysis' output stored in xreate::cfa::CFAGraph
- * - xreate::dfa::DFAPass to perform Data Flow Analysis(DFA). Output stored in xreate::dfa::DFAGraph
- * - xreate::interpretation::InterpretationPass to perform Interpretation analysis. See [Interpretation Overview](w/concepts/dfa)
- * - xreate::versions::VersionsPass to perform Versions Analysis. See [Versions Overview](w/concepts/versions)
+ * Currently there is a number of passes available, among them are:
+ * - \ref xreate::cfa::CFAPass to perform CFA(Control Flow Analysis). The output is stored in \ref xreate::cfa::CFAGraph.
+ * - \ref xreate::dfa::DFAPass to perform DFA(Data Flow Analysis). The output is stored in \ref xreate::dfa::DFAGraph.
+ * - \ref xreate::interpretation::InterpretationPass to perform the interpretation analysis. See \ref xreate::interpretation, [interpretation overview](/d/concepts/interpretation/).
*
- * Each pass should inherit xreate::IPass interface or xreate::AbstractPass as a more convenient wrapper.
- * xreate::PassManager is base class to manage passes and xreate::XreateManager derives xreate::PassManager to control builtin passes.
+ * Each pass either implements \ref xreate::IPass interface or inherits \ref xreate::AbstractPass as a more convenient wrapper.
+ * \ref xreate::PassManager is the base class to manage passes and \ref xreate::XreateManager inherits \ref xreate::PassManager to control builtin passes.
*
* \section reasoning_sect Reasoning
- * xreate::TranscendLayer is wrapper over external Clasp reasoner.
- * Data gathered by previously executed passes is composed(see xreate::IAnalysisReport, \ref analysis/aux.h for details) into _logic program_ as a _text_ according to Clasp reasoner's ASP syntax.
- * Current list of data sources is:
- * - Raw scripts. Client could append arbitrary ASP script to _logic program_
- * - Includes. There is possibility to point out external files with ASP scripts to append to _logic program_
- * - Diagnostic rules. Rules that produce diagnostic messages during compilation(warnings) or even able to halt compilation with errors
- * - DFA data. See xreate::dfa::DFAGraph
- * - CFA data. See xreate::cfa::CFAGraph
- * - Dominators Analysis. See xreate::dominators::DominatorsTreeAnalysisProvider
- * - Context rules. See xreate::ContextRule and general [Context Explanation](/w/concepts/context)
- *
- * Following analyses are performed currently bypassing ASP reasoner:
- * - \ref typeinference.h Type Inference
- * - xreate::interpretation::InterpretationPass Interpretation analysis
- * - xreate::versions::VersionsPass Versions analysis
+ * \ref xreate::TranscendLayer is a wrapper over an external ASP reasoner (currently [Clasp](https://potassco.org/clasp/)).
+ * Previously executed passes' output is collected(see \ref xreate::IAnalysisReport, \ref analysis/utils.h) to compose
+ * a _logic program_ in Clasp reasoner's ASP syntax format. See \ref xreate::TranscendLayer for more details.
*
- * Output of the external Clasp reasoner is recognized and accessed via *queries*.
- * Query is an interface between reasoner' output and rest of Xreate.
- * Each query inherits xreate::IQuery interface. Currently there are queries as follows:
- * - xreate::containers::Query to catch solutions regarding Containers implementation. See [Containers Explanation](/w/concepts/containers)
- * - xreate::context::ContextQuery to catch solution regarding Context. See [Context Explanation](/w/concepts/context)
+ * Clients may implement \ref xreate::IQuery interface to to access Clasp reasoner's solutions. There is number of existing queries, such as:
+ * - \ref xreate::containers::Query to get solutions regarding Containers.
+ * - \ref xreate::latex::LatexQuery to get solution regarding [Context](/d/concepts/context/).
+ * - \ref xreate::polymorph::PolymorphQuery to get solutions regarding Polymorphism.
*
- * \section compilation_sect Compilation
- * xreate::CompilePass iterates over xreate::AST tree and produces executable code fed by data(via xreate::Attachments) gathered by previous passes as well as data via queries(xreate::IQuery) from the external Clasp reasoner.
- * Compilation done using xreate::LLVMLayer(wrapper over LLVM byte machine) and based on following aspects:
- * - Containers support. See \ref compilation/containers.h
- * - Late Conext compilation. See xreate::context::LateContextCompiler2
- * - Interpretation support. See xreate::interpretation::TargetInterpretation
- * - Loop saturation support. See xreate::compilation::TransformerSaturation
- * - External Code access. See xreate::ExternLayer(wrapper over Clang library)
- *
- *\subsection compilation_adaptability Adaptability
+ * Also, currently a number of analyses are performed bypassing ASP reasoner:
+ * - \ref typeinference.h Type Inference.
+ * - \ref xreate::interpretation::InterpretationPass Interpretation analysis.
+ * - \ref xreate::versions::VersionsPass Versions analysis.
*
- * xreate::CompilePass's architecture allows adaptability in different ways
- * to alter function-level, code scope-level compilation and so on. More details in xreate::CompilePass description.
+ * \section compilation_sect Compilation
+ * \ref xreate::CompilePass iterates over \ref xreate::AST tree to produce bytecode using additional data supplied by
+ * previous passes(via \ref xreate::Attachments) along with data accessed via queries (\ref xreate::IQuery) from the external Clasp reasoner.
+ * Bytecode is generated using LLVM infrastructure represented by \ref xreate::LLVMLayer.
+ * There is a number of classes focused on particular compilation aspects, among them are:
+ * - Containers support. See \ref xreate::containers.
+ * - Context support. See \ref xreate::latex.
+ * - Interpretation support. See \ref xreate::interpretation.
+ * - Loop saturation support. See \ref xreate::compilation::TransformerSaturation.
+ * - Versions support. See \ref xreate::versions.
+ * - Late Transcend support. See \ref xreate::latereasoning.
+ * - External Code access. See \ref xreate::ExternLayer..
*/

Event Timeline